파티션 레이아웃

Android 10에서 루트 파일 시스템은 더 이상 ramdisk.img에 포함되지 않고 system.img로 병합됩니다. 즉, system.img는 항상 BOARD_BUILD_SYSTEM_ROOT_IMAGE가 설정된 것처럼 생성됩니다. Android 10을 실행 중인 기기

  • system-as-root 파티션 레이아웃을 사용합니다(동작을 변경하는 옵션 없이 빌드에 의해 자동으로 적용).
  • dm-linear에 필수인 램디스크를 사용해야 합니다.
  • BOARD_BUILD_SYSTEM_ROOT_IMAGEfalse로 설정해야 합니다. 이 설정은 램디스크를 사용하는 기기와 램디스크를 사용하지 않고 system.img를 직접 마운트하는 기기를 구분하는 데만 사용됩니다.

system-as-root 구성의 의미는 Android 9와 Android 10 간에 차이가 있습니다. Android 9 system-as-root 구성에서는 BOARD_BUILD_SYSTEM_ROOT_IMAGEtrue로 설정됩니다. 이로 인해 빌드는 루트 파일 시스템을 system.img에 병합한 다음 system.img를 루트 파일 시스템(rootfs)으로 마운트합니다. 이 구성은 Android 9를 실행하는 기기에서 필수이지만, Android 9로 업그레이드하는 기기와 Android 9보다 낮은 Android 버전을 실행하는 기기에서는 선택사항입니다. Android 10의 system-as-root 구성에서 빌드는 항상 $TARGET_SYSTEM_OUT$TARGET_ROOT_OUTsystem.img에 병합합니다. 이 구성은 Android 10을 실행하는 모든 기기의 기본 동작입니다.

Android 10에서는 무선 업데이트(OTA)를 통해 파티션의 생성, 크기 조정 또는 삭제가 가능한 사용자 공간 파티션 시스템인 동적 파티션을 지원하도록 변경되었습니다. 이러한 변경사항의 일환으로 Linux 커널은 Android 10을 실행하는 기기에 더 이상 논리 시스템 파티션을 마운트할 수 없으므로 이 작업은 1단계 초기화에 의해 처리됩니다.

다음 섹션에서는 시스템 전용 OTA의 system-as-root 요구사항을 설명하고, system-as-root를 사용하도록 기기를 업데이트하는 것에 관한 지침(파티션 레이아웃 변경 및 dm-verity 커널 요구사항 포함) 세부정보를 제공합니다. 램디스크 변경사항에 대한 자세한 내용은 Ramdisk 파티션을 참고하세요.

시스템 전용 OTA 정보

시스템 전용 OTA를 사용하면 다른 파티션을 변경하지 않고도 Android 버전에서 system.imgproduct.img를 업데이트할 수 있으며, 이를 위해서는 system-as-root 파티션 레이아웃이 필요합니다. Android 10을 실행하는 모든 기기에서 시스템 전용 OTA를 지원하려면 system-as-root 파티션 레이아웃을 사용해야 합니다.

  • system 파티션을 rootfs로 마운트하는 A/B 기기는 이미 system-as-root를 사용하므로 시스템 OTA를 지원하기 위해 변경할 필요가 없습니다.
  • A/B 이외의 기기는 /systemsystem 파티션을 마운트하므로 시스템 OTA를 지원하려면 system-as-root 파티션 레이아웃을 사용하도록 업데이트해야 합니다.

A/B 기기 및 A/B 이외의 기기에 관한 자세한 내용은 A/B (원활한) 시스템 업데이트를 참고하세요.

공급업체 오버레이 사용

공급업체 오버레이를 사용하면 기기를 부팅하는 동안 vendor 파티션의 변경사항을 오버레이할 수 있습니다. 공급업체 오버레이는 기기가 부팅될 때 vendor 파티션에 오버레이되는 product 파티션의 공급업체 모듈 집합으로, 기존 모듈을 대체하고 모듈에 추가됩니다.

기기가 부팅되면 init 프로세스가 1단계 마운트를 완료하고 기본 속성을 읽습니다. 그런 다음 /product/vendor_overlay/<target_vendor_version>을 검색하고 다음 조건을 충족하는 경우 관련 vendor 파티션 디렉터리에 각 하위 디렉터리를 마운트합니다.

  • /vendor/<overlay_dir>이 존재합니다.
  • /product/vendor_overlay/<target_vendor_version>/<overlay_dir>/vendor/<overlay_dir>과 동일한 파일 컨텍스트를 갖습니다.
  • init/vendor/<overlay_dir> 파일 컨텍스트에 마운트할 수 있습니다.

공급업체 오버레이 구현

/product/vendor_overlay/<target_vendor_version>에 공급업체 오버레이 파일을 설치합니다. 이러한 파일은 기기가 부팅될 때 vendor 파티션을 오버레이하여 동일한 이름의 파일을 대체하고 새 파일을 추가합니다. 공급업체 오버레이는 vendor 파티션에 있는 파일을 삭제할 수 없습니다.

