1 /*
2  * Copyright (C) 2011 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.content.pm.ApplicationInfo;
20 import android.content.pm.PackageManager;
21 import android.content.pm.PackageParser;
22 import android.content.pm.UserInfo;
23 import android.service.pm.PackageProto;
24 import android.util.proto.ProtoOutputStream;
25 
26 import com.android.server.pm.permission.PermissionsState;
27 
28 import java.io.File;
29 import java.util.List;
30 
31 /**
32  * Settings data for a particular package we know about.
33  */
34 public final class PackageSetting extends PackageSettingBase {
35     int appId;
36     PackageParser.Package pkg;
37     /**
38      * WARNING. The object reference is important. We perform integer equality and NOT
39      * object equality to check whether shared user settings are the same.
40      */
41     SharedUserSetting sharedUser;
42     /**
43      * Temporary holding space for the shared user ID. While parsing package settings, the
44      * shared users tag may come after the packages. In this case, we must delay linking the
45      * shared user setting with the package setting. The shared user ID lets us link the
46      * two objects.
47      */
48     private int sharedUserId;
49 
PackageSetting(String name, String realName, File codePath, File resourcePath, String legacyNativeLibraryPathString, String primaryCpuAbiString, String secondaryCpuAbiString, String cpuAbiOverrideString, long pVersionCode, int pkgFlags, int privateFlags, String parentPackageName, List<String> childPackageNames, int sharedUserId, String[] usesStaticLibraries, long[] usesStaticLibrariesVersions)50     PackageSetting(String name, String realName, File codePath, File resourcePath,
51             String legacyNativeLibraryPathString, String primaryCpuAbiString,
52             String secondaryCpuAbiString, String cpuAbiOverrideString,
53             long pVersionCode, int pkgFlags, int privateFlags, String parentPackageName,
54             List<String> childPackageNames, int sharedUserId, String[] usesStaticLibraries,
55             long[] usesStaticLibrariesVersions) {
56         super(name, realName, codePath, resourcePath, legacyNativeLibraryPathString,
57                 primaryCpuAbiString, secondaryCpuAbiString, cpuAbiOverrideString,
58                 pVersionCode, pkgFlags, privateFlags, parentPackageName, childPackageNames,
59                 usesStaticLibraries, usesStaticLibrariesVersions);
60         this.sharedUserId = sharedUserId;
61     }
62 
63     /**
64      * New instance of PackageSetting replicating the original settings.
65      * Note that it keeps the same PackageParser.Package instance.
66      */
PackageSetting(PackageSetting orig)67     PackageSetting(PackageSetting orig) {
68         super(orig, orig.realName);
69         doCopy(orig);
70     }
71 
72     /**
73      * New instance of PackageSetting replicating the original settings, but, allows specifying
74      * a real package name.
75      * Note that it keeps the same PackageParser.Package instance.
76      */
PackageSetting(PackageSetting orig, String realPkgName)77     PackageSetting(PackageSetting orig, String realPkgName) {
78         super(orig, realPkgName);
79         doCopy(orig);
80     }
81 
getSharedUserId()82     public int getSharedUserId() {
83         if (sharedUser != null) {
84             return sharedUser.userId;
85         }
86         return sharedUserId;
87     }
88 
getSharedUser()89     public SharedUserSetting getSharedUser() {
90         return sharedUser;
91     }
92 
93     @Override
toString()94     public String toString() {
95         return "PackageSetting{"
96             + Integer.toHexString(System.identityHashCode(this))
97             + " " + name + "/" + appId + "}";
98     }
99 
copyFrom(PackageSetting orig)100     public void copyFrom(PackageSetting orig) {
101         super.copyFrom(orig);
102         doCopy(orig);
103     }
104 
doCopy(PackageSetting orig)105     private void doCopy(PackageSetting orig) {
106         appId = orig.appId;
107         pkg = orig.pkg;
108         sharedUser = orig.sharedUser;
109         sharedUserId = orig.sharedUserId;
110     }
111 
112     @Override
getPermissionsState()113     public PermissionsState getPermissionsState() {
114         return (sharedUser != null)
115                 ? sharedUser.getPermissionsState()
116                 : super.getPermissionsState();
117     }
118 
getPackage()119     public PackageParser.Package getPackage() {
120         return pkg;
121     }
122 
getAppId()123     public int getAppId() {
124         return appId;
125     }
126 
setInstallPermissionsFixed(boolean fixed)127     public void setInstallPermissionsFixed(boolean fixed) {
128         installPermissionsFixed = fixed;
129     }
130 
areInstallPermissionsFixed()131     public boolean areInstallPermissionsFixed() {
132         return installPermissionsFixed;
133     }
134 
isPrivileged()135     public boolean isPrivileged() {
136         return (pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0;
137     }
138 
isOem()139     public boolean isOem() {
140         return (pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_OEM) != 0;
141     }
142 
isVendor()143     public boolean isVendor() {
144         return (pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_VENDOR) != 0;
145     }
146 
isProduct()147     public boolean isProduct() {
148         return (pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_PRODUCT) != 0;
149     }
150 
isSystemExt()151     public boolean isSystemExt() {
152         return (pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_SYSTEM_EXT) != 0;
153     }
154 
isOdm()155     public boolean isOdm() {
156         return (pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_ODM) != 0;
157     }
158 
isSystem()159     public boolean isSystem() {
160         return (pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0;
161     }
162 
isUpdatedSystem()163     public boolean isUpdatedSystem() {
164         return (pkgFlags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0;
165     }
166 
167     @Override
isSharedUser()168     public boolean isSharedUser() {
169         return sharedUser != null;
170     }
171 
isMatch(int flags)172     public boolean isMatch(int flags) {
173         if ((flags & PackageManager.MATCH_SYSTEM_ONLY) != 0) {
174             return isSystem();
175         }
176         return true;
177     }
178 
hasChildPackages()179     public boolean hasChildPackages() {
180         return childPackageNames != null && !childPackageNames.isEmpty();
181     }
182 
writeToProto(ProtoOutputStream proto, long fieldId, List<UserInfo> users)183     public void writeToProto(ProtoOutputStream proto, long fieldId, List<UserInfo> users) {
184         final long packageToken = proto.start(fieldId);
185         proto.write(PackageProto.NAME, (realName != null ? realName : name));
186         proto.write(PackageProto.UID, appId);
187         proto.write(PackageProto.VERSION_CODE, versionCode);
188         proto.write(PackageProto.INSTALL_TIME_MS, firstInstallTime);
189         proto.write(PackageProto.UPDATE_TIME_MS, lastUpdateTime);
190         proto.write(PackageProto.INSTALLER_NAME, installerPackageName);
191 
192         if (pkg != null) {
193             proto.write(PackageProto.VERSION_STRING, pkg.mVersionName);
194 
195             long splitToken = proto.start(PackageProto.SPLITS);
196             proto.write(PackageProto.SplitProto.NAME, "base");
197             proto.write(PackageProto.SplitProto.REVISION_CODE, pkg.baseRevisionCode);
198             proto.end(splitToken);
199 
200             if (pkg.splitNames != null) {
201                 for (int i = 0; i < pkg.splitNames.length; i++) {
202                     splitToken = proto.start(PackageProto.SPLITS);
203                     proto.write(PackageProto.SplitProto.NAME, pkg.splitNames[i]);
204                     proto.write(PackageProto.SplitProto.REVISION_CODE, pkg.splitRevisionCodes[i]);
205                     proto.end(splitToken);
206                 }
207             }
208         }
209         writeUsersInfoToProto(proto, PackageProto.USERS);
210         proto.end(packageToken);
211     }
212 
213     /** Updates all fields in the current setting from another. */
updateFrom(PackageSetting other)214     public void updateFrom(PackageSetting other) {
215         super.updateFrom(other);
216         appId = other.appId;
217         pkg = other.pkg;
218         sharedUserId = other.sharedUserId;
219         sharedUser = other.sharedUser;
220     }
221 }
222