1. 기본적으로 Settings에서 TimeZone의 GMT값을 Android\bionic\libc\zoneinfo\
zoneinfo.dat 파일에서 불러와 처리를 합니다.

그래서 만약 Timezone의 GMT값을 수정하고 싶을 경우에는  zoneinfo.dat, 및 idx 를 재생성 해주어야 합니다.

기존 폴더에서 생성 했다면, 다시  Android\bionic\libc\zoneinfo\ 폴더안에 복사해 주면 됩니다.

2. 기타 추가 사항에 대해서 정리 예정입니다. 좋은 정보 가지고 있으시다면, 글 부탁드려요 ^^
 

Settings -> Date and Time -> Use 24-hour format 을 Default로 설정하는 방법에 대해서 정리해 보았습니다.

일단 Use 24-hour format 기능은 onResume에서 아래와 같이 동작을 합니다.

@Override
protected void onResume() {
 super.onResume();

   ...

 ((CheckBoxPreference)mTime24Pref).setChecked(is24Hour());

   ...

}

 

private boolean is24Hour() {
  return DateFormat.is24HourFormat(this);
}

 

위의 소스를 보시면 is24HourFormat 함수를 통해서 24시간인지 아닌지를 Return해줍니다.

여기서 is24HourFormat 함수를 보면 다음과 같은데 여기서 Settings.System.TIME_12_24란 Key값을 가진 Systemproperty의 값을 받아오는 것을 확인 하실수 있습니다.

하지만 최초 부팅시 또는 초기화후 부팅시에는 value값이 존재하지 않음으로 null이 됩니다.

/**
* Returns true if user preference is set to 24-hour format.
* @param context the context to use for the content resolver
* @return true if 24 hour time format is selected, false otherwise.
*/
public static boolean is24HourFormat(Context context) {
String value = Settings.System.getString(context.getContentResolver(),
Settings.System.TIME_12_24);

if (value == null) {
Locale locale = context.getResources().getConfiguration().locale;

synchronized (sLocaleLock) {
if (sIs24HourLocale != null && sIs24HourLocale.equals(locale)) {
return sIs24Hour;
}
}

java.text.DateFormat natural =
java.text.DateFormat.getTimeInstance(
java.text.DateFormat.LONG, locale);


if (natural instanceof SimpleDateFormat) {
SimpleDateFormat sdf = (SimpleDateFormat) natural;
String pattern = sdf.toPattern();

if (pattern.indexOf('H') >= 0) {
value = "24";
} else {
value = "12";
}

} else {
value = "12";
}

synchronized (sLocaleLock) {
sIs24HourLocale = locale;
sIs24Hour = !value.equals("12");
}
}


boolean b24 = !(value == null || value.equals("12"));
return b24;
}

value 값이 null이므로 시스템으로 부터 Locale의 값을 가지고 와서 Time format을 확인한 후 value값이 12인지 24인지에 따라서 True or False를 리턴하게 됩니다.

Format의 확인 형식은 다음과 같습니다.

yyyy MM dd HH:mm             :  24시간을 표시

yyyy MM dd hh:mm a           : 12시간을 표시

여기서 "h"란 pattern을 확인 한 후 시간을 구분하게 됩니다.

하지만 여기서 한가지 의문이 생기게 됩니다.

왜 Locale을 불러오는지 말입니다.

그래서 확인한 결과 각각의 나라별 시간 표시 형식이 구분되어 있기 때문에 Locale을 사용하는 것을 확인하였습니다.

예를 들면 en_US같은 경우는 12시간을 표시하고, de_DE 같은 경우는 24시간을 표시하게 됩니다.

그래서 Locale을 사용하게 되는 것입니다.

그리고 시간의 패턴을 표시하기 위해서는 is24HourFormat 란 함수를 사용하여 확인한 후 12시간을 표시할 것인지 24시간을 표시할 것인지를 소스상에서

구분하는 것을 확인 하실수 있을것입니다.

여기까지가 24시간인지 아닌지를 체크하는 프로세스입니다.

그러면 이제 Locale을 변경을 해야되는데 이 값의 변경은 보통 SetupWizard에서 처리를 해줍니다.

