2011/08/05

svn on ubuntu

之前寫過幾篇跟 SVN 有關的文章,例如 svn server on win-xp ,或是 SVN 版本控管, 不過都是在 winXP 或是 Win7 上的,現在來寫一下怎樣在 Ubuntu 上安裝 svn。最後那篇值得沒用過的人參考一下。

首先,這樣的文章很容易找,例如 Ubuntu Help。不過我試了試會出點小問題,底下是我自己的小心得

一、照 Ubuntu Help 教的,先安裝套件:
sudo apt-get install subversion libapache2-svn
二、先決定自己的 repository 的佈置邏輯,以我為例,我是打算放在 /home/svn/PROJ 下,每個 PROJ 有一個 Repository, 也有得人懶得管理那麼複雜,所有 Projects 都放同一個 repository....決定好之後進行第三步,但是這邊舉例的兩種邏輯其實管理起來差異很大,我再補充補充:
1. 前一種在設定上比較麻煩,但是每個 Project 的 revision number(就是俗稱的版本號碼)是分開各自計算,好處就是可以對每個 Project 做版本控管,也可以做存取權限的控管,也就是可以分別控制誰可以存取
2. 後一種在設定上非常簡單,設過一次就不必再管理,但是將來的 Project 其實是在同一個repository 之下,無法分開控管
三、不管哪一種方式,總要先建立我要放 repository 的 home directory, 因此命令是:
$ sudo mkdir /home/svn
四、我弄了一個 shell script 叫 new-repository.sh....
#!/bin/bash
help()
{
  echo Usage: $0 PROJECT_NAME
  exit 0
}

[ "x$1" = "x" ] && help
SVN_HOME=/home/svn
cd $SVN_HOME
mkdir -p $1
svnadmin create $1
chown -R www-data:subversion $1
cd /home/svn/$1/conf
rm -f passwd svnserve.conf
ln -s $SVN_HOME/.conf/passwd .
ln -s $SVN_HOME/.conf/svnserve.conf .
五、要新弄一個 project 的話,只要簡單的下命令,不過請暫緩這個步驟,請先看第六步再回頭執行這一步:
$ sudo new-repository.sh MY-NEW-PROJECT
譬如
$ sudo new-repository.sh wade
六、從上面的 script 可以看到,事實上我也是讓每個 Project 用相同的存取設定,若您真的要分別管理的話,只要讓該 repository 裡面的 conf/passwd 或是 conf/svnserve.conf 不同即可, 這兩個檔的範例如下:
[users]
wade = iamwade
[general]
anon-access = read
auth-access = write
password-db = passwd
七、當您執行過第五步之後,就會產生一個適當的 repository, 那麼接下來就是要啟動 svn server....但是,竟然沒有 ubuntu 下的 /etc/init.d/svn 或是 /etc/init.d/svnserve....先看看怎麼啟動它:
$ sudo svnserve -d -r /home

$ sudo svnserve -d -r /home/svn
以上兩個方法,將來在存取時的路徑會不一樣,我是採用前一個
八、為了方便啟動/停止此項服務,我自己弄了個 /etc/init.d/svn, 內容如下,存好之後當然要讓它可執行($ sudo chmod +x /etc/init.d/svn):
#! /bin/sh
set -e

test -x /usr/bin/svnserve || exit 0
( /usr/bin/svnserve 2>&1 | grep -q exactly ) 2>/dev/null || exit 0

umask 022
SVN_OPTS="-d -r /home"

. /lib/lsb/init-functions

case "$1" in
  start)
        log_daemon_msg "Starting subversion server" "svnserve"
        if start-stop-daemon --start --quiet --oknodo --pidfile /var/run/svnserve.pid --exec /usr/bin/svnserve -- $SVN_OPTS; then
            pidof svnserve > /var/run/svnserve.pid
            log_end_msg 0
        else
            log_end_msg 1
        fi
        ;;
  stop)
        log_daemon_msg "Stopping subversion server" "svnserve"
        if start-stop-daemon --stop --quiet --oknodo --pidfile /var/run/svnserve.pid; then
            log_end_msg 0
        else
            log_end_msg 1
        fi
        ;;

  restart)
        log_daemon_msg "Restarting subversion server" "svnserve"
        start-stop-daemon --stop --quiet --oknodo --retry 30 --pidfile /var/run/svnserve.pid
        if start-stop-daemon --start --quiet --oknodo --pidfile /var/run/svnserve.pid --exec /usr/bin/svnserve -- $SVN_OPTS; then
            log_end_msg 0
        else
            log_end_msg 1
        fi
        ;;

  status)
        status_of_proc -p /var/run/svnserve.pid /usr/bin/svnserve svnserve && exit 0 || exit $?
        ;;

  *)
        log_action_msg "Usage: /etc/init.d/svn {start|stop|restart|status}"
        exit 1
esac

exit 0
九、弄好上面的檔之後,就可以用一般的方式來管理服務,譬如 /etc/init.d/svn start, 或是 /etc/init.d/svn stop 或是 /etc/init.d/status
十、以上,您已經可以用 svn co svn://localhost/svn/wade 來取回 wade,當然此時是空的,或是您可以用 svn import /some/where/of/wade svn://localhost/svn/wade。要 remote 使用只要把 localhost 取代成 IP 即可。順便講一下前面第七步講啟動時的兩個方法,我是用前者啟動,若要改成後者,則存取路徑範例是 svn co svn://localhost/wade 。不知道有沒有比較出不同?
十一、若是要用 http:// 也行,我舉我的設定如下,請修改 /etc/apache2/sites-available/default 或是 /etc/apache2/mods-available/dav_svn.conf,後者就整個內容相同即可,前者則要放在<VirtualHost>與</VirtualHost>之間,內容如下:
<Location /svn>
  DAV svn
  SVNParentPath /home/svn
  SVNListParentPath On
  AuthType Basic
  AuthName "wade's repository"
  AuthUserFile /home/svn/.conf/htpasswd
  Require valid-user
</Location>
十二、存好上面的檔之後,只需要 /etc/init.d/apache2 restart 即可生效
十三、對 http:// 的控制,上面並沒有分開控制存取權限,請對 Location 複製去改就可以,譬如:
<Location /svn/wade>
  DAV svn
  SVNPath /home/svn/wade
  # SVNListParentPath On
  AuthType Basic
  AuthName "wade's repository"
  AuthUserFile /home/svn/.conf/htpasswd
  Require valid-user
</Location>

2011/08/01

lftpget, wget, curl?

本文沒要談標題那麼大範圍。在取得 chromium os 的 source code 時,因為公司網路的關係,在抓 dev-java/icedtea6-bin-1.6.2-r2 時,一直出現 timeout 的現象,害我一直抓不完。曾經試過 wget, lftpget 兩套來抓,也都抓不完。

後來發現 curl 有些參數還頗優秀,如下:
--retry 50 <-- 指定個 50 次,總會抓成功了吧?沒想到沒用,因為.....
--retry-max-time 0 <-- 最大總嘗試時間.....呃,0 是無限大,這樣總行了吧?還是沒用,因為....retry 間隔是隨次數而加倍遞增,所以總嘗試時間會很久,最後會超過「整個操作的最大時間」,因此可以搭配
--retry-delay 20 <-- 這個可以限制嘗試間隔時間,不過「整個操作的最大時間」也要指明一下,如下
--max-time 2000 <-- 整個操作的最大時間,我想,這樣總夠了吧....

2011/07/01

google android nexus S adb howto

之前的中華電信 CHT8000 被我不小心掉進馬桶.....這事有點小故事,懶得多說,總之,最後我送修說要收我一萬多塊換板子,我當然不換,後來又堅持了一陣子,卻因為無法打電話,在接到副總來電無法對話之後,我只好忍痛買一支 google android nexus S。這支 Nexus S 好用是非常好用,而且非常省電,可是......我無法破解,在剛買第二天晚上我就試著要 root 它,失敗後竟然連開機都不行!!!天啊,只好花三百元送修還原。

好吧,以上小故事本來也不算什麼,誰知在這段送修的一週內,我又只好用回那台 CHT8000,竟然可以通話!!!!老天啊,這不是在玩我嗎?!

現在拿回 Nexus S 後,我不敢再 root 它,但是好歹也要給我能 adb 一下吧!!什麼叫 adb? 什麼叫 root? 不知道的人就不要看這篇算了。

參考一下這篇文章有提到怎樣讓你在 Ubuntu 下可以 adb....底下摘要一下:

$ cat /etc/udev/rules.d/51-android.rules
SUBSYSTEM=="usb", SYSFS{idVendor}=="18d1", MODE="0666"
$ sudo restart udev


接下來再插進 Nexus S 到 Ubuntu, 當然,你得在設定裡面打開 debug 選項,至於這項怎麼做我也不想多說,找一下就有了

2011/06/11

CDPATH 惹的禍

你曾經困擾於『/bin/bash: line 0: cd: libcore/$ANDROID_ROOT/libcore: No such file or directory』這樣的訊息嗎?我相信很少人會遇到。不過我會希望在下 cd command 時能方便的省略絕對路徑,所以我會設定 export CDPATH=".:..:$HOME", 而這樣的設定卻會帶來上述的 error message....

2011/06/10

android database management -2

前一篇所說的,sqlite3 還可以在命令列操作,

# sqlite3 -help                                         
Usage: sqlite3 [OPTIONS] FILENAME [SQL]
FILENAME is the name of an SQLite database. A new database is created
if the file does not previously exist.
OPTIONS include:
   -help                show this message
   -init filename       read/process named file
   -echo                print commands before execution
   -[no]header          turn headers on or off
   -bail                stop after hitting an error
   -interactive         force interactive I/O
   -batch               force batch I/O
   -column              set output mode to 'column'
   -csv                 set output mode to 'csv'
   -html                set output mode to HTML
   -line                set output mode to 'line'
   -list                set output mode to 'list'
   -separator 'x'       set output field separator (|)
   -stats               print memory stats before each finalize
   -nullvalue 'text'    set text string for NULL values
   -version             show SQLite version
裡面很多選項都跟上一篇寫的 sqlite3 命令有相對應。這邊講一下怎樣在 command line 寫成 script....

# sqlite3 /data/data/com.android.providers.settings/databases/settings.db "select * from system;"

上面的 sql 語法本來也可以在 sqlite3 命令提示下操作,寫在命令列則可以自動化。
# echo "select * from system;" | sqlite3 /data/data/com.android.providers.settings/databases/settings.db

用常見的 stdin 轉向也有同樣的功效,那麼,我們也可以寫在檔案中,再用 cat YourSQL.sql | sqlite3 YOUR_DATABASE 的方式
要特別跟大家講的是,有個 -init 選項,這個是進 sqlite3 的初始化, 也就是說....
1. 把你要的 sql 存檔,譬如把 select * from system; 存在 s.sql 中,然後用
2. sqlite3 -init s.sql /data/data/com.android.providers.settings/databases/settings.db 來執行的話,最後會停在 sqlite3 的命令提示符號下,所以與下面這方式是不同的...
3. cat s.sql | sqlite3 /data/data/com.android.providers.settings/databases/settings.db

2011/06/09

android database management -1

參考資訊: Android sqlite3 簡介, sqlite3 datatype, sqlite 語法

Android 用 Sqlite3 的格式來儲存資料,甚至系統的 setting, preference 都是如此,在進一步研究 sqlite3 之前,先列一下所有目前模擬機上的 database file(android 3.1):
/data/data/com.android.providers.contacts/databases/contacts2.db
/data/data/com.android.email/databases/EmailProvider.db
/data/data/com.android.email/databases/EmailProviderBody.db
/data/data/com.android.browser/app_databases/Databases.db
/data/data/com.android.browser/app_databases/https_mail.google.com_0/0000000000000001.db
/data/data/com.android.browser/app_appcache/ApplicationCache.db
/data/data/com.android.browser/databases/autofill.db
/data/data/com.android.browser/databases/webview.db
/data/data/com.android.browser/databases/browser2.db
/data/data/com.android.browser/databases/webviewCache.db
/data/data/com.android.browser/app_geolocation/CachedGeoposition.db
/data/data/com.android.browser/app_icons/WebpageIcons.db
/data/data/com.android.providers.downloads/databases/downloads.db
/data/data/com.android.quicksearchbox/databases/qsb-log.db
/data/data/com.android.inputmethod.latin/databases/userbigram_dict.db
/data/data/com.android.inputmethod.latin/databases/auto_dict.db
/data/data/com.android.providers.media/databases/internal.db
/data/data/com.android.providers.media/databases/external-80b2b02.db
/data/data/com.android.providers.settings/databases/settings.db
/data/data/com.android.providers.userdictionary/databases/user_dict.db
/data/data/com.android.launcher/databases/launcher.db
/data/data/com.android.providers.telephony/databases/mmssms.db
/data/data/com.android.providers.telephony/databases/telephony.db
/data/data/com.google.android.gsf/databases/gservices.db
/data/data/com.google.android.gsf/databases/googlesettings.db
/data/data/com.google.android.gsf/databases/subscribedfeeds.db
/data/data/com.google.android.gsf/databases/talk.db
/data/data/com.android.deskclock/databases/alarms.db
/data/system/accounts.db

