Pages

2011年5月5日 星期四

System Property

「System Property」是儲存資料常用的方式,如同「Windows Registry」。它的 APIs 散佈在 Android codebase 的各個角落:.mk、.rc、.java、.c.cpp 都找的到。簡單來說,System Property 分為「get」和「set」兩種方法,「get」相對而言就容易許多,因為不需要去檢查權限,code flow 只要呼叫到 libcutils 的 property_get 即可。所以底下只討論「set」。

  
  由上圖得知,send_prop_msg 會透過 socket 將 cmd message 送給 INIT,當 INIT 接收到後,會呼叫 handle_property_set_fd 來做處理,該函式就會呼叫 check_perms 檢查權限,這也是為什麼有時候設定屬性會失敗的原因。check_perms 參考底下的 ACL (Access Control List) 做判斷:

<PATH>
system/core/init/property_service.c
struct {
const char *prefix;
unsigned int uid;
unsigned int gid;
} property_perms[] = {
{ "net.rmnet0.",      AID_RADIO,    0 },
{ "net.usb",          AID_RADIO,    0 },
{ "net.gprs.",        AID_RADIO,    0 },
{ "net.ppp",          AID_RADIO,    0 },
{ "ril.",             AID_RADIO,    0 },
{ "gsm.",             AID_RADIO,    0 },
{ "persist.radio",    AID_RADIO,    0 },
{ "net.dns",          AID_RADIO,    0 },
{ "net.",             AID_SYSTEM,   0 },
{ "dev.",             AID_SYSTEM,   0 },
{ "runtime.",         AID_SYSTEM,   0 },
{ "hw.",              AID_SYSTEM,   0 },
{ "sys.",             AID_SYSTEM,   0 },
{ "service.",         AID_SYSTEM,   0 },
{ "wlan.",            AID_SYSTEM,   0 },
{ "dhcp.",            AID_SYSTEM,   0 },
{ "dhcp.",            AID_DHCP,     0 },
{ "vpn.",             AID_SYSTEM,   0 },
{ "vpn.",             AID_VPN,      0 },
{ "debug.",           AID_SHELL,    0 },
{ "log.",             AID_SHELL,    0 },
{ "service.adb.root", AID_SHELL,    0 },
{ "service.adb.tcp.port", AID_SHELL,    0 },
{ "persist.sys.",     AID_SYSTEM,   0 },
{ "persist.service.", AID_SYSTEM,   0 },
{ "persist.security.", AID_SYSTEM,   0 },
{ NULL, 0, 0 }
};
「check_perms」檢查的流程為:
  1. 如果 UID 為 ROOT .. PASS。
  2. 如果屬性為 ro 開頭,就接續判斷 ro. 之後的字串。
  3. 和 ACL 一一比對,prefix 要相同、且 uid/gid 有一個相同 .. PASS。
底下是 uid/gid 定義的地方
<PATH>

system/core/include/private/android_filesystem_config.h

#define AID_ROOT             0  /* traditional unix root user */

#define AID_SYSTEM        1000  /* system server */

#define AID_RADIO         1001  /* telephony subsystem, RIL */
#define AID_BLUETOOTH     1002  /* bluetooth subsystem */
#define AID_GRAPHICS      1003  /* graphics devices */
#define AID_INPUT         1004  /* input devices */
#define AID_AUDIO         1005  /* audio devices */
#define AID_CAMERA        1006  /* camera devices */
...
...
static const struct android_id_info android_ids[] = {
{ "root",      AID_ROOT, },
{ "system",    AID_SYSTEM, },
{ "radio",     AID_RADIO, },
{ "bluetooth", AID_BLUETOOTH, },
{ "graphics",  AID_GRAPHICS, },
{ "input",     AID_INPUT, },
{ "audio",     AID_AUDIO, },
{ "camera",    AID_CAMERA, },
...
};

之前為了在 BluetoothService.java (UID/GID 皆為 system) 設定屬性,定義了 persist.bluetooth.a2dp 和 audioflinger.bluetooth.a2dp,但怎麼設定都設定不動,後來胡亂地嘗試 persist.service.bluetooth.a2dp 就成功了,回過頭來看,就是因為滿足 ACL 的要求啦!

如果自行定義的 prefix 可以正常存取,要嘛 UID/GID 為 ROOT;不然就只能唯讀。最後補充一點,在 /default.prop 這個檔案內看到的屬性,是 makefile 中由 ADDITIONAL_DEFAULT_PROPERTIES 這個變數產生;而 /system/build.prop 的是 build/tools/buildinfo.sh 和以下這段所產生。
ADDITIONAL_BUILD_PROPERTIES :=
$(ADDITIONAL_BUILD_PROPERTIES) \
$(PROPERTY_PROPERTY_OVERRIDES)

