간만의 공개(?) 포스팅...


Android의 java.lang package에 포함되어 있는 Thread에는 resume()suspend() method가 구현되어 있다.

하지만 어느시점부터 deprecated 되어 버렸다.

뭐, 책임 질 수 없으니 필요하면 직접 구현해서 쓰라는 얘기겠지...


그래서 구글링으로 찾아서 사용하고, 정리해 둔다. (오래되어 출처는 잊어버림-0- 출처는 역시나 StackOverflow)


private Object mPauseLock;


@Override

public void run() {

while (!mFinished) {

                //Do something you need!!

synchronized (mPauseLock) {

while (mPaused) {

try {

mPauseLock.wait();

} catch (InterruptedException e) {}

}

}

}

}


/**

 * Pause this thread

 */

public void onPause() {

synchronized(mPauseLock) {

mPaused = true;

}

}


/**

 * Resume this thread

 */

public void onResume() {

synchronized(mPauseLock) {

mPaused = false;

mPauseLock.notifyAll();

}

}


Posted by 세월의돌
Posted by 세월의돌
리눅스 & 안드로이드2012. 3. 17. 13:24
adb shell로 target 또는 emulator의 shell을 실행 한 다음, shell에서 실행할 수 있는 바이너리를 생성할 필요가 있다.
이러한 경우 아래와 같이 Makefile을 만들어 컴파일 할 수 있다. (단, android 전체 소스가 빌드되어 있어야 함)

NDK_PATH = /home/user/android-ndk-r7b

NDK_ARCH = $(NDK_PATH)/platforms/android-14/arch-arm

SRC_ROOT = .

REF_ROOT = /home/user/source/android/out/target/product/generic/obj/

CC  = $(NDK_PATH)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86/bin/arm-linux-androideabi-gcc

CFLAGS  = -I$(REF_ROOT)/KERNEL_OBJ/usr/include -I$(NDK_ARCH)/usr/include/

LDFLAGS = -Wl,-rpath-link=$(REF_ROOT)/lib -L$(REF_ROOT)/lib -nostdlib $(REF_ROOT)/lib/crtbegin_dynamic.o -lc


all:

$(CC) -o abinary abinary.c $(CFLAGS) $(LDFLAGS)



Posted by 세월의돌
리눅스 & 안드로이드2012. 2. 24. 13:52
* 우선 안드로이드 소스를 빌드하기 위해서는 아래의 명령을 android 디렉토리에서 실행한다.

$ source build/envsetup.sh



* 특정 package만 빌드 하고자 할 경우

$ mmm packages/apps/AlarmClock



* 변경된 package를 포함하는 system.img를 생성하는 명령어

$ make snod



* SDK를 생성 하고자 할 경우

$ make sdk


* 특정 framework java library 만 빌드하는 경우 ex) framework.jar

$ cd framework/base

$ mm


Posted by 세월의돌
리눅스 & 안드로이드2012. 2. 24. 13:47
Android framework source를 빌드 하다가 다음과 같은 에러메시지를 만났다.

Error occurred during initialization of VM

Could not reserve enough space for object heap


구글링 해 보니, JVM을 실행할 때, 가용 메모리보다 더 큰 메모리 설정을 가지고 실행할 때 나타난다고 한다.
인터넷에는 보통 -Xms256m -Xmx512m 옵션을 직접 주는 방법들이 나와 있어서 JAVA_OPTS 환경변수를 이용해서 설정 해 보려고 했는데 잘 되지 않았다.

그래서 안드로이드 makefile 들을 뒤져보다, definitions.mk 파일에서 위의 옵션을 설정하는 부분을 발견했다.

codeaurora에 있는 ICS소스의 definitions.mk 파일의 내용중 아래가 해당 부분이다.

1519 #TODO: use a smaller -Xmx value for most libraries;

1520 #      only core.jar and framework.jar need a heap this big.

1521 # Avoid the memory arguments on Windows, dx fails to load for some reason with them.

1522 define transform-classes.jar-to-dex

1523 @echo "target Dex: $(PRIVATE_MODULE)"

1524 @mkdir -p $(dir $@)

1525 $(hide) $(DX) \

1526     $(if $(findstring windows,$(HOST_OS)),,-JXms16M -JXmx1536M) \

1527     --dex --output=$@ \

