embedded linux ,android

2010年11月3日 星期三

Intent 與 intent-filter

AndroidManifest.xml 向 framework 登記此AP,包含哪些activity,service等,所以android接獲intent時,就有資訊可以解析哪個應用程式最符合這個intent。

Intent 可以啟動activity,service,broadcast receiver,intent 可以指定action跟data,action是指要做什麼樣的事,例如打電話或編輯文章,data則是指此action boundle在一起的資料內容,以URI格式表示。

Intent分成兩種,implicit intent與explicit intent,明確的intent表示指定要啟動的activity,而implicit intent,則是透過設定intent-filter讓系統有能力解析最適合的activity或service等,intent要由哪個應用程式接收,有三種比對的filter,分別是<action>,<category>,<data>。,而implicit intent自動加入CATEGORY_DEFAULT,如果intent-filter中沒有android.intent.category
.DEFAULT,則match就會失敗,所以要讓activity或service接收implicit intent就必須要加入android.intent.category.DEFAULT。

intent-filter 可以被包在 activity,service,receiver中
<intent-filter android:icon="drawable resource" 
               android:label="string resource" 
               android:priority="integer"> 
    <action android:name="string" />
    //可以有很多action,只要其中一項符合即可,如果intent filter
    //沒有指定action,這此AP永不被執行,若intent沒有指定action
    //,則任何app的action filter皆符合此intent
    <category android:name="string" />
    //若intent有設定Category,必須intent的每項category都通過filter設定
    //的Category,若intent沒有設定Category,則都符合此intent
    <data android:name="string" />
    //1.當filter內沒有設定任何data tag,而intent內也沒有設定URI與data type,
    //那這test就通過
    //2.當filter有設定URI,沒有設定data type,而intent object也是只有URI沒有
    //data type,這時候通過,這通常只會發生在mailto: 與tel: 時
    //3.當filter內只有設定data type 沒有設定URI,而intent object有設定相同
    //的data type無URI則通過
    //4.當filter內設定的data type與URI都與intent Object內設定的對應即通過
    //若filter內只有設定data type而URI不設定,只有在intent Object內的
    //data type有對應,而URI為content: 或file:才會通過
</intent-filter>
intent機制的好處是,要擴充功能只要發出intent,android就會去找最適合的應用程式,不需要在自己的應用程式裡加code。


網路上收集的intent範例(轉自http://ysl-paradise.blogspot.com/2008/12/intent.html)
顯示網頁
Uri uri = Uri.parse("http://google.com");  
Intent it = new Intent(Intent.ACTION_VIEW, uri);  
startActivity(it);
顯示地圖
Uri uri = Uri.parse("geo:38.899533,-77.036476");  
Intent it = new Intent(Intent.ACTION_VIEW, uri);   
startActivity(it);   
//其他 geo URI 範例  
//geo:latitude,longitude  
//geo:latitude,longitude?z=zoom  
//geo:0,0?q=my+street+address  
//geo:0,0?q=business+near+city  
//google.streetview:cbll=lat,lng&cbp=1,yaw,,pitch,zoom&mz=mapZoom
路徑規劃
Uri uri = Uri.parse("http://maps.google.com/maps?f=d&saddr=startLat%20startLng&daddr=endLat%20endLng&hl=en");  
Intent it = new Intent(Intent.ACTION_VIEW, uri);  
startActivity(it);  
//where startLat, startLng, endLat, endLng are a long with 6 decimals like: 50.123456
撥打電話
//叫出撥號程式  
Uri uri = Uri.parse("tel:0800000123");  
Intent it = new Intent(Intent.ACTION_DIAL, uri);  
startActivity(it);  
//直接打電話出去  
Uri uri = Uri.parse("tel:0800000123");  
Intent it = new Intent(Intent.ACTION_CALL, uri);  
startActivity(it);  
//用這個,要在 AndroidManifest.xml 中,加上  
//  
傳送 SMS/MMS
//叫起簡訊程式  
Intent it = new Intent(Intent.ACTION_VIEW);  
it.putExtra("sms_body", "The SMS text");   
it.setType("vnd.android-dir/mms-sms");  
startActivity(it);  
//傳送簡訊  
Uri uri = Uri.parse("smsto:0800000123");  
Intent it = new Intent(Intent.ACTION_SENDTO, uri);  
it.putExtra("sms_body", "The SMS text");  
startActivity(it);  
//傳送 MMS  
Uri uri = Uri.parse("content://media/external/images/media/23");  
Intent it = new Intent(Intent.ACTION_SEND);   
it.putExtra("sms_body", "some text");   
it.putExtra(Intent.EXTRA_STREAM, uri);  
it.setType("image/png");   
startActivity(it);  
  
//如果是 HTC Sense 手機,你要用  
Intent sendIntent = new Intent("android.intent.action.SEND_MSG");    
sendIntent.putExtra("address", toText);    
sendIntent.putExtra(Intent.EXTRA_SUBJECT, "subject");   
sendIntent.putExtra("sms_body", textMessage);    
sendIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse(url));   
sendIntent.setType("image/jpeg");    
startActivity(sendIntent);  
  
