blob: 33de95e689342f38c444bc1716a38fd13e753b2a [file] [log] [blame]
Morten Krogh-Jespersena28fcdb2022-01-28 09:48:00 +01001// Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4
5package com.android.tools.r8.androidapi;
6
7import com.android.tools.r8.graph.DexItemFactory;
Morten Krogh-Jespersene742b1a2023-03-21 13:38:24 +01008import com.android.tools.r8.graph.DexProto;
Morten Krogh-Jespersena28fcdb2022-01-28 09:48:00 +01009import com.android.tools.r8.graph.DexReference;
Morten Krogh-Jespersenb1bfc242022-01-31 14:56:52 +010010import com.android.tools.r8.graph.DexType;
Morten Krogh-Jespersena28fcdb2022-01-28 09:48:00 +010011import com.android.tools.r8.utils.AndroidApiLevel;
Morten Krogh-Jespersen7c44fe42023-05-09 10:27:26 +020012import java.util.HashSet;
13import java.util.Set;
Morten Krogh-Jespersena28fcdb2022-01-28 09:48:00 +010014import java.util.function.BiConsumer;
15
Morten Krogh-Jespersen7c44fe42023-05-09 10:27:26 +020016public class AndroidApiLevelDatabaseHelper {
17
18 public static Set<String> notModeledTypes() {
Søren Gjesse7a366492024-06-26 09:38:58 +020019 // The types below are known not to be modeled by any api-versions.
Morten Krogh-Jespersen7c44fe42023-05-09 10:27:26 +020020 Set<String> notModeledTypes = new HashSet<>();
21 notModeledTypes.add("androidx.annotation.RecentlyNullable");
22 notModeledTypes.add("androidx.annotation.RecentlyNonNull");
23 notModeledTypes.add("android.annotation.Nullable");
24 notModeledTypes.add("android.annotation.NonNull");
Søren Gjesse6fdc87c2024-06-19 12:43:22 +020025 notModeledTypes.add("android.annotation.FlaggedApi");
Søren Gjesse7a366492024-06-26 09:38:58 +020026 notModeledTypes.add(
Søren Gjesse00f86ff2025-03-25 12:13:24 +010027 "android.adservices.ondevicepersonalization.FederatedComputeScheduleRequest");
28 notModeledTypes.add(
29 "android.adservices.ondevicepersonalization.FederatedComputeScheduleResponse");
Morten Krogh-Jespersen7c44fe42023-05-09 10:27:26 +020030 return notModeledTypes;
31 }
Morten Krogh-Jespersena28fcdb2022-01-28 09:48:00 +010032
Søren Gjesse7a366492024-06-26 09:38:58 +020033 public static Set<String> notModeledFields() {
34 // The fields below are known not to be modeled by any api-versions.
35 Set<String> notModeledFields = new HashSet<>();
36 notModeledFields.add("int android.app.appsearch.AppSearchResult.RESULT_DENIED");
37 notModeledFields.add("int android.app.appsearch.AppSearchResult.RESULT_RATE_LIMITED");
Søren Gjesse00f86ff2025-03-25 12:13:24 +010038
39 notModeledFields.add(
40 "int android.adservices.adselection.ReportEventRequest.FLAG_REPORTING_DESTINATION_COMPONENT_SELLER");
41 notModeledFields.add(
42 "int android.adservices.ondevicepersonalization.OnDevicePersonalizationManager.FEATURE_DISABLED");
43 notModeledFields.add(
44 "int android.adservices.ondevicepersonalization.OnDevicePersonalizationManager.FEATURE_ENABLED");
45 notModeledFields.add(
46 "int android.adservices.ondevicepersonalization.OnDevicePersonalizationManager.FEATURE_UNSUPPORTED");
47 notModeledFields.add(
48 "int android.adservices.ondevicepersonalization.InferenceInput$Params.MODEL_TYPE_EXECUTORCH");
Søren Gjesse7a366492024-06-26 09:38:58 +020049 return notModeledFields;
50 }
51
52 public static Set<String> notModeledMethods() {
53 // The methods below are known not to be modeled by any api-versions.
54 Set<String> notModelledMethods = new HashSet<>();
55 notModelledMethods.add(
56 "void android.adservices.customaudience.CustomAudienceManager.scheduleCustomAudienceUpdate(android.adservices.customaudience.ScheduleCustomAudienceUpdateRequest,"
57 + " java.util.concurrent.Executor,"
58 + " android.adservices.common.AdServicesOutcomeReceiver)");
Søren Gjesse00f86ff2025-03-25 12:13:24 +010059 notModelledMethods.add(
60 "android.adservices.ondevicepersonalization.InferenceOutput$Builder"
61 + " android.adservices.ondevicepersonalization.InferenceOutput$Builder.setData(byte[])");
62 notModelledMethods.add(
63 "android.adservices.common.AdTechIdentifier"
64 + " android.adservices.adselection.AdSelectionOutcome.getWinningSeller()");
65 notModelledMethods.add(
66 "void android.adservices.ondevicepersonalization.FederatedComputeScheduler.schedule(android.adservices.ondevicepersonalization.FederatedComputeScheduleRequest,"
67 + " java.util.concurrent.Executor, android.os.OutcomeReceiver)");
68
69 notModelledMethods.add(
70 "byte[] android.adservices.ondevicepersonalization.InferenceOutput.getData()");
71 notModelledMethods.add(
72 "byte[] android.adservices.ondevicepersonalization.InferenceInput.getData()");
73 notModelledMethods.add(
74 "void android.adservices.ondevicepersonalization.OnDevicePersonalizationManager.queryFeatureAvailability(java.lang.String,"
75 + " java.util.concurrent.Executor, android.os.OutcomeReceiver)");
76 notModelledMethods.add(
77 "void android.adservices.ondevicepersonalization.InferenceInput$Builder.<init>(android.adservices.ondevicepersonalization.InferenceInput$Params,"
78 + " byte[])");
79 notModelledMethods.add(
80 "android.adservices.ondevicepersonalization.InferenceInput$Builder"
81 + " android.adservices.ondevicepersonalization.InferenceInput$Builder.setInputData(byte[])");
Søren Gjesse7a366492024-06-26 09:38:58 +020082 return notModelledMethods;
83 }
84
Morten Krogh-Jespersena28fcdb2022-01-28 09:48:00 +010085 static void visitAdditionalKnownApiReferences(
86 DexItemFactory factory, BiConsumer<DexReference, AndroidApiLevel> apiLevelConsumer) {
Morten Krogh-Jespersene742b1a2023-03-21 13:38:24 +010087 addStringBuilderAndBufferMethods(factory, apiLevelConsumer);
88 addConcurrentKeySetViewMethods(factory, apiLevelConsumer);
89 addNfcMethods(factory, apiLevelConsumer);
90 addWebkitCookieSyncManagerMethods(factory, apiLevelConsumer);
91 addChronoTimeMethods(factory, apiLevelConsumer);
92 }
93
94 private static void addStringBuilderAndBufferMethods(
95 DexItemFactory factory, BiConsumer<DexReference, AndroidApiLevel> apiLevelConsumer) {
Morten Krogh-Jespersenb1bfc242022-01-31 14:56:52 +010096 // StringBuilder and StringBuffer lack api definitions for the exact same methods in
97 // api-versions.xml. See b/216587554 for related error.
98 for (DexType type : new DexType[] {factory.stringBuilderType, factory.stringBufferType}) {
99 apiLevelConsumer.accept(
100 factory.createMethod(type, factory.createProto(factory.intType), "capacity"),
101 AndroidApiLevel.B);
102 apiLevelConsumer.accept(
103 factory.createMethod(
104 type, factory.createProto(factory.intType, factory.intType), "codePointAt"),
105 AndroidApiLevel.B);
106 apiLevelConsumer.accept(
107 factory.createMethod(
108 type, factory.createProto(factory.intType, factory.intType), "codePointBefore"),
109 AndroidApiLevel.B);
110 apiLevelConsumer.accept(
111 factory.createMethod(
112 type,
113 factory.createProto(factory.intType, factory.intType, factory.intType),
114 "codePointCount"),
115 AndroidApiLevel.B);
116 apiLevelConsumer.accept(
117 factory.createMethod(
118 type, factory.createProto(factory.voidType, factory.intType), "ensureCapacity"),
119 AndroidApiLevel.B);
120 apiLevelConsumer.accept(
121 factory.createMethod(
122 type,
123 factory.createProto(
124 factory.voidType,
125 factory.intType,
126 factory.intType,
127 factory.charArrayType,
128 factory.intType),
129 "getChars"),
130 AndroidApiLevel.B);
131 apiLevelConsumer.accept(
132 factory.createMethod(
133 type, factory.createProto(factory.intType, factory.stringType), "indexOf"),
134 AndroidApiLevel.B);
135 apiLevelConsumer.accept(
136 factory.createMethod(
137 type,
138 factory.createProto(factory.intType, factory.stringType, factory.intType),
139 "indexOf"),
140 AndroidApiLevel.B);
141 apiLevelConsumer.accept(
142 factory.createMethod(
143 type, factory.createProto(factory.intType, factory.stringType), "lastIndexOf"),
144 AndroidApiLevel.B);
145 apiLevelConsumer.accept(
146 factory.createMethod(
147 type,
148 factory.createProto(factory.intType, factory.stringType, factory.intType),
149 "lastIndexOf"),
150 AndroidApiLevel.B);
151 apiLevelConsumer.accept(
152 factory.createMethod(
153 type,
154 factory.createProto(factory.intType, factory.intType, factory.intType),
155 "offsetByCodePoints"),
156 AndroidApiLevel.B);
157 apiLevelConsumer.accept(
158 factory.createMethod(
159 type,
160 factory.createProto(factory.voidType, factory.intType, factory.charType),
161 "setCharAt"),
162 AndroidApiLevel.B);
163 apiLevelConsumer.accept(
164 factory.createMethod(
165 type, factory.createProto(factory.voidType, factory.intType), "setLength"),
166 AndroidApiLevel.B);
167 apiLevelConsumer.accept(
168 factory.createMethod(
169 type, factory.createProto(factory.stringType, factory.intType), "substring"),
170 AndroidApiLevel.B);
171 apiLevelConsumer.accept(
172 factory.createMethod(
173 type,
174 factory.createProto(factory.stringType, factory.intType, factory.intType),
175 "substring"),
176 AndroidApiLevel.B);
177 apiLevelConsumer.accept(
178 factory.createMethod(type, factory.createProto(factory.voidType), "trimToSize"),
179 AndroidApiLevel.B);
180 }
Morten Krogh-Jespersena28fcdb2022-01-28 09:48:00 +0100181 }
Morten Krogh-Jespersene742b1a2023-03-21 13:38:24 +0100182
183 private static void addConcurrentKeySetViewMethods(
184 DexItemFactory factory, BiConsumer<DexReference, AndroidApiLevel> apiLevelConsumer) {
185 // KeysetView.getMap was also added in N (24).
186 apiLevelConsumer.accept(
187 factory.createMethod(
188 factory.concurrentHashMapKeySetViewType,
189 factory.createProto(factory.concurrentHashMapType),
190 "getMap"),
191 AndroidApiLevel.N);
192 }
193
194 private static void addNfcMethods(
195 DexItemFactory factory, BiConsumer<DexReference, AndroidApiLevel> apiLevelConsumer) {
196 String[] nfcClasses =
197 new String[] {
198 "Landroid/nfc/tech/Ndef;",
199 "Landroid/nfc/tech/NfcA;",
200 "Landroid/nfc/tech/NfcB;",
201 "Landroid/nfc/tech/NfcBarcode;",
202 "Landroid/nfc/tech/NfcF;",
203 "Landroid/nfc/tech/NdefFormatable;",
204 "Landroid/nfc/tech/IsoDep;",
205 "Landroid/nfc/tech/MifareClassic;",
206 "Landroid/nfc/tech/MifareUltralight;",
207 "Landroid/nfc/tech/NfcV;"
208 };
209 DexType tagType = factory.createType("Landroid/nfc/Tag;");
210 // Seems like all methods are available from api level G_MR1 but we choose K since some of these
211 // classes are introduced at 17.
212 for (String nfcClass : nfcClasses) {
213 DexType nfcClassType = factory.createType(nfcClass);
214 apiLevelConsumer.accept(
215 factory.createMethod(
216 nfcClassType, factory.createProto(factory.booleanType), "isConnected"),
217 AndroidApiLevel.K);
218 apiLevelConsumer.accept(
219 factory.createMethod(nfcClassType, factory.createProto(tagType), "getTag"),
220 AndroidApiLevel.K);
221 apiLevelConsumer.accept(
222 factory.createMethod(nfcClassType, factory.createProto(factory.voidType), "close"),
223 AndroidApiLevel.K);
224 apiLevelConsumer.accept(
225 factory.createMethod(nfcClassType, factory.createProto(factory.voidType), "connect"),
226 AndroidApiLevel.K);
227 }
228 }
229
230 private static void addWebkitCookieSyncManagerMethods(
231 DexItemFactory factory, BiConsumer<DexReference, AndroidApiLevel> apiLevelConsumer) {
232 // All of these are added in android.jar from at least 14.
233 DexType cookieSyncManager = factory.createType("Landroid/webkit/CookieSyncManager;");
234 DexProto voidProto = factory.createProto(factory.voidType);
235 for (String methodName : new String[] {"sync", "resetSync", "startSync", "stopSync", "run"}) {
236 apiLevelConsumer.accept(
237 factory.createMethod(cookieSyncManager, voidProto, methodName), AndroidApiLevel.I);
238 }
239 }
240
241 private static void addChronoTimeMethods(
242 DexItemFactory factory, BiConsumer<DexReference, AndroidApiLevel> apiLevelConsumer) {
243 DexType valueRangeType = factory.createType("Ljava/time/temporal/ValueRange;");
244 DexType chronoLocalDateType = factory.createType("Ljava/time/chrono/ChronoLocalDate;");
245 DexType temporalType = factory.createType("Ljava/time/temporal/Temporal;");
246 DexType temporalFieldType = factory.createType("Ljava/time/temporal/TemporalField;");
247 DexType temporalUnitType = factory.createType("Ljava/time/temporal/TemporalUnit;");
248 DexType temporalAmountType = factory.createType("Ljava/time/temporal/TemporalAmount;");
249 DexType temporalAdjusterType = factory.createType("Ljava/time/temporal/TemporalAdjuster;");
250
251 // All of these classes was added in 26.
252 String[] timeClasses =
253 new String[] {
254 "Ljava/time/chrono/JapaneseDate;",
255 "Ljava/time/chrono/MinguoDate;",
256 "Ljava/time/chrono/HijrahDate;",
257 "Ljava/time/chrono/ThaiBuddhistDate;"
258 };
259 for (String timeClass : timeClasses) {
260 DexType timeType = factory.createType(timeClass);
261 // int lengthOfMonth()
262 apiLevelConsumer.accept(
263 factory.createMethod(timeType, factory.createProto(factory.intType), "lengthOfMonth"),
264 AndroidApiLevel.O);
265 // int lengthOfYear()
266 apiLevelConsumer.accept(
267 factory.createMethod(timeType, factory.createProto(factory.intType), "lengthOfYear"),
268 AndroidApiLevel.O);
269 // boolean isSupported(java.time.temporal.TemporalField)
270 apiLevelConsumer.accept(
271 factory.createMethod(
272 timeType, factory.createProto(factory.booleanType, temporalFieldType), "isSupported"),
273 AndroidApiLevel.O);
274 // java.time.temporal.ValueRange range(java.time.temporal.TemporalField)
275 apiLevelConsumer.accept(
276 factory.createMethod(
277 timeType, factory.createProto(valueRangeType, temporalFieldType), "range"),
278 AndroidApiLevel.O);
279 // long getLong(java.time.temporal.TemporalField)
280 apiLevelConsumer.accept(
281 factory.createMethod(
282 timeType, factory.createProto(factory.longType, temporalFieldType), "getLong"),
283 AndroidApiLevel.O);
284 // java.time.chrono.ChronoLocalDateTime atTime(java.time.LocalTime)
285 apiLevelConsumer.accept(
286 factory.createMethod(
287 timeType,
288 factory.createProto(
289 factory.createType("Ljava/time/chrono/ChronoLocalDateTime;"),
290 factory.createType("Ljava/time/LocalTime;")),
291 "atTime"),
292 AndroidApiLevel.O);
293 // java.time.chrono.ChronoPeriod
294 // java.time.chrono.JapaneseDate.until(java.time.chrono.ChronoLocalDate)
295 apiLevelConsumer.accept(
296 factory.createMethod(
297 timeType,
298 factory.createProto(
299 factory.createType("Ljava/time/chrono/ChronoPeriod;"), chronoLocalDateType),
300 "until"),
301 AndroidApiLevel.O);
302 // long toEpochDay()
303 apiLevelConsumer.accept(
304 factory.createMethod(timeType, factory.createProto(factory.longType), "toEpochDay"),
305 AndroidApiLevel.O);
306 // long until(java.time.temporal.Temporal, java.time.temporal.TemporalUnit)
307 apiLevelConsumer.accept(
308 factory.createMethod(
309 timeType,
310 factory.createProto(factory.longType, temporalType, temporalUnitType),
311 "until"),
312 AndroidApiLevel.O);
313
314 // java.time.chrono.Era getEra()
315 apiLevelConsumer.accept(
316 factory.createMethod(
317 timeType,
318 factory.createProto(factory.createType("Ljava/time/chrono/Era;")),
319 "getEra"),
320 AndroidApiLevel.O);
321 // java.time.chrono.Chronology getChronology()
322 apiLevelConsumer.accept(
323 factory.createMethod(
324 timeType,
325 factory.createProto(factory.createType("Ljava/time/chrono/Chronology;")),
326 "getChronology"),
327 AndroidApiLevel.O);
328 DexType[] returnTypesForModificationMethods =
329 new DexType[] {chronoLocalDateType, temporalType};
330 for (DexType returnType : returnTypesForModificationMethods) {
331 // [returnType] minus(long, java.time.temporal.TemporalUnit)
332 apiLevelConsumer.accept(
333 factory.createMethod(
334 timeType,
335 factory.createProto(returnType, factory.longType, temporalUnitType),
336 "minus"),
337 AndroidApiLevel.O);
338 // [returnType] minus(java.time.temporal.TemporalAmount)
339 apiLevelConsumer.accept(
340 factory.createMethod(
341 timeType, factory.createProto(returnType, temporalAmountType), "minus"),
342 AndroidApiLevel.O);
343 // [returnType] plus(long, java.time.temporal.TemporalUnit)
344 apiLevelConsumer.accept(
345 factory.createMethod(
346 timeType,
347 factory.createProto(returnType, factory.longType, temporalUnitType),
348 "plus"),
349 AndroidApiLevel.O);
350 // [returnType] plus(java.time.temporal.TemporalAmount)
351 apiLevelConsumer.accept(
352 factory.createMethod(
353 timeType, factory.createProto(returnType, temporalAmountType), "plus"),
354 AndroidApiLevel.O);
355 // [returnType] with(java.time.temporal.TemporalField, long)
356 apiLevelConsumer.accept(
357 factory.createMethod(
358 timeType,
359 factory.createProto(returnType, temporalFieldType, factory.longType),
360 "with"),
361 AndroidApiLevel.O);
362 // [returnType] with(java.time.temporal.TemporalAdjuster)
363 apiLevelConsumer.accept(
364 factory.createMethod(
365 timeType, factory.createProto(returnType, temporalAdjusterType), "with"),
366 AndroidApiLevel.O);
367 }
368 }
369 // boolean java.time.chrono.HijrahDate.isLeapYear()
370 apiLevelConsumer.accept(
371 factory.createMethod(
372 factory.createType("Ljava/time/chrono/HijrahDate;"),
373 factory.createProto(factory.booleanType),
374 "isLeapYear"),
375 AndroidApiLevel.O);
376 }
Morten Krogh-Jespersena28fcdb2022-01-28 09:48:00 +0100377}