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

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值