1528     $(incremental_dex) \

1529     $(if $(NO_OPTIMIZE_DX), \

1530         --no-optimize) \

1531     $(if $(GENERATE_DEX_DEBUG), \

1532         --debug --verbose \

1533         --dump-to=$(@:.dex=.lst) \

1534         --dump-width=1000) \

1535     $(PRIVATE_DX_FLAGS) \

1536     $<

1537 endef


1526번 줄에 표시된 부분을 수정하면 (수치를 낮추면) 문제가 해결된다.
다른 방법이 있을지도 모르겠는데, 우선은 임시방편으로 해결 가능하다.

Posted by 세월의돌
리눅스 & 안드로이드2012. 2. 15. 08:05
repo script를 사용하면 여려개의 git으로 구성된 repository를 한 번에 처리할 수 있어서 편리하다.
하지만, 굳이 모든 git들이 필요하지 않다면 저장공간 낭비 뿐만 아니라, repo sync 시 시간이 오래 걸리기도 한다.
그런데 gerrit review system과 함께 사용하려면 어쩔 수 없이 repo upload를 해야 한다고 알 고 있었는데, 그렇다고 하기에는 너무 불편하고 불합리 하다고 생각이 들었다. (그렇게 만들었을 리 없지 않은가!)

결국, 방법은 있었다. 궁하지 않고 찾지 않아 잘 모르고 있었을 뿐...

repo script를 사용하는 git/gerrit 시스템에서 특정 git만 가져온 후, gerrit과 연동 되도록 하는 방법은 다음과 같다.

As-Is:   repo sync -> git commit -> repo upload
To-Be: git clone -> git commit -> git push

방법은, 본인이 clone으로 내려 받은 디렉토리에 생성되는 .git 디렉토리의 내부에 있는 config파일을 수정하는 것이다.