sqlite3 是一個 android device 上的內建命令,因此要使用的話就得進 device shell, 譬如 adb shell。執行 sqlite3 的畫面如下:
# which sqlite3
/system/xbin/sqlite3
# sqlite3                                                       
SQLite version 3.7.4
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite>

上面提供了幾點資訊:
1. sqlite3 放在 /system/xbin, 這是系統路徑
2. 版本是 3.7.4
3. sqlite3 的提示符號是 sqlite>
4. 每個命令要用分號 ; 來結束
5. 要取得說明請下 .help 命令

有些隱含的訊息像,命令都是以 . 開頭,這一點下過 .help 命令後就知道了,另外要離開 sqlite3 的話,可以下 .quit 命令,或是 ctrl-D

這篇先列所有命令先,也就是 .help 畫面:

sqlite> .help
.backup ?DB? FILE      Backup DB (default "main") to FILE
.bail ON|OFF           Stop after hitting an error.  Default OFF
.databases             List names and files of attached databases
.dump ?TABLE? ...      Dump the database in an SQL text format
                         If TABLE specified, only dump tables matching
                         LIKE pattern TABLE.
.echo ON|OFF           Turn command echo on or off
.exit                  Exit this program
.explain ?ON|OFF?      Turn output mode suitable for EXPLAIN on or off.
                         With no args, it turns EXPLAIN on.
.header(s) ON|OFF      Turn display of headers on or off
.help                  Show this message
.import FILE TABLE     Import data from FILE into TABLE
.indices ?TABLE?       Show names of all indices
                         If TABLE specified, only show indices for tables
                         matching LIKE pattern TABLE.
.load FILE ?ENTRY?     Load an extension library
.log FILE|off          Turn logging on or off.  FILE can be stderr/stdout
.mode MODE ?TABLE?     Set output mode where MODE is one of:
                         csv      Comma-separated values
                         column   Left-aligned columns.  (See .width)

                         html     HTML <table> code
                         insert   SQL insert statements for TABLE
                         line     One value per line
                         list     Values delimited by .separator string
                         tabs     Tab-separated values
                         tcl      TCL list elements
.nullvalue STRING      Print STRING in place of NULL values
.output FILENAME       Send output to FILENAME
.output stdout         Send output to the screen
.prompt MAIN CONTINUE  Replace the standard prompts
.quit                  Exit this program
.read FILENAME         Execute SQL in FILENAME
.restore ?DB? FILE     Restore content of DB (default "main") from FILE
.schema ?TABLE?        Show the CREATE statements
                         If TABLE specified, only show tables matching
                         LIKE pattern TABLE.
.separator STRING      Change separator used by output mode and .import
.show                  Show the current values for various settings
.stats ON|OFF          Turn stats on or off
.tables ?TABLE?        List names of tables
                         If TABLE specified, only list tables matching
                         LIKE pattern TABLE.
.timeout MS            Try opening locked tables for MS milliseconds
.width NUM1 NUM2 ...   Set column widths for "column" mode
.timer ON|OFF          Turn the CPU timer measurement on or off

2011/06/08

Android screenshot

要對 Android device screenshot 的話,最簡單的方法是透過 ddms, ddms 連上 device 後,就有個命令叫 screenshot 直接取回 png 格式。這方法可以在 Ubuntu/Windows 上進行,算是最方便的。

不過,若我們要做到像「每3秒取回一張 screenshot」要怎麼辦?首先,可以參考 Android source code 中的
sdk/screenshot/src/com/android/screenshot/Screenshot.java
它的做法基本上跟 ddms 的做法是完全一模一樣的,只是這個可以產生一個可執行檔,放在  out/host/linux-x86/bin/screenshot2.jar

上述 screenshot2 有搭配一個同名的 shell script 程式,純粹用來設定執行 out/host/linux-x86/framework/screenshot2.jar 的執行環境, 因為是 jar file, 理論上也可以在 windows 下執行才對,但是我沒測試過在 windows 下執行,想必也很複雜,因為還要裝 DDMS library。

還有一個辦法是透過直接抓取 /dev/graphics/fb0 來轉換,Android 是採用 framebuffer 來做 display device, 不過直接抓這個 framebuffer 的話,其格式是 raw image, 或是說,我們必須先研究出 android device framebuffer format, 這一點根據我的研究是每個產品都可以不一樣,每個 android version 也不見得相同。But….至少在我的 android 3.1 模擬機中,是 16 bpp, 這一點,最好是看上面提到的 sdk/screenshot/src/com/android/screenshot/Screenshot.java 中會有線索。

上述的提到的直接存取 framebuffer 的做法上,可以參考下面的方法:
$ adb pull /dev/graphics/fb0 fb0.raw   #
這一步可以抓回 device 上的  screenshot raw image
$ ffmpeg -vframes 1 -vcodec rawvideo -f rawvideo -pix_fmt rgb565le -s 1280x800 -i fb0.raw -f image2 -vcodec png fb0.png
# 上面 ffmpeg 的參數可以參考 Screenshot.java 給的線索,當然 code 本身沒有,自己印出來看就知道了

 
上述命令必須在有安裝 ffmpeg 的環境才能執行,因此是可以在 Ubuntu/Windows 下執行的。比較神奇的是,明明 file size 1280x800x4, 我原本以為是 32bpp, 結果是 16bpp

參考資訊: http://stackoverflow.com/questions/2807070/screenshot-of-the-nexus-one-from-adb

2011/04/19

sshfs on window7, dokan 簡介

繼上次寫過『sshfs』之後,一直沒在看這段,不過目前又有用到,上次寫的太簡單,這邊就多寫一些,當然若要用 winScp 也是不錯的選擇。

首先,到 http://dokan-dev.net/en/download/ 去抓檔案,必須抓的檔案有三個:
1. 抓 Dokan library, 目前是 dokan-0.6.0 2011/01/10,是個執行檔,執行它
2. 抓 dokan-sshfs-0.2.0,是個 msi, 沒錯,你沒看錯,是 0.2.0, 不知道為什麼作者要這樣放,執行它
3. 抓 0.2.0 的補丁。解壓它,然後蓋掉上面 0.2.0 安裝路徑下的檔案,共有5個

最後,就是執行上面覆蓋後的 DokanSSHFS.exe , 我是安裝在 C:\Program Files (x86)\Dokan\DokanSSHFS\

或請參考 sshfs for windows 一文

2011/03/21

Android ApiDemos

這篇目前就當成註記。

Android 有個很重要的 Sample code 叫 ApiDemos, 這個的重要性不止是它內附了非常多的 API demo 用法,還是 CTS 的測試項目之一。

有兩篇不錯的文章註記在這兒:
http://hunter2014.javaeye.com/blog/778160
http://cheng-min-i-taiwan.blogspot.com/2010/10/apidemos.html

2011/02/21

Help for adb on windows

求救!!!求救!!!,不知道有沒有朋友可以教一下,怎樣在 windows 編譯 adb? 因為工作上的需求,需要在 windows 修改屬於自己的 adb.....

關於這個問題,我有找到How to build Android Windows SDK,這篇講的不錯,不過我找到的第一篇是構建Windows版的Android SDK,只是兩篇都沒有教人怎樣成功編譯 adb on windows.....嗚呼

2011/02/14

libusb 初探4-device IO

usb 作為一個通用 IO bus,當然就具備同步與非同步,當然非同步相對複雜,我們就看同步IO的就好了

同步 IO 有二種(其實還有第三種叫 stream, 似乎沒被實作):
libusb_bulk_transfer() : Perform a USB bulk transfer.
及 libusb_interrupt_transfer() : Perform a USB interrupt transfer.

而要跟 device 溝通,很重要的一個函數叫 libusb_control_transfer()
Function Documentation

int libusb_control_transfer ( libusb_device_handle *  dev_handle,
    uint8_t  bmRequestType,
    uint8_t  bRequest,
    uint16_t  wValue,
    uint16_t  wIndex,
    unsigned char *  data,
    uint16_t  wLength,
    unsigned int  timeout  
)   
Perform a USB control transfer.

The direction of the transfer is inferred from the bmRequestType field of the setup packet.

The wValue, wIndex and wLength fields values should be given in host-endian byte order.

Parameters:
    dev_handle  a handle for the device to communicate with
    bmRequestType  the request type field for the setup packet
    bRequest  the request field for the setup packet
    wValue  the value field for the setup packet
    wIndex  the index field for the setup packet
    data  a suitably-sized data buffer for either input or output (depending on direction bits within bmRequestType)
    wLength  the length field for the setup packet. The data buffer should be at least this size.
    timeout  timeout (in millseconds) that this function should wait before giving up due to no response being received. For an unlimited timeout, use value 0.

Returns:
  on success, the number of bytes actually transferred
  LIBUSB_ERROR_TIMEOUT if the transfer timed out
  LIBUSB_ERROR_PIPE if the control request was not supported by the device
  LIBUSB_ERROR_NO_DEVICE if the device has been disconnected
  another LIBUSB_ERROR code on other failures
上面有句話不知道有沒注意到: The wValue, wIndex and wLength fields values should be given in host-endian byte order

底下來寫一點心得:

.首先就是找到 usb device 有兩種方法,一種是透過 cnt = libusb_get_device_list(NULL, &devs) 這樣的呼叫,另一種則是透過 devh = libusb_open_device_with_vid_pid(NULL, 0x05ba, 0x000a);

.在 libusb_get_device_list() 的第一個參數 libusb_context,這是讓你可以同時控制兩個 libusb sessions, 一般情況不必管這個值的話就給 NULL 即可

.底下有一段利用 libusb_control_transfer() 來跟 device 溝通的範例:
#define CTRL_IN                 (LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_IN)
#define USB_RQ                  0x04

static int print_f0_data(void)
{
        unsigned char data[0x10];
        int r;
        unsigned int i;

        r = libusb_control_transfer(devh, CTRL_IN, USB_RQ, 0xf0, 0, data,
                sizeof(data), 0);
        if (r < 0) {
                fprintf(stderr, "F0 error %d\n", r);
                return r;
        }
        if ((unsigned int) r < sizeof(data)) {
                fprintf(stderr, "short read (%d)\n", r);
                return -1;
        }

        printf("F0 data:");
        for (i = 0; i < sizeof(data); i++)
                printf("%02x ", data[i]);
        printf("\n");
        return 0;
}
其中libusb_control_transfer() 裡的第二個參數決定 request 的型態,以上例是 LIBUSB_REQUEST_TYPE_VENDOR, 這個是非 STANDARD, 因此視 application(device) 而定。 .這邊再舉個例子:
int config;
    uint8_t tmp = 0;
    r = libusb_control_transfer(dev, LIBUSB_ENDPOINT_IN,
           LIBUSB_REQUEST_GET_CONFIGURATION, 0, 0, &tmp, 1, 1000);
    if (r == 1) {
          config = tmp;
    }
