2017年11月15日 星期三

Android 系統筆記 - Big/Little endian

雖然是很一般的東西但偶而腦筋還是會打結呢....(´・ω・`;)

Big Endian 就是把最高位元組存到地址的最低位元. (這句話hen難理解對吧)

直接上範例:
地址假設我們從 0x00000000 開始
假設你有一個 32 位元的 integer 如下
int32_t big = 0x12345678;

地址最低位元當然就是 0x0000000囉
那麼最高位元組指的是什麼呢? 就是你的 0x12啦
Mapping到記憶體之後會變成這樣:

Address Value
0x00000000 0x12
0x00000001 0x34
0x00000002 0x56
0x00000003 0x78

反過來說 Little-endian 就是會變成這樣囉: 

Address Value
0x00000000 0x78
0x00000001 0x56
0x00000002 0x34
0x00000003 0x12

那假設你是一個 array 會怎麼樣呢?
我們令 int32_t test[2] = {0x12345678, 0x11223344}

記憶體的排列會變成這樣唷!

Address Value
0x00000000 0x78
0x00000001 0x56
0x00000002 0x34
0x00000003 0x12
0x00000004 0x44
0x00000005 0x33
0x00000006 0x22
0x00000007 0x11

也就是 Big-Endian 或者 Little-Endian 只有影響到該變數在記憶體存放的位置而已  (*´∀`)ノ

2017年11月7日 星期二

Android系統筆記 - Java HandlerThread

Java 的 Thread 已經被封裝成了幾種易用的形式, 簡單介紹一下幾個重點:

Runnable 
可以理解為"任務內容"
我們會把要完成的一件工作寫在Runnable的物件裡面.
例如這樣:
Runnable task = new Runnable() {
    public void run() {
        Log.e("Start run!");
    }
};

Thread
單執行序, 負責處理一個 Runnable 的物件.
用法也很簡單, 我們可以直接把上面那個 task 直接丟進去:
Thread oneTimeThread = new Thread(task);
oneTimeThread.start();
這樣就會開另外一個執行序去執行一次 task

另外Thread也有一個建構子是沒有帶入Runnable物件的,
這樣子呼叫start()就會直接執行Thread裡面的run()方法,
一般使用在你的物件去繼承了 Thread 的時候, 例如這樣:

public class myThread extends Thread {
    @Override
    public void run() {
        System.out.println("Thread start running!");
        for (;;) {
            System.out.println("Thread keep running!");
        }
    }

    public static void main(String[] argv) {
        Thread t = new myThread();
        t.start();
        for (;;) {
            System.out.println("Main Thread");
        }
    }
}

執行以後就會交錯印出訊息, 可能像這樣:
Main Thread
Main Thread
Thread start running!
Thread keep running!
Thread keep running!
Main Thread
Thread keep running!
Main Thread
(因為執行序的關係, main通常會先開始跑)

你也可以嘗試將 infinite for loop 換成只跑10次來觀察看看.
另外需要一提的是, 這個 Thread 物件也可以直接呼叫 run() method,
這時就會在 main thread 執行, 而不會另外開一個執行序去跑, 所以執行結果會變成這樣:
(把 infinite for loop 換成只跑10次)

Thread start running!
Thread keep running!
Thread keep running!
Main Thread
Main Thread
=> 等到 run() 方法執行完之後才會往下跑


HandlerThread
相較於上面的單執行序, 這個物件幫你封裝了MessageQueue在裏頭,
它的定位很像是 Native layer 的 Thread 物件, 啟動之後會自動運行 threadLoop(),
並且會等待事件進入時才開始工作 (可以想像成它呼叫了 pollOnce(-1))

handlerThread開始執行之後, 會開啟另外一個執行序來等待工作. (*這時候還沒有task放進去跑)
我會把它拿來處理asynchronous訊息的溝通, 用法如下:
HandlerThread workThread = new HandlerThread("WorkThread");
workThread.start(); // 開始等待事件進入

// 分發事件的方式要使用 Handler 物件來進行分配, 關於 Handler 請往下看
Handler workHandler = new Handler(workThread.getLooper());
workHandler.post(task);

// 除了 post 以外, 還有 postAtTime, postDelayed 等形式可以來控制 task 執行到的時間

* 因為這個執行序沒有所謂的執行結束, 所以不用的時候記得要關閉掉它
(例如, 放在 constructor 跟 destructor)

Handler
這個物件除了可以使用post()分配事件給HandlerThread,
還有一個用法是去override handleMessage(), 將事件預先定義好, 並使用 Message 來開始工作.
Handler workHandler = new Handler(workThread.getLooper()) {
    @Override
    public void handleMessage(Message msg) {
        super.handleMessage(msg);
        switch (msg.what) {
            case 1:
                Log.e("Handler", "Received message");
                break;
            default:
                Log.e("Handler", "Unsupprted message");
                break;
        }
    }
}

workHandler.sendEmptyMessage(1);
(有興趣進去看 Handler.java的話, 你會發現 post() 函數也是將 Runnable 物件封裝為 Message)

不定參數印 log

From the UNIXProcess_md.c #ifdef DEBUG_PROCESS   /* Debugging process code is difficult; where to write debug output? */ static void deb...