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;
595a37bc407ab1b8844c3541ff4e6653635b108bedHemant Guptaimport java.nio.ByteBuffer;
605a37bc407ab1b8844c3541ff4e6653635b108bedHemant Guptaimport java.util.Collections;
615a37bc407ab1b8844c3541ff4e6653635b108bedHemant Guptaimport java.util.Comparator;
625a37bc407ab1b8844c3541ff4e6653635b108bedHemant Guptaimport com.android.bluetooth.R;
635a37bc407ab1b8844c3541ff4e6653635b108bedHemant Guptaimport com.android.vcard.VCardComposer;
645a37bc407ab1b8844c3541ff4e6653635b108bedHemant Guptaimport com.android.vcard.VCardConfig;
655a37bc407ab1b8844c3541ff4e6653635b108bedHemant Guptaimport com.android.vcard.VCardPhoneNumberTranslationCallback;
66198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa
672f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yueimport java.io.IOException;
682f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yueimport java.io.OutputStream;
692c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fanimport java.util.ArrayList;
702c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
71198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawaimport javax.obex.Operation;
72198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawaimport javax.obex.ResponseCodes;
739d68ffa1079ca2e85a8ccf62bf8dca2f43f1ade3Tony Makimport javax.obex.ServerOperation;
74c7a57f31515107366589bd6875c3cc4af1fc806efredc
752c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fanpublic class BluetoothPbapVcardManager {
762f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue    private static final String TAG = "BluetoothPbapVcardManager";
772c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
784446eaa935994bc91d6d308303e8d27526b4590dLixin Yue    private static final boolean V = BluetoothPbapService.VERBOSE;
794446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
802c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    private ContentResolver mResolver;
812c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
822c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    private Context mContext;
832c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
84e10881ae39eb4affb7a78827f2060964e8534515Daisuke Miyakawa    private static final int PHONE_NUMBER_COLUMN_INDEX = 3;
852c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
862f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue    static final String SORT_ORDER_PHONE_NUMBER = CommonDataKinds.Phone.NUMBER + " ASC";
874446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
885006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai    static final String[] PHONES_CONTACTS_PROJECTION = new String[] {
895006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            Phone.CONTACT_ID, // 0
905006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            Phone.DISPLAY_NAME, // 1
915006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai    };
925006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai
935006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai    static final String[] PHONE_LOOKUP_PROJECTION = new String[] {
945006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            PhoneLookup._ID, PhoneLookup.DISPLAY_NAME
952b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh    };
962b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh
972b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh    static final int CONTACTS_ID_COLUMN_INDEX = 0;
982b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh
992b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh    static final int CONTACTS_NAME_COLUMN_INDEX = 1;
1002b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh
1015a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta    static long LAST_FETCHED_TIME_STAMP;
1025a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta
1032b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh    // call histories use dynamic handles, and handles should order by date; the
1042b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh    // most recently one should be the first handle. In table "calls", _id and
1052b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh    // date are consistent in ordering, to implement simply, we sort by _id
1062b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh    // here.
1072b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh    static final String CALLLOG_SORT_ORDER = Calls._ID + " DESC";
1082b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh
1095a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta    private static final int NEED_SEND_BODY = -1;
1105a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta
1112c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    public BluetoothPbapVcardManager(final Context context) {
1122c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        mContext = context;
1132c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        mResolver = mContext.getContentResolver();
1145a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta        LAST_FETCHED_TIME_STAMP = System.currentTimeMillis();
1152c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    }
1162c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
117c7a57f31515107366589bd6875c3cc4af1fc806efredc    /**
118c7a57f31515107366589bd6875c3cc4af1fc806efredc     * Create an owner vcard from the configured profile
119c7a57f31515107366589bd6875c3cc4af1fc806efredc     * @param vcardType21
120c7a57f31515107366589bd6875c3cc4af1fc806efredc     * @return
121c7a57f31515107366589bd6875c3cc4af1fc806efredc     */
1225a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta    private final String getOwnerPhoneNumberVcardFromProfile(
1235a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            final boolean vcardType21, final byte[] filter) {
124c7a57f31515107366589bd6875c3cc4af1fc806efredc        // Currently only support Generic Vcard 2.1 and 3.0
125c7a57f31515107366589bd6875c3cc4af1fc806efredc        int vcardType;
126c7a57f31515107366589bd6875c3cc4af1fc806efredc        if (vcardType21) {
127c7a57f31515107366589bd6875c3cc4af1fc806efredc            vcardType = VCardConfig.VCARD_TYPE_V21_GENERIC;
128c7a57f31515107366589bd6875c3cc4af1fc806efredc        } else {
129c7a57f31515107366589bd6875c3cc4af1fc806efredc            vcardType = VCardConfig.VCARD_TYPE_V30_GENERIC;
130c7a57f31515107366589bd6875c3cc4af1fc806efredc        }
1314a53a55dc10d3a26c94e5844f7d4a2565a67142cfredc
1324a53a55dc10d3a26c94e5844f7d4a2565a67142cfredc        if (!BluetoothPbapConfig.includePhotosInVcard()) {
1334a53a55dc10d3a26c94e5844f7d4a2565a67142cfredc            vcardType |= VCardConfig.FLAG_REFRAIN_IMAGE_EXPORT;
1344a53a55dc10d3a26c94e5844f7d4a2565a67142cfredc        }
1354a53a55dc10d3a26c94e5844f7d4a2565a67142cfredc
136c7a57f31515107366589bd6875c3cc4af1fc806efredc        return BluetoothPbapUtils.createProfileVCard(mContext, vcardType,filter);
137c7a57f31515107366589bd6875c3cc4af1fc806efredc    }
138c7a57f31515107366589bd6875c3cc4af1fc806efredc
139c7a57f31515107366589bd6875c3cc4af1fc806efredc    public final String getOwnerPhoneNumberVcard(final boolean vcardType21, final byte[] filter) {
140c7a57f31515107366589bd6875c3cc4af1fc806efredc        //Owner vCard enhancement: Use "ME" profile if configured
141c7a57f31515107366589bd6875c3cc4af1fc806efredc        if (BluetoothPbapConfig.useProfileForOwnerVcard()) {
142c7a57f31515107366589bd6875c3cc4af1fc806efredc            String vcard = getOwnerPhoneNumberVcardFromProfile(vcardType21, filter);
143c7a57f31515107366589bd6875c3cc4af1fc806efredc            if (vcard != null && vcard.length() != 0) {
144c7a57f31515107366589bd6875c3cc4af1fc806efredc                return vcard;
145c7a57f31515107366589bd6875c3cc4af1fc806efredc            }
146c7a57f31515107366589bd6875c3cc4af1fc806efredc        }
147c7a57f31515107366589bd6875c3cc4af1fc806efredc        //End enhancement
148c7a57f31515107366589bd6875c3cc4af1fc806efredc
1493c4d2c77c2fffe675fbe89ba58856686b6873d2fDaisuke Miyakawa        BluetoothPbapCallLogComposer composer = new BluetoothPbapCallLogComposer(mContext);
1502f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        String name = BluetoothPbapService.getLocalPhoneName();
1512f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        String number = BluetoothPbapService.getLocalPhoneNum();
1522f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        String vcard = composer.composeVCardForPhoneOwnNumber(Phone.TYPE_MOBILE, name, number,
1532f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                vcardType21);
1542f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        return vcard;
1552c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    }
1562c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
1572f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue    public final int getPhonebookSize(final int type) {
1582f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        int size;
1592f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        switch (type) {
1602f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            case BluetoothPbapObexServer.ContentType.PHONEBOOK:
1612f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                size = getContactsSize();
1622f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                break;
1632f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            default:
1642f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                size = getCallHistorySize(type);
1652f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                break;
1662c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
167c7a57f31515107366589bd6875c3cc4af1fc806efredc        if (V) Log.v(TAG, "getPhonebookSize size = " + size + " type = " + type);
1682f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        return size;
1692c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    }
1702c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
1712f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue    public final int getContactsSize() {
1723178b08c6823899dbb58513673bf2a80f637be7cRicky Wai        final Uri myUri = DevicePolicyUtils.getEnterprisePhoneUri(mContext);
1732f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        Cursor contactCursor = null;
1742f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        try {
1754ca05d6f02264b0eb2983e43d34ca4051434a4d4Ajay Panicker            contactCursor = mResolver.query(
1764ca05d6f02264b0eb2983e43d34ca4051434a4d4Ajay Panicker                    myUri, new String[] {Phone.CONTACT_ID}, null, null, Phone.CONTACT_ID);
1775006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            if (contactCursor == null) {
1785006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                return 0;
1792f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            }
180c438463431b171a67b22b50886ef8dd737c44004Andre Eisenbach            return getDistinctContactIdSize(contactCursor) + 1; // always has the 0.vcf
181c592e5a6de0011cd60f23ac18a7bd56d8eeb5dd1Hemant Gupta        } catch (CursorWindowAllocationException e) {
182c592e5a6de0011cd60f23ac18a7bd56d8eeb5dd1Hemant Gupta            Log.e(TAG, "CursorWindowAllocationException while getting Contacts size");
1832f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        } finally {
1842f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            if (contactCursor != null) {
1852f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                contactCursor.close();
1862f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            }
1872c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
1885006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai        return 0;
1892c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    }
1902c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
1912f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue    public final int getCallHistorySize(final int type) {
1922b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh        final Uri myUri = CallLog.Calls.CONTENT_URI;
1932f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        String selection = BluetoothPbapObexServer.createSelectionPara(type);
1942f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        int size = 0;
1952f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        Cursor callCursor = null;
1962f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        try {
1972f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            callCursor = mResolver.query(myUri, null, selection, null,
1982f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                    CallLog.Calls.DEFAULT_SORT_ORDER);
1992f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            if (callCursor != null) {
2002f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                size = callCursor.getCount();
2014446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            }
202c592e5a6de0011cd60f23ac18a7bd56d8eeb5dd1Hemant Gupta        } catch (CursorWindowAllocationException e) {
203c592e5a6de0011cd60f23ac18a7bd56d8eeb5dd1Hemant Gupta            Log.e(TAG, "CursorWindowAllocationException while getting CallHistory size");
2042f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        } finally {
2052f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            if (callCursor != null) {
2062f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                callCursor.close();
207c592e5a6de0011cd60f23ac18a7bd56d8eeb5dd1Hemant Gupta                callCursor = null;
2084446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            }
2092f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        }
2102f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        return size;
2112f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue    }
2124446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
2132f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue    public final ArrayList<String> loadCallHistoryList(final int type) {
2142b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh        final Uri myUri = CallLog.Calls.CONTENT_URI;
2152f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        String selection = BluetoothPbapObexServer.createSelectionPara(type);
2162f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        String[] projection = new String[] {
2179674eb043aeb1474aa23ddd0739e3b8f05432630Jay Shrauner                Calls.NUMBER, Calls.CACHED_NAME, Calls.NUMBER_PRESENTATION
2182f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        };
2192f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        final int CALLS_NUMBER_COLUMN_INDEX = 0;
2202f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        final int CALLS_NAME_COLUMN_INDEX = 1;
2219674eb043aeb1474aa23ddd0739e3b8f05432630Jay Shrauner        final int CALLS_NUMBER_PRESENTATION_COLUMN_INDEX = 2;
2222f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue
2232f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        Cursor callCursor = null;
2242f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        ArrayList<String> list = new ArrayList<String>();
2252f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        try {
2262f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            callCursor = mResolver.query(myUri, projection, selection, null,
2272b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh                    CALLLOG_SORT_ORDER);
2282f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            if (callCursor != null) {
2292f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                for (callCursor.moveToFirst(); !callCursor.isAfterLast();
2302f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                        callCursor.moveToNext()) {
2312f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                    String name = callCursor.getString(CALLS_NAME_COLUMN_INDEX);
2322f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                    if (TextUtils.isEmpty(name)) {
23377ba5f6684f4dd7e4b7fc37982271da5654aec07Staffan Lindvall                        // name not found, use number instead
2349674eb043aeb1474aa23ddd0739e3b8f05432630Jay Shrauner                        final int numberPresentation = callCursor.getInt(
2359674eb043aeb1474aa23ddd0739e3b8f05432630Jay Shrauner                                CALLS_NUMBER_PRESENTATION_COLUMN_INDEX);
2369674eb043aeb1474aa23ddd0739e3b8f05432630Jay Shrauner                        if (numberPresentation != Calls.PRESENTATION_ALLOWED) {
23777ba5f6684f4dd7e4b7fc37982271da5654aec07Staffan Lindvall                            name = mContext.getString(R.string.unknownNumber);
2389674eb043aeb1474aa23ddd0739e3b8f05432630Jay Shrauner                        } else {
2399674eb043aeb1474aa23ddd0739e3b8f05432630Jay Shrauner                            name = callCursor.getString(CALLS_NUMBER_COLUMN_INDEX);
24077ba5f6684f4dd7e4b7fc37982271da5654aec07Staffan Lindvall                        }
2412f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                    }
2422f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                    list.add(name);
2432f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                }
2442f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            }
245c592e5a6de0011cd60f23ac18a7bd56d8eeb5dd1Hemant Gupta        } catch (CursorWindowAllocationException e) {
246c592e5a6de0011cd60f23ac18a7bd56d8eeb5dd1Hemant Gupta            Log.e(TAG, "CursorWindowAllocationException while loading CallHistory");
2472f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        } finally {
2482f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            if (callCursor != null) {
2492f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                callCursor.close();
250c592e5a6de0011cd60f23ac18a7bd56d8eeb5dd1Hemant Gupta                callCursor = null;
2512c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            }
2522c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
2532f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        return list;
2542c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    }
2552c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
2562b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh    public final ArrayList<String> getPhonebookNameList(final int orderByWhat) {
2572f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        ArrayList<String> nameList = new ArrayList<String>();
258c7a57f31515107366589bd6875c3cc4af1fc806efredc        //Owner vCard enhancement. Use "ME" profile if configured
259c7a57f31515107366589bd6875c3cc4af1fc806efredc        String ownerName = null;
260c7a57f31515107366589bd6875c3cc4af1fc806efredc        if (BluetoothPbapConfig.useProfileForOwnerVcard()) {
261c7a57f31515107366589bd6875c3cc4af1fc806efredc            ownerName = BluetoothPbapUtils.getProfileName(mContext);
262c7a57f31515107366589bd6875c3cc4af1fc806efredc        }
263c7a57f31515107366589bd6875c3cc4af1fc806efredc        if (ownerName == null || ownerName.length()==0) {
264c7a57f31515107366589bd6875c3cc4af1fc806efredc            ownerName = BluetoothPbapService.getLocalPhoneName();
265c7a57f31515107366589bd6875c3cc4af1fc806efredc        }
266c7a57f31515107366589bd6875c3cc4af1fc806efredc        nameList.add(ownerName);
267c7a57f31515107366589bd6875c3cc4af1fc806efredc        //End enhancement
2684446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
2693178b08c6823899dbb58513673bf2a80f637be7cRicky Wai        final Uri myUri = DevicePolicyUtils.getEnterprisePhoneUri(mContext);
2702b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh        Cursor contactCursor = null;
2713c8b50f8dc1c4ce11168fb42a884f604d1810c46Hemant Gupta        // By default order is indexed
2723c8b50f8dc1c4ce11168fb42a884f604d1810c46Hemant Gupta        String orderBy = Phone.CONTACT_ID;
2732f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        try {
2743c8b50f8dc1c4ce11168fb42a884f604d1810c46Hemant Gupta            if (orderByWhat == BluetoothPbapObexServer.ORDER_BY_ALPHABETICAL) {
2753c8b50f8dc1c4ce11168fb42a884f604d1810c46Hemant Gupta                orderBy = Phone.DISPLAY_NAME;
2763c8b50f8dc1c4ce11168fb42a884f604d1810c46Hemant Gupta            }
2774ca05d6f02264b0eb2983e43d34ca4051434a4d4Ajay Panicker            contactCursor = mResolver.query(myUri, PHONES_CONTACTS_PROJECTION, null, null, orderBy);
2782b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh            if (contactCursor != null) {
2795006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                appendDistinctNameIdList(nameList,
280c438463431b171a67b22b50886ef8dd737c44004Andre Eisenbach                        mContext.getString(android.R.string.unknownName),
281c438463431b171a67b22b50886ef8dd737c44004Andre Eisenbach                        contactCursor);
2822f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            }
2833c8b50f8dc1c4ce11168fb42a884f604d1810c46Hemant Gupta        } catch (CursorWindowAllocationException e) {
2843c8b50f8dc1c4ce11168fb42a884f604d1810c46Hemant Gupta            Log.e(TAG, "CursorWindowAllocationException while getting phonebook name list");
285bf37a0295d110b77b635ca2986172bbdd59331bbAndre Eisenbach        } catch (Exception e) {
2863c8b50f8dc1c4ce11168fb42a884f604d1810c46Hemant Gupta            Log.e(TAG, "Exception while getting phonebook name list", e);
2872f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        } finally {
2882b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh            if (contactCursor != null) {
2892b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh                contactCursor.close();
290c592e5a6de0011cd60f23ac18a7bd56d8eeb5dd1Hemant Gupta                contactCursor = null;
2912f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            }
2922f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        }
2932f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        return nameList;
2944446eaa935994bc91d6d308303e8d27526b4590dLixin Yue    }
2954446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
2965a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta    final ArrayList<String> getSelectedPhonebookNameList(final int orderByWhat,
2975a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            final boolean vcardType21, int needSendBody, int pbSize, byte[] selector,
2985a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            String vcardselectorop) {
2995a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta        ArrayList<String> nameList = new ArrayList<String>();
3005a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta        PropertySelector vcardselector = new PropertySelector(selector);
3015a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta        VCardComposer composer = null;
3025a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta        int vcardType;
3035a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta
3045a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta        if (vcardType21) {
3055a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            vcardType = VCardConfig.VCARD_TYPE_V21_GENERIC;
3065a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta        } else {
3075a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            vcardType = VCardConfig.VCARD_TYPE_V30_GENERIC;
3085a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta        }
3095a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta
3105a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta        composer = BluetoothPbapUtils.createFilteredVCardComposer(mContext, vcardType, null);
3115a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta        composer.setPhoneNumberTranslationCallback(new VCardPhoneNumberTranslationCallback() {
3125a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta
3135a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            public String onValueReceived(
3145a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                    String rawValue, int type, String label, boolean isPrimary) {
3155a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                String numberWithControlSequence = rawValue.replace(PhoneNumberUtils.PAUSE, 'p')
3165a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                                                           .replace(PhoneNumberUtils.WAIT, 'w');
3175a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                return numberWithControlSequence;
3185a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            }
3195a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta        });
3205a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta
3215a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta        // Owner vCard enhancement. Use "ME" profile if configured
3225a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta        String ownerName = null;
3235a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta        if (BluetoothPbapConfig.useProfileForOwnerVcard()) {
3245a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            ownerName = BluetoothPbapUtils.getProfileName(mContext);
3255a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta        }
3265a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta        if (ownerName == null || ownerName.length() == 0) {
3275a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            ownerName = BluetoothPbapService.getLocalPhoneName();
3285a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta        }
3295a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta        nameList.add(ownerName);
3305a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta        // End enhancement
3315a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta
3325a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta        final Uri myUri = DevicePolicyUtils.getEnterprisePhoneUri(mContext);
3335a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta        Cursor contactCursor = null;
3345a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta        try {
3355a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            contactCursor = mResolver.query(
3365a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                    myUri, PHONES_CONTACTS_PROJECTION, null, null, Phone.CONTACT_ID);
3375a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta
3385a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            if (contactCursor != null) {
3395a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                if (!composer.initWithCallback(
3405a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                            contactCursor, new EnterpriseRawContactEntitlesInfoCallback())) {
3415a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                    return nameList;
3425a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                }
3435a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta
3445a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                while (!composer.isAfterLast()) {
3455a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                    String vcard = composer.createOneEntry();
3465a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                    if (vcard == null) {
3475a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                        Log.e(TAG, "Failed to read a contact. Error reason: "
3485a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                                        + composer.getErrorReason());
3495a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                        return nameList;
3505a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                    }
3515a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                    if (V) Log.v(TAG, "Checking selected bits in the vcard composer" + vcard);
3525a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta
3535a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                    if (!vcardselector.CheckVcardSelector(vcard, vcardselectorop)) {
3545a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                        Log.e(TAG, "vcard selector check fail");
3555a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                        vcard = null;
3565a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                        pbSize--;
3575a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                        continue;
3585a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                    } else {
3595a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                        String name = vcardselector.getName(vcard);
3605a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                        if (TextUtils.isEmpty(name)) {
3615a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                            name = mContext.getString(android.R.string.unknownName);
3625a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                        }
3635a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                        nameList.add(name);
3645a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                    }
3655a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                }
3665a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                if (orderByWhat == BluetoothPbapObexServer.ORDER_BY_INDEXED) {
3675a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                    if (V) Log.v(TAG, "getPhonebookNameList, order by index");
3685a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                    // Do not need to do anything, as we sort it by index already
3695a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                } else if (orderByWhat == BluetoothPbapObexServer.ORDER_BY_ALPHABETICAL) {
3705a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                    if (V) Log.v(TAG, "getPhonebookNameList, order by alpha");
3715a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                    Collections.sort(nameList);
3725a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                }
3735a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            }
3745a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta        } catch (CursorWindowAllocationException e) {
3755a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            Log.e(TAG, "CursorWindowAllocationException while getting Phonebook name list");
3765a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta        } finally {
3775a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            if (contactCursor != null) {
3785a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                contactCursor.close();
3795a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                contactCursor = null;
3805a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            }
3815a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta        }
3825a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta        return nameList;
3835a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta    }
3845a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta
3850dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao    public final ArrayList<String> getContactNamesByNumber(final String phoneNumber) {
3860dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao        ArrayList<String> nameList = new ArrayList<String>();
3871321cd814a7406260ba6282d9c71e1a2d8925262Hemant Gupta        ArrayList<String> tempNameList = new ArrayList<String>();
3880dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao
3890dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao        Cursor contactCursor = null;
390c438463431b171a67b22b50886ef8dd737c44004Andre Eisenbach        Uri uri = null;
391c438463431b171a67b22b50886ef8dd737c44004Andre Eisenbach        String[] projection = null;
392c438463431b171a67b22b50886ef8dd737c44004Andre Eisenbach
3935006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai        if (TextUtils.isEmpty(phoneNumber)) {
3943178b08c6823899dbb58513673bf2a80f637be7cRicky Wai            uri = DevicePolicyUtils.getEnterprisePhoneUri(mContext);
395c438463431b171a67b22b50886ef8dd737c44004Andre Eisenbach            projection = PHONES_CONTACTS_PROJECTION;
3964bba23a751f042596561eab0e677135d5267bcdfStaffan Lindvall        } else {
397c438463431b171a67b22b50886ef8dd737c44004Andre Eisenbach            uri = Uri.withAppendedPath(getPhoneLookupFilterUri(),
398c438463431b171a67b22b50886ef8dd737c44004Andre Eisenbach                Uri.encode(phoneNumber));
399c438463431b171a67b22b50886ef8dd737c44004Andre Eisenbach            projection = PHONE_LOOKUP_PROJECTION;
4004bba23a751f042596561eab0e677135d5267bcdfStaffan Lindvall        }
4014446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
4022f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        try {
4034ca05d6f02264b0eb2983e43d34ca4051434a4d4Ajay Panicker            contactCursor = mResolver.query(uri, projection, null, null, Phone.CONTACT_ID);
4040dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao
4050dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao            if (contactCursor != null) {
4065006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                appendDistinctNameIdList(nameList,
4075006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                        mContext.getString(android.R.string.unknownName),
408c438463431b171a67b22b50886ef8dd737c44004Andre Eisenbach                        contactCursor);
4095006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                if (V) {
4105006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                    for (String nameIdStr : nameList) {
4115006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                        Log.v(TAG, "got name " + nameIdStr + " by number " + phoneNumber);
4122f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                    }
4132f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                }
4142f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            }
415c592e5a6de0011cd60f23ac18a7bd56d8eeb5dd1Hemant Gupta        } catch (CursorWindowAllocationException e) {
416c592e5a6de0011cd60f23ac18a7bd56d8eeb5dd1Hemant Gupta            Log.e(TAG, "CursorWindowAllocationException while getting contact names");
4172f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        } finally {
4180dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao            if (contactCursor != null) {
4190dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao                contactCursor.close();
420c592e5a6de0011cd60f23ac18a7bd56d8eeb5dd1Hemant Gupta                contactCursor = null;
4212f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            }
4222c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
4231321cd814a7406260ba6282d9c71e1a2d8925262Hemant Gupta        int tempListSize = tempNameList.size();
4241321cd814a7406260ba6282d9c71e1a2d8925262Hemant Gupta        for (int index = 0; index < tempListSize; index++) {
4251321cd814a7406260ba6282d9c71e1a2d8925262Hemant Gupta            String object = tempNameList.get(index);
4261321cd814a7406260ba6282d9c71e1a2d8925262Hemant Gupta            if (!nameList.contains(object))
4271321cd814a7406260ba6282d9c71e1a2d8925262Hemant Gupta                nameList.add(object);
4281321cd814a7406260ba6282d9c71e1a2d8925262Hemant Gupta        }
4291321cd814a7406260ba6282d9c71e1a2d8925262Hemant Gupta
4300dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao        return nameList;
4312c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    }
4322c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
4335a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta    byte[] getCallHistoryPrimaryFolderVersion(final int type) {
4345a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta        final Uri myUri = CallLog.Calls.CONTENT_URI;
4355a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta        String selection = BluetoothPbapObexServer.createSelectionPara(type);
4365a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta        selection = selection + " AND date >= " + LAST_FETCHED_TIME_STAMP;
4375a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta
4385a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta        Log.d(TAG, "LAST_FETCHED_TIME_STAMP is " + LAST_FETCHED_TIME_STAMP);
4395a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta        Cursor callCursor = null;
4405a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta        long count = 0;
4415a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta        long primaryVcMsb = 0;
4425a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta        ArrayList<String> list = new ArrayList<String>();
4435a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta        try {
4445a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            callCursor = mResolver.query(myUri, null, selection, null, null);
4455a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            while (callCursor != null && callCursor.moveToNext()) {
4465a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                count = count + 1;
4475a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            }
4485a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta        } catch (Exception e) {
4495a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            Log.e(TAG, "exception while fetching callHistory pvc");
4505a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta        } finally {
4515a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            if (callCursor != null) {
4525a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                callCursor.close();
4535a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                callCursor = null;
4545a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            }
4555a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta        }
4565a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta
4575a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta        LAST_FETCHED_TIME_STAMP = System.currentTimeMillis();
4585a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta        Log.d(TAG, "getCallHistoryPrimaryFolderVersion count is " + count + " type is " + type);
4595a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta        ByteBuffer pvc = ByteBuffer.allocate(16);
4605a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta        pvc.putLong(primaryVcMsb);
461cf92c2759b709461acf7c36c08f4eef9c8004c85Hemant Gupta        Log.d(TAG, "primaryVersionCounter is " + BluetoothPbapUtils.primaryVersionCounter);
4625a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta        pvc.putLong(count);
4635a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta        return pvc.array();
4645a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta    }
4655a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta
4665a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta    final int composeAndSendSelectedCallLogVcards(final int type, Operation op,
4675a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            final int startPoint, final int endPoint, final boolean vcardType21, int needSendBody,
4685a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            int pbSize, boolean ignorefilter, byte[] filter, byte[] vcardselector,
4695a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            String vcardselectorop, boolean vcardselect) {
47059256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh        if (startPoint < 1 || startPoint > endPoint) {
47159256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh            Log.e(TAG, "internal error: startPoint or endPoint is not correct.");
47259256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh            return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
47359256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh        }
4742f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        String typeSelection = BluetoothPbapObexServer.createSelectionPara(type);
47559256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh
4762b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh        final Uri myUri = CallLog.Calls.CONTENT_URI;
47759256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh        final String[] CALLLOG_PROJECTION = new String[] {
47859256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh            CallLog.Calls._ID, // 0
47959256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh        };
48059256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh        final int ID_COLUMN_INDEX = 0;
48159256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh
48259256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh        Cursor callsCursor = null;
48359256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh        long startPointId = 0;
48459256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh        long endPointId = 0;
48559256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh        try {
48659256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh            // Need test to see if order by _ID is ok here, or by date?
48759256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh            callsCursor = mResolver.query(myUri, CALLLOG_PROJECTION, typeSelection, null,
4882b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh                    CALLLOG_SORT_ORDER);
48959256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh            if (callsCursor != null) {
49059256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh                callsCursor.moveToPosition(startPoint - 1);
49159256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh                startPointId = callsCursor.getLong(ID_COLUMN_INDEX);
49259256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh                if (V) Log.v(TAG, "Call Log query startPointId = " + startPointId);
49359256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh                if (startPoint == endPoint) {
49459256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh                    endPointId = startPointId;
49559256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh                } else {
49659256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh                    callsCursor.moveToPosition(endPoint - 1);
49759256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh                    endPointId = callsCursor.getLong(ID_COLUMN_INDEX);
49859256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh                }
49959256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh                if (V) Log.v(TAG, "Call log query endPointId = " + endPointId);
50059256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh            }
501c592e5a6de0011cd60f23ac18a7bd56d8eeb5dd1Hemant Gupta        } catch (CursorWindowAllocationException e) {
502c592e5a6de0011cd60f23ac18a7bd56d8eeb5dd1Hemant Gupta            Log.e(TAG, "CursorWindowAllocationException while composing calllog vcards");
50359256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh        } finally {
50459256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh            if (callsCursor != null) {
50559256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh                callsCursor.close();
506c592e5a6de0011cd60f23ac18a7bd56d8eeb5dd1Hemant Gupta                callsCursor = null;
50759256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh            }
50859256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh        }
50959256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh
5102f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        String recordSelection;
5112f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        if (startPoint == endPoint) {
51259256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh            recordSelection = Calls._ID + "=" + startPointId;
5132f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        } else {
5142b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh            // The query to call table is by "_id DESC" order, so change
5152b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh            // correspondingly.
5162b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh            recordSelection = Calls._ID + ">=" + endPointId + " AND " + Calls._ID + "<="
5172b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh                    + startPointId;
5184446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        }
5194446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
5202f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        String selection;
5212f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        if (typeSelection == null) {
5222f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            selection = recordSelection;
5232f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        } else {
5242f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            selection = "(" + typeSelection + ") AND (" + recordSelection + ")";
5254446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        }
5264446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
52759256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh        if (V) Log.v(TAG, "Call log query selection is: " + selection);
5284446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
5295a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta        return composeCallLogsAndSendSelectedVCards(op, selection, vcardType21, needSendBody,
5305a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                pbSize, null, ignorefilter, filter, vcardselector, vcardselectorop, vcardselect);
5314446eaa935994bc91d6d308303e8d27526b4590dLixin Yue    }
5324446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
5335a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta    final int composeAndSendPhonebookVcards(Operation op, final int startPoint, final int endPoint,
5345a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            final boolean vcardType21, String ownerVCard, int needSendBody, int pbSize,
5355a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            boolean ignorefilter, byte[] filter, byte[] vcardselector, String vcardselectorop,
5365a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            boolean vcardselect) {
53759256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh        if (startPoint < 1 || startPoint > endPoint) {
53859256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh            Log.e(TAG, "internal error: startPoint or endPoint is not correct.");
53959256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh            return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
54059256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh        }
54159256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh
5423178b08c6823899dbb58513673bf2a80f637be7cRicky Wai        final Uri myUri = DevicePolicyUtils.getEnterprisePhoneUri(mContext);
54359256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh        Cursor contactCursor = null;
5440ff315d60bb44c5cc4223abff48e086defaec8adTony Mak        Cursor contactIdCursor = new MatrixCursor(new String[] {
5450ff315d60bb44c5cc4223abff48e086defaec8adTony Mak            Phone.CONTACT_ID
5460ff315d60bb44c5cc4223abff48e086defaec8adTony Mak        });
54759256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh        try {
5484ca05d6f02264b0eb2983e43d34ca4051434a4d4Ajay Panicker            contactCursor = mResolver.query(
5494ca05d6f02264b0eb2983e43d34ca4051434a4d4Ajay Panicker                    myUri, PHONES_CONTACTS_PROJECTION, null, null, Phone.CONTACT_ID);
55059256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh            if (contactCursor != null) {
5510ff315d60bb44c5cc4223abff48e086defaec8adTony Mak                contactIdCursor = ContactCursorFilter.filterByRange(contactCursor, startPoint,
5520ff315d60bb44c5cc4223abff48e086defaec8adTony Mak                        endPoint);
55359256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh            }
554c592e5a6de0011cd60f23ac18a7bd56d8eeb5dd1Hemant Gupta        } catch (CursorWindowAllocationException e) {
555c592e5a6de0011cd60f23ac18a7bd56d8eeb5dd1Hemant Gupta            Log.e(TAG, "CursorWindowAllocationException while composing phonebook vcards");
55659256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh        } finally {
55759256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh            if (contactCursor != null) {
55859256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh                contactCursor.close();
55959256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh            }
56059256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh        }
5615a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta
5625a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta        if (vcardselect)
5635a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            return composeContactsAndSendSelectedVCards(op, contactIdCursor, vcardType21,
5645a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                    ownerVCard, needSendBody, pbSize, ignorefilter, filter, vcardselector,
5655a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                    vcardselectorop);
5665a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta        else
5675a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            return composeContactsAndSendVCards(
5685a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                    op, contactIdCursor, vcardType21, ownerVCard, ignorefilter, filter);
5694446eaa935994bc91d6d308303e8d27526b4590dLixin Yue    }
5704446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
5715a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta    final int composeAndSendPhonebookOneVcard(Operation op, final int offset,
5725a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            final boolean vcardType21, String ownerVCard, int orderByWhat, boolean ignorefilter,
5735a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            byte[] filter) {
5742b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh        if (offset < 1) {
5752b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh            Log.e(TAG, "Internal error: offset is not correct.");
5762b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh            return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
5772b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh        }
5783178b08c6823899dbb58513673bf2a80f637be7cRicky Wai        final Uri myUri = DevicePolicyUtils.getEnterprisePhoneUri(mContext);
5790ff315d60bb44c5cc4223abff48e086defaec8adTony Mak
5802b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh        Cursor contactCursor = null;
5810ff315d60bb44c5cc4223abff48e086defaec8adTony Mak        Cursor contactIdCursor = new MatrixCursor(new String[] {
5820ff315d60bb44c5cc4223abff48e086defaec8adTony Mak            Phone.CONTACT_ID
5830ff315d60bb44c5cc4223abff48e086defaec8adTony Mak        });
5843c8b50f8dc1c4ce11168fb42a884f604d1810c46Hemant Gupta        // By default order is indexed
5853c8b50f8dc1c4ce11168fb42a884f604d1810c46Hemant Gupta        String orderBy = Phone.CONTACT_ID;
5865006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai        try {
5873c8b50f8dc1c4ce11168fb42a884f604d1810c46Hemant Gupta            if (orderByWhat == BluetoothPbapObexServer.ORDER_BY_ALPHABETICAL) {
5883c8b50f8dc1c4ce11168fb42a884f604d1810c46Hemant Gupta                orderBy = Phone.DISPLAY_NAME;
5893c8b50f8dc1c4ce11168fb42a884f604d1810c46Hemant Gupta            }
5904ca05d6f02264b0eb2983e43d34ca4051434a4d4Ajay Panicker            contactCursor = mResolver.query(myUri, PHONES_CONTACTS_PROJECTION, null, null, orderBy);
5915006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai        } catch (CursorWindowAllocationException e) {
5925006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            Log.e(TAG,
5933c8b50f8dc1c4ce11168fb42a884f604d1810c46Hemant Gupta                "CursorWindowAllocationException while composing phonebook one vcard");
5945006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai        } finally {
5955006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            if (contactCursor != null) {
5963c8b50f8dc1c4ce11168fb42a884f604d1810c46Hemant Gupta                contactIdCursor = ContactCursorFilter.filterByOffset(contactCursor, offset);
5975006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                contactCursor.close();
5983c8b50f8dc1c4ce11168fb42a884f604d1810c46Hemant Gupta                contactCursor = null;
5992b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh            }
6005006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai        }
6015a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta        return composeContactsAndSendVCards(
6025a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                op, contactIdCursor, vcardType21, ownerVCard, ignorefilter, filter);
6030ff315d60bb44c5cc4223abff48e086defaec8adTony Mak    }
6040ff315d60bb44c5cc4223abff48e086defaec8adTony Mak
6050ff315d60bb44c5cc4223abff48e086defaec8adTony Mak    /**
6060ff315d60bb44c5cc4223abff48e086defaec8adTony Mak     * Filter contact cursor by certain condition.
6070ff315d60bb44c5cc4223abff48e086defaec8adTony Mak     */
6085a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta    private static final class ContactCursorFilter {
6090ff315d60bb44c5cc4223abff48e086defaec8adTony Mak        /**
6100ff315d60bb44c5cc4223abff48e086defaec8adTony Mak         *
6110ff315d60bb44c5cc4223abff48e086defaec8adTony Mak         * @param contactCursor
6120ff315d60bb44c5cc4223abff48e086defaec8adTony Mak         * @param offset
6130ff315d60bb44c5cc4223abff48e086defaec8adTony Mak         * @return a cursor containing contact id of {@code offset} contact.
6140ff315d60bb44c5cc4223abff48e086defaec8adTony Mak         */
6150ff315d60bb44c5cc4223abff48e086defaec8adTony Mak        public static Cursor filterByOffset(Cursor contactCursor, int offset) {
6160ff315d60bb44c5cc4223abff48e086defaec8adTony Mak            return filterByRange(contactCursor, offset, offset);
6170ff315d60bb44c5cc4223abff48e086defaec8adTony Mak        }
6180ff315d60bb44c5cc4223abff48e086defaec8adTony Mak
6190ff315d60bb44c5cc4223abff48e086defaec8adTony Mak        /**
6200ff315d60bb44c5cc4223abff48e086defaec8adTony Mak         *
6210ff315d60bb44c5cc4223abff48e086defaec8adTony Mak         * @param contactCursor
6220ff315d60bb44c5cc4223abff48e086defaec8adTony Mak         * @param startPoint
6230ff315d60bb44c5cc4223abff48e086defaec8adTony Mak         * @param endPoint
6240ff315d60bb44c5cc4223abff48e086defaec8adTony Mak         * @return a cursor containing contact ids of {@code startPoint}th to {@code endPoint}th
6250ff315d60bb44c5cc4223abff48e086defaec8adTony Mak         * contact.
6260ff315d60bb44c5cc4223abff48e086defaec8adTony Mak         */
6270ff315d60bb44c5cc4223abff48e086defaec8adTony Mak        public static Cursor filterByRange(Cursor contactCursor, int startPoint, int endPoint) {
6280ff315d60bb44c5cc4223abff48e086defaec8adTony Mak            final int contactIdColumn = contactCursor.getColumnIndex(Data.CONTACT_ID);
6290ff315d60bb44c5cc4223abff48e086defaec8adTony Mak            long previousContactId = -1;
6300ff315d60bb44c5cc4223abff48e086defaec8adTony Mak            // As startPoint, endOffset index starts from 1 to n, we set
6310ff315d60bb44c5cc4223abff48e086defaec8adTony Mak            // currentPoint base as 1 not 0
6320ff315d60bb44c5cc4223abff48e086defaec8adTony Mak            int currentOffset = 1;
6330ff315d60bb44c5cc4223abff48e086defaec8adTony Mak            final MatrixCursor contactIdsCursor = new MatrixCursor(new String[]{
6340ff315d60bb44c5cc4223abff48e086defaec8adTony Mak                    Phone.CONTACT_ID
6350ff315d60bb44c5cc4223abff48e086defaec8adTony Mak            });
6360ff315d60bb44c5cc4223abff48e086defaec8adTony Mak            while (contactCursor.moveToNext() && currentOffset <= endPoint) {
6370ff315d60bb44c5cc4223abff48e086defaec8adTony Mak                long currentContactId = contactCursor.getLong(contactIdColumn);
6380ff315d60bb44c5cc4223abff48e086defaec8adTony Mak                if (previousContactId != currentContactId) {
6390ff315d60bb44c5cc4223abff48e086defaec8adTony Mak                    previousContactId = currentContactId;
6400ff315d60bb44c5cc4223abff48e086defaec8adTony Mak                    if (currentOffset >= startPoint) {
6410ff315d60bb44c5cc4223abff48e086defaec8adTony Mak                        contactIdsCursor.addRow(new Long[]{currentContactId});
6420ff315d60bb44c5cc4223abff48e086defaec8adTony Mak                        if (V) Log.v(TAG, "contactIdsCursor.addRow: " + currentContactId);
6430ff315d60bb44c5cc4223abff48e086defaec8adTony Mak                    }
6440ff315d60bb44c5cc4223abff48e086defaec8adTony Mak                    currentOffset++;
6452b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh                }
6462b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh            }
6470ff315d60bb44c5cc4223abff48e086defaec8adTony Mak            return contactIdsCursor;
6482b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh        }
6492b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh    }
6502b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh
6515006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai    /**
6525006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai     * Handler enterprise contact id in VCardComposer
6535006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai     */
6545006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai    private static class EnterpriseRawContactEntitlesInfoCallback implements
6555006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            VCardComposer.RawContactEntitlesInfoCallback {
6565006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai        @Override
6575006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai        public VCardComposer.RawContactEntitlesInfo getRawContactEntitlesInfo(long contactId) {
6585006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            if (Contacts.isEnterpriseContactId(contactId)) {
6595006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                return new VCardComposer.RawContactEntitlesInfo(RawContactsEntity.CORP_CONTENT_URI,
6605006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                        contactId - Contacts.ENTERPRISE_CONTACT_ID_BASE);
6615006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            } else {
6625006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                return new VCardComposer.RawContactEntitlesInfo(RawContactsEntity.CONTENT_URI, contactId);
6635006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            }
6645006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai        }
6655006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai    }
6665006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai
6675a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta    private final int composeContactsAndSendVCards(Operation op, final Cursor contactIdCursor,
6685006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            final boolean vcardType21, String ownerVCard, boolean ignorefilter, byte[] filter) {
6692f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        long timestamp = 0;
6702f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        if (V) timestamp = System.currentTimeMillis();
6714446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
6725006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai        VCardComposer composer = null;
6735006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai        VCardFilter vcardfilter = new VCardFilter(ignorefilter ? null : filter);
6745f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach
6755006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai        HandlerForStringBuffer buffer = null;
6765006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai        try {
6775006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            // Currently only support Generic Vcard 2.1 and 3.0
6785006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            int vcardType;
6795006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            if (vcardType21) {
6805006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                vcardType = VCardConfig.VCARD_TYPE_V21_GENERIC;
6815006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            } else {
6825006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                vcardType = VCardConfig.VCARD_TYPE_V30_GENERIC;
6835006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            }
6845006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            if (!vcardfilter.isPhotoEnabled()) {
6855006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                vcardType |= VCardConfig.FLAG_REFRAIN_IMAGE_EXPORT;
6865006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            }
6875006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai
6885006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            // Enhancement: customize Vcard based on preferences/settings and
6895006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            // input from caller
6905006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            composer = BluetoothPbapUtils.createFilteredVCardComposer(mContext, vcardType, null);
6915006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            // End enhancement
6925006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai
6935006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            // BT does want PAUSE/WAIT conversion while it doesn't want the
6945006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            // other formatting
6955006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            // done by vCard library by default.
6965006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            composer.setPhoneNumberTranslationCallback(new VCardPhoneNumberTranslationCallback() {
6975006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                public String onValueReceived(String rawValue, int type, String label,
6985006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                        boolean isPrimary) {
6995006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                    // 'p' and 'w' are the standard characters for pause and
7005006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                    // wait
7015006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                    // (see RFC 3601)
7025006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                    // so use those when exporting phone numbers via vCard.
7035006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                    String numberWithControlSequence = rawValue
7045006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                            .replace(PhoneNumberUtils.PAUSE, 'p').replace(PhoneNumberUtils.WAIT,
7055006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                                    'w');
7065006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                    return numberWithControlSequence;
7074a53a55dc10d3a26c94e5844f7d4a2565a67142cfredc                }
7085006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            });
7095006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            buffer = new HandlerForStringBuffer(op, ownerVCard);
7105006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            Log.v(TAG, "contactIdCursor size: " + contactIdCursor.getCount());
7115006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            if (!composer.initWithCallback(contactIdCursor,
7125006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                    new EnterpriseRawContactEntitlesInfoCallback())
7135006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                    || !buffer.onInit(mContext)) {
7145006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
7155006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            }
7164446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
7175006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            while (!composer.isAfterLast()) {
7185006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                if (BluetoothPbapObexServer.sIsAborted) {
7195006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                    ((ServerOperation) op).isAborted = true;
7205006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                    BluetoothPbapObexServer.sIsAborted = false;
7215006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                    break;
7225006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                }
7235006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                String vcard = composer.createOneEntry();
7245006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                if (vcard == null) {
7255006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                    Log.e(TAG,
7265006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                            "Failed to read a contact. Error reason: " + composer.getErrorReason());
7272f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                    return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
7284446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                }
7295006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                if (V) Log.v(TAG, "vCard from composer: " + vcard);
730198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa
7315006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                vcard = vcardfilter.apply(vcard, vcardType21);
7325006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                vcard = StripTelephoneNumber(vcard);
7335f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach
7345006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                if (V) Log.v(TAG, "vCard after cleanup: " + vcard);
735c7a57f31515107366589bd6875c3cc4af1fc806efredc
7365006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                if (!buffer.onEntryCreated(vcard)) {
7375006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                    // onEntryCreate() already emits error.
7385006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                    return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
7393c4d2c77c2fffe675fbe89ba58856686b6873d2fDaisuke Miyakawa                }
7404446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            }
7415006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai        } finally {
7425006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            if (composer != null) {
7435006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                composer.terminate();
7445006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            }
7455006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            if (buffer != null) {
7465006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                buffer.onTerminate();
7475006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            }
7485006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai        }
7493c4d2c77c2fffe675fbe89ba58856686b6873d2fDaisuke Miyakawa
7505006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai        if (V) Log.v(TAG, "Total vcard composing and sending out takes "
7515006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                    + (System.currentTimeMillis() - timestamp) + " ms");
752198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa
7535006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai        return ResponseCodes.OBEX_HTTP_OK;
7545006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai    }
7555006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai
7565a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta    private final int composeContactsAndSendSelectedVCards(Operation op,
7575a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            final Cursor contactIdCursor, final boolean vcardType21, String ownerVCard,
7585a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            int needSendBody, int pbSize, boolean ignorefilter, byte[] filter, byte[] selector,
7595a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            String vcardselectorop) {
7605006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai        long timestamp = 0;
7615006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai        if (V) timestamp = System.currentTimeMillis();
7625006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai
7635a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta        VCardComposer composer = null;
7645a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta        VCardFilter vcardfilter = new VCardFilter(ignorefilter ? null : filter);
7655a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta        PropertySelector vcardselector = new PropertySelector(selector);
7665a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta
7675006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai        HandlerForStringBuffer buffer = null;
7685a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta
7695006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai        try {
7705a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            // Currently only support Generic Vcard 2.1 and 3.0
7715a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            int vcardType;
7725a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            if (vcardType21) {
7735a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                vcardType = VCardConfig.VCARD_TYPE_V21_GENERIC;
7745a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            } else {
7755a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                vcardType = VCardConfig.VCARD_TYPE_V30_GENERIC;
7765a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            }
7775a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            if (!vcardfilter.isPhotoEnabled()) {
7785a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                vcardType |= VCardConfig.FLAG_REFRAIN_IMAGE_EXPORT;
7795a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            }
7805006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai
7815a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            // Enhancement: customize Vcard based on preferences/settings and
7825a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            // input from caller
7835a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            composer = BluetoothPbapUtils.createFilteredVCardComposer(mContext, vcardType, null);
7845a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            // End enhancement
7855a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta
7865a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            /* BT does want PAUSE/WAIT conversion while it doesn't want the
7875a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta             * other formatting done by vCard library by default. */
7885a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            composer.setPhoneNumberTranslationCallback(new VCardPhoneNumberTranslationCallback() {
7895a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                public String onValueReceived(
7905a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                        String rawValue, int type, String label, boolean isPrimary) {
7915a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                    /* 'p' and 'w' are the standard characters for pause and wait
7925a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                     * (see RFC 3601) so use those when exporting phone numbers via vCard.*/
7935a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                    String numberWithControlSequence = rawValue.replace(PhoneNumberUtils.PAUSE, 'p')
7945a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                                                               .replace(PhoneNumberUtils.WAIT, 'w');
7955a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                    return numberWithControlSequence;
7965a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                }
7975a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            });
7985006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            buffer = new HandlerForStringBuffer(op, ownerVCard);
7995a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            Log.v(TAG, "contactIdCursor size: " + contactIdCursor.getCount());
8005a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            if (!composer.initWithCallback(
8015a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                        contactIdCursor, new EnterpriseRawContactEntitlesInfoCallback())
8025006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                    || !buffer.onInit(mContext)) {
8035006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
8045006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            }
805c7a57f31515107366589bd6875c3cc4af1fc806efredc
8065006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            while (!composer.isAfterLast()) {
8075006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                if (BluetoothPbapObexServer.sIsAborted) {
8085006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                    ((ServerOperation) op).isAborted = true;
8095006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                    BluetoothPbapObexServer.sIsAborted = false;
8105006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                    break;
811198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa                }
8125a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                String vcard = composer.createOneEntry();
8135006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                if (vcard == null) {
8145006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                    Log.e(TAG,
8155006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                            "Failed to read a contact. Error reason: " + composer.getErrorReason());
8165006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                    return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
817198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa                }
8185a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                if (V) Log.v(TAG, "Checking selected bits in the vcard composer" + vcard);
8195a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta
8205a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                if (!vcardselector.CheckVcardSelector(vcard, vcardselectorop)) {
8215a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                    Log.e(TAG, "vcard selector check fail");
8225a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                    vcard = null;
8235a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                    pbSize--;
8245a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                    continue;
8253c4d2c77c2fffe675fbe89ba58856686b6873d2fDaisuke Miyakawa                }
8265006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai
8275a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                Log.e(TAG, "vcard selector check pass");
8285a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta
8295a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                if (needSendBody == NEED_SEND_BODY) {
8305a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                    vcard = vcardfilter.apply(vcard, vcardType21);
8315a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                    vcard = StripTelephoneNumber(vcard);
8325a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta
8335a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                    if (V) Log.v(TAG, "vCard after cleanup: " + vcard);
8345a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta
8355a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                    if (!buffer.onEntryCreated(vcard)) {
8365a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                        // onEntryCreate() already emits error.
8375a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                        return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
8385a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                    }
8395a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                }
8405a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            }
8415a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta
8425a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            if (needSendBody != NEED_SEND_BODY) return pbSize;
8435a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta        } finally {
8445a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            if (composer != null) {
8455a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                composer.terminate();
8465a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            }
8475a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            if (buffer != null) {
8485a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                buffer.onTerminate();
8495a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            }
8505a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta        }
8515a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta
8525a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta        if (V)
8535a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            Log.v(TAG, "Total vcard composing and sending out takes "
8545a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                            + (System.currentTimeMillis() - timestamp) + " ms");
8555a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta
8565a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta        return ResponseCodes.OBEX_HTTP_OK;
8575a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta    }
8585a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta
8595a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta    private final int composeCallLogsAndSendSelectedVCards(Operation op, final String selection,
8605a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            final boolean vcardType21, int needSendBody, int pbSize, String ownerVCard,
8615a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            boolean ignorefilter, byte[] filter, byte[] selector, String vcardselectorop,
8625a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            boolean vCardSelct) {
8635a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta        long timestamp = 0;
8645a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta        if (V) timestamp = System.currentTimeMillis();
8655a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta
8665a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta        BluetoothPbapCallLogComposer composer = null;
8675a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta        HandlerForStringBuffer buffer = null;
8685a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta
8695a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta        try {
8705a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            VCardFilter vcardfilter = new VCardFilter(ignorefilter ? null : filter);
8715a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            PropertySelector vcardselector = new PropertySelector(selector);
8725a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            composer = new BluetoothPbapCallLogComposer(mContext);
8735a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            buffer = new HandlerForStringBuffer(op, ownerVCard);
8745a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            if (!composer.init(CallLog.Calls.CONTENT_URI, selection, null, CALLLOG_SORT_ORDER)
8755a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                    || !buffer.onInit(mContext)) {
8765a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
8775a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            }
8785a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta
8795a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            while (!composer.isAfterLast()) {
8805a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                if (BluetoothPbapObexServer.sIsAborted) {
8815a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                    ((ServerOperation) op).isAborted = true;
8825a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                    BluetoothPbapObexServer.sIsAborted = false;
8835a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                    break;
8845a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                }
8855a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                String vcard = composer.createOneEntry(vcardType21);
8865a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                if (vCardSelct) {
8875a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                    if (!vcardselector.CheckVcardSelector(vcard, vcardselectorop)) {
8885a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                        Log.e(TAG, "Checking vcard selector for call log");
8895a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                        vcard = null;
8905a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                        pbSize--;
8915a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                        continue;
8925a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                    }
8935a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                    if (needSendBody == NEED_SEND_BODY) {
8945a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                        if (vcard != null) {
8955a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                            vcard = vcardfilter.apply(vcard, vcardType21);
8965a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                        }
8975a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                        if (vcard == null) {
8985a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                            Log.e(TAG, "Failed to read a contact. Error reason: "
8995a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                                            + composer.getErrorReason());
9005a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                            return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
9015a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                        }
9025a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                        if (V) {
9035a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                            Log.v(TAG, "Vcard Entry:");
9045a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                            Log.v(TAG, vcard);
9055a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                        }
9065a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                        buffer.onEntryCreated(vcard);
9075a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                    }
9085a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                } else {
9095a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                    if (vcard == null) {
9105a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                        Log.e(TAG, "Failed to read a contact. Error reason: "
9115a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                                        + composer.getErrorReason());
9125a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                        return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
9135a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                    }
9145a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                    if (V) {
9155a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                        Log.v(TAG, "Vcard Entry:");
9165a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                        Log.v(TAG, vcard);
9175a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                    }
9185a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                    buffer.onEntryCreated(vcard);
9195a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                }
9205006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            }
9215a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            if (needSendBody != NEED_SEND_BODY && vCardSelct) return pbSize;
9225006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai        } finally {
9235006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            if (composer != null) {
9245006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                composer.terminate();
9255006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            }
9265006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            if (buffer != null) {
9275006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                buffer.onTerminate();
9284446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            }
9294446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        }
9304446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
9312f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        if (V) Log.v(TAG, "Total vcard composing and sending out takes "
9325006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                + (System.currentTimeMillis() - timestamp) + " ms");
9332f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        return ResponseCodes.OBEX_HTTP_OK;
9344446eaa935994bc91d6d308303e8d27526b4590dLixin Yue    }
9354446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
93629ab94a024ffce08229f1c2c6776d1e72d2a3f75Hemant Gupta    public String StripTelephoneNumber (String vCard){
93729ab94a024ffce08229f1c2c6776d1e72d2a3f75Hemant Gupta        String attr [] = vCard.split(System.getProperty("line.separator"));
93829ab94a024ffce08229f1c2c6776d1e72d2a3f75Hemant Gupta        String Vcard = "";
93929ab94a024ffce08229f1c2c6776d1e72d2a3f75Hemant Gupta            for (int i=0; i < attr.length; i++) {
94029ab94a024ffce08229f1c2c6776d1e72d2a3f75Hemant Gupta                if(attr[i].startsWith("TEL")) {
94129ab94a024ffce08229f1c2c6776d1e72d2a3f75Hemant Gupta                    attr[i] = attr[i].replace("(", "");
94229ab94a024ffce08229f1c2c6776d1e72d2a3f75Hemant Gupta                    attr[i] = attr[i].replace(")", "");
94329ab94a024ffce08229f1c2c6776d1e72d2a3f75Hemant Gupta                    attr[i] = attr[i].replace("-", "");
94429ab94a024ffce08229f1c2c6776d1e72d2a3f75Hemant Gupta                    attr[i] = attr[i].replace(" ", "");
94529ab94a024ffce08229f1c2c6776d1e72d2a3f75Hemant Gupta                }
94629ab94a024ffce08229f1c2c6776d1e72d2a3f75Hemant Gupta            }
94729ab94a024ffce08229f1c2c6776d1e72d2a3f75Hemant Gupta
94829ab94a024ffce08229f1c2c6776d1e72d2a3f75Hemant Gupta            for (int i=0; i < attr.length; i++) {
94929ab94a024ffce08229f1c2c6776d1e72d2a3f75Hemant Gupta                if(!attr[i].equals("")){
95029ab94a024ffce08229f1c2c6776d1e72d2a3f75Hemant Gupta                    Vcard = Vcard.concat(attr[i] + "\n");
95129ab94a024ffce08229f1c2c6776d1e72d2a3f75Hemant Gupta                }
95229ab94a024ffce08229f1c2c6776d1e72d2a3f75Hemant Gupta            }
95302fc1acb99dbf3ae0a710ee7e4b6de8dd779e84eRakesh Iyer        if (V) Log.v(TAG, "Vcard with stripped telephone no.: " + Vcard);
95429ab94a024ffce08229f1c2c6776d1e72d2a3f75Hemant Gupta        return Vcard;
95529ab94a024ffce08229f1c2c6776d1e72d2a3f75Hemant Gupta    }
95629ab94a024ffce08229f1c2c6776d1e72d2a3f75Hemant Gupta
9572f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue    /**
958ce8d51a3a43d113a4a6bad30d595c2a81d0f623cYoshiharu Kurita     * Handler to emit vCards to PCE.
9592f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue     */
9603c4d2c77c2fffe675fbe89ba58856686b6873d2fDaisuke Miyakawa    public class HandlerForStringBuffer {
9612f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        private Operation operation;
9624446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
9632f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        private OutputStream outputStream;
9642f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue
9652f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        private String phoneOwnVCard = null;
9662f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue
9672f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        public HandlerForStringBuffer(Operation op, String ownerVCard) {
9682f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            operation = op;
9692f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            if (ownerVCard != null) {
9702f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                phoneOwnVCard = ownerVCard;
9712f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                if (V) Log.v(TAG, "phone own number vcard:");
9722f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                if (V) Log.v(TAG, phoneOwnVCard);
9732c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            }
9742c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
9752c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
976ce8d51a3a43d113a4a6bad30d595c2a81d0f623cYoshiharu Kurita        private boolean write(String vCard) {
977ce8d51a3a43d113a4a6bad30d595c2a81d0f623cYoshiharu Kurita            try {
978ce8d51a3a43d113a4a6bad30d595c2a81d0f623cYoshiharu Kurita                if (vCard != null) {
979ce8d51a3a43d113a4a6bad30d595c2a81d0f623cYoshiharu Kurita                    outputStream.write(vCard.getBytes());
980ce8d51a3a43d113a4a6bad30d595c2a81d0f623cYoshiharu Kurita                    return true;
981ce8d51a3a43d113a4a6bad30d595c2a81d0f623cYoshiharu Kurita                }
982ce8d51a3a43d113a4a6bad30d595c2a81d0f623cYoshiharu Kurita            } catch (IOException e) {
983ce8d51a3a43d113a4a6bad30d595c2a81d0f623cYoshiharu Kurita                Log.e(TAG, "write outputstrem failed" + e.toString());
984ce8d51a3a43d113a4a6bad30d595c2a81d0f623cYoshiharu Kurita            }
985ce8d51a3a43d113a4a6bad30d595c2a81d0f623cYoshiharu Kurita            return false;
986ce8d51a3a43d113a4a6bad30d595c2a81d0f623cYoshiharu Kurita        }
987ce8d51a3a43d113a4a6bad30d595c2a81d0f623cYoshiharu Kurita
9882f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        public boolean onInit(Context context) {
9892f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            try {
9902f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                outputStream = operation.openOutputStream();
9912f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                if (phoneOwnVCard != null) {
992ce8d51a3a43d113a4a6bad30d595c2a81d0f623cYoshiharu Kurita                    return write(phoneOwnVCard);
9932c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                }
994ce8d51a3a43d113a4a6bad30d595c2a81d0f623cYoshiharu Kurita                return true;
9952f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            } catch (IOException e) {
9962f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                Log.e(TAG, "open outputstrem failed" + e.toString());
9972c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            }
998ce8d51a3a43d113a4a6bad30d595c2a81d0f623cYoshiharu Kurita            return false;
9992c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
10002c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
10012f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        public boolean onEntryCreated(String vcard) {
1002ce8d51a3a43d113a4a6bad30d595c2a81d0f623cYoshiharu Kurita            return write(vcard);
10032c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
10042c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
10052f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        public void onTerminate() {
10062f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            if (!BluetoothPbapObexServer.closeStream(outputStream, operation)) {
10072f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                if (V) Log.v(TAG, "CloseStream failed!");
10082c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            } else {
10092f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                if (V) Log.v(TAG, "CloseStream ok!");
10102c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            }
10112c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
10122c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    }
10136db8e703719f301f75acdf4acacc3296cc1b5016Hemant Gupta
10145f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach    public static class VCardFilter {
10155f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach        private static enum FilterBit {
10165211519fa7617f3e34b214264f59157db9f495aaSmriti Gupta            //       bit  property                  onlyCheckV21  excludeForV21
10175211519fa7617f3e34b214264f59157db9f495aaSmriti Gupta            FN (       1, "FN",                       true,         false),
10185211519fa7617f3e34b214264f59157db9f495aaSmriti Gupta            PHOTO(     3, "PHOTO",                    false,        false),
10195211519fa7617f3e34b214264f59157db9f495aaSmriti Gupta            BDAY(      4, "BDAY",                     false,        false),
10205211519fa7617f3e34b214264f59157db9f495aaSmriti Gupta            ADR(       5, "ADR",                      false,        false),
10215211519fa7617f3e34b214264f59157db9f495aaSmriti Gupta            EMAIL(     8, "EMAIL",                    false,        false),
10225211519fa7617f3e34b214264f59157db9f495aaSmriti Gupta            TITLE(    12, "TITLE",                    false,        false),
10235211519fa7617f3e34b214264f59157db9f495aaSmriti Gupta            ORG(      16, "ORG",                      false,        false),
10245211519fa7617f3e34b214264f59157db9f495aaSmriti Gupta            NOTE(     17, "NOTE",                     false,        false),
10255211519fa7617f3e34b214264f59157db9f495aaSmriti Gupta            URL(      20, "URL",                      false,        false),
10265211519fa7617f3e34b214264f59157db9f495aaSmriti Gupta            NICKNAME( 23, "NICKNAME",                 false,        true),
10275211519fa7617f3e34b214264f59157db9f495aaSmriti Gupta            DATETIME( 28, "X-IRMC-CALL-DATETIME",     false,        false);
10285f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach
10295f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach            public final int pos;
10305f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach            public final String prop;
10315f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach            public final boolean onlyCheckV21;
10325f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach            public final boolean excludeForV21;
10335f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach
10345f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach            FilterBit(int pos, String prop, boolean onlyCheckV21, boolean excludeForV21) {
10355f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach                this.pos = pos;
10365f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach                this.prop = prop;
10375f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach                this.onlyCheckV21 = onlyCheckV21;
10385f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach                this.excludeForV21 = excludeForV21;
10395f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach            }
10405f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach        }
10415f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach
10425f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach        private static final String SEPARATOR = System.getProperty("line.separator");
10435f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach        private final byte[] filter;
10445f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach
1045976a53f0f946e589aa2b5204ce3262abcf2afc55Hemant Gupta        //This function returns true if the attributes needs to be included in the filtered vcard.
1046976a53f0f946e589aa2b5204ce3262abcf2afc55Hemant Gupta        private boolean isFilteredIn(FilterBit bit, boolean vCardType21) {
10475f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach            final int offset = (bit.pos / 8) + 1;
10485f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach            final int bit_pos = bit.pos % 8;
1049976a53f0f946e589aa2b5204ce3262abcf2afc55Hemant Gupta            if (!vCardType21 && bit.onlyCheckV21) return true;
1050976a53f0f946e589aa2b5204ce3262abcf2afc55Hemant Gupta            if (vCardType21 && bit.excludeForV21) return false;
1051976a53f0f946e589aa2b5204ce3262abcf2afc55Hemant Gupta            if (filter == null || offset >= filter.length) return true;
10525f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach            return ((filter[filter.length - offset] >> bit_pos) & 0x01) != 0;
10535f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach        }
10545f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach
10555f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach        VCardFilter(byte[] filter) {
10565f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach            this.filter = filter;
10575f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach        }
10585f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach
10595f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach        public boolean isPhotoEnabled() {
1060976a53f0f946e589aa2b5204ce3262abcf2afc55Hemant Gupta            return isFilteredIn(FilterBit.PHOTO, false);
10615f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach        }
10625f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach
10635f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach        public String apply(String vCard, boolean vCardType21){
10645f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach            if (filter == null) return vCard;
10655f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach            String lines[] = vCard.split(SEPARATOR);
10665f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach            StringBuilder filteredVCard = new StringBuilder();
1067976a53f0f946e589aa2b5204ce3262abcf2afc55Hemant Gupta            boolean filteredIn = false;
10685f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach
10695f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach            for (String line : lines) {
10705f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach                // Check whether the current property is changing (ignoring multi-line properties)
10715f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach                // and determine if the current property is filtered in.
10725f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach                if (!Character.isWhitespace(line.charAt(0)) && !line.startsWith("=")) {
10735f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach                    String currentProp = line.split("[;:]")[0];
1074976a53f0f946e589aa2b5204ce3262abcf2afc55Hemant Gupta                    filteredIn = true;
10755f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach
10765f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach                    for (FilterBit bit : FilterBit.values()) {
10775f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach                        if (bit.prop.equals(currentProp)) {
1078976a53f0f946e589aa2b5204ce3262abcf2afc55Hemant Gupta                            filteredIn = isFilteredIn(bit, vCardType21);
10795f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach                            break;
10806db8e703719f301f75acdf4acacc3296cc1b5016Hemant Gupta                        }
10816db8e703719f301f75acdf4acacc3296cc1b5016Hemant Gupta                    }
10826db8e703719f301f75acdf4acacc3296cc1b5016Hemant Gupta
10835f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach                    // Since PBAP does not have filter bits for IM and SIP,
10845f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach                    // exclude them by default. Easiest way is to exclude all
10855211519fa7617f3e34b214264f59157db9f495aaSmriti Gupta                    // X- fields, except date time....
10865211519fa7617f3e34b214264f59157db9f495aaSmriti Gupta                    if (currentProp.startsWith("X-")) {
10875211519fa7617f3e34b214264f59157db9f495aaSmriti Gupta                        filteredIn = false;
10885211519fa7617f3e34b214264f59157db9f495aaSmriti Gupta                        if (currentProp.equals("X-IRMC-CALL-DATETIME")) {
10895211519fa7617f3e34b214264f59157db9f495aaSmriti Gupta                            filteredIn = true;
10905211519fa7617f3e34b214264f59157db9f495aaSmriti Gupta                        }
10915211519fa7617f3e34b214264f59157db9f495aaSmriti Gupta                    }
10926db8e703719f301f75acdf4acacc3296cc1b5016Hemant Gupta                }
10936db8e703719f301f75acdf4acacc3296cc1b5016Hemant Gupta
10945f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach                // Build filtered vCard
10955211519fa7617f3e34b214264f59157db9f495aaSmriti Gupta                if (filteredIn) {
10965211519fa7617f3e34b214264f59157db9f495aaSmriti Gupta                    filteredVCard.append(line + SEPARATOR);
10975211519fa7617f3e34b214264f59157db9f495aaSmriti Gupta                }
10986db8e703719f301f75acdf4acacc3296cc1b5016Hemant Gupta            }
10996db8e703719f301f75acdf4acacc3296cc1b5016Hemant Gupta
11005f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach            return filteredVCard.toString();
11016db8e703719f301f75acdf4acacc3296cc1b5016Hemant Gupta        }
11026db8e703719f301f75acdf4acacc3296cc1b5016Hemant Gupta    }
11035006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai
11045a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta    private static class PropertySelector {
11055a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta        private static enum PropertyMask {
11065a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            //               bit    property
11075a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            VERSION(0, "VERSION"),
11085a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            FN(1, "FN"),
11095a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            NAME(2, "N"),
11105a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            PHOTO(3, "PHOTO"),
11115a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            BDAY(4, "BDAY"),
11125a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            ADR(5, "ADR"),
11135a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            LABEL(6, "LABEL"),
11145a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            TEL(7, "TEL"),
11155a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            EMAIL(8, "EMAIL"),
11165a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            TITLE(12, "TITLE"),
11175a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            ORG(16, "ORG"),
11185a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            NOTE(17, "NOTE"),
11195a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            URL(20, "URL"),
11205a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            NICKNAME(23, "NICKNAME"),
11215a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            DATETIME(28, "DATETIME");
11225a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta
11235a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            public final int pos;
11245a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            public final String prop;
11255a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta
11265a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            PropertyMask(int pos, String prop) {
11275a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                this.pos = pos;
11285a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                this.prop = prop;
11295a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            }
11305a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta        }
11315a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta
11325a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta        private static final String SEPARATOR = System.getProperty("line.separator");
11335a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta        private final byte[] selector;
11345a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta
11355a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta        PropertySelector(byte[] selector) {
11365a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            this.selector = selector;
11375a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta        }
11385a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta
11395a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta        private boolean checkbit(int attr_bit, byte[] selector) {
11405a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            int selectorlen = selector.length;
11415a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            if (((selector[selectorlen - 1 - ((int) attr_bit / 8)] >> (attr_bit % 8)) & 0x01)
11425a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                    == 0) {
11435a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                return false;
11445a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            }
11455a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            return true;
11465a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta        }
11475a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta
11485a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta        private boolean checkprop(String vcard, String prop) {
11495a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            String lines[] = vcard.split(SEPARATOR);
11505a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            boolean isPresent = false;
11515a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            for (String line : lines) {
11525a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                if (!Character.isWhitespace(line.charAt(0)) && !line.startsWith("=")) {
11535a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                    String currentProp = line.split("[;:]")[0];
11545a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                    if (prop.equals(currentProp)) {
11555a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                        Log.d(TAG, "bit.prop.equals current prop :" + prop);
11565a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                        isPresent = true;
11575a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                        return isPresent;
11585a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                    }
11595a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                }
11605a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            }
11615a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta
11625a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            return isPresent;
11635a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta        }
11645a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta
11655a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta        private boolean CheckVcardSelector(String vcard, String vcardselectorop) {
11665a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            boolean selectedIn = true;
11675a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta
11685a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            for (PropertyMask bit : PropertyMask.values()) {
11695a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                if (checkbit(bit.pos, selector)) {
11705a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                    Log.d(TAG, "checking for prop :" + bit.prop);
11715a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                    if (vcardselectorop.equals("0")) {
11725a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                        if (checkprop(vcard, bit.prop)) {
11735a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                            Log.d(TAG, "bit.prop.equals current prop :" + bit.prop);
11745a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                            selectedIn = true;
11755a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                            break;
11765a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                        } else {
11775a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                            selectedIn = false;
11785a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                        }
11795a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                    } else if (vcardselectorop.equals("1")) {
11805a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                        if (!checkprop(vcard, bit.prop)) {
11815a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                            Log.d(TAG, "bit.prop.notequals current prop" + bit.prop);
11825a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                            selectedIn = false;
11835a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                            return selectedIn;
11845a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                        } else {
11855a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                            selectedIn = true;
11865a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                        }
11875a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                    }
11885a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                }
11895a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            }
11905a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            return selectedIn;
11915a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta        }
11925a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta
11935a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta        private String getName(String vcard) {
11945a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            String lines[] = vcard.split(SEPARATOR);
11955a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            String name = "";
11965a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            for (String line : lines) {
11975a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                if (!Character.isWhitespace(line.charAt(0)) && !line.startsWith("=")) {
11985a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                    if (line.startsWith("N:"))
11995a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                        name = line.substring(line.lastIndexOf(':'), line.length());
12005a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta                }
12015a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            }
12025a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            Log.d(TAG, "returning name: " + name);
12035a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta            return name;
12045a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta        }
12055a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta    }
12065a37bc407ab1b8844c3541ff4e6653635b108bedHemant Gupta
12075006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai    private static final Uri getPhoneLookupFilterUri() {
12085006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai        return PhoneLookup.ENTERPRISE_CONTENT_FILTER_URI;
12095006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai    }
1210c438463431b171a67b22b50886ef8dd737c44004Andre Eisenbach
12115006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai    /**
12125006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai     * Get size of the cursor without duplicated contact id. This assumes the
12136a50944dff2081fc161974cfae7d85d834b123cfSmriti Gupta     * given cursor is sorted by CONTACT_ID.
12145006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai     */
1215c438463431b171a67b22b50886ef8dd737c44004Andre Eisenbach    private static final int getDistinctContactIdSize(Cursor cursor) {
1216c438463431b171a67b22b50886ef8dd737c44004Andre Eisenbach        final int contactIdColumn = cursor.getColumnIndex(Data.CONTACT_ID);
1217c438463431b171a67b22b50886ef8dd737c44004Andre Eisenbach        final int idColumn = cursor.getColumnIndex(Data._ID);
12185006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai        long previousContactId = -1;
12195006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai        int count = 0;
12205006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai        cursor.moveToPosition(-1);
12215006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai        while (cursor.moveToNext()) {
1222c438463431b171a67b22b50886ef8dd737c44004Andre Eisenbach            final long contactId = cursor.getLong(contactIdColumn != -1 ? contactIdColumn : idColumn);
12235006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            if (previousContactId != contactId) {
12245006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                count++;
12255006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                previousContactId = contactId;
12265006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            }
12275006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai        }
12285006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai        if (V) {
12295006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            Log.i(TAG, "getDistinctContactIdSize result: " + count);
12305006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai        }
12315006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai        return count;
12325006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai    }
12335006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai
12345006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai    /**
1235c438463431b171a67b22b50886ef8dd737c44004Andre Eisenbach     * Append "display_name,contact_id" string array from cursor to ArrayList.
1236c438463431b171a67b22b50886ef8dd737c44004Andre Eisenbach     * This assumes the given cursor is sorted by CONTACT_ID.
12375006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai     */
12385006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai    private static void appendDistinctNameIdList(ArrayList<String> resultList,
1239c438463431b171a67b22b50886ef8dd737c44004Andre Eisenbach            String defaultName, Cursor cursor) {
1240c438463431b171a67b22b50886ef8dd737c44004Andre Eisenbach        final int contactIdColumn = cursor.getColumnIndex(Data.CONTACT_ID);
1241c438463431b171a67b22b50886ef8dd737c44004Andre Eisenbach        final int idColumn = cursor.getColumnIndex(Data._ID);
1242c438463431b171a67b22b50886ef8dd737c44004Andre Eisenbach        final int nameColumn = cursor.getColumnIndex(Data.DISPLAY_NAME);
12435006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai        cursor.moveToPosition(-1);
12445006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai        while (cursor.moveToNext()) {
1245c438463431b171a67b22b50886ef8dd737c44004Andre Eisenbach            final long contactId = cursor.getLong(contactIdColumn != -1 ? contactIdColumn : idColumn);
1246c438463431b171a67b22b50886ef8dd737c44004Andre Eisenbach            String displayName = nameColumn != -1 ? cursor.getString(nameColumn) : defaultName;
12475006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            if (TextUtils.isEmpty(displayName)) {
12485006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                displayName = defaultName;
12495006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            }
12505006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai
12516a50944dff2081fc161974cfae7d85d834b123cfSmriti Gupta            String newString = displayName + "," + contactId;
12526a50944dff2081fc161974cfae7d85d834b123cfSmriti Gupta            if (!resultList.contains(newString)) {
12536a50944dff2081fc161974cfae7d85d834b123cfSmriti Gupta                resultList.add(newString);
12545006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            }
12555006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai        }
12565006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai        if (V) {
12575006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            for (String nameId : resultList) {
12585006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                Log.i(TAG, "appendDistinctNameIdList result: " + nameId);
12595006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            }
12605006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai        }
12615006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai    }
12622c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan}
1263