Android Mokoid Open Source Project hacking

/*****************************************************************************
 *                Android Mokoid Open Source Project hacking
 *
 * 声明:
 *     1. 本文主要是为了了解Android HAL工作机制,从而决定分析mokoid开源项目;
 *     2. 源代码URL:https://code.google.com/p/mokoid/source/checkout;
 *     3. 本文通过从应用层-->HAL层逐层跟踪的方式进行代码分析,是为了得到整个
 *         Android框架的调用流程体系以及存在的原因;
 *     4. 本人在也在网上找了一些分析资料,无法从中找到连贯的思绪,于是决定
 *         自己整这个符合自己的思维习惯的代码解析,如果看你这些觉得难受,
 *         那就也自己动手分析,别人的终归是别人的,自己的才是自己的;
 *     5. Demo 1 重要的调用访问线路图:
 *         onCreate() <-- LedClient.java                      实现接口          aidl工具生成接口        接口定义
 *             _init() <-- new LedService() <-- LedService.java <== ILedService.Stub <-- ILedService.aidl <-- <interface>ILedService
 *                 hw_get_module() <-- mokoid_init() <-- com_mokoid_server_LedService.cpp
 *                     hardware.c <-- hardware.h
 *                         led.c <-- led.h
 *     6. Demo 2 重要的调用访问线路图:
 *         onCreate() <-- LedTest.java
 *             startService() <-- "com.mokoid.systemserve" <-- AndroidManifest.xml
 *                 new LedService()<-- LedSystemServer.java
 *                     hw_get_module() <-- mokoid_init() <--com_mokoid_server_LedService.cpp
 *                         hardware.c <-- hardware.h
 *                             led.c <-- led.h
 *                     ServiceManager.addService()<-- LedSystemServer.java
 *             LedManager.java
 *                 ILedService.Stub.asInterface() <-- ServiceManager.getService() <-- LedManager() <-- LedService.java <== ILedService.Stub <-- ILedService.aidl <-- <interface>ILedService
 *                     <interface>ILedService
 *                         这个接口对应上面的new LedService()实例,所以可以直接调用。
 *
 *                                   2015-6-27 晴 深圳 南山平山村 曾剑锋
 ****************************************************************************/

            \\\\\\\\\\\\\\\\\\\\\\\-*- 目录 -*-/////////////////////
            |  参考文章:
            |  一、代码工程文件架构:
            |  二、Demo 1 LedClient.java 跟踪:
            |  三、Demo 1 LedService.java 跟踪:
            |  四、Demo 1 ILedService.aidl 跟踪:
            |  五、Demo 1 Android.mk 跟踪:
            |  六、Demo 1 com_mokoid_server_LedService.cpp 跟踪:
            |  七、Demo 1 hardware.h 跟踪:
            |  八、Demo 1 led.c 跟踪:
            |  九、Demo 1 led.h 跟踪:
            |  十、Demo 2 LedTest.java 跟踪:
            |  十一、Demo 2 AndroidManifest.xml 跟踪:
            |  十二、Demo 2 LedSystemServer.java 跟踪:
            |  十三、Demo 2 LedManager.java 跟踪:
            \\\\\\\\\\\\\\\\\\\\\\\\\\\/////////////////////////////

参考文章:
    1. Android AIDL使用详解
        http://blog.csdn.net/luoshengyang/article/details/6677029
    2. 在Ubuntu上为Android系统编写Linux内核驱动程序
        http://blog.csdn.net/luoshengyang/article/details/6568411

