Android2009. 7. 24. 18:27

이글은, 구글 안드로이드 상의 Java 애플리케이션에서 native c/c++ 모듈을 Call 할 수 있는 가에
대한 것이다. 결론적으로 말하면 쉽지 않을 것 같지만 불가능 하지는 않을 듯 하다.
직접 JNI를 통해 결과를 검증해 보지는 않았지만, 대략적인 방법들과 문제점들을 정리해 보고자
한다.
 
 
1. JNI란 무엇인가? - JNI example 중심으로
 
This section presents the ReadFile example program. This example shows how you can use 
the Java Native Interface (JNI) to invoke a native method that makes C function calls to map a 
file into memory. 

About the Example 

You can call code written in any programming language from a program written in the Java 
language by declaring a native Java method, loading the library that contains the native code, 
and then calling the native method. The ReadFile source code below does exactly this. 
However, successfully running the program requires a few additional steps beyond compiling 
the Java language source file. After you compile, but before you run the example, you have to 
generate a header file. The native code implements the function defintions contained in the 
generated header file and implements the business logic as well. The following sections walk 
through all the steps.
import java.util.*;
class ReadFile {
 //Native method declaration
   native byte[] loadFile(String name);
 //Load the library
   static {
     System.loadLibrary("nativelib");
   }
 
   public static void main(String args[]) {
      byte buf[];
 //Create class instance
      ReadFile mappedFile=new ReadFile();
 //Call native method to load ReadFile.java
      buf=mappedFile.loadFile("ReadFile.java");
 //Print contents of ReadFile.java
      for(int i=0;i<buf.length;i++) {
          System.out.print((char)buf[i]);
      }
   }
}
Native Method Declaration 

The native declaration provides the bridge to run the native function in the Java virtual machine.
In this example, the loadFile function maps onto a C function called Java_ReadFile_loadFile.
The function implementation accepts a String that represents a file name and returns the 
contents of that file in the byte array.
native byte[] loadFile(String name); Load the Library
The library containing the native code implementation is loaded by a call to System.loadLibrary().
Placing this call in a static initializer ensures this library is only loaded once per class.
The library can be loaded outside of the static block if your application requires it. You might 
need to configure your environment so the loadLibrary method can find your native code library.
static { 
     System.loadLibrary("nativelib"); 
}
Compile the Program
 
To compile the program, just run the javac compiler command as you normally would: 
javac ReadFile.java
Next, you need to generate a header file with the native method declaration and implement the 
native method to call the C functions for loading and reading a file. 

Generate the Header File 

To generate a a header file, run the javah command on the ReadFile class. In this example, 
the generated header file is named ReadFile.h. It provides a method signature that you have 
to use when you implement the loadfile native function.
javah -jni ReadFile
Note: When running javah on your own classes, be sure to use the fully-qualified class name.
Method Signature 

The ReadFile.h header file defines the interface to map the Java language method to the native
C function. It uses a method signature to map the arguments and return value of the Java
language mappedfile.loadFile method to the loadFile native method in the nativelib library.
Here is the loadFile native method mapping (method signature):
/* * Class: ReadFile * Method: loadFile * Signature: (Ljava/lang/String;)[B */ 
JNIEXPORT jbyteArray JNICALL Java_ReadFile_loadFile (JNIEnv *, jobject, jstring);
The method signature parameters function as follows:
JNIEnv *: A pointer to the JNI environment. This pointer is a handle to the current thread 
in the Java virtual machine, and contains mapping and other hosuekeeping information. 
jobject: A reference to the method that called this native code. If the calling method is 
static, this parameter would be type jclass instead of jobject. 
jstring: The parameter supplied to the native method. In this example, it is the name of 
the file to be read. 
 
Implement the Native Method
 
In this native C source file, the loadFile definition is a copy and paste of the C declaration 
contained in ReadFile.h. The definition is followed by the native method implementation. 
JNI provides a mapping for both C and C++ by default.
#include <jni.h>
#include <sys/types.h>
#include <sys/
ipc.h>
#include <sys/shm.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
 
JNIEXPORT jbyteArray JNICALL Java_ReadFile_loadFile
  (JNIEnv * env, jobject jobj, jstring name) {
    caddr_t m;
    jbyteArray jb;
    jboolean iscopy;
    struct stat finfo;
    const char *mfile = (*env)->GetStringUTFChars(
                env, name, &iscopy);
    int fd = open(mfile, O_RDONLY);
    if (fd == -1) {
      printf("Could not open %sn", mfile);
    }
    lstat(mfile, &finfo);
    m = mmap((caddr_t) 0, finfo.st_size,
                PROT_READ, MAP_PRIVATE, fd, 0);
    if (m == (caddr_t)-1) {
      printf("Could not mmap %sn", mfile);
      return(0);
    }
    jb=(*env)->NewByteArray(env, finfo.st_size);
    (*env)->SetByteArrayRegion(env, jb, 0, 
 finfo.st_size, (jbyte *)m);
    close(fd);
    (*env)->ReleaseStringUTFChars(env, name, mfile);
    return (jb);
}
 
You can approach calling an existing C function instead of implementing one, in one of two ways: 
Map the name generated by JNI to the existing C function name. The Language Issues 
section shows how to map between Xbase database functions and Java language code 
Use the shared stubs code available from the JNI page on the java.sun.com web site.

Compile the Dynamic or Shared Object Library 

The library needs to be compiled as a dynamic or shared object library so it can be loaded at 
runtime. Static or archive libraries are compiled into an executable and cannot be loaded at 
runtime. The shared object or dynamic library for the loadFile example is compiled as follows:
Gnu C/Linux:
gcc  -o libnativelib.so -shared -Wl,-soname,libnative.so  
     -I/export/home/jdk1.2/include 
     -I/export/home/jdk1.2/include/linux nativelib.c  
     -static -lc
