• 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 package android.car;
17 
18 import android.annotation.NonNull;
19 import android.annotation.Nullable;
20 import android.car.annotation.ApiRequirements;
21 import android.car.annotation.ApiRequirements.CarVersion;
22 import android.car.annotation.ApiRequirements.PlatformVersion;
23 import android.os.Parcel;
24 import android.text.TextUtils;
25 
26 import java.util.Objects;
27 
28 /**
29  * Abstraction of Android APIs.
30  *
31  * <p>This class is used to represent a pair of major / minor API versions: the "major" version
32  * represents a "traditional" Android SDK release, while the "minor" is used to indicate incremental
33  * releases for that major.
34  *
35  * <p>This class is needed because the standard Android SDK API versioning only supports major
36  * releases, but {@code Car} APIs can now (starting on
37  * {@link android.os.Build.Build.VERSION_CODES#TIRAMISU Android 13}) be updated on minor releases
38  * as well.
39  *
40  * @param <T> implementation type
41  */
42 @ApiRequirements(minCarVersion = CarVersion.TIRAMISU_1,
43         minPlatformVersion = PlatformVersion.TIRAMISU_0)
44 public abstract class ApiVersion<T extends ApiVersion<?>> {
45 
46     /**
47      * When set, it's used on {@link #toString()} - useful for versions that are pre-defined
48      * (like {@code TIRAMISU_1}).
49      */
50     @Nullable
51     private final String mVersionName;
52 
53     private final int mMajorVersion;
54     private final int mMinorVersion;
55 
ApiVersion(int majorVersion, int minorVersion)56     ApiVersion(int majorVersion, int minorVersion) {
57         this(/* name= */ null, majorVersion, minorVersion);
58     }
59 
ApiVersion(String name, int majorVersion, int minorVersion)60     ApiVersion(String name, int majorVersion, int minorVersion) {
61         mVersionName = name;
62         mMajorVersion = majorVersion;
63         mMinorVersion = minorVersion;
64     }
65 
66     /**
67      * Checks if this API version meets the required version.
68      *
69      * @param requiredApiVersionMajor Required major version number.
70      * @param requiredApiVersionMinor Required minor version number.
71      * @return {@code true} if the {@link #getMajorVersion() major version} is newer than the
72      *         {@code requiredVersion}'s major or if the {@link #getMajorVersion() major version} is
73      *         the same as {@code requiredVersion}'s major with the {@link #getMinorVersion() minor
74      *         version} the same or newer than {@code requiredVersion}'s minor.
75      * @throws IllegalArgumentException if {@code requiredVersion} is not an instance of the same
76      *         class as this object.
77      */
78     @ApiRequirements(minCarVersion = CarVersion.TIRAMISU_1,
79             minPlatformVersion = PlatformVersion.TIRAMISU_0)
isAtLeast(@onNull T requiredVersion)80     public final boolean isAtLeast(@NonNull T requiredVersion) {
81         Objects.requireNonNull(requiredVersion);
82 
83         if (!this.getClass().isInstance(requiredVersion)) {
84             throw new IllegalArgumentException("Cannot compare " + this.getClass().getName()
85                     + " against " + requiredVersion.getClass().getName());
86         }
87 
88         int requiredApiVersionMajor = requiredVersion.getMajorVersion();
89         int requiredApiVersionMinor = requiredVersion.getMinorVersion();
90 
91         return (mMajorVersion > requiredApiVersionMajor)
92                 || (mMajorVersion == requiredApiVersionMajor
93                         && mMinorVersion >= requiredApiVersionMinor);
94     }
95 
96     /**
97      * Gets the major version of the API represented by this object.
98      */
99     @ApiRequirements(minCarVersion = CarVersion.TIRAMISU_1,
100             minPlatformVersion = PlatformVersion.TIRAMISU_0)
getMajorVersion()101     public final int getMajorVersion() {
102         return mMajorVersion;
103     }
104 
105     /**
106      * Gets the minor version change of API for the same {@link #getMajorVersion()}.
107      *
108      * <p>It will reset to {@code 0} whenever {@link #getMajorVersion()} is updated
109      * and will increase by {@code 1} if car builtin or other car platform part is changed with the
110      * same {@link #getMajorVersion()}.
111      *
112      * <p>Client should check this version to use APIs which were added in a minor-only version
113      * update.
114      */
115     @ApiRequirements(minCarVersion = CarVersion.TIRAMISU_1,
116             minPlatformVersion = PlatformVersion.TIRAMISU_0)
getMinorVersion()117     public final int getMinorVersion() {
118         return mMinorVersion;
119     }
120 
121     /**
122      * @hide
123      */
124     @Override
125     @ApiRequirements(minCarVersion = CarVersion.TIRAMISU_1,
126             minPlatformVersion = PlatformVersion.TIRAMISU_0)
equals(Object obj)127     public boolean equals(Object obj) {
128         if (this == obj) return true;
129         if (obj == null) return false;
130         if (getClass() != obj.getClass()) return false;
131         @SuppressWarnings("unchecked")
132         ApiVersion<T> other = (ApiVersion<T>) obj;
133         if (mMajorVersion != other.mMajorVersion) return false;
134         if (mMinorVersion != other.mMinorVersion) return false;
135         return true;
136     }
137 
138     /**
139      * @hide
140      */
141     @Override
142     @ApiRequirements(minCarVersion = CarVersion.TIRAMISU_1,
143             minPlatformVersion = PlatformVersion.TIRAMISU_0)
hashCode()144     public int hashCode() {
145         int prime = 31;
146         int result = 1;
147         result = prime * result + mMajorVersion;
148         result = prime * result + mMinorVersion;
149         return result;
150     }
151 
152     /**
153      * @hide
154      */
155     @Override
156     @NonNull
157     @ApiRequirements(minCarVersion = CarVersion.TIRAMISU_1,
158             minPlatformVersion = PlatformVersion.TIRAMISU_0)
toString()159     public final String toString() {
160         StringBuilder builder = new StringBuilder(getClass().getSimpleName()).append('[');
161         if (!TextUtils.isEmpty(mVersionName)) {
162             builder.append("name=").append(mVersionName).append(", ");
163         }
164         return builder
165                 .append("major=").append(mMajorVersion)
166                 .append(", minor=").append(mMinorVersion)
167                 .append(']').toString();
168     }
169 
170     /**
171      * @hide
172      */
173     @ApiRequirements(minCarVersion = CarVersion.TIRAMISU_1,
174             minPlatformVersion = PlatformVersion.TIRAMISU_0)
writeToParcel(Parcel dest)175     protected void writeToParcel(Parcel dest) {
176         dest.writeString(mVersionName);
177         dest.writeInt(getMajorVersion());
178         dest.writeInt(getMinorVersion());
179     }
180 
181     /**
182      * @hide
183      */
184     @ApiRequirements(minCarVersion = CarVersion.TIRAMISU_1,
185             minPlatformVersion = PlatformVersion.TIRAMISU_0)
readFromParcel(Parcel source, ApiVersionFactory<T> factory)186     protected static <T extends ApiVersion<?>> T readFromParcel(Parcel source,
187             ApiVersionFactory<T> factory) {
188         String name = source.readString();
189         int major = source.readInt();
190         int minor = source.readInt();
191         return factory.newInstance(name, major, minor);
192     }
193 
194     /**
195      * @hide
196      */
197     interface ApiVersionFactory<T extends ApiVersion<?>> {
198         @ApiRequirements(minCarVersion = CarVersion.TIRAMISU_1,
199                 minPlatformVersion = PlatformVersion.TIRAMISU_0)
newInstance(String name, int major, int minor)200         T newInstance(String name, int major, int minor);
201     }
202 }
203