说说aidl
Android系统中的进程之间不能共享内存,因此,需要提供一些机制在不同进程之间进行数据通信。
为了使其他的应用程序也可以访问本应用程序提供的服务,Android系统采用了远程过程调用(Remote Procedure Call,RPC)方式来实现。与很多其他的基于RPC的解决方案一样,Android使用一种接口定义语言(Interface Definition Language,IDL)来公开服务的接口。我们知道4个Android应用程序组件中的3个(Activity、BroadcastReceiver和ContentProvider)都可以进行跨进程访问,另外一个Android应用程序组件Service同样可以。因此,可以将这种可以跨进程访问的服务称为AIDL(Android Interface Definition Language)服务。
一个C/S框架,后台跑应用,前端调接口,就像linux Bluez后台跑bluetoothd的proxy org.bluez.xxx,android还是bluez,后台跑应用,前端来操控,类似AMS,am start xxx
自己写个aidl实例试一下
Mainactivity
public class MainActivity extends AppCompatActivity {
private IMyAidlInterface myAidlInterface;
private String name1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent(MainActivity.this,MyService.class);
startService(intent);
doBind();
}
private ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
myAidlInterface = IMyAidlInterface.Stub.asInterface(service);
final TextView oneView=(TextView)findViewById(R.id.textView3);
if(myAidlInterface != null)
{
try {
name1 = myAidlInterface.getname();
oneView.setText("get interface success");
}catch (RemoteException e){
e.printStackTrace();
oneView.setText("get interface fail");
}
} else{
oneView.setText("bind aidl success");
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
private boolean doBind(){
Intent intent = new Intent(MainActivity.this,MyService.class);
bindService(intent,conn,0);
return true;
}
public void onbind(View view) {
final TextView twoView = (TextView) findViewById(R.id.textView4);
twoView.setText(name1);
}
}
aidl interface
interface IMyAidlInterface {
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
double aDouble, String aString);
void setname(String name);
String getname();
}
service
public class MyService extends Service {
public String name = "interface getname print ok";
Binder mBinder = new IMyAidlInterface.Stub() {
@Override
public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {
}
@Override
public void setname(String name) throws RemoteException {
}
@Override
public String getname() throws RemoteException {
return name;
}
};
public MyService() {
}
public void onCreate(){
super.onCreate();
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
return mBinder;
}
public void setname(String name){
}
public String getname(){
return name;
}
}
测试效果
按按键可以调用service的接口,可以。
分析
测了一下, 一定要先startService(intent),才能Bind的到,这完全符合后台启动,前端再跑的玩法,就是这个意思,你不启动,接口不会实体化。
蓝牙aidl
framework==>aidl==>JNI==>BTIF==>BTM==>vendor(初始化和download fw)
package/app/Bluetooth的service后台部分,接口就是这个,放到GattService.java上去。
那framework是谁来Bind,BluetoothManagerService.java,BluetoothManagerService.java是Bind的地方,其它上层java就不说了,都要找它拿接口,拿到aidl上的接口。
还需要service启动
profile service 后台启动
调到AdapterService,Adapter再去启动各个service.
760 @SuppressWarnings("rawtypes")
761 private void setGattProfileServiceState(Class[] services, int state) {
762 if (state != BluetoothAdapter.STATE_ON && state != BluetoothAdapter.STATE_OFF) {
763 Log.w(TAG,"setGattProfileServiceState(): invalid state...Leaving...");
764 return;
765 }
766
767 int expectedCurrentState= BluetoothAdapter.STATE_OFF;
768 int pendingState = BluetoothAdapter.STATE_TURNING_ON;
769
770 if (state == BluetoothAdapter.STATE_OFF) {
771 expectedCurrentState= BluetoothAdapter.STATE_ON;
772 pendingState = BluetoothAdapter.STATE_TURNING_OFF;
773 }
774
775 for (int i=0; i <services.length;i++) {
776 String serviceName = services[i].getName();
777 String simpleName = services[i].getSimpleName();
778
779 if (simpleName.equals("GattService")) {
780 Integer serviceState = mProfileServicesState.get(serviceName);
781
782 if(serviceState != null && serviceState != expectedCurrentState) {
783 debugLog("setProfileServiceState() - Unable to "
784 + (state == BluetoothAdapter.STATE_OFF ? "start" : "stop" )
785 + " service " + serviceName
786 + ". Invalid state: " + serviceState);
787 continue;
788 }
789 debugLog("setProfileServiceState() - "
790 + (state == BluetoothAdapter.STATE_OFF ? "Stopping" : "Starting")
791 + " service " + serviceName);
792
793 mProfileServicesState.put(serviceName,pendingState);
794 Intent intent = new Intent(this,services[i]);
795 intent.putExtra(EXTRA_ACTION,ACTION_SERVICE_STATE_CHANGED);
796 intent.putExtra(BluetoothAdapter.EXTRA_STATE,state);
797 startService(intent);
798 return;
799 }
800 }
801 }
802
803
804 @SuppressWarnings("rawtypes")
"packages/apps/Bluetooth/src/com/android/bluetooth/btservice/AdapterService.java" 2555 lines --30%--
for (int i=0; i <services.length;i++) {
这里面有个for循环,就是一个一个打开service的,最后调用的是startService(intent);
profile service启动配置
Config.java去配置
是这个config.xml,但是要注意overlay,device会覆盖掉
最后就是在这里去配置打开运行的,很多时候,有些profile不想跑的时候,可以关闭