Android 시스템 컴파일 시 맞춤 복구 통합

Recovery 모드는 사용자가 일반 모드에서 수행할 수 없는 다음과 같은 일부 작업을 수행할 수 있도록 하는 Android 시스템의 특수 모드입니다.

  • 설치 또는 업그레이드 Android 시스템
  • 초기화
  • 캐시 지우기
  • SD 카드 포맷
  • 플래시 타사 ROM

Recovery 모드는 커널과 RAM 기본 시스템과 다른 시스템에 있는 디스크 로 구성됩니다. 파티션에서. LinuxAndroid

제3자 플래시와 같은 추가 기능을 원하는 경우 ROM제3자를 플래시할 수 있습니다 Recovery. 타사 Recovery 일반적으로 기본보다 더 많은 기능을 가지고 있지만 Recovery 불안정할 수도 있습니다.

머리말

타사 시스템 컴파일을 완료한 후 시스템을 플래시하기 위해 타사를 사용해야 하는 경우가 많습니다Recovery.

동시에 대부분의 시스템에 내장된 Recovery 기능은 상대적으로 단순하기 때문에 종종 타사 Recovery 우리 장치. , 새로운 시스템의 다음 플래시를 촉진합니다.

그렇다면 제3자를 Recovery 컴파일된 시스템에 직접 통합할 수 있는 방법이 있습니까?

많은 온라인 정보를 참조한 후 TWRP 이전 버전이 일정 기간 동안 존재했으며 Omini 시스템에 직접 통합됩니다. 하지만 현재의 새로운 시스템과 새로운 장치에서는 이것이 실현 불가능해 보입니다. 원래 방법을 사용하여 컴파일하는 동안 시스템 이미지와 플래시 패키지에 직접 통합할 수 없습니다.

동시에 TWRP의 형제OrangeFox의 컴파일 및 사용에 대한 연구를 시작하려고 했습니다. 먼저 공식 문서를 참고했습니다. OrangeFox 빌드 복사본을 컴파일Recovery하고 임시 시작<을 사용했습니다. a i=7> 및 플래시 패키지에 붓고 굳히기두 가지 방법이 사용됩니다OrangeFox Recovery.

OrangeFox Recovery의 응고 스크립트를 연구하고 이를 Android의 컴파일 및 패키징 프로세스와 결합한 후 플래시 패키지를 사용자 정의하는 기능을 구현하는 새로운 방법을 찾았습니다 Recovery.

구현 아이디어

시스템 컴파일 프로세스에서 Android 시스템의 각 부분은 일반적으로 먼저 이미지로 컴파일된 다음 이러한 이미지를 모아 완전한 플래시 패키지로 패키징합니다. Recovery는 일반적으로 별도의 파티션이거나 Boot 파티션에 통합되어 있으므로 이 부분만 교체하면 됩니다.

이 섹션에서는 파티션에서 시스템을 컴파일하는 동안 Recovery의 사용자 정의만 구현합니다. Boot

그러나 일반적으로Boot.img Recovery를 포함할 뿐만 아니라 시스템 시작 및 부팅에 사용되는 다른 콘텐츠도 포함하므로 이를 해결해야 합니다. 패키지 수정 .

포장을 풀다, 포장하다

먼저 OrangeFox RecoveryRecovery 응고 스크립트를 확인해야 합니다. 그중 recovery.img가 해당 스크립트입니다 a> Recovery 이미지에서 사용된 압축 풀기 및 패키징 도구는 MagiskBoot 이며, 코드의 경화 부분은 다음과 같습니다.

# a/META-INF/com/google/android/update-binary
magiskboot unpack -n recovery.img

# deal with ramdisk cpio
if [ ! -f "ramdisk.cpio" ]; then
    abort "- Error extracting the OrangeFox ramdisk. Quitting!"
fi
cp -f ramdisk.cpio ramdisk-ofrp.cpio
rm -f ramdisk.cpio
rm -f kernel dtb kernel_dtb

# deal with both slots
for slot in _a _b; do
    ui_print "- Running boot image patcher on slot $name$slot..."

    # dump the partition and unpack
    dd bs=1048576 if=$target$slot of=boot.img
    magiskboot unpack -h -n boot.img

    # 其他步骤

    cp -f ramdisk-ofrp.cpio ramdisk.cpio
    magiskboot repack -n boot.img

    blockdev --setrw $target$slot
    cat new-boot.img /dev/zero > $target$slot 2>/dev/null || true
    rm -f boot.img dtb kernel new-boot.img ramdisk.cpio header
    magiskboot cleanup
