ubuntu 在 R40e 上 還有 Debian 在 Sempron 2600 上

2011年1月31日 星期一

switch full-screen key in Dell NB

dell 的 nb, break/pause 是 del 鍵。
所以 遠端桌面連線 切換全螢幕 就要用 ctrl-atl-fn-del

2011年1月27日 星期四

svn commit error : MKACTIVITY of '/svn/PPD/!svn/act/85fa9262-861d-4e72-81f1-2accfe32d11b': Could not parse response

subversion commit 出現 error: svn commit -m Authentication realm: <http://subversion.smarkcom.com:80> Subversion repos Password for 'checko': svn: Commit failed (details follow): svn: MKACTIVITY of '/svn/PPD/!svn/act/85fa9262-861d-4e72-81f1-2accfe32d11b': Could not parse response charles-chang@rbtlegacy:~/svn_PPD/RefDocInEachStage/A2_Stage/Images/20110104-install$ 結果是 proxy 的問題,把 .subversion/server 裡的 proxy 設定comment 掉就可以。
ref:

2011年1月26日 星期三

key 在 framework/base//libs/ui/EventHub.cpp 把 LOG message 打開: #define LOG_NDEBUG 0 就會把 keyevent 的轉換機制 print 出來。
這就是 logcat 出來 touch lcd 時的log: V/EventHub( 2192): revents for 1 = 0x00000001 V/EventHub( 2192): /dev/input/event2 got: t0=95, t1=765659, type=3, code=0, v=406 V/EventHub( 2192): revents for 1 = 0x00000001 V/EventHub( 2192): /dev/input/event2 got: t0=95, t1=765678, type=3, code=1, v=279 V/EventHub( 2192): revents for 1 = 0x00000001 V/EventHub( 2192): /dev/input/event2 got: t0=95, t1=765682, type=3, code=24, v=83 V/EventHub( 2192): revents for 1 = 0x00000001 V/EventHub( 2192): /dev/input/event2 got: t0=95, t1=765689, type=1, code=330, v=1 V/EventHub( 2192): iev.code=330 outKeycode=0 outFlags=0x00000000 err=-19 V/EventHub( 2192): revents for 1 = 0x00000001 V/EventHub( 2192): /dev/input/event2 got: t0=95, t1=765698, type=0, code=0, v=0 V/EventHub( 2192): revents for 1 = 0x00000001 V/EventHub( 2192): /dev/input/event2 got: t0=95, t1=791410, type=3, code=24, v=0 V/EventHub( 2192): revents for 1 = 0x00000001 V/EventHub( 2192): /dev/input/event2 got: t0=95, t1=791434, type=1, code=330, v=0 V/EventHub( 2192): iev.code=330 outKeycode=0 outFlags=0x00000000 err=-19 V/EventHub( 2192): revents for 1 = 0x00000001 V/EventHub( 2192): /dev/input/event2 got: t0=95, t1=791452, type=0, code=0, v=0

logcat -b : choose buffer

