1 /*
2  * Copyright (C) 2017 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.compatibility.common.util;
18 
19 import android.os.Build;
20 
21 import java.lang.reflect.Field;
22 
23 /**
24  * Device-side compatibility utility class for reading device API level.
25  */
26 public class ApiLevelUtil {
27 
isBefore(int version)28     public static boolean isBefore(int version) {
29         return Build.VERSION.SDK_INT < version;
30     }
31 
isBefore(String version)32     public static boolean isBefore(String version) {
33         return Build.VERSION.SDK_INT < resolveVersionString(version);
34     }
35 
isAfter(int version)36     public static boolean isAfter(int version) {
37         return Build.VERSION.SDK_INT > version;
38     }
39 
isAfter(String version)40     public static boolean isAfter(String version) {
41         return Build.VERSION.SDK_INT > resolveVersionString(version);
42     }
43 
isAtLeast(int version)44     public static boolean isAtLeast(int version) {
45         return Build.VERSION.SDK_INT >= version;
46     }
47 
isAtLeast(String version)48     public static boolean isAtLeast(String version) {
49         return Build.VERSION.SDK_INT >= resolveVersionString(version);
50     }
51 
isAtMost(int version)52     public static boolean isAtMost(int version) {
53         return Build.VERSION.SDK_INT <= version;
54     }
55 
isAtMost(String version)56     public static boolean isAtMost(String version) {
57         return Build.VERSION.SDK_INT <= resolveVersionString(version);
58     }
59 
getApiLevel()60     public static int getApiLevel() {
61         return Build.VERSION.SDK_INT;
62     }
63 
codenameEquals(String name)64     public static boolean codenameEquals(String name) {
65         return Build.VERSION.CODENAME.equalsIgnoreCase(name.trim());
66     }
67 
codenameStartsWith(String prefix)68     public static boolean codenameStartsWith(String prefix) {
69         return Build.VERSION.CODENAME.startsWith(prefix);
70     }
71 
getCodename()72     public static String getCodename() {
73         return Build.VERSION.CODENAME;
74     }
75 
resolveVersionString(String versionString)76     protected static int resolveVersionString(String versionString) {
77         // Attempt 1: Parse version string as an integer, e.g. "23" for M
78         try {
79             return Integer.parseInt(versionString);
80         } catch (NumberFormatException e) { /* ignore for alternate approaches below */ }
81         // Attempt 2: Find matching field in VersionCodes utility class, return value
82         try {
83             Field versionField = VersionCodes.class.getField(versionString.toUpperCase());
84             return versionField.getInt(null); // no instance for VERSION_CODES, use null
85         } catch (IllegalAccessException | NoSuchFieldException e) { /* ignore */ }
86         // Attempt 3: Find field within android.os.Build.VERSION_CODES
87         try {
88             Field versionField = Build.VERSION_CODES.class.getField(versionString.toUpperCase());
89             return versionField.getInt(null); // no instance for VERSION_CODES, use null
90         } catch (IllegalAccessException | NoSuchFieldException e) {
91             throw new RuntimeException(
92                     String.format("Failed to parse version string %s", versionString), e);
93         }
94     }
95 }
96