首先給出整個架構,可以看到由上而下分成,
應用程式層 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); } }
沒有留言:
張貼留言