logcat 用來顯示 framework 中用 LOGE.I.V.D 等 print 的 message。
但是 system 好像有很多個 log buffer。
C:\Users\Checko>adb logcat --help Usage: logcat [options] [filterspecs] options include: -s Set default filter to silent. Like specifying filterspec '*:s' -f <filename> Log to file. Default to stdout -r [<kbytes>] Rotate log every kbytes. (16 if unspecified). Requires -f -n <count> Sets max number of rotated logs to <count>, default 4 -v <format> Sets the log print format, where <format> is one of: brief process tag thread raw time threadtime long -c clear (flush) the entire log and exit -d dump the log and then exit (don't block) -t <count> print only the most recent <count> lines (implies -d) -g get the size of the log's ring buffer and exit -b <buffer> request alternate ring buffer ('main' (default), 'radio', 'events') -B output the log in binary filterspecs are a series of <tag>[:priority] where <tag> is a log component tag (or * for all) and priority is: V Verbose D Debug I Info W Warn E Error F Fatal S Silent (supress all output) '*' means '*:d' and <tag> by itself means <tag>:v If not specified on the commandline, filterspec is set from ANDROID_LOG_TAGS. If no filterspec is found, filter defaults to '*:I' If not specified with -v, format is set from ANDROID_PRINTF_LOG or defaults to "brief" 可以看出,原來 log 有三個 ring buffer :main, radio, event。
default 是顯示 main。

所以我們用 logcat 沒有辦法顯示出 RIL 的 LOG messasge。
要用
logcat -b radio
ref : http://blog.lytsing.org/archives/476.html

captive portal - driver all web access to login page

像一些 wifi ap 第一次連線會把所有 web access都會導入到 他自己的 login page。 這樣的功能較 captive portal. 可以google 一下,就有很多資料,包括 opensource 的 CoovaChilli 還有內建 coovachilli 的

2011年1月21日 星期五

libusb-dev , libusb.h & usb.h

libusb 的 header file 好像換掉了,不是 libusb.h,改成 usb.h

用 aptitude search libusb 可以看到有 libusb-dev 這個 package。
install 後,用 dpkg -L libusb-dev 看一下這個 package 裝了什麼東西:
$dpkg -L libusb-dev /usr/bin/libusb-config /usr/include/usb.h /usr/lib/libusb.a /usr/lib/libusb.la /usr/lib/pkgconfig /usr/lib/pkgconfig/libusb.pc /usr/lib/libusb.so 可以看到沒有 libusb.h ....

libusb.org 有說明 這個相容性問題 http://www.libusb.org/wiki/libusb-1.0#Backwardscompatibility
libusb-1.0 is not backwards compatible with libusb-0.1 - all function names are different, etc. 
However, libusb-1.0 is designed to be happily installable alongside libusb-0.1 (even in the default 
configuration) so the lack of backwards compatibility is not really a problem - users can have both 
libusb versions present on the same system without conflict.

That said, there is a libusb-compat-0.1 compatibility layer. This is a "wrapper" which converts 
libusb-0.1 function calls to their 1.0 equivalents. For more info, see libusb-compat-0.1.
所以..要麻 install libusb-0.1 ,不然就要 libusb-compat-0.1。
不然就要改code.

把 code 的 include libusb.h 改 usb.h 試試。
就 OK 了。



從 pkg -L libusb 的 list 可以看到,有提供 libusb-config。
試 run 一下:
$libusb-config Usage: libusb-config [OPTIONS] [LIBRARIES] Options: [--prefix[=DIR]] [--exec-prefix[=DIR]] [--version] [--libs] [--cflags] 可以知道,就像 libsdl,用 libusb-config --libs , libusb-config --cflags 會列出build 時的 參數。



ref : http://www.linuxquestions.org/questions/linux-newbie-8/ubuntu-9-10-include-libusb-libusb-h-802880/
  • 看看能不能 fix mmc 的 slot 與 device mmcblk 的關係
  • ts_calibrate 會block 住 mcustub ,導致 mcu wait ready timeout, CPU reboot ---> 設法用 frok-exec 的方式啟動 mcustub,然後把他放在 ts_calibration 前,用 exec 啟動

fix xinput.d not exist -- 後續 of upgrade to squeeze

因為 upgrade 到 squeeze 後, x.org 重新安裝。之後 dist-upgrade 就會出現: update-alternatives: error: alternative path /etc/X11/xinit/xinput.d/scim-bridge doesn't exist. 查一下我連 xinput.d 這個 folder 都沒有,所以就 install xinput。 然後到舊的 把 xinput.d/sci* copy 過來,再作一次 dist-upgrade 就.. The following partially installed packages will be configured: scim-bridge-agent scim-bridge-client-gtk No packages will be installed, upgraded, or removed. 0 packages upgraded, 0 newly installed, 0 to remove and 0 not upgraded. Need to get 0 B of archives. After unpacking 0 B will be used. Setting up scim-bridge-agent (0.4.16-2+b1) ... update-alternatives: using /etc/X11/xinit/xinput.d/scim-bridge to provide /etc/X11/xinit/xinput.d/ja_JP (xinput-ja_JP) in auto mode. update-alternatives: using /etc/X11/xinit/xinput.d/scim-bridge to provide /etc/X11/xinit/xinput.d/ko_KR (xinput-ko_KR) in auto mode. update-alternatives: using /etc/X11/xinit/xinput.d/scim-bridge to provide /etc/X11/xinit/xinput.d/zh_CN (xinput-zh_CN) in auto mode. update-alternatives: using /etc/X11/xinit/xinput.d/scim-bridge to provide /etc/X11/xinit/xinput.d/zh_TW (xinput-zh_TW) in auto mode. update-alternatives: using /etc/X11/xinit/xinput.d/scim-bridge to provide /etc/X11/xinit/xinput.d/zh_HK (xinput-zh_HK) in auto mode. update-alternatives: using /etc/X11/xinit/xinput.d/scim-bridge to provide /etc/X11/xinit/xinput.d/zh_SG (xinput-zh_SG) in auto mode. Setting up scim-bridge-client-gtk (0.4.16-2+b1) ... 就 OK 了(?)

2011年1月20日 星期四

Android AlertDialog : Show different message on each call

為了效率(?),Android alert dialog 一旦建立,就 cache 在 system。即使消失,也留在 cache。
下次再showDialog( ) 時,就直接叫出cache 的 dialog,不會再 create 一次。

所以要是AlertDialog 第一次show和第二次 show 不一樣的 message。就沒有辦法。
即使每次 showDialog( ) 前都用 setMessage( ) 設定過不一樣的內容也沒效。

所以每個 message 都要寫一個 dialog ?

後來發現 android system 好像是以showDialog( id ) 的 id 作為 identify cached dialog 的依據。

所以 每次 call showDialog( ) 都傳入不同的 id,那麼 onCreateDialog( ) 就會每次都被呼叫。
這樣,就可以設定每次不一樣的 Alert Message 了。
package rtk.atp.testmcu; import rtk.atp.testmcu.R; import android.app.Activity; import android.app.AlertDialog; import android.app.Dialog; import android.content.DialogInterface; import android.os.Bundle; import android.view.View; public class testmcu extends Activity { private String dialogInfoString = "Test OK?"; public void buttonhandler(View view) { switch (view.getId()) { case R.id.btn_BacklightLevel1: dialogInfoString = "Press OK"; showDialog(1); break; case R.id.btn_BacklightLevel2: dialogInfoString = "Press Fail"; showDialog(2); break; } } protected Dialog onCreateDialog(int id) { AlertDialog.Builder dlg = new AlertDialog.Builder(this); dlg.setPositiveButton("OK", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { setTitle("Confirmed"); } }); dlg.setNegativeButton("Fail", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { setTitle("Canceled"); } }); dlg.setMessage(dialogInfoString); return dlg.create(); } public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); } } 重點就在 showDialog(1), showDialog(2);
可以看到實際上onCreateDialog( ) 並沒有參考 dialogid 來決定要顯示的內容。

2011年1月18日 星期二

socket interface syscomamnd daemon

follow 前篇,為了執行一堆有權限限制的 command,所以寫一個 syscommandd: #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <sys/un.h> #include <string.h> #define FDNAME "/data/syscommandfd" int main(int argc,char *argv[]) { int sock,msgsock,rval; struct sockaddr_un server; char buf[1024]; int runserver=3; int sysexitcode; unlink(FDNAME); sock = socket(AF_UNIX, SOCK_STREAM,0); if(sock<0) { perror("opening stream socket"); exit(1); } server.sun_family = AF_UNIX; strcpy(server.sun_path, FDNAME); if (bind(sock,(struct sockaddr *)&server, sizeof(struct sockaddr_un))) { perror("binding stream socket"); exit(1); } printf("socket has name:%s\n",server.sun_path); listen(sock,5); do { msgsock = accept(sock,0,0); if (msgsock == -1) perror("accept"); else do { bzero(buf,sizeof(buf)); if ((rval = read(msgsock, buf, 1024))<0) perror("reading stream message"); else if(rval>0) { printf("rcv : %s\n",buf); sysexitcode = system(buf); printf("sys exit code: %d\n",sysexitcode); } } while (rval > 0); runserver --; close(msgsock); } while(runserver); close(sock); unlink(FDNAME); printf("syscommandd..\n"); return 0; } Android.mk LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_SRC_FILES := syscommandd.c LOCAL_MODULE := syscommandd LOCAL_CFLAGS += -lpthread -lrt LOCAL_MODULE_TAGS := tests include $(BUILD_EXECUTABLE) 測試程式: c : #include <sys/types.h> #include <sys/socket.h> #include <sys/un.h> #include <stdio.h> int main(int argc,char *argv[]) { int sock; struct sockaddr_un server; char buf[1024]; if (argc < 3) { printf("usage:%s <pathname> <msg-to-server>", argv[0]); exit(1); } sock = socket(AF_UNIX, SOCK_STREAM, 0); if (sock < 0) { perror("opening stream socket"); exit(1); } server.sun_family = AF_UNIX; strcpy(server.sun_path, argv[1]); if (connect(sock, (struct sockaddr *) &server, sizeof(struct sockaddr_un)) < 0) { close(sock); perror("connecting stream socket"); exit(1); } if (write(sock, argv[2], strlen(argv[2])) < 0) perror("writing on stream socket"); close(sock); return 0; } Android Code,使用: public static void writeSocket(String shellcommand) throws IOException { LocalSocket sender = new LocalSocket(); sender.connect(new LocalSocketAddress("/data/syscommandfd",LocalSocketAddress.Namespace.FILESYSTEM)); sender.getOutputStream().write(shellcommand.getBytes()); sender.getOutputStream().close(); } 執行就: writeSocket("touch aa");