一、代码工程文件架构:
    .
    ├── Android.mk
    ├── apps                // 应用层软件,提供了2个Demo
    │   ├── Android.mk
    │   ├── LedClient       // Demo 1
    │   │   ├── AndroidManifest.xml
    │   │   ├── Android.mk
    │   │   └── src
    │   │       └── com
    │   │           └── mokoid
    │   │               └── LedClient
    │   │                   └── LedClient.java
    │   └── LedTest         // Demo 2
    │       ├── AndroidManifest.xml
    │       ├── Android.mk
    │       └── src
    │           └── com
    │               └── mokoid
    │                   └── LedTest
    │                       ├── LedSystemServer.java
    │                       └── LedTest.java
    ├── dma6410xp      // 这部分可以不用考虑
    │   ├── AndroidBoard.mk
    │   ├── AndroidProducts.mk
    │   ├── BoardConfig.mk
    │   ├── dma6410xp.mk
    │   ├── init.dma6410xp.rc
    │   ├── init.goldfish.sh
    │   └── init.rc
    ├── frameworks          // 框架层软件
    │   ├── Android.mk
    │   └── base
    │       ├── Android.mk
    │       ├── core
    │       │   └── java
    │       │       └── mokoid
    │       │           └── hardware
    │       │               ├── ILedService.aidl
    │       │               └── LedManager.java
    │       └── service
    │           ├── Android.mk
    │           ├── com.mokoid.server.xml
    │           ├── java
    │           │   └── com
    │           │       └── mokoid
    │           │           └── server
    │           │               └── LedService.java
    │           └── jni
    │               ├── Android.mk
    │               └── com_mokoid_server_LedService.cpp
    ├── hardware            // HAL层
    │   ├── Android.mk
    │   ├── libled
    │   │   ├── Android.mk
    │   │   └── libled.c
    │   └── modules
    │       ├── Android.mk
    │       ├── include
    │       │   └── mokoid
    │       │       └── led.h
    │       └── led
    │           ├── Android.mk
    │           └── led.c
    ├── hardware.h
    └── README.txt

二、Demo 1 LedClient.java 跟踪:
    // cat mokoid-master\apps\LedClient\src\com\mokoid\LedClient\LedClient.java
    package com.mokoid.LedClient;
    // 如果找不到类,可以通过导入的类来得知文件存在哪里
    import com.mokoid.server.LedService;       >-----------------+
                                                                 |
    import android.app.Activity;                                 |
    import android.os.Bundle;                                    |
    import android.widget.TextView;                              |
                                                                 |
    public class LedClient extends Activity {                    |
        @Override                                                |
        public void onCreate(Bundle savedInstanceState) {        |
            super.onCreate(savedInstanceState);                  |
                                                                 |
            // Call an API on the library.                       |
            // 创建Led灯服务对象,跟踪LedService类               |
            LedService ls = new LedService();     <--------------+
            ls.setOn(1);                                // 点亮第一个灯
            ls.setOff(2);                               // 关闭第二个灯

            TextView tv = new TextView(this);
            tv.setText("LED 1 is on. LED 2 is off.");   // 显示提示内容
            setContentView(tv);                         // 显示文本内容
        }
    }

三、Demo 1 LedService.java 跟踪:
    // cat mokoid-master\frameworks\base\service\java\com\mokoid\server\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;   >------------------------------+  // 跟踪接口
                                                                         |
    /**                                                                  |
     * ILedService.Stub就是ILedService.aidl由aidl工具自动生成的类。      |
     * Android Interface Definition Language (AIDL):                     |
     * The AIDL compiler creates an interface in the Java programming    |
     * language from your AIDL interface. This interface has an inner    |
     * abstract class named Stub that inherits the interface (and        |
     * implements a few additional methods necessary for the IPC call).  |
     * You must create a class that extends YourInterface.Stub and       |
     * implements the methods you declared in your .aidl file.           |
     */                                                                  |
    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);
    }

四、Demo 1 ILedService.aidl 跟踪:
    // cat mokoid-master\frameworks\base\core\java\mokoid\hardware\ILedService.aidl
    package mokoid.hardware;

    interface ILedService
    {
        boolean setOn(int led);
        boolean setOff(int led);
    }

五、Demo 1 Android.mk 跟踪:
    // cat mokoid-master\frameworks\base\service\jni\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:=         onload.cpp         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)