//底下這段更好,可在所有手機上用  
//refer to http://stackoverflow.com/questions/2165516/sending-mms-into-different-android-devices  
Intent intent = new Intent(Intent.ACTION_SENDTO, Uri.parse("mmsto:");   
intent.putExtra("address", );   
intent.putExtra("subject", );   
startActivity(intent);
傳送 Email
Uri uri = Uri.parse("mailto:xxx@abc.com");  
Intent it = new Intent(Intent.ACTION_SENDTO, uri);  
startActivity(it);  
Intent it = new Intent(Intent.ACTION_SEND);  
it.putExtra(Intent.EXTRA_EMAIL, "me@abc.com");  
it.putExtra(Intent.EXTRA_TEXT, "The email body text");  
it.setType("text/plain");  
startActivity(Intent.createChooser(it, "Choose Email Client"));  
Intent it=new Intent(Intent.ACTION_SEND);    
String[] tos={"me@abc.com"};    
String[] ccs={"you@abc.com"};    
it.putExtra(Intent.EXTRA_EMAIL, tos);    
it.putExtra(Intent.EXTRA_CC, ccs);    
it.putExtra(Intent.EXTRA_TEXT, "The email body text");    
it.putExtra(Intent.EXTRA_SUBJECT, "The email subject text");    
it.setType("message/rfc822");    
startActivity(Intent.createChooser(it, "Choose Email Client"));   
//傳送影音附件檔  
Intent it = new Intent(Intent.ACTION_SEND);  
it.putExtra(Intent.EXTRA_SUBJECT, "The email subject text");  
it.putExtra(Intent.EXTRA_STREAM, Uri.parse("file:///sdcard/mysong.mp3"));  
it.setType("audio/mp3");  
startActivity(Intent.createChooser(it, "Choose Email Client"));  
//傳送圖片附件檔  
Intent it = new Intent(Intent.ACTION_SEND);  
it.putExtra(Intent.EXTRA_SUBJECT, "The email subject text");  
it.putExtra(Intent.EXTRA_STREAM, Uri.parse("file:///sdcard/mypic.jpg"));  
it.setType("image/jpeg");  
startActivity(Intent.createChooser(it, "Choose Email Client"));  
顯示聯絡人清單
Intent it = new Intent(Intent.ACTION_VIEW, People.CONTENT_URI);  
startActivity(it);  
顯示某個朋友的詳細資料
Uri uriPerson = ContentUris.withAppendedId(People.CONTENT_URI, 5); //5 是朋友的 ID  
Intent it = new Intent(Intent.ACTION_VIEW, uriPerson);  
startActivity(it);  
播放多媒體
Intent it = new Intent(Intent.ACTION_VIEW);  
Uri uri = Uri.parse("file:///sdcard/song.mp3");  
it.setDataAndType(uri, "audio/mp3");  
startActivity(it);  
Uri uri = Uri.withAppendedPath(MediaStore.Audio.Media.INTERNAL_CONTENT_URI, "1");  
Intent it = new Intent(Intent.ACTION_VIEW, uri);  
startActivity(it);  
從圖庫中回傳選到的圖片
Intent it = new Intent(Intent.ACTION_GET_CONTENT);    
it.addCategory(Intent.CATEGORY_OPENABLE);    
it.setType("image/*");  
startActivityForResult(it, 0);  
//回傳的圖片可透過 it.getData() 取得圖片之 Uri
啟動照相機,並將相片存在指定的檔案中
Intent it = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);    
//假設你要將相片存在 /sdcard/xxx.jpg 中  
File f = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/xxx.jpg");  
it.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(f));   
startActivity(it, 0);  
Market 相關
//尋找某個應用程式  
Uri uri = Uri.parse("market://search?q=pname:pkg_name");  
Intent it = new Intent(Intent.ACTION_VIEW, uri);  
startActivity(it);  
//where pkg_name is the full package path for an application  
//顯示某應用程式詳細畫面  
Uri uri = Uri.parse("market://details?id=pkg_name_or_app_id");  
Intent it = new Intent(Intent.ACTION_VIEW, uri);  
startActivity(it);  
//where app_id is the application ID, find the ID   
//by clicking on your application on Market home   
//page, and notice the ID from the address bar  
Uninstall 應用程式
Uri uri = Uri.fromParts("package", strPackageName, null);   
Intent it = new Intent(Intent.ACTION_DELETE, uri);   
startActivity(it);
安裝 APK 檔
Uri uri = Uri.parse("url_of_apk_file");  
Intent it = new Intent(Intent.ACTION_VIEW, uri);  
it.setData(uri);  
it.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);  
it.setClassName("com.android.packageinstaller",  
                "com.android.packageinstaller.PackageInstallerActivity");  
