1.Android系统中启动框架
2.首先实现驱动程序
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/device.h>
#include <linux/fs.h>
#include <linux/types.h>
#include <linux/moduleparam.h>
#include <linux/slab.h>
#include <linux/ioctl.h>
#include <linux/cdev.h>
#include <linux/delay.h> #include <linux/gpio.h>
#include <mach/gpio.h>
#include <plat/gpio-cfg.h> static int led_gpios[] = {
EXYNOS4212_GPM4(),
EXYNOS4212_GPM4(),
EXYNOS4212_GPM4(),
EXYNOS4212_GPM4(),
}; static int led_open(struct inode *inode, struct file *file)
{
/* 配置GPIO为输出引脚 */
int i;
for (i = ; i < ; i++)
s3c_gpio_cfgpin(led_gpios[i], S3C_GPIO_OUTPUT); return ;
} /* app : ioctl(fd, cmd, arg) */
static long led_ioctl(struct file *filp, unsigned int cmd,
unsigned long arg)
{
/* 根据传入的参数设置GPIO */
/* cmd : 0-off, 1-on */
/* arg : 0-3, which led */ if ((cmd != ) && (cmd != ))
return -EINVAL; if (arg > )
return -EINVAL; gpio_set_value(led_gpios[arg], !cmd); return ;
} static struct file_operations leds_ops = {
.owner = THIS_MODULE, /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */
.open = led_open,
.unlocked_ioctl = led_ioctl, }; static int major;
static struct class *cls; int leds_init(void)
{
major = register_chrdev(, "leds", &leds_ops); /* 为了让系统udev,mdev给我们创建设备节点 */
/* 创建类, 在类下创建设备 : /sys */
cls = class_create(THIS_MODULE, "leds");
device_create(cls, NULL, MKDEV(major, ), NULL, "leds"); /* /dev/leds */ return ;
} void leds_exit(void)
{
device_destroy(cls, MKDEV(major, ));
class_destroy(cls);
unregister_chrdev(major, "leds");
} module_init(leds_init);
module_exit(leds_exit); MODULE_LICENSE("GPL");
MODULE_AUTHOR("www.100ask.net");
放入内核 drivers/char
修改 drivers/char/Makefile,添加:
obj-y += leds_4412.o
重新编译内核
或者将其编译成模块
#Makefile
obj-m := leds_4412.o
KDIR := /home/cent/work/androidL_Tiny4412/linux-3.0.
all:
make -C $(KDIR) M=$(PWD) modules CROSS_COMPILE=arm-linux- ARCH=arm
.PHONY: clean
clean:
rm -f *.ko *.o *.mod.c *.bak *.order *.symvers *~
执行 make后 用adb push 命令将其上传到开发板的/data/local 目录,adb shell 使用 insmod 命令将驱动模块加载到内核。
3.实现HAL层
//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 which, int status);
}; __END_DECLS #endif // ANDROID_LED_INTERFACE_H
//led_hal.c #define LOG_TAG "LedHal" /* 1. 实现一个名为HMI的hw_module_t结构体 */ /* 2. 实现一个open函数, 它返回led_device_t结构体 */ /* 3. 实现led_device_t结构体 */ /* 参考 hardware\libhardware\modules\vibrator\vibrator.c
*/ #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 <hardware/led_hal.h> #include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <utils/Log.h> static int fd; /** Close this device */
static int led_close(struct hw_device_t* device)
{
close(fd);
return ;
} static int led_open(struct led_device_t* dev)
{
fd = open("/dev/leds", O_RDWR);
ALOGI("led_open : %d", fd);
if (fd >= )
return ;
else
return -;
} static int led_ctrl(struct led_device_t* dev, int which, int status)
{
int ret = ioctl(fd, status, which);
ALOGI("led_ctrl : %d, %d, %d", which, 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 ;
} 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,
};
#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_MODULE_TAGS := eng include $(BUILD_SHARED_LIBRARY)
//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", (hw_module_t const**)&module);
if (err == ) {
/* 2. get device : module->methods->open */
err = module->methods->open(module, NULL, &device);
if (err == ) {
/* 3. call led_open */
led_device = (led_device_t *)device;
return led_device->led_open(led_device);
} else {
return -;
}
} return -;
} void ledClose(JNIEnv *env, jobject cls)
{
//ALOGI("native ledClose ...");
//close(fd);
} jint ledCtrl(JNIEnv *env, jobject cls, jint which, jint status)
{
ALOGI("native ledCtrl %d, %d", which, status);
return led_device->led_ctrl(led_device, which, status);
} static const JNINativeMethod methods[] = {
{"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",
methods, NELEM(methods));
} }
放到Android源码frameworks/base/services/core/jni/com_android_server_LedService.cpp位置
修改frameworks/base/services/core/jni/onload.cpp
添加:
int register_android_server_Watchdog(JNIEnv* env);
+int register_android_server_LedService(JNIEnv *env);
register_android_server_VibratorService(env);
+register_android_server_LedService(env);
package android.os; /** {@hide} */
interface ILedService
{
int ledCtrl(int which, int status);
}
把 ILedService.aidl 放入 frameworks/base/core/java/android/os
package com.android.server;
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() {
native_ledOpen();
} public static native int native_ledOpen();
public static native void native_ledClose();
public static native int native_ledCtrl(int which, int status);
}
frameworks/base/services/java/com/android/server/SystemServer.java中注册LedService
Slog.i(TAG, "Vibrator Service");
vibrator = new VibratorService(context);
ServiceManager.addService("vibrator", vibrator);
+Slog.i(TAG, "Led Service");
+ServiceManager.addService("led", new LedService());
package cc.icen.leddemo; import android.os.RemoteException;
import android.app.Activity;
import android.os.Bundle;
import android.widget.Button;
import android.view.View;
import android.widget.CheckBox;
import android.widget.Toast;
import android.os.ILedService;
import android.os.ServiceManager;
import android.util.Log; public class MainActivity extends Activity { private boolean ledon = false;
private Button button = null;
private CheckBox checkBoxLed1 = null;
private CheckBox checkBoxLed2 = null;
private CheckBox checkBoxLed3 = null;
private CheckBox checkBoxLed4 = null;
private ILedService iLedService = null; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); button = (Button) findViewById(R.id.BUTTON); iLedService = ILedService.Stub.asInterface(ServiceManager.getService("led"));
if(iLedService == null)
Log.d("tian","iLedService is null!!!!"); checkBoxLed1 = (CheckBox)findViewById(R.id.LED1);
checkBoxLed2 = (CheckBox)findViewById(R.id.LED2);
checkBoxLed3 = (CheckBox)findViewById(R.id.LED3);
checkBoxLed4 = (CheckBox)findViewById(R.id.LED4); button.setOnClickListener(new MyButtonListener()); } class MyButtonListener implements View.OnClickListener {
@Override
public void onClick(View v) {
ledon = !ledon;
if (ledon) {
button.setText("ALL OFF");
checkBoxLed1.setChecked(true);
checkBoxLed2.setChecked(true);
checkBoxLed3.setChecked(true);
checkBoxLed4.setChecked(true); try {
for (int i = 0; i < 4; i++)
iLedService.ledCtrl(i, 1);
} catch (RemoteException e) {
e.printStackTrace();
}
}
else {
button.setText("ALL ON");
checkBoxLed1.setChecked(false);
checkBoxLed2.setChecked(false);
checkBoxLed3.setChecked(false);
checkBoxLed4.setChecked(false); try {
for (int i = 0; i < 4; i++)
iLedService.ledCtrl(i, 0);
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
} public void onCheckboxClicked(View view) {
// Is the view now checked?
boolean checked = ((CheckBox) view).isChecked(); try {
// Check which checkbox was clicked
switch(view.getId()) {
case R.id.LED1:
if (checked) {
// Put some meat on the sandwich
Log.d("tian","1");
//Toast.makeText(getApplicationContext(), "LED1 on", Toast.LENGTH_SHORT).show();
iLedService.ledCtrl(0, 1);
Log.d("tian","2");
}
else {
// Remove the meat
//Toast.makeText(getApplicationContext(), "LED1 off", Toast.LENGTH_SHORT).show();
iLedService.ledCtrl(0, 0);
}
break;
case R.id.LED2:
if (checked) {
// Put some meat on the sandwich
//Toast.makeText(getApplicationContext(), "LED2 on", Toast.LENGTH_SHORT).show();
iLedService.ledCtrl(1, 1);
}
else {
// Remove the meat
//Toast.makeText(getApplicationContext(), "LED2 off", Toast.LENGTH_SHORT).show();
iLedService.ledCtrl(1, 0);
}
break; case R.id.LED3:
if (checked) {
// Put some meat on the sandwich
//Toast.makeText(getApplicationContext(), "LED3 on", Toast.LENGTH_SHORT).show();
iLedService.ledCtrl(2, 1);
}
else {
// Remove the meat
//Toast.makeText(getApplicationContext(), "LED3 off", Toast.LENGTH_SHORT).show();
iLedService.ledCtrl(2, 0);
}
break; case R.id.LED4:
if (checked) {
// Put some meat on the sandwich
//Toast.makeText(getApplicationContext(), "LED4 on", Toast.LENGTH_SHORT).show();
iLedService.ledCtrl(3, 1);
}
else {
// Remove the meat
//Toast.makeText(getApplicationContext(), "LED4 off", Toast.LENGTH_SHORT).show();
iLedService.ledCtrl(3, 0);
}
break;
// TODO: Veggie sandwich
}
} catch (RemoteException e) {
e.printStackTrace();
}
} }
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity"
android:orientation="vertical"
> <Button
android:id="@+id/BUTTON"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/app_name"
/> <CheckBox
android:id="@+id/LED1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/app_name"
android:onClick="onCheckboxClicked"
/> <CheckBox
android:id="@+id/LED2"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/app_name"
android:onClick="onCheckboxClicked"
/> <CheckBox
android:id="@+id/LED3"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/app_name"
android:onClick="onCheckboxClicked"
/> <CheckBox
android:id="@+id/LED4"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/app_name"
android:onClick="onCheckboxClicked"
/> </LinearLayout>
#Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS) # Build all java files in the java subdirectory
LOCAL_SRC_FILES := $(call all-subdir-java-files) # Name of the APK to build
LOCAL_PACKAGE_NAME := LEDDemo # Tell it to build an APK
include $(BUILD_PACKAGE)
android应用如何访问C库
安卓应用是由java编写的,而在android底层,如安卓底层的硬件驱动程序,都是由C/C++编写的,那应用层java是必须通过某种手段才能使用底层提供的硬件资源。毫无疑问,在java看要调用底层C实现的代码,中间必须要有一层接口,那就是JNI。本例要实现的就是JAVA如何访问底层C库。
假设JAVA应用需要实现的功能是控制底层硬件LED设备,包括开,关及控制操作。需要实现下述流程:
1 实现一个JAVA硬件控制类,声明本地的Native方法(操作硬件的接口),并使用static模块加载C的动态库。实现代码如下
public class HardControl{
//声明本地的Native方法
public static native int ledCtrl(int which, int status);
public static native int ledOpen();
public static native void ledClose(); //我们要在这个java程序里面加载C库,定义一个static模块
static {
//用System方法来加载C库
try { //添加捕获异常代码的快捷键为:ctrl+alt+T(前提先用鼠标选中需要捕获的代码)
System.loadLibrary("hardcontrol"); //参数为C库的库名
} catch (Exception e) {
e.printStackTrace();
}
}
}
注意,加载C库的方法为System.loadLibrary.
#include <jni.h>
#include <stdio.h>
#include <stdlib.h> #include <android/log.h> /* liblog */ jint ledOpen(JNIEnv *env, jobject cls)
{ __android_log_print(ANDROID_LOG_DEBUG, "LEDDemo", "native_ledOpen"); //调用这句就可以打印了。 return ;
} void ledClose(JNIEnv *env, jobject cls)
{
__android_log_print(ANDROID_LOG_DEBUG, "LEDDemo", "native_ledClose"); //调用这句就可以打印了。 } void ledCtrl(JNIEnv *env, jobject cls, jint which, jint status)
{
__android_log_print(ANDROID_LOG_DEBUG, "LEDDemo", "native_ledCtrl:%d %d", which, status); //调用这句就可以打印了。 return ;
} static const JNINativeMethod methods[] = {
{"ledOpen", "()I", (void *)ledOpen}, //() inside empty=> no params, 'I' means: return type is int
{"ledClose", "()V", (void *)ledClose},//() inside empty=> no params, 'V' means: return type is void
{"ledCtrl", "(II)I", (void *)ledCtrl}, //()inside two I => means two params, types is int, ouside () is 'I' ==> return type is int }; /* System.LoadLibrary */
JNI_OnLoad(JavaVM *jvm, void *reserved)
{
JNIEnv *env;
jclass cls;
if((*jvm)->GetEnv(jvm, (void**)&env, JNI_VERSION_1_4) != JNI_OK) {
return JNI_ERR;; //jni version not supported
} //find the class that realize the local native method: *.java, here is HardControl
//PS:here need to indification the package & class name.
// "." --> "/"
cls = (*env)->FindClass(env, "com/example/zhm/hardlibrary/HardControl");
if( cls == NULL )
{
return JNI_ERR;
} //find the class then register their methods . Java's method <==correspond with ==> C's method
if((*env)->RegisterNatives(env, cls, methods, sizeof(methods)/sizeof(methods[])) < ) // 3: means there are 3 funcs in methods.
{ } }