1*38e8c45fSAndroid Build Coastguard Worker#!/system/bin/sh 2*38e8c45fSAndroid Build Coastguard Worker 3*38e8c45fSAndroid Build Coastguard Worker# 4*38e8c45fSAndroid Build Coastguard Worker# Copyright (C) 2016 The Android Open Source Project 5*38e8c45fSAndroid Build Coastguard Worker# 6*38e8c45fSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"); 7*38e8c45fSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License. 8*38e8c45fSAndroid Build Coastguard Worker# You may obtain a copy of the License at 9*38e8c45fSAndroid Build Coastguard Worker# 10*38e8c45fSAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0 11*38e8c45fSAndroid Build Coastguard Worker# 12*38e8c45fSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software 13*38e8c45fSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS, 14*38e8c45fSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15*38e8c45fSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and 16*38e8c45fSAndroid Build Coastguard Worker# limitations under the License. 17*38e8c45fSAndroid Build Coastguard Worker# 18*38e8c45fSAndroid Build Coastguard Worker 19*38e8c45fSAndroid Build Coastguard Worker# This script runs as a postinstall step to drive otapreopt. It comes with the 20*38e8c45fSAndroid Build Coastguard Worker# OTA package, but runs /system/bin/otapreopt_chroot in the (old) active system 21*38e8c45fSAndroid Build Coastguard Worker# image. See system/extras/postinst/postinst.sh for some docs. 22*38e8c45fSAndroid Build Coastguard Worker 23*38e8c45fSAndroid Build Coastguard WorkerTARGET_SLOT="$1" 24*38e8c45fSAndroid Build Coastguard WorkerSTATUS_FD="$2" 25*38e8c45fSAndroid Build Coastguard Worker 26*38e8c45fSAndroid Build Coastguard Worker# Maximum number of packages/steps. 27*38e8c45fSAndroid Build Coastguard WorkerMAXIMUM_PACKAGES=1000 28*38e8c45fSAndroid Build Coastguard Worker 29*38e8c45fSAndroid Build Coastguard Worker# First ensure the system is booted. This is to work around issues when cmd would 30*38e8c45fSAndroid Build Coastguard Worker# infinitely loop trying to get a service manager (which will never come up in that 31*38e8c45fSAndroid Build Coastguard Worker# mode). b/30797145 32*38e8c45fSAndroid Build Coastguard WorkerBOOT_PROPERTY_NAME="dev.bootcomplete" 33*38e8c45fSAndroid Build Coastguard Worker 34*38e8c45fSAndroid Build Coastguard WorkerBOOT_COMPLETE=$(getprop $BOOT_PROPERTY_NAME) 35*38e8c45fSAndroid Build Coastguard Workerif [ "$BOOT_COMPLETE" != "1" ] ; then 36*38e8c45fSAndroid Build Coastguard Worker echo "$0: Error: boot-complete not detected." 37*38e8c45fSAndroid Build Coastguard Worker # We must return 0 to not block sideload. 38*38e8c45fSAndroid Build Coastguard Worker exit 0 39*38e8c45fSAndroid Build Coastguard Workerfi 40*38e8c45fSAndroid Build Coastguard Worker 41*38e8c45fSAndroid Build Coastguard Worker# Compute target slot suffix. 42*38e8c45fSAndroid Build Coastguard Worker# TODO: Once bootctl is not restricted, we should query from there. Or get this from 43*38e8c45fSAndroid Build Coastguard Worker# update_engine as a parameter. 44*38e8c45fSAndroid Build Coastguard Workerif [ "$TARGET_SLOT" = "0" ] ; then 45*38e8c45fSAndroid Build Coastguard Worker TARGET_SLOT_SUFFIX="_a" 46*38e8c45fSAndroid Build Coastguard Workerelif [ "$TARGET_SLOT" = "1" ] ; then 47*38e8c45fSAndroid Build Coastguard Worker TARGET_SLOT_SUFFIX="_b" 48*38e8c45fSAndroid Build Coastguard Workerelse 49*38e8c45fSAndroid Build Coastguard Worker echo "$0: Unknown target slot $TARGET_SLOT" 50*38e8c45fSAndroid Build Coastguard Worker exit 1 51*38e8c45fSAndroid Build Coastguard Workerfi 52*38e8c45fSAndroid Build Coastguard Worker 53*38e8c45fSAndroid Build Coastguard Worker# A source that infinitely emits arbitrary lines. 54*38e8c45fSAndroid Build Coastguard Worker# When connected to STDIN of another process, this source keeps STDIN open until 55*38e8c45fSAndroid Build Coastguard Worker# the consumer process closes STDIN or this script dies. 56*38e8c45fSAndroid Build Coastguard Workerfunction infinite_source { 57*38e8c45fSAndroid Build Coastguard Worker while echo .; do 58*38e8c45fSAndroid Build Coastguard Worker sleep 1 59*38e8c45fSAndroid Build Coastguard Worker done 60*38e8c45fSAndroid Build Coastguard Worker} 61*38e8c45fSAndroid Build Coastguard Worker 62*38e8c45fSAndroid Build Coastguard WorkerPR_DEXOPT_JOB_VERSION="$(pm art pr-dexopt-job --version)" 63*38e8c45fSAndroid Build Coastguard Workerif (( $? == 0 )) && (( $PR_DEXOPT_JOB_VERSION >= 3 )); then 64*38e8c45fSAndroid Build Coastguard Worker # Delegate to Pre-reboot Dexopt, a feature of ART Service. 65*38e8c45fSAndroid Build Coastguard Worker # ART Service decides what to do with this request: 66*38e8c45fSAndroid Build Coastguard Worker # - If Pre-reboot Dexopt is disabled or unsupported, the command returns 67*38e8c45fSAndroid Build Coastguard Worker # non-zero. This is always the case if the current system is Android 14 or 68*38e8c45fSAndroid Build Coastguard Worker # earlier. 69*38e8c45fSAndroid Build Coastguard Worker # - If Pre-reboot Dexopt is enabled in synchronous mode, the command blocks 70*38e8c45fSAndroid Build Coastguard Worker # until Pre-reboot Dexopt finishes, and returns zero no matter it succeeds or 71*38e8c45fSAndroid Build Coastguard Worker # not. This is the default behavior if the current system is Android 15. 72*38e8c45fSAndroid Build Coastguard Worker # - If Pre-reboot Dexopt is enabled in asynchronous mode, the command schedules 73*38e8c45fSAndroid Build Coastguard Worker # an asynchronous job and returns 0 immediately. The job will then run by the 74*38e8c45fSAndroid Build Coastguard Worker # job scheduler when the device is idle and charging. 75*38e8c45fSAndroid Build Coastguard Worker if infinite_source | pm art on-ota-staged --slot "$TARGET_SLOT_SUFFIX"; then 76*38e8c45fSAndroid Build Coastguard Worker # Handled by Pre-reboot Dexopt. 77*38e8c45fSAndroid Build Coastguard Worker exit 0 78*38e8c45fSAndroid Build Coastguard Worker fi 79*38e8c45fSAndroid Build Coastguard Worker echo "Pre-reboot Dexopt not enabled. Fall back to otapreopt." 80*38e8c45fSAndroid Build Coastguard Workerelse 81*38e8c45fSAndroid Build Coastguard Worker echo "Pre-reboot Dexopt is too old. Fall back to otapreopt." 82*38e8c45fSAndroid Build Coastguard Workerfi 83*38e8c45fSAndroid Build Coastguard Worker 84*38e8c45fSAndroid Build Coastguard Workerif [ "$(/system/bin/otapreopt_chroot --version)" != 2 ]; then 85*38e8c45fSAndroid Build Coastguard Worker # We require an updated chroot wrapper that reads dexopt commands from stdin. 86*38e8c45fSAndroid Build Coastguard Worker # Even if we kept compat with the old binary, the OTA preopt wouldn't work due 87*38e8c45fSAndroid Build Coastguard Worker # to missing sepolicy rules, so there's no use spending time trying to dexopt 88*38e8c45fSAndroid Build Coastguard Worker # (b/291974157). 89*38e8c45fSAndroid Build Coastguard Worker echo "$0: Current system image is too old to work with OTA preopt - skipping." 90*38e8c45fSAndroid Build Coastguard Worker exit 0 91*38e8c45fSAndroid Build Coastguard Workerfi 92*38e8c45fSAndroid Build Coastguard Worker 93*38e8c45fSAndroid Build Coastguard WorkerPREPARE=$(cmd otadexopt prepare) 94*38e8c45fSAndroid Build Coastguard Worker# Note: Ignore preparation failures. Step and done will fail and exit this. 95*38e8c45fSAndroid Build Coastguard Worker# This is necessary to support suspends - the OTA service will keep 96*38e8c45fSAndroid Build Coastguard Worker# the state around for us. 97*38e8c45fSAndroid Build Coastguard Worker 98*38e8c45fSAndroid Build Coastguard Worker# Create an array with all dexopt commands in advance, to know how many there are. 99*38e8c45fSAndroid Build Coastguard Workerotadexopt_cmds=() 100*38e8c45fSAndroid Build Coastguard Workerwhile (( ${#otadexopt_cmds[@]} < MAXIMUM_PACKAGES )) ; do 101*38e8c45fSAndroid Build Coastguard Worker DONE=$(cmd otadexopt done) 102*38e8c45fSAndroid Build Coastguard Worker if [ "$DONE" = "OTA complete." ] ; then 103*38e8c45fSAndroid Build Coastguard Worker break 104*38e8c45fSAndroid Build Coastguard Worker fi 105*38e8c45fSAndroid Build Coastguard Worker otadexopt_cmds+=("$(cmd otadexopt next)") 106*38e8c45fSAndroid Build Coastguard Workerdone 107*38e8c45fSAndroid Build Coastguard Worker 108*38e8c45fSAndroid Build Coastguard WorkerDONE=$(cmd otadexopt done) 109*38e8c45fSAndroid Build Coastguard Workercmd otadexopt cleanup 110*38e8c45fSAndroid Build Coastguard Worker 111*38e8c45fSAndroid Build Coastguard Workerecho "$0: Using streaming otapreopt_chroot on ${#otadexopt_cmds[@]} packages" 112*38e8c45fSAndroid Build Coastguard Worker 113*38e8c45fSAndroid Build Coastguard Workerfunction print_otadexopt_cmds { 114*38e8c45fSAndroid Build Coastguard Worker for cmd in "${otadexopt_cmds[@]}" ; do 115*38e8c45fSAndroid Build Coastguard Worker print "$cmd" 116*38e8c45fSAndroid Build Coastguard Worker done 117*38e8c45fSAndroid Build Coastguard Worker} 118*38e8c45fSAndroid Build Coastguard Worker 119*38e8c45fSAndroid Build Coastguard Workerfunction report_progress { 120*38e8c45fSAndroid Build Coastguard Worker while read count ; do 121*38e8c45fSAndroid Build Coastguard Worker # mksh can't do floating point arithmetic, so emulate a fixed point calculation. 122*38e8c45fSAndroid Build Coastguard Worker (( permilles = 1000 * count / ${#otadexopt_cmds[@]} )) 123*38e8c45fSAndroid Build Coastguard Worker printf 'global_progress %d.%03d\n' $((permilles / 1000)) $((permilles % 1000)) >&${STATUS_FD} 124*38e8c45fSAndroid Build Coastguard Worker done 125*38e8c45fSAndroid Build Coastguard Worker} 126*38e8c45fSAndroid Build Coastguard Worker 127*38e8c45fSAndroid Build Coastguard Workerprint_otadexopt_cmds | \ 128*38e8c45fSAndroid Build Coastguard Worker /system/bin/otapreopt_chroot $STATUS_FD $TARGET_SLOT_SUFFIX | \ 129*38e8c45fSAndroid Build Coastguard Worker report_progress 130*38e8c45fSAndroid Build Coastguard Worker 131*38e8c45fSAndroid Build Coastguard Workerif [ "$DONE" = "OTA incomplete." ] ; then 132*38e8c45fSAndroid Build Coastguard Worker echo "$0: Incomplete." 133*38e8c45fSAndroid Build Coastguard Workerelse 134*38e8c45fSAndroid Build Coastguard Worker echo "$0: Complete or error." 135*38e8c45fSAndroid Build Coastguard Workerfi 136*38e8c45fSAndroid Build Coastguard Worker 137*38e8c45fSAndroid Build Coastguard Workerprint -u${STATUS_FD} "global_progress 1.0" 138*38e8c45fSAndroid Build Coastguard Worker 139*38e8c45fSAndroid Build Coastguard Workerexit 0 140