done

이 코드를 통해 OrangeFox Recovery의 응고 과정은 다음과 같습니다.

    1. 이용MagiskBoot 장 제3방Recoveryramdisk.cpio
    1. 从系窟中 제출 boot.img;
    1. 추출된 파일의 압축을 풉니다. boot.img;
    1. 타사를 이용Recovery하여 ramdisk.cpio 파일의 압축을 풀고 추출한 후 boot.img 압축을 푼 파일을 교체합니다. < a i=4> 파일;ramdisk.cpio
    1. 재포장 boot.img 거울;
    1. 원래 파티션에 다시 쓰기

구체적인 조작

포장 프로세스 수정

고형화 단계의 비유를 시스템 컴파일 프로세스에 추가하고 컴파일된 이미지를 모아 플래시 패키지를 조립하는 이전 단계에서 교체를 구현하면 사용자 정의가 가능합니다. < i=1> 함수. Recovery

LineageOS 소스 코드를 살펴보면서 마침내 LineageOS에서 플래시 패키지에 이미지를 추가하는 코드의 일부를 발견했습니다. 파일에 있습니다:boot.img 관련 코드는 build/make/tools/releasetools/add_img_to_target_files.py

boot_image = None
if has_boot:
    banner("boot")
    boot_images = OPTIONS.info_dict.get("boot_images")
    if boot_images is None:
        boot_images = "boot.img"
    for index, b in enumerate(boot_images.split()):
        boot_image = common.GetBootableImage("IMAGES/" + b, b, OPTIONS.input_tmp, "BOOT")
        if boot_image:
            boot_image_path = os.path.join(OPTIONS.input_tmp, "IMAGES", b)
        if index == 0:
            partitions['boot'] = boot_image_path
        if not os.path.exists(boot_image_path):
            boot_image.WriteToDir(OPTIONS.input_tmp)
            if output_zip:
                boot_image.AddToZip(output_zip)

이 문단은 boot.img 플래시 패키지에 패키징되는 것에 대한 내용임을 알 수 있습니다. 실제로는 OrangeFox Recovery의 치료 스크립트와 다소 유사합니다. . 은 ab 두 파티션을 순회하여 관련 작업을 수행하므로 OrangeFox Recovery 의 응고 과정을 모방하고 다음과 같이 작성합니다. 함수, 여기서 입력 매개변수는 boot.img의 경로이고 코드는 다음과 같습니다.

def useCustomRecovery(boot_image_path):
    magiskboot = os.getenv('CUSTOM_MAGISKBOOT')
    recovery = os.getenv('CUSTOM_TWRP')
    if not magiskboot or not recovery: return
    origin_pwd = os.getcwd()
    new_pwd = os.path.join(os.getcwd(), "tmp")
    common.RunAndCheckOutput(["mkdir", "-p", new_pwd])
    os.chdir(new_pwd)
    common.RunAndCheckOutput([magiskboot, "unpack", "-n", recovery])
    if not os.path.exists("ramdisk.cpio"):
        common.RunAndCheckOutput(["rm", "-rf", new_pwd])
        os.chdir(origin_pwd)
        return
    common.RunAndCheckOutput(["cp", "-f", "ramdisk.cpio", "ramdisk-ofrp.cpio"])
    common.RunAndCheckOutput(["rm", "-f", "ramdisk.cpio"])
    common.RunAndCheckOutput(["rm", "-f", "kernel", "dtb", "kernel_dtb"])
    common.RunAndCheckOutput([magiskboot, "unpack", "-h", "-n", boot_image_path])
    common.RunAndCheckOutput(["cp", "-f", "ramdisk-ofrp.cpio", "ramdisk.cpio"])
    common.RunAndCheckOutput([magiskboot, "repack", "-n", boot_image_path])
    common.RunAndCheckOutput(["mv", "-f", "new-boot.img", boot_image_path])
    common.RunAndCheckOutput(["rm", "-rf", new_pwd])
    common.RunAndCheckOutput([magiskboot, "cleanup"])
    os.chdir(origin_pwd)

이 부분은 OrangeFox Recovery 의 응고 작업인 풀기, 교체, 재포장 작업과 동일합니다. 이 기능을 사용하면 원본 소스 코드를 직접 수정할 수 있습니다.

