Home | History | Annotate | Download | only in jobscheduler
      1 package com.android.cts.verifier.jobscheduler;
      2 
      3 import android.annotation.TargetApi;
      4 import android.app.job.JobInfo;
      5 import android.app.job.JobScheduler;
      6 import android.content.BroadcastReceiver;
      7 import android.content.Context;
      8 import android.content.Intent;
      9 import android.content.IntentFilter;
     10 import android.os.AsyncTask;
     11 import android.os.Bundle;
     12 import android.os.BatteryManager;
     13 import android.widget.Button;
     14 import android.widget.ImageView;
     15 import android.widget.TextView;
     16 import android.view.View;
     17 
     18 import com.android.cts.verifier.R;
     19 import com.android.cts.verifier.TimerProgressBar;
     20 
     21 /**
     22  *  This activity runs the following tests:
     23  *     - Ask the tester to ensure the phone is plugged in, and verify that jobs with charging
     24  *      constraints are run.
     25  *     - Ask the tester to unplug the phone, and verify that jobs with charging constraints will
     26  *      not run.
     27  */
     28 @TargetApi(21)
     29 public class ChargingConstraintTestActivity extends ConstraintTestActivity {
     30 
     31     private static final int ON_CHARGING_JOB_ID =
     32             ChargingConstraintTestActivity.class.hashCode() + 0;
     33     private static final int OFF_CHARGING_JOB_ID =
     34             ChargingConstraintTestActivity.class.hashCode() + 1;
     35 
     36     // Time in milliseconds to wait after power is connected for the phone
     37     // to get into charging mode.
     38     private static final long WAIT_FOR_CHARGING_DURATION = 3 * 60 * 1000;
     39 
     40     private static final int STATE_NOT_RUNNING = 0;
     41     private static final int STATE_WAITING_TO_START_ON_CHARGING_TEST = 1;
     42     private static final int STATE_ON_CHARGING_TEST_PASSED = 2;
     43 
     44     private int mTestState;
     45     TimerProgressBar mWaitingForChargingProgressBar;
     46     TextView mWaitingForChargingTextView;
     47     TextView mProblemWithChargerTextView;
     48 
     49     @Override
     50     protected void onCreate(Bundle savedInstanceState) {
     51         super.onCreate(savedInstanceState);
     52 
     53         // Set up the UI.
     54         setContentView(R.layout.js_charging);
     55         setPassFailButtonClickListeners();
     56         setInfoResources(R.string.js_charging_test, R.string.js_charging_instructions, -1);
     57         mStartButton = (Button) findViewById(R.id.js_charging_start_test_button);
     58         mWaitingForChargingProgressBar = (TimerProgressBar) findViewById(
     59             R.id.js_waiting_for_charging_progress_bar);
     60         mWaitingForChargingTextView = (TextView) findViewById(
     61             R.id.js_waiting_for_charging_text_view);
     62         mProblemWithChargerTextView = (TextView) findViewById(
     63             R.id.js_problem_with_charger_text_view);
     64 
     65         if (isDevicePluggedIn()){
     66             mStartButton.setEnabled(true);
     67         }
     68 
     69         if (!deviceHasBattery()) {
     70             // This device has hardwired power, so do not prompt about connecting
     71             // or disconnecting the charger, and ignore the "no power" test.
     72             findViewById(R.id.charger_prompt).setVisibility(View.GONE);
     73             findViewById(R.id.unplug_prompt).setVisibility(View.GONE);
     74             findViewById(R.id.unplug_test_description).setVisibility(View.GONE);
     75         }
     76 
     77         hideWaitingForStableChargingViews();
     78 
     79         mTestState = STATE_NOT_RUNNING;
     80 
     81         mJobScheduler = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);
     82 
     83         // Register receiver for connected/disconnected power events.
     84         IntentFilter intentFilter = new IntentFilter();
     85         intentFilter.addAction(Intent.ACTION_POWER_CONNECTED);
     86         intentFilter.addAction(Intent.ACTION_POWER_DISCONNECTED);
     87         intentFilter.addAction(BatteryManager.ACTION_CHARGING);
     88         intentFilter.addAction(BatteryManager.ACTION_DISCHARGING);
     89 
     90         registerReceiver(mChargingChangedReceiver, intentFilter);
     91     }
     92 
     93     @Override
     94     protected void onDestroy() {
     95         super.onDestroy();
     96         unregisterReceiver(mChargingChangedReceiver);
     97     }
     98 
     99     private boolean deviceHasBattery() {
    100         final Intent batteryInfo = registerReceiver(null,
    101                 new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
    102         return batteryInfo.getBooleanExtra(BatteryManager.EXTRA_PRESENT, true);
    103     }
    104 
    105     private boolean isDevicePluggedIn() {
    106         IntentFilter ifilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
    107         Intent batteryStatus = registerReceiver(null, ifilter);
    108         int status = batteryStatus.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
    109         // 0 indicates device is on battery power
    110         return status != 0;
    111     }
    112 
    113     @Override
    114     public void startTestImpl() {
    115         BatteryManager bm = (BatteryManager) getSystemService(BATTERY_SERVICE);
    116         if (bm.isCharging()) {
    117             new TestDevicePluggedInConstraint().execute();
    118         } else if (isDevicePluggedIn()) {
    119             mTestState = STATE_WAITING_TO_START_ON_CHARGING_TEST;
    120             showWaitingForStableChargingViews();
    121         }
    122     }
    123 
    124     private BroadcastReceiver mChargingChangedReceiver = new BroadcastReceiver() {
    125         @Override
    126         public void onReceive(Context context, Intent intent) {
    127             if (BatteryManager.ACTION_CHARGING.equals(intent.getAction())) {
    128                 if (mTestState == STATE_WAITING_TO_START_ON_CHARGING_TEST) {
    129                     mWaitingForChargingProgressBar.forceComplete();
    130                     hideWaitingForStableChargingViews();
    131                     new TestDevicePluggedInConstraint().execute();
    132                 }
    133             } else if (BatteryManager.ACTION_DISCHARGING.equals(intent.getAction())) {
    134                 // ignore this [spurious!] broadcast on non-battery devices
    135                 if (deviceHasBattery()) {
    136                     if (mTestState == STATE_ON_CHARGING_TEST_PASSED) {
    137                         new TestDeviceUnpluggedConstraint().execute();
    138                     }
    139                 }
    140             } else if (Intent.ACTION_POWER_CONNECTED.equals(intent.getAction())) {
    141                 if (mTestState == STATE_WAITING_TO_START_ON_CHARGING_TEST) {
    142                     showWaitingForStableChargingViews();
    143                 } else if (mTestState == STATE_NOT_RUNNING) {
    144                     mStartButton.setEnabled(true);
    145                 }
    146                 mStartButton.setEnabled(true);
    147             } else if (Intent.ACTION_POWER_DISCONNECTED.equals(intent.getAction())) {
    148                 hideWaitingForStableChargingViews();
    149             }
    150         }
    151     };
    152 
    153     /** Simple state boolean we use to determine whether to continue with the second test. */
    154     private boolean mDeviceUnpluggedTestPassed = false;
    155 
    156     /**
    157      * Test blocks and can't be run on the main thread.
    158      */
    159     private void testChargingConstraintFails_notCharging() {
    160         mTestEnvironment.setUp();
    161 
    162         mTestEnvironment.setExpectedExecutions(0);
    163         JobInfo runOnCharge = new JobInfo.Builder(OFF_CHARGING_JOB_ID, mMockComponent)
    164                 .setRequiresCharging(true)
    165                 .build();
    166         mJobScheduler.schedule(runOnCharge);
    167 
    168         boolean testPassed;
    169         try {
    170             testPassed = mTestEnvironment.awaitTimeout();
    171         } catch (InterruptedException e) {
    172             testPassed = false;
    173         }
    174         runOnUiThread(new ChargingConstraintTestResultRunner(OFF_CHARGING_JOB_ID, testPassed));
    175     }
    176 
    177     /**
    178      * Test blocks and can't be run on the main thread.
    179      */
    180     private void testChargingConstraintExecutes_onCharging() {
    181         mTestEnvironment.setUp();
    182 
    183         JobInfo delayConstraintAndUnexpiredDeadline =
    184                 new JobInfo.Builder(ON_CHARGING_JOB_ID, mMockComponent)
    185                         .setRequiresCharging(true)
    186                         .build();
    187 
    188         mTestEnvironment.setExpectedExecutions(1);
    189         mJobScheduler.schedule(delayConstraintAndUnexpiredDeadline);
    190 
    191         boolean testPassed;
    192         try {
    193             testPassed = mTestEnvironment.awaitExecution();
    194         } catch (InterruptedException e) {
    195             testPassed = false;
    196         }
    197 
    198         mTestState = testPassed ? STATE_ON_CHARGING_TEST_PASSED : STATE_NOT_RUNNING;
    199         runOnUiThread(new ChargingConstraintTestResultRunner(ON_CHARGING_JOB_ID, testPassed));
    200     }
    201 
    202     /** Run test for when the <bold>device is not connected to power.</bold>. */
    203     private class TestDeviceUnpluggedConstraint extends AsyncTask<Void, Void, Void> {
    204         @Override
    205         protected Void doInBackground(Void... voids) {
    206             testChargingConstraintFails_notCharging();
    207             notifyTestCompleted();
    208             return null;
    209         }
    210 
    211         @Override
    212         protected void onPostExecute(Void res) {
    213             mTestState = STATE_NOT_RUNNING;
    214             mStartButton.setEnabled(true);
    215         }
    216     }
    217 
    218     /** Run test for when the <bold>device is connected to power.</bold> */
    219     private class TestDevicePluggedInConstraint extends AsyncTask<Void, Void, Void> {
    220         @Override
    221         protected Void doInBackground(Void... voids) {
    222             testChargingConstraintExecutes_onCharging();
    223             return null;
    224         }
    225     }
    226 
    227     private class ChargingConstraintTestResultRunner extends TestResultRunner {
    228         ChargingConstraintTestResultRunner(int jobId, boolean testPassed) {
    229             super(jobId, testPassed);
    230         }
    231 
    232         @Override
    233         public void run() {
    234             ImageView view;
    235             if (mJobId == OFF_CHARGING_JOB_ID) {
    236                 view = (ImageView) findViewById(R.id.charging_off_test_image);
    237             } else if (mJobId == ON_CHARGING_JOB_ID) {
    238                 view = (ImageView) findViewById(R.id.charging_on_test_image);
    239             } else {
    240                 noteInvalidTest();
    241                 return;
    242             }
    243             view.setImageResource(mTestPassed ? R.drawable.fs_good : R.drawable.fs_error);
    244         }
    245     }
    246 
    247     private void showWaitingForStableChargingViews() {
    248         mWaitingForChargingProgressBar.start(WAIT_FOR_CHARGING_DURATION, 1000,
    249             new TimerProgressBar.TimerExpiredCallback(){
    250                 @Override
    251                 public void onTimerExpired() {
    252                     mProblemWithChargerTextView.setVisibility(View.VISIBLE);
    253                 }
    254             }
    255         );
    256         mWaitingForChargingProgressBar.setVisibility(View.VISIBLE);
    257         mWaitingForChargingTextView.setVisibility(View.VISIBLE);
    258         mProblemWithChargerTextView.setVisibility(View.GONE);
    259     }
    260 
    261     private void hideWaitingForStableChargingViews() {
    262         mWaitingForChargingProgressBar.forceComplete();
    263         mWaitingForChargingProgressBar.setVisibility(View.GONE);
    264         mWaitingForChargingTextView.setVisibility(View.GONE);
    265         mProblemWithChargerTextView.setVisibility(View.GONE);
    266     }
    267 }
    268