Gnu C++/Linux with Xbase
g++ -o libdbmaplib.so -shared -Wl,-soname,libdbmap.so  
    -I/export/home/jdk1.2/include 
    -I/export/home/jdk1.2/include/linux 
    dbmaplib.cc -static -lc -lxbase

Win32/WinNT/Win2000
cl -Ic:/jdk1.2/include 
   -Ic:/jdk1.2/include/win32 
   -LD nativelib.c -Felibnative.dll

Run the Example
 
To run the example, the Java virtual machine needs to be able to find the native library. To do this, 
set the library path to the current directory as follows:

Unix or Linux: LD_LIBRARY_PATH=`pwd` export LD_LIBRARY_PATH
Windows NT/2000/95: set PATH=%path%;.

With the library path properly specified for your platform, invoke the program as you normally would 
with the interpreter command:
 java ReadFile
 
 
2. 구글 안드로이드 상에서 JNI 지원 API

아래의 두가지 함수에 대한 안드로이드 상에서의 특별한 제약이 없다면 JNI 을 지원하기 위한 최소한의
조건은 만족된 듯하다
The core functional component is the use of the 'native' keyword and the bindings to the 
java.lang.System.loadLibary() API, which, does seem to be documented within the android reference:
 
java.lang.System
java.lang 
public final class
java.lang.System
java.lang.Object  
       java.lang.System 

Class System provides a standard place for programs to find system related information. 
All System API is static.
static  void  load(String pathName) : Loads the specified file as a dynamic library. 
static  void  loadLibrary(String libName) : Loads and links the library specified by the argument.

3. Dynamic & Shard Object Library 만들기
 
the question here is how to build a native .so (shared library), but we can refer to the JNI example 
above for instructions. we have also been informed, through this list that you can build native code 
on the device, but without UI bindings:
 
이 부분 중, 가장 어렵게 생각되는 부분은 Cross Compiler를 통해 shard object library를 만들 수 있느냐 일듯.
현재 안드로이드의 /system/lib 아래에는 안드로이드 Library들이 .so 형태로 존재함.
Posted by 삼스
Android/App개발2009. 7. 24. 17:15
class public .... extends Service 로 정의된 class들이며 실제 Service와 대응되는것은 아님.

1. MediaScannerService  
    ./packages/providers/MediaProvider/src/com/android/providers/media/MediaScannerService.java
2. CalendarAppWidgetService
    ./packages/providers/CalendarProvider/src/com/android/providers/calendar/CalendarAppWidgetService.java
3. DownloadService
    ./packages/providers/DownloadProvider/src/com/android/providers/downloads/DownloadService.java
4. MediaPlaybackService
    ./packages/apps/Music/src/com/android/music/MediaPlaybackService.java
5. StkAppService
    ./packages/apps/Stk/src/com/android/stk/StkAppService.java
6. MailService
    ./packages/apps/Email/src/com/android/email/service/MailService.java
7. AlertService
    ./packages/apps/Calendar/src/com/android/calendar/AlertService.java
8. BluetoothHeadsetService
    ./packages/apps/Phone/src/com/android/phone/BluetoothHeadsetService.java
9. NetworkQueryService
    ./packages/apps/Phone/src/com/android/phone/NetworkQueryService.java
10. SmsReceiverService
    ./packages/apps/Mms/src/com/android/mms/transaction/SmsReceiverService.java
11. TransactionService
    ./packages/apps/Mms/src/com/android/mms/transaction/TransactionService.java
12. DemoImPlugin
    ./packages/apps/IM/samples/PluginDemo/src/com/android/im/plugin/demo/DemoImPlugin.java
13. FrontDoorPlugin
    ./packages/apps/IM/src/com/android/im/app/FrontDoorPlugin.java
14. RemoteImService
    ./packages/apps/IM/src/com/android/im/service/RemoteImService.java
15. RssService
    ./development/samples/MySampleRss/src/com/example/codelab/rssexample/RssService.java
16. LocalServiceTest
    ./development/samples/ApiDemos/tests/src/com/example/android/apis/app/LocalServiceTest.java
17. ServiceStartArgument
    ./development/samples/ApiDemos/src/com/example/android/apis/app/ServiceStartArguments.java
18. RemoteService
    ./development/samples/ApiDemos/src/com/example/android/apis/app/RemoteService.java
19. NotifyingService
    ./development/samples/ApiDemos/src/com/example/android/apis/app/NotifyingService.java
20. AlarmService_Service
    ./development/samples/ApiDemos/src/com/example/android/apis/app/AlarmService_Service.java
21. LocalService
    ./development/samples/ApiDemos/src/com/example/android/apis/app/LocalService.java
22. IIORegistry
    ./frameworks/base/awt/javax/imageio/spi/IIORegistry.java
23. MessengerService
    ./frameworks/base/tests/AndroidTests/src/com/android/unit_tests/os/MessengerService.java
24. LocalService
    ./frameworks/base/tests/AndroidTests/src/com/android/unit_tests/activity/LocalService.java
25. DisabledService
  ./frameworks/base/tests/AndroidTests/EnabledTestApp/src/com/android/unit_tests/enabled_app/DisabledService.java
26. EnabledService
  ./frameworks/base/tests/AndroidTests/EnabledTestApp/src/com/android/unit_tests/enabled_app/EnabledService.java
27. AbstractInputMethodService
    ./frameworks/base/core/java/android/inputmethodservice/AbstractInputMethodService.java
28. IntentService
    ./frameworks/base/core/java/android/app/IntentService.java
