poll 에서 사용하는 timeout 변수의 계산은 재 시작해야 하는 서비스의 시작 시간을 맞추기 위해서 입니다. 재 시작 할 서비스는 이전에 시작 한 시간에서 5 초 후에 재 시작을 해주는 룰을 적용하고 있습니다.

서비스가 시작되면 time_started 에 시작 시간을 지정합니다.
서비스의 시작은 service_start 함수에서 처리하며, 이 함수의 마지막 단계에서 서비스의 시작 시간을 gettime() 으로 지정합니다.
( gettime() 은 초 단위로 리턴합니다. )

svc->time_started = gettime();

다음은 init 의 메인 루프 코드 입니다.
여기서 중요한 것들은 restart_processes, process_needs_restart, timeout , wait_for_one_process 의 관계입니다.

 

for(;;) {
    :
        restart_processes();

        if (process_needs_restart) {
            timeout = (process_needs_restart - gettime()) * 1000;
            if (timeout < 0)
                timeout = 0;
        }

        nr = poll(ufds, fd_count, timeout);
        if (nr <= 0)
            continue;

        if (ufds[2].revents == POLLIN) {
            /* we got a SIGCHLD - reap and restart as needed */
            read(signal_recv_fd, tmp, sizeof(tmp));
            while (!wait_for_one_process(0))
                ;
            continue;
        }
     :
    }

서비스가 종료 되어, SIGCHLD 시그널을 받으면( 여러 논의가 있었지만 여기서는 이것만 주목 하겠습니다.)
wait_for_one_process 함수를 호출 합니다.
wait_for_one_process 에서 주목 할 점은 해당 서비스의 flags 에 SVC_RESTARTING 속성을 더합니다.
실제로 재 시작 시키지는 않습니다.

svc->flags |= SVC_RESTARTING;

이후 init 의 for 루프를 다시 돌아서 restart_processes 를 호출 합니다.

static void restart_processes()
{
    process_needs_restart = 0;
    service_for_each_flags(SVC_RESTARTING,
                           restart_service_if_needed);
}

restart_processes 함수에서 process_needs_restart 변수를 0 으로 초기화 하고,
서비스 리스트 중에서 flags 에 SVC_RESTARTING 속성이 있는 것에 한해서 restart_service_if_needed 함수를 호출 합니다.
여기서 주목할 점은 링크드 리스트를 돈다는 것입니다. process_needs_restart 를 restart_service_if_needed 함수 내에서 설정 또는 변경 하는데, 모든 리스트가 다 돌고 난 후에 그 process_needs_restart 값이 init 에서 사용 됩니다.

 

static void restart_service_if_needed(struct service *svc)
{
    time_t next_start_time = svc->time_started + 5;

    if (next_start_time <= gettime()) {
        svc->flags &= (~SVC_RESTARTING);
        service_start(svc);
        return;
    }

    if ((next_start_time < process_needs_restart) ||
        (process_needs_restart == 0)) {
        process_needs_restart = next_start_time;
    }
}

restart_service_if_needed 함수에서는 svc->time_started 변수를 참조하는데, 이는 위에서도 설명 했듯이
서비스의 시작 시간 이였습니다. next_start_time 변수는 서비스가 이전에 시작 되었던 시간에서 5초를 더한 시간입니다.

결국 서비스가 재 시작 되어야 할 시간입니다. 서비스가 재 시작되어야 할 시간이 지났으면, service_start 함수를 호출해서 해당 서비스를 시작 시킴니다.
아직 재 시작 시킬 시간이 안되었다면, process_needs_restart 를 갱신하게 됩니다.

process_needs_restart 값이 초기값(0)이면, 지금 서비스의 재 시작 시간으로 갱신 되지만,
이 서비스 보다 링크드 리스트의 이전에 있던 서비스에 의해 갱신된 process_needs_restart 값을 가질 수도  있습니다.
그래서 지금 서비스의 재 시작 시간이 이전 서비스의 재 시작 시간보다 작으면, 지금 서비스의 재 시작 시간으로 process_needs_restart 를 갱신합니다.


