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