startActivity(it);   
//make sure the url_of_apk_file is readable for all users  

推薦書單<入手>

已購入
1. 嵌入式系統韌體揭密
2. 嵌入式系統—使用 C 和 GNU 開發工具 第二版
3. 嵌入式系統入門
4. 作業系統導論 第二版
5. Embedded Linux 開發實務徹底研究
6. 現代嵌入式系統專案實務
7. 建構嵌入式 Linux 系統 第二版
8. 编码:隐匿在计算机软硬件背后的语言
9. 系统程序员成长计划
10. 嵌入式Linux内存使用与性能优化

category , action 大全[轉]

http://chroya.javaeye.com/blog/685864 http://chroya.javaeye.com/blog/685871

2010年11月2日 星期二

Dma6410XP開發環境架設

Install Fedora 8
1. 複製SDK與書本光碟內容到NB
2. 利用VMware安裝Fedora8
3. 看DMA-6410XP_CE6.0&Android2.1_100818.pdf
4. 安裝vmware tool ( 語系轉成英文 )
    http://life.iiietc.ncu.edu.tw/xms/content/show.php?id=16092
    擴充vmware空間 vmware-vdiskmamager.exe -x 100Gb "D:/xxx.vmdk"


Cross Compiler for uboot and kernel
5. mkdir /usr/local/arm
6. tar -jxvf 4.3.1-eabi-armv6-20080707.tar.bz2 -C /usr/local/arm
7. vim ~/.bashrc
8. export PATH=/usr/local/arm/4.3.1-eabi-armv6/usr/bin:$PATH
9. . ~/.bashrc

build kernel
10. cp dma6410xp-linux-2.6.29_101010.tar.bz2 ~
11. cd ~
12. tar -jxvf dma6410xp-linux-2.6.29_101010.tar.bz2
13. cd  dma6410xp-linux-2.6.29
14. make clean
15. make smdk6410_android_128M_defconfig
16. make zImage


build uboot

17. cp dma6410-u-boot-1.1.6_100913.tar.bz2 ~
18. cd ~
19. tar -jxvf dma6410-u-boot-1.1.6_100913.tar.bz2
20. cd  dma6410-u-boot-1.1.6
21. make smdk6410_config
22. make 

22-1. yum install gperf
22-2  CD install libsdl-dev
build Android 
23mkdir ~/sdk
24. cd sdk
25. cp jdk-6u14-linux-i586.bin .
26chmod u+x jdk-6u14-linux-i586.bin
27./jdk-6u14-linux-i586.bin
22. vim ~/.bashrc
22export JAVA_HOME=/root/Android6410/sdk/jdk1.6.0_14
   export CLASSPATH=$CLASSPATH:$JAVA_HOME/lib:$JAVA_HOME/jre/lib
   export PATH=$JAVA_HOME/bin:$JAVA_HOME:/jre/bin:$PATH:$HOME/bin
