summaryrefslogtreecommitdiffstats
path: root/src/com/android/bluetooth/pbapclient/PbapClientConnectionHandler.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/bluetooth/pbapclient/PbapClientConnectionHandler.java')
-rw-r--r--src/com/android/bluetooth/pbapclient/PbapClientConnectionHandler.java124
1 files changed, 101 insertions, 23 deletions
diff --git a/src/com/android/bluetooth/pbapclient/PbapClientConnectionHandler.java b/src/com/android/bluetooth/pbapclient/PbapClientConnectionHandler.java
index 914b5b163..4e4a240f1 100644
--- a/src/com/android/bluetooth/pbapclient/PbapClientConnectionHandler.java
+++ b/src/com/android/bluetooth/pbapclient/PbapClientConnectionHandler.java
@@ -32,8 +32,10 @@ import android.util.Log;
import com.android.bluetooth.BluetoothObexTransport;
import com.android.bluetooth.R;
+import com.android.vcard.VCardEntry;
import java.io.IOException;
+import java.util.ArrayList;
import java.util.HashMap;
import javax.obex.ClientSession;
@@ -46,6 +48,15 @@ import javax.obex.ResponseCodes;
* controlling state machine.
*/
class PbapClientConnectionHandler extends Handler {
+ // Tradeoff: larger BATCH_SIZE leads to faster download rates, while smaller
+ // BATCH_SIZE is less prone to IO Exceptions if there is a download in
+ // progress when Bluetooth stack is torn down.
+ private static final int DEFAULT_BATCH_SIZE = 250;
+
+ // Upper limit on the indices of the vcf cards/entries, inclusive,
+ // i.e., valid indices are [0, 1, ... , UPPER_LIMIT]
+ private static final int UPPER_LIMIT = 65535;
+
static final String TAG = "PbapClientConnHandler";
static final boolean DBG = Utils.DBG;
static final boolean VDBG = Utils.VDBG;
@@ -88,16 +99,26 @@ class PbapClientConnectionHandler extends Handler {
private static final long PBAP_FILTER_NICKNAME = 1 << 23;
private static final int PBAP_SUPPORTED_FEATURE =
- PBAP_FEATURE_DEFAULT_IMAGE_FORMAT | PBAP_FEATURE_BROWSING | PBAP_FEATURE_DOWNLOADING;
+ PBAP_FEATURE_DEFAULT_IMAGE_FORMAT | PBAP_FEATURE_DOWNLOADING;
private static final long PBAP_REQUESTED_FIELDS =
PBAP_FILTER_VERSION | PBAP_FILTER_FN | PBAP_FILTER_N | PBAP_FILTER_PHOTO
| PBAP_FILTER_ADR | PBAP_FILTER_EMAIL | PBAP_FILTER_TEL | PBAP_FILTER_NICKNAME;
private static final int L2CAP_INVALID_PSM = -1;
public static final String PB_PATH = "telecom/pb.vcf";
+ public static final String FAV_PATH = "telecom/fav.vcf";
public static final String MCH_PATH = "telecom/mch.vcf";
public static final String ICH_PATH = "telecom/ich.vcf";
public static final String OCH_PATH = "telecom/och.vcf";
+ public static final String SIM_PB_PATH = "SIM1/telecom/pb.vcf";
+ public static final String SIM_MCH_PATH = "SIM1/telecom/mch.vcf";
+ public static final String SIM_ICH_PATH = "SIM1/telecom/ich.vcf";
+ public static final String SIM_OCH_PATH = "SIM1/telecom/och.vcf";
+
+ // PBAP v1.2.3 Sec. 7.1.2
+ private static final int SUPPORTED_REPOSITORIES_LOCALPHONEBOOK = 1 << 0;
+ private static final int SUPPORTED_REPOSITORIES_SIMCARD = 1 << 1;
+ private static final int SUPPORTED_REPOSITORIES_FAVORITES = 1 << 3;
public static final int PBAP_V1_2 = 0x0102;
public static final byte VCARD_TYPE_21 = 0;
@@ -239,29 +260,25 @@ class PbapClientConnectionHandler extends Handler {
break;
case MSG_DOWNLOAD:
- try {
- mAccountCreated = addAccount(mAccount);
- if (!mAccountCreated) {
- Log.e(TAG, "Account creation failed.");
- return;
- }
- // Start at contact 1 to exclued Owner Card PBAP 1.1 sec 3.1.5.2
- BluetoothPbapRequestPullPhoneBook request =
- new BluetoothPbapRequestPullPhoneBook(PB_PATH, mAccount,
- PBAP_REQUESTED_FIELDS, VCARD_TYPE_30, 0, 1);
- request.execute(mObexSession);
- PhonebookPullRequest processor =
- new PhonebookPullRequest(mPbapClientStateMachine.getContext(),
- mAccount);
- processor.setResults(request.getList());
- processor.onPullComplete();
- HashMap<String, Integer> callCounter = new HashMap<>();
- downloadCallLog(MCH_PATH, callCounter);
- downloadCallLog(ICH_PATH, callCounter);
- downloadCallLog(OCH_PATH, callCounter);
- } catch (IOException e) {
- Log.w(TAG, "DOWNLOAD_CONTACTS Failure" + e.toString());
+ mAccountCreated = addAccount(mAccount);
+ if (!mAccountCreated) {
+ Log.e(TAG, "Account creation failed.");
+ return;
}
+ if (isRepositorySupported(SUPPORTED_REPOSITORIES_FAVORITES)) {
+ downloadContacts(FAV_PATH);
+ }
+ if (isRepositorySupported(SUPPORTED_REPOSITORIES_LOCALPHONEBOOK)) {
+ downloadContacts(PB_PATH);
+ }
+ if (isRepositorySupported(SUPPORTED_REPOSITORIES_SIMCARD)) {
+ downloadContacts(SIM_PB_PATH);
+ }
+
+ HashMap<String, Integer> callCounter = new HashMap<>();
+ downloadCallLog(MCH_PATH, callCounter);
+ downloadCallLog(ICH_PATH, callCounter);
+ downloadCallLog(OCH_PATH, callCounter);
break;
default:
@@ -369,6 +386,59 @@ class PbapClientConnectionHandler extends Handler {
}
}
+ void downloadContacts(String path) {
+ try {
+ PhonebookPullRequest processor =
+ new PhonebookPullRequest(mPbapClientStateMachine.getContext(),
+ mAccount);
+
+ // Download contacts in batches of size DEFAULT_BATCH_SIZE
+ BluetoothPbapRequestPullPhoneBookSize requestPbSize =
+ new BluetoothPbapRequestPullPhoneBookSize(path,
+ PBAP_REQUESTED_FIELDS);
+ requestPbSize.execute(mObexSession);
+
+ int numberOfContactsRemaining = requestPbSize.getSize();
+ int startOffset = 0;
+ if (PB_PATH.equals(path)) {
+ // PBAP v1.2.3, Sec 3.1.5. The first contact in pb is owner card 0.vcf, which we
+ // do not want to download. The other phonebook objects (e.g., fav) don't have an
+ // owner card, so they don't need an offset.
+ startOffset = 1;
+ // "-1" because Owner Card 0.vcf is also included in /pb, but not in /fav.
+ numberOfContactsRemaining -= 1;
+ }
+
+ while ((numberOfContactsRemaining > 0) && (startOffset <= UPPER_LIMIT)) {
+ int numberOfContactsToDownload =
+ Math.min(Math.min(DEFAULT_BATCH_SIZE, numberOfContactsRemaining),
+ UPPER_LIMIT - startOffset + 1);
+ BluetoothPbapRequestPullPhoneBook request =
+ new BluetoothPbapRequestPullPhoneBook(path, mAccount,
+ PBAP_REQUESTED_FIELDS, VCARD_TYPE_30,
+ numberOfContactsToDownload, startOffset);
+ request.execute(mObexSession);
+ ArrayList<VCardEntry> vcards = request.getList();
+ if (path == FAV_PATH) {
+ // mark each vcard as a favorite
+ for (VCardEntry v : vcards) {
+ v.setStarred(true);
+ }
+ }
+ processor.setResults(vcards);
+ processor.onPullComplete();
+
+ startOffset += numberOfContactsToDownload;
+ numberOfContactsRemaining -= numberOfContactsToDownload;
+ }
+ if ((startOffset > UPPER_LIMIT) && (numberOfContactsRemaining > 0)) {
+ Log.w(TAG, "Download contacts incomplete, index exceeded upper limit.");
+ }
+ } catch (IOException e) {
+ Log.w(TAG, "Download contacts failure" + e.toString());
+ }
+ }
+
void downloadCallLog(String path, HashMap<String, Integer> callCounter) {
try {
BluetoothPbapRequestPullPhoneBook request =
@@ -419,4 +489,12 @@ class PbapClientConnectionHandler extends Handler {
Log.d(TAG, "Call Logs could not be deleted, they may not exist yet.");
}
}
+
+ private boolean isRepositorySupported(int mask) {
+ if (mPseRec == null) {
+ if (VDBG) Log.v(TAG, "No PBAP Server SDP Record");
+ return false;
+ }
+ return (mask & mPseRec.getSupportedRepositories()) != 0;
+ }
}