Merge remote branch 'goog/honeycomb' into honeycomb-mr1
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index d91f312..d8dda46 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -60,6 +60,10 @@
android:resource="@xml/accessory_filter" />
</activity>
+ <activity android:name=".ReportViewerActivity"
+ android:configChanges="keyboardHidden|orientation"
+ android:label="@string/report_viewer" />
+
<provider android:name=".TestResultsProvider"
android:authorities="com.android.cts.verifier.testresultsprovider" />
@@ -165,28 +169,6 @@
<meta-data android:name="test_parent" android:value="com.android.cts.verifier.bluetooth.BluetoothTestActivity" />
</activity>
- <activity android:name=".bluetooth.ConnectionAccessServerActivity"
- android:label="@string/bt_connection_access_server"
- android:configChanges="keyboardHidden|orientation">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.cts.intent.category.MANUAL_TEST" />
- </intent-filter>
- <meta-data android:name="test_category" android:value="@string/bt_device_communication" />
- <meta-data android:name="test_parent" android:value="com.android.cts.verifier.bluetooth.BluetoothTestActivity" />
- </activity>
-
- <activity android:name=".bluetooth.ConnectionAccessClientActivity"
- android:label="@string/bt_connection_access_client"
- android:configChanges="keyboardHidden|orientation">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.cts.intent.category.MANUAL_TEST" />
- </intent-filter>
- <meta-data android:name="test_category" android:value="@string/bt_device_communication" />
- <meta-data android:name="test_parent" android:value="com.android.cts.verifier.bluetooth.BluetoothTestActivity" />
- </activity>
-
<activity android:name=".bluetooth.DevicePickerActivity"
android:label="@string/bt_device_picker"
android:configChanges="keyboardHidden|orientation" />
diff --git a/apps/CtsVerifier/res/layout/report_viewer.xml b/apps/CtsVerifier/res/layout/report_viewer.xml
new file mode 100644
index 0000000..c397582
--- /dev/null
+++ b/apps/CtsVerifier/res/layout/report_viewer.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<EditText xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/report_text"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ />
diff --git a/apps/CtsVerifier/res/menu/test_list_menu.xml b/apps/CtsVerifier/res/menu/test_list_menu.xml
index 16323e9..e777791 100644
--- a/apps/CtsVerifier/res/menu/test_list_menu.xml
+++ b/apps/CtsVerifier/res/menu/test_list_menu.xml
@@ -3,9 +3,9 @@
<item android:id="@+id/clear"
android:icon="@android:drawable/ic_menu_delete"
android:title="@string/clear" />
- <item android:id="@+id/copy"
- android:icon="@android:drawable/ic_menu_upload"
- android:title="@string/copy" />
+ <item android:id="@+id/view"
+ android:icon="@android:drawable/ic_menu_view"
+ android:title="@string/view" />
<item android:id="@+id/export"
android:icon="@android:drawable/ic_menu_save"
android:title="@string/export" />
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index 3af663d..63f9236 100644
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -23,9 +23,6 @@
<string name="info_button_text">Info</string>
<string name="fail_button_text">Fail</string>
- <!-- Strings for TestResultsReport -->
- <string name="subject_header">CTS Verifier %1$s - %2$s</string>
-
<!-- Strings for TestListActivity -->
<string name="test_list_title">Manual Test List</string>
<string name="test_category_audio">Audio</string>
@@ -39,13 +36,15 @@
<string name="test_category_other">Other</string>
<string name="clear">Clear</string>
<string name="test_results_cleared">Test results cleared.</string>
- <string name="copy">Copy</string>
- <string name="test_results_copied">Test results copied to clipboard.</string>
+ <string name="view">View</string>
<string name="test_results_error">Couldn\'t create test results report.</string>
<string name="export">Export</string>
<string name="no_storage">Cannot save report to external storage, see log for details.</string>
<string name="report_saved">Report saved to: %s</string>
+ <!-- Strings for ReportViewerActivity -->
+ <string name="report_viewer">Report Viewer</string>
+
<!-- Strings for BackupTestActivity -->
<string name="backup_test">Data Backup Test</string>
<string name="backup_info">This test checks that data backup and automatic restore works
@@ -93,7 +92,6 @@
<string name="da_password_quality_alphanumeric">Alphanumeric</string>
<string name="da_password_quality_numeric">Numeric</string>
<string name="da_password_quality_something">Something</string>
- <string name="da_password_quality_unspecified">Unspecified</string>
<string name="da_password_minimum_length">Minimum Password Length</string>
<string name="da_maximum_failed_passwords_for_wipe">Maximum Failed Passwords for Wipe</string>
<string name="da_maximum_time_to_lock">Maximum Time to Lock</string>
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/PassFailButtons.java b/apps/CtsVerifier/src/com/android/cts/verifier/PassFailButtons.java
index b31d6c6..9991b9d 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/PassFailButtons.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/PassFailButtons.java
@@ -83,6 +83,9 @@
* Returns a unique identifier for the test. Usually, this is just the class name.
*/
String getTestId();
+
+ /** @return null or details about the test run. */
+ String getTestDetails();
}
public static class Activity extends android.app.Activity implements PassFailActivity {
@@ -111,6 +114,11 @@
public String getTestId() {
return getClass().getName();
}
+
+ @Override
+ public String getTestDetails() {
+ return null;
+ }
}
public static class ListActivity extends android.app.ListActivity implements PassFailActivity {
@@ -139,6 +147,11 @@
public String getTestId() {
return getClass().getName();
}
+
+ @Override
+ public String getTestDetails() {
+ return null;
+ }
}
public static class TestListActivity extends AbstractTestListActivity
@@ -168,6 +181,11 @@
public String getTestId() {
return getClass().getName();
}
+
+ @Override
+ public String getTestDetails() {
+ return null;
+ }
}
private static <T extends android.app.Activity & PassFailActivity>
@@ -175,7 +193,8 @@
View.OnClickListener clickListener = new View.OnClickListener() {
@Override
public void onClick(View target) {
- setTestResultAndFinish(activity, activity.getTestId(), target);
+ setTestResultAndFinish(activity, activity.getTestId(), activity.getTestDetails(),
+ target);
}
};
@@ -278,7 +297,7 @@
/** Set the test result corresponding to the button clicked and finish the activity. */
private static void setTestResultAndFinish(android.app.Activity activity, String testId,
- View target) {
+ String testDetails, View target) {
boolean passed;
switch (target.getId()) {
case R.id.pass_button:
@@ -290,16 +309,16 @@
default:
throw new IllegalArgumentException("Unknown id: " + target.getId());
}
- setTestResultAndFinish(activity, testId, passed);
+ setTestResultAndFinish(activity, testId, testDetails, passed);
}
/** Set the test result and finish the activity. */
public static void setTestResultAndFinish(android.app.Activity activity, String testId,
- boolean passed) {
+ String testDetails, boolean passed) {
if (passed) {
- TestResult.setPassedResult(activity, testId);
+ TestResult.setPassedResult(activity, testId, testDetails);
} else {
- TestResult.setFailedResult(activity, testId);
+ TestResult.setFailedResult(activity, testId, testDetails);
}
activity.finish();
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/ReportViewerActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/ReportViewerActivity.java
new file mode 100644
index 0000000..36ec213
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/ReportViewerActivity.java
@@ -0,0 +1,42 @@
+/*
+ * 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.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.widget.TextView;
+
+public class ReportViewerActivity extends Activity {
+
+ public static final String EXTRA_REPORT_CONTENTS = "reportContents";
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.report_viewer);
+
+ Intent intent = getIntent();
+ if (intent != null) {
+ String reportContents = intent.getStringExtra(EXTRA_REPORT_CONTENTS);
+ if (reportContents != null) {
+ TextView reportText = (TextView) findViewById(R.id.report_text);
+ reportText.setText(reportContents);
+ }
+ }
+ }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/TestListActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/TestListActivity.java
index f233312..c510653 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/TestListActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/TestListActivity.java
@@ -17,8 +17,8 @@
package com.android.cts.verifier;
import android.app.ListActivity;
+import android.content.Intent;
import android.os.Bundle;
-import android.text.ClipboardManager;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
@@ -52,8 +52,8 @@
handleClearItemSelected();
return true;
- case R.id.copy:
- handleCopyItemSelected();
+ case R.id.view:
+ handleViewItemSelected();
return true;
case R.id.export:
@@ -70,13 +70,12 @@
Toast.makeText(this, R.string.test_results_cleared, Toast.LENGTH_SHORT).show();
}
- private void handleCopyItemSelected() {
+ private void handleViewItemSelected() {
try {
TestResultsReport report = new TestResultsReport(this, mAdapter);
- ClipboardManager clipboardManager = (ClipboardManager)
- getSystemService(CLIPBOARD_SERVICE);
- clipboardManager.setText(report.getContents());
- Toast.makeText(this, R.string.test_results_copied, Toast.LENGTH_SHORT).show();
+ Intent intent = new Intent(this, ReportViewerActivity.class);
+ intent.putExtra(ReportViewerActivity.EXTRA_REPORT_CONTENTS, report.getContents());
+ startActivity(intent);
} catch (IOException e) {
Toast.makeText(this, R.string.test_results_error, Toast.LENGTH_SHORT).show();
Log.e(TAG, "Couldn't copy test results report", e);
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/TestListAdapter.java b/apps/CtsVerifier/src/com/android/cts/verifier/TestListAdapter.java
index 3f84f51..52d9b32 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/TestListAdapter.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/TestListAdapter.java
@@ -63,6 +63,9 @@
/** Mutable test results that will change as each test activity finishes. */
private final Map<String, Integer> mTestResults = new HashMap<String, Integer>();
+ /** Map from test name to test details. */
+ private final Map<String, String> mTestDetails = new HashMap<String, String>();
+
private final LayoutInflater mLayoutInflater;
/** {@link ListView} row that is either a test category header or a test. */
@@ -121,15 +124,15 @@
}
public void setTestResult(TestResult testResult) {
- new SetTestResultTask(testResult.getName(), testResult.getResult()).execute();
+ new SetTestResultTask(testResult.getName(), testResult.getResult(),
+ testResult.getDetails()).execute();
}
class RefreshTestResultsTask extends AsyncTask<Void, Void, RefreshResult> {
@Override
protected RefreshResult doInBackground(Void... params) {
List<TestListItem> rows = getRows();
- Map<String, Integer> results = getTestResults();
- return new RefreshResult(rows, results);
+ return getRefreshResults(rows);
}
@Override
@@ -139,6 +142,8 @@
mRows.addAll(result.mItems);
mTestResults.clear();
mTestResults.putAll(result.mResults);
+ mTestDetails.clear();
+ mTestDetails.putAll(result.mDetails);
notifyDataSetChanged();
}
}
@@ -146,27 +151,40 @@
static class RefreshResult {
List<TestListItem> mItems;
Map<String, Integer> mResults;
+ Map<String, String> mDetails;
- RefreshResult(List<TestListItem> items, Map<String, Integer> results) {
+ RefreshResult(List<TestListItem> items, Map<String, Integer> results,
+ Map<String, String> details) {
mItems = items;
mResults = results;
+ mDetails = details;
}
}
protected abstract List<TestListItem> getRows();
- Map<String, Integer> getTestResults() {
+ static final String[] REFRESH_PROJECTION = {
+ TestResultsProvider._ID,
+ TestResultsProvider.COLUMN_TEST_NAME,
+ TestResultsProvider.COLUMN_TEST_RESULT,
+ TestResultsProvider.COLUMN_TEST_DETAILS,
+ };
+
+ RefreshResult getRefreshResults(List<TestListItem> items) {
Map<String, Integer> results = new HashMap<String, Integer>();
+ Map<String, String> details = new HashMap<String, String>();
ContentResolver resolver = mContext.getContentResolver();
Cursor cursor = null;
try {
- cursor = resolver.query(TestResultsProvider.RESULTS_CONTENT_URI,
- TestResultsProvider.ALL_COLUMNS, null, null, null);
+ cursor = resolver.query(TestResultsProvider.RESULTS_CONTENT_URI, REFRESH_PROJECTION,
+ null, null, null);
if (cursor.moveToFirst()) {
do {
String testName = cursor.getString(1);
int testResult = cursor.getInt(2);
+ String testDetails = cursor.getString(3);
results.put(testName, testResult);
+ details.put(testName, testDetails);
} while (cursor.moveToNext());
}
} finally {
@@ -174,7 +192,7 @@
cursor.close();
}
}
- return results;
+ return new RefreshResult(items, results, details);
}
class ClearTestResultsTask extends AsyncTask<Void, Void, Void> {
@@ -193,14 +211,17 @@
private final int mResult;
- SetTestResultTask(String testName, int result) {
+ private final String mDetails;
+
+ SetTestResultTask(String testName, int result, String details) {
mTestName = testName;
mResult = result;
+ mDetails = details;
}
@Override
protected Void doInBackground(Void... params) {
- TestResultsProvider.setTestResult(mContext, mTestName, mResult);
+ TestResultsProvider.setTestResult(mContext, mTestName, mResult, mDetails);
return null;
}
}
@@ -261,6 +282,13 @@
: TestResult.TEST_RESULT_NOT_EXECUTED;
}
+ public String getTestDetails(int position) {
+ TestListItem item = getItem(position);
+ return mTestDetails.containsKey(item.testName)
+ ? mTestDetails.get(item.testName)
+ : null;
+ }
+
public boolean allTestsPassed() {
for (TestListItem item : mRows) {
if (item.isTest() && (!mTestResults.containsKey(item.testName)
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/TestResult.java b/apps/CtsVerifier/src/com/android/cts/verifier/TestResult.java
index 3b42c3b..68513ac 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/TestResult.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/TestResult.java
@@ -21,8 +21,9 @@
/**
* Object representing the result of a test activity like whether it succeeded or failed.
- * Use {@link #setPassedResult(Activity, String)} or {@link #setFailedResult(Activity, String)} from
- * a test activity like you would {@link Activity#setResult(int)} so that {@link TestListActivity}
+ * Use {@link #setPassedResult(Activity, String, String)} or
+ * {@link #setFailedResult(Activity, String, String)} from a test activity like you would
+ * {@link Activity#setResult(int)} so that {@link TestListActivity}
* will persist the test result and update its adapter and thus the list view.
*/
public class TestResult {
@@ -33,25 +34,30 @@
private static final String TEST_NAME = "name";
private static final String TEST_RESULT = "result";
+ private static final String TEST_DETAILS = "details";
private final String mName;
-
private final int mResult;
+ private final String mDetails;
/** Sets the test activity's result to pass. */
- public static void setPassedResult(Activity activity, String testId) {
- activity.setResult(Activity.RESULT_OK, createResult(activity, TEST_RESULT_PASSED, testId));
+ public static void setPassedResult(Activity activity, String testId, String testDetails) {
+ activity.setResult(Activity.RESULT_OK, createResult(activity, TEST_RESULT_PASSED, testId,
+ testDetails));
}
/** Sets the test activity's result to failed. */
- public static void setFailedResult(Activity activity, String testId) {
- activity.setResult(Activity.RESULT_OK, createResult(activity, TEST_RESULT_FAILED, testId));
+ public static void setFailedResult(Activity activity, String testId, String testDetails) {
+ activity.setResult(Activity.RESULT_OK, createResult(activity, TEST_RESULT_FAILED, testId,
+ testDetails));
}
- private static Intent createResult(Activity activity, int testResult, String testName) {
+ private static Intent createResult(Activity activity, int testResult, String testName,
+ String testDetails) {
Intent data = new Intent(activity, activity.getClass());
data.putExtra(TEST_NAME, testName);
data.putExtra(TEST_RESULT, testResult);
+ data.putExtra(TEST_DETAILS, testDetails);
return data;
}
@@ -59,15 +65,17 @@
* Convert the test activity's result into a {@link TestResult}. Only meant to be used by
* {@link TestListActivity}.
*/
- public static TestResult fromActivityResult(int resultCode, Intent data) {
+ static TestResult fromActivityResult(int resultCode, Intent data) {
String name = data.getStringExtra(TEST_NAME);
int result = data.getIntExtra(TEST_RESULT, TEST_RESULT_NOT_EXECUTED);
- return new TestResult(name, result);
+ String details = data.getStringExtra(TEST_DETAILS);
+ return new TestResult(name, result, details);
}
- private TestResult(String name, int result) {
+ private TestResult(String name, int result, String details) {
this.mName = name;
this.mResult = result;
+ this.mDetails = details;
}
/** Return the name of the test like "com.android.cts.verifier.foo.FooTest" */
@@ -79,4 +87,9 @@
public int getResult() {
return mResult;
}
+
+ /** Return null or string containing test output. */
+ public String getDetails() {
+ return mDetails;
+ }
}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/TestResultsBackupHelper.java b/apps/CtsVerifier/src/com/android/cts/verifier/TestResultsBackupHelper.java
index 0966de4..e4cd24a 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/TestResultsBackupHelper.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/TestResultsBackupHelper.java
@@ -58,6 +58,7 @@
int nameIndex = cursor.getColumnIndex(TestResultsProvider.COLUMN_TEST_NAME);
int resultIndex = cursor.getColumnIndex(TestResultsProvider.COLUMN_TEST_RESULT);
int infoSeenIndex = cursor.getColumnIndex(TestResultsProvider.COLUMN_TEST_INFO_SEEN);
+ int detailsIndex = cursor.getColumnIndex(TestResultsProvider.COLUMN_TEST_DETAILS);
ByteArrayOutputStream byteOutput = new ByteArrayOutputStream();
DataOutputStream dataOutput = new DataOutputStream(byteOutput);
@@ -67,10 +68,12 @@
String name = cursor.getString(nameIndex);
int result = cursor.getInt(resultIndex);
int infoSeen = cursor.getInt(infoSeenIndex);
+ String details = cursor.getString(detailsIndex);
dataOutput.writeUTF(name);
dataOutput.writeInt(result);
dataOutput.writeInt(infoSeen);
+ dataOutput.writeUTF(details != null ? details : "");
}
byte[] rawBytes = byteOutput.toByteArray();
@@ -102,17 +105,19 @@
String name = dataInput.readUTF();
int result = dataInput.readInt();
int infoSeen = dataInput.readInt();
+ String details = dataInput.readUTF();
values[i] = new ContentValues();
values[i].put(TestResultsProvider.COLUMN_TEST_NAME, name);
values[i].put(TestResultsProvider.COLUMN_TEST_RESULT, result);
values[i].put(TestResultsProvider.COLUMN_TEST_INFO_SEEN, infoSeen);
+ values[i].put(TestResultsProvider.COLUMN_TEST_DETAILS, details);
}
ContentResolver resolver = mContext.getContentResolver();
resolver.bulkInsert(TestResultsProvider.RESULTS_CONTENT_URI, values);
} else {
- failBackupTest();
+ Log.e(TAG, "Skipping key: " + data.getKey());
}
} catch (IOException e) {
Log.e(TAG, "Couldn't restore test results...", e);
@@ -122,7 +127,7 @@
private void failBackupTest() {
TestResultsProvider.setTestResult(mContext, BackupTestActivity.class.getName(),
- TestResult.TEST_RESULT_FAILED);
+ TestResult.TEST_RESULT_FAILED, null);
}
@Override
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/TestResultsProvider.java b/apps/CtsVerifier/src/com/android/cts/verifier/TestResultsProvider.java
index cc9dc73..df05519 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/TestResultsProvider.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/TestResultsProvider.java
@@ -53,12 +53,8 @@
/** Boolean indicating whether the test info has been seen. */
static final String COLUMN_TEST_INFO_SEEN = "testinfoseen";
- static final String[] ALL_COLUMNS = {
- _ID,
- COLUMN_TEST_NAME,
- COLUMN_TEST_RESULT,
- COLUMN_TEST_INFO_SEEN,
- };
+ /** String containing the test's details. */
+ static final String COLUMN_TEST_DETAILS = "testdetails";
private static final UriMatcher URI_MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
private static final int RESULTS_ALL = 1;
@@ -87,7 +83,7 @@
private static final String DATABASE_NAME = "results.db";
- private static final int DATABASE_VERSION = 5;
+ private static final int DATABASE_VERSION = 6;
TestResultsOpenHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
@@ -99,7 +95,8 @@
+ _ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
+ COLUMN_TEST_NAME + " TEXT, "
+ COLUMN_TEST_RESULT + " INTEGER,"
- + COLUMN_TEST_INFO_SEEN + " INTEGER DEFAULT 0);");
+ + COLUMN_TEST_INFO_SEEN + " INTEGER DEFAULT 0,"
+ + COLUMN_TEST_DETAILS + " TEXT);");
}
@Override
@@ -204,10 +201,12 @@
return null;
}
- static void setTestResult(Context context, String testName, int testResult) {
+ static void setTestResult(Context context, String testName, int testResult,
+ String testDetails) {
ContentValues values = new ContentValues(2);
values.put(TestResultsProvider.COLUMN_TEST_RESULT, testResult);
values.put(TestResultsProvider.COLUMN_TEST_NAME, testName);
+ values.put(TestResultsProvider.COLUMN_TEST_DETAILS, testDetails);
ContentResolver resolver = context.getContentResolver();
int numUpdated = resolver.update(TestResultsProvider.RESULTS_CONTENT_URI, values,
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/TestResultsReport.java b/apps/CtsVerifier/src/com/android/cts/verifier/TestResultsReport.java
index efc9c85..e40b428 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/TestResultsReport.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/TestResultsReport.java
@@ -22,6 +22,7 @@
import android.content.Context;
import android.os.Build;
+import android.text.TextUtils;
import android.util.Xml;
import java.io.ByteArrayOutputStream;
@@ -55,7 +56,7 @@
class TestResultsReport {
/** Version of the test report. Increment whenever adding new tags and attributes. */
- private static final int REPORT_VERSION = 1;
+ private static final int REPORT_VERSION = 2;
/** Format of the report's creation time. Maintain the same format at CTS. */
private static DateFormat DATE_FORMAT =
@@ -67,6 +68,7 @@
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 static final String TEST_DETAILS_TAG = "details";
private final Context mContext;
@@ -105,7 +107,7 @@
xml.attribute(null, "model", Build.MODEL);
xml.attribute(null, "product", Build.PRODUCT);
xml.attribute(null, "release", Build.VERSION.RELEASE);
- xml.attribute(null, "sdk", Build.VERSION.SDK);
+ xml.attribute(null, "sdk", Integer.toString(Build.VERSION.SDK_INT));
xml.endTag(null, BUILD_INFO_TAG);
xml.endTag(null, DEVICE_INFO_TAG);
@@ -118,6 +120,14 @@
xml.attribute(null, "title", item.title);
xml.attribute(null, "class-name", item.testName);
xml.attribute(null, "result", getTestResultString(mAdapter.getTestResult(i)));
+
+ String details = mAdapter.getTestDetails(i);
+ if (!TextUtils.isEmpty(details)) {
+ xml.startTag(null, TEST_DETAILS_TAG);
+ xml.text(details);
+ xml.endTag(null, TEST_DETAILS_TAG);
+ }
+
xml.endTag(null, TEST_TAG);
}
}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/AudioQualityVerifierActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/AudioQualityVerifierActivity.java
index 7d7c16d..755b62d 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/AudioQualityVerifierActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/AudioQualityVerifierActivity.java
@@ -280,6 +280,11 @@
}
@Override
+ public String getTestDetails() {
+ return genReport();
+ }
+
+ @Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(mReceiver);
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/MessageTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/MessageTestActivity.java
index c730aed..2c6324b 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/MessageTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/MessageTestActivity.java
@@ -342,7 +342,7 @@
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
- TestResult.setFailedResult(MessageTestActivity.this, getTestId());
+ TestResult.setFailedResult(MessageTestActivity.this, getTestId(), null);
finish();
}
})
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/streamquality/PlayVideoActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/streamquality/PlayVideoActivity.java
index efd076d..2b65421 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/streamquality/PlayVideoActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/streamquality/PlayVideoActivity.java
@@ -121,7 +121,7 @@
@Override
public void onClick(DialogInterface dialog, int which) {
PassFailButtons.setTestResultAndFinish(PlayVideoActivity.this,
- getTestId(), false);
+ getTestId(), null, false);
}
})
.show();
diff --git a/tests/tests/media/src/android/media/cts/MediaPlayerTestBase.java b/tests/tests/media/src/android/media/cts/MediaPlayerTestBase.java
index 1c3b28a..08ce270 100644
--- a/tests/tests/media/src/android/media/cts/MediaPlayerTestBase.java
+++ b/tests/tests/media/src/android/media/cts/MediaPlayerTestBase.java
@@ -21,12 +21,18 @@
import android.media.MediaPlayer;
import android.test.ActivityInstrumentationTestCase2;
+import java.io.IOException;
+import java.util.logging.Logger;
+
/**
* Base class for tests which use MediaPlayer to play audio or video.
*/
public class MediaPlayerTestBase extends ActivityInstrumentationTestCase2<MediaStubActivity> {
+ private static final Logger LOG = Logger.getLogger(MediaPlayerTestBase.class.getName());
+
protected static final int SLEEP_TIME = 1000;
protected static final int LONG_SLEEP_TIME = 6000;
+ protected static final int STREAM_RETRIES = 5;
public static class Monitor {
private boolean signalled;
@@ -100,9 +106,24 @@
}
}
+ /**
+ * Play a video at a path (expected to be a streaming URL). Will retry playback 5 times before
+ * failing.
+ */
protected void playVideoTest(String path, int width, int height) throws Exception {
- mMediaPlayer.setDataSource(path);
- playLoadedVideo(width, height);
+ boolean playedSuccessfully = false;
+ for (int i = 0; i < STREAM_RETRIES; i++) {
+ try {
+ mMediaPlayer.setDataSource(path);
+ playLoadedVideo(width, height);
+ playedSuccessfully = true;
+ break;
+ } catch (PrepareFailedException e) {
+ // prepare() can fail because of network issues, so try again
+ LOG.warning("prepare() failed on try " + i + ", trying playback again");
+ }
+ }
+ assertTrue("Stream did not play successfully after all attempts", playedSuccessfully);
}
protected void playVideoTest(int resid, int width, int height) throws Exception {
@@ -131,7 +152,12 @@
return true;
}
});
- mMediaPlayer.prepare();
+ try {
+ mMediaPlayer.prepare();
+ } catch (IOException e) {
+ mMediaPlayer.reset();
+ throw new PrepareFailedException();
+ }
mOnVideoSizeChangedCalled.waitForSignal();
mMediaPlayer.start();
@@ -142,4 +168,6 @@
Thread.sleep(SLEEP_TIME);
}
}
+
+ private static class PrepareFailedException extends Exception {}
}
diff --git a/tests/tests/net/src/android/net/cts/ListeningPortsTest.java b/tests/tests/net/src/android/net/cts/ListeningPortsTest.java
index b6e6efb..5c1ba7c 100644
--- a/tests/tests/net/src/android/net/cts/ListeningPortsTest.java
+++ b/tests/tests/net/src/android/net/cts/ListeningPortsTest.java
@@ -118,13 +118,18 @@
String localAddress = fields[1];
String state = fields[3];
+ String uid = fields[7];
assertTrue(procFilePath + " should have an IP address in the second column",
isAddress(localAddress));
+ String localIp = localAddress.split(":")[0];
+ int localPort = Integer.parseInt(localAddress.split(":")[1], 16);
+
if (!isException(localAddress) && isPortListening(state, isTcp)) {
throw new ListeningPortsAssertionError(
- "Found port listening on " + localAddress + " in " + procFilePath);
+ "Found port listening on addr=" + localIp + ", port="
+ + localPort + ", UID=" + uid + " in " + procFilePath);
}
}
} catch (FileNotFoundException notFound) {
diff --git a/tests/tests/permission/src/android/permission/cts/FileSystemPermissionTest.java b/tests/tests/permission/src/android/permission/cts/FileSystemPermissionTest.java
index 3cbb362..a0757fd 100644
--- a/tests/tests/permission/src/android/permission/cts/FileSystemPermissionTest.java
+++ b/tests/tests/permission/src/android/permission/cts/FileSystemPermissionTest.java
@@ -157,7 +157,9 @@
/**
* Verify that any publicly readable directories reachable from
- * the root directory are not writable.
+ * the root directory are not writable. World writable directories
+ * are a security hole and an application should only be able to
+ * write to it's own home directory.
*
* Note: Because not all directories are readable, this is a best-effort
* test only. Writable directories within unreadable subdirectories
@@ -170,25 +172,51 @@
private static final Set<String> OTHER_RANDOM_DIRECTORIES = new HashSet<String>(
Arrays.asList(
- "/data/backup",
- "/data/secure",
- "/data/system",
- "/data/dalvik-cache",
- "/data/property",
+ "/data/anr",
"/data/app",
"/data/app-private",
- "/data/local",
- "/data/misc",
+ "/data/backup",
+ "/data/btips",
+ "/data/btips/TI",
+ "/data/btips/TI/opp",
+ "/data/dalvik-cache",
+ "/data/data/.drm",
+ "/data/data/.drm/.wmdrm",
"/data/dontpanic",
- "/data/lost+found",
"/data/drm",
"/data/drm/rights",
- "/data/data/.drm",
- "/data/data/.drm/.wmdrm"
+ "/data/dump",
+ "/data/local",
+ "/data/local/tmp/com.nuance.android.vsuite.vsuiteapp",
+ "/data/log",
+ "/data/lost+found",
+ "/data/misc",
+ "/data/misc/bluetooth",
+ "/data/misc/dhcp",
+ "/data/misc/wifi",
+ "/data/misc/wifi/sockets",
+ "/data/property",
+ "/data/secure",
+ "/data/shared",
+ "/data/system",
+ "/data/wifi",
+ "/data/wiper",
+ "/data/wpstiles",
+ "/dbdata/databases",
+ "/mnt_ext",
+ "/mnt_ext/badablk2",
+ "/mnt_ext/badablk3",
+ "/mnt_ext/cache",
+ "/mnt_ext/data"
)
);
/**
+ * Verify that directories not discoverable by
+ * testAllOtherDirectoriesNotWritable are not writable. World
+ * writable directories are a security hole and an application
+ * should only be able to write to it's own home directory.
+ *
* Because /data and /data/data are not readable, we blindly try to
* poke around in there looking for bad directories. There has to be
* a better way...