Thursday, March 1, 2012

BlueDUN issue: why the "Start Service" button has no effect?

Symptoms: when click the "Start Service" button, the status comes back to the green color immediately.

The BlueDUN application allows to enable the bluetooth DUN profile for Android phones;  this profile is not officially supported by Google and you need an app to turn on this feature.   
Some firmwares (in particular the Motorola, and some HTC / Sony firmwares) don't allow the registration of DUN profile because it seems already registered even if not available.   

To check if the DUN profile is available or not for your device/firmware you can trace the systems logs with the Catlog app  (download it from Google Play, it is free):
- download and install the Catlog app, open it
- open BluDUN and click the "Start Service" button
- go back to Catlog and filter by BluetoothService

If you find this message:

W/BluetoothService( 448): Attempted to register a reserved UUID: 00001103-0000-1000-8000-00805f9b34fb

you will not able to use the BludDUN app.

The Catlog app requires a rooted firmware for Jelly Bean;  alternatively you can get the same report connecting the phone to a Windows / Mac or Linux PC:

1. Download the latest Android SDK (SDK Tools Only) for your SO from Google: Android SDK
2. Extract the ZIP file to your desired location
3. To get ADB, you need to install the SDK: Installing the SDK
    ( execute the SDK Manager and install the "Android SDK Platform Tools" )

Make sure in your phone the option Settings” -> “Developer Options” -> “Debugging” ->”USB debugging" is enabled;   open a terminal (cmd) and execute the command in the folder  .../android-sdk/platform-tools:

adb logcat 

   starts dumping debugging information from your handset to the console 

adb logcat -f <logfilename> 

   starts dumping debugging information from your handset to the file <logfilename>


The Android source code is open, so we can discover where is the problem:

If you want enable a profile, you need to call the listenUsingRfcommWithServiceRecord method of BluetoothAdapter class:

925   public BluetoothServerSocket listenUsingRfcommWithServiceRecord(String name, UUID uuid) throws IOException {
927       return createNewRfcommSocketAndRecord(name, uuid, true, true);
928  }

There are 2 parameters:  the first one is the name assigned to the new profile (you can see this name from Windows when you list the available BT services), the other is the Universally Unique Identifier (UUID) that identifies uniquely the profile type:

The base UUID is 00000000-0000-1000-8000-00805F9B34FB
The DUN profile code is 1103;  
The complete UUID for DUN profile is :  00001103-0000-1000-8000-00805F9B34FB

The listenUsingRfcommWithServiceRecord method calls the createNewRfcommSocketAndRecord method inside:

999  private BluetoothServerSocket createNewRfcommSocketAndRecord(String name, UUID uuid,
                  boolean auth, boolean encrypt) throws IOException 

and createNewRfcommSocketAndRecord calls:

1035    handle = mService.addRfcommServiceRecord(name, new ParcelUuid(uuid), channel, new Binder());

for registering the service record related to the UUID for a specific bluetooth channel.

The mService object is declared as an interface (IBluetooth); the implementation is the BluetoothService class:

public synchronized int addRfcommServiceRecord(String serviceName, ParcelUuid uuid,
            int channel, IBinder b) {
        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
        if (!isEnabledInternal()) return -1;

        if (serviceName == null || uuid == null || channel < 1 ||
                channel > BluetoothSocket.MAX_RFCOMM_CHANNEL) {
            return -1;
        if (BluetoothUuid.isUuidPresent(BluetoothUuid.RESERVED_UUIDS, uuid)) {
            Log.w(TAG, "Attempted to register a reserved UUID: " + uuid);
            return -1;
        int handle = addRfcommServiceRecordNative(serviceName,
                uuid.getUuid().getMostSignificantBits(), uuid.getUuid().getLeastSignificantBits(),
        if (DBG) log("new handle " + Integer.toHexString(handle));
        if (handle == -1) {
            return -1;

        int pid = Binder.getCallingPid();
        mServiceRecordToPid.put(new Integer(handle), new Integer(pid));
        try {
            b.linkToDeath(new Reaper(handle, pid), 0);
        } catch (RemoteException e) {}
        return handle;

Inside this method you can see the call: BluetoothUuid.isUuidPresent(BluetoothUuid.RESERVED_UUIDS, uuid)
and if it fails, returns the message showed in the system log: 

Attempted to register a reserved UUID: 00001103-0000-1000-8000-00805F9B34FB


The isUuidPresent method of BluetoothUuid class checks if the UUID you want to register is free; in other words, the firmware defines a list of taken UUID and the method checks if your UUID is included or not in this list.   If included, you cannot register the new profile.
The list is fixed and it is given by the  RESERVED_UUIDS constant:

RESERVED_UUIDS = { AudioSink, AudioSource, AdvAudioDist, HSP, Handsfree, AvrcpController, AvrcpTarget, ObexObjectPush, PANU, NAP }

Usually the list doesn't include the DUN profile:

AudioSink ="0000110B-0000-1000-8000-00805F9B34FB"
AudioSource ="0000110A-0000-1000-8000-00805F9B34FB"
AdvAudioDist ="0000110D-0000-1000-8000-00805F9B34FB"
HSP ="00001108-0000-1000-8000-00805F9B34FB"
HSP_AG ="00001112-0000-1000-8000-00805F9B34FB"
Handsfree ="0000111E-0000-1000-8000-00805F9B34FB"
Handsfree_AG ="0000111F-0000-1000-8000-00805F9B34FB"
AvrcpController ="0000110E-0000-1000-8000-00805F9B34FB"
AvrcpTarget ="0000110C-0000-1000-8000-00805F9B34FB"
ObexObjectPush ="00001105-0000-1000-8000-00805f9b34fb"
Hid ="00001124-0000-1000-8000-00805f9b34fb"
PANU ="00001115-0000-1000-8000-00805F9B34FB"
NAP ="00001116-0000-1000-8000-00805F9B34FB"
BNEP ="0000000f-0000-1000-8000-00805F9B34FB"
PBAP_PSE ="0000112f-0000-1000-8000-00805F9B34FB"

On the other hand, if the DUN profile was added in this list the BluetoothUuid.isUuidPresent returns true;  you get the message "Attempted to register a reserved UUID: "  the app will not able to register the new profile!

The question is:   why is the DUN profile is included inside this list if the DUN profile is not implemented?

Probably the reason is that the manufacturer doesn't want the DUN profile is enabled at the application level in their devices; maybe for security issues.