Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c69d1741 authored by Joseph Pirozzo's avatar Joseph Pirozzo
Browse files

PBAP Client SDP record

Add registration for PBAP Client SDP record when service is available.

Bug: 113505152
Test: Check SDP record via "sdptool browse"
Change-Id: I01a080385683d63c2cbb6e5a62f89d611b3e9cdd
parent e9281f49
Loading
Loading
Loading
Loading
+33 −0
Original line number Diff line number Diff line
@@ -307,6 +307,37 @@ static jint sdpCreateMapMnsRecordNative(JNIEnv* env, jobject obj,
  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 @@ static JNINativeMethod sMethods[] = {
     (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",
+1 −1
Original line number Diff line number Diff line
@@ -92,7 +92,6 @@ class PbapClientConnectionHandler extends Handler {
    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 @@ class PbapClientConnectionHandler extends Handler {
    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;

+37 −7
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ import android.util.Log;

import com.android.bluetooth.R;
import com.android.bluetooth.btservice.ProfileService;
import com.android.bluetooth.sdp.SdpManager;

import java.util.ArrayList;
import java.util.List;
@@ -47,12 +48,14 @@ public class PbapClientService extends ProfileService {
    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 @@ public class PbapClientService extends ProfileService {
        } 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 @@ public class PbapClientService extends ProfileService {
        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 @@ public class PbapClientService extends ProfileService {
        }
    }

    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) {
+24 −0
Original line number Diff line number Diff line
@@ -85,6 +85,9 @@ public class SdpManager {
    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 @@ public class SdpManager {
        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.