Rockchip系列之VendorStorage 新增framework系统jni+service接口访问(3)

简介: Rockchip系列之VendorStorage 新增framework系统jni+service接口访问(3)

Rockchip系列之VendorStorage 浅浅的介绍(1)-CSDN博客

Rockchip系列之VendorStorage uboot/kernel/user space 阶段接口使用介绍(2)_一歲抬頭的博客-CSDN博客

Rockchip系列之VendorStorage 新增framework系统jni+service接口访问(3)-CSDN博客

Rockchip系列之VendorStorage 新增framework封装VendorStorageManager访问(4)-CSDN博客

Rockchip 自定义vendorstorages数据再u-boot通过cmdline给kernel传递数据_一歲抬頭的博客-CSDN博客

本文主要介绍如何在Rockchip系列芯片中,使用JNI接口访问VendorStorage服务,并通过创建Android Service为应用提供这些访问接口。下面是一些核心的步骤。

1. 创建JNI接口

我在 com_android_server_VendorStorage_Service.cpp 文件中创建了两个JNI接口:native_vendor_readnative_vendor_write

  1. native_vendor_read:这个函数用于从VendorStorage中读取数据。首先,我打开 /dev/vendor_storage 设备文件,然后创建并初始化一个 rk_vendor_req 结构体,并设置其 tagidlen 字段。然后,我使用 ioctl 系统调用,调用 VENDOR_READ_IO 命令从VendorStorage读取数据。最后,我将读取到的数据转换为 jbyteArray 并返回。
  2. native_vendor_write:这个函数用于将数据写入VendorStorage。与 native_vendor_read 类似,我打开 /dev/vendor_storage 设备文件,并创建并初始化一个 rk_vendor_req 结构体。然后,我将待写入的数据从 jbyteArray 转换为 C 风格的数组,并设置到 rk_vendor_reqdata 字段。然后,我使用 ioctl 系统调用,调用 VENDOR_WRITE_IO 命令将数据写入VendorStorage。

我将这两个函数的声明添加到了一个 JNINativeMethod 数组中,然后在 register_com_android_server_VendorStorageService 函数中调用 jniRegisterNativeMethods 来注册这些本地方法。

// com_android_server_VendorStorage_Service.cpp
 
 
#include <jni.h>
#include <nativehelper/JNIHelp.h>
#include <android_runtime/AndroidRuntime.h>
#include <utils/misc.h>
#include <utils/Log.h>
#include <hardware/hardware.h>
#include <sys/ioctl.h>
 
// add some macro definitions from vendor_test.h
#define VENDOR_SN_ID        1
#define VENDOR_WIFI_MAC_ID      2
#define VENDOR_LAN_MAC_ID     3
#define VENDOR_BT_MAC_ID      4
#define VENDOR_HDCP_14_HDMI_ID      5
#define VENDOR_HDCP_14_DP_ID      6
#define VENDOR_HDCP_2x_ID     7
#define VENDOR_DRM_KEY_ID     8
#define VENDOR_PLAYREADY_Cert_ID    9
#define VENDOR_ATTENTION_KEY_ID     10
#define VENDOR_PLAYREADY_ROOT_KEY_0_ID    11
#define VENDOR_PLAYREADY_ROOT_KEY_1_ID    12
#define VENDOR_SENSOR_CALIBRATION_ID    13
#define VENDOR_IMEI_ID        15
#define VENDOR_CUSTOM_ID      16
#define EINK_VCOM_ID      17
//VENDOR_USER1和VENDOR_USER2是我自己新增的,默认是没有的,需要改内核。
#define VENDOR_USER1      18 
#define VENDOR_USER2      19
typedef   unsigned short      uint16;
typedef   unsigned int      uint32;
typedef   unsigned char     uint8;
 
#define VENDOR_MAX_SIZE   1024
#define VENDOR_REQ_TAG    0x56524551
#define VENDOR_READ_IO    _IOW('v', 0x01, (unsigned int)(0))
#define VENDOR_WRITE_IO   _IOW('v', 0x02, (unsigned int)(0))
 
#define VENDOR_ID_MAX 19
#define VENDOR_CMD_CUSTOM_LEN sizeof("VENDOR_CUSTOM_ID")
 
 
#define VENDOR_DEV "/dev/vendor_storage"
#define VENDOR_PR_HEX   0
#define VENDOR_PR_STRING  1
 
