Skip to content

Instantly share code, notes, and snippets.

@minhdangoz
Forked from tenzap/Readme.md
Created May 25, 2022 17:28

Revisions

  1. @tenzap tenzap revised this gist Jan 22, 2022. 1 changed file with 70 additions and 26 deletions.
    96 changes: 70 additions & 26 deletions open_gapps_install_script.sh
    Original file line number Diff line number Diff line change
    @@ -72,10 +72,24 @@ map_disk_img() {
    DEVICE="/dev/mapper/$(kpartx -a -v "$1" | cut -f 3 -d ' ' | sed "$line"'!'"d" )"
    elif [[ "$OS" == "Darwin" ]]; then
    # TODO
    echo "Not implemented/tested. Please do."
    exit 35
    DEVICE=$(hdiutil attach -imagekey diskimage-class=CRawDiskImage -nomount "$1" | grep "Linux Filesystem" | head -1 | cut -f 1 -d ' ')
    fi
    }

    unmap_disk_img() {
    if [[ "$OS" == "Linux" ]]; then
    if losetup | grep "$(realpath "$1")" > /dev/null; then
    kpartx -d -v "$1" > /dev/null 2>&1
    fi
    elif [[ "$OS" == "Darwin" ]]; then
    # TODO
    echo "Not implemented. Please do"
    exit 34;
    fi
    }

    is_mounted() {
    if [[ "$OS" == "Linux" ]]; then
    if mountpoint -q "$1"; then
    @@ -120,9 +134,7 @@ umount_img() {
    if is_mounted "$2"; then
    umount "$2"
    fi
    if losetup | grep "$(realpath "$1")" > /dev/null; then
    kpartx -d -v "$1"
    fi
    unmap_disk_img "$1"
    }

    # Mount the filesystems locally & use the installer.sh script provided by OpenGApps
    @@ -240,28 +252,56 @@ upsize_extfs() {

    downsize_extfs() {
    # $1 device/file holding the filesystem
    if file -b "$1" | grep "ext. filesystem data" > /dev/null; then
    "${ANDROID_SDK_ROOT}/emulator/bin64/e2fsck" -f "$1" 2> /dev/null
    "${ANDROID_SDK_ROOT}/emulator/bin64/resize2fs" -M "$1"
    "${ANDROID_SDK_ROOT}/emulator/bin64/e2fsck" -f "$1" 2> /dev/null
    "${ANDROID_SDK_ROOT}/emulator/bin64/resize2fs" -M "$1"
    }

    downsize_img() {
    local image="$1"
    echo -e "\n Downsizing image $1"

    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 (actually GPT) which contains an ext2/3/4 fs
    map_disk_img "$image"
    downsize_extfs "$DEVICE"
    BS=$(dumpe2fs -h "$DEVICE" 2> /dev/null | sed -n -e "s/Block size:\s*\(\d*\)/\1/p")
    BC=$(dumpe2fs -h "$DEVICE" 2> /dev/null | sed -n -e "s/Block count:\s*\(\d*\)/\1/p")
    unmap_disk_img "$image"

    SECTOR_SIZE=$(sgdisk -p "$image" | grep "Sector size (logical):" | cut -d " " -f 4)
    PART_NAME=$(sgdisk -i1 "$image" | sed -n -e "s/Partition name:\s*'\(.*\)'.*/\1/p")
    PART_OFFSET_SECTORS=$(sgdisk -i1 "$image" | grep "First sector" | cut -d " " -f 3)
    PART_SIZE_B=$(( BS * BC ))
    PART_END_B=$(( PART_OFFSET_SECTORS * SECTOR_SIZE + PART_SIZE_B ))
    GPT_FOOTER_SIZE_B=$((33 * SECTOR_SIZE))
    DISK_SIZE_B=$(( PART_END_B + GPT_FOOTER_SIZE_B ))

    truncate -s $DISK_SIZE_B "$image"
    sgdisk -Z "$image" > /dev/null 2>&1
    sgdisk -n 1:$PART_OFFSET_SECTORS:+$(( PART_SIZE_B / SECTOR_SIZE )) "$image" > /dev/null 2>&1
    sgdisk -c 1:"$PART_NAME" "$image" > /dev/null 2>&1
    sgdisk -t 1:8300 "$image" > /dev/null 2>&1
    elif file -b "$image" | grep "ext. filesystem data" > /dev/null; then
    downsize_extfs "${AVD_DIR}/tmp/$file"
    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
    # The system.img is not ext2/ext4 but a DOS/MBR boot sector (actually GPT) 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"
    map_disk_img "$image"
    SYS_EXT_PART_PATH="$DEVICE"
    upsize_extfs "$SYS_EXT_PART_PATH" ;
    kpartx -d -v "$image"
    unmap_disk_img "$image"
    echo "Resizing sysem partition to $size finished successfully!"
    elif file -b "$image" | grep "ext. filesystem data" > /dev/null; then
    upsize_extfs "$image" "$size"
    @@ -290,7 +330,8 @@ unpack_images() {
    for partition in $(jq -r ".partitions[].name" "$AVD_DIR/tmp/lpdump.json"); do
    echo -e "\nUnpacking & converting to read/write: $partition.img"

    local PART_SIZE=$(jq -r '.partitions[] | select(.name=="'$partition'").size ' "$AVD_DIR/tmp/lpdump.json")
    local PART_SIZE
    PART_SIZE=$(jq -r '.partitions[] | select(.name=="'$partition'").size ' "$AVD_DIR/tmp/lpdump.json")
    check_free_space "${AVD_DIR}/tmp" $(( PART_SIZE * 11 / 10 ))

    "$LPTOOLS_BIN_DIR/lpunpack" --slot=0 -p $partition "$DEVICE" "$AVD_DIR/tmp"
    @@ -320,12 +361,14 @@ unpack_images() {
    }

    set_new_size() {
    local USED_IN_KB NEW_SIZE_IN_B CUR_SIZE_IN_B

    mount_img "$AVD_DIR/tmp/system.img" "$RTDIR"
    local USED_IN_KB=$(df --output=used "$RTDIR" | tail -1)
    USED_IN_KB=$(df --output=used "$RTDIR" | tail -1)
    umount_img "$AVD_DIR/tmp/system.img" "$RTDIR"

    local NEW_SIZE_IN_B="$(( ( USED_IN_KB + REQUIRED_SPACE_FOR_OPENGAPPS_IN_MB * 1024 ) * 1024 ))"
    local CUR_SIZE_IN_B=$(wc -c "${AVD_DIR}/tmp/system.img" | cut -f 1 -d ' ')
    NEW_SIZE_IN_B="$(( ( USED_IN_KB + REQUIRED_SPACE_FOR_OPENGAPPS_IN_MB * 1024 ) * 1024 ))"
    CUR_SIZE_IN_B=$(wc -c "${AVD_DIR}/tmp/system.img" | cut -f 1 -d ' ')

    if [ $CUR_SIZE_IN_B -ge $NEW_SIZE_IN_B ]; then
    NEW_SIZE="$((CUR_SIZE_IN_B / 1024 / 1024 + 1))M"
    @@ -419,7 +462,7 @@ repack_images() {
    unset PROP_ARGS
    declare -a PROP_ARGS=()
    for line in $(grep "Prop:" "${AVD_DIR}/tmp/$partition.img.info_image.txt" | sed -e 's/.*Prop: \(.*\) -> \(.*\)/\1:\2/' -e "s/'//g"); do
    PROP_ARGS+=" --prop $line"
    PROP_ARGS+=(--prop "$line")
    done

    if [ ! $partition = "system" ]; then
    @@ -428,7 +471,7 @@ repack_images() {
    --partition_name $partition \
    --partition_size 0 \
    --image "${AVD_DIR}/tmp/$partition.img" \
    ${PROP_ARGS[@]}
    "${PROP_ARGS[@]}"

    "$TEMPDIR/avbtool.py" info_image --image "${AVD_DIR}/tmp/$partition.img"
    "$TEMPDIR/avbtool.py" verify_image --image "${AVD_DIR}/tmp/$partition.img"
    @@ -439,7 +482,7 @@ repack_images() {
    unset PROP_ARGS
    declare -a PROP_ARGS=()
    for line in $(grep "Prop:" "${AVD_DIR}/tmp/$partition.img.info_image.txt" | sed -e 's/.*Prop: \(.*\) -> \(.*\)/\1:\2/' -e "s/'//g"); do
    PROP_ARGS+=" --prop $line"
    PROP_ARGS+=(--prop "$line")
    done
    #"$TEMPDIR/avbtool.py" erase_footer --image "${AVD_DIR}/tmp/system.img"
    # We skip the rollback index value (--rollback-index)
    @@ -449,7 +492,7 @@ repack_images() {
    --image "${AVD_DIR}/tmp/system.img" \
    --algorithm SHA256_RSA2048 \
    --key "$TEMPDIR/testkey_rsa2048.pem" \
    ${PROP_ARGS[@]}
    "${PROP_ARGS[@]}"

    "$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"
    @@ -475,8 +518,8 @@ repack_images() {

    declare -a AVBTOOL_ADDITIONAL_ARGS=()
    for partition in $(jq -r ".partitions[].name" "$AVD_DIR/tmp/lpdump.json"); do
    if [ ! $partition = "system" ]; then
    AVBTOOL_ADDITIONAL_ARGS+=" --include_descriptors_from_image ${AVD_DIR}/tmp/$partition.img"
    if [ ! "$partition" = "system" ]; then
    AVBTOOL_ADDITIONAL_ARGS+=(--include_descriptors_from_image "${AVD_DIR}/tmp/$partition.img")
    fi
    done

    @@ -490,7 +533,7 @@ repack_images() {
    --padding_size 4096 \
    --output "${AVD_DIR}/tmp/vbmeta.img" \
    --chain_partition system:1:$TEMPDIR/system_rsa2048.avbpubkey \
    ${AVBTOOL_ADDITIONAL_ARGS[@]}
    "${AVBTOOL_ADDITIONAL_ARGS[@]}"
    #--include_descriptors_from_image "${AVD_DIR}/tmp/vendor.img"

    "$TEMPDIR/avbtool.py" info_image --image "${AVD_DIR}/tmp/vbmeta.img"
    @@ -527,8 +570,8 @@ repack_images() {
    PART_SIZE=$(wc -c "${AVD_DIR}/tmp/$partition.img" | cut -f 1 -d ' ')
    fi
    PART_SIZE_SUM=$(( PART_SIZE_SUM + PART_SIZE ))
    LPMAKE_PARTITION_ARGS+=" -p $partition:readonly:$PART_SIZE:$LPMAKE_GROUP_NAME"
    LPMAKE_PARTITION_ARGS+=" -i $partition=${AVD_DIR}/tmp/$partition.img"
    LPMAKE_PARTITION_ARGS+=(-p $partition:readonly:$PART_SIZE:$LPMAKE_GROUP_NAME)
    LPMAKE_PARTITION_ARGS+=(-i $partition="${AVD_DIR}/tmp/$partition.img")
    done

    if [[ $REPLICATE_LPDUMP -eq 1 ]]; then
    @@ -549,7 +592,7 @@ repack_images() {
    --metadata-size=$LPMAKE_METADATA_SIZE \
    --metadata-slots=$LPMAKE_METADATA_SLOTS \
    --output="${AVD_DIR}/tmp/super.img" \
    ${LPMAKE_PARTITION_ARGS[@]} \
    "${LPMAKE_PARTITION_ARGS[@]}" \
    --block-size=$LPMAKE_BLOCK_SIZE \
    --alignment=$LPMAKE_ALIGNMENT \
    --super-name="$LPMAKE_SUPER_NAME" \
    @@ -599,7 +642,8 @@ check_free_space() {
    # $1: file or device
    # $2: required space (in bytes)

    local MOUNT_POINT=$(stat -c %m -- "$1")
    local MOUNT_POINT
    MOUNT_POINT=$(stat -c %m -- "$1")
    AVAIL=$(( $(df --output=avail "$MOUNT_POINT" | tail -1) * 1024 ))
    if [ $AVAIL -le $(( $2 + 5 * 1024 * 1024 )) ]; then
    echo "Not enough space on disk. Need: $2. Available: $AVAIL. Exiting"
    @@ -639,7 +683,7 @@ install_with_opengapps_installer
    # Downsize images if extfs format
    for file in system.img product.img vendor.img system_ext.img; do
    if [ -e "${AVD_DIR}/tmp/$file" ]; then
    downsize_extfs "${AVD_DIR}/tmp/$file"
    downsize_img "${AVD_DIR}/tmp/$file"
    fi
    done

  2. @tenzap tenzap revised this gist Jan 21, 2022. 1 changed file with 4 additions and 1 deletion.
    5 changes: 4 additions & 1 deletion open_gapps_install_script.sh
    Original file line number Diff line number Diff line change
    @@ -5,6 +5,10 @@ USAGESTRING="Usage: ${0} <open_gapps_zip_file.zip> <user>";
    TEMPDIR="$(mktemp --tmpdir -d "gapps_installer.XXXX")"
    export RTDIR="/mnt/mounted_avd"

    # How much space to add to the system.img so that there is enough space to install OpenGApps
    # You may need to inscrease this if you install "super" variant
    REQUIRED_SPACE_FOR_OPENGAPPS_IN_MB=1400

    # for lpunpack, lpdump & lpmake
    LPTOOLS_BIN_DIR="/mnt/packages/git_repos/lpunpack_and_lpmake/bin"

    @@ -316,7 +320,6 @@ unpack_images() {
    }

    set_new_size() {
    local REQUIRED_SPACE_FOR_OPENGAPPS_IN_MB=800
    mount_img "$AVD_DIR/tmp/system.img" "$RTDIR"
    local USED_IN_KB=$(df --output=used "$RTDIR" | tail -1)
    umount_img "$AVD_DIR/tmp/system.img" "$RTDIR"
  3. @tenzap tenzap revised this gist Jan 21, 2022. 1 changed file with 1 addition and 0 deletions.
    1 change: 1 addition & 0 deletions Readme.md
    Original file line number Diff line number Diff line change
    @@ -10,6 +10,7 @@ Features:

    Tested on:
    - Debian Bullseye (11.x)
    - Android emulator version 31.1.4.0 (build_id 7920983)
    - Android 10, 11, 12 (API 29, 30, 31) 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.
    - On android 11 & 12 (API30 & 31) you need to apply these patches to opengapps if they haven't been merged upstream. Otherwise boot may never finish (staying on splash screen) https://github.com/opengapps/opengapps/issues/951 https://github.com/opengapps/opengapps/issues/952
    - 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
  4. @tenzap tenzap revised this gist Jan 21, 2022. 2 changed files with 201 additions and 87 deletions.
    20 changes: 10 additions & 10 deletions Readme.md
    Original file line number Diff line number Diff line change
    @@ -10,11 +10,10 @@ Features:

    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 10, 11, 12 (API 29, 30, 31) 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.
    - On android 11 & 12 (API30 & 31) you need to apply these patches to opengapps if they haven't been merged upstream. Otherwise boot may never finish (staying on splash screen) https://github.com/opengapps/opengapps/issues/951 https://github.com/opengapps/opengapps/issues/952
    - 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)
    @@ -30,17 +29,18 @@ The way it works:
    #### 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:
    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
    1. Tools -> 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
    4. x86 Images or x86_64 for Pie (Download if necessary)
    5. Give the AVD a name
    6. Choose "Show Advanced Settings...". Give the AVD at least 1536MB Internal Storage, and 512MB SD Card.
    7. You may set "Cold Boot"
    8. Finish
    3. Download the appropriate OpenGApps file from [opengapps.org](https://opengapps.org) (x86 / 9.0 / micro)
    4. Download the ZIP archive of this gist, unpack it and give it executable permission:
    ```
    @@ -63,7 +63,7 @@ The way it works:
    A sample transcript follows.
    #### Sample Transcript
    #### Sample Transcript (for Android Pie)
    ```
    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
    268 changes: 191 additions & 77 deletions open_gapps_install_script.sh
    Original file line number Diff line number Diff line change
    @@ -6,7 +6,7 @@ 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"
    LPTOOLS_BIN_DIR="/mnt/packages/git_repos/lpunpack_and_lpmake/bin"

    # path to fec binary
    FEC_BINARY="/mnt/packages/downloads/otatools/bin/fec"
    @@ -136,6 +136,13 @@ install_with_opengapps_installer() {
    mount_img "$AVD_DIR/tmp/system.img" "$RTDIR/system"
    fi
    mount_img "$AVD_DIR/tmp/vendor.img" "$RTDIR/vendor"
    if [ -e "$AVD_DIR/tmp/lpdump.json" ]; then
    if [ $(jq ".partitions | length" "$AVD_DIR/tmp/lpdump.json") -eq 4 ]; then
    mount_img "$AVD_DIR/tmp/system_ext.img" "$RTDIR/system_ext"
    mount_img "$AVD_DIR/tmp/product.img" "$RTDIR/product"
    fi
    fi

    mount_img "$AVD_DIR/cache.img" "$RTDIR/cache"

    if [ -d "$RTDIR/tmp" ]; then
    @@ -191,6 +198,12 @@ install_with_opengapps_installer() {
    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"
    if [ -e "$AVD_DIR/tmp/lpdump.json" ]; then
    if [ $(jq ".partitions | length" "$AVD_DIR/tmp/lpdump.json") -eq 4 ]; then
    umount_img "$AVD_DIR/tmp/system_ext.img" "$RTDIR/system_ext"
    umount_img "$AVD_DIR/tmp/product.img" "$RTDIR/product"
    fi
    fi
    #umount_img "$RTDIR/data"
    umount "$RTDIR/proc"
    umount "$RTDIR/dev"
    @@ -221,6 +234,14 @@ upsize_extfs() {
    fi
    }

    downsize_extfs() {
    # $1 device/file holding the filesystem
    if file -b "$1" | grep "ext. filesystem data" > /dev/null; then
    "${ANDROID_SDK_ROOT}/emulator/bin64/e2fsck" -f "$1" 2> /dev/null
    "${ANDROID_SDK_ROOT}/emulator/bin64/resize2fs" -M "$1"
    fi
    }

    resize_img() {
    local image="$1"
    local size="$2"
    @@ -253,24 +274,37 @@ unpack_images() {
    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"
    download_and_extract_aosp_scripts

    dd if="${DEVICE::-1}1" of="${AVD_DIR}/tmp/vbmeta.orig.img"
    "$TEMPDIR/avbtool.py" info_image --image "${AVD_DIR}/tmp/vbmeta.orig.img" > "${AVD_DIR}/tmp/vbmeta.orig.img.info_image.txt"

    for partition in $(jq -r ".partitions[].name" "$AVD_DIR/tmp/lpdump.json"); do
    echo -e "\nUnpacking & converting to read/write: $partition.img"

    local PART_SIZE=$(jq -r '.partitions[] | select(.name=="'$partition'").size ' "$AVD_DIR/tmp/lpdump.json")
    check_free_space "${AVD_DIR}/tmp" $(( PART_SIZE * 11 / 10 ))

    "$LPTOOLS_BIN_DIR/lpunpack" --slot=0 -p $partition "$DEVICE" "$AVD_DIR/tmp"
    "$TEMPDIR/avbtool.py" info_image --image "$AVD_DIR/tmp/$partition.img" > "$AVD_DIR/tmp/$partition.img.info_image.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
    FS_SIZE=$(wc -c "$AVD_DIR/tmp/$partition.img" | cut -f 1 -d ' ')
    e2fsck -f -y "$AVD_DIR/tmp/$partition.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"
    resize2fs "$AVD_DIR/tmp/$partition.img" $(( FS_SIZE * 11 / 10 / 1024 ))K
    e2fsck -y -E unshare_blocks "$AVD_DIR/tmp/$partition.img" > /dev/null 2>&1
    e2fsck -f -y "$AVD_DIR/tmp/$partition.img"
    done
    else
    check_free_space "${AVD_DIR}/tmp" $(wc -c "${ANDROID_SDK_ROOT}/${IMAGE_SYSDIR}/vendor.img" | cut -f 1 -d ' ')
    cp "${ANDROID_SDK_ROOT}/${IMAGE_SYSDIR}/vendor.img" "${AVD_DIR}/tmp/vendor.img"
    check_free_space "${AVD_DIR}/tmp" $(wc -c "${ANDROID_SDK_ROOT}/${IMAGE_SYSDIR}/system.img" | cut -f 1 -d ' ')
    cp "${ANDROID_SDK_ROOT}/${IMAGE_SYSDIR}/system.img" "${AVD_DIR}/tmp/system.img"
    fi
    if [ -f "${ANDROID_SDK_ROOT}/${IMAGE_SYSDIR}/encryptionkey.img" ]; then
    @@ -281,6 +315,22 @@ unpack_images() {
    fi
    }

    set_new_size() {
    local REQUIRED_SPACE_FOR_OPENGAPPS_IN_MB=800
    mount_img "$AVD_DIR/tmp/system.img" "$RTDIR"
    local USED_IN_KB=$(df --output=used "$RTDIR" | tail -1)
    umount_img "$AVD_DIR/tmp/system.img" "$RTDIR"

    local NEW_SIZE_IN_B="$(( ( USED_IN_KB + REQUIRED_SPACE_FOR_OPENGAPPS_IN_MB * 1024 ) * 1024 ))"
    local CUR_SIZE_IN_B=$(wc -c "${AVD_DIR}/tmp/system.img" | cut -f 1 -d ' ')

    if [ $CUR_SIZE_IN_B -ge $NEW_SIZE_IN_B ]; then
    NEW_SIZE="$((CUR_SIZE_IN_B / 1024 / 1024 + 1))M"
    else
    NEW_SIZE="$((NEW_SIZE_IN_B / 1024 / 1024 + 1))M"
    fi
    }

    cleanup_avd() {
    rm -f "${AVD_DIR}/vendor.img"
    rm -f "${AVD_DIR}/system.img"
    @@ -314,25 +364,7 @@ lptools_required() {
    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:
    download_and_extract_aosp_scripts() {
    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 \
    @@ -352,37 +384,84 @@ repack_images() {
    mk_combined_img.py
    chmod +x "$TEMPDIR/mk_vbmeta_boot_params.sh"
    chmod +x "$TEMPDIR/mk_combined_img.py"
    }

    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:
    download_and_extract_aosp_scripts

    # 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"
    for partition in $(jq -r ".partitions[].name" "$AVD_DIR/tmp/lpdump.json"); do
    unset PROP_ARGS
    declare -a PROP_ARGS=()
    for line in $(grep "Prop:" "${AVD_DIR}/tmp/$partition.img.info_image.txt" | sed -e 's/.*Prop: \(.*\) -> \(.*\)/\1:\2/' -e "s/'//g"); do
    PROP_ARGS+=" --prop $line"
    done

    if [ ! $partition = "system" ]; then
    #$TEMPDIR/avbtool.py erase_footer --image "${AVD_DIR}/tmp/$partition.img"
    PATH=$PATH:$FEC_PATH "$TEMPDIR/avbtool.py" add_hashtree_footer \
    --partition_name $partition \
    --partition_size 0 \
    --image "${AVD_DIR}/tmp/$partition.img" \
    ${PROP_ARGS[@]}

    "$TEMPDIR/avbtool.py" info_image --image "${AVD_DIR}/tmp/$partition.img"
    "$TEMPDIR/avbtool.py" verify_image --image "${AVD_DIR}/tmp/$partition.img"
    fi
    done


    unset PROP_ARGS
    declare -a PROP_ARGS=()
    for line in $(grep "Prop:" "${AVD_DIR}/tmp/$partition.img.info_image.txt" | sed -e 's/.*Prop: \(.*\) -> \(.*\)/\1:\2/' -e "s/'//g"); do
    PROP_ARGS+=" --prop $line"
    done
    #"$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
    --key "$TEMPDIR/testkey_rsa2048.pem" \
    ${PROP_ARGS[@]}

    "$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"

    # TODO - get the vendor_boot.img and combine it into vbmeta.img
    # But it seems to work fine without this (at least until API31)
    #
    # The vendor_boot.img is added into ramdisk.img of the emulator image
    # by this scripts probably:
    # https://cs.android.com/android/platform/superproject/+/master:device/generic/goldfish/tools/mk_qemu_ramdisk.py
    #
    # I don't know how to extract it from ramdisk.img to use it in `avbtool make_vbmeta_image`

    # Create vbmeta image with dm-verity disabled
    # https://wiki.postmarketos.org/wiki/Android_Verified_Boot_(AVB)
    # "$TEMPDIR/avbtool.py" make_vbmeta_image \
    @@ -391,6 +470,15 @@ repack_images() {
    # --output ${AVD_DIR}/tmp/vbmeta_disabled.img \
    # --chain_partition system:1:$TEMPDIR/system_rsa2048.avbpubkey

    declare -a AVBTOOL_ADDITIONAL_ARGS=()
    for partition in $(jq -r ".partitions[].name" "$AVD_DIR/tmp/lpdump.json"); do
    if [ ! $partition = "system" ]; then
    AVBTOOL_ADDITIONAL_ARGS+=" --include_descriptors_from_image ${AVD_DIR}/tmp/$partition.img"
    fi
    done

    REPLICATE_LPDUMP=0

    # Remove old vbmeta.img, then create vbmeta image
    rm -f "${AVD_DIR}/tmp/vbmeta.img"
    "$TEMPDIR/avbtool.py" make_vbmeta_image \
    @@ -399,13 +487,20 @@ repack_images() {
    --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"
    ${AVBTOOL_ADDITIONAL_ARGS[@]}
    #--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"

    if [[ $REPLICATE_LPDUMP -eq 1 ]]; then
    cp "${AVD_DIR}/tmp/vbmeta.orig.img" "${AVD_DIR}/tmp/vbmeta.img"
    fi

    "$TEMPDIR/avbtool.py" info_image --image "${AVD_DIR}/tmp/vbmeta.img" | tee "${AVD_DIR}/tmp/vbmeta.img.info_image.txt"

    # Create VerifiedBootParams.textproto
    AVBTOOL="$(realpath "$TEMPDIR/avbtool.py")" "$TEMPDIR/mk_vbmeta_boot_params.sh" \
    "${AVD_DIR}/tmp/vbmeta.img" \
    @@ -414,57 +509,53 @@ repack_images() {
    mv "${AVD_DIR}/tmp/VerifiedBootParams.textproto" "${AVD_DIR}/VerifiedBootParams.textproto"

    # Prepare variables to repack super.img with lpmake
    REPLICATE_LPDUMP=0
    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)

    declare -a LPMAKE_PARTITION_ARGS=()
    for partition in $(jq -r ".partitions[].name" "$AVD_DIR/tmp/lpdump.json"); do
    if [[ $REPLICATE_LPDUMP -eq 1 ]]; then
    PART_SIZE=$(jq -r '.partitions[] | select(.name=="'$partition'").size ' "$AVD_DIR/tmp/lpdump.json")
    else
    PART_SIZE=$(wc -c "${AVD_DIR}/tmp/$partition.img" | cut -f 1 -d ' ')
    fi
    PART_SIZE_SUM=$(( PART_SIZE_SUM + PART_SIZE ))
    LPMAKE_PARTITION_ARGS+=" -p $partition:readonly:$PART_SIZE:$LPMAKE_GROUP_NAME"
    LPMAKE_PARTITION_ARGS+=" -i $partition=${AVD_DIR}/tmp/$partition.img"
    done

    if [[ $REPLICATE_LPDUMP -eq 1 ]]; then
    LPMAKE_GROUP_MAX_SIZE=$(jq -r '.groups[] | select(.name=="'$LPMAKE_GROUP_NAME'").maximum_size' "$AVD_DIR/tmp/lpdump.json")
    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_GROUP_MAX_SIZE: round size to multiple of 1024*1024 (size of all partitions + 4MiB)
    LPMAKE_GROUP_MAX_SIZE=$(( ( ( PART_SIZE_SUM / 1024 / 1024 ) + 4 ) * 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
    check_free_space "${AVD_DIR}/tmp" $LPMAKE_DEVICE_SIZE
    "$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" \
    ${LPMAKE_PARTITION_ARGS[@]} \
    --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
    # Delete partition images (we now have super.img)
    for partition in $(jq -r ".partitions[].name" "$AVD_DIR/tmp/lpdump.json"); do
    rm "${AVD_DIR}/tmp/$partition.img"*
    done

    # 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"
    @@ -476,11 +567,13 @@ repack_images() {
    # 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"
    check_free_space "${AVD_DIR}/tmp" $(( $(wc -c "${AVD_DIR}/tmp/super.img" | cut -f 1 -d ' ') + 5 * 1024 * 1024 ))
    "$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/vbmeta.img"*
    rm "${AVD_DIR}/tmp/vbmeta.orig.img"*
    rm "${AVD_DIR}/tmp/super.img"
    rm "${AVD_DIR}/tmp/lpdump.json"
    rm "${AVD_DIR}/tmp/lpdump.txt"
    @@ -499,6 +592,18 @@ repack_images() {

    }

    check_free_space() {
    # $1: file or device
    # $2: required space (in bytes)

    local MOUNT_POINT=$(stat -c %m -- "$1")
    AVAIL=$(( $(df --output=avail "$MOUNT_POINT" | tail -1) * 1024 ))
    if [ $AVAIL -le $(( $2 + 5 * 1024 * 1024 )) ]; then
    echo "Not enough space on disk. Need: $2. Available: $AVAIL. Exiting"
    exit 15
    fi
    }

    ########## Functions END #############

    echo "Which AVD?"
    @@ -521,11 +626,20 @@ cleanup_avd
    unpack_images

    # Resize system.img
    resize_img "${AVD_DIR}/tmp/system.img" "3072M"
    set_new_size
    echo -e "\nResizing system.img to $NEW_SIZE"
    resize_img "${AVD_DIR}/tmp/system.img" "$NEW_SIZE"

    # Install with the OpenGApps installer in a chroot environment
    install_with_opengapps_installer

    # Downsize images if extfs format
    for file in system.img product.img vendor.img system_ext.img; do
    if [ -e "${AVD_DIR}/tmp/$file" ]; then
    downsize_extfs "${AVD_DIR}/tmp/$file"
    fi
    done

    # Repack images
    repack_images

  5. @tenzap tenzap revised this gist Jan 20, 2022. 1 changed file with 24 additions and 96 deletions.
    120 changes: 24 additions & 96 deletions open_gapps_install_script.chroot.sh
    Original file line number Diff line number Diff line change
    @@ -1,96 +1,24 @@
    --- 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

    # Set variables needed by the installer.sh script (when flashed through TWRP
    # they are set by META-INF/com/google/android/update-binary)
    export TMP="/tmp"
    case "$(uname -m)" in
    *86*) export BINARCH="x86";; # e.g. Zenfone is i686
    *ar*) export BINARCH="arm";; # i.e. armv7l and aarch64
    esac
    export OPENGAZIP="/tmp_opengappzip/$1"

    # Extract necessary files
    # Copied from META-INF/com/google/android/update-binary (of the OPENGAPPZIP)
    for f in app_densities.txt app_sizes.txt bkup_tail.sh gapps-remove.txt g.prop installer.sh busybox-x86 tar-x86 unzip-x86 zip-x86; do
    unzip -o "$OPENGAZIP" "$f" -d "$TMP"
    done

    # Now, patch the installer script (located in $RTDIR/$TMP)
    cd "$TMP"
    patch -p1 < "/tmp/opengapps_in_emulator/open_gapps_install_script.patch"

    # Run the installer.sh script
    cd /
    ash /tmp/installer.sh
  6. @tenzap tenzap revised this gist Jan 20, 2022. 1 changed file with 1 addition and 2 deletions.
    3 changes: 1 addition & 2 deletions Readme.md
    Original file line number Diff line number Diff line change
    @@ -30,10 +30,9 @@ The way it works:
    #### Instructions

    1. Ensure you have `unzip`, `kpartx`, `losetup`, `sgdisk`, `emulator`, `chroot` in your `PATH`.
    If you prefer to use the old method you will also need: `lzip`, `tar`, and `adb` 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).
    - `wget` in order to download some scripts from the Android sources (this is done for you by the script)
    - `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...
  7. @tenzap tenzap revised this gist Jan 20, 2022. 4 changed files with 490 additions and 139 deletions.
    9 changes: 7 additions & 2 deletions Readme.md
    Original file line number Diff line number Diff line change
    @@ -10,25 +10,30 @@ Features:

    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. copy the original images to the local folder of the android virtual device (AVD) (system.img, vendor.img...)
    2. clean-up current AVD (system.img, cache.img*, userdata*.img*, VerifiedBootParams.textproto)
    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`.
    If you prefer to use the old method you will also need: `lzip`, `tar`, and `adb` 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).
    - `wget` in order to download some scripts from the Android sources (this is done for you by the script)
    2. Create a new Android Virtual Device (AVD). For example using Android Studio:
    1. Tools -> Android -> AVD Manager
    2. Create Virtual Device...
    120 changes: 96 additions & 24 deletions open_gapps_install_script.chroot.sh
    Original file line number Diff line number Diff line change
    @@ -1,24 +1,96 @@
    #!/bin/bash

    # Set variables needed by the installer.sh script (when flashed through TWRP
    # they are set by META-INF/com/google/android/update-binary)
    export TMP="/tmp"
    case "$(uname -m)" in
    *86*) export BINARCH="x86";; # e.g. Zenfone is i686
    *ar*) export BINARCH="arm";; # i.e. armv7l and aarch64
    esac
    export OPENGAZIP="/tmp_opengappzip/$1"

    # Extract necessary files
    # Copied from META-INF/com/google/android/update-binary (of the OPENGAPPZIP)
    for f in app_densities.txt app_sizes.txt bkup_tail.sh gapps-remove.txt g.prop installer.sh busybox-x86 tar-x86 unzip-x86 zip-x86; do
    unzip -o "$OPENGAZIP" "$f" -d "$TMP"
    done

    # Now, patch the installer script (located in $RTDIR/$TMP)
    cd "$TMP"
    patch -p1 < "/tmp/opengapps_in_emulator/open_gapps_install_script.patch"

    # Run the installer.sh script
    cd /
    ash /tmp/installer.sh
    --- 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 }')
    30 changes: 26 additions & 4 deletions open_gapps_install_script.patch
    Original file line number Diff line number Diff line change
    @@ -1,20 +1,20 @@
    --- a/installer.sh
    +++ b/installer.sh
    @@ -986,11 +986,10 @@
    @@ -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 "$1"
    - echo "ui_print $1
    - ui_print" >> $OUTFD
    + echo "$1"
    }

    find_slot() {
    @@ -1187,27 +1188,27 @@
    @@ -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
    @@ -63,7 +63,29 @@

    ui_print " "

    @@ -2603,7 +2604,7 @@
    @@ -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
    470 changes: 361 additions & 109 deletions open_gapps_install_script.sh
    Original file line number Diff line number Diff line change
    @@ -1,28 +1,41 @@
    #!/usr/bin/env bash
    #!/bin/bash
    ZIPFILE=${1}
    USERNAME=${2}
    USAGESTRING="Usage: ${0} <open_gapps_zip_file.zip> <user>";
    TEMPDIR=/tmp/gapps_installer
    export RTDIR=/mnt/mounted_avd
    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};
    echo "$USAGESTRING";
    exit 1;
    fi

    if [ ! -f ${ZIPFILE} ]; then
    echo ${USAGESTRING};
    if [ ! -f "$ZIPFILE" ]; then
    echo "$USAGESTRING";
    exit 2;
    fi

    USER_HOME=$(sudo -u "$USERNAME" sh -c 'echo $HOME')
    USER_HOME="$(sudo -u "$USERNAME" sh -c 'echo $HOME')"

    if [ ! ${ANDROID_SDK_ROOT} ]; then
    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"
    @@ -32,7 +45,7 @@ if [ ! ${ANDROID_SDK_ROOT} ]; then
    fi
    fi

    if [ ! -d ${ANDROID_SDK_ROOT} ]; then
    if [ ! -d "$ANDROID_SDK_ROOT" ]; then
    echo "ANDROID_SDK_ROOT is not valid"
    exit 4;
    fi
    @@ -41,35 +54,38 @@ a="/$0"; a=${a%/*}; a=${a#/}; a=${a:-.}; SCRIPT_DIR="$(cd "$a"; pwd -P)" || exit

    ########## Functions BEGIN #############

    # The old way, by copying files through abd manually
    install_with_adb(){
    rm -rf ${TEMPDIR} && mkdir -p ${TEMPDIR}
    unzip ${ZIPFILE} 'Core/*' -d ${TEMPDIR}
    cd ${TEMPDIR}
    rm Core/setup*
    lzip -d Core/*.lz
    for f in $(ls Core/*.tar); do
    tar -x --strip-components 2 -f $f
    done

    echo "starting ${AVD}"

    ${ANDROID_SDK_ROOT}/emulator/emulator -netdelay none -netspeed full -avd ${AVD} -partition-size 1024 -writable-system > /dev/null 2>&1 &

    read -rsp $'\nPress enter when the emulator has booted...\n\n'

    adb root
    adb remount
    adb push etc /system
    adb push framework /system
    adb push app /system
    adb push priv-app /system

    sleep 5
    # adb reboot system
    # adb -e emu kill
    echo "Restart android in your emulator"
    echo "done."
    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() {
    @@ -79,28 +95,14 @@ mount_img() {
    local DEVICE

    if file -b "$1" | grep "DOS/MBR boot sector" > /dev/null; then
    OS=$(uname)
    if [[ $OS == "Linux" ]]; then
    if ! which kpartx > /dev/null; then
    echo "kpartx command missing, cannot continue";
    exit 11;
    fi
    DEVICE=$(kpartx -a -v "$1" | cut -f 3 -d ' ')
    if mountpoint -q "$2"; then
    mount -o remount "/dev/mapper/$DEVICE" "$2"
    else
    mount "/dev/mapper/$DEVICE" "$2"
    fi
    elif [[ $OS == "Darwin" ]]; then
    DEVICE=$(hdiutil attach -imagekey diskimage-class=CRawDiskImage -nomount "$1" | grep "Linux Filesystem" | head -1 | cut -f 1 -d ' ')
    if mount | grep -q "$2" > /dev/null; then
    map_disk_img "$1"
    if is_mounted "$2"; then
    mount -o remount "$DEVICE" "$2"
    else
    else
    mount "$DEVICE" "$2"
    fi
    fi
    elif file -b "$2" | grep "ext. filesystem data" > /dev/null; then
    if mountpoint -q "$2"; then
    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"
    @@ -111,30 +113,35 @@ mount_img() {
    umount_img() {
    # $1 image path
    # $2 mount path
    umount "$2"
    if is_mounted "$2"; then
    umount "$2"
    fi
    if losetup | grep "$(realpath "$1")" > /dev/null; then
    kpartx -d -v "$1"
    fi
    }

    # The new way: mouting the filesystems locally & using the installer.sh script provided by OpenGApps
    # 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/system.img" "$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/system.img" "$RTDIR"
    umount_img "$AVD_DIR/tmp/system.img" "$RTDIR"
    mkdir -p "$RTDIR/"{system,cache,vendor,proc,dev}
    mount_img "$AVD_DIR/system.img" "$RTDIR/system"
    mkdir
    mount_img "$AVD_DIR/tmp/system.img" "$RTDIR/system"
    fi
    mount_img "$AVD_DIR/vendor.img" "$RTDIR/vendor"
    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
    @@ -181,16 +188,17 @@ install_with_opengapps_installer() {
    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/vendor.img" "$RTDIR/vendor"
    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/system.img" "$RTDIR/system"
    umount_img "$AVD_DIR/tmp/system.img" "$RTDIR/system"
    else
    umount_img "$AVD_DIR/system.img" "$RTDIR"
    umount_img "$AVD_DIR/tmp/system.img" "$RTDIR"
    fi

    # Review the contents of the data partition, you may need to copy
    @@ -214,83 +222,327 @@ upsize_extfs() {
    }

    resize_img() {
    if file -b "${AVD_DIR}/system.img" | 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 $NEW_SIZE... (you can safely ignore the warning 'The kernel is still using the old partition table.')"
    fallocate -l $NEW_SIZE "${AVD_DIR}/system.img"
    PART_UUID=$(/usr/sbin/sgdisk -i 1 "${AVD_DIR}/system.img" | grep "unique GUID" | cut -d ' ' -f4)
    /usr/sbin/sgdisk -d 1 "${AVD_DIR}/system.img"
    /usr/sbin/sgdisk -n 1:0:0 "${AVD_DIR}/system.img"
    /usr/sbin/sgdisk -c 1:system "${AVD_DIR}/system.img"
    /usr/sbin/sgdisk -u 1:$PART_UUID "${AVD_DIR}/system.img"
    PART=$(/usr/sbin/kpartx -a -v "${AVD_DIR}/system.img" | cut -f 3 -d ' ')
    SYS_EXT_PART_PATH="/dev/mapper/$PART"
    upsize_extfs "$SYS_EXT_PART_PATH" ;
    /usr/sbin/kpartx -d -v "${AVD_DIR}/system.img"
    echo "Resizing sysem partition to $NEW_SIZE finished successfully!"
    elif file -b "${AVD_DIR}/system.img" | grep "ext. filesystem data" > /dev/null; then
    upsize_extfs "${AVD_DIR}/system.img" $NEW_SIZE
    else
    echo "${AVD_DIR}/system.img format not supported by this script"
    exit 10;
    fi
    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
    }

    copy_clean_avd() {
    echo -e "\ncopying, checking and resizing system.img for ${AVD}"
    cp "${ANDROID_SDK_ROOT}/${IMAGE_SYSDIR}/vendor.img" "${AVD_DIR}/vendor.img"
    cp "${ANDROID_SDK_ROOT}/${IMAGE_SYSDIR}/system.img" "${AVD_DIR}/system.img"
    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
    if [ -f "${ANDROID_SDK_ROOT}/${IMAGE_SYSDIR}/VerifiedBootParams.textproto" ]; then
    }

    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.
    # We have to disable it since we modify the system.img file. Otherwise the Android will not boot
    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
    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/"
    }

    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
    sudo -u "$USERNAME" "${ANDROID_SDK_ROOT}/emulator/emulator" -list-avds
    echo -en "\n>"
    read AVD
    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=$(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
    copy_clean_avd
    unpack_images

    # Resize system.img
    export NEW_SIZE=3000M
    resize_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=1500M/" ${AVD_DIR}/config.ini
    sed -i -e "s/disk.dataPartition.size.*/disk.dataPartition.size=1536M/" "${AVD_DIR}/config.ini"

    # Install with adb
    #install_with_adb
    # 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

    # Install with the OpenGApps installer in a chroot environment
    install_with_opengapps_installer
    rm -r "$TEMPDIR"
    rmdir "${AVD_DIR}/tmp"
  8. @tenzap tenzap revised this gist Jan 19, 2022. 2 changed files with 22 additions and 5 deletions.
    6 changes: 4 additions & 2 deletions Readme.md
    Original file line number Diff line number Diff line change
    @@ -10,8 +10,10 @@ Features:

    Tested on:
    - Debian Bullseye (11.x)
    - AOSP Pie (API 29) with google's x86/arm64 AOSP system-image
    - LineageOS 16.0 (API 29) with google's x86/arm64 AOSP system-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. copy the original images to the local folder of the android virtual device (AVD) (system.img, vendor.img...)
    21 changes: 18 additions & 3 deletions open_gapps_install_script.sh
    Original file line number Diff line number Diff line change
    @@ -124,6 +124,14 @@ install_with_opengapps_installer() {
    mkdir -p "$RTDIR"

    mount_img "$AVD_DIR/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/system.img" "$RTDIR"
    mkdir -p "$RTDIR/"{system,cache,vendor,proc,dev}
    mount_img "$AVD_DIR/system.img" "$RTDIR/system"
    mkdir
    fi
    mount_img "$AVD_DIR/vendor.img" "$RTDIR/vendor"
    mount_img "$AVD_DIR/cache.img" "$RTDIR/cache"

    @@ -132,6 +140,7 @@ install_with_opengapps_installer() {
    #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"
    @@ -176,8 +185,13 @@ install_with_opengapps_installer() {
    umount_img "$AVD_DIR/vendor.img" "$RTDIR/vendor"
    #umount_img "$RTDIR/data"
    umount "$RTDIR/proc"

    umount_img "$AVD_DIR/system.img" "$RTDIR"
    umount "$RTDIR/dev"
    if [[ "a$SYSIMG_IS_SYSTEM" == "atrue" ]]; then
    rmdir "$RTDIR/"{system,cache,vendor,proc,dev,tmp}
    umount_img "$AVD_DIR/system.img" "$RTDIR/system"
    else
    umount_img "$AVD_DIR/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)
    @@ -257,7 +271,8 @@ sudo -u $USERNAME ${ANDROID_SDK_ROOT}/emulator/emulator -list-avds
    echo -en "\n>"
    read AVD

    AVD_DIR="${USER_HOME}/.android/avd/${AVD}.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"="`
  9. @tenzap tenzap revised this gist Jan 18, 2022. 4 changed files with 879 additions and 101 deletions.
    589 changes: 529 additions & 60 deletions Readme.md
    Original file line number Diff line number Diff line change
    @@ -1,94 +1,563 @@
    #### Introduction

    This works to install Open GApps into the Android Emulator, working around the
    issue where the system partition is too small.
    This works to install OpenGApps into the Android Emulator

    With it, I can get Google Play installing into the emulator. Tested on KitKat (API 19), Lollipop (API 21) and Oreo (API 27).
    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)

    It's tested on MacOS.
    Tested on:
    - Debian Bullseye (11.x)
    - AOSP Pie (API 29) with google's x86/arm64 AOSP system-image
    - LineageOS 16.0 (API 29) with google's x86/arm64 AOSP system-image

    The way it works:
    1. copy the original images to the local folder of the android virtual device (AVD) (system.img, vendor.img...)
    2. clean-up current AVD (system.img, cache.img*, userdata*.img*, VerifiedBootParams.textproto)
    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

    #### Instructions

    1. Ensure you have `unzip`, `lzip`, `tar`, `emulator` and `adb` in your `PATH`.
    2. From Android Studio (v3.0.1) create a new Android Virtual Device (AVD). For example:
    1. Ensure you have `unzip`, `kpartx`, `losetup`, `sgdisk`, `emulator`, `chroot` in your `PATH`.
    If you prefer to use the old method you will also need: `lzip`, `tar`, and `adb` in your `PATH`.
    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
    6. Finish
    3. Download the appropriate Open GApps file from [opengapps.org]() (x86_64 / 6.0 / micro)
    4. Save the `open_gapps_install_script.sh` into the same folder, and give it executable permission:
    7. Finish
    3. Download the appropriate OpenGApps file from [opengapps.org](https://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. Run the `open_gapps_install_script.sh` with the Open GApps file as the first argument; e.g.
    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 open_gapps-x86_64-6.0-micro-20180123.zip
    ./open_gapps_install_script.sh /path/to/open_gapps-x86-9.0-micro-20220115.zip username
    ```
    6. When prompted for an AVD, copy the appropriate AVD name and paste it. Press Enter.
    7. Wait for the emulator to boot fully, then press Enter.
    8. Once the script tells you to "Restart android in your emulator", hold down the virtual power button to shutdown.
    9. Manually start the emulator again (press the 'play' button in Android Studio's AVD Manager).
    10. In the emulator, open the Google app and sign in with your google account.
    11. Shut down the emulator and start it again.
    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
    ```
    $ ./open_gapps_install_script.sh open_gapps-x86_64-6.0-micro-20180123.zip
    Archive: open_gapps-x86_64-6.0-micro-20180123.zip
    signed by SignApk
    extracting: /tmp/gapps_installer/Core/configupdater-all.tar.lz
    extracting: /tmp/gapps_installer/Core/defaultetc-common.tar.lz
    extracting: /tmp/gapps_installer/Core/defaultframework-common.tar.lz
    extracting: /tmp/gapps_installer/Core/gmscore-x86_64.tar.lz
    extracting: /tmp/gapps_installer/Core/googlebackuptransport-all.tar.lz
    extracting: /tmp/gapps_installer/Core/googlecontactssync-all.tar
    extracting: /tmp/gapps_installer/Core/googlefeedback-all.tar.lz
    extracting: /tmp/gapps_installer/Core/googleonetimeinitializer-all.tar.lz
    extracting: /tmp/gapps_installer/Core/googlepartnersetup-all.tar.lz
    extracting: /tmp/gapps_installer/Core/gsfcore-all.tar.lz
    extracting: /tmp/gapps_installer/Core/gsflogin-all.tar.lz
    extracting: /tmp/gapps_installer/Core/setupwizarddefault-all.tar.lz
    extracting: /tmp/gapps_installer/Core/setupwizardtablet-all.tar.lz
    extracting: /tmp/gapps_installer/Core/vending-x86_64.tar.lz
    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?
    Nexus_5X_Oreo_8.1_API_27
    Nexus_5_KitKat_API_19_32-bit_x86
    Nexus_5_Lollipop_API_22_32-bit
    Nexus_5_Marshmallow_API_23_x86_64
    API28
    Amazon_Fire_HD8_API_28
    LineageGo_Pixel_3_XL_API_28
    Pixel_3a_XL_API_28
    Pixel_3a_XL_API_29

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

    determining location of system.img file for Nexus_5_Marshmallow_API_23_x86_64 .../Users/mikecunneen/Library/Android/sdk/system-images/android-23/google_apis/x86_64/
    copying, checking and resizing system.img for Nexus_5_Marshmallow_API_23_x86_64
    copying encryptionkey.img ...
    e2fsck 1.42.13 (17-May-2015)
    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
    system: 1958/98304 files (0.0% non-contiguous), 358163/393216 blocks
    resize2fs 1.42.13 (17-May-2015)
    Resizing the filesystem on /Users/mikecunneen/.android/avd/Nexus_5_Marshmallow_API_23_x86_64.avd/system.img to 524288 (4k) blocks.
    The filesystem on /Users/mikecunneen/.android/avd/Nexus_5_Marshmallow_API_23_x86_64.avd/system.img is now 524288 (4k) blocks long.

    starting Nexus_5_Marshmallow_API_23_x86_64

    Press enter when the emulator has booted...

    adbd is already running as root
    remount succeeded
    etc/: 11 files pushed. 3.8 MB/s (58819 bytes in 0.015s)
    framework/: 3 files pushed. 34.8 MB/s (212217 bytes in 0.006s)
    app/: 1 file pushed. 81.9 MB/s (284795 bytes in 0.003s)
    priv-app/: 9 files pushed. 188.1 MB/s (93280033 bytes in 0.473s)
    restart android in your emulator
    done.

    /: ***** 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

    ```
    24 changes: 24 additions & 0 deletions open_gapps_install_script.chroot.sh
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,24 @@
    #!/bin/bash

    # Set variables needed by the installer.sh script (when flashed through TWRP
    # they are set by META-INF/com/google/android/update-binary)
    export TMP="/tmp"
    case "$(uname -m)" in
    *86*) export BINARCH="x86";; # e.g. Zenfone is i686
    *ar*) export BINARCH="arm";; # i.e. armv7l and aarch64
    esac
    export OPENGAZIP="/tmp_opengappzip/$1"

    # Extract necessary files
    # Copied from META-INF/com/google/android/update-binary (of the OPENGAPPZIP)
    for f in app_densities.txt app_sizes.txt bkup_tail.sh gapps-remove.txt g.prop installer.sh busybox-x86 tar-x86 unzip-x86 zip-x86; do
    unzip -o "$OPENGAZIP" "$f" -d "$TMP"
    done

    # Now, patch the installer script (located in $RTDIR/$TMP)
    cd "$TMP"
    patch -p1 < "/tmp/opengapps_in_emulator/open_gapps_install_script.patch"

    # Run the installer.sh script
    cd /
    ash /tmp/installer.sh
    74 changes: 74 additions & 0 deletions open_gapps_install_script.patch
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,74 @@
    --- a/installer.sh
    +++ b/installer.sh
    @@ -986,11 +986,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 "$1"
    - echo "ui_print $1
    - ui_print" >> $OUTFD
    }

    find_slot() {
    @@ -1187,27 +1188,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 " "

    @@ -2603,7 +2604,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 }')
    293 changes: 252 additions & 41 deletions open_gapps_install_script.sh
    Original file line number Diff line number Diff line change
    @@ -1,9 +1,16 @@
    #!/usr/bin/env bash
    ZIPFILE=${1}
    USAGESTRING="Usage: ${0} open_gapps_zip_file.zip";
    USERNAME=${2}
    USAGESTRING="Usage: ${0} <open_gapps_zip_file.zip> <user>";
    TEMPDIR=/tmp/gapps_installer
    export RTDIR=/mnt/mounted_avd

    if [ $# -lt 1 ]; then
    if [ $UID -ne 0 ]; then
    echo "Root rights needed"
    exit 9;
    fi

    if [ $# -lt 2 ]; then
    echo ${USAGESTRING};
    exit 1;
    fi
    @@ -13,58 +20,262 @@ if [ ! -f ${ZIPFILE} ]; then
    exit 2;
    fi

    if [ ! ${ANDROID_HOME} ]; then
    echo "ANDROID_HOME is not set"
    exit 3;
    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_HOME} ]; then
    echo "ANDROID_HOME is not valid"
    if [ ! -d ${ANDROID_SDK_ROOT} ]; then
    echo "ANDROID_SDK_ROOT is not valid"
    exit 4;
    fi

    rm -rf ${TEMPDIR} && mkdir -p ${TEMPDIR}
    unzip ${ZIPFILE} 'Core/*' -d ${TEMPDIR}
    cd ${TEMPDIR}
    rm Core/setup*
    lzip -d Core/*.lz
    for f in $(ls Core/*.tar); do
    tar -x --strip-components 2 -f $f
    done
    a="/$0"; a=${a%/*}; a=${a#/}; a=${a:-.}; SCRIPT_DIR="$(cd "$a"; pwd -P)" || exit 1

    ########## Functions BEGIN #############

    # The old way, by copying files through abd manually
    install_with_adb(){
    rm -rf ${TEMPDIR} && mkdir -p ${TEMPDIR}
    unzip ${ZIPFILE} 'Core/*' -d ${TEMPDIR}
    cd ${TEMPDIR}
    rm Core/setup*
    lzip -d Core/*.lz
    for f in $(ls Core/*.tar); do
    tar -x --strip-components 2 -f $f
    done

    echo "starting ${AVD}"

    ${ANDROID_SDK_ROOT}/emulator/emulator -netdelay none -netspeed full -avd ${AVD} -partition-size 1024 -writable-system > /dev/null 2>&1 &

    read -rsp $'\nPress enter when the emulator has booted...\n\n'

    adb root
    adb remount
    adb push etc /system
    adb push framework /system
    adb push app /system
    adb push priv-app /system

    sleep 5
    # adb reboot system
    # adb -e emu kill
    echo "Restart android in your emulator"
    echo "done."
    }

    mount_img() {
    # $1 image path
    # $2 mount path

    local DEVICE

    if file -b "$1" | grep "DOS/MBR boot sector" > /dev/null; then
    OS=$(uname)
    if [[ $OS == "Linux" ]]; then
    if ! which kpartx > /dev/null; then
    echo "kpartx command missing, cannot continue";
    exit 11;
    fi
    DEVICE=$(kpartx -a -v "$1" | cut -f 3 -d ' ')
    if mountpoint -q "$2"; then
    mount -o remount "/dev/mapper/$DEVICE" "$2"
    else
    mount "/dev/mapper/$DEVICE" "$2"
    fi
    elif [[ $OS == "Darwin" ]]; then
    DEVICE=$(hdiutil attach -imagekey diskimage-class=CRawDiskImage -nomount "$1" | grep "Linux Filesystem" | head -1 | cut -f 1 -d ' ')
    if mount | grep -q "$2" > /dev/null; then
    mount -o remount "$DEVICE" "$2"
    else
    mount "$DEVICE" "$2"
    fi
    fi
    elif file -b "$2" | grep "ext. filesystem data" > /dev/null; then
    if mountpoint -q "$2"; then
    mount -o remount "$1" "$2"
    else
    mount "$1" "$2"
    fi
    fi
    }

    umount_img() {
    # $1 image path
    # $2 mount path
    umount "$2"
    if losetup | grep "$(realpath "$1")" > /dev/null; then
    kpartx -d -v "$1"
    fi
    }

    # The new way: mouting the filesystems locally & using 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/system.img" "$RTDIR"
    mount_img "$AVD_DIR/vendor.img" "$RTDIR/vendor"
    mount_img "$AVD_DIR/cache.img" "$RTDIR/cache"

    #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 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"
    umount_img "$AVD_DIR/cache.img" "$RTDIR/cache"
    umount_img "$AVD_DIR/vendor.img" "$RTDIR/vendor"
    #umount_img "$RTDIR/data"
    umount "$RTDIR/proc"

    umount_img "$AVD_DIR/system.img" "$RTDIR"

    # 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() {
    if file -b "${AVD_DIR}/system.img" | 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 $NEW_SIZE... (you can safely ignore the warning 'The kernel is still using the old partition table.')"
    fallocate -l $NEW_SIZE "${AVD_DIR}/system.img"
    PART_UUID=$(/usr/sbin/sgdisk -i 1 "${AVD_DIR}/system.img" | grep "unique GUID" | cut -d ' ' -f4)
    /usr/sbin/sgdisk -d 1 "${AVD_DIR}/system.img"
    /usr/sbin/sgdisk -n 1:0:0 "${AVD_DIR}/system.img"
    /usr/sbin/sgdisk -c 1:system "${AVD_DIR}/system.img"
    /usr/sbin/sgdisk -u 1:$PART_UUID "${AVD_DIR}/system.img"
    PART=$(/usr/sbin/kpartx -a -v "${AVD_DIR}/system.img" | cut -f 3 -d ' ')
    SYS_EXT_PART_PATH="/dev/mapper/$PART"
    upsize_extfs "$SYS_EXT_PART_PATH" ;
    /usr/sbin/kpartx -d -v "${AVD_DIR}/system.img"
    echo "Resizing sysem partition to $NEW_SIZE finished successfully!"
    elif file -b "${AVD_DIR}/system.img" | grep "ext. filesystem data" > /dev/null; then
    upsize_extfs "${AVD_DIR}/system.img" $NEW_SIZE
    else
    echo "${AVD_DIR}/system.img format not supported by this script"
    exit 10;
    fi
    }

    copy_clean_avd() {
    echo -e "\ncopying, checking and resizing system.img for ${AVD}"
    cp "${ANDROID_SDK_ROOT}/${IMAGE_SYSDIR}/vendor.img" "${AVD_DIR}/vendor.img"
    cp "${ANDROID_SDK_ROOT}/${IMAGE_SYSDIR}/system.img" "${AVD_DIR}/system.img"
    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
    if [ -f "${ANDROID_SDK_ROOT}/${IMAGE_SYSDIR}/VerifiedBootParams.textproto" ]; then
    # If the file exists, maybe the emulator has Verity/Verified boot enabled.
    # We have to disable it since we modify the system.img file. Otherwise the Android will not boot
    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
    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/"
    }


    ########## Functions END #############

    echo "Which AVD?"
    emulator -list-avds
    sudo -u $USERNAME ${ANDROID_SDK_ROOT}/emulator/emulator -list-avds
    echo -en "\n>"
    read AVD

    echo -en "\ndetermining location of system.img file for ${AVD} ..."
    IMAGE_SYSDIR=`grep "image.sysdir.1" ${HOME}/.android/avd/${AVD}.avd/config.ini | cut -f2 -d"="`
    echo "${ANDROID_HOME}/${IMAGE_SYSDIR}"
    AVD_DIR="${USER_HOME}/.android/avd/${AVD}.avd"

    echo "copying, checking and resizing system.img for ${AVD}"
    cp "${ANDROID_HOME}/${IMAGE_SYSDIR}/system.img" "${HOME}/.android/avd/${AVD}.avd/system.img"
    if [ -f "${ANDROID_HOME}/${IMAGE_SYSDIR}/encryptionkey.img" ]; then
    echo "copying encryptionkey.img ..."
    cp "${ANDROID_HOME}/${IMAGE_SYSDIR}/encryptionkey.img" "${HOME}/.android/avd/${AVD}.avd/encryptionkey.img"
    fi
    "${ANDROID_HOME}/emulator/bin64/e2fsck" -f "${HOME}/.android/avd/${AVD}.avd/system.img"
    "${ANDROID_HOME}/emulator/bin64/resize2fs" "${HOME}/.android/avd/${AVD}.avd/system.img" 3072M
    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}"

    echo "starting ${AVD}"
    # Copy clean system.img to selected AVD and related stuff
    copy_clean_avd

    ${ANDROID_HOME}/tools/emulator -netdelay none -netspeed full -avd ${AVD} -partition-size 1024 -writable-system > /dev/null 2>&1 &
    # Resize system.img
    export NEW_SIZE=3000M
    resize_img

    read -rsp $'\nPress enter when the emulator has booted...\n\n'
    # Resize data partition
    sed -i -e "s/disk.dataPartition.size.*/disk.dataPartition.size=1500M/" ${AVD_DIR}/config.ini

    adb root
    adb remount
    adb push etc /system
    adb push framework /system
    adb push app /system
    adb push priv-app /system
    # Install with adb
    #install_with_adb

    sleep 5
    # adb reboot system
    # adb -e emu kill
    echo "Restart android in your emulator"
    echo "done."
    # Install with the OpenGApps installer in a chroot environment
    install_with_opengapps_installer
  10. @cunneen cunneen revised this gist Aug 5, 2019. 1 changed file with 11 additions and 10 deletions.
    21 changes: 11 additions & 10 deletions Readme.md
    Original file line number Diff line number Diff line change
    @@ -9,29 +9,30 @@ It's tested on MacOS.

    #### Instructions

    1. From Android Studio (v3.0.1) create a new Android Virtual Device (AVD). For example:
    1. Ensure you have `unzip`, `lzip`, `tar`, `emulator` and `adb` in your `PATH`.
    2. From Android Studio (v3.0.1) create a new Android Virtual Device (AVD). For example:
    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
    6. Finish
    2. Download the appropriate Open GApps file from [opengapps.org]() (x86_64 / 6.0 / micro)
    3. Save the `open_gapps_install_script.sh` into the same folder, and give it executable permission:
    3. Download the appropriate Open GApps file from [opengapps.org]() (x86_64 / 6.0 / micro)
    4. Save the `open_gapps_install_script.sh` into the same folder, and give it executable permission:
    ```
    chmod 755 open_gapps_install_script.sh
    ```
    4. Run the `open_gapps_install_script.sh` with the Open GApps file as the first argument; e.g.
    5. Run the `open_gapps_install_script.sh` with the Open GApps file as the first argument; e.g.
    ```
    open_gapps_install_script.sh open_gapps-x86_64-6.0-micro-20180123.zip
    ```
    5. When prompted for an AVD, copy the appropriate AVD name and paste it. Press Enter.
    6. Wait for the emulator to boot fully, then press Enter.
    7. Once the script tells you to "Restart android in your emulator", hold down the virtual power button to shutdown.
    8. Manually start the emulator again (press the 'play' button in Android Studio's AVD Manager).
    9. In the emulator, open the Google app and sign in with your google account.
    10. Shut down the emulator and start it again.
    6. When prompted for an AVD, copy the appropriate AVD name and paste it. Press Enter.
    7. Wait for the emulator to boot fully, then press Enter.
    8. Once the script tells you to "Restart android in your emulator", hold down the virtual power button to shutdown.
    9. Manually start the emulator again (press the 'play' button in Android Studio's AVD Manager).
    10. In the emulator, open the Google app and sign in with your google account.
    11. Shut down the emulator and start it again.
    A sample transcript follows.
  11. @cunneen cunneen revised this gist Aug 5, 2019. 1 changed file with 2 additions and 4 deletions.
    6 changes: 2 additions & 4 deletions open_gapps_install_script.sh
    Original file line number Diff line number Diff line change
    @@ -48,9 +48,7 @@ if [ -f "${ANDROID_HOME}/${IMAGE_SYSDIR}/encryptionkey.img" ]; then
    cp "${ANDROID_HOME}/${IMAGE_SYSDIR}/encryptionkey.img" "${HOME}/.android/avd/${AVD}.avd/encryptionkey.img"
    fi
    "${ANDROID_HOME}/emulator/bin64/e2fsck" -f "${HOME}/.android/avd/${AVD}.avd/system.img"
    "${ANDROID_HOME}/emulator/bin64/resize2fs" "${HOME}/.android/avd/${AVD}.avd/system.img" 2048M


    "${ANDROID_HOME}/emulator/bin64/resize2fs" "${HOME}/.android/avd/${AVD}.avd/system.img" 3072M

    echo "starting ${AVD}"

    @@ -69,4 +67,4 @@ sleep 5
    # adb reboot system
    # adb -e emu kill
    echo "Restart android in your emulator"
    echo "done.""
    echo "done."
  12. @cunneen cunneen created this gist Jan 24, 2018.
    93 changes: 93 additions & 0 deletions Readme.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,93 @@
    #### Introduction

    This works to install Open GApps into the Android Emulator, working around the
    issue where the system partition is too small.

    With it, I can get Google Play installing into the emulator. Tested on KitKat (API 19), Lollipop (API 21) and Oreo (API 27).

    It's tested on MacOS.

    #### Instructions

    1. From Android Studio (v3.0.1) create a new Android Virtual Device (AVD). For example:
    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
    6. Finish
    2. Download the appropriate Open GApps file from [opengapps.org]() (x86_64 / 6.0 / micro)
    3. Save the `open_gapps_install_script.sh` into the same folder, and give it executable permission:
    ```
    chmod 755 open_gapps_install_script.sh
    ```
    4. Run the `open_gapps_install_script.sh` with the Open GApps file as the first argument; e.g.
    ```
    open_gapps_install_script.sh open_gapps-x86_64-6.0-micro-20180123.zip
    ```
    5. When prompted for an AVD, copy the appropriate AVD name and paste it. Press Enter.
    6. Wait for the emulator to boot fully, then press Enter.
    7. Once the script tells you to "Restart android in your emulator", hold down the virtual power button to shutdown.
    8. Manually start the emulator again (press the 'play' button in Android Studio's AVD Manager).
    9. In the emulator, open the Google app and sign in with your google account.
    10. Shut down the emulator and start it again.
    A sample transcript follows.
    #### Sample Transcript
    ```
    $ ./open_gapps_install_script.sh open_gapps-x86_64-6.0-micro-20180123.zip
    Archive: open_gapps-x86_64-6.0-micro-20180123.zip
    signed by SignApk
    extracting: /tmp/gapps_installer/Core/configupdater-all.tar.lz
    extracting: /tmp/gapps_installer/Core/defaultetc-common.tar.lz
    extracting: /tmp/gapps_installer/Core/defaultframework-common.tar.lz
    extracting: /tmp/gapps_installer/Core/gmscore-x86_64.tar.lz
    extracting: /tmp/gapps_installer/Core/googlebackuptransport-all.tar.lz
    extracting: /tmp/gapps_installer/Core/googlecontactssync-all.tar
    extracting: /tmp/gapps_installer/Core/googlefeedback-all.tar.lz
    extracting: /tmp/gapps_installer/Core/googleonetimeinitializer-all.tar.lz
    extracting: /tmp/gapps_installer/Core/googlepartnersetup-all.tar.lz
    extracting: /tmp/gapps_installer/Core/gsfcore-all.tar.lz
    extracting: /tmp/gapps_installer/Core/gsflogin-all.tar.lz
    extracting: /tmp/gapps_installer/Core/setupwizarddefault-all.tar.lz
    extracting: /tmp/gapps_installer/Core/setupwizardtablet-all.tar.lz
    extracting: /tmp/gapps_installer/Core/vending-x86_64.tar.lz
    Which AVD?
    Nexus_5X_Oreo_8.1_API_27
    Nexus_5_KitKat_API_19_32-bit_x86
    Nexus_5_Lollipop_API_22_32-bit
    Nexus_5_Marshmallow_API_23_x86_64

    >Nexus_5_Marshmallow_API_23_x86_64
    determining location of system.img file for Nexus_5_Marshmallow_API_23_x86_64 .../Users/mikecunneen/Library/Android/sdk/system-images/android-23/google_apis/x86_64/
    copying, checking and resizing system.img for Nexus_5_Marshmallow_API_23_x86_64
    copying encryptionkey.img ...
    e2fsck 1.42.13 (17-May-2015)
    Pass 1: Checking inodes, blocks, and sizes
    Pass 2: Checking directory structure
    Pass 3: Checking directory connectivity
    Pass 4: Checking reference counts
    Pass 5: Checking group summary information
    system: 1958/98304 files (0.0% non-contiguous), 358163/393216 blocks
    resize2fs 1.42.13 (17-May-2015)
    Resizing the filesystem on /Users/mikecunneen/.android/avd/Nexus_5_Marshmallow_API_23_x86_64.avd/system.img to 524288 (4k) blocks.
    The filesystem on /Users/mikecunneen/.android/avd/Nexus_5_Marshmallow_API_23_x86_64.avd/system.img is now 524288 (4k) blocks long.

    starting Nexus_5_Marshmallow_API_23_x86_64

    Press enter when the emulator has booted...

    adbd is already running as root
    remount succeeded
    etc/: 11 files pushed. 3.8 MB/s (58819 bytes in 0.015s)
    framework/: 3 files pushed. 34.8 MB/s (212217 bytes in 0.006s)
    app/: 1 file pushed. 81.9 MB/s (284795 bytes in 0.003s)
    priv-app/: 9 files pushed. 188.1 MB/s (93280033 bytes in 0.473s)
    restart android in your emulator
    done.

    ```
    72 changes: 72 additions & 0 deletions open_gapps_install_script.sh
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,72 @@
    #!/usr/bin/env bash
    ZIPFILE=${1}
    USAGESTRING="Usage: ${0} open_gapps_zip_file.zip";
    TEMPDIR=/tmp/gapps_installer

    if [ $# -lt 1 ]; then
    echo ${USAGESTRING};
    exit 1;
    fi

    if [ ! -f ${ZIPFILE} ]; then
    echo ${USAGESTRING};
    exit 2;
    fi

    if [ ! ${ANDROID_HOME} ]; then
    echo "ANDROID_HOME is not set"
    exit 3;
    fi

    if [ ! -d ${ANDROID_HOME} ]; then
    echo "ANDROID_HOME is not valid"
    exit 4;
    fi

    rm -rf ${TEMPDIR} && mkdir -p ${TEMPDIR}
    unzip ${ZIPFILE} 'Core/*' -d ${TEMPDIR}
    cd ${TEMPDIR}
    rm Core/setup*
    lzip -d Core/*.lz
    for f in $(ls Core/*.tar); do
    tar -x --strip-components 2 -f $f
    done

    echo "Which AVD?"
    emulator -list-avds
    echo -en "\n>"
    read AVD

    echo -en "\ndetermining location of system.img file for ${AVD} ..."
    IMAGE_SYSDIR=`grep "image.sysdir.1" ${HOME}/.android/avd/${AVD}.avd/config.ini | cut -f2 -d"="`
    echo "${ANDROID_HOME}/${IMAGE_SYSDIR}"

    echo "copying, checking and resizing system.img for ${AVD}"
    cp "${ANDROID_HOME}/${IMAGE_SYSDIR}/system.img" "${HOME}/.android/avd/${AVD}.avd/system.img"
    if [ -f "${ANDROID_HOME}/${IMAGE_SYSDIR}/encryptionkey.img" ]; then
    echo "copying encryptionkey.img ..."
    cp "${ANDROID_HOME}/${IMAGE_SYSDIR}/encryptionkey.img" "${HOME}/.android/avd/${AVD}.avd/encryptionkey.img"
    fi
    "${ANDROID_HOME}/emulator/bin64/e2fsck" -f "${HOME}/.android/avd/${AVD}.avd/system.img"
    "${ANDROID_HOME}/emulator/bin64/resize2fs" "${HOME}/.android/avd/${AVD}.avd/system.img" 2048M



    echo "starting ${AVD}"

    ${ANDROID_HOME}/tools/emulator -netdelay none -netspeed full -avd ${AVD} -partition-size 1024 -writable-system > /dev/null 2>&1 &

    read -rsp $'\nPress enter when the emulator has booted...\n\n'

    adb root
    adb remount
    adb push etc /system
    adb push framework /system
    adb push app /system
    adb push priv-app /system

    sleep 5
    # adb reboot system
    # adb -e emu kill
    echo "Restart android in your emulator"
    echo "done.""