Android系统学习(三)------编写Android代码访问服务框架

版权声明:本文为 风筝 博主原创文章,转载请署名出处!!谢谢合作。文章地址: https://blog.csdn.net/Guet_Kite/article/details/86649486

你好!这里是风筝的博客,

欢迎和我一起交流。


  以操作rk3399板子上的led为例,上手来写代码!
  先弄好环境变量:

source build/envsetup.sh 
lunch

(一)编写AIDL文件:
  编写ILedService.aidl来描述访问服务接口:

package android.os;

/** {@hide} */
interface ILedService
{
	int ledOpen();
	int ledCtrl(int status);
	int ledClose();
}
  1. 把 ILedService.aidl 放入 frameworks/base/core/java/android/os
  2. 修改 frameworks/base/Android.mk 添加一行 core/java/android/os/ILedService.aidl \
  3. 源代码顶层目录下 mmm frameworks/base

(二) 编写Server文件:
  1.编写LedService.java:

package com.android.server;
import android.os.ILedService;
//函数名字和aidl文件里一样
public class LedService extends ILedService.Stub {
    private static final String TAG = "LedService";

	/* call native c function to access hardware */
	public int ledOpen() throws android.os.RemoteException
	{
		return native_ledOpen();
	}
	public int ledCtrl(int status) throws android.os.RemoteException
	{
		return native_ledCtrl(status);
	}
	public int ledClose() throws android.os.RemoteException
	{
		return native_ledClose();
	}
	public LedService() {
		native_ledOpen();
	}

	public static native int native_ledOpen();
	public static native int native_ledClose();
	public static native int native_ledCtrl(int status);
}

2.将LedService.java上传到frameworks/base/services/core/java/com/android/server/
3.Sevice不需要修改 frameworks/base/services/core/Android.mk 它的内容里已经把该目录下所有JAVA文件自动包含进去了:
        LOCAL_SRC_FILES += \
                $(call all-java-files-under,java)

3.修改frameworks/base/services/java/com/android/server/SystemServer.java 找到startOtherServices方法,里面的try {}区域 ,添加如下:

traceBeginAndSlog("StartLedService");//仿照vibrator 
 /*vibrator = new LedService(context);*/ 
 ServiceManager.addService("led", new LedService());//添加上面的LedService
 Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);

(三) 编写HAL文件:
1.编写led_hal.c文件:

#define LOG_TAG "LedHal"

#include <hardware/vibrator.h>
#include <hardware/hardware.h>
#include <cutils/log.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <utils/Log.h>
#include <hardware/led_hal.h>

static int fd;
/** Close this device */
static int led_close(struct hw_device_t* device)
{
	int ret;
	
	ret = close(fd);
	ALOGI("led_demo_open : %d", ret);
	return ret;
}

static int led_open(struct led_device_t* dev)
{
	fd = open("/dev/led_demo", O_RDWR);//打开/dev下设备
	ALOGI("led_demo_open : %d", fd);
	if (fd >= 0)
		return 0;
	else
		return -1;
}

static int led_ctrl(struct led_device_t* dev, int status)
{
	int ret;

	ret = ioctl(fd, status, which);
	ALOGI("led_demo_ctrl : %d, %d",status, ret);
	return ret;
}

static struct led_device_t led_dev = {
	.common = {
		.tag   = HARDWARE_DEVICE_TAG,
		.close = led_close,
	},
	.led_open  = led_open,
	.led_ctrl  = led_ctrl,
};

static int led_device_open(const struct hw_module_t* module, const char* id,
        struct hw_device_t** device)
{
	*device = &led_dev;
	return 0;
}

static struct hw_module_methods_t led_module_methods = {
    .open = led_device_open,
};
//id:led_demo!!!
struct hw_module_t HAL_MODULE_INFO_SYM = {
	.tag = HARDWARE_MODULE_TAG,
    .id = "led_demo",
    .methods = &led_module_methods,
};

2.编写led_hal.h文件:

#ifndef ANDROID_LED_INTERFACE_H
#define ANDROID_LED_INTERFACE_H

#include <stdint.h>
#include <sys/cdefs.h>
#include <sys/types.h>

#include <hardware/hardware.h>

__BEGIN_DECLS

