<有背景音樂,請打開喇叭,音樂檔很大,請耐心等候>

 那時,我是一個懵懂無知的少女,

 帶著含苞待放的羞怯,等待著我的愛情,

 我遇見英俊的你,我倆一見傾心,

 那時我的世界彷彿只剩下愛情,

 即使我知道,你的溫柔從未停止過,

 你說愛像雲,要自在漂浮才美麗,

 我癡癡等待,直到年華老去,

「繁華散盡淚成灰,斷弦搖琴玉消香,空嘆殘花夢如煙,天長水遠愁斷腸」

相信在開發 Android 裝置的工程師在做長時間測試的時候一定會遇到一個棘手的問題:
「該怎麼關掉 Screen Timeout?」否則裝置一下子就睡著了該怎麼測試?因為在網路上找不到相關的訊息,索性就自己寫一下。

基本上我有兩個辦法:

  1. 第一個辦法是給有能力可以編譯 Android 的開發人員,從 Android 的根目錄下尋找frameworks/base/packages/SettingsProvider/res/values/defaults.xml ,打開這個檔案,找關鍵字"def_screen_off_timeout",把這一行改成
    -1
    然後重新編譯與更新 Android Sytem。


  2. 第二個方法是給沒有辦法編譯 Android 或者像我這種懶得一直重新編譯的開發人員^^,進入 adb shell 裡面,cd 到 /data/data/com.android.providers.settings/databases/ ,輸入
    sqlite3 settings.db
    SQLite version 3.6.22
    Enter ".help" for instructions
    Enter SQL statements terminated with a ";"
    sqlite> update system SET value='-1' where name='screen_off_timeout';
    sqlite> select * from system where name='screen_off_timeout';
    51|screen_off_timeout|-1
    
    如果結果像最後一行這樣顯示 -1 表示成功了,接著輸入 .exit 離開,然後輸入
    reboot
    重新開機,好!開機完成後應該就可以"不眠不休"的測試了...^_^。

在介紹如何 debug 之前,首先必須知道的是,目前的系統到底有沒有記憶體洩漏?以下先介紹幾個常用的記憶體觀察法:

  • cat /proc/meminfo      // 粗略的觀察目前記憶體的種類以及各個種類的大小
  • ps                             // 觀察每個 process 目前記憶體使用的情況 
  • top                            // 看看前幾個記憶體使用最多的 process 是哪些
  • dumpsys meminfo      // Android 特有的指令,有更多的資訊







方法1 Memory Analyzer :

這個方法必須配合 Eclipse 使用,因為 Memory Analyzer (MAT) 是 Eclipse 的一個 Plugin。
  1. 第一個步驟當然是安裝 MAT,安裝得方法有許多種,你可以下載MemoryAnalyzer-1.0.1.201008091353.zip,解開到Plugins,或者在Eclipse上點選 Help --> Install New Software... --> Add,然後在 Name 輸入 Memory Analyzer ,在 Location 輸入 http://download.eclipse.org/mat/1.0/update-site/ ,如圖所示:
    按下 OK,之後要選擇安裝 Plugin 完成安裝程序。

  2. 一如往常的執行你想要 debug 的 Android 程式,然後透過進入 shell 裡面檢查 /data/misc/ 這個目錄是否有可讀寫的權限,因為我們等一下會 dump file 到這個目錄。另外,也可以簡單的把他的權限設成 777:
    adb shell
    chmod 777 /data/misc/
    

  3. 接下來執行程式到你認為會產生 leak 的地方,來回多執行幾次,然後利用 kill 這個指令送信號 SIGUSR1 (-10) 給你的 process (可以透過 ps 查看 Process ID),假設你要 debug "com.test.debug" 這個 process :
    ps
    ...
    PID UID       VSZ  Stat Command
    100 1000   255255    S  com.test.debug
    ...
    
    kill -10 100
    

  4. 你可以透過 logcat 來確認你的 process 有沒有收到 signal:
    logcat &
    

    如果看到類似如下的訊息表示有收到:
    I/dalvikvm(  236): threadid=3: reacting to signal 10
    I/dalvikvm(  236): SIGUSR1 forcing GC and HPROF dump
    I/dalvikvm(  236): hprof: dumping VM heap to "/data/misc/heap-dump-tm1291081439-pid100.hprof-hptemp".
    I/dalvikvm(  236): hprof: dumping heap strings to "/data/misc/heap-dump-tm1291081439-pid100.hprof".
    I/dalvikvm(  236): hprof: heap dump completed, temp file removed
    D/dalvikvm(  236): GC_HPROF_DUMP_HEAP freed 585 objects / 60000 bytes in 10595ms
    

    查看一下 /data/misc/ 目錄應該可以看到 heap-dump-tm1291081439-pid100.hprof:
    ls /data/misc/
    ...
    heap-dump-tm1291081439-pid100.hprof
    ...
    

  5. 離開 shell
    exit
    

    透過 adb pull 把這個檔案抓下來。
    adb pull /data/misc/heap-dump-tm1291081439-pid100.hprof
    

  6. 透過 hprof-conv 把剛剛抓下來的檔案轉換成 Memory Analyzer 認識的格式:
    hprof-conv heap-dump-tm1291081439-pid100.hprof debug.hprof
    

  7. 開啟 Eclipse,點選 Window --> Open Perspective --> Other... ,然後選擇 Memory Analyer。

  8. 點選 File --> Open Heap Dump... ,然後選擇剛剛轉換過的檔案 (此例為 debug.hprof)。接著會出現一個對話框,詢問你想產生什麼樣的報告,如下圖:
    此時我們的目的是偵測 memory leak,所以自然是選擇 Leak Suspects Report,按下 Finish 後,就會產生一個報告,告訴你可疑的地方。是不是很棒呢!


