Email me: jollen # jollen.org

more: Jollen 的 Embedded Linux 教育訓練

« January 2010 | (回到Blog入口) | March 2010 »

February 2010 歸檔

February 1, 2010

「Android Framework Introduction」講座

Android Framework 技術的重要性日漸提高,研究 Android Framework 架構或是內部結構成為一項重要的工作。明天(2/2)受邀至鴻海土城民生廠進行一場訓練課程,主題是「Android Framework Introduction」;議題雖然是「introduction」,但突然有個想法,希望能做更深入的 introduction。正好近期在整理研究資料,所以把抓出的議題也和大家分享。計畫介紹的技術主題(Features)如下:

1. Android Framework Features

  • SystemServer & ServerThread
  • Main Thread
  • android.app.Activity 與 android.app.Service
  • Android Process 模式
  • ServiceManager 與 getSystemService API
  • JNI & Native Method
  • Blocking & Long Operations
  • VMThread & Thread
  • Zygote 與 Linux fork System Call

2. Android Framework Development

  • Manager API
  • Proxy Object
  • Remote Object
  • Remotable Object
  • IInterface & IServiceManager

原本構想中的 introduction 是以 Android 的架構圖為主,逐一介紹每一層的關係以並做 source code 的導讀;不過,後來想了一下,因為只有 3 個小時的時間,再加上大家對「概念」可能都已經有一定程度的了解了,所以再做這種描述性的簡介,似乎意義不大。

於是,改採介紹「Features」的方式,將 Android 重要的技術點做「點擊式」的說明。「明天過後」歡迎大家來函索取這次的講稿,待未來講義更加完善時,再放置到網路上分享。

February 8, 2010

MOSP: Mokoid Project (Mokoid Open Source Project) 上線

為了能在「Jollen 的 Android Framework in a Nutshell 演講」上搭配範例做講解,因此「特製」了一個 LedManager 範例;此範例原來是「Android 框架與驅動程式整合: HAL 原理與實作訓練」培訓課程的實作範例,目前計畫以此範例的部份內容做為演講材料。歡迎有意參加 Jollen 的 Android Framework in a Nutshell 演講的朋友,事先下載 Mokoid 程式碼。

Mokoid 提供一個 LedTest 範例程式,同時,LedTest 也是 Mokoid 專案目前所提供的第一個「近乎完整」的範例。請大家參考 apps/LedTest/src/com/mokoid/LedTest/ 裡的程式碼。Mokoid 專案的第二個範例,計畫是「MotorManager」,目前仍處於測試階段,預計在《台北場》演講時釋出。

Mokoid 的目的是提供「教學開發板」一套完整的 architect code 供實驗課程使用,或是搭配正課做原理教學,當然,首要目的是應用在自已的培訓課程上。主要的理念是「去除使用 dirty code 教學的風氣」,不過,可能需要不少時間來實踐這個理想。

Mokoid Project 網址:http://mokoid.googlecode.com

February 9, 2010

Jollen 的 Android 系統管理雜記, #1: 關於 android.uid.system 與 AID_SYSTEM

在 [Mokoid] 的 LedTest 範例裡,找到 [AndroidManifest.xml] 檔案。這個檔案為應用程式的「交貨清單」;在開發 LedTest 的過程中,我們加入了一個屬性如下:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.mokoid.LedTest"
    android:sharedUserId="android.uid.system">

原來,ServiceManager 會去檢查應用程式的權限;Android 作業系統會根據 UID 做權限管制,這裡所講的 UID 就是 Linux 系統管理面所討論的 User ID,即使用者 ID。在 [frmeworks/base/cmds/servicemanager/service_manager.c] 裡,找到這段實作:

int svc_can_register(unsigned uid, uint16_t *name)
{
    unsigned n;
     
    if ((uid == 0) || (uid == AID_SYSTEM))
        return 1;
 
    for (n = 0; n < sizeof(allowed) / sizeof(allowed[0]); n++)
        if ((uid == allowed[n].uid) && str16eq(name, allowed[n].name))
            return 1;
 
    return 0;
}
 
int do_add_service(struct binder_state *bs,
                   uint16_t *s, unsigned len,
                   void *ptr, unsigned uid)
{
    struct svcinfo *si;
//    LOGI("add_service('%s',%p) uid=%d\n", str8(s), ptr, uid);
 
    if (!ptr || (len == 0) || (len > 127))
        return -1;
 
    if (!svc_can_register(uid, s)) {
        LOGE("add_service('%s',%p) uid=%d - PERMISSION DENIED\n",
             str8(s), ptr, uid);
        return -1;
    }
    ...
}