결국 재시작 하려고 하는 서비스 중 가장 먼저 재 시작 되어야 할 시간으로 process_needs_restart 가 갱신 됩니다.

다시 init 으로 돌아 와서

      if (process_needs_restart) {
            timeout = (process_needs_restart - gettime()) * 1000;
            if (timeout < 0)
                timeout = 0;
        }

 

timeout 값은 재 시작 되어야 할 서비스들 중에서 가장 먼저 재 시작 할 서비스의 재 시작 시간 만큼을 위한 대기 시간이 지정됩니다.

그리고 그 값을 poll 의 timeout 으로 지정합니다. poll 의 timeout 발생후 다시 restart_processes 함수를 호출 하게 됩니다.

'안드로이드 > 플랫폼' 카테고리의 다른 글

service_manager 흐름  (0) 2009.08.25
init 분석 open 하는 디바이스 - null, kmsg  (0) 2009.08.18
init 분석 - firmware  (0) 2009.07.28
init 분석 - 안드로이드 보안 및 권한  (0) 2009.07.28
프로세스, 기본 환경  (0) 2009.07.28
Posted by blee
,

오늘날 리눅스 커널에서 firmware를 사용하는 가장 광범위한 방법은 header file 에 static 하게 link 하는 것입니다.
이는 정책적으로 기술적으로 다음과 같은 이슈가 있습니다.

1. 드라이버의 firmware 는 업그레이드 되어 재배포 될 수 있습니다.
2. 비록 단 한번의 사용 일지라도 static 하게 link 된 firmware 는 영구히 메모리를 차지 합니다.
3. 사용자들은 firmware 를 메모리에서 해제하고, 드라이버를 제거하는 것에 대해 신경쓰지 않습니다.

그러한 이유로 request_firmware() 와 hotplug 간의 interface 나오게 된 것입니다.

다음의 리눅스에서 driver 와 hotplug 간의 일련의 절차 입니다.

kernel 에서 처리 : 
driver 초기화 시에 request_firmware 함수를 호출합니다.

  if(request_firmware(&fw_entry, $FIRMWARE, device) == 0)
  copy_fw_to_device(fw_entry->data, fw_entry->size);
 release(fw_entry);

$FIRMWARE 는 파일 이름입니다. 이는 제조사에서 배포되는 특정 hw가 동작 되도록 하는 code image 일 것입니다.
request_firmware -> _request_firmware -> fw_setup_device 함수를 거치면서,
/sys/class/firmware/xxx/loading, /sys/class/firmware/xxx/data 파일을 생성합니다.
 
( hotplug 를 호출 하기 전에 firmware 를 __start_builtin_fw ~ __end_builtin_fw 영역에서 먼저 찾습니다.
이는 kernel 에 static 하게 포함된 firmware 들 중에 맞는 것이 있는지 먼저 검색합니다. 이 영역에 있다면
hotplug 관련 절차를 거치지 않습니다. )
 
그리고 사용자 공간의 hotplug 가 호출 됩니다.
request_firmware 함수는 block 됩니다.

( /sys/class/firmware/timeout 에 지정된 시간 만큼 입니다. )

사용자 공간 - hotplug 에서 처리 :

사용자 영역에서 /sys/class/firmware/xxx/loading, /sys/class/firmware/xxx/data 파일이 나타나며,
 $DEVPATH, $FIRMWARE 는 환경변수로 전달 됩니다.

 HOTPLUG_FW_DIR=/usr/lib/hotplug/firmware/

 echo 1 > /sys/$DEVPATH/loading
 cat $HOTPLUG_FW_DIR/$FIRMWARE > /sysfs/$DEVPATH/data
 echo 0 > /sys/$DEVPATH/loading

 /sys/$DEVPATH/loading 에 1 를 write 하므로써, firmware 복사가 시작됨을 알립니다.
