xref: /aosp_15_r20/frameworks/native/cmds/installd/otapreopt_script.sh (revision 38e8c45f13ce32b0dcecb25141ffecaf386fa17f)
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