하지만 SetupWizard가 없을 경우에는 Default Locale로 설정을 해주는데, 이 값은 다음과 같은 경로의 MakeFile에서 설정을 해줍니다.

Android\device\samsung\YP-GS1\Product.mk

Android\device\samsung\YP-GS1\full_YP-GS1.mk

이 파일을 열어보면, 여러 설정들이 존재하는데 그 중에서 다음과 같은 부분을 확인 할 수 있습니다.

# Overrides

PRODUCT_MANUFACTURER:=samsung

PRODUCT_BRAND:=samsung

PRODUCT_NAME:=YP-GS1

PRODUCT_DEVICE:=YP-GS1

PRODUCT_LOCALES := en_GB \

en_US en_AU en_IE en_NZ en_ZA \

   de_AT de_CH de_DE \

   fr_FR fr_CH \

   it_IT \

   es_ES \

   es_US \

   nl_NL \

   pt_PT \

   pl_PL \

   tr_TR \

   ko_KR \

   ru_RU \

   bg_BG hr_HR cs_CZ da_DK nl_BE et_EE fi_FI el_GR \

   hu_HU is_IS ga_IE kk_KZ lv_LV lt_LT mk_MK no_NO \

   pt_PT ro_RO sr_RS sk_SK sl_SI sv_SE uk_UA

여기서 Product_locales부분을 확인 할 수 있는데 여기의 첫번째 값이 en_GB이냐 ko_KR이냐에 따라 최초 부팅시 Locale의 값이 바뀌게 됩니다.

그래서 만약 영국식 영어로 설정하고 싶을 경우에는 위와 같이 en_GB를 첫번째로 넣으시면 됩니다.

Locale Default 24 hour을 설정하는 방법은 다음과 같습니다.

Android/external/ICU4C/data/locales/en_GB.txt를 열어보면 다음과 같습니다.

 // ***************************************************************************

// *
// * Copyright (C) 2007 International Business Machines
// * Corporation and others.  All Rights Reserved.
// * Tool: com.ibm.icu.dev.tool.cldr.LDML2ICUConverter.java
// * Source File:<path>/common/main/en_GB.xml
// *
// ***************************************************************************
en_GB{
    NumberPatterns{
        "#,##0.###",
        "¤#,##0.00",
        "#,##0%",
        "#E0",
    }
    Version{"1.54"}
    calendar{
        gregorian{
            DateTimePatterns{
                "HH:mm:ss v",
                "HH:mm:ss z",
                "HH:mm:ss",
                "HH:mm",
                "EEEE, d MMMM yyyy",
                "d MMMM yyyy",
                "d MMM yyyy",
                "dd/MM/yyyy",
                "{1} {0}",
            }
        }
    }
    delimiters{
        alternateQuotationEnd{"”"}
        alternateQuotationStart{"“"}
        quotationEnd{"’"}
        quotationStart{"‘"}
    }
    zoneStrings{
        "meta:Europe_Central"{
            cu:int{1}
        }
        "meta:Europe_Eastern"{
            cu:int{1}
        }
        "meta:Europe_Western"{
            cu:int{1}
        }
    }
}

여기서 gregorian영역안에서 Format에 해당하는 부분들을 추가해야 합니다.
예를 들면, 
dayNames, monthNames, quarters 등을 추가하여야 하며, 이를 적용한 부분의 예는 다음과 같습니다.

 
 // ***************************************************************************