參考資料

Audio Reference

參考資料

Dalvik Heap Size Adjustment

調整這個數值,原則上,只要在 system/ 或者 framework/base/ 底下搜尋 dalvik.vm.heapsize 即可。這個東西可以在 init.c 用 property_set;可以在 init.rc 用 setprop;也可以像底下那樣,改在 makefile...##ReadMore##

PRODUCT_PROPERTY_OVERRIDES += \
   dalvik.vm.heapstartsize=5m \
   dalvik.vm.heapgrowthlimit=48m \
   dalvik.vm.heapsize=256m

系統啟動時,可以透過 adb shell getprop 來查看 dalvik.vm.heapsize 數值為何。

Monkey

之前為了檢驗修改執行緒優先權的應用程式,是否不易出現 ANR,所以用這個指令做重複性測試。##ReadMore##


<指令> 檢測 browser
./adb shell monkey -p  com.android.browser -v 50000

2011年5月4日 星期三

Low Memory Killer

當系統記憶體不足時,會依優先權來殺掉某些行程,以釋放記憶體。但是,Android 預設並沒有開啟這項功能,所以需要去啟用它。

<step1> Enable Kernel Module
CONFIG_ANDROID_LOW_MEMORY_KILLER=y

<step2> Setup Recycle Memory Criteria in init.rc
# Define the oom_adj values for the classes of processes that can be
# killed by the kernel.  These are used in ActivityManagerService.
setprop ro.FOREGROUND_APP_ADJ 0
setprop ro.VISIBLE_APP_ADJ 1
setprop ro.PERCEPTIBLE_APP_ADJ 2
setprop ro.HEAVY_WEIGHT_APP_ADJ 3
setprop ro.SECONDARY_SERVER_ADJ 4
setprop ro.BACKUP_APP_ADJ 5
setprop ro.HOME_APP_ADJ 6
setprop ro.HIDDEN_APP_MIN_ADJ 7
setprop ro.EMPTY_APP_ADJ 15

# Define the memory thresholds at which the above process classes will
# be killed.  These numbers are in pages (4k).
# These are currently tuned for tablets with approx 1GB RAM.
setprop ro.FOREGROUND_APP_MEM 8192
setprop ro.VISIBLE_APP_MEM 10240
setprop ro.PERCEPTIBLE_APP_MEM 12288
setprop ro.HEAVY_WEIGHT_APP_MEM 12288
setprop ro.SECONDARY_SERVER_MEM 14336
setprop ro.BACKUP_APP_MEM 14336
setprop ro.HOME_APP_MEM 14336
setprop ro.HIDDEN_APP_MEM 16384
setprop ro.EMPTY_APP_MEM 20480

# Write value must be consistent with the above properties.
# Note that the driver only supports 6 slots, so we have combined some of
# the classes into the same memory level; the associated processes of higher
# classes will still be killed first.
write /sys/module/lowmemorykiller/parameters/adj 0,1,2,4,7,15

write /proc/sys/vm/overcommit_memory 1
write /proc/sys/vm/min_free_order_shift 4
write /sys/module/lowmemorykiller/parameters/minfree 8192,10240,12288,14336,16384,20480

# Set init its forked children's oom_adj.
write /proc/1/oom_adj -16

# Tweak background writeout
write /proc/sys/vm/dirty_expire_centisecs 200
write /proc/sys/vm/dirty_background_ratio  5

  在 system/core/init/init.c 中會去讀取 init.rc,並將以上這些參數設定給 low memory killer。另外,上層還有一支 ActivityManagerService,但不知道他和底層 low memory killer 如何溝通。

2011年4月23日 星期六

Board Game in 內湖世界樹

三款遊戲介紹 ##ReadMore##

牙買加(Jamaica) .. <Link>
這是一款海盜拿金幣的遊戲,每回合會有一位玩家擲骰子,來決定每個人此次的白天、夜晚可以移動幾格,移動方式則定義在手牌中,可以前進、後退、拿金幣、拿水果、拿大砲等等。過程中可能需要付水果、付金幣,還會有機會和其他海盜打仗。最後只要有一位海盜繞完一圈,即結束遊戲,就可以結算看誰的金幣最多。


