Recovery
모드는 사용자가 일반 모드에서 수행할 수 없는 다음과 같은 일부 작업을 수행할 수 있도록 하는 Android
시스템의 특수 모드입니다.
- 설치 또는 업그레이드
Android
시스템 - 초기화
- 캐시 지우기
- SD 카드 포맷
- 플래시 타사 ROM
Recovery
모드는 커널과 RAM
기본 시스템과 다른 시스템에 있는 디스크 로 구성됩니다. 파티션에서. Linux
Android
제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 Recovery
의 Recovery
응고 스크립트를 확인해야 합니다. 그중 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
의 응고 과정은 다음과 같습니다.
-
- 이용
MagiskBoot
장 제3방Recovery
ramdisk.cpio
- 이용
-
- 从系窟中 제출
boot.img
;
- 从系窟中 제출
-
- 추출된 파일의 압축을 풉니다.
boot.img
;
- 추출된 파일의 압축을 풉니다.
-
- 타사를 이용
Recovery
하여ramdisk.cpio
파일의 압축을 풀고 추출한 후boot.img
압축을 푼 파일을 교체합니다. < a i=4> 파일;ramdisk.cpio
- 타사를 이용
-
- 재포장
boot.img
거울;
- 재포장
-
- 원래 파티션에 다시 쓰기
구체적인 조작
포장 프로세스 수정
고형화 단계의 비유를 시스템 컴파일 프로세스에 추가하고 컴파일된 이미지를 모아 플래시 패키지를 조립하는 이전 단계에서 교체를 구현하면 사용자 정의가 가능합니다. < 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
의 치료 스크립트와 다소 유사합니다. . 은 a
및 b
두 파티션을 순회하여 관련 작업을 수행하므로 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_MAGISKBOOT
및 CUSTOM_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 개발을 위한 필수 고급 자료