29. ServiceTestClass
    ./frameworks/base/test-runner/android/test/ServiceTestCase.java
30. LoadAverageService
    ./frameworks/base/services/java/com/android/server/LoadAverageService.java

Posted by 삼스
Android/App개발2009. 7. 24. 15:34


App에서 Framework을 통해 시스템서비스를 이용하는 구조에 대한 개념도임.

Posted by 삼스
Android2009. 7. 23. 23:10
Product설정파일을 통해 환경변수를 설정하여 선택적으로 빌드가능
 PRODUCT_NAME : 제품명
 PRODUCT_DEVICE : 디바이스명
 PRODUCT_LOCALE : 지역정보
 PRODUCT_PACKAGE_OVERLAY : 대체될 resource가 있는 Path
 PRODUCT_PROPERTY_OVERRIDES : 추가될 system property 항목이며 /system/build.prop에 저장됨.
 PRODUCT_PACKAGES : 기본적으로 설치될 app 목록

전체 과정을 간략히 설명하면, TARGET_BUILD_VARIANT에 따라서 System Property와 설치될 모듈을 결정합니다. 그 과정을 Makefile을 따라가면서 확인해 보겠습니다.

 

시작은 open_src폴더 아래 Makefile에서 build/core/main.mk로 이동합니다.

/Makefile

### DO NOT EDIT THIS FILE ###

include build/core/main.mk

### DO NOT EDIT THIS FILE ###

 

아래 build/core/main.mk를 보면 환경변수 TARGET_BUILD_VARIANT에 따라서 System Property를 다르게 설정하고 있습니다.

Part 1 : /build/core/main.mk

## user/userdebug ##

 

user_variant := $(filter userdebug user,$(TARGET_BUILD_VARIANT))

enable_target_debugging := true

ifneq (,$(user_variant))

  # Target is secure in user builds.

  ADDITIONAL_DEFAULT_PROPERTIES += ro.secure=1

 

  tags_to_install := user

  ifeq ($(user_variant),userdebug)

    # Pick up some extra useful tools

    tags_to_install += debug

  else

    # Disable debugging in plain user builds.

    enable_target_debugging :=

  endif

 

  # TODO: Always set WITH_DEXPREOPT (for user builds) once it works on OSX.

  # Also, remove the corresponding block in config/product_config.make.

  ifeq ($(HOST_OS)-$(WITH_DEXPREOPT_buildbot),linux-true)

    WITH_DEXPREOPT := true

  endif

 

  # Disallow mock locations by default for user builds

  ADDITIONAL_DEFAULT_PROPERTIES += ro.allow.mock.location=0

 

else # !user_variant

  # Turn on checkjni for non-user builds.

  ADDITIONAL_BUILD_PROPERTIES += ro.kernel.android.checkjni=1

  # Set device insecure for non-user builds.

  ADDITIONAL_DEFAULT_PROPERTIES += ro.secure=0

  # Allow mock locations by default for non user builds

  ADDITIONAL_DEFAULT_PROPERTIES += ro.allow.mock.location=1

endif # !user_variant

 

ifeq (true,$(strip $(enable_target_debugging)))

  # Target is more debuggable and adbd is on by default

  ADDITIONAL_DEFAULT_PROPERTIES += ro.debuggable=1 persist.service.adb.enable=1

  # Include the debugging/testing OTA keys in this build.

  INCLUDE_TEST_OTA_KEYS := true

else # !enable_target_debugging

  # Target is less debuggable and adbd is off by default

  ADDITIONAL_DEFAULT_PROPERTIES += ro.debuggable=0 persist.service.adb.enable=0

endif # !enable_target_debugging

 

## eng ##

 

ifeq ($(TARGET_BUILD_VARIANT),eng)

tags_to_install := user debug eng

# Don't require the setup wizard on eng builds

#eng모드에서 ro.setupwizard.mode property를 뺍니다.

  ADDITIONAL_BUILD_PROPERTIES := $(filter-out ro.setupwizard.mode=%,\

          $(call collapse-pairs, $(ADDITIONAL_BUILD_PROPERTIES)))

endif

 

 

TARGET_BUILD_VARIANT에 따른 동작은 아래와 같습니다.  Android.mk의 정의된 LOCAL_MODULE_TAGS를 정의하지 않은 모듈은 기본이 user 태그입니다. 따라서 이전에 eng로 설정되어 있는 모듈들이 설치되지 않은 이유는 명시적으로 eng태그를 설정해 주었기 때문입니다.

TARGET_BUILD_VARIANT

Actions

eng

- Installs modules tagged with: eng, debug, user, and/or development.

- Installs non-APK modules that have no tags specified.

- Installs APKs according to the product definition files, in addition to tagged APKs.

- ro.secure=0

- ro.debuggable=1

- ro.kernel.android.checkjni=1

- adb is enabled by default.

user

- Installs modules tagged with user.

- Installs non-APK modules that have no tags specified.

- Installs APKs according to the product definition files; tags are ignored for APK modules.

- ro.secure=1

- ro.debuggable=0

- adb is disabled by default.

userdebug

The same as user, except:

- Also installs modules tagged with debug.

- ro.debuggable=1

- adb is enabled by default.

 

 

빌드시 build/tools/findleaves.sh를 사용해서 각 폴더의 첫번째 Android.mk파일을 모두 찾아서 Makefile에 추가합니다. 하위 폴더에 Android.mk파일이 존재하더라도 상위 폴더에 Android.mk가 존재하면 상위 폴더에 있는 Android.mk까지만 찾습니다.

그리고 현재 Product설정파일의 TARGET_DEVICE BoardConfig.mk를 포함시킵니다.

 

Part 2 : /build/core/main.mk

# Can't use first-makefiles-under here because

