Understanding Android Bluetooth Code : part 1 – Application Framework

At the application framework level is the app’s code, which utilizes the android.bluetooth APIs to interact with the bluetooth hardware. Internally, this code calls the Bluetooth process through the Binder IPC mechanism.

Get the code :

$ git clone https://android.googlesource.com/platform/frameworks/base

$ git checkout -b lollipop-release origin/lollipop-release

$ cd base

Immediate search tells us following files are having code related to Bluetooth, this framework defines the basic package ” android.bluetooth ” which Provides classes that manage Bluetooth functionality, such as scanning for devices, connecting with devices, and managing data transfer between devices.

The Bluetooth APIs let applications: ( Refer Link for package details )

  • Scan for other Bluetooth devices (including BLE devices).
  • Query the local Bluetooth adapter for paired Bluetooth devices.
  • Establish RFCOMM channels/sockets.
  • Connect to specified sockets on other devices.
  • Transfer data to and from other devices.
  • Communicate with BLE devices, such as proximity sensors, heart rate monitors, fitness devices, and so on.
  • Act as a GATT client or a GATT server (BLE).

base$ find . -name *Bluetooth*

File : ./services/core/java/com/android/server/BluetoothManagerService.java

Now, lets understand how this file comes into picture, as we know “SystemServer” starts during booting of android, so during booting “Bluetooth Service Manager” gets added to the initialisation sequence,

Slog.i(TAG, “Bluetooth Manager Service”);
bluetooth = new BluetoothManagerService(context);
ServiceManager.addService(BluetoothAdapter.BLUETOOTH_MANAGER_SERVICE, bluetooth);

refer above code from SystemServer base/services/java/com/android/server/SystemServer.java

 above section of code calls “BluetoothManagerService” from ./services/core/java/com/android/server/BluetoothManagerService.java

BluetoothManagerService(Context context) {
mHandler = new BluetoothHandler(IoThread.get().getLooper());

mContext = context;
mBluetooth = null;
mBinding = false;
mUnbinding = false;
mEnable = false;
mState = BluetoothAdapter.STATE_OFF;
mQuietEnableExternal = false;
mEnableExternal = false;
mAddress = null;
mName = null;
mErrorRecoveryRetryCounter = 0;
mContentResolver = context.getContentResolver();
mCallbacks = new RemoteCallbackList<IBluetoothManagerCallback>();
mStateChangeCallbacks = new RemoteCallbackList<IBluetoothStateChangeCallback>();
IntentFilter filter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
filter.addAction(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED);
filter.addAction(Intent.ACTION_USER_SWITCHED);
registerForAirplaneMode(filter);
filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
mContext.registerReceiver(mReceiver, filter);
loadStoredNameAndAddress(); /* Retrieve the Bluetooth Adapter’s name and address and save it in the local cache */
if (isBluetoothPersistedStateOn()) { /* checks if previous saved state is ON */
mEnableExternal = true;
}

int sysUiUid = -1;
try {
sysUiUid = mContext.getPackageManager().getPackageUid(“com.android.systemui”,
UserHandle.USER_OWNER); /* USER_OWNER : A user id constant to indicate the “owner” user of the device, defined at core/java/android/os/UserHandle.java */
} catch (PackageManager.NameNotFoundException e) {
Log.wtf(TAG, “Unable to resolve SystemUI’s UID.”, e);
}
mSystemUiUid = sysUiUid;
}

That means, above service just prepares the bluetooth functionality. Logcat messages, might look like below,

D/BluetoothManagerService(  453): Loading stored name and address
D/BluetoothManagerService(  453): Stored bluetooth Name=null,Address=null

I/SystemServer(  453): Bluetooth Manager Service

I/PackageManager(  453): Running dexopt on: com.android.bluetooth

W/PackageManager(  453): Unknown permission com.google.android.gallery3d.permission.GALLERY_PROVIDER in package com.android.bluetooth
W/PackageManager(  453): Unknown permission android.permission.MMS_SEND_OUTBOX_MSG in package com.android.bluetooth

D/BluetoothTethering(  453): startMonitoring: target: Handler (com.android.server.ConnectivityService$NetworkStateTrackerHandler) {2c6ce818}
D/BluetoothTethering(  453): startMonitoring: mCsHandler: Handler (com.android.server.ConnectivityService$NetworkStateTrackerHandler) {2c6ce818}