// *
// * Copyright (C) 2007 International Business Machines
// * Corporation and others.  All Rights Reserved.
// * Tool: com.ibm.icu.dev.tool.cldr.LDML2ICUConverter.java
// * Source File:<path>/common/main/en_GB.xml
// *
// ***************************************************************************
en_GB{
    NumberPatterns{
        "#,##0.###",
        "¤#,##0.00",
        "#,##0%",
        "#E0",
    }
    Version{"1.54"}
    calendar{
        gregorian{
            DateTimePatterns{
                "HH:mm:ss v",
                "HH:mm:ss z",
                "HH:mm:ss",
                "HH:mm",
                "EEEE, d MMMM yyyy",
                "d MMMM yyyy",
                "d MMM yyyy",
                "dd/MM/yyyy",
                "{1} {0}",
            }
dayNames{ format{ abbreviated{ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", } wide{ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", } } stand-alone{ narrow{ "S", "M", "T", "W", "T", "F", "S", } } }
monthNames{ format{ abbreviated{ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", } wide{ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December", } } stand-alone{ narrow{ "J", "F", "M", "A", "M", "J", "J", "A", "S", "O", "N", "D", } } } quarters{ format{ abbreviated{ "Q1", "Q2", "Q3", "Q4", } wide{ "1st quarter", "2nd quarter", "3rd quarter", "4th quarter", } } stand-alone{ narrow{ "1", "2", "3", "4", } } }
} } delimiters{ alternateQuotationEnd{"”"} alternateQuotationStart{"“"} quotationEnd{"’"} quotationStart{"‘"} } zoneStrings{ "meta:Europe_Central"{ cu:int{1} } "meta:Europe_Eastern"{ cu:int{1} } "meta:Europe_Western"{ cu:int{1} } } }

gregorian
 영역안에 Format 영역을 추가 한 후 icudt44l.dat 파일을 생성한 후 stubdata 폴더에 복사하면 됩니다.

'안드로이드' 카테고리의 다른 글

ICU4C 빌드 방법.  (0) 2011.06.22
Time Zone 수정 방법.  (0) 2011.06.22
안드로이드 OS의 기본언어(locale) 설정하기  (0) 2011.06.15
Locale에 따른 시간 포멧 설정.  (0) 2011.06.15
PowerManager 사용시 유의점.  (0) 2011.06.13
안드로이드의  현재 설정  언어/국가/timezone 등은 

/data/property 디렉토리에  

persist.sys.timezone
persist.sys.language
persist.sys.country

이런 파일명으로  저장되어 있습니다. 

설정에서  언어들 바꾸고,  위 위치에 가서  cat 등으로 보시면 저장된 값이 바뀌어 있는 것을 보실 수 있습니다. 


즉,  부팅시에  이 파일이 있으면  해당 언어로  안드로이드 OS가 구동이 된다는 것입니다. 



그럼,  위 파일을  저장해 주는  방법이  OS 빌드 중에 어딘가에 있겠지요. 

이것은  init.rc 파일에 적어주면 되더군요. 

OS의 소스 디렉토리 중에서  

vender/업체/프로젝트/  로 된 디렉토리에 가시면,  init.rc 파일이 있는데요. 

01.# killed by the kernel.  These are used in ActivityManagerService.
02.setprop ro.FOREGROUND_APP_ADJ 0
03.setprop ro.VISIBLE_APP_ADJ 1
04.setprop ro.SECONDARY_SERVER_ADJ 2
05.setprop ro.BACKUP_APP_ADJ 2
06.setprop ro.HOME_APP_ADJ 4
07.setprop ro.HIDDEN_APP_MIN_ADJ 7
08.setprop ro.CONTENT_PROVIDER_ADJ 14
09.setprop ro.EMPTY_APP_ADJ 15
10. 
11.# for  default langudage
12.setprop persist.sys.language ko
13.setprop persist.sys.country KR
14.setprop persist.sys.timezone Asia/Seoul


위의  아래쪽 3줄 처럼 넣어 줍니다. 

setprop 의  위치가 중요하지는 않을 수도 있는데요. 
전 저 위치에 넣었습니다. 

이렇게 해서 OS를 빌드하면, 

최초 실행시에도 한글로  나온답니다. 

출처 : http://www.androidpub.com/203240 

build\target\product\sdk.mk or core.mk 등에서 사용되기도 함.
 

설정의 언어 목록을 수정하는 방법은 바이너리 빌드시에 Product.mk 파일을 수정해 주면 된다.

기본적으로 Product.mk 파일은 device/[company]/[Project]/Product.mk 또는 [Project Name].mk로 존재 합니다. 

PRODUCT_LOCALES := en_US ko_KR 이렇게 작성하면 목록에는 영어와 한국어 두개만 나타나게 된다.
 
그리고 Locale Default로는 en_US로 사용됩니다.

getDateInstance

public static final DateFormat  getDateInstance(int style,
                                               Locale  aLocale)
지정된 로케일에 대해, 지정된 포맷 스타일을 가지는 일자 포매터를 가져옵니다.