AID_SYSTEM 被定義為 1000,即 system server 的 UID。從上述的實作可以了解,ServiceManager 會去檢查應用程式的 UID,當 UID 不符規定時,便無法執行 do_add_service()。

也就是:當應用程式的 UID 不是 1000 時,是沒有權限新增 Android Service 的。所以,在 AndroidManifest.xml 裡加上 android:sharedUserId 屬性的目的在於此:將應用程式的 UID 定義為 android.uid.system 即 1000,程式即可具備新增 Android Service 的權限。

以 Mokoid 所提供的範例為例,「因為我們是在 Android 應用程式裡啟動 Android Service」,因此要特別留意這個部份。典型的新增 Android Service 做法是修改 frameworks/base/services/java/com/android/server/SystemServer.java 檔案,但是,「因為 3M 分支維護策略的理念是儘量避免更動原始的 Android 程式碼」,所以我們採取這種「Start LedService in a seperated process.」的做法。細節請參考 Mokoid 範例。

February 14, 2010

Android Framework「專案啟動」顧問方案:技術、工程與管理 Start-up 服務

為什麼要研究 Android Framework?這是一個軟體工程以及專案管理面的問題。Android Framework 是 Application Framework(應用軟體框架),所謂的 Framework 定義上指的是未完成(incomplete)或是不完善(not ready-to-use)的軟體程式庫(嚴格來說是 class library)。

近期收到有關「如何發展 Android 產品」的需求有增多的趨勢,而要解決的最核心問題就是「研究 Android Framework」。雖然目前與一些訓練單位合作,提供許多 Android Framework 方面的課程,但因為都是屬於純技術面,還缺少軟體工程以及專案管理面的內容,尚有不足的地方。

有鑑於此,花費近一個月的時間,整理了一套「標準顧問方案」為企業客戶提供這方面的 On-site 服務,以補齊不足之處。這套顧問方案共分為 5 個層面,並定名為「Android Framework 專案啟動顧問服務」,詳細說明如下。

Framework 是未完成品

「Framework 是參考實作、未完成品。」這是小弟過去在許多演講場合,和大家分享的觀念。

1. Framework is incomplete.

Framework 本身是不可用的,需要強化或填寫 framework 的空白,並設計相對應的應用程式,此時 framework 才能有作用。從學術上的定義來看,framework 本身是 class library,這套 class library 以物件導向的抽象觀念來設計,提供可重用(resuable)或可抽換的單元(component),並提供一套應用程式流程(flow)與反向控制點(Inverse of Control)。

2. Framework is not ready-to-use.

Framework 是 class library,不是一個作業系統。Android Framework 是一套 class library,Android 搭配 Linux kernel 成為 Android OS。因此,framework 必須搭配作業系統核心,並且完成產品端的軟體開發;此處所指的「軟體開發」經常性的工作有2項:1. 補齊驅動程式,2. 並且整合驅動程式與 application framework。

以上說明讓我們了解一點,「廠商需要著手完成收尾工作」,並且 framework 本身是採用物件導向觀念設計的 class library,這說明了研究 Android Framework 內部設計的重要性。

Android Framework 留下的空白

因為不完整,所以需要了解我們倒底要填寫什麼空白、擴充哪些功能、開發哪些 abstract class 等等,以建立完整可用的 Android Framework。通常,這是一項針對「產品規格」所進行的工作,即 Specification 階段就該完成的工作。

在專案啟動前期(in the begining)若沒有完善這項工作,將可能影響後面的實作工作(implementation)。

Framework 只能擴充不要修改

一個嚴格的軟體工程方法裡,針對 application framework 的完善工作,需要基於「基礎版」進行後續的程式碼撰寫,但是,這個「撰寫」(coding)的工作應該儘量避免修改原始的 framework 實作。即 application framework 具備 non-modifiable 的特性。

Framework 是一個物件導向設計的 class library,因此採用 override 方式就可以實現「擴充」框架的做法;了解 Android Framework 現有設計(OOD)並進行擴充,是重要的工程技術。

實現 3M 分支維護策略管理程式碼

Framework 是實體的物體(physical objects),例如:以 JAR 檔形式存在。Framework 不是抽象的,所以像是 GoF 便是一種非實體的觀念。如何在 Android Framework 原始碼裡,將擴充出來的部份產生實體物體,最基本的做法是建立獨立的 JAR 檔。當我們擴充或重用 Android Framework 時,就會面臨三個問題:1. 有哪些實體需要建立?2. 以及如何建立?3. 並且如何在不修改 Android Framework 程式碼的前提下完成這些工作?

