• 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.model;
18 
19 import static com.android.server.art.model.ArtFlags.DexoptFlags;
20 import static com.android.server.art.model.ArtFlags.PriorityClassApi;
21 
22 import android.annotation.NonNull;
23 import android.annotation.Nullable;
24 import android.annotation.SystemApi;
25 import android.os.Build;
26 
27 import androidx.annotation.RequiresApi;
28 
29 import com.android.internal.annotations.Immutable;
30 import com.android.server.art.ArtConstants;
31 import com.android.server.art.ReasonMapping;
32 import com.android.server.art.Utils;
33 
34 /** @hide */
35 @SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
36 @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
37 @Immutable
38 public class DexoptParams {
39     /** @hide */
40     @SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
41     public static final class Builder {
42         private DexoptParams mParams = new DexoptParams();
43 
44         /**
45          * Creates a builder.
46          *
47          * Uses default flags ({@link ArtFlags#defaultDexoptFlags()}).
48          *
49          * @param reason Compilation reason. Can be a string defined in {@link ReasonMapping} or a
50          *         custom string. If the value is a string defined in {@link ReasonMapping}, it
51          *         determines the compiler filter and/or the priority class, if those values are not
52          *         explicitly set. If the value is a custom string, the priority class and the
53          *         compiler filter must be explicitly set.
54          */
Builder(@onNull String reason)55         public Builder(@NonNull String reason) {
56             this(reason, ArtFlags.defaultDexoptFlags(reason));
57         }
58 
59         /**
60          * Same as above, but allows to specify flags.
61          */
Builder(@onNull String reason, @DexoptFlags int flags)62         public Builder(@NonNull String reason, @DexoptFlags int flags) {
63             mParams.mReason = reason;
64             setFlags(flags);
65         }
66 
67         /** Replaces all flags with the given value. */
68         @NonNull
setFlags(@exoptFlags int value)69         public Builder setFlags(@DexoptFlags int value) {
70             mParams.mFlags = value;
71             return this;
72         }
73 
74         /** Replaces the flags specified by the mask with the given value. */
75         @NonNull
setFlags(@exoptFlags int value, @DexoptFlags int mask)76         public Builder setFlags(@DexoptFlags int value, @DexoptFlags int mask) {
77             mParams.mFlags = (mParams.mFlags & ~mask) | (value & mask);
78             return this;
79         }
80 
81         /**
82          * The target compiler filter, passed as the {@code --compiler-filer} option to dex2oat.
83          * Supported values are listed in
84          * https://source.android.com/docs/core/dalvik/configure#compilation_options.
85          *
86          * Note that the compiler filter might be adjusted before the execution based on factors
87          * like whether the profile is available or whether the app is used by other apps. If not
88          * set, the default compiler filter for the given reason will be used.
89          */
90         @NonNull
setCompilerFilter(@onNull String value)91         public Builder setCompilerFilter(@NonNull String value) {
92             mParams.mCompilerFilter = value;
93             return this;
94         }
95 
96         /**
97          * The priority of the operation. If not set, the default priority class for the given
98          * reason will be used.
99          *
100          * @see PriorityClassApi
101          */
102         @NonNull
setPriorityClass(@riorityClassApi int value)103         public Builder setPriorityClass(@PriorityClassApi int value) {
104             mParams.mPriorityClass = value;
105             return this;
106         }
107 
108         /**
109          * The name of the split to dexopt, or null for the base split. This option is only
110          * available when {@link ArtFlags#FLAG_FOR_SINGLE_SPLIT} is set.
111          */
112         @NonNull
setSplitName(@ullable String value)113         public Builder setSplitName(@Nullable String value) {
114             mParams.mSplitName = value;
115             return this;
116         }
117 
118         /**
119          * Returns the built object.
120          *
121          * @throws IllegalArgumentException if the built options would be invalid
122          */
123         @NonNull
build()124         public DexoptParams build() {
125             if (mParams.mReason.isEmpty()) {
126                 throw new IllegalArgumentException("Reason must not be empty");
127             }
128             if (mParams.mReason.equals(ArtConstants.REASON_VDEX)) {
129                 throw new IllegalArgumentException(
130                         "Reason must not be '" + ArtConstants.REASON_VDEX + "'");
131             }
132 
133             if (mParams.mCompilerFilter.isEmpty()) {
134                 mParams.mCompilerFilter = ReasonMapping.getCompilerFilterForReason(mParams.mReason);
135             } else if (!Utils.isValidArtServiceCompilerFilter(mParams.mCompilerFilter)) {
136                 throw new IllegalArgumentException(
137                         "Invalid compiler filter '" + mParams.mCompilerFilter + "'");
138             }
139 
140             if (mParams.mPriorityClass == ArtFlags.PRIORITY_NONE) {
141                 mParams.mPriorityClass = ReasonMapping.getPriorityClassForReason(mParams.mReason);
142             } else if (mParams.mPriorityClass < 0 || mParams.mPriorityClass > 100) {
143                 throw new IllegalArgumentException("Invalid priority class "
144                         + mParams.mPriorityClass + ". Must be between 0 and 100");
145             }
146 
147             if ((mParams.mFlags & (ArtFlags.FLAG_FOR_PRIMARY_DEX | ArtFlags.FLAG_FOR_SECONDARY_DEX))
148                     == 0) {
149                 throw new IllegalArgumentException("Nothing to dexopt");
150             }
151 
152             if ((mParams.mFlags & ArtFlags.FLAG_FOR_PRIMARY_DEX) == 0
153                     && (mParams.mFlags & ArtFlags.FLAG_SHOULD_INCLUDE_DEPENDENCIES) != 0) {
154                 throw new IllegalArgumentException(
155                         "FLAG_SHOULD_INCLUDE_DEPENDENCIES must not set if FLAG_FOR_PRIMARY_DEX is "
156                         + "not set.");
157             }
158 
159             if ((mParams.mFlags & ArtFlags.FLAG_FOR_SINGLE_SPLIT) != 0) {
160                 if ((mParams.mFlags & ArtFlags.FLAG_FOR_PRIMARY_DEX) == 0) {
161                     throw new IllegalArgumentException(
162                             "FLAG_FOR_PRIMARY_DEX must be set when FLAG_FOR_SINGLE_SPLIT is set");
163                 }
164                 if ((mParams.mFlags
165                             & (ArtFlags.FLAG_FOR_SECONDARY_DEX
166                                     | ArtFlags.FLAG_SHOULD_INCLUDE_DEPENDENCIES))
167                         != 0) {
168                     throw new IllegalArgumentException(
169                             "FLAG_FOR_SECONDARY_DEX and FLAG_SHOULD_INCLUDE_DEPENDENCIES must "
170                             + "not be set when FLAG_FOR_SINGLE_SPLIT is set");
171                 }
172             } else {
173                 if (mParams.mSplitName != null) {
174                     throw new IllegalArgumentException(
175                             "Split name must not be set when FLAG_FOR_SINGLE_SPLIT is not set");
176                 }
177             }
178 
179             return mParams;
180         }
181     }
182 
183     /**
184      * A value indicating that dexopt shouldn't be run. This value is consumed by ART Services and
185      * is not propagated to dex2oat.
186      */
187     public static final String COMPILER_FILTER_NOOP = "skip";
188 
189     private @DexoptFlags int mFlags = 0;
190     private @NonNull String mCompilerFilter = "";
191     private @PriorityClassApi int mPriorityClass = ArtFlags.PRIORITY_NONE;
192     private @NonNull String mReason = "";
193     private @Nullable String mSplitName = null;
194 
DexoptParams()195     private DexoptParams() {}
196 
197     /** Returns all flags. */
getFlags()198     public @DexoptFlags int getFlags() {
199         return mFlags;
200     }
201 
202     /** The target compiler filter. */
getCompilerFilter()203     public @NonNull String getCompilerFilter() {
204         return mCompilerFilter;
205     }
206 
207     /** The priority class. */
getPriorityClass()208     public @PriorityClassApi int getPriorityClass() {
209         return mPriorityClass;
210     }
211 
212     /**
213      * The compilation reason.
214      *
215      * DO NOT directly use the string value to determine the resource usage and the process
216      * priority. Use {@link #getPriorityClass}.
217      */
getReason()218     public @NonNull String getReason() {
219         return mReason;
220     }
221 
222     /** The name of the split to dexopt, or null for the base split. */
getSplitName()223     public @Nullable String getSplitName() {
224         return mSplitName;
225     }
226 }
227