펌웨어 파일 $HOTPLUG_FW_DIR/$FIRMWARE 를 /sysfs/$DEVPATH/data 로 복사를 합니다.
/sys/$DEVPATH/loading 에 0 를 write 하므로써, firmware 복사가 완료됨을 알립니다. request_firmware 함수는 성공을 리턴합니다.
/sys/$DEVPATH/loading 에 -1 를 write 하면, 중지되며, request_firmware 함수는 실패를 리턴합니다.
 
kernel 에서 처리 :
request_firmware() 함수가 return 되면, fw_entry->data, fw_entry->size 에 firmware와 size 정보가 저장됩니다.
이를 driver 에서 특정 hw 에 맞는 작업을 수행하면 됩니다.

사용자 공간으로 전달되는 환경변수 :

SUBSYSTEM=module
DEVPATH=/module/firmware_sample_driver
LD_LIBRARY_PATH=:/user/app/lib
PATH=/sbin:/bin:/usr/sbin:/usr/bin:/user/app/bin
ACTION=add
PWD=/
SHLVL=1
HOME=/
SEQNUM=933
_=/usr/bin/env

정리 :
안드로이드 플래폼의 init 에서 uevent 를 이용하여, add 절차를 거치면서, firmware 를 필요로 하는 driver에서
firmware 를 전달 하는 과정(hotplug 와 driver 사이의 일어나는 일련의 절차)를 처리 해주고 있는 것입니다.

static int load_firmware(int fw_fd, int loading_fd, int data_fd)
{
    struct stat st;
    long len_to_copy;
    int ret = 0;

    if(fstat(fw_fd, &st) < 0)                     <--(주석) fstat는 열린 파일이나 핸들과 연관된 디렉토리의 정보를 stat 구조체에 저장
        return -1;
    len_to_copy = st.st_size;

//------------------------------------------------------------ 
//! echo 1 > /sys/$DEVPATH/loading
//------------------------------------------------------------ 
    write(loading_fd, "1", 1);  /* start transfer */

//------------------------------------------------------------ 
//! cat $HOTPLUG_FW_DIR/$FIRMWARE > /sysfs/$DEVPATH/data
//------------------------------------------------------------ 
    while (len_to_copy > 0) {
        char buf[PAGE_SIZE];
        ssize_t nr;

        nr = read(fw_fd, buf, sizeof(buf));    
        if(!nr)
            break;
        if(nr < 0) {
            ret = -1;
            break;
        }

        len_to_copy -= nr;
        while (nr > 0) {
            ssize_t nw = 0;

            nw = write(data_fd, buf + nw, nr); 
            if(nw <= 0) {
                ret = -1;
                goto out;
            }
            nr -= nw;
        }
    }

//------------------------------------------------------------ 
// echo 0 > /sys/$DEVPATH/loading 
//------------------------------------------------------------ 
out:
    if(!ret)
        write(loading_fd, "0", 1);  /* successful end of transfer */
    else
        write(loading_fd, "-1", 2); /* abort transfer */

    return ret;
}

참고 :  
kernel/Documentation/firmware_class/README
linux device driver model 관련 문서


Posted by blee
,

http://d.android.com/guide/topics/security/security.html

위 사이트는 안드로이드 security, permission 정책에 관한 문서 입니다.

문서의 서론만 옮겨 봤습니다.