/* Set custom_id to hex print default */
#define GET_PR_FORMAT(ID, FORMAT) \
if ((ID) == VENDOR_IMEI_ID || (ID) == VENDOR_SN_ID) \
FORMAT = VENDOR_PR_STRING; \
else \
FORMAT = VENDOR_PR_HEX;
 
struct rk_vendor_req {
    uint32 tag;
    uint16 id;
    uint16 len;
    uint8 data[1024];
};
 
namespace android {
 
static jbyteArray native_vendor_read(JNIEnv *env, jobject clazz, jint vendor_id) {
    uint8 p_buf[sizeof(struct rk_vendor_req)];
    struct rk_vendor_req *req;
    req = (struct rk_vendor_req *)p_buf;
    memset(p_buf, 0, sizeof(p_buf));
 
    int sys_fd = open(VENDOR_DEV, O_RDWR, 0);
    if(sys_fd < 0){
        ALOGE("vendor_storage open fail\n");
        return NULL;
    }
 
    req->tag = VENDOR_REQ_TAG;
    req->id = vendor_id;
    req->len = VENDOR_MAX_SIZE;
 
    int ret = ioctl(sys_fd, VENDOR_READ_IO, req);
    close(sys_fd);
 
    if(ret){
        ALOGE("vendor read error %d\n", ret);
        return NULL;
    }
 
    jbyteArray result = env->NewByteArray(req->len);
    env->SetByteArrayRegion(result, 0, req->len, (jbyte*)req->data);
 
    return result;
}
 
static jint native_vendor_write(JNIEnv *env, jobject clazz, jint vendor_id, jbyteArray data) {
    uint8 p_buf[sizeof(struct rk_vendor_req)];
    struct rk_vendor_req *req;
    req = (struct rk_vendor_req *)p_buf;
 
    int sys_fd = open(VENDOR_DEV, O_RDWR, 0);
    if(sys_fd < 0){
        ALOGE("vendor_storage open fail\n");
        return -1;
    }
 
    req->tag = VENDOR_REQ_TAG;
    req->id = vendor_id;
    req->len = env->GetArrayLength(data);
    env->GetByteArrayRegion(data, 0, req->len, (jbyte*)req->data);
 
    int ret = ioctl(sys_fd, VENDOR_WRITE_IO, req);
    close(sys_fd);
 
        if(ret){
        ALOGE("vendor write error\n");
        return -1;
        }
 
        return 0;
        }
 
        static const JNINativeMethod gMethods[] = {
        /* name, signature, funcPtr */
        {"native_vendor_read", "(I)[B", (void*)native_vendor_read},
        {"native_vendor_write", "(I[B)I", (void*)native_vendor_write},
        };
 
        int register_com_android_server_VendorStorageService(JNIEnv* env)
    {
        return jniRegisterNativeMethods(env,
        "com/android/server/VendorStorageService",
        gMethods,
        NELEM(gMethods));
        }
 
}; // namespace android

2. 创建Android Service

我在 com.android.server 包下创建了一个名为 VendorStorageService 的类,这个类继承了 IVendorStorageManager.Stub,并实现了其中的方法。

VendorStorageService 类提供了两个方法:vendorStorageWritevendorStorageRead

  1. vendorStorageWrite:这个方法使用 native_vendor_write JNI方法将数据写入VendorStorage,之前我在JNI层已经实现了这个函数。
  2. vendorStorageRead:这个方法使用 native_vendor_read JNI方法从VendorStorage读取数据,这个函数同样已经在JNI层实现。

package android.xxxx;
 
//IVendorStorageManager.aidl
 
interface IVendorStorageManager {
 
 
    // Write data to vendor storage with a given vendor id
    int vendorStorageWrite(int vendor_id, in byte[] data) ;
 
    // Read data from vendor storage with a given vendor id
    byte[] vendorStorageRead(int vendor_id) ;
}
 
package com.android.server;
 
import android.os.IBinder;
import android.xxxx.IVendorStorageManager;
import android.os.RemoteException;
import android.util.Slog;
import android.content.Context;
import android.util.Log;
 
public class VendorStorageService extends IVendorStorageManager.Stub {
    private Context mContext;
 
    private void handleException(Exception e) {
        Log.e("VendorStorageService", "An exception occurred: " + e.getMessage(), e);
    }
 
 
    //private static native void native_init();
    private static native int  native_vendor_write(int id, byte[] buffer);
    private static native byte[] native_vendor_read(int id);
 
