1 /* 2 * Copyright (C) 2020 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 android.jobscheduler.cts; 18 19 import static android.app.job.Flags.FLAG_HANDLE_ABANDONED_JOBS; 20 21 import android.app.job.JobInfo; 22 import android.app.job.JobParameters; 23 import android.app.job.JobScheduler; 24 import android.content.ClipData; 25 import android.content.Intent; 26 import android.os.Bundle; 27 import android.os.PersistableBundle; 28 import android.os.UserHandle; 29 import android.platform.test.annotations.RequiresFlagsEnabled; 30 31 import androidx.test.InstrumentationRegistry; 32 33 import com.android.compatibility.common.util.BatteryUtils; 34 import com.android.compatibility.common.util.SystemUtil; 35 36 /** 37 * Tests related to JobParameters objects. 38 */ 39 public class JobParametersTest extends BaseJobSchedulerTest { 40 private static final int JOB_ID = JobParametersTest.class.hashCode(); 41 42 private NetworkingHelper mNetworkingHelper; 43 44 @Override setUp()45 public void setUp() throws Exception { 46 super.setUp(); 47 mNetworkingHelper = 48 new NetworkingHelper(InstrumentationRegistry.getInstrumentation(), mContext); 49 } 50 51 @Override tearDown()52 public void tearDown() throws Exception { 53 mNetworkingHelper.tearDown(); 54 super.tearDown(); 55 } 56 testClipData()57 public void testClipData() throws Exception { 58 final ClipData clipData = ClipData.newPlainText("test", "testText"); 59 final int grantFlags = Intent.FLAG_GRANT_READ_URI_PERMISSION; 60 JobInfo ji = new JobInfo.Builder(JOB_ID, kJobServiceComponent) 61 .setClipData(clipData, grantFlags) 62 .build(); 63 64 kTestEnvironment.setExpectedExecutions(1); 65 mJobScheduler.schedule(ji); 66 runSatisfiedJob(JOB_ID); 67 assertTrue("Job didn't fire immediately", kTestEnvironment.awaitExecution()); 68 69 JobParameters params = kTestEnvironment.getLastStartJobParameters(); 70 assertEquals(clipData.getItemCount(), params.getClipData().getItemCount()); 71 assertEquals(clipData.getItemAt(0).getText(), params.getClipData().getItemAt(0).getText()); 72 assertEquals(grantFlags, params.getClipGrantFlags()); 73 } 74 testExtras()75 public void testExtras() throws Exception { 76 final PersistableBundle pb = new PersistableBundle(); 77 pb.putInt("random_key", 42); 78 JobInfo ji = new JobInfo.Builder(JOB_ID, kJobServiceComponent) 79 .setExtras(pb) 80 .build(); 81 82 kTestEnvironment.setExpectedExecutions(1); 83 mJobScheduler.schedule(ji); 84 runSatisfiedJob(JOB_ID); 85 assertTrue("Job didn't fire immediately", kTestEnvironment.awaitExecution()); 86 87 JobParameters params = kTestEnvironment.getLastStartJobParameters(); 88 final PersistableBundle extras = params.getExtras(); 89 assertNotNull(extras); 90 assertEquals(1, extras.keySet().size()); 91 assertEquals(42, extras.getInt("random_key")); 92 } 93 testExpedited()94 public void testExpedited() throws Exception { 95 JobInfo ji = new JobInfo.Builder(JOB_ID, kJobServiceComponent) 96 .setExpedited(true) 97 .build(); 98 99 kTestEnvironment.setExpectedExecutions(1); 100 mJobScheduler.schedule(ji); 101 runSatisfiedJob(JOB_ID); 102 assertTrue("Job didn't fire immediately", kTestEnvironment.awaitExecution()); 103 104 JobParameters params = kTestEnvironment.getLastStartJobParameters(); 105 assertTrue(params.isExpeditedJob()); 106 107 ji = new JobInfo.Builder(JOB_ID, kJobServiceComponent) 108 .setExpedited(false) 109 .build(); 110 111 kTestEnvironment.setExpectedExecutions(1); 112 mJobScheduler.schedule(ji); 113 runSatisfiedJob(JOB_ID); 114 assertTrue("Job didn't fire immediately", kTestEnvironment.awaitExecution()); 115 116 params = kTestEnvironment.getLastStartJobParameters(); 117 assertFalse(params.isExpeditedJob()); 118 } 119 testUserInitiated()120 public void testUserInitiated() throws Exception { 121 mNetworkingHelper.setAllNetworksEnabled(true); 122 startAndKeepTestActivity(); 123 JobInfo ji = new JobInfo.Builder(JOB_ID, kJobServiceComponent) 124 .setUserInitiated(true) 125 .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY) 126 .build(); 127 128 kTestEnvironment.setExpectedExecutions(1); 129 mJobScheduler.schedule(ji); 130 runSatisfiedJob(JOB_ID); 131 assertTrue("Job didn't fire immediately", kTestEnvironment.awaitExecution()); 132 133 JobParameters params = kTestEnvironment.getLastStartJobParameters(); 134 assertTrue(params.isUserInitiatedJob()); 135 136 ji = new JobInfo.Builder(JOB_ID, kJobServiceComponent) 137 .setUserInitiated(false) 138 .build(); 139 140 kTestEnvironment.setExpectedExecutions(1); 141 mJobScheduler.schedule(ji); 142 runSatisfiedJob(JOB_ID); 143 assertTrue("Job didn't fire immediately", kTestEnvironment.awaitExecution()); 144 145 params = kTestEnvironment.getLastStartJobParameters(); 146 assertFalse(params.isUserInitiatedJob()); 147 } 148 testJobId()149 public void testJobId() throws Exception { 150 JobInfo ji = new JobInfo.Builder(JOB_ID, kJobServiceComponent) 151 .build(); 152 153 kTestEnvironment.setExpectedExecutions(1); 154 mJobScheduler.schedule(ji); 155 runSatisfiedJob(JOB_ID); 156 assertTrue("Job didn't fire immediately", kTestEnvironment.awaitExecution()); 157 158 JobParameters params = kTestEnvironment.getLastStartJobParameters(); 159 assertEquals(JOB_ID, params.getJobId()); 160 } 161 testNamespaceJobParameters()162 public void testNamespaceJobParameters() throws Exception { 163 JobScheduler jsA = mJobScheduler.forNamespace("A"); 164 JobScheduler jsB = mJobScheduler.forNamespace("B"); 165 JobInfo jobA = new JobInfo.Builder(JOB_ID, kJobServiceComponent) 166 .setExpedited(true) 167 .build(); 168 JobInfo jobB = new JobInfo.Builder(JOB_ID, kJobServiceComponent) 169 .setRequiresStorageNotLow(true) 170 .build(); 171 172 kTestEnvironment.setExpectedExecutions(1); 173 setStorageStateLow(true); 174 assertEquals(JobScheduler.RESULT_SUCCESS, jsA.schedule(jobA)); 175 assertEquals(JobScheduler.RESULT_SUCCESS, jsB.schedule(jobB)); 176 177 runSatisfiedJob(JOB_ID, "A"); 178 runSatisfiedJob(JOB_ID, "B"); 179 assertTrue("Job A didn't fire", kTestEnvironment.awaitExecution()); 180 JobParameters params = kTestEnvironment.getLastStartJobParameters(); 181 assertEquals("A", params.getJobNamespace()); 182 183 kTestEnvironment.setExpectedExecutions(1); 184 setStorageStateLow(false); 185 runSatisfiedJob(JOB_ID, "A"); 186 runSatisfiedJob(JOB_ID, "B"); 187 assertTrue("Job B didn't fire", kTestEnvironment.awaitExecution()); 188 params = kTestEnvironment.getLastStartJobParameters(); 189 assertEquals("B", params.getJobNamespace()); 190 } 191 192 // JobParameters.getNetwork() tested in ConnectivityConstraintTest. 193 testStopReason()194 public void testStopReason() throws Exception { 195 verifyStopReason(new JobInfo.Builder(JOB_ID, kJobServiceComponent).build(), 196 JobParameters.STOP_REASON_TIMEOUT, 197 () -> SystemUtil.runShellCommand(getInstrumentation(), 198 "cmd jobscheduler timeout" 199 + " -u " + UserHandle.myUserId() 200 + " " + kJobServiceComponent.getPackageName() 201 + " " + JOB_ID)); 202 203 if (BatteryUtils.hasBattery()) { 204 setBatteryState(false, 100); 205 verifyStopReason(new JobInfo.Builder(JOB_ID, kJobServiceComponent) 206 .setRequiresBatteryNotLow(true).build(), 207 JobParameters.STOP_REASON_CONSTRAINT_BATTERY_NOT_LOW, 208 () -> setBatteryState(false, 5)); 209 210 setBatteryState(true, 100); 211 verifyStopReason(new JobInfo.Builder(JOB_ID, kJobServiceComponent) 212 .setRequiresCharging(true).build(), 213 JobParameters.STOP_REASON_CONSTRAINT_CHARGING, 214 () -> setBatteryState(false, 100)); 215 } 216 217 setStorageStateLow(false); 218 verifyStopReason(new JobInfo.Builder(JOB_ID, kJobServiceComponent) 219 .setRequiresStorageNotLow(true).build(), 220 JobParameters.STOP_REASON_CONSTRAINT_STORAGE_NOT_LOW, 221 () -> setStorageStateLow(true)); 222 } 223 224 @RequiresFlagsEnabled(FLAG_HANDLE_ABANDONED_JOBS) testStopReasonAbandonedJob()225 public void testStopReasonAbandonedJob() throws Exception { 226 verifyStopReason( 227 new JobInfo.Builder(JOB_ID, kJobServiceComponent).build(), 228 JobParameters.STOP_REASON_TIMEOUT_ABANDONED, 229 () -> SystemUtil.runShellCommand(getInstrumentation(), 230 "cmd jobscheduler stop -s " 231 + JobParameters.STOP_REASON_TIMEOUT_ABANDONED + " -i " 232 + JobParameters.INTERNAL_STOP_REASON_TIMEOUT_ABANDONED 233 + " -u " + UserHandle.myUserId() 234 + " " + kJobServiceComponent.getPackageName() 235 + " " + JOB_ID)); 236 } 237 verifyStopReason(JobInfo ji, int stopReason, ExceptionRunnable stopCode)238 private void verifyStopReason(JobInfo ji, int stopReason, ExceptionRunnable stopCode) 239 throws Exception { 240 kTestEnvironment.setExpectedExecutions(1); 241 kTestEnvironment.setContinueAfterStart(); 242 kTestEnvironment.setExpectedStopped(); 243 mJobScheduler.schedule(ji); 244 runSatisfiedJob(ji.getId()); 245 assertTrue("Job didn't fire immediately", kTestEnvironment.awaitExecution()); 246 247 JobParameters params = kTestEnvironment.getLastStartJobParameters(); 248 assertEquals(JobParameters.STOP_REASON_UNDEFINED, params.getStopReason()); 249 250 stopCode.run(); 251 assertTrue("Job didn't stop immediately", kTestEnvironment.awaitStopped()); 252 params = kTestEnvironment.getLastStopJobParameters(); 253 assertEquals(stopReason, params.getStopReason()); 254 } 255 testTransientExtras()256 public void testTransientExtras() throws Exception { 257 final Bundle b = new Bundle(); 258 b.putBoolean("random_bool", true); 259 JobInfo ji = new JobInfo.Builder(JOB_ID, kJobServiceComponent) 260 .setTransientExtras(b) 261 .build(); 262 263 kTestEnvironment.setExpectedExecutions(1); 264 mJobScheduler.schedule(ji); 265 runSatisfiedJob(JOB_ID); 266 assertTrue("Job didn't fire immediately", kTestEnvironment.awaitExecution()); 267 268 JobParameters params = kTestEnvironment.getLastStartJobParameters(); 269 assertEquals(b.size(), params.getTransientExtras().size()); 270 for (String key : b.keySet()) { 271 assertEquals(b.get(key), params.getTransientExtras().get(key)); 272 } 273 } 274 275 // JobParameters.getTriggeredContentAuthorities() tested in TriggerContentTest. 276 // JobParameters.getTriggeredContentUris() tested in TriggerContentTest. 277 // JobParameters.isOverrideDeadlineExpired() tested in TimingConstraintTest. 278 279 private interface ExceptionRunnable { run()280 void run() throws Exception; 281 } 282 } 283