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