blob: 0a61c443e0bd3044b8a9215b3bba0896f97e376f [file] [log] [blame]
Peter Visontay859206c2018-01-03 15:43:19 +00001/*
2 * Copyright (C) 2018 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 */
Svet Ganov8455ba22019-01-02 13:05:56 -080016package com.android.server.appop;
Peter Visontay859206c2018-01-03 15:43:19 +000017
Amith Yamasani23d4cd72019-04-10 17:57:00 -070018import static android.app.ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
Philip P. Moltmann4aacd712020-01-03 12:32:20 -080019import static android.app.AppOpsManager.FILTER_BY_PACKAGE_NAME;
20import static android.app.AppOpsManager.FILTER_BY_UID;
Peter Visontay859206c2018-01-03 15:43:19 +000021import static android.app.AppOpsManager.MODE_ALLOWED;
22import static android.app.AppOpsManager.MODE_ERRORED;
Amith Yamasani23d4cd72019-04-10 17:57:00 -070023import static android.app.AppOpsManager.MODE_FOREGROUND;
Peter Visontay76712362018-04-19 22:04:14 +010024import static android.app.AppOpsManager.OP_COARSE_LOCATION;
Philip P. Moltmann49bd9e12019-11-26 15:18:16 -080025import static android.app.AppOpsManager.OP_FLAGS_ALL;
Peter Visontay859206c2018-01-03 15:43:19 +000026import static android.app.AppOpsManager.OP_READ_SMS;
Peter Visontay76712362018-04-19 22:04:14 +010027import static android.app.AppOpsManager.OP_WIFI_SCAN;
Peter Visontay859206c2018-01-03 15:43:19 +000028import static android.app.AppOpsManager.OP_WRITE_SMS;
29
Philip P. Moltmann6b4f3d52019-05-08 15:14:09 -070030import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
31import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
32import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
33import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
34import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
35import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
36
Peter Visontay859206c2018-01-03 15:43:19 +000037import static com.google.common.truth.Truth.assertThat;
38import static com.google.common.truth.Truth.assertWithMessage;
39
Svet Ganov47641072019-06-06 12:57:12 -070040import static org.mockito.ArgumentMatchers.any;
Philip P. Moltmann6b4f3d52019-05-08 15:14:09 -070041import static org.mockito.ArgumentMatchers.anyInt;
42import static org.mockito.ArgumentMatchers.anyString;
43import static org.mockito.ArgumentMatchers.eq;
44import static org.mockito.ArgumentMatchers.nullable;
45
Amith Yamasani23d4cd72019-04-10 17:57:00 -070046import android.app.ActivityManager;
Winson470b15b2019-05-07 16:29:59 -070047import android.app.AppOpsManager;
Peter Visontay859206c2018-01-03 15:43:19 +000048import android.app.AppOpsManager.OpEntry;
49import android.app.AppOpsManager.PackageOps;
Svet Ganov47641072019-06-06 12:57:12 -070050import android.content.ContentResolver;
Peter Visontay859206c2018-01-03 15:43:19 +000051import android.content.Context;
Philip P. Moltmann6b4f3d52019-05-08 15:14:09 -070052import android.content.pm.PackageManagerInternal;
Peter Visontay859206c2018-01-03 15:43:19 +000053import android.os.Handler;
54import android.os.HandlerThread;
55import android.os.Process;
Winson470b15b2019-05-07 16:29:59 -070056import android.os.RemoteCallback;
Svet Ganov47641072019-06-06 12:57:12 -070057import android.provider.Settings;
Brett Chabota26eda92018-07-23 13:08:30 -070058
59import androidx.test.InstrumentationRegistry;
60import androidx.test.filters.SmallTest;
61import androidx.test.runner.AndroidJUnit4;
Peter Visontay859206c2018-01-03 15:43:19 +000062
Philip P. Moltmann6b4f3d52019-05-08 15:14:09 -070063import com.android.dx.mockito.inline.extended.StaticMockitoSession;
64import com.android.server.LocalServices;
Winson33eacc62020-01-24 12:02:58 -080065import com.android.server.pm.parsing.pkg.AndroidPackage;
Amith Yamasani23d4cd72019-04-10 17:57:00 -070066
Philip P. Moltmann6b4f3d52019-05-08 15:14:09 -070067import org.junit.After;
Peter Visontay859206c2018-01-03 15:43:19 +000068import org.junit.Before;
69import org.junit.Test;
70import org.junit.runner.RunWith;
Philip P. Moltmann6b4f3d52019-05-08 15:14:09 -070071import org.mockito.quality.Strictness;
Peter Visontay859206c2018-01-03 15:43:19 +000072
73import java.io.File;
Philip P. Moltmann9046d822019-12-13 15:59:49 -080074import java.util.Collections;
Peter Visontay859206c2018-01-03 15:43:19 +000075import java.util.List;
Winson470b15b2019-05-07 16:29:59 -070076import java.util.concurrent.CountDownLatch;
77import java.util.concurrent.TimeUnit;
78import java.util.concurrent.atomic.AtomicReference;
Peter Visontay859206c2018-01-03 15:43:19 +000079
80/**
81 * Unit tests for AppOpsService. Covers functionality that is difficult to test using CTS tests
82 * or for which we can write more detailed unit tests than CTS tests (because the internal APIs are
83 * more finegrained data than the public ones).
84 */
85@SmallTest
86@RunWith(AndroidJUnit4.class)
87public class AppOpsServiceTest {
88
89 private static final String TAG = AppOpsServiceTest.class.getSimpleName();
90 // State will be persisted into this XML file.
91 private static final String APP_OPS_FILENAME = "appops-service-test.xml";
92
Philip P. Moltmann6b4f3d52019-05-08 15:14:09 -070093 private static final Context sContext = InstrumentationRegistry.getTargetContext();
94 private static final String sMyPackageName = sContext.getOpPackageName();
95
Peter Visontay859206c2018-01-03 15:43:19 +000096 private File mAppOpsFile;
Peter Visontay859206c2018-01-03 15:43:19 +000097 private Handler mHandler;
98 private AppOpsService mAppOpsService;
Peter Visontay859206c2018-01-03 15:43:19 +000099 private int mMyUid;
100 private long mTestStartMillis;
Philip P. Moltmann6b4f3d52019-05-08 15:14:09 -0700101 private StaticMockitoSession mMockingSession;
102
Philip P. Moltmann6b4f3d52019-05-08 15:14:09 -0700103 private void setupAppOpsService() {
Philip P. Moltmannfe2fc3a2020-02-05 16:59:39 -0800104 mAppOpsService = new AppOpsService(mAppOpsFile, mHandler, spy(sContext));
Svet Ganov47641072019-06-06 12:57:12 -0700105 mAppOpsService.mHistoricalRegistry.systemReady(sContext.getContentResolver());
Philip P. Moltmann6b4f3d52019-05-08 15:14:09 -0700106
107 // Always approve all permission checks
108 doNothing().when(mAppOpsService.mContext).enforcePermission(anyString(), anyInt(),
109 anyInt(), nullable(String.class));
110 }
Peter Visontay859206c2018-01-03 15:43:19 +0000111
112 @Before
113 public void setUp() {
Philip P. Moltmann6b4f3d52019-05-08 15:14:09 -0700114 mAppOpsFile = new File(sContext.getFilesDir(), APP_OPS_FILENAME);
Peter Visontay859206c2018-01-03 15:43:19 +0000115 if (mAppOpsFile.exists()) {
116 // Start with a clean state (persisted into XML).
117 mAppOpsFile.delete();
118 }
119
120 HandlerThread handlerThread = new HandlerThread(TAG);
121 handlerThread.start();
122 mHandler = new Handler(handlerThread.getLooper());
Peter Visontay859206c2018-01-03 15:43:19 +0000123 mMyUid = Process.myUid();
124
Svet Ganov47641072019-06-06 12:57:12 -0700125 initializeStaticMocks();
126
Philip P. Moltmann6b4f3d52019-05-08 15:14:09 -0700127 setupAppOpsService();
Svet Ganov47641072019-06-06 12:57:12 -0700128
Peter Visontay859206c2018-01-03 15:43:19 +0000129 mTestStartMillis = System.currentTimeMillis();
130 }
131
Philip P. Moltmann6b4f3d52019-05-08 15:14:09 -0700132 @After
133 public void resetStaticMocks() {
134 mMockingSession.finishMocking();
135 }
136
Svet Ganov47641072019-06-06 12:57:12 -0700137 private void initializeStaticMocks() {
138 mMockingSession = mockitoSession()
139 .strictness(Strictness.LENIENT)
140 .spyStatic(LocalServices.class)
141 .spyStatic(Settings.Global.class)
142 .startMocking();
143
Philip P. Moltmann9046d822019-12-13 15:59:49 -0800144 // Mock LocalServices.getService(PackageManagerInternal.class).getPackage dependency
Svet Ganov47641072019-06-06 12:57:12 -0700145 // needed by AppOpsService
146 PackageManagerInternal mockPackageManagerInternal = mock(PackageManagerInternal.class);
Philip P. Moltmann9046d822019-12-13 15:59:49 -0800147 AndroidPackage mockMyPkg = mock(AndroidPackage.class);
148 when(mockMyPkg.isPrivileged()).thenReturn(false);
149 when(mockMyPkg.getUid()).thenReturn(mMyUid);
Philip P. Moltmann12ac3f42020-03-05 15:01:29 -0800150 when(mockMyPkg.getAttributions()).thenReturn(Collections.emptyList());
Philip P. Moltmann9046d822019-12-13 15:59:49 -0800151
152 when(mockPackageManagerInternal.getPackage(sMyPackageName)).thenReturn(mockMyPkg);
Svet Ganov47641072019-06-06 12:57:12 -0700153 doReturn(mockPackageManagerInternal).when(
154 () -> LocalServices.getService(PackageManagerInternal.class));
155
156 // Mock behavior to use specific Settings.Global.APPOP_HISTORY_PARAMETERS
157 doReturn(null).when(() -> Settings.Global.getString(any(ContentResolver.class),
158 eq(Settings.Global.APPOP_HISTORY_PARAMETERS)));
159 }
160
Peter Visontay859206c2018-01-03 15:43:19 +0000161 @Test
162 public void testGetOpsForPackage_noOpsLogged() {
163 assertThat(getLoggedOps()).isNull();
164 }
165
166 @Test
167 public void testNoteOperationAndGetOpsForPackage() {
Philip P. Moltmann6b4f3d52019-05-08 15:14:09 -0700168 mAppOpsService.setMode(OP_READ_SMS, mMyUid, sMyPackageName, MODE_ALLOWED);
169 mAppOpsService.setMode(OP_WRITE_SMS, mMyUid, sMyPackageName, MODE_ERRORED);
Peter Visontay859206c2018-01-03 15:43:19 +0000170
171 // Note an op that's allowed.
Stanislav Zholnin54762b22020-06-19 13:20:48 +0100172 mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName, null, false, null, false);
Peter Visontay859206c2018-01-03 15:43:19 +0000173 List<PackageOps> loggedOps = getLoggedOps();
174 assertContainsOp(loggedOps, OP_READ_SMS, mTestStartMillis, -1, MODE_ALLOWED);
175
176 // Note another op that's not allowed.
Stanislav Zholnin54762b22020-06-19 13:20:48 +0100177 mAppOpsService.noteOperation(OP_WRITE_SMS, mMyUid, sMyPackageName, null, false, null,
178 false);
Peter Visontay859206c2018-01-03 15:43:19 +0000179 loggedOps = getLoggedOps();
180 assertContainsOp(loggedOps, OP_READ_SMS, mTestStartMillis, -1, MODE_ALLOWED);
181 assertContainsOp(loggedOps, OP_WRITE_SMS, -1, mTestStartMillis, MODE_ERRORED);
182 }
183
Peter Visontay76712362018-04-19 22:04:14 +0100184 /**
185 * Tests the scenario where an operation's permission is controlled by another operation.
186 * For example the results of a WIFI_SCAN can be used to infer the location of a user, so the
187 * ACCESS_COARSE_LOCATION op is used to check whether WIFI_SCAN is allowed.
188 */
189 @Test
190 public void testNoteOperationAndGetOpsForPackage_controlledByDifferentOp() {
191 // This op controls WIFI_SCAN
Philip P. Moltmann6b4f3d52019-05-08 15:14:09 -0700192 mAppOpsService.setMode(OP_COARSE_LOCATION, mMyUid, sMyPackageName, MODE_ALLOWED);
Peter Visontay76712362018-04-19 22:04:14 +0100193
Philip P. Moltmannda554e42019-12-20 11:21:02 -0800194 assertThat(mAppOpsService.noteOperation(OP_WIFI_SCAN, mMyUid, sMyPackageName, null, false,
Stanislav Zholnin54762b22020-06-19 13:20:48 +0100195 null, false)).isEqualTo(MODE_ALLOWED);
Peter Visontay76712362018-04-19 22:04:14 +0100196
197 assertContainsOp(getLoggedOps(), OP_WIFI_SCAN, mTestStartMillis, -1,
198 MODE_ALLOWED /* default for WIFI_SCAN; this is not changed or used in this test */);
199
200 // Now set COARSE_LOCATION to ERRORED -> this will make WIFI_SCAN disabled as well.
Philip P. Moltmann6b4f3d52019-05-08 15:14:09 -0700201 mAppOpsService.setMode(OP_COARSE_LOCATION, mMyUid, sMyPackageName, MODE_ERRORED);
Philip P. Moltmannda554e42019-12-20 11:21:02 -0800202 assertThat(mAppOpsService.noteOperation(OP_WIFI_SCAN, mMyUid, sMyPackageName, null, false,
Stanislav Zholnin54762b22020-06-19 13:20:48 +0100203 null, false)).isEqualTo(MODE_ERRORED);
Peter Visontay76712362018-04-19 22:04:14 +0100204
205 assertContainsOp(getLoggedOps(), OP_WIFI_SCAN, mTestStartMillis, mTestStartMillis,
206 MODE_ALLOWED /* default for WIFI_SCAN; this is not changed or used in this test */);
207 }
208
Peter Visontay859206c2018-01-03 15:43:19 +0000209 // Tests the dumping and restoring of the in-memory state to/from XML.
210 @Test
211 public void testStatePersistence() {
Philip P. Moltmann6b4f3d52019-05-08 15:14:09 -0700212 mAppOpsService.setMode(OP_READ_SMS, mMyUid, sMyPackageName, MODE_ALLOWED);
213 mAppOpsService.setMode(OP_WRITE_SMS, mMyUid, sMyPackageName, MODE_ERRORED);
Stanislav Zholnin54762b22020-06-19 13:20:48 +0100214 mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName, null, false, null, false);
215 mAppOpsService.noteOperation(OP_WRITE_SMS, mMyUid, sMyPackageName, null, false, null,
216 false);
Peter Visontay859206c2018-01-03 15:43:19 +0000217 mAppOpsService.writeState();
218
219 // Create a new app ops service, and initialize its state from XML.
Philip P. Moltmann6b4f3d52019-05-08 15:14:09 -0700220 setupAppOpsService();
Peter Visontay859206c2018-01-03 15:43:19 +0000221 mAppOpsService.readState();
222
223 // Query the state of the 2nd service.
224 List<PackageOps> loggedOps = getLoggedOps();
225 assertContainsOp(loggedOps, OP_READ_SMS, mTestStartMillis, -1, MODE_ALLOWED);
226 assertContainsOp(loggedOps, OP_WRITE_SMS, -1, mTestStartMillis, MODE_ERRORED);
227 }
228
229 // Tests that ops are persisted during shutdown.
230 @Test
231 public void testShutdown() {
Philip P. Moltmann6b4f3d52019-05-08 15:14:09 -0700232 mAppOpsService.setMode(OP_READ_SMS, mMyUid, sMyPackageName, MODE_ALLOWED);
Stanislav Zholnin54762b22020-06-19 13:20:48 +0100233 mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName, null, false, null, false);
Peter Visontay859206c2018-01-03 15:43:19 +0000234 mAppOpsService.shutdown();
235
236 // Create a new app ops service, and initialize its state from XML.
Philip P. Moltmann6b4f3d52019-05-08 15:14:09 -0700237 setupAppOpsService();
Peter Visontay859206c2018-01-03 15:43:19 +0000238 mAppOpsService.readState();
239
240 // Query the state of the 2nd service.
241 List<PackageOps> loggedOps = getLoggedOps();
242 assertContainsOp(loggedOps, OP_READ_SMS, mTestStartMillis, -1, MODE_ALLOWED);
243 }
244
245 @Test
246 public void testGetOpsForPackage() {
Philip P. Moltmann6b4f3d52019-05-08 15:14:09 -0700247 mAppOpsService.setMode(OP_READ_SMS, mMyUid, sMyPackageName, MODE_ALLOWED);
Stanislav Zholnin54762b22020-06-19 13:20:48 +0100248 mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName, null, false, null, false);
Peter Visontay859206c2018-01-03 15:43:19 +0000249
250 // Query all ops
251 List<PackageOps> loggedOps = mAppOpsService.getOpsForPackage(
Philip P. Moltmann6b4f3d52019-05-08 15:14:09 -0700252 mMyUid, sMyPackageName, null /* all ops */);
Peter Visontay859206c2018-01-03 15:43:19 +0000253 assertContainsOp(loggedOps, OP_READ_SMS, mTestStartMillis, -1, MODE_ALLOWED);
254
255 // Query specific ops
256 loggedOps = mAppOpsService.getOpsForPackage(
Philip P. Moltmann6b4f3d52019-05-08 15:14:09 -0700257 mMyUid, sMyPackageName, new int[]{OP_READ_SMS, OP_WRITE_SMS});
Peter Visontay859206c2018-01-03 15:43:19 +0000258 assertContainsOp(loggedOps, OP_READ_SMS, mTestStartMillis, -1, MODE_ALLOWED);
259
260 // Query unknown UID
Philip P. Moltmann6b4f3d52019-05-08 15:14:09 -0700261 loggedOps = mAppOpsService.getOpsForPackage(mMyUid + 1, sMyPackageName, null /* all ops */);
Peter Visontay859206c2018-01-03 15:43:19 +0000262 assertThat(loggedOps).isNull();
263
264 // Query unknown package name
265 loggedOps = mAppOpsService.getOpsForPackage(mMyUid, "fake.package", null /* all ops */);
266 assertThat(loggedOps).isNull();
267
268 // Query op code that's not been logged
Philip P. Moltmann6b4f3d52019-05-08 15:14:09 -0700269 loggedOps = mAppOpsService.getOpsForPackage(mMyUid, sMyPackageName,
Peter Visontay859206c2018-01-03 15:43:19 +0000270 new int[]{OP_WRITE_SMS});
271 assertThat(loggedOps).isNull();
272 }
273
274 @Test
275 public void testPackageRemoved() {
Philip P. Moltmann6b4f3d52019-05-08 15:14:09 -0700276 mAppOpsService.setMode(OP_READ_SMS, mMyUid, sMyPackageName, MODE_ALLOWED);
Stanislav Zholnin54762b22020-06-19 13:20:48 +0100277 mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName, null, false, null, false);
Peter Visontay859206c2018-01-03 15:43:19 +0000278
279 List<PackageOps> loggedOps = getLoggedOps();
280 assertContainsOp(loggedOps, OP_READ_SMS, mTestStartMillis, -1, MODE_ALLOWED);
281
Philip P. Moltmann6b4f3d52019-05-08 15:14:09 -0700282 mAppOpsService.packageRemoved(mMyUid, sMyPackageName);
Peter Visontay859206c2018-01-03 15:43:19 +0000283 assertThat(getLoggedOps()).isNull();
284 }
285
Philip P. Moltmann0027a672019-06-29 03:36:19 +0000286
Nate Myren697650b2020-01-23 13:25:06 -0800287 /*
288 TODO ntmyren: re enable when we have time to rewrite test.
Winson470b15b2019-05-07 16:29:59 -0700289 @Test
290 public void testPackageRemovedHistoricalOps() throws InterruptedException {
291 mAppOpsService.setMode(OP_READ_SMS, mMyUid, sMyPackageName, MODE_ALLOWED);
Stanislav Zholnin54762b22020-06-19 13:20:48 +0100292 mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName, null, false, null, false);
Winson470b15b2019-05-07 16:29:59 -0700293
294 AppOpsManager.HistoricalOps historicalOps = new AppOpsManager.HistoricalOps(0, 15000);
Philip P. Moltmann4aacd712020-01-03 12:32:20 -0800295 historicalOps.increaseAccessCount(OP_READ_SMS, mMyUid, sMyPackageName, null,
Winson470b15b2019-05-07 16:29:59 -0700296 AppOpsManager.UID_STATE_PERSISTENT, 0, 1);
297
298 mAppOpsService.addHistoricalOps(historicalOps);
299
300 AtomicReference<AppOpsManager.HistoricalOps> resultOpsRef = new AtomicReference<>();
301 AtomicReference<CountDownLatch> latchRef = new AtomicReference<>(new CountDownLatch(1));
302 RemoteCallback callback = new RemoteCallback(result -> {
303 resultOpsRef.set(result.getParcelable(AppOpsManager.KEY_HISTORICAL_OPS));
304 latchRef.get().countDown();
305 });
306
307 // First, do a fetch to ensure it's written
Philip P. Moltmann4aacd712020-01-03 12:32:20 -0800308 mAppOpsService.getHistoricalOps(mMyUid, sMyPackageName, null, null,
309 FILTER_BY_UID | FILTER_BY_PACKAGE_NAME, 0, Long.MAX_VALUE, 0, callback);
Winson470b15b2019-05-07 16:29:59 -0700310
311 latchRef.get().await(5, TimeUnit.SECONDS);
312 assertThat(latchRef.get().getCount()).isEqualTo(0);
313 assertThat(resultOpsRef.get().isEmpty()).isFalse();
314
315 // Then, check it's deleted on removal
316 mAppOpsService.packageRemoved(mMyUid, sMyPackageName);
317
318 latchRef.set(new CountDownLatch(1));
319
Philip P. Moltmann4aacd712020-01-03 12:32:20 -0800320 mAppOpsService.getHistoricalOps(mMyUid, sMyPackageName, null, null,
321 FILTER_BY_UID | FILTER_BY_PACKAGE_NAME, 0, Long.MAX_VALUE, 0, callback);
Winson470b15b2019-05-07 16:29:59 -0700322
323 latchRef.get().await(5, TimeUnit.SECONDS);
324 assertThat(latchRef.get().getCount()).isEqualTo(0);
325 assertThat(resultOpsRef.get().isEmpty()).isTrue();
326 }
Nate Myren697650b2020-01-23 13:25:06 -0800327 */
Winson470b15b2019-05-07 16:29:59 -0700328
Peter Visontay859206c2018-01-03 15:43:19 +0000329 @Test
330 public void testUidRemoved() {
Philip P. Moltmann6b4f3d52019-05-08 15:14:09 -0700331 mAppOpsService.setMode(OP_READ_SMS, mMyUid, sMyPackageName, MODE_ALLOWED);
Stanislav Zholnin54762b22020-06-19 13:20:48 +0100332 mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName, null, false, null, false);
Peter Visontay859206c2018-01-03 15:43:19 +0000333
334 List<PackageOps> loggedOps = getLoggedOps();
335 assertContainsOp(loggedOps, OP_READ_SMS, mTestStartMillis, -1, MODE_ALLOWED);
336
337 mAppOpsService.uidRemoved(mMyUid);
338 assertThat(getLoggedOps()).isNull();
339 }
340
Amith Yamasani23d4cd72019-04-10 17:57:00 -0700341 private void setupProcStateTests() {
342 // For the location proc state tests
Philip P. Moltmann6b4f3d52019-05-08 15:14:09 -0700343 mAppOpsService.setMode(OP_COARSE_LOCATION, mMyUid, sMyPackageName, MODE_FOREGROUND);
Amith Yamasani23d4cd72019-04-10 17:57:00 -0700344 mAppOpsService.mConstants.FG_SERVICE_STATE_SETTLE_TIME = 0;
345 mAppOpsService.mConstants.TOP_STATE_SETTLE_TIME = 0;
346 mAppOpsService.mConstants.BG_STATE_SETTLE_TIME = 0;
347 }
348
349 @Test
350 public void testUidProcStateChange_cachedToTopToCached() throws Exception {
351 setupProcStateTests();
352
Hui Yu26969322019-08-21 14:56:35 -0700353 mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY,
354 ActivityManager.PROCESS_CAPABILITY_NONE);
Philip P. Moltmannda554e42019-12-20 11:21:02 -0800355 assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
Stanislav Zholnin54762b22020-06-19 13:20:48 +0100356 false, null, false)).isNotEqualTo(MODE_ALLOWED);
Amith Yamasani23d4cd72019-04-10 17:57:00 -0700357
Hui Yu26969322019-08-21 14:56:35 -0700358 mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_TOP,
359 ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION);
Philip P. Moltmannda554e42019-12-20 11:21:02 -0800360 assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
Stanislav Zholnin54762b22020-06-19 13:20:48 +0100361 false, null, false)).isEqualTo(MODE_ALLOWED);
Amith Yamasani23d4cd72019-04-10 17:57:00 -0700362
Hui Yu26969322019-08-21 14:56:35 -0700363 mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY,
364 ActivityManager.PROCESS_CAPABILITY_NONE);
Amith Yamasani23d4cd72019-04-10 17:57:00 -0700365 // Second time to make sure that settle time is overcome
366 Thread.sleep(50);
Hui Yu26969322019-08-21 14:56:35 -0700367 mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY,
368 ActivityManager.PROCESS_CAPABILITY_NONE);
Philip P. Moltmannda554e42019-12-20 11:21:02 -0800369 assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
Stanislav Zholnin54762b22020-06-19 13:20:48 +0100370 false, null, false)).isNotEqualTo(MODE_ALLOWED);
Amith Yamasani23d4cd72019-04-10 17:57:00 -0700371 }
372
373 @Test
Svet Ganov47641072019-06-06 12:57:12 -0700374 public void testUidProcStateChange_cachedToFgs() {
Amith Yamasani23d4cd72019-04-10 17:57:00 -0700375 setupProcStateTests();
Hui Yu26969322019-08-21 14:56:35 -0700376 mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY,
377 ActivityManager.PROCESS_CAPABILITY_NONE);
Philip P. Moltmannda554e42019-12-20 11:21:02 -0800378 assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
Stanislav Zholnin54762b22020-06-19 13:20:48 +0100379 false, null, false)).isNotEqualTo(MODE_ALLOWED);
Amith Yamasani23d4cd72019-04-10 17:57:00 -0700380
Hui Yu26969322019-08-21 14:56:35 -0700381 mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE,
382 ActivityManager.PROCESS_CAPABILITY_NONE);
Philip P. Moltmannda554e42019-12-20 11:21:02 -0800383 assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
Stanislav Zholnin54762b22020-06-19 13:20:48 +0100384 false, null, false)).isNotEqualTo(MODE_ALLOWED);
Amith Yamasani23d4cd72019-04-10 17:57:00 -0700385 }
386
387 @Test
Svet Ganov47641072019-06-06 12:57:12 -0700388 public void testUidProcStateChange_cachedToFgsLocation() {
Amith Yamasani23d4cd72019-04-10 17:57:00 -0700389 setupProcStateTests();
390
Hui Yu26969322019-08-21 14:56:35 -0700391 mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY,
392 ActivityManager.PROCESS_CAPABILITY_NONE);
Philip P. Moltmannda554e42019-12-20 11:21:02 -0800393 assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
Stanislav Zholnin54762b22020-06-19 13:20:48 +0100394 false, null, false)).isNotEqualTo(MODE_ALLOWED);
Amith Yamasani23d4cd72019-04-10 17:57:00 -0700395
Hui Yu26969322019-08-21 14:56:35 -0700396 mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE,
397 ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION);
Philip P. Moltmannda554e42019-12-20 11:21:02 -0800398 assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
Stanislav Zholnin54762b22020-06-19 13:20:48 +0100399 false, null, false)).isEqualTo(MODE_ALLOWED);
Amith Yamasani23d4cd72019-04-10 17:57:00 -0700400 }
401
402 @Test
403 public void testUidProcStateChange_topToFgs() throws Exception {
404 setupProcStateTests();
405
Hui Yu26969322019-08-21 14:56:35 -0700406 mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY,
407 ActivityManager.PROCESS_CAPABILITY_NONE);
Philip P. Moltmannda554e42019-12-20 11:21:02 -0800408 assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
Stanislav Zholnin54762b22020-06-19 13:20:48 +0100409 false, null, false)).isNotEqualTo(MODE_ALLOWED);
Amith Yamasani23d4cd72019-04-10 17:57:00 -0700410
Hui Yu26969322019-08-21 14:56:35 -0700411 mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_TOP,
412 ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION);
Philip P. Moltmannda554e42019-12-20 11:21:02 -0800413 assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
Stanislav Zholnin54762b22020-06-19 13:20:48 +0100414 false, null, false)).isEqualTo(MODE_ALLOWED);
Amith Yamasani23d4cd72019-04-10 17:57:00 -0700415
Hui Yu26969322019-08-21 14:56:35 -0700416 mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE,
417 ActivityManager.PROCESS_CAPABILITY_NONE);
Amith Yamasani23d4cd72019-04-10 17:57:00 -0700418 // Second time to make sure that settle time is overcome
419 Thread.sleep(50);
Hui Yu26969322019-08-21 14:56:35 -0700420 mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE,
421 ActivityManager.PROCESS_CAPABILITY_NONE);
Philip P. Moltmannda554e42019-12-20 11:21:02 -0800422 assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
Stanislav Zholnin54762b22020-06-19 13:20:48 +0100423 false, null, false)).isNotEqualTo(MODE_ALLOWED);
Amith Yamasani23d4cd72019-04-10 17:57:00 -0700424 }
425
426 @Test
427 public void testUidProcStateChange_topToFgsLocationToFgs() throws Exception {
428 setupProcStateTests();
429
Hui Yu26969322019-08-21 14:56:35 -0700430 mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY,
431 ActivityManager.PROCESS_CAPABILITY_NONE);
Philip P. Moltmannda554e42019-12-20 11:21:02 -0800432 assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
Stanislav Zholnin54762b22020-06-19 13:20:48 +0100433 false, null, false)).isNotEqualTo(MODE_ALLOWED);
Amith Yamasani23d4cd72019-04-10 17:57:00 -0700434
Hui Yu26969322019-08-21 14:56:35 -0700435 mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_TOP,
436 ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION);
Philip P. Moltmannda554e42019-12-20 11:21:02 -0800437 assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
Stanislav Zholnin54762b22020-06-19 13:20:48 +0100438 false, null, false)).isEqualTo(MODE_ALLOWED);
Amith Yamasani23d4cd72019-04-10 17:57:00 -0700439
Hui Yu26969322019-08-21 14:56:35 -0700440 mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE,
441 ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION);
Amith Yamasani23d4cd72019-04-10 17:57:00 -0700442 // Second time to make sure that settle time is overcome
443 Thread.sleep(50);
Hui Yu26969322019-08-21 14:56:35 -0700444 mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE,
445 ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION);
Philip P. Moltmannda554e42019-12-20 11:21:02 -0800446 assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
Stanislav Zholnin54762b22020-06-19 13:20:48 +0100447 false, null, false)).isEqualTo(MODE_ALLOWED);
Amith Yamasani23d4cd72019-04-10 17:57:00 -0700448
Hui Yu26969322019-08-21 14:56:35 -0700449 mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE,
450 ActivityManager.PROCESS_CAPABILITY_NONE);
Amith Yamasani23d4cd72019-04-10 17:57:00 -0700451 // Second time to make sure that settle time is overcome
452 Thread.sleep(50);
Hui Yu26969322019-08-21 14:56:35 -0700453 mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE,
454 ActivityManager.PROCESS_CAPABILITY_NONE);
Philip P. Moltmannda554e42019-12-20 11:21:02 -0800455 assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
Stanislav Zholnin54762b22020-06-19 13:20:48 +0100456 false, null, false)).isNotEqualTo(MODE_ALLOWED);
Amith Yamasani23d4cd72019-04-10 17:57:00 -0700457 }
458
Peter Visontay859206c2018-01-03 15:43:19 +0000459 private List<PackageOps> getLoggedOps() {
Philip P. Moltmann6b4f3d52019-05-08 15:14:09 -0700460 return mAppOpsService.getOpsForPackage(mMyUid, sMyPackageName, null /* all ops */);
Peter Visontay859206c2018-01-03 15:43:19 +0000461 }
462
463 private void assertContainsOp(List<PackageOps> loggedOps, int opCode, long minMillis,
464 long minRejectMillis, int mode) {
465
466 boolean opLogged = false;
467 for (PackageOps pkgOps : loggedOps) {
468 assertWithMessage("Unexpected UID").that(mMyUid).isEqualTo(pkgOps.getUid());
Philip P. Moltmann6b4f3d52019-05-08 15:14:09 -0700469 assertWithMessage("Unexpected package name").that(sMyPackageName).isEqualTo(
Peter Visontay859206c2018-01-03 15:43:19 +0000470 pkgOps.getPackageName());
471
472 for (OpEntry opEntry : pkgOps.getOps()) {
473 if (opCode != opEntry.getOp()) {
474 continue;
475 }
476 opLogged = true;
477
478 assertWithMessage("Unexpected mode").that(mode).isEqualTo(opEntry.getMode());
479 if (minMillis > 0) {
480 assertWithMessage("Unexpected timestamp")
Philip P. Moltmann49bd9e12019-11-26 15:18:16 -0800481 .that(opEntry.getLastAccessTime(OP_FLAGS_ALL)).isAtLeast(minMillis);
Peter Visontay859206c2018-01-03 15:43:19 +0000482 }
483 if (minRejectMillis > 0) {
Philip P. Moltmann49bd9e12019-11-26 15:18:16 -0800484 assertWithMessage("Unexpected rejection timestamp").that(
485 opEntry.getLastRejectTime(OP_FLAGS_ALL)).isAtLeast(minRejectMillis);
Peter Visontay859206c2018-01-03 15:43:19 +0000486 }
487 }
488 }
489 assertWithMessage("Op was not logged").that(opLogged).isTrue();
490 }
491}