Security and Permissions
Android is a multi-process system, in which each application (and parts of the system) runs in its own process. Most security between applications and the system is enforced at the process level through standard Linux facilities, such as user and group IDs that are assigned to applications. Additional finer-grained security features are provided through a "permission" mechanism that enforces restrictions on the specific operations that a particular process can perform, and per-URI permissions for granting ad-hoc access to specific pieces of data.
보안 및 권한
안드로이드는 멀티-프로세스 시스템이다, 시스템의 각 응용 프로그램은 자체 프로세스에서 실행됩니다. 응용 프로그램과 시스템 사이의 대부분의 보안은 프로세스 수준에서 애플리케이션에 할당된 사용자와 그룹 ID등으로 표준 리눅스 환경을 통해 시행됩니다. 추가적인 세밀한 보안 기능은 특정 프로세스 수행 할수 있는 구체적인 작업에 대한 제한을 적용하는 "permission" 메커니즘과 지정된 데이타에 ad-hoc 접권의 하가를 위한 per-URI 권한을 통해 제공되어 집니다.

이미 알고 있듯이 전통적인 linux 환경의 /etc/passwd 파일을 이용한 사용자 및 /etc/group 파일을 이용한 그룹 설정을 사용하지 않는 다는 것이 인상적입니다.

application 권한은 설치할때, 이러한 permission 이 결정되고, 이 후 변경하지 못 한다라고 하는데, 모든 안드로이드 어플리케이션은 AndroidManifest.xml 파일을 가지고 있으며, 이 파일을 통해서 권한 설정을 합니다. 그리고 안드로이드 어플리케이션은 인증서로 서명을 해야 합니다. 이 부분은 프로그램을 직접 만들어 봐야 겠네요 -_-;

안드로이드 어플리케이션에 대한 분석이라는 글에서 AndroidManifest.xml 파일에 대한 언급이 있어서 링크 합니다.  http://breathair.tistory.com/70

그렇다면, 안드로이드는 어떠한 사용자와 그룹으로 관리하는가? 이에 대한 인터넷 자료를 구할 수가 없었습니다. 그래서 직접 소스를 올렸습니다.

android_filesystem_config.h 파일에 USER ID, GROUP ID 가 정의 되어 있습니다.
( 소스경로 : system/core/include/private/android_filesystem_config.h )

android_dirs, android_files 의 배열은 mkrootfs 와 mkyaffs2image 툴로 루트 파일 시스템을 만들 때 적용된다고 주석에 나와 있습니다.
( mkbootfs 소스경로 : system/core/cpio/mkbootfs.c )

devices.c 에 정의된 devperms 배열은 init 에서 uevent 처리 하며, /dev/ 이하 파일을 만들어 줍니다.
( 소스경로 : system/core/init/devices.c )

USER ID와 GROUP ID 를 아래와 같이 분류해논 이유를 찾을려고 했는데, 잘 못 찾겠네요. -_-;

//---------------------------------------------------------------------------
// system/core/include/private/android_filesystem_config.h
//---------------------------------------------------------------------------
/* This is the master Users and Groups config for the platform.
** DO NOT EVER RENUMBER.
*/

#define AID_ROOT             0  /* traditional unix root user */
#define AID_SYSTEM        1000  /* system server */
#define AID_RADIO         1001  /* telephony subsystem, RIL */
#define AID_BLUETOOTH     1002  /* bluetooth subsystem */
#define AID_GRAPHICS      1003  /* graphics devices */
#define AID_INPUT         1004  /* input devices */
#define AID_AUDIO         1005  /* audio devices */
#define AID_CAMERA        1006  /* camera devices */
#define AID_LOG           1007  /* log devices */
#define AID_COMPASS       1008  /* compass device */
#define AID_MOUNT         1009  /* mountd socket */
#define AID_WIFI          1010  /* wifi subsystem */
#define AID_ADB           1011  /* android debug bridge (adbd) */
#define AID_INSTALL       1012  /* group for installing packages */
#define AID_MEDIA         1013  /* mediaserver process */
#define AID_DHCP          1014  /* dhcp client */
#define AID_SHELL         2000  /* adb and debug shell user */
#define AID_CACHE         2001  /* cache access */
#define AID_DIAG          2002  /* access to diagnostic resources */

/* The 3000 series are intended for use as supplemental group id's only.
 * They indicate special Android capabilities that the kernel is aware of. */
