一、添加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发送调用请求和数据。

NativeJavaNote
IBinderIBinder
IInterfaceIInterface
IXXXIXXXaidl文件定义
BBinderBinder通过JavaBBinder类作为桥梁
BpBinderBinderProxy通过JNI访问Native的实现
BnInterfaceN/A
BpInterfaceN/A
BnXXX Stubaidl工具自动生成server端
BpXXXProxyaidl工具自动生成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();
	    }
Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