首先給出整個架構,可以看到由上而下分成,
應用程式層 LedTest.apk
框架層 mokioid.jar
--實作 Manager ( 透過 aidl 溝通 )
--實作 Service
JNI 層 libmokoid_runtime.so
HAL 層 led.goldfish.so
[root@localhost mokoid]# tree
.
|-- Android.mk
|-- apps //應用程式層 LedTest.apk
| |-- Android.mk
| `-- LedTest
| |-- Android.mk
| |-- AndroidManifest.xml
| `-- src
| `-- com
| `-- mokoid
| `-- LedTest
| |-- LedSystemServer.java
| `-- LedTest.java
|-- dma6410xp //新產品分支設定
| |-- AndroidBoard.mk //一般keypad設定在這檔案
| |-- AndroidProducts.mk //andoird building system
//會自動去找這各檔案
| |-- BoardConfig.mk //一些board feature例如driver
| |-- dma6410xp.mk
|-- frameworks //框架層 mokioid.jar
| |-- Android.mk
| `-- base
| |-- Android.mk
| |-- core
| | `-- java //Manager層
| | `-- mokoid
| | `-- hardware
| | |-- ILedService.aidl
| | `-- LedManager.java
| `-- service
| |-- Android.mk
| |-- com.mokoid.server.xml
| |-- java //Service層
| | `-- com
| | `-- mokoid
| | `-- server
| | `-- LedService.java
| `-- jni //JNI層 libmokoid_runtime.so
| |-- Android.mk
| `-- com_mokoid_server_LedService.cpp
`-- hardware //硬體抽象層 led.goldfish.so
|-- Android.mk
`-- modules
|-- Android.mk
|-- include
| `-- mokoid
| `-- led.h
`-- led
|-- Android.mk
`-- led.c
26 directories, 35 files
[root@localhost mokoid]#
dma6410xp 新產品分支設定
AndroidProduct.mk
PRODUCT_MAKEFILES := \ $(LOCAL_DIR)/dma6410xp.mkDma6410xp.mk
// 繼承generic.mk的設定 包含標準的應用程式等
$(call inherit-product, $(SRC_TARGET_DIR)/product/generic.mk)
// 將新增的應用程式加入image中
PRODUCT_PACKAGES += \
LedTest
// 將此檔案複製到正確的路徑
PRODUCT_COPY_FILES := \
vendor/mokoid/frameworks/base/service/com.mokoid.server.xml:
system/etc/permissions/com.mokoid.server.xml
// 設定name 可用 make PRODUCT-dma6410xp-eng 來編譯image
PRODUCT_NAME := dma6410xp
PRODUCT_DEVICE := dma6410xp
AndroidBoard.mk
LOCAL_PATH := $(call my-dir) ifeq ($(TARGET_PREBUILT_KERNEL),) TARGET_PREBUILT_KERNEL := $(LOCAL_PATH)/kernel endif
BoardConfig.mk
hardware 硬體抽象層
android.mk
TARGET_CPU_ABI := armeabi BOARD_USES_GENERIC_AUDIO := true USE_CAMERA_STUB := true TARGET_NO_KERNEL := true
hardware 硬體抽象層
android.mk
//目前路徑 LOCAL_PATH := $(call my-dir) //清除local變數 include $(CLEAR_VARS) // c header file路徑 LOCAL_C_INCLUDES += \ vendor/mokoid/hardware/modules/include/ LOCAL_PRELINK_MODULE := false // 編譯完的so放在system/lib/hw下 LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw LOCAL_SHARED_LIBRARIES := liblog LOCAL_SRC_FILES := led.c // 模組名稱 LOCAL_MODULE := led.goldfish // 編譯成.so include $(BUILD_SHARED_LIBRARY)
led.h
#include <hardware/hardware.h>
#include <fcntl.h>
#include <errno.h>
#include <cutils/log.h>
#include <cutils/atomic.h>
/***************************************************************************/
// 繼承 struct hw_module_t
struct led_module_t {
struct hw_module_t common;
};
// 繼承 struct hw_module_t
struct led_control_device_t {
struct hw_device_t common;
/* open device node 返回的 fd */
int fd;
/* callback function 指向 led_on led_off 實作 */
int (*set_on)(struct led_control_device_t *dev, int32_t led);
int (*set_off)(struct led_control_device_t *dev, int32_t led);
};
/***************************************************************************/
struct led_control_context_t {
struct led_control_device_t device;
};
#define LED_HARDWARE_MODULE_ID "led"
led.c
android.mk
#define LOG_TAG "MokoidLedStub"
#include <hardware/hardware.h>
#include <fcntl.h>
#include <errno.h>
#include <cutils/log.h>
#include <cutils/atomic.h>
#include <mokoid/led.h>
/**
* Definition of kernel-space driver.
*/
#define LED_DEVICE "/dev/led"
#define LED_C608 1
#define LED_C609 2
static int led_device_close(struct hw_device_t* device)
{
struct led_control_device_t* ctx =
(struct led_control_device_t*)device;
if (ctx) {
close(ctx->fd);
free(ctx);
}
return 0;
}
static int led_on(struct led_control_device_t *dev, int32_t led)
{
int fd;
LOGI("LED Stub: set %d on.", led);
fd = dev->fd;
switch (led) {
case LED_C608:
ioctl(fd, 1, &led);
break;
case LED_C609:
ioctl(fd, 1, &led);
break;
default:
return -1;
}
return 0;
}
static int led_off(struct led_control_device_t *dev, int32_t led)
{
int fd;
LOGI("LED Stub: set %d off.", led);
fd = dev->fd;
switch (led) {
case LED_C608:
ioctl(fd, 2, &led);
break;
case LED_C609:
ioctl(fd, 2, &led);
break;
default:
return -1;
}
return 0;
}
static int led_device_open(const struct hw_module_t* module,
const char* name,
struct hw_device_t** device)
{
struct led_control_device_t *dev;
dev = (struct led_control_device_t *)malloc(sizeof(*dev));
memset(dev, 0, sizeof(*dev));
//初始化 led_control_device_t
dev->common.tag = HARDWARE_DEVICE_TAG;
dev->common.version = 0;
dev->common.module = module;
dev->common.close = led_device_close;
//設定實作函數指標
dev->set_on = led_on;
dev->set_off = led_off;
*device = &dev->common;
//open led device node
dev->fd = open(LED_DEVICE, O_RDONLY);
if (dev->fd < 0)
dev->fd = 2; /* Error Handler */
led_off(dev, LED_C608);
led_off(dev, LED_C609);
success:
return 0;
}
static struct hw_module_methods_t led_module_methods = {
open: led_device_open
};
// 一定要 HAL_MODULE_INFO_SYM 這名稱
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 Stub",
author: "The Mokoid Open Source Project",
methods: &led_module_methods,
}
/* supporting APIs go here. */
};
jni 讓C與Java可以溝通 android.mk
LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) //# [optional, user, eng] //# eng = required //# optinal = no install on target LOCAL_MODULE_TAGS := eng //# This is the target being built. LOCAL_MODULE:= libmokoid_runtime //# Target install path. LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES) //# All of the source files that we will compile. LOCAL_SRC_FILES:= \ com_mokoid_server_LedService.cpp //# All of the shared libraries we link against. LOCAL_SHARED_LIBRARIES := \ libandroid_runtime \ libnativehelper \ libcutils \ libutils \ libhardware //# No static libraries. LOCAL_STATIC_LIBRARIES := //# Also need the JNI headers. LOCAL_C_INCLUDES += \ $(JNI_H_INCLUDE) \ vendor/mokoid/hardware/modules/include/ //# No specia compiler flags. LOCAL_CFLAGS += //# Don't prelink this library. For more efficient code, you may want //# to add this library to the prelink map and set this to true. LOCAL_PRELINK_MODULE := false include $(BUILD_SHARED_LIBRARY)
com_mokoid_server_LedServoce.cpp
Android.mk
#define LOG_TAG "MokoidPlatform"
#include "utils/Log.h"
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <assert.h>
#include <jni.h>
#include <mokoid/led.h>
// -----------------------------------------------------------------
struct led_control_device_t *sLedDevice = NULL;
static jboolean mokoid_setOn(JNIEnv* env, jobject thiz, jint led) {
LOGI("LedService JNI: mokoid_setOn() is invoked.");
if (sLedDevice == NULL) {
LOGI("LedService JNI: sLedDevice was not fetched correctly.");
return -1;
} else {
return sLedDevice->set_on(sLedDevice, led);
}
}
static jboolean mokoid_setOff(JNIEnv* env, jobject thiz, jint led) {
LOGI("LedService JNI: mokoid_setOff() is invoked.");
if (sLedDevice == NULL) {
LOGI("LedService JNI: sLedDevice was not fetched correctly.");
return -1;
} else {
return sLedDevice->set_off(sLedDevice, led);
}
}
/** helper APIs */
static inline int led_control_open(const struct hw_module_t* module,
struct led_control_device_t** device) {
//取得 sLedDevice instance 指標
return module->methods->open(module,
LED_HARDWARE_MODULE_ID, (struct hw_device_t**)device);
}
static jboolean
mokoid_init(JNIEnv *env, jclass clazz)
{
led_module_t* module;
//利用 hw_get_module API 取得 hw_module_t
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;
}
// --------------------------------------------------------------
static const JNINativeMethod gMethods[] =
{
//java call c function
{"_init", "()Z", (void*)mokoid_init},
{ "_set_on", "(I)Z", (void*)mokoid_setOn },
{ "_set_off", "(I)Z", (void*)mokoid_setOff },
};
static int registerMethods(JNIEnv* env) {
static const char* const kClassName =
"com/mokoid/server/LedService";
jclass clazz;
/* look up the class */
clazz = env->FindClass(kClassName);
if (clazz == NULL) {
LOGE("Can't find class %s\n", kClassName);
return -1;
}
/* register all the methods */
if (env->RegisterNatives(clazz, gMethods,
sizeof(gMethods) / sizeof(gMethods[0])) != JNI_OK)
{
LOGE("Failed registering methods for %s\n", kClassName);
return -1;
}
/* fill out the rest of the ID cache */
return 0;
}
// ----------------------------------------------------------------
/*
* 當這個so被VM載入 則呼叫此function
*/
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("ERROR: GetEnv failed\n");
goto bail;
}
assert(env != NULL);
if (registerMethods(env) != 0) {
LOGE("ERROR: PlatformLibrary native registration failed\n");
goto bail;
}
/* success -- return valid version number */
result = JNI_VERSION_1_4;
bail:
return result;
}
framework 框架層Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := \
$(call all-subdir-java-files)
LOCAL_MODULE_TAGS := eng
LOCAL_MODULE := mokoid
LOCAL_SRC_FILES += \
core/java/mokoid/hardware/ILedService.aidl
include $(BUILD_JAVA_LIBRARY)
# The JNI component
include $(CLEAR_VARS)
include $(call all-makefiles-under,$(LOCAL_PATH))
com.mokoid.server.xml
LedService.java
package com.mokoid.server;
import android.util.Config;
import android.util.Log;
import android.content.Context;
import android.os.Binder;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.IBinder;
import mokoid.hardware.ILedService;
public final class LedService extends ILedService.Stub {
static {
System.load("/system/lib/libmokoid_runtime.so");
}
public LedService() {
Log.i("LedService", "Go to get LED Stub...");
_init();
}
/*
* Mokoid LED native methods.
*/
public boolean setOn(int led) {
Log.i("MokoidPlatform", "LED On");
return _set_on(led);
}
public boolean setOff(int led) {
Log.i("MokoidPlatform", "LED Off");
return _set_off(led);
}
private static native boolean _init();
private static native boolean _set_on(int led);
private static native boolean _set_off(int led);
}
ILedService.aidl
package mokoid.hardware;
interface ILedService
{
boolean setOn(int led);
boolean setOff(int led);
}
LedManager.java
package mokoid.hardware;
import android.content.Context;
import android.os.Binder;
import android.os.Bundle;
import android.os.Parcelable;
import android.os.ParcelFileDescriptor;
import android.os.Process;
import android.os.RemoteException;
import android.os.Handler;
import android.os.Message;
import android.os.ServiceManager;
import android.util.Log;
import mokoid.hardware.ILedService;
/**
* Class that lets you access the Mokoid LedService.
*/
public class LedManager
{
private static final String TAG = "LedManager";
private ILedService mLedService;
public LedManager() {
mLedService = ILedService.Stub.asInterface(
ServiceManager.getService("led"));
if (mLedService != null) {
Log.i(TAG, "The LedManager object is ready.");
}
}
public boolean LedOn(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 LedOff(int n) {
boolean result = false;
try {
result = mLedService.setOff(n);
} catch (RemoteException e) {
Log.e(TAG, "RemoteException in LedManager.LedOff:", e);
}
return result;
}
}
apps 應用程式層
Android.mk
Android.mk
LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE_TAGS := user # This is the target being built. LOCAL_PACKAGE_NAME := LedTest # Only compile source java files in this apk. LOCAL_SRC_FILES := $(call all-java-files-under, src) # Link against the current Android SDK. LOCAL_SDK_VERSION := current # Also link against our own custom library. LOCAL_JAVA_LIBRARIES := mokoid framework # We need to assign platform key to use ServiceManager.addService. LOCAL_CERTIFICATE := platform include $(BUILD_PACKAGE)AndroidManifest.xml
LedSystemServer.java
package com.mokoid.LedTest;
import com.mokoid.server.LedService;
import android.os.IBinder;
import android.os.ServiceManager;
import android.util.Log;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
public class LedSystemServer extends Service {
@Override
public IBinder onBind(Intent intent) {
return null;
}
public void onStart(Intent intent, int startId) {
Log.i("LedSystemServer", "Start LedService...");
/* Please also see SystemServer.java for your interests. */
LedService ls = new LedService();
try {
ServiceManager.addService("led", ls);
} catch (RuntimeException e) {
Log.e("LedSystemServer", "Start LedService failed.");
}
}
}
LedTest.java
package com.mokoid.LedTest;
import mokoid.hardware.LedManager;
import com.mokoid.server.LedService;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
import android.widget.Button;
import android.content.Intent;
import android.view.View;
public class LedTest extends Activity implements View.OnClickListener {
private LedManager mLedManager = null;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Start LedService in a seperated process.
startService(new Intent("com.mokoid.systemserver"));
// Just for testing. !! PLEASE DON't DO THIS !!
//LedService ls = new LedService();
Button btn = new Button(this);
btn.setText("Click to turn LED 1 On");
btn.setOnClickListener(this);
setContentView(btn);
}
public void onClick(View v) {
// Get LedManager.
if (mLedManager == null) {
Log.i("LedTest", "Creat a new LedManager object.");
mLedManager = new LedManager();
}
if (mLedManager != null) {
Log.i("LedTest", "Got LedManager object.");
}
/** Call methods in LedService via proxy object
* which is provided by LedManager.
*/
mLedManager.LedOn(1);
TextView tv = new TextView(this);
tv.setText("LED 1 is On.");
setContentView(tv);
}
}
沒有留言:
張貼留言