.最後再來看一個例子
void check_device(libusb_device *dev)
{
  ...
  int r = libusb_get_device_descriptor(dev, &desc);  // 先取得 device descriptor,因為內藏豐富資訊
  ...
  if (!is_adb_interface (desc.idVendor, desc.idProduct,
                         ADB_CLASS, ADB_SUBCLASS, ADB_PROTOCOL))
  { .... }

  /* 底下兩行再取得 device handler 的 bus, address 資訊, 以便給 libusb_open() 使用 */
  uh.dev_bus = libusb_get_bus_number(dev);
  uh.dev_addr = libusb_get_device_address(dev);

  /* 底下四行取得 device 的 active config descriptor,必須其 interface 有值才合法
     因為每個 usb device 是可以 config 成多個不同 device type,
     在此只需要取回現行的 config 即可(即 active config)
  */
  r = libusb_get_active_config_descriptor(dev, &config);
  if (config->interface != NULL) {
        found = check_usb_interfaces(config, &desc, &uh); // 檢查是否 support android adb
  }

  /* 底下開始要進一步與 device 溝通取回更多資訊 */

  r = libusb_open(dev, &uh.devh); // 類似 libusb_open_device_with_vid_pid()
  uh.dev = dev;

  if (found >= 0) {
        ....
        // 在對 endpoint 進行 I/O 之前,一定要 claim interface
        uh.interface = found;
        r = libusb_claim_interface(uh.devh, uh.interface);
        ....
        if (desc.iSerialNumber) {
            // reading serial
            uint16_t    buffer[128] = {0};
            uint16_t    languages[128] = {0};
            int languageCount = 0;

            memset(languages, 0, sizeof(languages));
            r = libusb_control_transfer(uh.devh,
                LIBUSB_ENDPOINT_IN |  LIBUSB_REQUEST_TYPE_STANDARD | LIBUSB_RECIPIENT_DEVICE,
                LIBUSB_REQUEST_GET_DESCRIPTOR, LIBUSB_DT_STRING << 8,
                0, (uint8_t *)languages, sizeof(languages), 0);
            ....
            languageCount = (r - 2) / 2;
            for (i = 1; i <= languageCount; ++i) {
                memset(buffer, 0, sizeof(buffer));

                /* 底下透過 request type 為 LIBUSB_REQUEST_TYPE_STANDARD 來指定
                   LIBUSB_REQUEST_GET_DESCRIPTOR 的方式取回 android device ID string
                   其傳回值型態由 LIBUSB_DT_STRING 指定,其值為 iSerialNumber
                */
                r = libusb_control_transfer(uh.devh,
                    LIBUSB_ENDPOINT_IN |  LIBUSB_REQUEST_TYPE_STANDARD | LIBUSB_RECIPIENT_DEVICE,
                    LIBUSB_REQUEST_GET_DESCRIPTOR, (LIBUSB_DT_STRING << 8) | desc.iSerialNumber,
                    languages[i], (uint8_t *)buffer, sizeof(buffer), 0);
                .... // 處理存在 buffer 中的 serial 資訊,也就是 android device ID
            }
            if (register_device(&uh, serial) == 0) {
                ..... // fail
            }
            else { // success
                libusb_ref_device(dev);
            }
        }
  }
  ......
}

libusb 初探3-usb device descriptor

完整說明請見 usb device descriptor,底下僅列出資料結構:

Data Fields

uint8_t bLength
Size of this descriptor (in bytes).
uint8_t bDescriptorType
Descriptor type.
uint16_t bcdUSB
USB specification release number in binary-coded decimal.
uint8_t bDeviceClass
USB-IF class code for the device.
uint8_t bDeviceSubClass
USB-IF subclass code for the device, qualified by the bDeviceClass value.
uint8_t bDeviceProtocol
USB-IF protocol code for the device, qualified by the bDeviceClass and bDeviceSubClass values.
uint8_t bMaxPacketSize0
Maximum packet size for endpoint 0.
uint16_t idVendor
USB-IF vendor ID.
uint16_t idProduct
USB-IF product ID.
uint16_t bcdDevice
Device release number in binary-coded decimal.
uint8_t iManufacturer
Index of string descriptor describing manufacturer.
uint8_t iProduct
Index of string descriptor describing product.
uint8_t iSerialNumber
Index of string descriptor containing device serial number.
uint8_t bNumConfigurations
Number of possible configurations.

libusb 初探2--libusb_get_device_list & libusb_get_device_descriptor

libusb_get_device_list() & libusb_get_device_descriptor() 這兩個函式,除了在 examples/lsusb.c 中出現範例之外,參考文件可以見libusb descriptor

攤開 libusb 的原始碼,裡面有一個 libusb_open_device_with_vid_pid(), 剛好就用了這兩個 api, 列之如下:


API_EXPORTED libusb_device_handle *libusb_open_device_with_vid_pid(
libusb_context *ctx, uint16_t vendor_id, uint16_t product_id)
{
struct libusb_device **devs;
struct libusb_device *found = NULL;
struct libusb_device *dev;
struct libusb_device_handle *handle = NULL;
size_t i = 0;
int r;

if (libusb_get_device_list(ctx, &devs) < 0) return NULL; while ((dev = devs[i++]) != NULL) { struct libusb_device_descriptor desc; r = libusb_get_device_descriptor(dev, &desc); if (r < 0) goto out; if (desc.idVendor == vendor_id && desc.idProduct == product_id) { found = dev; break; } } if (found) { r = libusb_open(found, &handle); if (r < 0) handle = NULL; } out: libusb_free_device_list(devs, 1); return handle; }

比較特別的就是多了 libusb_open()

透過 lsusb 研究 libusb

lsusb 是個很好用的工具,可以在 libusb取得,說明文件在這兒

打開 lsusb.c 可以看到程式架構很簡單除了初始化及後面的 print 及 free 外,比較重要的只有:
cnt = libusb_get_device_list(NULL, &devs)

原始碼如下:

int main(void)
{
libusb_device **devs;
int r;
ssize_t cnt;

r = libusb_init(NULL);
if (r < 0) return r; cnt = libusb_get_device_list(NULL, &devs); if (cnt < 0) return (int) cnt; print_devs(devs); libusb_free_device_list(devs, 1); libusb_exit(NULL); return 0; }


透過 libusb_get_device_list() 可以得到目前所有的 devices, 稍後再來看,先看看 print_devs()

static void print_devs(libusb_device **devs)
{
libusb_device *dev;
int i = 0;

while ((dev = devs[i++]) != NULL) {
struct libusb_device_descriptor desc;
int r = libusb_get_device_descriptor(dev, &desc);
if (r < 0) { fprintf(stderr, "failed to get device descriptor"); return; } printf("%04x:%04x (bus %d, device %d)\n", desc.idVendor, desc.idProduct, libusb_get_bus_number(dev), libusb_get_device_address(dev)); } }

對每個 usb device 做的動作就只有:
int r = libusb_get_device_descriptor(dev, &desc);
然後把 desc.idVendor, desc.idProduct, libusb_get_bus_number(dev), libusb_get_device_address(dev) 印出來

下一篇再來研究一下剩下的這兩個:
cnt = libusb_get_device_list(NULL, &devs)
int r = libusb_get_device_descriptor(dev, &desc);

2010/12/30

android 遠端搖控 remote control -- keyevent

android 要遠端控制的話,大抵上是用 adb 來實作,這邊的遠端其實不是網路理論上的那種 client server....

話說回來,光看 adb 的說明,可能還感覺不出遠端控制的效用,但是底下資訊幫著看的話,效果就大不同:

adb shell input text wirelessadb
adb shell input keyevent 66

上面是會讓 android 輸入 wirelessadb 然後送 "enter" 鍵,通常輸入文字是搜尋,所以代表可以查 wirelessadb
為了幫助我那可憐的有限記憶,底下把 keyevent 中能用的 key code 簡單的列下來,有篇非常好的文章值得有興趣的人進一步去研讀:
0 --> "KEYCODE_UNKNOWN"
1 --> "KEYCODE_MENU"
2 --> "KEYCODE_SOFT_RIGHT"
3 --> "KEYCODE_HOME"
4 --> "KEYCODE_BACK"
5 --> "KEYCODE_CALL"
6 --> "KEYCODE_ENDCALL"
7 --> "KEYCODE_0"
8 --> "KEYCODE_1"
9 --> "KEYCODE_2"
10 --> "KEYCODE_3"
11 --> "KEYCODE_4"
12 --> "KEYCODE_5"
13 --> "KEYCODE_6"
14 --> "KEYCODE_7"
15 --> "KEYCODE_8"
16 --> "KEYCODE_9"
17 --> "KEYCODE_STAR"
18 --> "KEYCODE_POUND"
19 --> "KEYCODE_DPAD_UP"
20 --> "KEYCODE_DPAD_DOWN"
21 --> "KEYCODE_DPAD_LEFT"
22 --> "KEYCODE_DPAD_RIGHT"
23 --> "KEYCODE_DPAD_CENTER"
24 --> "KEYCODE_VOLUME_UP"
25 --> "KEYCODE_VOLUME_DOWN"
26 --> "KEYCODE_POWER"
27 --> "KEYCODE_CAMERA"
28 --> "KEYCODE_CLEAR"
29 --> "KEYCODE_A"
30 --> "KEYCODE_B"
31 --> "KEYCODE_C"
32 --> "KEYCODE_D"
33 --> "KEYCODE_E"
34 --> "KEYCODE_F"
35 --> "KEYCODE_G"
36 --> "KEYCODE_H"
37 --> "KEYCODE_I"
38 --> "KEYCODE_J"
39 --> "KEYCODE_K"
40 --> "KEYCODE_L"
41 --> "KEYCODE_M"
42 --> "KEYCODE_N"
43 --> "KEYCODE_O"
44 --> "KEYCODE_P"
45 --> "KEYCODE_Q"
46 --> "KEYCODE_R"
47 --> "KEYCODE_S"
48 --> "KEYCODE_T"
49 --> "KEYCODE_U"
50 --> "KEYCODE_V"
51 --> "KEYCODE_W"
52 --> "KEYCODE_X"
53 --> "KEYCODE_Y"
54 --> "KEYCODE_Z"
55 --> "KEYCODE_COMMA"
56 --> "KEYCODE_PERIOD"
57 --> "KEYCODE_ALT_LEFT"
58 --> "KEYCODE_ALT_RIGHT"
59 --> "KEYCODE_SHIFT_LEFT"
60 --> "KEYCODE_SHIFT_RIGHT"
61 --> "KEYCODE_TAB"
62 --> "KEYCODE_SPACE"
63 --> "KEYCODE_SYM"
64 --> "KEYCODE_EXPLORER"
65 --> "KEYCODE_ENVELOPE"
66 --> "KEYCODE_ENTER"
67 --> "KEYCODE_DEL"
68 --> "KEYCODE_GRAVE"
69 --> "KEYCODE_MINUS"
70 --> "KEYCODE_EQUALS"
71 --> "KEYCODE_LEFT_BRACKET"
72 --> "KEYCODE_RIGHT_BRACKET"
73 --> "KEYCODE_BACKSLASH"
74 --> "KEYCODE_SEMICOLON"
75 --> "KEYCODE_APOSTROPHE"
76 --> "KEYCODE_SLASH"
77 --> "KEYCODE_AT"
78 --> "KEYCODE_NUM"
79 --> "KEYCODE_HEADSETHOOK"
80 --> "KEYCODE_FOCUS"
81 --> "KEYCODE_PLUS"
82 --> "KEYCODE_MENU"
83 --> "KEYCODE_NOTIFICATION"
84 --> "KEYCODE_SEARCH"
85 --> "TAG_LAST_KEYCODE"

2010/12/28

svn server on win-xp

自從兩年多前寫過一篇 svn 至今,終於「穩定」下來了,現在來寫一下 subversion server 安裝的部份。

先轉述一篇好文章的話:
匪夷所思的是國內資訊軟體公司中的資訊工程師似乎對其非常陌生」,
沒有 CVS/SVN 這類版本控制工具,任何修改程式碼的動作都會增加 programmer 大腦記憶體的負擔, programmer 將會浪費許多時間在搜尋與比對程式碼的工作之上』


subversion 原先由 CollabNet 維護,目前由 Apache 納入其專案中,可以至 Apache Subversion 專案查詢相關資訊。


---server---


1. 下載: 自 VisualSVN 下載最新的 binary, 我目前抓到的是 2.1.5
2. 執行它....這不必我多說,它是個 MSI 檔,可以自動進行大部份自動安裝工作,內含 svn server 2.1.5, 及 apache 2.2.17, svn client 1.6.15
3. 在安裝中,我選的是『Use Windows authentication』,畫面如下

4. 安裝之後,會問你要不要執行 VisualSVN Server Manager, 可以不執行,也可以叫出來看,當然看完可以按右上角的叉叉關掉,背景的 server 仍然會一直跑。畫面如下:
5. 接下來算是要維持日常的 server 維護工作,第一件事當然就是準備倉庫給 client 使用。做法很簡單,透過上面的管理界面跟檔案總管非常相像的按右鍵新增即可,畫面如下。仔細看的話,其實我是在最上層用『Create New Repository」新增了 EE1 這個倉庫,並在其下用『新增』『Project Structure』的方式新增了 android-testsuite 及 mfg-dll 兩個專案:
6. 檢查一下硬碟。根據上面的設定,我是把倉庫(Repository)放在 D:\SVN, 會發現 D:\SVN 確實有 EE1, 可是 D:\SVN\EE1\ 卻沒有 android-testsuite, 或是 mfg-dll 兩個目錄!!! 這是為什麼?原因是 EE1 是倉庫,而 android-testsuite, mfg-dll 兩個只是倉庫中的存貨。所有存貨都是在版本控制內的實體,而 subversion 並不是依靠存實體檔案的方式來控管,因此,請勿自行處理 D:\SVN\ 下面的目錄或檔案,這樣很容易損毀 subversion server system.

