1 /*
2  * Copyright (C) 2021 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 android.annotation.NonNull;
20 import android.annotation.Nullable;
21 import android.content.pm.ComponentInfo;
22 import android.content.pm.PackageManager;
23 import android.util.SparseArray;
24 
25 import com.android.internal.pm.pkg.component.ParsedMainComponent;
26 
27 /** @hide */
28 public class PackageStateUtils {
29 
isMatch(PackageState packageState, long flags)30     public static boolean isMatch(PackageState packageState, long flags) {
31         if ((flags & PackageManager.MATCH_SYSTEM_ONLY) != 0) {
32             return packageState.isSystem();
33         }
34         return true;
35     }
36 
queryInstalledUsers(PackageStateInternal pkgState, int[] users, boolean installed)37     public static int[] queryInstalledUsers(PackageStateInternal pkgState, int[] users,
38             boolean installed) {
39         int num = 0;
40         for (int user : users) {
41             if (pkgState.getUserStateOrDefault(user).isInstalled() == installed) {
42                 num++;
43             }
44         }
45         int[] res = new int[num];
46         num = 0;
47         for (int user : users) {
48             if (pkgState.getUserStateOrDefault(user).isInstalled() == installed) {
49                 res[num] = user;
50                 num++;
51             }
52         }
53         return res;
54     }
55 
isEnabledAndMatches(@ullable PackageStateInternal packageState, ComponentInfo componentInfo, long flags, int userId)56     public static boolean isEnabledAndMatches(@Nullable PackageStateInternal packageState,
57             ComponentInfo componentInfo, long flags, int userId) {
58         if (packageState == null) return false;
59 
60         final PackageUserStateInternal userState = packageState.getUserStateOrDefault(userId);
61         return PackageUserStateUtils.isMatch(userState, componentInfo, flags);
62     }
63 
isEnabledAndMatches(@ullable PackageStateInternal packageState, @NonNull ParsedMainComponent component, long flags, int userId)64     public static boolean isEnabledAndMatches(@Nullable PackageStateInternal packageState,
65             @NonNull ParsedMainComponent component, long flags, int userId) {
66         if (packageState == null) {
67             return false;
68         }
69 
70         final AndroidPackage pkg = packageState.getPkg();
71         if (pkg == null) {
72             return false;
73         }
74         final PackageUserStateInternal userState = packageState.getUserStateOrDefault(userId);
75         return PackageUserStateUtils.isMatch(userState, packageState.isSystem(),
76                 pkg.isEnabled(), component, flags);
77     }
78 
79     /**
80      * Return the earliest non-zero first-install timestamp of an installed app among all the users,
81      * unless none of the users have a non-zero first-install timestamp. In that case, return 0.
82      */
getEarliestFirstInstallTime( @ullable SparseArray<? extends PackageUserStateInternal> userStatesInternal)83     public static long getEarliestFirstInstallTime(
84             @Nullable SparseArray<? extends PackageUserStateInternal> userStatesInternal) {
85         if (userStatesInternal == null || userStatesInternal.size() == 0) {
86             return 0;
87         }
88         long earliestFirstInstallTime = Long.MAX_VALUE;
89         for (int i = 0; i < userStatesInternal.size(); i++) {
90             final long firstInstallTime = userStatesInternal.valueAt(i).getFirstInstallTimeMillis();
91             if (firstInstallTime != 0 && firstInstallTime < earliestFirstInstallTime) {
92                 earliestFirstInstallTime = firstInstallTime;
93             }
94         }
95         return earliestFirstInstallTime == Long.MAX_VALUE ? 0 : earliestFirstInstallTime;
96     }
97 }
98