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.ParsingPackageImpl.sForInternedString; 20 21 import static java.util.Collections.emptyMap; 22 23 import android.annotation.CallSuper; 24 import android.annotation.NonNull; 25 import android.annotation.Nullable; 26 import android.content.ComponentName; 27 import android.content.pm.PackageManager.Property; 28 import android.os.Bundle; 29 import android.os.Parcel; 30 import android.os.Parcelable; 31 import android.text.TextUtils; 32 33 import com.android.internal.util.CollectionUtils; 34 import com.android.internal.util.DataClass; 35 import com.android.internal.util.Parcelling; 36 import com.android.internal.util.Parcelling.BuiltIn.ForInternedString; 37 38 import java.util.ArrayList; 39 import java.util.Collections; 40 import java.util.List; 41 import java.util.Map; 42 43 /** @hide */ 44 public abstract class ParsedComponent implements Parcelable { 45 46 private static ParsedIntentInfo.ListParceler sForIntentInfos = Parcelling.Cache.getOrCreate( 47 ParsedIntentInfo.ListParceler.class); 48 49 @NonNull 50 @DataClass.ParcelWith(ForInternedString.class) 51 private String name; 52 int icon; 53 int labelRes; 54 @Nullable 55 CharSequence nonLocalizedLabel; 56 int logo; 57 int banner; 58 int descriptionRes; 59 60 // TODO(b/135203078): Replace flags with individual booleans, scoped by subclass 61 int flags; 62 63 @NonNull 64 @DataClass.ParcelWith(ForInternedString.class) 65 private String packageName; 66 67 @Nullable 68 @DataClass.PluralOf("intent") 69 @DataClass.ParcelWith(ParsedIntentInfo.ListParceler.class) 70 private List<ParsedIntentInfo> intents; 71 72 private ComponentName componentName; 73 74 @Nullable 75 protected Bundle metaData; 76 77 private Map<String, Property> mProperties = emptyMap(); 78 ParsedComponent()79 ParsedComponent() { 80 81 } 82 83 @SuppressWarnings("IncompleteCopyConstructor") ParsedComponent(ParsedComponent other)84 public ParsedComponent(ParsedComponent other) { 85 this.metaData = other.metaData; 86 this.name = other.name; 87 this.icon = other.getIcon(); 88 this.labelRes = other.getLabelRes(); 89 this.nonLocalizedLabel = other.getNonLocalizedLabel(); 90 this.logo = other.getLogo(); 91 this.banner = other.getBanner(); 92 93 this.descriptionRes = other.getDescriptionRes(); 94 95 this.flags = other.getFlags(); 96 97 this.setPackageName(other.packageName); 98 this.intents = new ArrayList<>(other.getIntents()); 99 } 100 addIntent(ParsedIntentInfo intent)101 public void addIntent(ParsedIntentInfo intent) { 102 this.intents = CollectionUtils.add(this.intents, intent); 103 } 104 105 /** Add a property to the component */ addProperty(@onNull Property property)106 public void addProperty(@NonNull Property property) { 107 this.mProperties = CollectionUtils.add(this.mProperties, property.getName(), property); 108 } 109 110 @NonNull getIntents()111 public List<ParsedIntentInfo> getIntents() { 112 return intents != null ? intents : Collections.emptyList(); 113 } 114 setName(String name)115 public ParsedComponent setName(String name) { 116 this.name = TextUtils.safeIntern(name); 117 return this; 118 } 119 120 @CallSuper setPackageName(@onNull String packageName)121 public void setPackageName(@NonNull String packageName) { 122 this.packageName = TextUtils.safeIntern(packageName); 123 //noinspection ConstantConditions 124 this.componentName = null; 125 126 // Note: this method does not edit name (which can point to a class), because this package 127 // name change is not changing the package in code, but the identifier used by the system. 128 } 129 130 @NonNull getComponentName()131 public ComponentName getComponentName() { 132 if (componentName == null) { 133 componentName = new ComponentName(getPackageName(), getName()); 134 } 135 return componentName; 136 } 137 138 @Override describeContents()139 public int describeContents() { 140 return 0; 141 } 142 143 @Override writeToParcel(Parcel dest, int flags)144 public void writeToParcel(Parcel dest, int flags) { 145 dest.writeString(this.name); 146 dest.writeInt(this.getIcon()); 147 dest.writeInt(this.getLabelRes()); 148 dest.writeCharSequence(this.getNonLocalizedLabel()); 149 dest.writeInt(this.getLogo()); 150 dest.writeInt(this.getBanner()); 151 dest.writeInt(this.getDescriptionRes()); 152 dest.writeInt(this.getFlags()); 153 sForInternedString.parcel(this.packageName, dest, flags); 154 sForIntentInfos.parcel(this.getIntents(), dest, flags); 155 dest.writeBundle(this.metaData); 156 dest.writeMap(this.mProperties); 157 } 158 ParsedComponent(Parcel in)159 protected ParsedComponent(Parcel in) { 160 // We use the boot classloader for all classes that we load. 161 final ClassLoader boot = Object.class.getClassLoader(); 162 //noinspection ConstantConditions 163 this.name = in.readString(); 164 this.icon = in.readInt(); 165 this.labelRes = in.readInt(); 166 this.nonLocalizedLabel = in.readCharSequence(); 167 this.logo = in.readInt(); 168 this.banner = in.readInt(); 169 this.descriptionRes = in.readInt(); 170 this.flags = in.readInt(); 171 //noinspection ConstantConditions 172 this.packageName = sForInternedString.unparcel(in); 173 this.intents = sForIntentInfos.unparcel(in); 174 this.metaData = in.readBundle(boot); 175 this.mProperties = in.readHashMap(boot); 176 } 177 178 @NonNull getName()179 public String getName() { 180 return name; 181 } 182 getIcon()183 public int getIcon() { 184 return icon; 185 } 186 getLabelRes()187 public int getLabelRes() { 188 return labelRes; 189 } 190 191 @Nullable getNonLocalizedLabel()192 public CharSequence getNonLocalizedLabel() { 193 return nonLocalizedLabel; 194 } 195 getLogo()196 public int getLogo() { 197 return logo; 198 } 199 getBanner()200 public int getBanner() { 201 return banner; 202 } 203 getDescriptionRes()204 public int getDescriptionRes() { 205 return descriptionRes; 206 } 207 getFlags()208 public int getFlags() { 209 return flags; 210 } 211 212 @NonNull getPackageName()213 public String getPackageName() { 214 return packageName; 215 } 216 217 @Nullable getMetaData()218 public Bundle getMetaData() { 219 return metaData; 220 } 221 222 @NonNull getProperties()223 public Map<String, Property> getProperties() { 224 return mProperties; 225 } 226 } 227