1 /*
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  */
16 
17 package com.android.server.appops;
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.OnOpNotedListener;
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 /**
40  * Tests watching noted ops.
41  */
42 @SmallTest
43 @RunWith(AndroidJUnit4.class)
44 public class AppOpsNotedWatcherTest {
45 
46     private static final long NOTIFICATION_TIMEOUT_MILLIS = 5000;
47 
48     @Test
testWatchNotedOps()49     public void testWatchNotedOps() {
50         // Create a mock listener
51         final OnOpNotedListener listener = mock(OnOpNotedListener.class);
52 
53         // Start watching noted ops
54         final AppOpsManager appOpsManager = getContext().getSystemService(AppOpsManager.class);
55         appOpsManager.startWatchingNoted(new int[]{AppOpsManager.OP_FINE_LOCATION,
56                 AppOpsManager.OP_CAMERA}, listener);
57 
58         // Note some ops
59         appOpsManager.noteOp(AppOpsManager.OP_FINE_LOCATION, Process.myUid(),
60                 getContext().getPackageName());
61         appOpsManager.noteOp(AppOpsManager.OP_CAMERA, Process.myUid(),
62                 getContext().getPackageName());
63 
64         // Verify that we got called for the ops being noted
65         final InOrder inOrder = inOrder(listener);
66         inOrder.verify(listener, timeout(NOTIFICATION_TIMEOUT_MILLIS)
67                 .times(1)).onOpNoted(eq(AppOpsManager.OPSTR_FINE_LOCATION),
68                 eq(Process.myUid()), eq(getContext().getPackageName()),
69                 eq(getContext().getAttributionTag()), eq(AppOpsManager.OP_FLAG_SELF),
70                 eq(AppOpsManager.MODE_ALLOWED));
71         inOrder.verify(listener, timeout(NOTIFICATION_TIMEOUT_MILLIS)
72                 .times(1)).onOpNoted(eq(AppOpsManager.OPSTR_CAMERA),
73                 eq(Process.myUid()), eq(getContext().getPackageName()),
74                 eq(getContext().getAttributionTag()), eq(AppOpsManager.OP_FLAG_SELF),
75                 eq(AppOpsManager.MODE_ALLOWED));
76 
77         // Stop watching
78         appOpsManager.stopWatchingNoted(listener);
79 
80         // This should be the only two callbacks we got
81         verifyNoMoreInteractions(listener);
82 
83         // Note the op again and verify it isn't being watched
84         appOpsManager.noteOp(AppOpsManager.OP_FINE_LOCATION);
85         verifyNoMoreInteractions(listener);
86 
87         // Start watching again
88         appOpsManager.startWatchingNoted(new int[]{AppOpsManager.OP_FINE_LOCATION,
89                 AppOpsManager.OP_CAMERA}, listener);
90 
91         // Note the op again
92         appOpsManager.noteOp(AppOpsManager.OP_FINE_LOCATION, Process.myUid(),
93                 getContext().getPackageName());
94 
95         // Verify it's watched again
96         verify(listener, timeout(NOTIFICATION_TIMEOUT_MILLIS)
97                 .times(2)).onOpNoted(eq(AppOpsManager.OPSTR_FINE_LOCATION),
98                 eq(Process.myUid()), eq(getContext().getPackageName()),
99                 eq(getContext().getAttributionTag()), eq(AppOpsManager.OP_FLAG_SELF),
100                 eq(AppOpsManager.MODE_ALLOWED));
101 
102         // Finish up
103         appOpsManager.stopWatchingNoted(listener);
104     }
105 
getContext()106     private static Context getContext() {
107         return InstrumentationRegistry.getContext();
108     }
109 }