RK3399 Android8.1从APK到driver的示例

1.先看driver 驱动层:
新增:kernel/drivers/char/virt_led.c

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/cdev.h>
#include <linux/uaccess.h>
#include <linux/fs.h>
#include <linux/ioport.h>
#include <linux/miscdevice.h>
#include <linux/ioctl.h>
#include <linux/delay.h>
#include <linux/gpio.h>
#include <asm/uaccess.h>

static int virt_leds_open(struct inode *inode, struct file *file)
{
	pr_info("virt_led: virt_leds_open\n");
	return 0;
}

static long virt_leds_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
	pr_info("virt_led: virt_leds_ioctl [cmd: %u] [args: %lu]\n", cmd, arg);
	return 0;
}

static int virt_leds_release(struct inode *inode, struct file *file)
{
	pr_info("virt_led: virt_leds_release\n");
	return 0;
}

static const struct file_operations virt_leds_fops = {
	.owner = THIS_MODULE,
	.open = virt_leds_open,
	.unlocked_ioctl = virt_leds_ioctl,
	.release = virt_leds_release,
}; 

static struct miscdevice virt_leds_misc = {
	.minor = MISC_DYNAMIC_MINOR,
	.fops = &virt_leds_fops,
	.name   = "virt_led",
}; 

static int __init virt_leds_init(void)
{
    int ret = -1;
	ret =  misc_register(&virt_leds_misc);   //注册字符设备
	if(ret < 0){
		pr_err("misc register error\n");
		return -1;
	}
    return 0;
}


static void __exit virt_leds_exit(void)
{
	misc_deregister(&virt_leds_misc);
}

module_init(virt_leds_init);
module_exit(virt_leds_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("mark wan");
MODULE_DESCRIPTION("virl led driver");

驱动下面Makefile的修改:kernel/drivers/char/Makefile

diff --git a/kernel/drivers/char/Makefile b/kernel/drivers/char/Makefile
index d8a7579300..e59fd309ae 100644
--- a/kernel/drivers/char/Makefile
+++ b/kernel/drivers/char/Makefile
@@ -60,3 +60,5 @@ js-rtc-y = rtc.o
 
 obj-$(CONFIG_TILE_SROM)                += tile-srom.o
 obj-$(CONFIG_XILLYBUS)         += xillybus/
+
+obj-y                       += virt_led.o
\ No newline at end of file

设备节点权限修改:system/core/rootdir/ueventd.rc

diff --git a/system/core/rootdir/ueventd.rc b/system/core/rootdir/ueventd.rc
index 88e642ae6d..d8f548019b 100644
--- a/system/core/rootdir/ueventd.rc
+++ b/system/core/rootdir/ueventd.rc
@@ -134,3 +134,6 @@ subsystem sound
 
 # DVB API device nodes
 /dev/dvb*                 0660   root       system
+
+# virt led
+/dev/virt_led             0777   root       root
\ No newline at end of file

2.hardware层:
新增:hardware/libhardware/modules/led/Android.mk

# hardware/libhardware/modules/led/Android.mk
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := led.default
LOCAL_MODULE_RELATIVE_PATH := hw

LOCAL_C_INCLUDES := hardware/libhardware
LOCAL_SRC_FILES := led_hal.c
LOCAL_SHARED_LIBRARIES := liblog
LOCAL_MULTILIB := 64
LOCAL_MODULE_TAGS := optional
LOCAL_CFLAGS += -Wno-unused-parameter

include $(BUILD_SHARED_LIBRARY)

新增:hardware/libhardware/modules/led/led_hal.c

/*
PATH: hardware/libhardware/modules/led/led_hal.c
*/

#define LOG_TAG "LedHal"

#include <hardware/hardware.h>

#include <cutils/log.h>

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <math.h>

#include <utils/Log.h>

#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>

#include <hardware/led_hal.h>



static int fd = -1;
static int led_close(struct hw_device_t * device)
{
	ALOGI("LED_HAL: led_close\n");
	if (fd > 0)
	{
		close(fd);
	}
	return 0;
}

static int led_open(struct led_device_t * dev)
{
	ALOGI("LED_HAL: led_open\n");
	fd = open("/dev/virt_led", O_RDWR);
	if (fd < 0)
	{
		ALOGE("LED_HAL: led_open fail, fd=%d\n", fd);
		return -1;
	}
	return 0;
}

static int led_ctrl(struct led_device_t* dev, int which, int status)
{
	int ret = -1;
	if (fd > 0)
	{
		ret = ioctl(fd, which, status);
	}
	ALOGI(" LED_HAL: ledCtrl: %d, %d, %d", which, status, ret);
	return ret;
}

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 hw_module_t* module, const char* id,
hw_device_t** device) 
{
	*device = &led_dev;
	return 0;
}


static struct hw_module_methods_t led_module_methods = {
    .open = led_device_open, 
};

struct hw_module_t HAL_MODULE_INFO_SYM = {
	.tag = HARDWARE_MODULE_TAG,
    .id = "led",
    .methods = &led_module_methods,
};

新增:hardware/libhardware/include/hardware/led_hal.h

#ifndef ANDROID_LED_HARDWARE_H
#define ANDROID_LED_HARDWARE_H

/*
PATH: hardware/libhardware/include/hardware/led_hal.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 which, int status);
};


__END_DECLS

#endif  // ANDROID_LED_HARDWARE_H

添加hardware模块到编译中:hardware/libhardware/modules/Android.mk

diff --git a/hardware/libhardware/modules/Android.mk b/hardware/libhardware/modules/Android.mk
index 462081dce8..7708c0e29d 100644
--- a/hardware/libhardware/modules/Android.mk
+++ b/hardware/libhardware/modules/Android.mk
@@ -10,5 +10,7 @@ hardware_modules := \
     usbaudio \
     usbcamera \
     vehicle \
+    led \
     vr
+
 include $(call all-named-subdir-makefiles,$(hardware_modules))

生成led.default.so库:build/make/target/product/embedded.mk

diff --git a/build/make/target/product/embedded.mk b/build/make/target/product/embedded.mk
index 4d6bb8b923..ec141b3a85 100644
--- a/build/make/target/product/embedded.mk
+++ b/build/make/target/product/embedded.mk
@@ -34,6 +34,7 @@ PRODUCT_PACKAGES += \
     dumpsys \
     fastboot \
     gralloc.default \
+    led.default \
     healthd \
     hwservicemanager \
     init \

3.framewrok层:
JNI代码:
新增:frameworks/base/services/core/jni/com_android_server_LedService.cpp

#define LOG_TAG "LedJNI"

#include "jni.h"
#include "JNIHelp.h"
#include "android_runtime/AndroidRuntime.h"

#include <utils/misc.h>
#include <utils/Log.h>
#include <hardware/led_hal.h>

#include <stdio.h>

#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>

namespace android
{
	static led_device_t* led_device = nullptr;

	jint ledOpen(JNIEnv *env, jobject cls)
	{
		int err;
		hw_module_t * module = nullptr;
		hw_device_t * device = nullptr;
		
		ALOGE("JNI_LED ledOpen\n");

		/*1. hw_get_module*/
		err = hw_get_module("led", (hw_module_t const**)&module);

		ALOGE("JNI_LED hw_get_module: %d  %p\n", err, module);
		if((err == 0) && (nullptr != module)){
			/*2. get device:  module->methods->open*/
			ALOGE("hw_get_module ok\n");
			err = module->methods->open(module, NULL, &device);
			if (err == 0) {
				if (nullptr == device)
				{
					ALOGE("device is null\n");
					return -1;
				}
				led_device = (led_device_t*)device;

				/*3. call led_open*/
				return led_device->led_open(led_device);
			} else {
				return -1;
			}
		}
		return -1;		
	}

	void ledClose(JNIEnv *env, jobject cls)
	{
		ALOGE("JNI_LED ledClose\n");
	}

	jint ledCtrl(JNIEnv *env, jobject cls, jint which, jint status)
	{
		ALOGE("JNI_LED ledCtrl : %d, %d\n", which, status);
		if (nullptr == led_device)
		{
			ALOGE("led_device is nullptr\n");
			return -1;
		}
		return led_device->led_ctrl(led_device, which, status);
	}

	static const JNINativeMethod method_table[] = {
		{"native_ledOpen", "()I", (void *)ledOpen},
		{"native_ledClose", "()V", (void *)ledClose},
		{"native_ledCtrl", "(II)I", (void *)ledCtrl},
	};

	
	int register_android_server_LedService(JNIEnv *env)
	{
		return jniRegisterNativeMethods(env, "com/android/server/LedService",
				method_table, NELEM(method_table));
	}

};

