#|我的第一个Android 驱动程序,驱动层 到framworks层

对于未知的技术我们心里总是比较忐忑,当你走进发现原来并不是你想象中那么难,关键是我们需要勇敢迈出第一步----------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层】

    推荐阅读