上一篇介绍了如何在android中制作kernel驱动,并在驱动中留下了dev和sys两种接口供应用程序调用。
Android11(RK3568)自定义服务制作(1)-Kernel驱动
一,驱动测试
可以先在external中创建一个hello的文件夹
里面创建以下两个文件。
Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE := hello
LOCAL_SRC_FILES := $(call all-subdir-c-files)
include $(BUILD_EXECUTABLE)
hello.c
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#define DEVICE_NAME "/dev/hello"
int main(int argc, char** argv)
{
int fd = -1;
int val = 0;
fd = open(DEVICE_NAME, O_RDWR);
if(fd == -1) {
printf("Failed to open device %s.\n", DEVICE_NAME);
return -1;
}
printf("Read original value:\n");
read(fd, &val, sizeof(val));
printf("%d.\n\n", val);
val = 5;
printf("Write value %d to %s.\n\n", val, DEVICE_NAME);
write(fd, &val, sizeof(val));
printf("Read the value again:\n");
read(fd, &val, sizeof(val));
printf("%d.\n\n", val);
close(fd);
return 0;
}
这两个是用来测试驱动是否挂载正确。如果驱动挂载OK的话,这里面应该会有对应的打印信息。
二,Service 接口制作
整个需要添加的文件较多,我仔细列了一个列表如下:
在frameworks/base/core/java/android/os中创建以下文件
IHelloService.aidl
package android.os;
/**
* @hide
*/
interface IHelloService {
void setVal(int val);
int getVal();
}
在frameworks/base/core/java/android/app下面创建HelloManager.java
/*
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.app;
import android.annotation.SdkConstant;
import android.annotation.SystemApi;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.RemoteException;
import android.os.IHelloService;
import android.util.Log;
public class HelloManager {
IHelloService mService;
public HelloManager(Context ctx,IHelloService service){
mService=service;
}
public void setVal(int value){
try{
mService.setVal(value);
}catch(Exception e){
Log.e("HelloManager",e.toString());
e.printStackTrace();
}
}
public int getVal(){
try{
return mService.getVal();
}catch(Exception e){
Log.e("HelloManager",e.toString());
e.printStackTrace();
}
return 0;
}
}
并在frameworks/base/core/java/android/app下面的SystemServiceRegistry.java中添加以下代码:
/*sommer.jiang 20211115,registerservice helloservice*/
registerService(Context.HELLO_SERVICE, HelloManager.class,
new CachedServiceFetcher<HelloManager>(){
@Override
public HelloManager createService(ContextImpl ctx) throws ServiceNotFoundException {
IBinder b = ServiceManager.getService(Context.HELLO_SERVICE);
IHelloService service = IHelloService.Stub.asInterface(b);
return new HelloManager(ctx, service);
}});
添加完注册后 请在frameworks/base/core/java/android/content/Context.java添加以下代码:
/*sommer.jiang 20140315 add for service hello*/
public static final String HELLO_SERVICE = "hello";
HELLO_SERVICE,
这些接口做完后,接下来必须在frameworks/base/Android.mk中添加以下内容:
core/java/android/os/IHelloService.aidl \
这样就完成了接口的定义,如果以后需要新的接口定义可以再到这里面来设置。
三,Service 层调用制作
接口添加完后,可以正式添加service了。
在frameworks/base/service/core/java/com/android/server/下添加以下内容:
HelloService.java
package com.android.server;
import android.content.Context;
import android.os.IHelloService;
import android.util.Slog;
public class HelloService extends IHelloService.Stub {
private static final String TAG = "HelloService";
HelloService() {
init_native();
}
public void setVal(int val) {
setVal_native(val);
}
public int getVal() {
return getVal_native();
}
private static native boolean init_native();
private static native void setVal_native(int val);
private static native int getVal_native();
};
在frameworks/base/service/core/jni/下添加以下内容:
新建com_android_server_HelloService.cpp文件,并在其中添加如下内容:
#define LOG_TAG "HelloService"
#include "jni.h"
#include "JNIHelp.h"
#include "android_runtime/AndroidRuntime.h"
#include <utils/misc.h>
#include <utils/Log.h>
#include <hardware/hardware.h>
#include <hardware/hello.h>
#include <stdio.h>
namespace android
{
/*在硬件抽象层中定义的硬件访问结构体,参考<hardware/hello.h>*/
struct hello_device_t* hello_device = NULL;
/*通过硬件抽象层定义的硬件访问接口设置硬件寄存器val的值*/
static void hello_setVal(JNIEnv* env, jobject clazz, jint value) {
int val = value;
ALOGI("Hello JNI: set value %d to device.", val);
if(!hello_device) {
ALOGI("Hello JNI: device is not open.");
return;
}
hello_device->set_val(hello_device, val);
}
/*通过硬件抽象层定义的硬件访问接口读取硬件寄存器val的值*/
static jint hello_getVal(JNIEnv* env, jobject clazz) {
int val = 0;
if(!hello_device) {
ALOGI("Hello JNI: device is not open.");
return val;
}
hello_device->get_val(hello_device, &val);
ALOGI("Hello JNI: get value %d from device.", val);
return val;
}
/*通过硬件抽象层定义的硬件模块打开接口打开硬件设备*/
static inline int hello_device_open(const hw_module_t* module, struct hello_device_t** device) {
return module->methods->open(module, HELLO_HARDWARE_MODULE_ID, (struct hw_device_t**)device);
}
/*通过硬件模块ID来加载指定的硬件抽象层模块并打开硬件*/
static jboolean hello_init(JNIEnv* env, jclass clazz) {
hello_module_t* module;
ALOGI("Hello JNI: initializing......");
if(hw_get_module(HELLO_HARDWARE_MODULE_ID, (const struct hw_module_t**)&module) == 0) {
ALOGI("Hello JNI: hello Stub found.");
if(hello_device_open(&(module->common), &hello_device) == 0) {
ALOGI("Hello JNI: hello device is open.");
return 0;
}
ALOGE("Hello JNI: failed to open hello device.");
return -1;
}
ALOGE("Hello JNI: failed to get hello stub module.");
return -1;
}
/*JNI方法表*/
static const JNINativeMethod method_table[] = {
{"init_native", "()Z", (void*)hello_init},
{"setVal_native", "(I)V", (void*)hello_setVal},
{"getVal_native", "()I", (void*)hello_getVal},
};
/*注册JNI方法*/
int register_android_server_HelloService(JNIEnv *env) {
return jniRegisterNativeMethods(env, "com/android/server/HelloService", method_table, NELEM(method_table));
}
};
在frameworks/base/service/core/jni/Android.mk下添加以下内容:
LOCAL_SRC_FILES += \
$(LOCAL_REL_DIR)/com_android_server_HelloService.cpp\
$(LOCAL_REL_DIR)/onload.cpp
在frameworks/base/service/core/jni/onload.cpp下添加以下内容:
namespace android {
//sommer.jiang,20211115,add hello jni
int register_android_server_HelloService(JNIEnv *env);
};
extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
{
//sommer.jiang,20211115,add hello jni
register_android_server_HelloService(env);
return JNI_VERSION_1_4;
}
最后必须在frameworks/base/service//java/com/android/server/SystemServer.java中添加如下功能
//sommer.jiang,20211115,add hello service
try {
Slog.i(TAG, "Hello Service");
ServiceManager.addService("hello", new HelloService());
} catch (Throwable e) {
Slog.e(TAG, "Failure starting Hello Service", e);
}
至此,所有的service功能都已经添加完毕。
添加完这些后,必须使用make update-api -j16来更新api接口。