JNI编译:frameworks/base/services/core/jni/Android.mk

diff --git a/frameworks/base/services/core/jni/Android.mk b/frameworks/base/services/core/jni/Android.mk
index b44362a6ee..59137cfe3a 100644
--- a/frameworks/base/services/core/jni/Android.mk
+++ b/frameworks/base/services/core/jni/Android.mk
@@ -40,6 +40,7 @@ LOCAL_SRC_FILES += \
     $(LOCAL_REL_DIR)/com_android_server_VibratorService.cpp \
     $(LOCAL_REL_DIR)/com_android_server_PersistentDataBlockService.cpp \
     $(LOCAL_REL_DIR)/com_android_server_GraphicsStatsService.cpp \
+    $(LOCAL_REL_DIR)/com_android_server_LedService.cpp \
     $(LOCAL_REL_DIR)/onload.cpp
 
 LOCAL_SRC_FILES += \

JNI注册:frameworks/base/services/core/jni/onload.cpp

diff --git a/frameworks/base/services/core/jni/onload.cpp b/frameworks/base/services/core/jni/onload.cpp
index 4d70384299..866eda12d0 100644
--- a/frameworks/base/services/core/jni/onload.cpp
+++ b/frameworks/base/services/core/jni/onload.cpp
@@ -53,6 +53,7 @@ int register_android_server_SyntheticPasswordManager(JNIEnv* env);
 int register_android_server_GraphicsStatsService(JNIEnv* env);
 int register_android_hardware_display_DisplayViewport(JNIEnv* env);
 int register_com_android_server_rkdisplay_RkDisplayModes(JNIEnv* env);
+int register_android_server_LedService(JNIEnv *env);
 };
 
 using namespace android;
@@ -100,6 +101,7 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
     register_android_server_GraphicsStatsService(env);
     register_android_hardware_display_DisplayViewport(env);
     register_com_android_server_rkdisplay_RkDisplayModes(env);
+    register_android_server_LedService(env);
 
     return JNI_VERSION_1_4;
 }

4.framework层:
Aidl:
新增:frameworks/base/core/java/android/os/ILedService.aidl

package android.os;

/** {@hide} */
interface ILedService
{
    int ledCtrl(int which, int status);
}

aidl的编译:修改frameworks/base/Android.mk

diff --git a/frameworks/base/Android.mk b/frameworks/base/Android.mk
index 3018c4eb30..7951aa194f 100755
--- a/frameworks/base/Android.mk
+++ b/frameworks/base/Android.mk
@@ -276,6 +276,7 @@ LOCAL_SRC_FILES += \
        core/java/android/os/IUpdateLock.aidl \
        core/java/android/os/IUserManager.aidl \
        core/java/android/os/IVibratorService.aidl \
+       core/java/android/os/ILedService.aidl \
        core/java/android/os/storage/IStorageManager.aidl \
        core/java/android/os/storage/IStorageEventListener.aidl \
        core/java/android/os/storage/IStorageShutdownObserver.aidl \

java接口:
新增:frameworks/base/services/core/java/com/android/server/LedService.java

package com.android.server;

import android.util.Log;
import android.util.Slog;
import android.os.ILedService;

public class LedService extends ILedService.Stub{
    private static final String TAG = "LedService";
	
	/*call native C function to access hardware*/
	public int ledCtrl(int which, int status) throws android.os.RemoteException{
		return native_ledCtrl(which, status);
	}

	public LedService()
	{
		Slog.e(TAG, "------------LedService--------------\n");
		native_ledOpen();
	}
	
	public static native int  native_ledOpen();
	public static native void  native_ledClose();
	public static native int native_ledCtrl(int which, int status);
}

System_server中添加服务:修改 frameworks/base/services/java/com/android/server/SystemServer.java