7, 接下來就是 client 端的操作了,可以看我那篇 svn 裡面的『TortoiseSVN (Client端) 使用流程』 一節。或是繼續往下看

---client---

1. 上傳新專案,通常新專案都是寫好一堆檔案了,此時可以一批次的上傳,在裝好 subversion client 之後,在要上傳的目錄按滑鼠右鍵,選擇 TortoiseSVN-->Import 即可,畫面如下

2. 在 Import 畫面照理說,應該填上面 server Manager 新增出來的倉庫網址,不過我習慣在一個倉庫裡放不同的 Project,其觀念與正統版本控制不太相符,但是帳號比較好管理。畫面如下:
  值得注意的是,我在硬碟中的目錄名稱是 SDC_FactoryDLL,而在 svn server  放的卻是 mfg-dll ,兩個可以是不一致。而完整的 subversion url 是 https://an970100770.quanta.corp:8443/svn/EE1/mfg-dll 而不是倉庫 url https://an970100770.quanta.corp:8443/svn/EE1

3. 如此一來,svn server 已經有所有檔案,而你原來上傳的目錄是在尚未管理的原始狀態。我這麼說你可能不是很懂,底下有兩個作法可以讓你體驗,看你喜歡哪一種挑選之實作一下:
  a. 刪除原來的整個目錄
  b. 選一個跟原來的目錄不同層的新工作目錄
然後.....在新工作目錄下,用滑鼠右鍵選 SVN Checkout, 在 url of repository 中填入 https://an970100770.quanta.corp:8443/svn/EE1/mfg-dll 即可完成工作,不過 Checkout Directory 則仍然會是倉庫的網址,我是另外存到相對應的目錄。畫面如下。當然第一次免不了要輸入帳號密碼。因為我在設定 svnserver 時用的是 windows 的認證機制,因此請填入你登入 windows 的帳號密碼即可。


檢查一下新下載的目錄,會發現每一層新的目錄都會多了一個 .svn 的子目錄,代表目前正受版本控制當中。

4. 若你想移除檔案的話,請不要直接刪除,而是透過 TortoiseSVN-->delete 來操作,因為這樣才會通知 server 做刪檔動作,若只是透過檔案總管操作刪檔的話,server  並不知道你要刪檔,這樣一來下次與系統同步更新時又會把你想刪除的檔抓下來。

5. 當你修改完程式之後,可以在檔案總管發現目錄變成紅色的驚嘆號,代表該目錄已經有被更動,你可以選擇馬上上傳到 server, 或是等工作到一段落後再上傳,畫面如下:



6. 所謂上傳到 svn server, 其實就是 svn commit 命令,畫面如下
7. 以上已經可以完成大部份的工作....不過最強的不是上傳檔案,否則你大概也會想說還不如直接壓縮來放就好。我們來看看一個基本的操作,跟前一版比對,畫面如下:
你可以發現右邊是新版的,它把變動的部份用黃色標註出來了

8. 若養成好習慣的話,每次上傳更新檔時都寫 log 訊息的話,這樣你可以透過 svn log 去取得上傳的 log 訊息,畫面如下:

9. 這樣一來,你知道了每次的更改,也就能隨時回到你想要的版本去,畫面中有個選項我一直沒提,就是 HEAD, 這代表最新的版本,例如我要回到「最原始」的狀態,以這邊來說是 revision 12....那就 checkout 的畫面填入 12, 要回到最新的版本,就勾選 HEAD, 勾選回到 revision 13 的畫面如下:


2010/12/27

android eclipse setup for ubuntu 10.10 64bit

寫過一篇android build on ubuntu 10.10,其實早就寫好關於 android app 的部份,只是並非寫在這兒,底下就貼一下。

* URL: http://developer.android.com/sdk/index.html
* Quick Start
  o Prepare your development computer
  o Download and install the SDK starter package
  o Install the ADT Plugin for Eclipse
  o Add Android platforms and other components to your SDK

Install Android SDK, Java, Eclipse

  * Host Environment: Ubuntu 10.04
  * Eclipse: sudo apt-get install eclipse eclipse-jdt
  * Start Eclipse:
    o 應用程式 ==> 軟體開發 ==> eclipse

Install ADT with Eclipse v3.5(Galileo)

  * URL: http://developer.android.com/sdk/eclipse-adt.html
  * Start Eclipse, then select Help > Install New Software.
  * In the Available Software dialog, click Add....
  * In the "Name" field: Android Plugin
  * In the "Location" field:
     https://dl-ssl.google.com/android/eclipse/
  * Click OK.
  * In the Available Software view:
    o Check the Developer Tools
      + Make sure check Android DDMS and Android Development Tools.
    o Click Next.
  * Click Next to read and accept the license agreement and install any dependencies, then click Finish.
  * Restart Eclipse.

Configuring the ADT Plugin

  * Select Window > Preferences
  * Select Android from the left panel.
  * SDK Location ==> click Browse ==> locate your downloaded SDK directory, such as "/home/wade/src/android/android-sdk-linux_86"
  * Click Apply, then OK.

Adding Android Platforms and Other...

  * URL: http://developer.android.com/sdk/adding-components.html
  * Windows --> Android SDK & AVD Manager

Install a Platform

  * In the Android SDK and AVD Manager, choose Available Packages in the left panel.
  * Click the repository site checkbox to display the components available for installation.
  * Select at least one platform to install, and click Install Selected. If you aren't sure which platform to install, use the latest version.

Create an AVD(做一次就好)

  * In Eclipse, choose Window > Android SDK and AVD Manager.
  * Select Virtual Devices in the left panel.
  * Click New.
     The Create New AVD dialog appears.
  * Type the name of the AVD, such as "my_avd".
  * Choose a target. The target is the platform (that is, the version of the Android SDK, such as 2.1) you want to run on the emulator.
      You can ignore the rest of the fields for now.
  * Click Create AVD.

Create a New Android Project

  * From Eclipse, select File > New > Project.
  * Select "Android" -> "Android Project" and click Next.
  * Fill in the project details with the following values:
    o Project name: HelloAndroid
    o Application name: Hello, Android
    o Package name: com.example.helloandroid (or your own private namespace)
    o Create Activity: HelloAndroid
    o Click Finish.

Construct the UI

Run the Application

  The Eclipse plugin makes it easy to run your applications:
  * Select Run > Run.
  * Select "Android Application".
    o Select Target Device
    o Project > Properties > Run/Debug Settings > Edit > Target > ....
  * For the first time to run android app, it will show "Select a way to run ...".
     Please select "Android Application"

Start Emulator(有兩個方法)

# Eclipse
  * By Project-->Run to start emulator with installation app
  * Window --> Android SDK and AVD Manager --> Virtual Devices, and then....
Select a device --> Start

# Command Line
  * $ export DISPLAY=:0.0
  $ emulator -system system.img -data userdata.img -ramdisk ramdisk.img

wifi 二三事

底下內容其實要找相關文獻很容易,我也一直懶得寫,但是剛好看到有人寫英文的,就順手翻譯下來。本文目的就是在命令列處理無線網路。底下的命令幾乎都要 root 權限,請自行取得,或是前面加上 sudo

.第一步是先透過 ifconfig -a 來查無線網路的裝置,不同的 Linux distribution 或是不同的無線網卡會有不同的命名方式,有的是 eth1, 有的是 wlan0,底下就假設是 wlan0
.再來用 iwlist wlan0 scan 來掃瞄 Access Point,舉例如下:
Cell 01 - Address: 00:11:22:33:44:55
          ESSID:"network-essid"
          Mode:Master
          Channel:11
          Frequency:2.462 GHz (Channel 11)
          Quality=100/100  Signal level:-47dBm  Noise level=-100dBm
          Encryption key:off
          .
          .
          .
.接下來可以用 iwconfig 來設定 essid, iwconfig wlan0 essid network-essid
.說穿了,就是用 iwconfig 來設定,還有很多項目可以設定,譬如頻率: iwconfig wlan0 freq 2.422G, or...
.以 channel 的方式來設定頻率相關資訊: iwconfig wlan0 channel 3,
.若在吵雜的環境中上網不良,可以試試修改「重試」次數: iwconfig wlan0 retry 16
.訊息不良的環境,甚至需要把封包切分小單位,譬如 iwconfig wlan0 frag 512
.有些網路卡不會馬上生效,必須加上這個: iwconfig wlan0 commit

以上用 iwconfig 來設定的全部選項可以放在一起,另外還有兩個命令可以用來幫助你 debug 無線網卡,一個是 iwspy 及 iwpriv

2010/12/24

monkey 又一章

寫過一篇Monkey 教學文件,不過那篇算是抄來的。

在 android /data/system/ 下有一個檔叫 packages.xml, 打開來看,會看到很多安裝的套件資訊,舉例來說,你可以找 <package 開頭的部份來看,此時你就可以知道有哪些套件可以進行 monkey 測試。

底下擷取部份內容說明一下....例如 第一個 <package name="com.android.soundrecorder" codePath="/system/app/SoundRecorder.apk"....

此時可以下 monkey -p com.android.soundrecorder -v 50 來對錄音軟體進行測試

