Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 0 additions & 74 deletions usr/lib/lxc-android/lxc-android-notify
Original file line number Diff line number Diff line change
@@ -1,82 +1,8 @@
#!/bin/bash

# When this script starts, the container is starting-up.
# On Android 10+ devices, we need to properly replicate APEX bind-mounts
# on the host system.

LXC_ROOTFS="/var/lib/lxc/android/rootfs"

info() {
echo "I: $@"
}

warning() {
echo "W: $@" >&2
}

error() {
echo "E: $@" >&2
exit 1
}

get_source_apex_name() {
NAME="$(echo ${1} | sed -E 's|\.v[0-9]+$||g')"

for choice in ${NAME} ${NAME}.release ${NAME}.debug ${NAME}.current; do
if [ -e "/android/system/apex/${choice}" ]; then
echo "${choice}"
break
fi
done
}

# Get Android container version
ANDROID_SDK_VERSION=$(grep ro.build.version.sdk= ${LXC_ROOTFS}/system/build.prop | cut -d "=" -f2)
if [ $(getconf LONG_BIT) == 32 ]; then
LIBDIR="lib"
else
LIBDIR="lib64"
fi

# Wait for the container
lxc-wait -n android -t 10 -s "RUNNING"

if [ $ANDROID_SDK_VERSION -ge 29 ]; then
# Android >= 10
info "Detected Android 10+ container"

# Wait for apex to show up
HYBRIS_LD_LIBRARY_PATH="/android/system/apex/com.android.runtime/${LIBDIR}/bionic:/android/system/apex/com.android.runtime.release/${LIBDIR}/bionic:/android/system/apex/com.android.runtime.debug/${LIBDIR}/bionic:/android/system/${LIBDIR}" \
WAITFORSERVICE_VALUE="ready" \
/usr/bin/waitforservice apexd.status

info "apexd ready, replicating bind-mounts"
for mpoint in /apex/*; do
# TODO: Actually determine from where the directory has been bind-mounted
# from, and support non-flattened apexes
if [ ! -d "${mpoint}" ] || [[ ${mpoint} == /apex/*@* ]]; then
continue
fi

apex=$(basename ${mpoint})
target="/apex/${apex}"

source_apex=$(get_source_apex_name ${apex})

if [ -z "${source_apex}" ]; then
warning "Unable to finx source apex for apex ${apex}"
continue
fi

source="/android/system/apex/${source_apex}"

if [ -d "${source}" ]; then
info "Replicating bind-mount for apex ${apex}"
mount --bind ${source} ${target}
fi
done
fi

# Notify systemd we're done
systemd-notify --ready --status="Container ready"

Expand Down
63 changes: 63 additions & 0 deletions usr/sbin/mount-android.sh
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,46 @@ parse_mount_flags() {
echo $options
}

get_apex_payload_offset() {
apex_file="$1"
python3 -c "
import zipfile

def calculate_offset(apex_path):
with zipfile.ZipFile(apex_path, 'r') as zf:
try:
with zf.open('apex_payload.img') as f:
return f._orig_compress_start
except KeyError:
pass
return 0 # apex_payload.img not found

print(calculate_offset('$apex_file'))
" 2>/dev/null || echo 0
}

mount_apex() {
source_path="$1"
target_path="$2"

if [ -d "$source_path" ]; then
# Directory-based APEX
mkdir -p "$target_path"
echo "Mounting flattened APEX $source_path to $target_path"
mount -o bind "$source_path" "$target_path"
elif [ -f "$source_path" ] && [[ "$source_path" == *.apex ]]; then
# File-based APEX
mkdir -p "$target_path"
offset=$(get_apex_payload_offset "$source_path")
if [ "$offset" -eq 0 ]; then
log "Unable to determine offset for APEX file $source_path, skipping"
return
fi
echo "Mounting APEX file $source_path to $target_path with offset $offset"
mount -o loop,offset=${offset},ro "$source_path" "$target_path"
fi
}

if [ -n "${BIND_MOUNT_PATH}" ] && ! mountpoint -q -- "${BIND_MOUNT_PATH}"; then
android_images="/userdata/android-rootfs.img /var/lib/lxc/android/android-rootfs.img"
for image in ${android_images}; do
Expand Down Expand Up @@ -181,3 +221,26 @@ cat ${fstab} ${EXTRA_FSTAB} | while read line; do
mount -o bind ${2} "${BIND_MOUNT_PATH}/${2}"
fi
done

if [ -d /android/apex ]; then
echo "Handling /android/apex mounts"

mount -t tmpfs android_apex /android/apex

for apex_dir in "/android/system/apex" "/android/system_ext/apex"; do
[ -d "$apex_dir" ] || continue

for apex_entry in "$apex_dir"/*; do
# Extract APEX name (remove directory suffixes and .apex extension)
apex_name=$(basename "$apex_entry" | sed 's/\.\(release\|debug\|apex\)$//')
target_path="/android/apex/${apex_name}"

case "$apex_name" in
com.android.runtime|com.android.art|com.android.i18n|com.android.vndk.*)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

aren't we filtering too much here? I have quite a lot of more mounted APEXes with the old method

mount_apex "$apex_entry" "$target_path"
;;
esac
done
done
fi

5 changes: 0 additions & 5 deletions var/lib/lxc/android/pre-start.sh
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,6 @@ else
mkdir -p /dev/__properties__
mkdir -p /dev/socket

# Mount a tmpfs on /apex if we should
if [ -e "/apex" ]; then
mount -t tmpfs tmpfs /apex
fi

# mount binderfs if needed
if [ ! -e /dev/binder ]; then
mkdir -p /dev/binderfs
Expand Down