六、Demo 1 com_mokoid_server_LedService.cpp 跟踪:
    // cat mokoid-master\frameworks\base\service\jni\com_mokoid_server_LedService.cpp
    #define LOG_TAG "Mokoid"
    #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) {
        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;

        // 接下来需要跟踪这一部分的代码,如何获取这一部分的内容
        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;
    }

    // --------------------------------------------------------------------------

    /*
     * Array of methods.
     *
     * Each entry has three fields: the name of the method, the method
     * signature, and a pointer to the native implementation.
     * 这里对应class LedService中的本地方法
     * 函数register_mokoid_server_LedService会把以C/C++实现的接口注册为java可调用的接口
     */
    static const JNINativeMethod gMethods[] = {
        { "_init",          "()Z",  (void *)mokoid_init },
        { "_set_on",        "(I)Z", (void *)mokoid_setOn },
        { "_set_off",       "(I)Z", (void *)mokoid_setOff },
    };

    /**
     * 在android源代码的注册该方法frameworks/base/services/jni/onload.cpp
     *  cat frameworks/base/services/jni/onload.cpp
     *      #include "JNIHelp.h"
     *      #include "jni.h"
     *      #include "utils/Log.h"
     *      #include "utils/misc.h"
     *
     *      namespace android {
     *      int register_android_server_AlarmManagerService(JNIEnv* env);
     *      int register_android_server_BatteryService(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_SerialService(JNIEnv* env);
     *      int register_android_server_UsbDeviceManager(JNIEnv* env);
     *      int register_android_server_UsbHostManager(JNIEnv* env);
     *      int register_android_server_VibratorService(JNIEnv* env);
     *      int register_android_server_SystemServer(JNIEnv* env);
     *      int register_android_server_location_GpsLocationProvider(JNIEnv* env);
     *      int register_android_server_connectivity_Vpn(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_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_BatteryService(env);
     *          register_android_server_UsbDeviceManager(env);
     *          register_android_server_UsbHostManager(env);
     *          register_android_server_VibratorService(env);
     *          register_android_server_SystemServer(env);
     *          register_android_server_location_GpsLocationProvider(env);
     *          register_android_server_connectivity_Vpn(env);
     *
     *          return JNI_VERSION_1_4;
     *      }
     *
     */
    int register_mokoid_server_LedService(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;
    }