<packages>
<package name="com.android.soundrecorder" codePath="/system/app/SoundRecorder.apk" nativeLibraryPath="/data/data/com.android.soundrecorder/lib" flags="1" ft="12d124faa98" it="12d124faa98" ut="12d124faa98" version="9" userId="10006">
<package name="android" codePath="/system/framework/framework-res.apk" flags="1" ft="12d12461578" it="12d12461578" ut="12d12461578" version="9" sharedUserId="1000">
<package name="com.android.launcher" codePath="/system/app/Launcher2.apk" nativeLibraryPath="/data/data/com.android.launcher/lib" flags="1" ft="12d124fae80" it="12d124fae80" ut="12d124fae80" version="9" userId="10023">
<package name="com.android.defcontainer" codePath="/system/app/DefaultContainerService.apk" nativeLibraryPath="/data/data/com.android.defcontainer/lib" flags="1" ft="12d124f7fa0" it="12d124f7fa0" ut="12d124f7fa0" version="9" userId="10024">
<package name="com.android.providers.contacts" codePath="/system/app/ContactsProvider.apk" nativeLibraryPath="/data/data/com.android.providers.contacts/lib" flags="1" ft="12d124f7fa0" it="12d124f7fa0" ut="12d124f7fa0" version="9" sharedUserId="10010">
<package name="com.android.settings" codePath="/system/app/Settings.apk" nativeLibraryPath="/data/data/com.android.settings/lib" flags="1" ft="12d1250bff0" it="12d1250bff0" ut="12d1250bff0" version="9" sharedUserId="1000">
<package name="com.android.quicksearchbox" codePath="/system/app/QuickSearchBox.apk" nativeLibraryPath="/data/data/com.android.quicksearchbox/lib" flags="1" ft="12d12496520" it="12d12496520" ut="12d12496520" version="110" userId="10028">
<package name="com.android.protips" codePath="/system/app/Protips.apk" nativeLibraryPath="/data/data/com.android.protips/lib" flags="1" ft="12d12547cf8" it="12d12547cf8" ut="12d12547cf8" version="1" userId="10026">
<package name="com.android.providers.applications" codePath="/system/app/ApplicationsProvider.apk" nativeLibraryPath="/data/data/com.android.providers.applications/lib" flags="1" ft="12d124f6c18" it="12d124f6c18" ut="12d124f6c18" version="9" sharedUserId="10010">
<package name="com.android.contacts" codePath="/system/app/Contacts.apk" nativeLibraryPath="/data/data/com.android.contacts/lib" flags="1" ft="12d1253b9a8" it="12d1253b9a8" ut="12d1253b9a8" version="9" sharedUserId="10010">
<package name="com.android.inputmethod.latin" codePath="/system/app/LatinIME.apk" nativeLibraryPath="/data/data/com.android.inputmethod.latin/lib" flags="1" ft="12d12548c98" it="12d12548c98" ut="12d12548c98" version="9" userId="10001">
<package name="com.android.phone" codePath="/system/app/Phone.apk" nativeLibraryPath="/data/data/com.android.phone/lib" flags="1" ft="12d12501028" it="12d12501028" ut="12d12501028" version="9" sharedUserId="1001">
<package name="com.android.calculator2" codePath="/system/app/Calculator.apk" nativeLibraryPath="/data/data/com.android.calculator2/lib" flags="1" ft="12d12549080" it="12d12549080" ut="12d12549080" version="9" userId="10014">
<package name="com.android.providers.drm" codePath="/system/app/DrmProvider.apk" nativeLibraryPath="/data/data/com.android.providers.drm/lib" flags="1" ft="12d124f8f40" it="12d124f8f40" ut="12d124f8f40" version="9" sharedUserId="10016">
<package name="com.android.htmlviewer" codePath="/system/app/HTMLViewer.apk" nativeLibraryPath="/data/data/com.android.htmlviewer/lib" flags="1" ft="12d124f9710" it="12d124f9710" ut="12d124f9710" version="9" userId="10017">
<package name="com.android.systemui" codePath="/system/app/SystemUI.apk" nativeLibraryPath="/data/data/com.android.systemui/lib" flags="1" ft="12d1254bf60" it="12d1254bf60" ut="12d1254bf60" version="9" sharedUserId="1000">
<package name="com.android.term" codePath="/system/app/Term.apk" nativeLibraryPath="/data/data/com.android.term/lib" flags="1" ft="12d124fc9d8" it="12d124fc9d8" ut="12d124fc9d8" version="9" userId="10018">
<package name="com.android.providers.calendar" codePath="/system/app/CalendarProvider.apk" nativeLibraryPath="/data/data/com.android.providers.calendar/lib" flags="1" ft="12d124f7bb8" it="12d124f7bb8" ut="12d124f7bb8" version="9" sharedUserId="10012">
<package name="com.android.bluetooth" codePath="/system/app/Bluetooth.apk" nativeLibraryPath="/data/data/com.android.bluetooth/lib" flags="1" ft="12d125459d0" it="12d125459d0" ut="12d125459d0" version="9" userId="10022">
<package name="com.android.speechrecorder" codePath="/system/app/SpeechRecorder.apk" nativeLibraryPath="/data/data/com.android.speechrecorder/lib" flags="1" ft="12d124fc208" it="12d124fc208" ut="12d124fc208" version="9" userId="10015">
<package name="com.android.development" codePath="/system/app/Development.apk" nativeLibraryPath="/data/data/com.android.development/lib" flags="1" ft="12d12544648" it="12d12544648" ut="12d12544648" version="1" userId="10000">
<package name="com.android.packageinstaller" codePath="/system/app/PackageInstaller.apk" nativeLibraryPath="/data/data/com.android.packageinstaller/lib" flags="1" ft="12d124fae80" it="12d124fae80" ut="12d124fae80" version="9" userId="10027">
<package name="com.android.calendar" codePath="/system/app/Calendar.apk" nativeLibraryPath="/data/data/com.android.calendar/lib" flags="1" ft="12d125461a0" it="12d125461a0" ut="12d125461a0" version="9" userId="10003">
<package name="com.android.providers.telephony" codePath="/system/app/TelephonyProvider.apk" nativeLibraryPath="/data/data/com.android.providers.telephony/lib" flags="1" ft="12d124fc9d8" it="12d124fc9d8" ut="12d124fc9d8" version="9" sharedUserId="1001">
<package name="com.android.browser" codePath="/system/app/Browser.apk" nativeLibraryPath="/data/data/com.android.browser/lib" flags="1" ft="12d124f8388" it="12d124f8388" ut="12d124f8388" version="9" userId="10002">
<package name="com.android.providers.subscribedfeeds" codePath="/system/app/AccountAndSyncSettings.apk" nativeLibraryPath="/data/data/com.android.providers.subscribedfeeds/lib" flags="1" ft="12d124f6c18" it="12d124f6c18" ut="12d124f6c18" version="9" sharedUserId="1000">
<package name="com.android.music" codePath="/system/app/Music.apk" nativeLibraryPath="/data/data/com.android.music/lib" flags="1" ft="12d125484c8" it="12d125484c8" ut="12d125484c8" version="9" userId="10008">
<package name="com.android.camera" codePath="/system/app/Camera.apk" nativeLibraryPath="/data/data/com.android.camera/lib" flags="1" ft="12d12546970" it="12d12546970" ut="12d12546970" version="1" userId="10011">
<package name="com.svox.pico" codePath="/system/app/PicoTts.apk" nativeLibraryPath="/data/data/com.svox.pico/lib" flags="1" ft="12d124fb268" it="12d124fb268" ut="12d124fb268" version="1" userId="10021">
<package name="com.cooliris.media" codePath="/system/app/Gallery3D.apk" nativeLibraryPath="/data/data/com.cooliris.media/lib" flags="1" ft="12d12549468" it="12d12549468" ut="12d12549468" version="30682" userId="10013">
<package name="com.android.email" codePath="/system/app/Email.apk" nativeLibraryPath="/data/data/com.android.email/lib" flags="1" ft="12d124fa6b0" it="12d124fa6b0" ut="12d124fa6b0" version="230000" userId="10020">
<package name="com.android.providers.downloads.ui" codePath="/system/app/DownloadProviderUi.apk" nativeLibraryPath="/data/data/com.android.providers.downloads.ui/lib" flags="1" ft="12d124f8f40" it="12d124f8f40" ut="12d124f8f40" version="9" sharedUserId="10016">
<package name="com.android.providers.userdictionary" codePath="/system/app/UserDictionaryProvider.apk" nativeLibraryPath="/data/data/com.android.providers.userdictionary/lib" flags="1" ft="12d124fcdc0" it="12d124fcdc0" ut="12d124fcdc0" version="9" sharedUserId="10010">
<package name="com.android.spare_parts" codePath="/system/app/SpareParts.apk" nativeLibraryPath="/data/data/com.android.spare_parts/lib" flags="1" ft="12d124fbe20" it="12d124fbe20" ut="12d124fbe20" version="9" userId="10005">
<package name="com.android.deskclock" codePath="/system/app/DeskClock.apk" nativeLibraryPath="/data/data/com.android.deskclock/lib" flags="1" ft="12d12547528" it="12d12547528" ut="12d12547528" version="202" userId="10009">
<package name="com.android.providers.settings" codePath="/system/app/SettingsProvider.apk" nativeLibraryPath="/data/data/com.android.providers.settings/lib" flags="1" ft="12d124fba38" it="12d124fba38" ut="12d124fba38" version="9" sharedUserId="1000">
<package name="android.tts" codePath="/system/app/TtsService.apk" nativeLibraryPath="/data/data/android.tts/lib" flags="1" ft="12d124fcdc0" it="12d124fcdc0" ut="12d124fcdc0" version="9" userId="10019">
<package name="com.android.mms" codePath="/system/app/Mms.apk" nativeLibraryPath="/data/data/com.android.mms/lib" flags="1" ft="12d124fbe20" it="12d124fbe20" ut="12d124fbe20" version="9" userId="10025">
<package name="com.android.provision" codePath="/system/app/Provision.apk" nativeLibraryPath="/data/data/com.android.provision/lib" flags="1" ft="12d124fb268" it="12d124fb268" ut="12d124fb268" version="9" userId="10004">
<package name="com.android.providers.media" codePath="/system/app/MediaProvider.apk" nativeLibraryPath="/data/data/com.android.providers.media/lib" flags="1" ft="12d124f9af8" it="12d124f9af8" ut="12d124f9af8" version="9" sharedUserId="10016">
<package name="com.android.providers.downloads" codePath="/system/app/DownloadProvider.apk" nativeLibraryPath="/data/data/com.android.providers.downloads/lib" flags="1" ft="12d124f8b58" it="12d124f8b58" ut="12d124f8b58" version="9" sharedUserId="10016">
<package name="com.android.certinstaller" codePath="/system/app/CertInstaller.apk" nativeLibraryPath="/data/data/com.android.certinstaller/lib" flags="1" ft="12d124f77d0" it="12d124f77d0" ut="12d124f77d0" version="9" userId="10007">
<package name="com.android.server.vpn" codePath="/system/app/VpnServices.apk" nativeLibraryPath="/data/data/com.android.server.vpn/lib" flags="1" ft="12d124fd1a8" it="12d124fd1a8" ut="12d124fd1a8" version="9" sharedUserId="1000">
</packages>

2010/11/11

android monkey 用法範例

文章原來源已遺失,好像類似情形不少,所以無法貼原文網址,原作者叫「俊傑」,感謝他:

Android 中Monkey的用法

簡介

Monkey是一個命令行工具,可以運行在模擬器裡或實際設備中。它向系統發送偽隨機的用戶事件流,實現對正在開發的應用程序進行壓力測試。Monkey包括許多選項,它們大致分為四大類:
  • 基本配置選項,如設置嘗試的事件數量。
  • 運行約束選項,如設置只對單獨的一個包進行測試。
  • 事件類型和頻率。
  • 調試選項。
在Monkey運行的時候,它生成事件,並把它們發給系統。 同時,Monkey還對測試中的系統進行監測,對下列三種情況進行特殊處理:
  • 如果限定了Monkey運行在一個或幾個特定的包上,那麼它會監測試圖轉到其它包的操作,並對其進行阻止。
  • 如果應用程序崩潰或接收到任何失控異常,Monkey將停止並報錯。
  • 如果應用程序產生了應用程序不響應(application not responding)的錯誤,Monkey將會停止並報錯。
按照選定的不同級別的反饋信息,在Monkey中還可以看到其執行過程報告和生成的事件。 Monkey基本用法 可以通過開發機器上的命令行或腳本來啟動Monkey。 由於Monkey運行在模擬器/設備環境中,所以必須用其環境中的shell來進行啟動。 可以通過在每條命令前加上adb shell來達到目的,也可以進入Shell後直接輸入Monkey命令。 基本語法如下: $ adb shell monkey [options] 如果不指定 options,Monkey將以無反饋模式啟動,並把事件任意發送到安裝在目標環境中的全部包。 下面是一個更為典型的命令行示例,它啟動指定的應用程序,並向其發送500個偽隨機事件: $ adb shell monkey -p your.package.name -v 500 命令選項參考 下表中列出了Monkey命令行可用的全部選項。
  • --help
    列出簡單的用法。
  • -v
    命令行的每一個-v將增加反饋信息的級別。Level 0(缺省值)除啟動提示、測試完成和最終結果之外,提供較少信息。Level 1提供較為詳細的測試信息,如逐個發送到Activity的事件。Level 2提供更加詳細的設置信息,如測試中被選中的或未被選中的Activity。
    事件
  • -s
    偽隨機數生成器的seed值。如果用相同的seed值再次運行Monkey,它將生成相同的事件序列。
  • --throttle
    在事件之間插入固定延遲。通過這個選項可以減緩Monkey的執行速度。如果不指定該選項,Monkey將不會被延遲,事件將儘可能快地被產成。
  • --pct-touch
    調整觸摸事件的百分比(觸摸事件是一個down-up事件,它發生在屏幕上的某單一位置)。
  • --pct-motion
    調整動作事件的百分比(動作事件由屏幕上某處的一個down事件、一系列的偽隨機事件和一個up事件組成)。
  • --pct-trackball
    調整軌跡事件的百分比(軌跡事件由一個或幾個隨機的移動組成,有時還伴隨有點擊)。
  • --pct-nav
    調整「基本」導航事件的百分比(導航事件由來自方向輸入設備的up/down/left/right組成)。
  • --pct-majornav
    調整「主要」導航事件的百分比(這些導航事件通常引發圖形界面中的動作,如:5-way鍵盤的中間按鍵、回退按鍵、菜單按鍵)
  • --pct-syskeys
    調整「系統」按鍵事件的百分比(這些按鍵通常被保留,由系統使用,如Home、Back、Start Call、End Call及音量控制鍵)。
  • --pct-appswitch
    調整啟動Activity的百分比。在隨機間隔裡,Monkey將執行一個startActivity()調用,作為最大程度覆蓋包中全部Activity的一種方法。
  • --pct-anyevent
    調整其它類型事件的百分比。它包羅了所有其它類型的事件,如:按鍵、其它不常用的設備按鈕、等等。
    約束限制
  • -p
    如果用此參數指定了一個或幾個包,Monkey將只允許系統啟動這些包裡的Activity。如果你的應用程序還需要訪問其它包裡的Activity(如選擇取一個聯繫人),那些包也需要在此同時指定。如果不指定任何包,Monkey將允許系統啟動全部包裡的Activity。要指定多個包,需要使用多個 -p選項,每個-p選項只能用於一個包。
  • -c
    如果用此參數指定了一個或幾個類別,Monkey將只允許系統啟動被這些類別中的某個類別列出的Activity。如果不指定任何類別,Monkey將選 擇下列類別中列出的Activity: Intent.CATEGORY_LAUNCHER或Intent.CATEGORY_MONKEY。要指定多個類別,需要使用多個-c選項,每個-c選 項只能用於一個類別。
    調試
  • --dbg-no-events
    設置此選項,Monkey將執行初始啟動,進入到一個測試Activity,然後不會再進一步生成事件。為了得到最佳結果,把它與-v、一個或幾個包約 束、以及一個保持Monkey運行30秒或更長時間的非零值聯合起來,從而提供一個環境,可以監視應用程序所調用的包之間的轉換。
  • --hprof
    設置此選項,將在Monkey事件序列之前和之後立即生成profiling報告。這將會在data/misc中生成大文件(~5Mb),所以要小心使用它。
  • --ignore-crashes
    通常,當應用程序崩潰或發生任何失控異常時,Monkey將停止運行。如果設置此選項,Monkey將繼續向系統發送事件,直到計數完成。
  • --ignore-timeouts
    通常,當應用程序發生任何超時錯誤(如「Application Not Responding」對話框)時,Monkey將停止運行。如果設置此選項,Monkey將繼續向系統發送事件,直到計數完成。
  • --ignore-security-exceptions
    通常,當應用程序發生許可錯誤(如啟動一個需要某些許可的Activity)時,Monkey將停止運行。如果設置了此選項,Monkey將繼續向系統發送事件,直到計數完成。
  • --kill-process-after-error
    通常,當Monkey由於一個錯誤而停止時,出錯的應用程序將繼續處於運行狀態。當設置了此選項時,將會通知系統停止發生錯誤的進程。注意,正常的(成功的)結束,並沒有停止啟動的進程,設備只是在結束事件之後,簡單地保持在最後的狀態。
  • --monitor-native-crashes
    監視並報告Android系統中本地代碼的崩潰事件。如果設置了--kill-process-after-error,系統將停止運行。
  • --wait-dbg
    停止執行中的Monkey,直到有調試器和它相連接。
