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 package com.android.tools.metalava 17 18 import com.android.tools.metalava.apilevels.ApiVersion 19 20 /** 21 * ID and aliases for a given SDK extension. 22 * 23 * An SDK extension has an [id] corresponding to an Android dessert release that it extends, e.g. 24 * the T extension has an [id] of 33. 25 * 26 * @param id: numerical ID of the extension SDK, primarily used in generated artifacts and consumed 27 * by tools 28 * @param shortname: short name for the SDK, primarily used in configuration files 29 * @param name: human-readable name for the SDK; used in the official documentation 30 * @param reference: Java symbol in the Android SDK with the same numerical value as the id, using a 31 * JVM signature like syntax: "some/clazz$INNER$FIELD" 32 */ 33 sealed class SdkExtension 34 private constructor( 35 val id: Int, 36 val shortname: String, 37 val name: String, 38 val reference: String, 39 ) { 40 /** 41 * Check to see whether this SDK extension supersedes the Android SDK version 42 * [androidSdkVersion]. 43 * 44 * A dessert based extension supersedes an Android SDK version if it is based on that version or 45 * earlier. 46 * 47 * A dessert independent extension will always supersede an Android SDK version. 48 * 49 * @param androidSdkVersion the version of the Android SDK in which an API element was added. 50 */ supersedesAndroidSdkVersionnull51 abstract fun supersedesAndroidSdkVersion(androidSdkVersion: ApiVersion): Boolean 52 53 init { 54 require(id >= 1) { "SDK extensions cannot have an id less than 1 but it is $id" } 55 } 56 57 companion object { 58 /** 59 * Create an [SdkExtension] from the attributes that appear in sdk-extension-info.xml and 60 * api-versions.xml files. 61 * 62 * If [id] is greater than or equal to [DESSERT_RELEASE_INDEPENDENT_SDK_BASE] then the 63 * [SdkExtension] is independent of the Android SDK version, otherwise [id] is the base SDK 64 * version of the extension. 65 */ fromXmlAttributesnull66 fun fromXmlAttributes(id: Int, shortname: String, name: String, reference: String) = 67 if (id >= DESSERT_RELEASE_INDEPENDENT_SDK_BASE) 68 DessertReleaseIndependentSdkExtension(id, shortname, name, reference) 69 else DessertReleaseBasedSdkExtension(id, shortname, name, reference) 70 71 /** 72 * The base of dessert release independent SDKs. 73 * 74 * A dessert release independent SDK is one which is not coupled to the Android dessert 75 * release numbering. Any SDK greater than or equal to this is not comparable to either each 76 * other, or to the Android dessert release. e.g. `1000000` is not the same as, later than, 77 * or earlier than SDK 31. Similarly, `1000001` is not the same as, later than, or earlier 78 * then `1000000`. 79 */ 80 private const val DESSERT_RELEASE_INDEPENDENT_SDK_BASE = 1000000 81 } 82 83 /** 84 * An [SdkExtension] that is based on a specific version of the Android Sdk. 85 * 86 * The [id] is the major version of the Android SDK on which this is based. 87 */ 88 private class DessertReleaseBasedSdkExtension( 89 id: Int, 90 shortname: String, 91 name: String, 92 reference: String, 93 ) : SdkExtension(id, shortname, name, reference) { 94 95 /** 96 * The base [ApiVersion] of this extension. This the version of the Android SDK to which 97 * this extension applies. 98 */ 99 private val baseSdkVersion = ApiVersion.fromLevel(id) 100 101 override fun supersedesAndroidSdkVersion(androidSdkVersion: ApiVersion) = 102 baseSdkVersion <= androidSdkVersion 103 } 104 105 /** An [SdkExtension] that is independent of an Android SDK version. */ 106 private class DessertReleaseIndependentSdkExtension( 107 id: Int, 108 shortname: String, 109 name: String, 110 reference: String, 111 ) : SdkExtension(id, shortname, name, reference) { supersedesAndroidSdkVersionnull112 override fun supersedesAndroidSdkVersion(androidSdkVersion: ApiVersion) = true 113 } 114 } 115