boot_image = None
if has_boot:
    banner("boot")
    boot_images = OPTIONS.info_dict.get("boot_images")
    if boot_images is None:
        boot_images = "boot.img"
    for index, b in enumerate(boot_images.split()):
        boot_image = common.GetBootableImage("IMAGES/" + b, b, OPTIONS.input_tmp, "BOOT")
        if boot_image:
            boot_image_path = os.path.join(OPTIONS.input_tmp, "IMAGES", b)
            if index == 0:
                partitions['boot'] = boot_image_path
            if not os.path.exists(boot_image_path):
                boot_image.WriteToDir(OPTIONS.input_tmp)
                if output_zip:
                    boot_image.AddToZip(output_zip)
        useCustomRecovery(boot_image_path)

지금 바로 이 파일에 함수를 추가하는 것을 잊지 마세요. 동시에 useCustomRecovery 함수에서 두 개의 환경 변수를 읽어야 한다는 점에 유의해야 합니다.< /span>

  • CUSTOM_MAGISKBOOT: 압축 풀기를 위한 MagiskBoot 도구의 절대 경로
  • CUSTOM_TWRP: 패키징해야 하는 제3자Recovery

환경 변수 열기

다음 명령을 통해 환경 변수를 설정할 수 있습니다.

export CUSTOM_MAGISKBOOT=<指向您使用的 MagiskBoot 工具的绝对路径>
export CUSTOM_TWRP=<指向您需要替换的 Recovery 镜像的绝对路径>

이 설정을 완료한 후 시스템을 다시 컴파일한 결과 여전히 시스템에 패키징되지 않은 것으로 나타났습니다. 이는 컴파일 프로세스 중에 환경 변수 읽기가 제한되기 때문입니다. 특정 환경 변수만 컴파일 프로세스에 전달되므로 자체 CUSTOM_MAGISKBOOT 및 <도 추가해야 합니다. a i=2>가 화이트리스트에 추가됩니다. CUSTOM_TWRP

수정이 필요한 해당 파일 위치는 build/soong/ui/build/ninja.go 경로 아래에 있으며, 수정된 코드는 다음과 같습니다.

func runNinjaForBuild(ctx Context, config Config) {
    // 其它代码
	if cmd.Environment.IsEnvTrue("ALLOW_NINJA_ENV") {
		ctx.Println("Allowing all environment variables during ninja; incremental builds may be unsafe.")
	} else {
		cmd.Environment.Allow(append([]string{
			/*
                其它参数
            */
			"PYTHONDONTWRITEBYTECODE",
			"TMPDIR",
			"USER",

			// Custom TWRP
			"CUSTOM_MAGISKBOOT",
			"CUSTOM_TWRP",

			// TODO: remove these carefully
			// Options for the address sanitizer.
			"ASAN_OPTIONS",
			/*
                其它参数
            */
		}, config.BuildBrokenNinjaUsesEnvVars()...)...)
	}
    // 其它代码
}

화이트리스트에 CUSTOM_MAGISKBOOTCUSTOM_TWRP를 추가하고 컴파일을 다시 시작하기만 하면 됩니다. 즉, 이제 컴파일 프로세스는 다음과 같습니다.

source build/envsetup.sh
export CUSTOM_MAGISKBOOT="<指向您使用的 MagiskBoot 工具的绝对路径>"
export CUSTOM_TWRP="<指向您需要替换的 Recovery 镜像的绝对路径>"
lunch lineage_[设备代号]-userdebug
croot
mka bacon

힘내 패치

동시에 수정이 쉽도록 편리한 Git패치를 만들었습니다. DogDayAndroid/Android-Builder<를 입력하시면 됩니다. a i =3> 내 패치를 확인해 보세요.

참고자료

이 기사를 공부한 후 얻은 것이 있습니까? 배움에는 끝이 없고 배움은 조류를 거슬러 항해하는 것과 같아서 전진하지 않으면 뒤로 물러나게 된다. 이 글에서는 위의 내용 외에도 고급 안드로이드 연습에 관한 많은 관련 정보를 준비했다. 열심히 활동하고 있는 여러분을 위해 무료로 제공됩니다. 많은 도움이 되었으면 좋겠습니다!

코드를 스캔하여 받으세요! Android 개발을 위한 필수 고급 자료

여기에 이미지 설명을 삽입하세요.

추천

출처blog.csdn.net/m0_56255097/article/details/134507398