代码路径:
frameworks/base/core/java/android/os/ILedService.aidl
out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/core/java/android/os/ILedService.java
frameworks/base/services/core/java/com/android/server/LedService.java
frameworks/base/services/java/com/android/server/SystemServer.java
frameworks/base/services/core/jni/onload.cpp
frameworks/base/services/core/jni/com_android_server_LedService.cpp
frameworks/base/services/core/jni/Android.mk
hardware/libhardware/include/hardware/led_hal.h
hardware/libhardware/modules/led/led_hal.c
hardware/libhardware/modules/led/Android.mk
hardware/libhardware/modules/Android.mk
out\target\common\obj\JAVA_LIBRARIES\framework_intermediates\classes.jar
一、创建AIDL
1、创建一个ILedService.aidl文件,在该文件中写入如下内容。
package android.os;
/** {@hide} */
interface ILedService
{
int ledCtrl(int which, int status);
}
2、将编写好的ILedService.aidl文件放到frameworks/base/core/java/android/os下面
3、将添加的ILedService.aidl文件在Android.mk文件中参与编译,在frameworks/base/Android.mk 添加一行
LOCAL_SRC_FILES += \
core/java/android/os/IVibratorService.aidl \
+ core/java/android/os/ILedService.aidl \
4、然后执行如下命令来编译frameworks模块
mmm frameworks/base 或者mma frameworks/base
mmm frameworks/base/core/res
最终编译的目标模块是:framework.jar
编译生成的文件的路径
out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/core/java/android/os/ILedService.java
ILedService.java内容如下所示
/*
* This file is auto-generated. DO NOT MODIFY.
* Original file: frameworks/base/core/java/android/os/ILedService.aidl
*/
package android.os;
/** {@hide} */
public interface ILedService extends android.os.IInterface
{
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements android.os.ILedService
{
private static final java.lang.String DESCRIPTOR = "android.os.ILedService";
/** Construct the stub at attach it to the interface. */
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
/**
* Cast an IBinder object into an android.os.ILedService interface,
* generating a proxy if needed.
*/
public static android.os.ILedService asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof android.os.ILedService))) {
return ((android.os.ILedService)iin);
}
return new android.os.ILedService.Stub.Proxy(obj);
}
@Override public android.os.IBinder asBinder()
{
return this;
}
@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
{
switch (code)
{
case INTERFACE_TRANSACTION:
{
reply.writeString(DESCRIPTOR);
return true;
}
case TRANSACTION_ledCtrl:
{
data.enforceInterface(DESCRIPTOR);
int _arg0;
_arg0 = data.readInt();
int _arg1;
_arg1 = data.readInt();
int _result = this.ledCtrl(_arg0, _arg1);
reply.writeNoException();
reply.writeInt(_result);
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
private static class Proxy implements android.os.ILedService
{
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote)
{
mRemote = remote;
}
@Override public android.os.IBinder asBinder()
{
return mRemote;
}
public java.lang.String getInterfaceDescriptor()
{
return DESCRIPTOR;
}
@Override public int ledCtrl(int which, int status) throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
int _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeInt(which);
_data.writeInt(status);
mRemote.transact(Stub.TRANSACTION_ledCtrl, _data, _reply, 0);
_reply.readException();
_result = _reply.readInt();
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
}
static final int TRANSACTION_ledCtrl = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
}
public int ledCtrl(int which, int status) throws android.os.RemoteException;
}
备注:添加过程中使用mmm可能会编译报错,如果报错就执行mma,然后再执行mmm就可以编译通过了
二、创建Server
1、创建一个服务端LedService.java文件,内容如下所示
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);
}
2、将LedService.java文件添加到该目录下面frameworks/base/services/core/java/com/android/server/
在SystemServer.java文件中startOtherServices()方法中添加启动LedService服务
private void startOtherServices() {
final Context context = mSystemContext;
VibratorService vibrator = null;
IStorageManager storageManager = null;
NetworkManagementService networkManagement = null;
NetworkStatsService networkStats = null;
NetworkPolicyManagerService networkPolicy = null;
ConnectivityService connectivity = null;
NetworkScoreService networkScore = null;
NsdService serviceDiscovery= null;
WindowManagerService wm = null;
SerialService serial = null;
NetworkTimeUpdateService networkTimeUpdater = null;
CommonTimeManagementService commonTimeMgmtService = null;
InputManagerService inputManager = null;
TelephonyRegistry telephonyRegistry = null;
ConsumerIrService consumerIr = null;
MmsServiceBroker mmsService = null;
HardwarePropertiesManagerService hardwarePropertiesService = null;
ConnectivityServiceEx connectivityEx = null;
//Bug 692795 PowerGuruService powerguru --> BEG
AbsPowerGuruService powerguru = null;
//Bug 692795 PowerGuruService powerguru --> END
PowerController powerctl = null;
+ Slog.i(TAG, "Led Service");
+ ServiceManager.addService("led", new LedService());
}
添加启动服务代码后,就执行如下命令编译出services.jar
mmm frameworks/base/services
最终编译的目标模块是:services.jar
备注:在services目录下面不需要把LedService.java添加进去,因为它的内容里已经把该目录下所有JAVA文件自动包含进去了,如下所示
LOCAL_SRC_FILES := $(call all-java-files-under,java)
三、创建JNI
1、创建一个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 == 0) {
/* 2. get device : module->methods->open */
err = module->methods->open(module, NULL, &device);
if (err == 0) {
/* 3. call led_open */
led_device = (led_device_t *)device;
return led_device->led_open(led_device);
} else {
return -1;
}
}
return -1;
}
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));
}
}
2、在onload.cpp文件中注册register_android_server_LedService服务
namespace android {
int register_android_server_AlarmManagerService(JNIEnv* env);
int register_android_server_BatteryStatsService(JNIEnv* env);
int register_android_server_ConsumerIrService(JNIEnv *env);
int register_android_server_InputApplicationHandle(JNIEnv* env);
int register_android_server_InputWindowHandle(JNIEnv* env);
int register_android_server_InputManager(JNIEnv* env);
int register_android_server_LightsService(JNIEnv* env);
int register_android_server_PowerManagerService(JNIEnv* env);
int register_android_server_storage_AppFuse(JNIEnv* env);
int register_android_server_SerialService(JNIEnv* env);
int register_android_server_SystemServer(JNIEnv* env);
int register_android_server_UsbDeviceManager(JNIEnv* env);
int register_android_server_UsbMidiDevice(JNIEnv* env);
int register_android_server_UsbHostManager(JNIEnv* env);
int register_android_server_vr_VrManagerService(JNIEnv* env);
int register_android_server_VibratorService(JNIEnv* env);
int register_android_server_location_ContextHubService(JNIEnv* env);
int register_android_server_location_GnssLocationProvider(JNIEnv* env);
int register_android_server_connectivity_Vpn(JNIEnv* env);
int register_android_server_connectivity_tethering_OffloadHardwareInterface(JNIEnv*);
int register_android_server_hdmi_HdmiCecController(JNIEnv* env);
int register_android_server_tv_TvUinputBridge(JNIEnv* env);
int register_android_server_tv_TvInputHal(JNIEnv* env);
int register_android_server_PersistentDataBlockService(JNIEnv* env);
int register_android_server_Watchdog(JNIEnv* env);
int register_android_server_HardwarePropertiesManagerService(JNIEnv* env);
int register_android_server_SyntheticPasswordManager(JNIEnv* env);
int register_android_server_GraphicsStatsService(JNIEnv* env);
int register_android_hardware_display_DisplayViewport(JNIEnv* env);
int register_android_server_ShutdownThread(JNIEnv* env);
+int register_android_server_LedService(JNIEnv *env);
};
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) {
ALOGE("GetEnv failed!");
return result;
}
ALOG_ASSERT(env, "Could not retrieve the env!");
register_android_server_broadcastradio_BroadcastRadioService(env);
register_android_server_broadcastradio_Tuner(vm, env);
register_android_server_PowerManagerService(env);
register_android_server_SerialService(env);
register_android_server_InputApplicationHandle(env);
register_android_server_InputWindowHandle(env);
register_android_server_InputManager(env);
register_android_server_LightsService(env);
register_android_server_AlarmManagerService(env);
register_android_server_UsbDeviceManager(env);
register_android_server_UsbMidiDevice(env);
register_android_server_UsbHostManager(env);
register_android_server_vr_VrManagerService(env);
register_android_server_VibratorService(env);
register_android_server_SystemServer(env);
register_android_server_location_ContextHubService(env);
register_android_server_location_GnssLocationProvider(env);
register_android_server_connectivity_Vpn(env);
register_android_server_connectivity_tethering_OffloadHardwareInterface(env);
register_android_server_ConsumerIrService(env);
register_android_server_BatteryStatsService(env);
register_android_server_hdmi_HdmiCecController(env);
register_android_server_tv_TvUinputBridge(env);
register_android_server_tv_TvInputHal(env);
register_android_server_PersistentDataBlockService(env);
register_android_server_Watchdog(env);
register_android_server_HardwarePropertiesManagerService(env);
register_android_server_storage_AppFuse(env);
register_android_server_SyntheticPasswordManager(env);
register_android_server_GraphicsStatsService(env);
register_android_hardware_display_DisplayViewport(env);
register_android_server_ShutdownThread(env);
+ register_android_server_LedService(env);
return JNI_VERSION_1_4;
}
3、将刚编写的com_android_server_LedService.cpp文件,在Android.mk文件中添加该文件编译到libandroid_servers.so.toc中去
$(LOCAL_REL_DIR)/com_android_server_VibratorService.cpp \
+ $(LOCAL_REL_DIR)/com_android_server_LedService.cpp \
4、编译命令
mmm frameworks/base/services
编译生成的文件
out/target/product//obj/SHARED_LIBRARIES/libandroid_servers_intermediates/libandroid_servers.so.toc
四、创建HAL
1、创建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
2、将led_hal.h文件拷贝到该目录下面:hardware\libhardware\include\hardware
3、hardware/libhardware/modules/在该目录下面创建led目录,在该目录下面创建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 0;
}
static int led_open(struct led_device_t* dev)
{
fd = open("/dev/leds", O_RDWR);
ALOGI("led_open : %d", fd);
if (fd >= 0)
return 0;
else
return -1;
}
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 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,
};
4、hardware/libhardware/modules/在该目录下面创建led目录,在该目录下面创建Android.mk文件
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := led.default
# HAL module implementation stored in
# hw/<VIBRATOR_HARDWARE_MODULE_ID>.default.so
LOCAL_MODULE_RELATIVE_PATH := hw
LOCAL_C_INCLUDES := hardware/libhardware
LOCAL_SRC_FILES := led_hal.c
LOCAL_SHARED_LIBRARIES := liblog
include $(BUILD_SHARED_LIBRARY)
5、hardware/libhardware/modules/目录下面的Android.mk中添加led模块
hardware_modules := \
audio_remote_submix \
camera \
gralloc \
hwcomposer \
input \
radio \
sensors \
thermal \
usbaudio \
usbcamera \
vehicle \
led \
vr
include $(call all-named-subdir-makefiles,$(hardware_modules))
6、编译命令
mmm hardware/libhardware/modules/led
编译生成的的文件
目标文件:out/target/product/sl8541e_cus_go/system/lib/hw/led.default.so
中间文件:out/target/product/sl8541e_cus_go/obj/SHARED_LIBRARIES/led.default_intermediates/led.default.so.toc
日志打印:
12-28 14:46:00.576 2550 2550 I LedService: native ledOpen ...
12-28 14:46:00.577 2550 2550 I LedHal : led_open : -1