#define AID_NET_BT_ADMIN  3001  /* bluetooth: create any socket */
#define AID_NET_BT        3002  /* bluetooth: create sco, rfcomm or l2cap sockets */
#define AID_INET          3003  /* can create AF_INET and AF_INET6 sockets */
#define AID_NET_RAW       3004  /* can create raw INET sockets */
#define AID_MISC          9998  /* access to misc storage */
#define AID_NOBODY        9999
#define AID_APP          10000 /* first app user */

static struct android_id_info android_ids[] = {
    { "root",      AID_ROOT, },
    { "system",    AID_SYSTEM, },
    { "radio",     AID_RADIO, },
    { "bluetooth", AID_BLUETOOTH, },
    { "graphics",  AID_GRAPHICS, },
    { "input",     AID_INPUT, },
    { "audio",     AID_AUDIO, },
    { "camera",    AID_CAMERA, },
    { "log",       AID_LOG, },
    { "compass",   AID_COMPASS, },
    { "mount",     AID_MOUNT, },
    { "wifi",      AID_WIFI, },
    { "dhcp",      AID_DHCP, },
    { "adb",       AID_ADB, },
    { "install",   AID_INSTALL, },
    { "media",     AID_MEDIA, },
    { "shell",     AID_SHELL, },
    { "cache",     AID_CACHE, },
    { "diag",      AID_DIAG, },
    { "net_bt_admin", AID_NET_BT_ADMIN, },
    { "net_bt",    AID_NET_BT, },
    { "inet",      AID_INET, },
    { "net_raw",   AID_NET_RAW, },
    { "misc",      AID_MISC, },
    { "nobody",    AID_NOBODY, },
};

/* Rules for directories.
** These rules are applied based on "first match", so they
** should start with the most specific path and work their
** way up to the root.
*/

static struct fs_path_config android_dirs[] = {
    { 00770, AID_SYSTEM, AID_CACHE,  "cache" },
    { 00771, AID_SYSTEM, AID_SYSTEM, "data/app" },
    { 00771, AID_SYSTEM, AID_SYSTEM, "data/app-private" },
    { 00771, AID_SYSTEM, AID_SYSTEM, "data/dalvik-cache" },
    { 00771, AID_SYSTEM, AID_SYSTEM, "data/data" },
    { 00771, AID_SHELL,  AID_SHELL,  "data/local/tmp" },
    { 00771, AID_SHELL,  AID_SHELL,  "data/local" },
    { 01771, AID_SYSTEM, AID_MISC,   "data/misc" },
    { 00770, AID_DHCP,   AID_DHCP,   "data/misc/dhcp" },
    { 00771, AID_SYSTEM, AID_SYSTEM, "data" },
    { 00750, AID_ROOT,   AID_SHELL,  "sbin" },
    { 00755, AID_ROOT,   AID_SHELL,  "system/bin" },
    { 00755, AID_ROOT,   AID_SHELL,  "system/xbin" },
    { 00777, AID_ROOT,   AID_ROOT,   "system/etc/ppp" }, /* REMOVE */
    { 00777, AID_ROOT,   AID_ROOT,   "sdcard" },
    { 00755, AID_ROOT,   AID_ROOT,   0 },
};


