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