JNI开发二之访问设备节点,使用JNI+AIDL的方式

需求:客户自己的第三方apk要求能够控制上层读写控制亮度等级/以及控制指纹开关,对于上层app控制硬件设备模块,一般做法都是通过对设备模块生成的设备节点文件进行读写实现,经过查询,指纹模块相关的设备节点是 “/dev/switch_gpio”,接下来就是想办法通过JNI进行读写了
Android 版本:10.0

前言:为了第三方apk直接使用访问设备节点,这里采用aidl +JNI的形式开发,采用aidl是为了自定义一个service manger,生成相应的jar包提供给apk,JNI的目的是为了JAVA层与C通信,在C中可以以C语言进行IO流读写
修改部分:

modified: device/mediatek/sepolicy/bsp/non_plat/device.te
modified: device/mediatek/sepolicy/bsp/non_plat/file_contexts
modified: device/mediatek/sepolicy/bsp/plat_private/service.te
modified: device/mediatek/sepolicy/bsp/plat_private/service_contexts
modified: device/mediatek/sepolicy/bsp/plat_private/system_server.te
modified: frameworks/base/Android.bp

modified: frameworks/base/core/java/android/app/SystemServiceRegistry.java
modified: frameworks/base/services/core/jni/Android.bp
modified: frameworks/base/services/core/jni/onload.cpp
modified: frameworks/base/services/java/com/android/server/SystemServer.java
modified: vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/display/ScreenshotButtonPreferenceController.java

+frameworks/base/core/java/android/app/SelfManager.java
+frameworks/base/core/java/android/os/ISelfManager.aidl
+frameworks/base/services/core/java/com/android/server/SelfManagerService.java
+frameworks/base/services/core/jni/com_android_server_SelfManagerService.cpp

一:aidl部分相应修改
1.自定义一个aidl文件
frameworks/base/core/java/android/os/ISelfManager.aidl

package android.os;
interface ISelfManager {

int readBrightness();

void writeBrightness(int level);

}

frameworks/base/services/core/java/com/android/server/SelfManagerService.java
//继承ISelfManager.Stub并重写其中的方法
package com.android.server;
import android.util.Log;
import android.os.ISelfManager;
public class SelfManagerService extends ISelfManager.Stub {
@Override
public int readBrightness() {
int result = tngpio_read();
Log.e(“zhy”, “read=” + result);
return result;
}

@Override
public void writeBrightness(int level) {
Log.e(“zhy”, “write:” + level);
tngpio_write(level);
}

private static native int tngpio_read();//本地接口
private static native void tngpio_write(int level);//本地接口

}

frameworks/base/core/java/android/app/SelfManager.java
//创建服务管理类,用于管理相应的接口方法可通过Context.getServcie()获取, 类似系统中的ActivityManager,MessageManager…

package android.app;

import android.util.Log;
import android.os.ISelfManager;
import android.content.Context;
import android.os.RemoteException;

/**

  • Interact with the overall activities running in the system.
    */
    public class SelfManager {
    private static String TAG = “SelfManager”;

    ISelfManager mSelfManager;

    public SelfManager(Context ctx,ISelfManager selfManager) {
    mSelfManager = selfManager;
    }

    public int readBrightness() throws RemoteException {

     return mSelfManager.readBrightness();
    

    }

    public void writeBrightness(int level) throws RemoteException {
    mSelfManager.writeBrightness(level);
    }
    }

