创建Service端
package com.android.server;
import android.app.ISimpleBinder;
import android.content.Context;
import android.os.IBinder;
import android.os.RemoteException;
/**
* Created by Albert on 2018/12/17.
*/
public class SimpleBinderService extends SystemService {
public SimpleBinderService(Context context) {
super(context);
}
@Override
public void onStart() {
publishBinderService(Context.SIMPLE_BINDER_SERVICE, mService);
}
private String replyToClient(String name) {
return "Nice to meet u, " + name;
}
private IBinder mService = new ISimpleBinder.Stub() {
@Override
public String replyToClient(String name) throws RemoteException {
return SimpleBinderService.this.replyToClient(name);
}
};
}
在Context中添加SIMPLE_BINDER_SERVICE服务名
public static final String SIMPLE_BINDER_SERVICE = "simple_binder";
注意这里没有hide,所以在整编之前需要 make update-api
编写客户端
package android.app.simplebinder;
import android.app.ISimpleBinder;
import android.content.Context;
import android.os.RemoteException;
/**
* Created by Albert on 2018/12/19.
*/
public class SimpleBinderManager {
private Context mContext;
private ISimpleBinder mService;
public SimpleBinderManager(Context context, ISimpleBinder service) {
mContext = context;
mService = service;
}
public String replyToClient(String name) {
try {
return mService.replyToClient(name);
} catch (RemoteException e) {
e.printStackTrace();
}
return "nothing reply";
}
}
在SystemServer中启动并注册到ServiceManager中
/**
* Starts a miscellaneous grab bag of stuff that has yet to be refactored
* and organized.
*/
private void startOtherServices() {
final Context context = mSystemContext;
......
traceBeginAndSlog("StartSimpleBinderService");
mSystemServiceManager.startService(SimpleBinderService.class);
traceEnd();
......
}
在SystemServiceRegistry中注册客户端
static {
registerService(Context.ACCESSIBILITY_SERVICE, AccessibilityManager.class,
new CachedServiceFetcher<AccessibilityManager>() {
@Override
public AccessibilityManager createService(ContextImpl ctx) {
return AccessibilityManager.getInstance(ctx);
}});
......
registerService(Context.SIMPLE_BINDER_SERVICE, SimpleBinderManager.class,
new CachedServiceFetcher<SimpleBinderManager>() {
@Override
public SimpleBinderManager createService(ContextImpl ctx) throws ServiceNotFoundException {
IBinder b = ServiceManager.getService(Context.SIMPLE_BINDER_SERVICE);
ISimpleBinder service = ISimpleBinder.Stub.asInterface(b);
if (service == null) {
Log.wtf(TAG, "failed to get simple binder service");
return null;
}
return new SimpleBinderManager(ctx, service);
}
});
......
}
添加seLinux权限
./bsp/plat_private/service_contexts:52:simple_binder u:object_r:simple_binder_service:s0
./bsp/prebuilts/api/26.0/plat_private/service_contexts:27:simple_binder u:object_r:simple_binder_service:s0
./bsp/prebuilts/api/26.0/plat_public/service.te:39:type simple_binder_service, app_api_service, system_server_service, service_manager_type;
./bsp/plat_public/service.te:45:type simple_binder_service, app_api_service, system_server_service, service_manager_type;
编译与测试
注意由于这里修改了seLinux权限,所以需要整编
测试应用如下
package com.example.android.simplebinder;
import android.app.Activity;
import android.app.simplebinder.SimpleBinderManager;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;
import com.example.android.helloactivity.R;
/**
* A minimal "Hello, World!" application.
*/
public class HelloActivity extends Activity {
private SimpleBinderManager mService;
/**
* Called with the activity is first created.
*/
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Set the layout for this activity. You can find it
// in res/layout/hello_activity.xml
View view = getLayoutInflater().inflate(R.layout.hello_activity, null);
setContentView(view);
mService = (SimpleBinderManager) getSystemService(Context.SIMPLE_BINDER_SERVICE);
}
public void onClick(View view) {
Toast.makeText(this, mService.replyToClient("jack" + ((int)Math.random()*5)), Toast.LENGTH_SHORT).show();
}
}
getSystemService如何获取客户端
这里主要说明ContextImpl中使用了一个客户端缓存,避免了重复创建客户端浪费资源,客户端具体的创建过程会在下章中讨论。
- 虚拟机加载SystemServiceRegistry时,会初始化一个保存CachedServiceFetcher的Hashmap
HashMap<String, ServiceFetcher<?>> SYSTEM_SERVICE_FETCHERS =new HashMap<String, ServiceFetcher<?>>();
2. 应用初始化自己的ContextImpl时会通过SystemServiceRegistry初始化一个缓存客户端的数组mServiceCache
// The system service cache for the system services that are cached per-ContextImpl.
final Object[] mServiceCache = SystemServiceRegistry.createServiceCache();
- 当使用
context.getSystemService(Context.SIMPLE_BINDER_SERVICE)
时会调用SystemServiceRegistry的getSystemService方法,如下:
/**
* Gets a system service from a given context.
*/
public static Object getSystemService(ContextImpl ctx, String name) {
// 获取service对应的fetcher
ServiceFetcher<?> fetcher = SYSTEM_SERVICE_FETCHERS.get(name);
// 使用fetcher获取客户端
return fetcher != null ? fetcher.getService(ctx) : null;
}
- fetcher获取客户端时分两步
- 通过ctx获取context中的客户端缓存
- 尝试从缓存中获取。获取成功,则返回客户端;否则创建客户端并保存到context的客户端缓存中并返回客户端。