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

SHUFFLED :   How to fix : ERROR: do_package_qa: QA Issue: No GNU_HASH in the elf binary

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

Android Android Commands Android Java Applications Application Libraries Bash / Shell Scripts Bluetooth driver Build Frameworks Commands and Packages Core Kernel C Programs Development Environment Setup Documents / Books Errors & Failures File Systems Framebuffer / Display Driver git Go Language Programs Hardware Platforms Home Kernel & Device Drivers Kernel Booting and Porting Linux, OS Concepts and Networking Linux Device Drivers Linux Host, Ubuntu, SysAdmin Linux Kernel Linux Networking Middleware Libraries, HAL NDK / Middleware / HAL Network Driver OS Concepts PHP Procfs Filesystem Programming Languages RaspberryPi Scripting and Automation Search Engine Optimisation ( SEO ) Social Media Socurce Code Management ( SCM ) System Administration, Security Testing and Debugging Uncategorized Userspace Utilities Web design and development Wordpress Yocto / Bitbake / Openembedded

Leave a Reply