[Android] adb wifi debugging 사용 방법

  1. 안드로이드 기기에서 개발자 옵션 켜기
  2. 개발자 옵션에서 “무선 디버깅” 켜기
  3. 무선 디버깅에서 페어링 코드로 기기 페어링 선택
  4. 호스트 컴퓨터에서 휴대폰에 나온 화면의 IP 주소 및 포트대로 adb pair <IP>:<PORT> 실행
    • 예제: adb pair 192.168.0.4:33917
  5. 호스트 컴퓨터에서 휴대폰에 나온 화면의 페어링 코드를 입력
    • 예제: Enter pairing code: 656685
  6. 연결됨. 호스트 컴퓨터에서 adb devices 를 실행하면 연결된 기기가 보일 것.
 dasomoli> ~> adb devices
List of devices attached
adb-R3CRC0G1A8L-FkwYCP._adb-tls-connect._tcp	device

[Android] “Running Android with low RAM” 의 Kernel Configuration

Except as noted, this content is licensed under Creative Commons Attribution 2.5. For details and restrictions, see the Content License.
 

원문: http://source.android.com/devices/low-ram.html
번역: 양정석<dasomoli@gmailREMOVETHIS.com>(근데 원래 혼자 보려던 거라 이상한 거 많음;;)

커널 설정


직접 회수(Direct reclaim)를 줄이기 위한 커널/ActivityManager 튜닝

