#!/bin/sh -e

# Workaround https://github.com/lxc/lxc/issues/3570
# If lxc-wait fails with "Failed to receive state from monitor", re-try
# up-to 10 times, 0.5 seconds apart.

RETRY=10
while ! err=$(lxc-wait -n android -s RUNNING -t 30 2>&1); do
    echo "$err" >&2
    if ! echo "$err"|grep -q 'Invalid argument - Failed to receive state from monitor'; then
        exit 1
    fi

    RETRY=$(( RETRY - 1 ))

    if [ $RETRY -le 0 ]; then
        echo "LXC container doesn't become running in time, exitting..." >&2
        exit 1
    fi

    echo "Workaround https://github.com/lxc/lxc/issues/3570, re-try up to ${RETRY} more time(s)." >&2
    sleep 0.5
done

containerpid="$(lxc-info -n android -p -H)"
if [ -n "$containerpid" ]; then
    while true; do
        [ -f /proc/$containerpid/root/dev/.coldboot_done ] && break
        sleep 0.1
    done

    if [ "$(systemctl get-default)" = "charger.target" ]; then
        # remount ro in case we get sudden power cut
        echo u > /proc/sysrq-trigger

        # When Android container boots as a charger, the property srevice might
        # not be brought up. Not that it's important in this mode anyway, so don't
        # bother waiting.
        exit 0
    fi

    # If the socket isn't available, 'getprop' falls back to reading files
    # manually, causing a false positive of propertyservice being up
    while [ ! -e /dev/socket/property_service ]; do sleep 0.1; done

    # This property is read by libhybris itself to pick a linker, so it
    # *MUST* be available before we emit 'android'.
    while [ -z "$(getprop ro.build.version.sdk)" ]; do sleep 0.1; done

    # Allow custom properties before announcing that the boot is completed
    if [ -f /custom/custom.prop ]; then
        while [ ! -e /dev/socket/property_service ]; do sleep 0.1; done
        grep "^custom\." /custom/custom.prop | sed 's/=/ /' | while read property value; do
            setprop $property $value
        done
    fi

    # Run `linkerconfig`. It requires `apexd` to finishes activating APEXes and
    # emit `/apex/apex-info-list.xml` (on applicable versions).
    if [ -d /android/linkerconfig ]; then
        mount -t tmpfs linkerconfig /android/linkerconfig

        timeout=300
        # https://stackoverflow.com/a/24421013
        while
            apex_status=$(getprop apexd.status)
            [ "$apex_status" != "activated" ] && \
            [ "$apex_status" != "ready" ] && \
            [ "$timeout" -gt 0 ]
        do
            sleep 0.1
            timeout=$((timeout - 1))
        done

        if [ "$apex_status" = "activated" ] || [ "$apex_status" = "ready" ]; then
            if [ -e /android/apex/.default-apex-info-list.xml ]; then
                touch /android/apex/apex-info-list.xml
                mount -o bind,ro \
                    /android/apex/.default-apex-info-list.xml \
                    /android/apex/apex-info-list.xml
            fi

            # We don't want linkerconfig failure to fail boot. Android/libhybris
            # linker can still function (in degraded mode) without this.
            /system/bin/linkerconfig --target /android/linkerconfig || true

            # Because we actually mount our paths under `/android`, fixup
            # generated config to ensure permitted paths are valid.
            for config in \
                /android/linkerconfig/ld.config.txt \
                /android/linkerconfig/*/ld.config.txt \
            ; do
                [ -e "$config" ] || continue
                awk '
                    function add_remove_prefix(path) {
                        # Note: AWK string indexing is 1-based.
                        if (substr(path, 1, 8) == "/android") {
                            return substr(path, 9)
                        } else {
                            return "/android" path
                        }
                    }

                    # For each path line, add an additional equivalent path
                    # with/without "/android".
                    $1 ~ /\.paths$/ {
                        print $0
                        print $1, "+=", add_remove_prefix($3)
                        next
                    }

                    # Non-path lines
                    { print $0 }
                ' "${config}" > "${config}.new"
                mv "${config}.new" "${config}"
            done
        else
            echo "WARNING: apexd fails to activate APEXes. Linkerconfig is" \
                 "skipped to avoid producing broken config."
        fi
    fi
else
    exit 1
fi
