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

Commit ac810e53 authored by Android (Google) Code Review's avatar Android (Google) Code Review
Browse files

Merge change 25779 into eclair

* changes:
  Add new API for fetching UUIDs using SDP.
parents 338c4855 1caa6d11
Loading
Loading
Loading
Loading
+45 −0
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ import android.util.Log;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.UUID;

/**
 * Represents a remote Bluetooth device.
@@ -225,6 +226,20 @@ public final class BluetoothDevice implements Parcelable {
    /** @hide */
    public static final String EXTRA_PASSKEY = "android.bluetooth.device.extra.PASSKEY";

    /**
     * Broadcast Action: This intent is used to broadcast the {@link UUID}
     * wrapped as a {@link ParcelUuid} of the remote device after it has been
     * fetched. This intent is sent only when the UUIDs of the remote device
     * are requested to be fetched using Service Discovery Protocol
     * <p> Always contains the extra field {@link #EXTRA_DEVICE}
     * <p> Always contains the extra filed {@link #EXTRA_UUID}
     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
     * @hide
     */
    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    public static final String ACTION_UUID =
            "android.bleutooth.device.action.UUID";

    /**
     * Broadcast Action: Indicates a failure to retrieve the name of a remote
     * device.
@@ -292,6 +307,15 @@ public final class BluetoothDevice implements Parcelable {
     * @hide */
    public static final int PAIRING_VARIANT_DISPLAY_PASSKEY = 4;

    /**
     * Used as an extra field in {@link #ACTION_UUID} intents,
     * Contains the {@link ParcelUuid}s of the remote device which is a parcelable
     * version of {@link UUID}.
     * @hide
     */
    public static final String EXTRA_UUID = "android.bluetooth.device.extra.UUID";


    private static IBluetooth sService;  /* Guarenteed constant after first object constructed */

    private final String mAddress;
