1 /*
2  * Copyright (C) 2022 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.server.appop;
18 
19 import static android.app.AppOpsManager.OP_COARSE_LOCATION;
20 import static android.app.AppOpsManager.OP_FINE_LOCATION;
21 
22 import static org.junit.Assert.assertEquals;
23 
24 import android.content.Context;
25 import android.os.Handler;
26 
27 import com.android.dx.mockito.inline.extended.ExtendedMockito;
28 import com.android.dx.mockito.inline.extended.StaticMockitoSession;
29 
30 import org.junit.After;
31 import org.junit.Before;
32 import org.junit.Test;
33 import org.mockito.Mock;
34 import org.mockito.Mockito;
35 import org.mockito.quality.Strictness;
36 
37 public class AppOpsLegacyRestrictionsTest {
38     private static final int UID_ANY = -2;
39 
40     final Object mClientToken = new Object();
41     final int mUserId1 = 65001;
42     final int mUserId2 = 65002;
43     final int mOpCode1 = OP_COARSE_LOCATION;
44     final int mOpCode2 = OP_FINE_LOCATION;
45     final String mPackageName = "com.example.test";
46     final String mAttributionTag = "test-attribution-tag";
47 
48     StaticMockitoSession mSession;
49 
50     @Mock
51     AppOpsService.Constants mConstants;
52 
53     @Mock
54     Context mContext;
55 
56     @Mock
57     Handler mHandler;
58 
59     @Mock
60     AppOpsCheckingServiceInterface mLegacyAppOpsService;
61 
62     AppOpsRestrictions mAppOpsRestrictions;
63 
64     @Before
setUp()65     public void setUp() {
66         mSession = ExtendedMockito.mockitoSession()
67                 .initMocks(this)
68                 .strictness(Strictness.LENIENT)
69                 .startMocking();
70         mConstants.TOP_STATE_SETTLE_TIME = 10 * 1000L;
71         mConstants.FG_SERVICE_STATE_SETTLE_TIME = 5 * 1000L;
72         mConstants.BG_STATE_SETTLE_TIME = 1 * 1000L;
73         Mockito.when(mHandler.post(Mockito.any(Runnable.class))).then(inv -> {
74             Runnable r = inv.getArgument(0);
75             r.run();
76             return true;
77         });
78         mAppOpsRestrictions = new AppOpsRestrictionsImpl(mContext, mHandler, mLegacyAppOpsService);
79     }
80 
81     @After
tearDown()82     public void tearDown() {
83         mSession.finishMocking();
84     }
85 
86     @Test
testSetAndGetSingleGlobalRestriction()87     public void testSetAndGetSingleGlobalRestriction() {
88         // Verify: empty
89         assertEquals(false, mAppOpsRestrictions.hasGlobalRestrictions(mClientToken));
90         assertEquals(false, mAppOpsRestrictions.getGlobalRestriction(mClientToken, mOpCode1));
91         // Act: add a restriction
92         assertEquals(true, mAppOpsRestrictions.setGlobalRestriction(mClientToken, mOpCode1, true));
93         // Act: add same restriction again (expect false; should be no-op)
94         assertEquals(false, mAppOpsRestrictions.setGlobalRestriction(mClientToken, mOpCode1, true));
95         // Verify: not empty
96         assertEquals(true, mAppOpsRestrictions.hasGlobalRestrictions(mClientToken));
97         assertEquals(true, mAppOpsRestrictions.getGlobalRestriction(mClientToken, mOpCode1));
98         // Act: remove the restriction
99         assertEquals(true, mAppOpsRestrictions.setGlobalRestriction(mClientToken, mOpCode1, false));
100         // Act: remove same restriction again (expect false; should be no-op)
101         assertEquals(false,
102                 mAppOpsRestrictions.setGlobalRestriction(mClientToken, mOpCode1, false));
103         // Verify: empty
104         assertEquals(false, mAppOpsRestrictions.hasGlobalRestrictions(mClientToken));
105         assertEquals(false, mAppOpsRestrictions.getGlobalRestriction(mClientToken, mOpCode1));
106     }
107 
108     @Test
testSetAndGetDoubleGlobalRestriction()109     public void testSetAndGetDoubleGlobalRestriction() {
110         // Act: add opCode1 restriction
111         assertEquals(true, mAppOpsRestrictions.setGlobalRestriction(mClientToken, mOpCode1, true));
112         // Act: add opCode2 restriction
113         assertEquals(true, mAppOpsRestrictions.setGlobalRestriction(mClientToken, mOpCode2, true));
114         // Verify: not empty
115         assertEquals(true, mAppOpsRestrictions.hasGlobalRestrictions(mClientToken));
116         // Act: remove opCode1 restriction
117         assertEquals(true, mAppOpsRestrictions.setGlobalRestriction(mClientToken, mOpCode1, false));
118         // Verify: not empty
119         assertEquals(true, mAppOpsRestrictions.hasGlobalRestrictions(mClientToken));
120         // Act: remove opCode2 restriction
121         assertEquals(true, mAppOpsRestrictions.setGlobalRestriction(mClientToken, mOpCode2, false));
122         // Verify: empty
123         assertEquals(false, mAppOpsRestrictions.hasGlobalRestrictions(mClientToken));
124     }
125 
126     @Test
testClearGlobalRestrictions()127     public void testClearGlobalRestrictions() {
128         // Act: clear (should be no-op)
129         assertEquals(false, mAppOpsRestrictions.clearGlobalRestrictions(mClientToken));
130         // Act: add opCodes
131         assertEquals(true, mAppOpsRestrictions.setGlobalRestriction(mClientToken, mOpCode1, true));
132         assertEquals(true, mAppOpsRestrictions.setGlobalRestriction(mClientToken, mOpCode2, true));
133         // Verify: not empty
134         assertEquals(true, mAppOpsRestrictions.hasGlobalRestrictions(mClientToken));
135         // Act: clear
136         assertEquals(true, mAppOpsRestrictions.clearGlobalRestrictions(mClientToken));
137         // Verify: empty
138         assertEquals(false, mAppOpsRestrictions.hasGlobalRestrictions(mClientToken));
139         // Act: clear (should be no-op)
140         assertEquals(false, mAppOpsRestrictions.clearGlobalRestrictions(mClientToken));
141     }
142 
143     @Test
testSetAndGetSingleUserRestriction()144     public void testSetAndGetSingleUserRestriction() {
145         // Verify: empty
146         assertEquals(false, mAppOpsRestrictions.hasUserRestrictions(mClientToken));
147         assertEquals(false, mAppOpsRestrictions.getUserRestriction(
148                 mClientToken, mUserId1, mOpCode1, mPackageName, mAttributionTag, false));
149         assertEquals(false, mAppOpsRestrictions.getUserRestriction(
150                 mClientToken, mUserId1, mOpCode1, mPackageName, mAttributionTag, true));
151         // Act: add a restriction
152         assertEquals(true, mAppOpsRestrictions.setUserRestriction(
153                 mClientToken, mUserId1, mOpCode1, true, null));
154         // Act: add the restriction again (should be no-op)
155         assertEquals(false, mAppOpsRestrictions.setUserRestriction(
156                 mClientToken, mUserId1, mOpCode1, true, null));
157         // Verify: not empty
158         assertEquals(true, mAppOpsRestrictions.hasUserRestrictions(mClientToken));
159         assertEquals(true, mAppOpsRestrictions.getUserRestriction(
160                 mClientToken, mUserId1, mOpCode1, mPackageName, mAttributionTag, false));
161         assertEquals(true, mAppOpsRestrictions.getUserRestriction(
162                 mClientToken, mUserId1, mOpCode1, mPackageName, mAttributionTag, true));
163         // Act: remove the restriction
164         assertEquals(true, mAppOpsRestrictions.setUserRestriction(
165                 mClientToken, mUserId1, mOpCode1, false, null));
166         // Act: remove the restriction again (should be no-op)
167         assertEquals(false, mAppOpsRestrictions.setUserRestriction(
168                 mClientToken, mUserId1, mOpCode1, false, null));
169         // Verify: empty
170         assertEquals(false, mAppOpsRestrictions.hasUserRestrictions(mClientToken));
171         assertEquals(false, mAppOpsRestrictions.getUserRestriction(
172                 mClientToken, mUserId1, mOpCode1, mPackageName, mAttributionTag, false));
173     }
174 
175     @Test
testSetAndGetDoubleUserRestriction()176     public void testSetAndGetDoubleUserRestriction() {
177         // Act: add opCode1 restriction
178         assertEquals(true, mAppOpsRestrictions.setUserRestriction(
179                 mClientToken, mUserId1, mOpCode1, true, null));
180         // Act: add opCode2 restriction
181         assertEquals(true, mAppOpsRestrictions.setUserRestriction(
182                 mClientToken, mUserId1, mOpCode2, true, null));
183         // Verify: not empty
184         assertEquals(true, mAppOpsRestrictions.hasUserRestrictions(mClientToken));
185         assertEquals(true, mAppOpsRestrictions.getUserRestriction(
186                 mClientToken, mUserId1, mOpCode1, mPackageName, mAttributionTag, false));
187         assertEquals(true, mAppOpsRestrictions.getUserRestriction(
188                 mClientToken, mUserId1, mOpCode1, mPackageName, mAttributionTag, true));
189         assertEquals(true, mAppOpsRestrictions.getUserRestriction(
190                 mClientToken, mUserId1, mOpCode2, mPackageName, mAttributionTag, false));
191         assertEquals(true, mAppOpsRestrictions.getUserRestriction(
192                 mClientToken, mUserId1, mOpCode2, mPackageName, mAttributionTag, true));
193         // Act: remove opCode1 restriction
194         assertEquals(true, mAppOpsRestrictions.setUserRestriction(
195                 mClientToken, mUserId1, mOpCode1, false, null));
196         // Verify: opCode1 is removed but not opCode22
197         assertEquals(true, mAppOpsRestrictions.hasUserRestrictions(mClientToken));
198         assertEquals(false, mAppOpsRestrictions.getUserRestriction(
199                 mClientToken, mUserId1, mOpCode1, mPackageName, mAttributionTag, false));
200         assertEquals(false, mAppOpsRestrictions.getUserRestriction(
201                 mClientToken, mUserId1, mOpCode1, mPackageName, mAttributionTag, true));
202         assertEquals(true, mAppOpsRestrictions.getUserRestriction(
203                 mClientToken, mUserId1, mOpCode2, mPackageName, mAttributionTag, false));
204         assertEquals(true, mAppOpsRestrictions.getUserRestriction(
205                 mClientToken, mUserId1, mOpCode2, mPackageName, mAttributionTag, true));
206         // Act: remove opCode2 restriction
207         assertEquals(true, mAppOpsRestrictions.setUserRestriction(
208                 mClientToken, mUserId1, mOpCode2, false, null));
209         // Verify: empty
210         assertEquals(false, mAppOpsRestrictions.getUserRestriction(
211                 mClientToken, mUserId1, mOpCode2, mPackageName, mAttributionTag, false));
212         assertEquals(false, mAppOpsRestrictions.getUserRestriction(
213                 mClientToken, mUserId1, mOpCode2, mPackageName, mAttributionTag, true));
214         assertEquals(false, mAppOpsRestrictions.hasUserRestrictions(mClientToken));
215     }
216 
217     @Test
testClearUserRestrictionsAllUsers()218     public void testClearUserRestrictionsAllUsers() {
219         // Act: clear (should be no-op)
220         assertEquals(false, mAppOpsRestrictions.clearUserRestrictions(mClientToken));
221         // Act: add restrictions
222         assertEquals(true, mAppOpsRestrictions.setUserRestriction(
223                 mClientToken, mUserId1, mOpCode1, true, null));
224         assertEquals(true, mAppOpsRestrictions.setUserRestriction(
225                 mClientToken, mUserId1, mOpCode2, true, null));
226         assertEquals(true, mAppOpsRestrictions.setUserRestriction(
227                 mClientToken, mUserId2, mOpCode1, true, null));
228         assertEquals(true, mAppOpsRestrictions.setUserRestriction(
229                 mClientToken, mUserId2, mOpCode2, true, null));
230         // Verify: not empty
231         assertEquals(true, mAppOpsRestrictions.hasUserRestrictions(mClientToken));
232         // Act: clear all user restrictions
233         assertEquals(true, mAppOpsRestrictions.clearUserRestrictions(mClientToken));
234         // Verify: empty
235         assertEquals(false, mAppOpsRestrictions.hasUserRestrictions(mClientToken));
236     }
237 
238     @Test
testClearUserRestrictionsSpecificUsers()239     public void testClearUserRestrictionsSpecificUsers() {
240         // Act: clear (should be no-op)
241         assertEquals(false, mAppOpsRestrictions.clearUserRestrictions(mClientToken, mUserId1));
242         // Act: add restrictions
243         assertEquals(true, mAppOpsRestrictions.setUserRestriction(
244                 mClientToken, mUserId1, mOpCode1, true, null));
245         assertEquals(true, mAppOpsRestrictions.setUserRestriction(
246                 mClientToken, mUserId1, mOpCode2, true, null));
247         assertEquals(true, mAppOpsRestrictions.setUserRestriction(
248                 mClientToken, mUserId2, mOpCode1, true, null));
249         assertEquals(true, mAppOpsRestrictions.setUserRestriction(
250                 mClientToken, mUserId2, mOpCode2, true, null));
251         // Verify: not empty
252         assertEquals(true, mAppOpsRestrictions.hasUserRestrictions(mClientToken));
253         // Act: clear userId1
254         assertEquals(true, mAppOpsRestrictions.clearUserRestrictions(mClientToken, mUserId1));
255         // Act: clear userId1 again (should be no-op)
256         assertEquals(false, mAppOpsRestrictions.clearUserRestrictions(mClientToken, mUserId1));
257         // Verify:  userId1 is removed but not userId2
258         assertEquals(false, mAppOpsRestrictions.getUserRestriction(
259                 mClientToken, mUserId1, mOpCode1, mPackageName, mAttributionTag, false));
260         assertEquals(true, mAppOpsRestrictions.getUserRestriction(
261                 mClientToken, mUserId2, mOpCode2, mPackageName, mAttributionTag, false));
262         // Act: clear userId2
263         assertEquals(true, mAppOpsRestrictions.clearUserRestrictions(mClientToken, mUserId2));
264         // Act: clear userId2 again (should be no-op)
265         assertEquals(false, mAppOpsRestrictions.clearUserRestrictions(mClientToken, mUserId2));
266         // Verify: empty
267         assertEquals(false, mAppOpsRestrictions.hasUserRestrictions(mClientToken));
268     }
269 
270     @Test
testNotify()271     public void testNotify() {
272         mAppOpsRestrictions.setUserRestriction(mClientToken, mUserId1, mOpCode1, true, null);
273         mAppOpsRestrictions.clearUserRestrictions(mClientToken);
274         Mockito.verify(mLegacyAppOpsService, Mockito.times(1))
275                 .notifyWatchersOfChange(mOpCode1, UID_ANY);
276     }
277 }
278