Skip to content

Instantly share code, notes, and snippets.

@minhdangoz
Forked from tenzap/Readme.md
Created May 25, 2022 17:28
Show Gist options
  • Save minhdangoz/ac8f7bf2ddaa8107a09d4af70f8fb025 to your computer and use it in GitHub Desktop.
Save minhdangoz/ac8f7bf2ddaa8107a09d4af70f8fb025 to your computer and use it in GitHub Desktop.
Install OpenGApps In Android Emulator (up to API31 / android 12 / S)

Introduction

This works to install OpenGApps into the Android Emulator

Features:

  • uses opengapps installer script (that we patch slightly)
  • linux only because we mount the ext2/4 disk images to modify them. Could be adapted for macos if you use hdiutil instead of kpartx and have installed tools to mount ext2/4 filesystems on macos
  • root permissions mandatory to mount disk images and enter chroot
  • removes verity/verified-boot from the virtual device (so that the AVD can boot, otherwise it would not boot because we didn't update the dm_params)

Tested on:

  • Debian Bullseye (11.x)
  • Android 10 (API 29) with google's x86_arm 'Google APIs' & 'Google Play' system-image. Please note that the auto update of Google play will lead to a constantly crashing "Google Play" App when using a Google APIs image. So, preferably use a Google Play image.
  • Android 8.1 Oreo (API 27) & 9.0 Pie (API 28) with google's x86_arm 'Google APIs' & 'Google Play' system-image. Note that with the 'Google APIs' image, the play store may crash after update, so prefer the Google Play system image as base. Details here: https://forum.xda-developers.com/t/gapps-daily-open-gapps-for-android-all-android-versions-devices.3098071/post-86282683
  • LineageOS 16.0 (API 28) with x86 AOSP system-image
  • For now this doesn't work on Android 10+ because it uses a new system.img that isn't supported yet. It would need to use google's lpunpack & lpmake to extract & recreate the system.img file

The way it works:

  1. clean-up current AVD (system.img, cache.img*, userdata*.img*, VerifiedBootParams.textproto)
  2. copy the original images to the local folder of the android virtual device (AVD) (system.img, vendor.img...) & unpacks the image in case of a Android Q+.
  3. resize the images so that it can contain opengapps
  4. mount the images, prepare the environment & chroot
  5. enter chroot to install the opengapps
    1. patch opengapps installer.sh
    2. proceed with open_gapps install
  6. cleanup environment & unmount images
  7. Repack the images (especially the system.img in the case of Android Q+)

Instructions

  1. Ensure you have unzip, kpartx, losetup, sgdisk, emulator, chroot in your PATH.
    For API 29 you need additional tools to unpack/repack & create the avb information:
    • binaries needed: lpunpack, lpmake, lpdump, fec (instructions are given when you run the script to get them).
    • python3, tar & wget in order to run and download some scripts from the Android sources
  2. Create a new Android Virtual Device (AVD). For example using Android Studio:
    1. Tools -> Android -> AVD Manager
    2. Create Virtual Device...
    3. Phone -> Nexus 5
    4. x86 Images -> Lollipop -> Marshmallow (API 23 x86_64) (Download if necessary)
    5. Give the AVD a name ("Nexus 5 Marshmallow API 23 x86_64")
    6. Choose "Show Advanced Settings...". Give the AVD at least 1536MB Internal Storage, and 512MB SD Card
    7. Finish
  3. Download the appropriate OpenGApps file from opengapps.org (x86 / 9.0 / micro)
  4. Download the ZIP archive of this gist, unpack it and give it executable permission:
    chmod 755 open_gapps_install_script.sh
    chmod 755 open_gapps_install_script.chroot.sh
    
  5. Login as root
  6. Run the open_gapps_install_script.sh with 2 arguments:
    1. Open GApps archive full path
    2. username of the user having the AVD
    ./open_gapps_install_script.sh /path/to/open_gapps-x86-9.0-micro-20220115.zip username
    
  7. When prompted for an AVD, copy the appropriate AVD name and paste it. Press Enter.
  8. When the script is finished, exit from your root shell and return to a normal user shell.
  9. Launch the AVD in the emulator. Please wait, it will take some time.
    emulator @my_AVD_name
    

A sample transcript follows.

Sample Transcript

root@debian:~# LC_ALL=C bash /home/username/open_gapps_install_script.sh /path/to/open_gapps-x86-9.0-pico_go-20220117-UNOFFICIAL.zip username

ANDROID_SDK_ROOT is not set, using default value: /home/username/Android/Sdk
Which AVD?
API28
Amazon_Fire_HD8_API_28
LineageGo_Pixel_3_XL_API_28
Pixel_3a_XL_API_28
Pixel_3a_XL_API_29

>API28

determining location of system.img file for API28 ... /home/username/Android/Sdk/system-images/android-28/google_apis/x86/

copying, checking and resizing system.img for API28
Disabling verity/verified-boot...

Resizing sysem partition to 3000M... (you can safely ignore the warning 'The kernel is still using the old partition table.')
Warning: The kernel is still using the old partition table.
The new table will be used at the next reboot or after you
run partprobe(8) or kpartx(8)
The operation has completed successfully.
Warning: The kernel is still using the old partition table.
The new table will be used at the next reboot or after you
run partprobe(8) or kpartx(8)
The operation has completed successfully.
Setting name!
partNum is 0
Warning: The kernel is still using the old partition table.
The new table will be used at the next reboot or after you
run partprobe(8) or kpartx(8)
The operation has completed successfully.
Warning: The kernel is still using the old partition table.
The new table will be used at the next reboot or after you
run partprobe(8) or kpartx(8)
The operation has completed successfully.
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 3A: Optimizing directories
Pass 4: Checking reference counts
Pass 5: Checking group summary information

/: ***** FILE SYSTEM WAS MODIFIED *****
/: 2968/161280 files (0.4% non-contiguous), 466645/644999 blocks
Resizing the filesystem on /dev/mapper/loop1p1 to 767739 (4k) blocks.
The filesystem on /dev/mapper/loop1p1 is now 767739 (4k) blocks long.

del devmap : loop1p1
loop deleted : /dev/loop1
Resizing sysem partition to 3000M finished successfully!

Mouting the images...

Original PID_Max was 65500
Run 'echo 65500 > /proc/sys/kernel/pid_max' to revert to it

Preparing the chroot environment...
Archive:  /mnt/mounted_avd/tmp_opengappzip/open_gapps-x86-9.0-pico_go-20220117-UNOFFICIAL.zip
signed by SignApk
 extracting: /mnt/mounted_avd/tmp/busybox-x86  

Entering the chroot environment to install OpenGApps...
Archive:  /tmp_opengappzip/open_gapps-x86-9.0-pico_go-20220117-UNOFFICIAL.zip
  inflating: app_densities.txt
Archive:  /tmp_opengappzip/open_gapps-x86-9.0-pico_go-20220117-UNOFFICIAL.zip
  inflating: app_sizes.txt
Archive:  /tmp_opengappzip/open_gapps-x86-9.0-pico_go-20220117-UNOFFICIAL.zip
  inflating: bkup_tail.sh
Archive:  /tmp_opengappzip/open_gapps-x86-9.0-pico_go-20220117-UNOFFICIAL.zip
  inflating: gapps-remove.txt
Archive:  /tmp_opengappzip/open_gapps-x86-9.0-pico_go-20220117-UNOFFICIAL.zip
  inflating: g.prop
Archive:  /tmp_opengappzip/open_gapps-x86-9.0-pico_go-20220117-UNOFFICIAL.zip
  inflating: installer.sh
Archive:  /tmp_opengappzip/open_gapps-x86-9.0-pico_go-20220117-UNOFFICIAL.zip
unzip: can't open 'busybox-x86': Text file busy
Archive:  /tmp_opengappzip/open_gapps-x86-9.0-pico_go-20220117-UNOFFICIAL.zip
  inflating: tar-x86
Archive:  /tmp_opengappzip/open_gapps-x86-9.0-pico_go-20220117-UNOFFICIAL.zip
  inflating: unzip-x86
Archive:  /tmp_opengappzip/open_gapps-x86-9.0-pico_go-20220117-UNOFFICIAL.zip
  inflating: zip-x86
patching file installer.sh
 
##############################
  _____   _____   ___   ____  
 /  _  \ |  __ \ / _ \ |  _ \ 
|  / \  || |__) | |_| || | \ \
| |   | ||  ___/|  __/ | | | |
|  \ /  || |    \ |__  | | | |
 \_/ \_/ |_|     \___| |_| |_|
       ___   _   ___ ___  ___ 
      / __| /_\ | _ \ _ \/ __|
     | (_ |/ _ \|  _/  _/\__ \
      \___/_/ \_\_| |_|  |___/
##############################
 
Open GApps pico_go 9.0 - 20220117
 
- Mounting partitions
...Progress:  1 %
 
- Gathering device & ROM information
 
grep: /tmp/recovery.log: No such file or directory
grep: /cache/recovery/log: No such file or directory
* Stock ROM GApps Currently Installed *
 
The installer detected that Stock ROM GApps are
already installed. If you are flashing over a
Nexus-compatible ROM there is no problem, but if
you are flashing over a custom ROM, you may want
to contact the developer to request the removal of
the included GApps. The installation will now
continue, but please be aware that any problems
that may occur depend on your ROM.
 
...Progress:  3 %
sed: /system/addon.d/70-gapps.sh: No such file or directory
...Progress:  4 %
- Performing system space calculations
 
du: /system/app/AndroidAutoPrebuilt: No such file or directory
du: /system/app/Books: No such file or directory
du: /system/app/CalculatorGooglePrebuilt: No such file or directory
du: /system/app/DMAgent: No such file or directory
du: /system/app/Duo: No such file or directory
du: /system/app/DuoGo: No such file or directory
du: /system/app/EditorsDocs: No such file or directory
du: /system/app/EditorsSheets: No such file or directory
du: /system/app/EditorsSlides: No such file or directory
du: /system/app/FitnessPrebuilt: No such file or directory
du: /system/app/GalleryGo: No such file or directory
du: /system/app/GMailGo: No such file or directory
du: /system/app/GoogleCalendarSyncAdapter: No such file or directory
du: /system/app/GoogleCamera: No such file or directory
du: /system/app/GoogleCameraLegacy: No such file or directory
du: /system/app/GoogleEarth: No such file or directory
du: /system/app/GoogleJapaneseInput: No such file or directory
du: /system/app/GoogleVrCore: No such file or directory
du: /system/app/GoogleZhuyinIME: No such file or directory
du: /system/app/Hangouts: No such file or directory
du: /system/app/KoreanIME: No such file or directory
du: /system/app/MapsGo: No such file or directory
du: /system/app/MarkupGoogle: No such file or directory
du: /system/app/MessagesGo: No such file or directory
du: /system/app/NavGo: No such file or directory
du: /system/app/Newsstand: No such file or directory
du: /system/app/PlayGames: No such file or directory
du: /system/app/PrebuiltExchange3Google: No such file or directory
du: /system/app/PrebuiltKeep: No such file or directory
du: /system/app/Recorder: No such file or directory
du: /system/app/SMSConnectPrebuilt: No such file or directory
du: /system/app/SoundPickerPrebuilt: No such file or directory
du: /system/app/Street: No such file or directory
du: /system/app/talkback: No such file or directory
du: /system/app/TranslatePrebuilt: No such file or directory
du: /system/app/Tycho: No such file or directory
du: /system/app/Wallet: No such file or directory
du: /system/app/WebViewGoogle: No such file or directory
du: /system/app/YouTubeGo: No such file or directory
du: /system/app/YouTubeMusicPrebuilt: No such file or directory
du: /system/etc/default-permissions/default-permissions.xml: No such file or directory
du: /system/etc/default-permissions/opengapps-permissions.xml: No such file or directory
du: /system/etc/permissions/com.google.android.camera2.xml: No such file or directory
du: /system/etc/permissions/com.google.android.camera.experimental2016.xml: No such file or directory
du: /system/etc/permissions/com.google.vr.platform.xml: No such file or directory
du: /system/etc/permissions/privapp-permissions-com.google.android.apps.cameralite.xml: No such file or directory
du: /system/etc/sysconfig/dialer_experience.xml: No such file or directory
du: /system/etc/sysconfig/google_exclusives_enable.xml: No such file or directory
du: /system/etc/sysconfig/google_vr_build.xml: No such file or directory
du: /system/lib/libjni_latinimegoogle.so: No such file or directory
du: /system/lib/libsketchology_native.so: No such file or directory
du: /system/priv-app/AndroidMigratePrebuilt: No such file or directory
du: /system/priv-app/AssistantGo: No such file or directory
du: /system/priv-app/CarrierSetup: No such file or directory
du: /system/priv-app/FilesGo: No such file or directory
du: /system/priv-app/GCS: No such file or directory
du: /system/priv-app/GmsCoreGo: No such file or directory
du: /system/priv-app/GoogleCameraGo: No such file or directory
du: /system/priv-app/GoogleContacts: No such file or directory
du: /system/priv-app/GoogleRestore: No such file or directory
du: /system/priv-app/GoogleSearchGo: No such file or directory
du: /system/priv-app/Phonesky: No such file or directory
du: /system/priv-app/PrebuiltGmsCorePi: No such file or directory
du: /system/priv-app/StorageManagerGoogle: No such file or directory
du: /system/priv-app/Turbo: No such file or directory
du: /system/priv-app/WellbeingPrebuilt: No such file or directory
du: /system/product/overlay/DefaultDialerOverlay.apk: No such file or directory
du: /system/product/overlay/PhoneOverlay.apk: No such file or directory
du: /system/product/overlay/PixelLauncherOverlay.apk: No such file or directory
du: /system/product/overlay/TelecomOverlay.apk: No such file or directory
du: /system/product/overlay/WellbeingOverlay.apk: No such file or directory
du: /system/usr/share/ime/google/d3_lms/en_us_d3_20180105.dict: No such file or directory
du: /system/usr/srec/en-US/: No such file or directory
du: /system/vendor/overlay/DefaultDialerOverlay.apk: No such file or directory
du: /system/vendor/overlay/PhoneOverlay.apk: No such file or directory
du: /system/vendor/overlay/PixelLauncherOverlay.apk: No such file or directory
du: /system/vendor/overlay/TelecomOverlay.apk: No such file or directory
du: /system/vendor/overlay/WellbeingOverlay.apk: No such file or directory
...Progress:  5 %
du: app/BooksStub: No such file or directory
du: app/BookmarkProvider: No such file or directory
du: app/CalendarGoogle: No such file or directory
du: app/CloudPrint: No such file or directory
du: app/DeskClockGoogle: No such file or directory
du: app/EditorsDocsStub: No such file or directory
du: app/EditorsSheetsStub: No such file or directory
du: app/EditorsSlidesStub: No such file or directory
du: app/Gmail: No such file or directory
du: app/Gmail2: No such file or directory
du: app/GoogleCalendar: No such file or directory
du: app/GoogleCloudPrint: No such file or directory
du: app/GoogleHangouts: No such file or directory
du: app/GoogleKeep: No such file or directory
du: app/GoogleLatinIme: No such file or directory
du: app/Keep: No such file or directory
du: app/NewsstandStub: No such file or directory
du: app/PartnerBookmarksProvider: No such file or directory
du: app/PrebuiltBugleStub: No such file or directory
du: app/PrebuiltKeepStub: No such file or directory
du: app/QuickSearchBox: No such file or directory
du: app/Vending: No such file or directory
du: priv-app/GmsCore: No such file or directory
du: priv-app/GoogleNow: No such file or directory
du: priv-app/GoogleSearch: No such file or directory
du: priv-app/GoogleHangouts: No such file or directory
du: priv-app/OneTimeInitializer: No such file or directory
du: priv-app/QuickSearchBox: No such file or directory
du: priv-app/Vending: No such file or directory
du: priv-app/Velvet_update: No such file or directory
du: priv-app/GmsCore_update: No such file or directory
du: product/app/BooksStub: No such file or directory
du: product/app/BookmarkProvider: No such file or directory
du: product/app/CalendarGoogle: No such file or directory
du: product/app/CloudPrint: No such file or directory
du: product/app/DeskClockGoogle: No such file or directory
du: product/app/EditorsDocsStub: No such file or directory
du: product/app/EditorsSheetsStub: No such file or directory
du: product/app/EditorsSlidesStub: No such file or directory
du: product/app/Gmail: No such file or directory
du: product/app/Gmail2: No such file or directory
du: product/app/GoogleCalendar: No such file or directory
du: product/app/GoogleCloudPrint: No such file or directory
du: product/app/GoogleHangouts: No such file or directory
du: product/app/GoogleKeep: No such file or directory
du: product/app/GoogleLatinIme: No such file or directory
du: product/app/Keep: No such file or directory
du: product/app/NewsstandStub: No such file or directory
du: product/app/PartnerBookmarksProvider: No such file or directory
du: product/app/PrebuiltBugleStub: No such file or directory
du: product/app/PrebuiltKeepStub: No such file or directory
du: product/app/QuickSearchBox: No such file or directory
du: product/app/Vending: No such file or directory
du: product/priv-app/GmsCore: No such file or directory
du: product/priv-app/GoogleNow: No such file or directory
du: product/priv-app/GoogleSearch: No such file or directory
du: product/priv-app/GoogleHangouts: No such file or directory
du: product/priv-app/OneTimeInitializer: No such file or directory
du: product/priv-app/QuickSearchBox: No such file or directory
du: product/priv-app/Vending: No such file or directory
du: product/priv-app/Velvet_update: No such file or directory
du: product/priv-app/GmsCore_update: No such file or directory
du: app/CanvasPackageInstaller: No such file or directory
du: app/ConfigUpdater: No such file or directory
du: app/GoogleBackupTransport: No such file or directory
du: app/GoogleFeedback: No such file or directory
du: app/GoogleLoginService: No such file or directory
du: app/GoogleOneTimeInitializer: No such file or directory
du: app/GooglePartnerSetup: No such file or directory
du: app/GoogleServicesFramework: No such file or directory
du: app/OneTimeInitializer: No such file or directory
du: app/Phonesky: No such file or directory
du: app/PrebuiltGmsCore: No such file or directory
du: app/SetupWizard: No such file or directory
du: app/Velvet: No such file or directory
du: product/app/CanvasPackageInstaller: No such file or directory
du: product/app/ConfigUpdater: No such file or directory
du: product/app/GoogleBackupTransport: No such file or directory
du: product/app/GoogleFeedback: No such file or directory
du: product/app/GoogleLoginService: No such file or directory
du: product/app/GoogleOneTimeInitializer: No such file or directory
du: product/app/GooglePartnerSetup: No such file or directory
du: product/app/GoogleServicesFramework: No such file or directory
du: product/app/OneTimeInitializer: No such file or directory
du: product/app/Phonesky: No such file or directory
du: product/app/PrebuiltGmsCore: No such file or directory
du: product/app/SetupWizard: No such file or directory
du: product/app/Velvet: No such file or directory
du: /system/lib/libjni_latinimegoogle.so: No such file or directory
du: /system/lib64/libjni_latinimegoogle.so: No such file or directory
du: /system/app/LatinIME/lib//libjni_latinimegoogle.so: No such file or directory
du: /system/lib/libjni_keyboarddecoder.so: No such file or directory
du: /system/lib64/libjni_keyboarddecoder.so: No such file or directory
du: /system/app/LatinIME/lib//libjni_keyboarddecoder.so: No such file or directory
du: /system/product/lib/libjni_latinimegoogle.so: No such file or directory
du: /system/product/lib64/libjni_latinimegoogle.so: No such file or directory
du: /system/product/app/LatinIME/lib//libjni_latinimegoogle.so: No such file or directory
du: /system/product/lib/libjni_keyboarddecoder.so: No such file or directory
du: /system/product/lib64/libjni_keyboarddecoder.so: No such file or directory
du: /system/product/app/LatinIME/lib//libjni_keyboarddecoder.so: No such file or directory
du: app/CalculatorGoogle: No such file or directory
du: priv-app/GoogleHome: No such file or directory
du: priv-app/Hangouts: No such file or directory
du: priv-app/PrebuiltExchange3Google: No such file or directory
du: priv-app/talkback: No such file or directory
du: priv-app/Wallet: No such file or directory
du: product/app/CalculatorGoogle: No such file or directory
du: product/priv-app/GoogleHome: No such file or directory
du: product/priv-app/Hangouts: No such file or directory
du: product/priv-app/PrebuiltExchange3Google: No such file or directory
du: product/priv-app/talkback: No such file or directory
du: product/priv-app/Wallet: No such file or directory
du: etc/g.prop: No such file or directory
du: addon.d/70-gapps.sh: No such file or directory
...Progress:  7 %
...Progress:  9 %
...Progress:  11 %
...Progress:  13 %
- Removing existing/obsolete Apps
 
- Installing core GApps
...Progress:  15 %
Archive:  /tmp_opengappzip/open_gapps-x86-9.0-pico_go-20220117-UNOFFICIAL.zip
signed by SignApk
 extracting: /tmp/Core/defaultetcgo-common.tar.lz  
Found Core/defaultetcgo-common DPI path: unknown
Archive:  /tmp_opengappzip/open_gapps-x86-9.0-pico_go-20220117-UNOFFICIAL.zip
signed by SignApk
 extracting: /tmp/Core/defaultframework-common.tar.lz  
Found Core/defaultframework-common DPI path: unknown
Archive:  /tmp_opengappzip/open_gapps-x86-9.0-pico_go-20220117-UNOFFICIAL.zip
signed by SignApk
 extracting: /tmp/Core/googlebackuptransport-all.tar.lz  
Found Core/googlebackuptransport-all DPI path: googlebackuptransport-all/nodpi
/tmp/tar-x86: googlebackuptransport-all/common: Not found in archive
/tmp/tar-x86: Exiting with failure status due to previous errors
Archive:  /tmp_opengappzip/open_gapps-x86-9.0-pico_go-20220117-UNOFFICIAL.zip
signed by SignApk
 extracting: /tmp/Core/googlecontactssync-all.tar.lz  
Found Core/googlecontactssync-all DPI path: googlecontactssync-all/nodpi
/tmp/tar-x86: googlecontactssync-all/common: Not found in archive
/tmp/tar-x86: Exiting with failure status due to previous errors
Archive:  /tmp_opengappzip/open_gapps-x86-9.0-pico_go-20220117-UNOFFICIAL.zip
signed by SignApk
 extracting: /tmp/Core/googlefeedback-all.tar.lz  
Found Core/googlefeedback-all DPI path: googlefeedback-all/nodpi
/tmp/tar-x86: googlefeedback-all/common: Not found in archive
/tmp/tar-x86: Exiting with failure status due to previous errors
Archive:  /tmp_opengappzip/open_gapps-x86-9.0-pico_go-20220117-UNOFFICIAL.zip
signed by SignApk
 extracting: /tmp/Core/googleonetimeinitializer-all.tar.lz  
Found Core/googleonetimeinitializer-all DPI path: googleonetimeinitializer-all/nodpi
/tmp/tar-x86: googleonetimeinitializer-all/common: Not found in archive
/tmp/tar-x86: Exiting with failure status due to previous errors
Archive:  /tmp_opengappzip/open_gapps-x86-9.0-pico_go-20220117-UNOFFICIAL.zip
signed by SignApk
 extracting: /tmp/Core/googlepartnersetup-all.tar.lz  
Found Core/googlepartnersetup-all DPI path: googlepartnersetup-all/nodpi
/tmp/tar-x86: googlepartnersetup-all/common: Not found in archive
/tmp/tar-x86: Exiting with failure status due to previous errors
Archive:  /tmp_opengappzip/open_gapps-x86-9.0-pico_go-20220117-UNOFFICIAL.zip
signed by SignApk
 extracting: /tmp/Core/gmscorego-arm.tar.lz  
Found Core/gmscorego-arm DPI path: gmscorego-arm/320
/tmp/tar-x86: gmscorego-arm/common: Not found in archive
/tmp/tar-x86: Exiting with failure status due to previous errors
Archive:  /tmp_opengappzip/open_gapps-x86-9.0-pico_go-20220117-UNOFFICIAL.zip
signed by SignApk
 extracting: /tmp/Core/gsfcore-all.tar.lz  
Found Core/gsfcore-all DPI path: gsfcore-all/nodpi
/tmp/tar-x86: gsfcore-all/common: Not found in archive
/tmp/tar-x86: Exiting with failure status due to previous errors
Archive:  /tmp_opengappzip/open_gapps-x86-9.0-pico_go-20220117-UNOFFICIAL.zip
signed by SignApk
 extracting: /tmp/Core/vending-x86.tar.lz  
Found Core/vending-x86 DPI path: vending-x86/nodpi
/tmp/tar-x86: vending-x86/common: Not found in archive
/tmp/tar-x86: Exiting with failure status due to previous errors
Archive:  /tmp_opengappzip/open_gapps-x86-9.0-pico_go-20220117-UNOFFICIAL.zip
signed by SignApk
 extracting: /tmp/Core/setupwizarddefault-all.tar.lz  
Found Core/setupwizarddefault-all DPI path: setupwizarddefault-all/nodpi
/tmp/tar-x86: setupwizarddefault-all/common: Not found in archive
/tmp/tar-x86: Exiting with failure status due to previous errors
Archive:  /tmp_opengappzip/open_gapps-x86-9.0-pico_go-20220117-UNOFFICIAL.zip
signed by SignApk
 extracting: /tmp/Core/configupdater-all.tar.lz  
Found Core/configupdater-all DPI path: configupdater-all/nodpi
/tmp/tar-x86: configupdater-all/common: Not found in archive
/tmp/tar-x86: Exiting with failure status due to previous errors
Archive:  /tmp_opengappzip/open_gapps-x86-9.0-pico_go-20220117-UNOFFICIAL.zip
signed by SignApk
 extracting: /tmp/Core/extservicesgoogle-all.tar.lz  
Found Core/extservicesgoogle-all DPI path: extservicesgoogle-all/nodpi
/tmp/tar-x86: extservicesgoogle-all/common: Not found in archive
/tmp/tar-x86: Exiting with failure status due to previous errors
Archive:  /tmp_opengappzip/open_gapps-x86-9.0-pico_go-20220117-UNOFFICIAL.zip
signed by SignApk
 extracting: /tmp/Core/extsharedgoogle-all.tar.lz  
Found Core/extsharedgoogle-all DPI path: extsharedgoogle-all/nodpi
/tmp/tar-x86: extsharedgoogle-all/common: Not found in archive
/tmp/tar-x86: Exiting with failure status due to previous errors
Archive:  /tmp_opengappzip/open_gapps-x86-9.0-pico_go-20220117-UNOFFICIAL.zip
signed by SignApk
 extracting: /tmp/Core/carriersetup-all.tar.lz  
Found Core/carriersetup-all DPI path: carriersetup-all/nodpi
/tmp/tar-x86: carriersetup-all/common: Not found in archive
/tmp/tar-x86: Exiting with failure status due to previous errors
Archive:  /tmp_opengappzip/open_gapps-x86-9.0-pico_go-20220117-UNOFFICIAL.zip
signed by SignApk
 extracting: /tmp/Core/backuprestore-all.tar.lz  
Found Core/backuprestore-all DPI path: backuprestore-all/nodpi
/tmp/tar-x86: backuprestore-all/common: Not found in archive
/tmp/tar-x86: Exiting with failure status due to previous errors
 
...Progress:  25 %
ln: /system/app/LatinIME/lib/x86/libjni_latinime.so: No such file or directory
ln: /system/product/app/LatinIME/lib/x86/libjni_latinime.so: No such file or directory
- Installing swypelibs
Archive:  /tmp_opengappzip/open_gapps-x86-9.0-pico_go-20220117-UNOFFICIAL.zip
signed by SignApk
 extracting: /tmp/Optional/swypelibs-lib-x86.tar.lz  
Found Optional/swypelibs-lib-x86 DPI path: unknown
ln: /system/product/app/LatinIME/lib/x86/libjni_latinimegoogle.so: No such file or directory
ln: /system/product/app/LatinIME/lib/x86/libjni_keyboarddecoder.so: No such file or directory
...Progress:  30 %
- Installing calsync
Archive:  /tmp_opengappzip/open_gapps-x86-9.0-pico_go-20220117-UNOFFICIAL.zip
signed by SignApk
 extracting: /tmp/GApps/calsync-all.tar.lz  
Found GApps/calsync-all DPI path: calsync-all/nodpi
/tmp/tar-x86: calsync-all/common: Not found in archive
/tmp/tar-x86: Exiting with failure status due to previous errors
...Progress:  42.5 %
- Installing dialerframework
Archive:  /tmp_opengappzip/open_gapps-x86-9.0-pico_go-20220117-UNOFFICIAL.zip
signed by SignApk
 extracting: /tmp/GApps/dialerframework-common.tar.lz  
Found GApps/dialerframework-common DPI path: unknown
...Progress:  55 %
- Installing googletts
Archive:  /tmp_opengappzip/open_gapps-x86-9.0-pico_go-20220117-UNOFFICIAL.zip
signed by SignApk
 extracting: /tmp/GApps/googletts-x86.tar.lz  
Found GApps/googletts-x86 DPI path: googletts-x86/nodpi
/tmp/tar-x86: googletts-x86/common: Not found in archive
/tmp/tar-x86: Exiting with failure status due to previous errors
...Progress:  67.5 %
- Installing packageinstallergoogle
Archive:  /tmp_opengappzip/open_gapps-x86-9.0-pico_go-20220117-UNOFFICIAL.zip
signed by SignApk
 extracting: /tmp/GApps/packageinstallergoogle-all.tar.lz  
Found GApps/packageinstallergoogle-all DPI path: packageinstallergoogle-all/nodpi
/tmp/tar-x86: packageinstallergoogle-all/common: Not found in archive
/tmp/tar-x86: Exiting with failure status due to previous errors
...Progress:  80 %
 
- Miscellaneous tasks
 
...Progress:  80 %
...Progress:  85 %
...Progress:  92 %
...Progress:  94 %
...Progress:  96 %
- Copying Log to /tmp_opengappzip
 
...Progress:  97 %
- Installation complete!
 
...Progress:  98 %
cp: can't stat '': No such file or directory
cp: can't stat '/system/default.prop': No such file or directory
cp: can't stat '/system/system_ext/build.prop': No such file or directory
cp: can't stat '/system_ext/build.prop': No such file or directory
cp: can't stat '/system_root/default.prop': No such file or directory
cp: can't stat '/system_root/build.prop': No such file or directory
cp: can't stat '/system_root/vendor/build.prop': No such file or directory
cp: can't stat '/system_root/product/build.prop': No such file or directory
cp: can't stat '/system_root/system_ext/build.prop': No such file or directory
cp: can't stat '/data/local.prop': No such file or directory
cp: can't stat '/build.prop': No such file or directory
cp: can't stat '/cache/recovery/log': No such file or directory
cp: can't stat '/tmp/recovery.log': No such file or directory
logcat read failure
...Progress:  100 %
- Unmounting partitions
 

Leaving chroot...

Unmouting the images...
umount: /mnt/mounted_avd/cache: not mounted.
umount: /mnt/mounted_avd/vendor: not mounted.
del devmap : loop2p1
loop deleted : /dev/loop2
del devmap : loop1p1
loop deleted : /dev/loop1

--- a/installer.sh
+++ b/installer.sh
@@ -1093,11 +1093,10 @@
# Pre-define Helper Functions
get_file_prop() { grep -m1 "^$2=" "$1" | cut -d= -f2-; }
-set_progress() { echo "set_progress $1" >> $OUTFD; }
+set_progress() { awk -v VAL=$1 'BEGIN {print "...Progress: ", (VAL * 100),"%" }' ; }
ui_print() {
- echo "ui_print $1
- ui_print" >> $OUTFD
+ echo "$1"
}
find_slot() {
@@ -1295,27 +1294,27 @@
[ "$ANDROID_ROOT" ] || ANDROID_ROOT=/system
# emulators can only flash booted and may need /system (on legacy images), or / (on system-as-root images), remounted rw
-if ! $BOOTMODE; then
- mount -o bind /dev/urandom /dev/random
- if [ -L /etc ]; then
- setup_mountpoint /etc
- cp -af /etc_link/* /etc
- sed -i 's; / ; /system_root ;' /etc/fstab
- fi
- umount_all
- mount_all
-fi
-if [ -d /dev/block/mapper ]; then
- for block in system vendor product system_ext; do
- for slot in "" _a _b; do
- blockdev --setrw /dev/block/mapper/$block$slot 2>/dev/null
- done
- done
-fi
-mount -o rw,remount -t auto /system || mount -o rw,remount -t auto /
-(mount -o rw,remount -t auto /vendor
-mount -o rw,remount -t auto /product
-mount -o rw,remount -t auto /system_ext) 2>/dev/null
+# if ! $BOOTMODE; then
+# mount -o bind /dev/urandom /dev/random
+# if [ -L /etc ]; then
+# setup_mountpoint /etc
+# cp -af /etc_link/* /etc
+# sed -i 's; / ; /system_root ;' /etc/fstab
+# fi
+# umount_all
+# mount_all
+# fi
+# if [ -d /dev/block/mapper ]; then
+# for block in system vendor product system_ext; do
+# for slot in "" _a _b; do
+# blockdev --setrw /dev/block/mapper/$block$slot 2>/dev/null
+# done
+# done
+# fi
+# mount -o rw,remount -t auto /system || mount -o rw,remount -t auto /
+# (mount -o rw,remount -t auto /vendor
+# mount -o rw,remount -t auto /product
+# mount -o rw,remount -t auto /system_ext) 2>/dev/null
ui_print " "
@@ -1444,8 +1443,8 @@
# Unmount and rollback script changes
set_progress 1.0
if ! $BOOTMODE; then
- ui_print "- Unmounting partitions"
- umount_all
+ #ui_print "- Unmounting partitions"
+ #umount_all
[ -L /etc_link ] && rm -rf /etc/*
local dir
(for dir in /apex /system /system_root /etc; do
@@ -1453,8 +1452,8 @@
rmdir $dir
mv -f ${dir}_link $dir
fi
- done
- umount -l /dev/random) 2>/dev/null
+ done) 2>/dev/null
+ #umount -l /dev/random
fi
# Finally, clean up $TMP
@@ -2762,7 +2761,7 @@
# Read and save system partition size details
df=$(df -k /system | tail -n 1)
case $df in
- /dev/block/*) df=$(echo "$df" | awk '{ print substr($0, index($0,$2)) }');;
+ /dev/*) df=$(echo "$df" | awk '{ print substr($0, index($0,$2)) }');;
esac
total_system_size_kb=$(echo "$df" | awk '{ print $1 }')
used_system_size_kb=$(echo "$df" | awk '{ print $2 }')
--- a/installer.sh
+++ b/installer.sh
@@ -1093,11 +1093,10 @@
# Pre-define Helper Functions
get_file_prop() { grep -m1 "^$2=" "$1" | cut -d= -f2-; }
-set_progress() { echo "set_progress $1" >> $OUTFD; }
+set_progress() { awk -v VAL=$1 'BEGIN {print "...Progress: ", (VAL * 100),"%" }' ; }
ui_print() {
- echo "ui_print $1
- ui_print" >> $OUTFD
+ echo "$1"
}
find_slot() {
@@ -1295,27 +1294,27 @@
[ "$ANDROID_ROOT" ] || ANDROID_ROOT=/system
# emulators can only flash booted and may need /system (on legacy images), or / (on system-as-root images), remounted rw
-if ! $BOOTMODE; then
- mount -o bind /dev/urandom /dev/random
- if [ -L /etc ]; then
- setup_mountpoint /etc
- cp -af /etc_link/* /etc
- sed -i 's; / ; /system_root ;' /etc/fstab
- fi
- umount_all
- mount_all
-fi
-if [ -d /dev/block/mapper ]; then
- for block in system vendor product system_ext; do
- for slot in "" _a _b; do
- blockdev --setrw /dev/block/mapper/$block$slot 2>/dev/null
- done
- done
-fi
-mount -o rw,remount -t auto /system || mount -o rw,remount -t auto /
-(mount -o rw,remount -t auto /vendor
-mount -o rw,remount -t auto /product
-mount -o rw,remount -t auto /system_ext) 2>/dev/null
+# if ! $BOOTMODE; then
+# mount -o bind /dev/urandom /dev/random
+# if [ -L /etc ]; then
+# setup_mountpoint /etc
+# cp -af /etc_link/* /etc
+# sed -i 's; / ; /system_root ;' /etc/fstab
+# fi
+# umount_all
+# mount_all
+# fi
+# if [ -d /dev/block/mapper ]; then
+# for block in system vendor product system_ext; do
+# for slot in "" _a _b; do
+# blockdev --setrw /dev/block/mapper/$block$slot 2>/dev/null
+# done
+# done
+# fi
+# mount -o rw,remount -t auto /system || mount -o rw,remount -t auto /
+# (mount -o rw,remount -t auto /vendor
+# mount -o rw,remount -t auto /product
+# mount -o rw,remount -t auto /system_ext) 2>/dev/null
ui_print " "
@@ -1444,8 +1443,8 @@
# Unmount and rollback script changes
set_progress 1.0
if ! $BOOTMODE; then
- ui_print "- Unmounting partitions"
- umount_all
+ #ui_print "- Unmounting partitions"
+ #umount_all
[ -L /etc_link ] && rm -rf /etc/*
local dir
(for dir in /apex /system /system_root /etc; do
@@ -1453,8 +1452,8 @@
rmdir $dir
mv -f ${dir}_link $dir
fi
- done
- umount -l /dev/random) 2>/dev/null
+ done) 2>/dev/null
+ #umount -l /dev/random
fi
# Finally, clean up $TMP
@@ -2762,7 +2761,7 @@
# Read and save system partition size details
df=$(df -k /system | tail -n 1)
case $df in
- /dev/block/*) df=$(echo "$df" | awk '{ print substr($0, index($0,$2)) }');;
+ /dev/*) df=$(echo "$df" | awk '{ print substr($0, index($0,$2)) }');;
esac
total_system_size_kb=$(echo "$df" | awk '{ print $1 }')
used_system_size_kb=$(echo "$df" | awk '{ print $2 }')
#!/bin/bash
ZIPFILE=${1}
USERNAME=${2}
USAGESTRING="Usage: ${0} <open_gapps_zip_file.zip> <user>";
TEMPDIR="$(mktemp --tmpdir -d "gapps_installer.XXXX")"
export RTDIR="/mnt/mounted_avd"
# for lpunpack, lpdump & lpmake
LPTOOLS_BIN_DIR="/mnt/packages/lineageos/lpunpack_and_lpmake/bin"
# path to fec binary
FEC_BINARY="/mnt/packages/downloads/otatools/bin/fec"
if [ -f "$FEC_BINARY" ]; then
FEC_PATH="$(dirname "$FEC_BINARY")"
else
FEC_PATH="$FEC_BINARY"
fi
OS="$(uname)"
if [ $UID -ne 0 ]; then
echo "Root rights needed"
exit 9;
fi
if [ $# -lt 2 ]; then
echo "$USAGESTRING";
exit 1;
fi
if [ ! -f "$ZIPFILE" ]; then
echo "$USAGESTRING";
exit 2;
fi
USER_HOME="$(sudo -u "$USERNAME" sh -c 'echo $HOME')"
if [ ! "$ANDROID_SDK_ROOT" ]; then
if [ -d "$USER_HOME/Android/Sdk" ]; then
echo "ANDROID_SDK_ROOT is not set, using default value: $USER_HOME/Android/Sdk"
ANDROID_SDK_ROOT="$USER_HOME/Android/Sdk"
else
echo "ANDROID_SDK_ROOT is not set"
exit 3;
fi
fi
if [ ! -d "$ANDROID_SDK_ROOT" ]; then
echo "ANDROID_SDK_ROOT is not valid"
exit 4;
fi
a="/$0"; a=${a%/*}; a=${a#/}; a=${a:-.}; SCRIPT_DIR="$(cd "$a"; pwd -P)" || exit 1
########## Functions BEGIN #############
map_disk_img() {
if [ ! -v 2 ]; then
line=1 # We want the 1st line
else
line=$2
fi
if [[ "$OS" == "Linux" ]]; then
if ! which kpartx > /dev/null; then
echo "kpartx command missing, cannot continue";
exit 11;
fi
DEVICE="/dev/mapper/$(kpartx -a -v "$1" | cut -f 3 -d ' ' | sed "$line"'!'"d" )"
elif [[ "$OS" == "Darwin" ]]; then
# TODO
DEVICE=$(hdiutil attach -imagekey diskimage-class=CRawDiskImage -nomount "$1" | grep "Linux Filesystem" | head -1 | cut -f 1 -d ' ')
fi
}
is_mounted() {
if [[ "$OS" == "Linux" ]]; then
if mountpoint -q "$1"; then
return 0
else
return 1
fi
elif [[ "$OS" == "Darwin" ]]; then
if mount | grep -q "$1" > /dev/null; then
return 0
else
return 1
fi
fi
}
mount_img() {
# $1 image path
# $2 mount path
local DEVICE
if file -b "$1" | grep "DOS/MBR boot sector" > /dev/null; then
map_disk_img "$1"
if is_mounted "$2"; then
mount -o remount "$DEVICE" "$2"
else
mount "$DEVICE" "$2"
fi
elif file -b "$1" | grep "ext. filesystem data" > /dev/null; then
if is_mounted "$2"; then
mount -o remount "$1" "$2"
else
mount "$1" "$2"
fi
fi
}
umount_img() {
# $1 image path
# $2 mount path
if is_mounted "$2"; then
umount "$2"
fi
if losetup | grep "$(realpath "$1")" > /dev/null; then
kpartx -d -v "$1"
fi
}
# Mount the filesystems locally & use the installer.sh script provided by OpenGApps
install_with_opengapps_installer() {
echo -e "\nMouting the images..."
# Mount the images
mkdir -p "$RTDIR"
mount_img "$AVD_DIR/tmp/system.img" "$RTDIR"
if [ ! -d "$RTDIR/system" ]; then
SYSIMG_IS_SYSTEM="true"
# On API27, system.img has the content of /system
umount_img "$AVD_DIR/tmp/system.img" "$RTDIR"
mkdir -p "$RTDIR/"{system,cache,vendor,proc,dev}
mount_img "$AVD_DIR/tmp/system.img" "$RTDIR/system"
fi
mount_img "$AVD_DIR/tmp/vendor.img" "$RTDIR/vendor"
mount_img "$AVD_DIR/cache.img" "$RTDIR/cache"
if [ -d "$RTDIR/tmp" ]; then
ROOT_TMP_EXISTED="true"
fi
#it doesn's seem userdata.img is used at first boot, so skip.
#mke2fs $AVD_DIR/userdata.img
#mount $AVD_DIR/userdata.img $RTDIR/data
mount --bind /proc/ "$RTDIR/proc"
mount --bind /dev/ "$RTDIR/dev"
# Mount dir holding the zip (so that it doesn't take space on "/system"
mkdir -p "$RTDIR/tmp_opengappzip"
mount --bind "$(dirname "$ZIPFILE")" "$RTDIR/tmp_opengappzip"
# Change pid_max to a value that suits the chroot
PID_MAX_ORIG=$(cat /proc/sys/kernel/pid_max)
echo -e "\nOriginal PID_Max was $PID_MAX_ORIG"
echo "Run 'echo $PID_MAX_ORIG > /proc/sys/kernel/pid_max' to revert to it"
echo 65500 > /proc/sys/kernel/pid_max
echo -e "\nPreparing the chroot environment..."
# Unpack busybox
unzip -o "$RTDIR/tmp_opengappzip/$(basename "$ZIPFILE")" busybox-x86 -d "$RTDIR/tmp"
mkdir -p "$RTDIR/tmp/bin"
$RTDIR/tmp/busybox-x86 --install "$RTDIR/tmp/bin"
# Copy patch & chroot script to chroot dir
mkdir -p "$RTDIR/tmp/opengapps_in_emulator"
cp "$SCRIPT_DIR/open_gapps_install_script.patch" "$RTDIR/tmp/opengapps_in_emulator"
cp "$SCRIPT_DIR/open_gapps_install_script.chroot.sh" "$RTDIR/tmp/opengapps_in_emulator"
chmod 755 "$SCRIPT_DIR/open_gapps_install_script.chroot.sh"
# Run script in chroot
echo -e "\nEntering the chroot environment to install OpenGApps..."
PATH=/tmp/bin:/system/bin:$PATH chroot "$RTDIR" "/tmp/bin/bash" "/tmp/opengapps_in_emulator/open_gapps_install_script.chroot.sh" "$(basename "$ZIPFILE")"
echo -e "\nLeaving chroot..."
# Make a copy of the /data partition because we can't load it into the chroot
#mkdir -p /tmp/my_avd_data
#cp -a "$RTDIR/data/*" /tmp/my_avd_data/
# Restore original pid_max
echo $PID_MAX_ORIG > /proc/sys/kernel/pid_max
# Unmount the images & cleanup
echo -e "\nUnmouting the images..."
umount "$RTDIR/tmp_opengappzip"
rmdir "$RTDIR/tmp_opengappzip"
if [ ! "a$ROOT_TMP_EXISTED" = "atrue" ]; then rmdir "$RTDIR/tmp" ; fi
umount_img "$AVD_DIR/cache.img" "$RTDIR/cache"
umount_img "$AVD_DIR/tmp/vendor.img" "$RTDIR/vendor"
#umount_img "$RTDIR/data"
umount "$RTDIR/proc"
umount "$RTDIR/dev"
if [[ "a$SYSIMG_IS_SYSTEM" == "atrue" ]]; then
rmdir "$RTDIR/"{system,cache,vendor,proc,dev,tmp}
umount_img "$AVD_DIR/tmp/system.img" "$RTDIR/system"
else
umount_img "$AVD_DIR/tmp/system.img" "$RTDIR"
fi
# Review the contents of the data partition, you may need to copy
# things over through adb once the emulator is loaded (if this works)
# adb push /tmp/my_avd_data/* /data
# rm -r /tmp/my_avd_data/
}
upsize_extfs() {
# $1 device path to the filesystem to upsize
# $2 size
"${ANDROID_SDK_ROOT}/emulator/bin64/e2fsck" -f "$1" 2> /dev/null
if [ -z "$2" ]; then
"${ANDROID_SDK_ROOT}/emulator/bin64/resize2fs" "$1" 2> /dev/null
else
"${ANDROID_SDK_ROOT}/emulator/bin64/resize2fs" "$1" "$2" 2> /dev/null
fi
}
resize_img() {
local image="$1"
local size="$2"
if file -b "$image" | grep "DOS/MBR boot sector" > /dev/null; then
# The system.img is not ext2/ext4 but a DOS/MBR boot sector which contains an ext2/3/4 fs
echo -e "\nResizing sysem partition to $size... (you can safely ignore the warning 'The kernel is still using the old partition table.')"
fallocate -l "$size" "$image"
PART_UUID=$(sgdisk -i 1 "$image" | grep "unique GUID" | cut -d ' ' -f4)
sgdisk -d 1 "$image"
sgdisk -n 1:0:0 "$image"
sgdisk -c 1:system "$image"
sgdisk -u 1:$PART_UUID "$image"
PART=$(kpartx -a -v "$image" | cut -f 3 -d ' ')
SYS_EXT_PART_PATH="/dev/mapper/$PART"
upsize_extfs "$SYS_EXT_PART_PATH" ;
kpartx -d -v "$image"
echo "Resizing sysem partition to $size finished successfully!"
elif file -b "$image" | grep "ext. filesystem data" > /dev/null; then
upsize_extfs "$image" "$size"
else
echo "$image format not supported by this script"
exit 10;
fi
}
unpack_images() {
echo -e "\nUnpack original partition images for ${AVD}"
mkdir -p "$AVD_DIR/tmp"
if [ $(kpartx "${ANDROID_SDK_ROOT}/${IMAGE_SYSDIR}/system.img" | wc -l) -gt 1 ]; then
lptools_required
# API 29 image (android Q) holding a super.img
map_disk_img "${ANDROID_SDK_ROOT}/${IMAGE_SYSDIR}/system.img" 2
"$LPTOOLS_BIN_DIR/lpunpack" --slot=0 -p system "$DEVICE" "$AVD_DIR/tmp"
"$LPTOOLS_BIN_DIR/lpunpack" --slot=0 -p vendor "$DEVICE" "$AVD_DIR/tmp"
"$LPTOOLS_BIN_DIR/lpdump" -j "$DEVICE" > "$AVD_DIR/tmp/lpdump.json"
"$LPTOOLS_BIN_DIR/lpdump" "$DEVICE" > "$AVD_DIR/tmp/lpdump.txt"
# Filesystems have the feature: EXT4_FEATURE_RO_COMPAT_SHARED_BLOCKS
# We need to remove it to mount rw,
# and at least resize the partition a bit if there is not enough space
for img in system.img vendor.img; do
FS_SIZE=$(wc -c "$AVD_DIR/tmp/$img" | cut -f 1 -d ' ')
e2fsck -f -y "$AVD_DIR/tmp/$img"
# Increase size by 10% to be able to unshare_blocks
resize2fs "$AVD_DIR/tmp/$img" $(( FS_SIZE * 11 / 10 / 1024 ))K
e2fsck -y -E unshare_blocks "$AVD_DIR/tmp/$img" > /dev/null 2>&1
e2fsck -f -y "$AVD_DIR/tmp/$img"
done
else
cp "${ANDROID_SDK_ROOT}/${IMAGE_SYSDIR}/vendor.img" "${AVD_DIR}/tmp/vendor.img"
cp "${ANDROID_SDK_ROOT}/${IMAGE_SYSDIR}/system.img" "${AVD_DIR}/tmp/system.img"
fi
if [ -f "${ANDROID_SDK_ROOT}/${IMAGE_SYSDIR}/encryptionkey.img" ]; then
if [ ! -f "${AVD_DIR}/encryptionkey.img" ]; then
echo "copying encryptionkey.img ..."
cp "${ANDROID_SDK_ROOT}/${IMAGE_SYSDIR}/encryptionkey.img" "${AVD_DIR}/encryptionkey.img"
fi
fi
}
cleanup_avd() {
rm -f "${AVD_DIR}/vendor.img"
rm -f "${AVD_DIR}/system.img"
rm -f "${AVD_DIR}/cache.img"
rm -f "${AVD_DIR}/cache.img.qcow2"
rm -f "${AVD_DIR}/userdata-qemu.img"
rm -f "${AVD_DIR}/userdata-qemu.img.qcow2"
rm -fr "${AVD_DIR}/snapshots/default_boot/"
}
disable_verified_boot_pre_q() {
# On Android Pie, we disable it since we modify the system.img file. Otherwise the emulator will not boot.
if [ -f "${ANDROID_SDK_ROOT}/${IMAGE_SYSDIR}/VerifiedBootParams.textproto" ] \
&& grep "^dm_param" "${ANDROID_SDK_ROOT}/${IMAGE_SYSDIR}/VerifiedBootParams.textproto" > /dev/null ; then
# If the file exists, maybe the emulator has Verity/Verified boot enabled.
if [ ! -f "${AVD_DIR}/VerifiedBootParams.textproto" ]; then
echo "copying VerifiedBootParams.textproto..."
cp "${ANDROID_SDK_ROOT}/${IMAGE_SYSDIR}/VerifiedBootParams.textproto" "${AVD_DIR}/VerifiedBootParams.textproto"
fi
echo "Disabling verity/verified-boot..."
sed -i -e "s/^dm_param/#dm_param/" "${AVD_DIR}/VerifiedBootParams.textproto"
fi
}
lptools_required() {
if [ ! -e $LPTOOLS_BIN_DIR/lpmake ] || [ ! -e $LPTOOLS_BIN_DIR/lpmake ] || [ ! -e $LPTOOLS_BIN_DIR/lpmake ]; then
echo "lpmake, lpdump and lpunpack are missing. Get them and check LPTOOLS_BIN_DIR in the script "
echo "Packaged sources (including the minimal android sources to build): https://github.com/LonelyFool/lpunpack_and_lpmake"
echo "Upstream sources (needs all android sources): https://android.googlesource.com/platform/system/extras/+/refs/heads/master/partition_tools/"
exit 8
fi
}
repack_images() {
# No need to repack if this is not a combined_img (appeard in android Q)
if [ $(kpartx "${ANDROID_SDK_ROOT}/${IMAGE_SYSDIR}/system.img" | wc -l) -le 1 ]; then return 0; fi
# Build the dynamic partiton system.img and the avb/verity/verified-boot related files/hases for android Q+ (10+)
lptools_required
if [ ! -e $FEC_BINARY ]; then
echo "fec binary missing. Get them and check FEC_BINARY in the script "
echo "prebuild binary can be found in the otatools here: https://forum.xda-developers.com/t/guide-ota-tools-lpunpack.4041843/"
exit 8
fi
# Doc for verified boot:
# https://android.googlesource.com/platform/external/avb/+/master/README.md
# Download & extract some required scripts & files from anroid sources:
wget -nc https://android.googlesource.com/platform/external/avb/+archive/master.tar.gz -O "$TEMPDIR/avbtool.tar.gz"
tar -xvf "$TEMPDIR/avbtool.tar.gz" -C "$TEMPDIR" \
avbtool.py \
test/data/testkey_rsa2048.pem \
test/data/testkey_rsa4096.pem
chmod +x "$TEMPDIR/avbtool.py"
mv "$TEMPDIR/test/data/testkey_rsa2048.pem" "$TEMPDIR/"
mv "$TEMPDIR/test/data/testkey_rsa4096.pem" "$TEMPDIR/"
rmdir "$TEMPDIR/test/data"
rmdir "$TEMPDIR/test"
# https://cs.android.com/android/platform/superproject/+/master:device/generic/goldfish/tools/mk_vbmeta_boot_params.sh
# https://cs.android.com/android/platform/superproject/+/master:device/generic/goldfish/tools/mk_combined_img.py
wget -nc https://android.googlesource.com/device/generic/goldfish/+archive/refs/heads/master/tools.tar.gz -O "$TEMPDIR/goldfish_tools.tar.gz"
tar -xvf "$TEMPDIR/goldfish_tools.tar.gz" -C "$TEMPDIR" \
mk_vbmeta_boot_params.sh \
mk_combined_img.py
chmod +x "$TEMPDIR/mk_vbmeta_boot_params.sh"
chmod +x "$TEMPDIR/mk_combined_img.py"
# Add Hashtree footer to the images
# We need the binary of "fec"
# Sources: here http://www.ka9q.net/code/fec/ or there https://android.googlesource.com/platform/external/fec/+/master/)
# Binary in otatools
#$TEMPDIR/avbtool.py erase_footer --image "${AVD_DIR}/tmp/vendor.img"
PATH=$PATH:$FEC_PATH "$TEMPDIR/avbtool.py" add_hashtree_footer \
--partition_name vendor \
--partition_size 0 \
--image "${AVD_DIR}/tmp/vendor.img"
#--prop com.android.build.system.os_version:10
"$TEMPDIR/avbtool.py" info_image --image "${AVD_DIR}/tmp/vendor.img"
"$TEMPDIR/avbtool.py" verify_image --image "${AVD_DIR}/tmp/vendor.img"
#"$TEMPDIR/avbtool.py" erase_footer --image "${AVD_DIR}/tmp/system.img"
# We skip the rollback index value (--rollback-index)
PATH=$PATH:$FEC_PATH "$TEMPDIR/avbtool.py" add_hashtree_footer \
--partition_name system \
--partition_size 0 \
--image "${AVD_DIR}/tmp/system.img" \
--algorithm SHA256_RSA2048 \
--key "$TEMPDIR/testkey_rsa2048.pem"
#--prop com.android.build.system.os_version:10 \
#--prop com.android.build.system.security_patch:2019-09-05
"$TEMPDIR/avbtool.py" info_image --image "${AVD_DIR}/tmp/system.img"
"$TEMPDIR/avbtool.py" verify_image --image "${AVD_DIR}/tmp/system.img" --key "$TEMPDIR/testkey_rsa2048.pem"
"$TEMPDIR/avbtool.py" extract_public_key --key "$TEMPDIR/testkey_rsa2048.pem" --output "$TEMPDIR/system_rsa2048.avbpubkey"
# Create vbmeta image with dm-verity disabled
# https://wiki.postmarketos.org/wiki/Android_Verified_Boot_(AVB)
# "$TEMPDIR/avbtool.py" make_vbmeta_image \
# --flags 2 \
# --padding_size 4096 \
# --output ${AVD_DIR}/tmp/vbmeta_disabled.img \
# --chain_partition system:1:$TEMPDIR/system_rsa2048.avbpubkey
# Remove old vbmeta.img, then create vbmeta image
rm -f "${AVD_DIR}/tmp/vbmeta.img"
"$TEMPDIR/avbtool.py" make_vbmeta_image \
--algorithm SHA256_RSA4096 \
--key "$TEMPDIR/testkey_rsa4096.pem" \
--padding_size 4096 \
--output "${AVD_DIR}/tmp/vbmeta.img" \
--chain_partition system:1:$TEMPDIR/system_rsa2048.avbpubkey \
--include_descriptors_from_image "${AVD_DIR}/tmp/vendor.img"
"$TEMPDIR/avbtool.py" info_image --image "${AVD_DIR}/tmp/vbmeta.img"
"$TEMPDIR/avbtool.py" verify_image --image "${AVD_DIR}/tmp/vbmeta.img" \
--expected_chain_partition system:1:$TEMPDIR/system_rsa2048.avbpubkey \
--key "$TEMPDIR/testkey_rsa4096.pem"
# Create VerifiedBootParams.textproto
AVBTOOL="$(realpath "$TEMPDIR/avbtool.py")" "$TEMPDIR/mk_vbmeta_boot_params.sh" \
"${AVD_DIR}/tmp/vbmeta.img" \
"${AVD_DIR}/tmp/system.img" \
"${AVD_DIR}/tmp/VerifiedBootParams.textproto"
mv "${AVD_DIR}/tmp/VerifiedBootParams.textproto" "${AVD_DIR}/VerifiedBootParams.textproto"
# Prepare variables to repack super.img with lpmake
REPLICATE_LPDUMP=0
if [[ $REPLICATE_LPDUMP -eq 1 ]]; then
LPMAKE_DEVICE_SIZE=$(jq -r '.block_devices[0].size' "$AVD_DIR/tmp/lpdump.json")
LPMAKE_SUPER_NAME=$(jq -r '.block_devices[0].name' "$AVD_DIR/tmp/lpdump.json")
LPMAKE_ALIGNMENT=$(jq -r '.block_devices[0].alignment' "$AVD_DIR/tmp/lpdump.json")
LPMAKE_BLOCK_SIZE=$(jq -r '.block_devices[0].block_size' "$AVD_DIR/tmp/lpdump.json")
LPMAKE_GROUP_NAME=$(jq -r '.partitions[0].group_name' "$AVD_DIR/tmp/lpdump.json")
LPMAKE_METADATA_SIZE=$(cat "$AVD_DIR/tmp/lpdump.txt" | grep "Metadata max size:" | cut -d ' ' -f 4)
LPMAKE_METADATA_SLOTS=$(cat "$AVD_DIR/tmp/lpdump.txt" | grep "Metadata slot count:" | cut -d ' ' -f 4)
LPMAKE_PART_SYSTEM_SIZE=$(jq -r '.partitions[] | select(.name | contains("system")).size ' "$AVD_DIR/tmp/lpdump.json")
LPMAKE_PART_VENDOR_SIZE=$(jq -r '.partitions[] | select(.name | contains("vendor")).size ' "$AVD_DIR/tmp/lpdump.json")
LPMAKE_GROUP_MAX_SIZE=$(jq -r '.groups[] | select(.name | contains ("'$LPMAKE_GROUP_NAME'")).maximum_size' "$AVD_DIR/tmp/lpdump.json")
else
LPMAKE_SUPER_NAME=$(jq -r '.block_devices[0].name' "$AVD_DIR/tmp/lpdump.json")
LPMAKE_ALIGNMENT=$(jq -r '.block_devices[0].alignment' "$AVD_DIR/tmp/lpdump.json")
LPMAKE_BLOCK_SIZE=$(jq -r '.block_devices[0].block_size' "$AVD_DIR/tmp/lpdump.json")
LPMAKE_GROUP_NAME=$(jq -r '.partitions[0].group_name' "$AVD_DIR/tmp/lpdump.json")
LPMAKE_METADATA_SIZE=$(cat "$AVD_DIR/tmp/lpdump.txt" | grep "Metadata max size:" | cut -d ' ' -f 4)
LPMAKE_METADATA_SLOTS=$(cat "$AVD_DIR/tmp/lpdump.txt" | grep "Metadata slot count:" | cut -d ' ' -f 4)
LPMAKE_PART_SYSTEM_SIZE=$(wc -c "$AVD_DIR/tmp/system.img" | cut -f 1 -d ' ')
LPMAKE_PART_VENDOR_SIZE=$(wc -c "$AVD_DIR/tmp/vendor.img" | cut -f 1 -d ' ')
# LPMAKE_GROUP_MAX_SIZE: round size to multiple of 1024*1024 (size of all partitions + 2MiB)
LPMAKE_GROUP_MAX_SIZE=$(( ( ( ( LPMAKE_PART_SYSTEM_SIZE + LPMAKE_PART_VENDOR_SIZE ) / 1024 / 1024 ) + 2 ) * 1024 * 1024))
# LPMAKE_DEVICE_SIZE = LPMAKE_GROUP_MAX_SIZE + 8MiB
LPMAKE_DEVICE_SIZE=$(( LPMAKE_GROUP_MAX_SIZE + ( 8 * 1024 * 1024 ) ))
#LPMAKE_DEVICE_SIZE=$(( $(jq -r '.block_devices[0].size' "$AVD_DIR/tmp/lpdump.json") + (100 * 1024 * 1024) ))
fi
# Repack the super.img
"$LPTOOLS_BIN_DIR/lpmake" \
--device-size=$LPMAKE_DEVICE_SIZE \
--metadata-size=$LPMAKE_METADATA_SIZE \
--metadata-slots=$LPMAKE_METADATA_SLOTS \
--output="${AVD_DIR}/tmp/super.img" \
-p system:readonly:$LPMAKE_PART_SYSTEM_SIZE:$LPMAKE_GROUP_NAME \
-i system="${AVD_DIR}/tmp/system.img" \
-p vendor:readonly:$LPMAKE_PART_VENDOR_SIZE:$LPMAKE_GROUP_NAME \
-i vendor="${AVD_DIR}/tmp/vendor.img" \
--block-size=$LPMAKE_BLOCK_SIZE \
--alignment=$LPMAKE_ALIGNMENT \
--super-name="$LPMAKE_SUPER_NAME" \
--group=$LPMAKE_GROUP_NAME:$LPMAKE_GROUP_MAX_SIZE
# Delete system.img & vendor.img (we now have super.img)
#for img in system.img vendor.img; do
# rm "${AVD_DIR}/tmp/$img"
#done
if [[ $REPLICATE_LPDUMP -eq 1 ]]; then
dd if="${DEVICE::-1}1" of="${AVD_DIR}/vbmeta.img"
fi
# Prepare image_config file to build the combined img that will be used as system.img for the emulator
echo "${AVD_DIR}/tmp/vbmeta.img vbmeta 1" > "${AVD_DIR}/tmp/image_config"
echo "${AVD_DIR}/tmp/super.img super 2" >> "${AVD_DIR}/tmp/image_config"
# Fix incorrect arguments when calling sgdisk (replace --type= by --typecode= )
sed -i -e "s/--type=/--typecode=/" "$TEMPDIR/mk_combined_img.py"
# Remove previous image (because the mk_combined_img.py behaves differently if the file already exists)
# Then, create the combined image
rm -f "${AVD_DIR}/tmp/combined.img"
"$TEMPDIR/mk_combined_img.py" -i "${AVD_DIR}/tmp/image_config" -o "${AVD_DIR}/tmp/combined.img"
# Cleanup
rm "${AVD_DIR}/tmp/image_config"
rm "${AVD_DIR}/tmp/vbmeta.img"
rm "${AVD_DIR}/tmp/super.img"
rm "${AVD_DIR}/tmp/lpdump.json"
rm "${AVD_DIR}/tmp/lpdump.txt"
# Some variables set in Android Makefile
#BOARD_AVB_ENABLE := true
#BOARD_AVB_ALGORITHM := SHA256_RSA4096
#BOARD_AVB_KEY_PATH := external/avb/test/data/$TEMPDIR/testkey_rsa4096.pem
# Enable chain partition for system. https://cs.android.com/android/platform/superproject/+/master:build/make/target/board/BoardConfigEmuCommon.mk;l=82?q=BOARD_AVB_SYSTEM_KEY_PATH&ss=android%2Fplatform%2Fsuperproject
#BOARD_AVB_SYSTEM_KEY_PATH := external/avb/test/data/$TEMPDIR/testkey_rsa2048.pem
#BOARD_AVB_SYSTEM_ALGORITHM := SHA256_RSA2048
#BOARD_AVB_SYSTEM_ROLLBACK_INDEX := $(PLATFORM_SECURITY_PATCH_TIMESTAMP)
#BOARD_AVB_SYSTEM_ROLLBACK_INDEX_LOCATION := 1
#BOARD_SUPER_PARTITION_SIZE := 3229614080
}
########## Functions END #############
echo "Which AVD?"
sudo -u "$USERNAME" "${ANDROID_SDK_ROOT}/emulator/emulator" -list-avds
echo -en "\n>"
read -r AVD
AVD_DIR=$(grep "path=" "${USER_HOME}/.android/avd/${AVD}.ini" | cut -f2 -d"=")
AVD_DIR=${AVD_DIR// } # trim
echo -en "\ndetermining location of system.img file for ${AVD} ... "
IMAGE_SYSDIR=$(grep "image.sysdir.1" "${AVD_DIR}/config.ini" | cut -f2 -d"=")
IMAGE_SYSDIR=${IMAGE_SYSDIR// } # trim
echo "${ANDROID_SDK_ROOT}/${IMAGE_SYSDIR}"
# Cleanup current avd instance
cleanup_avd
# Copy clean system.img to selected AVD and related stuff
unpack_images
# Resize system.img
resize_img "${AVD_DIR}/tmp/system.img" "3072M"
# Install with the OpenGApps installer in a chroot environment
install_with_opengapps_installer
# Repack images
repack_images
# Disable verfied boot (for version before Android-Q)
disable_verified_boot_pre_q
# Resize data partition
sed -i -e "s/disk.dataPartition.size.*/disk.dataPartition.size=1536M/" "${AVD_DIR}/config.ini"
# Install the built images into the avd
if [ $(kpartx "${ANDROID_SDK_ROOT}/${IMAGE_SYSDIR}/system.img" | wc -l) -le 1 ]; then
mv "${AVD_DIR}/tmp/system.img" "${AVD_DIR}"
mv "${AVD_DIR}/tmp/vendor.img" "${AVD_DIR}"
else
# Move combined.img to system.img for use by the emulator
mv "${AVD_DIR}/tmp/combined.img" "${AVD_DIR}/system.img"
fi
rm -r "$TEMPDIR"
rmdir "${AVD_DIR}/tmp"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment