1 /*
2  * Copyright (C) 2020 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.pkg;
18 
19 import static java.util.Collections.emptyList;
20 
21 import android.annotation.NonNull;
22 import android.annotation.Nullable;
23 import android.content.pm.PackageManager;
24 import android.content.pm.SharedLibraryInfo;
25 import android.text.TextUtils;
26 
27 import com.android.internal.util.CollectionUtils;
28 import com.android.internal.util.DataClass;
29 import com.android.server.pm.PackageSetting;
30 
31 import java.util.ArrayList;
32 import java.util.List;
33 
34 /**
35  * For use by {@link PackageSetting} to maintain functionality that used to exist in PackageParser.
36  *
37  * It is assumed that anything inside the package was not cached or written to disk, so none of
38  * these fields are either. They must be set on every boot from other state on the device.
39  *
40  * These fields are also not copied into any cloned PackageSetting, to preserve the old behavior
41  * where they would be lost implicitly by re-generating the package object.
42  * @hide
43  */
44 @DataClass(genSetters = true, genConstructor = false, genBuilder = false)
45 @DataClass.Suppress({"setLastPackageUsageTimeInMills", "setPackageSetting", "setUsesLibraryInfos"})
46 public class PackageStateUnserialized {
47 
48     private boolean hiddenUntilInstalled;
49 
50     @NonNull
51     private List<SharedLibraryWrapper> usesLibraryInfos = emptyList();
52 
53     @NonNull
54     private List<String> usesLibraryFiles = emptyList();
55 
56     private boolean updatedSystemApp;
57     private boolean apkInUpdatedApex;
58 
59     @NonNull
60     private volatile long[] lastPackageUsageTimeInMills;
61 
62     @Nullable
63     private String overrideSeInfo;
64 
65     @NonNull
66     private String seInfo;
67 
68     // TODO: Remove in favor of finer grained change notification
69     @NonNull
70     private final PackageSetting mPackageSetting;
71 
72     @Nullable
73     private String mApexModuleName;
74 
PackageStateUnserialized(@onNull PackageSetting packageSetting)75     public PackageStateUnserialized(@NonNull PackageSetting packageSetting) {
76         mPackageSetting = packageSetting;
77     }
78 
79     @NonNull
addUsesLibraryInfo(@onNull SharedLibraryWrapper value)80     public PackageStateUnserialized addUsesLibraryInfo(@NonNull SharedLibraryWrapper value) {
81         usesLibraryInfos = CollectionUtils.add(usesLibraryInfos, value);
82         return this;
83     }
84 
85     @NonNull
addUsesLibraryFile(@onNull String value)86     public PackageStateUnserialized addUsesLibraryFile(@NonNull String value) {
87         usesLibraryFiles = CollectionUtils.add(usesLibraryFiles, value);
88         return this;
89     }
90 
lazyInitLastPackageUsageTimeInMills()91     private long[] lazyInitLastPackageUsageTimeInMills() {
92         return new long[PackageManager.NOTIFY_PACKAGE_USE_REASONS_COUNT];
93     }
94 
setLastPackageUsageTimeInMills(int reason, long time)95     public PackageStateUnserialized setLastPackageUsageTimeInMills(int reason, long time) {
96         if (reason < 0) {
97             return this;
98         }
99         if (reason >= PackageManager.NOTIFY_PACKAGE_USE_REASONS_COUNT) {
100             return this;
101         }
102         getLastPackageUsageTimeInMills()[reason] = time;
103         // TODO(b/236180425): This method does not notify snapshot changes because it's called too
104         //  frequently, causing too many re-takes. This should be moved to a separate data structure
105         //  or merged with the general UsageStats to avoid tracking heavily mutated data in the
106         //  package data snapshot.
107         return this;
108     }
109 
getLatestPackageUseTimeInMills()110     public long getLatestPackageUseTimeInMills() {
111         long latestUse = 0L;
112         for (long use : getLastPackageUsageTimeInMills()) {
113             latestUse = Math.max(latestUse, use);
114         }
115         return latestUse;
116     }
117 
getLatestForegroundPackageUseTimeInMills()118     public long getLatestForegroundPackageUseTimeInMills() {
119         int[] foregroundReasons = {
120                 PackageManager.NOTIFY_PACKAGE_USE_ACTIVITY,
121                 PackageManager.NOTIFY_PACKAGE_USE_FOREGROUND_SERVICE
122         };
123 
124         long latestUse = 0L;
125         for (int reason : foregroundReasons) {
126             latestUse = Math.max(latestUse, getLastPackageUsageTimeInMills()[reason]);
127         }
128         return latestUse;
129     }
130 
updateFrom(PackageStateUnserialized other)131     public void updateFrom(PackageStateUnserialized other) {
132         this.hiddenUntilInstalled = other.hiddenUntilInstalled;
133 
134         if (!other.usesLibraryInfos.isEmpty()) {
135             this.usesLibraryInfos = new ArrayList<>(other.usesLibraryInfos);
136         }
137 
138         if (!other.usesLibraryFiles.isEmpty()) {
139             this.usesLibraryFiles = new ArrayList<>(other.usesLibraryFiles);
140         }
141 
142         this.updatedSystemApp = other.updatedSystemApp;
143         this.apkInUpdatedApex = other.apkInUpdatedApex;
144         this.lastPackageUsageTimeInMills = other.lastPackageUsageTimeInMills;
145         this.overrideSeInfo = other.overrideSeInfo;
146         this.seInfo = other.seInfo;
147         this.mApexModuleName = other.mApexModuleName;
148         mPackageSetting.onChanged();
149     }
150 
getNonNativeUsesLibraryInfos()151     public @NonNull List<SharedLibraryInfo> getNonNativeUsesLibraryInfos() {
152         var list = new ArrayList<SharedLibraryInfo>();
153         usesLibraryInfos = getUsesLibraryInfos();
154         for (int index = 0; index < usesLibraryInfos.size(); index++) {
155             var library = usesLibraryInfos.get(index);
156             if (!library.isNative()) {
157                 list.add(library.getInfo());
158             }
159 
160         }
161         return list;
162     }
163 
setHiddenUntilInstalled(boolean value)164     public PackageStateUnserialized setHiddenUntilInstalled(boolean value) {
165         hiddenUntilInstalled = value;
166         mPackageSetting.onChanged();
167         return this;
168     }
169 
setUsesLibraryInfos(@onNull List<SharedLibraryInfo> value)170     public PackageStateUnserialized setUsesLibraryInfos(@NonNull List<SharedLibraryInfo> value) {
171         var list = new ArrayList<SharedLibraryWrapper>();
172         for (int index = 0; index < value.size(); index++) {
173             list.add(new SharedLibraryWrapper(value.get(index)));
174         }
175         usesLibraryInfos = list;
176         mPackageSetting.onChanged();
177         return this;
178     }
179 
setUsesLibraryFiles(@onNull List<String> value)180     public PackageStateUnserialized setUsesLibraryFiles(@NonNull List<String> value) {
181         usesLibraryFiles = value;
182         mPackageSetting.onChanged();
183         return this;
184     }
185 
setUpdatedSystemApp(boolean value)186     public PackageStateUnserialized setUpdatedSystemApp(boolean value) {
187         updatedSystemApp = value;
188         mPackageSetting.onChanged();
189         return this;
190     }
191 
setApkInUpdatedApex(boolean value)192     public PackageStateUnserialized setApkInUpdatedApex(boolean value) {
193         apkInUpdatedApex = value;
194         mPackageSetting.onChanged();
195         return this;
196     }
197 
setLastPackageUsageTimeInMills(@onNull long... value)198     public PackageStateUnserialized setLastPackageUsageTimeInMills(@NonNull long... value) {
199         lastPackageUsageTimeInMills = value;
200         mPackageSetting.onChanged();
201         return this;
202     }
203 
setOverrideSeInfo(@ullable String value)204     public PackageStateUnserialized setOverrideSeInfo(@Nullable String value) {
205         overrideSeInfo = value;
206         mPackageSetting.onChanged();
207         return this;
208     }
209 
210     @NonNull
setSeInfo(@onNull String value)211     public PackageStateUnserialized setSeInfo(@NonNull String value) {
212         seInfo = TextUtils.safeIntern(value);
213         mPackageSetting.onChanged();
214         return this;
215     }
216 
217     @NonNull
setApexModuleName(@onNull String value)218     public PackageStateUnserialized setApexModuleName(@NonNull String value) {
219         mApexModuleName = value;
220         mPackageSetting.onChanged();
221         return this;
222     }
223 
224 
225 
226     // Code below generated by codegen v1.0.23.
227     //
228     // DO NOT MODIFY!
229     // CHECKSTYLE:OFF Generated code
230     //
231     // To regenerate run:
232     // $ codegen $ANDROID_BUILD_TOP/frameworks/base/services/core/java/com/android/server/pm/pkg/PackageStateUnserialized.java
233     //
234     // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
235     //   Settings > Editor > Code Style > Formatter Control
236     //@formatter:off
237 
238 
239     @DataClass.Generated.Member
isHiddenUntilInstalled()240     public boolean isHiddenUntilInstalled() {
241         return hiddenUntilInstalled;
242     }
243 
244     @DataClass.Generated.Member
getUsesLibraryInfos()245     public @NonNull List<SharedLibraryWrapper> getUsesLibraryInfos() {
246         return usesLibraryInfos;
247     }
248 
249     @DataClass.Generated.Member
getUsesLibraryFiles()250     public @NonNull List<String> getUsesLibraryFiles() {
251         return usesLibraryFiles;
252     }
253 
254     @DataClass.Generated.Member
isUpdatedSystemApp()255     public boolean isUpdatedSystemApp() {
256         return updatedSystemApp;
257     }
258 
259     @DataClass.Generated.Member
isApkInUpdatedApex()260     public boolean isApkInUpdatedApex() {
261         return apkInUpdatedApex;
262     }
263 
264     @DataClass.Generated.Member
getLastPackageUsageTimeInMills()265     public @NonNull long[] getLastPackageUsageTimeInMills() {
266         long[] _lastPackageUsageTimeInMills = lastPackageUsageTimeInMills;
267         if (_lastPackageUsageTimeInMills == null) {
268             synchronized(this) {
269                 _lastPackageUsageTimeInMills = lastPackageUsageTimeInMills;
270                 if (_lastPackageUsageTimeInMills == null) {
271                     _lastPackageUsageTimeInMills = lastPackageUsageTimeInMills = lazyInitLastPackageUsageTimeInMills();
272                 }
273             }
274         }
275         return _lastPackageUsageTimeInMills;
276     }
277 
278     @DataClass.Generated.Member
getOverrideSeInfo()279     public @Nullable String getOverrideSeInfo() {
280         return overrideSeInfo;
281     }
282 
283     @DataClass.Generated.Member
getSeInfo()284     public @NonNull String getSeInfo() {
285         return seInfo;
286     }
287 
288     @DataClass.Generated.Member
getPackageSetting()289     public @NonNull PackageSetting getPackageSetting() {
290         return mPackageSetting;
291     }
292 
293     @DataClass.Generated.Member
getApexModuleName()294     public @Nullable String getApexModuleName() {
295         return mApexModuleName;
296     }
297 
298     @DataClass.Generated(
299             time = 1671483772254L,
300             codegenVersion = "1.0.23",
301             sourceFile = "frameworks/base/services/core/java/com/android/server/pm/pkg/PackageStateUnserialized.java",
302             inputSignatures = "private  boolean hiddenUntilInstalled\nprivate @android.annotation.NonNull java.util.List<com.android.server.pm.pkg.SharedLibraryWrapper> usesLibraryInfos\nprivate @android.annotation.NonNull java.util.List<java.lang.String> usesLibraryFiles\nprivate  boolean updatedSystemApp\nprivate  boolean apkInUpdatedApex\nprivate volatile @android.annotation.NonNull long[] lastPackageUsageTimeInMills\nprivate @android.annotation.Nullable java.lang.String overrideSeInfo\nprivate @android.annotation.NonNull java.lang.String seInfo\nprivate final @android.annotation.NonNull com.android.server.pm.PackageSetting mPackageSetting\nprivate @android.annotation.Nullable java.lang.String mApexModuleName\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageStateUnserialized addUsesLibraryInfo(com.android.server.pm.pkg.SharedLibraryWrapper)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageStateUnserialized addUsesLibraryFile(java.lang.String)\nprivate  long[] lazyInitLastPackageUsageTimeInMills()\npublic  com.android.server.pm.pkg.PackageStateUnserialized setLastPackageUsageTimeInMills(int,long)\npublic  long getLatestPackageUseTimeInMills()\npublic  long getLatestForegroundPackageUseTimeInMills()\npublic  void updateFrom(com.android.server.pm.pkg.PackageStateUnserialized)\npublic @android.annotation.NonNull java.util.List<android.content.pm.SharedLibraryInfo> getNonNativeUsesLibraryInfos()\npublic  com.android.server.pm.pkg.PackageStateUnserialized setHiddenUntilInstalled(boolean)\npublic  com.android.server.pm.pkg.PackageStateUnserialized setUsesLibraryInfos(java.util.List<android.content.pm.SharedLibraryInfo>)\npublic  com.android.server.pm.pkg.PackageStateUnserialized setUsesLibraryFiles(java.util.List<java.lang.String>)\npublic  com.android.server.pm.pkg.PackageStateUnserialized setUpdatedSystemApp(boolean)\npublic  com.android.server.pm.pkg.PackageStateUnserialized setApkInUpdatedApex(boolean)\npublic  com.android.server.pm.pkg.PackageStateUnserialized setLastPackageUsageTimeInMills(long)\npublic  com.android.server.pm.pkg.PackageStateUnserialized setOverrideSeInfo(java.lang.String)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageStateUnserialized setSeInfo(java.lang.String)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageStateUnserialized setApexModuleName(java.lang.String)\nclass PackageStateUnserialized extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genSetters=true, genConstructor=false, genBuilder=false)")
303     @Deprecated
__metadata()304     private void __metadata() {}
305 
306 
307     //@formatter:on
308     // End of generated code
309 
310 }
311