• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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 android.content.pm.PackageManager.MATCH_DISABLED_COMPONENTS;
20 import static android.content.pm.PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS;
21 
22 import android.annotation.NonNull;
23 import android.content.pm.ComponentInfo;
24 import android.content.pm.PackageManager;
25 import android.os.Debug;
26 import android.util.DebugUtils;
27 import android.util.Slog;
28 
29 import com.android.server.pm.pkg.component.ParsedMainComponent;
30 import com.android.server.pm.pkg.parsing.ParsingPackageRead;
31 
32 /** @hide */
33 public class PackageUserStateUtils {
34 
35     private static final boolean DEBUG = false;
36     private static final String TAG = "PackageUserStateUtils";
37 
isMatch(@onNull PackageUserState state, ComponentInfo componentInfo, long flags)38     public static boolean isMatch(@NonNull PackageUserState state,
39             ComponentInfo componentInfo, long flags) {
40         return isMatch(state, componentInfo.applicationInfo.isSystemApp(),
41                 componentInfo.applicationInfo.enabled, componentInfo.enabled,
42                 componentInfo.directBootAware, componentInfo.name, flags);
43     }
44 
isMatch(@onNull PackageUserState state, boolean isSystem, boolean isPackageEnabled, ParsedMainComponent component, long flags)45     public static boolean isMatch(@NonNull PackageUserState state, boolean isSystem,
46             boolean isPackageEnabled, ParsedMainComponent component, long flags) {
47         return isMatch(state, isSystem, isPackageEnabled, component.isEnabled(),
48                 component.isDirectBootAware(), component.getName(), flags);
49     }
50 
51     /**
52      * Test if the given component is considered installed, enabled and a match for the given
53      * flags.
54      *
55      * <p>
56      * Expects at least one of {@link PackageManager#MATCH_DIRECT_BOOT_AWARE} and {@link
57      * PackageManager#MATCH_DIRECT_BOOT_UNAWARE} are specified in {@code flags}.
58      * </p>
59      */
isMatch(@onNull PackageUserState state, boolean isSystem, boolean isPackageEnabled, boolean isComponentEnabled, boolean isComponentDirectBootAware, String componentName, long flags)60     public static boolean isMatch(@NonNull PackageUserState state, boolean isSystem,
61             boolean isPackageEnabled, boolean isComponentEnabled,
62             boolean isComponentDirectBootAware, String componentName, long flags) {
63         final boolean matchUninstalled = (flags & PackageManager.MATCH_KNOWN_PACKAGES) != 0;
64         if (!isAvailable(state, flags) && !(isSystem && matchUninstalled)) {
65             return reportIfDebug(false, flags);
66         }
67 
68         if (!isEnabled(state, isPackageEnabled, isComponentEnabled, componentName, flags)) {
69             return reportIfDebug(false, flags);
70         }
71 
72         if ((flags & PackageManager.MATCH_SYSTEM_ONLY) != 0) {
73             if (!isSystem) {
74                 return reportIfDebug(false, flags);
75             }
76         }
77 
78         final boolean matchesUnaware = ((flags & PackageManager.MATCH_DIRECT_BOOT_UNAWARE) != 0)
79                 && !isComponentDirectBootAware;
80         final boolean matchesAware = ((flags & PackageManager.MATCH_DIRECT_BOOT_AWARE) != 0)
81                 && isComponentDirectBootAware;
82         return reportIfDebug(matchesUnaware || matchesAware, flags);
83     }
84 
isAvailable(@onNull PackageUserState state, long flags)85     public static boolean isAvailable(@NonNull PackageUserState state, long flags) {
86         // True if it is installed for this user and it is not hidden. If it is hidden,
87         // still return true if the caller requested MATCH_UNINSTALLED_PACKAGES
88         final boolean matchAnyUser = (flags & PackageManager.MATCH_ANY_USER) != 0;
89         final boolean matchUninstalled = (flags & PackageManager.MATCH_UNINSTALLED_PACKAGES) != 0;
90         return matchAnyUser
91                 || (state.isInstalled()
92                 && (!state.isHidden() || matchUninstalled));
93     }
94 
reportIfDebug(boolean result, long flags)95     public static boolean reportIfDebug(boolean result, long flags) {
96         if (DEBUG && !result) {
97             Slog.i(TAG, "No match!; flags: "
98                     + DebugUtils.flagsToString(PackageManager.class, "MATCH_", flags) + " "
99                     + Debug.getCaller());
100         }
101         return result;
102     }
103 
isEnabled(@onNull PackageUserState state, ComponentInfo componentInfo, long flags)104     public static boolean isEnabled(@NonNull PackageUserState state, ComponentInfo componentInfo,
105             long flags) {
106         return isEnabled(state, componentInfo.applicationInfo.enabled, componentInfo.enabled,
107                 componentInfo.name, flags);
108     }
109 
isEnabled(@onNull PackageUserState state, boolean isPackageEnabled, ParsedMainComponent parsedComponent, long flags)110     public static boolean isEnabled(@NonNull PackageUserState state, boolean isPackageEnabled,
111             ParsedMainComponent parsedComponent, long flags) {
112         return isEnabled(state, isPackageEnabled, parsedComponent.isEnabled(),
113                 parsedComponent.getName(), flags);
114     }
115 
116     /**
117      * Test if the given component is considered enabled.
118      */
isEnabled(@onNull PackageUserState state, boolean isPackageEnabled, boolean isComponentEnabled, String componentName, long flags)119     public static boolean isEnabled(@NonNull PackageUserState state,
120             boolean isPackageEnabled, boolean isComponentEnabled, String componentName,
121             long flags) {
122         if ((flags & MATCH_DISABLED_COMPONENTS) != 0) {
123             return true;
124         }
125 
126         // First check if the overall package is disabled; if the package is
127         // enabled then fall through to check specific component
128         switch (state.getEnabledState()) {
129             case PackageManager.COMPONENT_ENABLED_STATE_DISABLED:
130             case PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER:
131                 return false;
132             case PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED:
133                 if ((flags & MATCH_DISABLED_UNTIL_USED_COMPONENTS) == 0) {
134                     return false;
135                 }
136                 // fallthrough
137             case PackageManager.COMPONENT_ENABLED_STATE_DEFAULT:
138                 if (!isPackageEnabled) {
139                     return false;
140                 }
141                 // fallthrough
142             case PackageManager.COMPONENT_ENABLED_STATE_ENABLED:
143                 break;
144         }
145 
146         // Check if component has explicit state before falling through to
147         // the manifest default
148         if (state.isComponentEnabled(componentName)) {
149             return true;
150         } else if (state.isComponentDisabled(componentName)) {
151             return false;
152         }
153 
154         return isComponentEnabled;
155     }
156 
isPackageEnabled(@onNull PackageUserState state, @NonNull ParsingPackageRead pkg)157     public static boolean isPackageEnabled(@NonNull PackageUserState state,
158             @NonNull ParsingPackageRead pkg) {
159         switch (state.getEnabledState()) {
160             case PackageManager.COMPONENT_ENABLED_STATE_ENABLED:
161                 return true;
162             case PackageManager.COMPONENT_ENABLED_STATE_DISABLED:
163             case PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER:
164             case PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED:
165                 return false;
166             default:
167             case PackageManager.COMPONENT_ENABLED_STATE_DEFAULT:
168                 return pkg.isEnabled();
169         }
170     }
171 }
172