在Android 蓝牙(一) Bluetooth Settings 开启流程详解中第七步AdapterState.java--->OffState会调用到notifyAdapterStateChange()方法,我接着这个方法往下继续分析:
1.AdapterState.java--->notifyAdapterStateChange()
private void notifyAdapterStateChange(int newState) {
AdapterService adapterService = mAdapterService;
AdapterProperties adapterProperties = mAdapterProperties;
if ((adapterService == null) || (adapterProperties == null)) {
errorLog("notifyAdapterStateChange after cleanup:" + newState);
return;
}
int oldState = adapterProperties.getState();
adapterProperties.setState(newState);
infoLog("Bluetooth adapter state changed: " + oldState + "-> " + newState);
adapterService.updateAdapterState(oldState, newState);
}
2.AdapterService.java--->updateAdapterState()
void updateAdapterState(int prevState, int newState){
if (mCallbacks !=null) {
int n=mCallbacks.beginBroadcast();
debugLog("updateAdapterState() - Broadcasting state to " + n + " receivers.");
for (int i=0; i
3.BluetoothManagerService.java
BluetoothManagerService实现了这个回调方法,发送MESSAGE_BLUETOOTH_STATE_CHANGE信息
private final IBluetoothCallback mBluetoothCallback = new IBluetoothCallback.Stub() {
@Override
public void onBluetoothStateChange(int prevState, int newState) throws RemoteException {
Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_STATE_CHANGE,prevState,newState);
mHandler.sendMessage(msg);
}
};
接收MESSAGE_BLUETOOTH_STATE_CHANGE信息
private void bluetoothStateChangeHandler(int prevState, int newState) {
boolean isStandardBroadcast = true;
if (prevState == newState) { // No change. Nothing to do.
return;
}
// Notify all proxy objects first of adapter state change
if (newState == BluetoothAdapter.STATE_BLE_ON ||
newState == BluetoothAdapter.STATE_OFF) {
boolean intermediate_off = (prevState == BluetoothAdapter.STATE_TURNING_OFF
&& newState == BluetoothAdapter.STATE_BLE_ON);
if (newState == BluetoothAdapter.STATE_OFF) {
// If Bluetooth is off, send service down event to proxy objects, and unbind
if (DBG) Slog.d(TAG, "Bluetooth is complete send Service Down");
sendBluetoothServiceDownCallback();
unbindAndFinish();
sendBleStateChanged(prevState, newState);
// Don't broadcast as it has already been broadcast before
isStandardBroadcast = false;
} else if (!intermediate_off) {
// connect to GattService
if (DBG) Slog.d(TAG, "Bluetooth is in LE only mode");
if (mBluetoothGatt != null) {
if (DBG) Slog.d(TAG, "Calling BluetoothGattServiceUp");
onBluetoothGattServiceUp();
} else {
if (DBG) Slog.d(TAG, "Binding Bluetooth GATT service");
if (mContext.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_BLUETOOTH_LE)) {
Intent i = new Intent(IBluetoothGatt.class.getName());
doBind(i, mConnection, Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT, UserHandle.CURRENT);
}
}
sendBleStateChanged(prevState, newState);
//Don't broadcase this as std intent
isStandardBroadcast = false;
} else if (intermediate_off) {
if (DBG) Slog.d(TAG, "Intermediate off, back to LE only mode");
// For LE only mode, broadcast as is
sendBleStateChanged(prevState, newState);
sendBluetoothStateCallback(false); // BT is OFF for general users
// Broadcast as STATE_OFF
newState = BluetoothAdapter.STATE_OFF;
sendBrEdrDownCallback();
}
} else if (newState == BluetoothAdapter.STATE_ON) {
boolean isUp = (newState == BluetoothAdapter.STATE_ON);
// M: ALPS02962287: make sure mEnable true when BT on
mEnable = true;
sendBluetoothStateCallback(isUp);
sendBleStateChanged(prevState, newState);
} else if (newState == BluetoothAdapter.STATE_BLE_TURNING_ON ||
newState == BluetoothAdapter.STATE_BLE_TURNING_OFF ) {
sendBleStateChanged(prevState, newState);
isStandardBroadcast = false;
} else if (newState == BluetoothAdapter.STATE_TURNING_ON ||
newState == BluetoothAdapter.STATE_TURNING_OFF) {
sendBleStateChanged(prevState, newState);
}
if (isStandardBroadcast) {
if (prevState == BluetoothAdapter.STATE_BLE_ON) {
// Show prevState of BLE_ON as OFF to standard users
prevState = BluetoothAdapter.STATE_OFF;
}
//发送BluetoothAdapter.ACTION_STATE_CHANGED广播
Intent intent = new Intent(BluetoothAdapter.ACTION_STATE_CHANGED);
intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, prevState);
intent.putExtra(BluetoothAdapter.EXTRA_STATE, newState);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
mContext.sendBroadcastAsUser(intent, UserHandle.ALL, BLUETOOTH_PERM);
}
}
4.BluetoothEventManager.java注册接收BluetoothAdapter.ACTION_STATE_CHANGED
private class AdapterStateChangedHandler implements Handler {
public void onReceive(Context context, Intent intent,
BluetoothDevice device) {
int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE,
BluetoothAdapter.ERROR);
// update local profiles and get paired devices
mLocalAdapter.setBluetoothStateInt(state);
// send callback to update UI and possibly start scanning
synchronized (mCallbacks) {
for (BluetoothCallback callback : mCallbacks) {
//回调onBluetoothStateChanged方法
callback.onBluetoothStateChanged(state);
}
}
// Inform CachedDeviceManager that the adapter state has changed
mDeviceManager.onBluetoothStateChanged(state);
}
}
5.DeviceListPreferenceFragment implements BluetoothCallback,实现了onBluetoothStateChanged()方法
BluetoothSettings extends DeviceListPreferenceFragment,重写了onBluetoothStateChanged()方法,更新UI
@Override
public void onBluetoothStateChanged(int bluetoothState) {
super.onBluetoothStateChanged(bluetoothState);
updateContent(bluetoothState);
}
DevicePickerFragment 也继承了DeviceListPreferenceFragment,重写了onBluetoothStateChanged()方法,进行扫描的工作
@Override
public void onBluetoothStateChanged(int bluetoothState) {
super.onBluetoothStateChanged(bluetoothState);
if (bluetoothState == BluetoothAdapter.STATE_ON) {
enableScanning();
}
}
@VisibleForTesting
void enableScanning() {
// LocalBluetoothAdapter already handles repeated scan requests
//开始扫描
mLocalAdapter.startScanning(true);
mScanEnabled = true;
}
6.LocalBluetoothAdapter.java--->startScanning()
public void startScanning(boolean force) {
// Only start if we're not already scanning
if (!mAdapter.isDiscovering()) {
if (!force) {
// Don't scan more than frequently than SCAN_EXPIRATION_MS,
// unless forced
if (mLastScan + SCAN_EXPIRATION_MS > System.currentTimeMillis()) {
return;
}
// If we are playing music, don't scan unless forced.
A2dpProfile a2dp = mProfileManager.getA2dpProfile();
if (a2dp != null && a2dp.isA2dpPlaying()) {
return;
}
A2dpSinkProfile a2dpSink = mProfileManager.getA2dpSinkProfile();
if ((a2dpSink != null) && (a2dpSink.isA2dpPlaying())){
return;
}
}
if (mAdapter.startDiscovery()) {
mLastScan = System.currentTimeMillis();
}
}
}
7.BluetoothAdapter.java--->startDiscovery()
@RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
public boolean startDiscovery() {
if (getState() != STATE_ON) return false;
try {
mServiceLock.readLock().lock();
if (mService != null) return mService.startDiscovery();
} catch (RemoteException e) {
Log.e(TAG, "", e);
} finally {
mServiceLock.readLock().unlock();
}
return false;
}
8.AdapterService.java--->AdapterServiceBinder(内部类)--->startDiscovery()
public boolean startDiscovery() {
if (!Utils.checkCaller()) {
Log.w(TAG, "startDiscovery() - Not allowed for non-active user");
return false;
}
AdapterService service = getService();
if (service == null) return false;
return service.startDiscovery();
}
8.AdapterService.java--->startDiscovery()
boolean startDiscovery() {
debugLog("startDiscovery");
enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
"Need BLUETOOTH ADMIN permission");
//调到native方法了,进入JNI层
return startDiscoveryNative();
}
9.com_android_bluetooth_btservice_AdapterService.cpp--->startDiscoveryNative()
//开始扫描
static jboolean startDiscoveryNative(JNIEnv* env, jobject obj) {
ALOGV("%s", __func__);
if (!sBluetoothInterface) return JNI_FALSE;
int ret = sBluetoothInterface->start_discovery();
return (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
}
......
当kernel扫描结束后,又会通过JNI回到上层
static void device_found_callback(int num_properties,
bt_property_t* properties) {
CallbackEnv sCallbackEnv(__func__);
if (!sCallbackEnv.valid()) return;
ScopedLocalRef addr(sCallbackEnv.get(), NULL);
int addr_index;
for (int i = 0; i < num_properties; i++) {
if (properties[i].type == BT_PROPERTY_BDADDR) {
addr.reset(sCallbackEnv->NewByteArray(properties[i].len));
if (!addr.get()) {
ALOGE("Address is NULL (unable to allocate) in %s", __func__);
return;
}
sCallbackEnv->SetByteArrayRegion(addr.get(), 0, properties[i].len,
(jbyte*)properties[i].val);
addr_index = i;
}
}
if (!addr.get()) {
ALOGE("Address is NULL in %s", __func__);
return;
}
ALOGV("%s: Properties: %d, Address: %s", __func__, num_properties,
(const char*)properties[addr_index].val);
remote_device_properties_callback(BT_STATUS_SUCCESS,
(RawAddress*)properties[addr_index].val,
num_properties, properties);
sCallbackEnv->CallVoidMethod(sJniCallbacksObj, method_deviceFoundCallback,
addr.get());
}
10.RemoteDevices.java--->deviceFoundCallback()
将扫描到的设备,以广播的形式发送出去BluetoothDevice.ACTION_FOUND
void deviceFoundCallback(byte[] address) {
// The device properties are already registered - we can send the intent
// now
BluetoothDevice device = getDevice(address);
debugLog("deviceFoundCallback: Remote Address is:" + device);
DeviceProperties deviceProp = getDeviceProperties(device);
if (deviceProp == null) {
errorLog("Device Properties is null for Device:" + device);
return;
}
Intent intent = new Intent(BluetoothDevice.ACTION_FOUND);
intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
intent.putExtra(BluetoothDevice.EXTRA_CLASS,
new BluetoothClass(deviceProp.mBluetoothClass));
intent.putExtra(BluetoothDevice.EXTRA_RSSI, deviceProp.mRssi);
intent.putExtra(BluetoothDevice.EXTRA_NAME, deviceProp.mName);
mAdapterService.sendBroadcastMultiplePermissions(intent,
new String[] {AdapterService.BLUETOOTH_PERM,
android.Manifest.permission.ACCESS_COARSE_LOCATION});
}
BluetoothEventManager.java中注册接收BluetoothDevice.ACTION_FOUND
private class DeviceFoundHandler implements Handler {
public void onReceive(Context context, Intent intent,
BluetoothDevice device) {
short rssi = intent.getShortExtra(BluetoothDevice.EXTRA_RSSI, Short.MIN_VALUE);
BluetoothClass btClass = intent.getParcelableExtra(BluetoothDevice.EXTRA_CLASS);
String name = intent.getStringExtra(BluetoothDevice.EXTRA_NAME);
// TODO Pick up UUID. They should be available for 2.1 devices.
// Skip for now, there's a bluez problem and we are not getting uuids even for 2.1.
CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device);
if (cachedDevice == null) {
cachedDevice = mDeviceManager.addDevice(mLocalAdapter, mProfileManager, device);
Log.d(TAG, "DeviceFoundHandler created new CachedBluetoothDevice: "
+ cachedDevice);
}
cachedDevice.setRssi(rssi);
cachedDevice.setBtClass(btClass);
cachedDevice.setNewName(name);
cachedDevice.setJustDiscovered(true);
}
}
11.CachedBluetoothDeviceManager.java--->addDevice()
public CachedBluetoothDevice addDevice(LocalBluetoothAdapter adapter,
LocalBluetoothProfileManager profileManager,
BluetoothDevice device) {
CachedBluetoothDevice newDevice = new CachedBluetoothDevice(mContext, adapter,
profileManager, device);
synchronized (mCachedDevices) {
mCachedDevices.add(newDevice);
mBtManager.getEventManager().dispatchDeviceAdded(newDevice);
}
return newDevice;
}
12.BluetoothEventManager.java--->dispatchDeviceAdded()
void dispatchDeviceAdded(CachedBluetoothDevice cachedDevice) {
synchronized (mCallbacks) {
for (BluetoothCallback callback : mCallbacks) {
//又是熟悉的回调
callback.onDeviceAdded(cachedDevice);
}
}
}
13.DeviceListPreferenceFragment.java--->onDeviceAdded()
DeviceListPreferenceFragment实现了接口BluetoothCallback,到这里又回到了Settings中显示扫描的设备
@Override
public void onDeviceAdded(CachedBluetoothDevice cachedDevice) {
if (mDevicePreferenceMap.get(cachedDevice) != null) {
return;
}
// Prevent updates while the list shows one of the state messages
if (mLocalAdapter.getBluetoothState() != BluetoothAdapter.STATE_ON) return;
if (mFilter.matches(cachedDevice.getDevice())) {
createDevicePreference(cachedDevice);
}
}
void createDevicePreference(CachedBluetoothDevice cachedDevice) {
if (mDeviceListGroup == null) {
Log.w(TAG, "Trying to create a device preference before the list group/category "
+ "exists!");
return;
}
String key = cachedDevice.getDevice().getAddress();
BluetoothDevicePreference preference = (BluetoothDevicePreference) getCachedPreference(key);
if (preference == null) {
preference = new BluetoothDevicePreference(getPrefContext(), cachedDevice, this);
preference.setKey(key);
mDeviceListGroup.addPreference(preference);
} else {
// Tell the preference it is being re-used in case there is new info in the
// cached device.
preference.rebind();
}
initDevicePreference(preference);
mDevicePreferenceMap.put(cachedDevice, preference);
}