1#!/bin/bash
2#
3# Copyright (C) 2020 The Android Open Source Project
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9#      http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16
17#
18# This script creates the final boot image profile (suitable to include in the platform build).
19# The input to the script are:
20#   1) the boot.zip file which contains the boot classpath and system server jars.
21#      This file can be obtained from running `m dist` or by configuring the device with
22#      the `art/tools/boot-image-profile-configure-device.sh` script.
23#   2) the preloaded classes blacklist which specify what clases should not be preloaded
24#      in Zygote. Usually located in usually in frameworks/base/config/preloaded-classes-blacklist
25#   3) a list of raw boot image profiles extracted from devices. An example how to do that is
26#      by running `art/tools/boot-image-profile-extract-profile.sh` script.
27#
28# It is strongly recommended that you make use of extensive critical user journeys flows in order
29# to capture the raw boot image profiles described in #3.
30#
31# NOTE: by default, the script uses default arguments for producing the boot image profiles.
32# You might want to adjust the default generation arguments based on the shape of profile
33# and based on the metrics that matter for each product.
34#
35
36if [[ -z "$ANDROID_BUILD_TOP" ]]; then
37  echo "You must run on this after running envsetup.sh and launch target"
38  exit 1
39fi
40
41if [[ "$#" -lt 4 ]]; then
42  echo "Usage $0 <output-dir> <boot.zip-location> <preloaded-blacklist-location> <profile-input1> <profile-input2> ... <profman args>"
43  echo "Without any profman args the script will use defaults."
44  echo "Example: $0 output-dir boot.zip frameworks/base/config/preloaded-classes-blacklist android1.prof android2.prof"
45  echo "         $0 output-dir boot.zip frameworks/base/config/preloaded-classes-blacklist android.prof --profman-arg --upgrade-startup-to-hot=true"
46  echo "preloaded.black-list is usually in frameworks/base/config/preloaded-classes-blacklist"
47  exit 1
48fi
49
50echo "Creating work dir"
51WORK_DIR=/tmp/android-bcp
52mkdir -p "$WORK_DIR"
53
54OUT_DIR="$1"
55BOOT_ZIP="$2"
56PRELOADED_BLACKLIST="$3"
57shift 3
58
59# Read the profile input args.
60profman_profile_input_args=()
61while [[ "$#" -ge 1 ]] && [[ ! "$1" = '--profman-arg' ]]; do
62  profman_profile_input_args+=("--profile-file=$1")
63  shift
64done
65
66# Read the profman args.
67profman_args=()
68while [[ "$#" -ge 2 ]] && [[ "$1" = '--profman-arg' ]]; do
69  profman_args+=("$2")
70  shift 2
71done
72
73OUT_BOOT_PROFILE="$OUT_DIR"/boot-image-profile.txt
74OUT_PRELOADED_CLASSES="$OUT_DIR"/preloaded-classes
75OUT_SYSTEM_SERVER="$OUT_DIR"/art-profile
76
77echo "Changing dirs to the build top"
78cd "$ANDROID_BUILD_TOP"
79
80echo "Unziping boot.zip"
81BOOT_UNZIP_DIR="$WORK_DIR"/boot-dex
82ART_JARS="$BOOT_UNZIP_DIR"/dex_artjars_input
83BOOT_JARS="$BOOT_UNZIP_DIR"/dex_bootjars_input
84SYSTEM_SERVER_JAR="$BOOT_UNZIP_DIR"/system/framework/services.jar
85
86unzip -o "$BOOT_ZIP" -d "$BOOT_UNZIP_DIR"
87
88echo "Processing boot image jar files"
89jar_args=()
90for entry in "$ART_JARS"/*
91do
92  jar_args+=("--apk=$entry")
93done
94for entry in "$BOOT_JARS"/*
95do
96  jar_args+=("--apk=$entry")
97done
98profman_args+=("${jar_args[@]}")
99
100echo "Running profman for boot image profiles"
101# NOTE:
102# You might want to adjust the default generation arguments based on the data
103# For example, to update the selection thresholds you could specify:
104#  --method-threshold=10 \
105#  --class-threshold=10 \
106#  --preloaded-class-threshold=10 \
107#  --special-package=android:1 \
108#  --special-package=com.android.systemui:1 \
109# The threshold is percentage of total aggregation, that is, a method/class is
110# included in the profile only if it's used by at least x% of the packages.
111# (from 0% - include everything to 100% - include only the items that
112# are used by all packages on device).
113# The --special-package allows you to give a prioriority to certain packages,
114# meaning, if the methods is used by that package then the algorithm will use a
115# different selection thresholds.
116# (system server is identified as the "android" package)
117profman \
118  --generate-boot-image-profile \
119  "${profman_profile_input_args[@]}" \
120  --out-profile-path="$OUT_BOOT_PROFILE" \
121  --out-preloaded-classes-path="$OUT_PRELOADED_CLASSES" \
122  --preloaded-classes-blacklist="$PRELOADED_BLACKLIST" \
123  --special-package=android:1 \
124  --special-package=com.android.systemui:1 \
125  "${profman_args[@]}"
126
127echo "Done boot image profile"
128
129echo "Running profman for system server"
130# For system server profile we want to include everything usually
131# We also don't have a preloaded-classes file for it, so we ignore the argument.
132profman \
133  --generate-boot-image-profile \
134  "${profman_profile_input_args[@]}" \
135  --out-profile-path="$OUT_SYSTEM_SERVER" \
136  --apk="$SYSTEM_SERVER_JAR" \
137  --method-threshold=0 \
138  --class-threshold=0
139
140echo "Done system server"
141
142echo ""
143echo "Boot profile methods+classes count:          $(wc -l $OUT_BOOT_PROFILE)"
144echo "Preloaded classes count:                     $(wc -l $OUT_PRELOADED_CLASSES)"
145echo "System server profile methods+classes count: $(wc -l $OUT_SYSTEM_SERVER)"
146
147CLEAN_UP="${CLEAN_UP:-true}"
148if [[ "$CLEAN_UP" = "true" ]]; then
149  rm -rf "$WORK_DIR"
150fi