Updated trouble shooting section! 2009.10.8

Copied from 

http://hydtech.wordpress.com/2009/09/14/how-to-connect-to-ad-hoc-networks-using-tmobile-g1-android/

How to connect to Ad Hoc networks using Tmobile G1 Android

Intro

The G1 does not connect to ad hoc networks through the wifi manager but we can hack it to allow scanning and connecting to ad hocs. I’ve been trying to figure this out for the longest time. Before you begin, you need to root your G1 and be comfortable using the command line. We will be editing tiwlan.ini and wpa_supplicant.conf. I will be showing you 2 ways to edit the files. Using vi and adb.


Settings

edit tiwlan.ini to read:

WiFiAdHoc = 1
dot11DesiredSSID = HydtechAdhoc (or whatever name u want)
dot11DesiredBSSType = 0

edit wpa_supplicant.conf to read:

ctrl_interface=tiwlan0
update_config=1
eapol_version=1
ap_scan=2 (tells wpa_supplicant to scan hidden networks)

network={
ssid=”HydtechAdhoc”
scan_ssid=1 (for APs with multiple SSIDS)
mode=1
key_mgmt=NONE
group=WEP104
auth_alg=SHARED
wep_key0=”MyWepKey” (replace MyWepKey with your key)
}

How to edit using vi:

Download terminal from the market and type:

su (for superuser mode)
mount -o rw,remount -t yaffs2 /dev/block/mtdblock3 /system (mount partition as writable)
vi /system/etc/wifi/tiwlan.ini (open tiwlan.ini in vi text editor)

now type A to enter editing mode, finish editing your file and hold trackball+1 to stop editing. To save and exit type :wq

vi /data/misc/wifi/wpa_supplicant.conf (open file for editing)

edit with the settings given above and exit and don’t forget to change the partition back to read only
mount -o ro,remount -t yaffs2 /dev/block/mtdblock3 /system

reboot

How to edit files with adb on Ubuntu:

Connect your g1 to the computer using a usb cable and make sure USB debugging in enabled
Open up terminal and type
cd /home/hydtech/[android sdk folder]/tools (navigate to the directory which has you adb tool)

get the files from the device and place them in the root folder
sudo ./adb pull /system/etc/wifi/tiwlan.ini /
sudo ./adb pull /data/misc/wifi/wpa_supplicant.conf /

edit and save the files with the settings provided above using gedit or kate or what have you

make the partition read writable
adb shell
mount -o rw,remount -t yaffs2 /dev/block/mtdblock3 /system
exit

place the files back onto the device
sudo ./adb push /tiwlan.ini /system/etc/wifi/tiwlan.ini
sudo ./adb push /wpa_supplicant.conf /data/misc/wifi/wpa_supplicant.conf

make partition read only again
adb shell
mount -o ro,remount -t yaffs2 /dev/block/mtdblock3 /system
exit

reboot device.

Troubleshooting

shows connected but no internet
1. I was having a problem where the connection would keep disconnecting and when it would connect, it wouldn’t load pages. To fix this I had to disable my WEP key.

SSID not showing
2. If the SSID isn’t showing up in the list, make sure you have ap_scan=2 in your wpa_supplicant

Unsuccessful connection
3. Try enabling static IP if DHCP isn’t working for you. It’s under advanced menu. You will fail to establish the connection unless all entries under 'Use static IP' are filled.

Posted by kevino
,
출처: http://antonmelser.org/open-source/backup-install-restore-adp1.html


안드로이드 개발폰(ADP1)에서 백업,설치,복구 하는 방법


주의: 이 지침서는 안드로이드 개발폰에서만 적용되고 G1 폰이나 다른 안드로이드 단말기에서는 지원이 안됨

제 1장 필요한 도구 준비하기

1. 안드로이드 소스 컴파일

    다음 링크를 참조: http://source.android.com/download

우분투에서 설치 방법

$ sudo apt-get install git-core gnupg sun-java6-jdk flex bison gperf libsdl-dev libesd0-dev libwxgtk2.6-dev build-essential zip curl libncurses5-dev zlib1g-dev

