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 android.annotation.NonNull; 20 import android.annotation.Nullable; 21 import android.content.IntentFilter; 22 import android.content.pm.parsing.ParsingPackage; 23 import android.content.pm.parsing.ParsingUtils; 24 import android.content.pm.parsing.result.ParseInput; 25 import android.content.pm.parsing.result.ParseResult; 26 import android.content.res.Configuration; 27 import android.content.res.Resources; 28 import android.content.res.TypedArray; 29 import android.content.res.XmlResourceParser; 30 import android.os.Build; 31 import android.util.Slog; 32 33 import com.android.internal.annotations.VisibleForTesting; 34 35 import org.xmlpull.v1.XmlPullParserException; 36 37 import java.io.IOException; 38 39 /** @hide */ 40 class ParsedMainComponentUtils { 41 42 private static final String TAG = ParsingUtils.TAG; 43 44 @NonNull 45 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) parseMainComponent( Component component, String tag, String[] separateProcesses, ParsingPackage pkg, TypedArray array, int flags, boolean useRoundIcon, ParseInput input, int bannerAttr, int descriptionAttr, @Nullable Integer directBootAwareAttr, @Nullable Integer enabledAttr, int iconAttr, int labelAttr, int logoAttr, int nameAttr, @Nullable Integer processAttr, int roundIconAttr, @Nullable Integer splitNameAttr, @Nullable Integer attributionTagsAttr)46 static <Component extends ParsedMainComponent> ParseResult<Component> parseMainComponent( 47 Component component, String tag, String[] separateProcesses, ParsingPackage pkg, 48 TypedArray array, int flags, boolean useRoundIcon, ParseInput input, 49 int bannerAttr, int descriptionAttr, @Nullable Integer directBootAwareAttr, 50 @Nullable Integer enabledAttr, int iconAttr, int labelAttr, int logoAttr, int nameAttr, 51 @Nullable Integer processAttr, int roundIconAttr, @Nullable Integer splitNameAttr, 52 @Nullable Integer attributionTagsAttr) { 53 ParseResult<Component> result = ParsedComponentUtils.parseComponent(component, tag, pkg, 54 array, useRoundIcon, input, bannerAttr, descriptionAttr, iconAttr, labelAttr, 55 logoAttr, nameAttr, roundIconAttr); 56 if (result.isError()) { 57 return result; 58 } 59 60 if (directBootAwareAttr != null) { 61 component.directBootAware = array.getBoolean(directBootAwareAttr, false); 62 if (component.isDirectBootAware()) { 63 pkg.setPartiallyDirectBootAware(true); 64 } 65 } 66 67 if (enabledAttr != null) { 68 component.enabled = array.getBoolean(enabledAttr, true); 69 } 70 71 if (processAttr != null) { 72 CharSequence processName; 73 if (pkg.getTargetSdkVersion() >= Build.VERSION_CODES.FROYO) { 74 processName = array.getNonConfigurationString(processAttr, 75 Configuration.NATIVE_CONFIG_VERSION); 76 } else { 77 // Some older apps have been seen to use a resource reference 78 // here that on older builds was ignored (with a warning). We 79 // need to continue to do this for them so they don't break. 80 processName = array.getNonResourceString(processAttr); 81 } 82 83 // Backwards-compat, ignore error 84 ParseResult<String> processNameResult = ComponentParseUtils.buildProcessName( 85 pkg.getPackageName(), pkg.getProcessName(), processName, flags, 86 separateProcesses, input); 87 if (processNameResult.isError()) { 88 return input.error(processNameResult); 89 } 90 91 component.setProcessName(processNameResult.getResult()); 92 } 93 94 if (splitNameAttr != null) { 95 component.splitName = array.getNonConfigurationString(splitNameAttr, 0); 96 } 97 98 if (attributionTagsAttr != null) { 99 final String attributionTags = array.getNonConfigurationString(attributionTagsAttr, 0); 100 if (attributionTags != null) { 101 component.attributionTags = attributionTags.split("\\|"); 102 } 103 } 104 105 return input.success(component); 106 } 107 parseIntentFilter( ParsedMainComponent mainComponent, ParsingPackage pkg, Resources resources, XmlResourceParser parser, boolean visibleToEphemeral, boolean allowGlobs, boolean allowAutoVerify, boolean allowImplicitEphemeralVisibility, boolean failOnNoActions, ParseInput input)108 static ParseResult<ParsedIntentInfo> parseIntentFilter( 109 ParsedMainComponent mainComponent, 110 ParsingPackage pkg, Resources resources, XmlResourceParser parser, 111 boolean visibleToEphemeral, boolean allowGlobs, boolean allowAutoVerify, 112 boolean allowImplicitEphemeralVisibility, boolean failOnNoActions, 113 ParseInput input) throws IOException, XmlPullParserException { 114 ParseResult<ParsedIntentInfo> intentResult = ParsedIntentInfoUtils.parseIntentInfo( 115 mainComponent.getName(), pkg, resources, parser, allowGlobs, 116 allowAutoVerify, input); 117 if (intentResult.isError()) { 118 return input.error(intentResult); 119 } 120 121 ParsedIntentInfo intent = intentResult.getResult(); 122 int actionCount = intent.countActions(); 123 if (actionCount == 0 && failOnNoActions) { 124 Slog.w(TAG, "No actions in " + parser.getName() + " at " + pkg.getBaseApkPath() + " " 125 + parser.getPositionDescription()); 126 // Backward-compat, do not actually fail 127 return input.success(null); 128 } 129 130 int intentVisibility; 131 if (visibleToEphemeral) { 132 intentVisibility = IntentFilter.VISIBILITY_EXPLICIT; 133 } else if (allowImplicitEphemeralVisibility 134 && ComponentParseUtils.isImplicitlyExposedIntent(intent)){ 135 intentVisibility = IntentFilter.VISIBILITY_IMPLICIT; 136 } else { 137 intentVisibility = IntentFilter.VISIBILITY_NONE; 138 } 139 intent.setVisibilityToInstantApp(intentVisibility); 140 141 return input.success(intentResult.getResult()); 142 } 143 144 } 145