1 /* 2 * Copyright (C) 2021 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.bedstead.nene.utils; 18 19 import android.os.Build; 20 21 import java.lang.reflect.Field; 22 23 /** SDK Version checks. */ 24 public final class Versions { 25 26 /** Any version. */ 27 public static final int ANY = -1; 28 29 private static final String DEVELOPMENT_CODENAME = "S"; 30 Versions()31 private Versions() { 32 33 } 34 35 /** 36 * Throw a {@link UnsupportedOperationException} if the minimum version requirement is not met. 37 */ requireMinimumVersion(int min)38 public static void requireMinimumVersion(int min) { 39 if (!meetsSdkVersionRequirements(min, ANY)) { 40 throw new UnsupportedOperationException( 41 "Thie feature is only available on " 42 + versionToLetter(min) 43 + "+ (currently " + Build.VERSION.CODENAME + ")"); 44 } 45 } 46 versionToLetter(int version)47 private static String versionToLetter(int version) { 48 for (Field field : Build.VERSION_CODES.class.getFields()) { 49 if (!java.lang.reflect.Modifier.isStatic(field.getModifiers())) { 50 continue; 51 } 52 if (!field.getType().equals(int.class)) { 53 continue; 54 } 55 try { 56 int fieldValue = (int) field.get(null); 57 58 if (fieldValue == version) { 59 return field.getName(); 60 } 61 } catch (IllegalAccessException e) { 62 // Couldn't access this variable - ignore 63 } 64 } 65 66 throw new IllegalStateException("Could not find version with code " + version); 67 } 68 69 /** 70 * {@code true} if the minimum version requirement is met. 71 */ meetsMinimumSdkVersionRequirement(int min)72 public static boolean meetsMinimumSdkVersionRequirement(int min) { 73 return meetsSdkVersionRequirements(min, ANY); 74 } 75 76 /** 77 * {@code true} if the minimum and maximum version requirements are met. 78 * 79 * <p>Use {@link #ANY} to accept any version. 80 */ meetsSdkVersionRequirements(int min, int max)81 public static boolean meetsSdkVersionRequirements(int min, int max) { 82 if (min != ANY) { 83 if (min == Build.VERSION_CODES.CUR_DEVELOPMENT) { 84 if (!Build.VERSION.CODENAME.equals(DEVELOPMENT_CODENAME)) { 85 return false; 86 } 87 } else if (min > Build.VERSION.SDK_INT) { 88 return false; 89 } 90 } 91 92 if (max != ANY 93 && max != Build.VERSION_CODES.CUR_DEVELOPMENT 94 && max < Build.VERSION.SDK_INT) { 95 return false; 96 } 97 98 return true; 99 } 100 } 101