파라미터:
style - 지정하는 포맷 스타일. 다음에 예를 나타냅니다. US 로케일에서의 M/d/yy 에 대한 SHORT
aLocale - 지정된 로케일
반환값:
일자 포매터

boolean isScreenOn ()

void goToSleep (long time)

void reboot (String reason)

void userActivity (long when, boolean noChangeLights)

 

화면의 켜짐을 조사하거나 즉시 화면을 끄거나 재부팅하는 등의 기능을 제공한다. 화면을 강제로 끄는 goToSleep 메서드는 전원 버튼을 누르지 않아도 프로그램이 소프트웨어적으로 슬립 모드로 들어갈 수 있어 실용성이 있다. 그러나 아무나 사용할 수 있는 메서드는 아니므로 엄격한 제한이 따른다. 이 메서드를 사용하려면 DEVICE_POWER 퍼미션이 필요하며 또 시스템 앱으로 서명을 해야 한다.

기존 package\res\Value\strings.xml에서 선언된 문구에서 리소스에서
추가적으로 package\test_Model\res\Value\strings.xml를 이용하여 Resource Value의 값을 추가할 경우.

사용법
<add-resource type="string" name="no_action"></add-resource>
<string name="no_action">No</string> 

예>
======================================================= 
package\res\Value\strings.xml

<String id="test1"> test 1</String>
<String id="test2"> test 2</String>
<String id="test3"> test 3</String>
======================================================= 


======================================================= 
package\test_Model\res\Value\strings.xml
<add-resource type="string" name="test4"></add-resource>
<String id="test4"> test 4</String>

=======================================================

위와 같이 사용하게 되면 실질적으로는 다음과 같음.

======================================================= 

Resource : Strings.xml

<String id="test1"> test 1</String>
<String id="test2"> test 2</String>
<String id="test3"> test 3</String>
<String id="test4"> test 4</String>
=======================================================

안드로이드는 리눅스 커널을 이용한다. 따라서 리눅스의 시작 시퀀스 이후에 안드로이드 고유 시스템이 동작하게 된다.

기본적인 동작을 잘 설명한 곳( http://samse.tistory.com/112?srchid=BR1http%3A%2F%2Fsamse.tistory.com%2F112 )이 있어서 일부 발췌해 온다.


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

init은 /system/core/init 디렉토리에 관련 소스가 있다. init.rc 파일은 /system/core/rootdir/에 있다.

init이 하는 일과 init.rc 파일을 작성하는 방법에 대해서는 여기(http://www.aesop.or.kr/?document_srl=46566 )를 참조한다.

init이 하는 일을 정리하면 다음과 같다.

1. log system 초기화

2. /init.rc와 /init.%hardware$.rc 파일 파싱

3. 2번 스텝의 2개 파일에서 초기 선동작(early-init action) 수행

4. 디바이스 종속적인 초기화 작업 (예를 들어 /dev 에 모든 디바이스 노드 만듬)

5. property system 초기화 (property system은 공유 메모리로 동작하며 윈도우의 레지스트리와 같은 역활이다)

6. 2번 스텝의 2개 파일에서 초기 동작(init action) 수행

7. property service 시작

8. 2번 스텝의 2개 파일에서 선부팅(early boot), 부팅(boot) 동작 수행

9. 2번 스텝의 2개 파일에서 property 동작 수행

10. device/property가 /child process를 셋할때까지 대기하면서 rc 파일에 정의된 명령어를 수행한다.

위의 설명처럼 /out/target/product/XXX/init.rc 를 먼저 살펴 보자. 위에서 설명한 것처럼 폴더 권한 설정 등의 초기화 작업을 하고 나면

Demon을 올리는 작업을 하도록 되어 있다. 이를 정리하면 다음과 같다.

1) console : shell 을 시작 (system/core/sh/)

## Daemon processes to be run by init.
##
service console /system/bin/sh
console

2) abdb : abdb daemon을 시작 (system/core/adb/)

# adbd on at boot in emulator
on property:ro.kernel.qemu=1
start adbd

on property:persist.service.adb.enable=1
start adbd

on property:persist.service.adb.enable=0
stop adbd

3) servicemanager : binder system을 시작 (framework/base/cmds/servicemanager/)

