今天剛好看到這個百年千書計劃,裏面提供了一堆epub,於是就想說,可不可以放到我的手機SE T700上看呢?
就上getjar上找,就找到了Albite Reader。很高興地下載程式跟epub下來放到手機上,可以執行,但是結果卻都是一堆 ?
這到底怎麼回事,首先我試了軟體的編碼設置功能,沒有用。我懷疑 epub 裡的編碼是big5,而軟體的編碼選項裡卻沒有 big5,所以就上網找了一下,看要怎麼編輯 epub。看到這篇:Edit ePub eBooks with Your Favorite HTML Editor,才知道原來 epub 其實是個 zip 檔案,將副檔名更名為 zip 以後,就可以解開去看了。然後也發現了不錯的編輯工具:sigil。不過都沒有用,epub 裡的編碼是正確的。
那麼問題就出在軟體本身了,幸好軟體有開放原始碼而官方網站也有說明。大致看了官方網站的說明以後,才明白,問題出在字型上。軟體本身沒有包中文字!!!!這就麻煩了。官方網站也有說怎麼製作字型,不過他所使用的 Bitmap font generator 卻沒有支援中文字,因此無法產生出必要的 .png 跟 .xml 檔案,也沒辦法繼續後面的步驟,將 .png, .xml 轉成 .alf, .ali 了。
傷腦筋,看來如果要能用,一個方法就是寫程式去做出 Bitmap font generator 的功能,將字型轉成 .png, .xml,另外一個方法就是改寫 Reader 裡處理字型的部份了。
我想寫工具來轉字型應該是比較快的方法,在 AlbiteFontBuilder網頁裡有提到 .xml 的格式,看起來是將字型都顯示在 .png 以後,.xml 則是描述字(glyph)在 .png 裡的位置跟寬高。得到這個以後,應該就可以接著用 AlbiteFontBuilder 做出 .alf 與 .ali 了。
電影流水帳(2011/1/1~2011/2/7)
最近裝了網樂通,3月底前看電影不用收費,就趁過年期間看了幾部。
- Shrek Forever After(IMDB, Wikipedia),中譯:史瑞克快樂4神仙。看完以後有不少感觸,心裡想這根本就是給已婚者看的啊~的確是常常會覺得自己時間都被剝奪掉了,可是從另外一方面來看,的確,太太與小孩也給自己帶來不同的視野與責任,中間的平衡點怎麼去拿捏就是一門學問…可是,這很常是一個離婚的原因…好吧,言歸正傳,簡單說就是Shrek想偷閒回去過一天以前的生活,卻沒想到合約裡的陷阱,導致現在與未來的生活陷入危機,當然最後是皆大歡喜,破除了合約裡限制,重回原來的生活。相當好看的片,我個人推薦給已經結婚的人看,不過這並不代表看了以後,就會知道結婚不只是愛。
- Despicable Me(IMDB, Wikipedia),中譯:神偷奶爸。看了時候正在吃飯,一片混亂,所以沒什麼太大的感想,基本上是走溫情路線。主角是個不太成功的科技小偷,因為童年以及現實的種種因素,他決定去偷月亮。為了偷月,他需要準備許多道具,其中包括了縮小燈。在偷縮小燈的過程裡,他認識了3個女娃,並收養了她們,於是溫情從此展開。最後他收養了3個女娃,月亮偷成了,但縮小燈有缺陷,又還回原位了。
- Inception(IMDB, Wikipedia),中譯:全面啟動。這部片很好看,網路上應該有很多人分享了,這裡就不多說。
- 現實的五分鐘等於夢境裡的一小時。這裡我照著推算了一下,飛機上的十小時一共600分鐘,在夢境裡應該是五天才對,而不是一星期。
- 第1層夢境裡,Fischer潛意識持續在追殺他們,那他們從水裡脫逃以後,應該是繼續被追殺才對吧?那將近五天怎麼渡過?
- 最後老婆跟我還倒帶看了那個圖謄陀螺好幾次,看到底有沒有倒下。我是跟她說沒有,因為這部電影從一開始就是一個夢。
其他還有一些可能要反覆再多看幾次才會明白的細節,真是太玄了。
Run MiPony on Linux(wine)
因為看到MiPony可以快速下載freakshare.net的檔案,所以就想裝來試試看~
在Linux下,只能用wine,我用的版本是1.3。你得先安裝winetricks(sudo apt-get install winetricks),然後用winetricks裝上 gdiplus, fontfix, dotnet20, ie6(winetricks gdiplus fontfix dotnet20 ie6)。接著再用wine裝上MiPony,就可以了。
目前下載了十幾個檔案,都沒問題,真是太好了!!
Google reader expanded/list hack
google reader
最近把Google reader的tag都設到書籤裡去,想說這樣會比較快。
可是卻遇到一個問題,某些tag要看的時候想用Expanded,但某些tag卻想用List。本想說Google reader是不是可以藉著設URL Parameter的方式來解決這問題,查了Unofficial 的 Google reader API,卻沒找到答案。
只能手動 Hack 了。
啟用神兵 Firebug 查看以後,Google reader要show Expanded/List,是送 POST 到 https://www.google.com/reader/api/0/preference/set?client=scroll ,然後帶上3個參數:T、k、v ,T 用途不明,k 總是 is-card-view,v 在 Expanded 時是 true,List 時則是 false。
所以,看來是沒辦法,除非是書籤改用 javascript,寫成 bookmarklet 的方式才能達成。
GNU IceCat Privacy extension安裝總是失敗
之前都沒注意,直到GreaseMonkey升級,跑不起來,才發現這事情的嚴重性。
上網找了一下,果然已經有人跳腳:http://osdir.com/ml/bug-gnuzilla-gnu/2010-12/msg00057.html
就follow裏面的提供的網址:http://kb.mozillazine.org/Installing_extensions#Global_installation ,照裏面的指示去手動解壓縮 /usr/lib/icecat/extensions/privacy_ext.xpi 到 /usr/lib/icecat/extensions/privacy_features@gnuzilla.gnu.org 就行了。
DDMS抓圖
會看這個,是因為抓圖失敗…
ddms 會開啟本地的port 5037,這是由host端的adbd所listen的。接著寫入”framebuffer:” (AdbHelper.getFrameBuffer)。
target端的adbd收到以後,會建立一個thread,thread跑的是framebuffer_service.c裡的code。裏面很簡單,就開啟/dev/graphics/fb0,然後取 fb_var_screeninfo 的值,再根據得到的值來決定要讀多少bytes,寫回去到host端,最後寫完就關閉。
為什麼會抓不到圖呢?不知道,還找不到原因。
加快linux開機速度
在 1 second Linux boot to Qt! 看到的,標題超聳動,不過實際看到影片,真的是很嚇人,根本就是瞬間就開好了。投影片在這裡:The Right Approach to Minimal Boot Times
這個 topic 前兩年很熱門,當然啦,現在因為 Android 的關係,應該會更熱。下面是我看完的一些紀錄跟想法:
- 使用 Arjan van de Ven 對 kernel aync 的 patch
- 把不重要的 module 改成 loadable
- 修改init/do_mounts.c以提早mount root
- 修改init/main.c裡的init_post,看了以後,我想應該是避免掉open /dev/console還有移掉不必要的步驟以提速。
- improve memcpy (這我不知道是哪裡的,要再查看看)
- reduce kernel size:這可以加快 u-boot 載入時間。一般手段就移掉不必要的driver/module。
- reduce u-boot delay time:u-boot 預設有 delay time,這可以改掉
- kernel 壓縮或不壓縮:用zImage的話可以減少kernel大小,可是要評估解壓縮時間跟載入時間的平衡來決定壓縮或不壓縮。
- 利用 gcc 的 –finstrument-functions –function-sections 去 profile function 的時間 (簡報說加了這兩個 argument,就可以在 __cyg_profile_func_enter/__cyg_profile_func_exit 裡放 code,這個要鑽研 gcc 試試看。)
- 利用ubootchart/bootchart.org工具來測時間。
參考資料:
Lex 練習
看 lex & yacc 第一章的練習,然後改用 glib 的 GList 來做:
Lex 是用來 tokenize 輸入用的,也就是用來辨識說輸入裡有哪些東西是你要的。這個例子書上沒針對怎麼使用做解說,乍看之下,不容易懂。其實使用上就是打 verb is,表明說 is 是 verb,你可以一直輸入 verb read、verb write、noun book、noun dog….程式就會把你輸入的這些內容分類、放到list裏面去,之後你輸入 read、write、book 時,程式就會告訴你 read、write 是 verb,book 是 noun 。
改用 glib,是因為想練習 glib。g_list_find_custom令人意外地沒範例,不過用法挺簡單,主要變化在第二個參數,第二個參數是一個 function。該 function 第一個參數是 list 裡的元素,第二個參數就是 g_list_find_custom 裡的第二個參數,你可以參考 compare_word,應該是不難懂。
參考資料:
vold小記
- 根據 /system/etc/vold.fstab 去monitor可移除裝置。dev_mount label 掛載點 auto或第n個partition /sys下的路徑,要扣掉/sys
- NetlinkManager以netlink和kernel建立溝通管道以取得裝置insert/remove事件並做處置(NetlinkHandler)。
- NetlinkHandler內實際上是呼叫VolumeManager做進一步處理
- VolumeManager
- 管理的是Volume,DirectVolume是其子類別,這裡用了template pattern
- 負責mount/umount/share/unshare/format以及secure container
- 以CommandListener去listen以接收指令,也就是跟上層溝通的管道。(CommandListener, VoldCommand, Process, ResponseCode)。
- Volume/DirectVolume::mountVol 看來是個適合填 android usb gadget 所需資訊的地方。因為
- 有檢查狀態
- 可知道是哪一個partition或disk
- 可得知insert/remove狀態
- 需要/dev/device-mapper,所以kernel要把此部份打勾。這邊的設定還蠻多的:
CONFIG_MD=y CONFIG_BLK_DEV_DM=y CONFIG_DM_DEBUG=y CONFIG_DM_CRYPT=y CONFIG_DM_UEVENT=y CONFIG_CRYPTO_AEAD=y CONFIG_CRYPTO_AUTHENC=y CONFIG_CRYPTO_CBC=y CONFIG_CRYPTO_PCBC=y CONFIG_CRYPTO_HMAC=y CONFIG_CRYPTO_MD5=y CONFIG_CRYPTO_DES=y CONFIG_CRYPTO_TWOFISH=y CONFIG_CRYPTO_TWOFISH_COMMON=y
參考資料:
Airplane mode
在追bug時,去Trace的結果,後來發現如果Phone的RIL層有問題的話,會造成看起來沒有進Airplane mode但實際上卻已經進去的奇怪現象 。Android裡,選Airplane mode以後會發生的事情:
- AirplaneModeEnabler送broadcast message出來。有3個人會收到:1.wifi 2.bluetooth 3.Phone。wifi 跟 bluetooth 裡收到訊息以後的處理都很簡單,Phone 裡主要是呼叫 phone.setRadioPower() 這行 (Packages/apps/Phone/src/com/android/phone/PhoneApp.java)。
- 這時候會呼叫 GSMPhone/CDMAPhone 的 setRadioPower,GSMPhone/CDMAPhone 都繼承自 ServiceStateTracker,所以是呼叫 ServiceStateTracker.setRadioPower。
- ServiceStateTracker.setRadioPower 會呼叫 setPowerStateToDesired (CdmaServiceStateTracker/GsmServiceStateTracker),實際上又是呼叫 cm.setRadioPower
- cm 的型別是 CommandsInterface,只有 RIL 有實作此 interface (frameworks/base/telephony/java/com/android/internal/telephony/RIL.java)。自此,訊息往下丟到 RIL daemon,參照 reference-ril 裡的 setRadioState,之後處理完會回傳 RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED。
- RIL.java 的 processUnsolicited() 會處理,這邊會呼叫 setRadioStateFromRILInt(),setRadioStateFromRILInt()裏面又再呼叫 setRadioState (frameworks/base/telephony/java/com/android/internal/telephony/BaseCommands.java),這裡會去 notify,所以根據 mRadioStateChangedRestrants 找 registerForRadioStateChanged()
- 找 registerForRadioStateChanged 的結果,可以看到 GsmServiceStateTracker/CdmaServiceStateTracker 有去呼叫。再看 ServiceStateTracker 裡的 handler 去處理 EVENT_RADIO_STATE_CHANGED 的部份:setPowerStateToDesired() => pollState() => pollStateDone(),pollStateDone() 裏面就可以看到有用 phone.notifyServiceStateChanged(),notifyServiceStateChange 又是呼叫父類別的 notifyServiceStateChangedP()。
- notifyServiceStateChangedP() 呼叫 mNotifier.notifyServiceState。mNotifier 則是 DefaultPhoneNotifier,再看 DefaultPhoneNotifier,裏面就有 registry.notifyServiceState() (TelephonyRegistry.java),這會再呼叫 broadcastServiceStateChanged()。從這裡的 TelephonyIntents.ACTION_SERVICE_STATE_CHANGED 去找,可以發現只有 PhoneStateIntentReceiver 有收這個 broadcast message。
- PhoneStateIntentReceiver 會再去 sendMessage。AirplaneModeEnabler 裡就有使用 PhoneStateIntentReceiver,並註冊了自己的 handler,所以 AirplaneModeEnabler 最後就會收到,並且改變項目的狀態。
這段過程幾乎都是以非同步的方式在傳遞,並不是平鋪直敘的,所以我看了好幾次才確定是這麼一回事…沒邊寫邊記的話,恐怕會多繞好幾天…