对于未知的技术我们心里总是比较忐忑,当你走进发现原来并不是你想象中那么难,关键是我们需要勇敢迈出第一步----------Bill2019.08.23
本文分两部分:一、驱动层的添加
二、framworks层的代码添加,以及应用层的调用。
一、驱动层的添加
1.向内核添加我的驱动程序
kernel-3.18\drivers\misc\mediatek\Kconfig
增加:source "drivers/misc/mediatek/word_count/Kconfig"word_count/Kconfig:我的驱动配置信息
kernel-3.18\drivers\misc\mediatek\Kconfig\Makefile
增加:obj-$(CONFIG_WORD_COUNT) += word_count/CONFIG_WORD_COUNT 在cofig文件中配置:CONFIG_WORD_COUNT =y
需要特别说明一下:obj-y 表示程序编译到内核,obj-c 表示只是编译驱动程序,而没有加载到内核
2.编写驱动程序
#include
#include
#include
#include
#include
#include //定义设备文件名
#define DEVICE_NAME "wordcount"
static unsigned char mem[10000];
// 保存向设备文件写入的数据
static int word_count = 0;
#define TRUE 255
#define FALSE 0//判断指定字符是否为空格(包括空格符、制表符、回车符和换行符)
static unsigned char is_spacewhite(char c)
{
if (c == 32 || c == 9 || c == 13 || c == 10)
return TRUE;
else
return FALSE;
}static int get_word_count(const char *buf)
{
int n = 1;
int i = 0;
char c = ' ';
char flag = 0;
// 处理多个空格分隔的情况,0:正常情况,1:已遇到一个空格
if (*buf == '\0')
return 0;
//第1个字符是空格,从0开始计数
if (is_spacewhite(*buf) == TRUE)
n--;
//扫描字符串中的每一个字符
for (;
(c = *(buf + i)) != '\0';
i++)
{
//只由一个空格分隔单词的情况
if (flag == 1 && is_spacewhite(c) == FALSE)
{flag = 0;
}
//由多个空格分隔单词的情况,忽略多余的空格
else if (flag == 1 && is_spacewhite(c) == TRUE)
{continue;
}
//当前字符为空格是单词数加1
if (is_spacewhite(c) == TRUE)
{
n++;
flag = 1;
}
}
//如果字符串以一个或多个空格结尾,不计数(单词数减1)
if (is_spacewhite(*(buf + i - 1)) == TRUE)
n--;
return n;
}static ssize_t word_count_read(struct file *file, char __user *buf,
size_t count, loff_t *ppos)
{
unsigned char temp[4];
printk("xiaoshuilin word count read");
temp[0] = word_count >> 24;
temp[1] = word_count >> 16;
temp[2] = word_count >> 8;
temp[3] = word_count;
//由于驱动程序是运行在内核空间,而我们的android程序是运行在用户空间,他们之间是不能直接交互的需要借助一些接口来实现数据的交互copy_to_user copy_from_user 这两个方法就linux提供的接口
if (copy_to_user(buf, (void*) temp, 4))
{
return -EINVAL;
}
printk("xiaoshuilin word count read:%d", (int) count);
return count;
}static ssize_t word_count_write(struct file *file, const char __user *buf,
size_t count, loff_t *ppos)
{
ssize_t written = count;
printk("xiao word count write");
if (copy_from_user(mem, buf, count))
{
return -EINVAL;
}
mem[count] = '\0';
word_count = get_word_count(mem);
printk("xiao write:word count:%d\n", (int) word_count);
return written;
}//描述与设备文件触发的事件对应的回调函数指针
static struct file_operations dev_fops =
{ .owner = THIS_MODULE, .read = word_count_read, .write = word_count_write };
//描述设备文件的信息
static struct miscdevice misc =
{ .minor = MISC_DYNAMIC_MINOR, .name = DEVICE_NAME, .fops = &dev_fops };
//初始化Linux驱动
static int __init word_count_init(void)
{
int ret;
//建立设备文件
ret = misc_register(&misc);
//输出日志信息
printk("xiao word_count_init_successret=%d\n",ret);
return ret;
}// 卸载Linux驱动
static void __exit word_count_exit(void)
{
//删除设备文件
misc_deregister(&misc);
//输出日志信息
printk("word_count_init_exit_success\n");
} //注册初始化Linux驱动的函数,驱动程序的入口,相当于activity里面的oncreate
module_init( word_count_init);
//注册卸载Linux驱动的函数驱动程序的出口,相当activity里面的destroy
module_exit( word_count_exit);
MODULE_AUTHOR("lining");
MODULE_DESCRIPTION("statistics of word count.");
MODULE_ALIAS("word count module.");
MODULE_LICENSE("GPL");
至此驱动程序添加完成,不过我们还需要为其添加读写权限:
system\core\rootdir\eventd.rc## xiao
/dev/wordcount0666rootroot
至此驱动部分添加完成。
二、framworks层的代码添加,以及应用层的调用
思路:添加一个类似activityManager的服务,来完成应用层调用驱动。
1.添加服务
frameworks\base\services\java\com\android\server\SystemServer.java
private void startOtherServices() {
......省略不相关的代码
WordCountManagerService WordCountManager = null;
//addworcountManaerService
try{
traceBeginAndSlog("WordCountManagerService");
Slog.e(TAG, "start WordCountManagerService now");
WordCountManager = new WordCountManagerService(context);
ServiceManager.addService(Context.WORDCOUNT_SERVICE, WordCountManager); //把实例保存起来为应用层调用做准备
traceEnd();
}catch(Throwable e){
Slog.e(TAG, "start WordCountManagerService fail:"+e.toString());
reportWtf("starting WordCountManagerService fail", e);
}
}
WordCountManagerService 代码:
/*
* Copyright (C) 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 com.android.server;
import android.util.Log;
import android.content.Context;
import android.app.IWordCountManager;
//M: change default to public as DataShapingService
public class WordCountManagerService extends IWordCountManager.Stub {
private final String TAG="XIAO-WordCountManagerService";
private final Context mContext;
public WordCountManagerService(Context context){
mContext=context;
Log.d(TAG,"init WordCountManagerService");
}
@Override
public String read(){
String readOpen=readFromEvent();
Log.d(TAG,"readOpen form jni: "+readOpen);
return readOpen;
}@Override
public void writer(String data){
Log.d(TAG,"writer to jni: "+data);
writerToEvent(data);
} private native String readFromEvent();
private native void writerToEvent(String writer);
}
frameworks\base\core\java\android\app\SystemServiceRegistry.java
static {
............省略不相关代码
//通过这个代码的实现,后续在应用层中通过getSystemService(WordCountManager.class),就可以获取到WordCountManager registerService(Context.WORDCOUNT_SERVICE, WordCountManager.class,
new CachedServiceFetcher() {
@Override
public WordCountManager createService(ContextImpl ctx) throws ServiceNotFoundException {
IBinder b = ServiceManager.getServiceOrThrow(Context.WORDCOUNT_SERVICE);
IWordCountManager service = IWordCountManager.Stub.asInterface(b);
return new WordCountManager(service);
}});
}
frameworks\base\core\java\android\app\IWordCountManager.aidl
interface IWordCountManager {
String read();
void writer(String data);
frameworks\base\core\java\android\app\WordCountManager.java
package android.app;
import android.os.RemoteException;
public class WordCountManager {
privatefinal String TAG = "XIAO-WordCountManager";
private final IWordCountManager mService;
public WordCountManager(IWordCountManager mService) {
this.mService = mService;
}public String read() {
String data=https://www.it610.com/article/null;
try {
data= mService.read();
} catch (RemoteException ex) {
ex.printStackTrace();
}
return data;
}public void writer(String data) {
try {
mService.writer(data);
} catch (RemoteException ex) {
ex.printStackTrace();
}
}}
此处服务添加完成,不过还需要Android.mk上做修改否则会出现找不到类的情况。
frameworks\base\Android.mk
LOCAL_SRC_FILES += \
core/java/android/app/IWordCountManager.aidl
2.增加服务与驱动的交互,服务是java层代码,驱动是C/C++。所以我们需要增加一个JNI。
frameworks\base\services\core\jni\com_android_server_WordCountManagerService.cpp
/* //device/libs/android_runtime/android_server_AlarmManagerService.cpp
**
** 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.
*/#define LOG_TAG "WordCountManagerService"#include
#include "jni.h"
#include
#include
#include #include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include namespace android { char* jstring_to_pchar(JNIEnv* env, jstring str)
{
char* pstr = NULL;
jclass clsstring = env->FindClass("java/lang/String");
jstring strencode = env->NewStringUTF("utf-8");
jmethodID mid = env->GetMethodID(clsstring, "getBytes",
"(Ljava/lang/String;
)[B");
jbyteArray byteArray = (jbyteArray)(
(env)->CallObjectMethod(str, mid, strencode));
jsize size = (env)->GetArrayLength( byteArray);
jbyte* pbyte = (env)->GetByteArrayElements(byteArray, JNI_FALSE);
if (size > 0)
{
pstr = (char*) malloc(size);
memcpy(pstr, pbyte, size);
}
env->DeleteLocalRef(clsstring);
return pstr;
}static void android_server_WordCountManagerService_writerToEvent(JNIEnv* env, jobject obj, jstring data)
{int dev;
dev = open("/dev/wordcount", O_WRONLY);
char* pstr = jstring_to_pchar(env, data);
ALOGD("XIAO-android_server_WordCountManagerService_writerToEvent dev=%d ,pstr=%s\n",dev,pstr);
//const char* pstr = env->GetStringUTFChars(data, NULL);
if (pstr != NULL)
{
ssize_t write_size= write(dev,pstr, strlen(pstr));
ALOGD("XIAO-android_server_WordCountManagerService_writerToEvent write_size=%d \n",write_size);
}
close(dev);
}static jstring android_server_WordCountManagerService_readFromEvent(JNIEnv* env, jobject obj)
{
int dev;
int size;
char* buf=NULL;
struct stat statbuf;
dev = open("/dev/wordcount", O_RDONLY);
if(dev!=-1){
fstat(dev,&statbuf);
size=statbuf.st_size;
}else{
size=50;
}
size=50;
char bufs[size];
buf=bufs;
ssize_t read_size=read(dev, buf, size);
ALOGD("XIAO-android_server_WordCountManagerService_readFromEvent dev=%d ,size=%d\n",dev,size);
ALOGD("XIAO-android_server_WordCountManagerService_readForEvent buf=%s, read_size=%d \n",buf,read_size);
if(buf!=NULL){
jstring data=https://www.it610.com/article/env->NewStringUTF(buf);
ALOGD("XIAO-android_server_WordCountManagerService_readForEvent data=https://www.it610.com/article/%s /n",data);
close(dev);
return data;
} close(dev);
return NULL;
}
/// M: added for powerOffAlarm feature @{static const JNINativeMethod sMethods[] = {
/* name, signature, funcPtr */
{"writerToEvent", "(Ljava/lang/String;
)V", (void*)android_server_WordCountManagerService_writerToEvent},
{"readFromEvent", "()Ljava/lang/String;
", (void*)android_server_WordCountManagerService_readFromEvent},
};
int register_android_server_WordCountManagerServic(JNIEnv* env)
{
return jniRegisterNativeMethods(env, "com/android/server/WordCountManagerService",
sMethods, NELEM(sMethods));
}} /* namespace android */
frameworks\base\services\core\jni\Android.mk
LOCAL_SRC_FILES += \
$(LOCAL_REL_DIR)/com_android_server_WordCountManagerService.cpp
frameworks\base\services\core\jni\onload.cpp
namespace android {
int register_android_server_WordCountManagerServic(JNIEnv* env); //添加动态注销JNI的方法。
}
extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
{
JNIEnv* env = NULL;
jint result = -1;
if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
ALOGE("GetEnv failed!");
return result;
}
ALOG_ASSERT(env, "Could not retrieve the env!");
register_android_server_WordCountManagerServic(env); //调用注册方法
}
【#|我的第一个Android 驱动程序,驱动层 到framworks层】
推荐阅读
- 数据结构和算法|LeetCode 的正确使用方式
- #|7.分布式事务管理
- #|算法设计与分析(Java实现)——贪心算法(集合覆盖案例)
- #|算法设计与分析(Java实现)—— 动态规划 (0-1 背包问题)
- #|阿尔法点亮LED灯(一)汇编语言
- #|Multimedia
- #|ARM裸机开发(汇编LED灯实验(I.MX6UL芯片))
- 基础课|使用深度优先搜索(DFS)、广度优先搜索(BFS)、A* 搜索算法求解 (n^2 -1) 数码难题,耗时与内存占用(时空复杂度)对比(附((n^2 - 1) 数码问题控
- #|学习笔记 | Ch05 Pandas数据清洗 —— 缺失值、重复值、异常值
- win10|搏一搏 单车变摩托,是时候捣鼓一下家中的小米电视机啦。