• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 package android.server.wm;
18 
19 import android.app.UiAutomation;
20 
21 import androidx.annotation.Nullable;
22 import androidx.test.InstrumentationRegistry;
23 
24 import com.android.compatibility.common.util.SystemUtil;
25 
26 /**
27  * Helper to run code that might end up with nested permission requirements (eg. TaskOrganizer).
28  */
29 public class NestedShellPermission {
30     private static NestedShellPermission sInstance;
31 
32     private int mPermissionDepth = 0;
33 
NestedShellPermission()34     private NestedShellPermission() {}
35 
getInstance()36     synchronized private static NestedShellPermission getInstance() {
37         if (sInstance == null) {
38             sInstance = new NestedShellPermission();
39         }
40         return sInstance;
41     }
42 
43     /**
44      * Similar to {@link SystemUtil#runWithShellPermissionIdentity} except it supports nesting. Use
45      * this with anything that interacts with TestTaskOrganizer since async operations are common.
46      */
run(Runnable action)47     public static void run(Runnable action) {
48         run(action, null /* permissions */);
49     }
50 
51     /** Similar to {@link #run(Runnable)}, but allow to specify {@code permissions} to hold. */
run(Runnable action, @Nullable String... permissions)52     public static void run(Runnable action, @Nullable String... permissions) {
53         final NestedShellPermission self = getInstance();
54         final UiAutomation automan =
55                 InstrumentationRegistry.getInstrumentation().getUiAutomation();
56         synchronized (self) {
57             if (0 == self.mPermissionDepth++) {
58                 automan.adoptShellPermissionIdentity(permissions);
59             }
60         }
61         try {
62             action.run();
63         } finally {
64             synchronized (self) {
65                 if (0 == --self.mPermissionDepth) {
66                     automan.dropShellPermissionIdentity();
67                 }
68             }
69         }
70     }
71 }
72