1 /* 2 * Copyright (C) 2018 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.shareduidtests; 18 19 20 import android.annotation.TargetApi; 21 import android.app.job.JobInfo; 22 import android.content.ContentProviderClient; 23 import android.content.Intent; 24 import android.content.pm.PackageManager; 25 import android.os.Process; 26 27 /** 28 * Schedules jobs with the {@link android.app.job.JobScheduler} that grant permissions through 29 * ClipData. 30 */ 31 @TargetApi(26) 32 public class ClipDataJobTest extends ConstraintTest { 33 private static final String TAG = "ClipDataJobTest"; 34 35 /** Unique identifier for the job scheduled by this suite of tests. */ 36 public static final int CLIP_DATA_JOB_ID = ClipDataJobTest.class.hashCode(); 37 38 JobInfo.Builder mBuilder; 39 private ContentProviderClient mProvider; 40 41 @Override 42 public void setUp() throws Exception { 43 super.setUp(); 44 45 mBuilder = new JobInfo.Builder(CLIP_DATA_JOB_ID, kJobServiceComponent); 46 mProvider = getContext().getContentResolver().acquireContentProviderClient(mFirstUri); 47 assertNotNull(mProvider); 48 } 49 50 @Override 51 public void tearDown() throws Exception { 52 super.tearDown(); 53 mProvider.close(); 54 mJobScheduler.cancel(CLIP_DATA_JOB_ID); 55 } 56 57 /** 58 * Test basic granting of URI permissions associated with jobs. 59 */ 60 public void testClipDataGrant() throws Exception { 61 // Start out with storage low, so job is enqueued but not executed yet. 62 setStorageState(true); 63 64 // We need to get a permission grant so that we can grant it to ourself. 65 mProvider.call("grant", MY_PACKAGE, mFirstUriBundle); 66 assertEquals(PackageManager.PERMISSION_GRANTED, 67 getContext().checkUriPermission(mFirstUri, Process.myPid(), 68 Process.myUid(), Intent.FLAG_GRANT_READ_URI_PERMISSION)); 69 assertEquals(PackageManager.PERMISSION_GRANTED, 70 getContext().checkUriPermission(mFirstUri, Process.myPid(), 71 Process.myUid(), Intent.FLAG_GRANT_WRITE_URI_PERMISSION)); 72 73 // Schedule the job, the system should now also be holding a URI grant for us. 74 kTestEnvironment.setExpectedExecutions(1); 75 mJobScheduler.schedule(mBuilder.setRequiresStorageNotLow(true) 76 .setClipData(mFirstClipData, Intent.FLAG_GRANT_READ_URI_PERMISSION 77 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION).build()); 78 79 // Remove the explicit grant, we should still have a grant due to the job. 80 mProvider.call("revoke", MY_PACKAGE, mFirstUriBundle); 81 assertEquals(PackageManager.PERMISSION_GRANTED, 82 getContext().checkUriPermission(mFirstUri, Process.myPid(), 83 Process.myUid(), Intent.FLAG_GRANT_READ_URI_PERMISSION)); 84 assertEquals(PackageManager.PERMISSION_GRANTED, 85 getContext().checkUriPermission(mFirstUri, Process.myPid(), 86 Process.myUid(), Intent.FLAG_GRANT_WRITE_URI_PERMISSION)); 87 88 // Now allow the job to run and wait for it. 89 setStorageState(false); 90 assertTrue("Job with storage not low constraint did not fire when storage not low.", 91 kTestEnvironment.awaitExecution()); 92 93 // Make sure the job still had the permission granted. 94 assertEquals(PackageManager.PERMISSION_GRANTED, kTestEnvironment.getLastPermCheckRead()); 95 assertEquals(PackageManager.PERMISSION_GRANTED, kTestEnvironment.getLastPermCheckWrite()); 96 97 // And wait for everything to be cleaned up. 98 waitPermissionRevoke(mFirstUri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION, 5000); 99 } 100 101 /** 102 * Test that we correctly fail when trying to grant permissions to things we don't 103 * have access to. 104 */ 105 public void testClipDataGrant_Failed() throws Exception { 106 try { 107 mJobScheduler.schedule(mBuilder.setRequiresStorageNotLow(true) 108 .setClipData(mFirstClipData, Intent.FLAG_GRANT_READ_URI_PERMISSION 109 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION).build()); 110 } catch (SecurityException e) { 111 return; 112 } 113 114 fail("Security exception not thrown"); 115 } 116 117 /** 118 * Test basic granting of URI permissions associated with jobs and are correctly 119 * retained when rescheduling the job. 120 */ 121 public void testClipDataGrantReschedule() throws Exception { 122 // We need to get a permission grant so that we can grant it to ourself. 123 mProvider.call("grant", MY_PACKAGE, mFirstUriBundle); 124 assertEquals(PackageManager.PERMISSION_GRANTED, 125 getContext().checkUriPermission(mFirstUri, Process.myPid(), 126 Process.myUid(), Intent.FLAG_GRANT_READ_URI_PERMISSION)); 127 assertEquals(PackageManager.PERMISSION_GRANTED, 128 getContext().checkUriPermission(mFirstUri, Process.myPid(), 129 Process.myUid(), Intent.FLAG_GRANT_WRITE_URI_PERMISSION)); 130 131 // Schedule the job, the system should now also be holding a URI grant for us. 132 kTestEnvironment.setExpectedExecutions(1); 133 mJobScheduler.schedule(mBuilder.setMinimumLatency(60*60*1000) 134 .setClipData(mFirstClipData, Intent.FLAG_GRANT_READ_URI_PERMISSION 135 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION).build()); 136 137 // Remove the explicit grant, we should still have a grant due to the job. 138 mProvider.call("revoke", MY_PACKAGE, mFirstUriBundle); 139 assertEquals(PackageManager.PERMISSION_GRANTED, 140 getContext().checkUriPermission(mFirstUri, Process.myPid(), 141 Process.myUid(), Intent.FLAG_GRANT_READ_URI_PERMISSION)); 142 assertEquals(PackageManager.PERMISSION_GRANTED, 143 getContext().checkUriPermission(mFirstUri, Process.myPid(), 144 Process.myUid(), Intent.FLAG_GRANT_WRITE_URI_PERMISSION)); 145 146 // Now reschedule the job to have it happen right now. 147 mJobScheduler.schedule(mBuilder.setMinimumLatency(0) 148 .setClipData(mFirstClipData, Intent.FLAG_GRANT_READ_URI_PERMISSION 149 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION).build()); 150 assertTrue("Job with storage not low constraint did not fire when storage not low.", 151 kTestEnvironment.awaitExecution()); 152 153 // Make sure the job still had the permission granted. 154 assertEquals(PackageManager.PERMISSION_GRANTED, kTestEnvironment.getLastPermCheckRead()); 155 assertEquals(PackageManager.PERMISSION_GRANTED, kTestEnvironment.getLastPermCheckWrite()); 156 157 // And wait for everything to be cleaned up. 158 waitPermissionRevoke(mFirstUri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION, 5000); 159 } 160 } 161