2011年1月14日 星期五

Android extend OutputStream

class SocketOutputStream extends OutputStream { /** {@inheritDoc} */ @Override public void close() throws IOException { LocalSocketImpl.this.close(); } /** {@inheritDoc} */ @Override public void write (byte[] b) throws IOException { write(b, 0, b.length); } /** {@inheritDoc} */ @Override public void write (byte[] b, int off, int len) throws IOException { synchronized (writeMonitor) { FileDescriptor myFd = fd; if (myFd == null) throw new IOException("socket closed"); if (off < 0 || len < 0 || (off + len) > b.length ) { throw new ArrayIndexOutOfBoundsException(); } writeba_native(b, off, len, myFd); } } /** {@inheritDoc} */ @Override public void write (int b) throws IOException { synchronized (writeMonitor) { FileDescriptor myFd = fd; if (myFd == null) throw new IOException("socket closed"); write_native(b, myFd); } } } LocalSocketImp.java 作的 SocketOutputStream。
override write(byte[]). -- 不知道原來的java.Stream 有沒有這個。

所以 byte[] outdata={0x01,0x02,0x03,0x0a,0x0d}; outstream.write(outdata);

LocalSocketAddress.Namespace

LocalSocket 使用要注意 LocalSocketAddress 的設定 LocalSocketAddress(String name, Namespace namespace) 第二個 argument : namespace ,決定 name 的真正位置 (path)。
LocalSocketAddress.Namespace :
public enum Namespace { /** A socket in the Linux abstract namespace */ ABSTRACT(0), /** * A socket in the Android reserved namespace in /dev/socket. * Only the init process may create a socket here. */ RESERVED(1), /** * A socket named with a normal filesystem path. */ FILESYSTEM(2); /** The id matches with a #define in include/cutils/sockets.h */ private int id; Namespace (int id) { this.id = id; } 可以知道,follow 一般 linux 的用法,要用 LocalSocketAddress.Namespace.FILESYSTEM。
這樣才會完全依照 name 的內容來解析。
至於 另一個 LocalSocketAddress 的生成函數: public LocalSocketAddress(String name) { this(name,Namespace.ABSTRACT); } 不指定的時候,用 ABSTRACT。
至於每個 namespace 的真正位置,在 system/core/libcutils/sock_local_client.c: int socket_make_sockaddr_un(const char *name, int namespaceId, struct sockaddr_un *p_addr, socklen_t *alen) { memset (p_addr, 0, sizeof (*p_addr)); size_t namelen; switch (namespaceId) { case ANDROID_SOCKET_NAMESPACE_ABSTRACT: #ifdef HAVE_LINUX_LOCAL_SOCKET_NAMESPACE namelen = strlen(name); // Test with length +1 for the *initial* '\0'. if ((namelen + 1) > sizeof(p_addr->sun_path)) { goto error; } /* * Note: The path in this case is *not* supposed to be * '\0'-terminated. ("man 7 unix" for the gory details.) */ p_addr->sun_path[0] = 0; memcpy(p_addr->sun_path + 1, name, namelen); #else /*HAVE_LINUX_LOCAL_SOCKET_NAMESPACE*/ /* this OS doesn't have the Linux abstract namespace */ namelen = strlen(name) + strlen(FILESYSTEM_SOCKET_PREFIX); /* unix_path_max appears to be missing on linux */ if (namelen > sizeof(*p_addr) - offsetof(struct sockaddr_un, sun_path) - 1) { goto error; } strcpy(p_addr->sun_path, FILESYSTEM_SOCKET_PREFIX); strcat(p_addr->sun_path, name); #endif /*HAVE_LINUX_LOCAL_SOCKET_NAMESPACE*/ break; case ANDROID_SOCKET_NAMESPACE_RESERVED: namelen = strlen(name) + strlen(ANDROID_RESERVED_SOCKET_PREFIX); /* unix_path_max appears to be missing on linux */ if (namelen > sizeof(*p_addr) - offsetof(struct sockaddr_un, sun_path) - 1) { goto error; } strcpy(p_addr->sun_path, ANDROID_RESERVED_SOCKET_PREFIX); strcat(p_addr->sun_path, name); break; case ANDROID_SOCKET_NAMESPACE_FILESYSTEM: namelen = strlen(name); /* unix_path_max appears to be missing on linux */ if (namelen > sizeof(*p_addr) - offsetof(struct sockaddr_un, sun_path) - 1) { goto error; } strcpy(p_addr->sun_path, name); break; default: // invalid namespace id return -1; } p_addr->sun_family = AF_LOCAL; *alen = namelen + offsetof(struct sockaddr_un, sun_path) + 1; return 0; error: return -1; } 有點複雜,還要去查 core/libcutils/socket_local.h #define FILESYSTEM_SOCKET_PREFIX "/tmp/" #define ANDROID_RESERVED_SOCKET_PREFIX "/dev/socket/" * 如果沒有注意這個,在 connect 的時候,會有 connection denied 的 error。
ref:

Eclipse 3.6.1 on build newly created android project

Eclipse 剛 create 完 project 產生的 path 和 eclipse create 出來的不一樣。
所以 build 的時候會出現 R.java 找不到。

這時候看 Error message 就會知道 path 不正確: error 說去找 workspace/test,結果真正create 的是 workspace/name1/name2/test
(package name : name1.name2.test)

google 說這是 prebuild 的問題,所以先 clean 掉再重build 就 OK 了。

2011年1月13日 星期四

java/android Unix Domain Socket

framework/base/core/jni/android_net_LocalSocketImpl.cpp
sock_create --> create_native

用 java.net DatagramPacket

可是 java 不支援 UNIX Domain Socket
因為 UNIX Domain Socket 的 implement 跟 platform 相關。
所以。有一堆 java extension ...
所以 Android.net implement 了 LocalSocket。

Run Project on Real Target

用Eclipse 可以在真的 target 作 debugging.
ref: Set Up Device for Developement
大概就是: AndroidManigest.xml 的 project 的 property 要設: application: debug TRUE。 device 要設 settings - applications - developement - USB debugging enable.
確認 adb 可以連線。
就可以了。

這樣, run eclipse 的 debug 時,就會 install apk 到 real target,然後 run 起來。

如果先在 source code 中設好 break point,eclipse 就會切到 debug perspective.
可以作 step, view variable, ... etc

2011年1月12日 星期三

AF_UNIX, sendto and receive - in Android

這一篇(http://www.few.vu.nl/~jms/socket-info.html)有unix udp 的 client - server example: /* receiver */ #include <sys/types.h> #include <sys/socket.h> struct sockaddr myname; struct sockaddr from_name; char buf[80]; main() { int sock; int fromlen, cnt; sock = socket(AF_UNIX, SOCK_DGRAM, 0); if (sock < 0) { printf("socket failure %d\n", errno); exit(1); } myname.sa_family = AF_UNIX; strcpy(myname.sa_data, "/tmp/tsck"); if (bind(sock, &myname, strlen(myname.sa_data) + sizeof(name.sa_family)) < 0) { printf("bind failure %d\n", errno); exit(1); } cnt = recv(sock, buf, sizeof(buf)); // recfrom not work !! if (cnt < 0) { printf("recvfrom failure %d\n", errno); exit(1); } buf[cnt] = '\0'; /* assure null byte */ from_name.sa_data[fromlen] = '\0'; printf("'%s' received from %s\n", buf, from_name.sa_data); } /* sender */ #include <sys/types.h> #include <sys/socket.h> char buf[80]; struct sockaddr to_name; main() { int sock; sock = socket(AF_UNIX, SOCK_DGRAM, 0); if (sock < 0) { printf("socket failure %d\n", errno); exit(1); } to_name.sa_family = AF_UNIX; strcpy(to_name.sa_data, "/tmp/tsck"); strcpy(buf, "test data line"); cnt = sendto(sock, buf, strlen(buf), 0, &to_name, strlen(to_name.sa_data) + sizeof(to_name.sa_family)); if (cnt < 0) { printf("sendto failure %d\n", errno); exit(1); } } 我修改了一下 android 的 test_udp (system/extras/tests/bionic/libc/common/test_udp.c) #define PROGNAME "test_udp" #define DEFAULT_PORT 7000 #include <arpa/inet.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/socket.h> #include <unistd.h> #include <string.h> #define BUFLEN 512 #define NPACK 10 void diep(char *s) { perror(s); exit(1); } static void usage(int code) { printf("usage: %s [options]\n", PROGNAME); printf("options:\n"); printf(" -p<port> use specific port (default %d)\n", DEFAULT_PORT); printf(" -a<inet> use specific IP address\n"); printf(" -s run server (default is client)\n"); exit(code); } int main(int argc, char** argv) { int runServer = 0; int udpPort = DEFAULT_PORT; int useLocal = 0; int address = htonl(INADDR_ANY); struct sockaddr si_me, si_other; int s, i, slen; char buf[BUFLEN]; int cnt; while (argc > 1 && argv[1][0] == '-') { const char* optName = argv[1]+1; argc--; argv++; switch (optName[0]) { case 's': runServer = 1; break; default: usage(1); } } if (runServer) { if ((s=socket(AF_UNIX, SOCK_DGRAM, 0))==-1) diep("socket"); si_me.sa_family = AF_UNIX; strcpy(si_me.sa_data,"/data/tsck"); if (bind(s, &si_me, strlen(si_me.sa_data)+sizeof(si_me.sa_family))==-1) diep("bind"); printf("UDP server listening \n"); for (i=0; i<NPACK; i++) { cnt = read(s, buf, BUFLEN); printf("cnt=%d\n",cnt); if(cnt>=0){ buf[cnt]='\0'; printf("Received packet Data: %s\n",buf); } } printf("UDP server closing\n"); close(s); unlink("/data/tsck"); } else /* !runServer */ { if ((s=socket(AF_UNIX, SOCK_DGRAM, 0))==-1) diep("socket"); si_other.sa_family = AF_UNIX; strcpy(si_other.sa_data,"/data/tsck"); printf("UDP client sending packets \n"); for (i=0; i<NPACK; i++) { printf("Sending packet %d\n", i); sprintf(buf, "This is packet %d\n", i); if (sendto(s, buf, BUFLEN, 0, &si_other, strlen(si_other.sa_data)+sizeof(si_other.sa_family))==-1) diep("sendto()"); } close(s); printf("UDP client closing\n"); } return 0; } server close 後要 unlink,否則會留一個 file 在 /data/tsck。下次再 bind 就會 fail
ref: AF_UNIX, SOCK_DGRAM 好像不能用 recvfrom, 只能用 read, 否則有 data 近來時會有 argument error.

2011年1月11日 星期二

Android PNDK, native program

在 android/development/pdk/pndk/samples/sample 有 build native code 的 sample。 包含 Makefile。 其中的 Readme : (先照貼一下) Building native code applications and libraries STEP 1 Building an application. -------- 0) set the environment variable PREBUILT to point to the Android prebuilt directory export PREBUILT=<path_to_android_src>/prebuilt/<platform> where you type in the actual path to the android source in place of <path_to_android_src> and the platform you are using instead of <platform>: either linux-x86 or darwin-x86 1) Test the pndk install by building the hello world sample application: cd <your_pndk_base>/samples/sample make clean make The sample application uses hello.c to construct the hello binary, which you can load and run on the ARM device. To achieve proper runtime behavior, verify that: * crtbegin_dynamic.o is the first linked object file * crtend_android.o is last linked object. Both are set by the config.mk file in pndk/config. 2) Test that this works correctly by attaching your ARM-based device to the USB port and installing the application (hello) you just made by (in the commands below # is the ARM device's shell prompt): NOTE: need a development build so remount opens system permissions adb remount adb push hello system/app adb shell # cd system/app # ./hello Hello from the NDK; no user libraries. # exit 3) You may also build the c++ binary hello_cpp.cpp into an application: make -f Makefile.hello_cpp clean make -f Makefile.hello_cpp hello_cpp This uses the hello_cpp.cpp and hello_cpp.h files to construct the hello_cpp binary application, which you can load and run on the ARM device. Note that we do not provide for C++ exceptions thus you must use the -fno-exceptions flag when compiling. adb push hello_cpp system/app adb shell # cd system/app # ./hello_cpp C++ example printing message: Hello world! # exit STEP 2 Building and using a library ------- Makefile.lib in pndk/sample shows how to make either a shared library or a static library from the hellolibrary.c source. The example makes the libraries libhello-shared.so and libhello-static.a . Makefile.uselib then shows how to make an application that links against either a shared or a static library. They examples shows how to build the two applications use_hellolibrary-so and use-hellolibrary-a from the source use_hellolibrary.c. 1) To make a shared library and an application that uses it: make -f Makefile.lib clean make -f Makefile.lib sharedlib make -f Makefile.uselib clean make -f Makefile.uselib use_hellolibrary-so 2) Copy the shared library libhello-shared.so to /system/lib (or the location in which shared libraries are found by the kernel on your ARM-based device.) adb push libhello-shared.so system/lib You would not typically use the -shared or -static extensions in the filename, but the distinction is important in the case where a static and shared library are made in the same directory. Giving the files different names allows you to override the link defaults that default to a static library of the same name. 3) The application, use_hellolibrary-so, can now be tested by loading and running on the ARM device. adb push use_hellolibrary-so /system/app adb shell # cd system/app # ./use_hellolibrary-so Library printing message: Hello from the NDK. # exit 4) To make a static library: make -f Makefile.lib clean make -f Makefile.lib staticlib make -f Makefile.uselib clean make -f Makefile.uselib use_hellolibrary-a 5) Test the application use_hellolibrary-a by loading and running it on the ARM device. adb push use_hellolibrary-a system/app adb shell # cd system/app # ./use_hellolibrary-a Library printing message: Hello from the NDK. # exit SUMMARY: --------- To make everything execute the following: make clean make make -f Makefile.lib clean make -f Makefile.lib make -f Makefile.uselib clean make -f Makefile.uselib make -f Makefile.hello_cpp clean make -f Makefile.hello_cpp hello_cpp You should have: * The libraries libhello-static.a and libhello-shared.so built, the latter ready for installation, * The applications hello, use_hellolibrary-a, and use_hellolibrary-so available for installation on the ARM device. 那個設定path, toolchain. base rul 的 config.mk: # Assumes PREBUILT is defined to point to the correct flavor of the prebuilt # directory in the Android source tree CC := $(PREBUILT)/toolchain/arm-eabi-4.2.1/bin/arm-eabi-gcc AR := $(PREBUILT)/toolchain/arm-eabi-4.2.1/bin/arm-eabi-ar INC := -I$(NDK_BASE)/include/bionic/libc/arch-arm/include \ -I$(NDK_BASE)/include/kernel/include \ -I$(NDK_BASE)/include/bionic/libm/include \ -I$(NDK_BASE)/include/bionic/libm/include/arm \ -I$(NDK_BASE)/include/bionic/libc/include \ -I$(NDK_BASE)/include/bionic/libstdc++/include LINK := -nostdlib -Bdynamic \ -Wl,-T,$(NDK_BASE)/config/armelf.x \ -Wl,-dynamic-linker,/system/bin/linker \ -Wl,-z,nocopyreloc \ -L$(NDK_BASE)/lib \ -Wl,-rpath-link=$(NDK_BASE)/lib \ $(NDK_BASE)/lib/crtbegin_dynamic.o POSTLINK := $(NDK_BASE)/lib/crtend_android.o %.o: %.cpp $(CC) $(CFLAGS) -fno-exceptions -fno-rtti $(INC) -o $@ -c $< %.o: %.c $(CC) $(CFLAGS) $(INC) -o $@ -c $< NDK_BASE 在 sample/Makefile : NDK_BASE := ../.. 但是好像找不到正確的 NDK_BASE 位置..
那幾個 bionic 開頭的跟其他的 include 位置都不match。
download 官方 NDK 下來也一樣,

重新 mapping 一下好了:
INC include/bionic/libc/arch-arm/include : bionic/libc/arm-arm/include include/kernel/include : include/bionic/libm/include \ include/bionic/libm/include/arm \ include/bionic/libc/include \ include/bionic/libstdc++/include
ref 一下其他的:
target thumb C: test_pthread_mutex <= system/extras/tests/bionic/libc/common/test_pthread_mutex.c

prebuilt/linux-x86/toolchain/arm-eabi-4.4.0/bin/arm-eabi-gcc  
-I system/extras/tests/bionic/libc   
-I out/target/product/imx51_bbg/obj/EXECUTABLES/test_pthread_mutex_intermediates   -I system/core/include   
-I hardware/libhardware/include   
-I hardware/libhardware_legacy/include   
-I hardware/ril/include   
-I dalvik/libnativehelper/include   
-I frameworks/base/include   
-I frameworks/base/opengl/include   
-I external/skia/include   
-I out/target/product/imx51_bbg/obj/include   
-I bionic/libc/arch-arm/include   
-I bionic/libc/include   
-I bionic/libstdc++/include   
-I bionic/libc/kernel/common   
-I bionic/libc/kernel/arch-arm   
-I bionic/libm/include   
-I bionic/libm/include/arch/arm   
-I bionic/libthread_db/include  

-c  -fno-exceptions -Wno-multichar -msoft-float -fpic -ffunction-sections -funwind-tables -fstack-protector -fno-short-enums -march=armv7-a -mfloat-abi=softfp -mfpu=neon 

-include system/core/include/arch/linux-arm/AndroidConfig.h 

-I system/core/include/arch/linux-arm/ 

-mthumb-interwork -DANDROID -fmessage-length=0 
-W -Wall -Wno-unused -Winit-self -Wpointer-arith -Werror=return-type -Werror=non-virtual-dtor -Werror=address -Werror=sequence-point -DNDEBUG -g -Wstrict-aliasing=2 -finline-functions -fno-inline-functions-called-once -fgcse-after-reload -frerun-cse-after-loop -frename-registers -DNDEBUG -UDEBUG -mthumb -Os -fomit-frame-pointer -fno-strict-aliasing -finline-limit=64   
-D_XOPEN_SOURCE=600 -DHOST     -MD 
-o out/target/product/imx51_bbg/obj/EXECUTABLES/test_pthread_mutex_intermediates/common/test_pthread_mutex.o 
system/extras/tests/bionic/libc/common/test_pthread_mutex.c

target Executable: test_pthread_mutex (out/target/product/imx51_bbg/obj/EXECUTABLES/test_pthread_mutex_intermediates/LINKED/test_pthread_mutex)

prebuilt/linux-x86/toolchain/arm-eabi-4.4.0/bin/arm-eabi-g++ 
-nostdlib -Bdynamic 
-Wl,-T,build/core/armelf.x 
-Wl,-dynamic-linker,/system/bin/linker 
-Wl,--gc-sections 
-Wl,-z,nocopyreloc 
-o out/target/product/imx51_bbg/obj/EXECUTABLES/test_pthread_mutex_intermediates/LINKED/test_pthread_mutex 
-Lout/target/product/imx51_bbg/obj/lib 
-Wl,-rpath-link=out/target/product/imx51_bbg/obj/lib 
-lc -lstdc++ -lm  
out/target/product/imx51_bbg/obj/lib/crtbegin_dynamic.o         
out/target/product/imx51_bbg/obj/EXECUTABLES/test_pthread_mutex_intermediates/common/test_pthread_mutex.o         
-Wl,--no-undefined  
-Wl,--fix-cortex-a8  

/home/charles-chang/myandroid91/prebuilt/linux-x86/toolchain/arm-eabi-4.4.0/bin/../lib/gcc/arm-eabi/4.4.0/interwork/libgcc.a 
out/target/product/imx51_bbg/obj/lib/crtend_android.o

target Non-prelinked: test_pthread_mutex (out/target/product/imx51_bbg/symbols/system/bin/test_pthread_mutex)

out/host/linux-x86/bin/acp 
-fpt 
out/target/product/imx51_bbg/obj/EXECUTABLES/test_pthread_mutex_intermediates/LINKED/test_pthread_mutex out/target/product/imx51_bbg/symbols/system/bin/test_pthread_mutex

target Strip: test_pthread_mutex (out/target/product/imx51_bbg/obj/EXECUTABLES/test_pthread_mutex_intermediates/test_pthread_mutex)

out/host/linux-x86/bin/soslim
--strip --shady --quiet 
out/target/product/imx51_bbg/symbols/system/bin/test_pthread_mutex 
--outfile out/target/product/imx51_bbg/obj/EXECUTABLES/test_pthread_mutex_intermediates/test_pthread_mutex

Install: 
out/target/product/imx51_bbg/system/bin/test_pthread_mutex
out/host/linux-x86/bin/acp 
-fpt 
out/target/product/imx51_bbg/obj/EXECUTABLES/test_pthread_mutex_intermediates/test_pthread_mutex 
out/target/product/imx51_bbg/system/bin/test_pthread_mutex

install X and windows manager

$lspci | grep VGA 01:00 VGA compatible controller: ATI Technologies Inc RV350 AQ [Radeon 9600] 所以 install $sudo aptitude istall xorg xserver-xorg-video-radeon mesa-utils 然後 follow instruction.. # Xorg -configure # cp /root/xorg.conf.new /etc/X11/xorg.conf edit .xinitrc #!/bin/sh exec xterm 這樣 run startx 後,已經可以開啟 X,並且有 xterm。 但是沒有 windows manager。 所以 install 一個小的: $sudo aptitude install lwm 啟動 startx 後,再下 command : lwm& 就有 windows manager 了
ref: 後續:最後還是 install gnome (aptitude install gnome) ,然後修改 .xinitrc: exec gnome-session 就可以用 startx 進入 gnome。 可是重開機後,gdm3 就直接進 gnome 了。 比較一下當初 upgrade 完 squeeze 後,gdm login 完變成black screen (只有 mouse cursor) 好像是 video driver 的問題。從 ati 改成 radeon 就是現在的版本。

2011年1月10日 星期一

pthread

pthread 的 p 是 posix,也就是 posix 標準的 thread api。 fork 的 parent 和 child 沒有任何共用的地方。 但是 thread_create 出來的 thread 和 mother(?) process/thread 共用 所有的東西。 所以 thread 間的同步控制就更重要。 pthread 的標準就包含很多 process 間同步的物件。 從resource 共用來看 process 和 thread: thread 間要共用一個 array,就宣告一個 global array 就可以。 但是 process 間要共用一個 array,在 fork 之前就要先用 shmget,shmat 準備好。
  | Unable to migrate to dependency-based boot system                                                                                     │ 
 │                                                                                                                                       │ 
 │ Tests have determined that problems in the boot system exist which prevent migration to dependency-based boot sequencing:             │ 
 │                                                                                                                                       │ 
 │ insserv: warning: script 'S25libdevmapper1.02' missing LSB tags and overrides, insserv: warning: script 'libdevmapper1.02' missing    │ 
 │ LSB tags and overrides, , package atftpd removed but not purged, package console-tools removed but not purged, package dhcdbd         │ 
 │ removed but not purged, package fam removed but not purged, package kdm removed but not purged, package mysql-server-5.0 removed but  │ 
 │ not purged, package openvpn removed but not purged, package pcscd removed but not purged, package timidity removed but not purged     │ 
 │                                                                                                                                       │ 
 │ If the reported problem is a local modification, it needs to be fixed manually. If it's a bug in the package, it should be reported   │ 
 │ to the BTS and fixed in the package. See http://wiki.debian.org/LSBInitScripts/DependencyBasedBoot for more information about how to  │ 
 │ fix the problems preventing migration.                                                                                                │ 
 │                                                                                                                                       │ 
 │ To reattempt the migration process after the problems have been fixed, run "dpkg-reconfigure sysv-rc".       

 │ Unable to migrate to dependency-based boot system                                                                                     │ 
 │                                                                                                                                       │ 
 │ Tests have determined that problems in the boot system exist which prevent migration to dependency-based boot sequencing:             │ 
 │                                                                                                                                       │ 
 │ insserv: warning: script 'S25libdevmapper1.02' missing LSB tags and overrides, insserv: warning: script 'libdevmapper1.02' missing    │ 
 │ LSB tags and overrides, , package dhcdbd removed but not purged                                                                       │ 
 │                                                                                                                                       │ 
 │ If the reported problem is a local modification, it needs to be fixed manually. If it's a bug in the package, it should be reported   │ 
 │ to the BTS and fixed in the package. See http://wiki.debian.org/LSBInitScripts/DependencyBasedBoot for more information about how to  │ 
 │ fix the problems preventing migration.                                                                                                │ 
 │                                                                                                                                       │ 
 │ To reattempt the migration process after the problems have been fixed, run "dpkg-reconfigure sysv-rc".                                │ 
 │
在 system/extra/tests/bionic/libc 是一些bionic libc function 的 test program。
其中的 Makefile 特別寫成一個 source , 一個 executable。
readme 有說明 build 的方法:
    cd system/extras/tests/bionic/libc
    mm BIONIC_TESTS=1
特別寫的 script 是:
define device-test
  $(foreach file,$(1), \
    $(eval include $(CLEAR_VARS)) \
    $(eval LOCAL_SRC_FILES := $(file)) \
    $(eval LOCAL_MODULE := $(notdir $(file:%.c=%))) \
    $(eval LOCAL_MODULE := $(LOCAL_MODULE:%.cpp=%)) \
    $(eval LOCAL_CFLAGS += $(EXTRA_CFLAGS)) \
    $(eval LOCAL_MODULE_TAGS := tests) \
    $(eval include $(BUILD_EXECUTABLE)) \
  ) \
  $(eval EXTRA_CFLAGS :=)
endef
使用的 command:
sources := \
    common/test_getaddrinfo.c \
    common/test_gethostbyname.c \
    common/test_gethostname.c \
    common/test_pthread_cleanup_push.c \
    common/test_pthread_getcpuclockid.c \
    common/test_pthread_join.c \
    common/test_pthread_mutex.c \
    common/test_pthread_once.c \
    common/test_semaphore.c \
    common/test_seteuid.c \
    common/test_static_cpp_mutex.cpp \
    common/test_strftime_2039.c \
    common/test_tm_zone.c \
    common/test_udp.c \

EXTRA_LDLIBS := -lpthread -lrt
EXTRA_CFLAGS := -D_XOPEN_SOURCE=600 -DHOST

$(call device-test, $(sources))

2011年1月7日 星期五

memo

bionic 有 pthread_mutex 在 system/extras/tests/bionic/libc/common 有 test program,可以當做範例。

2011年1月6日 星期四

測試一下Chrome..會轉轉轉嗎?

Android IPC -- Bind

Android把 System V -IPC 拿掉,改用 Binder。

Binder 是 linux kernel 的一個 driver。user program 利用 /proc/binder 與他溝通。

Android 設計 ServiceManager 這個 program,作為 user program 和 binder 間的介面。

Binder 提供的 IPC 和被拿掉的 System V IPC 不一樣。
Android 好像只有用 Binder 實作出一個 IPC 的功能,就是類似 message的 send-reply。

但是不是任意兩個 process 都可以用 Binder 來作 IPC。
一個要是 Service,一個要是 Client。

Service 向 ServiceManager 註冊一個 Service/Interface, ServiceManager 會幫他把 service name, interface pointer 加到 Binder 的資料裡。

Client 向 ServiceManager 要求取得 XXX service (以 service name 為參數)。
ServiceManager 就會由 Binder 找出對應的 Service interface 給 Client。

然後 Client 就可以利用這個 interface 對 Service send msg.



這個 Interface prototype 是固定的,所以就像 IOControl 一樣, interface 的第一個 argument 是 function code,後面是 sendmsg (client to server), 再來是 reply (server reply to client)。

所以 service 在作這個 interface 的時候,就像 IoControl 一樣,依照 function code 對 sendmsg, replymsg 作不同的處置。



有點麻煩..

2011年1月5日 星期三

busybox 在 make menuconfig 後,會產生 .config 和 include/autoconf.h

make 接著產生 include/bbconfigopts.h , include/applet_tables.h

然後在 Makefile.custom 中。有
busybox.link: $(srctree)/applets/busybox.mkll $(objtree)/include/autoconf.h $(srctree)/include/applets.h $(Q)-$(SHELL) $^ >$@ 產生 busybox.link

bionic libc liked busybox

現在要 build 使用 bionic libc 的 busybox 變得比較簡單了。
這都要感謝 android-x86 專案。

因為 android-x86 已經把 busybox 內建在 source package,
所以只要把 external/busybox copy 到自己的專案就可以。
-- 他的 git link 到 .rep/project/external/busybox.git,有需要也可以一併 copy

然後就可以用 mm build 了。
如果你的 bionic 版本太舊,可以參考 android-x86 的 bionic 修改。
一般來說,會缺 這一篇 (http://lazyhack.net/compile-busybox-linked-bionic/ ) 講得幾個 system call.
bionic/libc/arch-arm/syscalls/adjtimex.S bionic/libc/arch-arm/syscalls/stime.S bionic/libc/arch-arm/syscalls/swapoff.S bionic/libc/arch-arm/syscalls/swapon.S bionic/libc/arch-arm/syscalls/sysinfo.S bionic/libc/arch-arm/syscalls/getsid.S 就 follow 把 android-x86 的 source code copy 過來。
還有修改 mk 和 header ,
這樣就可以重新 build bionic, busybox。
busybox build 完會 install 在 out 的 system/xbin 下面。

這樣就見識到 open source 的專案, user 會讓 function 漸漸的完整。

2011年1月4日 星期二

install disk

利用原來的 kerne, rootfs, 和 system image (主要是要用到裡面的 command)。來作 auto install disk

當然,target 要能選擇從另一個 sd 開機。

大概就是 pc 做的一樣:
  • partition
  • format
  • dd
所以所有 pc 上的 tool 都要找到 android/arm 的版本
  • fdisk -- busybox
  • mke2fs -- e2fsprog
  • dd -- busybox (android 付的 dd 不認識 K, M, G 等 size argument)
就這樣。
然後寫成 shell script,放到 init.rc 裡。

init.rc 可以參考 recovery 和 diskinstaller 裡的 init.rc 來作。
大概就是 甚麽都不用了,只要記得 mount partition 跟 class_start default
-----> 因為要 class_start default,接下來的一堆 service command h才會啟動。

上述動作都寫在同一個 shell script,然後由 service 叫起來:
service installall /sdcard/installall.sh console oneshot
因為 partition, format,dd 有相依,一個做完才能換另一個,所以要寫在同一個 script,如果用分別的 service 寫,在 sleep的時候,下一個service就會啟動了。

shell script 要注意, sh 在 /system/bin/sh

貼一下 diskinstall 的 init.rc: on init export PATH /sbin:/system/sbin:/system/bin export ANDROID_ROOT /system export ANDROID_DATA /data symlink /system/etc /etc mkdir /data mkdir /cache mount /tmp /tmp tmpfs # mount the installer needed partitions # mount ext2 /dev/block/sdb2 /data ro on boot ifup lo hostname localhost domainname localdomain class_start default service installer /system/bin/installer -p /dev/block/sdb2 console oneshot service logcat /system/bin/logcat console service console /system/bin/sh console

fdisk in shell script

nelson 說的 在 shell script 裡要用 fdisk ,可以這樣用: #!/bin/sh sudo fdisk /dev/sdc <lt; EOF n p 1 w EOF exit 其中有兩行只按 enter,對應 fdisk 的操作

2011年1月3日 星期一

partition table

partition table 就位在 以 0x55AA 結束的 第 0 sector 。
只有 4 個 entry 的空間,每個 partition 佔掉 16 bytes。
每個 partition entry 的內容:
 ------------------------------
| 00  |  1  | boot indicator   |
-------------------------------
| 01  |  3  | Start CHS        |
------------------------------
| 04  |  1  | Partition Type   |
------------------------------
| 05  |  3  | End CHD          |
------------------------------
| 08  |  4  | Start - LBA      |
------------------------------
| 0C  |  4  | End  - LBA       |
------------------------------

用一個 byte 代表 partition 的 id - 是什摩 partition,0x05 就是 extend partition。
如果是 extend partition,那個 partition table entry (16 bytes) 的 start sector,就代表 extend partition table 的所在位置。

extend partition table 的內容跟 mbr partition table 一模一樣,但是只有用到其中 4 個 partition entry 的兩個。
一個代表這個 parition 的內容
第二個代筆下一個 partition table 的位置

就這樣,像 linking list 一樣,連下去。 ...


所以 使用 mbr partition table ,最多只有 4 個 primary partition,但是 extend partition 的 數量則沒有限制。


ref

Android Init Language - init

Android source 的 system/core/init 有 readme,說明 init 的使用方法 (Android Init Language) 每個指令有四項選項:
  • Action
  • Command
  • Service
  • Options

Action 當 XX 事情發生時,依序執行下列的 command.. 這個 XX 事情稱為 " Trigger",有:
  • boot : init 開始執行
  • <name>=<value> : name == value 時
  • device-add-<path> / device-remove-<path> : 當 device add 或 remove 時。
  • service-exited-<name> : service 結束得時候。
Command
  • exec <path> [<argument>]* : fork and execute 'path'. init 會停止,等這個程式執行完畢
  • export <nam> <value> : set global environment variable
  • ifup <inteface>
  • import <filename> : 類似 include XXX
  • hostname <name> : 設定 hostname
  • chdir <directory> : change working directory
  • chmod <octal-mode> <path> : 變更 'path' 的權限
  • chown <owner> <group> <path>
  • chroot <directory> : change root directory
  • class_start <service classname > : 把同屬於 'class name' 的所有 service 啟動
  • class_stop <service classname >
  • domain <name>
  • insmod <path>
  • mkdir <path> [mode] [owner] [groupe] : create a new directory
  • mount <type> <device> <dir> [ <mount options>]*
  • setrop <name> <valu> : set system property
  • setrlimit <resource> <cir> <max> : 設定 resource 的使用值, max limit
  • start / stop <service> : 停止,啟動 service
  • symink <target> <path> : 就是 ln -s
  • sysclktz : set timezone
  • trigger <event> : Trigger Event
  • write <path> <string> [<string>]* : 開啟 file (path),寫入 string...
Service init 會叫起他門,並且依照 option ,當程式 exit 時,重新再叫起。 Options 用來決定 Service 的行為:
  • critical : 如果這個 service 在一分鐘內resart 4 次,把系統重新啟動,進入 recovery mode.
  • disabled : 不啟動
  • setenv <name> <value> : 啟動時,環境變數設好
  • socket <name> <type> <perm> [ <user> [<group>]] : create socket並且 pass 給啟動的程式
  • user >username> : 以 username 來執行
  • groupe <groupename> [<groupename>]* : 以 groupename 來執行
  • oneshoot : 執行一次就好,不用 restart
  • class <name> : 給定一個 classs name, 同屬一個 class 的所有 service 都要一起啟動,一起停止。
  • onrestart : 這個 service reatart 時,同時執行下列 command..

init 還會 upate 以下的 system property:
  • init.action : 目前的 action
  • init.command : 目前的 command
  • init.svc.<name> : 目前 'service' 的狀態。

所以要執行自己的 command 大概要用 exec ..

標籤

網誌存檔