공급업체 오버레이 파일은 vendor 파티션에서 대체하는 대상 파일과 동일한 파일 컨텍스트를 가져야 합니다. 기본적으로 /product/vendor_overlay/<target_vendor_version> 디렉터리에 있는 파일은 vendor_file 컨텍스트를 갖습니다. 공급업체 오버레이 파일과 교체 대상 파일 간 파일 컨텍스트가 일치하지 않는 경우 기기별 sepolicy에 올바른 파일 컨텍스트를 명시합니다. 파일 컨텍스트는 디렉터리 수준에서 설정됩니다. 공급업체 오버레이 디렉터리의 파일 컨텍스트가 대상 디렉터리와 일치하지 않고 올바른 파일 컨텍스트가 기기별 sepolicy에 지정되지 않은 경우, 공급업체 오버레이 디렉터리는 대상 디렉터리에 오버레이되지 않습니다.

공급업체 오버레이를 사용하려면 커널에서 CONFIG_OVERLAY_FS=y 설정을 통해 OverlayFS를 사용 설정해야 합니다. 또한 커널은 공통 커널 4.4 이상에서 병합되거나 "overlayfs: override_creds=off option bypass creator_cred"로 패치되어야 합니다.

공급업체 오버레이 구현 예

이 절차는 /vendor/lib/*, /vendor/etc/*, /vendor/app/* 디렉터리를 오버레이하는 공급업체 오버레이 구현 방법을 보여줍니다.

  1. 사전 빌드된 공급업체 파일을 device/<vendor>/<target>/vendor_overlay/<target_vendor_version>/에 추가합니다.

    device/google/device/vendor_overlay/28/lib/libfoo.so
    device/google/device/vendor_overlay/28/lib/libbar.so
    device/google/device/vendor_overlay/28/etc/baz.xml
    device/google/device/vendor_overlay/28/app/qux.apk
    
  2. 사전 빌드된 공급업체 파일을 device/google/device/device.mkproduct/vendor_overlay에 설치합니다.

    PRODUCT_COPY_FILES += \
        $(call find-copy-subdir-files,*,device/google/device/vendor_overlay,$(TARGET_COPY_OUT_PRODUCT)/vendor_overlay)
    
  3. 대상 vendor 파티션 파일이 vendor_file 이외의 컨텍스트를 갖는 경우 파일 컨텍스트를 정의합니다. /vendor/lib/*vendor_file 컨텍스트를 사용하므로 이 예에는 관련 디렉터리가 포함되지 않습니다.

    다음을 device/google/device-sepolicy/private/file_contexts에 추가합니다.

    /(product|system/product)/vendor_overlay/[0-9]+/etc(/.*)?   u:object_r:vendor_configs_file:s0
    /(product|system/product)/vendor_overlay/[0-9]+/app(/.*)?   u:object_r:vendor_app_file:s0
    
  4. init 프로세스를 사용하여 공급업체 오버레이를 vendor_file이 아닌 파일 컨텍스트에 마운트합니다. init 프로세스에 이미 vendor_file 컨텍스트에 마운트할 권한이 있으므로 이 예에서는 vendor_file 정책을 정의하지 않습니다.

    다음을 device/google/device-sepolicy/public/init.te에 추가합니다.

    allow init vendor_configs_file:dir mounton;
    allow init vendor_app_file:dir mounton;
    

공급업체 오버레이 검증

공급업체 오버레이 구성을 검증하려면 /product/vendor_overlay/<target_vendor_version>/<overlay_dir>에 파일을 추가하고 파일이 /vendor/<overlay_dir>에 있는 파일에 오버레이되었는지 확인합니다.

userdebug 빌드의 경우 Atest용 테스트 모듈이 있습니다.

$ atest -v fs_mgr_vendor_overlay_test

system-as-root로 업데이트

system-as-root를 사용하도록 A/B 이외의 기기를 업데이트하려면 boot.imgsystem.img의 파티션 스키마를 업데이트하고, dm-verity를 설정하고, 기기별 루트 폴더에서 부팅 종속 항목을 삭제해야 합니다.

파티션 업데이트

/bootrecovery 파티션으로 변경하는 A/B 기기와 달리 A/B 이외의 기기는 대체 슬롯 파티션(예: boot_a에서 boot_b로)이 없으므로 /recovery 파티션을 별도로 유지해야 합니다. /recovery가 A/B 이외의 기기에서 삭제되고 A/B 스키마와 유사하게 되는 경우 /boot 파티션 업데이트에 실패하면 복구 모드가 종료될 수 있습니다. 따라서 A/B가 아닌 기기의 경우 /recovery 파티션은 반드시 /boot로부터 독립된 파티션이어야 합니다. 이는 복구 이미지가 Android 8.1.0 이하를 실행하는 기기와 동일하게 지연된 방식으로 계속 업데이트된다는 것을 의미합니다.

다음 표에는 Android 9 이전 및 이후, A/B가 아닌 기기의 이미지 파티션 차이가 나와 있습니다.

이미지 램디스크(9 이전) System-as-root(9 이후)
boot.img 커널과 ramdisk.img를 포함합니다.

ramdisk.img
  -/
    - init.rc
    - init
    - etc -> /system/etc
    - system/ (mount point)
    - vendor/ (mount point)
    - odm/ (mount point)
    ...
일반 부팅 커널만 포함합니다.
recovery.img 복구 커널과 복구 ramdisk.img를 포함합니다.
system.img 다음을 포함합니다.

system.img
  -/
    - bin/
    - etc
    - vendor -> /vendor
    - ...
원본 system.imgramdisk.img의 병합된 콘텐츠를 포함합니다.

system.img
  -/
    - init.rc
    - init
    - etc -> /system/etc
    - system/
      - bin/
      - etc/
      - vendor -> /vendor
      - ...
    - vendor/ (mount point)
    - odm/ (mount point)
    ...

파티션 자체는 변경되지 않습니다. 램디스크와 system-as-root 모두 다음 파티션 스키마를 사용합니다.

  • /boot
  • /system
  • /system
  • /recovery
  • /vendor

dm-verity 설정

system-as-root에서 커널은 dm-verity가 있는 /(마운트 지점) 아래에 system.img를 마운트해야 합니다. AOSP는 system.img에서 다음과 같은 dm-verity 구현을 지원합니다.

vboot 1.0

vboot 1.0의 경우 커널은 /system의 Android 관련 메타데이터를 파싱한 다음 dm-verity 매개변수로 변환하여 dm-verity를 설정해야 합니다. 이때 이 커널 패치가 필요합니다. 다음 예는 커널 명령줄을 통해 system-as-root에 관한 dm-verity 관련 설정을 보여줍니다.

ro root=/dev/dm-0 rootwait skip_initramfs init=/init
dm="system none ro,0 1 android-verity /dev/sda34"
veritykeyid=id:7e4333f9bba00adfe0ede979e28ed1920492b40f

vboot 2.0

vboot 2.0(AVB)의 경우 부트로더는 external/avb/libavb를 통합한 다음 /system해시트리 설명자를 파싱하고, 이를 dm-verity 매개변수로 변환하고, 마지막으로 매개변수를 커널 명령줄을 통해 커널에 전달합니다. /system의 해시트리 설명자는 /vbmeta 또는 /system 자체에 있을 수 있습니다.

vboot 2.0은 다음 커널 패치를 필요로 합니다.

다음 예는 커널 명령줄을 통해 system-as-root에 관한 dm-verity 관련 설정을 보여줍니다.

ro root=/dev/dm-0 rootwait  skip_initramfs init=/init

dm="1 vroot none ro 1,0 5159992 verity 1
PARTUUID=00000016-0000-0000-0000-000000000000
PARTUUID=00000016-0000-0000-0000-000000000000 4096 4096 644999 644999
sha1 d80b4a8be3b58a8ab86fad1b498640892d4843a2
8d08feed2f55c418fb63447fec0d32b1b107e42c 10 restart_on_corruption
ignore_zero_blocks use_fec_from_device
PARTUUID=00000016-0000-0000-0000-000000000000 fec_roots 2 fec_blocks
650080 fec_start 650080"

기기별 루트 폴더 사용

system-as-root를 사용하면 일반 시스템 이미지(GSI)가 기기에서 플래시된 후(공급업체 테스트 도구 모음의 테스트를 실행하기 전)에는 전체 루트 디렉터리 콘텐츠가 system-as-root GSI에 의해 대체되므로 BOARD_ROOT_EXTRA_FOLDERS와 함께 추가된 기기별 루트 폴더는 삭제됩니다. 이러한 폴더가 삭제되면 기기별 루트 폴더에 관한 종속 항목이 존재하는 경우(예: 마운트 지점으로 사용되는 경우) 기기가 부팅되지 않을 수 있습니다.

이 문제를 방지하려면 기기별 루트 폴더를 추가하는 데 BOARD_ROOT_EXTRA_FOLDERS를 사용하지 않아야 합니다. 기기별 마운트 지점을 지정해야 하는 경우 변경 목록에 추가된 /mnt/vendor/<mount point>를 사용합니다. 이러한 공급업체별 마운트 지점은 fs_mgr이 이를 /mnt/vendor/* 아래에 자동으로 생성하므로 추가 설정 없이 fstab 기기 트리(1단계 마운트 시) 및 /vendor/etc/fstab.{ro.hardware} 파일 모두에 직접 지정될 수 있습니다.