七、Demo 1 hardware.h 跟踪:
    // android 源代码里 cat hardware/libhardware/include/hardware/hardware.h
    /*
     * Copyright (C) 2008 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.
     */

    #ifndef ANDROID_INCLUDE_HARDWARE_HARDWARE_H
    #define ANDROID_INCLUDE_HARDWARE_HARDWARE_H

    #include <stdint.h>
    #include <sys/cdefs.h>

    #include <cutils/native_handle.h>
    #include <system/graphics.h>

    __BEGIN_DECLS

    /*
     * Value for the hw_module_t.tag field
     * 这里提供字符合成方式
     */
    #define MAKE_TAG_CONSTANT(A,B,C,D) (((A) << 24) | ((B) << 16) | ((C) << 8) | (D))

    /**
     * 需要合成的module、device的tag
     */
    #define HARDWARE_MODULE_TAG MAKE_TAG_CONSTANT(‘H‘, ‘W‘, ‘M‘, ‘T‘)
    #define HARDWARE_DEVICE_TAG MAKE_TAG_CONSTANT(‘H‘, ‘W‘, ‘D‘, ‘T‘)

    /**
     * 提供硬件api版本合成方法
     */
    #define HARDWARE_MAKE_API_VERSION(maj,min) \
                ((((maj) & 0xff) << 8) | ((min) & 0xff))

    #define HARDWARE_MAKE_API_VERSION_2(maj,min,hdr) \
                ((((maj) & 0xff) << 24) | (((min) & 0xff) << 16) | ((hdr) & 0xffff))
    #define HARDWARE_API_VERSION_2_MAJ_MIN_MASK 0xffff0000
    #define HARDWARE_API_VERSION_2_HEADER_MASK  0x0000ffff

    /*
     * The current HAL API version.   -->  当前的硬件api版本 1.0
     *
     * All module implementations must set the hw_module_t.hal_api_version field
     * to this value when declaring the module with HAL_MODULE_INFO_SYM.
     *
     * Note that previous implementations have always set this field to 0.
     * Therefore, libhardware HAL API will always consider versions 0.0 and 1.0
     * to be 100% binary compatible.
     *
     * 设置当前版本为1.0
     */
    #define HARDWARE_HAL_API_VERSION HARDWARE_MAKE_API_VERSION(1, 0)

    /*
     * Helper macros for module implementors.  -->  提供的版本生成宏
     *
     * The derived modules should provide convenience macros for supported
     * versions so that implementations can explicitly specify module/device
     * versions at definition time.
     *
     * Use this macro to set the hw_module_t.module_api_version field.
     */
    #define HARDWARE_MODULE_API_VERSION(maj,min) HARDWARE_MAKE_API_VERSION(maj,min)
    #define HARDWARE_MODULE_API_VERSION_2(maj,min,hdr) HARDWARE_MAKE_API_VERSION_2(maj,min,hdr)

    /*
     * Use this macro to set the hw_device_t.version field
     */
    #define HARDWARE_DEVICE_API_VERSION(maj,min) HARDWARE_MAKE_API_VERSION(maj,min)
    #define HARDWARE_DEVICE_API_VERSION_2(maj,min,hdr) HARDWARE_MAKE_API_VERSION_2(maj,min,hdr)

    struct hw_module_t;
    struct hw_module_methods_t;
    struct hw_device_t;

    /**
     * 每一个硬件模块都一个HAL_MODULE_INFO_SYM结构体
     * Every hardware module must have a data structure named HAL_MODULE_INFO_SYM
     * and the fields of this data structure must begin with hw_module_t
     * followed by module specific information.
     */
    typedef struct hw_module_t {
        /** tag must be initialized to HARDWARE_MODULE_TAG */
        /** 这个tag的值必须初始化为 HARDWARE_MODULE_TAG */
        uint32_t tag;

        /**
         * 对于模块实现的版本,模块开发者有责任更新版本
         * The API version of the implemented module. The module owner is
         * responsible for updating the version when a module interface has
         * changed.
         *
         * The derived modules such as gralloc and audio own and manage this field.
         * The module user must interpret the version field to decide whether or
         * not to inter-operate with the supplied module implementation.
         * For example, SurfaceFlinger is responsible for making sure that
         * it knows how to manage different versions of the gralloc-module API,
         * and AudioFlinger must know how to do the same for audio-module API.
         *
         * The module API version should include a major and a minor component.
         * For example, version 1.0 could be represented as 0x0100. This format
         * implies that versions 0x0100-0x01ff are all API-compatible.
         *
         * In the future, libhardware will expose a hw_get_module_version()
         * (or equivalent) function that will take minimum/maximum supported
         * versions as arguments and would be able to reject modules with
         * versions outside of the supplied range.
         */
        uint16_t module_api_version;
    #define version_major module_api_version
        /**
         * version_major/version_minor defines are supplied here for temporary
         * source code compatibility. They will be removed in the next version.
         * ALL clients must convert to the new version format.
         */

        /**
         * The API version of the HAL module interface. This is meant to
         * version the hw_module_t, hw_module_methods_t, and hw_device_t
         * structures and definitions.
         *
         * The HAL interface owns this field. Module users/implementations
         * must NOT rely on this value for version information.
         *
         * Presently, 0 is the only valid value.
         */
        uint16_t hal_api_version;
    #define version_minor hal_api_version

        /** Identifier of module */
        /** 模块的标识符,独一无二的,用于区分各个模块,也用于获取模块 */
        const char *id;

        /** Name of this module */
        /** 模块的名字 */
        const char *name;

        /** Author/owner/implementor of the module */
        /** 模块的实现者 */
        const char *author;

        /** Modules methods */
        struct hw_module_methods_t* methods;

        /** module‘s dso */
        void* dso;

        /** padding to 128 bytes, reserved for future use */
        uint32_t reserved[32-7];

    } hw_module_t;

    typedef struct hw_module_methods_t {
        /** Open a specific device */
        /** 目前唯一的方法,打开一个设备的方法 */
        int (*open)(const struct hw_module_t* module, const char* id,
                struct hw_device_t** device);

    } hw_module_methods_t;

    /**
     * Every device data structure must begin with hw_device_t
     * followed by module specific public methods and attributes.
     */
    typedef struct hw_device_t {
        /** tag must be initialized to HARDWARE_DEVICE_TAG */
        uint32_t tag;

        /**
         * Version of the module-specific device API. This value is used by
         * the derived-module user to manage different device implementations.
         *
         * The module user is responsible for checking the module_api_version
         * and device version fields to ensure that the user is capable of
         * communicating with the specific module implementation.
         *
         * One module can support multiple devices with different versions. This
         * can be useful when a device interface changes in an incompatible way
         * but it is still necessary to support older implementations at the same
         * time. One such example is the Camera 2.0 API.
         *
         * This field is interpreted by the module user and is ignored by the
         * HAL interface itself.
         */
        uint32_t version;

        /** reference to the module this device belongs to */
        /** 指向设备所属的硬件模块 */
        struct hw_module_t* module;

        /** padding reserved for future use */
        uint32_t reserved[12];

        /** Close this device */
        /** 关闭设备的方法 */
        int (*close)(struct hw_device_t* device);

    } hw_device_t;

    /**
     * Name of the hal_module_info
     */
    #define HAL_MODULE_INFO_SYM         HMI

    /**
     * Name of the hal_module_info as a string
     */
    #define HAL_MODULE_INFO_SYM_AS_STR  "HMI"

    /**
     * 通过id获取模块
     * Get the module info associated with a module by id.
     *
     * @return: 0 == success, <0 == error and *module == NULL
     */
    // jni中通过这个来获取底层的模块
    int hw_get_module(const char *id, const struct hw_module_t **module);  

    /**
     * Get the module info associated with a module instance by class ‘class_id‘
     * and instance ‘inst‘.
     *
     * Some modules types necessitate multiple instances. For example audio supports
     * multiple concurrent interfaces and thus ‘audio‘ is the module class
     * and ‘primary‘ or ‘a2dp‘ are module interfaces. This implies that the files
     * providing these modules would be named audio.primary.<variant>.so and
     * audio.a2dp.<variant>.so
     *
     * @return: 0 == success, <0 == error and *module == NULL
     */
    int hw_get_module_by_class(const char *class_id, const char *inst,
                               const struct hw_module_t **module);

    __END_DECLS

    #endif  /* ANDROID_INCLUDE_HARDWARE_HARDWARE_H */

