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