1 /* 2 * Copyright (C) 2016 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.pm; 18 19 import android.annotation.Nullable; 20 import android.annotation.UserIdInt; 21 import android.content.Context; 22 import android.os.UserHandle; 23 import android.text.TextUtils; 24 import android.util.ArraySet; 25 import android.util.SparseArray; 26 27 import com.android.internal.R; 28 import com.android.internal.annotations.GuardedBy; 29 30 import java.util.List; 31 import java.util.Objects; 32 import java.util.Set; 33 34 /** 35 * Manages package names that need special protection. 36 * 37 * TODO: This class should persist the information by itself, and also keeps track of device admin 38 * packages for all users. Then PMS.isPackageDeviceAdmin() should use it instead of talking 39 * to DPMS. 40 */ 41 public class ProtectedPackages { 42 @UserIdInt 43 @GuardedBy("this") 44 private int mDeviceOwnerUserId; 45 46 @Nullable 47 @GuardedBy("this") 48 private String mDeviceOwnerPackage; 49 50 @Nullable 51 @GuardedBy("this") 52 private SparseArray<String> mProfileOwnerPackages; 53 54 @Nullable 55 @GuardedBy("this") 56 private final String mDeviceProvisioningPackage; 57 58 @Nullable 59 @GuardedBy("this") 60 private final SparseArray<Set<String>> mOwnerProtectedPackages = new SparseArray<>(); 61 ProtectedPackages(Context context)62 public ProtectedPackages(Context context) { 63 mDeviceProvisioningPackage = context.getResources().getString( 64 R.string.config_deviceProvisioningPackage); 65 } 66 67 /** 68 * Sets the device/profile owner information. 69 */ setDeviceAndProfileOwnerPackages( int deviceOwnerUserId, String deviceOwnerPackage, SparseArray<String> profileOwnerPackages)70 public synchronized void setDeviceAndProfileOwnerPackages( 71 int deviceOwnerUserId, String deviceOwnerPackage, 72 SparseArray<String> profileOwnerPackages) { 73 mDeviceOwnerUserId = deviceOwnerUserId; 74 mDeviceOwnerPackage = 75 (deviceOwnerUserId == UserHandle.USER_NULL) ? null : deviceOwnerPackage; 76 mProfileOwnerPackages = (profileOwnerPackages == null) ? null 77 : profileOwnerPackages.clone(); 78 } 79 80 /** Sets packages protected by a device or profile owner. */ setOwnerProtectedPackages( @serIdInt int userId, @Nullable List<String> packageNames)81 public synchronized void setOwnerProtectedPackages( 82 @UserIdInt int userId, @Nullable List<String> packageNames) { 83 if (packageNames == null) { 84 mOwnerProtectedPackages.remove(userId); 85 } else { 86 mOwnerProtectedPackages.put(userId, new ArraySet<>(packageNames)); 87 } 88 } 89 hasDeviceOwnerOrProfileOwner(int userId, String packageName)90 private synchronized boolean hasDeviceOwnerOrProfileOwner(int userId, String packageName) { 91 if (packageName == null) { 92 return false; 93 } 94 if (mDeviceOwnerPackage != null) { 95 if ((mDeviceOwnerUserId == userId) 96 && (packageName.equals(mDeviceOwnerPackage))) { 97 return true; 98 } 99 } 100 if (mProfileOwnerPackages != null) { 101 if (packageName.equals(mProfileOwnerPackages.get(userId))) { 102 return true; 103 } 104 } 105 return false; 106 } 107 getDeviceOwnerOrProfileOwnerPackage(int userId)108 public synchronized String getDeviceOwnerOrProfileOwnerPackage(int userId) { 109 if (mDeviceOwnerUserId == userId) { 110 return mDeviceOwnerPackage; 111 } 112 if (mProfileOwnerPackages == null) { 113 return null; 114 } 115 return mProfileOwnerPackages.get(userId); 116 } 117 118 /** 119 * Returns {@code true} if a given package is protected. Otherwise, returns {@code false}. 120 * 121 * <p>A protected package means that, apart from the package owner, no system or privileged apps 122 * can modify its data or package state. 123 */ isProtectedPackage(@serIdInt int userId, String packageName)124 private synchronized boolean isProtectedPackage(@UserIdInt int userId, String packageName) { 125 return packageName != null && (packageName.equals(mDeviceProvisioningPackage) 126 || isOwnerProtectedPackage(userId, packageName)); 127 } 128 129 /** 130 * Returns {@code true} if the given package is a protected package set by any device or 131 * profile owner. 132 */ isOwnerProtectedPackage( @serIdInt int userId, String packageName)133 private synchronized boolean isOwnerProtectedPackage( 134 @UserIdInt int userId, String packageName) { 135 return hasProtectedPackages(userId) 136 ? isPackageProtectedForUser(userId, packageName) 137 : isPackageProtectedForUser(UserHandle.USER_ALL, packageName); 138 } 139 isPackageProtectedForUser( @serIdInt int userId, String packageName)140 private synchronized boolean isPackageProtectedForUser( 141 @UserIdInt int userId, String packageName) { 142 int userIdx = mOwnerProtectedPackages.indexOfKey(userId); 143 return userIdx >= 0 && mOwnerProtectedPackages.valueAt(userIdx).contains(packageName); 144 } 145 hasProtectedPackages(@serIdInt int userId)146 private synchronized boolean hasProtectedPackages(@UserIdInt int userId) { 147 return mOwnerProtectedPackages.indexOfKey(userId) >= 0; 148 } 149 150 /** 151 * Returns {@code true} if a given package's state is protected. Otherwise, returns 152 * {@code false}. 153 * 154 * <p>This is not applicable if the caller is the package owner. 155 */ isPackageStateProtected(@serIdInt int userId, String packageName)156 public boolean isPackageStateProtected(@UserIdInt int userId, String packageName) { 157 return hasDeviceOwnerOrProfileOwner(userId, packageName) 158 || isProtectedPackage(userId, packageName); 159 } 160 161 /** 162 * Returns {@code true} if a given package's data is protected. Otherwise, returns 163 * {@code false}. 164 */ isPackageDataProtected(@serIdInt int userId, String packageName)165 public boolean isPackageDataProtected(@UserIdInt int userId, String packageName) { 166 return hasDeviceOwnerOrProfileOwner(userId, packageName) 167 || isProtectedPackage(userId, packageName); 168 } 169 170 /** 171 * Returns {@code true} if a given package is the device provisioning package. Otherwise, 172 * returns {@code false}. 173 */ isDeviceProvisioningPackage(String packageName)174 public synchronized boolean isDeviceProvisioningPackage(String packageName) { 175 return !TextUtils.isEmpty(mDeviceProvisioningPackage) && Objects.equals( 176 mDeviceProvisioningPackage, packageName); 177 } 178 } 179