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