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