1 /* 2 * Copyright (C) 2017 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.cts.deviceandprofileowner; 18 19 import static android.app.admin.DevicePolicyManager.EXTRA_DELEGATION_SCOPES; 20 import static android.app.admin.DevicePolicyManager.DELEGATION_APP_RESTRICTIONS; 21 import static android.app.admin.DevicePolicyManager.DELEGATION_BLOCK_UNINSTALL; 22 import static android.app.admin.DevicePolicyManager.DELEGATION_CERT_INSTALL; 23 import static android.app.admin.DevicePolicyManager.DELEGATION_ENABLE_SYSTEM_APP; 24 25 import android.app.admin.DevicePolicyManager; 26 import android.content.BroadcastReceiver; 27 import android.content.ComponentName; 28 import android.content.Context; 29 import android.content.Intent; 30 import android.content.IntentFilter; 31 import android.test.MoreAsserts; 32 33 import java.util.Arrays; 34 import java.util.List; 35 import java.util.concurrent.Semaphore; 36 import java.util.concurrent.TimeUnit; 37 38 /** 39 * Test that an app granted delegation scopes via {@link DevicePolicyManager#setDelegatedScopes} is 40 * notified of its new scopes by a broadcast. 41 */ 42 public class DelegationTest extends BaseDeviceAdminTest { 43 44 private static final String DELEGATE_PKG = "com.android.cts.delegate"; 45 private static final String DELEGATE_ACTIVITY_NAME = 46 DELEGATE_PKG + ".DelegatedScopesReceiverActivity"; 47 private static final String TEST_PKG = "com.android.cts.apprestrictions.targetapp"; 48 49 // Broadcasts received from the delegate app. 50 private static final String ACTION_REPORT_SCOPES = "com.android.cts.delegate.report_scopes"; 51 private static final String ACTION_RUNNING = "com.android.cts.delegate.running"; 52 53 // Semaphores to synchronize communication with delegate app. 54 private volatile String[] mReceivedScopes; 55 private Semaphore mReceivedScopeReportSemaphore; 56 private Semaphore mReceivedRunningSemaphore; 57 58 // Receiver for incoming broadcasts from the delegate app. 59 private final BroadcastReceiver mReceiver = new BroadcastReceiver() { 60 @Override 61 public void onReceive(Context context, Intent intent) { 62 if (ACTION_REPORT_SCOPES.equals(intent.getAction())) { 63 synchronized (DelegationTest.this) { 64 mReceivedScopes = intent.getStringArrayExtra(EXTRA_DELEGATION_SCOPES); 65 mReceivedScopeReportSemaphore.release(); 66 } 67 } else if (ACTION_RUNNING.equals(intent.getAction())) { 68 synchronized (DelegationTest.this) { 69 mReceivedRunningSemaphore.release(); 70 } 71 } 72 } 73 }; 74 75 @Override 76 public void setUp() throws Exception { 77 super.setUp(); 78 mReceivedScopeReportSemaphore = new Semaphore(0); 79 mReceivedRunningSemaphore = new Semaphore(0); 80 mReceivedScopes = null; 81 IntentFilter filter = new IntentFilter(); 82 filter.addAction(ACTION_REPORT_SCOPES); 83 filter.addAction(ACTION_RUNNING); 84 mContext.registerReceiver(mReceiver, filter); 85 } 86 87 @Override 88 public void tearDown() throws Exception { 89 mContext.unregisterReceiver(mReceiver); 90 super.tearDown(); 91 } 92 93 public void testDelegateReceivesScopeChangedBroadcast() throws InterruptedException { 94 // Prepare the scopes to be delegated. 95 final List<String> scopes = Arrays.asList( 96 DELEGATION_CERT_INSTALL, 97 DELEGATION_APP_RESTRICTIONS, 98 DELEGATION_BLOCK_UNINSTALL, 99 DELEGATION_ENABLE_SYSTEM_APP); 100 101 // Start delegate so it can receive the scopes changed broadcast from DevicePolicyManager. 102 startAndWaitDelegateActivity(); 103 104 // Set the delegated scopes. 105 mDevicePolicyManager.setDelegatedScopes(ADMIN_RECEIVER_COMPONENT, DELEGATE_PKG, scopes); 106 107 // Wait until the delegate reports its new scopes. 108 String reportedScopes[] = waitReportedScopes(); 109 110 // Check that the reported scopes correspond to scopes we delegated. 111 assertNotNull("Received null scopes from delegate", reportedScopes); 112 MoreAsserts.assertContentsInAnyOrder("Delegated scopes do not match broadcasted scopes", 113 scopes, reportedScopes); 114 } 115 116 public void testCantDelegateToUninstalledPackage() { 117 // Prepare the package name and scopes to be delegated. 118 final String NON_EXISTENT_PKG = "com.android.nonexistent.delegate"; 119 final List<String> scopes = Arrays.asList( 120 DELEGATION_CERT_INSTALL, 121 DELEGATION_ENABLE_SYSTEM_APP); 122 try { 123 // Trying to delegate to non existent package should throw. 124 mDevicePolicyManager.setDelegatedScopes(ADMIN_RECEIVER_COMPONENT, 125 NON_EXISTENT_PKG, scopes); 126 fail("Should throw when delegating to non existent package"); 127 } catch(IllegalArgumentException expected) { 128 } 129 // Assert no scopes were delegated. 130 assertTrue("Delegation scopes granted to non existent package", mDevicePolicyManager 131 .getDelegatedScopes(ADMIN_RECEIVER_COMPONENT, NON_EXISTENT_PKG).isEmpty()); 132 } 133 134 public void testCanRetrieveDelegates() { 135 final List<String> someScopes = Arrays.asList( 136 DELEGATION_APP_RESTRICTIONS, 137 DELEGATION_ENABLE_SYSTEM_APP); 138 final List<String> otherScopes = Arrays.asList( 139 DELEGATION_BLOCK_UNINSTALL, 140 DELEGATION_ENABLE_SYSTEM_APP); 141 142 // In the beginning there are no delegates. 143 assertTrue("No delegates should be found", getDelegatePackages(DELEGATION_APP_RESTRICTIONS) 144 .isEmpty()); 145 assertTrue("No delegates should be found", getDelegatePackages(DELEGATION_BLOCK_UNINSTALL) 146 .isEmpty()); 147 assertTrue("No delegates should be found", getDelegatePackages(DELEGATION_ENABLE_SYSTEM_APP) 148 .isEmpty()); 149 150 // After delegating scopes to two packages. 151 mDevicePolicyManager.setDelegatedScopes(ADMIN_RECEIVER_COMPONENT, 152 DELEGATE_PKG, someScopes); 153 mDevicePolicyManager.setDelegatedScopes(ADMIN_RECEIVER_COMPONENT, 154 TEST_PKG, otherScopes); 155 156 // The expected delegates are returned. 157 assertTrue("Expected delegate not found", getDelegatePackages(DELEGATION_APP_RESTRICTIONS) 158 .contains(DELEGATE_PKG)); 159 assertTrue("Expected delegate not found", getDelegatePackages(DELEGATION_BLOCK_UNINSTALL) 160 .contains(TEST_PKG)); 161 assertTrue("Expected delegate not found", getDelegatePackages(DELEGATION_ENABLE_SYSTEM_APP) 162 .contains(DELEGATE_PKG)); 163 assertTrue("Expected delegate not found", getDelegatePackages(DELEGATION_ENABLE_SYSTEM_APP) 164 .contains(TEST_PKG)); 165 166 // Packages are only returned in their recpective scopes. 167 assertFalse("Unexpected delegate package", getDelegatePackages(DELEGATION_APP_RESTRICTIONS) 168 .contains(TEST_PKG)); 169 assertFalse("Unexpected delegate package", getDelegatePackages(DELEGATION_BLOCK_UNINSTALL) 170 .contains(DELEGATE_PKG)); 171 assertFalse("Unexpected delegate package", getDelegatePackages(DELEGATION_CERT_INSTALL) 172 .contains(DELEGATE_PKG)); 173 assertFalse("Unexpected delegate package", getDelegatePackages(DELEGATION_CERT_INSTALL) 174 .contains(TEST_PKG)); 175 } 176 177 private List<String> getDelegatePackages(String scope) { 178 return mDevicePolicyManager.getDelegatePackages(ADMIN_RECEIVER_COMPONENT, scope); 179 } 180 181 private void startAndWaitDelegateActivity() throws InterruptedException { 182 mContext.startActivity(new Intent() 183 .setComponent(new ComponentName(DELEGATE_PKG, DELEGATE_ACTIVITY_NAME)) 184 .addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NEW_TASK)); 185 assertTrue("DelegateApp did not start in time.", 186 mReceivedRunningSemaphore.tryAcquire(10, TimeUnit.SECONDS)); 187 } 188 189 private String[] waitReportedScopes() throws InterruptedException { 190 assertTrue("DelegateApp did not report scope in time.", 191 mReceivedScopeReportSemaphore.tryAcquire(10, TimeUnit.SECONDS)); 192 return mReceivedScopes; 193 } 194 } 195