方法2 libc_debug.so : 

這個方法基本上是將 libc.so 換成 libc_debug.so 利用 libc_debug.so 提供多項偵錯的功能來查看記事體是否被不當的使用。

  1. 將 /system/lib/libc.so 替換成 /system/lib/libc_debug.so
  2. 重啟系統 adb shell reboot 
  3. adb shell setprop libc.debug.malloc 1" (or 5, or 10 for slightly different behaviors)
  4. 新增 "native=true" 到你的 ~/.android/ddms.cfg 檔案中
  5. 啟動 stand-alone 版的 DDMS. 接著你應該會看到有 "Native Heap" tab 出現,切到這個頁面後就可以 native memory 的使用情況。


方法3 c/c++ debugger : 

利用c/c++ debugger 來協助 debug c/c++ 層的 memory leak,接下的例子會使用 dmalloc 來 debug JNI native library.

  1. 先到 dmalloc 的官方網站 http://www.dmalloc.com 下載 source code。
  2. 交叉編譯 dmalloc,我個人是偏好用 Android NDK 來編譯,不過在這之前必須要先產生原本的 Makefile 然後照著 Makefile 來產生 Android.mk
    1. 執行 configure
      ./configure --prefix=/arm-linux/ --enable-cxx --enable-threads
      
      其中/arm-linux/是隨便指定的路徑,反正我們只是想要參考 Makefile。
    2. 參考 Makefile,轉換成 Android.mk
    3. 執行 ndk-build 來編譯 dmalloc
  3. 因為我們是要 debug JNI 的 native library 所以沒辦法透過一般的設定環境變倏地方法來指定 debug options:
    DMALLOC_OPTIONS=debug=0x4e48503,inter=100,log=/sdcard/dmalloc.%p
    export DMALLOC_OPTIONS
    

    必須自行在程式進入點指定 debug option,以 JNI 為例,可以利用 JNI_OnLoad() 當作是進入點,此外,離開的時候也必須關閉:
    #include "dmalloc.h"
    
    JNIEXPORT jint JNICALL JNI_OnLoad (
    ) {
        dmalloc_debug_setup ("debug=0x4e48503,inter=100,log=/sdcard/dmalloc.%p");
    }
    
    JNIEXPORT void JNICALL JNI_OnUnLoad (
    ) {
        dmalloc_shutdown ();
    }
    

    然後利用 dmalloc_mark() 與 dmalloc_log_changed() 來標記要偵錯的區段,下面我們以一個 JNI function 為例,故意造成 memory leak:
    unsigned long mark;
    
    JNIEXPORT void JNICALL JNI_com_example_debug_Test (
        JNIEnv* env,
        jobject thisArg
    ) {
        // Mark the start of debug
        mark = dmalloc_mark();
    
        // Leak memory 1000 bytes.
        char* leak = (char*) malloc (1000);
    
        // log unfreed pointers that have been added to
        // the heap since mark
        dmalloc_log_changed (
            mark,
            1,    // log unfreed pointers
            0,    // do not log freed pointers
            1     // log each pnt otherwise summary
        );
    }
    

    一旦這個 function 被呼叫,就會在 /sdcard/ 目錄下產生類似 dmalloc.1000 (副檔名是這個process 的 PID),然後裡面就會告訴你那一行發生 memory leak了。
    948436802: 1: Dmalloc version '5.5.2' from 'http://dmalloc.com/'
    948436802: 1: flags = 0x4e48503, logfile 'logfile'
    948436802: 1: interval = 100, addr = 0, seen # = 0, limit = 0
    948436802: 1: starting time = 948436802
    948436802: 1: process pid = 1000
    ...
    

