1 /* 2 * Copyright (C) 2008 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 android.tests.getinfo; 18 19 import android.app.Activity; 20 import android.app.ActivityManager; 21 import android.app.ActivityManager.MemoryInfo; 22 import android.app.Instrumentation; 23 import android.content.Context; 24 import android.content.Intent; 25 import android.content.pm.FeatureInfo; 26 import android.content.pm.PackageManager; 27 import android.content.res.Configuration; 28 import android.os.Build; 29 import android.os.Bundle; 30 import android.os.Environment; 31 import android.os.UserManager; 32 import android.os.SystemProperties; 33 import android.telephony.TelephonyManager; 34 import android.text.TextUtils; 35 import android.util.DisplayMetrics; 36 import android.util.Log; 37 import android.view.Display; 38 import android.view.WindowManager; 39 40 import com.android.compatibility.common.util.ShellIdentityUtils; 41 42 import java.io.IOException; 43 import java.lang.reflect.Field; 44 import java.lang.reflect.InvocationTargetException; 45 import java.lang.reflect.Method; 46 import java.util.ArrayList; 47 import java.util.Arrays; 48 import java.util.HashSet; 49 import java.util.List; 50 import java.util.Scanner; 51 import java.util.Set; 52 53 public class DeviceInfoInstrument extends Instrumentation implements DeviceInfoConstants { 54 55 private static final String TAG = "DeviceInfoInstrument"; 56 57 private static Bundle mResults = new Bundle(); 58 DeviceInfoInstrument()59 public DeviceInfoInstrument() { 60 super(); 61 } 62 63 @Override onCreate(Bundle arguments)64 public void onCreate(Bundle arguments) { 65 start(); 66 } 67 68 @Override onStart()69 public void onStart() { 70 addResult(BUILD_ID, Build.ID); 71 addResult(PRODUCT_NAME, Build.PRODUCT); 72 addResult(BUILD_DEVICE, Build.DEVICE); 73 addResult(BUILD_BOARD, Build.BOARD); 74 addResult(BUILD_MANUFACTURER, Build.MANUFACTURER); 75 addResult(BUILD_BRAND, Build.BRAND); 76 addResult(BUILD_MODEL, Build.MODEL); 77 addResult(BUILD_TYPE, Build.TYPE); 78 addResult(BUILD_FINGERPRINT, Build.FINGERPRINT); 79 addResult(BUILD_ABI, Build.CPU_ABI); 80 addResult(BUILD_ABI2, Build.CPU_ABI2); 81 addResult(BUILD_ABIS, TextUtils.join(",", Build.SUPPORTED_ABIS)); 82 addResult(BUILD_ABIS_32, TextUtils.join(",", Build.SUPPORTED_32_BIT_ABIS)); 83 addResult(BUILD_ABIS_64, TextUtils.join(",", Build.SUPPORTED_64_BIT_ABIS)); 84 addResult(SERIAL_NUMBER, Build.SERIAL); 85 86 addResult(REFERENCE_BUILD_FINGERPRINT, 87 SystemProperties.get("ro.build.reference.fingerprint", "")); 88 89 addResult(VERSION_RELEASE, Build.VERSION.RELEASE); 90 addResult(VERSION_SDK, Build.VERSION.SDK); 91 addResult(VERSION_BASE_OS, Build.VERSION.BASE_OS); 92 addResult(VERSION_SECURITY_PATCH, Build.VERSION.SECURITY_PATCH); 93 94 DisplayMetrics metrics = new DisplayMetrics(); 95 WindowManager wm = (WindowManager) getContext().getSystemService( 96 Context.WINDOW_SERVICE); 97 Display d = wm.getDefaultDisplay(); 98 d.getRealMetrics(metrics); 99 addResult(RESOLUTION, String.format("%sx%s", metrics.widthPixels, metrics.heightPixels)); 100 addResult(SCREEN_DENSITY, metrics.density); 101 addResult(SCREEN_X_DENSITY, metrics.xdpi); 102 addResult(SCREEN_Y_DENSITY, metrics.ydpi); 103 104 String screenDensityBucket = getScreenDensityBucket(metrics); 105 addResult(SCREEN_DENSITY_BUCKET, screenDensityBucket); 106 107 String screenSize = getScreenSize(); 108 addResult(SCREEN_SIZE, screenSize); 109 110 Configuration configuration = getContext().getResources().getConfiguration(); 111 addResult(SMALLEST_SCREEN_WIDTH_DP, configuration.smallestScreenWidthDp); 112 113 Intent intent = new Intent(); 114 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 115 intent.setClass(this.getContext(), DeviceInfoActivity.class); 116 117 DeviceInfoActivity activity = (DeviceInfoActivity) startActivitySync(intent); 118 waitForIdleSync(); 119 activity.waitForAcitityToFinish(); 120 121 TelephonyManager tm = (TelephonyManager) getContext().getSystemService( 122 Context.TELEPHONY_SERVICE); 123 // network 124 String network = tm.getNetworkOperatorName(); 125 addResult(NETWORK, network.trim()); 126 // imei 127 String imei = ShellIdentityUtils.invokeMethodWithShellPermissions(tm, 128 (telephonyManager) -> telephonyManager.getDeviceId()); 129 addResult(IMEI, imei); 130 131 // imsi 132 String imsi = ShellIdentityUtils.invokeMethodWithShellPermissions(tm, 133 (telephonyManager) -> telephonyManager.getSubscriberId()); 134 addResult(IMSI, imsi); 135 136 // phone number 137 String phoneNumber = tm.getLine1Number(); 138 addResult(PHONE_NUMBER, phoneNumber); 139 140 // features 141 String features = getFeatures(); 142 addResult(FEATURES, features); 143 144 // processes 145 String processes = getProcesses(); 146 addResult(PROCESSES, processes); 147 148 // OpenGL ES version 149 String openGlEsVersion = getOpenGlEsVersion(); 150 addResult(OPEN_GL_ES_VERSION, openGlEsVersion); 151 152 // partitions 153 String partitions = getPartitions(); 154 addResult(PARTITIONS, partitions); 155 156 // System libraries 157 String sysLibraries = getSystemLibraries(); 158 addResult(SYS_LIBRARIES, sysLibraries); 159 160 // Storage devices 161 addResult(STORAGE_DEVICES, getStorageDevices()); 162 163 // Multi-user support 164 addResult(MULTI_USER, getMultiUserInfo()); 165 166 // Encrypted 167 addResult(ENCRYPTED, getEncrypted()); 168 169 // Memory Info 170 addResult(IS_LOW_RAM_DEVICE, isLowRamDevice()); 171 addResult(MEMORY_CLASS, getMemoryClass()); 172 addResult(LARGE_MEMORY_CLASS, getLargeMemoryClass()); 173 addResult(TOTAL_MEMORY, getTotalMemory()); 174 175 // CPU Info 176 addResult(AVAILABLE_PROCESSORS, Runtime.getRuntime().availableProcessors()); 177 178 finish(Activity.RESULT_OK, mResults); 179 } 180 181 /** 182 * Add string result. 183 * 184 * @param key the string of the key name. 185 * @param value string value. 186 */ addResult(final String key, final String value)187 static void addResult(final String key, final String value){ 188 mResults.putString(key, value); 189 } 190 191 /** 192 * Add integer result. 193 * 194 * @param key the string of the key name. 195 * @param value integer value. 196 */ addResult(final String key, final int value)197 static void addResult(final String key, final int value){ 198 mResults.putInt(key, value); 199 } 200 201 /** 202 * Add float result. 203 * 204 * @param key the string of the key name. 205 * @param value float value. 206 */ addResult(final String key, final float value)207 static void addResult(final String key, final float value){ 208 mResults.putFloat(key, value); 209 } 210 getScreenSize()211 private String getScreenSize() { 212 Configuration config = getContext().getResources().getConfiguration(); 213 int screenLayout = config.screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK; 214 String screenSize = String.format("0x%x", screenLayout); 215 switch (screenLayout) { 216 case Configuration.SCREENLAYOUT_SIZE_SMALL: 217 screenSize = "small"; 218 break; 219 220 case Configuration.SCREENLAYOUT_SIZE_NORMAL: 221 screenSize = "normal"; 222 break; 223 224 case Configuration.SCREENLAYOUT_SIZE_LARGE: 225 screenSize = "large"; 226 break; 227 228 case Configuration.SCREENLAYOUT_SIZE_XLARGE: 229 screenSize = "xlarge"; 230 break; 231 232 case Configuration.SCREENLAYOUT_SIZE_UNDEFINED: 233 screenSize = "undefined"; 234 break; 235 } 236 return screenSize; 237 } 238 getScreenDensityBucket(DisplayMetrics metrics)239 private String getScreenDensityBucket(DisplayMetrics metrics) { 240 switch (metrics.densityDpi) { 241 case DisplayMetrics.DENSITY_LOW: 242 return "ldpi"; 243 244 case DisplayMetrics.DENSITY_MEDIUM: 245 return "mdpi"; 246 247 case DisplayMetrics.DENSITY_TV: 248 return "tvdpi"; 249 250 case DisplayMetrics.DENSITY_HIGH: 251 return "hdpi"; 252 253 case DisplayMetrics.DENSITY_XHIGH: 254 return "xdpi"; 255 256 default: 257 return "" + metrics.densityDpi; 258 } 259 } 260 261 /** 262 * Return a summary of the device's feature as a semi-colon-delimited list of colon separated 263 * name and availability pairs like "feature1:sdk:true;feature2:sdk:false;feature3:other:true;". 264 */ getFeatures()265 private String getFeatures() { 266 StringBuilder features = new StringBuilder(); 267 268 try { 269 Set<String> checkedFeatures = new HashSet<String>(); 270 271 PackageManager packageManager = getContext().getPackageManager(); 272 for (String featureName : getPackageManagerFeatures()) { 273 checkedFeatures.add(featureName); 274 boolean hasFeature = packageManager.hasSystemFeature(featureName); 275 addFeature(features, featureName, "sdk", hasFeature); 276 } 277 278 FeatureInfo[] featureInfos = packageManager.getSystemAvailableFeatures(); 279 if (featureInfos != null) { 280 for (FeatureInfo featureInfo : featureInfos) { 281 if (featureInfo.name != null && !checkedFeatures.contains(featureInfo.name)) { 282 addFeature(features, featureInfo.name, "other", true); 283 } 284 } 285 } 286 } catch (Exception exception) { 287 Log.e(TAG, "Error getting features: " + exception.getMessage(), exception); 288 } 289 290 return features.toString(); 291 } 292 addFeature(StringBuilder features, String name, String type, boolean available)293 private static void addFeature(StringBuilder features, String name, String type, 294 boolean available) { 295 features.append(name).append(':').append(type).append(':').append(available).append(';'); 296 } 297 298 /** 299 * Use reflection to get the features defined by the SDK. If there are features that do not fit 300 * the convention of starting with "FEATURE_" then they will still be shown under the 301 * "Other Features" section. 302 * 303 * @return list of feature names from sdk 304 */ getPackageManagerFeatures()305 private List<String> getPackageManagerFeatures() { 306 try { 307 List<String> features = new ArrayList<String>(); 308 Field[] fields = PackageManager.class.getFields(); 309 for (Field field : fields) { 310 if (field.getName().startsWith("FEATURE_")) { 311 String feature = (String) field.get(null); 312 features.add(feature); 313 } 314 } 315 return features; 316 } catch (IllegalAccessException illegalAccess) { 317 throw new RuntimeException(illegalAccess); 318 } 319 } 320 321 /** 322 * Return a semi-colon-delimited list of the root processes that were running on the phone 323 * or an error message. 324 */ getProcesses()325 private static String getProcesses() { 326 StringBuilder builder = new StringBuilder(); 327 328 try { 329 String[] rootProcesses = RootProcessScanner.getRootProcesses(); 330 for (String rootProcess : rootProcesses) { 331 builder.append(rootProcess).append(':').append(0).append(';'); 332 } 333 } catch (Exception exception) { 334 Log.e(TAG, "Error getting processes: " + exception.getMessage(), exception); 335 builder.append(exception.getMessage()); 336 } 337 338 return builder.toString(); 339 } 340 341 /** @return a string containing the Open GL ES version number or an error message */ getOpenGlEsVersion()342 private String getOpenGlEsVersion() { 343 PackageManager packageManager = getContext().getPackageManager(); 344 FeatureInfo[] featureInfos = packageManager.getSystemAvailableFeatures(); 345 if (featureInfos != null && featureInfos.length > 0) { 346 for (FeatureInfo featureInfo : featureInfos) { 347 // Null feature name means this feature is the open gl es version feature. 348 if (featureInfo.name == null) { 349 return featureInfo.getGlEsVersion(); 350 } 351 } 352 } 353 return "No feature for Open GL ES version."; 354 } 355 getPartitions()356 private String getPartitions() { 357 try { 358 StringBuilder builder = new StringBuilder(); 359 Process df = new ProcessBuilder("df").start(); 360 Scanner scanner = new Scanner(df.getInputStream()); 361 try { 362 while (scanner.hasNextLine()) { 363 builder.append(scanner.nextLine()).append(';'); 364 } 365 return builder.toString(); 366 } finally { 367 scanner.close(); 368 } 369 } catch (IOException e) { 370 return "Not able to run df for partition information."; 371 } 372 } 373 getSystemLibraries()374 private String getSystemLibraries() { 375 PackageManager pm = getContext().getPackageManager(); 376 String list[] = pm.getSystemSharedLibraryNames(); 377 378 StringBuilder builder = new StringBuilder(); 379 for (String lib : list) { 380 builder.append(lib); 381 builder.append(";"); 382 } 383 384 return builder.toString(); 385 } 386 getStorageDevices()387 private String getStorageDevices() { 388 int count = 0; 389 count = Math.max(count, getContext().getExternalCacheDirs().length); 390 count = Math.max(count, getContext().getExternalFilesDirs(null).length); 391 count = Math.max( 392 count, getContext().getExternalFilesDirs(Environment.DIRECTORY_PICTURES).length); 393 count = Math.max(count, getContext().getObbDirs().length); 394 395 if (Environment.isExternalStorageEmulated()) { 396 if (count == 1) { 397 return "1 emulated"; 398 } else { 399 return "1 emulated, " + (count - 1) + " physical media"; 400 } 401 } else { 402 return count + " physical media"; 403 } 404 } 405 getMultiUserInfo()406 private String getMultiUserInfo() { 407 try { 408 final Method method = UserManager.class.getMethod("getMaxSupportedUsers"); 409 final Integer maxUsers = (Integer) method.invoke(null); 410 if (maxUsers == 1) { 411 return "single user"; 412 } else { 413 return maxUsers + " users supported"; 414 } 415 } catch (ClassCastException e) { 416 } catch (NoSuchMethodException e) { 417 } catch (InvocationTargetException e) { 418 } catch (IllegalAccessException e) { 419 } 420 421 return "unknown"; 422 } 423 getProperty(String property)424 private static String getProperty(String property) 425 throws IOException { 426 Process process = new ProcessBuilder("getprop", property).start(); 427 Scanner scanner = null; 428 String line = ""; 429 try { 430 scanner = new Scanner(process.getInputStream()); 431 line = scanner.nextLine(); 432 } finally { 433 if (scanner != null) { 434 scanner.close(); 435 } 436 } 437 return line; 438 } 439 getEncrypted()440 private int getEncrypted() { 441 try { 442 return "encrypted".equals(getProperty("ro.crypto.state")) ? 1 : 0; 443 } catch (IOException e) { 444 } 445 446 return 0; 447 } 448 isLowRamDevice()449 private String isLowRamDevice() { 450 ActivityManager activityManager = (ActivityManager) getContext() 451 .getSystemService(Context.ACTIVITY_SERVICE); 452 return activityManager.isLowRamDevice() ? "true" : "false"; 453 } 454 getMemoryClass()455 private String getMemoryClass() { 456 ActivityManager activityManager = (ActivityManager) getContext() 457 .getSystemService(Context.ACTIVITY_SERVICE); 458 return String.valueOf(activityManager.getMemoryClass()); 459 } 460 getLargeMemoryClass()461 private String getLargeMemoryClass() { 462 ActivityManager activityManager = (ActivityManager) getContext() 463 .getSystemService(Context.ACTIVITY_SERVICE); 464 return String.valueOf(activityManager.getLargeMemoryClass()); 465 } 466 getTotalMemory()467 private String getTotalMemory() { 468 ActivityManager activityManager = (ActivityManager) getContext() 469 .getSystemService(Context.ACTIVITY_SERVICE); 470 471 MemoryInfo memoryInfo = new MemoryInfo(); 472 activityManager.getMemoryInfo(memoryInfo); 473 return String.valueOf(memoryInfo.totalMem); 474 } 475 } 476