1,蓝牙协议/服务端的启动
上一篇文章中,分析了Bluetooth.apk启动过程,启动Bluetooth.apk时,一般启动了AdapterService这一对应的服务。查看package/app/Bluetooth的源码,里面主要是一些具体的协议,其中每一个协议对应一个具体的服务。那么,这些服务是何时以及如何启动的呢?
在android 5.1 中,打开蓝牙时,在AdapterService的setProfileServiceState中就会逐个启动支持的服务,方法如下:
private void setProfileServiceState(Class[] services, int state) {
if (state != BluetoothAdapter.STATE_ON && state != BluetoothAdapter.STATE_OFF) {
debugLog("setProfileServiceState() - Invalid state, leaving...");
return;
}
int expectedCurrentState= BluetoothAdapter.STATE_OFF;
int pendingState = BluetoothAdapter.STATE_TURNING_ON;
if (state == BluetoothAdapter.STATE_OFF) {
expectedCurrentState= BluetoothAdapter.STATE_ON;
pendingState = BluetoothAdapter.STATE_TURNING_OFF;
}
for (int i=0; i <services.length;i++) {
String serviceName = services[i].getName();
Integer serviceState = mProfileServicesState.get(serviceName);
if(serviceState != null && serviceState != expectedCurrentState) {
debugLog("setProfileServiceState() - Unable to "
+ (state == BluetoothAdapter.STATE_OFF ? "start" : "stop" )
+ " service " + serviceName
+ ". Invalid state: " + serviceState);
continue;
}
debugLog("setProfileServiceState() - "
+ (state == BluetoothAdapter.STATE_OFF ? "Stopping" : "Starting")
+ " service " + serviceName);
if (state == BluetoothAdapter.STATE_ON && mDisabledProfiles.contains(serviceName)) {
Log.i(TAG, "skipping " + serviceName + " (disabled)");
continue;
}
if (DBG) {
Log.w(TAG, (state == BluetoothAdapter.STATE_OFF? "Stopping" : "Starting" ) +" service " +
serviceName);
}
mProfileServicesState.put(serviceName,pendingState);
Intent intent = new Intent(this,services[i]);
intent.putExtra(EXTRA_ACTION,ACTION_SERVICE_STATE_CHANGED);
intent.putExtra(BluetoothAdapter.EXTRA_STATE,state);
intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
startService(intent);
}
}
但是在android 6.0 中,在打开蓝牙,最后调用AdapterService的
setGattProfileServiceState的仅仅启动GattService这一服务,紧接着的调用
BluetoothAdapter的enable方法, notifyUserAction方法最后会调用setProfileServiceState方法启动其他的服务,但是这样做好像意义不大。
public boolean enable() {
android.util.SeempLog.record(56);
int state = STATE_OFF;
if (isEnabled() == true){
if (DBG) Log.d(TAG, "enable(): BT is already enabled..!");
return true;
}
//Use service interface to get the exact state
if (mService != null) {
try {
state = mService.getState();
} catch (RemoteException e) {Log.e(TAG, "", e);}
}
if (state == BluetoothAdapter.STATE_BLE_ON) { // 蓝牙已经打开
Log.e(TAG, "BT is in BLE_ON State");
notifyUserAction(true); // 发出通知
return true;
}
try {
return mManagerService.enable();
} catch (RemoteException e) {Log.e(TAG, "", e);}
return false;
}
在android 6.0中,其他协议的服务启动我有些疑惑,到底在什么时候启动的呢?
请看下节。
2,设置里服务端的启动
在手机里面,这些服务应该都有获取,并且服务端和客户端已经绑定,那么代码在哪儿呢?
在这里android 5.1和android 6.0还是有些微小的区别,代码路径不一样,在android6.0 中,设置里面之外,还有一个文件夹,路径如下,
frameworks\base\packages\SettingsLib\src\com\android\settingslib\bluetooth
包含的文件:
基本上每一个profile文件就对应;而在android 5.1 中,这些文件都包含在
packages\apps\Settings\src\com\android\settings\bluetooth之中。其他的基本原理是完全一样的。
启动设置,打开蓝牙设置,设置里的协议客户端就会创建,然后启动服务端并且和服务端绑定在一起,流程图如下:
这里以PanProfile为例来说明, PanProfile的构造函数如下,
PanProfile(Context context) {
BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
adapter.getProfileProxy(context, new PanServiceListener(),
BluetoothProfile.PAN);
}
private BluetoothPan mService;
private boolean mIsProfileReady;
private final class PanServiceListener
implements BluetoothProfile.ServiceListener {
public void onServiceConnected(int profile, BluetoothProfile proxy) {
if (V) Log.d(TAG,"Bluetooth service connected");
mService = (BluetoothPan) proxy;
mIsProfileReady=true;
}
public void onServiceDisconnected(int profile) {
if (V) Log.d(TAG,"Bluetooth service disconnected");
mIsProfileReady=false;
}
}
private final BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
private BluetoothHeadsetClient mHfpClient = null;
private void enableHFP() {
mBluetoothAdapter.getProfileProxy(getApplicationContext(), new ServiceListener() {
public void onServiceConnected(int profile,BluetoothProfile proxy) {
if (profile == BluetoothProfile.HEADSET_CLIENT) {
android.util.Log.d("fang ", "init mBluetoothHeadset");
mHfpClient = (BluetoothHeadsetClient) proxy;
}
}
public void onServiceDisconnected(int profile) {
if (profile == BluetoothProfile.HEADSET_CLIENT) {
mHfpClient = null;
}
}
}, BluetoothProfile.HEADSET_CLIENT);
}
public boolean getProfileProxy(Context context, BluetoothProfile.ServiceListener listener,
int profile) {
if (context == null || listener == null) return false;
if (profile == BluetoothProfile.HEADSET) {
BluetoothHeadset headset = new BluetoothHeadset(context, listener);
return true;
} else if (profile == BluetoothProfile.A2DP) {
BluetoothA2dp a2dp = new BluetoothA2dp(context, listener);
return true;
} else if (profile == BluetoothProfile.A2DP_SINK) {
BluetoothA2dpSink a2dpSink = new BluetoothA2dpSink(context, listener);
return true;
} else if (profile == BluetoothProfile.AVRCP_CONTROLLER) {
BluetoothAvrcpController avrcp = new BluetoothAvrcpController(context, listener);
return true;
} else if (profile == BluetoothProfile.INPUT_DEVICE) {
BluetoothInputDevice iDev = new BluetoothInputDevice(context, listener);
return true;
} else if (profile == BluetoothProfile.PAN) {
BluetoothPan pan = new BluetoothPan(context, listener);
return true;
} else if (profile == BluetoothProfile.DUN) {
BluetoothDun dun = new BluetoothDun(context, listener);
return true;
} else if (profile == BluetoothProfile.HEALTH) {
BluetoothHealth health = new BluetoothHealth(context, listener);
return true;
} else if (profile == BluetoothProfile.MAP) {
BluetoothMap map = new BluetoothMap(context, listener);
return true;
} else if (profile == BluetoothProfile.HEADSET_CLIENT) {
BluetoothHeadsetClient headsetClient = new BluetoothHeadsetClient(context, listener);
return true;
} else if (profile == BluetoothProfile.SAP) {
BluetoothSap sap = new BluetoothSap(context, listener);
return true;
} else if (profile == BluetoothProfile.HID_DEVICE) {
BluetoothHidDevice hidd = new BluetoothHidDevice(context, listener);
return true;
} else {
return false;
}
}
BluetoothHeadsetClient(Context context, ServiceListener l) {
mContext = context;
mServiceListener = l;
mAdapter = BluetoothAdapter.getDefaultAdapter();
IBluetoothManager mgr = mAdapter.getBluetoothManager();
if (mgr != null) {
try {
mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
} catch (RemoteException e) {
Log.e(TAG,"",e);
}
}
doBind();
}
boolean doBind() {
Intent intent = new Intent(IBluetoothHeadsetClient.class.getName());
ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
intent.setComponent(comp);
if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
android.os.Process.myUserHandle())) {
Log.e(TAG, "Could not bind to Bluetooth Headset Client Service with " + intent);
return false;
}
return true;
}
<service
android:process="@string/process"
android:name = ".hfpclient.HeadsetClientService"
android:enabled="@bool/profile_supported_hfpclient">
<intent-filter>
<action android:name="android.bluetooth.IBluetoothHeadsetClient" />
</intent-filter>
</service>
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName className, IBinder service) {
if (DBG) Log.d(TAG, "Proxy object connected");
mService = IBluetoothHeadsetClient.Stub.asInterface(service);
if (mServiceListener != null) {
mServiceListener.onServiceConnected(BluetoothProfile.HEADSET_CLIENT,
BluetoothHeadsetClient.this);
}
}
@Override
public void onServiceDisconnected(ComponentName className) {
if (DBG) Log.d(TAG, "Proxy object disconnected");
mService = null;
if (mServiceListener != null) {
mServiceListener.onServiceDisconnected(BluetoothProfile.HEADSET_CLIENT);
}
}
};