Home | History | Annotate | Download | only in cts
      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     /** Force the scheduler to consider the device to be on stable charging. */
     45     private static final Intent EXPEDITE_STABLE_CHARGING =
     46             new Intent("com.android.server.task.controllers.BatteryController.ACTION_CHARGING_STABLE");
     47 
     48     /** Environment that notifies of JobScheduler callbacks. */
     49     static MockJobService.TestEnvironment kTestEnvironment =
     50             MockJobService.TestEnvironment.getTestEnvironment();
     51     static TriggerContentJobService.TestEnvironment kTriggerTestEnvironment =
     52             TriggerContentJobService.TestEnvironment.getTestEnvironment();
     53     /** Handle for the service which receives the execution callbacks from the JobScheduler. */
     54     static ComponentName kJobServiceComponent;
     55     static ComponentName kTriggerContentServiceComponent;
     56     JobScheduler mJobScheduler;
     57 
     58     Context mContext;
     59 
     60     static final String MY_PACKAGE = "android.jobscheduler.cts";
     61 
     62     static final String JOBPERM_PACKAGE = "android.jobscheduler.cts.jobperm";
     63     static final String JOBPERM_AUTHORITY = "android.jobscheduler.cts.jobperm.provider";
     64     static final String JOBPERM_PERM = "android.jobscheduler.cts.jobperm.perm";
     65 
     66     Uri mFirstUri;
     67     Bundle mFirstUriBundle;
     68     Uri mSecondUri;
     69     Bundle mSecondUriBundle;
     70     ClipData mFirstClipData;
     71     ClipData mSecondClipData;
     72 
     73     boolean mStorageStateChanged;
     74 
     75     @Override
     76     public void injectInstrumentation(Instrumentation instrumentation) {
     77         super.injectInstrumentation(instrumentation);
     78         mContext = instrumentation.getContext();
     79         kJobServiceComponent = new ComponentName(getContext(), MockJobService.class);
     80         kTriggerContentServiceComponent = new ComponentName(getContext(),
     81                 TriggerContentJobService.class);
     82         mJobScheduler = (JobScheduler) getContext().getSystemService(Context.JOB_SCHEDULER_SERVICE);
     83         mFirstUri = Uri.parse("content://" + JOBPERM_AUTHORITY + "/protected/foo");
     84         mFirstUriBundle = new Bundle();
     85         mFirstUriBundle.putParcelable("uri", mFirstUri);
     86         mSecondUri = Uri.parse("content://" + JOBPERM_AUTHORITY + "/protected/bar");
     87         mSecondUriBundle = new Bundle();
     88         mSecondUriBundle.putParcelable("uri", mSecondUri);
     89         mFirstClipData = new ClipData("JobPerm1", new String[] { "application/*" },
     90                 new ClipData.Item(mFirstUri));
     91         mSecondClipData = new ClipData("JobPerm2", new String[] { "application/*" },
     92                 new ClipData.Item(mSecondUri));
     93         try {
     94             SystemUtil.runShellCommand(getInstrumentation(), "cmd activity set-inactive "
     95                     + mContext.getPackageName() + " false");
     96         } catch (IOException e) {
     97             Log.w("ConstraintTest", "Failed setting inactive false", e);
     98         }
     99     }
    100 
    101     public Context getContext() {
    102         return mContext;
    103     }
    104 
    105     @Override
    106     public void setUp() throws Exception {
    107         super.setUp();
    108         kTestEnvironment.setUp();
    109         kTriggerTestEnvironment.setUp();
    110         mJobScheduler.cancelAll();
    111     }
    112 
    113     @Override
    114     public void tearDown() throws Exception {
    115         if (mStorageStateChanged) {
    116             // Put storage service back in to normal operation.
    117             SystemUtil.runShellCommand(getInstrumentation(), "cmd devicestoragemonitor reset");
    118             mStorageStateChanged = false;
    119         }
    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      */
    127     protected void sendExpediteStableChargingBroadcast() {
    128         getContext().sendBroadcast(EXPEDITE_STABLE_CHARGING);
    129     }
    130 
    131     public void assertHasUriPermission(Uri uri, int grantFlags) {
    132         if ((grantFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
    133             assertEquals(PackageManager.PERMISSION_GRANTED,
    134                     getContext().checkUriPermission(uri, Process.myPid(),
    135                             Process.myUid(), Intent.FLAG_GRANT_READ_URI_PERMISSION));
    136         }
    137         if ((grantFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
    138             assertEquals(PackageManager.PERMISSION_GRANTED,
    139                     getContext().checkUriPermission(uri, Process.myPid(),
    140                             Process.myUid(), Intent.FLAG_GRANT_WRITE_URI_PERMISSION));
    141         }
    142     }
    143 
    144     void waitPermissionRevoke(Uri uri, int access, long timeout) {
    145         long startTime = SystemClock.elapsedRealtime();
    146         while (getContext().checkUriPermission(uri, Process.myPid(), Process.myUid(), access)
    147                 != PackageManager.PERMISSION_DENIED) {
    148             try {
    149                 Thread.sleep(50);
    150             } catch (InterruptedException e) {
    151             }
    152             if ((SystemClock.elapsedRealtime()-startTime) >= timeout) {
    153                 fail("Timed out waiting for permission revoke");
    154             }
    155         }
    156     }
    157 
    158     // Note we are just using storage state as a way to control when the job gets executed.
    159     void setStorageState(boolean low) throws Exception {
    160         mStorageStateChanged = true;
    161         String res;
    162         if (low) {
    163             res = SystemUtil.runShellCommand(getInstrumentation(),
    164                     "cmd devicestoragemonitor force-low -f");
    165         } else {
    166             res = SystemUtil.runShellCommand(getInstrumentation(),
    167                     "cmd devicestoragemonitor force-not-low -f");
    168         }
    169         int seq = Integer.parseInt(res.trim());
    170         long startTime = SystemClock.elapsedRealtime();
    171 
    172         // Wait for the storage update to be processed by job scheduler before proceeding.
    173         int curSeq;
    174         do {
    175             curSeq = Integer.parseInt(SystemUtil.runShellCommand(getInstrumentation(),
    176                     "cmd jobscheduler get-storage-seq").trim());
    177             if (curSeq == seq) {
    178                 return;
    179             }
    180         } while ((SystemClock.elapsedRealtime()-startTime) < 1000);
    181 
    182         fail("Timed out waiting for job scheduler: expected seq=" + seq + ", cur=" + curSeq);
    183     }
    184 
    185     String getJobState(int jobId) throws Exception {
    186         return SystemUtil.runShellCommand(getInstrumentation(),
    187                 "cmd jobscheduler get-job-state " + kJobServiceComponent.getPackageName()
    188                         + " " + jobId).trim();
    189     }
    190 
    191     void assertJobReady(int jobId) throws Exception {
    192         String state = getJobState(jobId);
    193         assertTrue("Job unexpectedly not ready, in state: " + state, state.contains("ready"));
    194     }
    195 
    196     void assertJobWaiting(int jobId) throws Exception {
    197         String state = getJobState(jobId);
    198         assertTrue("Job unexpectedly not waiting, in state: " + state, state.contains("waiting"));
    199     }
    200 
    201     void assertJobNotReady(int jobId) throws Exception {
    202         String state = getJobState(jobId);
    203         assertTrue("Job unexpectedly ready, in state: " + state, !state.contains("ready"));
    204     }
    205 }
    206