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