diff --git a/frameworks/base/services/java/com/android/server/SystemServer.java b/frameworks/base/services/java/com/android/server/SystemServer.java
index 0ea9f1766c..21f8f10434 100755
--- a/frameworks/base/services/java/com/android/server/SystemServer.java
+++ b/frameworks/base/services/java/com/android/server/SystemServer.java
@@ -681,6 +681,7 @@ public final class SystemServer {
      */
     private void startOtherServices() {
         final Context context = mSystemContext;
+        LedService mLedService = null;
         VibratorService vibrator = null;
         IStorageManager storageManager = null;
         NetworkManagementService networkManagement = null;
@@ -796,6 +797,13 @@ public final class SystemServer {
             ServiceManager.addService("vibrator", vibrator);
             traceEnd();
 
+            /*-------------------------------------添加ledService--------------------------------------*/ 
+            traceBeginAndSlog("StartLedService");
+            mLedService = new LedService();
+            ServiceManager.addService("led", mLedService);
+            traceEnd();
+            /*-----------------------------------------------------------------------------------------*/
+
             if (!disableConsumerIr) {
                 traceBeginAndSlog("StartConsumerIrService");
                 consumerIr = new ConsumerIrService(context);

5.APK编写:
MainActivity.java

//这里是直接使用 ServiceManager
package com.example.ledservice;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.Toast;

import android.os.ServiceManager;
import android.os.ILedService;


public class MainActivity extends AppCompatActivity {

    private int button_cnt = 0;
    private ILedService iLedService = null;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        iLedService = ILedService.Stub.asInterface(ServiceManager.getService("led"));

        Button button2 = (Button)findViewById(R.id.button2);
        button2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                button_cnt++;
                if (0 == button_cnt % 2) {
                    try {
                        iLedService.ledCtrl(0,0);
                        iLedService.ledCtrl(1,0);
                    } catch (Exception e){
                        e.printStackTrace();
                    }
                    ((Button)view).setText("ALL OFF");
                    Toast.makeText(MainActivity.this, "ALL LED OFF", Toast.LENGTH_SHORT).show();
                } else {
                    try {
                        iLedService.ledCtrl(0,1);
                        iLedService.ledCtrl(1,1);
                    } catch (Exception e){
                        e.printStackTrace();
                    }
                    ((Button)view).setText("ALL ON");
                    Toast.makeText(MainActivity.this, "ALL LED ON", Toast.LENGTH_SHORT).show();
                }

            }
        });

        CheckBox checkbox3 = (CheckBox)findViewById(R.id.checkBox3);
        checkbox3.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
                if (b) {
                    try {
                        iLedService.ledCtrl(0,1);
                    } catch (Exception e){
                        e.printStackTrace();
                    }
                    Toast.makeText(MainActivity.this, "LED1 on", Toast.LENGTH_SHORT).show();
                } else {
                    try {
                        iLedService.ledCtrl(0,0);
                    } catch (Exception e){
                        e.printStackTrace();
                    }
                    Toast.makeText(MainActivity.this, "LED1 off", Toast.LENGTH_SHORT).show();
                }
            }
        });

        CheckBox checkbox4 = (CheckBox)findViewById(R.id.checkBox4);
        checkbox4.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
                if (b) {
                    try {
                        iLedService.ledCtrl(1,1);
                    } catch (Exception e){
                        e.printStackTrace();
                    }
                    Toast.makeText(MainActivity.this, "LED2 on", Toast.LENGTH_SHORT).show();
                } else {
                    try {
                        iLedService.ledCtrl(1,0);
                    } catch (Exception e){
                        e.printStackTrace();
                    }
                    Toast.makeText(MainActivity.this, "LED2 off", Toast.LENGTH_SHORT).show();
                }
            }
        });
    }

    @Override
    protected void onDestroy() {
        try {
            iLedService.ledCtrl(0,0);
            iLedService.ledCtrl(1,0);
        } catch (Exception e){
            e.printStackTrace();
        }
        super.onDestroy();
    }
}


