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.util.SparseArray;
24 
25 import com.android.internal.R;
26 import com.android.internal.annotations.GuardedBy;
27 
28 /**
29  * Manages package names that need special protection.
30  *
31  * TODO: This class should persist the information by itself, and also keeps track of device admin
32  * packages for all users.  Then PMS.isPackageDeviceAdmin() should use it instead of talking
33  * to DPMS.
34  */
35 public class ProtectedPackages {
36     @UserIdInt
37     @GuardedBy("this")
38     private int mDeviceOwnerUserId;
39 
40     @Nullable
41     @GuardedBy("this")
42     private String mDeviceOwnerPackage;
43 
44     @Nullable
45     @GuardedBy("this")
46     private SparseArray<String> mProfileOwnerPackages;
47 
48     @Nullable
49     @GuardedBy("this")
50     private final String mDeviceProvisioningPackage;
51 
52     private final Context mContext;
53 
ProtectedPackages(Context context)54     public ProtectedPackages(Context context) {
55         mContext = context;
56         mDeviceProvisioningPackage = mContext.getResources().getString(
57                 R.string.config_deviceProvisioningPackage);
58     }
59 
60     /**
61      * Sets the device/profile owner information.
62      */
setDeviceAndProfileOwnerPackages( int deviceOwnerUserId, String deviceOwnerPackage, SparseArray<String> profileOwnerPackages)63     public synchronized void setDeviceAndProfileOwnerPackages(
64             int deviceOwnerUserId, String deviceOwnerPackage,
65             SparseArray<String> profileOwnerPackages) {
66         mDeviceOwnerUserId = deviceOwnerUserId;
67         mDeviceOwnerPackage =
68                 (deviceOwnerUserId == UserHandle.USER_NULL) ? null : deviceOwnerPackage;
69         mProfileOwnerPackages = (profileOwnerPackages == null) ? null
70                 : profileOwnerPackages.clone();
71     }
72 
hasDeviceOwnerOrProfileOwner(int userId, String packageName)73     private synchronized boolean hasDeviceOwnerOrProfileOwner(int userId, String packageName) {
74         if (packageName == null) {
75             return false;
76         }
77         if (mDeviceOwnerPackage != null) {
78             if ((mDeviceOwnerUserId == userId)
79                     && (packageName.equals(mDeviceOwnerPackage))) {
80                 return true;
81             }
82         }
83         if (mProfileOwnerPackages != null) {
84             if (packageName.equals(mProfileOwnerPackages.get(userId))) {
85                 return true;
86             }
87         }
88         return false;
89     }
90 
getDeviceOwnerOrProfileOwnerPackage(int userId)91     public synchronized String getDeviceOwnerOrProfileOwnerPackage(int userId) {
92         if (mDeviceOwnerUserId == userId) {
93             return mDeviceOwnerPackage;
94         }
95         if (mProfileOwnerPackages == null) {
96             return null;
97         }
98         return mProfileOwnerPackages.get(userId);
99     }
100 
101     /**
102      * Returns {@code true} if a given package is protected. Otherwise, returns {@code false}.
103      *
104      * <p>A protected package means that, apart from the package owner, no system or privileged apps
105      * can modify its data or package state.
106      */
isProtectedPackage(String packageName)107     private synchronized boolean isProtectedPackage(String packageName) {
108         return packageName != null && packageName.equals(mDeviceProvisioningPackage);
109     }
110 
111     /**
112      * Returns {@code true} if a given package's state is protected. Otherwise, returns
113      * {@code false}.
114      *
115      * <p>This is not applicable if the caller is the package owner.
116      */
isPackageStateProtected(@serIdInt int userId, String packageName)117     public boolean isPackageStateProtected(@UserIdInt int userId, String packageName) {
118         return hasDeviceOwnerOrProfileOwner(userId, packageName)
119                 || isProtectedPackage(packageName);
120     }
121 
122     /**
123      * Returns {@code true} if a given package's data is protected. Otherwise, returns
124      * {@code false}.
125      */
isPackageDataProtected(@serIdInt int userId, String packageName)126     public boolean isPackageDataProtected(@UserIdInt int userId, String packageName) {
127         return hasDeviceOwnerOrProfileOwner(userId, packageName)
128                 || isProtectedPackage(packageName);
129     }
130 }
131