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