summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkgui <kgui@google.com>2023-11-14 16:48:47 +0800
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2024-01-29 23:39:54 +0000
commit0bdb70db6eb089b27d05ef1110b5dacc4a502836 (patch)
treea80b3e0ffa8cc1b552686cb3260e5f5ffa49cd02
parent8346ee5c6c6239868f893cdb72080e55843d7904 (diff)
downloadcts-0bdb70db6eb089b27d05ef1110b5dacc4a502836.tar.gz
Support a "System" toggle in CTS-Verifier. When it's enabled:
1. camera ITS test (both folded and unfolded) is filtered to be shown in the list. 2. the test_result.xml has the "verify-system" as the suite_plan's value. More demos are in b/301678868. Bug: 301678868 Test: local built CTS-V (cherry picked from https://android-review.googlesource.com/q/commit:9ef42944abc073b3c69757ebdab26e559e6008f6) Merged-In: Ic9c945a10e50f27de6c71716ff134bf68fdee359 Change-Id: Ic9c945a10e50f27de6c71716ff134bf68fdee359
-rw-r--r--apps/CtsVerifier/res/layout/system_switch.xml32
-rw-r--r--apps/CtsVerifier/res/menu/test_list_menu.xml7
-rw-r--r--apps/CtsVerifier/res/values/strings.xml6
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/ManifestTestListAdapter.java29
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/ReportExporter.java51
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/TestListActivity.java228
6 files changed, 246 insertions, 107 deletions
diff --git a/apps/CtsVerifier/res/layout/system_switch.xml b/apps/CtsVerifier/res/layout/system_switch.xml
new file mode 100644
index 00000000000..d810f18f684
--- /dev/null
+++ b/apps/CtsVerifier/res/layout/system_switch.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2023 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.
+-->
+
+<!-- Switch button to enable verifier-system plan. -->
+<RelativeLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="match_parent"
+ android:orientation="horizontal" >
+ <Switch
+ android:id="@+id/switch_button"
+ android:text="@string/system"
+ android:textOn="@string/system_on"
+ android:textOff="@string/system_off"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_centerHorizontal="true"
+ android:layout_centerVertical="true" />
+</RelativeLayout> \ No newline at end of file
diff --git a/apps/CtsVerifier/res/menu/test_list_menu.xml b/apps/CtsVerifier/res/menu/test_list_menu.xml
index 95bfd5877e9..70982b09263 100644
--- a/apps/CtsVerifier/res/menu/test_list_menu.xml
+++ b/apps/CtsVerifier/res/menu/test_list_menu.xml
@@ -4,7 +4,12 @@
android:id="@+id/switch_item"
android:title="@string/view"
android:actionLayout="@layout/display_mode_switch"
- android:showAsAction="ifRoom" />
+ android:showAsAction="always" />
+ <item
+ android:id="@+id/system_switch_item"
+ android:title="@string/system"
+ android:actionLayout="@layout/system_switch"
+ android:showAsAction="always" />
<item android:id="@+id/clear"
android:icon="@android:drawable/ic_menu_delete"
android:title="@string/clear"
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index 790f06bf502..f9347120514 100644
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -17,7 +17,8 @@
<string name="app_name">CTS Verifier</string>
<string name="module_id">noabi CtsVerifier</string>
- <string name="title_version">CTS Verifier %1$s</string>
+ <string name="title_version">Verifier %1$s</string>
+ <string name="version_number_format">Version #: %d</string>
<string name="pass_button_text">Pass</string>
<string name="info_button_text">Info</string>
@@ -36,6 +37,9 @@
<string name="search_label">TestListActivity</string>
<string name="search_hint">Search Tests</string>
<string name="search_title">Search</string>
+ <string name="system">System</string>
+ <string name="system_on">ON</string>
+ <string name="system_off">OFF</string>
<!-- Strings for CtsReportLog warning -->
<string name="reportlog_warning_title">CTS-Verifier Report Log</string>
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/ManifestTestListAdapter.java b/apps/CtsVerifier/src/com/android/cts/verifier/ManifestTestListAdapter.java
index a6d536aeecc..e0c94ae4562 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/ManifestTestListAdapter.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/ManifestTestListAdapter.java
@@ -186,6 +186,13 @@ public class ManifestTestListAdapter extends TestListAdapter {
*/
private static final String USER_TYPE_VISIBLE_BG_USER = "visible_background_non-profile_user";
+ /** The name of the camera ITS test of a {@link TestListItem}. */
+ private static final String CAMERA_ITS_TEST =
+ "com.android.cts.verifier.camera.its.ItsTestActivity";
+
+ /** The name of the camera ITS test (folded mode) of a {@link TestListItem}. */
+ private static final String CAMERA_ITS_TEST_FOLDED = CAMERA_ITS_TEST + "[folded]";
+
private final HashSet<String> mDisabledTests;
private Context mContext;
@@ -223,8 +230,9 @@ public class ManifestTestListAdapter extends TestListAdapter {
}
}
- if (mTestFilter != null) {
- // Filter test rows dynamically when the filter is specified.
+ if (mTestFilter != null || TestListActivity.getIsSystemEnabled()) {
+ // Filter test rows dynamically when the filter is specified or verifier-system plan is
+ // enabled.
return getRowsWithDisplayMode(sCurrentDisplayMode.toString());
} else {
return mDisplayModesTests.getOrDefault(
@@ -607,6 +615,20 @@ public class ManifestTestListAdapter extends TestListAdapter {
.contains(mTestFilter.toLowerCase(Locale.getDefault()));
}
+ /**
+ * Checks whether the test matches the current status of verifier-system plan.
+ *
+ * <p>When verifier-system plan is disabled, all CTS-V tests are shown.
+ *
+ * <p>When verifier-system plan is enabled, specific tests are filtered out, e.g., camera ITS.
+ */
+ private static boolean matchSystemPlanStatus(String testName) {
+ if (testName == null || !TestListActivity.getIsSystemEnabled()) {
+ return true;
+ }
+ return !testName.equals(CAMERA_ITS_TEST) && !testName.equals(CAMERA_ITS_TEST_FOLDED);
+ }
+
private boolean isVisibleBackgroundNonProfileUser() {
if (!SdkLevel.isAtLeastU()) {
Log.d(LOG_TAG, "isVisibleBagroundNonProfileUser() returning false on pre-UDC device");
@@ -660,7 +682,8 @@ public class ManifestTestListAdapter extends TestListAdapter {
&& matchAllConfigs(mContext, test.requiredConfigs)
&& matchDisplayMode(test.displayMode, mode)
&& !matchAnyExcludedUserType(test.excludedUserTypes)
- && macthTestFilter(test.title)) {
+ && macthTestFilter(test.title)
+ && matchSystemPlanStatus(test.testName)) {
if (test.applicableFeatures == null || hasAnyFeature(test.applicableFeatures)) {
// Add suffix in test name if the test is in the folded mode.
test.testName = setTestNameSuffix(mode, test.testName);
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/ReportExporter.java b/apps/CtsVerifier/src/com/android/cts/verifier/ReportExporter.java
index f95393a3101..baa19519c26 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/ReportExporter.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/ReportExporter.java
@@ -50,9 +50,7 @@ import java.util.Locale;
import java.util.logging.Level;
import java.util.logging.Logger;
-/**
- * Background task to generate a report and save it to external storage.
- */
+/** Background task to generate a report and save it to external storage. */
public class ReportExporter extends AsyncTask<Void, Void, String> {
private static final String TAG = ReportExporter.class.getSimpleName();
private static final boolean DEBUG = true;
@@ -65,7 +63,10 @@ public class ReportExporter extends AsyncTask<Void, Void, String> {
private static final String LOG_URL = null;
private static final String REFERENCE_URL = null;
private static final String SUITE_NAME_METADATA_KEY = "SuiteName";
- private static final String SUITE_PLAN = "verifier";
+ // Default CTS-V suite_plan shown in test_result.xml.
+ private static final String DEFAULT_SUITE_PLAN = "verifier";
+ // CTS Verifier System suite_plan shown in test_result.xml.
+ private static final String SYSTEM_SUITE_PLAN = "verifier-system";
private static final String SUITE_BUILD = "0";
private static final String ZIP_EXTENSION = ".zip";
private final long START_MS = System.currentTimeMillis();
@@ -88,9 +89,10 @@ public class ReportExporter extends AsyncTask<Void, Void, String> {
}
File reportLogFolder =
- new File(Environment.getExternalStorageDirectory().getAbsolutePath()
- + File.separator
- + LOGS_DIRECTORY);
+ new File(
+ Environment.getExternalStorageDirectory().getAbsolutePath()
+ + File.separator
+ + LOGS_DIRECTORY);
copyFilesRecursively(reportLogFolder, tempDir);
}
@@ -104,10 +106,7 @@ public class ReportExporter extends AsyncTask<Void, Void, String> {
for (File file : files) {
Path src = Paths.get(file.getAbsolutePath());
- Path dest = Paths.get(
- destFolder.getAbsolutePath()
- + File.separator
- + file.getName());
+ Path dest = Paths.get(destFolder.getAbsolutePath() + File.separator + file.getName());
try {
Files.copy(src, dest, StandardCopyOption.REPLACE_EXISTING);
} catch (IOException ex) {
@@ -119,7 +118,6 @@ public class ReportExporter extends AsyncTask<Void, Void, String> {
}
}
-
@Override
protected String doInBackground(Void... params) {
if (!Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
@@ -148,15 +146,24 @@ public class ReportExporter extends AsyncTask<Void, Void, String> {
copyReportFiles(tempDir);
// create a File object for a report ZIP file
- File reportZipFile = new File(
- verifierReportsDir, getReportName(suiteName) + ZIP_EXTENSION);
+ File reportZipFile = new File(verifierReportsDir, getReportName(suiteName) + ZIP_EXTENSION);
try {
// Serialize the report
String versionName = Version.getVersionName(mContext);
- ResultHandler.writeResults(suiteName, versionName, SUITE_PLAN, SUITE_BUILD,
- result, tempDir, START_MS, END_MS, REFERENCE_URL, LOG_URL,
- COMMAND_LINE_ARGS, null);
+ ResultHandler.writeResults(
+ suiteName,
+ versionName,
+ TestListActivity.getIsSystemEnabled() ? SYSTEM_SUITE_PLAN : DEFAULT_SUITE_PLAN,
+ SUITE_BUILD,
+ result,
+ tempDir,
+ START_MS,
+ END_MS,
+ REFERENCE_URL,
+ LOG_URL,
+ COMMAND_LINE_ARGS,
+ null);
// Serialize the screenshots metadata if at least one exists
if (containsScreenshotMetadata(result)) {
@@ -200,8 +207,8 @@ public class ReportExporter extends AsyncTask<Void, Void, String> {
Log.d(TAG, "---- saveReportOnInternalStorage(" + reportZipFile.getAbsolutePath() + ")");
}
try {
- ParcelFileDescriptor pfd = ParcelFileDescriptor.open(
- reportZipFile, ParcelFileDescriptor.MODE_READ_ONLY);
+ ParcelFileDescriptor pfd =
+ ParcelFileDescriptor.open(reportZipFile, ParcelFileDescriptor.MODE_READ_ONLY);
InputStream is = new ParcelFileDescriptor.AutoCloseInputStream(pfd);
File verifierDir = mContext.getDir(REPORT_DIRECTORY, Context.MODE_PRIVATE);
@@ -223,8 +230,7 @@ public class ReportExporter extends AsyncTask<Void, Void, String> {
for (String resultFileName : ResultHandler.RESULT_RESOURCES) {
InputStream rawStream = null;
try {
- rawStream = mContext.getAssets().open(
- String.format("report/%s", resultFileName));
+ rawStream = mContext.getAssets().open(String.format("report/%s", resultFileName));
} catch (IOException e) {
LOG.log(Level.WARNING, "Failed to load " + resultFileName + " from assets.");
}
@@ -242,7 +248,8 @@ public class ReportExporter extends AsyncTask<Void, Void, String> {
private String getReportName(String suiteName) {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy.MM.dd_HH.mm.ss", Locale.ENGLISH);
String date = dateFormat.format(new Date());
- return String.format("%s-%s-%s-%s-%s-%s",
+ return String.format(
+ "%s-%s-%s-%s-%s-%s",
date, suiteName, Build.MANUFACTURER, Build.PRODUCT, Build.DEVICE, Build.ID);
}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/TestListActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/TestListActivity.java
index 790bf73e956..e3f06ddb2cf 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/TestListActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/TestListActivity.java
@@ -55,6 +55,11 @@ public class TestListActivity extends AbstractTestListActivity implements View.O
// Default is unfolded mode, and it will be changed when clicking the switch button.
public static volatile String sCurrentDisplayMode = DisplayMode.UNFOLDED.toString();
+ // Whether the verifier-system plan is enabled.
+ private static boolean sIsSystemEnabled = false;
+ // Whether the system switch has been toggled.
+ private static boolean sHasSystemToggled = false;
+
private String[] mRequestedPermissions;
// Enumerates the display modes, including unfolded and folded.
@@ -124,31 +129,6 @@ public class TestListActivity extends AbstractTestListActivity implements View.O
}
}
- private void createContinue() {
- if (!isTaskRoot()) {
- finish();
- }
-
- // Restores the last display mode when launching the app after killing the process.
- if (getCurrentDisplayMode().equals(DisplayMode.FOLDED.toString())) {
- sCurrentDisplayMode = DisplayMode.FOLDED.toString();
- }
-
- setTitle(getString(R.string.title_version, Version.getVersionName(this)));
-
- if (!getWindow().hasFeature(Window.FEATURE_ACTION_BAR)) {
- View footer = getLayoutInflater().inflate(R.layout.test_list_footer, null);
-
- footer.findViewById(R.id.clear).setOnClickListener(this);
- footer.findViewById(R.id.export).setOnClickListener(this);
-
- getListView().addFooterView(footer);
- }
-
- setTestListAdapter(
- new ManifestTestListAdapter(/* context= */ this, /* testParent= */ null));
- }
-
@Override
public void onRequestPermissionsResult(
int requestCode, String permissions[], int[] grantResults) {
@@ -175,25 +155,6 @@ public class TestListActivity extends AbstractTestListActivity implements View.O
}
}
- private AlertDialog sendUserToSettings() {
- return new AlertDialog.Builder(this)
- .setTitle("Please grant all permissions")
- .setPositiveButton(
- "Ok",
- (dialog, which) -> {
- if (which == AlertDialog.BUTTON_POSITIVE) {
- startActivity(
- new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
- .setData(
- Uri.fromParts(
- "package",
- getPackageName(),
- null)));
- }
- })
- .show();
- }
-
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
@@ -221,6 +182,26 @@ public class TestListActivity extends AbstractTestListActivity implements View.O
}
});
+ // Switch button for verifier-system plan.
+ item = (MenuItem) menu.findItem(R.id.system_switch_item);
+ item.setActionView(R.layout.system_switch);
+ final Switch systemSwitch = item.getActionView().findViewById(R.id.switch_button);
+
+ systemSwitch.setChecked(sIsSystemEnabled);
+ systemSwitch.setOnCheckedChangeListener(
+ new CompoundButton.OnCheckedChangeListener() {
+
+ @Override
+ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+ if (!sHasSystemToggled && isChecked) {
+ sHasSystemToggled = true;
+ notifyUserSystemPlan(systemSwitch);
+ } else {
+ updateIsSystemEnabled(isChecked);
+ }
+ }
+ });
+
SearchView searchView = (SearchView) menu.findItem(R.id.search_test).getActionView();
searchView.setOnQueryTextListener(
new SearchView.OnQueryTextListener() {
@@ -250,6 +231,129 @@ public class TestListActivity extends AbstractTestListActivity implements View.O
return handleMenuItemSelected(item.getItemId()) ? true : super.onOptionsItemSelected(item);
}
+ /** Gets the verifier-system plan enabled status. */
+ static boolean getIsSystemEnabled() {
+ return sIsSystemEnabled;
+ }
+
+ /** Checks if a list of int array contains a given int value. */
+ private static boolean arrayContains(int[] array, int value) {
+ if (array == null) {
+ return false;
+ }
+ for (int element : array) {
+ if (element == value) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /** Removes the first occurrence of a string from a given string array. */
+ private static String[] removeString(String[] cur, String val) {
+ if (cur == null) {
+ return null;
+ }
+ final int n = cur.length;
+ for (int i = 0; i < n; i++) {
+ if (Objects.equals(cur[i], val)) {
+ String[] ret = new String[n - 1];
+ if (i > 0) {
+ System.arraycopy(cur, 0, ret, 0, i);
+ }
+ if (i < (n - 1)) {
+ System.arraycopy(cur, i + 1, ret, i, n - i - 1);
+ }
+ return ret;
+ }
+ }
+ return cur;
+ }
+
+ private void createContinue() {
+ if (!isTaskRoot()) {
+ finish();
+ }
+
+ // Restores the last display mode when launching the app after killing the process.
+ if (getCurrentDisplayMode().equals(DisplayMode.FOLDED.toString())) {
+ sCurrentDisplayMode = DisplayMode.FOLDED.toString();
+ }
+
+ setTitle(getString(R.string.title_version, Version.getVersionName(this)));
+
+ if (!getWindow().hasFeature(Window.FEATURE_ACTION_BAR)) {
+ View footer = getLayoutInflater().inflate(R.layout.test_list_footer, null);
+
+ footer.findViewById(R.id.clear).setOnClickListener(this);
+ footer.findViewById(R.id.export).setOnClickListener(this);
+
+ getListView().addFooterView(footer);
+ }
+
+ setTestListAdapter(
+ new ManifestTestListAdapter(/* context= */ this, /* testParent= */ null));
+ }
+
+ private AlertDialog sendUserToSettings() {
+ return new AlertDialog.Builder(this)
+ .setTitle("Please grant all permissions")
+ .setPositiveButton(
+ "Ok",
+ (dialog, which) -> {
+ if (which == AlertDialog.BUTTON_POSITIVE) {
+ startActivity(
+ new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
+ .setData(
+ Uri.fromParts(
+ "package",
+ getPackageName(),
+ null)));
+ }
+ })
+ .show();
+ }
+
+ /** Notifies the user about the verifier-system plan. */
+ private AlertDialog notifyUserSystemPlan(Switch systemSwitch) {
+ return new AlertDialog.Builder(this)
+ .setTitle("Verifier System Plan")
+ .setMessage(
+ "This is a feature to execute verifier tests for the system layer"
+ + " partitions. Click \"Yes\" to proceed or \"No\" to run all of the"
+ + " verifier tests.")
+ .setPositiveButton(
+ "Yes",
+ new DialogInterface.OnClickListener() {
+
+ public void onClick(DialogInterface dialog, int whichButton) {
+ updateIsSystemEnabled(true);
+ }
+ })
+ .setNegativeButton(
+ "No",
+ new DialogInterface.OnClickListener() {
+
+ public void onClick(DialogInterface dialog, int whichButton) {
+ systemSwitch.setChecked(false);
+ }
+ })
+ .show();
+ }
+
+ /** Updates the verifier-system plan enabled status and refreshes the test list. */
+ private void updateIsSystemEnabled(boolean isChecked) {
+ Log.i(TAG, "verifier-system plan enabled: " + isChecked);
+ sIsSystemEnabled = isChecked;
+ handleSwitchItemSelected();
+ }
+
+ /** Sets up the flags after switching display mode and reloads tests on UI. */
+ private void handleSwitchItemSelected() {
+ setCurrentDisplayMode(sCurrentDisplayMode);
+ mAdapter.loadTestResults();
+ }
+
private void handleClearItemSelected() {
new AlertDialog.Builder(this)
.setMessage(R.string.test_results_clear_title)
@@ -273,12 +377,6 @@ public class TestListActivity extends AbstractTestListActivity implements View.O
new ReportExporter(this, mAdapter).execute();
}
- /** Sets up the flags after switching display mode and reloads tests on UI. */
- private void handleSwitchItemSelected() {
- setCurrentDisplayMode(sCurrentDisplayMode);
- mAdapter.loadTestResults();
- }
-
private boolean handleMenuItemSelected(int id) {
if (id == R.id.clear) {
handleClearItemSelected();
@@ -323,34 +421,4 @@ public class TestListActivity extends AbstractTestListActivity implements View.O
.getString(DisplayMode.class.getName(), "");
return mode;
}
-
- private static boolean arrayContains(int[] array, int value) {
- if (array == null) return false;
- for (int element : array) {
- if (element == value) {
- return true;
- }
- }
- return false;
- }
-
- private static String[] removeString(String[] cur, String val) {
- if (cur == null) {
- return null;
- }
- final int n = cur.length;
- for (int i = 0; i < n; i++) {
- if (Objects.equals(cur[i], val)) {
- String[] ret = new String[n - 1];
- if (i > 0) {
- System.arraycopy(cur, 0, ret, 0, i);
- }
- if (i < (n - 1)) {
- System.arraycopy(cur, i + 1, ret, i, n - i - 1);
- }
- return ret;
- }
- }
- return cur;
- }
}