BluetoothPbapObexServer.java revision 9522370104410f24602ac98172bfbda27f89780d
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;
362c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fanimport android.os.Message;
372c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fanimport android.os.Handler;
3818bde766b20c899310ebdd5ca823e30ff27d407fLixin Yueimport android.text.TextUtils;
392c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fanimport android.util.Log;
402f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yueimport android.provider.CallLog.Calls;
412f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yueimport android.provider.CallLog;
422c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
432c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fanimport java.io.IOException;
442c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fanimport java.io.OutputStream;
452c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fanimport java.util.ArrayList;
464446eaa935994bc91d6d308303e8d27526b4590dLixin Yueimport java.util.Arrays;
472c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
482c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fanimport javax.obex.ServerRequestHandler;
492c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fanimport javax.obex.ResponseCodes;
502c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fanimport javax.obex.ApplicationParameter;
510b1b0069658326e8c12dc0f887e4319c5227feb5Lixin Yueimport javax.obex.ServerOperation;
522c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fanimport javax.obex.Operation;
532c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fanimport javax.obex.HeaderSet;
542c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
552c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fanpublic class BluetoothPbapObexServer extends ServerRequestHandler {
562c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
572c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    private static final String TAG = "BluetoothPbapObexServer";
582c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
594446eaa935994bc91d6d308303e8d27526b4590dLixin Yue    private static final boolean D = BluetoothPbapService.DEBUG;
604446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
614446eaa935994bc91d6d308303e8d27526b4590dLixin Yue    private static final boolean V = BluetoothPbapService.VERBOSE;
622c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
634446eaa935994bc91d6d308303e8d27526b4590dLixin Yue    private static final int UUID_LENGTH = 16;
642c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
65d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue    // The length of suffix of vcard name - ".vcf" is 5
66d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue    private static final int VCARD_NAME_SUFFIX_LENGTH = 5;
672c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
682c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    // 128 bit UUID for PBAP
692c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    private static final byte[] PBAP_TARGET = new byte[] {
702c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            0x79, 0x61, 0x35, (byte)0xf0, (byte)0xf0, (byte)0xc5, 0x11, (byte)0xd8, 0x09, 0x66,
712c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            0x08, 0x00, 0x20, 0x0c, (byte)0x9a, 0x66
722c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    };
732c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
744446eaa935994bc91d6d308303e8d27526b4590dLixin Yue    // Currently not support SIM card
75d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue    private static final String[] LEGAL_PATH = {
762c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            "/telecom", "/telecom/pb", "/telecom/ich", "/telecom/och", "/telecom/mch",
774446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            "/telecom/cch"
784446eaa935994bc91d6d308303e8d27526b4590dLixin Yue    };
794446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
804446eaa935994bc91d6d308303e8d27526b4590dLixin Yue    @SuppressWarnings("unused")
814446eaa935994bc91d6d308303e8d27526b4590dLixin Yue    private static final String[] LEGAL_PATH_WITH_SIM = {
824446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            "/telecom", "/telecom/pb", "/telecom/ich", "/telecom/och", "/telecom/mch",
832c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            "/telecom/cch", "/SIM1", "/SIM1/telecom", "/SIM1/telecom/ich", "/SIM1/telecom/och",
842c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            "/SIM1/telecom/mch", "/SIM1/telecom/cch", "/SIM1/telecom/pb"
854446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
862c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    };
872c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
884446eaa935994bc91d6d308303e8d27526b4590dLixin Yue    // SIM card
894446eaa935994bc91d6d308303e8d27526b4590dLixin Yue    private static final String SIM1 = "SIM1";
904446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
912c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    // missed call history
922c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    private static final String MCH = "mch";
932c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
942c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    // incoming call history
952c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    private static final String ICH = "ich";
962c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
972c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    // outgoing call history
982c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    private static final String OCH = "och";
992c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
1002c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    // combined call history
1012c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    private static final String CCH = "cch";
1022c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
1032c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    // phone book
1042c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    private static final String PB = "pb";
1052c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
1062c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    private static final String ICH_PATH = "/telecom/ich";
1072c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
1082c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    private static final String OCH_PATH = "/telecom/och";
1092c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
1102c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    private static final String MCH_PATH = "/telecom/mch";
1112c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
1122c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    private static final String CCH_PATH = "/telecom/cch";
1132c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
1142c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    private static final String PB_PATH = "/telecom/pb";
1152c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
1162c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    // type for list vcard objects
1172c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    private static final String TYPE_LISTING = "x-bt/vcard-listing";
1182c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
1192c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    // type for get single vcard object
1202c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    private static final String TYPE_VCARD = "x-bt/vcard";
1212c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
1224446eaa935994bc91d6d308303e8d27526b4590dLixin Yue    // to indicate if need send body besides headers
123d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue    private static final int NEED_SEND_BODY = -1;
124d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue
1252c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    // type for download all vcard objects
1262c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    private static final String TYPE_PB = "x-bt/phonebook";
1272c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
128d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue    // The number of indexes in the phone book.
129d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue    private boolean mNeedPhonebookSize = false;
1302c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
131d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue    // The number of missed calls that have not been checked on the PSE at the
132d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue    // point of the request. Only apply to "mch" case.
133d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue    private boolean mNeedNewMissedCallsNum = false;
1342c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
135d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue    private int mMissedCallSize = 0;
1362c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
137d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue    // record current path the client are browsing
138d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue    private String mCurrentPath = "";
1392c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
140d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue    private Handler mCallback = null;
1412c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
1422f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue    private Context mContext;
1432f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue
1442f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue    private BluetoothPbapVcardManager mVcardManager;
1452f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue
1462b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh    private int mOrderBy  = ORDER_BY_INDEXED;
1472b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh
14877b122f551ae37811c75ae76fa2029f7b3f2f404a    private static int CALLLOG_NUM_LIMIT = 50;
14977b122f551ae37811c75ae76fa2029f7b3f2f404a
1502b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh    public static int ORDER_BY_INDEXED = 0;
1512b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh
1522b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh    public static int ORDER_BY_ALPHABETICAL = 1;
1532b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh
1540b1b0069658326e8c12dc0f887e4319c5227feb5Lixin Yue    public static boolean sIsAborted = false;
1550b1b0069658326e8c12dc0f887e4319c5227feb5Lixin Yue
156d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue    public static class ContentType {
157d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        public static final int PHONEBOOK = 1;
1582c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
159d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        public static final int INCOMING_CALL_HISTORY = 2;
1602c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
161d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        public static final int OUTGOING_CALL_HISTORY = 3;
1622c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
163d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        public static final int MISSED_CALL_HISTORY = 4;
1642c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
165d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        public static final int COMBINED_CALL_HISTORY = 5;
166d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue    }
1672c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
1682f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue    public BluetoothPbapObexServer(Handler callback, Context context) {
1692c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        super();
1702c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        mCallback = callback;
1712f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        mContext = context;
1722f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        mVcardManager = new BluetoothPbapVcardManager(mContext);
173d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue
174d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        // set initial value when ObexServer created
1752f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        mMissedCallSize = mVcardManager.getPhonebookSize(ContentType.MISSED_CALL_HISTORY);
1764446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        if (D) Log.d(TAG, "Initialize mMissedCallSize=" + mMissedCallSize);
1772c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    }
1782c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
1792c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    @Override
180c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue    public int onConnect(final HeaderSet request, HeaderSet reply) {
181c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue        if (V) logHeader(request);
1822c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        try {
183c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue            byte[] uuid = (byte[])request.getHeader(HeaderSet.TARGET);
184c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue            if (uuid == null) {
185c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue                return ResponseCodes.OBEX_HTTP_NOT_ACCEPTABLE;
186c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue            }
187c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue            if (D) Log.d(TAG, "onConnect(): uuid=" + Arrays.toString(uuid));
1884446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
189c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue            if (uuid.length != UUID_LENGTH) {
1902c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                Log.w(TAG, "Wrong UUID length");
1912c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                return ResponseCodes.OBEX_HTTP_NOT_ACCEPTABLE;
1922c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            }
1932c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            for (int i = 0; i < UUID_LENGTH; i++) {
194c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue                if (uuid[i] != PBAP_TARGET[i]) {
1952c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                    Log.w(TAG, "Wrong UUID");
1962c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                    return ResponseCodes.OBEX_HTTP_NOT_ACCEPTABLE;
1972c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                }
1982c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            }
199c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue            reply.setHeader(HeaderSet.WHO, uuid);
2002c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        } catch (IOException e) {
2012c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            Log.e(TAG, e.toString());
2022c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
2032c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
2042c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
205c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue        try {
206c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue            byte[] remote = (byte[])request.getHeader(HeaderSet.WHO);
207c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue            if (remote != null) {
208c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue                if (D) Log.d(TAG, "onConnect(): remote=" + Arrays.toString(remote));
209c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue                reply.setHeader(HeaderSet.TARGET, remote);
210c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue            }
211c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue        } catch (IOException e) {
212c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue            Log.e(TAG, e.toString());
213c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue            return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
214c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue        }
215c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue
216c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue        if (V) Log.v(TAG, "onConnect(): uuid is ok, will send out " +
2174446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                "MSG_SESSION_ESTABLISHED msg.");
2184446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
2192c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        Message msg = Message.obtain(mCallback);
2202c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        msg.what = BluetoothPbapService.MSG_SESSION_ESTABLISHED;
2212c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        msg.sendToTarget();
2222c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
2232c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        return ResponseCodes.OBEX_HTTP_OK;
2242c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    }
2252c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
2262c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    @Override
2272c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    public void onDisconnect(final HeaderSet req, final HeaderSet resp) {
2284446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        if (D) Log.d(TAG, "onDisconnect(): enter");
229c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue        if (V) logHeader(req);
2304446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
2312c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        resp.responseCode = ResponseCodes.OBEX_HTTP_OK;
2322c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        if (mCallback != null) {
2332c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            Message msg = Message.obtain(mCallback);
2342c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            msg.what = BluetoothPbapService.MSG_SESSION_DISCONNECTED;
2352c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            msg.sendToTarget();
2364446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            if (V) Log.v(TAG, "onDisconnect(): msg MSG_SESSION_DISCONNECTED sent out.");
2372c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
2382c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    }
2392c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
2402c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    @Override
2410b1b0069658326e8c12dc0f887e4319c5227feb5Lixin Yue    public int onAbort(HeaderSet request, HeaderSet reply) {
2420b1b0069658326e8c12dc0f887e4319c5227feb5Lixin Yue        if (D) Log.d(TAG, "onAbort(): enter.");
2430b1b0069658326e8c12dc0f887e4319c5227feb5Lixin Yue        sIsAborted = true;
2440b1b0069658326e8c12dc0f887e4319c5227feb5Lixin Yue        return ResponseCodes.OBEX_HTTP_OK;
2450b1b0069658326e8c12dc0f887e4319c5227feb5Lixin Yue    }
2460b1b0069658326e8c12dc0f887e4319c5227feb5Lixin Yue
2470b1b0069658326e8c12dc0f887e4319c5227feb5Lixin Yue    @Override
2482c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    public int onPut(final Operation op) {
2494446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        if (D) Log.d(TAG, "onPut(): not support PUT request.");
2502c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        return ResponseCodes.OBEX_HTTP_BAD_REQUEST;
2512c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    }
2522c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
2532c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    @Override
2542c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    public int onSetPath(final HeaderSet request, final HeaderSet reply, final boolean backup,
2552c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            final boolean create) {
256c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue        if (V) logHeader(request);
2574446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        if (D) Log.d(TAG, "before setPath, mCurrentPath ==  " + mCurrentPath);
2584446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
2592c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        String current_path_tmp = mCurrentPath;
2602c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        String tmp_path = null;
2612c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        try {
2622c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            tmp_path = (String)request.getHeader(HeaderSet.NAME);
2632c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        } catch (IOException e) {
2642c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            Log.e(TAG, "Get name header fail");
2652c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
2662c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
2674446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        if (D) Log.d(TAG, "backup=" + backup + " create=" + create + " name=" + tmp_path);
268d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue
269d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        if (backup) {
270d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue            if (current_path_tmp.length() != 0) {
271d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                current_path_tmp = current_path_tmp.substring(0,
272d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                        current_path_tmp.lastIndexOf("/"));
273d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue            }
274d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        } else {
2752c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            if (tmp_path == null) {
2762c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                current_path_tmp = "";
2772c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            } else {
2782c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                current_path_tmp = current_path_tmp + "/" + tmp_path;
2792c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            }
2802c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
2812c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
2822c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        if ((current_path_tmp.length() != 0) && (!isLegalPath(current_path_tmp))) {
283d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue            if (create) {
284d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                Log.w(TAG, "path create is forbidden!");
285d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                return ResponseCodes.OBEX_HTTP_FORBIDDEN;
286d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue            } else {
287d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                Log.w(TAG, "path is not legal");
288a4508589f298c67fda54c344760ae39f0f375c11Lixin Yue                return ResponseCodes.OBEX_HTTP_NOT_FOUND;
289d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue            }
2902c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
2912c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        mCurrentPath = current_path_tmp;
2924446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        if (V) Log.v(TAG, "after setPath, mCurrentPath ==  " + mCurrentPath);
2934446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
2942c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        return ResponseCodes.OBEX_HTTP_OK;
2952c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    }
2962c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
2972c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    @Override
2982c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    public void onClose() {
2992c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        if (mCallback != null) {
3002c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            Message msg = Message.obtain(mCallback);
3012c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            msg.what = BluetoothPbapService.MSG_SERVERSESSION_CLOSE;
3022c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            msg.sendToTarget();
3034446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            if (D) Log.d(TAG, "onClose(): msg MSG_SERVERSESSION_CLOSE sent out.");
3042c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
3052c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    }
3062c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
3072c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    @Override
3080b1b0069658326e8c12dc0f887e4319c5227feb5Lixin Yue    public int onGet(Operation op) {
30920b5a93b6e18cd441065edfdf676ad612affc507Jaikumar Ganesh        sIsAborted = false;
3102c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        HeaderSet request = null;
3112c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        HeaderSet reply = new HeaderSet();
3122c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        String type = "";
3132c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        String name = "";
3142c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        byte[] appParam = null;
3152c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        AppParamValue appParamValue = new AppParamValue();
3162c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        try {
3172c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            request = op.getReceivedHeader();
3182c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            type = (String)request.getHeader(HeaderSet.TYPE);
3192c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            name = (String)request.getHeader(HeaderSet.NAME);
3202c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            appParam = (byte[])request.getHeader(HeaderSet.APPLICATION_PARAMETER);
3212c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        } catch (IOException e) {
3222c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            Log.e(TAG, "request headers error");
3232c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
3242c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
325d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue
326c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue        if (V) logHeader(request);
3274446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        if (D) Log.d(TAG, "OnGet type is " + type + "; name is " + name);
328d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue
32918bde766b20c899310ebdd5ca823e30ff27d407fLixin Yue        if (type == null) {
330a4508589f298c67fda54c344760ae39f0f375c11Lixin Yue            return ResponseCodes.OBEX_HTTP_NOT_ACCEPTABLE;
33118bde766b20c899310ebdd5ca823e30ff27d407fLixin Yue        }
332d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        // Accroding to specification,the name header could be omitted such as
333d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        // sony erriccsonHBH-DS980
334d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue
335d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        // For "x-bt/phonebook" and "x-bt/vcard-listing":
336d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        // if name == null, guess what carkit actually want from current path
337d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        // For "x-bt/vcard":
338d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        // We decide which kind of content client would like per current path
339d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue
340d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        boolean validName = true;
34118bde766b20c899310ebdd5ca823e30ff27d407fLixin Yue        if (TextUtils.isEmpty(name)) {
342d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue            validName = false;
343d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        }
344d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue
345d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        if (!validName || (validName && type.equals(TYPE_VCARD))) {
3464446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            if (D) Log.d(TAG, "Guess what carkit actually want from current path (" +
3474446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                    mCurrentPath + ")");
3484446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
3492b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh            if (mCurrentPath.equals(PB_PATH)) {
350d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                appParamValue.needTag = ContentType.PHONEBOOK;
3512b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh            } else if (mCurrentPath.equals(ICH_PATH)) {
352d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                appParamValue.needTag = ContentType.INCOMING_CALL_HISTORY;
3532b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh            } else if (mCurrentPath.equals(OCH_PATH)) {
354d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                appParamValue.needTag = ContentType.OUTGOING_CALL_HISTORY;
3552b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh            } else if (mCurrentPath.equals(MCH_PATH)) {
356d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                appParamValue.needTag = ContentType.MISSED_CALL_HISTORY;
357d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                mNeedNewMissedCallsNum = true;
3582b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh            } else if (mCurrentPath.equals(CCH_PATH)) {
359d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                appParamValue.needTag = ContentType.COMBINED_CALL_HISTORY;
360d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue            } else {
361d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                Log.w(TAG, "mCurrentpath is not valid path!!!");
362a4508589f298c67fda54c344760ae39f0f375c11Lixin Yue                return ResponseCodes.OBEX_HTTP_NOT_ACCEPTABLE;
3632c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            }
3644446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            if (D) Log.v(TAG, "onGet(): appParamValue.needTag=" + appParamValue.needTag);
3654446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        } else {
3664446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            // Not support SIM card currently
3674446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            if (name.contains(SIM1.subSequence(0, SIM1.length()))) {
3684446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                Log.w(TAG, "Not support access SIM card info!");
3694446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                return ResponseCodes.OBEX_HTTP_NOT_ACCEPTABLE;
3704446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            }
3714446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
3724446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            // we have weak name checking here to provide better
3732c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            // compatibility with other devices,although unique name such as
3742c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            // "pb.vcf" is required by SIG spec.
3752c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            if (name.contains(PB.subSequence(0, PB.length()))) {
376d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                appParamValue.needTag = ContentType.PHONEBOOK;
3774446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                if (D) Log.v(TAG, "download phonebook request");
378d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue            } else if (name.contains(ICH.subSequence(0, ICH.length()))) {
379d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                appParamValue.needTag = ContentType.INCOMING_CALL_HISTORY;
3804446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                if (D) Log.v(TAG, "download incoming calls request");
381d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue            } else if (name.contains(OCH.subSequence(0, OCH.length()))) {
382d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                appParamValue.needTag = ContentType.OUTGOING_CALL_HISTORY;
3834446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                if (D) Log.v(TAG, "download outgoing calls request");
384d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue            } else if (name.contains(MCH.subSequence(0, MCH.length()))) {
385d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                appParamValue.needTag = ContentType.MISSED_CALL_HISTORY;
386d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                mNeedNewMissedCallsNum = true;
3874446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                if (D) Log.v(TAG, "download missed calls request");
388d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue            } else if (name.contains(CCH.subSequence(0, CCH.length()))) {
389d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                appParamValue.needTag = ContentType.COMBINED_CALL_HISTORY;
3904446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                if (D) Log.v(TAG, "download combined calls request");
391d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue            } else {
392d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                Log.w(TAG, "Input name doesn't contain valid info!!!");
393a4508589f298c67fda54c344760ae39f0f375c11Lixin Yue                return ResponseCodes.OBEX_HTTP_NOT_ACCEPTABLE;
3942c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            }
3952c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
396d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue
3974ce32fccf381a3b448f0d5ff56665201c0e0e6d3Ola Johnsson        if ((appParam != null) && !parseApplicationParameter(appParam, appParamValue)) {
398d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue            return ResponseCodes.OBEX_HTTP_BAD_REQUEST;
399d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        }
400d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue
4012c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        // listing request
4022c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        if (type.equals(TYPE_LISTING)) {
4032c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            return pullVcardListing(appParam, appParamValue, reply, op);
4042c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
4052c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        // pull vcard entry request
4062c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        else if (type.equals(TYPE_VCARD)) {
4072c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            return pullVcardEntry(appParam, appParamValue, op, name, mCurrentPath);
4082c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
4092c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        // down load phone book request
4102c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        else if (type.equals(TYPE_PB)) {
4112c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            return pullPhonebook(appParam, appParamValue, reply, op, name);
4122c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        } else {
4132c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            Log.w(TAG, "unknown type request!!!");
414a4508589f298c67fda54c344760ae39f0f375c11Lixin Yue            return ResponseCodes.OBEX_HTTP_NOT_ACCEPTABLE;
4152c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
416d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue    }
4172c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
4182c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    /** check whether path is legal */
4192c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    private final boolean isLegalPath(final String str) {
4202c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        if (str.length() == 0) {
4212c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            return true;
4222c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
4234446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        for (int i = 0; i < LEGAL_PATH.length; i++) {
424d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue            if (str.equals(LEGAL_PATH[i])) {
4252c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                return true;
4262c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            }
4272c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
4282c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        return false;
4292c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    }
4302c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
4312c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    private class AppParamValue {
4322c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        public int maxListCount;
4332c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
4342c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        public int listStartOffset;
4352c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
4362c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        public String searchValue;
4372c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
4382b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh        // Indicate which vCard parameter the search operation shall be carried
4392b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh        // out on. Can be "Name | Number | Sound", default value is "Name".
4402c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        public String searchAttr;
4412c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
4422b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh        // Indicate which sorting order shall be used for the
4432b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh        // <x-bt/vcard-listing> listing object.
4442b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh        // Can be "Alphabetical | Indexed | Phonetical", default value is
4452b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh        // "Indexed".
4462b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh        public String order;
4472b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh
4482c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        public int needTag;
4492c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
4502c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        public boolean vcard21;
4512c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
4522c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        public AppParamValue() {
4534ce32fccf381a3b448f0d5ff56665201c0e0e6d3Ola Johnsson            maxListCount = 0xFFFF;
4542c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            listStartOffset = 0;
4552c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            searchValue = "";
4562c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            searchAttr = "";
4572b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh            order = "";
4582c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            needTag = 0x00;
4592c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            vcard21 = true;
4602c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
4612c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
4622c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        public void dump() {
4632c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            Log.i(TAG, "maxListCount=" + maxListCount + " listStartOffset=" + listStartOffset
4642c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                    + " searchValue=" + searchValue + " searchAttr=" + searchAttr + " needTag="
4652b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh                    + needTag + " vcard21=" + vcard21 + " order=" + order);
4662c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
4672c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    }
4682c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
4692c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    /** To parse obex application parameter */
4702c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    private final boolean parseApplicationParameter(final byte[] appParam,
4712c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            AppParamValue appParamValue) {
4722c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        int i = 0;
473d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        boolean parseOk = true;
4742c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        while (i < appParam.length) {
4752c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            switch (appParam[i]) {
4762c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                case ApplicationParameter.TRIPLET_TAGID.FILTER_TAGID:
4772c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                    i += 2; // length and tag field in triplet
4782c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                    i += ApplicationParameter.TRIPLET_LENGTH.FILTER_LENGTH;
4792c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                    break;
4802c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                case ApplicationParameter.TRIPLET_TAGID.ORDER_TAGID:
4812c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                    i += 2; // length and tag field in triplet
4822b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh                    appParamValue.order = Byte.toString(appParam[i]);
4832c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                    i += ApplicationParameter.TRIPLET_LENGTH.ORDER_LENGTH;
4842c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                    break;
4852c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                case ApplicationParameter.TRIPLET_TAGID.SEARCH_VALUE_TAGID:
4862c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                    i += 1; // length field in triplet
4872c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                    // length of search value is variable
4884ce32fccf381a3b448f0d5ff56665201c0e0e6d3Ola Johnsson                    int length = appParam[i];
4890dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao                    if (length == 0) {
4900dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao                        parseOk = false;
4910dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao                        break;
4920dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao                    }
4930dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao                    if (appParam[i+length] == 0x0) {
4940dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao                        appParamValue.searchValue = new String(appParam, i + 1, length-1);
4950dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao                    } else {
4960dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao                        appParamValue.searchValue = new String(appParam, i + 1, length);
4970dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao                    }
4984ce32fccf381a3b448f0d5ff56665201c0e0e6d3Ola Johnsson                    i += length;
4992c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                    i += 1;
5002c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                    break;
5012c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                case ApplicationParameter.TRIPLET_TAGID.SEARCH_ATTRIBUTE_TAGID:
5022c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                    i += 2;
5032c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                    appParamValue.searchAttr = Byte.toString(appParam[i]);
5042c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                    i += ApplicationParameter.TRIPLET_LENGTH.SEARCH_ATTRIBUTE_LENGTH;
5052c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                    break;
5062c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                case ApplicationParameter.TRIPLET_TAGID.MAXLISTCOUNT_TAGID:
5072c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                    i += 2;
5082c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                    if (appParam[i] == 0 && appParam[i + 1] == 0) {
509d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                        mNeedPhonebookSize = true;
5102c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                    } else {
5112c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                        int highValue = appParam[i] & 0xff;
5122c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                        int lowValue = appParam[i + 1] & 0xff;
5132c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                        appParamValue.maxListCount = highValue * 256 + lowValue;
5142c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                    }
5152c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                    i += ApplicationParameter.TRIPLET_LENGTH.MAXLISTCOUNT_LENGTH;
5162c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                    break;
5172c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                case ApplicationParameter.TRIPLET_TAGID.LISTSTARTOFFSET_TAGID:
5182c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                    i += 2;
519d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                    int highValue = appParam[i] & 0xff;
520d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                    int lowValue = appParam[i + 1] & 0xff;
521d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                    appParamValue.listStartOffset = highValue * 256 + lowValue;
5222c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                    i += ApplicationParameter.TRIPLET_LENGTH.LISTSTARTOFFSET_LENGTH;
5232c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                    break;
5242c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                case ApplicationParameter.TRIPLET_TAGID.FORMAT_TAGID:
5252c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                    i += 2;// length field in triplet
5262b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh                    if (appParam[i] != 0) {
5272c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                        appParamValue.vcard21 = false;
5282c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                    }
5292c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                    i += ApplicationParameter.TRIPLET_LENGTH.FORMAT_LENGTH;
5302c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                    break;
5312c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                default:
532d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                    parseOk = false;
5334446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                    Log.e(TAG, "Parse Application Parameter error");
5342c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                    break;
5352c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            }
5362c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
537d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue
5384446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        if (D) appParamValue.dump();
5394446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
540d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        return parseOk;
5412c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    }
5422c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
5432c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    /** Form and Send an XML format String to client for Phone book listing */
5440b1b0069658326e8c12dc0f887e4319c5227feb5Lixin Yue    private final int sendVcardListingXml(final int type, Operation op,
5452c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            final int maxListCount, final int listStartOffset, final String searchValue,
5462c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            String searchAttr) {
5472c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        StringBuilder result = new StringBuilder();
5482c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        int itemsFound = 0;
5492c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        result.append("<?xml version=\"1.0\"?>");
5502c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        result.append("<!DOCTYPE vcard-listing SYSTEM \"vcard-listing.dtd\">");
5512c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        result.append("<vCard-listing version=\"1.0\">");
5522c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
5532c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        // Phonebook listing request
554d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        if (type == ContentType.PHONEBOOK) {
5554ce32fccf381a3b448f0d5ff56665201c0e0e6d3Ola Johnsson            if (searchAttr.equals("0")) { // search by name
5564ce32fccf381a3b448f0d5ff56665201c0e0e6d3Ola Johnsson                itemsFound = createList(maxListCount, listStartOffset, searchValue, result,
5570dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao                        "name");
5584ce32fccf381a3b448f0d5ff56665201c0e0e6d3Ola Johnsson            } else if (searchAttr.equals("1")) { // search by number
5594ce32fccf381a3b448f0d5ff56665201c0e0e6d3Ola Johnsson                itemsFound = createList(maxListCount, listStartOffset, searchValue, result,
5600dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao                        "number");
5612c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            }// end of search by number
5622c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            else {
563d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                return ResponseCodes.OBEX_HTTP_PRECON_FAILED;
5642c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            }
5652c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
5662c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        // Call history listing request
5672c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        else {
5682f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            ArrayList<String> nameList = mVcardManager.loadCallHistoryList(type);
569d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue            int requestSize = nameList.size() >= maxListCount ? maxListCount : nameList.size();
570d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue            int startPoint = listStartOffset;
571d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue            int endPoint = startPoint + requestSize;
572d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue            if (endPoint > nameList.size()) {
573d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                endPoint = nameList.size();
574d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue            }
5754446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            if (D) Log.d(TAG, "call log list, size=" + requestSize + " offset=" + listStartOffset);
5764446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
577d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue            for (int j = startPoint; j < endPoint; j++) {
578d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                // listing object begin with 1.vcf
579d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                result.append("<card handle=\"" + (j + 1) + ".vcf\" name=\"" + nameList.get(j)
5804446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                        + "\"" + "/>");
5812c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                itemsFound++;
5822c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            }
5832c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
5842c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        result.append("</vCard-listing>");
5852c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
5864446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        if (V) Log.v(TAG, "itemsFound =" + itemsFound);
587d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue
588d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        return pushBytes(op, result.toString());
5892c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    }
5902c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
5914ce32fccf381a3b448f0d5ff56665201c0e0e6d3Ola Johnsson    private int createList(final int maxListCount, final int listStartOffset,
5920dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao            final String searchValue, StringBuilder result, String type) {
5934ce32fccf381a3b448f0d5ff56665201c0e0e6d3Ola Johnsson        int itemsFound = 0;
5940dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao        ArrayList<String> nameList = mVcardManager.getPhonebookNameList(mOrderBy);
5950dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao        final int requestSize = nameList.size() >= maxListCount ? maxListCount : nameList.size();
5960dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao        final int listSize = nameList.size();
5970dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao        String compareValue = "", currentValue;
5984ce32fccf381a3b448f0d5ff56665201c0e0e6d3Ola Johnsson
5990dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao        if (D) Log.d(TAG, "search by " + type + ", requestSize=" + requestSize + " offset="
6004ce32fccf381a3b448f0d5ff56665201c0e0e6d3Ola Johnsson                    + listStartOffset + " searchValue=" + searchValue);
6014ce32fccf381a3b448f0d5ff56665201c0e0e6d3Ola Johnsson
6020dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao        if (type.equals("number")) {
6030dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao            // query the number, to get the names
6040dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao            ArrayList<String> names = mVcardManager.getContactNamesByNumber(searchValue);
6050dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao            for (int i = 0; i < names.size(); i++) {
6060dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao                compareValue = names.get(i).trim();
6070dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao                if (D) Log.d(TAG, "compareValue=" + compareValue);
6080dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao                for (int pos = listStartOffset; pos < listSize &&
6090dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao                        itemsFound < requestSize; pos++) {
6100dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao                    currentValue = nameList.get(pos);
6110dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao                    if (D) Log.d(TAG, "currentValue=" + currentValue);
6120dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao                    if (currentValue.startsWith(compareValue)) {
6130dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao                        itemsFound++;
6140dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao                        result.append("<card handle=\"" + pos + ".vcf\" name=\""
6150dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao                                + currentValue + "\"" + "/>");
6160dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao                    }
6170dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao                }
6180dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao                if (itemsFound >= requestSize) {
6190dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao                    break;
6200dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao                }
6210dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao            }
6220dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao        } else {
6230dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao            if (searchValue != null) {
6240dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao                compareValue = searchValue.trim();
6250dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao            }
6260dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao            for (int pos = listStartOffset; pos < listSize &&
6270dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao                    itemsFound < requestSize; pos++) {
6280dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao                currentValue = nameList.get(pos);
6290dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao                if (D) Log.d(TAG, "currentValue=" + currentValue);
6300dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao                if (searchValue == null || currentValue.startsWith(compareValue)) {
6310dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao                    itemsFound++;
6320dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao                    result.append("<card handle=\"" + pos + ".vcf\" name=\""
6330dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao                            + currentValue + "\"" + "/>");
6340dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao                }
6354ce32fccf381a3b448f0d5ff56665201c0e0e6d3Ola Johnsson            }
6364ce32fccf381a3b448f0d5ff56665201c0e0e6d3Ola Johnsson        }
6374ce32fccf381a3b448f0d5ff56665201c0e0e6d3Ola Johnsson        return itemsFound;
6384ce32fccf381a3b448f0d5ff56665201c0e0e6d3Ola Johnsson    }
6394ce32fccf381a3b448f0d5ff56665201c0e0e6d3Ola Johnsson
6402c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    /**
6412c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan     * Function to send obex header back to client such as get phonebook size
6422c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan     * request
6432c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan     */
6442c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    private final int pushHeader(final Operation op, final HeaderSet reply) {
6452c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        OutputStream outputStream = null;
646d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue
6474446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        if (D) Log.d(TAG, "Push Header");
6484446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        if (D) Log.d(TAG, reply.toString());
649d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue
6504446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        int pushResult = ResponseCodes.OBEX_HTTP_OK;
6512c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        try {
6522c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            op.sendHeaders(reply);
6532c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            outputStream = op.openOutputStream();
6542c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            outputStream.flush();
6552c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        } catch (IOException e) {
6562c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            Log.e(TAG, e.toString());
6574446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            pushResult = ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
6582c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        } finally {
6592c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            if (!closeStream(outputStream, op)) {
6604446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                pushResult = ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
6612c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            }
6622c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
6634446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        return pushResult;
6642c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    }
6652c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
6662c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    /** Function to send vcard data to client */
6670b1b0069658326e8c12dc0f887e4319c5227feb5Lixin Yue    private final int pushBytes(Operation op, final String vcardString) {
6682f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        if (vcardString == null) {
6692f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            Log.w(TAG, "vcardString is null!");
6702c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            return ResponseCodes.OBEX_HTTP_OK;
6712c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
6724446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
6732f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        int vcardStringLen = vcardString.length();
6742f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        if (D) Log.d(TAG, "Send Data: len=" + vcardStringLen);
6752f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue
6762f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        OutputStream outputStream = null;
6772f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        int pushResult = ResponseCodes.OBEX_HTTP_OK;
6782c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        try {
6792c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            outputStream = op.openOutputStream();
6802c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        } catch (IOException e) {
6812c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            Log.e(TAG, "open outputstrem failed" + e.toString());
6822f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
6832f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        }
6842f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue
6852f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        int position = 0;
6862f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        long timestamp = 0;
6872f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        int outputBufferSize = op.getMaxPacketSize();
6882f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        if (V) Log.v(TAG, "outputBufferSize = " + outputBufferSize);
6892f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        while (position != vcardStringLen) {
6900b1b0069658326e8c12dc0f887e4319c5227feb5Lixin Yue            if (sIsAborted) {
6910b1b0069658326e8c12dc0f887e4319c5227feb5Lixin Yue                ((ServerOperation)op).isAborted = true;
6920b1b0069658326e8c12dc0f887e4319c5227feb5Lixin Yue                sIsAborted = false;
6930b1b0069658326e8c12dc0f887e4319c5227feb5Lixin Yue                break;
6940b1b0069658326e8c12dc0f887e4319c5227feb5Lixin Yue            }
6952f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            if (V) timestamp = System.currentTimeMillis();
6962f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            int readLength = outputBufferSize;
6972f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            if (vcardStringLen - position < outputBufferSize) {
6982f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                readLength = vcardStringLen - position;
6992f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            }
7002f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            String subStr = vcardString.substring(position, position + readLength);
7012f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            try {
7022f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                outputStream.write(subStr.getBytes(), 0, readLength);
7032f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            } catch (IOException e) {
7042f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                Log.e(TAG, "write outputstrem failed" + e.toString());
7054446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                pushResult = ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
7062f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                break;
7072f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            }
7082f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            if (V) {
7092f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                Log.v(TAG, "Sending vcard String position = " + position + " readLength "
7102f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                        + readLength + " bytes took " + (System.currentTimeMillis() - timestamp)
7112f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                        + " ms");
7122c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            }
7132f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            position += readLength;
7142c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
7152f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue
7162f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        if (V) Log.v(TAG, "Send Data complete!");
7172f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue
7182f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        if (!closeStream(outputStream, op)) {
7192f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            pushResult = ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
7202f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        }
7212f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue
7224446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        return pushResult;
7232c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    }
7242c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
7254446eaa935994bc91d6d308303e8d27526b4590dLixin Yue    private final int handleAppParaForResponse(AppParamValue appParamValue, int size,
7260b1b0069658326e8c12dc0f887e4319c5227feb5Lixin Yue            HeaderSet reply, Operation op) {
727d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        byte[] misnum = new byte[1];
7282c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        ApplicationParameter ap = new ApplicationParameter();
729d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue
730d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        // In such case, PCE only want the number of index.
731d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        // So response not contain any Body header.
732d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        if (mNeedPhonebookSize) {
7332f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            if (V) Log.v(TAG, "Need Phonebook size in response header.");
734d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue            mNeedPhonebookSize = false;
735d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue
7362c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            byte[] pbsize = new byte[2];
737d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue
7382c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            pbsize[0] = (byte)((size / 256) & 0xff);// HIGH VALUE
7392c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            pbsize[1] = (byte)((size % 256) & 0xff);// LOW VALUE
7402c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            ap.addAPPHeader(ApplicationParameter.TRIPLET_TAGID.PHONEBOOKSIZE_TAGID,
7412c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                    ApplicationParameter.TRIPLET_LENGTH.PHONEBOOKSIZE_LENGTH, pbsize);
742d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue
743d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue            if (mNeedNewMissedCallsNum) {
7449522370104410f24602ac98172bfbda27f89780dYoshiharu Kurita                mNeedNewMissedCallsNum = false;
745d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                int nmnum = size - mMissedCallSize;
746d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                mMissedCallSize = size;
747d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue
748d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                nmnum = nmnum > 0 ? nmnum : 0;
749d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                misnum[0] = (byte)nmnum;
750d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                ap.addAPPHeader(ApplicationParameter.TRIPLET_TAGID.NEWMISSEDCALLS_TAGID,
751d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                        ApplicationParameter.TRIPLET_LENGTH.NEWMISSEDCALLS_LENGTH, misnum);
7524446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                if (D) Log.d(TAG, "handleAppParaForResponse(): mNeedNewMissedCallsNum=true,  num= "
7534446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                            + nmnum);
754d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue            }
7552c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            reply.setHeader(HeaderSet.APPLICATION_PARAMETER, ap.getAPPparam());
756d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue
7574446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            if (D) Log.d(TAG, "Send back Phonebook size only, without body info! Size= " + size);
758d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue
7592c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            return pushHeader(op, reply);
7602c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
7612c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
762d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        // Only apply to "mch" download/listing.
763d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        // NewMissedCalls is used only in the response, together with Body
764d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        // header.
765d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        if (mNeedNewMissedCallsNum) {
7662f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            if (V) Log.v(TAG, "Need new missed call num in response header.");
767d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue            mNeedNewMissedCallsNum = false;
7684446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
769d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue            int nmnum = size - mMissedCallSize;
770d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue            mMissedCallSize = size;
771d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue
7722c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            nmnum = nmnum > 0 ? nmnum : 0;
7732c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            misnum[0] = (byte)nmnum;
7742c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            ap.addAPPHeader(ApplicationParameter.TRIPLET_TAGID.NEWMISSEDCALLS_TAGID,
7752c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                    ApplicationParameter.TRIPLET_LENGTH.NEWMISSEDCALLS_LENGTH, misnum);
7762c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            reply.setHeader(HeaderSet.APPLICATION_PARAMETER, ap.getAPPparam());
7774446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            if (D) Log.d(TAG, "handleAppParaForResponse(): mNeedNewMissedCallsNum=true,  num= "
7784446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                        + nmnum);
7792c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
780d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue            // Only Specifies the headers, not write for now, will write to PCE
781d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue            // together with Body
782d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue            try {
783d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                op.sendHeaders(reply);
784d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue            } catch (IOException e) {
785d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                Log.e(TAG, e.toString());
786d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
7872c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            }
7882c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
789d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        return NEED_SEND_BODY;
790d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue    }
7912c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
792d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue    private final int pullVcardListing(byte[] appParam, AppParamValue appParamValue,
7930b1b0069658326e8c12dc0f887e4319c5227feb5Lixin Yue            HeaderSet reply, Operation op) {
794d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        String searchAttr = appParamValue.searchAttr.trim();
7952c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
796d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        if (searchAttr == null || searchAttr.length() == 0) {
797d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue            // If searchAttr is not set by PCE, set default value per spec.
798d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue            appParamValue.searchAttr = "0";
7994446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            if (D) Log.d(TAG, "searchAttr is not set by PCE, assume search by name by default");
8002b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh        } else if (!searchAttr.equals("0") && !searchAttr.equals("1")) {
801d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue            Log.w(TAG, "search attr not supported");
8022b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh            if (searchAttr.equals("2")) {
803d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                // search by sound is not supported currently
804d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                Log.w(TAG, "do not support search by sound");
805d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                return ResponseCodes.OBEX_HTTP_NOT_IMPLEMENTED;
806d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue            }
807d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue            return ResponseCodes.OBEX_HTTP_PRECON_FAILED;
808d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        } else {
8094446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            Log.i(TAG, "searchAttr is valid: " + searchAttr);
8102c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
8112c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
8122f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        int size = mVcardManager.getPhonebookSize(appParamValue.needTag);
8134446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        int needSendBody = handleAppParaForResponse(appParamValue, size, reply, op);
8144446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        if (needSendBody != NEED_SEND_BODY) {
8154446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            return needSendBody;
8162c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
817d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue
8182f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        if (size == 0) {
8192f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            if (V) Log.v(TAG, "PhonebookSize is 0, return.");
8202f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            return ResponseCodes.OBEX_HTTP_OK;
8212f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        }
8222f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue
8232b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh        String orderPara = appParamValue.order.trim();
8242b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh        if (TextUtils.isEmpty(orderPara)) {
8252b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh            // If order parameter is not set by PCE, set default value per spec.
8260dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao            orderPara = "0";
8272b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh            if (D) Log.d(TAG, "Order parameter is not set by PCE. " +
8282b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh                       "Assume order by 'Indexed' by default");
8292b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh        } else if (!orderPara.equals("0") && !orderPara.equals("1")) {
8302b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh            if (V) Log.v(TAG, "Order parameter is not supported: " + appParamValue.order);
8312b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh            if (orderPara.equals("2")) {
8322b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh                // Order by sound is not supported currently
8332b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh                Log.w(TAG, "Do not support order by sound");
8342b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh                return ResponseCodes.OBEX_HTTP_NOT_IMPLEMENTED;
8352b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh            }
8362b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh            return ResponseCodes.OBEX_HTTP_PRECON_FAILED;
8372b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh        } else {
8382b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh            Log.i(TAG, "Order parameter is valid: " + orderPara);
8392b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh        }
8402b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh
8412b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh        if (orderPara.equals("0")) {
8422b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh            mOrderBy = ORDER_BY_INDEXED;
8432b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh        } else if (orderPara.equals("1")) {
8442b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh            mOrderBy = ORDER_BY_ALPHABETICAL;
8452b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh        }
8462b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh
8474446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        int sendResult = sendVcardListingXml(appParamValue.needTag, op, appParamValue.maxListCount,
8484446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                appParamValue.listStartOffset, appParamValue.searchValue,
8494446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                appParamValue.searchAttr);
8504446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        return sendResult;
8512c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    }
8522c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
8532c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    private final int pullVcardEntry(byte[] appParam, AppParamValue appParamValue,
8540b1b0069658326e8c12dc0f887e4319c5227feb5Lixin Yue            Operation op, final String name, final String current_path) {
855d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        if (name == null || name.length() < VCARD_NAME_SUFFIX_LENGTH) {
8564446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            if (D) Log.d(TAG, "Name is Null, or the length of name < 5 !");
857a4508589f298c67fda54c344760ae39f0f375c11Lixin Yue            return ResponseCodes.OBEX_HTTP_NOT_ACCEPTABLE;
8582c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
859d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        String strIndex = name.substring(0, name.length() - VCARD_NAME_SUFFIX_LENGTH + 1);
8602f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        int intIndex = 0;
8612c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        if (strIndex.trim().length() != 0) {
8622c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            try {
8632c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                intIndex = Integer.parseInt(strIndex);
8642c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            } catch (NumberFormatException e) {
8652c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                Log.e(TAG, "catch number format exception " + e.toString());
866a4508589f298c67fda54c344760ae39f0f375c11Lixin Yue                return ResponseCodes.OBEX_HTTP_NOT_ACCEPTABLE;
8672c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            }
8682c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
869d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue
8702f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        int size = mVcardManager.getPhonebookSize(appParamValue.needTag);
8712f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        if (size == 0) {
8722f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            if (V) Log.v(TAG, "PhonebookSize is 0, return.");
8736f02f510e5dc3fb994516128f2de1d78bc7f9b1eStaffan Lindvall            return ResponseCodes.OBEX_HTTP_NOT_FOUND;
8744446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        }
8754446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
8762f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        boolean vcard21 = appParamValue.vcard21;
877d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        if (appParamValue.needTag == 0) {
878d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue            Log.w(TAG, "wrong path!");
879a4508589f298c67fda54c344760ae39f0f375c11Lixin Yue            return ResponseCodes.OBEX_HTTP_NOT_ACCEPTABLE;
880d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        } else if (appParamValue.needTag == ContentType.PHONEBOOK) {
8814446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            if (intIndex < 0 || intIndex >= size) {
8824446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                Log.w(TAG, "The requested vcard is not acceptable! name= " + name);
8836f02f510e5dc3fb994516128f2de1d78bc7f9b1eStaffan Lindvall                return ResponseCodes.OBEX_HTTP_NOT_FOUND;
8842f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            } else if (intIndex == 0) {
885d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                // For PB_PATH, 0.vcf is the phone number of this phone.
8862f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                String ownerVcard = mVcardManager.getOwnerPhoneNumberVcard(vcard21);
8872f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                return pushBytes(op, ownerVcard);
8882f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            } else {
8892b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh                return mVcardManager.composeAndSendPhonebookOneVcard(op, intIndex, vcard21, null,
8902b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh                        mOrderBy );
891d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue            }
892d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        } else {
8934446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            if (intIndex <= 0 || intIndex > size) {
894d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                Log.w(TAG, "The requested vcard is not acceptable! name= " + name);
8956f02f510e5dc3fb994516128f2de1d78bc7f9b1eStaffan Lindvall                return ResponseCodes.OBEX_HTTP_NOT_FOUND;
896d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue            }
897d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue            // For others (ich/och/cch/mch), 0.vcf is meaningless, and must
898d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue            // begin from 1.vcf
899d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue            if (intIndex >= 1) {
9002f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                return mVcardManager.composeAndSendCallLogVcards(appParamValue.needTag, op,
90118bde766b20c899310ebdd5ca823e30ff27d407fLixin Yue                        intIndex, intIndex, vcard21);
902d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue            }
9032c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
9042f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        return ResponseCodes.OBEX_HTTP_OK;
9052c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    }
9062c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
9072c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    private final int pullPhonebook(byte[] appParam, AppParamValue appParamValue, HeaderSet reply,
9080b1b0069658326e8c12dc0f887e4319c5227feb5Lixin Yue            Operation op, final String name) {
9092c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        // code start for passing PTS3.2 TC_PSE_PBD_BI_01_C
9102c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        if (name != null) {
9112c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            int dotIndex = name.indexOf(".");
9122c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            String vcf = "vcf";
9132c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            if (dotIndex >= 0 && dotIndex <= name.length()) {
9142c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                if (name.regionMatches(dotIndex + 1, vcf, 0, vcf.length()) == false) {
9152c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                    Log.w(TAG, "name is not .vcf");
9162c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                    return ResponseCodes.OBEX_HTTP_NOT_ACCEPTABLE;
9172c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                }
9182c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            }
919d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        } // code end for passing PTS3.2 TC_PSE_PBD_BI_01_C
9202c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
9212f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        int pbSize = mVcardManager.getPhonebookSize(appParamValue.needTag);
9224446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        int needSendBody = handleAppParaForResponse(appParamValue, pbSize, reply, op);
9234446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        if (needSendBody != NEED_SEND_BODY) {
9244446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            return needSendBody;
9252c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
9262c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
9272f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        if (pbSize == 0) {
9282f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            if (V) Log.v(TAG, "PhonebookSize is 0, return.");
9292f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            return ResponseCodes.OBEX_HTTP_OK;
9302f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        }
9312f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue
932d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        int requestSize = pbSize >= appParamValue.maxListCount ? appParamValue.maxListCount
933d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue                : pbSize;
934d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue        int startPoint = appParamValue.listStartOffset;
93518bde766b20c899310ebdd5ca823e30ff27d407fLixin Yue        if (startPoint < 0 || startPoint >= pbSize) {
93618bde766b20c899310ebdd5ca823e30ff27d407fLixin Yue            Log.w(TAG, "listStartOffset is not correct! " + startPoint);
93718bde766b20c899310ebdd5ca823e30ff27d407fLixin Yue            return ResponseCodes.OBEX_HTTP_OK;
93818bde766b20c899310ebdd5ca823e30ff27d407fLixin Yue        }
93918bde766b20c899310ebdd5ca823e30ff27d407fLixin Yue
94077b122f551ae37811c75ae76fa2029f7b3f2f404a        // Limit the number of call log to CALLLOG_NUM_LIMIT
94177b122f551ae37811c75ae76fa2029f7b3f2f404a        if (appParamValue.needTag != BluetoothPbapObexServer.ContentType.PHONEBOOK) {
94277b122f551ae37811c75ae76fa2029f7b3f2f404a            if (requestSize > CALLLOG_NUM_LIMIT) {
94377b122f551ae37811c75ae76fa2029f7b3f2f404a               requestSize = CALLLOG_NUM_LIMIT;
94477b122f551ae37811c75ae76fa2029f7b3f2f404a            }
94577b122f551ae37811c75ae76fa2029f7b3f2f404a        }
94677b122f551ae37811c75ae76fa2029f7b3f2f404a
94718bde766b20c899310ebdd5ca823e30ff27d407fLixin Yue        int endPoint = startPoint + requestSize - 1;
94818bde766b20c899310ebdd5ca823e30ff27d407fLixin Yue        if (endPoint > pbSize - 1) {
94918bde766b20c899310ebdd5ca823e30ff27d407fLixin Yue            endPoint = pbSize - 1;
9502c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
9514446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        if (D) Log.d(TAG, "pullPhonebook(): requestSize=" + requestSize + " startPoint=" +
9524446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                startPoint + " endPoint=" + endPoint);
9534446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
9542f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        boolean vcard21 = appParamValue.vcard21;
9552f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        if (appParamValue.needTag == BluetoothPbapObexServer.ContentType.PHONEBOOK) {
95618bde766b20c899310ebdd5ca823e30ff27d407fLixin Yue            if (startPoint == 0) {
9572f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                String ownerVcard = mVcardManager.getOwnerPhoneNumberVcard(vcard21);
95818bde766b20c899310ebdd5ca823e30ff27d407fLixin Yue                if (endPoint == 0) {
95918bde766b20c899310ebdd5ca823e30ff27d407fLixin Yue                    return pushBytes(op, ownerVcard);
96018bde766b20c899310ebdd5ca823e30ff27d407fLixin Yue                } else {
96118bde766b20c899310ebdd5ca823e30ff27d407fLixin Yue                    return mVcardManager.composeAndSendPhonebookVcards(op, 1, endPoint, vcard21,
96218bde766b20c899310ebdd5ca823e30ff27d407fLixin Yue                            ownerVcard);
96318bde766b20c899310ebdd5ca823e30ff27d407fLixin Yue                }
9642f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            } else {
96518bde766b20c899310ebdd5ca823e30ff27d407fLixin Yue                return mVcardManager.composeAndSendPhonebookVcards(op, startPoint, endPoint,
96618bde766b20c899310ebdd5ca823e30ff27d407fLixin Yue                        vcard21, null);
9672f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            }
9682f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        } else {
96918bde766b20c899310ebdd5ca823e30ff27d407fLixin Yue            return mVcardManager.composeAndSendCallLogVcards(appParamValue.needTag, op,
97018bde766b20c899310ebdd5ca823e30ff27d407fLixin Yue                    startPoint + 1, endPoint + 1, vcard21);
9712c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
9722c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    }
9732c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
9742f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue    public static boolean closeStream(final OutputStream out, final Operation op) {
9752c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        boolean returnvalue = true;
9762c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        try {
9772c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            if (out != null) {
9782c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                out.close();
9792c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            }
9802c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        } catch (IOException e) {
9812c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            Log.e(TAG, "outputStream close failed" + e.toString());
9822c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            returnvalue = false;
9832c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
9842c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        try {
9852c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            if (op != null) {
9862c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                op.close();
9872c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            }
9882c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        } catch (IOException e) {
9894446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            Log.e(TAG, "operation close failed" + e.toString());
9902c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            returnvalue = false;
9912c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
9922c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        return returnvalue;
9932c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    }
9942c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
995d896162ef022a5607b13bae5177637ff3f18b737Lixin Yue    // Reserved for future use. In case PSE challenge PCE and PCE input wrong
9962c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    // session key.
9972c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    public final void onAuthenticationFailure(final byte[] userName) {
9982c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    }
999c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue
10002f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue    public static final String createSelectionPara(final int type) {
10012f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        String selection = null;
10022f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        switch (type) {
10032f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            case ContentType.INCOMING_CALL_HISTORY:
10042f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                selection = Calls.TYPE + "=" + CallLog.Calls.INCOMING_TYPE;
10052f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                break;
10062f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            case ContentType.OUTGOING_CALL_HISTORY:
10072f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                selection = Calls.TYPE + "=" + CallLog.Calls.OUTGOING_TYPE;
10082f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                break;
10092f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            case ContentType.MISSED_CALL_HISTORY:
10102f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                selection = Calls.TYPE + "=" + CallLog.Calls.MISSED_TYPE;
10112f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                break;
10122f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            default:
10132f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                break;
10142f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        }
10152f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        if (V) Log.v(TAG, "Call log selection: " + selection);
10162f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        return selection;
10172f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue    }
10182f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue
10192f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue    public static final void logHeader(HeaderSet hs) {
1020c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue        Log.v(TAG, "Dumping HeaderSet " + hs.toString());
1021c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue        try {
1022c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue
1023c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue            Log.v(TAG, "COUNT : " + hs.getHeader(HeaderSet.COUNT));
1024c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue            Log.v(TAG, "NAME : " + hs.getHeader(HeaderSet.NAME));
1025c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue            Log.v(TAG, "TYPE : " + hs.getHeader(HeaderSet.TYPE));
1026c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue            Log.v(TAG, "LENGTH : " + hs.getHeader(HeaderSet.LENGTH));
1027c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue            Log.v(TAG, "TIME_ISO_8601 : " + hs.getHeader(HeaderSet.TIME_ISO_8601));
1028c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue            Log.v(TAG, "TIME_4_BYTE : " + hs.getHeader(HeaderSet.TIME_4_BYTE));
1029c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue            Log.v(TAG, "DESCRIPTION : " + hs.getHeader(HeaderSet.DESCRIPTION));
1030c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue            Log.v(TAG, "TARGET : " + hs.getHeader(HeaderSet.TARGET));
1031c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue            Log.v(TAG, "HTTP : " + hs.getHeader(HeaderSet.HTTP));
1032c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue            Log.v(TAG, "WHO : " + hs.getHeader(HeaderSet.WHO));
1033c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue            Log.v(TAG, "OBJECT_CLASS : " + hs.getHeader(HeaderSet.OBJECT_CLASS));
1034c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue            Log.v(TAG, "APPLICATION_PARAMETER : " + hs.getHeader(HeaderSet.APPLICATION_PARAMETER));
1035c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue        } catch (IOException e) {
1036c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue            Log.e(TAG, "dump HeaderSet error " + e);
1037c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue        }
1038c5495c585c0d19cdd20963e5a2144e5f984a306eLixin Yue    }
10392c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan}
1040