> vi .git/config

 [remote "origin"]

        fetch = +refs/heads/*:refs/remotes/origin/*

        url = ssh://localhost:12345/android/vendor/com/apps/AlarmClock.git

        push = HEAD:refs/for/repository_master   <== 추가


repository_master는 banch name! (용어가 정확한지는 잘 모르겠다)

Posted by 세월의돌
처음 나에게  platform.x509.pem과 platform.pk8 두 개의 파일이 전달 되었다.
그리고는 이 두 개의 파일을 이용해 platform signing을 해야 했는데, 어떻게 해야 하는지 전혀 몰랐다.

구글링을 해 보면, "keystore를 생성해서 해라", "jks 파일을 생성해라" 등등의 내용이 있었지만, 당장 내가 원하는 글들은 아니었다. 그렇게 찾다가 발견한 문서에서 내 상황에 적합한 글을 발견해서 테스트 해보니, 정말 제대로 동작을 하는것이 아닌가! 그래서 여기에 정리한다.

1. 우선 signing이 되지 않은 apk 파일이 필요하므로 이클립스에서 export를 해야 한다.
방법은 해당 프로젝트에서 마우스 오른쪽 버튼을 클릭 > Android Tools > Export Unsinged Application Package를 선택하고, 원하는 경로를 지정하면 apk파일이 출력된다.

2. Android 전체 소스를 빌드하면 생성되는(?) android/out/host/linux-x86/framework/signapk.jar 파일을 작업하고자 하는 시스템으로 복사한다. (예를 들면 linux에서 Windows로 복사)

3.  명령창(Windows의 경우)에서 아래와 같이 입력한 후 실행한다. 단, 경로는 해당 파일들의 위치로 적절히 맞춰 주어야 한다.

java -jar signapk.jar platform.x509.pem platform.pk8 unsigned_app.apk signed_app.apk

 
여기서 unsigned_app.apk 파일은 위의 1번에서 export 한 unsigned apk 이고, signed_app.apk 파일은 signed_app이 저장될 이름을 나타낸다. 즉, unsigned_app.apk 파일을 signing 하여 signed_app.apk라는 파일로 저장한다는 의미.

Posted by 세월의돌
리눅스 & 안드로이드2012. 1. 26. 20:24
한동안 안드로이드 자체와는 약간 멀어져 있었고, 그래서 Ice Cream Sandwich에 대해서도 귀 동냥만 하고 있었다.
그러다가 다시 안드로이드 app.을 개발해야 하는 상황이 되어, 이클립스에서 ICS emulator를 생성하고 실행 해 보려고 하니 제대로 실행이 되지 않았다. 제목과 같이 PANIC: Could not open xxx.ini 라는 메시지를 뿜어내기만 할 뿐...

그래서 구글링을 해보니 경로 관련 문제라는 이야기가 제일 많았다. AVD를 생성하는 경로가 기본적으로 C:\Users\계정\.android\로 설정되기 때문에, 경로상에 한글(계정이름)이 들어 있으면 그럴 수 있다는 내용. 그러나 나는 계정으로 한글을 사용하지 않기 때문에 동일한 문제는 아니었다.

그런데, 개인적으로 "My Documents"를 잘 활용(?) 하기 때문에, 많은 자료들이 해당 폴더에 들어있고, 그래서 포맷을 하게 되면 backup을 해야 하는 불편함이 있었다. 그래서 "My Documents"의 경로를 D드라이브로 변경 해 두는 습관이 생겼다.

이러한 이유로, 혹시나 하는 마음으로 D드라이브를 열어보니, .android 디렉토리에 내가 생성한 AVD 파일과 디렉토리가 생성되어 있었다.

1. 우선은 간단하게, D:\에 있는 .ini파일과 디렉토리를 기본경로로 이동(혹은 복사) 해 주면 문제가 해결된다.(그러나 근본적인 해결책은 아니다)
2. 이것을 해결하기 위해서는, "컴퓨터>속성>고급 시스템 설정>환경변수"에서 ANDROID_SDK_HOME을 추가하고, 원하는 경로를 추가 해 주면 된다. (재부팅이 필요한듯)

Posted by 세월의돌
리눅스 & 안드로이드2011. 12. 22. 17:39
Android App.의 메모리 사용량을 어떻게 측정할 것인가 많이 고민을 했던것 같다.
그리고 지금도 고민하고 있는 듯.

우선 나 자신이 제대로 된 개념이 없기 때문인 것 같다.
그런데 딱히 제대로 된 자료도 없었던 것 같은데...
그동안 못 찾았던 것인지, 없었던 것인지 모르겠지만, 괜찮은 글을 하나 발견했다.
역시나 stack overflow에서 찾아낸 글. (아니 구글이 찾아 줬지;;)

adb shell dumpsys meminfo pid 를 실행하여 출력된 정보 가운데  내가 필요했던 정보는, (Pss) total과 (priv dirty) total 이었다.
(Pss) total은 공유되는 메모리를 포함한 크기이고, (priv dirty)는 다른 프로세스와는 공유할 수 없는 메모리(페이지) 크기라는 것.
여기서 (priv dirty)는 다르게 생각 해 보면, 이 프로세스가 제거되고나면 바로 반환되어 시스템이(또는 다른 프로세스가) 사용할 수 있는 메모리라고 생각 할 수도 있겠다.

여기서 약간 애매모호한 상황이 발생하는데, 어떤 크기를 프로세스(또는 app.)가 사용한다고 생각해야 할 것인가 이다.
공유자원이 메모리에 하나도 로드되지 않은 상태라면, (Pss) 크기 만큼의 메모리가 필요할 것이고, 이미 공유자원이 메모리에 로드되어 단순히 page mapping만 하면 되는 경우에는 (priv dirty) 크기 만큼의 메모리만 있어도 된다는 얘기.

결론적으로는, 항상 최악의 상황을 고려해야 하므로 내가 개발한 app.이 실행되기위한 메모리는 (Pss) 만큼이라고 생각해야 하지 않을까? (잘못 생각하고 있다면, 고수 분들께서 지적해 주시면 감사하겠습니다 ^^; )

Note that memory usage on modern operating systems like Linux is an extremely complicated and difficult to understand area. In fact the chances of you actually correctly interpreting whatever numbers you get is extremely low. (Pretty much every time I look at memory usage numbers with other engineers, there is always a long discussion about what they actually mean that only results in a vague conclusion.)

First thing is to probably read the last part of this article which has some discussion of how memory is managed on Android.

Now ActivityManager.getMemoryInfo() is our highest-level API for looking at overall memory usage. This is mostly there to help an application gauge how close the system is coming to having no more memory for background processes, thus needing to start killing needed processes like services. For pure Java applications, this should be of little use, since the Java heap limit is there in part to avoid one app from being able to stress the system to this point.

Going lower-level, you can use the Debug API to get raw kernel-level information about memory usage.

Note starting with 2.0 there is also an API, ActivityManager.getProcessMemoryInfo, to get this information about another process.

This returns a low-level MemoryInfo structure with all of this data:

/** The proportional set size for dalvik. */
public int dalvikPss;
/** The private dirty pages used by dalvik. */
public int dalvikPrivateDirty;
/** The shared dirty pages used by dalvik. */
public int dalvikSharedDirty;