過去在課程或演講經常所提出的「3M 分支維護策略」就是一個簡易的解決方案。

建立 Android Framework 開發主機

為客戶建立一台專門的開發主機,是最後一項工作。除了提供範例與開發環境外,也會給予一個基本的訓練。

咨詢方案規劃

Jollen's Consulting 工作室聯合幾位不同領域的專家,在 Android Framework 的專案研發上做了一些討論,並且提出一個針對企業的咨詢方案,大綱如下:

《1 .觀念入門》Framework 是未完成品
《2. 實務應用》Android Framework 留下的空白
《3. 設計理論》Framework 只能擴充不要修改
《4. 分支管理》實現 3M 分支維護策略管理程式碼
《5. 開發環境》建立 Android Framework 開發主機

這是一套咨詢方案(Consulting),對象是「有意採用 Android 發展產品、想要正確並有效起步」的企業客戶。這套方案的方向是以「專案管理」、「產品開發」以及「軟體工程」做為出發點,雖然只是一個提供 Start-up 的 consulting 服務,但過去實行的成效良好,因此,將本方案公佈在這裡,期望 Jollen's Consulting 的專家團隊,能在「企業導入 Android 工程技術」上有所貢獻。過去的做法,經常是採購實驗板,並自行摸索;本方案提供的是「Start Up」服務,比起自行摸索的做法,更有效率、也更整體。

本方案過去服務過大陸與美國的企業。一些做法,目前也應用在自有的開發項目上。本方案目前的做法是以2-3天的 On-site 顧問服務方式進行,客戶端建議的參與人員必須包含1名專職的PM。本方案的顧問團隊,也包含了 2 位具備 PMP 資格的專案管理師,能為大家在開發上的專案管理提供一些觀念。

February 26, 2010

Override Context.getSystemService()

Context.getSystemService() 是一個很重要的 API,也是「Android 應用程式控制硬體」的起點。在一個開發項目中,如何擴展 getSystemService() 的實作成為一個重要的課題。

幾天前與客戶進行技術討論時,適巧討論到這個議題,因此在這裡做一個簡單的紀錄與大家分享。應用程式要存取手機上的 Sensor 裝置時,須取得 SensorManager 物件,程式寫法如下:

public class mokoidSensor extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
         
        SensorManager sensor = (SensorManager)getSystemService(SENSOR_SERVICE);
        sensor.getSensors();
        /* Do something. */
    }
}

如果手機上有一個「馬達」裝置,程式碼的寫法,依此邏輯來推論,設想的程式碼會是這樣:

MotorManager motor = (MotorManager)getSystemService(MOTOR_SERVICE);

只是,AOSP 上的程式碼並無 Motor Service 硬體服務,因此除了加入 MotorManager 與 MotorService 設計外,也要擴充 getSystemService() API。實際能採行的做法很多,這裡討論二種方式:

1. 土方法
2. 符合架構

土方法是一個簡單的方式,直接到 [ApplicationContext.java] 裡把程式碼改掉。這個方式簡單有效,不費勁。

符合架構的方法,是基於「Application Framework 不能修改」的前提下來進行設計。也就是,不要變動 Context 的設計、也不要修改 ApplicationContext 實作。AOSP 的 [Activity.java] 以 override 的方式,展示了這個做法:

    @Override
    public Object getSystemService(String name) {
        if (getBaseContext() == null) {
            throw new IllegalStateException(
                    "System services not available to Activities before onCreate()");
        }
 
        if (WINDOW_SERVICE.equals(name)) {
            return mWindowManager;
        } else if (SEARCH_SERVICE.equals(name)) {
            ensureSearchManager();
            return mSearchManager;
        }
        return super.getSystemService(name);
    }

因此,改用以下的設計:

public class mokoidActivity extends Activity {
    ...
    @Override
    public Object getSystemService(String name) {
 
        if (MOTOR_SERVICE.equals(name)) {
            MotorManager mMotorManager = new MotorManager();
            return mMotorManager;
        }
        return super.getSystemService(name);
    }	
	...
}

應用程式的部份也要做修改:

public class HelloWorld extends mokoidActivity {
}

目前為止,這只是一個想法,尚未實作驗證。

關於 February 2010

此頁面包含了在February 2010發表於Jollen's Blog的所有日記,它們從老到新列出。

前一個存檔 January 2010

後一個存檔 March 2010

更多信息可在 主索引 頁和 歸檔 頁看到。

Top | 授權條款 | Jollen's Forum: Blog 評論、討論與搜尋
Copyright(c) 2006 www.jollen.org