在Android framework中添加系统aidl服务供app调用

在Android framework中添加系统aidl服务供app调用

1.添加aidl服务,首先需要写一个.aidl文件,这里添加在framework/base/core/java/android/hardware下,新建一个ICopyCameraData.aidl文件,文件内容如下:

// ICopyCameraData.aidl
package android.hardware;

// Declare any non-default types here with import statements
import android.hardware.ICameraDataCallBack;
interface ICopyCameraData {
    /**
     * Demonstrates some basic types that you can use as parameters
     * and return values in AIDL.
     */
   byte[] onPreviewFrame();
   void setPreviewFrame(in byte[] data);
   void registerCallBack(ICameraDataCallBack callback);
	
   void unRegisterCallBack(ICameraDataCallBack callback);
}

因为在aidl中需要用到接口回调,所以还需要在同目录下新建一个ICameraDataCallBack.aidl文件,内容如下:

// ICopyCameraData.aidl
package android.hardware;

// Declare any non-default types here with import statements

interface ICameraDataCallBack {
    /**
     * Demonstrates some basic types that you can use as parameters
     * and return values in AIDL.
     */
   void setPreviewFrame(in byte[] data);
}

因为aidl用于进程间通信,所以在ICopyCameraData.aidl文件中的方法供服务器端使用,在ICameraDataCallBack.aidl文件中的方法供客户端调用。

2.在添加完文件之后,要在framework/base下的Android.mk中将新加的两个文件加入编译,这样才能自动编译出后边要用的java文件,按照之前在文件中已有的aidl样式添加即可(注意:在Android O以上,已经移到Android.bp中):

"core/java/android/hardware/ICopyCameraData.aidl",
"core/java/android/hardware/ICameraDataCallBack.aidl",

3.接下来就要编写需要添加的服务了,在framework/base/services/core/java/com/android/server下新加CameraDataService.java去实现刚写的.aidl文件中的方法:

package com.android.server;


import android.hardware.Camera;
import android.os.RemoteException;
import android.content.Context;
import android.hardware.ICopyCameraData;
import android.hardware.ICameraDataCallBack;
import android.util.Log;
import android.os.RemoteCallbackList;

public class CameraDataService extends ICopyCameraData.Stub {
    private byte[] mData;
    private RemoteCallbackList<ICameraDataCallBack> mRemoteCallbackList = new RemoteCallbackList<ICameraDataCallBack>();
    @Override
    public byte[] onPreviewFrame() throws RemoteException {
        return mData;
    }

    @Override
    public void setPreviewFrame(byte[] data) throws RemoteException {
            mData = data;
            final int len = mRemoteCallbackList.beginBroadcast();
            for(int i = 0; i < len; i++) {
                    ICameraDataCallBack mCallback = mRemoteCallbackList.getBroadcastItem(i);
                    if(mCallback!=null){
                       mCallback.setPreviewFrame(data);
                   }
            }
             mRemoteCallbackList.finishBroadcast();
    }

    @Override
    public void registerCallBack(ICameraDataCallBack callback) throws RemoteException {
          mRemoteCallbackList.register(callback);
          final int N=mRemoteCallbackList.beginBroadcast();
          Log.e("registerListener", "size:"+N);
          mRemoteCallbackList.finishBroadcast();
    }

    @Override
    public void unRegisterCallBack(ICameraDataCallBack callback) throws RemoteException {
         mRemoteCallbackList.unregister(callback);
         final int N=mRemoteCallbackList.beginBroadcast();
         Log.e("unregisterListener", "size:"+N);
         mRemoteCallbackList.finishBroadcast();
    }

    public CameraDataService(Context context){
    }   
}

首先这里的构造函数不能少,registerCallBack和unRegisterCallBack方法其实是固定的写法,就是将ICameraDataCallBack接口注册到服务中。setPreviewFrame()中的方法是可以自定义的,这里传递的是byte[]数组类型。

4.由于添加的是系统级别的服务,所以需要在系统启动的时候将这个服务启动起来,在framework/base/services/java/com/android/server中的SystemServer.java中的startOtherServices()方法中,添加刚才写服务:

CameraDataService cameraDataService = null;
try {
      cameraDataService = new CameraDataService(context);
      ServiceManager.addService("cameraDataService", cameraDataService);
} catch (Throwable e) {
      reportWtf("starting cameraDataService", e);
}

这样就将可以在开机的时候将自定义服务启动起来,但要注意,这个服务不要启动的太早。addService参数里的名称是可以随便起的,后边要用到。

5.添加系统服务是需要权限的,在system/sepolicy/service/下的service_contexts.te中按照文件的格式,在文件的末尾添加

cameraDataService                         u:object_r:cameradata_service:s0

这里的cameraDataService就是我们之前在SystemServer中起的服务名称,需要一致。
在system/sepolicy/service/下的service.te中按照文件的格式,在文件的末尾添加

type cameradata_service,            system_api_service, system_server_service, service_manager_type;

6.在添加完上边的权限之后,这时候服务已经可以注册到系统中了,但是在使用中还是需要一些SELinux权限,这里我还没有添加,先用adb shell setenforce 0调试。

7.这时的服务已经是一个正常的系统服务了,可以使用了。接下来是使用方法。在服务端我是在framework的camera.java中去传递一个应用获取到的camera数据给另外一个应用使用:
(1)首先获取服务:

       //bindRemoteService();
        copyCameraData = ICopyCameraData.Stub.asInterface(ServiceManager.getService("cameraDataService"));
        try{
           // copyCameraData.registerCallBack(mCameraDataCallBack);
            copyCameraData.asBinder().linkToDeath(mDeathRecipient, 0);
        }catch(Exception e){
        }

(2)在获取数据的地方,将数据传给服务:

             if(mPreviewCallback != null){
                    mPreviewCallback.onPreviewFrame(yuv,Camera.this);
                    try{
                        copyCameraData.setPreviewFrame(yuv);
                    }catch(Exception e){
                        e.printStackTrace();
                     }
                }

8.接着就是客户端,也就是app去调用服务获取数据了:
(1)获取服务,并注册回调

copyCameraData = ICopyCameraData.Stub.asInterface(ServiceManager.getService("cameraDataService"));
try{
    copyCameraData.registerCallBack(mCameraDataCallBack);
}catch(Exception e){}

(2)获取回调实例

 private ICameraDataCallBack mCameraDataCallBack=new ICameraDataCallBack.Stub() {
        @Override
        public void setPreviewFrame(byte[] data) throws RemoteException {
            try{
                Log.e("callback","setPreviewFrame"+data.length);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
};

(3)在应用销毁时取消注册服务:

 try{
     copyCameraData.unRegisterCallBack(mCameraDataCallBack);
 }catch(Exception e){
 }

至此服务添加完成。

  • 4
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值