接下來看一個實例 Monkey 的用法是$ adb shell monkey -p your.package.name -v 500 首先,我們要找到應用程序在Emulator中所對應的包名,我一開始是一個個目錄找的,前7步完成了這項工作,最終發現應用程序包都在 data/data下,你可以在shell中cd data/data,然後ls查看當前Emulator中的所有應用程序包。 假如我們想對SDK中的APIDemos做壓力測試,
  1. 在Eclipse中新建工程,將

    F:\android-sdk-windows\platforms\android-2.0\samples\ApiDemos添加到工程中點擊運行,此時,他的APK應該加載到了Emulator上

  2. 在命令行輸入adb shell

  3. 輸入ls查看當前文件夾下的目錄,執行結果如下

    C:\Documents and Settings\Administrator>adb shell
    # ls
    ls
    sqlite_stmt_journals
    config
    cache
    sdcard
    d
    etc
    system
    sys
    sbin
    proc
    init.rc
    init.goldfish.rc
    init
    default.prop
    data
    root
    dev

  4. 應用程序包都在data下,我們輸入cd data進入data文件夾,如下

    # cd data
    cd data
    
  5. 輸入ls查看文件夾下的內容,如下所示:

    # ls
    ls
    misc
    local
    data
    app-private
    app
    property
    anr
    backup
    dontpanic
    dalvik-cache
    system
    lost+found

  6. 還有個data,所有的應用程序就在這個data下了,進入這個data,然後輸入ls如下:

    # cd data
    cd data
    # ls
    ls
    com.android.mms
    com.android.providers.applications
    com.android.globalsearch
    com.android.calculator2
    com.android.spare_parts
    com.android.gesture.builder
    com.android.music
    com.android.sdksetup
    com.android.packageinstaller
    com.android.fallback
    com.android.providers.settings
    com.android.providers.drm
    com.android.development
    com.android.providers.telephony
    com.android.inputmethod.pinyin
    com.android.htmlviewer
    com.android.settings
    com.android.netspeed
    com.android.providers.userdictionary
    com.android.browser
    com.android.contacts
    com.android.alarmclock
    com.android.camera
    com.android.providers.contacts
    jp.co.omronsoft.openwnn
    com.android.launcher
    com.android.phone
    com.android.soundrecorder
    com.google.android.providers.enhancedgooglesearch
    com.svox.pico
    com.android.customlocale
    com.android.term
    com.android.providers.downloads
    com.android.providers.media
    com.android.email
    android.tts
    com.android.inputmethod.latin
    com.android.server.vpn
    com.example.android.apis

  7. 最後一個就是我們剛才加載的APIDemo的應用程序包

  8. 可以直接輸入monkey -p com.example.android.apis -v 50,結果如下,也可以退出shell,在命令行輸入,adb shell monkey -p com.example.android.apis -v 50 ,運行過程中,Emulator中的應用程序在不斷地切換畫面,可以看一下,呵呵:)

    # monkey -p com.example.android.apis -v 50
    monkey -p com.example.android.apis -v 50
    :Monkey: seed=0 count=50
    :AllowPackage: com.example.android.apis
    :IncludeCategory: android.intent.category.LAUNCHER
    :IncludeCategory: android.intent.category.MONKEY
    // Event percentages:
    //   0: 15.0%
    //   1: 10.0%
    //   2: 15.0%
    //   3: 25.0%
    //   4: 15.0%
    //   5: 2.0%
    //   6: 2.0%
    //   7: 1.0%
    //   8: 15.0%
    :Switch: #Intent;action=android.intent.action.MAIN;category=android.intent.categ
    ory.LAUNCHER;launchFlags=0x10000000;component=com.example.android.apis/.ApiDemos
    ;end
        // Allowing start of Intent { act=android.intent.action.MAIN cat=[android.in
    tent.category.LAUNCHER] cmp=com.example.android.apis/.ApiDemos } in package com.
    example.android.apis
    :Sending Pointer ACTION_MOVE x=-4.0 y=2.0
    :Sending Pointer ACTION_UP x=0.0 y=0.0
        // Allowing start of Intent { cmp=com.example.android.apis/.ApiDemos } in pa
    ckage com.example.android.apis
    :Sending Pointer ACTION_DOWN x=207.0 y=282.0
    :Sending Pointer ACTION_UP x=189.0 y=289.0
        // Allowing start of Intent { cmp=com.example.android.apis/.app.Intents } in
    package com.example.android.apis
    :Sending Pointer ACTION_DOWN x=95.0 y=259.0
    :Sending Pointer ACTION_UP x=95.0 y=259.0
    :Sending Pointer ACTION_DOWN x=295.0 y=223.0
    :Sending Pointer ACTION_UP x=290.0 y=213.0
    :Sending Pointer ACTION_MOVE x=-5.0 y=3.0
    :Dropped: keys=0 pointers=0 trackballs=0 flips=0
    ## Network stats: elapsed time=3799ms (3799ms mobile, 0ms wifi, 0ms not connecte
    d)
    // Monkey finished

2010/11/10

windows 上跑 adb 簡介

Android 基本上都可以透過 adb 從外面跟 DUT 溝通,可以參考 http://developer.android.com/guide/developing/tools/adb.html 的說明。
adb 只是 Android SDK 的一個工具,可以從 http://dl.google.com/android/android-sdk_r07-windows.zip 下載,或是從 http://developer.android.com/sdk/index.html 查最新的版本

網頁上文件說的很複雜,因為那是教人寫 Android Application 的文件,基本上最簡單的做法就是:
0. 安裝 windows 端的 android usb driver,這一步可能你們已經安裝了,可以把 DUT 插到 PC 上看能不能抓到裝置就知道了,若是未認得的裝置,再來安裝usb driver
1. 從上面的網址下載 SDK
2. 解開壓縮檔,譬如放在 android-sdk-windows 下
3. 直接進入 android-sdk-windows\tools 下用 cmd mode 的視窗(就是執行cmd.exe) 執行adb 即可

底下簡介一下 adb 的使用,當然都是在 cmd mode 下執行, 為了方便我底下說明,把要安裝的 TestSuite.apk 放在 C:\ android-sdk-windows\tools 下,可以依實際位置修改底下的命令:
  • C:\ android-sdk-windows\tools > adb devices <-- 查連接的 android devices,請先接一台就好
  • C:\ android-sdk-windows\tools > adb shell ls / <-- 遠端在 DUT 上的命令,假設只有連接一台,這個命令範例類似 dir C:\ 之意
  • C:\ android-sdk-windows\tools > adb push .\TestSuite.apk /data/TestSuite.apk <-- 將 TestSuite 從外面放到 DUT 上
  • C:\ android-sdk-windows\tools > adb install /data/TestSuite.apk <-- 要執行過上面的命令才能執行此命令。安裝後那台 DUT 就可以看到 TestSuite 的應用程式圖示
  • C:\ android-sdk-windows\tools > adb pull /proc/meminfo <-- 這樣可以抓到 DUT 上的 /proc/meminfo 這個檔,那是抓的當時 DUT 記憶體使用狀況
  • C:\ android-sdk-windows\tools > adb logcat <-- DUT 在執行應用程式時,通常會產生一堆的 標準log, 可以用這個命令抓下來,但是這個命令不會停止,若要離開請用 Ctrl-C 中斷它
  • C:\ android-sdk-windows\tools > adb reboot recovery <-- 可以讓 DUT 重開機進入 Recovery mode


Windows 上的 usb driver, 可以自 http://dl.google.com/android/repository/usb_driver_r03-windows.zip 取得,問題是網路上很難查到這樣的網址,這邊公佈一下我找的方法:

首先,取得 http://dl.google.com/android/repository/repository.xml,這個檔就是 android 的倉庫清單,剩下的就簡單了,譬如....裡面有一筆 <sdk:url>usb_driver_r03-windows.zip</sdk:url>,這樣就可以查到剛剛上面貼的 url: http://dl.google.com/android/repository/usb_driver_r03-windows.zip

2010/11/08

一個簡單的硬碟效能測試 -- dd

dd 是一個很特別的指令,尤其在 android 中並沒有 cp 存在,只有 dd....
當然,我會這樣說,就是可以用dd 來複製檔案,大家也都會 dd if=SOURCE of=TARGET 即可,底下再說一點點它特別之處

dd if=/dev/fd0 of=/home/sam/MBRboot.image bs=512 count=2
上面這樣可以將軟碟片的前面 512x2==1024 個 byte 讀出來,寫成一個新檔案叫 MBRboot.image

dd if=/dev/sda of=/home/sam/MBR.image bs=512 count=1
上面也是一樣道理,可以把硬體的開機磁區寫到一個新檔案叫 MBR.image

所謂的硬碟開機磁區,就是一個 partition table + boot code, 若您只需要 boot code, 可以用下面的方法:
dd if=/dev/sda of=/home/sam/MBR_boot.image bs=446 count=1

那還有沒有其他用法?
dd if=/dev/uramdom bs=1024 count=1000000 of=/home/sam/1Gb.file
dd if=/home/sam/1Gb.file bs=64k | dd of=/dev/null
上面的方法可以用來簡單測試硬碟效能,也就是你搭配將上面兩行寫成一個 shell, 再搭配 time 來量時間
若不想用 /dev/uramdom 也可以用 /dev/zero 來取代

如果想弄一個空的 1G 檔案出來,一般會寫成
dd if=/dev/zero of=1G-file bs=1M count=1024
可是啊,這樣真的就要寫「很久很久」,卻又有一個很簡單的方式,一瞬間就寫完了,真的是神奇
dd if=/dev/zero of=1G-file bs=1 count=0 seek=1G

2010/11/04

Android 開機過程 boot sequence

請見The Android boot process from power on一文

全部有幾個階段:
1. Power on and boot ROM code execution
2. The boot loader
3. The Linux kernel
4. The init process
5. Zygote and Dalvik
6. The system server
7. Boot completed

在 kernel 之前還算跟一般的 embedded linux 一樣,但是在 init 之後就完全走它自己的路。先來看前面步驟的示意圖