service servicemanager /system/bin/servicemanager
user system
critical
onrestart restart zygote
onrestart restart media

4) vold : volume daemon 시작 (system/core/vold/)

service vold /system/bin/vold
socket vold stream 0660 root mount

#service mountd /system/bin/mountd
# socket mountd stream 0660 root mount

5) debuggerd : debug system을 시작 (system/debuggerd/)

service debuggerd /system/bin/debuggerd

6) rild : radio interface layer daemon을 시작 (hardware/ril/rild/)

service ril-daemon /system/bin/rild
socket rild stream 660 root radio
socket rild-debug stream 660 radio system
user root
group radio cache inet misc

7) Zygote : (frameworks/base/cmds/app_process/)

service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
socket zygote stream 666
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on

8) media : AudioFlinger, MediaPlayerService, CameraService를 시작 (frameworks/base/media/mediaserver/)

service media /system/bin/mediaserver
user media
group system audio camera graphics inet net_bt net_bt_admin

관련 코드를 보면 굉장히 간단하다. (framework/base/media/mediaserver/main_mediaserver.cpp)

int main(int argc, char** argv)
{
sp<ProcessState> proc(ProcessState::self());
sp<IServiceManager> sm = defaultServiceManager();
LOGI("ServiceManager: %p", sm.get());
AudioFlinger::instantiate();
MediaPlayerService::instantiate();
CameraService::instantiate();

ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
}

9) bootsound : boot sound (system/media/audio/ui/boot.mp3)를 재생, (그런데 이 바이너리는 실제 찾을 수 없네...?. 그리고 샘플 파일도 안 만들어 지네)

service bootsound /system/bin/playmp3
user media
group audio
oneshot

10) dbus : dbus daemon 시작 (BlueZ 즉 Bluetooth 관련 서비스) (external/dbus/bus/)

service dbus /system/bin/dbus-daemon --system --nofork
socket dbus stream 660 bluetooth bluetooth
user bluetooth
group bluetooth net_bt_admin

11) hcid : hcid의 stdout, stdin을 안드로이드 logging sytstem으로 redirect (external/bluez/hcid/)

service hcid /system/bin/hcid -s -n -f /etc/bluez/hcid.conf
socket bluetooth stream 660 bluetooth bluetooth
socket dbus_bluetooth stream 660 bluetooth bluetooth
# init.rc does not yet support applying capabilities, so run as root and
# let hcid drop uid to bluetooth with the right linux capabilities
group bluetooth net_bt_admin misc
disabled

12) hfag : Bluetooth handsfree audio gateway 시작 (BlueZ 만 사용) (external/bluez/utils/tools/)

service hfag /system/bin/sdptool add --channel=10 HFAG
user bluetooth
group bluetooth net_bt_admin
disabled
oneshot

13) hsag : Bluetooth headset audio gateway 시작 (BlueZ 만 사용) (external/bluez/utils/tools/)

service hsag /system/bin/sdptool add --channel=11 HSAG
user bluetooth
group bluetooth net_bt_admin
disabled
oneshot

14) install : install package daemon 시작 (frameworks/cmds/installd/)

service installd /system/bin/installd
socket installd stream 600 system system

15) flash_recovery : /system/recovery.img를 로드 (bootable/recovery/mtdutils/)

service flash_recovery /system/bin/flash_image recovery /system/recovery.img
oneshot

강조한 것처럼 바와 같이 servicemanager을 이용해서 zygote와 media를 시작하고 SD 카드와 USB의 mount 등을 처리하는 vold 데몬을 올린다. 이후 부팅 사운드를 재생하거나 다른 필요한 데몬들을 올리게 된다. 이후 다시 강조한 부분을 보면 zygote를 이용해서 system server 를 시작한다. 이후 media를 다시 시작한다(?)

안드로이드의 system server는 Native Service와 여러가지 기본 서비스(core system service 라고도 한다)들로 이루어진다.

/framework/base/cmds/system_server/library/system_init.cpp 를 보면 system_init() 함수가 있다. 이 파일은 실제 사용한다기 보다는 초기화 흐름을 알게 해주는 코드로 보인다.

