| package com.android.cts.verifier.jobscheduler; |
| |
| import android.annotation.TargetApi; |
| import android.app.job.JobInfo; |
| import android.app.job.JobScheduler; |
| import android.content.BroadcastReceiver; |
| import android.content.Context; |
| import android.content.Intent; |
| import android.content.IntentFilter; |
| import android.os.AsyncTask; |
| import android.os.Bundle; |
| import android.os.BatteryManager; |
| import android.widget.Button; |
| import android.widget.ImageView; |
| import android.widget.TextView; |
| import android.view.View; |
| |
| import com.android.cts.verifier.R; |
| import com.android.cts.verifier.TimerProgressBar; |
| |
| /** |
| * This activity runs the following tests: |
| * - Ask the tester to ensure the phone is plugged in, and verify that jobs with charging |
| * constraints are run. |
| * - Ask the tester to unplug the phone, and verify that jobs with charging constraints will |
| * not run. |
| */ |
| @TargetApi(21) |
| public class ChargingConstraintTestActivity extends ConstraintTestActivity { |
| |
| private static final int ON_CHARGING_JOB_ID = |
| ChargingConstraintTestActivity.class.hashCode() + 0; |
| private static final int OFF_CHARGING_JOB_ID = |
| ChargingConstraintTestActivity.class.hashCode() + 1; |
| |
| // Time in milliseconds to wait after power is connected for the phone |
| // to get into charging mode. |
| private static final long WAIT_FOR_CHARGING_DURATION = 3 * 60 * 1000; |
| |
| private static final int STATE_NOT_RUNNING = 0; |
| private static final int STATE_WAITING_TO_START_ON_CHARGING_TEST = 1; |
| private static final int STATE_ON_CHARGING_TEST_PASSED = 2; |
| |
| private int mTestState; |
| TimerProgressBar mWaitingForChargingProgressBar; |
| TextView mWaitingForChargingTextView; |
| TextView mProblemWithChargerTextView; |
| |
| @Override |
| protected void onCreate(Bundle savedInstanceState) { |
| super.onCreate(savedInstanceState); |
| |
| // Set up the UI. |
| setContentView(R.layout.js_charging); |
| setPassFailButtonClickListeners(); |
| setInfoResources(R.string.js_charging_test, R.string.js_charging_instructions, -1); |
| mStartButton = (Button) findViewById(R.id.js_charging_start_test_button); |
| mWaitingForChargingProgressBar = (TimerProgressBar) findViewById( |
| R.id.js_waiting_for_charging_progress_bar); |
| mWaitingForChargingTextView = (TextView) findViewById( |
| R.id.js_waiting_for_charging_text_view); |
| mProblemWithChargerTextView = (TextView) findViewById( |
| R.id.js_problem_with_charger_text_view); |
| |
| if (isDevicePluggedIn()){ |
| mStartButton.setEnabled(true); |
| } |
| |
| hideWaitingForStableChargingViews(); |
| |
| mTestState = STATE_NOT_RUNNING; |
| |
| mJobScheduler = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE); |
| |
| // Register receiver for connected/disconnected power events. |
| IntentFilter intentFilter = new IntentFilter(); |
| intentFilter.addAction(Intent.ACTION_POWER_CONNECTED); |
| intentFilter.addAction(Intent.ACTION_POWER_DISCONNECTED); |
| intentFilter.addAction(BatteryManager.ACTION_CHARGING); |
| intentFilter.addAction(BatteryManager.ACTION_DISCHARGING); |
| |
| registerReceiver(mChargingChangedReceiver, intentFilter); |
| } |
| |
| @Override |
| protected void onDestroy() { |
| super.onDestroy(); |
| unregisterReceiver(mChargingChangedReceiver); |
| } |
| |
| private boolean isDevicePluggedIn() { |
| IntentFilter ifilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED); |
| Intent batteryStatus = registerReceiver(null, ifilter); |
| int status = batteryStatus.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1); |
| // 0 indicates device is on battery power |
| return status != 0; |
| } |
| |
| @Override |
| public void startTestImpl() { |
| BatteryManager bm = (BatteryManager) getSystemService(BATTERY_SERVICE); |
| if (bm.isCharging()) { |
| new TestDevicePluggedInConstraint().execute(); |
| } else if (isDevicePluggedIn()) { |
| mTestState = STATE_WAITING_TO_START_ON_CHARGING_TEST; |
| showWaitingForStableChargingViews(); |
| } |
| } |
| |
| private BroadcastReceiver mChargingChangedReceiver = new BroadcastReceiver() { |
| @Override |
| public void onReceive(Context context, Intent intent) { |
| if (BatteryManager.ACTION_CHARGING.equals(intent.getAction())) { |
| if (mTestState == STATE_WAITING_TO_START_ON_CHARGING_TEST) { |
| mWaitingForChargingProgressBar.forceComplete(); |
| hideWaitingForStableChargingViews(); |
| new TestDevicePluggedInConstraint().execute(); |
| } |
| } else if (BatteryManager.ACTION_DISCHARGING.equals(intent.getAction())) { |
| if (mTestState == STATE_ON_CHARGING_TEST_PASSED) { |
| new TestDeviceUnpluggedConstraint().execute(); |
| } |
| } else if (Intent.ACTION_POWER_CONNECTED.equals(intent.getAction())) { |
| if (mTestState == STATE_WAITING_TO_START_ON_CHARGING_TEST) { |
| showWaitingForStableChargingViews(); |
| } else if (mTestState == STATE_NOT_RUNNING) { |
| mStartButton.setEnabled(true); |
| } |
| mStartButton.setEnabled(true); |
| } else if (Intent.ACTION_POWER_DISCONNECTED.equals(intent.getAction())) { |
| hideWaitingForStableChargingViews(); |
| } |
| } |
| }; |
| |
| /** Simple state boolean we use to determine whether to continue with the second test. */ |
| private boolean mDeviceUnpluggedTestPassed = false; |
| |
| /** |
| * Test blocks and can't be run on the main thread. |
| */ |
| private void testChargingConstraintFails_notCharging() { |
| mTestEnvironment.setUp(); |
| |
| mTestEnvironment.setExpectedExecutions(0); |
| JobInfo runOnCharge = new JobInfo.Builder(OFF_CHARGING_JOB_ID, mMockComponent) |
| .setRequiresCharging(true) |
| .build(); |
| mJobScheduler.schedule(runOnCharge); |
| |
| boolean testPassed; |
| try { |
| testPassed = mTestEnvironment.awaitTimeout(); |
| } catch (InterruptedException e) { |
| testPassed = false; |
| } |
| runOnUiThread(new ChargingConstraintTestResultRunner(OFF_CHARGING_JOB_ID, testPassed)); |
| } |
| |
| /** |
| * Test blocks and can't be run on the main thread. |
| */ |
| private void testChargingConstraintExecutes_onCharging() { |
| mTestEnvironment.setUp(); |
| |
| JobInfo delayConstraintAndUnexpiredDeadline = |
| new JobInfo.Builder(ON_CHARGING_JOB_ID, mMockComponent) |
| .setRequiresCharging(true) |
| .build(); |
| |
| mTestEnvironment.setExpectedExecutions(1); |
| mJobScheduler.schedule(delayConstraintAndUnexpiredDeadline); |
| |
| boolean testPassed; |
| try { |
| testPassed = mTestEnvironment.awaitExecution(); |
| } catch (InterruptedException e) { |
| testPassed = false; |
| } |
| |
| mTestState = testPassed ? STATE_ON_CHARGING_TEST_PASSED : STATE_NOT_RUNNING; |
| runOnUiThread(new ChargingConstraintTestResultRunner(ON_CHARGING_JOB_ID, testPassed)); |
| } |
| |
| /** Run test for when the <bold>device is not connected to power.</bold>. */ |
| private class TestDeviceUnpluggedConstraint extends AsyncTask<Void, Void, Void> { |
| @Override |
| protected Void doInBackground(Void... voids) { |
| testChargingConstraintFails_notCharging(); |
| notifyTestCompleted(); |
| return null; |
| } |
| |
| @Override |
| protected void onPostExecute(Void res) { |
| mTestState = STATE_NOT_RUNNING; |
| mStartButton.setEnabled(true); |
| } |
| } |
| |
| /** Run test for when the <bold>device is connected to power.</bold> */ |
| private class TestDevicePluggedInConstraint extends AsyncTask<Void, Void, Void> { |
| @Override |
| protected Void doInBackground(Void... voids) { |
| testChargingConstraintExecutes_onCharging(); |
| return null; |
| } |
| } |
| |
| private class ChargingConstraintTestResultRunner extends TestResultRunner { |
| ChargingConstraintTestResultRunner(int jobId, boolean testPassed) { |
| super(jobId, testPassed); |
| } |
| |
| @Override |
| public void run() { |
| ImageView view; |
| if (mJobId == OFF_CHARGING_JOB_ID) { |
| view = (ImageView) findViewById(R.id.charging_off_test_image); |
| } else if (mJobId == ON_CHARGING_JOB_ID) { |
| view = (ImageView) findViewById(R.id.charging_on_test_image); |
| } else { |
| noteInvalidTest(); |
| return; |
| } |
| view.setImageResource(mTestPassed ? R.drawable.fs_good : R.drawable.fs_error); |
| } |
| } |
| |
| private void showWaitingForStableChargingViews() { |
| mWaitingForChargingProgressBar.start(WAIT_FOR_CHARGING_DURATION, 1000, |
| new TimerProgressBar.TimerExpiredCallback(){ |
| @Override |
| public void onTimerExpired() { |
| mProblemWithChargerTextView.setVisibility(View.VISIBLE); |
| } |
| } |
| ); |
| mWaitingForChargingProgressBar.setVisibility(View.VISIBLE); |
| mWaitingForChargingTextView.setVisibility(View.VISIBLE); |
| mProblemWithChargerTextView.setVisibility(View.GONE); |
| } |
| |
| private void hideWaitingForStableChargingViews() { |
| mWaitingForChargingProgressBar.forceComplete(); |
| mWaitingForChargingProgressBar.setVisibility(View.GONE); |
| mWaitingForChargingTextView.setVisibility(View.GONE); |
| mProblemWithChargerTextView.setVisibility(View.GONE); |
| } |
| } |