1 /*
2  * Copyright 2019 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.car.settings.testutils;
18 
19 import android.app.AppOpsManager;
20 import android.app.AppOpsManager.OpEntry;
21 import android.app.AppOpsManager.PackageOps;
22 
23 import com.google.common.collect.HashBasedTable;
24 import com.google.common.collect.ImmutableList;
25 import com.google.common.collect.Table;
26 
27 import org.robolectric.annotation.Implementation;
28 import org.robolectric.annotation.Implements;
29 
30 import java.util.Collections;
31 import java.util.List;
32 import java.util.Map;
33 import java.util.Objects;
34 
35 @Implements(value = AppOpsManager.class)
36 public class ShadowAppOpsManager {
37 
38     private Table<Integer, InternalKey, Integer> mOpToKeyToMode = HashBasedTable.create();
39 
40     @Implementation
setMode(int code, int uid, String packageName, int mode)41     protected void setMode(int code, int uid, String packageName, int mode) {
42         InternalKey key = new InternalKey(uid, packageName);
43         mOpToKeyToMode.put(code, key, mode);
44     }
45 
46     /** Convenience method to get the mode directly instead of wrapped in an op list. */
getMode(int code, int uid, String packageName)47     public int getMode(int code, int uid, String packageName) {
48         Integer mode = mOpToKeyToMode.get(code, new InternalKey(uid, packageName));
49         return mode == null ? AppOpsManager.opToDefaultMode(code) : mode;
50     }
51 
52     @Implementation
getPackagesForOps(int[] ops)53     protected List<PackageOps> getPackagesForOps(int[] ops) {
54         if (ops == null) {
55             return Collections.emptyList();
56         }
57         ImmutableList.Builder<PackageOps> result = new ImmutableList.Builder<>();
58         for (int i = 0; i < ops.length; i++) {
59             int op = ops[i];
60             Map<InternalKey, Integer> keyToModeMap = mOpToKeyToMode.rowMap().get(op);
61             if (keyToModeMap == null) {
62                 continue;
63             }
64             for (InternalKey key : keyToModeMap.keySet()) {
65                 Integer mode = keyToModeMap.get(key);
66                 if (mode == null) {
67                     mode = AppOpsManager.opToDefaultMode(op);
68                 }
69                 OpEntry opEntry = new OpEntry(op, mode);
70                 PackageOps packageOp = new PackageOps(key.mPackageName, key.mUid,
71                         Collections.singletonList(opEntry));
72                 result.add(packageOp);
73             }
74         }
75         return result.build();
76     }
77 
78     private static class InternalKey {
79         private int mUid;
80         private String mPackageName;
81 
InternalKey(int uid, String packageName)82         InternalKey(int uid, String packageName) {
83             mUid = uid;
84             mPackageName = packageName;
85         }
86 
87         @Override
equals(Object obj)88         public boolean equals(Object obj) {
89             if (obj instanceof InternalKey) {
90                 InternalKey that = (InternalKey) obj;
91                 return mUid == that.mUid && mPackageName.equals(that.mPackageName);
92             }
93             return false;
94         }
95 
96         @Override
hashCode()97         public int hashCode() {
98             return Objects.hash(mUid, mPackageName);
99         }
100     }
101 }
102