blob: d871a2ba1a73eae3e81f9d434370f00e81acfe5f [file] [log] [blame]
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.jobscheduler.cts;
import static android.jobscheduler.cts.jobtestapp.TestJobService.ACTION_JOB_STARTED;
import static android.jobscheduler.cts.jobtestapp.TestJobService.ACTION_JOB_STOPPED;
import static android.jobscheduler.cts.jobtestapp.TestJobService.JOB_PARAMS_EXTRA_KEY;
import static android.server.wm.WindowManagerState.STATE_RESUMED;
import android.app.job.JobParameters;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.jobscheduler.cts.jobtestapp.TestActivity;
import android.jobscheduler.cts.jobtestapp.TestJobSchedulerReceiver;
import android.os.SystemClock;
import android.server.wm.WindowManagerStateHelper;
import android.util.Log;
/**
* Common functions to interact with the test app.
*/
class TestAppInterface {
private static final String TAG = TestAppInterface.class.getSimpleName();
static final String TEST_APP_PACKAGE = "android.jobscheduler.cts.jobtestapp";
private static final String TEST_APP_ACTIVITY = TEST_APP_PACKAGE + ".TestActivity";
static final String TEST_APP_RECEIVER = TEST_APP_PACKAGE + ".TestJobSchedulerReceiver";
private final Context mContext;
private final int mJobId;
/* accesses must be synchronized on itself */
private final TestJobStatus mTestJobStatus = new TestJobStatus();
TestAppInterface(Context ctx, int jobId) {
mContext = ctx;
mJobId = jobId;
final IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(ACTION_JOB_STARTED);
intentFilter.addAction(ACTION_JOB_STOPPED);
mContext.registerReceiver(mReceiver, intentFilter);
}
void cleanup() {
final Intent cancelJobsIntent = new Intent(TestJobSchedulerReceiver.ACTION_CANCEL_JOBS);
cancelJobsIntent.setComponent(new ComponentName(TEST_APP_PACKAGE, TEST_APP_RECEIVER));
cancelJobsIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mContext.sendBroadcast(cancelJobsIntent);
mContext.sendBroadcast(new Intent(TestActivity.ACTION_FINISH_ACTIVITY));
mContext.unregisterReceiver(mReceiver);
mTestJobStatus.reset();
}
void scheduleJob(boolean allowWhileIdle, boolean needNetwork) {
final Intent scheduleJobIntent = new Intent(TestJobSchedulerReceiver.ACTION_SCHEDULE_JOB);
scheduleJobIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
scheduleJobIntent.putExtra(TestJobSchedulerReceiver.EXTRA_JOB_ID_KEY, mJobId);
scheduleJobIntent.putExtra(TestJobSchedulerReceiver.EXTRA_ALLOW_IN_IDLE, allowWhileIdle);
scheduleJobIntent.putExtra(TestJobSchedulerReceiver.EXTRA_REQUIRE_NETWORK_ANY, needNetwork);
scheduleJobIntent.setComponent(new ComponentName(TEST_APP_PACKAGE, TEST_APP_RECEIVER));
mContext.sendBroadcast(scheduleJobIntent);
}
void startAndKeepTestActivity() {
startAndKeepTestActivity(false);
}
void startAndKeepTestActivity(boolean waitForResume) {
final Intent testActivity = new Intent();
testActivity.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
ComponentName testComponentName = new ComponentName(TEST_APP_PACKAGE, TEST_APP_ACTIVITY);
testActivity.setComponent(testComponentName);
mContext.startActivity(testActivity);
if (waitForResume) {
new WindowManagerStateHelper().waitForActivityState(testComponentName, STATE_RESUMED);
}
}
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "Received action " + intent.getAction());
switch (intent.getAction()) {
case ACTION_JOB_STARTED:
case ACTION_JOB_STOPPED:
final JobParameters params = intent.getParcelableExtra(JOB_PARAMS_EXTRA_KEY);
Log.d(TAG, "JobId: " + params.getJobId());
synchronized (mTestJobStatus) {
mTestJobStatus.running = ACTION_JOB_STARTED.equals(intent.getAction());
mTestJobStatus.jobId = params.getJobId();
}
break;
}
}
};
boolean awaitJobStart(long maxWait) throws Exception {
return waitUntilTrue(maxWait, () -> {
synchronized (mTestJobStatus) {
return (mTestJobStatus.jobId == mJobId) && mTestJobStatus.running;
}
});
}
boolean awaitJobStop(long maxWait) throws Exception {
return waitUntilTrue(maxWait, () -> {
synchronized (mTestJobStatus) {
return (mTestJobStatus.jobId == mJobId) && !mTestJobStatus.running;
}
});
}
private boolean waitUntilTrue(long maxWait, Condition condition) throws Exception {
final long deadLine = SystemClock.uptimeMillis() + maxWait;
do {
Thread.sleep(500);
} while (!condition.isTrue() && SystemClock.uptimeMillis() < deadLine);
return condition.isTrue();
}
private static final class TestJobStatus {
int jobId;
boolean running;
private void reset() {
running = false;
}
}
private interface Condition {
boolean isTrue() throws Exception;
}
}