一、以增加ActionService为例,首先在framework层增加几个文件
1、frameworks/base/services/java/com/android/server/ActionService.java
2、frameworks/base/core/java/android/app/IActionManager.aidl
3、frameworks/base/core/java/android/app/ActionManager.java
4、frameworks/base/services/core/jni/com_android_server_ActionService.cpp
package com.android.server;
import android.app.ActionManager;
import android.app.IActionManager;
public class ActionService extends IActionManager.Stub {
private static native boolean init_native();
private static native void setIR_native(int val);
private static native void setLedColor_native(int val);
private static final String TAG = "ActionService";
private Context mContext;
private static boolean launcherHasStart = false;
public ActionService(Context context) {
mContext = context;
//Log.e(TAG, "I am handling ACTION_SERVICE init service. added by zs 20180517 for test start to register service");
}
@Override
public void init(){
init_native();
}
@Override
public void setIR(int status) {
setIR_native(status);
}
@Override
public void setLedColor(int status) {
//Log.i(TAG,"---------->>>>yxj add: call setLedColor()");
setLedColor_native(status);
}
}
/* //device/java/android/android/app/IAlarmManager.aidl
**
** Copyright 2006, 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.app.PendingIntent;
*/
/**
* System private API for talking with the action manager service.
*
* {@hide}
*/
interface IActionManager {
void init();
void setIR(int status);
void setLedColor(int status);
}
package android.app;
import android.content.Context;
import android.content.Intent;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.app.IActionManager;
import android.util.Log;
/**
* @hide
*/
public class ActionManager {
private static IActionManager mService;
private Context mContext;
private static final String TAG = "ActionManager";
ActionManager(Context context, IActionManager service) {
mService = service;
mContext = context;
}
/*
function: set IR on/off
parm:1 is on, 0 is off
*/
public void setIR(int status) {
try {
mService.setIR(status);
} catch (RemoteException ex) {
}
}
/*
function: set led color
parm:1 is blue color, 0 is red
*/
public void setLedColor(int status) {
try {
//Log.i(TAG, "--------->>>>yxj add: setLedColor = " + status);
mService.setLedColor(status);
} catch (RemoteException ex) {
}
}
}
#define LOG_TAG "ActionService"
#include "jni.h"
#include "JNIHelp.h"
#include "android_runtime/AndroidRuntime.h"
#include
#include
#include
#include
#include
namespace android
{
struct action_device_t* action_device = NULL;
static inline int action_device_open(const hw_module_t* module, struct action_device_t** device) {
return module->methods->open(module, ACTION_HARDWARE_MODULE_ID, (struct hw_device_t**)device);
}
static jboolean action_init(JNIEnv* env, jclass /* clazz */) {
action_module_t* module;
//ALOGI("------------->>>>yxj add: *action JNI: initializing......");
if(hw_get_module(ACTION_HARDWARE_MODULE_ID, (const struct hw_module_t**)&module) == 0) {
ALOGI("------------->>>>yxj add: action JNI: action Stub found.");
if(action_device_open(&(module->common), &action_device) == 0) {
ALOGI("------------->>>>yxj add: action JNI: action device is open.");
return 1;
}
ALOGE("------------->>>>yxj add: action JNI: failed to open action device.");
return 0;
}
ALOGE("------------->>>>yxj add: action JNI: failed to get action stub module.");
return 0;
}
static void set_IR(JNIEnv* env, jobject clazz, jint value) {
// int val = 0; //masked by zs 20180515
if(!action_device) {
ALOGI("------------->>>>yxj add: action JNI: device is not open.");
return ;
}
//ALOGI("------------->>>>yxj add: action JNI: set_IR to device location1.");
action_device->setIR(action_device, value);
// ALOGI("------------->>>>yxj add: action JNI: set_IR to device. location2");
}
static void set_led_color(JNIEnv* env, jobject clazz, jint value) {
//ALOGI("------------->>>>yxj add: action JNI: set value %d to device.", value);
if(!action_device) {
ALOGI("------------->>>>yxj add: action JNI: device is not open.");
return;
}
action_device->setLedColor(action_device, value);
}
/*JNI 方法表*/
static const JNINativeMethod method_table[] = {
{"init_native", "()Z", (void*)action_init},
{"setIR_native", "(I)V", (void*)set_IR},
{"setLedColor_native", "(I)V", (void*)set_led_color},
};
/*注册JNI 方法*/
int register_android_server_ActionService(JNIEnv *env) {
return jniRegisterNativeMethods(env, "com/android/server/ActionService", method_table, NELEM(method_table) );
}
};
二、注册与添加服务
1、在frameworks/base/services/core/jni/onload.cpp文件中的两个方法中分别添加:
int register_android_server_ActionService(JNIEnv* env);
register_android_server_ActionService(env);
2、在frameworks/base/services/java/com/android/server/SystemServer.java文件中startOtherServices()方法中添加
try {
ServiceManager.addService(Context.ACTION_SERVICE, new ActionService(context));
} catch (Throwable e) {
Slog.e(TAG, "Failure starting action Service", e);
}
3、frameworks/base/services/core/jni/Android.mk文件中增加:
$(LOCAL_REL_DIR)/com_android_server_ActionService.cpp \
4、frameworks/base/core/java/android/content/Context.java文件中增加:
public static final String ACTION_SERVICE = "action";
5、frameworks/base/core/java/android/app/SystemServiceRegistry.java文件增加
registerService(Context.ACTION_SERVICE, ActionManager.class,
new CachedServiceFetcher
@Override
public ActionManager createService(ContextImpl ctx) {
IBinder b = ServiceManager.getService(Context.ACTION_SERVICE);
IActionManager service = IActionManager.Stub.asInterface(b);
return new ActionManager(ctx.getOuterContext(), service);
}});
6、文件frameworks/base/Android.mk中增加
core/java/android/app/IActionManager.aidl \
7、文件device/rockchip/common/device.mk增加
PRODUCT_PACKAGES += action.default
三、底层相关修改:
1、添加文件hardware/libhardware/include/hardware/action.h
hardware/libhardware/modules/action/action.c
hardware/libhardware/modules/action/Android.mk
#ifndef ANDROID_action_INTERFACE_H
#define ANDROID_action_INTERFACE_H
#include
__BEGIN_DECLS
#define ACTION_HARDWARE_MODULE_ID "action"
struct action_module_t {
struct hw_module_t common;
};
struct action_device_t {
struct hw_device_t common;
int fd;
int (*setIR)(struct action_device_t* dev, int val);
int (*setLedColor)(struct action_device_t* dev, int val);
};
__END_DECLS
#endif
#define LOG_TAG "ActionHAL"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define MODULE_NAME "action"
#define MODULE_AUTHOR "action"
#define DEVICE_NAME "/dev/action_dev"
#define SET_AUDIO_SOUCE 1
#define SET_FM_FREQ 3
#define SET_FM_STATUS 5
#define SET_IR 7
#define SET_VOLUME 9
#define SET_LED_COLOR 11
#define SET_IR_BAND 13
#define SET_ENABLE_BACKLIGHT 15
#define SET_HMDI_RESET 17
static int action_device_open(const struct hw_module_t* module, const char* name, struct hw_device_t** device);
static int action_device_close(struct hw_device_t* device);
static int set_IR(struct action_device_t* dev, int val);
static int set_led_color(struct action_device_t* dev, int val);
static struct hw_module_methods_t action_module_methods = {
open: action_device_open
};
struct action_module_t HAL_MODULE_INFO_SYM = {
common: {
tag: HARDWARE_MODULE_TAG,
version_major: 1,
version_minor: 0,
id: ACTION_HARDWARE_MODULE_ID,
name: MODULE_NAME,
author: MODULE_AUTHOR,
methods: &action_module_methods,
}
};
static int action_device_open(const struct hw_module_t* module, const char* name, struct hw_device_t** device) {
struct action_device_t* dev;
//ALOGD("------------->>>>yxj add: %s", __FUNCTION__);
dev = (struct action_device_t*)malloc(sizeof(struct action_device_t));
if(!dev) {
return -EFAULT;
}
memset(dev, 0, sizeof(struct action_device_t));
dev->common.tag = HARDWARE_DEVICE_TAG;
dev->common.version = 0;
dev->common.module = (hw_module_t*)module;
dev->common.close = action_device_close;
dev->setIR = set_IR;
dev->setLedColor = set_led_color;
dev->fd = open("/dev/action_dev", O_RDWR);
if((dev->fd) < 0)
{
ALOGD("------------->>>>yxj add: open /dev/action_dev fail: error = %s\n", strerror(errno));
free(dev);
return -EFAULT;
}
//ALOGD("------------->>>>yxj add: %s, dev->fd = %d", __FUNCTION__, dev->fd);
*device = &(dev->common);
return 0;
}
static int action_device_close(struct hw_device_t* device) {
struct action_device_t* action_device = (struct action_device_t*)device;
if(action_device) {
close(action_device->fd);
free(action_device);
}
return 0;
}
static int set_IR(struct action_device_t* dev, int val) {
//ALOGD("------------->>>>yxj add: %s, %d", __FUNCTION__, val);
ioctl(dev->fd, SET_IR, val);
return 0;
}
static int set_led_color(struct action_device_t * dev, int val){
//ALOGD("------------->>>>yxj add: %s, %d", __FUNCTION__, val);
ioctl(dev->fd, SET_LED_COLOR, val);
return 0;
}
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_PRELINK_MODULE := false
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
LOCAL_SHARED_LIBRARIES := liblog libcutils
LOCAL_SRC_FILES := action.c
LOCAL_MODULE := action.default
include $(BUILD_SHARED_LIBRARY)
2、在文件system/core/rootdir/ueventd.rc中增加
/dev/action_dev 0666 system system
3、hardware/libhardware/modules/Android.mk文件hardware_modules中增加
action
4、device/rockchip/common/sepolicy/system_server.te文件增加
allow system_server action_device:chr_file rw_file_perms;
5、device/rockchip/common/sepolicy/service.te增加
type action_service, system_server_service, service_manager_type;
6、device/rockchip/common/sepolicy/service_contexts增加
action u:object_r:action_service:s0
7、device/rockchip/common/sepolicy/file_contexts增加
/dev/action_dev u:object_r:action_device:s0
8、device/rockchip/common/sepolicy/device.te
type action_device, dev_type;
9、增加文件kernel/drivers/char/action/action_dev.c
/*
* File:
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define ACTION_DEV_MAJOR_NUM 235
#define ACTION_DEV_MINOR_NUM 1
#define SET_AUDIO_SOUCE 1
#define SET_FM_FREQ 3
#define SET_FM_STATUS 5
#define SET_IR 7
#define SET_VOLUME 9
#define SET_LED_COLOR 11
#define SET_IR_BAND 13
#define SET_ENABLE_BACKLIGHT 15
#define SET_HMDI_RESET 17
#define DEV_NAME "action_dev"
struct led_data{
struct delayed_work work;
int led_flag;
int stop_flash_flag;
struct mutex mutex;
};
static struct class *action_class;
static int ir_gpio, ir_gpio1, ir_gpio2, fm_ctl_gpio, hdmi_5v_gpio, led_gpio, detect_hw_version;
static int first_set_ir_flag = 0;
static struct workqueue_struct *led_workqueue = NULL;
static struct led_data *action_led = NULL;
extern int sleep_gpio;
extern void set_current_source(int source);
extern void set_fmkqn800_status(int status);
extern void set_fmkqn800_freq(int freq);
extern void adjust_volume(int volume);
extern bool Check_Adv7181_Singal(void);
//extern void Adv7181ModeChange(int val);
extern void set_system_boot_finish_to_enable_backlight(int val);
static int action_dev_open(struct inode *inode, struct file *file)
{
return 0;
}
static int action_dev_release(struct inode *inode, struct file *file)
{
return 0;
}
static int action_dev_read(struct file *file, char __user *buf, size_t count,
loff_t *offset)
{
int disc_gpio, ret, detect_hw_version_gpio;
disc_gpio = gpio_get_value(hdmi_5v_gpio);
if(Check_Adv7181_Singal()==true)
disc_gpio = disc_gpio | 0x00000010;
detect_hw_version_gpio = gpio_get_value(detect_hw_version);
disc_gpio = disc_gpio | (detect_hw_version_gpio << 8);
ret = copy_to_user(buf, &disc_gpio, count) ? -EFAULT : ret;;
return ret;
}
static long action_dev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
int ret = 0;
int parm = (int)arg;
switch(cmd){
case SET_AUDIO_SOUCE:
//printk("-------->>>>yxj add: SET_AUDIO_SOUCE, parm = %d\n", parm);
set_current_source(parm);
break;
case SET_FM_STATUS:
//printk("-------->>>>yxj add: SET_FM_STATUS, parm = %d\n", parm);
if(parm == 1){
gpio_direction_output(fm_ctl_gpio, 1);
msleep(200);
set_fmkqn800_status(parm);
}
else if(parm == 0){
set_fmkqn800_status(parm);
gpio_direction_output(fm_ctl_gpio, 0);
}
else
{
//Adv7181ModeChange(parm);
}
/*else if(parm == 3){
// set_fmkqn800_status(parm);
Adv7181ModeChange(1);
//gpio_direction_output(fm_ctl_gpio, 0);
}
else if(parm == 4){
// set_fmkqn800_status(parm);
Adv7181ModeChange(0);
//gpio_direction_output(fm_ctl_gpio, 0);
}*/
break;
case SET_FM_FREQ:
set_fmkqn800_freq(parm);
break;
case SET_IR:
if(first_set_ir_flag == 0)
{
gpio_direction_output(ir_gpio, 1);
first_set_ir_flag = 1;
}
if(parm == 1){
gpio_direction_output(ir_gpio1, 1);
}
else{
gpio_direction_output(ir_gpio1, 0);
}
break;
case SET_VOLUME:
adjust_volume(parm);
break;
case SET_LED_COLOR:
action_led->stop_flash_flag = 1;
mutex_lock(&action_led->mutex);
if(parm == 1){
gpio_direction_output(led_gpio, 0);
}
else{
gpio_direction_output(led_gpio, 1);
}
mutex_unlock(&action_led->mutex);
break;
case SET_IR_BAND:
if(parm == 1){
gpio_direction_output(ir_gpio2, 1); //A band
}
else{
gpio_direction_output(ir_gpio2, 0); //B band
}
break;
case SET_ENABLE_BACKLIGHT:
set_system_boot_finish_to_enable_backlight(parm);
break;
case SET_HMDI_RESET:
if(parm == 1){
gpio_direction_output(sleep_gpio, 1);
}
else{
gpio_direction_output(sleep_gpio, 0);
}
break;
default:
break;
}
return ret;
}
struct file_operations action_dev_ops = {
.owner = THIS_MODULE,
.unlocked_ioctl = action_dev_ioctl,
.open = action_dev_open,
.read = action_dev_read,
.release = action_dev_release,
};
static struct of_device_id action_dt_match[] = {
{ .compatible = "action, action_dev", },
};
MODULE_DEVICE_TABLE(of, action_dt_match);
static void led_work_func(struct work_struct *work)
{
if(action_led->stop_flash_flag == 1)
return;
mutex_lock(&action_led->mutex);
if(action_led->led_flag == 1){
gpio_direction_output(led_gpio, 1);
action_led->led_flag = 0;
}else{
gpio_direction_output(led_gpio, 0);
action_led->led_flag = 1;
}
mutex_unlock(&action_led->mutex);
queue_delayed_work(led_workqueue, &action_led->work, 300);
}
static int action_probe(struct platform_device *pdev)
{
int ret;
struct device_node *np = (&(pdev->dev))->of_node;
action_led = kzalloc(sizeof(*action_led), GFP_KERNEL);
if (action_led == NULL)
{
printk("Alloc GFP_KERNEL memory failed.");
return -ENOMEM;
}
INIT_DELAYED_WORK(&action_led->work, led_work_func);
mutex_init(&action_led->mutex);
ir_gpio = of_get_named_gpio(np, "ir_gpio", 0);
ir_gpio1 = of_get_named_gpio(np, "ir_gpio1", 0);
ir_gpio2 = of_get_named_gpio(np, "ir_gpio2", 0);
fm_ctl_gpio = of_get_named_gpio(np, "fm_ctl_gpio", 0);
hdmi_5v_gpio = of_get_named_gpio(np, "hdmi_5v_gpio", 0);
led_gpio = of_get_named_gpio(np, "led_gpio", 0);
detect_hw_version = of_get_named_gpio(np, "detect_hw_version", 0);
gpio_request(ir_gpio, "ir_gpio");
gpio_request(ir_gpio1, "ir_gpio1");
gpio_request(ir_gpio2, "ir_gpio2");
gpio_request(fm_ctl_gpio, "fm_ctl_gpio");
gpio_request(hdmi_5v_gpio, "hdmi_5v_gpio");
gpio_request(led_gpio, "led_gpio");
gpio_request(detect_hw_version, "detect_hw_version");
gpio_direction_output(ir_gpio, 0);
gpio_direction_output(ir_gpio2, 1);
gpio_direction_input(hdmi_5v_gpio);
gpio_direction_input(detect_hw_version);
//gpio_direction_output(fm_ctl_gpio, 1);//added by zs for test
ret = register_chrdev(ACTION_DEV_MAJOR_NUM, DEV_NAME, &action_dev_ops);
action_class = class_create(THIS_MODULE, DEV_NAME);
device_create(action_class, NULL, MKDEV(ACTION_DEV_MAJOR_NUM, ACTION_DEV_MINOR_NUM), NULL, DEV_NAME);
if(ret < 0){
printk("---->>>yxj add: [%d]fail to register the character device\n", ret);
return ret;
}
queue_delayed_work(led_workqueue, &action_led->work, 100);
return 0;
}
static int action_remove(struct platform_device *pdev)
{
unregister_chrdev(ACTION_DEV_MAJOR_NUM, DEV_NAME);
return 0;
}
static struct platform_driver action_driver = {
.probe = action_probe,
.remove = action_remove,
.driver = {
.name = DEV_NAME,
.owner = THIS_MODULE,
.of_match_table = action_dt_match,
},
};
int __init action_init(void)
{
int retval;
led_workqueue = create_singlethread_workqueue("led_wq");
if (!led_workqueue)
{
printk("Creat workqueue failed.");
return -ENOMEM;
}
retval = platform_driver_register(&action_driver);
return retval;
}
void __exit action_exit(void)
{
cancel_delayed_work(&action_led->work);
flush_workqueue(led_workqueue);
kfree(action_led);
destroy_workqueue(led_workqueue);
platform_driver_unregister(&action_driver);
}
module_init(action_init);
module_exit(action_exit);
MODULE_AUTHOR("action team");
MODULE_DESCRIPTION("ation_dev");
MODULE_LICENSE("GPL");
10、kernel/arch/arm/boot/dts/rk3288-evb-android-rk808-lvds.dts中增加
action_dev {
compatible = "action, action_dev";
status = "okay";
ir_gpio = <&gpio7 11 GPIO_ACTIVE_HIGH>;
ir_gpio1 = <&gpio7 13 GPIO_ACTIVE_HIGH>;
ir_gpio2 = <&gpio7 14 GPIO_ACTIVE_HIGH>;
fm_ctl_gpio = <&gpio7 15 GPIO_ACTIVE_HIGH>;
hdmi_5v_gpio = <&gpio5 14 GPIO_ACTIVE_HIGH>;
led_gpio = <&gpio7 12 GPIO_ACTIVE_HIGH>;
detect_hw_version = <&gpio5 10 GPIO_ACTIVE_HIGH>;
};
11、kernel/.config kernel/.config.old kernel/arch/arm/configs/rockchip_defconfig 增加
CONFIG_ACTION_CHAR_DEV=y
12、kernel/drivers/char/Kconfig增加
source "drivers/char/action/Kconfig"
13、kernel/drivers/char/Makefile增加
obj-$(CONFIG_ACTION_CHAR_DEV) += action/
14、增加文件
#
# action character device configuration
#
menu "Action character device"
config ACTION_CHAR_DEV
bool "ACTION CHAR DEV"
default y
help
ACTION CHAR DEV driver.
endmenu
15、增加文件
#
# drivers/char/action/Makefile
#
obj-$(CONFIG_ACTION_CHAR_DEV) += action_dev.o
obj-$(CONFIG_FMK9N800) += fmk9n800.o
obj-$(CONFIG_ACTION_CH7107) += ch7107.o
16、kernel/include/config/auto.conf增加
CONFIG_ACTION_CHAR_DEV=y
17、kernel/include/config/auto.conf.cmd增加
drivers/char/action/Kconfig \
18、kernel/include/generated/autoconf.h增加
#define CONFIG_ACTION_CHAR_DEV 1