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_read
和 native_vendor_write
。
native_vendor_read
:这个函数用于从VendorStorage中读取数据。首先,我打开/dev/vendor_storage
设备文件,然后创建并初始化一个rk_vendor_req
结构体,并设置其tag
,id
和len
字段。然后,我使用ioctl
系统调用,调用VENDOR_READ_IO
命令从VendorStorage读取数据。最后,我将读取到的数据转换为jbyteArray
并返回。native_vendor_write
:这个函数用于将数据写入VendorStorage。与native_vendor_read
类似,我打开/dev/vendor_storage
设备文件,并创建并初始化一个rk_vendor_req
结构体。然后,我将待写入的数据从jbyteArray
转换为 C 风格的数组,并设置到rk_vendor_req
的data
字段。然后,我使用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
类提供了两个方法:vendorStorageWrite
和 vendorStorageRead
。
vendorStorageWrite
:这个方法使用native_vendor_write
JNI方法将数据写入VendorStorage,之前我在JNI层已经实现了这个函数。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。如果你有任何问题或者想法,欢迎在评论区留言。