extern "C" status_t system_init()
{
LOGI("Entered system_init()");

sp<ProcessState> proc(ProcessState::self());

sp<IServiceManager> sm = defaultServiceManager();
LOGI("ServiceManager: %p\n", sm.get());

sp<GrimReaper> grim = new GrimReaper();
sm->asBinder()->linkToDeath(grim, grim.get(), 0);

char propBuf[PROPERTY_VALUE_MAX];
property_get("system_init.startsurfaceflinger", propBuf, "1");
if (strcmp(propBuf, "1") == 0) {
// Start the SurfaceFlinger
SurfaceFlinger::instantiate();
}

// On the simulator, audioflinger et al don't get started the
// same way as on the device, and we need to start them here
if (!proc->supportsProcesses()) {

// Start the AudioFlinger
AudioFlinger::instantiate();

// Start the media playback service
MediaPlayerService::instantiate();

// Start the camera service
CameraService::instantiate();
}

// And now start the Android runtime. We have to do this bit
// of nastiness because the Android runtime initialization requires
// some of the core system services to already be started.
// All other servers should just start the Android runtime at
// the beginning of their processes's main(), before calling
// the init function.
LOGI("System server: starting Android runtime.\n");

AndroidRuntime* runtime = AndroidRuntime::getRuntime();

LOGI("System server: starting Android services.\n");
runtime->callStatic("com/android/server/SystemServer", "init2");

// If running in our own process, just go into the thread
// pool. Otherwise, call the initialization finished
// func to let this process continue its initilization.
if (proc->supportsProcesses()) {
LOGI("System server: entering thread pool.\n");
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
LOGI("System server: exiting thread pool.\n");
}
return NO_ERROR;
}

코드를 보면 알겠지만 크게 다음 순서로 초기화 과정이 이루어진다.

1. Native Service 초기화

SurfaceFlinger

AudioFlinger

MediaPlayerService

CameraService

2. Android RunTime 시작

SystemServer

안드로이드가 동작하기 위한 여러가지 기본 서비스들(또는 JAVA 서비스)을 시작하는 곳이 SystemServer이다.

파일 위치는 다음과 같다.

/frameworks/base/services/java/com/android/server/SystemServer.java

SystemServer 클래스는 init2() 함수를 호출하게되면 ServerThread를 동작시키고 여기에서 다양한 서비스들을 시작한다.

서비스 시작하는 순서대로 대충 정리하면 다음과 같다.(run 함수의 내용을 그냥 정리한 것이며 * 표시 없는 것은 주서비스이고 * 표시 있는 것은 부가 서비스이다)

Power Manager 시작

Activity Manager 생성

ActivityManager를 생성해서 context를 받으면 이후 서비스들에는 context를 전달한다.

(아직 이 구조는 잘 모르겠지만 서비스들에서 설정이나 특정 이벤트들을 브로드 캐스팅하기 위해서는 context를 이용해야 하는 것 같다. ActivityManger에서 이를 위한 초기화 과정이 이루어지고 이후 서비스들은 context를 가지고 서로간의 통신이나 Focus 이동이 생길 수 있도록 하고 있는 것 같다. 이것은 아직은 어디까지나 추측이다.)

Telephony Registry 시작

Package Manager 시작

System Process로 Activity Manager 설정

Context Manager 시작

System Context Providers 시작

Battery Service 시작

* Hardware Service 시작

Alarm Manager 시작

Sensor Service 시작

Window Manager 시작

Bluetooth Service 시작

BluetoothDeviceService

BluetoothA2dpService

*Status Bar Service 시작

ClipboardService

InputMethodManagerService

*NetStat Service 시작

*Connectivity Service 시작

*Notification Manager 시작

Mount Service 시작

*DeviceStorageMonitor Service 시작

*Location Manager 시작

*SearchManager Service 시작

*Clipboard Service 시작

*Fallback Checkin Service 시작

*WallpaperService 시작

*Audio Service 시작

*Headset Observer 시작

(?)AppWidgetService

*AdbSettingsObserver 시작

(?)HDMISettingsObserver 시작


Key events executed on key-up