    // Constructor
    public VendorStorageService(Context context) {
        mContext = context;
        // Initialize the native library
        //native_init();
    }
 
    // Implement vendor storage write method
    @Override
    public int vendorStorageWrite(int vendor_id, byte[] data) throws RemoteException {
        if (data == null) {
            throw new NullPointerException("data is null");
        }
        if (data.length > 1024) {
            throw new IllegalArgumentException("data is too large");
        }
        return native_vendor_write(vendor_id, data);
    }
 
    // Implement vendor storage read method
    @Override
    public byte[] vendorStorageRead(int vendor_id) throws RemoteException {
        byte[] data = native_vendor_read(vendor_id);
        if (data == null) {
            return null;
        }
        byte[] result = new byte[data.length];
        System.arraycopy(data, 0, result, 0, data.length);
        return result;
    }
}

这样,我就创建了一个可以通过Java层访问VendorStorage的Android服务。用户可以通过绑定这个服务来访问VendorStorage。

3. 总结

通过这篇文章,我介绍了如何在Rockchip系列芯片中,使用JNI接口访问VendorStorage服务,并创建Android Service为应用提供这些接口。希望本文能帮助你更好地理解和使用VendorStorage。如果你有任何问题或者想法,欢迎在评论区留言。

相关文章
|
4月前
|
编译器 Linux PHP
【Azure App Service】为部署在App Service上的PHP应用开启JIT编译器
【Azure App Service】为部署在App Service上的PHP应用开启JIT编译器
|
7月前
|
存储 Java Android开发
Rockchip系列之UART 新增framework系统jni+service接口访问(2)
Rockchip系列之UART 新增framework系统jni+service接口访问(2)
65 1
|
7月前
|
Java Android开发 C++
Rockchip系列之CAN 新增framework系统jni接口访问(2)
Rockchip系列之CAN 新增framework系统jni接口访问(2)
67 3
|
7月前
|
安全 Java Android开发
Rockchip系列之客制化GPIO接口jni+service接口访问(4)
Rockchip系列之客制化GPIO接口jni+service接口访问(4)
60 0
|
7月前
|
存储 传感器 JSON
Rockchip系列之VendorStorage 新增framework封装VendorStorageManager访问(4)
Rockchip系列之VendorStorage 新增framework封装VendorStorageManager访问(4)
64 0
|
XML 数据可视化 程序员
(一).NET Core WebAPI集成Swagger做接口管理
什么是Swagger? Swagger 是一个规范且完整的框架,用于生成、描述、调用和可视化 RESTful 风格的 Web 服务。 Swagger 的目标是对 REST API 定义一个标准且和语言无关的接口,可以让人和计算机拥有无须访问源码、文档或网络流量监测就可以发现和理解服务的能力。当通过 Swagger 进行正确定义,用户可以理解远程服务并使用最少实现逻辑与远程服务进行交互。与为底层编程所实现的接口类似,Swagger 消除了调用服务时可能会有的猜测。 Swagger 有什么优势? 支持 API 自动生成同步的在线文档:使用 Swagger 后可以直接通过代码生成文档,不再需
(一).NET Core WebAPI集成Swagger做接口管理
|
3月前
|
安全
11-26>pe_xscan 改进 O10-Winsock LSP(Layered Service Provider)项的显示内容
11-26>pe_xscan 改进 O10-Winsock LSP(Layered Service Provider)项的显示内容
|
4月前
|
开发框架 .NET Docker
【Azure 应用服务】App Service .NET Core项目在Program.cs中自定义添加的logger.LogInformation,部署到App Service上后日志不显示Log Stream中的问题
【Azure 应用服务】App Service .NET Core项目在Program.cs中自定义添加的logger.LogInformation,部署到App Service上后日志不显示Log Stream中的问题
|
4月前
|
编解码 Java API
【Azure 媒体服务】记录使用Java调用Media Service API时候遇见的一些问题
【Azure 媒体服务】记录使用Java调用Media Service API时候遇见的一些问题
|
4月前
【Azure 应用服务】App Service 配置 Application Settings 访问Storage Account得到 could not be resolved: '*.file.core.windows.net'的报错。没有解析成对应中国区 Storage Account地址 *.file.core.chinacloudapi.cn
【Azure 应用服务】App Service 配置 Application Settings 访问Storage Account得到 could not be resolved: '*.file.core.windows.net'的报错。没有解析成对应中国区 Storage Account地址 *.file.core.chinacloudapi.cn