1 /* 2 * Copyright (C) 2014 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 package android.jobscheduler.cts; 17 18 import android.annotation.TargetApi; 19 import android.app.Instrumentation; 20 import android.app.job.JobScheduler; 21 import android.content.ClipData; 22 import android.content.ComponentName; 23 import android.content.Context; 24 import android.content.Intent; 25 import android.content.pm.PackageManager; 26 import android.jobscheduler.MockJobService; 27 import android.jobscheduler.TriggerContentJobService; 28 import android.net.Uri; 29 import android.os.Bundle; 30 import android.os.Process; 31 import android.os.SystemClock; 32 import android.test.InstrumentationTestCase; 33 import android.util.Log; 34 35 import com.android.compatibility.common.util.SystemUtil; 36 37 import java.io.IOException; 38 39 /** 40 * Common functionality from which the other test case classes derive. 41 */ 42 @TargetApi(21) 43 public abstract class ConstraintTest extends InstrumentationTestCase { 44 /** Environment that notifies of JobScheduler callbacks. */ 45 static MockJobService.TestEnvironment kTestEnvironment = 46 MockJobService.TestEnvironment.getTestEnvironment(); 47 static TriggerContentJobService.TestEnvironment kTriggerTestEnvironment = 48 TriggerContentJobService.TestEnvironment.getTestEnvironment(); 49 /** Handle for the service which receives the execution callbacks from the JobScheduler. */ 50 static ComponentName kJobServiceComponent; 51 static ComponentName kTriggerContentServiceComponent; 52 JobScheduler mJobScheduler; 53 54 Context mContext; 55 56 static final String MY_PACKAGE = "android.jobscheduler.cts"; 57 58 static final String JOBPERM_PACKAGE = "android.jobscheduler.cts.jobperm"; 59 static final String JOBPERM_AUTHORITY = "android.jobscheduler.cts.jobperm.provider"; 60 static final String JOBPERM_PERM = "android.jobscheduler.cts.jobperm.perm"; 61 62 Uri mFirstUri; 63 Bundle mFirstUriBundle; 64 Uri mSecondUri; 65 Bundle mSecondUriBundle; 66 ClipData mFirstClipData; 67 ClipData mSecondClipData; 68 69 boolean mStorageStateChanged; 70 71 @Override injectInstrumentation(Instrumentation instrumentation)72 public void injectInstrumentation(Instrumentation instrumentation) { 73 super.injectInstrumentation(instrumentation); 74 mContext = instrumentation.getContext(); 75 kJobServiceComponent = new ComponentName(getContext(), MockJobService.class); 76 kTriggerContentServiceComponent = new ComponentName(getContext(), 77 TriggerContentJobService.class); 78 mJobScheduler = (JobScheduler) getContext().getSystemService(Context.JOB_SCHEDULER_SERVICE); 79 mFirstUri = Uri.parse("content://" + JOBPERM_AUTHORITY + "/protected/foo"); 80 mFirstUriBundle = new Bundle(); 81 mFirstUriBundle.putParcelable("uri", mFirstUri); 82 mSecondUri = Uri.parse("content://" + JOBPERM_AUTHORITY + "/protected/bar"); 83 mSecondUriBundle = new Bundle(); 84 mSecondUriBundle.putParcelable("uri", mSecondUri); 85 mFirstClipData = new ClipData("JobPerm1", new String[] { "application/*" }, 86 new ClipData.Item(mFirstUri)); 87 mSecondClipData = new ClipData("JobPerm2", new String[] { "application/*" }, 88 new ClipData.Item(mSecondUri)); 89 try { 90 SystemUtil.runShellCommand(getInstrumentation(), "cmd activity set-inactive " 91 + mContext.getPackageName() + " false"); 92 } catch (IOException e) { 93 Log.w("ConstraintTest", "Failed setting inactive false", e); 94 } 95 } 96 getContext()97 public Context getContext() { 98 return mContext; 99 } 100 101 @Override setUp()102 public void setUp() throws Exception { 103 super.setUp(); 104 kTestEnvironment.setUp(); 105 kTriggerTestEnvironment.setUp(); 106 mJobScheduler.cancelAll(); 107 } 108 109 @Override tearDown()110 public void tearDown() throws Exception { 111 SystemUtil.runShellCommand(getInstrumentation(), "cmd battery reset"); 112 if (mStorageStateChanged) { 113 // Put storage service back in to normal operation. 114 SystemUtil.runShellCommand(getInstrumentation(), "cmd devicestoragemonitor reset"); 115 mStorageStateChanged = false; 116 } 117 118 // The super method should be called at the end. 119 super.tearDown(); 120 } 121 122 /** 123 * The scheduler will usually only flush its queue of unexpired jobs when the device is 124 * considered to be on stable power - that is, plugged in for a period of 2 minutes. 125 * Rather than wait for this to happen, we cheat and send this broadcast instead. 126 */ sendExpediteStableChargingBroadcast()127 protected void sendExpediteStableChargingBroadcast() throws IOException { 128 // Faking the device to be 90% charging and then to be 91%, so that it triggers 129 // BatteryManager.ACTION_CHARGING in the upward change-level transition logic. 130 SystemUtil.runShellCommand(getInstrumentation(), "cmd battery set level 90"); 131 SystemUtil.runShellCommand(getInstrumentation(), "cmd battery set level 91"); 132 } 133 assertHasUriPermission(Uri uri, int grantFlags)134 public void assertHasUriPermission(Uri uri, int grantFlags) { 135 if ((grantFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) { 136 assertEquals(PackageManager.PERMISSION_GRANTED, 137 getContext().checkUriPermission(uri, Process.myPid(), 138 Process.myUid(), Intent.FLAG_GRANT_READ_URI_PERMISSION)); 139 } 140 if ((grantFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) { 141 assertEquals(PackageManager.PERMISSION_GRANTED, 142 getContext().checkUriPermission(uri, Process.myPid(), 143 Process.myUid(), Intent.FLAG_GRANT_WRITE_URI_PERMISSION)); 144 } 145 } 146 waitPermissionRevoke(Uri uri, int access, long timeout)147 void waitPermissionRevoke(Uri uri, int access, long timeout) { 148 long startTime = SystemClock.elapsedRealtime(); 149 while (getContext().checkUriPermission(uri, Process.myPid(), Process.myUid(), access) 150 != PackageManager.PERMISSION_DENIED) { 151 try { 152 Thread.sleep(50); 153 } catch (InterruptedException e) { 154 } 155 if ((SystemClock.elapsedRealtime()-startTime) >= timeout) { 156 fail("Timed out waiting for permission revoke"); 157 } 158 } 159 } 160 161 // Note we are just using storage state as a way to control when the job gets executed. setStorageState(boolean low)162 void setStorageState(boolean low) throws Exception { 163 mStorageStateChanged = true; 164 String res; 165 if (low) { 166 res = SystemUtil.runShellCommand(getInstrumentation(), 167 "cmd devicestoragemonitor force-low -f"); 168 } else { 169 res = SystemUtil.runShellCommand(getInstrumentation(), 170 "cmd devicestoragemonitor force-not-low -f"); 171 } 172 int seq = Integer.parseInt(res.trim()); 173 long startTime = SystemClock.elapsedRealtime(); 174 175 // Wait for the storage update to be processed by job scheduler before proceeding. 176 int curSeq; 177 do { 178 curSeq = Integer.parseInt(SystemUtil.runShellCommand(getInstrumentation(), 179 "cmd jobscheduler get-storage-seq").trim()); 180 if (curSeq == seq) { 181 return; 182 } 183 } while ((SystemClock.elapsedRealtime()-startTime) < 1000); 184 185 fail("Timed out waiting for job scheduler: expected seq=" + seq + ", cur=" + curSeq); 186 } 187 getJobState(int jobId)188 String getJobState(int jobId) throws Exception { 189 return SystemUtil.runShellCommand(getInstrumentation(), 190 "cmd jobscheduler get-job-state --user cur " 191 + kJobServiceComponent.getPackageName() + " " + jobId).trim(); 192 } 193 assertJobReady(int jobId)194 void assertJobReady(int jobId) throws Exception { 195 String state = getJobState(jobId); 196 assertTrue("Job unexpectedly not ready, in state: " + state, state.contains("ready")); 197 } 198 assertJobWaiting(int jobId)199 void assertJobWaiting(int jobId) throws Exception { 200 String state = getJobState(jobId); 201 assertTrue("Job unexpectedly not waiting, in state: " + state, state.contains("waiting")); 202 } 203 assertJobNotReady(int jobId)204 void assertJobNotReady(int jobId) throws Exception { 205 String state = getJobState(jobId); 206 assertTrue("Job unexpectedly ready, in state: " + state, !state.contains("ready")); 207 } 208 } 209