Android 2.0 is designed to run on devices that use virtual keys for HOME, MENU, BACK, and SEARCH, rather than physical keys. To support the best user experience on those devices, the Android platform now executes these buttons at key-up, for a key-down/key-up pair, rather than key-down. This helps prevent accidental button events and lets the user press the button area and then drag out of it without generating an event.

This change in behavior should only affect your application if it is intercepting button events and taking an action on key-down, rather than on key-up. Especially if your application is intercepting the BACK key, you should make sure that your application is handling the key events properly.

In general, intercepting the BACK key in an application is not recommended, however, if your application is doing so and it invokes some action on key-down, rather than key-up, you should modify your code.

If your application will use APIs introduced in Android 2.0 (API Level 5), you can take advantage of new APIs for managing key-event pairs:

  • If you are intercepting the BACK key in an activity or dialog, just implement the new onBackPressed() method.
  • If you are intercepting the BACK key in a view, you should track the key event on key-down (through the new startTracking() method), then invoke the action at key up. Here's a pattern you can use:

http://docs.androidside.com/docs/sdk/android-2.0.html
        public boolean onKeyDown(int keyCode, KeyEvent event) {
           
    if (keyCode == KeyEvent.KEYCODE_BACK
                   
    && event.getRepeatCount() == 0) {
               
    event.startTracking();
               
    return true;
           
    }
           
    return super.onKeyDown(keyCode, event);
       
    }

       
    public boolean onKeyUp(int keyCode, KeyEvent event) {
           
    if (keyCode == KeyEvent.KEYCODE_BACK && event.isTracking()
                   
    && !event.isCanceled()) {
               
    // *** DO ACTION HERE ***
               
    return true;
           
    }
           
    return super.onKeyUp(keyCode, event);
       
    }

If you want to update a legacy application so that its handling of the BACK key works properly for both Android 2.0 and older platform versions, you can use an approach similar to that shown above. Your code can catch the target button event on key-down, set a flag to track the key event, and then also catch the event on key-up, executing the desired action if the tracking flag is set. You'll also want to watch for focus changes and clear the tracking flag when gaining/losing focus.

Android 에서 key, touch, trackball 같은 event의 경우에는 WindowManagerService라는 서비스에서 Event Dispatch에 의해서 관리가 됩니다.
Event Dispatch 경로를 간단히 나타내면 아래와 같습니다.
 
문제는 이 WindowManagerService에서 이벤트를 Dispatch할 때
Home Key와 Power(Endcall) Key의 경우에는 Event를 받을 View에 Dispatch하기 전에
먼저 HomeKey와 Power(Endcall)Key의 작업을 수행한 후 Dispatch시키지 않는 다는 것입니다.
 
이는 안드로이드 키이벤트 정책 상의 이유로
PhoneWindowManager의 interceptKeyTi(HomeKey관련) interceptKeyTq(Power,Endcall Key관련)함수에
해당 작업이 정의되어 있습니다.
 
실제로 이 두 함수를 수정하면 Event를 해당 View까지 Dispatch 시킬 수 있지만…
권장되는 사항은 아닙니다.
 
이와 같은 이유로 HomeKey와 Power(Endcall)Key는 keydown,up 과 같은 함수로 인식 할 수 없는 것입니다.

출처 : http://blog.naver.com/realwind/20119124672 

'안드로이드' 카테고리의 다른 글

안드로이드 부팅 순서  (0) 2011.05.16
Key events executed on key-up  (0) 2011.05.12
Thread 우선순위 설정.  (0) 2011.05.03
Looper  (0) 2011.05.03
DIP를 px로 변환하기  (0) 2011.04.21

public class SchedulingTest4 {

    public static void main(String args[]) {
        Thread[] t = new RunThread4[3];
    
        t[0] = new RunThread4("☆");
        t[0].start(); 
        t[0].setPriority(1);  // ☆ 가장 느린 우선 순위
        
        t[1] = new RunThread4("◑");        
        t[1].start();
        t[1].setPriority(5);

        t[2] = new RunThread4("○");        
        t[2].start();        
        t[2].setPriority(10); // ○ 가장 빠른 우선 순위
        /*
        System.out.println("t[0]" + t[0].getPriority());
        System.out.println("t[1]" + t[1].getPriority());
        System.out.println("t[2]" + t[2].getPriority());
        */        
    } 
}

+ Recent posts