注:整理自某个pdf
android系统从下至上分层:
kernel → HAL -->routime(虚拟机和一些其他的库)-->framework-->app
我们要添加的服务为 LedService
在 app 中直接可以这样使用
LedManager ledManage = getSystemService(Context.LED_SERVICE);
ledManager.setOn();//设置手机灯的开关
ledManager.setOff();
要达到这个上面的目的,需要在系统的 Context.java 和 ContextImpl.java 里面做如下工
作
Context.java
public static final String LED_SERVICE = "led";//添加该行
-
public Object getSystemService(String name) {
-
if (WINDOW_SERVICE.
equals(name)) {
-
return WindowManagerImpl.getDefault();
-
}
else
if (LAYOUT_INFLATER_SERVICE.
equals(name)) {
-
synchronized (mSync) {
-
LayoutInflater inflater = mLayoutInflater;
-
if (inflater !=
null) {
-
return inflater;
-
}
-
mLayoutInflater = inflater =
-
PolicyManager.makeNewLayoutInflater(getOuterContext());
-
return inflater;
-
}
-
}
else
if (ACTIVITY_SERVICE.
equals(name)) {
-
return getActivityManager();
-
}
else
if (INPUT_METHOD_SERVICE.
equals(name)) {
-
return InputMethodManager.getInstance(
this);
-
}
else
if (ALARM_SERVICE.
equals(name)) {
-
return getAlarmManager();
-
}
else
if (ACCOUNT_SERVICE.
equals(name)) {
-
return getAccountManager();
-
}
else
if (POWER_SERVICE.
equals(name)) {
-
return getPowerManager();
-
}
else
if (CONNECTIVITY_SERVICE.
equals(name)) {
-
return getConnectivityManager();
-
}
else
if (THROTTLE_SERVICE.
equals(name)) {
-
return getThrottleManager();
-
}
else
if (WIFI_SERVICE.
equals(name)) {
-
return getWifiManager();
-
}
else
if (NOTIFICATION_SERVICE.
equals(name)) {
-
return getNotificationManager();
-
}
else
if (KEYGUARD_SERVICE.
equals(name)) {
-
return
new KeyguardManager();
-
}
else
if (ACCESSIBILITY_SERVICE.
equals(name)) {
-
return AccessibilityManager.getInstance(
this);
-
}
else
if (LOCATION_SERVICE.
equals(name)) {
-
return getLocationManager();
-
}
else
if (SEARCH_SERVICE.
equals(name)) {
-
return getSearchManager();
-
}
else
if (SENSOR_SERVICE.
equals(name)) {
-
return getSensorManager();}
else
if (STORAGE_SERVICE.
equals(name)) {
-
return getStorageManager();
-
}
else
if (VIBRATOR_SERVICE.
equals(name)) {
-
return getVibrator();
-
}
else
if (STATUS_BAR_SERVICE.
equals(name)) {
-
synchronized (mSync) {
-
if (mStatusBarManager ==
null) {
-
mStatusBarManager =
new StatusBarManager(getOuterContext());
-
}
-
return mStatusBarManager;
-
}
-
}
else
if (AUDIO_SERVICE.
equals(name)) {
-
return getAudioManager();
-
}
else
if (TELEPHONY_SERVICE.
equals(name)) {
-
return getTelephonyManager();
-
}
else
if (CLIPBOARD_SERVICE.
equals(name)) {
-
return getClipboardManager();
-
}
else
if (WALLPAPER_SERVICE.
equals(name)) {
-
return getWallpaperManager();
-
}
else
if (DROPBOX_SERVICE.
equals(name)) {
-
return getDropBoxManager();
-
}
else
if (DEVICE_POLICY_SERVICE.
equals(name)) {
-
return getDevicePolicyManager();
-
}
else
if (UI_MODE_SERVICE.
equals(name)) {
-
return getUiModeManager();
-
}
else
if (DOWNLOAD_SERVICE.
equals(name)) {
-
return getDownloadManager();
-
}
else
if (NFC_SERVICE.
equals(name)) {
-
return getNfcManager();
-
}else if(LED_SERVICE.equals(name))
-
{
-
Log.d("ContextImpl", "get LedManager success");
-
return getLedManager();
-
}
-
return
null;
-
}
-
private LedManager getLedManager()
-
{
-
synchronized (mSync) {
-
if (mLedManager == null) {
-
mLedManager = new LedManager();
-
}
-
}
-
return mLedManager;
-
}
其中
LedManager
类的定义如下:
-
package android.app;
-
import android.os.RemoteException;
-
import android.os.ServiceManager;
-
import android.util.Log;
-
public
class LedManager
-
{
-
private
static
final String TAG =
"LedManager";
-
private ILedManager mLedService;
public LedManager() {
-
mLedService =
-
ILedManager.Stub.asInterface(ServiceManager.getService(
"led"));
-
if (mLedService !=
null) {
-
Log.i(TAG,
"The LedManager object is ready.");
-
}
-
}
-
public boolean setOn(int n) {
-
boolean result =
false;
-
try {
-
result = mLedService.setOn(n);
-
}
catch (RemoteException e) {
-
Log.e(TAG,
"RemoteException in LedManager.LedOn:", e);
-
}
-
return result;
-
}
-
public boolean setOff(int n) {
-
boolean result =
false;
-
try {
-
result = mLedService.setOff(n);
-
}
catch (RemoteException e) {
-
Log.e(TAG,
"RemoteException in LedManager.LedOff:", e);
-
}
-
return result;
-
}
-
}
由于我们用用
LedManager
取得一个系统服务
LedService
,所以此处就用到了一个
IPC
机制,通过
aidl
,两个进程之间进行通信,这样当操作 LedManager 的时候就如同操作 LedService 了,在这里这个 aidl 文件
如下:
-
IledManager.aidl
-
package android.app;
-
interface ILedManager
-
{
-
boolean setOn(int led);
-
boolean setOff(int led);
-
}
frameworks/base/Android.mk 文件增加:
frameworks/base/services/java/com/android/server/ LedService.java 的内容如下
LOCAL_SRC_FILES += \ core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl \ core/java/android/accessibilityservice/IEventListener.aidl \ core/java/android/accounts/IAccountManager.aidl \ core/java/android/accounts/IAccountManagerResponse.aidl \ core/java/android/accounts/IAccountAuthenticator.aidl \ core/java/android/accounts/IAccountAuthenticatorResponse.aidl \ core/java/android/app/IActivityController.aidl \ core/java/android/app/IActivityPendingResult.aidl \ core/java/android/app/IActivityWatcher.aidl \ core/java/android/app/ILedManager.aidl \ core/java/android/app/IAlarmManager.aidl \ core/java/android/app/IBackupAgent.aidl \ core/java/android/app/IInstrumentationWatcher.aidl \ core/java/android/app/INotificationManager.aidl \ core/java/android/app/ISearchManager.aidl \core/java/android/app/ISearchManagerCallback.aidl \ core/java/android/app/IServiceConnection.aidl \ core/java/android/app/IThumbnailReceiver.aidl \ core/java/android/app/ITransientNotification.aidl \ core/java/android/app/IUiModeManager.aidl \
-
import android.content.Context;
-
import android.os.ServiceManager;
-
import android.util.Log;
-
import android.os.IBinder;
-
import android.app.ILedManager;
-
public
final
class LedService extends ILedManager.Stub {
-
public LedService(Context context) {
-
Log.i(
"LedService",
"Go to get LED Stub...");
-
ServiceManager.addService(
"led", LedService.
this);
-
_init();
-
}
-
/*
-
* Mokoid LED native methods.
-
*/
-
public boolean setOn(int led) {
-
Log.i(
"MokoidPlatform",
"LED On");
-
return _setOn(led);
-
}
-
public boolean setOff(int led) {
-
Log.i(
"MokoidPlatform",
"LED Off");
-
return _setOff(led);
-
}
private static native boolean _init();
-
private static native boolean _setOn(int led);
-
private static native boolean _setOff(int led);
-
}
到此为止 我们就可以使用 LedManager 来使用 LedService 的方法了
由于 LedManager 是在我们的 app 里面,是属于我们程序的进程的,但是 LedService 是系统启动的时候就启
动的服务程序,是属于 systemServer 进程,不同的进程是不能通信的, android 采用了 aidl 的方式,底层
是采用 binder 驱动,通过共享内存来达到通信目的的。
在 ledService.java 里面有几个 native 方法,这几个方法在 java 层调用,但是实现是在 c++ 层的,这里是
通过 jni 调用来达到 java 代码调用 c++ 代码的
这里的 jni 文件如下
frameworks/base/services/jni/com_android_server_LedServic
e.cpp
这个文件名不能随便命名,要遵循 包名 _ 类名 .cpp 的原则
-
#define LOG_TAG "Dragon"
-
#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/led.h>
-
#define LOG_NDDEBUG 0 // 定义后,LOGD能够输出
-
#define LOG_NIDEBUG 0 // 定义后,LOGI能够输出
-
#define LOG_NDEBUG 0 // 定义后,LOGV能够输出
-
namespace android
-
{
-
struct led_control_device_t *sLedDevice = NULL;
-
static jboolean setOn(JNIEnv * env ,jobject clazz,jint led)
-
{
-
LOGI(
"LedService JNI: setOn() is invoked");
-
if(sLedDevice ==
NULL)
-
{
-
return
-1;
-
}
else
-
{
-
return sLedDevice->set_led_on(sLedDevice,led);
-
}
-
}
-
static jboolean setOff(JNIEnv * env ,jobject clazz,jint led)
-
{
-
LOGI(
"LedService JNI: setOff() is invoked.");
-
if (sLedDevice ==
NULL) {LOGI(
"LedService JNI: sLedDevice was not fetched correctly.");
-
return
-1;
-
}
else {
-
return sLedDevice->set_led_off(sLedDevice, led);
-
}
-
}
-
/** helper APIs */
-
static inline int led_control_open(const struct hw_module_t* module,
-
struct led_control_device_t** device) {
-
return
module->methods->open(
module,
-
LED_HARDWARE_MODULE_ID, (struct
hw_device_t**)device);
-
}
-
static jboolean init(JNIEnv * evn ,jclass clazz)
-
{
-
led_module_t *
module;
-
if(hw_get_module(LED_HARDWARE_MODULE_ID,(
const
hw_module_t **)&
module) ==
0)
-
{
-
LOGI(
"LedService JNI: LED Stub found.");
-
if (led_control_open(&
module->common, &sLedDevice) ==
0) {
-
LOGI(
"LedService JNI: Got Stub operations.");
-
return
0;
-
}
-
}
-
LOGE(
"LedService JNI: Get Stub operations failed.");
-
return
-1;
-
}
//
传统的
jni
调用,函数名也是有一定规则的,但是
android
改变了这种方式,通过一下这种方式就可以把java 层和 c++ 层的代码映射起来
// 第一个参数是 java 层要调用的方法,第二个参数是第一个参数 ( 也就是 java 层调用的函数 ) 的参数和返回
值 , 第三个参数是 c++ 层要调用的函数
-
static
const JNINativeMethod gMethods[] = {
-
{
"_init",
"()Z", (
void *)init },
-
{
"_setOn",
"(I)Z", (
void *)setOn },
-
{
"_setOff",
"(I)Z", (
void *)setOff },
-
};
//
这个函数很重要,这里是注册我们上面定义的那些方法的
-
int register_android_server_LedService(JNIEnv *env)
-
{
-
return jniRegisterNativeMethods(env,
"com/android/server/LedService",
-
gMethods, NELEM(gMethods));
-
}}
这里要注意的是,必须在下面这个函数里面调用我们上面的那个注册函数,不然编译能过,最后手机也跑不起来
frameworks/base/services/jni/onload.cpp
-
using
namespace
android;
-
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) {
-
LOGE(
"GetEnv failed!");
-
return result;
-
}
-
LOG_ASSERT(env,
"Could not retrieve the env!");
-
register_android_server_PowerManagerService(env);
-
register_android_server_InputManager(env);
-
register_android_server_LightsService(env);
-
register_android_server_AlarmManagerService(env);
-
register_android_server_BatteryService(env);
-
register_android_server_VibratorService(env);
-
register_android_server_SystemServer(env);
-
register_android_server_location_GpsLocationProvider(env);
-
register_android_server_LedService(env);
-
//加上这句就好了
-
return JNI_VERSION_1_4;
-
}
到这里我们就从
java
层彻底到了
c/c++
层了,在上面那个
cpp
文件里面的头文件有个叫做hardware/led.h 的文件,这个文件的路径是
hardware/libhardware/include/hardware/led.h
对应的 led.c 路径是
hardware/msm7k/libdragon-led/led.c 文件
这两个文件就是属于 android 的 HAL 层了
HAL 层主要是为了让硬件厂商不许要公开起驱动源代码
led.c 文件的内容如下:
-
#define LOG_TAG "LedStub"
-
#include <hardware/hardware.h>
-
#include <fcntl.h>
-
#include <errno.h>
-
#include <cutils/log.h>
-
#include <cutils/atomic.h>
-
#include <hardware/led.h>
-
#define GPG3DAT2_ON 0x4800;
-
#define GPG3DAT2_OFF 0x4801;
-
#define LOG_NDDEBUG 0 // 定义后,LOGD 能够输出
-
#define LOG_NIDEBUG 0 // 定义后,LOGI 能够输出
-
#define LOG_NDEBUG 0 // 定义后,LOGV 能够输出
-
int fd;
-
int led_device_close(struct hw_device_t * device)
-
{
-
struct led_control_device_t * ctx = (struct led_control_device_t *)device;
-
if(ctx)
-
{
-
free(ctx);
-
}
-
close(fd);
-
return
0;
-
}
-
int led_on(struct led_control_device_t *dev ,int32_t led)
-
{
-
LOGI(
"LED Stub: set *d off.",led);
-
return
0;
-
}
-
int led_off(struct led_control_device_t *dev ,int32_t led)
-
{
-
char buf[
32] ;
-
int n ;
-
LOGI(
"LED Stub: set %d off.",led);
-
//这里就调用了led驱动程序
-
if((fd = open(
"/dev/led",O_RDWR))==
-1)
-
{
-
LOGI(
"LED open error");
-
}
-
else
-
{
-
LOGI(
"LED open ok");
-
n = read(fd,buf,
32);
-
LOGI(
"LED Stub: read %s data from led driver",buf);
-
close(fd);
-
}
-
return
0;
-
}
-
static int led_device_open(const struct hw_module_t * module,const char*
-
name ,struct hw_device_t ** device)
-
{
-
//下面是填充 led_control_device_t 结构体
-
struct led_control_device_t *dev;
-
dev = (struct
led_control_device_t *)
malloc(
sizeof(*dev));
-
memset(dev,
0,
sizeof(*dev));
-
dev->common.tag = HARDWARE_DEVICE_TAG;
-
dev->common.version =
0;
-
dev->common.
module =
module;
-
dev->common.close = led_device_close;
-
dev->set_led_on = led_on;
-
dev->set_led_off = led_off;
-
*device = &dev->common;
-
success:
-
return
0;
-
}
-
static
struct hw_module_methods_t led_module_methods =
-
{
-
open: led_device_open
-
};
-
const
struct led_module_t HAL_MODULE_INFO_SYM =
-
{
-
common:
-
{
-
tag:HARDWARE_MODULE_TAG,
-
version_major:
1,
-
version_minor:
0,
-
id:LED_HARDWARE_MODULE_ID,
-
name:
"Sample LED Stud",
-
author:
"Open Source Project",
-
methods:&led_module_methods,
-
}
-
};
-
-
-
下面是
led
驱动程序的实现代码
led_driver.c
-
#include <linux/init.h>
-
#include <linux/module.h>
-
#include <linux/device.h>
-
#include <linux/kernel.h> /* printk() */
-
#include <linux/slab.h> /* kmalloc() */
-
#include <linux/fs.h> /* everything... */
-
#include <linux/errno.h> /* error codes */
-
#include <linux/types.h> /* size_t */
-
#include <linux/proc_fs.h>
-
#include <linux/fcntl.h> /* O_ACCMODE */
-
#include <asm/system.h> /* cli(), *_flags */
-
#include <asm/uaccess.h> /* copy_from/to_user */
-
#define DRIVER_AUTHOR "xxxxx"
-
#define DRIVER_DESC "HELLO WORLD DRIVER"
-
#define DEVICE_NAME "led"
-
MODULE_LICENSE(
"Dual BSD/GPL");
-
MODULE_AUTHOR(DRIVER_AUTHOR);
-
MODULE_DESCRIPTION(DRIVER_DESC);
-
int led_open(struct inode *inode, struct file *filp);
-
int led_release(struct inode *inode, struct file*filp);
-
ssize_t led_read(struct file *filp,
char *buf,
size_t count,
loff_t *f_pos);
-
ssize_t led_write(struct file *filp, __user
char *buf,
size_t count,
loff_t *f_pos);
-
void led_exit(void);
-
int led_init(void);
-
struct file_operations led_fops = {
-
read: led_read,
-
write: led_write,
-
open: led_open,
-
release: led_release
-
};
-
module_init(led_init);
-
module_exit(led_exit);
-
int led_major =
60;
-
char * led_buffer;
-
static
struct class *led_class;
-
int led_init()
-
{
-
int result;
-
result = register_chrdev(led_major,DEVICE_NAME,&led_fops);
-
if(result<
0)
-
{
-
printk(
"<1> : LED cannot obtain major number %d \n",led_major);
-
return result;
-
}
-
led_buffer = kmalloc(
2,GFP_KERNEL);
-
if(!led_buffer)
-
{
-
result = -ENOMEM;
-
goto fail;
-
}
-
memset(led_buffer,
0,
2);
-
printk(
"<1>Inserting module\n");
-
//注册一个类,使 mdev 可以在"/dev/"目录下面建立设备节点
-
led_class = class_create(THIS_MODULE, DEVICE_NAME);
-
if(IS_ERR(led_class))
-
{
-
printk(
"Err: failed in EmbedSky-leds class. \n");
-
return
-1;
-
}
-
//创建一个设备节点,节点名为 DEVICE_NAME
-
device_create(led_class,
NULL, MKDEV(led_major,
0),
NULL,
-
DEVICE_NAME);
-
//官方文档为 class_device_create(led_class, NULL, MKDEV(LED_MAJOR, 0),
-
NULL, DEVICE_NAME);
-
printk(DEVICE_NAME
" initialized\n");
-
return result;
-
}
-
void led_exit()
-
{
-
unregister_chrdev(led_major,
"");
-
if(led_buffer)
-
{
-
kfree(led_buffer);
-
}
-
printk(
"<1>LED Removing module \n");
-
}
-
//在 HAL 层调用 open()函数就相当与调用下面这个 led_open 函数
-
int led_open(struct inode *inode,struct file *filp)
-
{
-
printk(
"<1>Open device successfully\n");
-
return
0;
-
}
-
int led_release(struct inode * inode,struct file * filp)
-
{
-
printk(
"<1>Release device successfully\n");
-
return
0;
-
}
-
//在 HAL 层调用 read()函数就相当与调用下面这个 led_read 函数
-
ssize_t led_read(struct file *filp,
char * buf,
size_t count,
loff_t * f_pos)
-
{
-
int n =
0;
-
n = copy_to_user(buf,led_buffer,
sizeof(led_buffer)/
sizeof(
char);
-
printk(
"<1>read from user char is %s\n",led_buffer);
-
if(*f_pos ==
0)
-
{
-
*f_pos += n;
-
return n;
-
}
-
else
-
{
-
return *f_pos + n;
-
}
-
}
-
ssize_t led_write(struct file *filp,
char * buf,
size_t count,
loff_t * f_pos)
-
{
-
int n =
0;
-
n = copy_from_user(led_buffer,buf,
sizeof(buf)/
sizeof(
char));
-
printk(
"<1>write from user char is %s\n",led_buffer);
-
return
1;
-
}
通过以上步骤就完成了从
kernel
层到
app
层添加一个服务的功能,对于上面的驱动模块的话,是通过单独编译成 .ko 文件,然后 push 到手机里面通过 insmod 动态加载到内核里面
的 , 要看内核 log 信息可以通过 adb shell dmesg 查看,上层 log 信息通过 adb shell
logcat 查看 , 当然驱动程序也可以放在 kernel/driver/ 新建 led 文件夹 /led.c 下面直接编译
到 kernel 里面,这样就可以每次启动系统的时候自动运行驱动了,不过这样的话需要修改
源代码的配置文件 。