1 /* 2 * Copyright (C) 2010 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.android.cts.verifier; 18 19 import static com.android.cts.verifier.TestListActivity.sCurrentDisplayMode; 20 import static com.android.cts.verifier.TestListActivity.sInitialLaunch; 21 22 import android.content.ContentResolver; 23 import android.content.Context; 24 import android.content.Intent; 25 import android.database.ContentObserver; 26 import android.database.Cursor; 27 import android.os.AsyncTask; 28 import android.os.Handler; 29 import android.view.LayoutInflater; 30 import android.view.View; 31 import android.view.ViewGroup; 32 import android.widget.BaseAdapter; 33 import android.widget.ListView; 34 import android.widget.TextView; 35 36 import com.android.compatibility.common.util.ReportLog; 37 import com.android.cts.verifier.TestListActivity.DisplayMode; 38 39 import java.io.ByteArrayInputStream; 40 import java.io.IOException; 41 import java.io.ObjectInputStream; 42 import java.util.ArrayList; 43 import java.util.HashMap; 44 import java.util.List; 45 import java.util.Map; 46 47 /** 48 * {@link BaseAdapter} that handles loading, refreshing, and setting test 49 * results. What tests are shown can be customized by overriding 50 * {@link #getRows()}. See {@link ArrayTestListAdapter} and 51 * {@link ManifestTestListAdapter} for examples. 52 */ 53 public abstract class TestListAdapter extends BaseAdapter { 54 55 /** Activities implementing {@link Intent#ACTION_MAIN} and this will appear in the list. */ 56 public static final String CATEGORY_MANUAL_TEST = "android.cts.intent.category.MANUAL_TEST"; 57 58 /** View type for a category of tests like "Sensors" or "Features" */ 59 private static final int CATEGORY_HEADER_VIEW_TYPE = 0; 60 61 /** View type for an actual test like the Accelerometer test. */ 62 private static final int TEST_VIEW_TYPE = 1; 63 64 /** Padding around the text views and icons. */ 65 private static final int PADDING = 10; 66 67 private final Context mContext; 68 69 /** Immutable data of tests like the test's title and launch intent. */ 70 private final List<TestListItem> mRows = new ArrayList<TestListItem>(); 71 72 /** Mutable test results that will change as each test activity finishes. */ 73 private final Map<String, Integer> mTestResults = new HashMap<String, Integer>(); 74 75 /** Map from test name to test details. */ 76 private final Map<String, String> mTestDetails = new HashMap<String, String>(); 77 78 /** Map from test name to {@link ReportLog}. */ 79 private final Map<String, ReportLog> mReportLogs = new HashMap<String, ReportLog>(); 80 81 /** Map from test name to {@link TestResultHistoryCollection}. */ 82 private final Map<String, TestResultHistoryCollection> mHistories = new HashMap<>(); 83 84 private final LayoutInflater mLayoutInflater; 85 86 /** Map from display mode to the list of {@link TestListItem}. 87 * Records the TestListItem from main view only, including unfolded mode and folded mode 88 * respectively. */ 89 protected Map<String, List<TestListItem>> mDisplayModesTests = new HashMap<>(); 90 91 /** Flag to identify the test data from {@link ManifestTestListAdapter}. 92 * The source of data for the adapter is various, such as ManifestTestListAdapter and 93 * ArrayTestListAdapter, and the data of foldable tests are from ManifestTestListAdapter. */ 94 protected static boolean adapterFromManifest; 95 96 /** Flag to identify the test data in main view from {@link ManifestTestListAdapter}. 97 * ManifestTestListAdapter provides test data for main view and subtests. 98 * Getting foldable tests is from main view only. */ 99 protected static boolean hasTestParentInManifestAdapter; 100 101 /** {@link ListView} row that is either a test category header or a test. */ 102 public static class TestListItem { 103 104 /** Title shown in the {@link ListView}. */ 105 final String title; 106 107 /** Test name with class and test ID to uniquely identify the test. Null for categories. */ 108 String testName; 109 110 /** Intent used to launch the activity from the list. Null for categories. */ 111 final Intent intent; 112 113 /** Features necessary to run this test. */ 114 final String[] requiredFeatures; 115 116 /** Configs necessary to run this test. */ 117 final String[] requiredConfigs; 118 119 /** Intent actions necessary to run this test. */ 120 final String[] requiredActions; 121 122 /** Features such that, if any present, the test gets excluded from being shown. */ 123 final String[] excludedFeatures; 124 125 /** If any of of the features are present the test is meaningful to run. */ 126 final String[] applicableFeatures; 127 128 /** Configs display mode to run this test. */ 129 final String displayMode; 130 131 // TODO: refactor to use a Builder approach instead 132 newTest(Context context, int titleResId, String testName, Intent intent, String[] requiredFeatures, String[] excludedFeatures, String[] applicableFeatures)133 public static TestListItem newTest(Context context, int titleResId, String testName, 134 Intent intent, String[] requiredFeatures, String[] excludedFeatures, 135 String[] applicableFeatures) { 136 return newTest(context.getString(titleResId), testName, intent, requiredFeatures, 137 excludedFeatures, applicableFeatures); 138 } 139 newTest(Context context, int titleResId, String testName, Intent intent, String[] requiredFeatures, String[] excludedFeatures)140 public static TestListItem newTest(Context context, int titleResId, String testName, 141 Intent intent, String[] requiredFeatures, String[] excludedFeatures) { 142 return newTest(context.getString(titleResId), testName, intent, requiredFeatures, 143 excludedFeatures, /* applicableFeatures= */ null); 144 } 145 newTest(Context context, int titleResId, String testName, Intent intent, String[] requiredFeatures)146 public static TestListItem newTest(Context context, int titleResId, String testName, 147 Intent intent, String[] requiredFeatures) { 148 return newTest(context.getString(titleResId), testName, intent, requiredFeatures, 149 /* excludedFeatures= */ null, /* applicableFeatures= */ null); 150 } 151 newTest(String title, String testName, Intent intent, String[] requiredFeatures, String[] requiredConfigs, String[] requiredActions, String[] excludedFeatures, String[] applicableFeatures, String displayMode)152 public static TestListItem newTest(String title, String testName, Intent intent, 153 String[] requiredFeatures, String[] requiredConfigs, String[] requiredActions, 154 String[] excludedFeatures, String[] applicableFeatures, String displayMode) { 155 return new TestListItem(title, testName, intent, requiredFeatures, requiredConfigs, 156 requiredActions, excludedFeatures, applicableFeatures, displayMode); 157 } 158 newTest(String title, String testName, Intent intent, String[] requiredFeatures, String[] requiredConfigs, String[] excludedFeatures, String[] applicableFeatures)159 public static TestListItem newTest(String title, String testName, Intent intent, 160 String[] requiredFeatures, String[] requiredConfigs, String[] excludedFeatures, 161 String[] applicableFeatures) { 162 return new TestListItem(title, testName, intent, requiredFeatures, requiredConfigs, 163 /* requiredActions = */ null, excludedFeatures, applicableFeatures, 164 /* displayMode= */ null); 165 } 166 newTest(String title, String testName, Intent intent, String[] requiredFeatures, String[] excludedFeatures, String[] applicableFeatures)167 public static TestListItem newTest(String title, String testName, Intent intent, 168 String[] requiredFeatures, String[] excludedFeatures, String[] applicableFeatures) { 169 return new TestListItem(title, testName, intent, requiredFeatures, 170 /* requiredConfigs= */ null, /* requiredActions = */ null, excludedFeatures, 171 applicableFeatures, /* displayMode= */ null); 172 } 173 newTest(String title, String testName, Intent intent, String[] requiredFeatures, String[] excludedFeatures)174 public static TestListItem newTest(String title, String testName, Intent intent, 175 String[] requiredFeatures, String[] excludedFeatures) { 176 return new TestListItem(title, testName, intent, requiredFeatures, 177 /* requiredConfigs= */ null, /* requiredActions = */ null, excludedFeatures, 178 /* applicableFeatures= */ null, /* displayMode= */ null); 179 } 180 newTest(String title, String testName, Intent intent, String[] requiredFeatures)181 public static TestListItem newTest(String title, String testName, Intent intent, 182 String[] requiredFeatures) { 183 return new TestListItem(title, testName, intent, requiredFeatures, 184 /* requiredConfigs= */ null, /* requiredActions = */ null, 185 /* excludedFeatures= */ null, /* applicableFeatures= */ null, 186 /* displayMode= */ null); 187 } 188 newCategory(Context context, int titleResId)189 public static TestListItem newCategory(Context context, int titleResId) { 190 return newCategory(context.getString(titleResId)); 191 } 192 newCategory(String title)193 public static TestListItem newCategory(String title) { 194 return new TestListItem(title, /* testName= */ null, /* intent= */ null, 195 /* requiredFeatures= */ null, /* requiredConfigs= */ null, 196 /* requiredActions = */ null, /* excludedFeatures= */ null, 197 /* applicableFeatures= */ null, /* displayMode= */ null); 198 } 199 TestListItem(String title, String testName, Intent intent, String[] requiredFeatures, String[] excludedFeatures, String[] applicableFeatures)200 protected TestListItem(String title, String testName, Intent intent, 201 String[] requiredFeatures, String[] excludedFeatures, String[] applicableFeatures) { 202 this(title, testName, intent, requiredFeatures, /* requiredConfigs= */ null, 203 /* requiredActions = */ null, excludedFeatures, applicableFeatures, 204 /* displayMode= */ null); 205 } 206 TestListItem(String title, String testName, Intent intent, String[] requiredFeatures, String[] requiredConfigs, String[] requiredActions, String[] excludedFeatures, String[] applicableFeatures, String displayMode)207 protected TestListItem(String title, String testName, Intent intent, 208 String[] requiredFeatures, String[] requiredConfigs, String[] requiredActions, 209 String[] excludedFeatures, String[] applicableFeatures, String displayMode) { 210 this.title = title; 211 if (!sInitialLaunch) { 212 testName = setTestNameSuffix(sCurrentDisplayMode, testName); 213 } 214 this.testName = testName; 215 this.intent = intent; 216 this.requiredActions = requiredActions; 217 this.requiredFeatures = requiredFeatures; 218 this.requiredConfigs = requiredConfigs; 219 this.excludedFeatures = excludedFeatures; 220 this.applicableFeatures = applicableFeatures; 221 this.displayMode = displayMode; 222 } 223 isTest()224 boolean isTest() { 225 return intent != null; 226 } 227 } 228 TestListAdapter(Context context)229 public TestListAdapter(Context context) { 230 this.mContext = context; 231 this.mLayoutInflater = 232 (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 233 234 TestResultContentObserver observer = new TestResultContentObserver(); 235 ContentResolver resolver = context.getContentResolver(); 236 resolver.registerContentObserver(TestResultsProvider.getResultContentUri(context), true, observer); 237 } 238 loadTestResults()239 public void loadTestResults() { 240 new RefreshTestResultsTask().execute(); 241 } 242 clearTestResults()243 public void clearTestResults() { 244 new ClearTestResultsTask().execute(); 245 } 246 setTestResult(TestResult testResult)247 public void setTestResult(TestResult testResult) { 248 String name = testResult.getName(); 249 250 // Append existing history 251 TestResultHistoryCollection histories = testResult.getHistoryCollection(); 252 histories.merge(null, mHistories.get(name)); 253 254 new SetTestResultTask(name, testResult.getResult(), 255 testResult.getDetails(), testResult.getReportLog(), histories).execute(); 256 } 257 258 class RefreshTestResultsTask extends AsyncTask<Void, Void, RefreshResult> { 259 @Override doInBackground(Void... params)260 protected RefreshResult doInBackground(Void... params) { 261 List<TestListItem> rows; 262 // When initial launch, needs to fetch tests in the unfolded/folded mode 263 // to be stored in mDisplayModesTests as the basis for the future switch. 264 if (sInitialLaunch) { 265 getRows(); 266 sInitialLaunch = false; 267 } 268 269 if (checkTestsFromMainView()) { 270 rows = mDisplayModesTests.get(sCurrentDisplayMode); 271 }else { 272 rows = getRows(); 273 } 274 return getRefreshResults(rows); 275 } 276 277 @Override onPostExecute(RefreshResult result)278 protected void onPostExecute(RefreshResult result) { 279 super.onPostExecute(result); 280 mRows.clear(); 281 mRows.addAll(result.mItems); 282 mTestResults.clear(); 283 mTestResults.putAll(result.mResults); 284 mTestDetails.clear(); 285 mTestDetails.putAll(result.mDetails); 286 mReportLogs.clear(); 287 mReportLogs.putAll(result.mReportLogs); 288 mHistories.clear(); 289 mHistories.putAll(result.mHistories); 290 notifyDataSetChanged(); 291 } 292 } 293 294 static class RefreshResult { 295 List<TestListItem> mItems; 296 Map<String, Integer> mResults; 297 Map<String, String> mDetails; 298 Map<String, ReportLog> mReportLogs; 299 Map<String, TestResultHistoryCollection> mHistories; 300 RefreshResult( List<TestListItem> items, Map<String, Integer> results, Map<String, String> details, Map<String, ReportLog> reportLogs, Map<String, TestResultHistoryCollection> histories)301 RefreshResult( 302 List<TestListItem> items, 303 Map<String, Integer> results, 304 Map<String, String> details, 305 Map<String, ReportLog> reportLogs, 306 Map<String, TestResultHistoryCollection> histories) { 307 mItems = items; 308 mResults = results; 309 mDetails = details; 310 mReportLogs = reportLogs; 311 mHistories = histories; 312 } 313 } 314 getRows()315 protected abstract List<TestListItem> getRows(); 316 317 static final String[] REFRESH_PROJECTION = { 318 TestResultsProvider._ID, 319 TestResultsProvider.COLUMN_TEST_NAME, 320 TestResultsProvider.COLUMN_TEST_RESULT, 321 TestResultsProvider.COLUMN_TEST_DETAILS, 322 TestResultsProvider.COLUMN_TEST_METRICS, 323 TestResultsProvider.COLUMN_TEST_RESULT_HISTORY, 324 }; 325 getRefreshResults(List<TestListItem> items)326 RefreshResult getRefreshResults(List<TestListItem> items) { 327 Map<String, Integer> results = new HashMap<String, Integer>(); 328 Map<String, String> details = new HashMap<String, String>(); 329 Map<String, ReportLog> reportLogs = new HashMap<String, ReportLog>(); 330 Map<String, TestResultHistoryCollection> histories = new HashMap<>(); 331 ContentResolver resolver = mContext.getContentResolver(); 332 Cursor cursor = null; 333 try { 334 cursor = resolver.query(TestResultsProvider.getResultContentUri(mContext), REFRESH_PROJECTION, 335 null, null, null); 336 if (cursor.moveToFirst()) { 337 do { 338 String testName = cursor.getString(1); 339 int testResult = cursor.getInt(2); 340 String testDetails = cursor.getString(3); 341 ReportLog reportLog = (ReportLog) deserialize(cursor.getBlob(4)); 342 TestResultHistoryCollection historyCollection = 343 (TestResultHistoryCollection) deserialize(cursor.getBlob(5)); 344 results.put(testName, testResult); 345 details.put(testName, testDetails); 346 reportLogs.put(testName, reportLog); 347 histories.put(testName, historyCollection); 348 } while (cursor.moveToNext()); 349 } 350 } finally { 351 if (cursor != null) { 352 cursor.close(); 353 } 354 } 355 return new RefreshResult(items, results, details, reportLogs, histories); 356 } 357 358 class ClearTestResultsTask extends AsyncTask<Void, Void, Void> { 359 360 @Override doInBackground(Void... params)361 protected Void doInBackground(Void... params) { 362 ContentResolver resolver = mContext.getContentResolver(); 363 resolver.delete(TestResultsProvider.getResultContentUri(mContext), "1", null); 364 return null; 365 } 366 } 367 368 class SetTestResultTask extends AsyncTask<Void, Void, Void> { 369 370 private final String mTestName; 371 private final int mResult; 372 private final String mDetails; 373 private final ReportLog mReportLog; 374 private final TestResultHistoryCollection mHistoryCollection; 375 SetTestResultTask( String testName, int result, String details, ReportLog reportLog, TestResultHistoryCollection historyCollection)376 SetTestResultTask( 377 String testName, 378 int result, 379 String details, 380 ReportLog reportLog, 381 TestResultHistoryCollection historyCollection) { 382 mTestName = testName; 383 mResult = result; 384 mDetails = details; 385 mReportLog = reportLog; 386 mHistoryCollection = historyCollection; 387 } 388 389 @Override doInBackground(Void... params)390 protected Void doInBackground(Void... params) { 391 TestResultsProvider.setTestResult( 392 mContext, mTestName, mResult, mDetails, mReportLog, mHistoryCollection); 393 return null; 394 } 395 } 396 397 class TestResultContentObserver extends ContentObserver { 398 TestResultContentObserver()399 public TestResultContentObserver() { 400 super(new Handler()); 401 } 402 403 @Override onChange(boolean selfChange)404 public void onChange(boolean selfChange) { 405 super.onChange(selfChange); 406 loadTestResults(); 407 } 408 } 409 410 @Override areAllItemsEnabled()411 public boolean areAllItemsEnabled() { 412 // Section headers for test categories are not clickable. 413 return false; 414 } 415 416 @Override isEnabled(int position)417 public boolean isEnabled(int position) { 418 return getItem(position).isTest(); 419 } 420 421 @Override getItemViewType(int position)422 public int getItemViewType(int position) { 423 return getItem(position).isTest() ? TEST_VIEW_TYPE : CATEGORY_HEADER_VIEW_TYPE; 424 } 425 426 @Override getViewTypeCount()427 public int getViewTypeCount() { 428 return 2; 429 } 430 431 @Override getCount()432 public int getCount() { 433 if (!sInitialLaunch && checkTestsFromMainView()) { 434 return mDisplayModesTests.get(sCurrentDisplayMode).size(); 435 } 436 return mRows.size(); 437 } 438 439 @Override getItem(int position)440 public TestListItem getItem(int position) { 441 if (checkTestsFromMainView()) { 442 return mDisplayModesTests.get(sCurrentDisplayMode).get(position); 443 } 444 return mRows.get(position); 445 } 446 447 @Override getItemId(int position)448 public long getItemId(int position) { 449 return position; 450 } 451 getTestResult(int position)452 public int getTestResult(int position) { 453 TestListItem item = getItem(position); 454 return mTestResults.containsKey(item.testName) 455 ? mTestResults.get(item.testName) 456 : TestResult.TEST_RESULT_NOT_EXECUTED; 457 } 458 getTestDetails(int position)459 public String getTestDetails(int position) { 460 TestListItem item = getItem(position); 461 return mTestDetails.containsKey(item.testName) 462 ? mTestDetails.get(item.testName) 463 : null; 464 } 465 getReportLog(int position)466 public ReportLog getReportLog(int position) { 467 TestListItem item = getItem(position); 468 return mReportLogs.containsKey(item.testName) 469 ? mReportLogs.get(item.testName) 470 : null; 471 } 472 473 /** 474 * Get test result histories. 475 * 476 * @param position The position of test. 477 * @return A {@link TestResultHistoryCollection} object containing test result histories of tests. 478 */ getHistoryCollection(int position)479 public TestResultHistoryCollection getHistoryCollection(int position) { 480 TestListItem item = getItem(position); 481 return mHistories.containsKey(item.testName) 482 ? mHistories.get(item.testName) 483 : null; 484 } 485 486 /** 487 * Get test item by the given display mode and position. 488 * 489 * @param mode The display mode. 490 * @param position The position of test. 491 * @return A {@link TestListItem} object containing the test item. 492 */ getItem(String mode, int position)493 public TestListItem getItem(String mode, int position) { 494 return mDisplayModesTests.get(mode).get(position); 495 } 496 497 /** 498 * Get test item count by the given display mode. 499 * 500 * @param mode The display mode. 501 * @return A count of test items. 502 */ getCount(String mode)503 public int getCount(String mode){ 504 return mDisplayModesTests.get(mode).size(); 505 } 506 507 /** 508 * Get test result by the given display mode and position. 509 * 510 * @param mode The display mode. 511 * @param position The position of test. 512 * @return The test item result. 513 */ getTestResult(String mode, int position)514 public int getTestResult(String mode, int position) { 515 TestListItem item = mDisplayModesTests.get(mode).get(position); 516 return mTestResults.containsKey(item.testName) 517 ? mTestResults.get(item.testName) 518 : TestResult.TEST_RESULT_NOT_EXECUTED; 519 } 520 521 /** 522 * Get test details by the given display mode and position. 523 * 524 * @param mode The display mode. 525 * @param position The position of test. 526 * @return A string containing the test details. 527 */ getTestDetails(String mode, int position)528 public String getTestDetails(String mode, int position) { 529 TestListItem item = mDisplayModesTests.get(mode).get(position); 530 return mTestDetails.containsKey(item.testName) 531 ? mTestDetails.get(item.testName) 532 : null; 533 } 534 535 /** 536 * Get test report log by the given display mode and position. 537 * 538 * @param mode The display mode. 539 * @param position The position of test. 540 * @return A {@link ReportLog} object containing the test report log of the test item. 541 */ getReportLog(String mode, int position)542 public ReportLog getReportLog(String mode, int position) { 543 TestListItem item = mDisplayModesTests.get(mode).get(position); 544 return mReportLogs.containsKey(item.testName) 545 ? mReportLogs.get(item.testName) 546 : null; 547 } 548 549 /** 550 * Get test result histories by the given display mode and position. 551 * 552 * @param mode The display mode. 553 * @param position The position of test. 554 * @return A {@link TestResultHistoryCollection} object containing the test result histories of 555 * the test item. 556 */ getHistoryCollection(String mode, int position)557 public TestResultHistoryCollection getHistoryCollection(String mode, int position) { 558 TestListItem item = mDisplayModesTests.get(mode).get(position); 559 return mHistories.containsKey(item.testName) 560 ? mHistories.get(item.testName) 561 : null; 562 } 563 allTestsPassed()564 public boolean allTestsPassed() { 565 for (TestListItem item : mRows) { 566 if (item.isTest() && (!mTestResults.containsKey(item.testName) 567 || (mTestResults.get(item.testName) != TestResult.TEST_RESULT_PASSED))) { 568 return false; 569 } 570 } 571 return true; 572 } 573 574 @Override getView(int position, View convertView, ViewGroup parent)575 public View getView(int position, View convertView, ViewGroup parent) { 576 TextView textView; 577 if (convertView == null) { 578 int layout = getLayout(position); 579 textView = (TextView) mLayoutInflater.inflate(layout, parent, false); 580 } else { 581 textView = (TextView) convertView; 582 } 583 584 TestListItem item = getItem(position); 585 textView.setText(item.title); 586 textView.setPadding(PADDING, 0, PADDING, 0); 587 textView.setCompoundDrawablePadding(PADDING); 588 589 if (item.isTest()) { 590 int testResult = getTestResult(position); 591 int backgroundResource = 0; 592 int iconResource = 0; 593 594 /** TODO: Remove fs_ prefix from feature icons since they are used here too. */ 595 switch (testResult) { 596 case TestResult.TEST_RESULT_PASSED: 597 backgroundResource = R.drawable.test_pass_gradient; 598 iconResource = R.drawable.fs_good; 599 break; 600 601 case TestResult.TEST_RESULT_FAILED: 602 backgroundResource = R.drawable.test_fail_gradient; 603 iconResource = R.drawable.fs_error; 604 break; 605 606 case TestResult.TEST_RESULT_NOT_EXECUTED: 607 break; 608 609 default: 610 throw new IllegalArgumentException("Unknown test result: " + testResult); 611 } 612 613 textView.setBackgroundResource(backgroundResource); 614 textView.setCompoundDrawablesWithIntrinsicBounds(0, 0, iconResource, 0); 615 } 616 617 return textView; 618 } 619 getLayout(int position)620 private int getLayout(int position) { 621 int viewType = getItemViewType(position); 622 switch (viewType) { 623 case CATEGORY_HEADER_VIEW_TYPE: 624 return R.layout.test_category_row; 625 case TEST_VIEW_TYPE: 626 return android.R.layout.simple_list_item_1; 627 default: 628 throw new IllegalArgumentException("Illegal view type: " + viewType); 629 630 } 631 } 632 deserialize(byte[] bytes)633 public static Object deserialize(byte[] bytes) { 634 if (bytes == null || bytes.length == 0) { 635 return null; 636 } 637 ByteArrayInputStream byteStream = new ByteArrayInputStream(bytes); 638 ObjectInputStream objectInput = null; 639 try { 640 objectInput = new ObjectInputStream(byteStream); 641 return objectInput.readObject(); 642 } catch (IOException e) { 643 return null; 644 } catch (ClassNotFoundException e) { 645 return null; 646 } finally { 647 try { 648 if (objectInput != null) { 649 objectInput.close(); 650 } 651 byteStream.close(); 652 } catch (IOException e) { 653 // Ignore close exception. 654 } 655 } 656 } 657 658 /** 659 * Sets test name suffix. In the folded mode, the suffix is [folded]; otherwise, it is empty 660 * string. 661 * 662 * @param mode A string of current display mode. 663 * @param name A string of test name. 664 * @return A string of test name with suffix, [folded], in the folded mode. 665 * A string of input test name in the unfolded mode. 666 */ setTestNameSuffix(String mode, String name)667 public static String setTestNameSuffix(String mode, String name) { 668 if (name != null && mode.equals(DisplayMode.FOLDED.toString()) 669 && !name.endsWith(DisplayMode.FOLDED.asSuffix())){ 670 return name + DisplayMode.FOLDED.asSuffix(); 671 } 672 return name; 673 } 674 675 /** 676 * Checks if the tests are from main view for foldable tests. 677 * 678 * @return True if the tests from main view, otherwise, return false. 679 */ checkTestsFromMainView()680 private static boolean checkTestsFromMainView() { 681 return adapterFromManifest && !hasTestParentInManifestAdapter; 682 } 683 } 684