1. Power on and boot ROM code execution




  • A. The Boot ROM code will detect the boot media using a system register that maps to some physical balls on the asic. This is to determine where to find the first stage of the boot loader.
  • B. Once the boot media sequence is established the boot ROM will try to load the first stage boot loader to internal RAM. Once the boot loader is in place the boot ROM code will perform a jump and execution continues in the boot loader.

2. The boot loader



  • A. The first boot loader stage will detect and set up external RAM.
  • B. Once external RAM is available and the system is ready the to run something more significant the first stage will load the main boot loader and place it in external RAM.
  • C. The second stage of the boot loader is the first major program that will run. This may contain code to set up file systems, additional memory, network support and other things. On a mobile phone it may also be responsible for loading code for the modem CPU and setting up low level memory protections and security options.
  • D. Once the boot loader is done with any special tasks it will look for a Linux kernel to boot. It will load this from the boot media (or some other source depending on system configuration) and place it in the RAM. It will also place some boot parameters in memory for the kernel to read when it starts up.
  • E. Once the boot loader is done it will perform a jump to the Linux kernel, usually some decompression routine, and the kernel assumes system responsibility.

3. The Linux kernel

  • A. Once the memory management units and caches have been initialized the system will be able to use virtual memory and launch user space processes.
  • B. The kernel will look in the root file system for the init process (found under system/core/init in the Android open source tree) and launch it as the initial user space process.

4. The init process

  • A. The init process in Android will look for a file called init.rc. This is a script that describes the system services, file system and other parameters that need to be set up. The init.rc script is placed in system/core/rootdir in the Android open source project.
  • B. The init process will parse the init script and launch the system service processes.

5. Zygote and Dalvik

The Zygote is launched by the init process and will basically just start executing and initialize the Dalvik VM.

6. The system server

The system server is the first java component to run in the system. It will start all the Android services such as telephony manager and bluetooth. Start up of each service is currently written directly into the run method of the system server. The system server source can be found in the file frameworks/base/services/java/com/android/server/SystemServer.java in the open source project.

7. Boot completed

Once the System Server is up and running and the system boot has completed there is a standard broadcast action called ACTION_BOOT_COMPLETED. To start your own service, register an alarm or otherwise make your application perform some action after boot you should register to receive this broadcast intent.

2010/10/31

為你的電腦降溫 cooldown CPU

請直接參考BBOY 寫的這篇 Frequency Scaling

在linux底下首先打開make menuconfig-> Power Management support --->
[*] CPU Frequency scaling --->
Default CPUFreq governor (userspace)
< > 'performance' governor
< > 'powersave' governor
-*- 'userspace' governor for userspace frequency scaling
< > 'ondemand' cpufreq policy governor
< > 'conservative' cpufreq governor

接著echo你想要的頻率到/sys底下的file node。
ex:"echo 500000000 > /sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed"
如果我們去查一下該目錄,可以發現
# ls -l /sys/devices/system/cpu/cpu0/cpufreq
總計 0
-r--r--r-- 1 root root 4096 2010-10-31 23:44 affected_cpus
-r-------- 1 root root 4096 2010-10-31 23:44 cpuinfo_cur_freq
-r--r--r-- 1 root root 4096 2010-10-31 21:39 cpuinfo_max_freq
-r--r--r-- 1 root root 4096 2010-10-31 23:44 cpuinfo_min_freq
-r--r--r-- 1 root root 4096 2010-10-31 23:44 cpuinfo_transition_latency
-r--r--r-- 1 root root 4096 2010-10-31 23:44 related_cpus
-r--r--r-- 1 root root 4096 2010-10-31 21:41 scaling_available_frequencies
-r--r--r-- 1 root root 4096 2010-10-31 21:41 scaling_available_governors
-r--r--r-- 1 root root 4096 2010-10-31 21:41 scaling_cur_freq
-r--r--r-- 1 root root 4096 2010-10-31 21:41 scaling_driver
-rw-r--r-- 1 root root 4096 2010-10-31 21:39 scaling_governor
-rw-r--r-- 1 root root 4096 2010-10-31 21:41 scaling_max_freq
-rw-r--r-- 1 root root 4096 2010-10-31 21:41 scaling_min_freq
-rw-r--r-- 1 root root 4096 2010-10-31 23:41 scaling_setspeed
drwxr-xr-x 2 root root    0 2010-10-31 23:44 stats
底下就試著....
# cd /sys/devices/system/cpu/cpu0/cpufreq
# cat cpuinfo_cur_freq
2000000
發現我的電腦目前的頻率也才 2000000, 似乎單位與原文中的不一樣。
後來我去試著用c3dl demo來衡量 CPU 速度,確實可以透過原文章中的方式調慢,我的命令如下:
# for i in 0 1; do echo 1000000 > /sys/devices/system/cpu/cpu$i/cpufreq/scaling_setspeed; done

原文章有更多有用的資訊,有興趣的人請親自前往觀看

2010/10/25

cross compile busybox for android (為 android 準備 busybox)

我主要是參考cross compile busybox for android,大綱是:

1. 準備 cross compile 工具。
1. 這一項我原本試著用 ubuntu 的內建工具,也就是 xxxx-arm-linux-gnueabi 套件組,可是失敗。
2. 在文中提到可以自Download Sourcery G++ Lite Edition for ARM下載,請選『EABI』、『IA32 GNU/Linux TAR』,我下載的版本是 https://sourcery.mentor.com/public/gnu_toolchain/arm-none-linux-gnueabi/arm-2010q1-202-arm-none-linux-gnueabi-i686-pc-linux-gnu.tar.bz2

3. 解壓後,我是放在 /usr/local/cross-arm 下

2. 若不想自己編譯,也可以從 busybox 網站直接下載執行檔,我試過可以執行的有 busybox-armv6l, busybox-armv5l, busybox-armv4tl

3. 下載 busybox source code, 上面執行檔最新的是 1.17.2, 但是 source code 是 1.17.3, 因此也可以自己編譯 最新的 busybox 1.17.3 source code
1. 解壓後,使用 make menuconfig 來選擇組態
2. Busybox Settings -> Build Options -> 裡面,挑下面的選項,將它編譯成靜態載入
[*] Build BusyBox as a static binary (no shared libs)
3. 在同樣的地方,挑 () Cross Compiler prefex,按 Enter 後必須填第一步安裝的 cross compile tools, 我的是:
/usr/local/cross-arm/bin/arm-none-linux-gnueabi-
確定後剛剛的選項會變成:
(/usr/local/cross-arm/bin/arm-none-linux-gnueabi-) Cross Compiler prefex
4. 在 Busybox Settings -> Installation Options-> 裡面,挑下面的選項,讓 busybox 可以不必安裝到 /usr 下
[*] Don't use /usr
註:1.19.3 版移到 Busybox Settings -> General Configuration -> 下面了
4. 上面的選項存檔、離開後,就可以用 make 來編譯
5. 放到 device 上,我是模擬機,道理一樣:
adb push busybox /data/busybox.exe
上面是故意改名字的,下一步要用到
6. adb shell:
# mkdir /data/busybox
# cd /data/busybox
# /data/busybox.exe --install .

7. 改變 PATH 環境變數
這一項比較麻煩,原則上就是要改變 system image, 所以有兩個方法,一個是自己改 ramdisk.img, 要用這一招的話請參考 busybox及bash在android中的安裝及init.rc修改
還有一個方法,就是第一點文中的方法,將系統重新掛載成 rewritable.....

su #取得root權限
mount -o remount,rw /dev/block/mtdblock6 /system #重新mount使/system可寫
mv busybox /system/bin/ #移動busybox
chmod 777 /system/bin/busybox #設為可執行
/system/bin/busybox --isntall .
mount -o remount,ro /dev/block/mtdblock6 /system #恢復/system為只讀

2010/10/12

android dynamic GUI 動態介面--範例程式

先來看看 config 檔,
$ cat Sample.xml

<?xml version="1.0" encoding="UTF-8"?>
<cmds>
<cmd text="Test1" path="Add\add" params="3 5"/>
<cmd text="Test2" path="Add\add" params="7 9"/>
</cmds>


$ cat Sample1.xml

<?xml version="1.0" encoding="UTF-8"?>
<cmds>
<cmd text="umount sdcard" path="/system/bin/umount" params="/sdcard"/>
<cmd text="top" path="/system/bin/top" params=""/>
<cmd text="reboot" path="/system/bin/reboot" params=""/>
</cmds>


範例程式如下:

package com.example.helloandroid;

import android.app.Activity;
import android.os.Bundle;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.File;

import org.w3c.dom.Document;
import org.w3c.dom.NodeList;

import android.view.View;
import android.widget.LinearLayout;
import android.widget.Button;
import android.widget.TextView;

public class HelloAndroid extends Activity {
/** 底下這個是放分析 xml 完的內容,資料結構要自己再想過,或是直接以 DOM 的方式存取,而不必另外放也可以
也就是在外面也是用 Document doc 這個物件來存取
**/
String[][] items;

// 底下這三個是我們的 GUI 上會有的元件的「容器」
Button cmd[];
TextView cmdPath;
TextView cmdParam;

/** Called when the activity is first created. */
/** onCreate() 是每個應用程式的入口,所以算是一般 C 裡面的 main() **/
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// setContentView(R.layout.main); // 這個是原來的 HelloAndroid 範例程式,我們不需要原來的 layout 設計,用自己的方式
// 目前以 LinearLayout 來設計,可以改成矩陣式的,不過最好是可以容許橫拿直拿動態調整,第一版可以不必有此彈性功能
LinearLayout layout = new LinearLayout(this);
layout.setOrientation(1);

// 呼叫我們的 XML file 分析載入函式
GetXMLInfo();

// 底下這三個是我們的 GUI 上會有的元件的「容器」
cmd = new Button[items.length];
cmdPath = new TextView(this);
cmdParam = new TextView(this);

/** 底下就是直接把 XML 內容, 也就是 items 拿來放到 GUI 上
資料結構可以改變,整個 GUI 也可以改變設計
**/
int iCmd;
for (iCmd=0; iCmd<items.length; iCmd++)
{
cmd[iCmd] = new Button(this);
cmd[iCmd].setId(iCmd);

/** 為每個 button 加上按鍵的事件以便做出反應 **/
cmd[iCmd].setOnClickListener(new Button.OnClickListener()
{
public void onClick(View v)
{
cmdPath.setText(items[v.getId()][1]);
cmdParam.setText(items[v.getId()][2]);
}
});
cmd[iCmd].setText(items[iCmd][0]);
layout.addView(cmd[iCmd]); // 最後真正加到我們的 layout 中
}
// 上面的 for 迴圈是加按鍵,底下只是加上顯示訊息的文字區塊
layout.addView(cmdPath);
layout.addView(cmdParam);
setContentView(layout);
}
private void GetXMLInfo()
{
try{
File f=new File("/sdcard/Sample.xml");
DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
DocumentBuilder builder=factory.newDocumentBuilder();
Document doc = builder.parse(f);
NodeList nl = doc.getElementsByTagName("cmd");

int _cmdLength = nl.getLength();
int _cmdAttributes=3;

items = new String[_cmdLength][_cmdAttributes];

for (int i=0;i<_cmdLength;i++){

items[i][0]= nl.item(i).getAttributes().getNamedItem("text").getNodeValue();
items[i][1]= nl.item(i).getAttributes().getNamedItem("path").getNodeValue();
items[i][2]= nl.item(i).getAttributes().getNamedItem("params").getNodeValue();

}

//System.out.println("cmd " + RecordS.length);

}
catch(Exception e){
e.printStackTrace();
}
}
}


執行時:
$ adb push Sample.xml /sdcard/Sample.xml
----呼叫該應用執行





----換成新的 GUI, 用新的 Sample1.xml 取代原先的 Sample.xml, 記得放的檔名是一樣的
$ adb push Sample1.xml /sdcard/Sample.xml
----呼叫該應用執行

android dynamic GUI 動態介面

--動態 GUI--
寫應用程式,動態 GUI 是常常會有此需求的,原則上Dynamic Layout 的簡單概念,可以參考這篇:
http://www.dreamincode.net/forums/topic/130521-android-part-iii-dynamic-layouts/

在網路上找到一個寶庫, 一堆 Android source code 含有 test tools:
http://devdaily.com/java/jwarehouse/android/
其中有一份 DynamicLayout() 的範例:
http://devdaily.com/java/jwarehouse/android/core/java/android/text/DynamicLayout.java.shtml

