Android增加系统服务访问底层硬件

一、以增加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 <utils/misc.h>
#include <utils/Log.h>
#include <hardware/hardware.h>
#include <hardware/action.h>
#include <stdio.h>

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<ActionManager>() {
            @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 <hardware/hardware.h>

__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 <hardware/hardware.h>
#include <hardware/action.h>

#include <stdio.h>
#include <stdlib.h>

#include <fcntl.h>
#include <errno.h>
#include <cutils/log.h>
#include <cutils/atomic.h>

#include <linux/ioctl.h>
#include <linux/types.h>

#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 <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
#include <linux/ioctl.h>
#include <linux/device.h>

#include <asm/io.h>
#include <linux/delay.h>

#include <asm/mach-types.h>

#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>

#include <linux/of_gpio.h>
#include <linux/slab.h>
#include <linux/mutex.h>


#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

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值