23. cp dma6410XP_android2.1_source_100920.tar.bz2 ~
24. tar -jxf dma6410XP_android2.1_source_100920.tar.bz2
25. cd android_source 
26. source ./build_android_env
27. ./build_android.sh


燒image


install 2.1 SDK

Android SDK Tools使用

這邊文章介紹幾個SDK tools

1. emulator
2. mksdcard
3. adb
4. DDMS

[root@localhost ~]# cd /home/online/android-sdk-linux_x86-1.6_r1/tools/
[root@localhost tools]# 
[root@localhost tools]# ls
adb         dmtracedump      hprof-conv  source.properties
android     draw9patch       lib         sqlite3
apkbuilder  emulator         mksdcard    traceview
ddms        hierarchyviewer  NOTICE.txt  zipalign
[root@localhost tools]# ./android list target
Available Android targets:
id: 1
     Name: Android 1.5
     Type: Platform
     API level: 3
     Revision: 1
     Skins: QVGA-P, HVGA (default), HVGA-L, HVGA-P, QVGA-L
id: 2
     Name: Android 1.6
     Type: Platform
     API level: 4
     Revision: 1
     Skins: HVGA (default), QVGA, WVGA800, WVGA854
id: 3
     Name: Google APIs
     Type: Add-On
     Vendor: Google Inc.
     Revision: 3
     Description: Android + Google APIs
     Based on Android 1.5 (API level 3)
     Libraries:
      * com.google.android.maps (maps.jar)
          API for Google Maps
     Skins: QVGA-P, HVGA-L, HVGA (default), QVGA-L, HVGA-P
id: 4
     Name: Google APIs
     Type: Add-On
     Vendor: Google Inc.
     Revision: 1
     Description: Android + Google APIs
     Based on Android 1.6 (API level 4)
     Libraries:
      * com.google.android.maps (maps.jar)
          API for Google Maps
     Skins: WVGA854, HVGA (default), WVGA800, QVGA
[root@localhost tools]#  ./android create avd --target 2 --name myavd
Android 1.6 is a basic Android platform.
Do you wish to create a custom hardware profile [no]
Created AVD 'myavd' based on Android 1.6, with the following hardware config:
hw.lcd.density=160
[root@localhost tools]#  mksdcard 512M mycard
[root@localhost tools]# ./emulator -avd myavd -skin HVGA -sdcard mycard &
[1] 4446
[root@localhost tools]# emulator: warning: opening audio output failed


[root@localhost tools]# ./android list avd
Available Android Virtual Devices:
    Name: sdk_1_6
    Path: /root/.android/avd/sdk_1_6.avd
  Target: Android 1.6 (API level 4)
    Skin: HVGA
  Sdcard: 32M
---------
    Name: avd16
    Path: /root/.android/avd/avd16.avd
  Target: Android 1.6 (API level 4)
    Skin: HVGA
---------
    Name: myavd
    Path: /root/.android/avd/myavd.avd
  Target: Android 1.6 (API level 4)
    Skin: HVGA
[root@localhost tools]# adb devices
List of devices attached 
emulator-5554   device

[root@localhost tools]# adb get-state
device
[root@localhost tools]# adb get-serialno
emulator-5554
[root@localhost tools]# #adb -s emulator-5554 install xxx.apk
[root@localhost tools]# #adb -s emulator-5554 uninstall com.example.xxx.xxx.apk
[root@localhost tools]# #adb shell
[root@localhost tools]# #adb pull <remote> <local>
[root@localhost tools]# #adb push <local> <remote>
[root@localhost tools]# #adb logcat
[root@localhost tools]# #adb bugreport
[root@localhost tools]# 
DDMS

2010年10月31日 星期日

以Android HAL 方式擴充 Framework

這邊詳細說明 Jollen Mokoid 專案如何擴充新硬體
首先給出整個架構,可以看到由上而下分成
應用程式層  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.mk
Dma6410xp.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
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
#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
#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
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);
    }
}