blob: de6f55ba10533252434795f0653341ad3cd6df7c [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.
Philip P. Moltmannda554e42019-12-20 11:21:02 -0800172 mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName, null, false, null);
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.
Philip P. Moltmannda554e42019-12-20 11:21:02 -0800177 mAppOpsService.noteOperation(OP_WRITE_SMS, mMyUid, sMyPackageName, null, false, null);
Peter Visontay859206c2018-01-03 15:43:19 +0000178 loggedOps = getLoggedOps();
179 assertContainsOp(loggedOps, OP_READ_SMS, mTestStartMillis, -1, MODE_ALLOWED);
180 assertContainsOp(loggedOps, OP_WRITE_SMS, -1, mTestStartMillis, MODE_ERRORED);
181 }
182
Peter Visontay76712362018-04-19 22:04:14 +0100183 /**
184 * Tests the scenario where an operation's permission is controlled by another operation.
185 * For example the results of a WIFI_SCAN can be used to infer the location of a user, so the
186 * ACCESS_COARSE_LOCATION op is used to check whether WIFI_SCAN is allowed.
187 */
188 @Test
189 public void testNoteOperationAndGetOpsForPackage_controlledByDifferentOp() {
190 // This op controls WIFI_SCAN
Philip P. Moltmann6b4f3d52019-05-08 15:14:09 -0700191 mAppOpsService.setMode(OP_COARSE_LOCATION, mMyUid, sMyPackageName, MODE_ALLOWED);
Peter Visontay76712362018-04-19 22:04:14 +0100192
Philip P. Moltmannda554e42019-12-20 11:21:02 -0800193 assertThat(mAppOpsService.noteOperation(OP_WIFI_SCAN, mMyUid, sMyPackageName, null, false,
194 null)).isEqualTo(MODE_ALLOWED);
Peter Visontay76712362018-04-19 22:04:14 +0100195
196 assertContainsOp(getLoggedOps(), OP_WIFI_SCAN, mTestStartMillis, -1,
197 MODE_ALLOWED /* default for WIFI_SCAN; this is not changed or used in this test */);
198
199 // Now set COARSE_LOCATION to ERRORED -> this will make WIFI_SCAN disabled as well.
Philip P. Moltmann6b4f3d52019-05-08 15:14:09 -0700200 mAppOpsService.setMode(OP_COARSE_LOCATION, mMyUid, sMyPackageName, MODE_ERRORED);
Philip P. Moltmannda554e42019-12-20 11:21:02 -0800201 assertThat(mAppOpsService.noteOperation(OP_WIFI_SCAN, mMyUid, sMyPackageName, null, false,
202 null)).isEqualTo(MODE_ERRORED);
Peter Visontay76712362018-04-19 22:04:14 +0100203
204 assertContainsOp(getLoggedOps(), OP_WIFI_SCAN, mTestStartMillis, mTestStartMillis,
205 MODE_ALLOWED /* default for WIFI_SCAN; this is not changed or used in this test */);
206 }
207
Peter Visontay859206c2018-01-03 15:43:19 +0000208 // Tests the dumping and restoring of the in-memory state to/from XML.
209 @Test
210 public void testStatePersistence() {
Philip P. Moltmann6b4f3d52019-05-08 15:14:09 -0700211 mAppOpsService.setMode(OP_READ_SMS, mMyUid, sMyPackageName, MODE_ALLOWED);
212 mAppOpsService.setMode(OP_WRITE_SMS, mMyUid, sMyPackageName, MODE_ERRORED);
Philip P. Moltmannda554e42019-12-20 11:21:02 -0800213 mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName, null, false, null);
214 mAppOpsService.noteOperation(OP_WRITE_SMS, mMyUid, sMyPackageName, null, false, null);
Peter Visontay859206c2018-01-03 15:43:19 +0000215 mAppOpsService.writeState();
216
217 // Create a new app ops service, and initialize its state from XML.
Philip P. Moltmann6b4f3d52019-05-08 15:14:09 -0700218 setupAppOpsService();
Peter Visontay859206c2018-01-03 15:43:19 +0000219 mAppOpsService.readState();
220
221 // Query the state of the 2nd service.
222 List<PackageOps> loggedOps = getLoggedOps();
223 assertContainsOp(loggedOps, OP_READ_SMS, mTestStartMillis, -1, MODE_ALLOWED);
224 assertContainsOp(loggedOps, OP_WRITE_SMS, -1, mTestStartMillis, MODE_ERRORED);
225 }
226
227 // Tests that ops are persisted during shutdown.
228 @Test
229 public void testShutdown() {
Philip P. Moltmann6b4f3d52019-05-08 15:14:09 -0700230 mAppOpsService.setMode(OP_READ_SMS, mMyUid, sMyPackageName, MODE_ALLOWED);
Philip P. Moltmannda554e42019-12-20 11:21:02 -0800231 mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName, null, false, null);
Peter Visontay859206c2018-01-03 15:43:19 +0000232 mAppOpsService.shutdown();
233
234 // Create a new app ops service, and initialize its state from XML.
Philip P. Moltmann6b4f3d52019-05-08 15:14:09 -0700235 setupAppOpsService();
Peter Visontay859206c2018-01-03 15:43:19 +0000236 mAppOpsService.readState();
237
238 // Query the state of the 2nd service.
239 List<PackageOps> loggedOps = getLoggedOps();
240 assertContainsOp(loggedOps, OP_READ_SMS, mTestStartMillis, -1, MODE_ALLOWED);
241 }
242
243 @Test
244 public void testGetOpsForPackage() {
Philip P. Moltmann6b4f3d52019-05-08 15:14:09 -0700245 mAppOpsService.setMode(OP_READ_SMS, mMyUid, sMyPackageName, MODE_ALLOWED);
Philip P. Moltmannda554e42019-12-20 11:21:02 -0800246 mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName, null, false, null);
Peter Visontay859206c2018-01-03 15:43:19 +0000247
248 // Query all ops
249 List<PackageOps> loggedOps = mAppOpsService.getOpsForPackage(
Philip P. Moltmann6b4f3d52019-05-08 15:14:09 -0700250 mMyUid, sMyPackageName, null /* all ops */);
Peter Visontay859206c2018-01-03 15:43:19 +0000251 assertContainsOp(loggedOps, OP_READ_SMS, mTestStartMillis, -1, MODE_ALLOWED);
252
253 // Query specific ops
254 loggedOps = mAppOpsService.getOpsForPackage(
Philip P. Moltmann6b4f3d52019-05-08 15:14:09 -0700255 mMyUid, sMyPackageName, new int[]{OP_READ_SMS, OP_WRITE_SMS});
Peter Visontay859206c2018-01-03 15:43:19 +0000256 assertContainsOp(loggedOps, OP_READ_SMS, mTestStartMillis, -1, MODE_ALLOWED);
257
258 // Query unknown UID
Philip P. Moltmann6b4f3d52019-05-08 15:14:09 -0700259 loggedOps = mAppOpsService.getOpsForPackage(mMyUid + 1, sMyPackageName, null /* all ops */);
Peter Visontay859206c2018-01-03 15:43:19 +0000260 assertThat(loggedOps).isNull();
261
262 // Query unknown package name
263 loggedOps = mAppOpsService.getOpsForPackage(mMyUid, "fake.package", null /* all ops */);
264 assertThat(loggedOps).isNull();
265
266 // Query op code that's not been logged
Philip P. Moltmann6b4f3d52019-05-08 15:14:09 -0700267 loggedOps = mAppOpsService.getOpsForPackage(mMyUid, sMyPackageName,
Peter Visontay859206c2018-01-03 15:43:19 +0000268 new int[]{OP_WRITE_SMS});
269 assertThat(loggedOps).isNull();
270 }
271
272 @Test
273 public void testPackageRemoved() {
Philip P. Moltmann6b4f3d52019-05-08 15:14:09 -0700274 mAppOpsService.setMode(OP_READ_SMS, mMyUid, sMyPackageName, MODE_ALLOWED);
Philip P. Moltmannda554e42019-12-20 11:21:02 -0800275 mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName, null, false, null);
Peter Visontay859206c2018-01-03 15:43:19 +0000276
277 List<PackageOps> loggedOps = getLoggedOps();
278 assertContainsOp(loggedOps, OP_READ_SMS, mTestStartMillis, -1, MODE_ALLOWED);
279
Philip P. Moltmann6b4f3d52019-05-08 15:14:09 -0700280 mAppOpsService.packageRemoved(mMyUid, sMyPackageName);
Peter Visontay859206c2018-01-03 15:43:19 +0000281 assertThat(getLoggedOps()).isNull();
282 }
283
Philip P. Moltmann0027a672019-06-29 03:36:19 +0000284
Nate Myren697650b2020-01-23 13:25:06 -0800285 /*
286 TODO ntmyren: re enable when we have time to rewrite test.
Winson470b15b2019-05-07 16:29:59 -0700287 @Test
288 public void testPackageRemovedHistoricalOps() throws InterruptedException {
289 mAppOpsService.setMode(OP_READ_SMS, mMyUid, sMyPackageName, MODE_ALLOWED);
Philip P. Moltmannda554e42019-12-20 11:21:02 -0800290 mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName, null, false, null);
Winson470b15b2019-05-07 16:29:59 -0700291
292 AppOpsManager.HistoricalOps historicalOps = new AppOpsManager.HistoricalOps(0, 15000);
Philip P. Moltmann4aacd712020-01-03 12:32:20 -0800293 historicalOps.increaseAccessCount(OP_READ_SMS, mMyUid, sMyPackageName, null,
Winson470b15b2019-05-07 16:29:59 -0700294 AppOpsManager.UID_STATE_PERSISTENT, 0, 1);
295
296 mAppOpsService.addHistoricalOps(historicalOps);
297
298 AtomicReference<AppOpsManager.HistoricalOps> resultOpsRef = new AtomicReference<>();
299 AtomicReference<CountDownLatch> latchRef = new AtomicReference<>(new CountDownLatch(1));
300 RemoteCallback callback = new RemoteCallback(result -> {
301 resultOpsRef.set(result.getParcelable(AppOpsManager.KEY_HISTORICAL_OPS));
302 latchRef.get().countDown();
303 });
304
305 // First, do a fetch to ensure it's written
Philip P. Moltmann4aacd712020-01-03 12:32:20 -0800306 mAppOpsService.getHistoricalOps(mMyUid, sMyPackageName, null, null,
307 FILTER_BY_UID | FILTER_BY_PACKAGE_NAME, 0, Long.MAX_VALUE, 0, callback);
Winson470b15b2019-05-07 16:29:59 -0700308
309 latchRef.get().await(5, TimeUnit.SECONDS);
310 assertThat(latchRef.get().getCount()).isEqualTo(0);
311 assertThat(resultOpsRef.get().isEmpty()).isFalse();
312
313 // Then, check it's deleted on removal
314 mAppOpsService.packageRemoved(mMyUid, sMyPackageName);
315
316 latchRef.set(new CountDownLatch(1));
317
Philip P. Moltmann4aacd712020-01-03 12:32:20 -0800318 mAppOpsService.getHistoricalOps(mMyUid, sMyPackageName, null, null,
319 FILTER_BY_UID | FILTER_BY_PACKAGE_NAME, 0, Long.MAX_VALUE, 0, callback);
Winson470b15b2019-05-07 16:29:59 -0700320
321 latchRef.get().await(5, TimeUnit.SECONDS);
322 assertThat(latchRef.get().getCount()).isEqualTo(0);
323 assertThat(resultOpsRef.get().isEmpty()).isTrue();
324 }
Nate Myren697650b2020-01-23 13:25:06 -0800325 */
Winson470b15b2019-05-07 16:29:59 -0700326
Peter Visontay859206c2018-01-03 15:43:19 +0000327 @Test
328 public void testUidRemoved() {
Philip P. Moltmann6b4f3d52019-05-08 15:14:09 -0700329 mAppOpsService.setMode(OP_READ_SMS, mMyUid, sMyPackageName, MODE_ALLOWED);
Philip P. Moltmannda554e42019-12-20 11:21:02 -0800330 mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName, null, false, null);
Peter Visontay859206c2018-01-03 15:43:19 +0000331
332 List<PackageOps> loggedOps = getLoggedOps();
333 assertContainsOp(loggedOps, OP_READ_SMS, mTestStartMillis, -1, MODE_ALLOWED);
334
335 mAppOpsService.uidRemoved(mMyUid);
336 assertThat(getLoggedOps()).isNull();
337 }
338
Amith Yamasani23d4cd72019-04-10 17:57:00 -0700339 private void setupProcStateTests() {
340 // For the location proc state tests
Philip P. Moltmann6b4f3d52019-05-08 15:14:09 -0700341 mAppOpsService.setMode(OP_COARSE_LOCATION, mMyUid, sMyPackageName, MODE_FOREGROUND);
Amith Yamasani23d4cd72019-04-10 17:57:00 -0700342 mAppOpsService.mConstants.FG_SERVICE_STATE_SETTLE_TIME = 0;
343 mAppOpsService.mConstants.TOP_STATE_SETTLE_TIME = 0;
344 mAppOpsService.mConstants.BG_STATE_SETTLE_TIME = 0;
345 }
346
347 @Test
348 public void testUidProcStateChange_cachedToTopToCached() throws Exception {
349 setupProcStateTests();
350
Hui Yu26969322019-08-21 14:56:35 -0700351 mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY,
352 ActivityManager.PROCESS_CAPABILITY_NONE);
Philip P. Moltmannda554e42019-12-20 11:21:02 -0800353 assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
354 false, null)).isNotEqualTo(MODE_ALLOWED);
Amith Yamasani23d4cd72019-04-10 17:57:00 -0700355
Hui Yu26969322019-08-21 14:56:35 -0700356 mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_TOP,
357 ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION);
Philip P. Moltmannda554e42019-12-20 11:21:02 -0800358 assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
359 false, null)).isEqualTo(MODE_ALLOWED);
Amith Yamasani23d4cd72019-04-10 17:57:00 -0700360
Hui Yu26969322019-08-21 14:56:35 -0700361 mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY,
362 ActivityManager.PROCESS_CAPABILITY_NONE);
Amith Yamasani23d4cd72019-04-10 17:57:00 -0700363 // Second time to make sure that settle time is overcome
364 Thread.sleep(50);
Hui Yu26969322019-08-21 14:56:35 -0700365 mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY,
366 ActivityManager.PROCESS_CAPABILITY_NONE);
Philip P. Moltmannda554e42019-12-20 11:21:02 -0800367 assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
368 false, null)).isNotEqualTo(MODE_ALLOWED);
Amith Yamasani23d4cd72019-04-10 17:57:00 -0700369 }
370
371 @Test
Svet Ganov47641072019-06-06 12:57:12 -0700372 public void testUidProcStateChange_cachedToFgs() {
Amith Yamasani23d4cd72019-04-10 17:57:00 -0700373 setupProcStateTests();
Hui Yu26969322019-08-21 14:56:35 -0700374 mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY,
375 ActivityManager.PROCESS_CAPABILITY_NONE);
Philip P. Moltmannda554e42019-12-20 11:21:02 -0800376 assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
377 false, null)).isNotEqualTo(MODE_ALLOWED);
Amith Yamasani23d4cd72019-04-10 17:57:00 -0700378
Hui Yu26969322019-08-21 14:56:35 -0700379 mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE,
380 ActivityManager.PROCESS_CAPABILITY_NONE);
Philip P. Moltmannda554e42019-12-20 11:21:02 -0800381 assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
382 false, null)).isNotEqualTo(MODE_ALLOWED);
Amith Yamasani23d4cd72019-04-10 17:57:00 -0700383 }
384
385 @Test
Svet Ganov47641072019-06-06 12:57:12 -0700386 public void testUidProcStateChange_cachedToFgsLocation() {
Amith Yamasani23d4cd72019-04-10 17:57:00 -0700387 setupProcStateTests();
388
Hui Yu26969322019-08-21 14:56:35 -0700389 mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY,
390 ActivityManager.PROCESS_CAPABILITY_NONE);
Philip P. Moltmannda554e42019-12-20 11:21:02 -0800391 assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
392 false, null)).isNotEqualTo(MODE_ALLOWED);
Amith Yamasani23d4cd72019-04-10 17:57:00 -0700393
Hui Yu26969322019-08-21 14:56:35 -0700394 mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE,
395 ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION);
Philip P. Moltmannda554e42019-12-20 11:21:02 -0800396 assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
397 false, null)).isEqualTo(MODE_ALLOWED);
Amith Yamasani23d4cd72019-04-10 17:57:00 -0700398 }
399
400 @Test
401 public void testUidProcStateChange_topToFgs() throws Exception {
402 setupProcStateTests();
403
Hui Yu26969322019-08-21 14:56:35 -0700404 mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY,
405 ActivityManager.PROCESS_CAPABILITY_NONE);
Philip P. Moltmannda554e42019-12-20 11:21:02 -0800406 assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
407 false, null)).isNotEqualTo(MODE_ALLOWED);
Amith Yamasani23d4cd72019-04-10 17:57:00 -0700408
Hui Yu26969322019-08-21 14:56:35 -0700409 mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_TOP,
410 ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION);
Philip P. Moltmannda554e42019-12-20 11:21:02 -0800411 assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
412 false, null)).isEqualTo(MODE_ALLOWED);
Amith Yamasani23d4cd72019-04-10 17:57:00 -0700413
Hui Yu26969322019-08-21 14:56:35 -0700414 mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE,
415 ActivityManager.PROCESS_CAPABILITY_NONE);
Amith Yamasani23d4cd72019-04-10 17:57:00 -0700416 // Second time to make sure that settle time is overcome
417 Thread.sleep(50);
Hui Yu26969322019-08-21 14:56:35 -0700418 mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE,
419 ActivityManager.PROCESS_CAPABILITY_NONE);
Philip P. Moltmannda554e42019-12-20 11:21:02 -0800420 assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
421 false, null)).isNotEqualTo(MODE_ALLOWED);
Amith Yamasani23d4cd72019-04-10 17:57:00 -0700422 }
423
424 @Test
425 public void testUidProcStateChange_topToFgsLocationToFgs() throws Exception {
426 setupProcStateTests();
427
Hui Yu26969322019-08-21 14:56:35 -0700428 mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY,
429 ActivityManager.PROCESS_CAPABILITY_NONE);
Philip P. Moltmannda554e42019-12-20 11:21:02 -0800430 assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
431 false, null)).isNotEqualTo(MODE_ALLOWED);
Amith Yamasani23d4cd72019-04-10 17:57:00 -0700432
Hui Yu26969322019-08-21 14:56:35 -0700433 mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_TOP,
434 ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION);
Philip P. Moltmannda554e42019-12-20 11:21:02 -0800435 assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
436 false, null)).isEqualTo(MODE_ALLOWED);
Amith Yamasani23d4cd72019-04-10 17:57:00 -0700437
Hui Yu26969322019-08-21 14:56:35 -0700438 mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE,
439 ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION);
Amith Yamasani23d4cd72019-04-10 17:57:00 -0700440 // Second time to make sure that settle time is overcome
441 Thread.sleep(50);
Hui Yu26969322019-08-21 14:56:35 -0700442 mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE,
443 ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION);
Philip P. Moltmannda554e42019-12-20 11:21:02 -0800444 assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
445 false, null)).isEqualTo(MODE_ALLOWED);
Amith Yamasani23d4cd72019-04-10 17:57:00 -0700446
Hui Yu26969322019-08-21 14:56:35 -0700447 mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE,
448 ActivityManager.PROCESS_CAPABILITY_NONE);
Amith Yamasani23d4cd72019-04-10 17:57:00 -0700449 // Second time to make sure that settle time is overcome
450 Thread.sleep(50);
Hui Yu26969322019-08-21 14:56:35 -0700451 mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE,
452 ActivityManager.PROCESS_CAPABILITY_NONE);
Philip P. Moltmannda554e42019-12-20 11:21:02 -0800453 assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
454 false, null)).isNotEqualTo(MODE_ALLOWED);
Amith Yamasani23d4cd72019-04-10 17:57:00 -0700455 }
456
Peter Visontay859206c2018-01-03 15:43:19 +0000457 private List<PackageOps> getLoggedOps() {
Philip P. Moltmann6b4f3d52019-05-08 15:14:09 -0700458 return mAppOpsService.getOpsForPackage(mMyUid, sMyPackageName, null /* all ops */);
Peter Visontay859206c2018-01-03 15:43:19 +0000459 }
460
461 private void assertContainsOp(List<PackageOps> loggedOps, int opCode, long minMillis,
462 long minRejectMillis, int mode) {
463
464 boolean opLogged = false;
465 for (PackageOps pkgOps : loggedOps) {
466 assertWithMessage("Unexpected UID").that(mMyUid).isEqualTo(pkgOps.getUid());
Philip P. Moltmann6b4f3d52019-05-08 15:14:09 -0700467 assertWithMessage("Unexpected package name").that(sMyPackageName).isEqualTo(
Peter Visontay859206c2018-01-03 15:43:19 +0000468 pkgOps.getPackageName());
469
470 for (OpEntry opEntry : pkgOps.getOps()) {
471 if (opCode != opEntry.getOp()) {
472 continue;
473 }
474 opLogged = true;
475
476 assertWithMessage("Unexpected mode").that(mode).isEqualTo(opEntry.getMode());
477 if (minMillis > 0) {
478 assertWithMessage("Unexpected timestamp")
Philip P. Moltmann49bd9e12019-11-26 15:18:16 -0800479 .that(opEntry.getLastAccessTime(OP_FLAGS_ALL)).isAtLeast(minMillis);
Peter Visontay859206c2018-01-03 15:43:19 +0000480 }
481 if (minRejectMillis > 0) {
Philip P. Moltmann49bd9e12019-11-26 15:18:16 -0800482 assertWithMessage("Unexpected rejection timestamp").that(
483 opEntry.getLastRejectTime(OP_FLAGS_ALL)).isAtLeast(minRejectMillis);
Peter Visontay859206c2018-01-03 15:43:19 +0000484 }
485 }
486 }
487 assertWithMessage("Op was not logged").that(opLogged).isTrue();
488 }
489}