1 /* 2 * Copyright (C) 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.internal.infra; 18 19 import android.annotation.NonNull; 20 import android.annotation.Nullable; 21 import android.annotation.UserIdInt; 22 import android.content.ComponentName; 23 import android.util.ArraySet; 24 import android.util.SparseArray; 25 26 import com.android.internal.annotations.GuardedBy; 27 28 import java.io.PrintWriter; 29 import java.util.List; 30 31 /** 32 * Helper class used to manage a {@link WhitelistHelper} per user instance when the main service 33 * cannot hold a lock when external entities (typically {@code ActivityManagerService}) needs to 34 * get allowlist info. 35 * 36 * <p>This class is thread safe. 37 */ 38 // TODO: add unit tests 39 public class GlobalWhitelistState { 40 41 // Uses full-name to avoid collision with service-provided mLock 42 protected final Object mGlobalWhitelistStateLock = new Object(); 43 44 // TODO: should not be exposed directly 45 @Nullable 46 @GuardedBy("mGlobalWhitelistStateLock") 47 protected SparseArray<WhitelistHelper> mWhitelisterHelpers; 48 49 /** 50 * Sets the allowlist for the given user. 51 */ setWhitelist(@serIdInt int userId, @Nullable List<String> packageNames, @Nullable List<ComponentName> components)52 public void setWhitelist(@UserIdInt int userId, @Nullable List<String> packageNames, 53 @Nullable List<ComponentName> components) { 54 synchronized (mGlobalWhitelistStateLock) { 55 if (mWhitelisterHelpers == null) { 56 mWhitelisterHelpers = new SparseArray<>(1); 57 } 58 WhitelistHelper helper = mWhitelisterHelpers.get(userId); 59 if (helper == null) { 60 helper = new WhitelistHelper(); 61 mWhitelisterHelpers.put(userId, helper); 62 } 63 helper.setWhitelist(packageNames, components); 64 } 65 } 66 67 /** 68 * Checks if the given package is allowlisted for the given user. 69 */ isWhitelisted(@serIdInt int userId, @NonNull String packageName)70 public boolean isWhitelisted(@UserIdInt int userId, @NonNull String packageName) { 71 synchronized (mGlobalWhitelistStateLock) { 72 if (mWhitelisterHelpers == null) return false; 73 final WhitelistHelper helper = mWhitelisterHelpers.get(userId); 74 return helper == null ? false : helper.isWhitelisted(packageName); 75 } 76 } 77 78 /** 79 * Checks if the given component is allowlisted for the given user. 80 */ isWhitelisted(@serIdInt int userId, @NonNull ComponentName componentName)81 public boolean isWhitelisted(@UserIdInt int userId, @NonNull ComponentName componentName) { 82 synchronized (mGlobalWhitelistStateLock) { 83 if (mWhitelisterHelpers == null) return false; 84 final WhitelistHelper helper = mWhitelisterHelpers.get(userId); 85 return helper == null ? false : helper.isWhitelisted(componentName); 86 } 87 } 88 89 /** 90 * Gets the allowlisted components for the given package and user. 91 */ getWhitelistedComponents(@serIdInt int userId, @NonNull String packageName)92 public ArraySet<ComponentName> getWhitelistedComponents(@UserIdInt int userId, 93 @NonNull String packageName) { 94 synchronized (mGlobalWhitelistStateLock) { 95 if (mWhitelisterHelpers == null) return null; 96 final WhitelistHelper helper = mWhitelisterHelpers.get(userId); 97 return helper == null ? null : helper.getWhitelistedComponents(packageName); 98 } 99 } 100 101 /** 102 * Gets packages that are either entirely allowlisted or have components that are allowlisted 103 * for the given user. 104 */ getWhitelistedPackages(@serIdInt int userId)105 public ArraySet<String> getWhitelistedPackages(@UserIdInt int userId) { 106 synchronized (mGlobalWhitelistStateLock) { 107 if (mWhitelisterHelpers == null) return null; 108 final WhitelistHelper helper = mWhitelisterHelpers.get(userId); 109 return helper == null ? null : helper.getWhitelistedPackages(); 110 } 111 } 112 113 /** 114 * Resets the allowlist for the given user. 115 */ resetWhitelist(@onNull int userId)116 public void resetWhitelist(@NonNull int userId) { 117 synchronized (mGlobalWhitelistStateLock) { 118 if (mWhitelisterHelpers == null) return; 119 mWhitelisterHelpers.remove(userId); 120 if (mWhitelisterHelpers.size() == 0) { 121 mWhitelisterHelpers = null; 122 } 123 } 124 } 125 126 /** 127 * Dumps it! 128 */ dump(@onNull String prefix, @NonNull PrintWriter pw)129 public void dump(@NonNull String prefix, @NonNull PrintWriter pw) { 130 pw.print(prefix); pw.print("State: "); 131 synchronized (mGlobalWhitelistStateLock) { 132 if (mWhitelisterHelpers == null) { 133 pw.println("empty"); 134 return; 135 } 136 pw.print(mWhitelisterHelpers.size()); pw.println(" services"); 137 final String prefix2 = prefix + " "; 138 for (int i = 0; i < mWhitelisterHelpers.size(); i++) { 139 final int userId = mWhitelisterHelpers.keyAt(i); 140 final WhitelistHelper helper = mWhitelisterHelpers.valueAt(i); 141 helper.dump(prefix2, "Whitelist for userId " + userId, pw); 142 } 143 } 144 } 145 } 146