/*
//这里是使用的反射的方式
package com.example.ledservice;

import androidx.appcompat.app.AppCompatActivity;

import android.nfc.Tag;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.Toast;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;


//import android.os.ServiceManager;
//import android.os.ILedService;

public class MainActivity extends AppCompatActivity {
    private int button_cnt = 0;
    //private ILedService iLedService = null;
    Object proxy = null;
    Method ledCtrl = null;

    private static final String TAG = "FanShe";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //iLedService = ILedService.Stub.asInterface(ServiceManager.getService("led"));
        //iLedService = getSystemService("Led");

        Method getService = null;
        try {
            getService = Class.forName("android.os.ServiceManager").getMethod("getService",String.class);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        IBinder ledService = null;
        try {
            ledService = (IBinder) getService.invoke(null,"led");
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        Method  asInterface = null;
        try {
            asInterface = Class.forName("android.os.ILedService$Stub").getMethod("asInterface", IBinder.class);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        try {
            proxy = asInterface.invoke(null,ledService);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        try {
            ledCtrl = Class.forName("android.os.ILedService$Stub$Proxy").getMethod("ledCtrl", int.class, int.class);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }


        Button button2 = (Button)findViewById(R.id.button2);
        button2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                button_cnt++;
                if (0 == button_cnt % 2) {
                    try {
                        //iLedService.ledCtrl(0,0);
                        //iLedService.ledCtrl(1,0);
                        Log.i(TAG, "ALL OFF: ");
                        ledCtrl.invoke(proxy, 0, 0);
                        ledCtrl.invoke(proxy, 1, 1);
                    } catch (Exception e){
                        e.printStackTrace();
                    }
                    ((Button)view).setText("ALL OFF");
                    Toast.makeText(MainActivity.this, "ALL LED OFF", Toast.LENGTH_SHORT).show();
                } else {
                    try {
                        //iLedService.ledCtrl(0,1);
                        //iLedService.ledCtrl(1,1);
                        Log.i(TAG, "ALL ON: ");
                        ledCtrl.invoke(proxy, 0, 1);
                        ledCtrl.invoke(proxy, 1, 1);
                    } catch (Exception e){
                        e.printStackTrace();
                    }
                    ((Button)view).setText("ALL ON");
                    Toast.makeText(MainActivity.this, "ALL LED ON", Toast.LENGTH_SHORT).show();
                }

            }
        });

        CheckBox checkbox3 = (CheckBox)findViewById(R.id.checkBox3);
        checkbox3.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
                if (b) {
                    try {
                        //iLedService.ledCtrl(0,1);
                        Log.i(TAG, "button2: ");
                        ledCtrl.invoke(proxy, 0, 1);
                    } catch (Exception e){
                        e.printStackTrace();
                    }
                    Toast.makeText(MainActivity.this, "LED1 on", Toast.LENGTH_SHORT).show();
                } else {
                    try {
                        //iLedService.ledCtrl(0,0);
                        ledCtrl.invoke(proxy, 0, 0);
                    } catch (Exception e){
                        e.printStackTrace();
                    }
                    Toast.makeText(MainActivity.this, "LED1 off", Toast.LENGTH_SHORT).show();
                }
            }
        });

        CheckBox checkbox4 = (CheckBox)findViewById(R.id.checkBox4);
        checkbox4.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
                if (b) {
                    try {
                        //iLedService.ledCtrl(1,1);
                        ledCtrl.invoke(proxy, 1, 1);
                    } catch (Exception e){
                        e.printStackTrace();
                    }
                    Toast.makeText(MainActivity.this, "LED2 on", Toast.LENGTH_SHORT).show();
                } else {
                    try {
                        //iLedService.ledCtrl(1,0);
                        ledCtrl.invoke(proxy, 1, 0);
                    } catch (Exception e){
                        e.printStackTrace();
                    }
                    Toast.makeText(MainActivity.this, "LED2 off", Toast.LENGTH_SHORT).show();
                }
            }
        });
    }

    @Override
    protected void onDestroy() {
        try {
            //iLedService.ledCtrl(0,0);
            //iLedService.ledCtrl(1,0);
            ledCtrl.invoke(proxy, 0, 0);
            ledCtrl.invoke(proxy, 1, 0);
        } catch (Exception e){
            e.printStackTrace();
        }
        super.onDestroy();
    }
}

*/
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值