struct led_device_t {
    struct hw_device_t common;

	int (*led_open)(struct led_device_t* dev);
	int (*led_ctrl)(struct led_device_t* dev, int status);
};

__END_DECLS
#endif  // ANDROID_LED_INTERFACE_H

3.将led_hal.h 文件上传到hardware/libhardware/include/hardware/
在hardware/libhardware/modules/目录下新建led目录,并将led_hal.c文件长传到此led目录下。
4.在hardware/libhardware/modules/led/目录下编写Android.mk文件:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := led.default

# HAL module implementation stored in
# hw/<VIBRATOR_HARDWARE_MODULE_ID>.default.so
LOCAL_MODULE_RELATIVE_PATH := hw
LOCAL_C_INCLUDES := hardware/libhardware
LOCAL_SRC_FILES := led_hal.c
LOCAL_SHARED_LIBRARIES := liblog
LOCAL_MODULE_TAGS := optional

include $(BUILD_SHARED_LIBRARY)

5.源代码顶层目录下 mmm hardware/libhardware/modules/led

(四) 编写Service文件(JNI接口):
1.编写com_android_server_LedService.cpp文件:

#define LOG_TAG "LedService"

#include "jni.h"
#include "JNIHelp.h"
#include "android_runtime/AndroidRuntime.h"
#include <utils/misc.h>
#include <utils/Log.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <hardware/led_hal.h>

namespace android
{
static led_device_t* led_device;

jint ledOpen(JNIEnv *env, jobject cls)
{
	jint err;
    hw_module_t* module;
	hw_device_t* device;

	ALOGI("native ledOpen ...");

	/* 1. hw_get_module */
    err = hw_get_module("led_demo", (hw_module_t const**)&module);//和id匹配
    if (err == 0) {
		/* 2. get device : module->methods->open */
	    err = module->methods->open(module, NULL, &device);
	    if (err == 0) {
			/* 3. call led_open */
	        led_device = (led_device_t *)device;
			return led_device->led_open(led_device);
	    } else {
	        return -1;
    	}
    }
	
    return -1;	
}

jint ledClose(JNIEnv *env, jobject cls)
{
	ALOGI("native ledClose ...");
	return led_device->common.close(NULL);
}

jint ledCtrl(JNIEnv *env, jobject cls, jint status)
{
	ALOGI("native ledCtrl %d", status);
	return led_device->led_ctrl(led_device,  status);
}

static const JNINativeMethod methods[] = {
	{"native_ledOpen", "()I", (void *)ledOpen},
	{"native_ledClose", "()I", (void *)ledClose},
	{"native_ledCtrl", "(I)I", (void *)ledCtrl},
};
	
int register_android_server_LedService(JNIEnv *env)
{
    return jniRegisterNativeMethods(env, "com/android/server/LedService",
            methods, NELEM(methods));
}

}

2.将com_android_server_LedService.cpp文件上传到 frameworks/base/services/core/jni/目录
3.修改frameworks/base/services/core/jni/目录下的onload.cpp文件:
在namespace android {} 区域添加声明:

int register_android_server_LedService(JNIEnv *env);

在JNI_OnLoad函数里添加:

register_android_server_LedService(env);

4.修改 frameworks/base/services/core/jni/Android.mk ,LOCAL_SRC_FILES += \ 下面添加:

$(LOCAL_REL_DIR)/com_android_server_LedService.cpp \

5.源代码顶层目录下 mmm frameworks/base/services

(五) 生成映像文件:
1.在out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/目录下,取出 classes.jar 文件,编写Android APP代码时需要用到。
2.make snod 生成system.img映像文件。
3.执行nanopi m4的编译脚本:./build-nanopc-t4 -M,进行打包。

最后,从Android M开始,安卓源代码的默认编译器从javac改成了jack,这玩意还真不好用,而且如果不手动停止Jack Server,它还会在后台一直运行,占用内存不放,jack也不会生成中间件classes.jar了,真是麻烦啊。最后还是得执行./build-nanopc-t4 -a -M编译一下Android才看到classes.jar
APP可以参考韦老师的编写:https://github.com/weidongshan/APP_0001_LEDDemo/tree/v7

猜你喜欢

转载自blog.csdn.net/Guet_Kite/article/details/86649486