1 /*
2  * Copyright (C) 2008 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;
18 
19 import android.annotation.SuppressLint;
20 import android.app.Activity;
21 import android.app.Service;
22 import android.compat.annotation.UnsupportedAppUsage;
23 import android.content.BroadcastReceiver;
24 import android.content.ComponentName;
25 import android.content.ContentResolver;
26 import android.content.Context;
27 import android.graphics.drawable.Drawable;
28 import android.os.Build;
29 import android.os.Parcel;
30 import android.util.Printer;
31 
32 /**
33  * Base class containing information common to all application components
34  * ({@link ActivityInfo}, {@link ServiceInfo}).  This class is not intended
35  * to be used by itself; it is simply here to share common definitions
36  * between all application components.  As such, it does not itself
37  * implement Parcelable, but does provide convenience methods to assist
38  * in the implementation of Parcelable in subclasses.
39  */
40 @android.ravenwood.annotation.RavenwoodKeepWholeClass
41 public class ComponentInfo extends PackageItemInfo {
42     /**
43      * Global information about the application/package this component is a
44      * part of.
45      */
46     public ApplicationInfo applicationInfo;
47 
48     /**
49      * The name of the process this component should run in.
50      * From the "android:process" attribute or, if not set, the same
51      * as <var>applicationInfo.processName</var>.
52      */
53     public String processName;
54 
55     /**
56      * The name of the split in which this component is declared.
57      * Null if the component was declared in the base APK.
58      */
59     public String splitName;
60 
61     /**
62      * Set of attribution tags that should be automatically applied to this
63      * component.
64      * <p>
65      * When this component represents an {@link Activity}, {@link Service},
66      * {@link ContentResolver} or {@link BroadcastReceiver}, each instance will
67      * be automatically configured with {@link Context#createAttributionContext}
68      * using the first attribution tag contained here.
69      * <p>
70      * Additionally, when this component represents a {@link BroadcastReceiver}
71      * and the sender of a broadcast requires the receiver to hold one or more
72      * specific permissions, those permission checks will be performed using
73      * each of the attributions tags contained here.
74      *
75      * @see Context#createAttributionContext(String)
76      */
77     @SuppressLint({"MissingNullability", "MutableBareField"})
78     public String[] attributionTags;
79 
80     /**
81      * A string resource identifier (in the package's resources) containing
82      * a user-readable description of the component.  From the "description"
83      * attribute or, if not set, 0.
84      */
85     public int descriptionRes;
86 
87     /**
88      * Indicates whether or not this component may be instantiated.  Note that this value can be
89      * overridden by the one in its parent {@link ApplicationInfo}.
90      */
91     public boolean enabled = true;
92 
93     /**
94      * Set to true if this component is available for use by other applications.
95      * Comes from {@link android.R.attr#exported android:exported} of the
96      * &lt;activity&gt;, &lt;receiver&gt;, &lt;service&gt;, or
97      * &lt;provider&gt; tag.
98      */
99     public boolean exported = false;
100 
101     /**
102      * Indicates if this component is aware of direct boot lifecycle, and can be
103      * safely run before the user has entered their credentials (such as a lock
104      * pattern or PIN).
105      */
106     public boolean directBootAware = false;
107 
ComponentInfo()108     public ComponentInfo() {
109     }
110 
ComponentInfo(ComponentInfo orig)111     public ComponentInfo(ComponentInfo orig) {
112         super(orig);
113         applicationInfo = orig.applicationInfo;
114         processName = orig.processName;
115         splitName = orig.splitName;
116         attributionTags = orig.attributionTags;
117         descriptionRes = orig.descriptionRes;
118         enabled = orig.enabled;
119         exported = orig.exported;
120         directBootAware = orig.directBootAware;
121     }
122 
123     /** @hide */
loadUnsafeLabel(PackageManager pm)124     @Override public CharSequence loadUnsafeLabel(PackageManager pm) {
125         if (nonLocalizedLabel != null) {
126             return nonLocalizedLabel;
127         }
128         ApplicationInfo ai = applicationInfo;
129         CharSequence label;
130         if (labelRes != 0) {
131             label = pm.getText(packageName, labelRes, ai);
132             if (label != null) {
133                 return label;
134             }
135         }
136         if (ai.nonLocalizedLabel != null) {
137             return ai.nonLocalizedLabel;
138         }
139         if (ai.labelRes != 0) {
140             label = pm.getText(packageName, ai.labelRes, ai);
141             if (label != null) {
142                 return label;
143             }
144         }
145         return name;
146     }
147 
148     /**
149      * Return whether this component and its enclosing application are enabled.
150      */
isEnabled()151     public boolean isEnabled() {
152         return enabled && applicationInfo.enabled;
153     }
154 
155     /**
156      * Return the icon resource identifier to use for this component.  If
157      * the component defines an icon, that is used; else, the application
158      * icon is used.
159      *
160      * @return The icon associated with this component.
161      */
getIconResource()162     public final int getIconResource() {
163         return icon != 0 ? icon : applicationInfo.icon;
164     }
165 
166     /**
167      * Return the logo resource identifier to use for this component.  If
168      * the component defines a logo, that is used; else, the application
169      * logo is used.
170      *
171      * @return The logo associated with this component.
172      */
getLogoResource()173     public final int getLogoResource() {
174         return logo != 0 ? logo : applicationInfo.logo;
175     }
176 
177     /**
178      * Return the banner resource identifier to use for this component. If the
179      * component defines a banner, that is used; else, the application banner is
180      * used.
181      *
182      * @return The banner associated with this component.
183      */
getBannerResource()184     public final int getBannerResource() {
185         return banner != 0 ? banner : applicationInfo.banner;
186     }
187 
188     /** {@hide} */
189     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
getComponentName()190     public ComponentName getComponentName() {
191         return new ComponentName(packageName, name);
192     }
193 
dumpFront(Printer pw, String prefix)194     protected void dumpFront(Printer pw, String prefix) {
195         super.dumpFront(pw, prefix);
196         if (processName != null && !packageName.equals(processName)) {
197             pw.println(prefix + "processName=" + processName);
198         }
199         if (splitName != null) {
200             pw.println(prefix + "splitName=" + splitName);
201         }
202         if (attributionTags != null && attributionTags.length > 0) {
203             StringBuilder tags = new StringBuilder();
204             tags.append(attributionTags[0]);
205             for (int i = 1; i < attributionTags.length; i++) {
206                 tags.append(", ");
207                 tags.append(attributionTags[i]);
208             }
209             pw.println(prefix + "attributionTags=[" + tags + "]");
210         }
211         pw.println(prefix + "enabled=" + enabled + " exported=" + exported
212                 + " directBootAware=" + directBootAware);
213         if (descriptionRes != 0) {
214             pw.println(prefix + "description=" + descriptionRes);
215         }
216     }
217 
dumpBack(Printer pw, String prefix)218     protected void dumpBack(Printer pw, String prefix) {
219         dumpBack(pw, prefix, DUMP_FLAG_ALL);
220     }
221 
dumpBack(Printer pw, String prefix, int dumpFlags)222     void dumpBack(Printer pw, String prefix, int dumpFlags) {
223         if ((dumpFlags & DUMP_FLAG_APPLICATION) != 0) {
224             if (applicationInfo != null) {
225                 pw.println(prefix + "ApplicationInfo:");
226                 applicationInfo.dump(pw, prefix + "  ", dumpFlags);
227             } else {
228                 pw.println(prefix + "ApplicationInfo: null");
229             }
230         }
231         super.dumpBack(pw, prefix);
232     }
233 
writeToParcel(Parcel dest, int parcelableFlags)234     public void writeToParcel(Parcel dest, int parcelableFlags) {
235         super.writeToParcel(dest, parcelableFlags);
236         applicationInfo.writeToParcel(dest, parcelableFlags);
237         dest.writeString8(processName);
238         dest.writeString8(splitName);
239         dest.writeString8Array(attributionTags);
240         dest.writeInt(descriptionRes);
241         dest.writeInt(enabled ? 1 : 0);
242         dest.writeInt(exported ? 1 : 0);
243         dest.writeInt(directBootAware ? 1 : 0);
244     }
245 
ComponentInfo(Parcel source)246     protected ComponentInfo(Parcel source) {
247         super(source);
248         applicationInfo = ApplicationInfo.CREATOR.createFromParcel(source);
249         processName = source.readString8();
250         splitName = source.readString8();
251         attributionTags = source.createString8Array();
252         descriptionRes = source.readInt();
253         enabled = (source.readInt() != 0);
254         exported = (source.readInt() != 0);
255         directBootAware = (source.readInt() != 0);
256     }
257 
258     /**
259      * @hide
260      */
261     @Override
262     @android.ravenwood.annotation.RavenwoodThrow(blockedBy = android.content.res.Resources.class)
loadDefaultIcon(PackageManager pm)263     public Drawable loadDefaultIcon(PackageManager pm) {
264         return applicationInfo.loadIcon(pm);
265     }
266 
267     /**
268      * @hide
269      */
270     @android.ravenwood.annotation.RavenwoodThrow(blockedBy = android.content.res.Resources.class)
loadDefaultBanner(PackageManager pm)271     @Override protected Drawable loadDefaultBanner(PackageManager pm) {
272         return applicationInfo.loadBanner(pm);
273     }
274 
275     /**
276      * @hide
277      */
278     @Override
279     @android.ravenwood.annotation.RavenwoodThrow(blockedBy = android.content.res.Resources.class)
loadDefaultLogo(PackageManager pm)280     protected Drawable loadDefaultLogo(PackageManager pm) {
281         return applicationInfo.loadLogo(pm);
282     }
283 
284     /**
285      * @hide
286      */
getApplicationInfo()287     @Override public ApplicationInfo getApplicationInfo() {
288         return applicationInfo;
289     }
290 }
291