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 com.android.server.appop;
18 
19 import static org.mockito.Mockito.eq;
20 import static org.mockito.Mockito.inOrder;
21 import static org.mockito.Mockito.mock;
22 import static org.mockito.Mockito.timeout;
23 import static org.mockito.Mockito.verify;
24 import static org.mockito.Mockito.verifyNoMoreInteractions;
25 
26 import android.app.AppOpsManager;
27 import android.app.AppOpsManager.OnOpStartedListener;
28 import android.content.Context;
29 import android.os.Process;
30 
31 import androidx.test.InstrumentationRegistry;
32 import androidx.test.filters.SmallTest;
33 import androidx.test.runner.AndroidJUnit4;
34 
35 import org.junit.Test;
36 import org.junit.runner.RunWith;
37 import org.mockito.InOrder;
38 
39 /** Tests watching started ops. */
40 @SmallTest
41 @RunWith(AndroidJUnit4.class)
42 public class AppOpsStartedWatcherTest {
43 
44     private static final long NOTIFICATION_TIMEOUT_MILLIS = 5000;
45 
46     @Test
testWatchStartedOps()47     public void testWatchStartedOps() {
48         // Create a mock listener
49         final OnOpStartedListener listener = mock(OnOpStartedListener.class);
50 
51         // Start watching started ops
52         final AppOpsManager appOpsManager = getContext().getSystemService(AppOpsManager.class);
53         appOpsManager.startWatchingStarted(new int[]{AppOpsManager.OP_FINE_LOCATION,
54                 AppOpsManager.OP_CAMERA}, listener);
55 
56         // Start some ops
57         appOpsManager.startOp(AppOpsManager.OP_FINE_LOCATION);
58         appOpsManager.startOp(AppOpsManager.OP_CAMERA);
59         appOpsManager.startOp(AppOpsManager.OP_RECORD_AUDIO);
60 
61         // Verify that we got called for the ops being started
62         final InOrder inOrder = inOrder(listener);
63         inOrder.verify(listener, timeout(NOTIFICATION_TIMEOUT_MILLIS)
64                 .times(1)).onOpStarted(eq(AppOpsManager.OP_FINE_LOCATION),
65                 eq(Process.myUid()), eq(getContext().getPackageName()),
66                 eq(getContext().getAttributionTag()), eq(AppOpsManager.OP_FLAG_SELF),
67                 eq(AppOpsManager.MODE_ALLOWED), eq(OnOpStartedListener.START_TYPE_STARTED),
68                 eq(AppOpsManager.ATTRIBUTION_FLAGS_NONE),
69                 eq(AppOpsManager.ATTRIBUTION_CHAIN_ID_NONE));
70         inOrder.verify(listener, timeout(NOTIFICATION_TIMEOUT_MILLIS)
71                 .times(1)).onOpStarted(eq(AppOpsManager.OP_CAMERA),
72                 eq(Process.myUid()), eq(getContext().getPackageName()),
73                 eq(getContext().getAttributionTag()), eq(AppOpsManager.OP_FLAG_SELF),
74                 eq(AppOpsManager.MODE_ALLOWED), eq(OnOpStartedListener.START_TYPE_STARTED),
75                 eq(AppOpsManager.ATTRIBUTION_FLAGS_NONE),
76                 eq(AppOpsManager.ATTRIBUTION_CHAIN_ID_NONE));
77 
78         // Stop watching
79         appOpsManager.stopWatchingStarted(listener);
80 
81         // This should be the only two callbacks we got
82         verifyNoMoreInteractions(listener);
83 
84         // Start the op again and verify it isn't being watched
85         appOpsManager.startOp(AppOpsManager.OP_FINE_LOCATION);
86         appOpsManager.finishOp(AppOpsManager.OP_FINE_LOCATION);
87         verifyNoMoreInteractions(listener);
88 
89         // Start watching an op again (only CAMERA this time)
90         appOpsManager.startWatchingStarted(new int[]{AppOpsManager.OP_CAMERA}, listener);
91 
92         // Note the ops again
93         appOpsManager.startOp(AppOpsManager.OP_CAMERA);
94         appOpsManager.startOp(AppOpsManager.OP_FINE_LOCATION);
95 
96         // Verify it's watched again
97         verify(listener, timeout(NOTIFICATION_TIMEOUT_MILLIS)
98                 .times(2)).onOpStarted(eq(AppOpsManager.OP_CAMERA),
99                 eq(Process.myUid()), eq(getContext().getPackageName()),
100                 eq(getContext().getAttributionTag()), eq(AppOpsManager.OP_FLAG_SELF),
101                 eq(AppOpsManager.MODE_ALLOWED), eq(OnOpStartedListener.START_TYPE_STARTED),
102                 eq(AppOpsManager.ATTRIBUTION_FLAGS_NONE),
103                 eq(AppOpsManager.ATTRIBUTION_CHAIN_ID_NONE));
104         verifyNoMoreInteractions(listener);
105 
106         // Finish up
107         appOpsManager.finishOp(AppOpsManager.OP_CAMERA);
108         appOpsManager.finishOp(AppOpsManager.OP_FINE_LOCATION);
109         appOpsManager.stopWatchingStarted(listener);
110     }
111 
getContext()112     private static Context getContext() {
113         return InstrumentationRegistry.getContext();
114     }
115 }
116