或者我們可以從底下的問題開始了解我在說什麼:
1. 有人問他想要從 XML 來動態呈現 GUI,但是求問者有些功能做不到
http://efreedom.com/Question/1-2901333/Dynamic-Layout-Change-Runtime
2. 所以有人就回答他,用 setLayoutParams() 或請參考:
http://efreedom.com/Question/1-2693744/Android-Runtime-Layout-Tutorial

--執行外部命令--
至於 Dynamic Layout 之後,每個按鈕的功能,就變成要處理 button event.....再加上執行外部命令功能
http://code.google.com/p/market-enabler/wiki/ShellCommands
想要完整的 code 的話,可以參考:
http://gimite.net/en/index.php?Run%20native%20executable%20in%20Android%20App

還有相對簡單的方法是用 Java RunTime:
http://developer.android.com/reference/java/lang/Runtime.html
如果要使用 RunTime 的話,要能夠對外部命令做 I/O, 完整範例可以參考:
http://devdaily.com/java/edu/pj/pj010016/

2010/09/20

android adb over wifi

android adb 算是非常好用的介面,不過....預設是用 USB 來連接 Host 與 Device。有沒有方法可以透過無線網路?

首先,要能讓 Device 知道該透過 TCP/IP 或是 USB,似乎只能二選一切換,方法是:
-- 切成 TCP/IP --
setprop service.adb.tcp.port 5555
stop adbd
start adbd

-- 或切成 USB --
setprop service.adb.tcp.port -1
stop adbd
start adbd

在 Host 端,就可以用下面命令讓 adb 連線
adb tcpip 5555
adb connect WIFI.IP.ADDRESS:5555
-- 或透過 usb --
adb usb

SMART EDISON

愛迪生一向被稱讚,這邊就有一個用他的名字來取的一個新詞,用在思維、溝通、做事上很值得參考:
S.M.A.R.T E.D.I.S.O.N

全稱是:
Specific: 說話做事講究具體,不空洞
Measurable: 所有數據、問題,都應該可量測,不能太理論、抽象、高調
Accountable: 責任清楚,之前上過一堂「當責」的課,用的也是這個詞
Relevant: 切題,也就是所謂題中之意要符合目的與整體的價值
Timeline: 講究時效性,時機重於一切,等端出解決方案時黃花菜都涼了,客人跑光了,那就失去其意義

Emotional: 要能激勵人心、讓人熱情澎湃,不要澆息大夥兒的工作熱忱
Decisive: 能堅決果斷,要具備決定性的思維,做事不拖泥帶水,不做三姑六婆式的思維
Integrated: 要能整合、整體性的思維,而不是散兵游勇般的各自作戰
Sensory: 要能與別人感同身受,而不能唱獨角戲,不能自我感覺太良好而自絕於大眾之外
Optimistic: 要具樂觀思維,要影響並提升團體的樂觀氛圍,永不放棄,總要「再試一次」
Now: 立刻做

2010/09/17

Gtalk HOWTO Multi-Clients

現在因為申請 google appengine 的帳號後,就變成有多個 google 帳號,可以安裝 firefox + gmail checker....此時若想利用像 gtalk 來隨時讓人找得到,或是檢查郵件也是不錯的方式。

但是 gtalk 預設只能上一個帳號,一個非常簡單的方法:
1. 在啟動 Gtalk 的小圖示(捷徑圖示)按右鍵選內容,找到命令路徑加上 /nomutex, 以我的來說是 "C:\Program Files\Google\Google Talk\googletalk.exe" /nomutex /startmenu
2. 在 gtalk 登入畫面,不要勾選 Remember password

第二步若是來不及的話,只要在登入後的 system tray 按右鍵功能表選 Sign Out, 再按左鍵叫出登入畫面即可。注意此時不要勾選 Remember password!!! 這樣你就可以叫多個 gtalk 出來,user name 輸入全部的 email 即可。

2010/09/15

android java.util.zip.ZipException: duplicate entry: hyts_Foo.c

這個標題有點長,是因為直接貼訊息。編譯 android cts 時出現的錯誤,我的解決辦法就是把錯誤訊息中的重複檔案砍了....包括

./dalvik/libcore/support/src/test/resources/hyts_Foo.c 及
./dalvik/libcore/dom/src/test/resources/ 底下的
hc_staff.xml
staff2.xml
staffNS.dtd
xhtml1-strict.dtd
staff2.dtd
staff.dtd
staff.xml

2010/09/09

如何經營辦公室戀情

底下內容來自公司的內部文件,覺得不錯就貼上來了。老是遇到總字輩的玩辦公室戀情,底下的人總是感覺非常無奈,官位愈高,應愈謹言慎行啊!

--

隨著工作時間佔我們的生活重心愈來愈重,與同事互動的機會越來越多,在相互合作的氣氛中,也許您會發現對一些同事有不一樣的感覺,或察覺到身邊的辦公室戀情慢慢增加了。辦公室戀情處理的好,不但對工作氣氛有加分效果,更有可能促成佳偶良緣;但如果稍有不慎,卻也可能造成辦公室的災難,當事人也會身陷八卦中心,增加困擾。本月文章與您分享幾個面對辦公室戀情的方式。

Tip1.誠實的處理感情議題

請先檢視自己的心態,如果只是想尋求短期的心理安慰或是一時衝動,並沒有發展長期關係的意願,請您三思而後行。在辦公室裡,如何維持正直公平是非常重要的,如果您的身份不宜,或是只想搞曖昧增加生活刺激,是非常危險的事情,而且會為自己與組織引起非常大的危機,因此保持情感上的誠實是非常重要的。

Tip2.如果辦公室戀情的對象與您有權力關係,請想清楚再做決定

如果您的對象與您有權力關係,例如是您的客戶,廠商或是上司,部屬,您要注意,戀情可能會有兩極化的結果。特別是面臨結束關係時,您又是提出分手的一方,而且結束的過程並不夠理智成熟;那麼在分手後,有可能會面臨到工作上無理的要求,或是提出無謂的刁難,讓工作關係更加惡劣,需要極高的智慧,才能拿捏好其中的尺度。因為職場戀情與職位高低有必然的權力關係或潛在風險,因此當您面臨這個議題時,必須要更加審慎的思考所有可能後果,再做決定。

Tip3務必保持低調

如果您不希望您們的戀情受到太多的關注,或是被拿到顯微鏡下放大,那麼,請您務必保持低調,尤其是在同個辦公室裡,無心的一舉一動,如果被有意的解讀,或是只要有同事對您們其中一人有不滿或抱怨,都有可能影響工作。因此衷心的建議,除非決定要結婚了才通知大家,否則低調保守的處理這份戀情,不但能夠降低對辦公室工作的干擾,也會使感情之路省掉很多不必要的外在眼光。

Tips4享受真正認識一個人並且成熟交往的樂趣

事實上,辦公室是屬於遇見適合對象的好地點之ㄧ,因為您會透過工作互動看到身邊的人展現出他的個性、如何處理事情、面對壓力時最真實的樣子。您會是在真正了解以及認識這個人的個
性與特質之後才做出決定。在工作場合所遇到的對象,會較其他地方認識的對象,更深入且合適。所以一旦您要發展辦公室戀情,用成熟的方式去面對,您會享受到感情生活裡美好的感受。

結語:

辦公室戀情本身並無對錯,只是您一定要誠實且成熟的處理兩人感情。因此建議您如果遇到辦公室戀情或是身邊有同事正身處辦公室戀情中,您可以根據上述的幾個提醒作為感情發展的參考。若是能夠請楚了解辦公室戀情中拿捏公私關係的尺度,以及職務權力不同可能會造成的衝擊,在成熟的考慮之下發展辦公室戀情,就能夠享有愉快的心情與有效率的工作。

2010/08/17

ubuntu 10.10 將可內建支援多點觸控

詳情請見Multi-touch Support Lands in Maverick

既然有新聞,就自己去找,在 ubuntu 10.10 系統上,確實可以找到 utouch:

$sudo apt-cache search utouch
libutouch-geis-dev - Gesture engine interface support - dev files
libutouch-geis-doc - Gesture engine interface support - documentation
libutouch-geis1 - Gesture engine interface support
libutouch-grail-dev - Gesture Recognition And Instantiation Library - dev files
libutouch-grail1 - Gesture Recognition And Instantiation Library
utouch - A meta-package to install gesture libraries and tools
utouch-geis-tools - Gesture engine interface support - test tools
utouch-gesturetest - Test tool for the X Gesture extension
utouch-grail-tools - Gesture Recognition And Instantiation Library - test tools
xserver-xorg-input-mutouch - X.Org X server -- muTouch input driver


重點是,這邊感嘆一下,好像都國外廠商在玩這個,國內玩 Linux 的廠商沒半個願意搞....

2010/08/06

empathy under proxy

Empathy 是 Ubuntu 預設的 IM client, 可以支援相當多的 IM, 包括 MSN, Yahoo IM, gtalk。
敝公司會把 gtalk 的 5222/5223 擋住,此時可以用 gmail 裡面的 Port 設定值,也就是用 https在用的 443, 設定範例如下

account : username@gmail.com
encryption required TLS/ssl : (YES)
ignore ssl certificate error : (YES)
server : talk.google.com
port : 443
use old ssl : (YES)

或請參考下面的圖
.叫出帳號設定,可以在新增帳號時就設定,或是用修改的方式

.設定畫面如下,或請參考上面的設定值

2010/08/03

android build on ubuntu 10.04

Dependance
  • sudo apt-get install git-core gnupg flex bison gperf build-essential zip curl zlib1g-dev gcc-multilib g++-multilib libc6-dev-i386 lib32ncurses5-dev ia32-libs x11proto-core-dev libx11-dev lib32readline5-dev lib32z-dev java-common unixodbc libsdl-dev libesd0-dev
Java
  • sudo add-apt-repository "deb http://archive.canonical.com/ lucid partner"
    sudo apt-get update
    sudo apt-get install sun-java6-jdk
Source Code
  • curl http://android.git.kernel.org/repo > ~/bin/repo
  • chmod a+x ~/bin/repo
  • mkdir -p ~/src/android
  • cd ~/src/android
  • repo init -u git://android.git.kernel.org/platform/manifest.git
  • repo sync
  • repo forall -c git checkout --track -b sai-master korg/master
Environment
  • export JAVA_HOME=/usr/lib/jvm/java-6-sun/
    export PATH=$PATH:${JAVA_HOME}/bin:$HOME/src/android/android-sdk-linux_86/tools:$HOME/src/android/out/host/linux-x86/bin
    export ANDROID_PRODUCT_OUT=$HOME/src/android/out/target/product/generic
  • chmod a+x build/envsetup.sh
  • source build/envsetup.sh
Build
  • make -j4
Run
  • export DISPLAY=:0.0
    #ps: 如果沒有設定 DISPLAY, 會顯示的訊息跟一般的 X app 不一樣,如下:
    SDL init failure, reason is: No available video device
  • emulator -system system.img -data userdata.img -ramdisk ramdisk.img

2010/06/04

如何加速 dd?

dd 是很常見的命令,但是在大量資料的複製時,會顯得非常慢,最簡單的範例是
dd if=/dev/zero of=/vmem.img count=2G
2G 以目前來說非常常見,例如要把一個作業系統放到隨身碟中,或是像 ChromiumOS 也差不多就這個數值。

我把我測試執行的結果貼一下:

首先用 bs=4M 來試,這個數值是 ChromiumOS 的 script 中內建的值:

$ time dd if=my-8G.img of=/dev/sdc bs=4M

1919+1 records in
1919+1 records out
8050966528 bytes (8.1 GB) copied, 1189.83 s, 6.8 MB/s

real 19m49.848s
user 0m0.030s
sys 0m18.410s


接下來用預設的來比對,預設的 block size 是 512byte

$ sudo time dd if=my-8G.img of=/dev/sdc
15724544+0 records in
15724544+0 records out
8050966528 bytes (8.1 GB) copied, 6303.21 s, 1.3 MB/s

real 105m3.254s
user 0m7.740s
sys 1m36.380s


最後,用一個更大的比較一下,用 12M

$sudo  time dd if=my-8G.img of=/dev/sdc bs=12M
639+1 records in
639+1 records out
8050966528 bytes (8.1 GB) copied, 1060.62 s, 7.6 MB/s

real 17m40.653s
user 0m0.010s
sys 0m11.730s


會發現,4M 遠比預設值快非常多,而 12M 與 4M 相差不大,但是仍然有比較快。
以上僅供參考