/* Rules for files.
** These rules are applied based on "first match", so they
** should start with the most specific path and work their
** way up to the root. Prefixes ending in * denotes wildcard
** and will allow partial matches.
*/
static struct fs_path_config android_files[] = {
    { 00555, AID_ROOT,      AID_ROOT,      "system/etc/ppp/ip-up" },
    { 00555, AID_ROOT,      AID_ROOT,      "system/etc/ppp/ip-down" },
    { 00440, AID_ROOT,      AID_SHELL,     "system/etc/init.goldfish.rc" },
    { 00550, AID_ROOT,      AID_SHELL,     "system/etc/init.goldfish.sh" },
    { 00440, AID_ROOT,      AID_SHELL,     "system/etc/init.trout.rc" },
    { 00550, AID_ROOT,      AID_SHELL,     "system/etc/init.ril" },
    { 00550, AID_ROOT,      AID_SHELL,     "system/etc/init.testmenu" },
    { 00550, AID_ROOT,      AID_SHELL,     "system/etc/init.gprs-pppd" },
    { 00550, AID_DHCP,      AID_SHELL,     "system/etc/dhcpcd/dhcpcd-run-hooks" },
    { 00440, AID_BLUETOOTH, AID_BLUETOOTH, "system/etc/dbus.conf" },
    { 00440, AID_BLUETOOTH, AID_BLUETOOTH, "system/etc/bluez/hcid.conf" },
    { 00440, AID_BLUETOOTH, AID_BLUETOOTH, "system/etc/bluez/input.conf" },
    { 00440, AID_BLUETOOTH, AID_BLUETOOTH, "system/etc/bluez/audio.conf" },
    { 00440, AID_RADIO,     AID_AUDIO,     "/system/etc/AudioPara4.csv" },
    { 00644, AID_SYSTEM,    AID_SYSTEM,    "data/app/*" },
    { 00644, AID_SYSTEM,    AID_SYSTEM,    "data/app-private/*" },
    { 00644, AID_APP,       AID_APP,       "data/data/*" },
        /* the following two files are INTENTIONALLY set-gid and not set-uid.
         * Do not change. */
    { 02755, AID_ROOT,      AID_NET_RAW,   "system/bin/ping" },
    { 02755, AID_ROOT,      AID_INET,      "system/bin/netcfg" },
        /* the following four files are INTENTIONALLY set-uid, but they
     * are NOT included on user builds. */
    { 06755, AID_ROOT,      AID_ROOT,      "system/xbin/su" },
    { 06755, AID_ROOT,      AID_ROOT,      "system/xbin/librank" },
    { 06755, AID_ROOT,      AID_ROOT,      "system/xbin/procrank" },
    { 06755, AID_ROOT,      AID_ROOT,      "system/xbin/procmem" },
    { 00755, AID_ROOT,      AID_SHELL,     "system/bin/*" },
    { 00755, AID_ROOT,      AID_SHELL,     "system/xbin/*" },
    { 00750, AID_ROOT,      AID_SHELL,     "sbin/*" },
    { 00755, AID_ROOT,      AID_ROOT,      "bin/*" },
    { 00750, AID_ROOT,      AID_SHELL,     "init*" },
    { 00644, AID_ROOT,      AID_ROOT,       0 },
};

//---------------------------------------------------------------------------
// system/core/init/devices.c
//---------------------------------------------------------------------------

static struct perms_ devperms[] = {
    { "/dev/null",          0666,   AID_ROOT,       AID_ROOT,       0 },
    { "/dev/zero",          0666,   AID_ROOT,       AID_ROOT,       0 },
    { "/dev/full",          0666,   AID_ROOT,       AID_ROOT,       0 },
    { "/dev/ptmx",          0666,   AID_ROOT,       AID_ROOT,       0 },
    { "/dev/tty",           0666,   AID_ROOT,       AID_ROOT,       0 },
    { "/dev/random",        0666,   AID_ROOT,       AID_ROOT,       0 },
    { "/dev/urandom",       0666,   AID_ROOT,       AID_ROOT,       0 },
    { "/dev/ashmem",        0666,   AID_ROOT,       AID_ROOT,       0 },
    { "/dev/binder",        0666,   AID_ROOT,       AID_ROOT,       0 },

        /* logger should be world writable (for logging) but not readable */
    { "/dev/log/",          0662,   AID_ROOT,       AID_LOG,        1 },