八、Demo 1 led.c 跟踪:
    // cat mokoid-master\hardware\modules\led\led.c
    #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>

    /*****************************************************************************/

    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);
        }
        return 0;
    }

    int led_on(struct led_control_device_t *dev, int32_t led)
    {
        LOGI("LED Stub: set %d on.", led);

        return 0;
    }

    int led_off(struct led_control_device_t *dev, int32_t led)
    {
        LOGI("LED Stub: set %d off.", led);

        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));

        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;

    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 Stub",
            author: "The Mokoid Open Source Project",
            methods: &led_module_methods,
        }
        /* supporting APIs go here */
    };

九、Demo 1 led.h 跟踪:
    // cat mokoid-master\hardware\modules\include\mokoid\led.h
    #include <hardware/hardware.h>

    #include <fcntl.h>
    #include <errno.h>

    #include <cutils/log.h>
    #include <cutils/atomic.h>

    /***************************************************************************/

    struct led_module_t {
       struct hw_module_t common;
    };

    struct led_control_device_t {
       struct hw_device_t common;

       /* attributes */
       int fd;

       /* supporting control APIs go here */
       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"

十、Demo 2 LedTest.java 跟踪:
    // cat mokoid-master\apps\LedTest\src\com\mokoid\LedTest\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.
            // 开启服务程序,Intent中的名字在AndroidManifest.xml中有配置
            startService(new Intent("com.mokoid.systemserver"));

            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.");
                // 创建一个LedManager,会去获取已经注册了的一个模块
                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);
        }
    }

十一、Demo 2 AndroidManifest.xml 跟踪:
    // cat mokoid-master\apps\LedTest\AndroidManifest.xml
    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.mokoid.LedTest"
        android:sharedUserId="android.uid.system">

        <uses-permission android:name="android.permission.ACCESS_CHECKIN_PROPERTIES"/>
        <uses-permission android:name="android.permission.READ_USER_DICTIONARY"/>
        <uses-permission android:name="android.permission.WRITE_USER_DICTIONARY"/>

        <application>

            <!-- This tells the system about the custom library used by the
                 application, so that it can be properly loaded and linked
                 to the app when the app is initialized. -->
            <uses-library android:name="com.mokoid.server" />

            <activity android:name=".LedTest">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN"/>
                    <category android:name="android.intent.category.LAUNCHER"/>
                </intent-filter>
            </activity>
            <service android:name=".LedSystemServer"
                      android:process=".LedSystemServer" >
                <intent-filter>
                    <action android:name="com.mokoid.systemserver"/>  <!-- 启动服务名 -->
                    <category android:name="android.intent.category.DEFAULT"/>
                </intent-filter>
            </service>
        </application>
    </manifest>

