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.TestListAdapter.setTestNameSuffix; 21 22 import android.app.ActionBar; 23 import android.app.AlertDialog; 24 import android.app.Dialog; 25 import android.content.ContentResolver; 26 import android.content.ContentValues; 27 import android.content.Context; 28 import android.content.DialogInterface; 29 import android.content.DialogInterface.OnCancelListener; 30 import android.content.pm.PackageManager; 31 import android.database.Cursor; 32 import android.os.Bundle; 33 import android.os.PowerManager; 34 import android.os.PowerManager.WakeLock; 35 import android.view.LayoutInflater; 36 import android.view.MenuItem; 37 import android.view.View; 38 import android.view.View.OnClickListener; 39 import android.widget.ImageButton; 40 import android.widget.Toast; 41 42 import com.android.compatibility.common.util.ReportLog; 43 44 import java.util.List; 45 import java.util.stream.Collectors; 46 import java.util.stream.IntStream; 47 48 /** 49 * {@link Activity}s to handle clicks to the pass and fail buttons of the pass fail buttons layout. 50 * 51 * <ol> 52 * <li>Include the pass fail buttons layout in your layout: 53 * <pre><include layout="@layout/pass_fail_buttons" /></pre> 54 * </li> 55 * <li>Extend one of the activities and call setPassFailButtonClickListeners after 56 * setting your content view.</li> 57 * <li>Make sure to call setResult(RESULT_CANCEL) in your Activity initially.</li> 58 * <li>Optionally call setInfoTextResources to add an info button that will show a 59 * dialog with instructional text.</li> 60 * </ol> 61 */ 62 public class PassFailButtons { 63 private static final String INFO_TAG = "CtsVerifierInstructions"; 64 65 // Need different IDs for these alerts or else the first one created 66 // will just be reused, with the old title/message. 67 private static final int INFO_DIALOG_ID = 1337; 68 private static final int REPORTLOG_DIALOG_ID = 1338; 69 70 private static final String INFO_DIALOG_VIEW_ID = "infoDialogViewId"; 71 private static final String INFO_DIALOG_TITLE_ID = "infoDialogTitleId"; 72 private static final String INFO_DIALOG_MESSAGE_ID = "infoDialogMessageId"; 73 74 // ReportLog file for CTS-Verifier. The "stream" name gets mapped to the test class name. 75 public static final String GENERAL_TESTS_REPORT_LOG_NAME = "CtsVerifierGeneralTestCases"; 76 public static final String AUDIO_TESTS_REPORT_LOG_NAME = "CtsVerifierAudioTestCases"; 77 78 private static final String SECTION_UNDEFINED = "undefined_section_name"; 79 80 // Interface mostly for making documentation and refactoring easier... 81 public interface PassFailActivity { 82 83 /** 84 * Hooks up the pass and fail buttons to click listeners that will record the test results. 85 * <p> 86 * Call from {@link Activity#onCreate} after {@link Activity #setContentView(int)}. 87 */ setPassFailButtonClickListeners()88 void setPassFailButtonClickListeners(); 89 90 /** 91 * Adds an initial informational dialog that appears when entering the test activity for 92 * the first time. Also enables the visibility of an "Info" button between the "Pass" and 93 * "Fail" buttons that can be clicked to show the information dialog again. 94 * <p> 95 * Call from {@link Activity#onCreate} after {@link Activity #setContentView(int)}. 96 * 97 * @param titleId for the text shown in the dialog title area 98 * @param messageId for the text shown in the dialog's body area 99 */ setInfoResources(int titleId, int messageId, int viewId)100 void setInfoResources(int titleId, int messageId, int viewId); 101 getPassButton()102 View getPassButton(); 103 104 /** 105 * Returns a unique identifier for the test. Usually, this is just the class name. 106 */ getTestId()107 String getTestId(); 108 109 /** @return null or details about the test run. */ getTestDetails()110 String getTestDetails(); 111 112 /** 113 * Set the result of the test and finish the activity. 114 * 115 * @param passed Whether or not the test passed. 116 */ setTestResultAndFinish(boolean passed)117 void setTestResultAndFinish(boolean passed); 118 119 /** 120 * @return true if the test module will write a ReportLog entry 121 * 122 * Note that in order to obtain a non-null CtsVerifierReportLog object from 123 * the getReportLog() method, the activity must override this method to return true 124 * and should implement the getReportFileName(), getReportSectionName() and 125 * recordTestResults() methods. 126 * 127 * If this method returns true and the user did not setup up CtsVerifier correctly 128 * with respect to accessing local data on the DUT; 129 * <code> 130 * adb shell appops set com.android.cts.verifier android:read_device_identifiers allow 131 * adb shell appops set com.android.cts.verifier MANAGE_EXTERNAL_STORAGE 0 132 * </code> 133 * a warning dialog will be displayed when invoking that test. 134 */ requiresReportLog()135 public boolean requiresReportLog(); 136 137 /** 138 * @return The name of the file to store the (suite of) ReportLog information. 139 * 140 * If a test uses the CtsVerifierReportLog, it should implement this method to provide 141 * a file name for the (JSON) report log data. This does not need to be unique to the 142 * test, perhaps specific to a set of related tests. 143 */ getReportFileName()144 public String getReportFileName(); 145 146 /** 147 * @return A unique name to serve as a section header in the CtsVerifierReportLog file. 148 * Tests need to conform to the underscore_delineated_name standard for use with 149 * the protobuff/json ReportLog parsing in Google3 150 * 151 * If the test implements this method, it should also implement the requiresReportLog() 152 * method to return true and the getReportFileName() and recordTestResults() methods. 153 */ getReportSectionName()154 public String getReportSectionName(); 155 156 /** 157 * Test subclasses can override this to record their CtsVerifierReportLogs. 158 * This is called when the test is exited. 159 * 160 * NOTE: If the test gathers reportLog data, the test class should implement 161 * the requiresReportLog() to return true, and implement the getReportFileName() and 162 * getReportSectionName() methods. 163 */ recordTestResults()164 void recordTestResults(); 165 166 /** 167 * @return A {@link ReportLog} that is used to record test metric data or null. 168 * 169 * If a test calls this method it must implement the requiresReportLog() to return true, 170 * and implement the getReportFileName() and getReportSectionName() methods, otherwise 171 * this method will return null. 172 */ getReportLog()173 CtsVerifierReportLog getReportLog(); 174 175 /** 176 * @return A {@link TestResultHistoryCollection} that is used to record test execution time. 177 */ getHistoryCollection()178 TestResultHistoryCollection getHistoryCollection(); 179 } /* class PassFailButtons.PassFailActivity */ 180 181 public static class Activity extends android.app.Activity implements PassFailActivity { 182 private WakeLock mWakeLock; 183 private CtsVerifierReportLog mReportLog; 184 private final TestResultHistoryCollection mHistoryCollection; 185 186 protected boolean mRequireReportLogToPass; 187 Activity()188 public Activity() { 189 this.mHistoryCollection = new TestResultHistoryCollection(); 190 if (requiresReportLog()) { 191 // if the subclass reports a report filename, they need a ReportLog object 192 newReportLog(); 193 } 194 } 195 196 @Override onResume()197 protected void onResume() { 198 super.onResume(); 199 if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH)) { 200 mWakeLock = ((PowerManager) getSystemService(Context.POWER_SERVICE)) 201 .newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "PassFailButtons"); 202 mWakeLock.acquire(); 203 } 204 205 if (mReportLog != null && !mReportLog.isOpen()) { 206 showReportLogWarningDialog(this); 207 } 208 } 209 210 @Override onPause()211 protected void onPause() { 212 super.onPause(); 213 if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH)) { 214 mWakeLock.release(); 215 } 216 } 217 218 @Override setPassFailButtonClickListeners()219 public void setPassFailButtonClickListeners() { 220 setPassFailClickListeners(this); 221 } 222 223 @Override setInfoResources(int titleId, int messageId, int viewId)224 public void setInfoResources(int titleId, int messageId, int viewId) { 225 setInfo(this, titleId, messageId, viewId); 226 } 227 228 @Override getPassButton()229 public View getPassButton() { 230 return getPassButtonView(this); 231 } 232 233 @Override onCreateDialog(int id, Bundle args)234 public Dialog onCreateDialog(int id, Bundle args) { 235 return createDialog(this, id, args); 236 } 237 238 @Override getTestId()239 public String getTestId() { 240 return setTestNameSuffix(sCurrentDisplayMode, getClass().getName()); 241 } 242 243 @Override getTestDetails()244 public String getTestDetails() { 245 return null; 246 } 247 248 @Override setTestResultAndFinish(boolean passed)249 public void setTestResultAndFinish(boolean passed) { 250 PassFailButtons.setTestResultAndFinishHelper( 251 this, getTestId(), getTestDetails(), passed, getReportLog(), 252 getHistoryCollection()); 253 } 254 newReportLog()255 protected CtsVerifierReportLog newReportLog() { 256 return mReportLog = new CtsVerifierReportLog( 257 getReportFileName(), getReportSectionName()); 258 } 259 260 @Override requiresReportLog()261 public boolean requiresReportLog() { 262 return false; 263 } 264 265 @Override getReportLog()266 public CtsVerifierReportLog getReportLog() { 267 return mReportLog; 268 } 269 270 /** 271 * A mechanism to block tests from passing if no ReportLog data has been collected. 272 * @return true if the ReportLog is open OR if the test does not require that. 273 */ isReportLogOkToPass()274 public boolean isReportLogOkToPass() { 275 return !mRequireReportLogToPass || (mReportLog != null & mReportLog.isOpen()); 276 } 277 278 /** 279 * @return The name of the file to store the (suite of) ReportLog information. 280 */ 281 @Override getReportFileName()282 public String getReportFileName() { return GENERAL_TESTS_REPORT_LOG_NAME; } 283 284 @Override getReportSectionName()285 public String getReportSectionName() { 286 return setTestNameSuffix(sCurrentDisplayMode, SECTION_UNDEFINED); 287 } 288 289 @Override getHistoryCollection()290 public TestResultHistoryCollection getHistoryCollection() { return mHistoryCollection; } 291 292 @Override onCreate(Bundle savedInstanceState)293 protected void onCreate(Bundle savedInstanceState) { 294 super.onCreate(savedInstanceState); 295 ActionBar actBar = getActionBar(); 296 if (actBar != null) { 297 actBar.setDisplayHomeAsUpEnabled(true); 298 } 299 } 300 301 @Override onOptionsItemSelected(MenuItem item)302 public boolean onOptionsItemSelected(MenuItem item) { 303 if (item.getItemId() == android.R.id.home) { 304 onBackPressed(); 305 return true; 306 } 307 return super.onOptionsItemSelected(item); 308 } 309 310 @Override recordTestResults()311 public void recordTestResults() { 312 // default - NOP 313 } 314 } /* class PassFailButtons.Activity */ 315 316 public static class ListActivity extends android.app.ListActivity implements PassFailActivity { 317 318 private final CtsVerifierReportLog mReportLog; 319 private final TestResultHistoryCollection mHistoryCollection; 320 ListActivity()321 public ListActivity() { 322 mHistoryCollection = new TestResultHistoryCollection(); 323 mReportLog = null; 324 } 325 326 @Override setPassFailButtonClickListeners()327 public void setPassFailButtonClickListeners() { 328 setPassFailClickListeners(this); 329 } 330 331 @Override setInfoResources(int titleId, int messageId, int viewId)332 public void setInfoResources(int titleId, int messageId, int viewId) { 333 setInfo(this, titleId, messageId, viewId); 334 } 335 336 @Override getPassButton()337 public View getPassButton() { 338 return getPassButtonView(this); 339 } 340 341 @Override onCreateDialog(int id, Bundle args)342 public Dialog onCreateDialog(int id, Bundle args) { 343 return createDialog(this, id, args); 344 } 345 346 @Override getTestId()347 public String getTestId() { 348 return setTestNameSuffix(sCurrentDisplayMode, getClass().getName()); 349 } 350 351 @Override getTestDetails()352 public String getTestDetails() { 353 return null; 354 } 355 356 @Override setTestResultAndFinish(boolean passed)357 public void setTestResultAndFinish(boolean passed) { 358 PassFailButtons.setTestResultAndFinishHelper( 359 this, getTestId(), getTestDetails(), passed, getReportLog(), 360 getHistoryCollection()); 361 } 362 363 @Override requiresReportLog()364 public boolean requiresReportLog() { 365 return false; 366 } 367 368 @Override getReportLog()369 public CtsVerifierReportLog getReportLog() { 370 return mReportLog; 371 } 372 373 /** 374 * @return The name of the file to store the (suite of) ReportLog information. 375 */ 376 @Override getReportFileName()377 public String getReportFileName() { return GENERAL_TESTS_REPORT_LOG_NAME; } 378 379 @Override getReportSectionName()380 public String getReportSectionName() { 381 return setTestNameSuffix(sCurrentDisplayMode, SECTION_UNDEFINED); 382 } 383 384 @Override getHistoryCollection()385 public TestResultHistoryCollection getHistoryCollection() { return mHistoryCollection; } 386 387 @Override onCreate(Bundle savedInstanceState)388 protected void onCreate(Bundle savedInstanceState) { 389 super.onCreate(savedInstanceState); 390 ActionBar actBar = getActionBar(); 391 if (actBar != null) { 392 actBar.setDisplayHomeAsUpEnabled(true); 393 } 394 } 395 396 @Override onOptionsItemSelected(MenuItem item)397 public boolean onOptionsItemSelected(MenuItem item) { 398 if (item.getItemId() == android.R.id.home) { 399 onBackPressed(); 400 return true; 401 } 402 return super.onOptionsItemSelected(item); 403 } 404 405 @Override recordTestResults()406 public void recordTestResults() { 407 // default - NOP 408 } 409 } // class PassFailButtons.ListActivity 410 411 public static class TestListActivity extends AbstractTestListActivity 412 implements PassFailActivity { 413 414 private final CtsVerifierReportLog mReportLog; 415 TestListActivity()416 public TestListActivity() { 417 // TODO(b/186555602): temporary hack^H^H^H^H workaround to fix crash 418 // This DOES NOT in fact fix that bug. 419 // if (true) this.mReportLog = new CtsVerifierReportLog(b/186555602, "42"); else 420 421 this.mReportLog = new CtsVerifierReportLog(getReportFileName(), getReportSectionName()); 422 } 423 424 @Override setPassFailButtonClickListeners()425 public void setPassFailButtonClickListeners() { 426 setPassFailClickListeners(this); 427 } 428 429 @Override setInfoResources(int titleId, int messageId, int viewId)430 public void setInfoResources(int titleId, int messageId, int viewId) { 431 setInfo(this, titleId, messageId, viewId); 432 } 433 434 @Override getPassButton()435 public View getPassButton() { 436 return getPassButtonView(this); 437 } 438 439 @Override onCreateDialog(int id, Bundle args)440 public Dialog onCreateDialog(int id, Bundle args) { 441 return createDialog(this, id, args); 442 } 443 444 @Override getTestId()445 public String getTestId() { 446 return setTestNameSuffix(sCurrentDisplayMode, getClass().getName()); 447 } 448 449 @Override getTestDetails()450 public String getTestDetails() { 451 return null; 452 } 453 454 @Override setTestResultAndFinish(boolean passed)455 public void setTestResultAndFinish(boolean passed) { 456 PassFailButtons.setTestResultAndFinishHelper( 457 this, getTestId(), getTestDetails(), passed, getReportLog(), 458 getHistoryCollection()); 459 } 460 461 @Override requiresReportLog()462 public boolean requiresReportLog() { 463 return false; 464 } 465 466 @Override getReportLog()467 public CtsVerifierReportLog getReportLog() { 468 return mReportLog; 469 } 470 471 /** 472 * @return The name of the file to store the (suite of) ReportLog information. 473 */ 474 @Override getReportFileName()475 public String getReportFileName() { return GENERAL_TESTS_REPORT_LOG_NAME; } 476 477 @Override getReportSectionName()478 public String getReportSectionName() { 479 return setTestNameSuffix(sCurrentDisplayMode, SECTION_UNDEFINED); 480 } 481 482 483 /** 484 * Get existing test history to aggregate. 485 */ 486 @Override getHistoryCollection()487 public TestResultHistoryCollection getHistoryCollection() { 488 List<TestResultHistoryCollection> histories = 489 IntStream.range(0, mAdapter.getCount()) 490 .mapToObj(mAdapter::getHistoryCollection) 491 .collect(Collectors.toList()); 492 TestResultHistoryCollection historyCollection = new TestResultHistoryCollection(); 493 historyCollection.merge(getTestId(), histories); 494 return historyCollection; 495 } 496 updatePassButton()497 public void updatePassButton() { 498 getPassButton().setEnabled(mAdapter.allTestsPassed()); 499 } 500 501 @Override onCreate(Bundle savedInstanceState)502 protected void onCreate(Bundle savedInstanceState) { 503 super.onCreate(savedInstanceState); 504 ActionBar actBar = getActionBar(); 505 if (actBar != null) { 506 actBar.setDisplayHomeAsUpEnabled(true); 507 } 508 } 509 510 @Override onOptionsItemSelected(MenuItem item)511 public boolean onOptionsItemSelected(MenuItem item) { 512 if (item.getItemId() == android.R.id.home) { 513 onBackPressed(); 514 return true; 515 } 516 return super.onOptionsItemSelected(item); 517 } 518 519 @Override recordTestResults()520 public void recordTestResults() { 521 // default - NOP 522 } 523 } // class PassFailButtons.TestListActivity 524 525 protected static <T extends android.app.Activity & PassFailActivity> setPassFailClickListeners(final T activity)526 void setPassFailClickListeners(final T activity) { 527 View.OnClickListener clickListener = new View.OnClickListener() { 528 @Override 529 public void onClick(View target) { 530 setTestResultAndFinish(activity, activity.getTestId(), activity.getTestDetails(), 531 activity.getReportLog(), activity.getHistoryCollection(), target); 532 } 533 }; 534 535 View passButton = activity.findViewById(R.id.pass_button); 536 passButton.setOnClickListener(clickListener); 537 passButton.setOnLongClickListener(new View.OnLongClickListener() { 538 @Override 539 public boolean onLongClick(View view) { 540 Toast.makeText(activity, R.string.pass_button_text, Toast.LENGTH_SHORT).show(); 541 return true; 542 } 543 }); 544 545 View failButton = activity.findViewById(R.id.fail_button); 546 failButton.setOnClickListener(clickListener); 547 failButton.setOnLongClickListener(new View.OnLongClickListener() { 548 @Override 549 public boolean onLongClick(View view) { 550 Toast.makeText(activity, R.string.fail_button_text, Toast.LENGTH_SHORT).show(); 551 return true; 552 } 553 }); 554 } // class PassFailButtons.<T extends android.app.Activity & PassFailActivity> 555 setInfo(final android.app.Activity activity, final int titleId, final int messageId, final int viewId)556 protected static void setInfo(final android.app.Activity activity, final int titleId, 557 final int messageId, final int viewId) { 558 // Show the middle "info" button and make it show the info dialog when clicked. 559 View infoButton = activity.findViewById(R.id.info_button); 560 infoButton.setVisibility(View.VISIBLE); 561 infoButton.setOnClickListener(new OnClickListener() { 562 @Override 563 public void onClick(View view) { 564 showInfoDialog(activity, titleId, messageId, viewId); 565 } 566 }); 567 infoButton.setOnLongClickListener(new View.OnLongClickListener() { 568 @Override 569 public boolean onLongClick(View view) { 570 Toast.makeText(activity, R.string.info_button_text, Toast.LENGTH_SHORT).show(); 571 return true; 572 } 573 }); 574 575 // Show the info dialog if the user has never seen it before. 576 if (!hasSeenInfoDialog(activity)) { 577 showInfoDialog(activity, titleId, messageId, viewId); 578 } 579 } 580 hasSeenInfoDialog(android.app.Activity activity)581 protected static boolean hasSeenInfoDialog(android.app.Activity activity) { 582 ContentResolver resolver = activity.getContentResolver(); 583 Cursor cursor = null; 584 try { 585 cursor = resolver.query(TestResultsProvider.getTestNameUri(activity), 586 new String[] {TestResultsProvider.COLUMN_TEST_INFO_SEEN}, null, null, null); 587 return cursor.moveToFirst() && cursor.getInt(0) > 0; 588 } finally { 589 if (cursor != null) { 590 cursor.close(); 591 } 592 } 593 } 594 showInfoDialog(final android.app.Activity activity, int titleId, int messageId, int viewId)595 protected static void showInfoDialog(final android.app.Activity activity, int titleId, 596 int messageId, int viewId) { 597 Bundle args = new Bundle(); 598 args.putInt(INFO_DIALOG_TITLE_ID, titleId); 599 args.putInt(INFO_DIALOG_MESSAGE_ID, messageId); 600 args.putInt(INFO_DIALOG_VIEW_ID, viewId); 601 activity.showDialog(INFO_DIALOG_ID, args); 602 } 603 showReportLogWarningDialog(final android.app.Activity activity)604 protected static void showReportLogWarningDialog(final android.app.Activity activity) { 605 Bundle args = new Bundle(); 606 args.putInt(INFO_DIALOG_TITLE_ID, R.string.reportlog_warning_title); 607 args.putInt(INFO_DIALOG_MESSAGE_ID, R.string.reportlog_warning_body); 608 args.putInt(INFO_DIALOG_VIEW_ID, -1); 609 activity.showDialog(REPORTLOG_DIALOG_ID, args); 610 } 611 createDialog(final android.app.Activity activity, int id, Bundle args)612 protected static Dialog createDialog(final android.app.Activity activity, int id, Bundle args) { 613 switch (id) { 614 case INFO_DIALOG_ID: 615 case REPORTLOG_DIALOG_ID: 616 return createInfoDialog(activity, id, args); 617 default: 618 throw new IllegalArgumentException("Bad dialog id: " + id); 619 } 620 } 621 createInfoDialog(final android.app.Activity activity, int id, Bundle args)622 protected static Dialog createInfoDialog(final android.app.Activity activity, int id, 623 Bundle args) { 624 int viewId = args.getInt(INFO_DIALOG_VIEW_ID); 625 int titleId = args.getInt(INFO_DIALOG_TITLE_ID); 626 int messageId = args.getInt(INFO_DIALOG_MESSAGE_ID); 627 628 AlertDialog.Builder builder = new AlertDialog.Builder(activity).setIcon( 629 android.R.drawable.ic_dialog_info).setTitle(titleId); 630 if (viewId > 0) { 631 LayoutInflater inflater = (LayoutInflater) activity 632 .getSystemService(Context.LAYOUT_INFLATER_SERVICE); 633 builder.setView(inflater.inflate(viewId, null)); 634 } else { 635 builder.setMessage(messageId); 636 } 637 builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { 638 @Override 639 public void onClick(DialogInterface dialog, int which) { 640 markSeenInfoDialog(activity); 641 } 642 }).setOnCancelListener(new OnCancelListener() { 643 @Override 644 public void onCancel(DialogInterface dialog) { 645 markSeenInfoDialog(activity); 646 } 647 }); 648 return builder.create(); 649 } 650 markSeenInfoDialog(android.app.Activity activity)651 protected static void markSeenInfoDialog(android.app.Activity activity) { 652 ContentResolver resolver = activity.getContentResolver(); 653 ContentValues values = new ContentValues(2); 654 String activityName = setTestNameSuffix(sCurrentDisplayMode, activity.getClass().getName()); 655 values.put(TestResultsProvider.COLUMN_TEST_NAME, activityName); 656 values.put(TestResultsProvider.COLUMN_TEST_INFO_SEEN, 1); 657 int numUpdated = resolver.update( 658 TestResultsProvider.getTestNameUri(activity), values, null, null); 659 if (numUpdated == 0) { 660 resolver.insert(TestResultsProvider.getResultContentUri(activity), values); 661 } 662 } 663 664 /** Set the test result corresponding to the button clicked and finish the activity. */ setTestResultAndFinish(android.app.Activity activity, String testId, String testDetails, ReportLog reportLog, TestResultHistoryCollection historyCollection, View target)665 protected static void setTestResultAndFinish(android.app.Activity activity, String testId, 666 String testDetails, ReportLog reportLog, TestResultHistoryCollection historyCollection, 667 View target) { 668 669 boolean passed; 670 if (target.getId() == R.id.pass_button) { 671 passed = true; 672 } else if (target.getId() == R.id.fail_button) { 673 passed = false; 674 } else { 675 throw new IllegalArgumentException("Unknown id: " + target.getId()); 676 } 677 678 // Let test classes record their CTSVerifierReportLogs 679 ((PassFailActivity) activity).recordTestResults(); 680 681 setTestResultAndFinishHelper(activity, testId, testDetails, passed, reportLog, historyCollection); 682 } 683 684 /** Set the test result and finish the activity. */ setTestResultAndFinishHelper(android.app.Activity activity, String testId, String testDetails, boolean passed, ReportLog reportLog, TestResultHistoryCollection historyCollection)685 protected static void setTestResultAndFinishHelper(android.app.Activity activity, String testId, 686 String testDetails, boolean passed, ReportLog reportLog, 687 TestResultHistoryCollection historyCollection) { 688 if (passed) { 689 TestResult.setPassedResult(activity, testId, testDetails, reportLog, historyCollection); 690 } else { 691 TestResult.setFailedResult(activity, testId, testDetails, reportLog, historyCollection); 692 } 693 694 // We store results here straight into the content provider so it can be fetched by the 695 // CTSInteractive host 696 TestResultsProvider.setTestResult( 697 activity, testId, passed ? 1 : 2, testDetails, reportLog, historyCollection, 698 null); 699 700 activity.finish(); 701 } 702 getPassButtonView(android.app.Activity activity)703 protected static ImageButton getPassButtonView(android.app.Activity activity) { 704 return (ImageButton) activity.findViewById(R.id.pass_button); 705 } 706 707 } // class PassFailButtons 708