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

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

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

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

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

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

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

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

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

相信在開發 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台。

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