@@ -507,6 +531,27 @@ public final class BluetoothDevice implements Parcelable {
        return null;
    }

     /**
      *  Perform a SDP query on the remote device to get the UUIDs
      *  supported. This API is asynchronous and an Intent is sent,
      *  with the UUIDs supported by the remote end. If there is an error
      *  in getting the SDP records or if the process takes a long time,
      *  an Intent is sent with the UUIDs that is currently present in the
      *  cache. Clients should use the {@link getUuids} to get UUIDs
      *  is SDP is not to be performed.
      *
      *  @return False if the sanity check fails, True if the process
      *               of initiating an ACL connection to the remote device
      *               was started.
      *  @hide
      */
     public boolean fetchUuidsWithSdp() {
        try {
            return sService.fetchRemoteUuidsWithSdp(mAddress);
        } catch (RemoteException e) {Log.e(TAG, "", e);}
        return false;
    }

    /** @hide */
    public int getServiceChannel(ParcelUuid uuid) {
         try {
+1 −0
Original line number Diff line number Diff line
@@ -53,6 +53,7 @@ interface IBluetooth
    String getRemoteName(in String address);
    int getRemoteClass(in String address);
    ParcelUuid[] getRemoteUuids(in String address);
    boolean fetchRemoteUuidsWithSdp(in String address);
    int getRemoteServiceChannel(in String address,in ParcelUuid uuid);

    boolean setPin(in String address, in byte[] pin);
+23 −0
Original line number Diff line number Diff line
@@ -330,6 +330,9 @@ class BluetoothEventLoop {
            Log.e(TAG, "onDevicePropertyChanged: Address of the remote device in null");
            return;
        }
        if (DBG) {
            log("Device property changed:" + address + "property:" + name);
        }
        BluetoothDevice device = mAdapter.getRemoteDevice(address);
        if (name.equals("Name")) {
            Intent intent = new Intent(BluetoothDevice.ACTION_NAME_CHANGED);
@@ -366,6 +369,7 @@ class BluetoothEventLoop {
                uuid = str.toString();
            }
            mBluetoothService.setRemoteDeviceProperty(address, name, uuid);
            mBluetoothService.sendUuidIntent(address);
        } else if (name.equals("Paired")) {
            if (propValues[1].equals("true")) {
                mBluetoothService.getBondState().setBondState(address, BluetoothDevice.BOND_BONDED);
@@ -528,6 +532,25 @@ class BluetoothEventLoop {
        return;
    }

    private void onDiscoverServicesResult(String deviceObjectPath, boolean result) {
        String address = mBluetoothService.getAddressFromObjectPath(deviceObjectPath);
        // We don't parse the xml here, instead just query Bluez for the properties.
        if (result) {
            String[] properties = mBluetoothService.getRemoteDeviceProperties(address);
            mBluetoothService.addRemoteDeviceProperties(address, properties);
        }
        mBluetoothService.sendUuidIntent(address);
    }

    private void onCreateDeviceResult(String address, boolean result) {
        if (DBG) {
            log("Result of onCreateDeviceResult:" + result);
        }
        if (!result) {
            mBluetoothService.sendUuidIntent(address);
        }
    }

    private void onRestartRequired() {
        if (mBluetoothService.isEnabled()) {
            Log.e(TAG, "*** A serious error occured (did bluetoothd crash?) - " +
+61 −0
Original line number Diff line number Diff line
@@ -76,10 +76,17 @@ public class BluetoothService extends IBluetooth.Stub {

    private static final int MESSAGE_REGISTER_SDP_RECORDS = 1;
    private static final int MESSAGE_FINISH_DISABLE = 2;
    private static final int MESSAGE_UUID_INTENT = 3;

    // The timeout used to sent the UUIDs Intent
    // This timeout should be greater than the page timeout
    private static final int UUID_INTENT_DELAY = 6000;

    private final Map<String, String> mAdapterProperties;
    private final HashMap <String, Map<String, String>> mDeviceProperties;

    private final ArrayList <String> mUuidIntentTracker;

    static {
        classInitNative();
    }
@@ -104,6 +111,7 @@ public class BluetoothService extends IBluetooth.Stub {
        mIsDiscovering = false;
        mAdapterProperties = new HashMap<String, String>();
        mDeviceProperties = new HashMap<String, Map<String,String>>();
        mUuidIntentTracker = new ArrayList<String>();
        registerForAirplaneMode();
    }

@@ -291,6 +299,11 @@ public class BluetoothService extends IBluetooth.Stub {
            case MESSAGE_FINISH_DISABLE:
                finishDisable(msg.arg1 != 0);
                break;
            case MESSAGE_UUID_INTENT:
                String address = (String)msg.obj;
                if (address != null)
                    sendUuidIntent(address);
                break;
            }
        }
    };
@@ -976,6 +989,10 @@ public class BluetoothService extends IBluetooth.Stub {
        if (!BluetoothAdapter.checkBluetoothAddress(address)) {
            return null;
        }
        return getUuidFromCache(address);
    }

    private ParcelUuid[] getUuidFromCache(String address) {
        String value = getRemoteDeviceProperty(address, "UUIDs");
        if (value == null) return null;

@@ -990,6 +1007,36 @@ public class BluetoothService extends IBluetooth.Stub {
        return uuids;
    }

    public synchronized boolean fetchRemoteUuidsWithSdp(String address) {
        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
        if (!BluetoothAdapter.checkBluetoothAddress(address)) {
            return false;
        }

        if (mUuidIntentTracker.contains(address)) {
            // An SDP query for this address is already in progress
            return true;
        }

        boolean ret;
        if (getBondState(address) == BluetoothDevice.BOND_BONDED) {
            String path = getObjectPathFromAddress(address);
            if (path == null) return false;

            // Use an empty string for the UUID pattern
            ret = discoverServicesNative(path, "");
        } else {
            ret = createDeviceNative(address);
        }

        mUuidIntentTracker.add(address);

        Message message = mHandler.obtainMessage(MESSAGE_UUID_INTENT);
        message.obj = address;
        mHandler.sendMessageDelayed(message, UUID_INTENT_DELAY);
        return ret;
    }

    /**
     * Gets the rfcomm channel associated with the UUID.
     *
@@ -1121,6 +1168,18 @@ public class BluetoothService extends IBluetooth.Stub {
                Settings.System.AIRPLANE_MODE_ON, 0) == 1;
    }

    /* Broadcast the Uuid intent */
    /*package*/ synchronized void sendUuidIntent(String address) {
        if (mUuidIntentTracker.contains(address)) {
            ParcelUuid[] uuid = getUuidFromCache(address);
            Intent intent = new Intent(BluetoothDevice.ACTION_UUID);
            intent.putExtra(BluetoothDevice.EXTRA_UUID, uuid);
            mContext.sendBroadcast(intent, BLUETOOTH_ADMIN_PERM);

            mUuidIntentTracker.remove(address);
        }
    }

    @Override
    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
        pw.println("\nmIsAirplaneSensitive = " + mIsAirplaneSensitive + "\n");
@@ -1284,4 +1343,6 @@ public class BluetoothService extends IBluetooth.Stub {
    private native boolean setPairingConfirmationNative(String address, boolean confirm,
            int nativeData);
    private native boolean setDevicePropertyBooleanNative(String objectPath, String key, int value);
    private native boolean createDeviceNative(String address);
    private native boolean discoverServicesNative(String objectPath, String pattern);
}
+54 −0
Original line number Diff line number Diff line
@@ -48,6 +48,8 @@ static jmethodID method_onDeviceRemoved;
static jmethodID method_onDeviceDisconnectRequested;

static jmethodID method_onCreatePairedDeviceResult;
static jmethodID method_onCreateDeviceResult;
static jmethodID method_onDiscoverServicesResult;
static jmethodID method_onGetDeviceServiceChannelResult;

static jmethodID method_onRequestPinCode;
@@ -92,6 +94,10 @@ static void classInitNative(JNIEnv* env, jclass clazz) {

    method_onCreatePairedDeviceResult = env->GetMethodID(clazz, "onCreatePairedDeviceResult",
                                                         "(Ljava/lang/String;I)V");
    method_onCreateDeviceResult = env->GetMethodID(clazz, "onCreateDeviceResult",
                                                         "(Ljava/lang/String;Z)V");
    method_onDiscoverServicesResult = env->GetMethodID(clazz, "onDiscoverServicesResult",
                                                         "(Ljava/lang/String;Z)V");

    method_onAgentAuthorize = env->GetMethodID(clazz, "onAgentAuthorize",
                                               "(Ljava/lang/String;Ljava/lang/String;)Z");
@@ -1097,6 +1103,54 @@ done:
    free(user);
}

void onCreateDeviceResult(DBusMessage *msg, void *user, void *n) {
    LOGV(__FUNCTION__);

    native_data_t *nat = (native_data_t *)n;
    const char *address= (const char *)user;
    DBusError err;
    dbus_error_init(&err);
    JNIEnv *env;
    nat->vm->GetEnv((void**)&env, nat->envVer);

    LOGV("... Address = %s", address);

    bool result = JNI_TRUE;
    if (dbus_set_error_from_message(&err, msg)) {
        LOG_AND_FREE_DBUS_ERROR(&err);
        result = JNI_FALSE;
    }
    env->CallVoidMethod(nat->me,
                        method_onCreateDeviceResult,
                        env->NewStringUTF(address),
                        result);
    free(user);
}

void onDiscoverServicesResult(DBusMessage *msg, void *user, void *n) {
    LOGV(__FUNCTION__);

    native_data_t *nat = (native_data_t *)n;
    const char *path = (const char *)user;
    DBusError err;
    dbus_error_init(&err);
    JNIEnv *env;
    nat->vm->GetEnv((void**)&env, nat->envVer);

    LOGV("... Device Path = %s", path);

    bool result = JNI_TRUE;
    if (dbus_set_error_from_message(&err, msg)) {
        LOG_AND_FREE_DBUS_ERROR(&err);
        result = JNI_FALSE;
    }
    env->CallVoidMethod(nat->me,
                        method_onDiscoverServicesResult,
                        env->NewStringUTF(path),
                        result);
    free(user);
}

void onGetDeviceServiceChannelResult(DBusMessage *msg, void *user, void *n) {
    LOGV(__FUNCTION__);

Loading