/** The proportional set size for the native heap. */
public int nativePss;
/** The private dirty pages used by the native heap. */
public int nativePrivateDirty;
/** The shared dirty pages used by the native heap. */
public int nativeSharedDirty;

/** The proportional set size for everything else. */
public int otherPss;
/** The private dirty pages used by everything else. */
public int otherPrivateDirty;
/** The shared dirty pages used by everything else. */
public int otherSharedDirty;

But as to what the difference is between "Pss", "PrivateDirty", and "SharedDirty"... well now the fun begins.

A lot of memory in Android (and Linux systems in general) is actually shared across multiple processes. So how much memory a processes uses is really not clear. Add on top of that paging out to disk (let alone swap which we don't use on Android) and it is even less clear.

Thus if you were to take all of the physical RAM actually mapped in to each process, and add up all of the processes, you would probably end up with a number much greater than the actual total RAM.

The Pss number is a metric the kernel computes that takes into account memory sharing -- basically each page of RAM in a process is scaled by a ratio of the number of other processes also using that page. This way you can (in theory) add up the pss across all processes to see the total RAM they are using, and compare pss between processes to get a rough idea of their relative weight.

The other interesting metric here is PrivateDirty, which is basically the amount of RAM inside the process that can not be paged to disk (it is not backed by the same data on disk), and is not shared with any other processes. Another way to look at this is the RAM that will become available to the system when that process goes away (and probably quickly subsumed into caches and other uses of it).

That is pretty much the SDK APIs for this. However there is more you can do as a developer with your device.

Using adb, there is a lot of information you can get about the memory use of a running system. A common one is the command "adb shell dumpsys meminfo" which will spit out a bunch of information about the memory use of each Java process, containing the above info as well as a variety of other things. You can also tack on the name or pid of a single process to see, for example "adb shell dumpsys meminfo system" give me the system process:

** MEMINFO in pid 890 [system] **
                    native   dalvik    other    total
            size:    10940     7047      N/A    17987
       allocated:     8943     5516      N/A    14459
            free:      336     1531      N/A     1867
           (Pss):     4585     9282    11916    25783
  (shared dirty):     2184     3596      916     6696
    (priv dirty):     4504     5956     7456    17916

 Objects
           Views:      149        ViewRoots:        4
     AppContexts:       13       Activities:        0
          Assets:        4    AssetManagers:        4
   Local Binders:      141    Proxy Binders:      158
Death Recipients:       49
 OpenSSL Sockets:        0

 SQL
            heap:      205          dbFiles:        0
       numPagers:        0   inactivePageKB:        0
    activePageKB:        0

The top section is the main one, where "size" is the total size in address space of a particular heap, "allocated" is the kb of actual allocations that heap things it has, "free" is the remaining kb free the heap has for additional allocations, and "pss" and "priv dirty" are the same as discussed before specific to pages associated with each of the heaps.

If you just want to look at memory usage across all processes, you can use the command "adb shell procrank". Output of this on the same system looks like:

  PID      Vss      Rss      Pss      Uss  cmdline
  890   84456K   48668K   25850K   21284K  system_server
 1231   50748K   39088K   17587K   13792K  com.android.launcher2
  947   34488K   28528K   10834K    9308K  com.android.wallpaper
  987   26964K   26956K    8751K    7308K  com.google.process.gapps
  954   24300K   24296K    6249K    4824K  com.android.phone
  948   23020K   23016K    5864K    4748K  com.android.inputmethod.latin
  888   25728K   25724K    5774K    3668K  zygote
  977   24100K   24096K    5667K    4340K  android.process.acore
...
   59     336K     332K      99K      92K  /system/bin/installd
   60     396K     392K      93K      84K  /system/bin/keystore
   51     280K     276K      74K      68K  /system/bin/servicemanager
   54     256K     252K      69K      64K  /system/bin/debuggerd

Here the Vss and Rss columns are basically noise (these are the straight-forward address space and RAM usage of a process, where if you add up the RAM usage across processes you get an ridiculously large number).

Pss is as we've seen before, and Uss is Priv Dirty.

Interesting thing to note here: Pss and Uss are slightly (or more than slightly) different than what we saw in meminfo. Why is that? Well procrank uses a different kernel mechanism to collect its data than meminfo does, and they give slightly different results. Why is that? Honestly I haven't a clue. I believe procrank may be the more accurate one... but really, this just leave the point: "take any memory info you get with a grain of salt; often a very large grain."

Finally there is the command "adb shell cat /proc/meminfo" that gives a summary of the overall memory usage of the system. There is a lot of data here, only the first few numbers worth discussing (and the remaining ones understood by few people, and my questions of those few people about them often resulting in conflicting explanations):

MemTotal:         395144 kB
MemFree:          184936 kB
Buffers:             880 kB
Cached:            84104 kB
SwapCached:            0 kB

MemTotal is the total amount of memory available to the kernel and user space (often less than the actual physical RAM of the device, since some of that RAM is needed for the radio, DMA buffers, etc).

MemFree is the amount of RAM that is not being used at all. The number you see here is very high; typically on an Android system this would be only a few MB, since we try to use available memory to keep processes running

Cached is the RAM being used for filesystem caches and other such things. Typical systems will need to have 20MB or so for this to avoid getting into bad paging states; the Android out of memory killer is tuned for a particular system to make sure that background processes are killed before the cached RAM is consumed too much by them to result in such paging.



추가로, Google I/O 2011: Memory management for Android Apps 동영상도 함께 걸어놓아야 겠다.
 
Posted by 세월의돌
리눅스 & 안드로이드2011. 12. 9. 14:31
형상관리 도구를 사용하면서 commit 메시지는 상당히 중요하지만 귀찮은 부분이기도 하다.

Git을 사용할 때, 윈도우 환경에서 사용할 수 있는 변변한 GUI 클라이언트가 없는 관계로 LINUX 터미널에서 작업을 하게 된다.
LINUX 사용자들이 널리(?) 사용하고 있는 vi(m)을 이용해서 commit 메시지를 작성할 수 있지만, 부득이한 사정으로 commit 메시지를 조금씩 조금씩 추가해서 작성할 경우 미리 작성 해 놓은 파일로 바로 commit을 할 수 있다면 편리할 수도 있을 것 같았다. (물론 copy & paste의 방법이 있기도 한데, 그냥 찾아보고 싶기도 하였고... 암튼 언젠가 필요한 상황이 몇 번은 생기지 않을까? : ) 풉)

