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