十二、Demo 2 LedSystemServer.java 跟踪:
    // cat mokoid-master\apps\LedTest\src\com\mokoid\LedTest\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. */
            // 创建Led服务对象
            LedService ls = new LedService();

            try {
                // 将Led服务对象添加到系统服务管理器中去
                // 这样其他的进程、线程就可以通过系统服务管理器获取Led服务对象
                ServiceManager.addService("led", ls);
            } catch (RuntimeException e) {
                Log.e("LedSystemServer", "Start LedService failed.");
            }
        }
    }

十三、Demo 2 LedManager.java 跟踪:
    // cat mokoid-master\frameworks\base\core\java\mokoid\hardware\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() {

            // 从系统服务管理中获取ledservice实例
            // ILedService.Stub.asInterface,目前对这个部分还是不是很了解
            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;
        }
    }
时间: 2024-10-06 12:40:39

Android Mokoid Open Source Project hacking的相关文章

Welcome to the Android Open Source Project!

Android is an open-source software stack for a wide range of mobile devices and a corresponding open-source project led by Google. Here you can find the information and source code you need to learn more about the Android platform. From there you can

Mac Error Create Android Project - “Errors running builder &#39;Android Resource Manager&#39; on project”

http://stackoverflow.com/questions/18096315/mac-error-create-android-project-errors-running-builder-android-resource-man 在mac笔记本上运行android eclipse报标题的错误,然后在stackoverflow上找到了答案 18down votefavorite 5 I spent the whole day just trying to create a simple

Android Studio之导入Project

Android Studio之导入Project Android Studio到现在已经发展到0.8+的版本了,最近也在试着使用它,原因是多方面的,一则毕竟是未来的趋势,二则是github上越来越多的大牛开源项目都是基于Android Studio的,因此会使用Android Studio将成为一件必须的任务. 关于Android Studio的下载和安装,网上一搜一大堆的文章,本文不准备累赘地谈论这些问题,主要说一下如何在Android Studio中导入已有的项目进去. 在具体下面的工作之前

Android Studio左边栏Project不见了?

很多Android Stuio初学者可能会一不小心把左边的Project栏给关了,结果发现找很久也没找到怎么再打开Project栏. 如图,点击左下角按钮,Project就出来了. Android Studio左边栏Project不见了?,布布扣,bubuko.com

Android开发工具全面转向Android Studio(3)——AS project/module的目录结构(与Eclipse对比)

如果AS完全还没摸懂的,建议先看下Android开发工具全面转向Android Studio(2)——AS project/module的CRUD. 1.其实AS project/module的目录结构很简单,我浓缩成2张图给总结了,先看图,再看下面的文字,因为还有些细节图上体现不出来(我这个图上的项目来源于我之前的Eclipse项目,并且有lib项目库相互依赖) 2.上面的图很直观,但也很眼花缭乱,我再针对图总结下重点和疑问点. ①在AS的世界里,文件夹都以模块(module)为单位组织的,其

报错 Android Pre Compiler&#39; on project

项目报错,Android Pre Compiler' on project 反复clean也没有办法,终于在StackOverflow找到答案, 打开项目的属性->Resources -> Resource filters. 点击   "Add..." -> Check "Exclude all", "Files and folders", "All children". 输入框输入 ".svn&q

[cocos2dx笔记004] android添加?静态库project

(基于2.2.2版本号) 这步比較麻烦,不像vs2013那样好设置.參考了非常多文章.还是不能解决这个问题.仅仅有慢慢摸索了.在这里贴出来,希望能让大家能少走点弯路. 还是其于前面的文章提到的mylib这个样例.[cocos2dx笔记003] Vs2013添加?静态库project首先进到external\mylib,用文本编辑器打Android.mk 并改动图中圈中的部分 改动结果例如以下 LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) L

Android Studio中关于Project与Module

在Android Studio中一个Project和Eclipse中的WorkSpace是相似的,而一个Module与Eclipse中的Project是相似的(大致可以这么的认为) 若在Android Studio中的一个Project(工作空间)中Import/New  1:N个Module,单个的Module直接在运行的时候选择合适的Module则会运行那个项目: 若在同一个Project中调用多个Module,需要在主Module(姑且这么认识他,作为启动的Module,默认是app目录下

Errors running builder &#39;Android Resource Manager&#39; on project &#39;DeskClock&#39;.

Errors occurred during the build. Errors running builder 'Android Resource Manager' on project 'DeskClock'. java.lang.NullPointerException delete the project and import it again. Errors running builder 'Android Resource Manager' on project 'DeskClock