직접 회수는 하나의 프로세스 또는 커널이 메모리의 한 페이지를 (직접 혹은 새로운 페이지 안의 폴트로 인해서) 할당하고자 하며, 커널이 모든 사용 가능한 자유 메모리를 사용하고 있을 때 일어납니다. 이것은 커널에게 하나의 페이지를 해제하는 동안 할당을 막도록 요구합니다. 결국 이것은 더티한 File-backed 페이지를 플러싱하기 위한 디스크 I/O나 lowmemorykiller가 프로세스 하나를 죽이기를 기다리는 것을 종종 요구합니다. 이것은 UI 스레드를 포함하는 어떤 스레드에 추가 I/O를 일으킬 수 있습니다.
직접 회수를 피하기 위해서 커널은 kswapd나 백그라운드 회수를 촉발시키는 워터마크를 가집니다. 이것은 페이지들을 해제하도록 시도해서 다음에 그를 할당하는 리얼 타임 스레드가 빨리 수행할 수 있도록 하는 하나의 스레드입니다.
백그라운드 회수를 촉발시키는 디폴트 임계값은 2GB 디바이스에서 2MB, 512MB 디바이스에서 636KB로, 상당히 낮습니다. 그리고 커널은 그저 수 MB의 메모리를 백그라운드 회수 시에 회수할 뿐입니다. 이것은 수 MB 이상을 빨리 할당하는 어떤 프로세스는 빨리 직접 회수를 치게 될 것이라는 것을 의미합니다.
새로운 커널에 튜닝 가능한 지원이 android-3.4 커널 브랜치에 패치 92189d47f66c67e5fd92eafaa287e153197a454f(“add extra free kbytes tunable”)로 추가됩니다. 이 패치를 디바이스의 커널로 체리픽하는 것은 ActivityManager가 커널에게 3개의 풀스크린 32 bpp 버퍼의 메모리를 자유롭게 유지하도록 할 것임을 이야기하는 것을 허용할 것입니다.
이들 임계값은 프레임워크 config.xml을 통해 설정될 수 있습니다.
<!– 커널 내에 (존재한다면) 튜닝 가능한 /proc/sys/vm/extra_free_kbytes를 셋팅하는 디바이스 설정. 높은 값은 커널이 free를 유지하는 메모리의 양을 증가시키고, 할당 시간을 줄이고, lowmemerykiller가 더 빨리 죽이도록 할 것입니다. 낮은 값은 프로세스들에 의해 더 많은 메모리를 사용하도록 하지만 디스크 I/O나 lowmemorykiller 상에서의 대기를 막는 더 많은 할당이 일어날 것입니다. 화면 크기에 기초한 ActivityManager에 의해 선택된 기본 값은 덮어씌움. 0은 커널의 기본 값을 넘는 추가 메모리를 유지하는 것을 막습니다. -1은 기본값을 유지합니다 –>
<integer name=”config_extraFreeKbytesAbsolute”>-1</integer>
<!– 커널 내에 (존재한다면) 튜닝 가능한 /proc/sys/vm/extra_free_kbytes를 조정하는 디바이스 설정. 0은 ActivityManager가 고르는 기본 값을 사용합니다. 양수 값은 커널이 해제를 유지하는 메모리의 양을 증가시키고, 할당 시간을 줄이고, lowmemorykiller 가 더 빨리 죽이도록 할 것입니다. 음수 값은 프로세스들에 의해 사용되는 메모리를 더 많이 허용하지만, 디스크 I/O나 lowmemorykiller 상의 대기를 막는 더 많은 할당이 일어날 것입니다. 화면 크기에 기초한 ActivityManager에 의해 선택된 기본 값은 직접 더해짐. –>
<integer name=”config_extraFreeKbytesAdjust”>0</integer>
LowMemoryKiller 튜닝
ActivityManager는 각 우선 순위 단계 버킷 안에서 프로세스를 실행하는데 필요한 file-backed 페이지(캐시된(cached) 페이지)의 워킹 셋의 그 예상치를 맞추기 위해서 LowMemoryKiller의 임계값을 설정합니다. 디바이스가 워킹 셋을 위한 높은 요구 사항을 갖는다면, 예를 들면, 벤더 UI가 더 많은 메모리를 요구하거나 더 많은 서비스가 추가되었다면, 임계값은 증가될 수 있습니다.
작아지고 있는 캐시 때문에 디스크 스레싱(thrashing)이 일어나기 전에 백그라운드 프로세스들이 죽여지고 있어서, 너무 많은 메모리가 file backed 페이지를 위해 예약되어 지고 있다면 임계값을 줄일 수 있습니다. 
<!– 커널 내의 lowmemorykiller 내의 튜닝 가능한 minfree를 셋팅하는 디바이스 설정. 높은 값은 lowmemorykiller가 더 일찍 켜지고, 파일 캐시 안에 더 많은 메모리를 유지하고, I/O 스레싱을 막도록 할 것이지만, 메모리 내에 더 적은 프로세스가 머물도록 할 것입니다. 낮은 값은 더 많은 프로세스가 메모리 상에 유지되지만, 너무 낮으면 스레싱을 일으킬 것입니다. 화면 크기와 가장 큰 lowmemorykiller 버킷을 위한 전체 메모리에 기초해서 ActivityManager에 의해 선택된 기본값을 덮어쓰고, 더 작은 버킷에 비례해서 크기가 조정됨. -1은 기본값을 유지 —>
<integer name=”config_lowMemoryKillerMinFreeKbytesAbsolute”>-1</integer>
<!– 커널 내의 lowmemorykiller 내의 튜닝 가능한 minfree를 조정하는 디바이스 설정. 높은 값은 lowmemorykiller가 더 일찍 켜지고, 파일 캐시 안에 더 많은 메모리를 유지하고, I/O 스레싱을 막도록 할 것이지만, 메모리 내에 더 적은 프로세스가 머물도록 할 것입니다. 낮은 값은 더 많은 프로세스가 메모리 상에 유지되지만, 너무 낮으면 스레싱을 일으킬 것입니다. 화면 크기와 가장 큰 lowmemorykiller 버킷을 위한 전체 메모리에 기초해서 ActivityManager에 의해 선택된 기본값에 직접 더해지고, 더 작은 버킷에 비례해서 크기가 조정됨. 0은 기본값을 유지 —>
<integer name=”config_lowMemoryKillerMinFreeKbytesAdjust”>0</integer>

