1 package com.android.cts.verifier.jobscheduler; 2 3 import android.annotation.TargetApi; 4 import android.app.job.JobScheduler; 5 import android.content.BroadcastReceiver; 6 import android.content.ComponentName; 7 import android.content.Context; 8 import android.content.Intent; 9 import android.os.Bundle; 10 import android.view.View; 11 import android.widget.Button; 12 import android.widget.Toast; 13 14 import com.android.cts.verifier.PassFailButtons; 15 16 import java.util.concurrent.CountDownLatch; 17 import java.util.concurrent.TimeUnit; 18 19 @TargetApi(21) 20 public abstract class ConstraintTestActivity extends PassFailButtons.Activity { 21 /** 22 * Intent we use to force the job scheduler to consider any ready jobs that otherwise it may 23 * have decided to be lazy about. 24 */ 25 protected static final Intent EXPEDITE_STABLE_CHARGING = 26 new Intent("com.android.server.task.controllers.BatteryController.ACTION_CHARGING_STABLE"); 27 28 protected ComponentName mMockComponent; 29 30 protected MockJobService.TestEnvironment mTestEnvironment; 31 protected JobScheduler mJobScheduler; 32 33 /** Avoid cases where user might press "start test" more than once. */ 34 private boolean mTestInProgress; 35 /** 36 * Starts the test - set up by subclass, which also controls the logic for how/when the test 37 * can be started. 38 */ 39 protected Button mStartButton; 40 41 @Override onCreate(Bundle savedInstanceState)42 protected void onCreate(Bundle savedInstanceState) { 43 super.onCreate(savedInstanceState); 44 45 mJobScheduler = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE); 46 mMockComponent = new ComponentName(this, MockJobService.class); 47 mTestEnvironment = MockJobService.TestEnvironment.getTestEnvironment(); 48 } 49 50 /** OnClickListener for the "Start Test" ({@link #mStartButton}) button */ startTest(View v)51 public final void startTest(View v) { 52 if (mTestInProgress) { 53 Toast toast = 54 Toast.makeText( 55 ConstraintTestActivity.this, 56 "Test already in progress", 57 Toast.LENGTH_SHORT); 58 toast.show(); 59 return; 60 } else { 61 mTestInProgress = true; 62 startTestImpl(); 63 } 64 } 65 66 /** Called by subclasses to allow the user to rerun the test if necessary. */ notifyTestCompleted()67 protected final void notifyTestCompleted() { 68 mTestInProgress = false; 69 } 70 71 /** Implemented by subclasses to determine logic for running the test. */ startTestImpl()72 protected abstract void startTestImpl(); 73 74 /** 75 * Broadcast the provided intent, and register a receiver to notify us after the broadcast has 76 * been processed. 77 * This function will block until the broadcast comes back, and <bold>cannot</bold> be called 78 * on the main thread. 79 * @return True if we received the callback, false if not. 80 */ sendBroadcastAndBlockForResult(Intent intent)81 protected boolean sendBroadcastAndBlockForResult(Intent intent) { 82 final CountDownLatch latch = new CountDownLatch(1); 83 sendOrderedBroadcast(intent, null, new BroadcastReceiver() { 84 @Override 85 public void onReceive(Context context, Intent intent) { 86 latch.countDown(); 87 } 88 }, null, -1, null, null); 89 try { 90 return latch.await(5, TimeUnit.SECONDS); 91 } catch (InterruptedException e) { 92 return false; 93 } 94 } 95 96 /** Extended by test activities to report results of a test. */ 97 protected abstract class TestResultRunner implements Runnable { 98 final int mJobId; 99 final boolean mTestPassed; 100 TestResultRunner(int jobId, boolean testPassed)101 TestResultRunner(int jobId, boolean testPassed) { 102 mJobId = jobId; 103 mTestPassed = testPassed; 104 } noteInvalidTest()105 protected void noteInvalidTest() { 106 final Toast toast = 107 Toast.makeText( 108 ConstraintTestActivity.this, 109 "Invalid result returned from test thread: job=" + mJobId + ", res=" 110 + mTestPassed, 111 Toast.LENGTH_SHORT); 112 toast.show(); 113 } 114 } 115 } 116