그래서 찾아보니 꼼수(?)를 사용해서 이용할 수 있는 방법이 있었다. (세상엔 똑똑한 사람들이 정말 많다ㅎㅎ)

git config --global core.editor "cp ~/git_commit_msg.txt"

또는

# vi ~/.gitconfig 실행 후 아래 카테고리에 추가 혹은 수정


[core]

editor = cp ~/git_commit_msg.txt


위와 같이 설정 해 두고, 홈 디렉토리에 git_commit_msg.txt 라는 파일로 commit 메시지를 작성 해두고, commit을 하면 텍스트 파일의 내용이 commit 메시지로 추가된다.

P.S. 원리를 간략히 설명하면 다음과 같다.
Git에서 commit 메시지를 작성할 때 사용할 편집기를 지정 해 두면, 현재 indexing 된 파일들의 목록을 .git/COMMIT_EDITMSG 파일로 생성한 후 해당 파일을 열도록 되어 있다.

즉, 예를들어 편집기를 'gedit'으로 설정 해 두었다면, 아래와 같은 명령이 commit하는 시점에 실행된다고 이해하면 될 듯.

# gedit .git/COMMIT_EDITMSG

그리고 지금 설정한 대로 위 명령을 바꿔보면,
# cp ~/git_commit_msg.txt .git/COMMIT_EDITMSG 


위와 같이 실행 되므로, COMMIT_EDITMSG라는 파일이 내가 생성한 파일로 대치되고, 해당 내용이 commit 메시지로 사용되게 된다.

Posted by 세월의돌