여러분의 홈 디렉토리에 ~/bin 디렉토리가 있고 패스에 포함되어 있는지 확인
$ cd ~
$ mkdir bin
$ echo $PATH
(if it's not then add it to .bashrc then $ source .bashrc)

Download the repo script and make sure it is executable:
$ curl http://android.git.kernel.org/repo >~/bin/repo
$ chmod a+x ~/bin/repo

Ok, now we have the tools, we need to get  the source. And don't worry, this takes a LONG time - it's over 2GB, so unless you have a fibre link, you're in for a very long wait.

$ mkdir mydroid
$ cd mydroid
$ repo init -u git://android.git.kernel.org/platform/manifest.git

If it asks you for things, then answer as you like - they don't need to be true (except maybe a valid google address) but to be honest you're not risking much... then

$ repo sync
(this is what takes the time)

When that finally finishes there are a few binary-only files you need to copy from the phone. Here are the instructions copied from here:

  1. (we've already done step 1)
  2. download local_manifest.xml here
  3. put local_manifest.xml in the .repo directory (next to the main manifest.xml)
  4. repo sync (to download the three new projects)
  5. in vendor/htc/dream/ there is a script that must be run (from that directory) to extract some proprietary binaries from your device.*
  6. create a buildspec.mk at the top of your source tree and add TARGET_PRODUCT:=htc_dream to it
  7. (we do this straight after)

$ make 

  시간이 많이 걸리니 낮잠 때려도 좋을듯


이 과정이 끝나면 여러가지 이미지들과 유용한 툴(fastboot)이 같이 생성된다.


2. 안드로이드 SDK 설치할 것: (나중에 다 필요함)
    
    참고 http://developer.android.com/sdk/1.5_r3/index.html

3. 수정된 recovery.img를 받을 것

    참고: http://forum.xda-developers.com/showthread.php?t=466174

    ADP1 버전을 받을 것


제 2장 ADB1 의 설치된 파일 백업하기


4. ADP1을 fastboot모드로 설정하기



Backup/install/restore Android on an Android Developer Phone 1 (ADP1)
I bought and ADP1 on the 4th of January, and was keen as mustard to compile the latest and greatest from source. Having read around the place that it wasn't particularly stable or useable, I naturally wanted to be able to restore the default settings to get back a useable phone. So I head over to source.android.com looking for instructions. Great, they've got instructions for building for the dream (ADP1 hardware) but absolutely NOTHING for backup or restore. So I thought, oh well, Google Is My Friend... but no, on this occasion, Google was not my friend.

I found multitudes of info, mainly from the excellent xda-developers forum but came across something very frustrating - instructions for modding/cracking (+ doing what I wanted) the T-Mobile G1, with not so helpful "works with the ADP1" tacked on for good measure. All the info was there but it was all but clear what I needed to do, as I ALREADY have root access, and no OTA (Over The Air, took me a while!) updates were going to de-root me. I wanted to install/change the absolute minimum - after all, I paid over 400€ (I'm living in France, around 560$), and it's a developer phone - why should I have to install recovery.img/update.zip/? What's more, there werre always infuriating: "Step 4. Click here and follow instructions", only to find a "Step 3. Click here for instructions" in the second list, and so on! So I finally posted on android-discuss, and the very helpful lbcoder provided me with great instructions. His original instructions are here but here I will be augmenting them with explanations - my goal here is to provide clear and concise instructions for people who have an ADP1 and want to test it out and revert and are sick of having to sift though t-mobile-g1-specific crap. I also got quite a bit of knowledge from the posts made by Koush, including here.

A final word of warning  -

IF YOU HAVE A T-MOBILE G1 OR ANY OTHER SIMLOCKED VERSION THESE INSTRUCTIONS ARE NOT FOR YOU.

That felt good! So here goes... These instructions worked for me - YMMV. I am running a fairly standard Debian Lenny x86 (on an Athlon X2, which is x64, but anyway) but these instructions should be ok for any recent debian-based system. You should be fairly knowledgeable about linux and happy with the command line. These instructions may not work for non-debian systems, probably won't for Mac, and DEFINITELY won't work for windows. I am not interested in either of the later systems, so don't ask for help for those systems.  I'll try to do as much hand-holding as possible but if you're not comfortable with linux or the CL, then I can't help. You shouldn't need ANY android-specific knowledge - if you know linux and things aren't clear, I'll update the article. You should also have had a bit of a play with the stock install of the phone and know how to set it up and turn it off... I intend updating this article with more explanations of the various parts of android internals as I learn more, so stop back and have a look if you haven't become a guru in the meantime.

Standard disclaimer: I will be in no way, shape, or form be held responsible if the instructions don't work for you or brick your phone!

The backup will be smaller if you get rid of all the pictures/movies/music/random apps you have installed, so get rid of as much as possible (you can always put it back later...).

Part A - downloading the necessary files/programmes/code.

1. Get the android source and compile.
Here is an abbreviation of the instructions mentioned here.The linked site (android) has more explanation.

$ sudo apt-get install git-core gnupg sun-java6-jdk flex bison gperf libsdl-dev libesd0-dev libwxgtk2.6-dev build-essential zip curl libncurses5-dev zlib1g-dev

Make sure you have a ~/bin directory in your home directory, and check to be sure that this bin directory is in your path:
$ cd ~
$ mkdir bin
$ echo $PATH
(if it's not then add it to .bashrc then $ source .bashrc)

Download the repo script and make sure it is executable:
$ curl http://android.git.kernel.org/repo >~/bin/repo
$ chmod a+x ~/bin/repo

Ok, now we have the tools, we need to get  the source. And don't worry, this takes a LONG time - it's over 2GB, so unless you have a fibre link, you're in for a very long wait.

$ mkdir mydroid
$ cd mydroid
$ repo init -u git://android.git.kernel.org/platform/manifest.git

If it asks you for things, then answer as you like - they don't need to be true (except maybe a valid google address) but to be honest you're not risking much... then

$ repo sync
(this is what takes the time)

When that finally finishes there are a few binary-only files you need to copy from the phone. Here are the instructions copied from here:

  1. (we've already done step 1)
  2. download local_manifest.xml here
  3. put local_manifest.xml in the .repo directory (next to the main manifest.xml)
  4. repo sync (to download the three new projects)
  5. in vendor/htc/dream/ there is a script that must be run (from that directory) to extract some proprietary binaries from your device.*
  6. create a buildspec.mk at the top of your source tree and add TARGET_PRODUCT:=htc_dream to it
  7. (we do this straight after)

$ make 
(this could also take hours)

Both of the very long commands are quicker for subsequent update/compiles, but still take an age. The compile also generates a tool that we will be using quite a bit (in mydroid/out/host/linux-x86/bin/) - fastboot. This wee gem lets you do lots of cool stuff but more on that later.

2. Get the android sdk.
The sdk has some very useful tools for interacting with a running android system, and that includes your new ADP1 phone. Download it from here. Extract to somewhere useful. I've seen a lot that the tools directory of the SDK needs to be in your $PATH, but haven't actually found that to be true - it can't hurt though.

3. Get your hands on JF's (JesusFreak) modified recovery.img. Calm down! I know it's an xda-developers link but it's just for the download (1GB goes very quickly when you post 30MB files...), the only thing you need to read is for finding the link for the ADP1 version. http://forum.xda-developers.com/showthread.php?t=466174. Download the ADP1 version! If he has already updated the post and the version has changed (and you want to follow these instructions to the word, but subsequent versions are probably better) then drop me a line and I'll post the file here. You need to extract the archive (and remember where you put it) - recovery.img is at data/recovery.img.

Part B - Backing up your phone. 
Ok, so that was easy - we've done nothing unusual, it's all standard linux stuff. Now we get to plug in the phone... 
Before you start getting worried, the xda-developers file we downloaded is NOT going to be installed to the phone. We use it like you would a livecd (or SystemRescueCD, or whatever). It boots us to a minimal, non-running system in memory so we can backup without having all those temp files (think /proc, /dev, etc.). This is done with help from the fastboot binary we compiled in step 1.

4. Start your ADP1 in fastboot mode: From power off, hold the camera button while turning on (keep your finger on the camera button, then press on), this will get you into a mode that says "serial0" with androids on skateboards. Plug in the USB (wait for a bit) and press the "back" button. It should now be in fastboot mode, and instead of "serial0" it will say "fastboot". Try the back button a few more times (and wait a few seconds in between) if you don't see fastboot straight away.

5. From your computer, run the command "fastboot boot recovery.img". This will send recovery.img to your ADP1 WITHOUT writing it and will cause it to boot. For me (and others on debian-based systems, as I've read), fastboot doesn't work unless you're root (something to do with standard permissions on USB devices mounted automatically). Now cd into the data directory you got from the JF download in step 3. Presuming your username is "me", and you put the android source in ~/mydroid you should execute something like:
$ sudo /home/me/mydroid/out/host/linux-x86/bin/fastboot boot recovery.img

As sudo is broken on debian, you'll need to put the full path in each time (putting it in your path, even if you are in the sudo group it doesn't work).

6. When the recovery.img has finished booting, it presents a menu, one of which is to create a backup. The backup will be written to the sdcard in the /nandroid/ directory. It should tell you the backup was successful. You should now reboot your phone (another menu option), and mount it, so you can copy the backup to your computer (or like me also to some online storage!). 

Part C - Installing from the compiled source.
You have already compiled all the necessary image files, so here we go...

7. get to where the installable images were created

$ cd ~/mydroid/out/target/product/dream

8. Boot your phone to fastboot, like we did in Part B, 4. You should then execute the following commands and get similar output (the file sizes will change):

me@debian:~/mydroid/out/target/product/dream$ sudo /home/me/mydroid/out/host/linux-x86/bin/fastboot flash system system.img
sending 'system' (51086 KB)... OKAY
writing 'system'... OKAY
me@debian:~/mydroid/out/target/product/dream$ sudo /home/me/mydroid/out/host/linux-x86/bin/fastboot flash boot boot.img
sending 'boot' (1418 KB)... OKAY
writing 'boot'... OKAY
me@debian:~/mydroid/out/target/product/dream$ sudo /home/me/mydroid/out/host/linux-x86/bin/fastboot flash userdata userdata.img
sending 'userdata' (2 KB)... OKAY
writing 'userdata'... OKAY
me@debian:~/mydroid/out/target/product/dream$ sudo fastboot reboot

You should now be booting to a source-compiled system! You'll need to rerun the registering process (which you've already done) but you can now do it at a later time than first boot.

9. Have a play, on 2009-01-25 there we still lots of things broken and/or missing. I've seen lots of talk of a "cupcake" release being pushed to T-Mobile users some time before the end of Feb. but with the state of the source, I can't imagine how...

Part D - Reverting to your stock image.

10. So now you want to get back to what you had before. First thing you need to do is get to where your backups are, let's say they are in /home/me/HT848GZ40218/20090121-1931, though you will have something slightly different (the date, for sure, the machine name maybe):

$ cd  ~/HT848GZ40218/20090121-1931

 Now simply execute the same commands you did to install the source (output from fastboot omitted, if you don't get output, IT DIDN'T WORK):

$ sudo /home/me/mydroid/out/host/linux-x86/bin/fastboot flash system system.img
$ sudo /home/me/mydroid/out/host/linux-x86/bin/fastboot flash boot boot.img
$ sudo /home/me/mydroid/out/host/linux-x86/bin/fastboot flash userdata userdata.img
$ sudo /home/me/mydroid/out/host/linux-x86/bin/fastboot reboot

The data image could be called data.img and not userdata.img. If that is the case, then just change the .img filename and not the partition to flash - it still needs to be $... flash userdata data.img.

 You should now have everything restored to normal. It may not be EXACTLY like it was before but all my apps and config were restored and working, and that's all I cared about.You can also use these instructions to try out other people's images/compiling. I tried out this (which didn't work for me), and this (which did, and was pretty good). Simply extract the archives and run the "fastboot flash system system.img", etc.Then fastboot reboot, play, and revert to your stock backup.

Feel free to drop me a line (in About Me) if you find any errors (or take real offense to my blatant plagiarism!) in this document...

Random advice/comments:

1. I had the google apps (gmail, contacts, calendar) stop syncing at one point. It seemed to happen when I went out of my provider's area (from France to Spain) with no roaming. Rebooting the phone solved this.

2. I've had a few emails from people commenting on their experiences and would like to thank everyone for their input on the article. One in particular gave some comments on getting a build to work properly. I initially thought about posting the comments but then realised it would be a mistake... We're at the bleeding edge of android development here, and one commit could render the advice useless. I DO definitely think that if you are having any problems with building and/or modules functioning (or not), then always search for the latest google groups posts by JBQ. He's a googler, and seems to be interested in making life for us ADP1 owners interesting by both committing code to get things to work, and providing advice and workarounds.

3. Now you can install the (almost, see article) Official upgrade from Google! See here for instructions!

Posted by kevino
,

*Reference: http://honeypod.blogspot.com/2007/12/compile-android-kernel-from-source.html



Compile Android kernel from the source

I confirmed the following procedure only on my linux host (FC8). Sorry for Windows and Mac users.

1. Get toolchains from CodeSourcery (Choose ARM GNU/Linux and IA32 GNU/Linux).

2. Get kernl source code from here.

3. Deploy toolcains and kernel source and enter in the kernel source tree.

$ mkdir -p android
$ cd android
$ tar xjvf ../arm-2007q3-51-arm-none-linux-gnueabi-i686-pc-linux-gnu.tar.bz2
$ tar xzvf ../linux-2.6.23-android-m3-rc20.tar.gz
$ cd kernel


4. Get the config.gz from the running emulator by the following way.

$ adb pull /proc/config.gz .

5. Decommpress the config.gz and rename it as .config

$ gunzip config.gz
$ mv config .config

6. Specify CROSS_COMPILE in the Makefile.

CROSS_COMPILE=../arm-2007q3/bin/arm-none-linux-gnueabi-

7. Comment out LDFLAGS_BUILD_ID[*1] in the same Makefile.

#LDFLAGS_BUILD_ID = $(patsubst -Wl$(comma)%,%,\
$(call ld-option, -Wl$(comma)--build-id,))

8. Make the kernel

$ make

9. Check zImage is created and the size is nearly same as the kernel-qemu in the Andorid SDK.

$ ls -l arch/arm/boot/zImage
-rwxrwxr-x 1 motz motz 1234712 2007-12-01 18:06 arch/arm/boot/zImage
$ ls -l $SDK/tools/lib/images/kernel-qemu
-rwxrwxr-x 1 motz motz 1245836 2007-11-12 5:59 ...sdk/tools/lib/images/kernel-qemu

10. Run emulator with the created kernel.

$ emulator -kernel arch/arm/boot/zImage





[*1]: The LDFLAGS_BUILD_ID enables --build-id option of ld if available. The --build-id option is relatively new. The current emulator does not seem to support the kernel linked with this option. See here if you are interested in the detail of this option.
Posted by kevino
,
0. Android에 삼바 서버를 올릴 것
0-1. 윈도우 탐색기에서 네트워크 검색으로 G1이 검색되는지 확인

1. net view
If this command output RPC error( system error #1728), then other choice will be next.

2. net use ( copied from http://itka.kr/zbxe/10075 )

가끔 매번 사용해야하는 네트워크 드라이브를 주소를 넣고 항상 입력하기란 번거롭습니다.
그럴때 아래 내용을 netdrive.cmd 파일로 만들어 시작프로그램에 넣어두시기 바래요
그럼 컴퓨터 시작과 동시에 자동으로 네트워크 드라이브를 연결 합니다.

net use /delete *

@echo off

set USER=[사용자명]

set PASSWD=[비밀번호]

net use [드라이브명] [\\경로명] %PASSWD% /user:%USER%

net use [드라이브명] [\\경로명]

net use [드라이브명] [\\경로명]

위에 한글로 표시한 부분은 각자 구성에 맞게 설정을 변경 하셔야 합니다.

 

) 1

Set USER=me

Set PASSWD=P@SSWARD

net use x: \\192.168.10.2\public %PASSWD% /user:%USER%

예2) net use z: \\Android-G1


삭제할 경우에는 

net use /delete [드라이브명 또는 *]

예1) net use /delete z:






3. net view 사용법


c:\>net view /DOMAIN

Domain


-------------------------------------------------------------------------------

WORKGROUP

명령을 잘 실행했습니다.



E:\>net view /DOMAIN:WORKGROUP

서버 이름            설명


-------------------------------------------------------------------------------

\\ANDROID-G1           AndroidSamba

\\DESK                 desktop

\\LOUIS-PC             notebook

\\UBUNTUSVR            VMWareUbuntu

명령을 잘 실행했습니다.


주의할 점


A. PlugIn: CP850과 CP437을 안드로이드 용으로 컴파일한다.

 서버를 컴파일할때 CODEPAGEDIR 속성을 /system/lib으로 할 것


B. G1폰의 파티션의 남아 있는 용량이 부족할 수 있다.



4. dlopen사용법


보통 plugin으로 동작하는 것들은 동적라이브러리로 만들어지는데 이를 안드로이드에서 이용하고자 하면 지켜야 할 것들이 몇가지 있으니 주의해야 한다.


1. 일반적으로 새롭게 만들어진 실행 이미지( 실행파일 및 동적라이브러리)의 사용자 권한은 root로 설정된다.

2. 안드로이드에서는 파티션에 따라 root가 관리할 수 있는 디렉토리와 system이 관리하는 디렉토리로 나뉘게 되는데 꼭맞는 디렉토리에 실행 이미지가 존재하지 않으면 이상 동작하게 된다. 예를 들어 동적 라이브러리를 root권한이 아닌 system 디렉토리에 넣고 실행하게 되면 실패하고 root 권한이 설정된 폴더에 있는 경우 정상 동작할 수 있다. 이경우에도 실행이미지의 경우 파일 속성에 실행가능 속성을 꼭 해줘야 하는 점을 잊지 말자

3. 일반적으로 system 관리하의 디렉토리에 파일을 복사하게 되면 실행속성이 제거가 된다.


Posted by kevino
,

Android Tips


 

1. 안드로이드 에뮬레이터에서 화면 방향을 바꾸려면
    --> 숫자키9를 Num lock을 해제한 상태에서 누른다

2. Quick launcher에서 설정하고 난후 실행하기위해서는 SYM + 해당 알파벳을 누른다. 예를 들어 Search + a 의 경우 화면 키보드에서 SYM키를 마우스 버튼으로 누른 상태에서 "a"를 누르면 해당 애플리케이션이 실행된다.


3. Android G1에서 root권한 및 cp와 같은 유틸리티 설치 하는 법

Add busybox

  1. download busybox by tapping and holding (long pressing) this file and choosing save link to your sd card (using android browser)
  2. remount system as read-write
    • mount -o remount,rw -t yaffs2 /dev/block/mtdblock3 /system
  3. copy and rename busybox.asc to /system/bin/busybox
    • dd if=/sdcard/download/busybox.asc of=/system/bin/busybox
  4. make it executable
    • chmod 4755 /system/bin/busybox
  5. go there
    • cd /system/bin/
  6. this gives you cp (great for making more symlinks)
    • busybox cp -s busybox cp
  7. start sh (this is busybox sh and has more commands and is easier to use)
    • busybox sh

You will not need to create any more symlinks if you plan on installing any recent JF update as he has done this for you.

P.S. If you have adb running you can paste this in to do all of the previous commands at once (much faster).


1. mount -o remount,rw -t yaffs2 /dev/block/mtdblock3 /system 
2. dd if=/sdcard/download/busybox.asc of=/system/bin/busybox 
3. chmod 4755 /system/bin/busybox 
4. cd /system/bin/ 
5. busybox cp -s busybox cp 
6. busybox sh




Login:

If you've read the previous posts, you should have Busybox running on the phone. That means a proper shell (Ash), and plenty of Unix utilities to play with. Good.
But that's still not quite what we are looking for. We'd like to be able to store our aliases in a 
.profile startup file. We'd like to add our own stuff to the startup process. We'd like to feel at $HOME on our Android.

So we're going to do just that ! But as we've seen already, Android is not built to do that out of the box : no/etc/passwd, no $HOME, and a strange startup script. Let's have a look.

Passwd and Group

First thing : we should add a passwd and a group file in /etc. The problem, as you might have noticed, is that etc is not in your ramdisk directory. It is not in ramdisk.img, but rather in system.img. Actually, /etc is just a symlink to /system/etc(talk about crazy file system hierarchy !). Since modifying system.img is a bit more difficult than building a cpio archive, we too are going to play the symlink game.

Let's put our files somewhere (I've chosen /usr/share), and symlink to them from /etc.

cd my_ramdisk_dir mkdir -p usr/share cd usr/share echo root::0:0:root:/home:/bin/ash > passwd echo root::0: > group cd ../.. find usr >> ramdisk_list

Modifying the Startup Script

In order to make all our symlinks, we have to modify the startup script. This script is called init.rc, and is part of the ramdisk. Let's edit this init.rc file. The % … % comments are mine, and I'll show you the context of my edits, so you can patch :

% Let's add a tmp and home directory. Home should be in a "permanent" storage place, in /data. /tmp should not. % # Backward compatibility symlink /system/etc /etc symlink /data/local /home symlink /cache /tmp % Modify these mount commands to have everything in rw, not ro % mount rootfs rootfs / rw remount mount yaffs2 mtd@system /system rw remount % Add this before the "on boot" block. This creates the symlinks % # add special persistent config files symlink /usr/share/passwd /system/etc/passwd symlink /usr/share/group /system/etc/group

An finally, let's create our own rc startup script, to be run at the end of all other scripts. At the end of the init.rc file, add this line :

service rc /bin/rc

Profiler

Android startup shell comes with some global variables that should be carried over to our shell. We should also configure$PATH. So we are going to create a profile file in /etc. In your ramdisk dir, in usr/share, create a file named profile with this content :

export ANDROID_ROOT=/system export LD_LIBRARY_PATH=/system/lib export PATH=/bin:/sbin:/system/sbin:/system/bin:/system/xbin export BOOTCLASSPATH=/system/framework/core.jar:/system/framework/ext.jar:/system/framework/framework.jar:/system/framework/android.policy.jar:/system/framework/services.jar export ANDROID_BOOTLOGO=1 export ANDROID_ASSETS=/system/app export EXTERNAL_STORAGE=/sdcard export ANDROID_DATA=/data export ANDROID_PROPERTY_WORKSPACE=9,32768

Only PATH is important here. All the other variables were already set up in the Android shell (you can check by typing setafter connecting with adb shell). I've found that the network does not work if ANDROID_PROPERTY_WORKSPACE is not set up properly. Check that the number I give is the same as the one you have.
Then add a line in 
init.rc to create the symlink. And add usr/share/profile to ramdisk_list.

You will also be able to create your own .profile file in your $HOME directory on Android. You can strore your aliases and variables there, since /home has been symlinked to a /data subdirectory, and is persistent across reboots.

Testing

You can now rebuild the mydisk.img ramdisk, using cpio. Then start the emulator with this ramdisk. Log in with adb shell. If everything went fine, you should be able to login using /bin/login. The username is root, no password (you can change your /etc/passwd file if you want one).

Voila ! a real login shell, with properly set up variables and a $HOME to live in.





The Six Million Dollar LibC

AndroidToday, Gentle Reader, we will examine the Bionic library, a slim libc developed by Google for use in the Android mobile software platform. Bionic is clearly tailored for supporting the Android system, but it is interesting to see what might be done with it in other embedded system contexts.

Google's stated goals for Bionic include:

  1. BSD license: Android uses a Linux kernel, but they wanted to keep the GPL and LGPL out of user space.
  2. Small size: glibc is very large, and though uClibC is considerably smaller it is encumbered by the LGPL.
  3. Speed: designed for CPUs at relatively low clock frequencies, Bionic needs to be fast. In practice this seems to drive the decisions of what to leave out, rather than any special Google pixie dust to make code go fast.

In this article we'll delve into the Bionic libc via source inspection, retrieved from the git repository in October 2008. The library is written to support ARM CPUs, though some x86 support is also present. There is no support for other CPU architectures, which makes it a bit inconvenient as all of my current systems are PowerPC or MIPS. Nonetheless I'll concede that for the mobile phone market which Bionic targets, ARM is the only architecture which matters.

As one might expect for a BSD-licensed libc, a significant amount of code is sourced from OpenBSDNetBSD, and FreeBSD. Additional BSD-licensed bits come from Sun and public domain code like the time zone package. There is also a significant amount of new code written by Google, particularly in the pthread implementation.


 
C++ support

So what is different about the Bionic libc versus glibc? The most striking differences are in the C++ support, as detailed in the CAVEATS file:

  • The Bionic libc routines do not handle C++ exceptions. They neither throw exceptions themselves, nor will they pass exceptions from a called function back through to their caller. So for example, if the cmp() routine passed to qsort() throws an exception the caller of qsort() will not see it.
     
    Support for C++ exceptions adds significant overhead to function calls, even just to pass thrown exceptions back to the caller. As Android's primary programming language is Java, which handles exceptions entirely within the runtime package, the designers chose to omit the lower level exception support. C++ code can still use exceptions internally, so long as they do not cross a libc routine. In practice, it would be difficult to actually guarantee that exceptions never try to transit a library routine.
  • There is no C++ Standard Template Library included. Developers are free supply their own, such as the free SGI implementation.

Lack of exceptions is obviously a big deal for C++ programmers, but nonetheless we'll push on.


 
libpthread

The pthread implementation appears to be completely new and developed by Google specifically for Android. It is, quite deliberately, not a complete implementation of POSIX pthreads. It implements those features necessary to support threads in the Dalvik JVM, and only selectively thereafter.

In other embedded Linux environments, the pthread library is crucial. There are a large number of developers in this space from a vxWorks background, to whom threads are simply the way software should be written. So we'll spend a bit more time delving into libpthread.

  • Mutexes, rwlocks, condvars, etc are all implemented using kernel futexes, which makes the user space implementation impressively simple. It seems a little too simple actually, I intend to spend a bit more time studying the implementation and Ulrich Drepper's futex whitepaper.
  • There is no pthread_cancel(). Threads can exit, but can not be killed by another thread.
  • There is no pthread_atfork(). This routine is useful if you're going to fork from a threaded process, allowing cleanups of resources which should not be held in the child. I've mostly seen pthread_atfork() used to deal with mutex locking issues, and need to study how the use of futexes affects fork().
  • Thread local storage is implemented, with up to 64 keys handled. Android reserves several of these for its own use: the per-thread id and errno, as well as two variables related to OpenGL whose function I do not understand. Interestingly the ARM implementation places the TLS map at the magic address 0xffff0ff0 in all processes. This technique is presumably part of the Google performance enhancing pixie dust.
  • POSIX realtime thread extensions like pthread_attr_{set,get}inheritsched and pthread_attr_{set,get}scope are not implemented. Frankly I've never worked on a system which did implement these APIs and am completely unfamiliar with them, so I don't find their omission surprising.

I haven't drawn a final conclusion of the Bionic pthread implementation yet. It is pleasingly simple, but lack of pthread_atfork() is troublesome and use of a magic address for the TLS map may make porting to other architectures more difficult. I need to get this puppy running on a PowerPC system and see how well it works.


 
Miscellaneous notes

In the course of digging through the library I generated a number of other notes, which don't really clump into categories. So I'm simply going to dump it all upon the Gentle Reader, in hopes that some of it is useful.

  • The README says there is no libm, though the source for libm is present with a large number of math routines. I need to investigate further whether it really works, or whether the README is out of date.
  • There is no wchar_t and no LOCALE support. I think this is fine: wchar_t is an idea whose time has come... and gone. The world has moved on to Unicode with its various fixed and variable width encodings, which the wide character type is not particularly useful for. 
    I've used ICU in recent projects for internationalization support, and this is also what Google suggests in the README for Bionic.
  • There is a shared memory region of configuration properties. For example, DNS settings are stored in shared memory and not /etc/resolv.conf. The Android API also makes this shared memory configuration store available to applications via property_get() and property_set().
  • As one might expect, the stdio/stdlib/string/unistd implementation comes from OpenBSDNetBSD, and FreeBSD with minimal changes. The only change I noticed was to remove the LOCALE support from strtod() (i.e., is the decimal point a period or a comma? In the Bionic library it is always a period).
  • There is no openlog() or syslog() implementation. There is a __libc_android_log_print() routine, to support Android's own logging mechanism.
  • Bionic uses Doug Lea's malloc, dlmalloc. Bionic also provides a hash table to track allocations looking for leaks, in malloc_leak.c.
  • There is no pty support that I can find, and no openpty(). There are reports of people starting an SSH daemon on a jailbroken Android device, so presumably there is some pseudo-terminal implementation which I've missed.
  • There are no asynchronous AIO routines like aio_read() or aio_write().
  • Bionic contains an MD5 and SHA1 implementation, but no crypt(). Android uses OpenSSL for any cryptographic needs.
  • Android dispenses with most file-based Unix administration. Bionic does not implement getfsent, because there is no /etc/fstab. Somewhat incongruously there is a /var/run/utmp, and so getutent() is implemented.
  • Android implements its own account management, and does not use /etc/passwd. There is no getpwent(), and getpwnam()/getpwuid() are implemented as wrappers around an Android ID service. At present, the Android ID service consists of 25 hard-coded accounts in <android_filesystem_config.h>
  • Bionic isn't finished. getprotobyname(), for example, will simply print "FIX ME! implement getprotobyname() __FILE__:__LINE__"
  • There is no termios support (good riddance).

 
Conclusion

Bionic is certainly interesting, and pleasingly small. It also represents a philosophical outlook of keeping the GPL some distance away from the application code.

Bionic is a BSD-based libc with support for Linux system calls and interfaces. If the lack of C++ exceptions or other limitations prove untenable, the syscall and pthread mutex implementation could be repurposed into the heavier FreeBSD/NetBSD/OpenBSD libc, though handling thread cancellation using the Bionic mutexes could require additional work.


 
Postscript

If you don't understand the reference in the title of this article, don't fret: you have simply not watched enough bad 1970's American television.

Update: In the comments, Ahmed Darwish points out another Android-related article discussing the kernel and power management interfaces Google added.

Update2: Embedded Alley is working on a MIPS port of the Android software.

Update3: In the comments Shuhrat Dehkanov points out an interview with David Turner, who works at Google on the Bionic implementation. Shuhrat also notes that you might have to log in to Google Groups to see the attachment. "Here is an overview by David Turner (though non-official) which answers some of the questions/unclear parts in your article."



Posted by kevino
,
Introduction Android [펌] Android   

2009/06/23 11:37

복사http://blog.naver.com/free2824/60071631321


안드로이드에서 사용하는 언어는 자바이지만 SUN의 자바와 API와 버추얼머신이 다르다. 
Dalvik 이라는 회사의 버추얼머신이 있었는데 구글에서 회사를 통째로 사들였다고 한다. 이때문에 안드로이드는 SUN의 라이센스로부터 자유롭다. 



안드로이드 플랫폼은 크게 네 부분으로 나뉜다. 커널부분, 하드웨어추상레이어, 라이브러리, 응용프로그램 프레임워크. 라이브러리들은 C/C++로 구현이 되어 있다. 기존의 여러 프로젝트 들을 통합하였기 때문에 C로 구현된 것들이 대부분이고 C++도 있다. 응용프로그램 프레임워크는 자바로 구현되어 있다. 프레임워크와 라이브러리 사이에는 자바와 C 사이의 서로다른 호출 규약등을 맵핑하는 JNI라는 마셜러가 존재한다. 하드웨어 드라이버를 C로 만들면 JNI를 구현해야 한다. 이를 위한 구글 가이드가 있고 샘플도 공개되어 있다. 그리고 SDK를 생성하여 응용프로그램 개발자에게 전달하면 된다. 하드웨어 부분은 구글에서 표준으로 정해두었기 때문에 따로 만질 필요가 없다. 추상레이어도 스펙이 다 되어있어 응용프로그램을 개발할 때는 API로 보이게 된다. 
 기존 임베디드리눅스와 안드로이드의 차이점중 한가지는 장치드라이버들( 그래픽, 오디오, 카메라 등 )이 커널영역이 아닌 유저모드에서 동작한다. 유저모드로 동작 시키면 자신에게 할당되어 있는 번지에만 접근할 수 있기 때문에 조금 더 안전하지만 하드에어 제어시에는 MMU등을 참조하는 등의 추가적인 작업이 필요하기 때문에 조금 불편할 수 있다. 이렇게 드라이버들을 유저영역에 넣은 이유는 라이센스문제, 안정성, 문서화의 편리성( 커널버전이 업데이트 될 때마다 드라이버에 대한 문서를 갱신할 필요가 없다 ), 플러그인 방식으로 드라이버 배포가 가능한점이 있다. 안드로이드에서는 기존 리눅스의 라이브러리로 만든 것들은 동작하지 않는다고 보면 된다. 같은 이름의 라이브러리라 할지라도 안드로이드의 라이브러리들은 스마트폰에 탑재하는 것을 기준으로 불필요한 코드들을 제거하고 최적화를 해두었기 때문이다. POSIX Thread 관련 라이브러리를 예로 들면 create, join 등의 필수 함수를 제외한 나머지함수는 모두 제거되어있다. 




Android Kernel

왜 안드로이드는 리눅스 커널 기반일까. 생각하기 나름이겠지만 우선 오픈소스이고 안전하게 입증된 드라이버 모델(well abstracted )이 적용되어 있고, 메모리 프로세스 관리 모델을 제공하고, 하드웨어와 입출력에 대한 보안모델을 제공하고, 공유라이브러리를 지원하는 등 비용과 시간이 적게 드는 이유가 한몫 한것 같다. 

현재 커널 안정화버전은 2.6.27 이다. 구글에서 순수 리눅스 커널을 가져다가 안드로이드 용으로 패치한 것이다. 기존의 리눅스와는 다르게 GLIBC를 지원하지 않고 EABI( Embedded Arm Binary Interface?)와 Binder를 사용한다. 그리고 커널 기능 향상을 위해 Alarm, Ashamem(공유메모리), Low memory-killer, debugger, logger 컴포넌트가 추가되었다. 

유저모드는 허가된 자원에만 접근이 가능하고 프로그램의 안정성을 높일 수 있지만 하드웨어 효율성은 떨어질 수 있다. 반대로 커널모드는 하드웨어 효율성은 높지만 안정성은 떨어질 수 있다. 안드로이드는 기본 드라이버들을 제외한 나머지 드라이버들은 유저스페이스에서 동작한다. 일반 PC는 사람의 생명을 빼았지는 않지만, 심장박동 컨트롤러, 핸드폰만 가지고 조난 당했을 경우와 같이 스마트폰을 모델로 하면 생명과 연결될 수 있기 때문에 안정성이 속도나 효율보다 더 중요하다. 
 
이전에는 일반적으로 일반 gcc를 썼지만 최근의 리눅스 커널을 빌드할 경우에는 ARM사에서 표준으로 정해둔 ABI( arm binary interface ) 규격의 컴파일러를 사용한다. 현재 안드로이드는 EABI( Extended??..) 기능을 지원한다. 일반 컴파일러에서 빌드한 것을 EABI에서 실행할 수 없기 때문에 EABI 컴파일러로 다시 빌드해야 한다. 최근의 임베디드 컴파일러는 대부분 EABI컴파일러 이다. 실수 연산방식에 있어서 하드플로팅포인트와 소프트웨어 플로팅포인트를 혼합하여 빌드할 수 있다. 기존의 ABI는 빌드옵션에서 VFP(Vector Floating Point)를 선택하거나 해제할 수 있었는데 이는 환경이 달라지면 다시 빌드 해야하는 단점이 있었다. EABI는 혼용이 되기 때문에 빌드의 부담이 줄어든다. 또한 구조체 팩킹이 편해졌고 호환성이 증가하였다. 그리고 syscall 규약에 변경사항이 있다. 이전에는 전달인자 4개까지는 레지스터를 쓰고 5개부터는 스택을 사용했는데 레지스터를 r0, r1, r2, r4 처럼 연속된 순서로 했었다.  EABI는 레지스터 간격이 달라지는등 호출 규약이 달라졌다. 

Kernel Enhancement

기존의 임베디드 리눅스에 없던 안드로이드만의 향상된 기능에는 알람, 로우메모리킬러, 공유메모리드라이버, 커널디버거, 바인더, 파워매니지먼트, 로거가 있다. 결국 포팅 이슈는 이것들과 관련될 것이다. 스마트폰으로 만들다 보니까 알람이 기본적으로 제공되어야 한다. 포팅 시 이 기능을 사용하고 싶지 않다면 다른기능과 맞물려 있기 때문에 확인해보고 작업을 진행해야 한다. 공유메모리드라이버는 안드로이드에서 커스터마이징을 했고 메모리 할당이 필요하면 전부 ashmem에 있는 라이브러리를 이용한다. 
리눅스에서는 각 프로세스마다 우선순위를 주고 메모리가 부족하면 우선순위가 낮은 것을 없앤다. 안드로이드는 프로세스마다 우선순위를 주지 않고 그룹마다 우선순위를 준다. 그 이유는 바인더 때문이다.  메모리 부족 시 우선순위가 낮은 그룹을 제거한다. 안드로이드에는 프로그램 종료 기능이 없다. 화면은 내릴 수 있지만 알아서 프로그램이 제거되기 때문이다. 자바로 응용프로그램을 만들기 때문에 가비지컬렉터가 있다. 종료버튼이 있다 하더라도 UI가 없어질 뿐 그 자체가 바로 종료되는 것은 아니다. 
이중 가장 중요한 것은 바인더라고 할 수 있다. 바인더에 의해 안드로이드와 기존 리눅스의 차이가 생긴다. 커널버전 2.6.30이상부터는 커널과 안드로이드가 통합된다는 말이 있는데 2.6.29이전의 커널은 바인더폴트( 메모리 회수에 문제가 있는 버그)가 있었다. 그럼 기존에 나왔던 안드로이드폰들도 이 버그가 있었을까? 아마도 개발인력이 많기 때문에 자체적으로 해결했을 것 같다. 바인더 서비스를 넣으면 기존의 전통적인 커널구조가 객체지향 구조로 바뀐다. 컴포넌트 중심으로 양쪽간 메시지를 주고받는 구조로 바뀐다는 말이다. 이것의 장점은 한쪽이 잘못 되어도 반대쪽까지 잘못되지는 않는다는 점. 응답을 못받거나 결과만 이상하게 나올 뿐이다. 
전원관리기능은 기존의 리눅스가 가지고 있는 3단계에 2개를 더해 5단계로 이루어진다. 안드로이드 커널을 설정할때는 자신의 하드웨어에 전원관리 모듈이 없어도 반드시 포함시켜야 한다. 포팅을 하게 되면 시간이 지날수록 이것들에 집중해야 할 것이다. 

Binder


바인더는 프로그램과 데이터를 공유하기 위한 것이다. 기존의 IPC는 보안이슈와 오버헤드이슈가 있다. 리눅스에서도 오픈바인더를 쓸 수 있지만 안드로이드에서 더 활성화를 시켜 두었다. 2.6.29에 기존 버그들이 완벽하게 패치되었다. 이전의 방식은 커널을 통해서 데이터를 공유하였다.(커널의 공유메모리 영역에 데이터를 올려두고 시그널등의 이벤트를 받아 메시지 큐 등을 써서 - 세마포어, 뮤텍스, 스레드 등 ). 바인더는 커널쪽의 메인호스팅이 없고 바인드라는 서비스가 있는 것이다. 바인드를 호출하면 응용프로그램과 디바이스쪽에 바인드서비스가 붙어 서로 통신하게 된다. 바인드서비스는 커널이 아니다. 서로다른 서비스간, 응용프로그램간 데이터를 주고받을 때 동작하게 된다. 여기서의 단점은, 기존의 방식은 하나의 매개체가 있고 공유해서 썼지만 바인드는 각각의 서비스마다 바인더가 있어야 하기 때문에 메모리 낭비가 되는 측면이 있다. 그럼에도 불구하고 쓰는 이유는 바인더는 각각 별개로 동작하기 때문에 주고 받는 통신을 가로챔 당할 가능성이 더 낮아지므로 보안성이 더 오르기 때문이다. 메모리 낭비를 줄이기 위해 바인더를 230kb정도의 크기로 최소화 시켰다. 바인더는 원래 PalmOS에 있던 것이기 때문에 라이센스가 있다. 약 3000라인정도 된다. 
바인더는 스레드 풀을 유지한다. 드라이버, 매니저 서비스마다 바인더가 양쪽에 붙게 되는데 풀로 관리한다는 것은 요구가 있기 전에 미리 자료구조화 시켜 자원을 확보해 두고 바로 맵핑해서 쓸 수 있도록, 바인드 하는데 시간이 걸리지 않도록 되어 있다.  응용 A가 B 디바이스드라이버와 통신을 하게 되면 채널이 생성되는데 만약 채널안에 연결되는 프로그램이 A 이외에 C도 존재 한다면 B가 종료되었다고 해서 바인더가 종료되면 안된다. 이를 위해 참조계수가 있어서 참조계수가 0이 되면 바인드서비스를 해제한다. 

Low Memory Killer
리소스가 부족할 때 자동으로 실행된다. 안드로이드는 그룹 당 우선순위를 주어 해당되는 그룹을 한번에 해제한다. 그룹은 참조계수랑 연관이 있다.  ( 아마도 참조계수가 0 인 것들이 먼저 해제 될듯. ) 
아래 그림은 Low Memory Killer 소스의 일부분이다. 프로세스가 실행되면 프로세스테이블에 등록되어 관리가 된다. 메모리 부족현상이 생기면 shirink 함수가 실행되어 링크드리스트로 되어있는 프로세스컨트롤 블록들을 끝까지 탐색한다. 제거되어야 할 프로세스가 있으면 SIGKILL을 전송한다. 


Power Management 
기존 리눅스드라이버의 파워매니저에 계층을 하나 더 올렸다. 보통 핸드폰은 5단계를 사용한다. 키보드-액정-CPU 순으로 전원이 차단되면서 제일 마지막은 D램에만 전원을 공급하는 상태가 된다. 전원은 CPU가 아닌 PMIC라는 전원공급칩이 제어를 한다. D램에만 전원이 공급되는 상태라도 터치스크린은 잠기지 않는다. 이 상태에서 발생하는 인터럽트도 PMIC가 관리한다. 

Native Libraries

기존의 라이브러리를 그대로 사용하지 않고 EABI로 빌드된 라이브러리이다. 기존의 리눅스는 PC가 모태이기 때문에, 스마트 디바이스환경을 위해 만들어진 것이 아니기 때문에 arm또는 스마트디바이스에 최적화 되어 있지 않다. 바인더가 있고 자바의 JNI를 통해 C코드와 연결되기 때문에 필수적으로 사용되는 C라이브러리 사이즈를 줄이고 효율을 더 좋게 하였다. 안드로이드의 네이티브 라이브러리는 Bionic Lib이라고 부른다. 임베디드 리눅스쪽 라이브러리를 안드로이드로 가져오면 동작하지 않는다. 대부분이 BSD 라이센스기 때문에 코드공개의 의무가 없다. 그리고 프로세스마다 로드 되므로 작은 사이즈( libc.so 사이즈 231Kb )로 되어 있고 경량 pthread가 구현되어 있다. 모든 Native 코드는 bionic과 함께 컴파일 되어야 한다. 웹킷은 오픈소스 브라우저 기반이다. 애플의 사파리, 노키아의 심비안에 이미 적용되어 성능은 검증되어 있다. 브라우저 속도가 아주 빠른것이 특징이다. HTML 표준을 따르고 Active X는 지원하지 않는다. 미디어프레임워크는 PocketVideo OpenCORE 플랫폼 기반이다. 동영상 디코딩을 하며 표준 Video, Audio, Still-frame 포맷을 지원한다. 이를 이용해 상용제품을 양산할 경우 코덱 라이센스에 대한 비용이 발생할 수 있다. SQLite 는 기본 데이터 베이스이다. Mysql과 거의 유사하다. 위치기반 서비스등을 할 때 유용하게 쓰일 수 있다. 
Surface Manager는 모든 응용프로그램의 surface rendering을 프레임버퍼로 전달한다. 프레임버퍼는 LCD와 CPU속도에 차이가 있기 때문에  DRAM 또는 SRAM에 똑같은 구조를 만들어 두고 메모리 블록 전체를 복사해서 한번에 LCD에 출력한다. 이 때 그 메모리 공간을 프레임버퍼라고 한다. 기존의 임베디드리눅스는 2D, 3D를 따로 처리했지만 이 경우에는 동시에 2D, 3D를 처리한다. 화면 합성이나 결합, 반투명 효과등을 한번에 처리할 수 있다. 2D는 단일버퍼로 충분하지만 3D는 데이터량이 많아 단일버퍼로는 병목현상이 생길 수 있기 때문에 프레임버퍼를 더블프레임을 쓴다.  기존의 버퍼 사이즈를 두배로 늘려주면 된다. 더블버퍼링을 2D에도 적용하면 전경그림과 배경그림을 별도로 관리할 수 있어 오버헤드가 줄어든다. 

Audio Manager는 오디오 처리를 한다. 오디로 출력 라우팅 기능이 구현되어 있다. 이전에는 OSS를 사용했는데 안드로이드에서 제대로 동작하지 않기 때문에 ALSA를 써야한다. 기본적으로 ALSA는 디폴트 볼륨이 0 으로 설정되어 있기 때문에 테스트를 하기 위해서는 init 부분에서 볼륨설정을 먼저 해줘야 한다. 

Android Runtime
 

SUN의 자바는 명령들이 전부 8비트 길이를 가지지만 안드로이드는 4바이트이다. 기존의 SUN은 명령어가 스택에 들어가기 때문에 PUSH,POP명령어를 쓰고 Dalvik은 뱅크드레지스터를 이용한 복사명령을 이용하고 레지스터에서 바로 실행시키기 때문에 속도가 더 빠르다. 4바이트가 레지스터에 전부 들어가기 때문에 낮은사양에서도 느려지지 않는 효과도 있다. 프로그램동작은 자바코드이고 드라이버들은 대부분 C/C++이지만 그 사이에 JNI가 있기때문에 동작이 가능하다. JNI는 자바코드에서 C나 C++  라이브러리를 호출할 수 있도록 만들어진 규약이다. 안드로이드에서 응용프로그램은 C/C++로도 만들 수 있다. 대신 UI를 가지기는 힘들다. 백그라운드 서비스를 제작할 경우 굳이 자바로 할 필요는 없다.

HAL ( Hardware Abstraction Layer )

예전에는 하드웨어 드라이버를 하드웨어 제작자가 만들었지만 요즘은 추상계층을 두어 상위 드라이버나 하위 네이티브 드라이버를 서로 독립적으로 개발할 수 있고 응용프로그램도 독립적으로 동작할 수 있다. 이는 일관된 함수 이름과 형식이 있기때문에 가능하다. 개발자가 구현하기 쉽게 표준화된 API들이 존재하며 모든 제조사가 자신의 컴포넌트를 안드로이드 플랫폼에 넣을 수 있도록 구성되었다. HAL은 라이센스문제를 피하고 안정성을 위해 유저스페이스에 존재한다. 

Application Framework
액 티비티 매니저는 응용프로그램의 생명주기를 담당한다. 패키지 매니저는 시스템에서 동작중인 응용프로그램들의 정보를 담당한다. 윈도우 매니저는 모든 응용프로그램과 관련된 화면을 담당한다. 뷰 시스템은 표준 위젯을 담당한다. 처음 바탕화면이 위젯이다. 윈도우는 dll 파일이 많지만 안드로이드는 하나의 패키지 파일로 되어있어 프로그램 배포가 쉽다. 

Bootup Sequence

리눅스는 기본적으로 init이 가장먼저 실행된다. init.rc 라는 이름의 파일에는 init이 해야할 작업들이 기록되어 있다. 파일시스템 마운팅, 폴더 권한설정, 캐시폴더 삭제, 시작프로그램 동작 등이 기록되어 있다. 우선 데몬을 올린다. 데몬은 init에 의해 리눅스와 같이 시작되었다가 리눅스가 종료될 때 없어지는 프로그램으로서 데몬을 작성하는 규격에 따라 만들어져야 한다. Zygote가 Dalvik을 초기화 한다. C 밑에 있는 기본라이브러리들은 런타임을 통해 실행되고 상위 서비스들은 Dalvik을 통해 실행된다. 이러한 과정들을 위한 설정은 해당하는 config 파일을 수정하면 된다. 어떤 동작들을 바꾸고 싶으면 기본적으로 init.rc를 바꾸면 되고 Zygote를 바꾸고 싶으면 그 설정파일을 바꾸면 된다. 그리고 시스템서버, 서페이스매니저, 오디오매니저들이 올라간다. 그 다음에는 시스템 서비스들이 활성화 된다. 이들은 서비스이므로 서비스매니저에 등록된다. 

Bootup Sequence - Zygote
Zygote가 실행되면 시스템 서비스가 활성화 된다. 응용프로그램에서는 android.process.* 을 가지고 접근할 수있다. Zygote와 시스템서버간에는 IPC 소켓으로( 127.0.0.x ) 통신을 한다. 

< 부팅 완료 후 각 프로세스들의 상태 >
Android Internals Reference
http://code.google.com/intl/ko/android/
http://groups.google.com/group/android-internals
http://www.android-internals.org/
http://groups.google.com/groups/profile?enc_user=_EKOshMAAADzFnauhYxa0ga8JtF8CI5fWMj6vob75xS36mXc24h6ww
http://groups.google.com/groups/profile?enc_user=lYDbNxEAAAD8uJiqPP7Wd-bc9b1O3waCkdEasx1kiYTQavV7mdW13Q
Posted by kevino
,

[First written by Steve Guo, please keep the mark if forwarding.]

In this topic you will learn some information about Android process management. First let’s take a look at the launched processes during Android booting.

USER PID PPID VSIZE RSS WCHAN PC NAME

root 1 0 264 176 c00acc6c 0000c36c S /init

root 28 1 724 308 c0051354 afe0c4cc S /system/bin/sh

system 30 1 796 248 c026516c afe0b74c S /system/bin/servicemanager

root 31 1 1824 316 ffffffff afe0b50c S /system/bin/mountd

root 32 1 652 248 c02976e0 afe0c0bc S /system/bin/debuggerd

radio 33 1 5344 664 ffffffff afe0bdbc S /system/bin/rild

root 34 1 71028 18828 c00ad308 afe0b874 S zygote

media 37 1 16812 3456 ffffffff afe0b74c S /system/bin/mediaserver

root 39 1 788 288 c02f9ae4 afe0b50c S /system/bin/installd

system 86 34 187756 21836 ffffffff afe0b74c S system_server

radio 118 34 103476 13896 ffffffff afe0c824 S com.android.phone

app_4 124 34 117848 19248 ffffffff afe0c824 S android.process.acore

app_5 139 34 98672 11516 ffffffff afe0c824 S com.android.mms

app_3 151 34 92096 10976 ffffffff afe0c824 S com.android.alarmclock

app_6 161 34 94436 12616 ffffffff afe0c824 S com.android.calendar

app_9 173 34 93248 11728 ffffffff afe0c824 S android.process.media

app_15 182 34 91848 9764 ffffffff afe0c824 S com.android.voicedialer

app_16 190 34 94524 10812 ffffffff afe0c824 S android.process.im

They can be divided into three kinds.

Root Process

init is the first process after kernel booting. The major task it performs:

l Parser and execute init.rc and init.%hardware%.rc

l Automatically generate device node under /dev

l Start log and property service

l Monitor for device, property set and child process exit events

Native Application Process

According to init.rc, init will fork the following native application process.

console : star a shell.

servicemanager : start binder IPC service manager.

mountd : mount all fs defined in /system/etc/mountd.conf if started, receive commands through local socket to mount any fs.

debuggerd : start debug system.

rild : start radio interface layer daemon.

zygote : start Android Java VM Runtime and start system server. It’s the most important process.

mediaserver : start AudioFlinger, MediaPlayerService and CameraService.

installd : start install package daemon.

JAVA Application Process

Every JAVA application process is forked from zygote process. system_server is a special JAVA process, which is directly forked from zygote.. Other JAVA process is created from ActivityManagerService(run in system_server process) like this.

int pid = Process.start("android.app.ActivityThread",

mSimpleProcessManagement ? app.processName : null, uid, uid,

gids, ((app.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) != 0), null);

While Process.java use UNIX domain socket to communicate with zygote. So the overall picture is shown as following.

clip_image002

System Server

It’s the first JAVA application launched by zygote. It starts the core Android services, e.g. ActivityManager, WindowManager, PackageManager etc. It’s the Android core engine.

Persistent Application

During booting, ActivityManagerService.systemReady will start all persistent applications.

List apps = ActivityThread.getPackageManager().

getPersistentApplications(PackageManager.GET_SHARED_LIBRARY_FILES);

if (apps != null) {

int N = apps.size();

int i;

for (i=0; i<N; i++) {

ApplicationInfo info

= (ApplicationInfo)apps.get(i);

if (info != null &&

!info.packageName.equals("android")) {

addAppLocked(info);

}

}

}

Currently only Phone application is registered as a persistent app in AndroidManifest.xml like this.

<application android:name="PhoneApp"

android:persistent="true"

android:label="@string/dialerIconLabel"

android:icon="@drawable/ic_launcher_phone">

So during booting, only phone application is automatically launched. It’s the “com.android.phone” process.

The First Activity

The first activity is launched by senting Intent.CATEGORY_HOME intent from ActivityManagerService.

Intent intent = new Intent(

mTopAction,

mTopData != null ? Uri.parse(mTopData) : null);

intent.setComponent(mTopComponent);

if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {

intent.addCategory(Intent.CATEGORY_HOME );

}

ActivityInfo aInfo =

intent.resolveActivityInfo(mContext.getPackageManager(),

PackageManager.GET_SHARED_LIBRARY_FILES);

if (aInfo != null) {

intent.setComponent(new ComponentName(

aInfo.applicationInfo.packageName, aInfo.name));

// Don't do this if the home app is currently being

// instrumented.

ProcessRecord app = getProcessRecordLocked(aInfo.processName,

aInfo.applicationInfo.uid);

if (app == null || app.instrumentationClass == null) {

intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);

startActivityLocked(null, intent, null, null, 0, aInfo,

null, null, 0, 0, 0, false);

}

}

It’s the “android.process.acore” process. (The process name is defined in AndroidManifest.xml)

Auto-launched Application After Booting

When activity idle is detected in ActivityManagerService, it will broadcast ACTION_BOOT_COMPLETED intent at the first time.

if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {

// Tell anyone interested that we are done booting!

synchronized (this) {

broadcastIntentLocked(null, null,

new Intent(Intent.ACTION_BOOT_COMPLETED , null),

null, null, 0, null, null,

android.Manifest.permission.RECEIVE_BOOT_COMPLETED,

false, false, MY_PID, Process.SYSTEM_UID);

}

}

Currently, MMS, AlarmClock, Calendar, MediaProvider, VoiceDialer and IM have registered as a receiver for ACTION_BOOT_COMPLETED intent in their AndroidManifest.xml. So they will be automatically launched. (This explains the remained JAVA process.)

Email also registers as a receiver for ACTION_BOOT_COMPLETED intent in its AndroidManifest.xml, but it defines android:enable=”false”. So it won’t be launched.

<receiver android:name=".service.BootReceiver"

android:enabled="false"

>

<intent-filter>

<action android:name="android.intent.action.BOOT_COMPLETED" />

</intent-filter>

<intent-filter>

<action android:name="android.intent.action.DEVICE_STORAGE_LOW" />

</intent-filter>

<intent-filter>

<action android:name="android.intent.action.DEVICE_STORAGE_OK" />

</intent-filter>

</receiver>

DownloadProvider also registers as a receiver for ACTION_BOOT_COMPLETED intent in its AndroidManifest.xml, but it defines android:exported=”false”. So it won’t be launched.

<receiver android:name=".DownloadReceiver" android:exported="false" >

<intent-filter>

<action android:name="android.intent.action.BOOT_COMPLETED" />

<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />

</intent-filter>

</receiver>

Behind the JAVA process

system_server is a special case. It calls ActivityThread.java’s systemMain static function, which creates an instance of ActivityThread. ActivityThread then creates an instance of ApplicationThread, Application and ApplicationContext.

Every other JAVA process works in a different way. It’s controlled by system_server while forked by zygote. When any JAVA process other than system_server is forked from zygote, it automatically calls ActivityThread.java’s main static function(See Process.java and the following code snippet).

try {

ZygoteInit.invokeStaticMain(cloader, className, mainArgs);

} catch (RuntimeException ex) {

logAndPrintError (newStderr, "Error starting. ", ex);

}

The ActivityThread.java’s main function creates an instance of ActivityThread. ActivityThread then creates an instance of ApplicationThread. The ApplicationThread will work as an IBinder object to interact with ActivityManagerService in system_server. The new process does nothting at this time other than waiting IPC call from system_server. The Application and ApplicationContext object won’t be created at this time. Actually it’s deferred to when the process really works, eg. start an activity, receive intent or start a service.

For example, when start an activity, ActivityManagerService know which process the to-be-launched activity should run in, so it will RPC call ApplicationThread’s scheduleLaunchActivity to launch a new activity in that process. ApplicationThread then post a message to let ActivityThread know it needs to start an activity. ActivityThread then creates Application and ApplicationContext object. After that, it calls Instrumentation, then Instrumentation finally calls JAVA dalvik VM to really create an activity JAVA object.

Posted by kevino
,