1 /* 2 * Copyright (C) 2012 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 com.example.android.deviceconfig; 18 19 import android.annotation.SuppressLint; 20 import android.annotation.TargetApi; 21 import android.content.Context; 22 import android.content.pm.FeatureInfo; 23 import android.content.pm.PackageManager; 24 import android.content.res.Configuration; 25 import android.content.res.Resources; 26 import android.hardware.Camera; 27 import android.hardware.Camera.CameraInfo; 28 import android.os.Build; 29 import android.os.Environment; 30 import android.os.StatFs; 31 import android.util.DisplayMetrics; 32 import android.util.Log; 33 import android.view.ViewConfiguration; 34 import android.widget.Toast; 35 36 import org.w3c.dom.Document; 37 import org.w3c.dom.Element; 38 import org.w3c.dom.Text; 39 40 import java.io.BufferedReader; 41 import java.io.File; 42 import java.io.FileNotFoundException; 43 import java.io.FileOutputStream; 44 import java.io.FileReader; 45 import java.io.IOException; 46 import java.util.ArrayList; 47 import java.util.Calendar; 48 import java.util.List; 49 import java.util.Locale; 50 51 import javax.xml.XMLConstants; 52 import javax.xml.parsers.DocumentBuilderFactory; 53 import javax.xml.parsers.ParserConfigurationException; 54 import javax.xml.transform.OutputKeys; 55 import javax.xml.transform.Transformer; 56 import javax.xml.transform.TransformerConfigurationException; 57 import javax.xml.transform.TransformerException; 58 import javax.xml.transform.TransformerFactory; 59 import javax.xml.transform.TransformerFactoryConfigurationError; 60 import javax.xml.transform.dom.DOMSource; 61 import javax.xml.transform.stream.StreamResult; 62 63 public class ConfigGenerator { 64 private Context mCtx; 65 private String mExtensions; 66 67 public static final String NS_DEVICES_XSD = "http://schemas.android.com/sdk/devices/1"; 68 69 /** 70 * The "devices" element is the root element of this schema. 71 * 72 * It must contain one or more "device" elements that each define the 73 * hardware, software, and states for a given device. 74 */ 75 public static final String NODE_DEVICES = "devices"; 76 77 /** 78 * A "device" element contains a "hardware" element, a "software" element 79 * for each API version it supports, and a "state" element for each possible 80 * state the device could be in. 81 */ 82 public static final String NODE_DEVICE = "device"; 83 84 /** 85 * The "hardware" element contains all of the hardware information for a 86 * given device. 87 */ 88 public static final String NODE_HARDWARE = "hardware"; 89 90 /** 91 * The "software" element contains all of the software information for an 92 * API version of the given device. 93 */ 94 public static final String NODE_SOFTWARE = "software"; 95 96 /** 97 * The "state" element contains all of the parameters for a given state of 98 * the device. It's also capable of redefining hardware configurations if 99 * they change based on state. 100 */ 101 102 public static final String NODE_STATE = "state"; 103 104 public static final String NODE_KEYBOARD = "keyboard"; 105 public static final String NODE_TOUCH = "touch"; 106 public static final String NODE_GL_EXTENSIONS = "gl-extensions"; 107 public static final String NODE_GL_VERSION = "gl-version"; 108 public static final String NODE_NETWORKING = "networking"; 109 public static final String NODE_REMOVABLE_STORAGE = "removable-storage"; 110 public static final String NODE_FLASH = "flash"; 111 public static final String NODE_LIVE_WALLPAPER_SUPPORT = "live-wallpaper-support"; 112 public static final String NODE_BUTTONS = "buttons"; 113 public static final String NODE_CAMERA = "camera"; 114 public static final String NODE_LOCATION = "location"; 115 public static final String NODE_GPU = "gpu"; 116 public static final String NODE_DOCK = "dock"; 117 public static final String NODE_YDPI = "ydpi"; 118 public static final String NODE_POWER_TYPE = "power-type"; 119 public static final String NODE_Y_DIMENSION = "y-dimension"; 120 public static final String NODE_SCREEN_RATIO = "screen-ratio"; 121 public static final String NODE_NAV_STATE = "nav-state"; 122 public static final String NODE_MIC = "mic"; 123 public static final String NODE_RAM = "ram"; 124 public static final String NODE_XDPI = "xdpi"; 125 public static final String NODE_DIMENSIONS = "dimensions"; 126 public static final String NODE_ABI = "abi"; 127 public static final String NODE_MECHANISM = "mechanism"; 128 public static final String NODE_MULTITOUCH = "multitouch"; 129 public static final String NODE_NAV = "nav"; 130 public static final String NODE_PIXEL_DENSITY = "pixel-density"; 131 public static final String NODE_SCREEN_ORIENTATION = "screen-orientation"; 132 public static final String NODE_AUTOFOCUS = "autofocus"; 133 public static final String NODE_SCREEN_SIZE = "screen-size"; 134 public static final String NODE_DESCRIPTION = "description"; 135 public static final String NODE_BLUETOOTH_PROFILES = "bluetooth-profiles"; 136 public static final String NODE_SCREEN = "screen"; 137 public static final String NODE_SENSORS = "sensors"; 138 public static final String NODE_DIAGONAL_LENGTH = "diagonal-length"; 139 public static final String NODE_SCREEN_TYPE = "screen-type"; 140 public static final String NODE_KEYBOARD_STATE = "keyboard-state"; 141 public static final String NODE_X_DIMENSION = "x-dimension"; 142 public static final String NODE_CPU = "cpu"; 143 public static final String NODE_INTERNAL_STORAGE = "internal-storage"; 144 public static final String NODE_NAME = "name"; 145 public static final String NODE_MANUFACTURER = "manufacturer"; 146 public static final String NODE_API_LEVEL = "api-level"; 147 public static final String ATTR_DEFAULT = "default"; 148 public static final String ATTR_UNIT = "unit"; 149 public static final String UNIT_BYTES = "B"; 150 public static final String UNIT_KIBIBYTES = "KiB"; 151 public static final String UNIT_MEBIBYTES = "MiB"; 152 public static final String UNIT_GIBIBYTES = "GiB"; 153 public static final String UNIT_TEBIBYTES = "TiB"; 154 public static final String LOCAL_NS = "d"; 155 public static final String PREFIX = LOCAL_NS + ":"; 156 157 private static final String TAG = "ConfigGenerator"; 158 159 public ConfigGenerator(Context context, String extensions) { 160 mCtx = context; 161 mExtensions = extensions; 162 } 163 164 @SuppressLint("WorldReadableFiles") 165 public String generateConfig() { 166 Resources resources = mCtx.getResources(); 167 PackageManager packageMgr = mCtx.getPackageManager(); 168 DisplayMetrics metrics = resources.getDisplayMetrics(); 169 Configuration config = resources.getConfiguration(); 170 171 try { 172 Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument(); 173 174 Element devices = doc.createElement(PREFIX + NODE_DEVICES); 175 devices.setAttribute(XMLConstants.XMLNS_ATTRIBUTE + ":xsi", 176 XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI); 177 devices.setAttribute(XMLConstants.XMLNS_ATTRIBUTE + ":" + LOCAL_NS, NS_DEVICES_XSD); 178 doc.appendChild(devices); 179 180 Element device = doc.createElement(PREFIX + NODE_DEVICE); 181 devices.appendChild(device); 182 183 Element name = doc.createElement(PREFIX + NODE_NAME); 184 device.appendChild(name); 185 name.appendChild(doc.createTextNode(android.os.Build.MODEL)); 186 Element manufacturer = doc.createElement(PREFIX + NODE_MANUFACTURER); 187 device.appendChild(manufacturer); 188 manufacturer.appendChild(doc.createTextNode(android.os.Build.MANUFACTURER)); 189 190 Element hardware = doc.createElement(PREFIX + NODE_HARDWARE); 191 device.appendChild(hardware); 192 193 Element screen = doc.createElement(PREFIX + NODE_SCREEN); 194 hardware.appendChild(screen); 195 196 Element screenSize = doc.createElement(PREFIX + NODE_SCREEN_SIZE); 197 screen.appendChild(screenSize); 198 Text screenSizeText; 199 switch (config.screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) { 200 case Configuration.SCREENLAYOUT_SIZE_SMALL: 201 screenSizeText = doc.createTextNode("small"); 202 break; 203 case Configuration.SCREENLAYOUT_SIZE_NORMAL: 204 screenSizeText = doc.createTextNode("normal"); 205 break; 206 case Configuration.SCREENLAYOUT_SIZE_LARGE: 207 screenSizeText = doc.createTextNode("large"); 208 break; 209 case Configuration.SCREENLAYOUT_SIZE_XLARGE: 210 screenSizeText = doc.createTextNode("xlarge"); 211 break; 212 default: 213 screenSizeText = doc.createTextNode(" "); 214 break; 215 } 216 screenSize.appendChild(screenSizeText); 217 218 Element diagonalLength = doc.createElement(PREFIX + NODE_DIAGONAL_LENGTH); 219 screen.appendChild(diagonalLength); 220 double xin = metrics.widthPixels / metrics.xdpi; 221 double yin = metrics.heightPixels / metrics.ydpi; 222 double diag = Math.sqrt(Math.pow(xin, 2) + Math.pow(yin, 2)); 223 diagonalLength.appendChild(doc.createTextNode( 224 String.format(Locale.US, "%1$.2f", diag))); 225 226 Element pixelDensity = doc.createElement(PREFIX + NODE_PIXEL_DENSITY); 227 screen.appendChild(pixelDensity); 228 Text pixelDensityText; 229 switch (metrics.densityDpi) { 230 case DisplayMetrics.DENSITY_LOW: 231 pixelDensityText = doc.createTextNode("ldpi"); 232 break; 233 case DisplayMetrics.DENSITY_MEDIUM: 234 pixelDensityText = doc.createTextNode("mdpi"); 235 break; 236 case DisplayMetrics.DENSITY_TV: 237 pixelDensityText = doc.createTextNode("tvdpi"); 238 break; 239 case DisplayMetrics.DENSITY_HIGH: 240 pixelDensityText = doc.createTextNode("hdpi"); 241 break; 242 case DisplayMetrics.DENSITY_XHIGH: 243 pixelDensityText = doc.createTextNode("xhdpi"); 244 break; 245 default: 246 pixelDensityText = doc.createTextNode(" "); 247 } 248 pixelDensity.appendChild(pixelDensityText); 249 250 Element screenRatio = doc.createElement(PREFIX + NODE_SCREEN_RATIO); 251 screen.appendChild(screenRatio); 252 Text screenRatioText; 253 switch (config.screenLayout & Configuration.SCREENLAYOUT_LONG_MASK) { 254 case Configuration.SCREENLAYOUT_LONG_YES: 255 screenRatioText = doc.createTextNode("long"); 256 break; 257 case Configuration.SCREENLAYOUT_LONG_NO: 258 screenRatioText = doc.createTextNode("notlong"); 259 break; 260 default: 261 screenRatioText = doc.createTextNode(" "); 262 break; 263 } 264 screenRatio.appendChild(screenRatioText); 265 266 Element dimensions = doc.createElement(PREFIX + NODE_DIMENSIONS); 267 screen.appendChild(dimensions); 268 269 Element xDimension = doc.createElement(PREFIX + NODE_X_DIMENSION); 270 dimensions.appendChild(xDimension); 271 xDimension.appendChild(doc.createTextNode(Integer.toString(metrics.widthPixels))); 272 273 Element yDimension = doc.createElement(PREFIX + NODE_Y_DIMENSION); 274 dimensions.appendChild(yDimension); 275 yDimension.appendChild(doc.createTextNode(Integer.toString(metrics.heightPixels))); 276 277 Element xdpi = doc.createElement(PREFIX + NODE_XDPI); 278 screen.appendChild(xdpi); 279 xdpi.appendChild(doc.createTextNode(Double.toString(metrics.xdpi))); 280 281 Element ydpi = doc.createElement(PREFIX + NODE_YDPI); 282 screen.appendChild(ydpi); 283 ydpi.appendChild(doc.createTextNode(Double.toString(metrics.ydpi))); 284 285 Element touch = doc.createElement(PREFIX + NODE_TOUCH); 286 screen.appendChild(touch); 287 288 Element multitouch = doc.createElement(PREFIX + NODE_MULTITOUCH); 289 touch.appendChild(multitouch); 290 Text multitouchText; 291 if (packageMgr 292 .hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN_MULTITOUCH_JAZZHAND)) { 293 multitouchText = doc.createTextNode("jazz-hands"); 294 } else if (packageMgr 295 .hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN_MULTITOUCH_DISTINCT)) { 296 multitouchText = doc.createTextNode("distinct"); 297 } else if (packageMgr.hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN_MULTITOUCH)) { 298 multitouchText = doc.createTextNode("basic"); 299 } else { 300 multitouchText = doc.createTextNode("none"); 301 } 302 multitouch.appendChild(multitouchText); 303 304 Element mechanism = doc.createElement(PREFIX + NODE_MECHANISM); 305 touch.appendChild(mechanism); 306 Text mechanismText; 307 switch (config.touchscreen) { 308 case Configuration.TOUCHSCREEN_STYLUS: 309 mechanismText = doc.createTextNode("stylus"); 310 case Configuration.TOUCHSCREEN_FINGER: 311 mechanismText = doc.createTextNode("finger"); 312 case Configuration.TOUCHSCREEN_NOTOUCH: 313 mechanismText = doc.createTextNode("notouch"); 314 default: 315 mechanismText = doc.createTextNode(" "); 316 } 317 mechanism.appendChild(mechanismText); 318 319 // Create an empty place holder node for screen-type since we can't 320 // actually determine it 321 322 Element screenType = doc.createElement(PREFIX + NODE_SCREEN_TYPE); 323 touch.appendChild(screenType); 324 screenType.appendChild(doc.createTextNode(" ")); 325 326 Element networking = doc.createElement(PREFIX + NODE_NETWORKING); 327 hardware.appendChild(networking); 328 Text networkingText = doc.createTextNode(""); 329 networking.appendChild(networkingText); 330 if (packageMgr.hasSystemFeature(PackageManager.FEATURE_WIFI)) { 331 networkingText.appendData("\nWifi"); 332 } 333 if (packageMgr.hasSystemFeature(PackageManager.FEATURE_BLUETOOTH)) { 334 networkingText.appendData("\nBluetooth"); 335 } 336 if (packageMgr.hasSystemFeature(PackageManager.FEATURE_NFC)) { 337 networkingText.appendData("\nNFC"); 338 } 339 340 Element sensors = doc.createElement(PREFIX + NODE_SENSORS); 341 hardware.appendChild(sensors); 342 Text sensorsText = doc.createTextNode(""); 343 sensors.appendChild(sensorsText); 344 if (packageMgr.hasSystemFeature(PackageManager.FEATURE_SENSOR_ACCELEROMETER)) { 345 sensorsText.appendData("\nAccelerometer"); 346 } 347 if (packageMgr.hasSystemFeature(PackageManager.FEATURE_SENSOR_BAROMETER)) { 348 sensorsText.appendData("\nBarometer"); 349 } 350 if (packageMgr.hasSystemFeature(PackageManager.FEATURE_SENSOR_COMPASS)) { 351 sensorsText.appendData("\nCompass"); 352 } 353 if (packageMgr.hasSystemFeature(PackageManager.FEATURE_LOCATION_GPS)) { 354 sensorsText.appendData("\nGPS"); 355 } 356 if (packageMgr.hasSystemFeature(PackageManager.FEATURE_SENSOR_GYROSCOPE)) { 357 sensorsText.appendData("\nGyroscope"); 358 } 359 if (packageMgr.hasSystemFeature(PackageManager.FEATURE_SENSOR_LIGHT)) { 360 sensorsText.appendData("\nLightSensor"); 361 } 362 if (packageMgr.hasSystemFeature(PackageManager.FEATURE_SENSOR_PROXIMITY)) { 363 sensorsText.appendData("\nProximitySensor"); 364 } 365 366 Element mic = doc.createElement(PREFIX + NODE_MIC); 367 hardware.appendChild(mic); 368 Text micText; 369 if (packageMgr.hasSystemFeature(PackageManager.FEATURE_MICROPHONE)) { 370 micText = doc.createTextNode("true"); 371 } else { 372 micText = doc.createTextNode("false"); 373 } 374 mic.appendChild(micText); 375 376 if (android.os.Build.VERSION.SDK_INT >= 9){ 377 List<Element> cameras = getCameraElements(doc); 378 for (Element cam : cameras){ 379 hardware.appendChild(cam); 380 } 381 } else { 382 Camera c = Camera.open(); 383 Element camera = doc.createElement(PREFIX + NODE_CAMERA); 384 hardware.appendChild(camera); 385 Element location = doc.createElement(PREFIX + NODE_LOCATION); 386 camera.appendChild(location); 387 // All camera's before API 9 were on the back 388 location.appendChild(doc.createTextNode("back")); 389 Camera.Parameters cParams = c.getParameters(); 390 Element autofocus = doc.createElement(PREFIX + NODE_AUTOFOCUS); 391 camera.appendChild(autofocus); 392 List<String> foci = cParams.getSupportedFocusModes(); 393 if (foci == null) { 394 autofocus.appendChild(doc.createTextNode(" ")); 395 } else if (foci.contains(Camera.Parameters.FOCUS_MODE_AUTO)) { 396 autofocus.appendChild(doc.createTextNode("true")); 397 } else { 398 autofocus.appendChild(doc.createTextNode("false")); 399 } 400 401 Element flash = doc.createElement(PREFIX + NODE_FLASH); 402 camera.appendChild(flash); 403 List<String> flashes = cParams.getSupportedFlashModes(); 404 if (flashes == null || !flashes.contains(Camera.Parameters.FLASH_MODE_ON)) { 405 flash.appendChild(doc.createTextNode("false")); 406 } else { 407 flash.appendChild(doc.createTextNode("true")); 408 } 409 c.release(); 410 } 411 412 413 Element keyboard = doc.createElement(PREFIX + NODE_KEYBOARD); 414 hardware.appendChild(keyboard); 415 Text keyboardText; 416 switch (config.keyboard) { 417 case Configuration.KEYBOARD_NOKEYS: 418 keyboardText = doc.createTextNode("nokeys"); 419 break; 420 case Configuration.KEYBOARD_12KEY: 421 keyboardText = doc.createTextNode("12key"); 422 break; 423 case Configuration.KEYBOARD_QWERTY: 424 keyboardText = doc.createTextNode("qwerty"); 425 break; 426 default: 427 keyboardText = doc.createTextNode(" "); 428 } 429 keyboard.appendChild(keyboardText); 430 431 Element nav = doc.createElement(PREFIX + NODE_NAV); 432 hardware.appendChild(nav); 433 Text navText; 434 switch (config.navigation) { 435 case Configuration.NAVIGATION_DPAD: 436 navText = doc.createTextNode("dpad"); 437 case Configuration.NAVIGATION_TRACKBALL: 438 navText = doc.createTextNode("trackball"); 439 case Configuration.NAVIGATION_WHEEL: 440 navText = doc.createTextNode("wheel"); 441 case Configuration.NAVIGATION_NONAV: 442 navText = doc.createTextNode("nonav"); 443 default: 444 navText = doc.createTextNode(" "); 445 } 446 nav.appendChild(navText); 447 448 Element ram = doc.createElement(PREFIX + NODE_RAM); 449 hardware.appendChild(ram); 450 // totalMemory given in bytes, divide by 1048576 to get RAM in MiB 451 String line; 452 long ramAmount = 0; 453 String unit = UNIT_BYTES; 454 try { 455 BufferedReader meminfo = new BufferedReader(new FileReader("/proc/meminfo")); 456 while ((line = meminfo.readLine()) != null) { 457 String[] vals = line.split("[\\s]+"); 458 if (vals[0].equals("MemTotal:")) { 459 try { 460 /* 461 * We're going to want it as a string eventually, 462 * but parsing it lets us validate it's actually a 463 * number and something strange isn't going on 464 */ 465 ramAmount = Long.parseLong(vals[1]); 466 unit = vals[2]; 467 break; 468 } catch (NumberFormatException e) { 469 // Ignore 470 } 471 } 472 } 473 meminfo.close(); 474 } catch (FileNotFoundException e) { 475 // Ignore 476 } 477 if (ramAmount > 0) { 478 if (unit.equals("B")) { 479 unit = UNIT_BYTES; 480 } else if (unit.equals("kB")) { 481 unit = UNIT_KIBIBYTES; 482 } else if (unit.equals("MB")) { 483 unit = UNIT_MEBIBYTES; 484 } else if (unit.equals("GB")) { 485 unit = UNIT_GIBIBYTES; 486 } else { 487 unit = " "; 488 } 489 } 490 ram.setAttribute(ATTR_UNIT, unit); 491 ram.appendChild(doc.createTextNode(Long.toString(ramAmount))); 492 493 Element buttons = doc.createElement(PREFIX + NODE_BUTTONS); 494 hardware.appendChild(buttons); 495 Text buttonsText; 496 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { 497 buttonsText = doc.createTextNode(getButtonsType()); 498 } else { 499 buttonsText = doc.createTextNode("hard"); 500 } 501 buttons.appendChild(buttonsText); 502 503 Element internalStorage = doc.createElement(PREFIX + NODE_INTERNAL_STORAGE); 504 hardware.appendChild(internalStorage); 505 StatFs rootStat = new StatFs(Environment.getRootDirectory().getAbsolutePath()); 506 long bytesAvailable = rootStat.getBlockSize() * rootStat.getBlockCount(); 507 long internalStorageSize = bytesAvailable / (1024 * 1024); 508 internalStorage.appendChild(doc.createTextNode(Long.toString(internalStorageSize))); 509 internalStorage.setAttribute(ATTR_UNIT, UNIT_MEBIBYTES); 510 511 Element externalStorage = doc.createElement(PREFIX + NODE_REMOVABLE_STORAGE); 512 hardware.appendChild(externalStorage); 513 externalStorage.appendChild(doc.createTextNode(" ")); 514 515 516 // Don't know CPU, GPU types 517 Element cpu = doc.createElement(PREFIX + NODE_CPU); 518 hardware.appendChild(cpu); 519 cpu.appendChild(doc.createTextNode(" ")); 520 Element gpu = doc.createElement(PREFIX + NODE_GPU); 521 hardware.appendChild(gpu); 522 gpu.appendChild(doc.createTextNode(" ")); 523 524 Element abi = doc.createElement(PREFIX + NODE_ABI); 525 hardware.appendChild(abi); 526 Text abiText = doc.createTextNode(""); 527 abi.appendChild(abiText); 528 abiText.appendData("\n" + android.os.Build.CPU_ABI); 529 abiText.appendData("\n" + android.os.Build.CPU_ABI2); 530 531 // Don't know about either the dock or plugged-in element 532 Element dock = doc.createElement(PREFIX + NODE_DOCK); 533 hardware.appendChild(dock); 534 dock.appendChild(doc.createTextNode(" ")); 535 536 Element pluggedIn = doc.createElement(PREFIX + NODE_POWER_TYPE); 537 hardware.appendChild(pluggedIn); 538 pluggedIn.appendChild(doc.createTextNode(" ")); 539 540 Element software = doc.createElement(PREFIX + NODE_SOFTWARE); 541 device.appendChild(software); 542 543 Element apiLevel = doc.createElement(PREFIX + NODE_API_LEVEL); 544 software.appendChild(apiLevel); 545 apiLevel.appendChild(doc.createTextNode(Integer 546 .toString(android.os.Build.VERSION.SDK_INT))); 547 548 Element liveWallpaperSupport = doc.createElement(PREFIX + NODE_LIVE_WALLPAPER_SUPPORT); 549 software.appendChild(liveWallpaperSupport); 550 if (packageMgr.hasSystemFeature(PackageManager.FEATURE_LIVE_WALLPAPER)) { 551 liveWallpaperSupport.appendChild(doc.createTextNode("true")); 552 } else { 553 liveWallpaperSupport.appendChild(doc.createTextNode("flase")); 554 } 555 556 Element bluetoothProfiles = doc.createElement(PREFIX + NODE_BLUETOOTH_PROFILES); 557 software.appendChild(bluetoothProfiles); 558 bluetoothProfiles.appendChild(doc.createTextNode(" ")); 559 560 Element glVersion = doc.createElement(PREFIX + NODE_GL_VERSION); 561 software.appendChild(glVersion); 562 String glVersionString = " "; 563 564 FeatureInfo[] features = packageMgr.getSystemAvailableFeatures(); 565 for (FeatureInfo feature : features) { 566 if (feature.reqGlEsVersion > 0) { 567 glVersionString = feature.getGlEsVersion(); 568 break; 569 } 570 } 571 572 glVersion.appendChild(doc.createTextNode(glVersionString)); 573 574 Element glExtensions = doc.createElement(PREFIX + NODE_GL_EXTENSIONS); 575 software.appendChild(glExtensions); 576 if (mExtensions != null && !mExtensions.trim().equals("")) { 577 glExtensions.appendChild(doc.createTextNode(mExtensions)); 578 } else { 579 glExtensions.appendChild(doc.createTextNode(" ")); 580 } 581 582 Transformer tf = TransformerFactory.newInstance().newTransformer(); 583 tf.setOutputProperty(OutputKeys.INDENT, "yes"); 584 tf.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2"); 585 DOMSource source = new DOMSource(doc); 586 String filename = String.format("devices_%1$tm_%1$td_%1$ty.xml", Calendar.getInstance() 587 .getTime()); 588 File dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS); 589 File outFile = new File(dir, filename); 590 FileOutputStream out = new FileOutputStream(new File(dir, filename)); 591 StreamResult result = new StreamResult(out); 592 tf.transform(source, result); 593 out.flush(); 594 out.close(); 595 return outFile.getAbsolutePath(); 596 } catch (ParserConfigurationException e) { 597 error("Parser config exception", e); 598 } catch (TransformerConfigurationException e) { 599 error("Transformer config exception", e); 600 } catch (TransformerFactoryConfigurationError e) { 601 error("TransformerFactory config exception", e); 602 } catch (TransformerException e) { 603 error("Error transforming", e); 604 } catch (IOException e) { 605 error("I/O Error", e); 606 } 607 return null; 608 } 609 610 @TargetApi(9) 611 private List<Element> getCameraElements(Document doc) { 612 List<Element> cList = new ArrayList<Element>(); 613 for (int i = 0; i < Camera.getNumberOfCameras(); i++) { 614 Element camera = doc.createElement(PREFIX + NODE_CAMERA); 615 cList.add(camera); 616 Element location = doc.createElement(PREFIX + NODE_LOCATION); 617 camera.appendChild(location); 618 Text locationText; 619 Camera.CameraInfo cInfo = new Camera.CameraInfo(); 620 Camera.getCameraInfo(i, cInfo); 621 if (cInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { 622 locationText = doc.createTextNode("front"); 623 } else if (cInfo.facing == CameraInfo.CAMERA_FACING_BACK) { 624 locationText = doc.createTextNode("back"); 625 } else { 626 locationText = doc.createTextNode(" "); 627 } 628 location.appendChild(locationText); 629 630 Camera c = Camera.open(i); 631 Camera.Parameters cParams = c.getParameters(); 632 633 Element autofocus = doc.createElement(PREFIX + NODE_AUTOFOCUS); 634 camera.appendChild(autofocus); 635 List<String> foci = cParams.getSupportedFocusModes(); 636 if (foci == null) { 637 autofocus.appendChild(doc.createTextNode(" ")); 638 } else if (foci.contains(Camera.Parameters.FOCUS_MODE_AUTO)) { 639 autofocus.appendChild(doc.createTextNode("true")); 640 } else { 641 autofocus.appendChild(doc.createTextNode("false")); 642 } 643 644 Element flash = doc.createElement(PREFIX + NODE_FLASH); 645 camera.appendChild(flash); 646 List<String> flashes = cParams.getSupportedFlashModes(); 647 if (flashes == null || !flashes.contains(Camera.Parameters.FLASH_MODE_ON)) { 648 flash.appendChild(doc.createTextNode("false")); 649 } else { 650 flash.appendChild(doc.createTextNode("true")); 651 } 652 c.release(); 653 } 654 return cList; 655 } 656 657 @TargetApi(14) 658 private String getButtonsType() { 659 ViewConfiguration vConfig = ViewConfiguration.get(mCtx); 660 661 if (vConfig.hasPermanentMenuKey()) { 662 return "hard"; 663 } else { 664 return "soft"; 665 } 666 } 667 668 private void error(String err, Throwable e) { 669 Toast.makeText(mCtx, "Error Generating Configuration", Toast.LENGTH_SHORT).show(); 670 Log.e(TAG, err); 671 Log.e(TAG, e.getLocalizedMessage()); 672 } 673 } 674