Automatic sources dropoff on 2020-06-10 18:32:38.095721

The change is generated with prebuilt drop tool.

Change-Id: I24cbf6ba6db262a1ae1445db1427a08fee35b3b4
diff --git a/com/android/server/pm/ProtectedPackages.java b/com/android/server/pm/ProtectedPackages.java
new file mode 100644
index 0000000..4da3cc3
--- /dev/null
+++ b/com/android/server/pm/ProtectedPackages.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm;
+
+import android.annotation.Nullable;
+import android.annotation.UserIdInt;
+import android.content.Context;
+import android.os.UserHandle;
+import android.util.SparseArray;
+
+import com.android.internal.R;
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.ArrayUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Manages package names that need special protection.
+ *
+ * TODO: This class should persist the information by itself, and also keeps track of device admin
+ * packages for all users.  Then PMS.isPackageDeviceAdmin() should use it instead of talking
+ * to DPMS.
+ */
+public class ProtectedPackages {
+    @UserIdInt
+    @GuardedBy("this")
+    private int mDeviceOwnerUserId;
+
+    @Nullable
+    @GuardedBy("this")
+    private String mDeviceOwnerPackage;
+
+    @Nullable
+    @GuardedBy("this")
+    private SparseArray<String> mProfileOwnerPackages;
+
+    @Nullable
+    @GuardedBy("this")
+    private final String mDeviceProvisioningPackage;
+
+    @Nullable
+    @GuardedBy("this")
+    private List<String> mDeviceOwnerProtectedPackages;
+
+    private final Context mContext;
+
+    public ProtectedPackages(Context context) {
+        mContext = context;
+        mDeviceProvisioningPackage = mContext.getResources().getString(
+                R.string.config_deviceProvisioningPackage);
+    }
+
+    /**
+     * Sets the device/profile owner information.
+     */
+    public synchronized void setDeviceAndProfileOwnerPackages(
+            int deviceOwnerUserId, String deviceOwnerPackage,
+            SparseArray<String> profileOwnerPackages) {
+        mDeviceOwnerUserId = deviceOwnerUserId;
+        mDeviceOwnerPackage =
+                (deviceOwnerUserId == UserHandle.USER_NULL) ? null : deviceOwnerPackage;
+        mProfileOwnerPackages = (profileOwnerPackages == null) ? null
+                : profileOwnerPackages.clone();
+    }
+
+    public synchronized void setDeviceOwnerProtectedPackages(List<String> packageNames) {
+        mDeviceOwnerProtectedPackages = new ArrayList<String>(packageNames);
+    }
+
+    private synchronized boolean hasDeviceOwnerOrProfileOwner(int userId, String packageName) {
+        if (packageName == null) {
+            return false;
+        }
+        if (mDeviceOwnerPackage != null) {
+            if ((mDeviceOwnerUserId == userId)
+                    && (packageName.equals(mDeviceOwnerPackage))) {
+                return true;
+            }
+        }
+        if (mProfileOwnerPackages != null) {
+            if (packageName.equals(mProfileOwnerPackages.get(userId))) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public synchronized String getDeviceOwnerOrProfileOwnerPackage(int userId) {
+        if (mDeviceOwnerUserId == userId) {
+            return mDeviceOwnerPackage;
+        }
+        if (mProfileOwnerPackages == null) {
+            return null;
+        }
+        return mProfileOwnerPackages.get(userId);
+    }
+
+    /**
+     * Returns {@code true} if a given package is protected. Otherwise, returns {@code false}.
+     *
+     * <p>A protected package means that, apart from the package owner, no system or privileged apps
+     * can modify its data or package state.
+     */
+    private synchronized boolean isProtectedPackage(String packageName) {
+        return packageName != null && (packageName.equals(mDeviceProvisioningPackage)
+                || ArrayUtils.contains(mDeviceOwnerProtectedPackages, packageName));
+    }
+
+    /**
+     * Returns {@code true} if a given package's state is protected. Otherwise, returns
+     * {@code false}.
+     *
+     * <p>This is not applicable if the caller is the package owner.
+     */
+    public boolean isPackageStateProtected(@UserIdInt int userId, String packageName) {
+        return hasDeviceOwnerOrProfileOwner(userId, packageName)
+                || isProtectedPackage(packageName);
+    }
+
+    /**
+     * Returns {@code true} if a given package's data is protected. Otherwise, returns
+     * {@code false}.
+     */
+    public boolean isPackageDataProtected(@UserIdInt int userId, String packageName) {
+        return hasDeviceOwnerOrProfileOwner(userId, packageName)
+                || isProtectedPackage(packageName);
+    }
+}