android系统开发binder调用(C++和java相互调用)
一、添加java端系统service1.添加aidl文件在framework/base下面新建文件夹gateway/java/com/cns/android/gateway创建IGatewaySystemService.aidlpackage com.cns.android.gateway;import com.cns.android.gateway.IGatewayS...
一、添加java端系统service
1.添加aidl文件
- 在framework/base下面新建文件夹gateway/java/com/cns/android/gateway
创建IGatewaySystemService.aidl
package com.cns.android.gateway;
import com.cns.android.gateway.IGatewaySystemCallback;
/**
* {@hide}
*/
interface IGatewaySystemService {
//开启log
void beginLog();
//关闭log
void endLog();
//注册回调
void registerGatewaySystemCallbackCallback(IGatewaySystemCallback callback);
//解除注册
void unregisterGatewaySystemCallbackCallback(IGatewaySystemCallback callback);
}
- 创建回调aidl
package com.cns.android.gateway;
interface IGatewaySystemCallback{
}
- 创建Android.mk
把aidl文件添加到framework/base/Android.mk中(这是我的aidl路径,具体的改成自己的)
LOCAL_SRC_FILES += \
\***
../../vendor/cns_gateway_utils/aidl/com/cns/android/gateway/IGatewaySystemService.aidl \
../../vendor/cns_gateway_utils/aidl/com/cns/android/gateway/IGatewaySystemCallback.aidl \
编译framework/base/Android.mk
系统编译的时候,会在out目录下生成对应的IGatewaySystemService.java、IGatewaySystemCallback.java文件
- 修改build/make/core/pathmap.mk 不然会找不到可编译文件
FRAMEWORKS_BASE_SUBDIRS := \
$(addsuffix /java, \
core \
graphics \
***
gateway \
)
- 修改白名单whitelist,否则编译会报错,找不到类
build/core/tasks/check_boot_jars/package_whitelist.txt
有些系统得位置在build/make/core/tasks/check_boot_jars/package_whitelist.txt
#framework.jar下添加
com.cns.android.gateway
2.添加aidl实现类service
GatewaySystemService.java
package com.cns.android.gateway;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.os.RemoteException;
import android.provider.Settings;
import android.service.notification.StatusBarNotification;
import android.util.Log;
//集成binder
public class GatewaySystemService extends IGatewaySystemService.Stub{
private final String TAG = this.getClass().toString();
private Context mContext;
private final static String actionName = "com.cns.android.notemanager.NotificationMonitor";
private final static String packageName = "com.archermind.notemanager";
public GatewaySystemService(Context context){
this.mContext = context;
Log.d(TAG,"+++++++init GatewaySystemService+++++++++");
}
//开启log
public void beginLog(){
}
//关闭log
public void endLog(){
}
// //注册回调
public void registerGatewaySystemCallbackCallback(IGatewaySystemCallback callback){
}
//解除注册
public void unregisterGatewaySystemCallbackCallback(IGatewaySystemCallback callback){
}
}
系统service最终的实现在这个类里面
3.注册service
(1)frameworks/base/services/java/com/android/server/SystemServer.java的startOtherServices方法中添加注册服务方法
traceBeginAndSlog("StartGatewaySystemService");
try {
ServiceManager.addService(Context.GATEWAY_SYSTEM_SERVICE,
new GatewaySystemService(mSystemContext));
} catch (Throwable e) {
reportWtf("starting GatewaySystemService", e);
}
traceEnd();
(2)Context.GATEWAY_SYSTEM_SERVICE 是在Context中添加的常量
frameworks/base/core/java/android/content/Context.java
@SystemApi
public static final String GATEWAY_SYSTEM_SERVICE = "gateway_system_service";
4.添加manager类
app可以通过manager来调用binder Service
创建manager类
package com.cns.android.gateway;
import android.content.Context;
import android.os.RemoteException;
import android.util.Log;
public class GatewaySystemManager {
private final Context mContext;
private final String TAG = this.getClass().toString();
private IGatewaySystemService mService;
public GatewaySystemManager(Context context,IGatewaySystemService service) {
super();
mContext = context;
this.mService = service;
Log.d(TAG,"GatewaySystemManager init");
}
//开启log
public void beginLog(){
try {
mService.beginLog();
}catch (RemoteException ex){
ex.printStackTrace();
}
}
//关闭log
public void endLog(){
try {
mService.endLog();
}catch (RemoteException ex){
ex.printStackTrace();
}
}
//注册回调
public void registerGatewaySystemCallbackCallback(IGatewaySystemCallback callback){
try {
mService.registerGatewaySystemCallbackCallback(callback);
}catch (RemoteException ex){
ex.printStackTrace();
}
}
//解除注册
public void unregisterGatewaySystemCallbackCallback(IGatewaySystemCallback callback){
try {
mService.unregisterGatewaySystemCallbackCallback(callback);
}catch (RemoteException ex){
ex.printStackTrace();
}
}
}
在这里会去调用binder Service中的方法
5.注册manager
frameworks/base/core/java/android/app/SystemServiceRegistry.java中注册Manager
registerService(Context.GATEWAY_SYSTEM_SERVICE, GatewaySystemManager.class, new CachedServiceFetcher<GatewaySystemManager>() {
@Override
public GatewaySystemManager createService(ContextImpl ctx) throws ServiceNotFoundException {
IBinder b = ServiceManager.getServiceOrThrow(Context.GATEWAY_SYSTEM_SERVICE);
IGatewaySystemService service = IGatewaySystemService.Stub.asInterface(b);
return new GatewaySystemManager(ctx.getOuterContext(),service);
}
});
}
6.添加te规则
有可能添加的te权限跟原来的权限会冲突,所以需要在编译的时候根据错误修改
audit(1441759284.810:5): avc: denied { read } for pid=1494 comm="sdcard" name="0" dev="nandk" ino=245281 scontext=u:r:sdcardd:s0 tcontext=u:object_r:system_data_file:s0 tclass=dir permissive=0
scontext = u:r:sdcardd
tcontext= u:object_r:system_data_file:s0
tclass = dir
avc: denied { read }
在scontext所指的.te文件(例如sdcardd.te)中加入类似如下allowe内容:
allow sdcardd system_data_file:dir read;
修改scontext.te文件
allow scontext tcontext:tclass denied
要加入的权限很多时,可以用中括号,比如:
allow sdcardd system_data_file:dir { read write add_name create};
例子:
07-05 20:10:44.186 351-351/? E/SELinux: avc: denied { find } for service=gateway_system_service pid=10347 uid=10075 scontext=u:r:untrusted_app:s0:c512,c768 tcontext=u:object_r:gateway_system_service:s0 tclass=service_manager
scontext=u:r:untrusted_app
tcontext=u:object_r:gateway_system_service
tclass=service_manager
avc: denied { find }
根据公式,修改untrusted_app.te文件,
添加allow untrusted_app gateway_system_service:service_manager find
make installclean后重新编译,刷boot.img才会生效。
二、java实现client
1.通过Manager调用
在上面,注册了GatewaySystemService的Manager GatewaySystemManager
可以通过
GatewaySystemManager gatewaySystemManager = (GatewaySystemManager) mContext.getSystemService("gateway_system_service");//获取manager
调用manager方法,最终调用GatewaySystemService方法
gatewaySystemManager.beginLog();
2.通过Binder调用
IBinder b = ServiceManager.getService("gateway_system_service");
IGatewaySystemService service = IGatewaySystemService.Stub.asInterface(b);
service.beginLog();//直接调用
三、native实现Binder service
1.定义INotificationGatewayService.aidl
package android.notification;
import android.notification.INotificationGatewayCallback;
/**
* {@hide}
*/
interface INotificationGatewayService {
const String SERVICE_NAME = "notification_service";
/**
* new notification to linux
* param priority: [-2,2]. 2 is highest priority
* param isAction: set true,it is triggered and opened the detailed page
*/
void addNotification(String title, String content, String icon, String notificationid, String packageName, int priority,boolean isAction);
/**
* new popup to linux.
* param paramsJson: see specific doc
*/
void addPopup(String notificationid, String packageName, String icon, String paramsJson);
/**
* delete all notifications of certain app(app uninstall)
*/
void delAllNotification(String packageName);
/**
* register callback
*/
void registerNotificationCallback(INotificationGatewayCallback callback);
}
2.定义INotificationGatewayCallback.aidl
package android.notification;
interface INotificationGatewayCallback{
/**
* click event, android will receive and handle
*/
void onClickNotification(String notificationid);
/**
* delete notification
*/
void onDelNotification(String notificationid);
}
2.把aidl放进Android.mk文件中
LOCAL_SRC_FILES := \
INotificationGatewayCallback.aidl \
INotificationGatewayService.aidl \
NotificationBinderService.cpp \
main.cpp
这样会在out目录下编译出Bp和Bn
3.实现Service方法
(1)定义头文件NotificationBinderService.h
/*
* NotificationBinderService.h
*
* Created on: May 22, 2018
* Author: young
*/
#ifndef NOTIFICATIONBINDERSERVICE_HPP_
#define NOTIFICATIONBINDERSERVICE_HPP_
#include <android/notification/BnNotificationGatewayService.h>//调用编译自动生成的头文件
#include <android/notification/INotificationGatewayCallback.h>
using namespace android;
using namespace android::notification;
using namespace android::binder;
using namespace std;
namespace android {
namespace notification {
//继承BnNotificationGatewayService ,此文件是自动编译生成,可以通过locate BnNotificationGatewayService找到
//BnNotificationGatewayService 是Service,具体的方法都是在这个里面实现的
class NotificationBinderService: public BnNotificationGatewayService, public IBinder::DeathRecipient {
public:
NotificationBinderService();
~NotificationBinderService();
::android::binder::Status addNotification(const ::android::String16& title, const ::android::String16& content, const ::android::String16& icon, const ::android::String16& notificationid, const ::android::String16& packageName, int32_t priority, bool isAction) override;
::android::binder::Status addPopup(const ::android::String16& notificationid, const ::android::String16& packageName, const ::android::String16& icon, const ::android::String16& paramsJson) override;
::android::binder::Status delAllNotification(const ::android::String16& packageName) override;
::android::binder::Status registerNotificationCallback(const ::android::sp<::android::notification::INotificationGatewayCallback>& callback) override;
void onClickNotification(const ::android::String16& notificationid);
void onDelNotification(const ::android::String16& notificationid);
private:
NotificationBinderService(const NotificationBinderService&) = delete;
NotificationBinderService& operator=(const NotificationBinderService&) = delete;
void binderDied(const wp<IBinder>& who) override;
android::sp<android::notification::INotificationGatewayCallback> callback_;
std::mutex mutex_;
};
}
}
(2)定义具体的实现文件 NotificationBinderService.cpp
/*
* NotificationBinderService.cpp
*
* Created on: May 22, 2018
* Author: young
*/
#include "NotificationBinderService.h"
#include <binder/IPCThreadState.h>
#include <binder/Status.h>
namespace android {
namespace notification {
NotificationBinderService::NotificationBinderService() {
ALOGE("Notification>>NotificationBinderService");
}
NotificationBinderService::~NotificationBinderService() {
}
::android::binder::Status NotificationBinderService::addNotification(const ::android::String16& title, const ::android::String16& content, const ::android::String16& icon, const ::android::String16& notificationid, const ::android::String16& packageName, int32_t priority, bool isAction){
const char* retitle = android::String8(title).string();
char re1[strlen(retitle)] ;
strcpy(re1,retitle);
const char* reicon = android::String8(icon).string();
char re2[strlen(reicon)];
strcpy(re2,reicon);
const char* renotificationid = android::String8(notificationid).string();
char re3[strlen(renotificationid)];
strcpy(re3,renotificationid);
const char* repackageName = android::String8(packageName).string();
char re4[strlen(repackageName)];
strcpy(re4,repackageName);
ALOGE("Notification>>REQ_ADD_NOTIFICATION title:%s icon:%s notificationid:%s packageName:%s priority:%d isAction:%d",re1,re2,re3,re4,priority,isAction);
return binder::Status::ok();
}
::android::binder::Status NotificationBinderService::addPopup(const ::android::String16& notificationid, const ::android::String16& packageName, const ::android::String16& icon, const ::android::String16& paramsJson) {
ALOGE("Notification>>REQ_ADD_POPUP notificationid:%s packageName:%s icon:%s paramsJson:%s",notificationid.string(),packageName.string(),icon.string(),paramsJson.string());
return binder::Status::ok();
}
::android::binder::Status NotificationBinderService::delAllNotification(const ::android::String16& packageName){
ALOGE("Notification>>REQ_DEL_ALL packageName:%s",packageName.string());
return binder::Status::ok();
}
binder::Status NotificationBinderService::registerNotificationCallback(const ::android::sp<::android::notification::INotificationGatewayCallback>& callback) {
std::lock_guard < std::mutex > guard(mutex_);
if (callback_.get()) {
ALOGD("Notification>>Failed to register callback, already registered");
return binder::Status::fromStatusT(ALREADY_EXISTS);
}
ALOGD("Notification>>Success to register callback, already registered");
callback_ = callback;
IInterface::asBinder(callback_)->linkToDeath(this);
return binder::Status::ok();
}
//callback and pass on to binder client
void NotificationBinderService::onClickNotification(const ::android::String16& notificationid) {
if (!callback_.get()) {
ALOGD("Notification>>INotificationGatewayCallback callback_ is null notificationid:%s",notificationid.string());
return;
}
ALOGD("Notification>>onClickNotification");
binder::Status status = callback_->onClickNotification(notificationid);
}
void NotificationBinderService::onDelNotification(const ::android::String16& notificationid) {
if (!callback_.get()) {
ALOGD("Notification>>INotificationGatewayCallback callback_ is null notificationid:%s",notificationid.string());
return;
}
ALOGD("Notification>>onDelNotification");
binder::Status status = callback_->onDelNotification(notificationid);
}
void NotificationBinderService::binderDied(const wp<IBinder>& /* who */) {
std::lock_guard < std::mutex > guard(mutex_);
callback_ = nullptr;
}
}
}
(3)编译main.cpp方法,用来运行注册service
#include "NotificationBinderService.h"
int main(int argc, char **argv)
{
android::sp<ProcessState> proc(ProcessState::self());
android::sp<NotificationBinderService> server = new NotificationBinderService();
android::sp<android::IServiceManager> sm(android::defaultServiceManager());
android::status_t service_status = sm->addService(android::String16(INotificationGatewayService::SERVICE_NAME()), server, false);
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
return 0;
}
四、native 实现Binder client
int
main() {
android::sp<ProcessState> proc(ProcessState::self());
sp<IServiceManager> sm = defaultServiceManager();
sp<IBinder> binder = sm->getService(String16(INotificationGatewayService::SERVICE_NAME());
sp<INotificationBinderService> cs = interface_cast<INotificationBinderService>(binder);
cs->onClickNotification(String16("10"));//调用service里面的方法
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
return 0;
}
五、java client调用native service
这个跟二java实现client是一样的,
1.添加aidl文件
根据C++的aidl文件,同样的复制一份,放到android文件中编译,(注意这里的aidl文件一定要相同,否则在调用的时候会出现方法不统一而调用出错的问题)
我是aidl统一放到相同的位置,C++或者framework要调用的时候,都直接去引用就行了
根据一种方法,添加aidl到framework/base下的Android.mk中
LOCAL_SRC_FILES += \
***
../../vendor/cns_gateway_utils/aidl/com/cns/android/gateway/IGatewaySystemService.aidl \
../../vendor/cns_gateway_utils/aidl/com/cns/android/gateway/IGatewaySystemCallback.aidl \
编译framework/base/Android.mk
2.调用Service
IBinder notificationBinder = ServiceManager.getService("notificationservice");
INotificationGatewayService notificationGatewayService = INotificationGatewayService.Stub.asInterface(notificationBinder);
INotificationGatewayCallback notificationGatewayCallback callback = new NotificationGatewayCallback(context);
try {
notificationGatewayService.registerNotificationCallback(callback);
} catch (RemoteException e) {
e.printStackTrace();
}
六、native client调用java service
跟native client调用native service是一样的
sp<IServiceManager> sm = defaultServiceManager();
sp<IBinder> binder = sm->getService(String16(INotificationGatewayService::SERVICE_NAME());
sp<INotificationBinderService> cs = interface_cast<INotificationBinderService>(binder);
cs->onClickNotification(String16("10"));//调用service里面的方法
Binder 的学习已经接近尾声了,我们已经研究了Binder Driver, C/C++的实现,就差最后一个部分了,Binder在Java端的实现了。Java端的实现与Native端类似,我们用下面的表格和类图概括他们的关系
BpXXX、BnXXX同时实现一个接口IXXX。BpXXX主要是用来处理java层传下来的服务请求,然后通过transact将处理请求传给BnXXX(通过binder)。BpINTERFACE是client端的代理接口,BnINTERFACE是server端的代理接口。
BpBinder(Binder Proxy):主要功能是负责client向Bn发送调用请求的数据。它是client端binder通信的核心对象,通过调用transact函数,client就可以向Bn发送调用请求和数据。
Native | Java | Note |
---|---|---|
IBinder | IBinder | |
IInterface | IInterface | |
IXXX | IXXX | aidl文件定义 |
BBinder | Binder | 通过JavaBBinder类作为桥梁 |
BpBinder | BinderProxy | 通过JNI访问Native的实现 |
BnInterface | N/A | |
BpInterface | N/A | |
BnXXX Stub | aidl工具自动生成 | server端 |
BpXXX | Proxy | aidl工具自动生成client端 |
七、app调用java service
注意如果需要app调用到系统Manager或者Service的话,因为原生的sdk是没有我们新加的类的,所以我们需要用以下方法来获取系统Service
1.获取系统Manager GatewaySystemManager
GatewaySystemManager的包名是package com.cns.android.gateway;
所以,要在app下建立相同的包名和类名
在app中新建包package com.cns.android.gateway;
并且新建GatewaySystemManager方法
然后按照系统GatewaySystemManager方法 写入空方法
public GatewaySystemManager(Context context,IGatewaySystemService service) {
}
//开启log
public void beginLog(){
}
//关闭log
public void endLog(){
}
//注册回调
public void registerGatewaySystemCallbackCallback(IGatewaySystemCallback callback){
}
//解除注册
public void unregisterGatewaySystemCallbackCallback(IGatewaySystemCallback callback){
}
}
app会先去framework中找相应包名和类名的方法,并调用里面的方法
八、app调用native service
也是同样道理,需要复制一份aidl文件到app中,然后根据java 调用native service的方法
INotificationGatewayService notificationGatewayService = INotificationGatewayService.Stub.asInterface(notificationBinder);
INotificationGatewayCallback notificationGatewayCallback callback = new NotificationGatewayCallback(context);
try {
notificationGatewayService.registerNotificationCallback(callback);
} catch (RemoteException e) {
e.printStackTrace();
}
更多推荐
所有评论(0)