• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.art;
18 
19 import static com.android.server.art.model.ArtFlags.PriorityClassApi;
20 
21 import android.annotation.FlaggedApi;
22 import android.annotation.NonNull;
23 import android.annotation.StringDef;
24 import android.annotation.SystemApi;
25 import android.os.Build;
26 import android.os.SystemProperties;
27 import android.text.TextUtils;
28 
29 import androidx.annotation.RequiresApi;
30 
31 import com.android.art.flags.Flags;
32 import com.android.server.art.model.ArtFlags;
33 import com.android.server.pm.PackageManagerLocal;
34 
35 import dalvik.system.DexFile;
36 
37 import java.lang.annotation.Retention;
38 import java.lang.annotation.RetentionPolicy;
39 import java.util.Set;
40 
41 /**
42  * Maps a compilation reason to a compiler filter and a priority class.
43  *
44  * @hide
45  */
46 @SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
47 @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
48 public class ReasonMapping {
ReasonMapping()49     private ReasonMapping() {}
50 
51     // Keep this in sync with `ArtShellCommand.printHelp` except for 'inactive'.
52 
53     /** Dexopting apps on the first boot after flashing or factory resetting the device. */
54     public static final String REASON_FIRST_BOOT = "first-boot";
55     /** Dexopting apps on the next boot after an OTA. */
56     public static final String REASON_BOOT_AFTER_OTA = "boot-after-ota";
57     /** Dexopting apps on the next boot after a mainline update. */
58     public static final String REASON_BOOT_AFTER_MAINLINE_UPDATE = "boot-after-mainline-update";
59     /** Installing an app after user presses the "install"/"update" button. */
60     public static final String REASON_INSTALL = "install";
61     /** Dexopting apps in the background. */
62     public static final String REASON_BG_DEXOPT = "bg-dexopt";
63     /** Invoked by cmdline. */
64     public static final String REASON_CMDLINE = "cmdline";
65     /** Downgrading the compiler filter when an app is not used for a long time. */
66     public static final String REASON_INACTIVE = "inactive";
67     /**
68      * Dexopting apps before the reboot for an OTA or a mainline update, known as Pre-reboot
69      * Dexopt.
70      */
71     @FlaggedApi(Flags.FLAG_ART_SERVICE_V3)
72     public static final String REASON_PRE_REBOOT_DEXOPT = "ab-ota";
73 
74     // Reasons for Play Install Hints (go/install-hints).
75     public static final String REASON_INSTALL_FAST = "install-fast";
76     public static final String REASON_INSTALL_BULK = "install-bulk";
77     public static final String REASON_INSTALL_BULK_SECONDARY = "install-bulk-secondary";
78     public static final String REASON_INSTALL_BULK_DOWNGRADED = "install-bulk-downgraded";
79     public static final String REASON_INSTALL_BULK_SECONDARY_DOWNGRADED =
80             "install-bulk-secondary-downgraded";
81 
82     /** @hide */
83     public static final Set<String> REASONS_FOR_INSTALL = Set.of(REASON_INSTALL,
84             REASON_INSTALL_FAST, REASON_INSTALL_BULK, REASON_INSTALL_BULK_SECONDARY,
85             REASON_INSTALL_BULK_DOWNGRADED, REASON_INSTALL_BULK_SECONDARY_DOWNGRADED);
86 
87     // Keep this in sync with `ArtShellCommand.printHelp`.
88     /** @hide */
89     public static final Set<String> BATCH_DEXOPT_REASONS =
90             Set.of(REASON_FIRST_BOOT, REASON_BOOT_AFTER_OTA, REASON_BOOT_AFTER_MAINLINE_UPDATE,
91                     REASON_BG_DEXOPT, REASON_PRE_REBOOT_DEXOPT);
92 
93     /** @hide */
94     public static final Set<String> BOOT_REASONS =
95             Set.of(REASON_FIRST_BOOT, REASON_BOOT_AFTER_OTA, REASON_BOOT_AFTER_MAINLINE_UPDATE);
96 
97     /**
98      * Reasons for {@link ArtManagerLocal#dexoptPackages}.
99      *
100      * @hide
101      */
102     // clang-format off
103     @StringDef(prefix = "REASON_", value = {
104         REASON_FIRST_BOOT,
105         REASON_BOOT_AFTER_OTA,
106         REASON_BOOT_AFTER_MAINLINE_UPDATE,
107         REASON_BG_DEXOPT,
108         REASON_PRE_REBOOT_DEXOPT,
109     })
110     // clang-format on
111     @Retention(RetentionPolicy.SOURCE)
112     public @interface BatchDexoptReason {}
113 
114     /**
115      * Reasons for {@link ArtManagerLocal#onBoot(String, Executor, Consumer<OperationProgress>)}.
116      *
117      * @hide
118      */
119     // clang-format off
120     @StringDef(prefix = "REASON_", value = {
121         REASON_FIRST_BOOT,
122         REASON_BOOT_AFTER_OTA,
123         REASON_BOOT_AFTER_MAINLINE_UPDATE,
124     })
125     // clang-format on
126     @Retention(RetentionPolicy.SOURCE)
127     public @interface BootReason {}
128 
129     /**
130      * Loads the compiler filter from the system property for the given reason and checks for
131      * validity.
132      *
133      * @throws IllegalArgumentException if the reason is invalid
134      * @throws IllegalStateException if the system property value is invalid
135      *
136      * @hide
137      */
138     @NonNull
getCompilerFilterForReason(@onNull String reason)139     public static String getCompilerFilterForReason(@NonNull String reason) {
140         String value = SystemProperties.get("pm.dexopt." + reason);
141         if (TextUtils.isEmpty(value)) {
142             throw new IllegalArgumentException("No compiler filter for reason '" + reason + "'");
143         }
144         if (!Utils.isValidArtServiceCompilerFilter(value)) {
145             throw new IllegalStateException(
146                     "Got invalid compiler filter '" + value + "' for reason '" + reason + "'");
147         }
148         return value;
149     }
150 
151     /**
152      * Loads the compiler filter from the system property for:
153      * - shared libraries
154      * - apps used by other apps without a dex metadata file
155      *
156      * @throws IllegalStateException if the system property value is invalid
157      *
158      * @hide
159      */
160     @NonNull
getCompilerFilterForShared()161     public static String getCompilerFilterForShared() {
162         // "shared" is technically not a compilation reason, but the compiler filter is defined as a
163         // system property as if "shared" is a reason.
164         String value = getCompilerFilterForReason("shared");
165         if (DexFile.isProfileGuidedCompilerFilter(value)) {
166             throw new IllegalStateException(
167                     "Compiler filter for 'shared' must not be profile guided, got '" + value + "'");
168         }
169         return value;
170     }
171 
172     /**
173      * Returns the priority for the given reason.
174      *
175      * @throws IllegalArgumentException if the reason is invalid
176      * @see PriorityClassApi
177      *
178      * @hide
179      */
getPriorityClassForReason(@onNull String reason)180     public static @PriorityClassApi byte getPriorityClassForReason(@NonNull String reason) {
181         switch (reason) {
182             case REASON_FIRST_BOOT:
183             case REASON_BOOT_AFTER_OTA:
184             case REASON_BOOT_AFTER_MAINLINE_UPDATE:
185                 return ArtFlags.PRIORITY_BOOT;
186             case REASON_INSTALL_FAST:
187                 return ArtFlags.PRIORITY_INTERACTIVE_FAST;
188             case REASON_INSTALL:
189             case REASON_CMDLINE:
190                 return ArtFlags.PRIORITY_INTERACTIVE;
191             case REASON_BG_DEXOPT:
192             case REASON_PRE_REBOOT_DEXOPT:
193             case REASON_INACTIVE:
194             case REASON_INSTALL_BULK:
195             case REASON_INSTALL_BULK_SECONDARY:
196             case REASON_INSTALL_BULK_DOWNGRADED:
197             case REASON_INSTALL_BULK_SECONDARY_DOWNGRADED:
198                 return ArtFlags.PRIORITY_BACKGROUND;
199             default:
200                 throw new IllegalArgumentException("No priority class for reason '" + reason + "'");
201         }
202     }
203 
204     /**
205      * Loads the concurrency from the system property, for batch dexopt ({@link
206      * ArtManagerLocal#dexoptPackages}). The default is tuned to strike a good balance between
207      * device load and dexopt coverage, depending on the situation.
208      *
209      * @hide
210      */
getConcurrencyForReason(@onNull @atchDexoptReason String reason)211     public static int getConcurrencyForReason(@NonNull @BatchDexoptReason String reason) {
212         // TODO(jiakaiz): Revisit the concurrency for non-boot reasons.
213         return SystemProperties.getInt("pm.dexopt." + reason + ".concurrency",
214                 BOOT_REASONS.contains(reason) ? 4 : 1 /* def */);
215     }
216 }
217