D/BluetoothManagerService(  453): Message: 20
D/BluetoothManagerService(  453): Added callback: android.bluetooth.BluetoothAdapter$1@2c6a7810:true
D/BluetoothManagerService(  453): Message: 30
W/ContextImpl(  453): Calling a method in the system process without a qualified user: android.app.ContextImpl.bindService:1543 android.bluetooth.BluetoothPan.doBind:149 android.bluetooth.BluetoothPan.<init>:141 android.bluetooth.BluetoothAdapter.getProfileProxy:1190 android.bluetooth.BluetoothTetheringDataTracker.startMonitoring:116

D/BluetoothManagerService(  453): Message: 20

READ  Check Bluetooth services of a remote device

D/BluetoothManagerService(  453): Added callback: android.bluetooth.IBluetoothManagerCallback$Stub$Proxy@2c3f0ae8:true

D/BluetoothManagerService(  453): Message: 300
D/BluetoothManagerService(  453): MESSAGE_USER_SWITCHED

 

The above messages gets printed from, services/core/java/com/android/server/BluetoothManagerService.java, function         ” 

public void handleMessage(Message msg) {
if (DBG) Log.d (TAG, “Message: ” + msg.what);
switch (msg.what) {
}

}

these messages are declared at the initial of file.

private static final int MESSAGE_REGISTER_ADAPTER = 20;

private static final int MESSAGE_REGISTER_STATE_CHANGE_CALLBACK = 30;

private static final int MESSAGE_USER_SWITCHED = 300;

———————————————————————————————————————————————————

./core/java/android/bluetooth/BluetoothManager.java

High level manager used to obtain an instance of an BluetoothAdapter and to conduct overall Bluetooth Management. ( Refer Link to check actual functions defined by this class )

./core/java/android/bluetooth/IBluetoothManagerCallback.aidl

File : ./core/java/android/bluetooth/IBluetoothManager.aidl

/**
* System private API for talking with the Bluetooth service.
*
* {@hide}
*/
interface IBluetoothManager
{
IBluetooth registerAdapter(in IBluetoothManagerCallback callback);
void unregisterAdapter(in IBluetoothManagerCallback callback);
void registerStateChangeCallback(in IBluetoothStateChangeCallback callback);
void unregisterStateChangeCallback(in IBluetoothStateChangeCallback callback);
boolean isEnabled();
boolean enable();
boolean enableNoAutoConnect();
boolean disable(boolean persist);
IBluetoothGatt getBluetoothGatt();

String getAddress();
String getName();
}

——————————————————————————————————————

File : ./core/java/android/bluetooth/BluetoothAdapter.java

Represents the local device Bluetooth adapter. The BluetoothAdapter lets you perform fundamental Bluetooth tasks, such as initiate device discovery, query a list of bonded (paired) devices, instantiate a BluetoothDevice using a known MAC address, and create a BluetoothServerSocket to listen for connection requests from other devices, and start a scan for Bluetooth LE devices.

Refer : http://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html

Logcat messages :

D/BluetoothAdapter(  605): 741632288: getState() :  mService = null. Returning STATE_OFF
D/BluetoothAdapter(  605): 741632288: getState() :  mService = null. Returning STATE_OFF

This messages comes from following section of code,

/**
* Get the current state of the local Bluetooth adapter.
* <p>Possible return values are
* {@link #STATE_OFF},
* {@link #STATE_TURNING_ON},
* {@link #STATE_ON},
* {@link #STATE_TURNING_OFF}.
* <p>Requires {@link android.Manifest.permission#BLUETOOTH}
*
* @return current state of Bluetooth adapter
*/
public int getState() {
try {
synchronized(mManagerCallback) {
if (mService != null)
{
int state=  mService.getState();
if (VDBG) Log.d(TAG, “” + hashCode() + “: getState(). Returning ” + state);
return state;
}
// TODO(BT) there might be a small gap during STATE_TURNING_ON that
//          mService is null, handle that case
}
} catch (RemoteException e) {Log.e(TAG, “”, e);}
        if (DBG) Log.d(TAG, “” + hashCode() + “: getState() :  mService = null. Returning STATE_OFF”);
return STATE_OFF;
}

==============================================================

User Interface & Control of Bluetooth :

All Bluetooth user control things are defined in below files,

