Merge "PBAP Client SDP record"
diff --git a/jni/com_android_bluetooth_sdp.cpp b/jni/com_android_bluetooth_sdp.cpp
index c2eb5ce..827db71 100644
--- a/jni/com_android_bluetooth_sdp.cpp
+++ b/jni/com_android_bluetooth_sdp.cpp
@@ -307,6 +307,37 @@
return handle;
}
+static jint sdpCreatePbapPceRecordNative(JNIEnv* env, jobject obj,
+ jstring name_str, jint version) {
+ ALOGD("%s", __func__);
+ if (!sBluetoothSdpInterface) return -1;
+
+ bluetooth_sdp_record record = {}; // Must be zero initialized
+ record.pce.hdr.type = SDP_TYPE_PBAP_PCE;
+
+ const char* service_name = NULL;
+ if (name_str != NULL) {
+ service_name = env->GetStringUTFChars(name_str, NULL);
+ record.pce.hdr.service_name = (char*)service_name;
+ record.pce.hdr.service_name_length = strlen(service_name);
+ } else {
+ record.pce.hdr.service_name = NULL;
+ record.pce.hdr.service_name_length = 0;
+ }
+ record.pce.hdr.profile_version = version;
+
+ int handle = -1;
+ int ret = sBluetoothSdpInterface->create_sdp_record(&record, &handle);
+ if (ret != BT_STATUS_SUCCESS) {
+ ALOGE("SDP Create record failed: %d", ret);
+ } else {
+ ALOGD("SDP Create record success - handle: %d", handle);
+ }
+
+ if (service_name) env->ReleaseStringUTFChars(name_str, service_name);
+ return handle;
+}
+
static jint sdpCreatePbapPseRecordNative(JNIEnv* env, jobject obj,
jstring name_str, jint scn,
jint l2cap_psm, jint version,
@@ -474,6 +505,8 @@
(void*)sdpCreateMapMasRecordNative},
{"sdpCreateMapMnsRecordNative", "(Ljava/lang/String;IIII)I",
(void*)sdpCreateMapMnsRecordNative},
+ {"sdpCreatePbapPceRecordNative", "(Ljava/lang/String;I)I",
+ (void*)sdpCreatePbapPceRecordNative},
{"sdpCreatePbapPseRecordNative", "(Ljava/lang/String;IIIII)I",
(void*)sdpCreatePbapPseRecordNative},
{"sdpCreateOppOpsRecordNative", "(Ljava/lang/String;III[B)I",
diff --git a/src/com/android/bluetooth/pbapclient/PbapClientConnectionHandler.java b/src/com/android/bluetooth/pbapclient/PbapClientConnectionHandler.java
index c060ab2..5c3fa4f 100644
--- a/src/com/android/bluetooth/pbapclient/PbapClientConnectionHandler.java
+++ b/src/com/android/bluetooth/pbapclient/PbapClientConnectionHandler.java
@@ -92,7 +92,6 @@
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 PBAP_V1_2 = 0x0102;
private static final int L2CAP_INVALID_PSM = -1;
public static final String PB_PATH = "telecom/pb.vcf";
@@ -100,6 +99,7 @@
public static final String ICH_PATH = "telecom/ich.vcf";
public static final String OCH_PATH = "telecom/och.vcf";
+ public static final int PBAP_V1_2 = 0x0102;
public static final byte VCARD_TYPE_21 = 0;
public static final byte VCARD_TYPE_30 = 1;
diff --git a/src/com/android/bluetooth/pbapclient/PbapClientService.java b/src/com/android/bluetooth/pbapclient/PbapClientService.java
index 4775e4b..f150cdd 100644
--- a/src/com/android/bluetooth/pbapclient/PbapClientService.java
+++ b/src/com/android/bluetooth/pbapclient/PbapClientService.java
@@ -31,6 +31,7 @@
import com.android.bluetooth.R;
import com.android.bluetooth.btservice.AdapterService;
import com.android.bluetooth.btservice.ProfileService;
+import com.android.bluetooth.sdp.SdpManager;
import java.util.ArrayList;
import java.util.List;
@@ -47,12 +48,14 @@
private static final boolean VDBG = Utils.VDBG;
private static final String TAG = "PbapClientService";
+ private static final String SERVICE_NAME = "Phonebook Access PCE";
// MAXIMUM_DEVICES set to 10 to prevent an excessive number of simultaneous devices.
private static final int MAXIMUM_DEVICES = 10;
private Map<BluetoothDevice, PbapClientStateMachine> mPbapClientStateMachineMap =
new ConcurrentHashMap<>();
private static PbapClientService sPbapClientService;
private PbapBroadcastReceiver mPbapBroadcastReceiver = new PbapBroadcastReceiver();
+ private int mSdpHandle = -1;
@Override
public IProfileServiceBinder initBinder() {
@@ -73,13 +76,17 @@
} catch (Exception e) {
Log.w(TAG, "Unable to register pbapclient receiver", e);
}
+
removeUncleanAccounts();
+ registerSdpRecord();
setPbapClientService(this);
return true;
}
@Override
protected boolean stop() {
+ setPbapClientService(null);
+ cleanUpSdpRecord();
try {
unregisterReceiver(mPbapBroadcastReceiver);
} catch (Exception e) {
@@ -88,14 +95,8 @@
for (PbapClientStateMachine pbapClientStateMachine : mPbapClientStateMachineMap.values()) {
pbapClientStateMachine.doQuit();
}
- return true;
- }
-
- @Override
- protected void cleanup() {
removeUncleanAccounts();
- // TODO: Should move to stop()
- setPbapClientService(null);
+ return true;
}
void cleanupDevice(BluetoothDevice device) {
@@ -127,6 +128,35 @@
}
}
+ private void registerSdpRecord() {
+ SdpManager sdpManager = SdpManager.getDefaultManager();
+ if (sdpManager == null) {
+ Log.e(TAG, "SdpManager is null");
+ return;
+ }
+ mSdpHandle = sdpManager.createPbapPceRecord(SERVICE_NAME,
+ PbapClientConnectionHandler.PBAP_V1_2);
+ }
+
+ private void cleanUpSdpRecord() {
+ if (mSdpHandle < 0) {
+ Log.e(TAG, "cleanUpSdpRecord, SDP record never created");
+ return;
+ }
+ int sdpHandle = mSdpHandle;
+ mSdpHandle = -1;
+ SdpManager sdpManager = SdpManager.getDefaultManager();
+ if (sdpManager == null) {
+ Log.e(TAG, "cleanUpSdpRecord failed, sdpManager is null, sdpHandle=" + sdpHandle);
+ return;
+ }
+ Log.i(TAG, "cleanUpSdpRecord, mSdpHandle=" + sdpHandle);
+ if (!sdpManager.removeSdpRecord(sdpHandle)) {
+ Log.e(TAG, "cleanUpSdpRecord, removeSdpRecord failed, sdpHandle=" + sdpHandle);
+ }
+ }
+
+
private class PbapBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
diff --git a/src/com/android/bluetooth/sdp/SdpManager.java b/src/com/android/bluetooth/sdp/SdpManager.java
index d0cca25..d5e3770 100644
--- a/src/com/android/bluetooth/sdp/SdpManager.java
+++ b/src/com/android/bluetooth/sdp/SdpManager.java
@@ -85,6 +85,9 @@
private native int sdpCreateMapMnsRecordNative(String serviceName, int rfcommChannel,
int l2capPsm, int version, int features);
+ private native int sdpCreatePbapPceRecordNative(String serviceName,
+ int version);
+
private native int sdpCreatePbapPseRecordNative(String serviceName, int rfcommChannel,
int l2capPsm, int version, int repositories, int features);
@@ -537,6 +540,27 @@
return sdpCreateMapMnsRecordNative(serviceName, rfcommChannel, l2capPsm, version, features);
}
+ /**
+ * Create a Client side Phone Book Access Profile Service Record.
+ * Create the record once, and reuse it for all connections.
+ * If changes to a record is needed remove the old record using {@link removeSdpRecord}
+ * and then create a new one.
+ * @param serviceName The textual name of the service
+ * @param version The Profile version number (As specified in the Bluetooth
+ * PBAP specification)
+ * @return a handle to the record created. The record can be removed again
+ * using {@link removeSdpRecord}(). The record is not linked to the
+ * creation/destruction of BluetoothSockets, hence SDP record cleanup
+ * is a separate process.
+ */
+ public int createPbapPceRecord(String serviceName, int version) {
+ if (!sNativeAvailable) {
+ throw new RuntimeException(TAG + " sNativeAvailable == false - native not initialized");
+ }
+ return sdpCreatePbapPceRecordNative(serviceName, version);
+ }
+
+
/**
* Create a Server side Phone Book Access Profile Service Record.
* Create the record once, and reuse it for all connections.