# --mindepth=2 makes the prunes not work.

subdir_makefiles += \

    $(shell build/tools/findleaves.sh --prune="./out" $(subdirs) Android.mk)

 

# Boards may be defined under $(SRC_TARGET_DIR)/board/$(TARGET_DEVICE)

# or under vendor/*/$(TARGET_DEVICE).  Search in both places, but

# make sure only one exists.

# Real boards should always be associated with an OEM vendor.

board_config_mk := \

    $(strip $(wildcard \

        $(SRC_TARGET_DIR)/board/$(TARGET_DEVICE)/BoardConfig.mk \

        vendor/*/$(TARGET_DEVICE)/BoardConfig.mk \

    ))

ifeq ($(board_config_mk),)

  $(error No config file found for TARGET_DEVICE $(TARGET_DEVICE))

endif

ifneq ($(words $(board_config_mk)),1)

  $(error Multiple board config files for TARGET_DEVICE $(TARGET_DEVICE): $(board_config_mk))

endif

include $(board_config_mk)

TARGET_DEVICE_DIR := $(patsubst %/,%,$(dir $(board_config_mk)))

board_config_mk :=

 

# Clean up/verify variables defined by the board config file.

TARGET_BOOTLOADER_BOARD_NAME := $(strip $(TARGET_BOOTLOADER_BOARD_NAME))

 

#

# Include all of the makefiles in the system

#

 

ifneq ($(ONE_SHOT_MAKEFILE),)

# We've probably been invoked by the "mm" shell function

# with a subdirectory's makefile.

include $(ONE_SHOT_MAKEFILE)

# Change CUSTOM_MODULES to include only modules that were

# defined by this makefile; this will install all of those

# modules as a side-effect.  Do this after including ONE_SHOT_MAKEFILE

# so that the modules will be installed in the same place they

# would have been with a normal make.

CUSTOM_MODULES := $(sort $(call get-tagged-modules,$(ALL_MODULE_TAGS),))

FULL_BUILD :=

INTERNAL_DEFAULT_DOCS_TARGETS :=

# Stub out the notice targets, which probably aren't defined

# when using ONE_SHOT_MAKEFILE.

NOTICE-HOST-%: ;

NOTICE-TARGET-%: ;

else

include $(subdir_makefiles)

endif

# -------------------------------------------------------------------

# All module makefiles have been included at this point.

# -------------------------------------------------------------------

 

build/tools/findleaves.sh 동작 예제

$find hardware –name “*.mk”

hardware/libhardware/Android.mk

hardware/libhardware/modules/overlay/Android.mk

hardware/libhardware_legacy/Android.mk

hardware/libhardware_legacy/flashlight/Android.mk

hardware/libhardware_legacy/gps/Android.mk

hardware/libhardware_legacy/led/Android.mk

hardware/libhardware_legacy/mount/Android.mk

hardware/libhardware_legacy/power/Android.mk

hardware/libhardware_legacy/qemu/Android.mk

hardware/libhardware_legacy/qemu_tracing/Android.mk

hardware/libhardware_legacy/tests/gpstest/Android.mk

hardware/libhardware_legacy/uevent/Android.mk

hardware/libhardware_legacy/vibrator/Android.mk

hardware/libhardware_legacy/wifi/Android.mk

hardware/ril/libril/Android.mk

hardware/ril/rild/Android.mk

hardware/ril/gpstest/Android.mk

hardware/ril/libsecril-client/Android.mk

hardware/ril/rilclient-test/Android.mk

hardware/ril/secril_multi/Android.mk

hardware/modules/sensors/Android.mk

hardware/msm7k/Android.mk

hardware/msm7k/libaudio/Android.mk

hardware/msm7k/libcamera/Android.mk

hardware/msm7k/libcopybit/Android.mk

hardware/msm7k/librpc/Android.mk

hardware/msm7k/yuv420sp2rgb/Android.mk

 

$ ./build/tools/findleaves.sh hardware Android.mk

hardware/libhardware/Android.mk => 폴더구조의 첫번째 Android.mk만 포함됨

hardware/libhardware_legacy/Android.mk

hardware/modules/sensors/Android.mk

hardware/msm7k/Android.mk

hardware/ril/gpstest/Android.mk

hardware/ril/libril/Android.mk

hardware/ril/libsecril-client/Android.mk

hardware/ril/rilclient-test/Android.mk

hardware/ril/rild/Android.mk

hardware/ril/secril_multi/Android.mk

 

hardware/msm7k/Android.mk 파일에서 아래와 같이 하위의 Android.mk파일을 상황에 따라서 include를 하여 필요한 모듈만 컴파일하여 추가시킬 때 사용할 수 있습니다. (이것을 사용해서 Samsung Open Source쪽 변경 소스 관리를 할 수 있을 것으로 보입니다. )

ifneq ($(filter capella7200, surf, $(TARGET_DEVICE)), )

  include $(all-subdir-makefiles)

endif

 

설치될 모듈들을 선택하고, LOCAL_OVERRIDES_PACKAGES로 선택된 Package를 항목에서 삭제합니다.

Part 3 : build/core/main.mk

# -------------------------------------------------------------------

# Figure out our module sets.

 

# Of the modules defined by the component makefiles,

# determine what we actually want to build.

# If a module has the "restricted" tag on it, it

# poisons the rest of the tags and shouldn't appear

# on any list.

Default_MODULES := $(sort $(ALL_DEFAULT_INSTALLED_MODULES) \

                          $(ALL_BUILT_MODULES) \

                          $(CUSTOM_MODULES))

# TODO: Remove the 3 places in the tree that use

# ALL_DEFAULT_INSTALLED_MODULES and get rid of it from this list.

 

ifdef FULL_BUILD

  # The base list of modules to build for this product is specified

  # by the appropriate product definition file, which was included

  # by product_config.make.

  user_PACKAGES := $(call module-installed-files, \

                       $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PACKAGES))

  ifeq (0,1)

    $(info user packages for $(TARGET_DEVICE) ($(INTERNAL_PRODUCT)):)

    $(foreach p,$(user_PACKAGES),$(info :   $(p)))

    $(error done)

  endif

else

  # We're not doing a full build, and are probably only including

  # a subset of the module makefiles.  Don't try to build any modules

  # requested by the product, because we probably won't have rules

  # to build them.

  user_PACKAGES :=

endif

# Use tags to get the non-APPS user modules.  Use the product

# definition files to get the APPS user modules.

user_MODULES := $(sort $(call get-tagged-modules,user,_class@APPS restricted))

user_MODULES := $(user_MODULES) $(user_PACKAGES)

 

eng_MODULES := $(sort $(call get-tagged-modules,eng,restricted))

debug_MODULES := $(sort $(call get-tagged-modules,debug,restricted))

tests_MODULES := $(sort $(call get-tagged-modules,tests,restricted))

 

ifeq ($(strip $(tags_to_install)),)

$(error ASSERTION FAILED: tags_to_install should not be empty)

endif

modules_to_install := $(sort $(Default_MODULES) \

          $(foreach tag,$(tags_to_install),$($(tag)_MODULES)))

 

# Some packages may override others using LOCAL_OVERRIDES_PACKAGES.

# Filter out (do not install) any overridden packages.

overridden_packages := $(call get-package-overrides,$(modules_to_install))

ifdef overridden_packages

#  old_modules_to_install := $(modules_to_install)

  modules_to_install := \

      $(filter-out $(foreach p,$(overridden_packages),$(p) %/$(p).apk), \

          $(modules_to_install))

endif

 

추가로Android의 모든 Application은 고유한 Key를 사용해서 Signning을 수행해야 합니다. 어떤 Key Signning을 할지를 결정은 LOCAL_CERTIFICATE에 기술합니다.

packages/apps/Camera/Android.mk

LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)

 

LOCAL_MODULE_TAGS := user

 

LOCAL_SRC_FILES := $(call all-java-files-under, src)

 

LOCAL_PACKAGE_NAME := Camera

LOCAL_CERTIFICATE := media

#LOCAL_CERTIFICATE := vendor/samsung/products/security/media   => 명시적으로 선택가능

 

LOCAL_STATIC_JAVA_LIBRARIES := googlelogin-client

 

#include $(BUILD_PACKAGE)

 

# Use the following include to make our test apk.

#include $(call all-makefiles-under,$(LOCAL_PATH))

 

package.mk파일을 보시면 LOCAL_CERTIFICATE가 설정되지 않으면 testkey가 사용되며, 관련 private certificate /build/target/product/security/폴더에 있는 key값을 사용합니다.

mkkey.sh   => key값을 생성하기 위한 명령어, Samsung Android폰 개발시 고유한 key를 생성해서 출시해야함.

media.pk8

media.x509.pem

platform.pk8

platform.x509.pem

shared.pk8

shared.x509.pem

testkey.pk8

testkey.x509.pem

 

/build/core/package.mk

# Pick a key to sign the package with.  If this package hasn't specified

# an explicit certificate, use the default.

# Secure release builds will have their packages signed after the fact,

# so it's ok for these private keys to be in the clear.

ifeq ($(LOCAL_CERTIFICATE),)

    LOCAL_CERTIFICATE := testkey

endif

# If this is not an absolute certificate, assign it to a generic one.

ifeq ($(dir $(strip $(LOCAL_CERTIFICATE))),./)

    LOCAL_CERTIFICATE := $(SRC_TARGET_DIR)/product/security/$(LOCAL_CERTIFICATE)

endif

private_key := $(LOCAL_CERTIFICATE).pk8

certificate := $(LOCAL_CERTIFICATE).x509.pem

 

$(LOCAL_BUILT_MODULE): $(private_key) $(certificate) $(SIGNAPK_JAR)

$(LOCAL_BUILT_MODULE): PRIVATE_PRIVATE_KEY := $(private_key)

$(LOCAL_BUILT_MODULE): PRIVATE_CERTIFICATE := $(certificate)

 

PACKAGES.$(LOCAL_PACKAGE_NAME).PRIVATE_KEY := $(private_key)

PACKAGES.$(LOCAL_PACKAGE_NAME).CERTIFICATE := $(certificate)

 

# Define the rule to build the actual package.

$(LOCAL_BUILT_MODULE): $(AAPT) | $(ZIPALIGN)

$(LOCAL_BUILT_MODULE): PRIVATE_JNI_SHARED_LIBRARIES := $(jni_shared_libraries)

$(LOCAL_BUILT_MODULE): $(all_res_assets) $(jni_shared_libraries) $(full_android_manifest)

    @echo "target Package: $(PRIVATE_MODULE) ($@)"

    $(create-empty-package)

    $(add-assets-to-package)

ifneq ($(jni_shared_libraries),)

    $(add-jni-shared-libs-to-package)

endif

ifneq ($(full_classes_jar),)

    $(add-dex-to-package)

endif

    $(sign-package)

    @# Alignment must happen after all other zip operations.

    $(align-package)

 

# Save information about this package

PACKAGES.$(LOCAL_PACKAGE_NAME).OVERRIDES := $(strip $(LOCAL_OVERRIDES_PACKAGES))

PACKAGES.$(LOCAL_PACKAGE_NAME).RESOURCE_FILES := $(all_resources)

 

PACKAGES := $(PACKAGES) $(LOCAL_PACKAGE_NAME)

 

Posted by 삼스
Android/App개발2009. 7. 23. 19:33
In order to use in on the device (use the attached busybox.tar)
$ tar -xvf busybox.tar 
$ adb shell 
# mkdir /data/busybox
# exit
$ adb push busybox /data/busybox
$ adb shell 
# cd data/busybox
# ./busybox --install
# export PATH=/data/busybox:$PATH

Posted by 삼스
Android/App개발2009. 7. 20. 20:23
Parcelable Object 만들기 (1) Android Life 

2009/07/17 16:24

복사http://blog.naver.com/visualc98/74522627


[Parcel Class?]

 

Android의 핵심 중에서 Binder Driver라는 녀석이 있습니다.
Linux Kernel의 driver로 되어 있고, IPC이긴 하지만 기존의 IPC와는 살짝 다른 녀석 입니다.

 

저도 어떻게 만들었는지는 잘 모릅니다만, 
shared memory를 통하여 오버헤드도 적고 프로세스 사이에 비동기로 호출도 이루어 진다고 합니다.
그리고 Binder는 기존 IPC처럼 데이터만 전달 하는게 아니라,
하나의 프로세스에서 다른 프로세스로 Object를 넘길 수도 있게끔 설계 되어 있습니다.
(물론 Serialize 기술을 사용하면 Object도 주고 받을 순 있지요.)

 

Binder를 통해서 넘기는 메세지 (data 와 object references) 는 
Parcel 클래스에 저장이 되어서 넘어가게 됩니다. Parcel은 메세지 컨테이너인 셈이죠.

Parcel is not a general-purpose serialization mechanism. This class (and the corresponding Parcelable API for placing arbitrary objects into a Parcel) is designed as a high-performance IPC transport.

Parcel 클래스는 고성능 IPC 전송을 가능하게 끔 설계가 되어 있기 때문에,

모든 객체에 대해서 평범하게 serialization하지 않습니다. 
그래서 모든 Object들을 Binder를 통해 주고 받을 수는 없습니다.

 


[Parcelable Interface]

 

Primitive Type과 Primitive Array Type은 기본적으로 parcelable 합니다.

뭐 그냥 일반 데이터인거죠.
그리고 
Parcelable Interface를 implements한 클래스가 (당연히) parcelable 합니다.

 

오늘 우리가 할 일이 바로 이 Parcelable Interface를 사용하여
parcelable Object를 만드는 일 인 것이죠.

사실 parcelable한 type들이 많이 있습니다만, 나머지는 잘 모르겠군요... 어렵습니다.
여튼 오늘은 parcelable Object를 만드는 것만 생각 합시다.

 


[Parcelable Rect]

 

Rect 클래스야 다들 쉽게 만드실 겁니다.
left, top, right, bottom 4개의 필드만 있으면 되죠.


integer든 float이든 상관 없습니다만....
Android에는 Rect 클래스의 float 버전이 RectF 클래스 라고 따로 되어 있기 때문에,

저는 integer로 만들겁니다.


public class Rect {
    public int left;
    public int top;
    public int right;
    public int bottom;
}


뭐 아주 간단 합니다. 그냥 C에서의 구조체 수준이네요.
이것을 parcelable하게 바꾸어 봅시다.

 

Step 1.


public class Rect implements Parcelable {
    public int left;
    public int top;
    public int right;
    public int bottom;
    
    public int describeContents() {
        return 0;
    }
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(left);
        dest.writeInt(top);
        dest.writeInt(right);
        dest.writeInt(bottom);
    }
}


Parcelable을 implements하게 되면 꼭 추가해야 한다는 메소드 두 개도 같이 넣었습니다.
내용도 채워 봤어요.

 

describeContents() 메소드는 일단 건너뛰고...
writeToParcel() 메소드는 Parcel에 데이터를 쓰는 부분 입니다.
그냥 무작정 쓰면 됩니다. 전 아무 생각 없이 순서대로 그냥 썼습니다.

 

그럼 이제 에러도 없으니 parcelable한 Rect 클래스가 되었느냐... 라고 한다면 아직 아닙니다.
쓰는건 있는데 읽는건 없네요...

 

Parcel로 부터 값을 읽어 오기 위해서는 Parcelable.Creator Interface 가 필요합니다.

 


[Parcelable.Creator Interface]

 

Parcel 에서 Parcelable 클래스의 인스턴스를 만들 때
CREATOR라는 static field를 찾아서 실행 합니다.
CREATOR는 
Parcelable.Creator<T> type 으로 만들어져야 하는데 
이건 선언과 동시에 반드시 initialize 되어야 합니다.

 

클래스 따로 만들어서 initialize 하기도 쉽지 않습니다.
그냥 익명 클래스로 만들어 버립시다.

 

Step 2.


public class Rect implements Parcelable {
    public int left;
    public int top;
    public int right;
    public int bottom;
    
    public int describeContents() {
        return 0;
    }
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(left);
        dest.writeInt(top);
        dest.writeInt(right);
        dest.writeInt(bottom);
    }
    
    public static final Parcelable.Creator<Rect> CREATOR new Creator<Rect>() {
        public Rect createFromParcel(Parcel source) {
            Rect r   = new Rect();
            r.left   = source.readInt();
            r.top    = source.readInt();
            r.right  = source.readInt();
            r.bottom = source.readInt();
            return r;
        }
        public Rect[] newArray(int size) {
            return new Rect[size];
        }
    };
}


Parcelable.Creator<T> 클래스는 createFromParcel() 과 newArray() 메소스가 필요 합니다.

 

newArray() 메소드도 일단 넘어가고...
createFromParcel() 메소드를 보면 리턴이 Rect입니다.
그래서 Parcel에서 값을 읽어 새로운 Rect 인스턴스를 리턴 하는 구조로 만들면 끝입니다.

 

readInt()를 했는데, 이것은 writeToParcel() 메소드에서 썼던 순서대로 읽어 오는 것입니다.
쓸 때는 무작정 썼지만 읽을 때는 조심스럽게 읽어야하죠.

 

이제 비로소 parcelable Rect 클래스를 만들었습니다.
그냥 별거 없군요...

 


[Appendix]

 

위에서 describeContents() 메소드와 newArray() 메소드는 그냥 넘어 갔었습니다.
네... 뭐 사실 잘 모르기도 합니다만, 
그냥 보통 parcelable Object를 만드는데에 크게 중요한 부분은 아니지요. 아하하...

 

describeContents() 에서는 어떤 특별한 객체를 포함하고 있는지에 대한 설명을
리턴값으로 표현 하는 것이라고 보면 됩니다.
bit mask 형식의 integer를 리턴 하며,
값을 체크 할 때 bit mask 체크를 해서 어떤 것들이 들어 있는지 알 수 있습니다.

 

현재 사용하는 플래그는 Parcelable.CONTENTS_FILE_DESCRIPTOR (0x00000001) 
하나 밖에 정의 되어 있지 않습니다.
소스를 다 뒤져 보지 않아서 또 어떤 값들이 쓰이는지는 확인 해보지 못했네요...

 

newArray() 메소드는 그냥 배열로 만들어서 리턴 하는 겁니다.
Parcel.createTypedArray() 메소드에서 newArray() 메소드를 호출 하는 걸 확인 했습니다.
나중에 createTypedArray() 메소드를 사용 할 일이 있다면 newArray()가 호출이 되는 것이지요.

Posted by 삼스
Android/App개발2009. 7. 19. 17:01
Pro. Android 발췌

Posted by 삼스
Android2009. 7. 17. 18:23
http://modian.tistory.com/entry/Android-Basic

Android Anatomy

Linux Kernel
  • Android는 Linux Kernel을 기반으로 하고 있다.  왜 Linux System이 아닌 Kernel인가?
    • 어찌보면 당연하다. Mobile Device 상에서 full linux 필요없다.  하지만 Android를 넷북이나 UMPC 등으로 영역을 확장한다면 좀 다른 얘기가 될지도 모른다
    • Android is not Linux
      • Android는 Linux Kernel을 기반으로 하는 Mobile Platform이라고 정의하길 선호한다.
    • Native windowing system, glibc support(gnu c library), 표준 linux utilities 등을 포함하지 않고 있다.
      • 일종의 file system 및 하드웨어를 제어하기 위한 드라이버 등, 최소한의 Linux를 채용하고 있다고 볼 수 있다.
      • Android는 Linux Kernel의 안정적인 System 운영 측면을 가져온 것이다.  Linux의 지속적인 업데이트 또한 장점이 되었을 것이다.
      •        


    • Linux 2.6.24를 기반으로 하였으나 최근 발표된 Android 1.5에서는 Linux 2.6.29로 업그레이드 됨
    • Kernel enhancements를 통해 Android를 지원
      • Alarm / Ashmen(Android shared memory) / Binder / Power Management / Low Memory Killer / Kernel Debugger / Logger
    • Why Linux kernel?
      • Great memory and process management
      • Permissions-based security model
      • Proven driver model
      • Support for shared libraries
      • It's already open source
    • Application과 Service는 별개의 process에서 동작을 하지만 상호 communicate 하거나 data를 공유할 필요가 있다.  이는 IPC (Inter Process Communication)를 통해 지원 : Binder
      • High performance through shared memory
      • Per-process thread pool for processing requests
      • Reference counting, and mapping of object reference across processes
      • Synchronous calls between processes
      • AIDL(Android Interface Definition Language)
    • PM (Power Management) Solution
      • 기본적으로 Linux Power Management를 기반으로 구성 (on top of it)
      • More aggressive power management policy - 결국 좀 더 타이트한 policy를 통해 pm을 한다는 내용
      • Components make requests to keep the power on throught "wake locks"
      • Support different types of wake locks
      • Android.os.PowerManager - use wake locks carefully!

Native Libraries
  • Bionic Libc
    •  What is - 일종의 c library로 android에서는 다음과 같은 이유로 standard c lib가 아닌 bionic libc를 쓰기로 함
      • Bionic은 custom libc implementation, optimized for embedded use
      • License 문제 - standard c lib는 GPL이므로 사용자는 자신의 code를 open 해야 함으로 이로부터 자유롭게 하기 위해
        • BSD License
      • Size - android에서는 will load in each process 해야 함으로, so it needs to be small
        • Small size and fast code paths
      • Fast - mobile device와 같은 한정된 CPU에 최적화되어 빠르다
        • Very fast and small custom pthread implementation
      • 단점 or 장점?
        • Doesn't support certain POSIX features
        • Not compatible with Gnu Libc (glibc)
        • All native code must be compiled against bionic
  • Function Libraries
    • WebKit - 현재까지 알려진 Web 엔진 가운데 가장 괜찮음 : 애플사파리(아이폰포함), Nokia 등이 WebKit 기반 Web 엔진 사용
      • Based on open source WebKit browser
      • Renders pages in full (desktop) view
      • Full CSS, Javascript, DOM, AJAX support
      • Support for single-column and adative view rendering
    • Media Framework
      • Based on PacketVideo OpenCORE platform
      • Supports standard video, audio, still-frame formats
      • Support for hardware/software codec plug-ins - 기본 지원외에 format은 plug-in을 통해 또는 hardware accelerator등이 장착된 mobile device에도 plug-in을 사용하여 fully 지원할 수 있다.
    • SQLite
      • Light-weight transactional data store
      • Back end for most platform data storage
  • Native Servers
    • Surface Flinger
      • Provides system-wide surface "composer", handling all surface rendering to frame buffer device
      • Can combine 2D and 3D surfaces and surfaces from multiple applications
      • Surfaces passed as buffers via Binder IPC calls
      • Can use OpenGL ES and 2D hardware accelerator for its compositions
      • Double-buffering using page-flip
    • Audio Flinger
      • Manages all audio output devices
      • Processes multiple audio streams into PCM audio out paths
      • Handles audio routing to various outputs
  • Hardware Abstraction Libraries
    • User space C/C++ library layer
    • Defines the interface that Android requires hardware "drivers" to implement
    • Separates the Android platform logic from the hardware interface
    • Why do we need a user-space HAL? - HAL 영역이 왜 필요한가 : 당연 - Linux에서 kernel driver가 존재할 텐데 왜 굳이 Android용 HAL을 제공하는가에 대한 문제
      • Not all components have standardized kernel driver interface - 현재 제공되는 Linux system 상에서 모든 component의 driver interface에 대한 표준화가 되어있는 것은 아니다
      • Kernel drivers are GPL which exposes any proprietary IP - kernel driver는 현재 GPL로 되어 있어 그대로 사용하게 되면 연계 소스코드에 대해 오픈을 해야 한다
      • Android has specific requirements for hardware drivers

Android Runtime
  • Dalvik Virtual Machine
    • 사용자에게 Java를 이용해 app을 작성하게 하고 이러한 Java platform 기반 app을 모바일 device상에서 동작하게 하기 위한 최적의 환경을 제공하기 위해 기존의 Java VM과는 별도로 Google이 제공하는 VM이라고 할 수 있다
    • 일반 VM과는 다음과 같은 다른 특징을 가지고 있다
      • The VM was slimmed down to use less space
      • Dalvik has no Just-in-time compiler
      • The constant pool has been modified to use only 32-bit indexes to simplify the interpreter
      • It uses its own bytecode, not Java bytecode
    • Android's custom clean-room implementation virtual machine
      • Provides application portability and runtime consistency
      • Runs optimized file format (.dex) and Dalvik bytecode
      • Java .class/.jar files converted to .dex at build time
    • Designed for embedded environment
      • Supports multiple virtual machine processes per device
      • Highly CPU-optimized bytecode interpreter
      • Uses runtime memory very efficiently
  • Core Libraries
    • Core APIs for Java language provide a powerful, yet simple and familiar development platform
    • Data structures, Utilities, File access, Network Access, Graphics, …

Application Framework
  • Core Platform Services
    • Services that are essential to the Android platform
    • Behind the scenes - applications typically don’t access them directly
    • Activity Manager, Package Manager, Window Manager, Resource Manager, Content Providers, View System
  • Hardware Services
    • Provide access to lower-level hardware APIs
    • Typically accessed through local Manager object
      • LocationManager lm = (LocationManager) Context.getSystemService(Context.LOCATION_SERVICE);
    • Telephony Service, Location Service, Bluetooth Service, WiFi Service, USB Service, Sensor Service

Android Physiology

Start-up Walkthrough

  • Runtime Walkthrough
    • It all starts with init… - similar to most Linux-based systems at startup, the bootloader loads the Linux kernel and starts the init process.
    • Init starts Linux daemons, including:
      • USB Daemon (usbd) to manage USB connections
      • Android Debug Bridge (adbd) to manage ADB connections
      • Debugger Daemon (debuggerd) to manage debug processes requests (dump memory, etc.)
      • Radio Interface Layer Daemon (rild) to manage communication with the radio
    • Init process starts the zygote process:
      • A nascent process which initializes a Dalvik VM instance
      • Loads classes and listens on socket for requests to spawn VMs
      • Forks on request to create VM instances for managed processes
      • Copy-on-write to maximize re-use and minimize footprint
    • Init starts runtime process:
      • Initializes Service Manager - the context manager for Binder that handles service registration and lookup
      • Registers Service Manager as default context manager for Binder services
    • Runtime process sends request for Zygote to start System Service
      • Zygote forks a new VM instance for the System Service process and starts the service
      • System Service starts the native system servers, including:
        • Surface Flinger, Audio Flinger
    • Native system servers register with Service Manager as IPC service targets:
    • System Service starts the Android managed services:
    • Android managed Services register with Service Manager:
    • After system server loads all services, the system is ready..
    • Each subsequent application is launched in it's own process

Layer Interaction
  • There are 3 main flavors of Android layer cake:
    • App -> Runtime Service -> lib
    • App -> Runtime Service -> Native Service -> lib
    • App -> Runtime Service -> Native Daemon -> lib
  • App -> Runtime Service -> lib
  • App -> Runtime Service -> Native Service -> lib
  • App -> Runtime Service -> Native Daemon -> lib




Posted by 삼스
Android2009. 7. 17. 17:19
http://yotteum.tistory.com/1

안드로이드에서 사용하는 언어는 자바이지만 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 삼스
Android/App개발2009. 7. 12. 00:15
안드로이드 sdk에 제공되는 어플말고 android full source에 들어있는 어플은 이클립스상에서 수정하려고 하면 관련 클래스들이 없어서 빌드가 안되는 문제가 있음.
이 경우 해결하기 위한 방법은 아래 2가지가 있음.

1. android.jar에서 필요로 하는 class들이 없는 경우 full source빌드후 생성된 class파일을 강제로 android.jar파일에 추가한뒤 이클립스에서 빌드하면 됨.

2. http://source.android.com/using-eclipse 에 따르는 방법.
Posted by 삼스