ArrayTestListAdapter Class
I wanted to do what StreamingVideoActivity was doing with
TestListAdapter where it customized what rows were being
returned by overriding getRows.
So I moved code in TestListAdapter that scanned the
AndroidManifest to its own class called ManifestTestListAdapter.
I then extracted ArrayTestListAdapter from StreamingVideoActivity,
so you can call add(TestListItem) to build up a list of tests.
Change-Id: If3d2bacc52e19f326467a36ab55aa52c49f765cc
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/AbstractTestListActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/AbstractTestListActivity.java
index bc1931b..9b53bfd 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/AbstractTestListActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/AbstractTestListActivity.java
@@ -29,8 +29,8 @@
protected TestListAdapter mAdapter;
- protected void prepareTestListAdapter(String parent) {
- mAdapter = new TestListAdapter(this, parent);
+ protected void setTestListAdapter(TestListAdapter adapter) {
+ mAdapter = adapter;
setListAdapter(mAdapter);
mAdapter.loadTestResults();
}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/ArrayTestListAdapter.java b/apps/CtsVerifier/src/com/android/cts/verifier/ArrayTestListAdapter.java
new file mode 100644
index 0000000..29440f0
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/ArrayTestListAdapter.java
@@ -0,0 +1,45 @@
+/*
+ * 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 java.util.ArrayList;
+import java.util.List;
+
+/**
+ * {@link TestListAdapter} that works like {@link android.widget.ArrayAdapter}
+ * where items can be added by calling {@link #add(TestListItem)} repeatedly.
+ */
+public class ArrayTestListAdapter extends TestListAdapter {
+
+ private final List<TestListItem> mRows = new ArrayList<TestListItem>();
+
+ public ArrayTestListAdapter(Context context) {
+ super(context);
+ }
+
+ public void add(TestListItem item) {
+ mRows.add(item);
+ notifyDataSetChanged();
+ }
+
+ @Override
+ protected List<TestListItem> getRows() {
+ return mRows;
+ }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/ManifestTestListAdapter.java b/apps/CtsVerifier/src/com/android/cts/verifier/ManifestTestListAdapter.java
new file mode 100644
index 0000000..fdea120
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/ManifestTestListAdapter.java
@@ -0,0 +1,192 @@
+/*
+ * 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.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.os.Bundle;
+import android.widget.ListView;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * {@link TestListAdapter} that populates the {@link TestListActivity}'s {@link ListView} by
+ * reading data from the CTS Verifier's AndroidManifest.xml.
+ * <p>
+ * Making a new test activity to appear in the list requires the following steps:
+ *
+ * <ol>
+ * <li>REQUIRED: Add an activity to the AndroidManifest.xml with an intent filter with a
+ * main action and the MANUAL_TEST category.
+ * <pre>
+ * <intent-filter>
+ * <action android:name="android.intent.action.MAIN" />
+ * <category android:name="android.cts.intent.category.MANUAL_TEST" />
+ * </intent-filter>
+ * </pre>
+ * </li>
+ * <li>OPTIONAL: Add a meta data attribute to indicate what category of tests the activity
+ * should belong to. If you don't add this attribute, your test will show up in the
+ * "Other" tests category.
+ * <pre>
+ * <meta-data android:name="test_category" android:value="@string/test_category_security" />
+ * </pre>
+ * </li>
+ * <li>OPTIONAL: Add a meta data attribute to indicate whether this test has a parent test.
+ * <pre>
+ * <meta-data android:name="test_parent" android:value="com.android.cts.verifier.bluetooth.BluetoothTestActivity" />
+ * </pre>
+ * </li>
+ * </ol>
+ */
+public class ManifestTestListAdapter extends TestListAdapter {
+
+ private static final String TEST_CATEGORY_META_DATA = "test_category";
+
+ private static final String TEST_PARENT_META_DATA = "test_parent";
+
+ private Context mContext;
+
+ private String mTestParent;
+
+ public ManifestTestListAdapter(Context context, String testParent) {
+ super(context);
+ mContext = context;
+ mTestParent = testParent;
+ }
+
+ @Override
+ protected List<TestListItem> getRows() {
+
+ /*
+ * 1. Get all the tests belonging to the test parent.
+ * 2. Get all the tests keyed by their category.
+ * 3. Flatten the tests and categories into one giant list for the list view.
+ */
+
+ List<ResolveInfo> infos = getResolveInfosForParent();
+ Map<String, List<TestListItem>> testsByCategory = getTestsByCategory(infos);
+
+ List<String> testCategories = new ArrayList<String>(testsByCategory.keySet());
+ Collections.sort(testCategories);
+
+ List<TestListItem> allRows = new ArrayList<TestListItem>();
+ for (String testCategory : testCategories) {
+ allRows.add(TestListItem.newCategory(testCategory));
+
+ List<TestListItem> tests = testsByCategory.get(testCategory);
+ Collections.sort(tests, new Comparator<TestListItem>() {
+ @Override
+ public int compare(TestListItem item, TestListItem otherItem) {
+ return item.title.compareTo(otherItem.title);
+ }
+ });
+ allRows.addAll(tests);
+ }
+ return allRows;
+ }
+
+ List<ResolveInfo> getResolveInfosForParent() {
+ Intent mainIntent = new Intent(Intent.ACTION_MAIN);
+ mainIntent.addCategory(CATEGORY_MANUAL_TEST);
+
+ PackageManager packageManager = mContext.getPackageManager();
+ List<ResolveInfo> list = packageManager.queryIntentActivities(mainIntent,
+ PackageManager.GET_ACTIVITIES | PackageManager.GET_META_DATA);
+ int size = list.size();
+
+ List<ResolveInfo> matchingList = new ArrayList<ResolveInfo>();
+ for (int i = 0; i < size; i++) {
+ ResolveInfo info = list.get(i);
+ String parent = getTestParent(mContext, info.activityInfo.metaData);
+ if ((mTestParent == null && parent == null)
+ || (mTestParent != null && mTestParent.equals(parent))) {
+ matchingList.add(info);
+ }
+ }
+ return matchingList;
+ }
+
+ Map<String, List<TestListItem>> getTestsByCategory(List<ResolveInfo> list) {
+ Map<String, List<TestListItem>> testsByCategory =
+ new HashMap<String, List<TestListItem>>();
+
+ int size = list.size();
+ for (int i = 0; i < size; i++) {
+ ResolveInfo info = list.get(i);
+ String title = getTitle(mContext, info.activityInfo);
+ String testName = info.activityInfo.name;
+ Intent intent = getActivityIntent(info.activityInfo);
+ TestListItem item = TestListItem.newTest(title, testName, intent);
+
+ String testCategory = getTestCategory(mContext, info.activityInfo.metaData);
+ addTestToCategory(testsByCategory, testCategory, item);
+ }
+
+ return testsByCategory;
+ }
+
+ static String getTestCategory(Context context, Bundle metaData) {
+ String testCategory = null;
+ if (metaData != null) {
+ testCategory = metaData.getString(TEST_CATEGORY_META_DATA);
+ }
+ if (testCategory != null) {
+ return testCategory;
+ } else {
+ return context.getString(R.string.test_category_other);
+ }
+ }
+
+ static String getTestParent(Context context, Bundle metaData) {
+ return metaData != null ? metaData.getString(TEST_PARENT_META_DATA) : null;
+ }
+
+ static String getTitle(Context context, ActivityInfo activityInfo) {
+ if (activityInfo.labelRes != 0) {
+ return context.getString(activityInfo.labelRes);
+ } else {
+ return activityInfo.name;
+ }
+ }
+
+ static Intent getActivityIntent(ActivityInfo activityInfo) {
+ Intent intent = new Intent();
+ intent.setClassName(activityInfo.packageName, activityInfo.name);
+ return intent;
+ }
+
+ static void addTestToCategory(Map<String, List<TestListItem>> testsByCategory,
+ String testCategory, TestListItem item) {
+ List<TestListItem> tests;
+ if (testsByCategory.containsKey(testCategory)) {
+ tests = testsByCategory.get(testCategory);
+ } else {
+ tests = new ArrayList<TestListItem>();
+ }
+ testsByCategory.put(testCategory, tests);
+ tests.add(item);
+ }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/TestListActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/TestListActivity.java
index d407a63..f233312 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/TestListActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/TestListActivity.java
@@ -35,7 +35,7 @@
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- prepareTestListAdapter(null);
+ setTestListAdapter(new ManifestTestListAdapter(this, null));
}
@Override
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/TestListAdapter.java b/apps/CtsVerifier/src/com/android/cts/verifier/TestListAdapter.java
index 79a8b48..36b1d6a 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/TestListAdapter.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/TestListAdapter.java
@@ -19,13 +19,9 @@
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
-import android.content.pm.ActivityInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
import android.database.ContentObserver;
import android.database.Cursor;
import android.os.AsyncTask;
-import android.os.Bundle;
import android.os.Handler;
import android.view.LayoutInflater;
import android.view.View;
@@ -35,49 +31,21 @@
import android.widget.TextView;
import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
- * {@link BaseAdapter} that populates the {@link TestListActivity}'s {@link ListView}.
- * Making a new test activity to appear in the list requires the following steps:
- *
- * <ol>
- * <li>REQUIRED: Add an activity to the AndroidManifest.xml with an intent filter with a
- * main action and the MANUAL_TEST category.
- * <pre>
- * <intent-filter>
- * <action android:name="android.intent.action.MAIN" />
- * <category android:name="android.cts.intent.category.MANUAL_TEST" />
- * </intent-filter>
- * </pre>
- * </li>
- * <li>OPTIONAL: Add a meta data attribute to indicate what category of tests the activity
- * should belong to. If you don't add this attribute, your test will show up in the
- * "Other" tests category.
- * <pre>
- * <meta-data android:name="test_category" android:value="@string/test_category_security" />
- * </pre>
- * </li>
- * <li>OPTIONAL: Add a meta data attribute to indicate whether this test has a parent test.
- * <pre>
- * <meta-data android:name="test_parent" android:value="com.android.cts.verifier.bluetooth.BluetoothTestActivity" />
- * </pre>
- * </li>
- * </ol>
+ * {@link BaseAdapter} that handles loading, refreshing, and setting test
+ * results. What tests are shown can be customized by overriding
+ * {@link #getRows()}. See {@link ArrayTestListAdapter} and
+ * {@link ManifestTestListAdapter} for examples.
*/
-public class TestListAdapter extends BaseAdapter {
+public abstract class TestListAdapter extends BaseAdapter {
/** Activities implementing {@link Intent#ACTION_MAIN} and this will appear in the list. */
public static final String CATEGORY_MANUAL_TEST = "android.cts.intent.category.MANUAL_TEST";
- private static final String TEST_CATEGORY_META_DATA = "test_category";
-
- private static final String TEST_PARENT_META_DATA = "test_parent";
-
/** View type for a category of tests like "Sensors" or "Features" */
private static final int CATEGORY_HEADER_VIEW_TYPE = 0;
@@ -89,10 +57,8 @@
private final Context mContext;
- private final String mTestParent;
-
/** Immutable data of tests like the test's title and launch intent. */
- private final List<TestListItem> mRows = new ArrayList<TestListAdapter.TestListItem>();
+ private final List<TestListItem> mRows = new ArrayList<TestListItem>();
/** Mutable test results that will change as each test activity finishes. */
private final Map<String, Integer> mTestResults = new HashMap<String, Integer>();
@@ -111,9 +77,6 @@
/** Intent used to launch the activity from the list. Null for categories. */
final Intent intent;
- /** Tests within this test. For instance, the Bluetooth test contains more tests. */
- final List<TestListItem> subItems = new ArrayList<TestListItem>();
-
public static TestListItem newTest(String title, String testName, Intent intent) {
return new TestListItem(title, testName, intent);
}
@@ -135,15 +98,10 @@
boolean isTest() {
return intent != null;
}
-
- void addTestListItem(TestListItem item) {
- subItems.add(item);
- }
}
- public TestListAdapter(Context context, String testParent) {
+ public TestListAdapter(Context context) {
this.mContext = context;
- this.mTestParent = testParent;
this.mLayoutInflater =
(LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
@@ -193,117 +151,7 @@
}
}
- protected List<TestListItem> getRows() {
-
- /*
- * 1. Get all the tests belonging to the test parent.
- * 2. Get all the tests keyed by their category.
- * 3. Flatten the tests and categories into one giant list for the list view.
- */
-
- List<ResolveInfo> infos = getResolveInfosForParent();
- Map<String, List<TestListItem>> testsByCategory = getTestsByCategory(infos);
-
- List<String> testCategories = new ArrayList<String>(testsByCategory.keySet());
- Collections.sort(testCategories);
-
- List<TestListItem> allRows = new ArrayList<TestListItem>();
- for (String testCategory : testCategories) {
- allRows.add(TestListItem.newCategory(testCategory));
-
- List<TestListItem> tests = testsByCategory.get(testCategory);
- Collections.sort(tests, new Comparator<TestListItem>() {
- @Override
- public int compare(TestListItem item, TestListItem otherItem) {
- return item.title.compareTo(otherItem.title);
- }
- });
- allRows.addAll(tests);
- }
- return allRows;
- }
-
- List<ResolveInfo> getResolveInfosForParent() {
- Intent mainIntent = new Intent(Intent.ACTION_MAIN);
- mainIntent.addCategory(CATEGORY_MANUAL_TEST);
-
- PackageManager packageManager = mContext.getPackageManager();
- List<ResolveInfo> list = packageManager.queryIntentActivities(mainIntent,
- PackageManager.GET_ACTIVITIES | PackageManager.GET_META_DATA);
- int size = list.size();
-
- List<ResolveInfo> matchingList = new ArrayList<ResolveInfo>();
- for (int i = 0; i < size; i++) {
- ResolveInfo info = list.get(i);
- String parent = getTestParent(mContext, info.activityInfo.metaData);
- if ((mTestParent == null && parent == null)
- || (mTestParent != null && mTestParent.equals(parent))) {
- matchingList.add(info);
- }
- }
- return matchingList;
- }
-
- Map<String, List<TestListItem>> getTestsByCategory(List<ResolveInfo> list) {
- Map<String, List<TestListItem>> testsByCategory =
- new HashMap<String, List<TestListItem>>();
-
- int size = list.size();
- for (int i = 0; i < size; i++) {
- ResolveInfo info = list.get(i);
- String title = getTitle(mContext, info.activityInfo);
- String testName = info.activityInfo.name;
- Intent intent = getActivityIntent(info.activityInfo);
- TestListItem item = TestListItem.newTest(title, testName, intent);
-
- String testCategory = getTestCategory(mContext, info.activityInfo.metaData);
- addTestToCategory(testsByCategory, testCategory, item);
- }
-
- return testsByCategory;
- }
-
- static String getTestCategory(Context context, Bundle metaData) {
- String testCategory = null;
- if (metaData != null) {
- testCategory = metaData.getString(TEST_CATEGORY_META_DATA);
- }
- if (testCategory != null) {
- return testCategory;
- } else {
- return context.getString(R.string.test_category_other);
- }
- }
-
- static String getTestParent(Context context, Bundle metaData) {
- return metaData != null ? metaData.getString(TEST_PARENT_META_DATA) : null;
- }
-
- static String getTitle(Context context, ActivityInfo activityInfo) {
- if (activityInfo.labelRes != 0) {
- return context.getString(activityInfo.labelRes);
- } else {
- return activityInfo.name;
- }
- }
-
- static Intent getActivityIntent(ActivityInfo activityInfo) {
- Intent intent = new Intent();
- intent.setClassName(activityInfo.packageName, activityInfo.name);
- return intent;
- }
-
- static void addTestToCategory(Map<String, List<TestListItem>> testsByCategory,
- String testCategory, TestListItem item) {
- List<TestListItem> tests;
- if (testsByCategory.containsKey(testCategory)) {
- tests = testsByCategory.get(testCategory);
- } else {
- tests = new ArrayList<TestListItem>();
- }
- testsByCategory.put(testCategory, tests);
- tests.add(item);
- }
+ protected abstract List<TestListItem> getRows();
Map<String, Integer> getTestResults() {
Map<String, Integer> results = new HashMap<String, Integer>();
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BluetoothTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BluetoothTestActivity.java
index 93d2804..4ddfa51 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BluetoothTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BluetoothTestActivity.java
@@ -16,6 +16,7 @@
package com.android.cts.verifier.bluetooth;
+import com.android.cts.verifier.ManifestTestListAdapter;
import com.android.cts.verifier.PassFailButtons;
import com.android.cts.verifier.R;
@@ -33,7 +34,7 @@
setPassFailButtonClickListeners();
setInfoResources(R.string.bluetooth_test, R.string.bluetooth_test_info, -1);
- prepareTestListAdapter(getClass().getName());
+ setTestListAdapter(new ManifestTestListAdapter(this, getClass().getName()));
if (BluetoothAdapter.getDefaultAdapter() == null) {
showNoBluetoothDialog();
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/streamquality/StreamingVideoActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/streamquality/StreamingVideoActivity.java
index 8a01423..6335648 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/streamquality/StreamingVideoActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/streamquality/StreamingVideoActivity.java
@@ -16,6 +16,7 @@
package com.android.cts.verifier.streamquality;
+import com.android.cts.verifier.ArrayTestListAdapter;
import com.android.cts.verifier.PassFailButtons;
import com.android.cts.verifier.R;
import com.android.cts.verifier.TestListAdapter;
@@ -26,8 +27,6 @@
import android.os.Bundle;
import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.List;
/**
* Tests for verifying the quality of streaming videos. Plays streams of different formats over
@@ -130,42 +129,37 @@
setPassFailButtonClickListeners();
setInfoResources(R.string.streaming_video, R.string.streaming_video_info, -1);
- prepareTestListAdapter(getTestId());
getPassButton().setEnabled(false);
+ setTestListAdapter(getStreamAdapter());
}
- @Override
- protected void prepareTestListAdapter(String parent) {
- mAdapter = new TestListAdapter(this, parent) {
- @Override
- protected List<TestListItem> getRows() {
- List<TestListItem> streams = new ArrayList<TestListItem>();
- // TODO: Enable RTSP streams
- /*
- streams.add(TestListItem.newCategory("RTSP"));
- for (Stream stream : RTSP_STREAMS) {
- addStreamToTests(streams, stream);
- }
- */
+ private TestListAdapter getStreamAdapter() {
+ ArrayTestListAdapter adapter = new ArrayTestListAdapter(this);
- streams.add(TestListItem.newCategory("HTTP Progressive"));
- for (Stream stream : HTTP_STREAMS) {
- addStreamToTests(streams, stream);
- }
- return streams;
- }
- };
- setListAdapter(mAdapter);
- mAdapter.registerDataSetObserver(new DataSetObserver() {
+ // TODO: Enable RTSP streams
+ /*
+ adapter.add(TestListItem.newCategory("RTSP"));
+ for (Stream stream : RTSP_STREAMS) {
+ addStreamToTests(streams, stream);
+ }
+ */
+
+ adapter.add(TestListItem.newCategory("HTTP Progressive"));
+ for (Stream stream : HTTP_STREAMS) {
+ addStreamToTests(adapter, stream);
+ }
+
+ adapter.registerDataSetObserver(new DataSetObserver() {
@Override
public void onChanged() {
updatePassButton();
}
});
- mAdapter.loadTestResults();
+
+ return adapter;
}
- private void addStreamToTests(List<TestListItem> streams, Stream stream) {
+ private void addStreamToTests(ArrayTestListAdapter streams, Stream stream) {
Intent i = new Intent(StreamingVideoActivity.this, PlayVideoActivity.class);
i.putExtra(PlayVideoActivity.EXTRA_STREAM, stream);
streams.add(TestListItem.newTest(stream.name, PlayVideoActivity.getTestId(stream.code), i));