CTS Verifier XML Reports
Bug 4878013
1. Add a version name and code to the CTS Verifier. Show the
version name on the welcome screen.
2. Share a XML report instead of a plain text report. See
TestResultsReport for the format.
Change-Id: I10d21b7ea4d468472fc15866d7259e456d6741a6
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index fddbcae..8c900e2 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -17,8 +17,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.cts.verifier"
- android:versionCode="1"
- android:versionName="1.0">
+ android:versionCode="2"
+ android:versionName="2.3_r4">
<uses-sdk android:minSdkVersion="5"></uses-sdk>
diff --git a/apps/CtsVerifier/res/layout/main.xml b/apps/CtsVerifier/res/layout/main.xml
index d6cb6cd..cdfb8f4 100644
--- a/apps/CtsVerifier/res/layout/main.xml
+++ b/apps/CtsVerifier/res/layout/main.xml
@@ -26,12 +26,21 @@
android:text="@string/continue_button_text"
/>
<TextView
- android:id="@+id/welcome_text"
+ android:id="@+id/version_text"
android:gravity="center"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_above="@+id/continue_button"
- android:padding="10dip"
+ android:paddingBottom="10dip"
+ style="@style/VersionFont"
+ />
+ <TextView
+ android:id="@+id/welcome_text"
+ android:gravity="center"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_above="@+id/version_text"
+ android:paddingTop="10dip"
android:text="@string/welcome_text"
style="@style/WelcomeFont"
/>
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index 08bd98b..f2257a2 100644
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -16,6 +16,7 @@
<resources>
<string name="app_name">CTS Verifier</string>
<string name="welcome_text">Welcome to the CTS Verifier!</string>
+ <string name="version_text">%1$s</string>
<string name="continue_button_text">Continue</string>
<string name="pass_button_text">Pass</string>
@@ -23,11 +24,7 @@
<string name="fail_button_text">Fail</string>
<!-- Strings for TestResultsReport -->
- <string name="subject_header">[CTS Verifier %1$s]</string>
- <string name="body_header">CTS Verifier %1$s Test Results</string>
- <string name="pass_result">PASS</string>
- <string name="fail_result">FAIL</string>
- <string name="not_executed_result">NOT_EXECUTED</string>
+ <string name="subject_header">CTS Verifier %1$s - %2$s</string>
<!-- Strings for TestListActivity -->
<string name="test_list_title">Manual Test List</string>
@@ -43,6 +40,7 @@
<string name="test_results_copied">Test results copied to clipboard.</string>
<string name="share">Share</string>
<string name="share_test_results">Share Test Results</string>
+ <string name="test_results_error">Couldn\'t create test results report.</string>
<!-- Strings for BluetoothActivity -->
<string name="bluetooth_test">Bluetooth Test</string>
diff --git a/apps/CtsVerifier/res/values/styles.xml b/apps/CtsVerifier/res/values/styles.xml
index c5b05cb..c7fe859 100644
--- a/apps/CtsVerifier/res/values/styles.xml
+++ b/apps/CtsVerifier/res/values/styles.xml
@@ -3,4 +3,7 @@
<style name="WelcomeFont" parent="@android:style/TextAppearance.Large">
<item name="android:textColor">#9fbf3b</item>
</style>
+ <style name="VersionFont" parent="@android:style/TextAppearance.Large">
+ <item name="android:textColor">#ffffff</item>
+ </style>
</resources>
\ No newline at end of file
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/CtsVerifierActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/CtsVerifierActivity.java
index e35674c..ee3184b 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/CtsVerifierActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/CtsVerifierActivity.java
@@ -20,8 +20,9 @@
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
-import android.view.Window;
import android.view.View.OnClickListener;
+import android.view.Window;
+import android.widget.TextView;
/** {@link Activity} that displays an introduction to the verifier. */
public class CtsVerifierActivity extends Activity {
@@ -40,6 +41,9 @@
}
};
+ TextView versionText = (TextView) findViewById(R.id.version_text);
+ versionText.setText(getString(R.string.version_text, Version.getVersionName(this)));
+
findViewById(R.id.detective_logo).setOnClickListener(clickListener);
findViewById(R.id.continue_button).setOnClickListener(clickListener);
}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/TestListActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/TestListActivity.java
index 244caab..fe41583 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/TestListActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/TestListActivity.java
@@ -22,6 +22,7 @@
import android.content.Intent;
import android.os.Bundle;
import android.text.ClipboardManager;
+import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
@@ -29,10 +30,15 @@
import android.widget.ListView;
import android.widget.Toast;
+import java.io.IOException;
+
/** {@link ListActivity} that displays a list of manual tests. */
public class TestListActivity extends ListActivity {
+ private static final String TAG = TestListActivity.class.getSimpleName();
+
private static final int LAUNCH_TEST_REQUEST_CODE = 1;
+
private TestListAdapter mAdapter;
@Override
@@ -109,19 +115,29 @@
}
private void handleCopyItemSelected() {
- TestResultsReport report = new TestResultsReport(this, mAdapter);
- ClipboardManager clipboardManager = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
- clipboardManager.setText(report.getBody());
- Toast.makeText(this, R.string.test_results_copied, Toast.LENGTH_SHORT).show();
+ try {
+ TestResultsReport report = new TestResultsReport(this, mAdapter);
+ ClipboardManager clipboardManager = (ClipboardManager)
+ getSystemService(CLIPBOARD_SERVICE);
+ clipboardManager.setText(report.getBody());
+ Toast.makeText(this, R.string.test_results_copied, Toast.LENGTH_SHORT).show();
+ } catch (IOException e) {
+ Toast.makeText(this, R.string.test_results_error, Toast.LENGTH_SHORT).show();
+ Log.e(TAG, "Coudn't copy test results report", e);
+ }
}
private void handleShareItemSelected() {
- Intent target = new Intent(Intent.ACTION_SEND);
- target.setType("text/plain");
-
- TestResultsReport report = new TestResultsReport(this, mAdapter);
- target.putExtra(Intent.EXTRA_SUBJECT, report.getSubject());
- target.putExtra(Intent.EXTRA_TEXT, report.getBody());
- startActivity(Intent.createChooser(target, getString(R.string.share_test_results)));
+ try {
+ Intent target = new Intent(Intent.ACTION_SEND);
+ TestResultsReport report = new TestResultsReport(this, mAdapter);
+ target.setType(report.getType());
+ target.putExtra(Intent.EXTRA_SUBJECT, report.getSubject());
+ target.putExtra(Intent.EXTRA_TEXT, report.getBody());
+ startActivity(Intent.createChooser(target, getString(R.string.share_test_results)));
+ } catch (IOException e) {
+ Toast.makeText(this, R.string.test_results_error, Toast.LENGTH_SHORT).show();
+ Log.e(TAG, "Coudn't share test results report", e);
+ }
}
}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/TestResultsReport.java b/apps/CtsVerifier/src/com/android/cts/verifier/TestResultsReport.java
index 18a08fe..c7af68a 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/TestResultsReport.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/TestResultsReport.java
@@ -18,90 +18,131 @@
import com.android.cts.verifier.TestListAdapter.TestListItem;
-import android.content.Context;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.os.Build;
+import org.xmlpull.v1.XmlSerializer;
-/** Plain text report of the current test results. */
+import android.content.Context;
+import android.os.Build;
+import android.util.Xml;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Locale;
+
+/**
+ * XML text report of the current test results.
+ * <p>
+ * Sample:
+ * <pre>
+ * <?xml version='1.0' encoding='utf-8' standalone='yes' ?>
+ * <test-results-report report-version="1" creation-time="Tue Jun 28 11:04:10 PDT 2011">
+ * <verifier-info version-name="2.3_r4" version-code="2" />
+ * <device-info>
+ * <build-info fingerprint="google/soju/crespo:2.3.4/GRJ22/121341:user/release-keys" />
+ * </device-info>
+ * <test-results>
+ * <test title="Audio Quality Verifier" class-name="com.android.cts.verifier.audioquality.AudioQualityVerifierActivity" result="not-executed" />
+ * <test title="Hardware/Software Feature Summary" class-name="com.android.cts.verifier.features.FeatureSummaryActivity" result="fail" />
+ * <test title="Bluetooth Test" class-name="com.android.cts.verifier.bluetooth.BluetoothTestActivity" result="fail" />
+ * <test title="SUID File Scanner" class-name="com.android.cts.verifier.suid.SuidFilesActivity" result="not-executed" />
+ * <test title="Accelerometer Test" class-name="com.android.cts.verifier.sensors.AccelerometerTestActivity" result="pass" />
+ * </test-results>
+ * </test-results-report>
+ * </pre>
+ */
class TestResultsReport {
+ /** Version of the test report. Increment whenever adding new tags and attributes. */
+ private static final int REPORT_VERSION = 1;
+
+ /** Format of the report's creation time. Maintain the same format at CTS. */
+ private static DateFormat DATE_FORMAT =
+ new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy", Locale.ENGLISH);
+
+ private static final String TEST_RESULTS_REPORT_TAG = "test-results-report";
+ private static final String VERIFIER_INFO_TAG = "verifier-info";
+ private static final String DEVICE_INFO_TAG = "device-info";
+ private static final String BUILD_INFO_TAG = "build-info";
+ private static final String TEST_RESULTS_TAG = "test-results";
+ private static final String TEST_TAG = "test";
+
private final Context mContext;
private final TestListAdapter mAdapter;
- private final String mVersionName;
-
TestResultsReport(Context context, TestListAdapter adapter) {
this.mContext = context;
this.mAdapter = adapter;
- this.mVersionName = getVersionName(context);
}
- private static String getVersionName(Context context) {
- try {
- PackageManager packageManager = context.getPackageManager();
- PackageInfo info = packageManager.getPackageInfo(context.getPackageName(), 0);
- return info.versionName;
- } catch (NameNotFoundException e) {
- throw new RuntimeException("Could not get find package information for "
- + context.getPackageName());
- }
+ String getType() {
+ return "application/xml";
}
String getSubject() {
- return new StringBuilder()
- .append(mContext.getString(R.string.subject_header, mVersionName))
- .append(' ')
- .append(Build.FINGERPRINT)
- .toString();
+ return mContext.getString(R.string.subject_header,
+ Version.getVersionName(mContext),
+ Build.FINGERPRINT);
}
- String getBody() {
- StringBuilder builder = new StringBuilder()
- .append(mContext.getString(R.string.body_header, mVersionName))
- .append("\n\n")
- .append(Build.FINGERPRINT)
- .append("\n\n");
+ String getBody() throws IllegalArgumentException, IllegalStateException, IOException {
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ XmlSerializer xml = Xml.newSerializer();
+ xml.setOutput(outputStream, "utf-8");
+ xml.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
+ xml.startDocument("utf-8", true);
+
+ xml.startTag(null, TEST_RESULTS_REPORT_TAG);
+ xml.attribute(null, "report-version", Integer.toString(REPORT_VERSION));
+ xml.attribute(null, "creation-time", DATE_FORMAT.format(new Date()));
+
+ xml.startTag(null, VERIFIER_INFO_TAG);
+ xml.attribute(null, "version-name", Version.getVersionName(mContext));
+ xml.attribute(null, "version-code", Integer.toString(Version.getVersionCode(mContext)));
+ xml.endTag(null, VERIFIER_INFO_TAG);
+
+ xml.startTag(null, DEVICE_INFO_TAG);
+ xml.startTag(null, BUILD_INFO_TAG);
+ xml.attribute(null, "fingerprint", Build.FINGERPRINT);
+ xml.endTag(null, BUILD_INFO_TAG);
+ xml.endTag(null, DEVICE_INFO_TAG);
+
+ xml.startTag(null, TEST_RESULTS_TAG);
int count = mAdapter.getCount();
for (int i = 0; i < count; i++) {
TestListItem item = mAdapter.getItem(i);
- if (!item.isTest()) {
- builder.append(item.title).append('\n');
- } else {
- builder.append(item.title)
- .append(".....")
- .append(getTestResultString(mAdapter.getTestResult(i)))
- .append('\n');
- }
-
- if (i + 1 < count && !mAdapter.getItem(i + 1).isTest()) {
- builder.append('\n');
+ if (item.isTest()) {
+ xml.startTag(null, TEST_TAG);
+ xml.attribute(null, "title", item.title);
+ xml.attribute(null, "class-name", item.className);
+ xml.attribute(null, "result", getTestResultString(mAdapter.getTestResult(i)));
+ xml.endTag(null, TEST_TAG);
}
}
- return builder.toString();
+ xml.endTag(null, TEST_RESULTS_TAG);
+
+ xml.endTag(null, TEST_RESULTS_REPORT_TAG);
+ xml.endDocument();
+
+ return outputStream.toString("utf-8");
}
private String getTestResultString(int testResult) {
- int resId = 0;
switch (testResult) {
case TestResult.TEST_RESULT_PASSED:
- resId = R.string.pass_result;
- break;
+ return "pass";
case TestResult.TEST_RESULT_FAILED:
- resId = R.string.fail_result;
- break;
+ return "fail";
case TestResult.TEST_RESULT_NOT_EXECUTED:
- resId = R.string.not_executed_result;
- break;
+ return "not-executed";
default:
throw new IllegalArgumentException("Unknown test result: " + testResult);
}
- return mContext.getString(resId);
}
}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/Version.java b/apps/CtsVerifier/src/com/android/cts/verifier/Version.java
new file mode 100644
index 0000000..e7b6121
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/Version.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.verifier;
+
+import android.content.Context;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+
+class Version {
+
+ static String getVersionName(Context context) {
+ return getPackageInfo(context).versionName;
+ }
+
+ static int getVersionCode(Context context) {
+ return getPackageInfo(context).versionCode;
+ }
+
+ static PackageInfo getPackageInfo(Context context) {
+ try {
+ PackageManager packageManager = context.getPackageManager();
+ return packageManager.getPackageInfo(context.getPackageName(), 0);
+ } catch (NameNotFoundException e) {
+ throw new RuntimeException("Could not get find package information for "
+ + context.getPackageName());
+ }
+ }
+}