• 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.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