( Managing System UI, http://developer.android.com/training/system-ui/index.html & Refer https://developer.android.com/design/handhelds/index.html#system-bars )

./packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothController.java
./packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java
./packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothUtil.java
./packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java

base/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
base/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java
base/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java
base/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java

================================================================

./core/java/android/bluetooth/BluetoothHealthCallback.java
./core/java/android/bluetooth/BluetoothAudioConfig.java
./core/java/android/bluetooth/BluetoothGattServer.java
./core/java/android/bluetooth/BluetoothPan.java
./core/java/android/bluetooth/BluetoothA2dp.java
./core/java/android/bluetooth/IBluetoothInputDevice.aidl
./core/java/android/bluetooth/BluetoothUuid.java
./core/java/android/bluetooth/IBluetoothGattCallback.aidl
./core/java/android/bluetooth/BluetoothHealth.java
./core/java/android/bluetooth/BluetoothGattCallbackWrapper.java
./core/java/android/bluetooth/BluetoothHeadsetClient.java
./core/java/android/bluetooth/BluetoothAssignedNumbers.java
./core/java/android/bluetooth/IBluetoothCallback.aidl
./core/java/android/bluetooth/BluetoothGatt.java
./core/java/android/bluetooth/BluetoothMap.java
./core/java/android/bluetooth/BluetoothManager.java
./core/java/android/bluetooth/IBluetoothHealthCallback.aidl
./core/java/android/bluetooth/BluetoothGattService.java
./core/java/android/bluetooth/IBluetoothManagerCallback.aidl
./core/java/android/bluetooth/IBluetoothManager.aidl
./core/java/android/bluetooth/IBluetoothStateChangeCallback.aidl
./core/java/android/bluetooth/IBluetoothA2dp.aidl
./core/java/android/bluetooth/IBluetoothAvrcpController.aidl
./core/java/android/bluetooth/BluetoothPbap.java
./core/java/android/bluetooth/BluetoothInputDevice.java
./core/java/android/bluetooth/BluetoothHeadset.java
./core/java/android/bluetooth/le/BluetoothLeScanner.java
./core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
./core/java/android/bluetooth/le/BluetoothLeUtils.java
./core/java/android/bluetooth/IBluetoothHeadset.aidl
./core/java/android/bluetooth/BluetoothA2dpSink.java
./core/java/android/bluetooth/IBluetoothHeadsetPhone.aidl
./core/java/android/bluetooth/BluetoothHeadsetClientCall.aidl
./core/java/android/bluetooth/BluetoothHealthAppConfiguration.aidl
./core/java/android/bluetooth/IBluetoothA2dpSink.aidl
./core/java/android/bluetooth/IBluetoothPan.aidl
./core/java/android/bluetooth/BluetoothServerSocket.java
./core/java/android/bluetooth/BluetoothActivityEnergyInfo.aidl
./core/java/android/bluetooth/IBluetoothMap.aidl
./core/java/android/bluetooth/IBluetooth.aidl
./core/java/android/bluetooth/BluetoothDevice.java
./core/java/android/bluetooth/BluetoothClass.java
./core/java/android/bluetooth/IBluetoothHealth.aidl
./core/java/android/bluetooth/BluetoothOutputStream.java
./core/java/android/bluetooth/IBluetoothPbap.aidl
./core/java/android/bluetooth/IBluetoothGatt.aidl
./core/java/android/bluetooth/BluetoothAvrcpController.java
./core/java/android/bluetooth/BluetoothActivityEnergyInfo.java
./core/java/android/bluetooth/BluetoothInputStream.java
./core/java/android/bluetooth/BluetoothGattDescriptor.java
./core/java/android/bluetooth/BluetoothSocket.java
./core/java/android/bluetooth/BluetoothDevice.aidl
./core/java/android/bluetooth/BluetoothDevicePicker.java
./core/java/android/bluetooth/BluetoothMasInstance.java
./core/java/android/bluetooth/BluetoothProfile.java
./core/java/android/bluetooth/BluetoothAudioConfig.aidl
./core/java/android/bluetooth/BluetoothHealthAppConfiguration.java
./core/java/android/bluetooth/IBluetoothHeadsetClient.aidl

./core/java/android/bluetooth/BluetoothAvrcp.java
./core/java/android/bluetooth/BluetoothGattCharacteristic.java
./core/java/android/bluetooth/BluetoothGattServerCallback.java
./core/java/android/bluetooth/BluetoothHeadsetClientCall.java
./core/java/android/bluetooth/IBluetoothGattServerCallback.aidl
./core/java/android/bluetooth/BluetoothGattCallback.java

./core/tests/bluetoothtests/src/android/bluetooth/BluetoothStressTest.java
./core/tests/bluetoothtests/src/android/bluetooth/BluetoothTestUtils.java
./core/tests/bluetoothtests/src/android/bluetooth/BluetoothTestRunner.java
./core/tests/bluetoothtests/src/android/bluetooth/BluetoothInstrumentation.java
./core/tests/bluetoothtests/src/android/bluetooth/BluetoothRebootStressTest.java
./core/tests/bluetoothtests/src/android/bluetooth/BluetoothUuidTest.java

Leave a Reply

Your email address will not be published. Required fields are marked *