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 package com.android.cts.delegate; 17 18 import static android.app.admin.DevicePolicyManager.DELEGATION_APP_RESTRICTIONS; 19 import static com.android.cts.delegate.DelegateTestUtils.assertExpectException; 20 21 import android.app.admin.DevicePolicyManager; 22 import android.content.BroadcastReceiver; 23 import android.content.ComponentName; 24 import android.content.Context; 25 import android.content.Intent; 26 import android.content.IntentFilter; 27 import android.os.Bundle; 28 import android.os.UserManager; 29 import android.test.InstrumentationTestCase; 30 import android.test.MoreAsserts; 31 32 import java.util.Arrays; 33 import java.util.List; 34 import java.util.concurrent.Semaphore; 35 import java.util.concurrent.TimeUnit; 36 37 /** 38 * Test that an app given the {@link DevicePolicyManager#DELEGATION_APP_RESTRICTIONS} scope via 39 * {@link DevicePolicyManager#setDelegatedScopes} can manage app restrictions. 40 */ 41 public class AppRestrictionsDelegateTest extends InstrumentationTestCase { 42 43 private static final String APP_RESTRICTIONS_TARGET_PKG = 44 "com.android.cts.apprestrictions.targetapp"; 45 private static final String APP_RESTRICTIONS_ACTIVITY_NAME = 46 APP_RESTRICTIONS_TARGET_PKG + ".ApplicationRestrictionsActivity"; 47 private static final String ACTION_RESTRICTIONS_VALUE = 48 "com.android.cts.apprestrictions.targetapp.RESTRICTIONS_VALUE"; 49 50 private static final Bundle BUNDLE_0 = createBundle0(); 51 private static final Bundle BUNDLE_1 = createBundle1(); 52 53 private static final long TIMEOUT_SECONDS = 10; 54 55 private final BroadcastReceiver mReceiver = new BroadcastReceiver() { 56 @Override 57 public void onReceive(Context context, Intent intent) { 58 String action = intent.getAction(); 59 if (ACTION_RESTRICTIONS_VALUE.equals(action)) { 60 mReceivedRestrictions = intent.getBundleExtra("value"); 61 mOnRestrictionsSemaphore.release(); 62 } 63 } 64 }; 65 66 private Context mContext; 67 private DevicePolicyManager mDpm; 68 private final Semaphore mOnRestrictionsSemaphore = new Semaphore(0); 69 private Bundle mReceivedRestrictions; 70 71 @Override 72 protected void setUp() throws Exception { 73 super.setUp(); 74 75 mContext = getInstrumentation().getContext(); 76 mDpm = mContext.getSystemService(DevicePolicyManager.class); 77 78 mContext.registerReceiver(mReceiver, new IntentFilter(ACTION_RESTRICTIONS_VALUE)); 79 } 80 81 @Override 82 protected void tearDown() throws Exception { 83 mContext.unregisterReceiver(mReceiver); 84 super.tearDown(); 85 } 86 87 public void testCannotAccessApis() { 88 assertFalse("DelegateApp should not be an app restrictions delegate", 89 amIAppRestrictionsDelegate()); 90 91 assertExpectException(SecurityException.class, 92 "Caller with uid \\d+ is not a delegate of scope", () -> { 93 mDpm.setApplicationRestrictions(null, APP_RESTRICTIONS_TARGET_PKG, null); 94 }); 95 96 assertExpectException(SecurityException.class, 97 "Caller with uid \\d+ is not a delegate of scope", () -> { 98 mDpm.getApplicationRestrictions(null, APP_RESTRICTIONS_TARGET_PKG); 99 }); 100 } 101 102 public void testCanAccessApis() throws InterruptedException { 103 assertTrue("DelegateApp is not an app restrictions delegate", amIAppRestrictionsDelegate()); 104 try { 105 mDpm.setApplicationRestrictions(null, APP_RESTRICTIONS_TARGET_PKG, BUNDLE_0); 106 assertBundle0(mDpm.getApplicationRestrictions(null, APP_RESTRICTIONS_TARGET_PKG)); 107 108 // Check that the target app can retrieve the same restrictions. 109 assertBundle0(waitForChangedRestriction()); 110 111 // Test overwriting 112 mDpm.setApplicationRestrictions(null, APP_RESTRICTIONS_TARGET_PKG, BUNDLE_1); 113 assertBundle1(mDpm.getApplicationRestrictions(null, APP_RESTRICTIONS_TARGET_PKG)); 114 assertBundle1(waitForChangedRestriction()); 115 } finally { 116 mDpm.setApplicationRestrictions(null, APP_RESTRICTIONS_TARGET_PKG, new Bundle()); 117 assertTrue( 118 mDpm.getApplicationRestrictions(null, APP_RESTRICTIONS_TARGET_PKG).isEmpty()); 119 } 120 } 121 122 // Should be consistent with assertBundle0 123 private static Bundle createBundle0() { 124 Bundle result = new Bundle(); 125 result.putString("dummyString", "value"); 126 return result; 127 } 128 129 // Should be consistent with createBundle0 130 private void assertBundle0(Bundle bundle) { 131 assertEquals(1, bundle.size()); 132 assertEquals("value", bundle.getString("dummyString")); 133 } 134 135 // Should be consistent with assertBundle1 136 private static Bundle createBundle1() { 137 Bundle result = new Bundle(); 138 result.putInt("dummyInt", 1); 139 return result; 140 } 141 142 // Should be consistent with createBundle1 143 private void assertBundle1(Bundle bundle) { 144 assertEquals(1, bundle.size()); 145 assertEquals(1, bundle.getInt("dummyInt")); 146 } 147 148 private void startTestActivity() { 149 mContext.startActivity(new Intent() 150 .setComponent(new ComponentName( 151 APP_RESTRICTIONS_TARGET_PKG, APP_RESTRICTIONS_ACTIVITY_NAME)) 152 .addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NEW_TASK)); 153 } 154 155 private Bundle waitForChangedRestriction() throws InterruptedException { 156 startTestActivity(); 157 assertTrue("App restrictions target app did not respond in time", 158 mOnRestrictionsSemaphore.tryAcquire(TIMEOUT_SECONDS, TimeUnit.SECONDS)); 159 return mReceivedRestrictions; 160 } 161 162 private boolean amIAppRestrictionsDelegate() { 163 final List<String> scopes = mDpm.getDelegatedScopes(null, mContext.getPackageName()); 164 return scopes.contains(DELEGATION_APP_RESTRICTIONS); 165 } 166 } 167