1/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.bluetooth.client.pbap;
18
19import android.bluetooth.BluetoothDevice;
20import android.os.Handler;
21import android.os.Message;
22import android.util.Log;
23
24import java.lang.ref.WeakReference;
25
26/**
27 * Public API to control Phone Book Profile (PCE role only).
28 * <p>
29 * This class defines methods that shall be used by application for the
30 * retrieval of phone book objects from remote device.
31 * <p>
32 * How to connect to remote device which is acting in PSE role:
33 * <ul>
34 * <li>Create a <code>BluetoothDevice</code> object which corresponds to remote
35 * device in PSE role;
36 * <li>Create an instance of <code>BluetoothPbapClient</code> class, passing
37 * <code>BluetothDevice</code> object along with a <code>Handler</code> to it;
38 * <li>Use {@link #setPhoneBookFolderRoot}, {@link #setPhoneBookFolderUp} and
39 * {@link #setPhoneBookFolderDown} to navigate in virtual phone book folder
40 * structure
41 * <li>Use {@link #pullPhoneBookSize} or {@link #pullVcardListingSize} to
42 * retrieve the size of selected phone book
43 * <li>Use {@link #pullPhoneBook} to retrieve phone book entries
44 * <li>Use {@link #pullVcardListing} to retrieve list of entries in the phone
45 * book
46 * <li>Use {@link #pullVcardEntry} to pull single entry from the phone book
47 * </ul>
48 * Upon completion of each call above PCE will notify application if operation
49 * completed successfully (along with results) or failed.
50 * <p>
51 * Therefore, application should handle following events in its message queue
52 * handler:
53 * <ul>
54 * <li><code>EVENT_PULL_PHONE_BOOK_SIZE_DONE</code>
55 * <li><code>EVENT_PULL_VCARD_LISTING_SIZE_DONE</code>
56 * <li><code>EVENT_PULL_PHONE_BOOK_DONE</code>
57 * <li><code>EVENT_PULL_VCARD_LISTING_DONE</code>
58 * <li><code>EVENT_PULL_VCARD_ENTRY_DONE</code>
59 * <li><code>EVENT_SET_PHONE_BOOK_DONE</code>
60 * </ul>
61 * and
62 * <ul>
63 * <li><code>EVENT_PULL_PHONE_BOOK_SIZE_ERROR</code>
64 * <li><code>EVENT_PULL_VCARD_LISTING_SIZE_ERROR</code>
65 * <li><code>EVENT_PULL_PHONE_BOOK_ERROR</code>
66 * <li><code>EVENT_PULL_VCARD_LISTING_ERROR</code>
67 * <li><code>EVENT_PULL_VCARD_ENTRY_ERROR</code>
68 * <li><code>EVENT_SET_PHONE_BOOK_ERROR</code>
69 * </ul>
70 * <code>connect</code> and <code>disconnect</code> methods are introduced for
71 * testing purposes. An application does not need to use them as the session
72 * connection and disconnection happens automatically internally.
73 */
74public class BluetoothPbapClient {
75    private static final String TAG = "BluetoothPbapClient";
76
77    /**
78     * Path to local incoming calls history object
79     */
80    public static final String ICH_PATH = "telecom/ich.vcf";
81
82    /**
83     * Path to local outgoing calls history object
84     */
85    public static final String OCH_PATH = "telecom/och.vcf";
86
87    /**
88     * Path to local missed calls history object
89     */
90    public static final String MCH_PATH = "telecom/mch.vcf";
91
92    /**
93     * Path to local combined calls history object
94     */
95    public static final String CCH_PATH = "telecom/cch.vcf";
96
97    /**
98     * Path to local main phone book object
99     */
100    public static final String PB_PATH = "telecom/pb.vcf";
101
102    /**
103     * Path to incoming calls history object stored on the phone's SIM card
104     */
105    public static final String SIM_ICH_PATH = "SIM1/telecom/ich.vcf";
106
107    /**
108     * Path to outgoing calls history object stored on the phone's SIM card
109     */
110    public static final String SIM_OCH_PATH = "SIM1/telecom/och.vcf";
111
112    /**
113     * Path to missed calls history object stored on the phone's SIM card
114     */
115    public static final String SIM_MCH_PATH = "SIM1/telecom/mch.vcf";
116
117    /**
118     * Path to combined calls history object stored on the phone's SIM card
119     */
120    public static final String SIM_CCH_PATH = "SIM1/telecom/cch.vcf";
121
122    /**
123     * Path to main phone book object stored on the phone's SIM card
124     */
125    public static final String SIM_PB_PATH = "SIM1/telecom/pb.vcf";
126
127    /**
128     * Indicates to server that default sorting order shall be used for vCard
129     * listing.
130     */
131    public static final byte ORDER_BY_DEFAULT = -1;
132
133    /**
134     * Indicates to server that indexed sorting order shall be used for vCard
135     * listing.
136     */
137    public static final byte ORDER_BY_INDEXED = 0;
138
139    /**
140     * Indicates to server that alphabetical sorting order shall be used for the
141     * vCard listing.
142     */
143    public static final byte ORDER_BY_ALPHABETICAL = 1;
144
145    /**
146     * Indicates to server that phonetical (based on sound attribute) sorting
147     * order shall be used for the vCard listing.
148     */
149    public static final byte ORDER_BY_PHONETIC = 2;
150
151    /**
152     * Indicates to server that Name attribute of vCard shall be used to carry
153     * out the search operation on
154     */
155    public static final byte SEARCH_ATTR_NAME = 0;
156
157    /**
158     * Indicates to server that Number attribute of vCard shall be used to carry
159     * out the search operation on
160     */
161    public static final byte SEARCH_ATTR_NUMBER = 1;
162
163    /**
164     * Indicates to server that Sound attribute of vCard shall be used to carry
165     * out the search operation
166     */
167    public static final byte SEARCH_ATTR_SOUND = 2;
168
169    /**
170     * VCard format version 2.1
171     */
172    public static final byte VCARD_TYPE_21 = 0;
173
174    /**
175     * VCard format version 3.0
176     */
177    public static final byte VCARD_TYPE_30 = 1;
178
179    /* 64-bit mask used to filter out VCard fields */
180    // TODO: Think of extracting to separate class
181    public static final long VCARD_ATTR_VERSION = 0x000000000000000001;
182    public static final long VCARD_ATTR_FN = 0x000000000000000002;
183    public static final long VCARD_ATTR_N = 0x000000000000000004;
184    public static final long VCARD_ATTR_PHOTO = 0x000000000000000008;
185    public static final long VCARD_ATTR_BDAY = 0x000000000000000010;
186    public static final long VCARD_ATTR_ADDR = 0x000000000000000020;
187    public static final long VCARD_ATTR_LABEL = 0x000000000000000040;
188    public static final long VCARD_ATTR_TEL = 0x000000000000000080;
189    public static final long VCARD_ATTR_EMAIL = 0x000000000000000100;
190    public static final long VCARD_ATTR_MAILER = 0x000000000000000200;
191    public static final long VCARD_ATTR_TZ = 0x000000000000000400;
192    public static final long VCARD_ATTR_GEO = 0x000000000000000800;
193    public static final long VCARD_ATTR_TITLE = 0x000000000000001000;
194    public static final long VCARD_ATTR_ROLE = 0x000000000000002000;
195    public static final long VCARD_ATTR_LOGO = 0x000000000000004000;
196    public static final long VCARD_ATTR_AGENT = 0x000000000000008000;
197    public static final long VCARD_ATTR_ORG = 0x000000000000010000;
198    public static final long VCARD_ATTR_NOTE = 0x000000000000020000;
199    public static final long VCARD_ATTR_REV = 0x000000000000040000;
200    public static final long VCARD_ATTR_SOUND = 0x000000000000080000;
201    public static final long VCARD_ATTR_URL = 0x000000000000100000;
202    public static final long VCARD_ATTR_UID = 0x000000000000200000;
203    public static final long VCARD_ATTR_KEY = 0x000000000000400000;
204    public static final long VCARD_ATTR_NICKNAME = 0x000000000000800000;
205    public static final long VCARD_ATTR_CATEGORIES = 0x000000000001000000;
206    public static final long VCARD_ATTR_PROID = 0x000000000002000000;
207    public static final long VCARD_ATTR_CLASS = 0x000000000004000000;
208    public static final long VCARD_ATTR_SORT_STRING = 0x000000000008000000;
209    public static final long VCARD_ATTR_X_IRMC_CALL_DATETIME =
210            0x000000000010000000;
211
212    /**
213     * Maximal number of entries of the phone book that PCE can handle
214     */
215    public static final short MAX_LIST_COUNT = (short) 0xFFFF;
216
217    /**
218     * Event propagated upon completion of <code>setPhoneBookFolderRoot</code>,
219     * <code>setPhoneBookFolderUp</code> or <code>setPhoneBookFolderDown</code>
220     * request.
221     * <p>
222     * This event indicates that request completed successfully.
223     * @see #setPhoneBookFolderRoot
224     * @see #setPhoneBookFolderUp
225     * @see #setPhoneBookFolderDown
226     */
227    public static final int EVENT_SET_PHONE_BOOK_DONE = 1;
228
229    /**
230     * Event propagated upon completion of <code>pullPhoneBook</code> request.
231     * <p>
232     * This event carry on results of the request.
233     * <p>
234     * The resulting message contains:
235     * <table>
236     * <tr>
237     * <td><code>msg.arg1</code></td>
238     * <td>newMissedCalls parameter (only in case of missed calls history object
239     * request)</td>
240     * </tr>
241     * <tr>
242     * <td><code>msg.obj</code></td>
243     * <td>which is a list of <code>VCardEntry</code> objects</td>
244     * </tr>
245     * </table>
246     * @see #pullPhoneBook
247     */
248    public static final int EVENT_PULL_PHONE_BOOK_DONE = 2;
249
250    /**
251     * Event propagated upon completion of <code>pullVcardListing</code>
252     * request.
253     * <p>
254     * This event carry on results of the request.
255     * <p>
256     * The resulting message contains:
257     * <table>
258     * <tr>
259     * <td><code>msg.arg1</code></td>
260     * <td>newMissedCalls parameter (only in case of missed calls history object
261     * request)</td>
262     * </tr>
263     * <tr>
264     * <td><code>msg.obj</code></td>
265     * <td>which is a list of <code>BluetoothPbapCard</code> objects</td>
266     * </tr>
267     * </table>
268     * @see #pullVcardListing
269     */
270    public static final int EVENT_PULL_VCARD_LISTING_DONE = 3;
271
272    /**
273     * Event propagated upon completion of <code>pullVcardEntry</code> request.
274     * <p>
275     * This event carry on results of the request.
276     * <p>
277     * The resulting message contains:
278     * <table>
279     * <tr>
280     * <td><code>msg.obj</code></td>
281     * <td>vCard as and object of type <code>VCardEntry</code></td>
282     * </tr>
283     * </table>
284     * @see #pullVcardEntry
285     */
286    public static final int EVENT_PULL_VCARD_ENTRY_DONE = 4;
287
288    /**
289     * Event propagated upon completion of <code>pullPhoneBookSize</code>
290     * request.
291     * <p>
292     * This event carry on results of the request.
293     * <p>
294     * The resulting message contains:
295     * <table>
296     * <tr>
297     * <td><code>msg.arg1</code></td>
298     * <td>size of the phone book</td>
299     * </tr>
300     * </table>
301     * @see #pullPhoneBookSize
302     */
303    public static final int EVENT_PULL_PHONE_BOOK_SIZE_DONE = 5;
304
305    /**
306     * Event propagated upon completion of <code>pullVcardListingSize</code>
307     * request.
308     * <p>
309     * This event carry on results of the request.
310     * <p>
311     * The resulting message contains:
312     * <table>
313     * <tr>
314     * <td><code>msg.arg1</code></td>
315     * <td>size of the phone book listing</td>
316     * </tr>
317     * </table>
318     * @see #pullVcardListingSize
319     */
320    public static final int EVENT_PULL_VCARD_LISTING_SIZE_DONE = 6;
321
322    /**
323     * Event propagated upon completion of <code>setPhoneBookFolderRoot</code>,
324     * <code>setPhoneBookFolderUp</code> or <code>setPhoneBookFolderDown</code>
325     * request. This event indicates an error during operation.
326     */
327    public static final int EVENT_SET_PHONE_BOOK_ERROR = 101;
328
329    /**
330     * Event propagated upon completion of <code>pullPhoneBook</code> request.
331     * This event indicates an error during operation.
332     */
333    public static final int EVENT_PULL_PHONE_BOOK_ERROR = 102;
334
335    /**
336     * Event propagated upon completion of <code>pullVcardListing</code>
337     * request. This event indicates an error during operation.
338     */
339    public static final int EVENT_PULL_VCARD_LISTING_ERROR = 103;
340
341    /**
342     * Event propagated upon completion of <code>pullVcardEntry</code> request.
343     * This event indicates an error during operation.
344     */
345    public static final int EVENT_PULL_VCARD_ENTRY_ERROR = 104;
346
347    /**
348     * Event propagated upon completion of <code>pullPhoneBookSize</code>
349     * request. This event indicates an error during operation.
350     */
351    public static final int EVENT_PULL_PHONE_BOOK_SIZE_ERROR = 105;
352
353    /**
354     * Event propagated upon completion of <code>pullVcardListingSize</code>
355     * request. This event indicates an error during operation.
356     */
357    public static final int EVENT_PULL_VCARD_LISTING_SIZE_ERROR = 106;
358
359    /**
360     * Event propagated when PCE has been connected to PSE
361     */
362    public static final int EVENT_SESSION_CONNECTED = 201;
363
364    /**
365     * Event propagated when PCE has been disconnected from PSE
366     */
367    public static final int EVENT_SESSION_DISCONNECTED = 202;
368    public static final int EVENT_SESSION_AUTH_REQUESTED = 203;
369    public static final int EVENT_SESSION_AUTH_TIMEOUT = 204;
370
371    public enum ConnectionState {
372        DISCONNECTED, CONNECTING, CONNECTED, DISCONNECTING;
373    }
374
375    private final Handler mClientHandler;
376    private final BluetoothPbapSession mSession;
377    private ConnectionState mConnectionState = ConnectionState.DISCONNECTED;
378
379    private SessionHandler mSessionHandler;
380
381    private static class SessionHandler extends Handler {
382
383        private final WeakReference<BluetoothPbapClient> mClient;
384
385        SessionHandler(BluetoothPbapClient client) {
386            mClient = new WeakReference<BluetoothPbapClient>(client);
387        }
388
389        @Override
390        public void handleMessage(Message msg) {
391            Log.d(TAG, "handleMessage: what=" + msg.what);
392
393            BluetoothPbapClient client = mClient.get();
394            if (client == null) {
395                return;
396            }
397
398            switch (msg.what) {
399                case BluetoothPbapSession.REQUEST_FAILED:
400                {
401                    BluetoothPbapRequest req = (BluetoothPbapRequest) msg.obj;
402
403                    if (req instanceof BluetoothPbapRequestPullPhoneBookSize) {
404                        client.sendToClient(EVENT_PULL_PHONE_BOOK_SIZE_ERROR);
405                    } else if (req instanceof BluetoothPbapRequestPullVcardListingSize) {
406                        client.sendToClient(EVENT_PULL_VCARD_LISTING_SIZE_ERROR);
407                    } else if (req instanceof BluetoothPbapRequestPullPhoneBook) {
408                        client.sendToClient(EVENT_PULL_PHONE_BOOK_ERROR);
409                    } else if (req instanceof BluetoothPbapRequestPullVcardListing) {
410                        client.sendToClient(EVENT_PULL_VCARD_LISTING_ERROR);
411                    } else if (req instanceof BluetoothPbapRequestPullVcardEntry) {
412                        client.sendToClient(EVENT_PULL_VCARD_ENTRY_ERROR);
413                    } else if (req instanceof BluetoothPbapRequestSetPath) {
414                        client.sendToClient(EVENT_SET_PHONE_BOOK_ERROR);
415                    }
416
417                    break;
418                }
419
420                case BluetoothPbapSession.REQUEST_COMPLETED:
421                {
422                    BluetoothPbapRequest req = (BluetoothPbapRequest) msg.obj;
423
424                    if (req instanceof BluetoothPbapRequestPullPhoneBookSize) {
425                        int size = ((BluetoothPbapRequestPullPhoneBookSize) req).getSize();
426                        client.sendToClient(EVENT_PULL_PHONE_BOOK_SIZE_DONE, size);
427
428                    } else if (req instanceof BluetoothPbapRequestPullVcardListingSize) {
429                        int size = ((BluetoothPbapRequestPullVcardListingSize) req).getSize();
430                        client.sendToClient(EVENT_PULL_VCARD_LISTING_SIZE_DONE, size);
431
432                    } else if (req instanceof BluetoothPbapRequestPullPhoneBook) {
433                        BluetoothPbapRequestPullPhoneBook r = (BluetoothPbapRequestPullPhoneBook) req;
434                        client.sendToClient(EVENT_PULL_PHONE_BOOK_DONE, r.getNewMissedCalls(),
435                                r.getList());
436
437                    } else if (req instanceof BluetoothPbapRequestPullVcardListing) {
438                        BluetoothPbapRequestPullVcardListing r = (BluetoothPbapRequestPullVcardListing) req;
439                        client.sendToClient(EVENT_PULL_VCARD_LISTING_DONE, r.getNewMissedCalls(),
440                                r.getList());
441
442                    } else if (req instanceof BluetoothPbapRequestPullVcardEntry) {
443                        BluetoothPbapRequestPullVcardEntry r = (BluetoothPbapRequestPullVcardEntry) req;
444                        client.sendToClient(EVENT_PULL_VCARD_ENTRY_DONE, r.getVcard());
445
446                    } else if (req instanceof BluetoothPbapRequestSetPath) {
447                        client.sendToClient(EVENT_SET_PHONE_BOOK_DONE);
448                    }
449
450                    break;
451                }
452
453                case BluetoothPbapSession.AUTH_REQUESTED:
454                    client.sendToClient(EVENT_SESSION_AUTH_REQUESTED);
455                    break;
456
457                case BluetoothPbapSession.AUTH_TIMEOUT:
458                    client.sendToClient(EVENT_SESSION_AUTH_TIMEOUT);
459                    break;
460
461                /*
462                 * app does not need to know when session is connected since
463                 * OBEX session is managed inside BluetoothPbapSession
464                 * automatically - we add this only so app can visualize PBAP
465                 * connection status in case it wants to
466                 */
467
468                case BluetoothPbapSession.SESSION_CONNECTING:
469                    client.mConnectionState = ConnectionState.CONNECTING;
470                    break;
471
472                case BluetoothPbapSession.SESSION_CONNECTED:
473                    client.mConnectionState = ConnectionState.CONNECTED;
474                    client.sendToClient(EVENT_SESSION_CONNECTED);
475                    break;
476
477                case BluetoothPbapSession.SESSION_DISCONNECTED:
478                    client.mConnectionState = ConnectionState.DISCONNECTED;
479                    client.sendToClient(EVENT_SESSION_DISCONNECTED);
480                    break;
481            }
482        }
483    };
484
485    private void sendToClient(int eventId) {
486        sendToClient(eventId, 0, null);
487    }
488
489    private void sendToClient(int eventId, int param) {
490        sendToClient(eventId, param, null);
491    }
492
493    private void sendToClient(int eventId, Object param) {
494        sendToClient(eventId, 0, param);
495    }
496
497    private void sendToClient(int eventId, int param1, Object param2) {
498        mClientHandler.obtainMessage(eventId, param1, 0, param2).sendToTarget();
499    }
500
501    /**
502     * Constructs PCE object
503     *
504     * @param device BluetoothDevice that corresponds to remote acting in PSE
505     *            role
506     * @param handler the handle that will be used by PCE to notify events and
507     *            results to application
508     * @throws NullPointerException
509     */
510    public BluetoothPbapClient(BluetoothDevice device, Handler handler) {
511        if (device == null) {
512            throw new NullPointerException("BluetothDevice is null");
513        }
514
515        mClientHandler = handler;
516
517        mSessionHandler = new SessionHandler(this);
518
519        mSession = new BluetoothPbapSession(device, mSessionHandler);
520    }
521
522    /**
523     * Starts a pbap session. <pb> This method set up rfcomm session, obex
524     * session and waits for requests to be transfered to PSE.
525     */
526    public void connect() {
527        mSession.start();
528    }
529
530    @Override
531    public void finalize() {
532        if (mSession != null) {
533            mSession.stop();
534        }
535    }
536
537    /**
538     * Stops all the active transactions and disconnects from the server.
539     */
540    public void disconnect() {
541        mSession.stop();
542    }
543
544    /**
545     * Aborts current request, if any
546     */
547    public void abort() {
548        mSession.abort();
549    }
550
551    public ConnectionState getState() {
552        return mConnectionState;
553    }
554
555    /**
556     * Sets current folder to root
557     *
558     * @return <code>true</code> if request has been sent successfully;
559     *         <code>false</code> otherwise; upon completion PCE sends
560     *         {@link #EVENT_SET_PHONE_BOOK_DONE} or
561     *         {@link #EVENT_SET_PHONE_BOOK_ERROR} in case of failure
562     */
563    public boolean setPhoneBookFolderRoot() {
564        BluetoothPbapRequest req = new BluetoothPbapRequestSetPath(false);
565        return mSession.makeRequest(req);
566    }
567
568    /**
569     * Sets current folder to parent
570     *
571     * @return <code>true</code> if request has been sent successfully;
572     *         <code>false</code> otherwise; upon completion PCE sends
573     *         {@link #EVENT_SET_PHONE_BOOK_DONE} or
574     *         {@link #EVENT_SET_PHONE_BOOK_ERROR} in case of failure
575     */
576    public boolean setPhoneBookFolderUp() {
577        BluetoothPbapRequest req = new BluetoothPbapRequestSetPath(true);
578        return mSession.makeRequest(req);
579    }
580
581    /**
582     * Sets current folder to selected sub-folder
583     *
584     * @param folder the name of the sub-folder
585     * @return @return <code>true</code> if request has been sent successfully;
586     *         <code>false</code> otherwise; upon completion PCE sends
587     *         {@link #EVENT_SET_PHONE_BOOK_DONE} or
588     *         {@link #EVENT_SET_PHONE_BOOK_ERROR} in case of failure
589     */
590    public boolean setPhoneBookFolderDown(String folder) {
591        BluetoothPbapRequest req = new BluetoothPbapRequestSetPath(folder);
592        return mSession.makeRequest(req);
593    }
594
595    /**
596     * Requests for the number of entries in the phone book.
597     *
598     * @param pbName absolute path to the phone book
599     * @return <code>true</code> if request has been sent successfully;
600     *         <code>false</code> otherwise; upon completion PCE sends
601     *         {@link #EVENT_PULL_PHONE_BOOK_SIZE_DONE} or
602     *         {@link #EVENT_PULL_PHONE_BOOK_SIZE_ERROR} in case of failure
603     */
604    public boolean pullPhoneBookSize(String pbName) {
605        BluetoothPbapRequestPullPhoneBookSize req = new BluetoothPbapRequestPullPhoneBookSize(
606                pbName);
607
608        return mSession.makeRequest(req);
609    }
610
611    /**
612     * Requests for the number of entries in the phone book listing.
613     *
614     * @param folder the name of the folder to be retrieved
615     * @return <code>true</code> if request has been sent successfully;
616     *         <code>false</code> otherwise; upon completion PCE sends
617     *         {@link #EVENT_PULL_VCARD_LISTING_SIZE_DONE} or
618     *         {@link #EVENT_PULL_VCARD_LISTING_SIZE_ERROR} in case of failure
619     */
620    public boolean pullVcardListingSize(String folder) {
621        BluetoothPbapRequestPullVcardListingSize req = new BluetoothPbapRequestPullVcardListingSize(
622                folder);
623
624        return mSession.makeRequest(req);
625    }
626
627    /**
628     * Pulls complete phone book. This method pulls phone book which entries are
629     * of <code>VCARD_TYPE_21</code> type and each single vCard contains minimal
630     * required set of fields and the number of entries in response is not
631     * limited.
632     *
633     * @param pbName absolute path to the phone book
634     * @return <code>true</code> if request has been sent successfully;
635     *         <code>false</code> otherwise; upon completion PCE sends
636     *         {@link #EVENT_PULL_PHONE_BOOK_DONE} or
637     *         {@link #EVENT_PULL_PHONE_BOOK_ERROR} in case of failure
638     */
639    public boolean pullPhoneBook(String pbName) {
640        return pullPhoneBook(pbName, 0, VCARD_TYPE_21, 0, 0);
641    }
642
643    /**
644     * Pulls complete phone book. This method pulls all entries from the phone
645     * book.
646     *
647     * @param pbName absolute path to the phone book
648     * @param filter bit mask which indicates which fields of the vCard shall be
649     *            included in each entry of the resulting list
650     * @param format vCard format of entries in the resulting list
651     * @return <code>true</code> if request has been sent successfully;
652     *         <code>false</code> otherwise; upon completion PCE sends
653     *         {@link #EVENT_PULL_PHONE_BOOK_DONE} or
654     *         {@link #EVENT_PULL_PHONE_BOOK_ERROR} in case of failure
655     */
656    public boolean pullPhoneBook(String pbName, long filter, byte format) {
657        return pullPhoneBook(pbName, filter, format, 0, 0);
658    }
659
660    /**
661     * Pulls complete phone book. This method pulls entries from the phone book
662     * limited to the number of <code>maxListCount</code> starting from the
663     * position of <code>listStartOffset</code>.
664     * <p>
665     * The resulting list contains vCard objects in version
666     * <code>VCARD_TYPE_21</code> which in turns contain minimal required set of
667     * vCard fields.
668     *
669     * @param pbName absolute path to the phone book
670     * @param maxListCount limits number of entries in the response
671     * @param listStartOffset offset to the first entry of the list that would
672     *            be returned
673     * @return <code>true</code> if request has been sent successfully;
674     *         <code>false</code> otherwise; upon completion PCE sends
675     *         {@link #EVENT_PULL_PHONE_BOOK_DONE} or
676     *         {@link #EVENT_PULL_PHONE_BOOK_ERROR} in case of failure
677     */
678    public boolean pullPhoneBook(String pbName, int maxListCount, int listStartOffset) {
679        return pullPhoneBook(pbName, 0, VCARD_TYPE_21, maxListCount, listStartOffset);
680    }
681
682    /**
683     * Pulls complete phone book.
684     *
685     * @param pbName absolute path to the phone book
686     * @param filter bit mask which indicates which fields of the vCard hall be
687     *            included in each entry of the resulting list
688     * @param format vCard format of entries in the resulting list
689     * @param maxListCount limits number of entries in the response
690     * @param listStartOffset offset to the first entry of the list that would
691     *            be returned
692     * @return <code>true</code> if request has been sent successfully;
693     *         <code>false</code> otherwise; upon completion PCE sends
694     *         {@link #EVENT_PULL_PHONE_BOOK_DONE} or
695     *         {@link #EVENT_PULL_PHONE_BOOK_ERROR} in case of failure
696     */
697    public boolean pullPhoneBook(String pbName, long filter, byte format, int maxListCount,
698            int listStartOffset) {
699        BluetoothPbapRequest req = new BluetoothPbapRequestPullPhoneBook(pbName, filter, format,
700                maxListCount, listStartOffset);
701        return mSession.makeRequest(req);
702    }
703
704    /**
705     * Pulls list of entries in the phone book.
706     * <p>
707     * This method pulls the list of entries in the <code>folder</code>.
708     *
709     * @param folder the name of the folder to be retrieved
710     * @return <code>true</code> if request has been sent successfully;
711     *         <code>false</code> otherwise; upon completion PCE sends
712     *         {@link #EVENT_PULL_VCARD_LISTING_DONE} or
713     *         {@link #EVENT_PULL_VCARD_LISTING_ERROR} in case of failure
714     */
715    public boolean pullVcardListing(String folder) {
716        return pullVcardListing(folder, ORDER_BY_DEFAULT, SEARCH_ATTR_NAME, null, 0, 0);
717    }
718
719    /**
720     * Pulls list of entries in the <code>folder</code>.
721     *
722     * @param folder the name of the folder to be retrieved
723     * @param order the sorting order of the resulting list of entries
724     * @return <code>true</code> if request has been sent successfully;
725     *         <code>false</code> otherwise; upon completion PCE sends
726     *         {@link #EVENT_PULL_VCARD_LISTING_DONE} or
727     *         {@link #EVENT_PULL_VCARD_LISTING_ERROR} in case of failure
728     */
729    public boolean pullVcardListing(String folder, byte order) {
730        return pullVcardListing(folder, order, SEARCH_ATTR_NAME, null, 0, 0);
731    }
732
733    /**
734     * Pulls list of entries in the <code>folder</code>. Only entries where
735     * <code>searchAttr</code> attribute of vCard matches <code>searchVal</code>
736     * will be listed.
737     *
738     * @param folder the name of the folder to be retrieved
739     * @param searchAttr vCard attribute which shall be used to carry out search
740     *            operation on
741     * @param searchVal text string used by matching routine to match the value
742     *            of the attribute indicated by SearchAttr
743     * @return <code>true</code> if request has been sent successfully;
744     *         <code>false</code> otherwise; upon completion PCE sends
745     *         {@link #EVENT_PULL_VCARD_LISTING_DONE} or
746     *         {@link #EVENT_PULL_VCARD_LISTING_ERROR} in case of failure
747     */
748    public boolean pullVcardListing(String folder, byte searchAttr, String searchVal) {
749        return pullVcardListing(folder, ORDER_BY_DEFAULT, searchAttr, searchVal, 0, 0);
750    }
751
752    /**
753     * Pulls list of entries in the <code>folder</code>.
754     *
755     * @param folder the name of the folder to be retrieved
756     * @param order the sorting order of the resulting list of entries
757     * @param maxListCount limits number of entries in the response
758     * @param listStartOffset offset to the first entry of the list that would
759     *            be returned
760     * @return <code>true</code> if request has been sent successfully;
761     *         <code>false</code> otherwise; upon completion PCE sends
762     *         {@link #EVENT_PULL_VCARD_LISTING_DONE} or
763     *         {@link #EVENT_PULL_VCARD_LISTING_ERROR} in case of failure
764     */
765    public boolean pullVcardListing(String folder, byte order, int maxListCount,
766            int listStartOffset) {
767        return pullVcardListing(folder, order, SEARCH_ATTR_NAME, null, maxListCount,
768                listStartOffset);
769    }
770
771    /**
772     * Pulls list of entries in the <code>folder</code>.
773     *
774     * @param folder the name of the folder to be retrieved
775     * @param maxListCount limits number of entries in the response
776     * @param listStartOffset offset to the first entry of the list that would
777     *            be returned
778     * @return <code>true</code> if request has been sent successfully;
779     *         <code>false</code> otherwise; upon completion PCE sends
780     *         {@link #EVENT_PULL_VCARD_LISTING_DONE} or
781     *         {@link #EVENT_PULL_VCARD_LISTING_ERROR} in case of failure
782     */
783    public boolean pullVcardListing(String folder, int maxListCount, int listStartOffset) {
784        return pullVcardListing(folder, ORDER_BY_DEFAULT, SEARCH_ATTR_NAME, null, maxListCount,
785                listStartOffset);
786    }
787
788    /**
789     * Pulls list of entries in the <code>folder</code>.
790     *
791     * @param folder the name of the folder to be retrieved
792     * @param order the sorting order of the resulting list of entries
793     * @param searchAttr vCard attribute which shall be used to carry out search
794     *            operation on
795     * @param searchVal text string used by matching routine to match the value
796     *            of the attribute indicated by SearchAttr
797     * @param maxListCount limits number of entries in the response
798     * @param listStartOffset offset to the first entry of the list that would
799     *            be returned
800     * @return <code>true</code> if request has been sent successfully;
801     *         <code>false</code> otherwise; upon completion PCE sends
802     *         {@link #EVENT_PULL_VCARD_LISTING_DONE} or
803     *         {@link #EVENT_PULL_VCARD_LISTING_ERROR} in case of failure
804     */
805    public boolean pullVcardListing(String folder, byte order, byte searchAttr,
806            String searchVal, int maxListCount, int listStartOffset) {
807        BluetoothPbapRequest req = new BluetoothPbapRequestPullVcardListing(folder, order,
808                searchAttr, searchVal, maxListCount, listStartOffset);
809        return mSession.makeRequest(req);
810    }
811
812    /**
813     * Pulls single vCard object
814     *
815     * @param handle handle to the vCard which shall be pulled
816     * @return <code>true</code> if request has been sent successfully;
817     *         <code>false</code> otherwise; upon completion PCE sends
818     *         {@link #EVENT_PULL_VCARD_DONE} or
819     * @link #EVENT_PULL_VCARD_ERROR} in case of failure
820     */
821    public boolean pullVcardEntry(String handle) {
822        return pullVcardEntry(handle, (byte) 0, VCARD_TYPE_21);
823    }
824
825    /**
826     * Pulls single vCard object
827     *
828     * @param handle handle to the vCard which shall be pulled
829     * @param filter bit mask of the vCard fields that shall be included in the
830     *            resulting vCard
831     * @param format resulting vCard version
832     * @return <code>true</code> if request has been sent successfully;
833     *         <code>false</code> otherwise; upon completion PCE sends
834     *         {@link #EVENT_PULL_VCARD_DONE}
835     * @link #EVENT_PULL_VCARD_ERROR} in case of failure
836     */
837    public boolean pullVcardEntry(String handle, long filter, byte format) {
838        BluetoothPbapRequest req = new BluetoothPbapRequestPullVcardEntry(handle, filter, format);
839        return mSession.makeRequest(req);
840    }
841
842    public boolean setAuthResponse(String key) {
843        Log.d(TAG, " setAuthResponse key=" + key);
844        return mSession.setAuthResponse(key);
845    }
846}
847