• 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.NonNull;
22 import android.annotation.StringDef;
23 import android.annotation.SystemApi;
24 import android.os.Build;
25 import android.os.SystemProperties;
26 import android.text.TextUtils;
27 
28 import androidx.annotation.RequiresApi;
29 
30 import com.android.server.art.model.ArtFlags;
31 import com.android.server.pm.PackageManagerLocal;
32 
33 import dalvik.system.DexFile;
34 
35 import java.lang.annotation.Retention;
36 import java.lang.annotation.RetentionPolicy;
37 import java.util.Set;
38 
39 /**
40  * Maps a compilation reason to a compiler filter and a priority class.
41  *
42  * @hide
43  */
44 @SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
45 @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
46 public class ReasonMapping {
ReasonMapping()47     private ReasonMapping() {}
48 
49     // Keep this in sync with `ArtShellCommand.printHelp` except for 'inactive'.
50 
51     /** Dexopting apps on the first boot after flashing or factory resetting the device. */
52     public static final String REASON_FIRST_BOOT = "first-boot";
53     /** Dexopting apps on the next boot after an OTA. */
54     public static final String REASON_BOOT_AFTER_OTA = "boot-after-ota";
55     /** Dexopting apps on the next boot after a mainline update. */
56     public static final String REASON_BOOT_AFTER_MAINLINE_UPDATE = "boot-after-mainline-update";
57     /** Installing an app after user presses the "install"/"update" button. */
58     public static final String REASON_INSTALL = "install";
59     /** Dexopting apps in the background. */
60     public static final String REASON_BG_DEXOPT = "bg-dexopt";
61     /** Invoked by cmdline. */
62     public static final String REASON_CMDLINE = "cmdline";
63     /** Downgrading the compiler filter when an app is not used for a long time. */
64     public static final String REASON_INACTIVE = "inactive";
65 
66     // Reasons for Play Install Hints (go/install-hints).
67     public static final String REASON_INSTALL_FAST = "install-fast";
68     public static final String REASON_INSTALL_BULK = "install-bulk";
69     public static final String REASON_INSTALL_BULK_SECONDARY = "install-bulk-secondary";
70     public static final String REASON_INSTALL_BULK_DOWNGRADED = "install-bulk-downgraded";
71     public static final String REASON_INSTALL_BULK_SECONDARY_DOWNGRADED =
72             "install-bulk-secondary-downgraded";
73 
74     /** @hide */
75     public static final Set<String> REASONS_FOR_INSTALL = Set.of(REASON_INSTALL,
76             REASON_INSTALL_FAST, REASON_INSTALL_BULK, REASON_INSTALL_BULK_SECONDARY,
77             REASON_INSTALL_BULK_DOWNGRADED, REASON_INSTALL_BULK_SECONDARY_DOWNGRADED);
78 
79     // Keep this in sync with `ArtShellCommand.printHelp`.
80     /** @hide */
81     public static final Set<String> BATCH_DEXOPT_REASONS = Set.of(REASON_FIRST_BOOT,
82             REASON_BOOT_AFTER_OTA, REASON_BOOT_AFTER_MAINLINE_UPDATE, REASON_BG_DEXOPT);
83 
84     /**
85      * Reasons for {@link ArtManagerLocal#dexoptPackages}.
86      *
87      * @hide
88      */
89     // clang-format off
90     @StringDef(prefix = "REASON_", value = {
91         REASON_FIRST_BOOT,
92         REASON_BOOT_AFTER_OTA,
93         REASON_BOOT_AFTER_MAINLINE_UPDATE,
94         REASON_BG_DEXOPT,
95     })
96     // clang-format on
97     @Retention(RetentionPolicy.SOURCE)
98     public @interface BatchDexoptReason {}
99 
100     /**
101      * Reasons for {@link ArtManagerLocal#onBoot(String, Executor, Consumer<OperationProgress>)}.
102      *
103      * @hide
104      */
105     // clang-format off
106     @StringDef(prefix = "REASON_", value = {
107         REASON_FIRST_BOOT,
108         REASON_BOOT_AFTER_OTA,
109         REASON_BOOT_AFTER_MAINLINE_UPDATE,
110     })
111     // clang-format on
112     @Retention(RetentionPolicy.SOURCE)
113     public @interface BootReason {}
114 
115     /**
116      * Loads the compiler filter from the system property for the given reason and checks for
117      * validity.
118      *
119      * @throws IllegalArgumentException if the reason is invalid
120      * @throws IllegalStateException if the system property value is invalid
121      *
122      * @hide
123      */
124     @NonNull
getCompilerFilterForReason(@onNull String reason)125     public static String getCompilerFilterForReason(@NonNull String reason) {
126         String value = SystemProperties.get("pm.dexopt." + reason);
127         if (TextUtils.isEmpty(value)) {
128             throw new IllegalArgumentException("No compiler filter for reason '" + reason + "'");
129         }
130         if (!Utils.isValidArtServiceCompilerFilter(value)) {
131             throw new IllegalStateException(
132                     "Got invalid compiler filter '" + value + "' for reason '" + reason + "'");
133         }
134         return value;
135     }
136 
137     /**
138      * Loads the compiler filter from the system property for:
139      * - shared libraries
140      * - apps used by other apps without a dex metadata file
141      *
142      * @throws IllegalStateException if the system property value is invalid
143      *
144      * @hide
145      */
146     @NonNull
getCompilerFilterForShared()147     public static String getCompilerFilterForShared() {
148         // "shared" is technically not a compilation reason, but the compiler filter is defined as a
149         // system property as if "shared" is a reason.
150         String value = getCompilerFilterForReason("shared");
151         if (DexFile.isProfileGuidedCompilerFilter(value)) {
152             throw new IllegalStateException(
153                     "Compiler filter for 'shared' must not be profile guided, got '" + value + "'");
154         }
155         return value;
156     }
157 
158     /**
159      * Returns the priority for the given reason.
160      *
161      * @throws IllegalArgumentException if the reason is invalid
162      * @see PriorityClassApi
163      *
164      * @hide
165      */
getPriorityClassForReason(@onNull String reason)166     public static @PriorityClassApi byte getPriorityClassForReason(@NonNull String reason) {
167         switch (reason) {
168             case REASON_FIRST_BOOT:
169             case REASON_BOOT_AFTER_OTA:
170             case REASON_BOOT_AFTER_MAINLINE_UPDATE:
171                 return ArtFlags.PRIORITY_BOOT;
172             case REASON_INSTALL_FAST:
173                 return ArtFlags.PRIORITY_INTERACTIVE_FAST;
174             case REASON_INSTALL:
175             case REASON_CMDLINE:
176                 return ArtFlags.PRIORITY_INTERACTIVE;
177             case REASON_BG_DEXOPT:
178             case REASON_INACTIVE:
179             case REASON_INSTALL_BULK:
180             case REASON_INSTALL_BULK_SECONDARY:
181             case REASON_INSTALL_BULK_DOWNGRADED:
182             case REASON_INSTALL_BULK_SECONDARY_DOWNGRADED:
183                 return ArtFlags.PRIORITY_BACKGROUND;
184             default:
185                 throw new IllegalArgumentException("No priority class for reason '" + reason + "'");
186         }
187     }
188 
189     /**
190      * Loads the concurrency from the system property, for batch dexopt ({@link
191      * ArtManagerLocal#dexoptPackages}), or 1 if the system property is not found or cannot be
192      * parsed.
193      *
194      * @hide
195      */
getConcurrencyForReason(@onNull @atchDexoptReason String reason)196     public static int getConcurrencyForReason(@NonNull @BatchDexoptReason String reason) {
197         return SystemProperties.getInt("pm.dexopt." + reason + ".concurrency", 1 /* def */);
198     }
199 }
200