• 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.component;
18 
19 import android.annotation.AttrRes;
20 import android.annotation.NonNull;
21 import android.annotation.Nullable;
22 import android.content.Intent;
23 import android.content.IntentFilter;
24 import android.content.pm.parsing.FrameworkParsingPackageUtils;
25 import android.content.pm.parsing.result.ParseInput;
26 import android.content.pm.parsing.result.ParseResult;
27 import android.content.res.Resources;
28 import android.content.res.TypedArray;
29 import android.content.res.XmlResourceParser;
30 import android.text.TextUtils;
31 
32 import com.android.server.pm.pkg.PackageUserState;
33 import com.android.server.pm.pkg.PackageUserStateUtils;
34 import com.android.server.pm.pkg.parsing.ParsingPackage;
35 import com.android.server.pm.pkg.parsing.ParsingPackageUtils;
36 import com.android.server.pm.pkg.parsing.ParsingUtils;
37 
38 import org.xmlpull.v1.XmlPullParser;
39 import org.xmlpull.v1.XmlPullParserException;
40 
41 import java.io.IOException;
42 
43 /**
44  * @hide
45  */
46 public class ComponentParseUtils {
47 
isImplicitlyExposedIntent(ParsedIntentInfo intentInfo)48     public static boolean isImplicitlyExposedIntent(ParsedIntentInfo intentInfo) {
49         IntentFilter intentFilter = intentInfo.getIntentFilter();
50         return intentFilter.hasCategory(Intent.CATEGORY_BROWSABLE)
51                 || intentFilter.hasAction(Intent.ACTION_SEND)
52                 || intentFilter.hasAction(Intent.ACTION_SENDTO)
53                 || intentFilter.hasAction(Intent.ACTION_SEND_MULTIPLE);
54     }
55 
parseAllMetaData( ParsingPackage pkg, Resources res, XmlResourceParser parser, String tag, Component component, ParseInput input)56     static <Component extends ParsedComponentImpl> ParseResult<Component> parseAllMetaData(
57             ParsingPackage pkg, Resources res, XmlResourceParser parser, String tag,
58             Component component, ParseInput input) throws XmlPullParserException, IOException {
59         final int depth = parser.getDepth();
60         int type;
61         while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
62                 && (type != XmlPullParser.END_TAG || parser.getDepth() > depth)) {
63             if (type != XmlPullParser.START_TAG) {
64                 continue;
65             }
66 
67             final ParseResult result;
68             if ("meta-data".equals(parser.getName())) {
69                 result = ParsedComponentUtils.addMetaData(component, pkg, res, parser, input);
70             } else {
71                 result = ParsingUtils.unknownTag(tag, pkg, parser, input);
72             }
73 
74             if (result.isError()) {
75                 return input.error(result);
76             }
77         }
78 
79         return input.success(component);
80     }
81 
82     @NonNull
buildProcessName(@onNull String pkg, String defProc, CharSequence procSeq, int flags, String[] separateProcesses, ParseInput input)83     public static ParseResult<String> buildProcessName(@NonNull String pkg, String defProc,
84             CharSequence procSeq, int flags, String[] separateProcesses, ParseInput input) {
85         if ((flags & ParsingPackageUtils.PARSE_IGNORE_PROCESSES) != 0 && !"system".contentEquals(
86                 procSeq)) {
87             return input.success(defProc != null ? defProc : pkg);
88         }
89         if (separateProcesses != null) {
90             for (int i = separateProcesses.length - 1; i >= 0; i--) {
91                 String sp = separateProcesses[i];
92                 if (sp.equals(pkg) || sp.equals(defProc) || sp.contentEquals(procSeq)) {
93                     return input.success(pkg);
94                 }
95             }
96         }
97         if (procSeq == null || procSeq.length() <= 0) {
98             return input.success(defProc);
99         }
100 
101         ParseResult<String> nameResult = ComponentParseUtils.buildCompoundName(pkg, procSeq,
102                 "process", input);
103         return input.success(TextUtils.safeIntern(nameResult.getResult()));
104     }
105 
106     @NonNull
buildTaskAffinityName(String pkg, String defProc, CharSequence procSeq, ParseInput input)107     public static ParseResult<String> buildTaskAffinityName(String pkg, String defProc,
108             CharSequence procSeq, ParseInput input) {
109         if (procSeq == null) {
110             return input.success(defProc);
111         }
112         if (procSeq.length() <= 0) {
113             return input.success(null);
114         }
115         return buildCompoundName(pkg, procSeq, "taskAffinity", input);
116     }
117 
buildCompoundName(String pkg, CharSequence procSeq, String type, ParseInput input)118     public static ParseResult<String> buildCompoundName(String pkg, CharSequence procSeq,
119             String type, ParseInput input) {
120         String proc = procSeq.toString();
121         char c = proc.charAt(0);
122         if (pkg != null && c == ':') {
123             if (proc.length() < 2) {
124                 return input.error("Bad " + type + " name " + proc + " in package " + pkg
125                         + ": must be at least two characters");
126             }
127             String subName = proc.substring(1);
128             final ParseResult<?> nameResult = FrameworkParsingPackageUtils.validateName(input,
129                     subName, false, false);
130             if (nameResult.isError()) {
131                 return input.error("Invalid " + type + " name " + proc + " in package " + pkg
132                         + ": " + nameResult.getErrorMessage());
133             }
134             return input.success(pkg + proc);
135         }
136         if (!"system".equals(proc)) {
137             final ParseResult<?> nameResult = FrameworkParsingPackageUtils.validateName(input, proc,
138                     true, false);
139             if (nameResult.isError()) {
140                 return input.error("Invalid " + type + " name " + proc + " in package " + pkg
141                         + ": " + nameResult.getErrorMessage());
142             }
143         }
144         return input.success(proc);
145     }
146 
flag(int flag, @AttrRes int attribute, TypedArray typedArray)147     public static int flag(int flag, @AttrRes int attribute, TypedArray typedArray) {
148         return typedArray.getBoolean(attribute, false) ? flag : 0;
149     }
150 
flag(int flag, @AttrRes int attribute, boolean defaultValue, TypedArray typedArray)151     public static int flag(int flag, @AttrRes int attribute, boolean defaultValue,
152             TypedArray typedArray) {
153         return typedArray.getBoolean(attribute, defaultValue) ? flag : 0;
154     }
155 
156     /**
157      * This is not state aware. Avoid and access through PackageInfoUtils in the system server.
158      */
159     @Nullable
getNonLocalizedLabel( ParsedComponent component)160     public static CharSequence getNonLocalizedLabel(
161             ParsedComponent component) {
162         return component.getNonLocalizedLabel();
163     }
164 
165     /**
166      * This is not state aware. Avoid and access through PackageInfoUtils in the system server.
167      * <p>
168      * This is a method of the utility class to discourage use.
169      */
getIcon(ParsedComponent component)170     public static int getIcon(ParsedComponent component) {
171         return component.getIcon();
172     }
173 
isMatch(PackageUserState state, boolean isSystem, boolean isPackageEnabled, ParsedMainComponent component, long flags)174     public static boolean isMatch(PackageUserState state, boolean isSystem,
175             boolean isPackageEnabled, ParsedMainComponent component, long flags) {
176         return PackageUserStateUtils.isMatch(state, isSystem, isPackageEnabled,
177                 component.isEnabled(), component.isDirectBootAware(), component.getName(), flags);
178     }
179 
isEnabled(PackageUserState state, boolean isPackageEnabled, ParsedMainComponent parsedComponent, long flags)180     public static boolean isEnabled(PackageUserState state, boolean isPackageEnabled,
181             ParsedMainComponent parsedComponent, long flags) {
182         return PackageUserStateUtils.isEnabled(state, isPackageEnabled, parsedComponent.isEnabled(),
183                 parsedComponent.getName(), flags);
184     }
185 }
186