1b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh/*
2b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh * Copyright (c) 2008-2009, Motorola, Inc.
3b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh *
4b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh * All rights reserved.
5b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh *
6b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh * Redistribution and use in source and binary forms, with or without
7b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh * modification, are permitted provided that the following conditions are met:
8b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh *
9b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh * - Redistributions of source code must retain the above copyright notice,
10b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh * this list of conditions and the following disclaimer.
11b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh *
12b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh * - Redistributions in binary form must reproduce the above copyright notice,
13b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh * this list of conditions and the following disclaimer in the documentation
14b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh * and/or other materials provided with the distribution.
15b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh *
16b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh * - Neither the name of the Motorola, Inc. nor the names of its contributors
17b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh * may be used to endorse or promote products derived from this software
18b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh * without specific prior written permission.
19b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh *
20b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
24b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh * POSSIBILITY OF SUCH DAMAGE.
31b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh */
322c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
332c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fanpackage com.android.bluetooth.pbap;
342c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
352f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yueimport android.content.Context;
36ff33061e763656438daea7249e45e38b8a174288kschulzimport android.content.ContentResolver;
37ff33061e763656438daea7249e45e38b8a174288kschulzimport android.database.Cursor;
382c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fanimport android.os.Message;
392c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fanimport android.os.Handler;
402f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yueimport android.provider.CallLog.Calls;
412f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yueimport android.provider.CallLog;
42ff33061e763656438daea7249e45e38b8a174288kschulzimport android.text.TextUtils;
43ff33061e763656438daea7249e45e38b8a174288kschulzimport android.util.Log;
442c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
452c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fanimport java.io.IOException;
462c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fanimport java.io.OutputStream;
47e479e18951a375a548e617e86e3b1b7d121351a1Fredimport java.text.CharacterIterator;
48e479e18951a375a548e617e86e3b1b7d121351a1Fredimport java.text.StringCharacterIterator;
492c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fanimport java.util.ArrayList;
504446eaa935994bc91d6d308303e8d27526b4590dLixin Yueimport java.util.Arrays;
512c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
522c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fanimport javax.obex.ServerRequestHandler;
532c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fanimport javax.obex.ResponseCodes;
542c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fanimport javax.obex.ApplicationParameter;
550b1b0069658326e8c12dc0f887e4319c5227feb5Lixin Yueimport javax.obex.ServerOperation;
562c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fanimport javax.obex.Operation;
572c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fanimport javax.obex.HeaderSet;
582c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
592c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fanpublic class BluetoothPbapObexServer extends ServerRequestHandler {
602c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
612c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    private static final String TAG = "BluetoothPbapObexServer";
622c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
634446eaa935994bc91d6d308303e8d27526b4590dLixin Yue    private static final boolean D = BluetoothPbapService.DEBUG;
644446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
654446eaa935994bc91d6d308303e8d27526b4590dLixin Yue    private static final boolean V = BluetoothPbapService.VERBOSE;
662c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
674446eaa935994bc91d6d308303e8d27526b4590dLixin Yue    private static final int UUID_LENGTH = 16;
682c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
69d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue    // The length of suffix of vcard name - ".vcf" is 5
70d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue    private static final int VCARD_NAME_SUFFIX_LENGTH = 5;
712c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
722c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    // 128 bit UUID for PBAP
732c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    private static final byte[] PBAP_TARGET = new byte[] {
742c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            0x79, 0x61, 0x35, (byte)0xf0, (byte)0xf0, (byte)0xc5, 0x11, (byte)0xd8, 0x09, 0x66,
752c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            0x08, 0x00, 0x20, 0x0c, (byte)0x9a, 0x66
762c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    };
772c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
784446eaa935994bc91d6d308303e8d27526b4590dLixin Yue    // Currently not support SIM card
79d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue    private static final String[] LEGAL_PATH = {
802c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            "/telecom", "/telecom/pb", "/telecom/ich", "/telecom/och", "/telecom/mch",
814446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            "/telecom/cch"
824446eaa935994bc91d6d308303e8d27526b4590dLixin Yue    };
834446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
844446eaa935994bc91d6d308303e8d27526b4590dLixin Yue    @SuppressWarnings("unused")
854446eaa935994bc91d6d308303e8d27526b4590dLixin Yue    private static final String[] LEGAL_PATH_WITH_SIM = {
864446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            "/telecom", "/telecom/pb", "/telecom/ich", "/telecom/och", "/telecom/mch",
872c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            "/telecom/cch", "/SIM1", "/SIM1/telecom", "/SIM1/telecom/ich", "/SIM1/telecom/och",
882c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            "/SIM1/telecom/mch", "/SIM1/telecom/cch", "/SIM1/telecom/pb"
894446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
902c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    };
912c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
924446eaa935994bc91d6d308303e8d27526b4590dLixin Yue    // SIM card
934446eaa935994bc91d6d308303e8d27526b4590dLixin Yue    private static final String SIM1 = "SIM1";
944446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
952c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    // missed call history
962c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    private static final String MCH = "mch";
972c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
982c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    // incoming call history
992c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    private static final String ICH = "ich";
1002c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
1012c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    // outgoing call history
1022c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    private static final String OCH = "och";
1032c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
1042c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    // combined call history
1052c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    private static final String CCH = "cch";
1062c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
1072c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    // phone book
1082c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    private static final String PB = "pb";
1092c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
110b99a8af5a27318bb5ae3745531d5a2175370b892Hemant Gupta    private static final String TELECOM_PATH = "/telecom";
111b99a8af5a27318bb5ae3745531d5a2175370b892Hemant Gupta
1122c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    private static final String ICH_PATH = "/telecom/ich";
1132c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
1142c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    private static final String OCH_PATH = "/telecom/och";
1152c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
1162c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    private static final String MCH_PATH = "/telecom/mch";
1172c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
1182c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    private static final String CCH_PATH = "/telecom/cch";
1192c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
1202c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    private static final String PB_PATH = "/telecom/pb";
1212c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
1222c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    // type for list vcard objects
1232c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    private static final String TYPE_LISTING = "x-bt/vcard-listing";
1242c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
1252c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    // type for get single vcard object
1262c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    private static final String TYPE_VCARD = "x-bt/vcard";
1272c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
1284446eaa935994bc91d6d308303e8d27526b4590dLixin Yue    // to indicate if need send body besides headers
129d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue    private static final int NEED_SEND_BODY = -1;
130d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue
1312c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    // type for download all vcard objects
1322c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    private static final String TYPE_PB = "x-bt/phonebook";
1332c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
134d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue    // The number of indexes in the phone book.
135d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue    private boolean mNeedPhonebookSize = false;
1362c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
137d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue    // The number of missed calls that have not been checked on the PSE at the
138d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue    // point of the request. Only apply to "mch" case.
139d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue    private boolean mNeedNewMissedCallsNum = false;
1402c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
141d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue    private int mMissedCallSize = 0;
1422c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
143d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue    // record current path the client are browsing
144d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue    private String mCurrentPath = "";
1452c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
146d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue    private Handler mCallback = null;
1472c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
1482f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue    private Context mContext;
1492f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue
1502f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue    private BluetoothPbapVcardManager mVcardManager;
1512f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue
1522b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh    private int mOrderBy  = ORDER_BY_INDEXED;
1532b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh
15477b122f551ae37811c75ae76fa2029f7b3f2f404a    private static int CALLLOG_NUM_LIMIT = 50;
15577b122f551ae37811c75ae76fa2029f7b3f2f404a
1562b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh    public static int ORDER_BY_INDEXED = 0;
1572b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh
1582b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh    public static int ORDER_BY_ALPHABETICAL = 1;
1592b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh
1600b1b0069658326e8c12dc0f887e4319c5227feb5Lixin Yue    public static boolean sIsAborted = false;
1610b1b0069658326e8c12dc0f887e4319c5227feb5Lixin Yue
162d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue    public static class ContentType {
163d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        public static final int PHONEBOOK = 1;
1642c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
165d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        public static final int INCOMING_CALL_HISTORY = 2;
1662c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
167d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        public static final int OUTGOING_CALL_HISTORY = 3;
1682c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
169d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        public static final int MISSED_CALL_HISTORY = 4;
1702c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
171d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        public static final int COMBINED_CALL_HISTORY = 5;
172d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue    }
1732c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
1742f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue    public BluetoothPbapObexServer(Handler callback, Context context) {
1752c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        super();
1762c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        mCallback = callback;
1772f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        mContext = context;
1782f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        mVcardManager = new BluetoothPbapVcardManager(mContext);
1792c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    }
1802c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
1812c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    @Override
182c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue    public int onConnect(final HeaderSet request, HeaderSet reply) {
183c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue        if (V) logHeader(request);
1848fa8d120e86c7488616cc7f7310843f15278b5d9Zhihai Xu        notifyUpdateWakeLock();
1852c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        try {
186c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue            byte[] uuid = (byte[])request.getHeader(HeaderSet.TARGET);
187c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue            if (uuid == null) {
188c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue                return ResponseCodes.OBEX_HTTP_NOT_ACCEPTABLE;
189c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue            }
190c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue            if (D) Log.d(TAG, "onConnect(): uuid=" + Arrays.toString(uuid));
1914446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
192c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue            if (uuid.length != UUID_LENGTH) {
1932c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                Log.w(TAG, "Wrong UUID length");
1942c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                return ResponseCodes.OBEX_HTTP_NOT_ACCEPTABLE;
1952c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            }
1962c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            for (int i = 0; i < UUID_LENGTH; i++) {
197c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue                if (uuid[i] != PBAP_TARGET[i]) {
1982c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                    Log.w(TAG, "Wrong UUID");
1992c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                    return ResponseCodes.OBEX_HTTP_NOT_ACCEPTABLE;
2002c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                }
2012c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            }
202c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue            reply.setHeader(HeaderSet.WHO, uuid);
2032c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        } catch (IOException e) {
2042c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            Log.e(TAG, e.toString());
2052c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
2062c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
2072c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
208c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue        try {
209c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue            byte[] remote = (byte[])request.getHeader(HeaderSet.WHO);
210c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue            if (remote != null) {
211c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue                if (D) Log.d(TAG, "onConnect(): remote=" + Arrays.toString(remote));
212c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue                reply.setHeader(HeaderSet.TARGET, remote);
213c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue            }
214c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue        } catch (IOException e) {
215c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue            Log.e(TAG, e.toString());
216c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue            return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
217c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue        }
218c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue
219c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue        if (V) Log.v(TAG, "onConnect(): uuid is ok, will send out " +
2204446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                "MSG_SESSION_ESTABLISHED msg.");
2214446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
2222c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        Message msg = Message.obtain(mCallback);
2232c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        msg.what = BluetoothPbapService.MSG_SESSION_ESTABLISHED;
2242c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        msg.sendToTarget();
2252c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
2262c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        return ResponseCodes.OBEX_HTTP_OK;
2272c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    }
2282c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
2292c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    @Override
2302c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    public void onDisconnect(final HeaderSet req, final HeaderSet resp) {
2314446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        if (D) Log.d(TAG, "onDisconnect(): enter");
232c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue        if (V) logHeader(req);
2338fa8d120e86c7488616cc7f7310843f15278b5d9Zhihai Xu        notifyUpdateWakeLock();
2342c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        resp.responseCode = ResponseCodes.OBEX_HTTP_OK;
2352c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        if (mCallback != null) {
2362c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            Message msg = Message.obtain(mCallback);
2372c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            msg.what = BluetoothPbapService.MSG_SESSION_DISCONNECTED;
2382c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            msg.sendToTarget();
2394446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            if (V) Log.v(TAG, "onDisconnect(): msg MSG_SESSION_DISCONNECTED sent out.");
2402c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
2412c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    }
2422c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
2432c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    @Override
2440b1b0069658326e8c12dc0f887e4319c5227feb5Lixin Yue    public int onAbort(HeaderSet request, HeaderSet reply) {
2450b1b0069658326e8c12dc0f887e4319c5227feb5Lixin Yue        if (D) Log.d(TAG, "onAbort(): enter.");
2468fa8d120e86c7488616cc7f7310843f15278b5d9Zhihai Xu        notifyUpdateWakeLock();
2470b1b0069658326e8c12dc0f887e4319c5227feb5Lixin Yue        sIsAborted = true;
2480b1b0069658326e8c12dc0f887e4319c5227feb5Lixin Yue        return ResponseCodes.OBEX_HTTP_OK;
2490b1b0069658326e8c12dc0f887e4319c5227feb5Lixin Yue    }
2500b1b0069658326e8c12dc0f887e4319c5227feb5Lixin Yue
2510b1b0069658326e8c12dc0f887e4319c5227feb5Lixin Yue    @Override
2522c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    public int onPut(final Operation op) {
2534446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        if (D) Log.d(TAG, "onPut(): not support PUT request.");
2548fa8d120e86c7488616cc7f7310843f15278b5d9Zhihai Xu        notifyUpdateWakeLock();
2552c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        return ResponseCodes.OBEX_HTTP_BAD_REQUEST;
2562c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    }
2572c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
2582c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    @Override
25976dc9e2d09ea7f2655e557462c149a0c6b6dd771Mick Lin    public int onDelete(final HeaderSet request, final HeaderSet reply) {
26076dc9e2d09ea7f2655e557462c149a0c6b6dd771Mick Lin        if (D) Log.d(TAG, "onDelete(): not support PUT request.");
26176dc9e2d09ea7f2655e557462c149a0c6b6dd771Mick Lin        notifyUpdateWakeLock();
26276dc9e2d09ea7f2655e557462c149a0c6b6dd771Mick Lin        return ResponseCodes.OBEX_HTTP_BAD_REQUEST;
26376dc9e2d09ea7f2655e557462c149a0c6b6dd771Mick Lin    }
26476dc9e2d09ea7f2655e557462c149a0c6b6dd771Mick Lin
26576dc9e2d09ea7f2655e557462c149a0c6b6dd771Mick Lin    @Override
2662c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    public int onSetPath(final HeaderSet request, final HeaderSet reply, final boolean backup,
2672c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            final boolean create) {
268c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue        if (V) logHeader(request);
2694446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        if (D) Log.d(TAG, "before setPath, mCurrentPath ==  " + mCurrentPath);
2708fa8d120e86c7488616cc7f7310843f15278b5d9Zhihai Xu        notifyUpdateWakeLock();
2712c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        String current_path_tmp = mCurrentPath;
2722c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        String tmp_path = null;
2732c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        try {
2742c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            tmp_path = (String)request.getHeader(HeaderSet.NAME);
2752c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        } catch (IOException e) {
2762c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            Log.e(TAG, "Get name header fail");
2772c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
2782c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
2794446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        if (D) Log.d(TAG, "backup=" + backup + " create=" + create + " name=" + tmp_path);
280d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue
281d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        if (backup) {
282d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue            if (current_path_tmp.length() != 0) {
283d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                current_path_tmp = current_path_tmp.substring(0,
284d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                        current_path_tmp.lastIndexOf("/"));
285d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue            }
286d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        } else {
2872c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            if (tmp_path == null) {
2882c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                current_path_tmp = "";
2892c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            } else {
2902c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                current_path_tmp = current_path_tmp + "/" + tmp_path;
2912c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            }
2922c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
2932c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
2942c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        if ((current_path_tmp.length() != 0) && (!isLegalPath(current_path_tmp))) {
295d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue            if (create) {
296d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                Log.w(TAG, "path create is forbidden!");
297d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                return ResponseCodes.OBEX_HTTP_FORBIDDEN;
298d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue            } else {
299d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                Log.w(TAG, "path is not legal");
300a4508589f298c67fda54c344760ae39f0f375c11Lixin Yue                return ResponseCodes.OBEX_HTTP_NOT_FOUND;
301d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue            }
3022c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
3032c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        mCurrentPath = current_path_tmp;
3044446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        if (V) Log.v(TAG, "after setPath, mCurrentPath ==  " + mCurrentPath);
3054446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
3062c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        return ResponseCodes.OBEX_HTTP_OK;
3072c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    }
3082c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
3092c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    @Override
3102c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    public void onClose() {
3112c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        if (mCallback != null) {
3122c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            Message msg = Message.obtain(mCallback);
3132c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            msg.what = BluetoothPbapService.MSG_SERVERSESSION_CLOSE;
3142c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            msg.sendToTarget();
3154446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            if (D) Log.d(TAG, "onClose(): msg MSG_SERVERSESSION_CLOSE sent out.");
3162c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
3172c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    }
3182c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
3192c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    @Override
3200b1b0069658326e8c12dc0f887e4319c5227feb5Lixin Yue    public int onGet(Operation op) {
3218fa8d120e86c7488616cc7f7310843f15278b5d9Zhihai Xu        notifyUpdateWakeLock();
32220b5a93b6e18cd441065edfdf676ad612affc507Jaikumar Ganesh        sIsAborted = false;
3232c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        HeaderSet request = null;
3242c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        HeaderSet reply = new HeaderSet();
3252c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        String type = "";
3262c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        String name = "";
3272c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        byte[] appParam = null;
3282c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        AppParamValue appParamValue = new AppParamValue();
3292c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        try {
3302c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            request = op.getReceivedHeader();
3312c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            type = (String)request.getHeader(HeaderSet.TYPE);
3322c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            name = (String)request.getHeader(HeaderSet.NAME);
3332c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            appParam = (byte[])request.getHeader(HeaderSet.APPLICATION_PARAMETER);
3342c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        } catch (IOException e) {
3352c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            Log.e(TAG, "request headers error");
3362c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
3372c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
338d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue
339c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue        if (V) logHeader(request);
3404446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        if (D) Log.d(TAG, "OnGet type is " + type + "; name is " + name);
341d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue
34218bde766b20c899310ebdd5ca823e30ff27d407fLixin Yue        if (type == null) {
343a4508589f298c67fda54c344760ae39f0f375c11Lixin Yue            return ResponseCodes.OBEX_HTTP_NOT_ACCEPTABLE;
34418bde766b20c899310ebdd5ca823e30ff27d407fLixin Yue        }
345d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        // Accroding to specification,the name header could be omitted such as
346d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        // sony erriccsonHBH-DS980
347d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue
348d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        // For "x-bt/phonebook" and "x-bt/vcard-listing":
349d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        // if name == null, guess what carkit actually want from current path
350d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        // For "x-bt/vcard":
351d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        // We decide which kind of content client would like per current path
352d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue
353d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        boolean validName = true;
35418bde766b20c899310ebdd5ca823e30ff27d407fLixin Yue        if (TextUtils.isEmpty(name)) {
355d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue            validName = false;
356d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        }
357d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue
358d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        if (!validName || (validName && type.equals(TYPE_VCARD))) {
3594446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            if (D) Log.d(TAG, "Guess what carkit actually want from current path (" +
3604446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                    mCurrentPath + ")");
3614446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
3622b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh            if (mCurrentPath.equals(PB_PATH)) {
363d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                appParamValue.needTag = ContentType.PHONEBOOK;
3642b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh            } else if (mCurrentPath.equals(ICH_PATH)) {
365d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                appParamValue.needTag = ContentType.INCOMING_CALL_HISTORY;
3662b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh            } else if (mCurrentPath.equals(OCH_PATH)) {
367d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                appParamValue.needTag = ContentType.OUTGOING_CALL_HISTORY;
3682b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh            } else if (mCurrentPath.equals(MCH_PATH)) {
369d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                appParamValue.needTag = ContentType.MISSED_CALL_HISTORY;
370d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                mNeedNewMissedCallsNum = true;
3712b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh            } else if (mCurrentPath.equals(CCH_PATH)) {
372d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                appParamValue.needTag = ContentType.COMBINED_CALL_HISTORY;
373b99a8af5a27318bb5ae3745531d5a2175370b892Hemant Gupta            } else if (mCurrentPath.equals(TELECOM_PATH)) {
374b99a8af5a27318bb5ae3745531d5a2175370b892Hemant Gupta                /* PBAP 1.1.1 change */
375b99a8af5a27318bb5ae3745531d5a2175370b892Hemant Gupta                if (!validName && type.equals(TYPE_LISTING)) {
376b99a8af5a27318bb5ae3745531d5a2175370b892Hemant Gupta                    Log.e(TAG, "invalid vcard listing request in default folder");
377b99a8af5a27318bb5ae3745531d5a2175370b892Hemant Gupta                    return ResponseCodes.OBEX_HTTP_NOT_FOUND;
378b99a8af5a27318bb5ae3745531d5a2175370b892Hemant Gupta                }
379d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue            } else {
380d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                Log.w(TAG, "mCurrentpath is not valid path!!!");
381a4508589f298c67fda54c344760ae39f0f375c11Lixin Yue                return ResponseCodes.OBEX_HTTP_NOT_ACCEPTABLE;
3822c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            }
3834446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            if (D) Log.v(TAG, "onGet(): appParamValue.needTag=" + appParamValue.needTag);
3844446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        } else {
3854446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            // Not support SIM card currently
3864446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            if (name.contains(SIM1.subSequence(0, SIM1.length()))) {
3874446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                Log.w(TAG, "Not support access SIM card info!");
3884446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                return ResponseCodes.OBEX_HTTP_NOT_ACCEPTABLE;
3894446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            }
3904446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
3914446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            // we have weak name checking here to provide better
3922c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            // compatibility with other devices,although unique name such as
3932c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            // "pb.vcf" is required by SIG spec.
39476dc9e2d09ea7f2655e557462c149a0c6b6dd771Mick Lin            if (isNameMatchTarget(name, PB)) {
395d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                appParamValue.needTag = ContentType.PHONEBOOK;
3964446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                if (D) Log.v(TAG, "download phonebook request");
39776dc9e2d09ea7f2655e557462c149a0c6b6dd771Mick Lin            } else if (isNameMatchTarget(name, ICH)) {
398d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                appParamValue.needTag = ContentType.INCOMING_CALL_HISTORY;
3994446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                if (D) Log.v(TAG, "download incoming calls request");
40076dc9e2d09ea7f2655e557462c149a0c6b6dd771Mick Lin            } else if (isNameMatchTarget(name, OCH)) {
401d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                appParamValue.needTag = ContentType.OUTGOING_CALL_HISTORY;
4024446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                if (D) Log.v(TAG, "download outgoing calls request");
40376dc9e2d09ea7f2655e557462c149a0c6b6dd771Mick Lin            } else if (isNameMatchTarget(name, MCH)) {
404d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                appParamValue.needTag = ContentType.MISSED_CALL_HISTORY;
405d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                mNeedNewMissedCallsNum = true;
4064446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                if (D) Log.v(TAG, "download missed calls request");
40776dc9e2d09ea7f2655e557462c149a0c6b6dd771Mick Lin            } else if (isNameMatchTarget(name, CCH)) {
408d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                appParamValue.needTag = ContentType.COMBINED_CALL_HISTORY;
4094446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                if (D) Log.v(TAG, "download combined calls request");
410d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue            } else {
411d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                Log.w(TAG, "Input name doesn't contain valid info!!!");
41276dc9e2d09ea7f2655e557462c149a0c6b6dd771Mick Lin                return ResponseCodes.OBEX_HTTP_NOT_FOUND;
4132c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            }
4142c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
415d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue
4164ce32fccf381a3b448f0d5ff56665201c0e0e6d3Ola Johnsson        if ((appParam != null) && !parseApplicationParameter(appParam, appParamValue)) {
417d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue            return ResponseCodes.OBEX_HTTP_BAD_REQUEST;
418d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        }
419d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue
4202c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        // listing request
4212c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        if (type.equals(TYPE_LISTING)) {
4222c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            return pullVcardListing(appParam, appParamValue, reply, op);
4232c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
4242c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        // pull vcard entry request
4252c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        else if (type.equals(TYPE_VCARD)) {
4262c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            return pullVcardEntry(appParam, appParamValue, op, name, mCurrentPath);
4272c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
4282c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        // down load phone book request
4292c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        else if (type.equals(TYPE_PB)) {
4302c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            return pullPhonebook(appParam, appParamValue, reply, op, name);
4312c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        } else {
4322c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            Log.w(TAG, "unknown type request!!!");
433a4508589f298c67fda54c344760ae39f0f375c11Lixin Yue            return ResponseCodes.OBEX_HTTP_NOT_ACCEPTABLE;
4342c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
435d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue    }
4362c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
43776dc9e2d09ea7f2655e557462c149a0c6b6dd771Mick Lin    private boolean isNameMatchTarget(String name, String target) {
43876dc9e2d09ea7f2655e557462c149a0c6b6dd771Mick Lin        String contentTypeName = name;
43976dc9e2d09ea7f2655e557462c149a0c6b6dd771Mick Lin        if (contentTypeName.endsWith(".vcf")) {
44076dc9e2d09ea7f2655e557462c149a0c6b6dd771Mick Lin            contentTypeName = contentTypeName
44176dc9e2d09ea7f2655e557462c149a0c6b6dd771Mick Lin                    .substring(0, contentTypeName.length() - ".vcf".length());
44276dc9e2d09ea7f2655e557462c149a0c6b6dd771Mick Lin        }
44376dc9e2d09ea7f2655e557462c149a0c6b6dd771Mick Lin        // There is a test case: Client will send a wrong name "/telecom/pbpb".
44476dc9e2d09ea7f2655e557462c149a0c6b6dd771Mick Lin        // So we must use the String between '/' and '/' as a indivisible part
44576dc9e2d09ea7f2655e557462c149a0c6b6dd771Mick Lin        // for comparing.
44676dc9e2d09ea7f2655e557462c149a0c6b6dd771Mick Lin        String[] nameList = contentTypeName.split("/");
44776dc9e2d09ea7f2655e557462c149a0c6b6dd771Mick Lin        for (String subName : nameList) {
44876dc9e2d09ea7f2655e557462c149a0c6b6dd771Mick Lin            if (subName.equals(target)) {
44976dc9e2d09ea7f2655e557462c149a0c6b6dd771Mick Lin                return true;
45076dc9e2d09ea7f2655e557462c149a0c6b6dd771Mick Lin            }
45176dc9e2d09ea7f2655e557462c149a0c6b6dd771Mick Lin        }
45276dc9e2d09ea7f2655e557462c149a0c6b6dd771Mick Lin        return false;
45376dc9e2d09ea7f2655e557462c149a0c6b6dd771Mick Lin    }
45476dc9e2d09ea7f2655e557462c149a0c6b6dd771Mick Lin
4552c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    /** check whether path is legal */
4562c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    private final boolean isLegalPath(final String str) {
4572c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        if (str.length() == 0) {
4582c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            return true;
4592c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
4604446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        for (int i = 0; i < LEGAL_PATH.length; i++) {
461d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue            if (str.equals(LEGAL_PATH[i])) {
4622c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                return true;
4632c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            }
4642c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
4652c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        return false;
4662c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    }
4672c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
4682c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    private class AppParamValue {
4692c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        public int maxListCount;
4702c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
4712c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        public int listStartOffset;
4722c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
4732c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        public String searchValue;
4742c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
4752b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh        // Indicate which vCard parameter the search operation shall be carried
4762b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh        // out on. Can be "Name | Number | Sound", default value is "Name".
4772c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        public String searchAttr;
4782c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
4792b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh        // Indicate which sorting order shall be used for the
4802b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh        // <x-bt/vcard-listing> listing object.
4812b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh        // Can be "Alphabetical | Indexed | Phonetical", default value is
4822b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh        // "Indexed".
4832b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh        public String order;
4842b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh
4852c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        public int needTag;
4862c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
4872c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        public boolean vcard21;
4882c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
4896db8e703719f301f75acdf4acacc3296cc1b5016Hemant Gupta        public byte[] filter;
4906db8e703719f301f75acdf4acacc3296cc1b5016Hemant Gupta
4916db8e703719f301f75acdf4acacc3296cc1b5016Hemant Gupta        public boolean ignorefilter;
4926db8e703719f301f75acdf4acacc3296cc1b5016Hemant Gupta
4932c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        public AppParamValue() {
4944ce32fccf381a3b448f0d5ff56665201c0e0e6d3Ola Johnsson            maxListCount = 0xFFFF;
4952c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            listStartOffset = 0;
4962c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            searchValue = "";
4972c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            searchAttr = "";
4982b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh            order = "";
4992c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            needTag = 0x00;
5002c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            vcard21 = true;
5016db8e703719f301f75acdf4acacc3296cc1b5016Hemant Gupta            //Filter is not set by default
5026db8e703719f301f75acdf4acacc3296cc1b5016Hemant Gupta            ignorefilter = true;
5036db8e703719f301f75acdf4acacc3296cc1b5016Hemant Gupta            filter = new byte[] {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} ;
5042c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
5052c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
5062c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        public void dump() {
5072c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            Log.i(TAG, "maxListCount=" + maxListCount + " listStartOffset=" + listStartOffset
5082c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                    + " searchValue=" + searchValue + " searchAttr=" + searchAttr + " needTag="
5092b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh                    + needTag + " vcard21=" + vcard21 + " order=" + order);
5102c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
5112c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    }
5122c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
5132c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    /** To parse obex application parameter */
5142c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    private final boolean parseApplicationParameter(final byte[] appParam,
5152c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            AppParamValue appParamValue) {
5162c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        int i = 0;
517d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        boolean parseOk = true;
5186db8e703719f301f75acdf4acacc3296cc1b5016Hemant Gupta        while ((i < appParam.length) && (parseOk == true)) {
5192c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            switch (appParam[i]) {
5202c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                case ApplicationParameter.TRIPLET_TAGID.FILTER_TAGID:
5212c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                    i += 2; // length and tag field in triplet
5226db8e703719f301f75acdf4acacc3296cc1b5016Hemant Gupta                    for (int index=0; index < ApplicationParameter.TRIPLET_LENGTH.FILTER_LENGTH;
5236db8e703719f301f75acdf4acacc3296cc1b5016Hemant Gupta                         index++) {
5246db8e703719f301f75acdf4acacc3296cc1b5016Hemant Gupta                        if (appParam[i+index] != 0){
5256db8e703719f301f75acdf4acacc3296cc1b5016Hemant Gupta                            appParamValue.ignorefilter = false;
5266db8e703719f301f75acdf4acacc3296cc1b5016Hemant Gupta                            appParamValue.filter[index] = appParam[i+index];
5276db8e703719f301f75acdf4acacc3296cc1b5016Hemant Gupta                        }
5286db8e703719f301f75acdf4acacc3296cc1b5016Hemant Gupta                    }
5292c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                    i += ApplicationParameter.TRIPLET_LENGTH.FILTER_LENGTH;
5302c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                    break;
5312c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                case ApplicationParameter.TRIPLET_TAGID.ORDER_TAGID:
5322c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                    i += 2; // length and tag field in triplet
5332b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh                    appParamValue.order = Byte.toString(appParam[i]);
5342c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                    i += ApplicationParameter.TRIPLET_LENGTH.ORDER_LENGTH;
5352c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                    break;
5362c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                case ApplicationParameter.TRIPLET_TAGID.SEARCH_VALUE_TAGID:
5372c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                    i += 1; // length field in triplet
5382c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                    // length of search value is variable
5394ce32fccf381a3b448f0d5ff56665201c0e0e6d3Ola Johnsson                    int length = appParam[i];
5400dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao                    if (length == 0) {
5410dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao                        parseOk = false;
5420dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao                        break;
5430dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao                    }
5440dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao                    if (appParam[i+length] == 0x0) {
5450dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao                        appParamValue.searchValue = new String(appParam, i + 1, length-1);
5460dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao                    } else {
5470dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao                        appParamValue.searchValue = new String(appParam, i + 1, length);
5480dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao                    }
5494ce32fccf381a3b448f0d5ff56665201c0e0e6d3Ola Johnsson                    i += length;
5502c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                    i += 1;
5512c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                    break;
5522c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                case ApplicationParameter.TRIPLET_TAGID.SEARCH_ATTRIBUTE_TAGID:
5532c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                    i += 2;
5542c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                    appParamValue.searchAttr = Byte.toString(appParam[i]);
5552c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                    i += ApplicationParameter.TRIPLET_LENGTH.SEARCH_ATTRIBUTE_LENGTH;
5562c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                    break;
5572c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                case ApplicationParameter.TRIPLET_TAGID.MAXLISTCOUNT_TAGID:
5582c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                    i += 2;
5592c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                    if (appParam[i] == 0 && appParam[i + 1] == 0) {
560d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                        mNeedPhonebookSize = true;
5612c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                    } else {
5622c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                        int highValue = appParam[i] & 0xff;
5632c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                        int lowValue = appParam[i + 1] & 0xff;
5642c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                        appParamValue.maxListCount = highValue * 256 + lowValue;
5652c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                    }
5662c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                    i += ApplicationParameter.TRIPLET_LENGTH.MAXLISTCOUNT_LENGTH;
5672c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                    break;
5682c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                case ApplicationParameter.TRIPLET_TAGID.LISTSTARTOFFSET_TAGID:
5692c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                    i += 2;
570d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                    int highValue = appParam[i] & 0xff;
571d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                    int lowValue = appParam[i + 1] & 0xff;
572d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                    appParamValue.listStartOffset = highValue * 256 + lowValue;
5732c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                    i += ApplicationParameter.TRIPLET_LENGTH.LISTSTARTOFFSET_LENGTH;
5742c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                    break;
5752c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                case ApplicationParameter.TRIPLET_TAGID.FORMAT_TAGID:
5762c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                    i += 2;// length field in triplet
5772b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh                    if (appParam[i] != 0) {
5782c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                        appParamValue.vcard21 = false;
5792c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                    }
5802c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                    i += ApplicationParameter.TRIPLET_LENGTH.FORMAT_LENGTH;
5812c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                    break;
5822c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                default:
583d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                    parseOk = false;
5844446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                    Log.e(TAG, "Parse Application Parameter error");
5852c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                    break;
5862c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            }
5872c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
588d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue
5894446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        if (D) appParamValue.dump();
5904446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
591d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        return parseOk;
5922c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    }
5932c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
5942c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    /** Form and Send an XML format String to client for Phone book listing */
5950b1b0069658326e8c12dc0f887e4319c5227feb5Lixin Yue    private final int sendVcardListingXml(final int type, Operation op,
5962c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            final int maxListCount, final int listStartOffset, final String searchValue,
5972c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            String searchAttr) {
5982c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        StringBuilder result = new StringBuilder();
5992c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        int itemsFound = 0;
6002c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        result.append("<?xml version=\"1.0\"?>");
6012c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        result.append("<!DOCTYPE vcard-listing SYSTEM \"vcard-listing.dtd\">");
6022c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        result.append("<vCard-listing version=\"1.0\">");
6032c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
6042c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        // Phonebook listing request
605d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        if (type == ContentType.PHONEBOOK) {
6064ce32fccf381a3b448f0d5ff56665201c0e0e6d3Ola Johnsson            if (searchAttr.equals("0")) { // search by name
6074ce32fccf381a3b448f0d5ff56665201c0e0e6d3Ola Johnsson                itemsFound = createList(maxListCount, listStartOffset, searchValue, result,
6080dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao                        "name");
6094ce32fccf381a3b448f0d5ff56665201c0e0e6d3Ola Johnsson            } else if (searchAttr.equals("1")) { // search by number
6104ce32fccf381a3b448f0d5ff56665201c0e0e6d3Ola Johnsson                itemsFound = createList(maxListCount, listStartOffset, searchValue, result,
6110dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao                        "number");
6122c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            }// end of search by number
6132c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            else {
614d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                return ResponseCodes.OBEX_HTTP_PRECON_FAILED;
6152c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            }
6162c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
6172c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        // Call history listing request
6182c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        else {
6192f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            ArrayList<String> nameList = mVcardManager.loadCallHistoryList(type);
620d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue            int requestSize = nameList.size() >= maxListCount ? maxListCount : nameList.size();
621d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue            int startPoint = listStartOffset;
622d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue            int endPoint = startPoint + requestSize;
623d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue            if (endPoint > nameList.size()) {
624d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                endPoint = nameList.size();
625d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue            }
6264446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            if (D) Log.d(TAG, "call log list, size=" + requestSize + " offset=" + listStartOffset);
6274446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
628d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue            for (int j = startPoint; j < endPoint; j++) {
629e479e18951a375a548e617e86e3b1b7d121351a1Fred                writeVCardEntry(j+1, nameList.get(j),result);
6302c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            }
6312c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
6322c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        result.append("</vCard-listing>");
6332c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
6344446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        if (V) Log.v(TAG, "itemsFound =" + itemsFound);
635d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue
636d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        return pushBytes(op, result.toString());
6372c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    }
6382c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
6394ce32fccf381a3b448f0d5ff56665201c0e0e6d3Ola Johnsson    private int createList(final int maxListCount, final int listStartOffset,
6400dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao            final String searchValue, StringBuilder result, String type) {
6414ce32fccf381a3b448f0d5ff56665201c0e0e6d3Ola Johnsson        int itemsFound = 0;
6420dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao        ArrayList<String> nameList = mVcardManager.getPhonebookNameList(mOrderBy);
6430dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao        final int requestSize = nameList.size() >= maxListCount ? maxListCount : nameList.size();
6440dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao        final int listSize = nameList.size();
6450dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao        String compareValue = "", currentValue;
6464ce32fccf381a3b448f0d5ff56665201c0e0e6d3Ola Johnsson
6470dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao        if (D) Log.d(TAG, "search by " + type + ", requestSize=" + requestSize + " offset="
6484ce32fccf381a3b448f0d5ff56665201c0e0e6d3Ola Johnsson                    + listStartOffset + " searchValue=" + searchValue);
6494ce32fccf381a3b448f0d5ff56665201c0e0e6d3Ola Johnsson
6500dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao        if (type.equals("number")) {
6510dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao            // query the number, to get the names
6520dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao            ArrayList<String> names = mVcardManager.getContactNamesByNumber(searchValue);
6530dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao            for (int i = 0; i < names.size(); i++) {
6540dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao                compareValue = names.get(i).trim();
6550dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao                if (D) Log.d(TAG, "compareValue=" + compareValue);
6560dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao                for (int pos = listStartOffset; pos < listSize &&
6570dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao                        itemsFound < requestSize; pos++) {
6580dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao                    currentValue = nameList.get(pos);
6590dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao                    if (D) Log.d(TAG, "currentValue=" + currentValue);
6601321cd814a7406260ba6282d9c71e1a2d8925262Hemant Gupta                    if (currentValue.equals(compareValue)) {
6610dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao                        itemsFound++;
66290d9ea96c0b0f3209dc03667e21d14a13ca1f614Hemant Gupta                        if (currentValue.contains(","))
66390d9ea96c0b0f3209dc03667e21d14a13ca1f614Hemant Gupta                           currentValue = currentValue.substring(0, currentValue.lastIndexOf(','));
664e479e18951a375a548e617e86e3b1b7d121351a1Fred                        writeVCardEntry(pos, currentValue,result);
6650dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao                    }
6660dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao                }
6670dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao                if (itemsFound >= requestSize) {
6680dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao                    break;
6690dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao                }
6700dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao            }
6710dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao        } else {
6720dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao            if (searchValue != null) {
673c3a43ae7d1f54495fb4d830d08386aee75e0e997Hemant Gupta                compareValue = searchValue.trim().toLowerCase();
6740dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao            }
6750dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao            for (int pos = listStartOffset; pos < listSize &&
6760dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao                    itemsFound < requestSize; pos++) {
6770dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao                currentValue = nameList.get(pos);
678130969d18eadbd94361fe95bf16b8131cdea6168Hemant Gupta                if (currentValue.contains(","))
679130969d18eadbd94361fe95bf16b8131cdea6168Hemant Gupta                    currentValue = currentValue.substring(0, currentValue.lastIndexOf(','));
680130969d18eadbd94361fe95bf16b8131cdea6168Hemant Gupta
681c3a43ae7d1f54495fb4d830d08386aee75e0e997Hemant Gupta                if (searchValue.isEmpty() || ((currentValue.toLowerCase()).startsWith(compareValue))) {
6820dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao                    itemsFound++;
683e479e18951a375a548e617e86e3b1b7d121351a1Fred                    writeVCardEntry(pos, currentValue,result);
6840dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao                }
6854ce32fccf381a3b448f0d5ff56665201c0e0e6d3Ola Johnsson            }
6864ce32fccf381a3b448f0d5ff56665201c0e0e6d3Ola Johnsson        }
6874ce32fccf381a3b448f0d5ff56665201c0e0e6d3Ola Johnsson        return itemsFound;
6884ce32fccf381a3b448f0d5ff56665201c0e0e6d3Ola Johnsson    }
6894ce32fccf381a3b448f0d5ff56665201c0e0e6d3Ola Johnsson
6902c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    /**
6912c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan     * Function to send obex header back to client such as get phonebook size
6922c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan     * request
6932c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan     */
6942c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    private final int pushHeader(final Operation op, final HeaderSet reply) {
6952c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        OutputStream outputStream = null;
696d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue
6974446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        if (D) Log.d(TAG, "Push Header");
6984446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        if (D) Log.d(TAG, reply.toString());
699d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue
7004446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        int pushResult = ResponseCodes.OBEX_HTTP_OK;
7012c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        try {
7022c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            op.sendHeaders(reply);
7032c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            outputStream = op.openOutputStream();
7042c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            outputStream.flush();
7052c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        } catch (IOException e) {
7062c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            Log.e(TAG, e.toString());
7074446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            pushResult = ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
7082c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        } finally {
7092c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            if (!closeStream(outputStream, op)) {
7104446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                pushResult = ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
7112c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            }
7122c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
7134446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        return pushResult;
7142c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    }
7152c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
7162c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    /** Function to send vcard data to client */
7170b1b0069658326e8c12dc0f887e4319c5227feb5Lixin Yue    private final int pushBytes(Operation op, final String vcardString) {
7182f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        if (vcardString == null) {
7192f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            Log.w(TAG, "vcardString is null!");
7202c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            return ResponseCodes.OBEX_HTTP_OK;
7212c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
7224446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
7232f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        OutputStream outputStream = null;
7242f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        int pushResult = ResponseCodes.OBEX_HTTP_OK;
7252c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        try {
7262c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            outputStream = op.openOutputStream();
727ce8d51a3a43d113a4a6bad30d595c2a81d0f623cYoshiharu Kurita            outputStream.write(vcardString.getBytes());
728ce8d51a3a43d113a4a6bad30d595c2a81d0f623cYoshiharu Kurita            if (V) Log.v(TAG, "Send Data complete!");
7292c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        } catch (IOException e) {
730ce8d51a3a43d113a4a6bad30d595c2a81d0f623cYoshiharu Kurita            Log.e(TAG, "open/write outputstrem failed" + e.toString());
731ce8d51a3a43d113a4a6bad30d595c2a81d0f623cYoshiharu Kurita            pushResult = ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
7322c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
7332f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue
7342f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        if (!closeStream(outputStream, op)) {
7352f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            pushResult = ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
7362f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        }
7372f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue
7384446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        return pushResult;
7392c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    }
7402c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
7414446eaa935994bc91d6d308303e8d27526b4590dLixin Yue    private final int handleAppParaForResponse(AppParamValue appParamValue, int size,
7420b1b0069658326e8c12dc0f887e4319c5227feb5Lixin Yue            HeaderSet reply, Operation op) {
743d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        byte[] misnum = new byte[1];
7442c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        ApplicationParameter ap = new ApplicationParameter();
745d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue
746d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        // In such case, PCE only want the number of index.
747d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        // So response not contain any Body header.
748d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        if (mNeedPhonebookSize) {
7492f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            if (V) Log.v(TAG, "Need Phonebook size in response header.");
750d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue            mNeedPhonebookSize = false;
751d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue
7522c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            byte[] pbsize = new byte[2];
753d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue
7542c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            pbsize[0] = (byte)((size / 256) & 0xff);// HIGH VALUE
7552c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            pbsize[1] = (byte)((size % 256) & 0xff);// LOW VALUE
7562c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            ap.addAPPHeader(ApplicationParameter.TRIPLET_TAGID.PHONEBOOKSIZE_TAGID,
7572c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                    ApplicationParameter.TRIPLET_LENGTH.PHONEBOOKSIZE_LENGTH, pbsize);
758d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue
759d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue            if (mNeedNewMissedCallsNum) {
7609522370104410f24602ac98172bfbda27f89780dYoshiharu Kurita                mNeedNewMissedCallsNum = false;
761ff33061e763656438daea7249e45e38b8a174288kschulz                int nmnum = 0;
762ff33061e763656438daea7249e45e38b8a174288kschulz                ContentResolver contentResolver;
763ff33061e763656438daea7249e45e38b8a174288kschulz                contentResolver = mContext.getContentResolver();
764ff33061e763656438daea7249e45e38b8a174288kschulz
765ff33061e763656438daea7249e45e38b8a174288kschulz                Cursor c = contentResolver.query(
766ff33061e763656438daea7249e45e38b8a174288kschulz                    Calls.CONTENT_URI,
767ff33061e763656438daea7249e45e38b8a174288kschulz                    null,
768ff33061e763656438daea7249e45e38b8a174288kschulz                    Calls.TYPE + " = " + Calls.MISSED_TYPE + " AND " + android.provider.CallLog.Calls.NEW + " = 1",
769ff33061e763656438daea7249e45e38b8a174288kschulz                    null,
770ff33061e763656438daea7249e45e38b8a174288kschulz                    Calls.DEFAULT_SORT_ORDER);
771ff33061e763656438daea7249e45e38b8a174288kschulz
772ff33061e763656438daea7249e45e38b8a174288kschulz                if (c != null) {
773ff33061e763656438daea7249e45e38b8a174288kschulz                  nmnum = c.getCount();
774ff33061e763656438daea7249e45e38b8a174288kschulz                  c.close();
775ff33061e763656438daea7249e45e38b8a174288kschulz                }
776d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue
777d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                nmnum = nmnum > 0 ? nmnum : 0;
778d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                misnum[0] = (byte)nmnum;
779ff33061e763656438daea7249e45e38b8a174288kschulz                if (D) Log.d(TAG, "handleAppParaForResponse(): mNeedNewMissedCallsNum=true,  num= " + nmnum);
780d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue            }
7812c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            reply.setHeader(HeaderSet.APPLICATION_PARAMETER, ap.getAPPparam());
782ff33061e763656438daea7249e45e38b8a174288kschulz
7834446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            if (D) Log.d(TAG, "Send back Phonebook size only, without body info! Size= " + size);
784d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue
7852c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            return pushHeader(op, reply);
7862c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
7872c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
788d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        // Only apply to "mch" download/listing.
789d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        // NewMissedCalls is used only in the response, together with Body
790d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        // header.
791d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        if (mNeedNewMissedCallsNum) {
7922f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            if (V) Log.v(TAG, "Need new missed call num in response header.");
793d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue            mNeedNewMissedCallsNum = false;
794ff33061e763656438daea7249e45e38b8a174288kschulz            int nmnum = 0;
795ff33061e763656438daea7249e45e38b8a174288kschulz            ContentResolver contentResolver;
796ff33061e763656438daea7249e45e38b8a174288kschulz            contentResolver = mContext.getContentResolver();
797ff33061e763656438daea7249e45e38b8a174288kschulz
798ff33061e763656438daea7249e45e38b8a174288kschulz            Cursor c = contentResolver.query(
799ff33061e763656438daea7249e45e38b8a174288kschulz                Calls.CONTENT_URI,
800ff33061e763656438daea7249e45e38b8a174288kschulz                null,
801ff33061e763656438daea7249e45e38b8a174288kschulz                Calls.TYPE + " = " + Calls.MISSED_TYPE + " AND " + android.provider.CallLog.Calls.NEW + " = 1",
802ff33061e763656438daea7249e45e38b8a174288kschulz                null,
803ff33061e763656438daea7249e45e38b8a174288kschulz                Calls.DEFAULT_SORT_ORDER);
804ff33061e763656438daea7249e45e38b8a174288kschulz
805ff33061e763656438daea7249e45e38b8a174288kschulz            if (c != null) {
806ff33061e763656438daea7249e45e38b8a174288kschulz              nmnum = c.getCount();
807ff33061e763656438daea7249e45e38b8a174288kschulz              c.close();
808ff33061e763656438daea7249e45e38b8a174288kschulz            }
809d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue
8102c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            nmnum = nmnum > 0 ? nmnum : 0;
8112c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            misnum[0] = (byte)nmnum;
812ff33061e763656438daea7249e45e38b8a174288kschulz            if (D) Log.d(TAG, "handleAppParaForResponse(): mNeedNewMissedCallsNum=true,  num= " + nmnum);
813ff33061e763656438daea7249e45e38b8a174288kschulz
8142c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            ap.addAPPHeader(ApplicationParameter.TRIPLET_TAGID.NEWMISSEDCALLS_TAGID,
8152c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                    ApplicationParameter.TRIPLET_LENGTH.NEWMISSEDCALLS_LENGTH, misnum);
8162c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            reply.setHeader(HeaderSet.APPLICATION_PARAMETER, ap.getAPPparam());
8174446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            if (D) Log.d(TAG, "handleAppParaForResponse(): mNeedNewMissedCallsNum=true,  num= "
8184446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                        + nmnum);
8192c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
820d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue            // Only Specifies the headers, not write for now, will write to PCE
821d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue            // together with Body
822d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue            try {
823d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                op.sendHeaders(reply);
824d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue            } catch (IOException e) {
825d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                Log.e(TAG, e.toString());
826d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
8272c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            }
8282c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
829d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        return NEED_SEND_BODY;
830d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue    }
8312c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
832d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue    private final int pullVcardListing(byte[] appParam, AppParamValue appParamValue,
8330b1b0069658326e8c12dc0f887e4319c5227feb5Lixin Yue            HeaderSet reply, Operation op) {
834d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        String searchAttr = appParamValue.searchAttr.trim();
8352c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
836d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        if (searchAttr == null || searchAttr.length() == 0) {
837d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue            // If searchAttr is not set by PCE, set default value per spec.
838d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue            appParamValue.searchAttr = "0";
8394446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            if (D) Log.d(TAG, "searchAttr is not set by PCE, assume search by name by default");
8402b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh        } else if (!searchAttr.equals("0") && !searchAttr.equals("1")) {
841d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue            Log.w(TAG, "search attr not supported");
8422b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh            if (searchAttr.equals("2")) {
843d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                // search by sound is not supported currently
844d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                Log.w(TAG, "do not support search by sound");
845d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                return ResponseCodes.OBEX_HTTP_NOT_IMPLEMENTED;
846d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue            }
847d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue            return ResponseCodes.OBEX_HTTP_PRECON_FAILED;
848d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        } else {
8494446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            Log.i(TAG, "searchAttr is valid: " + searchAttr);
8502c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
8512c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
8522f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        int size = mVcardManager.getPhonebookSize(appParamValue.needTag);
8534446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        int needSendBody = handleAppParaForResponse(appParamValue, size, reply, op);
8544446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        if (needSendBody != NEED_SEND_BODY) {
8554446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            return needSendBody;
8562c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
857d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue
8582f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        if (size == 0) {
8592f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            if (V) Log.v(TAG, "PhonebookSize is 0, return.");
8602f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            return ResponseCodes.OBEX_HTTP_OK;
8612f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        }
8622f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue
8632b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh        String orderPara = appParamValue.order.trim();
8642b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh        if (TextUtils.isEmpty(orderPara)) {
8652b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh            // If order parameter is not set by PCE, set default value per spec.
8660dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao            orderPara = "0";
8672b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh            if (D) Log.d(TAG, "Order parameter is not set by PCE. " +
8682b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh                       "Assume order by 'Indexed' by default");
8692b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh        } else if (!orderPara.equals("0") && !orderPara.equals("1")) {
8702b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh            if (V) Log.v(TAG, "Order parameter is not supported: " + appParamValue.order);
8712b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh            if (orderPara.equals("2")) {
8722b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh                // Order by sound is not supported currently
8732b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh                Log.w(TAG, "Do not support order by sound");
8742b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh                return ResponseCodes.OBEX_HTTP_NOT_IMPLEMENTED;
8752b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh            }
8762b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh            return ResponseCodes.OBEX_HTTP_PRECON_FAILED;
8772b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh        } else {
8782b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh            Log.i(TAG, "Order parameter is valid: " + orderPara);
8792b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh        }
8802b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh
8812b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh        if (orderPara.equals("0")) {
8822b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh            mOrderBy = ORDER_BY_INDEXED;
8832b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh        } else if (orderPara.equals("1")) {
8842b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh            mOrderBy = ORDER_BY_ALPHABETICAL;
8852b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh        }
8862b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh
8874446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        int sendResult = sendVcardListingXml(appParamValue.needTag, op, appParamValue.maxListCount,
8884446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                appParamValue.listStartOffset, appParamValue.searchValue,
8894446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                appParamValue.searchAttr);
8904446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        return sendResult;
8912c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    }
8922c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
8932c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    private final int pullVcardEntry(byte[] appParam, AppParamValue appParamValue,
8940b1b0069658326e8c12dc0f887e4319c5227feb5Lixin Yue            Operation op, final String name, final String current_path) {
895d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        if (name == null || name.length() < VCARD_NAME_SUFFIX_LENGTH) {
8964446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            if (D) Log.d(TAG, "Name is Null, or the length of name < 5 !");
897a4508589f298c67fda54c344760ae39f0f375c11Lixin Yue            return ResponseCodes.OBEX_HTTP_NOT_ACCEPTABLE;
8982c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
899d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        String strIndex = name.substring(0, name.length() - VCARD_NAME_SUFFIX_LENGTH + 1);
9002f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        int intIndex = 0;
9012c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        if (strIndex.trim().length() != 0) {
9022c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            try {
9032c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                intIndex = Integer.parseInt(strIndex);
9042c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            } catch (NumberFormatException e) {
9052c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                Log.e(TAG, "catch number format exception " + e.toString());
906a4508589f298c67fda54c344760ae39f0f375c11Lixin Yue                return ResponseCodes.OBEX_HTTP_NOT_ACCEPTABLE;
9072c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            }
9082c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
909d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue
9102f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        int size = mVcardManager.getPhonebookSize(appParamValue.needTag);
9112f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        if (size == 0) {
9122f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            if (V) Log.v(TAG, "PhonebookSize is 0, return.");
9136f02f510e5dc3fb994516128f2de1d78bc7f9b1eStaffan Lindvall            return ResponseCodes.OBEX_HTTP_NOT_FOUND;
9144446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        }
9154446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
9162f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        boolean vcard21 = appParamValue.vcard21;
917d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        if (appParamValue.needTag == 0) {
918d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue            Log.w(TAG, "wrong path!");
919a4508589f298c67fda54c344760ae39f0f375c11Lixin Yue            return ResponseCodes.OBEX_HTTP_NOT_ACCEPTABLE;
920d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        } else if (appParamValue.needTag == ContentType.PHONEBOOK) {
9214446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            if (intIndex < 0 || intIndex >= size) {
9224446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                Log.w(TAG, "The requested vcard is not acceptable! name= " + name);
9236f02f510e5dc3fb994516128f2de1d78bc7f9b1eStaffan Lindvall                return ResponseCodes.OBEX_HTTP_NOT_FOUND;
9242f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            } else if (intIndex == 0) {
925d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                // For PB_PATH, 0.vcf is the phone number of this phone.
926c7a57f31515107366589bd6875c3cc4af1fc806efredc                String ownerVcard = mVcardManager.getOwnerPhoneNumberVcard(vcard21,null);
9272f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                return pushBytes(op, ownerVcard);
9282f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            } else {
9292b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh                return mVcardManager.composeAndSendPhonebookOneVcard(op, intIndex, vcard21, null,
9306db8e703719f301f75acdf4acacc3296cc1b5016Hemant Gupta                        mOrderBy, appParamValue.ignorefilter, appParamValue.filter);
931d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue            }
932d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        } else {
9334446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            if (intIndex <= 0 || intIndex > size) {
934d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                Log.w(TAG, "The requested vcard is not acceptable! name= " + name);
9356f02f510e5dc3fb994516128f2de1d78bc7f9b1eStaffan Lindvall                return ResponseCodes.OBEX_HTTP_NOT_FOUND;
936d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue            }
937d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue            // For others (ich/och/cch/mch), 0.vcf is meaningless, and must
938d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue            // begin from 1.vcf
939d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue            if (intIndex >= 1) {
9402f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                return mVcardManager.composeAndSendCallLogVcards(appParamValue.needTag, op,
9416db8e703719f301f75acdf4acacc3296cc1b5016Hemant Gupta                        intIndex, intIndex, vcard21, appParamValue.ignorefilter,
9426db8e703719f301f75acdf4acacc3296cc1b5016Hemant Gupta                        appParamValue.filter);
943d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue            }
9442c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
9452f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        return ResponseCodes.OBEX_HTTP_OK;
9462c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    }
9472c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
9482c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    private final int pullPhonebook(byte[] appParam, AppParamValue appParamValue, HeaderSet reply,
9490b1b0069658326e8c12dc0f887e4319c5227feb5Lixin Yue            Operation op, final String name) {
9502c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        // code start for passing PTS3.2 TC_PSE_PBD_BI_01_C
9512c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        if (name != null) {
9522c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            int dotIndex = name.indexOf(".");
9532c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            String vcf = "vcf";
9542c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            if (dotIndex >= 0 && dotIndex <= name.length()) {
9552c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                if (name.regionMatches(dotIndex + 1, vcf, 0, vcf.length()) == false) {
9562c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                    Log.w(TAG, "name is not .vcf");
9572c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                    return ResponseCodes.OBEX_HTTP_NOT_ACCEPTABLE;
9582c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                }
9592c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            }
960d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        } // code end for passing PTS3.2 TC_PSE_PBD_BI_01_C
9612c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
9622f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        int pbSize = mVcardManager.getPhonebookSize(appParamValue.needTag);
9634446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        int needSendBody = handleAppParaForResponse(appParamValue, pbSize, reply, op);
9644446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        if (needSendBody != NEED_SEND_BODY) {
9654446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            return needSendBody;
9662c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
9672c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
9682f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        if (pbSize == 0) {
9692f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            if (V) Log.v(TAG, "PhonebookSize is 0, return.");
9702f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            return ResponseCodes.OBEX_HTTP_OK;
9712f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        }
9722f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue
973d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        int requestSize = pbSize >= appParamValue.maxListCount ? appParamValue.maxListCount
974d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                : pbSize;
975d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        int startPoint = appParamValue.listStartOffset;
97618bde766b20c899310ebdd5ca823e30ff27d407fLixin Yue        if (startPoint < 0 || startPoint >= pbSize) {
97718bde766b20c899310ebdd5ca823e30ff27d407fLixin Yue            Log.w(TAG, "listStartOffset is not correct! " + startPoint);
97818bde766b20c899310ebdd5ca823e30ff27d407fLixin Yue            return ResponseCodes.OBEX_HTTP_OK;
97918bde766b20c899310ebdd5ca823e30ff27d407fLixin Yue        }
98018bde766b20c899310ebdd5ca823e30ff27d407fLixin Yue
98177b122f551ae37811c75ae76fa2029f7b3f2f404a        // Limit the number of call log to CALLLOG_NUM_LIMIT
98277b122f551ae37811c75ae76fa2029f7b3f2f404a        if (appParamValue.needTag != BluetoothPbapObexServer.ContentType.PHONEBOOK) {
98377b122f551ae37811c75ae76fa2029f7b3f2f404a            if (requestSize > CALLLOG_NUM_LIMIT) {
98477b122f551ae37811c75ae76fa2029f7b3f2f404a               requestSize = CALLLOG_NUM_LIMIT;
98577b122f551ae37811c75ae76fa2029f7b3f2f404a            }
98677b122f551ae37811c75ae76fa2029f7b3f2f404a        }
98777b122f551ae37811c75ae76fa2029f7b3f2f404a
98818bde766b20c899310ebdd5ca823e30ff27d407fLixin Yue        int endPoint = startPoint + requestSize - 1;
98918bde766b20c899310ebdd5ca823e30ff27d407fLixin Yue        if (endPoint > pbSize - 1) {
99018bde766b20c899310ebdd5ca823e30ff27d407fLixin Yue            endPoint = pbSize - 1;
9912c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
9924446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        if (D) Log.d(TAG, "pullPhonebook(): requestSize=" + requestSize + " startPoint=" +
9934446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                startPoint + " endPoint=" + endPoint);
9944446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
9952f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        boolean vcard21 = appParamValue.vcard21;
9962f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        if (appParamValue.needTag == BluetoothPbapObexServer.ContentType.PHONEBOOK) {
99718bde766b20c899310ebdd5ca823e30ff27d407fLixin Yue            if (startPoint == 0) {
998c7a57f31515107366589bd6875c3cc4af1fc806efredc                String ownerVcard = mVcardManager.getOwnerPhoneNumberVcard(vcard21,null);
99918bde766b20c899310ebdd5ca823e30ff27d407fLixin Yue                if (endPoint == 0) {
100018bde766b20c899310ebdd5ca823e30ff27d407fLixin Yue                    return pushBytes(op, ownerVcard);
100118bde766b20c899310ebdd5ca823e30ff27d407fLixin Yue                } else {
100218bde766b20c899310ebdd5ca823e30ff27d407fLixin Yue                    return mVcardManager.composeAndSendPhonebookVcards(op, 1, endPoint, vcard21,
10036db8e703719f301f75acdf4acacc3296cc1b5016Hemant Gupta                            ownerVcard, appParamValue.ignorefilter, appParamValue.filter);
100418bde766b20c899310ebdd5ca823e30ff27d407fLixin Yue                }
10052f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            } else {
100618bde766b20c899310ebdd5ca823e30ff27d407fLixin Yue                return mVcardManager.composeAndSendPhonebookVcards(op, startPoint, endPoint,
10076db8e703719f301f75acdf4acacc3296cc1b5016Hemant Gupta                        vcard21, null, appParamValue.ignorefilter, appParamValue.filter);
10082f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            }
10092f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        } else {
101018bde766b20c899310ebdd5ca823e30ff27d407fLixin Yue            return mVcardManager.composeAndSendCallLogVcards(appParamValue.needTag, op,
10116db8e703719f301f75acdf4acacc3296cc1b5016Hemant Gupta                    startPoint + 1, endPoint + 1, vcard21, appParamValue.ignorefilter,
10126db8e703719f301f75acdf4acacc3296cc1b5016Hemant Gupta                    appParamValue.filter);
10132c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
10142c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    }
10152c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
10162f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue    public static boolean closeStream(final OutputStream out, final Operation op) {
10172c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        boolean returnvalue = true;
10182c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        try {
10192c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            if (out != null) {
10202c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                out.close();
10212c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            }
10222c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        } catch (IOException e) {
10232c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            Log.e(TAG, "outputStream close failed" + e.toString());
10242c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            returnvalue = false;
10252c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
10262c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        try {
10272c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            if (op != null) {
10282c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                op.close();
10292c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            }
10302c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        } catch (IOException e) {
10314446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            Log.e(TAG, "operation close failed" + e.toString());
10322c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            returnvalue = false;
10332c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
10342c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        return returnvalue;
10352c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    }
10362c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
1037d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue    // Reserved for future use. In case PSE challenge PCE and PCE input wrong
10382c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    // session key.
10392c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    public final void onAuthenticationFailure(final byte[] userName) {
10402c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    }
1041c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue
10422f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue    public static final String createSelectionPara(final int type) {
10432f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        String selection = null;
10442f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        switch (type) {
10452f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            case ContentType.INCOMING_CALL_HISTORY:
10462f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                selection = Calls.TYPE + "=" + CallLog.Calls.INCOMING_TYPE;
10472f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                break;
10482f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            case ContentType.OUTGOING_CALL_HISTORY:
10492f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                selection = Calls.TYPE + "=" + CallLog.Calls.OUTGOING_TYPE;
10502f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                break;
10512f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            case ContentType.MISSED_CALL_HISTORY:
10522f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                selection = Calls.TYPE + "=" + CallLog.Calls.MISSED_TYPE;
10532f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                break;
10542f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            default:
10552f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                break;
10562f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        }
10572f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        if (V) Log.v(TAG, "Call log selection: " + selection);
10582f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        return selection;
10592f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue    }
10602f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue
1061e479e18951a375a548e617e86e3b1b7d121351a1Fred    /**
1062e479e18951a375a548e617e86e3b1b7d121351a1Fred     * XML encode special characters in the name field
1063e479e18951a375a548e617e86e3b1b7d121351a1Fred     */
1064e479e18951a375a548e617e86e3b1b7d121351a1Fred    private void xmlEncode(String name, StringBuilder result) {
1065e479e18951a375a548e617e86e3b1b7d121351a1Fred        if (name == null) {
1066e479e18951a375a548e617e86e3b1b7d121351a1Fred            return;
1067e479e18951a375a548e617e86e3b1b7d121351a1Fred        }
1068e479e18951a375a548e617e86e3b1b7d121351a1Fred
1069e479e18951a375a548e617e86e3b1b7d121351a1Fred        final StringCharacterIterator iterator = new StringCharacterIterator(name);
1070e479e18951a375a548e617e86e3b1b7d121351a1Fred        char character =  iterator.current();
1071e479e18951a375a548e617e86e3b1b7d121351a1Fred        while (character != CharacterIterator.DONE ){
1072e479e18951a375a548e617e86e3b1b7d121351a1Fred            if (character == '<') {
1073e479e18951a375a548e617e86e3b1b7d121351a1Fred                result.append("&lt;");
1074e479e18951a375a548e617e86e3b1b7d121351a1Fred            }
1075e479e18951a375a548e617e86e3b1b7d121351a1Fred            else if (character == '>') {
1076e479e18951a375a548e617e86e3b1b7d121351a1Fred                result.append("&gt;");
1077e479e18951a375a548e617e86e3b1b7d121351a1Fred            }
1078e479e18951a375a548e617e86e3b1b7d121351a1Fred            else if (character == '\"') {
1079e479e18951a375a548e617e86e3b1b7d121351a1Fred                result.append("&quot;");
1080e479e18951a375a548e617e86e3b1b7d121351a1Fred            }
1081e479e18951a375a548e617e86e3b1b7d121351a1Fred            else if (character == '\'') {
1082e479e18951a375a548e617e86e3b1b7d121351a1Fred                result.append("&#039;");
1083e479e18951a375a548e617e86e3b1b7d121351a1Fred            }
1084e479e18951a375a548e617e86e3b1b7d121351a1Fred            else if (character == '&') {
1085e479e18951a375a548e617e86e3b1b7d121351a1Fred                result.append("&amp;");
1086e479e18951a375a548e617e86e3b1b7d121351a1Fred            }
1087e479e18951a375a548e617e86e3b1b7d121351a1Fred            else {
1088e479e18951a375a548e617e86e3b1b7d121351a1Fred                // The char is not a special one, add it to the result as is
1089e479e18951a375a548e617e86e3b1b7d121351a1Fred                result.append(character);
1090e479e18951a375a548e617e86e3b1b7d121351a1Fred            }
1091e479e18951a375a548e617e86e3b1b7d121351a1Fred            character = iterator.next();
1092e479e18951a375a548e617e86e3b1b7d121351a1Fred        }
1093e479e18951a375a548e617e86e3b1b7d121351a1Fred    }
1094e479e18951a375a548e617e86e3b1b7d121351a1Fred
1095e479e18951a375a548e617e86e3b1b7d121351a1Fred    private void writeVCardEntry(int vcfIndex, String name, StringBuilder result) {
1096e479e18951a375a548e617e86e3b1b7d121351a1Fred        result.append("<card handle=\"");
1097e479e18951a375a548e617e86e3b1b7d121351a1Fred        result.append(vcfIndex);
1098e479e18951a375a548e617e86e3b1b7d121351a1Fred        result.append(".vcf\" name=\"");
1099e479e18951a375a548e617e86e3b1b7d121351a1Fred        xmlEncode(name, result);
1100e479e18951a375a548e617e86e3b1b7d121351a1Fred        result.append("\"/>");
1101e479e18951a375a548e617e86e3b1b7d121351a1Fred    }
1102e479e18951a375a548e617e86e3b1b7d121351a1Fred
11038fa8d120e86c7488616cc7f7310843f15278b5d9Zhihai Xu    private void notifyUpdateWakeLock() {
11048fa8d120e86c7488616cc7f7310843f15278b5d9Zhihai Xu        Message msg = Message.obtain(mCallback);
11058fa8d120e86c7488616cc7f7310843f15278b5d9Zhihai Xu        msg.what = BluetoothPbapService.MSG_ACQUIRE_WAKE_LOCK;
11068fa8d120e86c7488616cc7f7310843f15278b5d9Zhihai Xu        msg.sendToTarget();
11078fa8d120e86c7488616cc7f7310843f15278b5d9Zhihai Xu    }
11088fa8d120e86c7488616cc7f7310843f15278b5d9Zhihai Xu
11092f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue    public static final void logHeader(HeaderSet hs) {
1110c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue        Log.v(TAG, "Dumping HeaderSet " + hs.toString());
1111c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue        try {
1112c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue
1113c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue            Log.v(TAG, "COUNT : " + hs.getHeader(HeaderSet.COUNT));
1114c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue            Log.v(TAG, "NAME : " + hs.getHeader(HeaderSet.NAME));
1115c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue            Log.v(TAG, "TYPE : " + hs.getHeader(HeaderSet.TYPE));
1116c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue            Log.v(TAG, "LENGTH : " + hs.getHeader(HeaderSet.LENGTH));
1117c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue            Log.v(TAG, "TIME_ISO_8601 : " + hs.getHeader(HeaderSet.TIME_ISO_8601));
1118c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue            Log.v(TAG, "TIME_4_BYTE : " + hs.getHeader(HeaderSet.TIME_4_BYTE));
1119c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue            Log.v(TAG, "DESCRIPTION : " + hs.getHeader(HeaderSet.DESCRIPTION));
1120c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue            Log.v(TAG, "TARGET : " + hs.getHeader(HeaderSet.TARGET));
1121c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue            Log.v(TAG, "HTTP : " + hs.getHeader(HeaderSet.HTTP));
1122c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue            Log.v(TAG, "WHO : " + hs.getHeader(HeaderSet.WHO));
1123c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue            Log.v(TAG, "OBJECT_CLASS : " + hs.getHeader(HeaderSet.OBJECT_CLASS));
1124c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue            Log.v(TAG, "APPLICATION_PARAMETER : " + hs.getHeader(HeaderSet.APPLICATION_PARAMETER));
1125c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue        } catch (IOException e) {
1126c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue            Log.e(TAG, "dump HeaderSet error " + e);
1127c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue        }
1128c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue    }
11292c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan}
1130