1 /* 2 * Copyright (C) 2021 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.job; 18 19 import android.annotation.TargetApi; 20 import android.app.job.JobInfo; 21 import android.app.job.JobScheduler; 22 import android.content.ComponentName; 23 import android.content.Context; 24 import android.os.DeviceIdleManager; 25 import android.test.AndroidTestCase; 26 27 import com.android.server.job.MockBiasJobService.TestEnvironment; 28 import com.android.server.job.MockBiasJobService.TestEnvironment.Event; 29 30 import java.util.ArrayList; 31 32 @TargetApi(24) 33 public class BiasSchedulingTest extends AndroidTestCase { 34 /** Environment that notifies of JobScheduler callbacks. */ 35 private static final TestEnvironment sTestEnvironment = TestEnvironment.getTestEnvironment(); 36 /** Handle for the service which receives the execution callbacks from the JobScheduler. */ 37 private static ComponentName sJobServiceComponent; 38 private JobScheduler mJobScheduler; 39 40 // The system overrides the test app bias to be a minimum of FOREGROUND_SERVICE. We can 41 // bypass that override by using a bias of at least bound foreground service. 42 private static final int HIGH_BIAS = JobInfo.BIAS_BOUND_FOREGROUND_SERVICE + 1; 43 private static final int LOW_BIAS = JobInfo.BIAS_BOUND_FOREGROUND_SERVICE; 44 45 @Override setUp()46 public void setUp() throws Exception { 47 super.setUp(); 48 sTestEnvironment.setUp(); 49 sJobServiceComponent = new ComponentName(getContext(), MockBiasJobService.class); 50 mJobScheduler = (JobScheduler) getContext().getSystemService(Context.JOB_SCHEDULER_SERVICE); 51 mJobScheduler.cancelAll(); 52 getContext().getSystemService(DeviceIdleManager.class).endIdle("BiasSchedulingTest"); 53 } 54 55 @Override tearDown()56 public void tearDown() throws Exception { 57 mJobScheduler.cancelAll(); 58 super.tearDown(); 59 } 60 testLowerBiasJobPreempted()61 public void testLowerBiasJobPreempted() throws Exception { 62 for (int i = 0; i < JobConcurrencyManager.MAX_CONCURRENCY_LIMIT; ++i) { 63 JobInfo job = new JobInfo.Builder(100 + i, sJobServiceComponent) 64 .setBias(LOW_BIAS) 65 .setOverrideDeadline(0) 66 .build(); 67 mJobScheduler.schedule(job); 68 } 69 final int higherBiasJobId = 100 + JobConcurrencyManager.MAX_CONCURRENCY_LIMIT; 70 JobInfo jobHigher = new JobInfo.Builder(higherBiasJobId, sJobServiceComponent) 71 .setBias(HIGH_BIAS) 72 .setMinimumLatency(2000) 73 .setOverrideDeadline(4000) 74 .build(); 75 mJobScheduler.schedule(jobHigher); 76 Thread.sleep(10000); // Wait for jobHigher to preempt one of the lower bias jobs 77 78 Event jobHigherExecution = new Event(TestEnvironment.EVENT_START_JOB, higherBiasJobId); 79 ArrayList<Event> executedEvents = sTestEnvironment.getExecutedEvents(); 80 boolean wasJobHigherExecuted = executedEvents.contains(jobHigherExecution); 81 boolean wasSomeJobPreempted = false; 82 for (Event event: executedEvents) { 83 if (event.event == TestEnvironment.EVENT_PREEMPT_JOB) { 84 wasSomeJobPreempted = true; 85 break; 86 } 87 } 88 assertTrue("No job was preempted.", wasSomeJobPreempted); 89 assertTrue("Lower bias jobs were not preempted.", wasJobHigherExecuted); 90 } 91 testHigherBiasJobNotPreempted()92 public void testHigherBiasJobNotPreempted() throws Exception { 93 for (int i = 0; i < JobConcurrencyManager.DEFAULT_CONCURRENCY_LIMIT; ++i) { 94 JobInfo job = new JobInfo.Builder(100 + i, sJobServiceComponent) 95 .setBias(HIGH_BIAS) 96 .setOverrideDeadline(0) 97 .build(); 98 mJobScheduler.schedule(job); 99 } 100 final int lowerBiasJobId = 100 + JobConcurrencyManager.DEFAULT_CONCURRENCY_LIMIT; 101 JobInfo jobLower = new JobInfo.Builder(lowerBiasJobId, sJobServiceComponent) 102 .setBias(LOW_BIAS) 103 .setMinimumLatency(2000) 104 .setOverrideDeadline(3000) 105 .build(); 106 mJobScheduler.schedule(jobLower); 107 Thread.sleep(10000); 108 109 Event jobLowerExecution = new Event(TestEnvironment.EVENT_START_JOB, lowerBiasJobId); 110 boolean wasLowerExecuted = sTestEnvironment.getExecutedEvents().contains(jobLowerExecution); 111 assertFalse("Higher bias job was preempted.", wasLowerExecuted); 112 } 113 } 114