1 // Copyright 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 package org.chromium.base; 6 7 import android.content.Context; 8 import android.content.pm.ApplicationInfo; 9 import android.content.pm.PackageInfo; 10 import android.content.pm.PackageManager; 11 import android.content.pm.PackageManager.NameNotFoundException; 12 import android.os.Build; 13 import android.os.StrictMode; 14 15 import org.chromium.base.annotations.CalledByNative; 16 17 /** 18 * BuildInfo is a utility class providing easy access to {@link PackageInfo} information. This is 19 * primarily of use for accessing package information from native code. 20 */ 21 public class BuildInfo { 22 private static final String TAG = "BuildInfo"; 23 private static final int MAX_FINGERPRINT_LENGTH = 128; 24 25 /** 26 * BuildInfo is a static utility class and therefore shouldn't be instantiated. 27 */ 28 private BuildInfo() {} 29 30 @CalledByNative 31 public static String getDevice() { 32 return Build.DEVICE; 33 } 34 35 @CalledByNative 36 public static String getBrand() { 37 return Build.BRAND; 38 } 39 40 @CalledByNative 41 public static String getAndroidBuildId() { 42 return Build.ID; 43 } 44 45 /** 46 * @return The build fingerprint for the current Android install. The value is truncated to a 47 * 128 characters as this is used for crash and UMA reporting, which should avoid huge 48 * strings. 49 */ 50 @CalledByNative 51 public static String getAndroidBuildFingerprint() { 52 return Build.FINGERPRINT.substring( 53 0, Math.min(Build.FINGERPRINT.length(), MAX_FINGERPRINT_LENGTH)); 54 } 55 56 @CalledByNative 57 public static String getDeviceManufacturer() { 58 return Build.MANUFACTURER; 59 } 60 61 @CalledByNative 62 public static String getDeviceModel() { 63 return Build.MODEL; 64 } 65 66 @CalledByNative 67 public static String getGMSVersionCode(Context context) { 68 String msg = "gms versionCode not available."; 69 try { 70 PackageManager packageManager = context.getPackageManager(); 71 PackageInfo packageInfo = packageManager.getPackageInfo("com.google.android.gms", 0); 72 msg = Integer.toString(packageInfo.versionCode); 73 } catch (NameNotFoundException e) { 74 Log.d(TAG, "GMS package is not found.", e); 75 } 76 return msg; 77 } 78 79 @CalledByNative 80 public static String getPackageVersionCode(Context context) { 81 String msg = "versionCode not available."; 82 try { 83 PackageManager pm = context.getPackageManager(); 84 PackageInfo pi = pm.getPackageInfo(context.getPackageName(), 0); 85 msg = ""; 86 if (pi.versionCode > 0) { 87 msg = Integer.toString(pi.versionCode); 88 } 89 } catch (NameNotFoundException e) { 90 Log.d(TAG, msg); 91 } 92 return msg; 93 } 94 95 @CalledByNative 96 public static String getPackageVersionName(Context context) { 97 String msg = "versionName not available"; 98 try { 99 PackageManager pm = context.getPackageManager(); 100 PackageInfo pi = pm.getPackageInfo(context.getPackageName(), 0); 101 msg = ""; 102 if (pi.versionName != null) { 103 msg = pi.versionName; 104 } 105 } catch (NameNotFoundException e) { 106 Log.d(TAG, msg); 107 } 108 return msg; 109 } 110 111 @CalledByNative 112 public static String getPackageLabel(Context context) { 113 // Third-party code does disk read on the getApplicationInfo call. http://crbug.com/614343 114 StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads(); 115 try { 116 PackageManager packageManager = context.getPackageManager(); 117 ApplicationInfo appInfo = packageManager.getApplicationInfo(context.getPackageName(), 118 PackageManager.GET_META_DATA); 119 CharSequence label = packageManager.getApplicationLabel(appInfo); 120 return label != null ? label.toString() : ""; 121 } catch (NameNotFoundException e) { 122 return ""; 123 } finally { 124 StrictMode.setThreadPolicy(oldPolicy); 125 } 126 } 127 128 @CalledByNative 129 public static String getPackageName(Context context) { 130 String packageName = context != null ? context.getPackageName() : null; 131 return packageName != null ? packageName : ""; 132 } 133 134 @CalledByNative 135 public static String getBuildType() { 136 return Build.TYPE; 137 } 138 139 /** 140 * Check if this is a debuggable build of Android. Use this to enable developer-only features. 141 */ 142 public static boolean isDebugAndroid() { 143 return "eng".equals(Build.TYPE) || "userdebug".equals(Build.TYPE); 144 } 145 146 @CalledByNative 147 public static int getSdkInt() { 148 return Build.VERSION.SDK_INT; 149 } 150 151 /** 152 * @return Whether the current build version is greater than Android N. 153 */ 154 public static boolean isGreaterThanN() { 155 return Build.VERSION.SDK_INT > 24 || Build.VERSION.CODENAME.equals("NMR1"); 156 } 157 158 /** 159 * @return Whether the current device is running Android O release or newer. 160 */ 161 public static boolean isAtLeastO() { 162 return !"REL".equals(Build.VERSION.CODENAME) 163 && ("O".equals(Build.VERSION.CODENAME) || Build.VERSION.CODENAME.startsWith("OMR")); 164 } 165 166 /** 167 * @return Whether the current app targets the SDK for at least O 168 */ 169 public static boolean targetsAtLeastO(Context appContext) { 170 return isAtLeastO() 171 && appContext.getApplicationInfo().targetSdkVersion 172 == Build.VERSION_CODES.CUR_DEVELOPMENT; 173 } 174 } 175