Framework의 설정 참고 소스 코드: frameworks/base/services/java/com/android/server/am/ProcessList.java

[Android] ${ro.hardware}를 사용한 하드웨어 별 init.rc 처리

안 적어 놓으니 역시나 까먹는다. 아래는 ARM 32비트에 국한한다.

커널 부팅의 마지막에 init 프로세스가 시작되면, 램디스크 안에 든 init.rc 파일을 읽어 처리하게 된다. 별 다른 처리를 하지 않았다면, 기본적으로 system/core/rootdir/init.rc 파일이 램디스크로 복사되므로 이 파일을 읽어 처리한다.
이 init.rc 파일에서는 ro.hardware 프로퍼티 값에 따라 init.${ro.hardware}.rc 파일을 읽어 처리하게 되는데 이 파일로 각 보드마다 다른 처리를 가능하게 한다.
여기서 ro.hardware 프로퍼티 값은 init(system/core/init) 안에서 다음과 같은 순서로 셋팅한다.

1. /proc/cpuinfo 를 읽어서 이 안의 “Hardware:” 뒤의 값을 소문자로 모두 바꿔 사용(system/core/init/util.c 의 get_hardware_name())
2. 부트로더에서 cmdline 으로 androidboot.hardware 값이 넘어왔다면, ro.boot.hardware 프로퍼티로 셋팅한다(system/core/init/init.c 의 import_kernel_nv()).[ro.boot.hardware 값은 꼭 부트로더에서 넘어오지 않을 수도 있다]
3. ro.boot.hardware 프로퍼티 값이 있다면, 앞에서 /proc/cpuinfo 에서 읽은 값을 오버라이드한다.

위의 순서를 거쳐 셋팅된 ro.hardware 프로퍼티를 사용해서 init.${ro.hardware}.rc 파일을 읽게 된다.

1. 의 경우를 사용할 때는 /proc/cpuinfo 값을 사용하므로, 리눅스 커널의 사용되는 struct machine_desc 안의 .name 을 사용하게 된다.
/proc/cpuinfo 에서 “Hardware: ” 를 출력하는 부분은 리눅스 커널 소스의 arch/arm/kernel/setup.c 안의 c_show() 함수를 보면 되는데, 다음과 같다.

