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 import android.util.Log;
15 
16 import org.chromium.base.annotations.CalledByNative;
17 
18 /**
19  * BuildInfo is a utility class providing easy access to {@link PackageInfo} information. This is
20  * primarily of use for accessing package information from native code.
21  */
22 public class BuildInfo {
23     private static final String TAG = "BuildInfo";
24     private static final int MAX_FINGERPRINT_LENGTH = 128;
25 
26     /**
27      * BuildInfo is a static utility class and therefore shouldn't be instantiated.
28      */
BuildInfo()29     private BuildInfo() {}
30 
31     @CalledByNative
getDevice()32     public static String getDevice() {
33         return Build.DEVICE;
34     }
35 
36     @CalledByNative
getBrand()37     public static String getBrand() {
38         return Build.BRAND;
39     }
40 
41     @CalledByNative
getAndroidBuildId()42     public static String getAndroidBuildId() {
43         return Build.ID;
44     }
45 
46     /**
47      * @return The build fingerprint for the current Android install.  The value is truncated to a
48      *         128 characters as this is used for crash and UMA reporting, which should avoid huge
49      *         strings.
50      */
51     @CalledByNative
getAndroidBuildFingerprint()52     public static String getAndroidBuildFingerprint() {
53         return Build.FINGERPRINT.substring(
54                 0, Math.min(Build.FINGERPRINT.length(), MAX_FINGERPRINT_LENGTH));
55     }
56 
57     @CalledByNative
getDeviceManufacturer()58     public static String getDeviceManufacturer() {
59         return Build.MANUFACTURER;
60     }
61 
62     @CalledByNative
getDeviceModel()63     public static String getDeviceModel() {
64         return Build.MODEL;
65     }
66 
67     @CalledByNative
getGMSVersionCode(Context context)68     public static String getGMSVersionCode(Context context) {
69         String msg = "gms versionCode not available.";
70         try {
71             PackageManager packageManager = context.getPackageManager();
72             PackageInfo packageInfo = packageManager.getPackageInfo("com.google.android.gms", 0);
73             msg = Integer.toString(packageInfo.versionCode);
74         } catch (NameNotFoundException e) {
75             Log.d(TAG, "GMS package is not found: %s", e);
76         }
77         return msg;
78     }
79 
80     @CalledByNative
getPackageVersionCode(Context context)81     public static String getPackageVersionCode(Context context) {
82         String msg = "versionCode not available.";
83         try {
84             PackageManager pm = context.getPackageManager();
85             PackageInfo pi = pm.getPackageInfo(context.getPackageName(), 0);
86             msg = "";
87             if (pi.versionCode > 0) {
88                 msg = Integer.toString(pi.versionCode);
89             }
90         } catch (NameNotFoundException e) {
91             Log.d(TAG, msg);
92         }
93         return msg;
94     }
95 
96     @CalledByNative
getPackageVersionName(Context context)97     public static String getPackageVersionName(Context context) {
98         String msg = "versionName not available";
99         try {
100             PackageManager pm = context.getPackageManager();
101             PackageInfo pi = pm.getPackageInfo(context.getPackageName(), 0);
102             msg = "";
103             if (pi.versionName != null) {
104                 msg = pi.versionName;
105             }
106         } catch (NameNotFoundException e) {
107             Log.d(TAG, msg);
108         }
109         return msg;
110     }
111 
112     @CalledByNative
getPackageLabel(Context context)113     public static String getPackageLabel(Context context) {
114         // Third-party code does disk read on the getApplicationInfo call. http://crbug.com/614343
115         StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
116         try {
117             PackageManager packageManager = context.getPackageManager();
118             ApplicationInfo appInfo = packageManager.getApplicationInfo(context.getPackageName(),
119                     PackageManager.GET_META_DATA);
120             CharSequence label = packageManager.getApplicationLabel(appInfo);
121             return  label != null ? label.toString() : "";
122         } catch (NameNotFoundException e) {
123             return "";
124         } finally {
125             StrictMode.setThreadPolicy(oldPolicy);
126         }
127     }
128 
129     @CalledByNative
getPackageName(Context context)130     public static String getPackageName(Context context) {
131         String packageName = context != null ? context.getPackageName() : null;
132         return packageName != null ? packageName : "";
133     }
134 
135     @CalledByNative
getBuildType()136     public static String getBuildType() {
137         return Build.TYPE;
138     }
139 
140     @CalledByNative
getSdkInt()141     public static int getSdkInt() {
142         return Build.VERSION.SDK_INT;
143     }
144 
145     /**
146      * @return Whether the current build version is greater than Android N.
147      */
isGreaterThanN()148     public static boolean isGreaterThanN() {
149         return Build.VERSION.SDK_INT > 24 || Build.VERSION.CODENAME.equals("NMR1");
150     }
151 }
152