        /* these should not be world writable */
    { "/dev/android_adb",   0660,   AID_ADB,        AID_ADB,        0 },
    { "/dev/android_adb_enable",   0660,   AID_ADB,        AID_ADB,        0 },
    { "/dev/ttyMSM0",       0600,   AID_BLUETOOTH,  AID_BLUETOOTH,  0 },
    { "/dev/ttyHS0",        0600,   AID_BLUETOOTH,  AID_BLUETOOTH,  0 },
    { "/dev/uinput",        0600,   AID_BLUETOOTH,  AID_BLUETOOTH,  0 },
    { "/dev/alarm",         0664,   AID_SYSTEM,     AID_RADIO,      0 },
    { "/dev/tty0",          0660,   AID_ROOT,       AID_SYSTEM,     0 },
    { "/dev/graphics/",     0660,   AID_ROOT,       AID_GRAPHICS,   1 },
    { "/dev/hw3d",          0660,   AID_SYSTEM,     AID_GRAPHICS,   0 },
    { "/dev/input/",        0660,   AID_ROOT,       AID_INPUT,      1 },
    { "/dev/eac",           0660,   AID_ROOT,       AID_AUDIO,      0 },
    { "/dev/cam",           0660,   AID_ROOT,       AID_CAMERA,     0 },
    { "/dev/pmem",          0660,   AID_SYSTEM,     AID_GRAPHICS,   0 },
    { "/dev/pmem_gpu",      0660,   AID_SYSTEM,     AID_GRAPHICS,   1 },
    { "/dev/pmem_adsp",     0660,   AID_SYSTEM,     AID_AUDIO,      1 },
    { "/dev/pmem_camera",   0660,   AID_SYSTEM,     AID_CAMERA,     1 },
    { "/dev/oncrpc/",       0660,   AID_ROOT,       AID_SYSTEM,     1 },
    { "/dev/adsp/",         0660,   AID_SYSTEM,     AID_AUDIO,      1 },
    { "/dev/mt9t013",       0660,   AID_SYSTEM,     AID_SYSTEM,     0 },
    { "/dev/akm8976_daemon",0640,   AID_COMPASS,    AID_SYSTEM,     0 },
    { "/dev/akm8976_aot",   0640,   AID_COMPASS,    AID_SYSTEM,     0 },
    { "/dev/akm8976_pffd",  0640,   AID_COMPASS,    AID_SYSTEM,     0 },
    { "/dev/msm_pcm_out",   0660,   AID_SYSTEM,     AID_AUDIO,      1 },
    { "/dev/msm_pcm_in",    0660,   AID_SYSTEM,     AID_AUDIO,      1 },
    { "/dev/msm_pcm_ctl",   0660,   AID_SYSTEM,     AID_AUDIO,      1 },
    { "/dev/msm_snd",       0660,   AID_SYSTEM,     AID_AUDIO,      1 },
    { "/dev/msm_mp3",       0660,   AID_SYSTEM,     AID_AUDIO,      1 },
    { "/dev/msm_audpre",    0660,   AID_SYSTEM,     AID_AUDIO,      0 },
    { "/dev/htc-acoustic",  0660,   AID_SYSTEM,     AID_AUDIO,      0 },
    { "/dev/smd0",          0640,   AID_RADIO,      AID_RADIO,      0 },
    { "/dev/qmi",           0640,   AID_RADIO,      AID_RADIO,      0 },
    { "/dev/qmi0",          0640,   AID_RADIO,      AID_RADIO,      0 },
    { "/dev/qmi1",          0640,   AID_RADIO,      AID_RADIO,      0 },
    { "/dev/qmi2",          0640,   AID_RADIO,      AID_RADIO,      0 },
    { NULL, 0, 0, 0, 0 },
};

'안드로이드 > 플랫폼' 카테고리의 다른 글

init 분석 - 메인루프의 poll 의 timeout  (0) 2009.07.28
init 분석 - firmware  (0) 2009.07.28
프로세스, 기본 환경  (0) 2009.07.28
안드로이드 부팅과정  (0) 2009.07.28
안드로이드 커널 빌드  (0) 2009.07.28
Posted by blee
,