1 /*
2  * Copyright (C) 2020 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 @file:JvmName("TestPermissionUtil")
18 
19 package com.android.testutils
20 
21 import androidx.test.platform.app.InstrumentationRegistry
22 import com.android.testutils.ExceptionUtils.ThrowingRunnable
23 import com.android.testutils.ExceptionUtils.ThrowingSupplier
24 
25 /**
26  * Run the specified [task] with the specified [permissions] obtained through shell
27  * permission identity.
28  *
29  * Passing in an empty list of permissions can grant all shell permissions, but this is
30  * discouraged as it also causes the process to temporarily lose non-shell permissions.
31  */
32 fun <T> runAsShell(vararg permissions: String, task: () -> T): T {
33     val autom = InstrumentationRegistry.getInstrumentation().uiAutomation
34     autom.adoptShellPermissionIdentity(*permissions)
35     try {
36         return task()
37     } finally {
38         autom.dropShellPermissionIdentity()
39     }
40 }
41 
42 /**
43  * Convenience overload of [runAsShell] that uses a [ThrowingSupplier] for Java callers, when
44  * only one/two/three permissions are needed.
45  */
46 @JvmOverloads
47 fun <T> runAsShell(
48     perm1: String,
49     perm2: String = "",
50     perm3: String = "",
51     supplier: ThrowingSupplier<T>
52 ): T = runAsShell(*getNonEmptyVarargs(perm1, perm2, perm3)) { supplier.get() }
53 
54 /**
55  * Convenience overload of [runAsShell] that uses a [ThrowingRunnable] for Java callers, when
56  * only one/two/three permissions are needed.
57  */
58 @JvmOverloads
59 fun runAsShell(
60     perm1: String,
61     perm2: String = "",
62     perm3: String = "",
63     runnable: ThrowingRunnable
64 ): Unit = runAsShell(*getNonEmptyVarargs(perm1, perm2, perm3)) { runnable.run() }
65 
66 /**
67  * Get an array containing the first consecutive non-empty arguments out of three arguments.
68  *
69  * The first argument is assumed to be non-empty.
70  */
71 private fun getNonEmptyVarargs(arg1: String, arg2: String, arg3: String): Array<String> {
72     return when {
73         arg2 == "" -> arrayOf(arg1)
74         arg3 == "" -> arrayOf(arg1, arg2)
75         else -> arrayOf(arg1, arg2, arg3)
76     }
77 }