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