<有背景音樂,請打開喇叭,音樂檔很大,請耐心等候>

好久以前曾經幫同事 Roger 做過婚禮記錄,但這一些記錄也隨著之前發表過的網站關閉而消失了,前陣子 Roger 父親的事情讓我感慨良多,藉著今天是 Roger 的生日,也順便把這些照片再做一番整理,也對希望 Roger 的父親能夠在天堂裡保佑我們,以馬內利。

出發去迎娶之前先拜祭家裡的祖先,祖先們啊, Roger 已經長大囉!今天就要娶媳婦過門了,請你們要好好保佑他...
↘


傳統的習俗還是要遵守的...
↘


Roger 拿著漂亮的捧花要準備出發囉!ㄟㄟ...少年耶,你笑得很僵耶!是很緊張吧!有我在免驚啦!...呵呵...^^
↘


出發前郵差先生還送來一封信,有幸福的預感喔!...^^
↘


Roger 的人生大事,父親不敢大意,在臨行前不忘再三叮嚀...
↘



想見到新娘哪有這麼容易啊?好姊妹當然要考考這位新郎官啦!Roger 說時遲那時快立刻掏出放在褲襠的..."紅包"...嘿嘿...還好我事先有準備,這下應該搞定了吧!
↘


嗯...紅包這招是不錯,不過,為了姊妹的「性福」,體能考驗還是要來一下啦!不是猛龍不過江,看我 Roger 輕鬆過關,嘿嘿...俺可是有練過的喔!...^^
↘


通過重重的考驗終於見到新娘啦! Rita 看起來好高興喔!不過我在一旁觀察到 Rita 父親的神情似乎有一些感傷,人家說:「女兒是父親前世的情人」真的一點也沒錯...女兒要嫁人總是捨不得的。
↘


拜別女方家長
↘





現場瀰漫著一種既喜氣又感傷的氣氛,我從 Rita 跟他父親的互動雖然不多但是卻可以看出他們的感情很好...
↘


這時候 Roger 機警的安撫丈母娘的情緒,這一招果然讓丈母娘放心許多...「師奶殺手」Roger 果然不是浪得虛名喔!呵呵...^^
↘


Rita 看著窗外的神情好美啊!就像一個美麗的「天使」(這也是我選這首背景音樂的原因)。看著窗外似乎也看到了未來,而 Roger 你應該知道吧!你就是她的未來...
↘


傳統的習俗是新娘出發前要把扇子丟掉...
↘


到新郎家囉!下車前要先摸個橘子,有吉利的意思喔!
↘


過火盆跟採瓦片也是一種招福的習俗。
↘


祭祖,啟稟祖先家裡今後將多一個成員囉,請祖先好好保佑葉家的媳婦。
↘


新娘給長輩奉茶啦!這也是古禮之一喔!
↘


看長輩笑得合不攏嘴...呵呵...
↘


來場景換到了新竹的勝利堂,接下來就是基督教的結婚儀式了。
↘


這位風度翩翩的帥哥就是新郎耶,一度以為是瓊瑤劇裡面的男主角呢...帥氣指數破表...呵呵...
↘


花童、伴娘跟新娘依序出場...
↘


牧師正在祝福這對新人,牧師口才很好,現場氣氛很歡樂喔...
↘


底下的新人聚精會神的再聆聽。
↘


交換戒指
↘


掀頭紗
↘


祝福
↘


說完新郎可以吻新娘了,接下來就是這種激情狂吻了...真令人臉紅心跳啊...
↘


詩歌祝福
↘


Rita 給媽媽一個深深的擁抱,媽媽...謝謝您。
↘


入洞房囉...接下來兒童不宜,所以就不貼囉...呵呵...其實接下來我也沒拍到啦!THE END!
↘


不知道大家知不知道 meld 這個 visual diff viewer 呢!?個人覺得在 Linux 的環境底下這可能是最好的 viewer 了。有機會再跟各位詳細介紹吧!

如果沒有安裝過不妨先安裝一下:

sudo apt-get install meld

接著設定 GIT 讓他使用 Meld :
git config --global diff.external meld

然後像往常一樣比較某一個檔案:
git diff HEAD^ filename
其中 HEAD^ 是指上一個版本。

Meld 會被叫起來,但是會說參數錯誤 "Wrong number of arguments (Got 7)"。 原因是 GIT 會送 7 個參數給 Meld ,但是 Meld 只需要兩個參數,兩個需要比較的檔名。所以不能直接用 Meld ,必須要做一點小修改:

在自己的的目錄下建立一個 git-meld.sh 的 script:
vi ~/git-meld.sh

加入以下內容:
#!/bin/sh
meld $2 $5

改變檔案的屬性:
chmod 777 ~/git-meld.sh

然後把 external diff 改成這個 shell script :
git config --global diff.external ~/git-meld.sh

大功告成。

Ubuntu 9.04 之前的 gcc 和 g++ 的版本都是 4.3 的,但是 Ubuntu 9.10 以後卻換成了 4.4 的。 而 4.4 除了檢查更加嚴格外也改了某些函數的回傳型別,把 char* 改成了更嚴謹的 const char* 其用意是讓這些函數更安全。

由於修改 android source code 可是一大工程,而且 source code 隨著 google 的修改版本一直在 update ,除非決定自己 maintain 否則修改可不是一個合理的行為。所以把 gcc 和 g++ 還原成 4.3 版是一個比較可行的辦法。

首先安裝 4.3 版的 gcc 和 g++ :


sudo apt-get install gcc-4.3 g++-4.3 g++-4.3-multilib


接著刪掉原本的 link :


sudo rm /usr/bin/gcc
sudo rm /usr/bin/g++


產生指到成舊版的 link :


sudo ln -s /usr/bin/gcc-4.3 /usr/bin/gcc
sudo ln -s /usr/bin/g++-4.3 /usr/bin/g++


補充:在 Ubuntu 10.10 之後有一種稱為 fastjar 的工具, 是以 c 語言寫成的工具,比原本 java 版本的快了 100 倍. 但是目前有一些穩定性的疑慮,所以如果在 Ubuntu 10.10 發現類似 "unable to access file: corrupted zip file" 這樣的錯誤,可以試著執行:

sudo update-alternatives --config jar


然後會出現:
There are 2 choices for the alternative jar (providing /usr/bin/jar).

Selection Path Priority Status
------------------------------------------------------------
* 0 /usr/bin/fastjar 100 auto mode
1 /usr/bin/fastjar 100 manual mode
2 /usr/lib/jvm/java-6-sun/bin/jar 63 manual mode

Press enter to keep the current choice[*], or type selection number:


輸入 2, 選擇 java 版的就可以了。

自從家裡有個小搗蛋出生之後,對這種防過敏的東西就特別有興趣。因為我本身有過敏的體質,所以很希望這種不好的過敏現象不要發生在下一代身上。關於對抗過敏基本上可以分成兩派,死豬不怕水燙派跟預防派,死豬派是認為基本上環境不是個人小小的力量可以改變的,就算是改變了自家的環境,到了外面依然污染嚴重,既然如此就應該讓小孩從小習慣污染,以後才能適應惡劣的環境。另一派的說法是從過敏發生的原因來著手,過敏的原因其實就是身體對抗污染環境的一種保護機制,也是對抗體對自身發出的一種警告。抗體的本意是好的,他盡忠職守的阻止過敏原進入人體,所以才會一直打噴嚏流鼻水。然而更深入研究會發現,這些抗體其實本來是不認識這些過敏原的,當過敏原與抗體接觸後,抗體才會產生記憶來記住這些過敏原,等下次再發現這些過敏原,抗體就會起來對抗。這也就是為什麼花粉症通常再搬到某個地方的第二年以後才會發生。

基於我是預防派的,所以對486強烈推薦的「大王空氣清淨機」一直有著濃厚的興趣。終於在一次過敏又來襲的時候,敗給了心中的小惡魔..../_\
有興趣的人請看請看486的文章:
http://blog.yam.com/kiss486/article/26499887
http://blog.yam.com/kiss486/article/29637297

廢話不多說,直接開箱吧!


箱子超大的...

打開箱子終於看到廬山真面目了,真的很大一台,甚至快要是除濕機兩倍大了,但是也是這麼大台才稱的上是大王,因為他的濾網也很大。

打開前面的蓋子可以很清楚的看到 HEPA 濾網,這就是可以有效過濾過敏原的關鍵啦!又大又厚呢!家裡的過敏原就靠你來清除了。

喔...幸好有輪子可以在房子裡推來推去,真是貼心的設計。

這次的團購還有附贈10片活性炭濾網以及馬達五年保固,真的很划算,難怪熱銷近600台。

這幾天用下來的結果真的很不錯,機器一啟動,真的可以明顯的感覺到空氣變好了。很神奇的是今天我本來鼻子又不通了,所以給他打開強力風速,咦...開機大概一個小時我的鼻子竟然通了,神奇啊...讚啦!...^^