4.将aidl文件添加到makefile中
— a/frameworks/base/Android.bp
+++ b/frameworks/base/Android.bp
@@ -263,6 +263,7 @@ java_defaults {
“core/java/android/os/IRecoverySystem.aidl”,
“core/java/android/os/IRecoverySystemProgressListener.aidl”,
“core/java/android/os/IRemoteCallback.aidl”,

  • “core/java/android/os/ISelfManager.aidl”,
    “core/java/android/os/ISchedulingPolicyService.aidl”,
    “:statsd_aidl”,
    “core/java/android/os/ISystemUpdateManager.aidl”,

5.注册系统服务,后面framework层可通过Context.getService()形式获取
— a/frameworks/base/core/java/android/app/SystemServiceRegistry.java
+++ b/frameworks/base/core/java/android/app/SystemServiceRegistry.java
@@ -204,6 +204,8 @@ import java.lang.reflect.Method;

import java.util.concurrent.atomic.AtomicInteger;

+import android.os.ISelfManager;
+
/**

  • Manages all of the system services that can be returned by {@link Context#getSystemService}.
  • Used by {@link ContextImpl}.
    @@ -613,7 +615,18 @@ public final class SystemServiceRegistry {
    ISystemUpdateManager service = ISystemUpdateManager.Stub.asInterface(b);
    return new SystemUpdateManager(service);
    }});
  • registerService(“selfservice”, SelfManager.class,
  • new CachedServiceFetcher() {
  • @Override
  • public SelfManager createService(ContextImpl ctx) {
  • IBinder b = ServiceManager.getService(“selfservice”);
  • ISelfManager service = ISelfManager.Stub.asInterface(b);
  • return new SelfManager(ctx,service);
  • }});
  •    registerService(Context.TELEPHONY_SERVICE, TelephonyManager.class,
               new CachedServiceFetcher() {
           @Override
    

6.将自定义系统服务SelfManagerService 无法加入加ServiceManager,加入到SystemServer开机将会启动
— a/frameworks/base/services/java/com/android/server/SystemServer.java
+++ b/frameworks/base/services/java/com/android/server/SystemServer.java
@@ -990,6 +990,12 @@ public final class SystemServer {
mSystemServiceManager.startService(KeyChainSystemService.class);
traceEnd();

  • //kzh add start

  • ServiceManager.addService(“selfservice”, new SelfManagerService());

  • //end

           traceBeginAndSlog("StartSchedulingPolicyService");
           ServiceManager.addService("scheduling_policy", new SchedulingPolicyService());
           traceEnd();
    

7.android具有selinux机制,不允许自定义的SystemServer被访问。所以得先添加自定义的SystemServer
(1)添加service
— a/device/mediatek/sepolicy/bsp/plat_private/service_contexts
+++ b/device/mediatek/sepolicy/bsp/plat_private/service_contexts
@@ -59,3 +59,5 @@ vendor.trustonic.teeregistryservice.ITeeRegistryService u:object_r:teeregist

#camerapostalgo
mediatek.campostalgo u:object_r:camerapostalgo_service:s0
+
+selfservice u:object_r:self_service:s0

(2)指定服务类型
— a/device/mediatek/sepolicy/bsp/plat_private/service.te
+++ b/device/mediatek/sepolicy/bsp/plat_private/service.te
@@ -7,3 +7,4 @@ type aal_service, service_manager_type;
type mtk_connmetrics_service, service_manager_type;
type terservice_service, service_manager_type;
type camerapostalgo_service, service_manager_type;
+type self_service, app_api_service, system_api_service, system_server_service, service_manager_type;
至此aidl部分已经添加完成,第三方apk可以调用和使用自定义的SelfManager 了。

二 :JNI部分修改
1.添加c文件,com_android_server_SelfManagerService.cpp,文件命名是有原因的,是因为我们的本地接口在com/android/server/SelfManagerService.java中,所以我们这样命名
frameworks/base/services/core/jni/com_android_server_SelfManagerService.cpp:
#define LOG_TAG “zhy”

#include “jni.h”
#include
#include “android_runtime/AndroidRuntime.h”
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

//方法在驱动中生成的节点
#define DEV_NAME “/dev/switch_gpio”

namespace android
{
static jint com_android_server_SelfManagerService_tngpio_read (JNIEnv* env, jobject clazz)
{
FILE *fp = NULL;
fp = fopen(DEV_NAME, “w+”);
char buff[255];
fgets(buff, 255, fp);
fclose(fp);
return atoi(buff);
}

static void com_android_server_SelfManagerService_tngpio_write (JNIEnv* env, jobject clazz, int level)
{ 
ALOGE("tngpio_write level= %d", level);
FILE *fp = NULL;
fp = fopen(DEV_NAME, "w+");
char str[255];
sprintf(str,"%d",level);
fputs(str,fp);
fclose(fp);
}

/Java本地接口方法表/
static JNINativeMethod method_table[] = {
{ “tngpio_read”, “()I”, (void*)com_android_server_SelfManagerService_tngpio_read },
{ “tngpio_write”, “(I)V”, (void*)com_android_server_SelfManagerService_tngpio_write }
};

/注册Java本地接口方法/
int register_android_server_SelfManagerService(JNIEnv *env)
{
return jniRegisterNativeMethods(env, “com/android/server/SelfManagerService”,
method_table, NELEM(method_table));
}
};

2.将.cpp文件添加到makefile中
— a/frameworks/base/services/core/jni/Android.bp
+++ b/frameworks/base/services/core/jni/Android.bp
@@ -52,6 +52,7 @@ cc_library_static {
“com_android_server_GraphicsStatsService.cpp”,
“com_android_server_am_AppCompactor.cpp”,
“com_android_server_am_LowMemDetector.cpp”,

  • “com_android_server_SelfManagerService.cpp”,
    “onload.cpp”,
    “:lib_networkStatsFactory_native”,
    ],
  1. 这部分应该是为了注册,用于查询匹配
    — a/frameworks/base/services/core/jni/onload.cpp
    +++ b/frameworks/base/services/core/jni/onload.cpp
    @@ -57,6 +57,7 @@ int register_android_server_net_NetworkStatsService(JNIEnv* env);
    int register_android_server_security_VerityUtils(JNIEnv* env);
    int register_android_server_am_AppCompactor(JNIEnv* env);
    int register_android_server_am_LowMemDetector(JNIEnv* env);
    +int register_android_server_SelfManagerService(JNIEnv* env);
    };

using namespace android;
@@ -107,5 +108,6 @@ extern “C” jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
register_android_server_security_VerityUtils(env);
register_android_server_am_AppCompactor(env);
register_android_server_am_LowMemDetector(env);

  • register_android_server_SelfManagerService(env);
    return JNI_VERSION_1_4;
    }
    到这里JNI部分也是添加完成

三:编译验证结果
make之前需要make update-api,
在settings中通过一个switch开关切换操作
发现设备卡死然后自动重启,通过查询log得知
报selinux错误:
05-20 12:53:31.612 915 915 W Binder:915_D: type=1400 audit(0.0:126): avc: denied { read write } for name=“switch_gpio” dev=“tmpfs” ino=10853 scontext=u:r:system_server:s0 tcontext=u:object_r:device:s0 tclass=chr_file permissive=0
Android app对/dev下的设备是不具有读写权限的,应用程序怎样才能读写/dev下设备呢?

— a/device/mediateksample/tb8766p1_64_bsp/init.project.rc

+++ b/device/mediateksample/tb8766p1_64_bsp/init.project.rc

@@ -9,6 +9,10 @@ on init

on post-fs-data

chmod 0666 sys/devices/platform/1000b000.pinctrl/mt_gpio

  • chmod 0666 /dev/switch_gpio

  • chown root system /dev/switch_gpio

#Camera

 chmod 0660 /dev/MAINAF

2.添加设备

— a/device/mediatek/sepolicy/bsp/non_plat/file_contexts

+++ b/device/mediatek/sepolicy/bsp/non_plat/file_contexts

@@ -74,6 +74,8 @@

/dev/socket/wo_epdg_ipsec(/.*)? u:object_r:wo_epdg_ipsec_socket:s0

/dev/ttyC5 u:object_r:nwkopt_device:s0

/dev/mix_event u:object_r:tx_device:s0

+/dev/switch_gpio u:object_r:switch_gpio_device:s0

3.指定设备类型

— a/device/mediatek/sepolicy/bsp/non_plat/device.te

+++ b/device/mediatek/sepolicy/bsp/non_plat/device.te

@@ -24,8 +24,7 @@ allow system_server teei_client_device:chr_file r_file_perms;

Purpose : Add permission for nwk

type nwkopt_device, dev_type;

type tx_device, dev_type;

-# add for usb switch

+type switch_gpio_device, dev_type;

4.添加权限,允许system_server 对该switch_gpio_device设备进行读写权限

— a/device/mediatek/sepolicy/bsp/non_plat/device.te

+++ b/device/mediatek/sepolicy/bsp/non_plat/device.te

@@ -24,8 +24,7 @@ allow system_server teei_client_device:chr_file r_file_perms;

Purpose : Add permission for nwk

type nwkopt_device, dev_type;

type tx_device, dev_type;

type switch_gpio_device, dev_type;

+allow system_server switch_gpio_device:chr_file rw_file_perms;

最后验证ok

你可能感兴趣的:(JNI开发二之访问设备节点,使用JNI+AIDL的方式)