1 /*
<lambda>null2  * Copyright (C) 2023 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.devicepolicy.cts
17 
18 import android.app.admin.DevicePolicyManager
19 import android.content.ComponentName
20 import android.os.PersistableBundle
21 import com.android.bedstead.harrier.BedsteadJUnit4
22 import com.android.bedstead.harrier.DeviceState
23 import com.android.bedstead.harrier.annotations.Postsubmit
24 import com.android.bedstead.harrier.annotations.RequireRunOnSystemUser
25 import com.android.bedstead.enterprise.annotations.CanSetPolicyTest
26 import com.android.bedstead.enterprise.annotations.CannotSetPolicyTest
27 import com.android.bedstead.enterprise.annotations.EnsureHasDeviceOwner
28 import com.android.bedstead.enterprise.annotations.EnsureHasProfileOwner
29 import com.android.bedstead.enterprise.annotations.PolicyAppliesTest
30 import com.android.bedstead.harrier.policies.TransferOwnership
31 import com.android.bedstead.harrier.policies.TransferOwnershipForDeviceOwner
32 import com.android.bedstead.harrier.policies.TransferOwnershipForProfileOwner
33 import com.android.bedstead.nene.TestApis
34 import com.android.compatibility.common.util.ApiTest
35 import com.android.eventlib.truth.EventLogsSubject
36 import com.android.eventlib.truth.EventLogsSubject.assertThat
37 import com.android.queryable.queries.BundleQuery
38 import com.android.queryable.queries.ReceiverQuery
39 import com.google.common.truth.Truth
40 import com.google.common.truth.Truth.assertThat
41 import org.junit.ClassRule
42 import org.junit.Rule
43 import org.junit.Test
44 import org.junit.runner.RunWith
45 import org.testng.Assert
46 import org.testng.Assert.assertThrows
47 
48 // TODO(b/298202673: Add tests for behavior for all policies)
49 @RunWith(BedsteadJUnit4::class)
50 class TransferOwnershipTest {
51     @ApiTest(apis = ["android.app.admin.DevicePolicyManager#transferOwnership", "android.app.admin.DevicePolicyManager#getTransferOwnershipBundle"])
52     @Postsubmit(reason = "new test")
53     @CanSetPolicyTest(policy = [TransferOwnership::class])
54     fun transferOwnership_getTransferOwnershipBundle_bundleReceivedByTargetAdmin() {
55         targetDeviceAdminTestAppSupportsTransferOwnership.install().use { testApp ->
56             try {
57                 deviceState.dpc().devicePolicyManager().transferOwnership(
58                     deviceState.dpc().componentName(), targetAdmin, bundle
59                 )
60 
61                 assertThat(
62                     testApp.devicePolicyManager().transferOwnershipBundle.getBoolean(KEY)).isTrue()
63             } finally {
64                 removeDeviceAdmin()
65             }
66         }
67     }
68 
69     @ApiTest(apis = ["android.app.admin.DevicePolicyManager#transferOwnership"])
70     @Postsubmit(reason = "new test")
71     @CannotSetPolicyTest(policy = [TransferOwnership::class], includeNonDeviceAdminStates = false)
72     fun transferOwnership_cannotSet_throwsException() {
73         targetDeviceAdminTestAppSupportsTransferOwnership.install().use {
74             assertThrows(SecurityException::class.java) {
75                 deviceState.dpc().devicePolicyManager().transferOwnership(
76                     deviceState.dpc().componentName(), targetAdmin, bundle
77                 )
78             }
79         }
80     }
81 
82     @ApiTest(apis = ["android.app.admin.DevicePolicyManager#transferOwnership", "android.app.admin.DevicePolicyManager#getTransferOwnershipBundle"])
83     @Postsubmit(reason = "new test")
84     @CanSetPolicyTest(policy = [TransferOwnership::class])
85     fun transferOwnership_nullBundleTransferred_getTransferOwnershipBundle_emptyBundleReceivedByTargetAdmin() {
86         targetDeviceAdminTestAppSupportsTransferOwnership.install().use { testApp ->
87             try {
88                 deviceState.dpc().devicePolicyManager().transferOwnership(
89                     deviceState.dpc().componentName(), targetAdmin,  /* bundle= */null
90                 )
91 
92                 assertThat(
93                     testApp.devicePolicyManager().transferOwnershipBundle.isEmpty()).isTrue()
94             } finally {
95                 removeDeviceAdmin()
96             }
97         }
98     }
99 
100     @ApiTest(apis = ["android.app.admin.DevicePolicyManager#transferOwnership"])
101     @Postsubmit(reason = "new test")
102     @CanSetPolicyTest(policy = [TransferOwnershipForDeviceOwner::class])
103     fun transferOwnership_deviceOwner_ownershipTransferredToTargetAdmin() {
104         targetDeviceAdminTestAppSupportsTransferOwnership.install().use {
105             try {
106                 deviceState.dpc().devicePolicyManager().transferOwnership(
107                     deviceState.dpc().componentName(), targetAdmin, bundle
108                 )
109 
110                 assertThat(TestApis.devicePolicy().getDeviceOwner()!!.componentName())
111                     .isEqualTo(targetAdmin)
112             } finally {
113                 removeDeviceAdmin()
114             }
115         }
116     }
117 
118     @ApiTest(apis = ["android.app.admin.DevicePolicyManager#transferOwnership"])
119     @Postsubmit(reason = "new test")
120     @CanSetPolicyTest(policy = [TransferOwnershipForProfileOwner::class])
121     fun transferOwnership_profileOwner_ownershipTransferredToTargetAdmin() {
122         targetDeviceAdminTestAppSupportsTransferOwnership.install().use {
123             try {
124                 deviceState.dpc().devicePolicyManager().transferOwnership(
125                     deviceState.dpc().componentName(), targetAdmin, bundle
126                 )
127 
128                 assertThat(TestApis.devicePolicy().getProfileOwner()!!.componentName())
129                     .isEqualTo(targetAdmin)
130             } finally {
131                 removeDeviceAdmin()
132             }
133         }
134     }
135 
136     @CanSetPolicyTest(policy = [TransferOwnership::class])
137     @Postsubmit(reason = "new test")
138     @ApiTest(apis = ["android.app.admin.DevicePolicyManager#getTransferOwnershipBundle"])
139     fun getTransferOwnershipBundle_nonDpc_throwsException() {
140             targetDeviceAdminTestAppSupportsTransferOwnership.install().use {
141                 try {
142                     deviceState.dpc().devicePolicyManager().transferOwnership(
143                         deviceState.dpc().componentName(), targetAdmin, bundle
144                     )
145                     assertThrows(SecurityException::class.java) {
146                         localDevicePolicyManager.transferOwnershipBundle
147                     }
148                 } finally {
149                     removeDeviceAdmin()
150                 }
151             }
152         }
153 
154     @ApiTest(apis = ["android.app.admin.DevicePolicyManager#transferOwnership"])
155     @Postsubmit(reason = "new test")
156     @CanSetPolicyTest(policy = [TransferOwnership::class])
157     fun transferOwnership_invalidTarget_throwsException() {
158         try {
159             assertThrows(IllegalArgumentException::class.java) {
160                 deviceState.dpc().devicePolicyManager().transferOwnership(
161                     deviceState.dpc().componentName(), invalidComponentName, bundle
162                 )
163             }
164         } finally {
165             removeDeviceAdmin()
166         }
167     }
168 
169     @ApiTest(apis = ["android.app.admin.DevicePolicyManager#transferOwnership"])
170     @EnsureHasProfileOwner
171     @Postsubmit(reason = "new test")
172     @Test
173     fun transferOwnership_disableCamera_policyRetainedAfterTransfer() {
174         targetDeviceAdminTestAppSupportsTransferOwnership.install().use { testApp ->
175             try {
176                 deviceState.dpc().devicePolicyManager().setCameraDisabled(
177                     deviceState.dpc().componentName(), true
178                 )
179                 deviceState.dpc().devicePolicyManager().transferOwnership(
180                     deviceState.dpc().componentName(), targetAdmin, bundle
181                 )
182                 assertThat(testApp.devicePolicyManager().getCameraDisabled(targetAdmin)).isTrue()
183             } finally {
184                 removeDeviceAdmin()
185             }
186         }
187     }
188 
189     @ApiTest(apis = ["android.app.admin.DevicePolicyManager#transferOwnership"])
190     @Postsubmit(reason = "new test")
191     @EnsureHasProfileOwner
192     @Test
193     fun transferOwnership_profileOwner_sendsOwnerChangedBroadcast() {
194         targetDeviceAdminTestAppSupportsTransferOwnership.install().use {
195             try {
196                 deviceState.registerBroadcastReceiver(ACTION_PROFILE_OWNER_CHANGED)
197                     .use { receiver ->
198                         deviceState.dpc().devicePolicyManager().transferOwnership(
199                             deviceState.dpc().componentName(), targetAdmin, bundle
200                         )
201                         assertThat(receiver.awaitForBroadcast()!!.action).isEqualTo(
202                             ACTION_PROFILE_OWNER_CHANGED
203                         )
204                     }
205             } finally {
206                 removeDeviceAdmin()
207             }
208         }
209     }
210 
211     @ApiTest(apis = ["android.app.admin.DevicePolicyManager#transferOwnership"])
212     @Postsubmit(reason = "new test")
213     @EnsureHasDeviceOwner
214     @RequireRunOnSystemUser // Same as device owner
215     @Test
216     fun transferOwnership_deviceOwner_sendsOwnerChangedBroadcast() {
217         targetDeviceAdminTestAppSupportsTransferOwnership.install().use {
218             try {
219                 deviceState.registerBroadcastReceiver(ACTION_DEVICE_OWNER_CHANGED)
220                     .use { receiver ->
221                         deviceState.dpc().devicePolicyManager().transferOwnership(
222                             deviceState.dpc().componentName(), targetAdmin, bundle
223                         )
224 
225                         receiver.awaitForBroadcastOrFail()
226                     }
227             } finally {
228                 removeDeviceAdmin()
229             }
230         }
231     }
232 
233     @ApiTest(apis = ["android.app.admin.DevicePolicyManager#transferOwnership"])
234     @Postsubmit(reason = "new test")
235     @CanSetPolicyTest(policy = [TransferOwnership::class])
236     fun transferOwnership_noMetadata_throwsException() {
237         targetDeviceAdminTestAppDoesNotSupportTransferOwnership.install().use {
238             assertThrows(IllegalArgumentException::class.java) {
239                 deviceState.dpc().devicePolicyManager().transferOwnership(
240                     deviceState.dpc().componentName(), targetAdmin, emptyBundle
241                 )
242             }
243         }
244     }
245 
246     @ApiTest(apis = ["android.app.admin.DevicePolicyManager#transferOwnership"])
247     @Postsubmit(reason = "new test")
248     @CanSetPolicyTest(policy = [TransferOwnership::class])
249     fun transferOwnership_sameAdmin_throwsException() {
250         targetDeviceAdminTestAppSupportsTransferOwnership.install().use {
251             assertThrows(IllegalArgumentException::class.java) {
252                 deviceState.dpc().devicePolicyManager().transferOwnership(
253                     deviceState.dpc().componentName(), deviceState.dpc().componentName(),
254                     emptyBundle
255                 )
256             }
257         }
258     }
259 
260     /**
261      * Remove whichever device admin (device owner or profile owner) the test is running for.
262      */
263     private fun removeDeviceAdmin() {
264         TestApis.devicePolicy().getDeviceOwner()?.remove()
265         TestApis.users().all().forEach {
266             TestApis.devicePolicy().getProfileOwner(it)?.remove()
267         }
268     }
269 
270     @ApiTest(apis = ["android.app.admin.DeviceAdminReceiver#onTransferOwnershipCompleted"])
271     @Postsubmit(reason = "new test")
272     @PolicyAppliesTest(policy = [TransferOwnership::class])
273     @Test
274     fun transferOwnership_callsOnTransferOwnershipCompletedCallback() {
275         targetDeviceAdminTestAppSupportsTransferOwnership.install().use {testApp ->
276             try {
277                 deviceState.dpc().devicePolicyManager().transferOwnership(
278                     deviceState.dpc().componentName(), targetAdmin, bundle
279                 )
280 
281                 assertThat(testApp.events().transferOwnershipComplete()
282                     .whereDeviceAdminReceiver().broadcastReceiver().receiverClass().className().isEqualTo(
283                         targetAdmin.className)
284                     .whereBundle().key(KEY).booleanValue().isEqualTo(bundle.getBoolean(KEY))).eventOccurred()
285             } finally {
286                 removeDeviceAdmin()
287             }
288         }
289     }
290 
291     // TODO: Add test of onTransferAffiliatedProfileOwnershipComplete
292     companion object {
293         @JvmField
294         @ClassRule
295         @Rule
296         val deviceState = DeviceState()
297         private val transferOwnershipMetadataQuery = BundleQuery.bundle().where().key(
298             "supports-transfer-ownership"
299         ).stringValue().isEqualTo("true")
300         private val targetDeviceAdminTestAppSupportsTransferOwnership =
301             deviceState.testApps().query()
302                 .whereIsDeviceAdmin().isTrue()
303                 .whereReceivers().contains(
304                     ReceiverQuery.receiver().where().metadata().contains(
305                         transferOwnershipMetadataQuery
306                     )
307                 ).get()
308         private val targetDeviceAdminTestAppDoesNotSupportTransferOwnership =
309             deviceState.testApps().query()
310                 .whereIsDeviceAdmin().isTrue()
311                 .whereReceivers().contains(
312                     ReceiverQuery.receiver().where().metadata().doesNotContain(
313                         transferOwnershipMetadataQuery
314                     )
315                 ).get()
316         private const val KEY = "VALUE"
317         private const val ACTION_DEVICE_OWNER_CHANGED = "android.app.action.DEVICE_OWNER_CHANGED"
318         private const val ACTION_PROFILE_OWNER_CHANGED = "android.app.action.PROFILE_OWNER_CHANGED"
319         private val bundle = PersistableBundle().apply { putBoolean(KEY, true) }
320 
321         private val emptyBundle = PersistableBundle()
322         private val targetAdmin = ComponentName(
323             targetDeviceAdminTestAppSupportsTransferOwnership.packageName(),
324             targetDeviceAdminTestAppSupportsTransferOwnership.packageName()
325                     + ".DeviceAdminReceiver"
326         )
327         private val invalidComponentName = ComponentName("invalid", "invalid")
328         private val localDevicePolicyManager =
329             TestApis.context().instrumentedContext().getSystemService(
330                 DevicePolicyManager::class.java
331             )!!
332     }
333 }
334