反抗軍(The resistance) .. <Link>
這是一款耍心機的遊戲,帝國軍混進反抗軍當中,試圖破壞每一場戰役。每回合會有領袖決定人選,當領袖指派某些人後,由大家投票決選,如果大夥都同意由「這些人」出征,那麼,接下來這些人可以拿到圈和叉的手牌,如果這些人打出來的牌,包含一個叉,表示這場戰役就是由帝國軍獲勝,最後拿到三勝者即結束遊戲。當壞人(帝國軍)是一件很累的事情。


世界七大奇蹟(7 Wonders) .. <Link>
這款遊戲我覺得還蠻好玩的,因為他需要發展原料、科技,也需要打仗,就像在玩世紀帝國一樣,所以,也比較吸引我們這些年輕小夥子。不過,由於手牌規則比較多,有興趣的就去看連結囉!


相關連結

2011年3月3日 星期四

Ubuntu 10.04 64bits 安裝 adobe flash player

  如果使用 64 位元的 Ubuntu,安裝 flash player 時,需下載代號為「square」的版本,它是給 64 位元作業系統使用的... <點這裡>。接著依尋以下步驟:
  1. 找到「Download plug-in for 64-bit Linux」,然後下載。
  2. 解壓縮會看到 libflashplayer.so。
  3. 將檔案移動至 /usr/lib/firefox-3.6.8/plugins/。
  4. 重新啟動 FireFox 即可。

2011年2月19日 星期六

JaveSE Sample

圖片連續播放範例 - 使用 Applet
import java.awt.Image ;
import java.awt.Graphics ;
import java.awt.event.ActionEvent ;
import java.awt.event.ActionListener ;
import java.applet.Applet ;
import javax.swing.Timer ; // 利用 Timer 觸發事件

public class Animation extends Applet implements ActionListener {

Image[] imgArray ;
Timer timer ;
final int imgPerSecond = 10 ;
final int latency = 10000/imgPerSecond ; // 延遲時間單位為毫秒
int id = 0 ;

public void init() {
imgArray = new Image[imgPerSecond] ;
for( int i = 0 ; i < color="#666666">// 逐一載入影像檔案
imgArray[i] = getImage( getCodeBase(), i+".gif" ) ;
}

public void start() {
timer = new Timer( latency, this ) ; // 計時器時間到時會通知this(動畫測試)物件
timer.start(); // 啟動計時器
}

public void paint( Graphics g ) {
g.drawImage( imgArray[id], 0, 0, this ) ;
}

public void actionPerformed( ActionEvent event ) { // 計時器時間到時被呼叫的方法
id = ( id + 1 ) % imgPerSecond ;
repaint() ; // 此方法會清除繪圖區之後呼叫paint方法
}

}
使用時,在 Html 檔案中加入
其中 *.class 為要載入的 class 檔,寬高可自行設定。

Advantage of StringBuilder

在 J2SE 5.0 後新增的 API,在這之前處理字串是使用 java.lang 中的 String,不過 String 物件是不可修改內容【註一】,因此會造成每修改一下,就有新物件產生,如此在效能上會造成影響,以下是程式碼說明使用 String 和 StringBuilder 上的差異...

public class StringBuilderUsed {
public static void main( String[] args ) {
  String text = "" ;

long beginTime = System.currentTimeMillis() ;
for( int i = 0 ; i < 10000 ; ++i )
text = text + i ; // 使用 String 串接
long endTime = System.currentTimeMillis() ;

System.out.println( "執行時間:" + ( endTime - beginTime ) ) ;

  StringBuilder builder = new StringBuilder("") ;

beginTime = System.currentTimeMillis() ;
for( int i = 0 ; i < 10000 ; ++i )
builder.append( String.valueOf(i) ) ; // 使用 StringBuilder 串接
endTime = System.currentTimeMillis() ;

System.out.println( "執行時間:" + ( endTime - beginTime ) ) ;
}
}

執行後的結果:
使用 String 的執行時間:6187 ms
使用 StringBuilder 的執行時間:16 ms
【註一】乍看之下我們可以任意讀寫 String 物件中的內容,事實上,當你修改裡頭的內容,系統會新增一個 String 物件來擺放你修改後的值,而原先的 String
物件則會放置到 string pool,詳細參考 Java SE 6 技術手冊。

2011年2月9日 星期三

快速復原遺失的「顯示桌面」捷徑

  在工作列的快速啟動裡有一個很好用的捷徑,叫做「顯示桌面」,點一下就可以把所有視窗最小化,方便存取桌面項目或是重新開啟需要的視窗。##ReadMore##

  不過總是有人會不小心把「顯示桌面」刪除,或是不知道拖到哪裡去了,這裡有一個快速復原的方法:
開始 -> 執行
regsvr32 /n /i:u shell32
 
Blogger Templates