static int c_show(struct seq_file *m, void *v)
{
        …

        seq_printf(m, “Hardware\t: %s\n”, machine_name);

        …

machine_name 은 커널 부팅 중 (arch/arm/kernel/setup.c 의) setup_arch() 에서 다음처럼 셋팅한다.

void __init setup_arch(char **cmdline_p)
{

        …
        machine_name = mdesc->name;

        …

struct machine_desc 안의 .name 은 대부분 머신 파일 안에서 MACHINE_START(_type, _name) 매크로를 통해 선언한다. _name이 .name이 된다. 그러므로 결국 _name 에 들어가는 값이 읽혀 소문자로 바뀌어 사용된다. 예를 들면, Nexus 10 디바이스의 경우 다음과 같이 arch/arm/mach-exynos/board-manta.c 안에 다음과 같이 정의되어 있다. 여기서는 “Manta” 가 소문자로 모두 바뀌어 manta 로 사용된다.

MACHINE_START(MANTA, “Manta”)
        … 
MACHINE_END


참고로, MACHINE_START 매크로는 arch/arm/include/asm/mach/arch.h 에 있는데 다음과 같다.

#define MACHINE_START(_type,_name)                      \
static const struct machine_desc __mach_desc_##_type    \
 __used                                                 \
 __attribute__((__section__(“.arch.info.init”))) = {    \
        .nr             = MACH_TYPE_##_type,            \
        .name           = _name,
#define MACHINE_END                             \
};

2. 의 경우는 cmdline 을 통해 넘어오므로, 부트로더에서 ATAG를 통해 cmdline 에 셋팅하여 넘기는 것이 가장 정상적인 방법이고, 편법으로는 cmdline 을 바꿀 수 있는 여러가지 방법(예를 들면, 커널 컴파일 타임에 셋팅한다든지, boot.img 를 만들 때 cmdline 을 설정해 준다든지 등)을 통해 셋팅할 수 있다.(아니면 아예 ro.boot.hardware 값을 직접 셋팅해도 아마?)
androidboot.hardware 값이 ro.boot.hardware 프로퍼티 값이 되는 과정은 system/core/init/init.c 의 import_kernel_nv() 함수 내에서 처리된다.

static void import_kernel_nv(char *name, int for_emulator)
{                          
    …
    if (!strcmp(name,”qemu”)) {
        strlcpy(qemu, value, sizeof(qemu));
    } else if (!strncmp(name, “androidboot.”, 12) && name_len > 12) {
        const char *boot_prop_name = name + 12;
        char prop[PROP_NAME_MAX];
        int cnt;
        
        cnt = snprintf(prop, sizeof(prop), “ro.boot.%s”, boot_prop_name);
        if (cnt < PROP_NAME_MAX)
            property_set(prop, value);
    }
}

3. 의 ro.boot.hardware 프로퍼티 값이 ro.hardware 프로퍼티 값으로 셋팅되는 과정은 system/core/init/init.c 의 export_kernel_boot_props() 에서 수행된다. 이 과정 중에 ro.boot.hardware 프로퍼티 값이 있다면, 1. 의 /proc/cpuinfo 을 통해 얻은 값을 오버라이드하게 된다.

static void export_kernel_boot_props(void)
{
    … 
    /* if this was given on kernel command line, override what we read
     * before (e.g. from /proc/cpuinfo), if anything */
    ret = property_get(“ro.boot.hardware”, tmp);
    if (ret)
        strlcpy(hardware, tmp, sizeof(hardware));

    property_set(“ro.hardware”, hardware);  

[Ubuntu 10.04] sun-java6-jdk 설치

partner repo 에서 제공하던 것이 안된다.

PPA repo 를 이용한다.

sudo apt-get install python-software-properties

sudo add-apt-repository ppa:sun-java-community-team/sun-java6

sudo apt-get update

sudo apt-get install sun-java6-jdk

sudo update-java-alternatives -s java-6-sun

Proxy 환경에서 add-apt-repository ppa:sun-java-community-team/sun-java6 에서 “couldn’t connect to host” 에러가 나는 경우 환경 변수 http_proxy, https_proxy, ftp_proxy 가 sudo 에서도 먹도록 다음을 /etc/sudoers 에 추가한다.

Defaults env_keep = “http_proxy https_proxy ftp_proxy”

참고 : http://www.bogdanovic.se/installing-oracle-sun-jdk-6-on-ubuntu

         https://help.ubuntu.com/community/AptGet/Howto#Setting_up_apt-get_to_use_a_http-proxy

[Linux Kernel] 부트로더 cmdline 확장 – CONFIG_CMDLINE_EXTEND

CONFIG_CMDLINE_EXTEND 옵션을 켜면 CONFIG_CMDLINE 의 cmdline 뒤에 부트로더에서 넘기는 cmdline 을 덧붙인다.

ARM 의 경우 arch/arm/kernel/setup.c 에 보면 다음과 같은 것들을 볼 수 있다.


static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;

static int __init parse_tag_cmdline(const struct tag *tag)
{
#if defined(CONFIG_CMDLINE_EXTEND)
        strlcat(default_command_line, ” “, COMMAND_LINE_SIZE);
        strlcat(default_command_line, tag->u.cmdline.cmdline,
                COMMAND_LINE_SIZE);
#elif defined(CONFIG_CMDLINE_FORCE)
        pr_warning(“Ignoring tag cmdline (using the default kernel command line)\n”);
#else
        strlcpy(default_command_line, tag->u.cmdline.cmdline,
                COMMAND_LINE_SIZE);
#endif
        return 0;
}


참고로 안드로이드의 경우, boot.img 에 쓰이는 cmdline 에 아무것도 없을 것이라고 기대된다. boot.img 안에 있는 cmdline 의 경우 fastboot -c 옵션을 통해 디버깅 목적으로 쓸 때 사용되곤 한다.

이 문서의 저작권은 GPL을 따른다(This document is released under the GPL license).

Linux kernel, ramdisk 사용 및 Android 빌드 시스템에서의 설정

Linux 커널의 경우 램디스크를 여러 종류를 사용하는데 이 중 initramfs/initrd 를 사용하는 경우
CONFIG_BLK_DEV_INITRD 를 설정하고, CONFIG_INITRAMFS_SOURCE 에 root 파일템이 만들어져 있는 디렉토리 경로를 써준다.
Android 빌드 시스템에서는 커널 및 램디스크를 합쳐서 boot.img 를 만들어 사용하는데,
이 때, 사용될 Kernel Command line 을 지정할 수 있다. 이 때 TARGET_NO_KERNEL은 false 여야 한다.
이는 build/core/Makefile 에서 확인할 수 있다. 

BOARD_KERNEL_CMDLINE := $(strip $(BOARD_KERNEL_CMDLINE))
ifdef BOARD_KERNEL_CMDLINE
  INTERNAL_BOOTIMAGE_ARGS += –cmdline “$(BOARD_KERNEL_CMDLINE)”
endif

이 외에도 Kernel Base address, Page Size 등도 지정할 수 있다.

BOARD_KERNEL_BASE := $(strip $(BOARD_KERNEL_BASE))
ifdef BOARD_KERNEL_BASE
  INTERNAL_BOOTIMAGE_ARGS += –base $(BOARD_KERNEL_BASE)
endif
BOARD_KERNEL_PAGESIZE := $(strip $(BOARD_KERNEL_PAGESIZE))
ifdef BOARD_KERNEL_PAGESIZE
  INTERNAL_BOOTIMAGE_ARGS += –pagesize $(BOARD_KERNEL_PAGESIZE)
endif

TARGET_BOOTIMAGE_USE_EXT2 를 true로 하면 ext2 파일시스템의 boot image를 만드는 것 같다.

ifeq ($(TARGET_BOOTIMAGE_USE_EXT2),true)
tmp_dir_for_image := $(call intermediates-dir-for,EXECUTABLES,boot_img)/bootimg
INTERNAL_BOOTIMAGE_ARGS += –tmpdir $(tmp_dir_for_image)
INTERNAL_BOOTIMAGE_ARGS += –genext2fs $(MKEXT2IMG)
$(INSTALLED_BOOTIMAGE_TARGET): $(MKEXT2IMG) $(INTERNAL_BOOTIMAGE_FILES)
    $(call pretty,”Target boot image: $@”)
    $(hide) $(MKEXT2BOOTIMG) $(INTERNAL_BOOTIMAGE_ARGS) –output $@
else # TARGET_BOOTIMAGE_USE_EXT2 != true
$(INSTALLED_BOOTIMAGE_TARGET): $(MKBOOTIMG) $(INTERNAL_BOOTIMAGE_FILES)
    $(call pretty,”Target boot image: $@”)
    $(hide) $(MKBOOTIMG) $(INTERNAL_BOOTIMAGE_ARGS) –output $@
    $(hide) $(call assert-max-image-size,$@,$(BOARD_BOOTIMAGE_PARTITION_SIZE),raw)
endif # TARGET_BOOTIMAGE_USE_EXT2

예제)

TARGET_NO_KERNEL := false
BOARD_KERNEL_BASE := 0x30000000
BOARD_KERNEL_PAGESIZE := 4096
BOARD_KERNEL_CMDLINE := console=ttyFIQ0 no_console_suspend