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.location.injector;
18 
19 import android.location.util.identity.CallerIdentity;
20 import android.util.SparseArray;
21 
22 import com.android.internal.util.Preconditions;
23 
24 import java.util.HashMap;
25 
26 /**
27  * Version of AppOpsHelper for testing. All app ops are allowed until notified otherwise.
28  */
29 public class FakeAppOpsHelper extends AppOpsHelper {
30 
31     private static class AppOp {
AppOp()32         AppOp() {}
33         boolean mAllowed = true;
34         int mStarted = 0;
35         int mNoteCount = 0;
36     }
37 
38     private final HashMap<String, SparseArray<AppOp>> mAppOps;
39 
FakeAppOpsHelper()40     public FakeAppOpsHelper() {
41         mAppOps = new HashMap<>();
42     }
43 
setAppOpAllowed(int appOp, String packageName, boolean allowed)44     public void setAppOpAllowed(int appOp, String packageName, boolean allowed) {
45         AppOp myAppOp = getOp(packageName, appOp);
46         myAppOp.mAllowed = allowed;
47         notifyAppOpChanged(packageName);
48     }
49 
isAppOpStarted(int appOp, String packageName)50     public boolean isAppOpStarted(int appOp, String packageName) {
51         AppOp myAppOp = getOp(packageName, appOp);
52         return myAppOp.mStarted > 0;
53     }
54 
getAppOpNoteCount(int appOp, String packageName)55     public int getAppOpNoteCount(int appOp, String packageName) {
56         AppOp myAppOp = getOp(packageName, appOp);
57         return myAppOp.mNoteCount;
58     }
59 
60     @Override
startOpNoThrow(int appOp, CallerIdentity callerIdentity)61     public boolean startOpNoThrow(int appOp, CallerIdentity callerIdentity) {
62         AppOp myAppOp = getOp(callerIdentity.getPackageName(), appOp);
63         if (!myAppOp.mAllowed) {
64             return false;
65         }
66         myAppOp.mStarted++;
67         return true;
68     }
69 
70     @Override
finishOp(int appOp, CallerIdentity callerIdentity)71     public void finishOp(int appOp, CallerIdentity callerIdentity) {
72         AppOp myAppOp = getOp(callerIdentity.getPackageName(), appOp);
73         Preconditions.checkState(myAppOp.mStarted > 0);
74         myAppOp.mStarted--;
75     }
76 
77     @Override
checkOpNoThrow(int appOp, CallerIdentity callerIdentity)78     public boolean checkOpNoThrow(int appOp, CallerIdentity callerIdentity) {
79         AppOp myAppOp = getOp(callerIdentity.getPackageName(), appOp);
80         return myAppOp.mAllowed;
81     }
82 
83     @Override
noteOp(int appOp, CallerIdentity callerIdentity)84     public boolean noteOp(int appOp, CallerIdentity callerIdentity) {
85         if (!noteOpNoThrow(appOp, callerIdentity)) {
86             throw new SecurityException(
87                     "noteOp not allowed for op " + appOp + " and caller " + callerIdentity);
88         }
89 
90         return true;
91     }
92 
93     @Override
noteOpNoThrow(int appOp, CallerIdentity callerIdentity)94     public boolean noteOpNoThrow(int appOp, CallerIdentity callerIdentity) {
95         AppOp myAppOp = getOp(callerIdentity.getPackageName(), appOp);
96         if (!myAppOp.mAllowed) {
97             return false;
98         }
99         myAppOp.mNoteCount++;
100         return true;
101     }
102 
getOp(String packageName, int appOp)103     private AppOp getOp(String packageName, int appOp) {
104         SparseArray<AppOp> ops = mAppOps.get(packageName);
105         if (ops == null) {
106             ops = new SparseArray<>();
107             mAppOps.put(packageName, ops);
108         }
109 
110         AppOp myAppOp;
111         if (ops.contains(appOp)) {
112             myAppOp = ops.get(appOp);
113         } else {
114             myAppOp = new AppOp();
115             ops.put(appOp, myAppOp);
116         }
117 
118         return myAppOp;
119     }
120 }
121