#!/bin/bash # # Copyright (C) 2020 The Android Open Source Project # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # This script creates the framework boot image and system server profiles # (suitable to include in the platform build). # The input to the script are: # 1) the boot.zip file which contains the boot classpath and system server jars. # This file can be obtained from running `m dist` or by configuring the device with # the `art/tools/boot-image-profile-configure-device.sh` script. # 2) the preloaded classes denylist which specify what classes should not be preloaded # in Zygote. Usually located in frameworks/base/config/preloaded-classes-denylist # 3) a list of raw boot image profiles extracted from devices. An example how to do that is # by running `art/tools/boot-image-profile-extract-profile.sh` script. # # It is strongly recommended that you make use of extensive critical user journeys flows in order # to capture the raw boot image profiles described in #3. # # NOTE: by default, the script uses default arguments for producing the boot image profiles. # You might want to adjust the default generation arguments based on the shape of profile # and based on the metrics that matter for each product. # if [[ -z "$ANDROID_BUILD_TOP" ]]; then echo "You must run on this after running envsetup.sh and launch target" exit 1 fi if [[ "$#" -lt 4 ]]; then echo "Usage $0 ... " echo "Without any profman args the script will use defaults." echo "Example: $0 output-dir boot.zip frameworks/base/config/preloaded-classes-denylist android1.prof android2.prof" echo " $0 output-dir boot.zip frameworks/base/config/preloaded-classes-denylist android.prof --profman-arg --upgrade-startup-to-hot=true" echo "preloaded-deny-list-location is usually frameworks/base/config/preloaded-classes-denylist" exit 1 fi echo "Creating work dir" WORK_DIR=/tmp/android-bcp mkdir -p "$WORK_DIR" OUT_DIR="$1" BOOT_ZIP="$2" PRELOADED_DENYLIST="$3" shift 3 # Read the profile input args. profman_profile_input_args=() boot_image_profman_args=() system_server_profman_args=() while [[ "$#" -ge 1 ]]; do # Read the profman args. if [[ "$#" -ge 2 ]]; then if [[ "$1" = '--profman-arg' ]]; then boot_image_profman_args+=("$2") system_server_profman_args+=("$2") shift 2 continue fi if [[ "$1" = '--boot-image-profman-arg' ]]; then boot_image_profman_args+=("$2") shift 2 continue fi if [[ "$1" = '--system-server-profman-arg' ]]; then system_server_profman_args+=("$2") shift 2 continue fi fi profman_profile_input_args+=("--profile-file=$1") shift done OUT_BOOT_PROFILE="$OUT_DIR"/boot-image-profile.txt OUT_PRELOADED_CLASSES="$OUT_DIR"/preloaded-classes OUT_SYSTEM_SERVER="$OUT_DIR"/art-profile ART_JARS=("core-oj.jar core-libart.jar okhttp.jar bouncycastle.jar apache-xml.jar") echo "Changing dirs to the build top" cd "$ANDROID_BUILD_TOP" echo "Unziping boot.zip" BOOT_UNZIP_DIR="$WORK_DIR"/boot-dex BOOT_JARS="$BOOT_UNZIP_DIR"/dex_bootjars_input SYSTEM_SERVER_JAR="$BOOT_UNZIP_DIR"/system/framework/services.jar unzip -o "$BOOT_ZIP" -d "$BOOT_UNZIP_DIR" echo "Processing boot image jar files" jar_args=() for entry in "$BOOT_JARS"/* do # Ignore ART jars, since we want fromework related jars only. jar_name=$(basename "$entry") if [[ " ${ART_JARS[*]} " != *\ ${jar_name}\ * ]]; then jar_args+=("--apk=$entry") fi done echo "Running profman for boot image profiles" # NOTE: # You might want to adjust the default generation arguments based on the data # For example, to update the selection thresholds you could specify: # - For boot image profile: # --boot-image-profman-arg --method-threshold=10 \ # --boot-image-profman-arg --class-threshold=10 \ # --boot-image-profman-arg --preloaded-class-threshold=10 \ # --boot-image-profman-arg --special-package=android:1 \ # --boot-image-profman-arg --special-package=com.android.systemui:1 \ # - For System Server: # --system-server-profman-arg --method-threshold=10 \ # --system-server-profman-arg --class-threshold=10 \ # --system-server-profman-arg --special-package=android:1 \ # --system-server-profman-arg --special-package=com.android.systemui:1 \ # You can use --profman-arg to specify the arguments for both boot image # and system server. # # The threshold is percentage of total aggregation, that is, a method/class is # included in the profile only if it's used by at least x% of the packages. # (from 0% - include everything to 100% - include only the items that # are used by all packages on device). # The --special-package allows you to give a prioriority to certain packages, # meaning, if the methods is used by that package then the algorithm will use a # different selection thresholds. # (system server is identified as the "android" package) if [[ "${#boot_image_profman_args[*]}" -eq 0 ]]; then boot_image_profman_args+=("--special-package=android:1") boot_image_profman_args+=("--special-package=com.android.systemui:1") fi boot_image_profman_args+=("${jar_args[@]}") profman \ --generate-boot-image-profile \ "${profman_profile_input_args[@]}" \ --out-profile-path="$OUT_BOOT_PROFILE" \ --out-preloaded-classes-path="$OUT_PRELOADED_CLASSES" \ --preloaded-classes-denylist="$PRELOADED_DENYLIST" \ "${boot_image_profman_args[@]}" echo "Done boot image profile" echo "Running profman for system server" # We don't have a preloaded-classes nor a denylist files for System Server, so we ignore the arguments. # We also set the thresholds to 0 to include everything if no args are specified. if [[ "${#system_server_profman_args[*]}" -eq 0 ]]; then system_server_profman_args+=("--method-threshold=0") system_server_profman_args+=("--class-threshold=0") fi profman \ --generate-boot-image-profile \ "${profman_profile_input_args[@]}" \ --out-profile-path="$OUT_SYSTEM_SERVER" \ --apk="$SYSTEM_SERVER_JAR" \ "${system_server_profman_args[@]}" echo "Done system server" echo "" echo "Boot profile methods+classes count: $(wc -l $OUT_BOOT_PROFILE)" echo "Preloaded classes count: $(wc -l $OUT_PRELOADED_CLASSES)" echo "System server profile methods+classes count: $(wc -l $OUT_SYSTEM_SERVER)" CLEAN_UP="${CLEAN_UP:-true}" if [[ "$CLEAN_UP" = "true" ]]; then rm -rf "$WORK_DIR" fi