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.ActivityInfo.RESIZE_MODE_FORCE_RESIZEABLE;
20 import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
21 import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
22 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
23 import static android.content.pm.parsing.ParsingPackageImpl.sForInternedString;
24 import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_UNSPECIFIED;
25 
26 import android.annotation.Nullable;
27 import android.app.ActivityTaskManager;
28 import android.content.ComponentName;
29 import android.content.pm.ActivityInfo;
30 import android.content.pm.PackageManager;
31 import android.content.pm.PackageParser;
32 import android.os.Parcel;
33 import android.os.Parcelable;
34 import android.text.TextUtils;
35 
36 import com.android.internal.util.DataClass;
37 import com.android.internal.util.Parcelling.BuiltIn.ForInternedString;
38 
39 /** @hide **/
40 public class ParsedActivity extends ParsedMainComponent {
41 
42     int theme;
43     int uiOptions;
44 
45     @Nullable
46     @DataClass.ParcelWith(ForInternedString.class)
47     private String targetActivity;
48 
49     @Nullable
50     @DataClass.ParcelWith(ForInternedString.class)
51     private String parentActivityName;
52     @Nullable
53     String taskAffinity;
54     int privateFlags;
55     @Nullable
56     @DataClass.ParcelWith(ForInternedString.class)
57     private String permission;
58 
59     int launchMode;
60     int documentLaunchMode;
61     int maxRecents;
62     int configChanges;
63     int softInputMode;
64     int persistableMode;
65     int lockTaskLaunchMode;
66 
67     int screenOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
68     int resizeMode = ActivityInfo.RESIZE_MODE_RESIZEABLE;
69 
70     @Nullable
71     private Float maxAspectRatio;
72 
73     @Nullable
74     private Float minAspectRatio;
75 
76     private boolean supportsSizeChanges;
77 
78     @Nullable
79     String requestedVrComponent;
80     int rotationAnimation = -1;
81     int colorMode;
82 
83     @Nullable
84     ActivityInfo.WindowLayout windowLayout;
85 
ParsedActivity(ParsedActivity other)86     public ParsedActivity(ParsedActivity other) {
87         super(other);
88         this.theme = other.theme;
89         this.uiOptions = other.uiOptions;
90         this.targetActivity = other.targetActivity;
91         this.parentActivityName = other.parentActivityName;
92         this.taskAffinity = other.taskAffinity;
93         this.privateFlags = other.privateFlags;
94         this.permission = other.permission;
95         this.launchMode = other.launchMode;
96         this.documentLaunchMode = other.documentLaunchMode;
97         this.maxRecents = other.maxRecents;
98         this.configChanges = other.configChanges;
99         this.softInputMode = other.softInputMode;
100         this.persistableMode = other.persistableMode;
101         this.lockTaskLaunchMode = other.lockTaskLaunchMode;
102         this.screenOrientation = other.screenOrientation;
103         this.resizeMode = other.resizeMode;
104         this.maxAspectRatio = other.maxAspectRatio;
105         this.minAspectRatio = other.minAspectRatio;
106         this.supportsSizeChanges = other.supportsSizeChanges;
107         this.requestedVrComponent = other.requestedVrComponent;
108         this.rotationAnimation = other.rotationAnimation;
109         this.colorMode = other.colorMode;
110         this.windowLayout = other.windowLayout;
111     }
112 
113     /**
114      * Generate activity object that forwards user to App Details page automatically.
115      * This activity should be invisible to user and user should not know or see it.
116      */
makeAppDetailsActivity(String packageName, String processName, int uiOptions, String taskAffinity, boolean hardwareAccelerated)117     public static ParsedActivity makeAppDetailsActivity(String packageName, String processName,
118             int uiOptions, String taskAffinity, boolean hardwareAccelerated) {
119         ParsedActivity activity = new ParsedActivity();
120         activity.setPackageName(packageName);
121         activity.theme = android.R.style.Theme_NoDisplay;
122         activity.exported = true;
123         activity.setName(PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME);
124         activity.setProcessName(processName);
125         activity.uiOptions = uiOptions;
126         activity.taskAffinity = taskAffinity;
127         activity.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
128         activity.documentLaunchMode = ActivityInfo.DOCUMENT_LAUNCH_NONE;
129         activity.maxRecents = ActivityTaskManager.getDefaultAppRecentsLimitStatic();
130         activity.configChanges = PackageParser.getActivityConfigChanges(0, 0);
131         activity.softInputMode = 0;
132         activity.persistableMode = ActivityInfo.PERSIST_NEVER;
133         activity.screenOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
134         activity.resizeMode = RESIZE_MODE_FORCE_RESIZEABLE;
135         activity.lockTaskLaunchMode = 0;
136         activity.setDirectBootAware(false);
137         activity.rotationAnimation = ROTATION_ANIMATION_UNSPECIFIED;
138         activity.colorMode = ActivityInfo.COLOR_MODE_DEFAULT;
139         if (hardwareAccelerated) {
140             activity.setFlags(activity.getFlags() | ActivityInfo.FLAG_HARDWARE_ACCELERATED);
141         }
142         return activity;
143     }
144 
makeAlias(String targetActivityName, ParsedActivity target)145     static ParsedActivity makeAlias(String targetActivityName, ParsedActivity target) {
146         ParsedActivity alias = new ParsedActivity();
147         alias.setPackageName(target.getPackageName());
148         alias.setTargetActivity(targetActivityName);
149         alias.configChanges = target.configChanges;
150         alias.flags = target.flags;
151         alias.privateFlags = target.privateFlags;
152         alias.icon = target.icon;
153         alias.logo = target.logo;
154         alias.banner = target.banner;
155         alias.labelRes = target.labelRes;
156         alias.nonLocalizedLabel = target.nonLocalizedLabel;
157         alias.launchMode = target.launchMode;
158         alias.lockTaskLaunchMode = target.lockTaskLaunchMode;
159         alias.descriptionRes = target.descriptionRes;
160         alias.screenOrientation = target.screenOrientation;
161         alias.taskAffinity = target.taskAffinity;
162         alias.theme = target.theme;
163         alias.softInputMode = target.softInputMode;
164         alias.uiOptions = target.uiOptions;
165         alias.parentActivityName = target.parentActivityName;
166         alias.maxRecents = target.maxRecents;
167         alias.windowLayout = target.windowLayout;
168         alias.resizeMode = target.resizeMode;
169         alias.maxAspectRatio = target.maxAspectRatio;
170         alias.minAspectRatio = target.minAspectRatio;
171         alias.supportsSizeChanges = target.supportsSizeChanges;
172         alias.requestedVrComponent = target.requestedVrComponent;
173         alias.directBootAware = target.directBootAware;
174         alias.setProcessName(target.getProcessName());
175         return alias;
176 
177         // Not all attributes from the target ParsedActivity are copied to the alias.
178         // Careful when adding an attribute and determine whether or not it should be copied.
179 //        alias.enabled = target.enabled;
180 //        alias.exported = target.exported;
181 //        alias.permission = target.permission;
182 //        alias.splitName = target.splitName;
183 //        alias.documentLaunchMode = target.documentLaunchMode;
184 //        alias.persistableMode = target.persistableMode;
185 //        alias.rotationAnimation = target.rotationAnimation;
186 //        alias.colorMode = target.colorMode;
187 //        alias.intents.addAll(target.intents);
188 //        alias.order = target.order;
189 //        alias.metaData = target.metaData;
190     }
191 
setMaxAspectRatio(int resizeMode, float maxAspectRatio)192     public ParsedActivity setMaxAspectRatio(int resizeMode, float maxAspectRatio) {
193         if (resizeMode == ActivityInfo.RESIZE_MODE_RESIZEABLE
194                 || resizeMode == ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION) {
195             // Resizeable activities can be put in any aspect ratio.
196             return this;
197         }
198 
199         if (maxAspectRatio < 1.0f && maxAspectRatio != 0) {
200             // Ignore any value lesser than 1.0.
201             return this;
202         }
203 
204         this.maxAspectRatio = maxAspectRatio;
205         return this;
206     }
207 
setMinAspectRatio(int resizeMode, float minAspectRatio)208     public ParsedActivity setMinAspectRatio(int resizeMode, float minAspectRatio) {
209         if (resizeMode == RESIZE_MODE_RESIZEABLE
210                 || resizeMode == RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION) {
211             // Resizeable activities can be put in any aspect ratio.
212             return this;
213         }
214 
215         if (minAspectRatio < 1.0f && minAspectRatio != 0) {
216             // Ignore any value lesser than 1.0.
217             return this;
218         }
219 
220         this.minAspectRatio = minAspectRatio;
221         return this;
222     }
223 
setSupportsSizeChanges(boolean supportsSizeChanges)224     public ParsedActivity setSupportsSizeChanges(boolean supportsSizeChanges) {
225         this.supportsSizeChanges = supportsSizeChanges;
226         return this;
227     }
228 
setFlags(int flags)229     public ParsedActivity setFlags(int flags) {
230         this.flags = flags;
231         return this;
232     }
233 
setResizeMode(int resizeMode)234     public ParsedActivity setResizeMode(int resizeMode) {
235         this.resizeMode = resizeMode;
236         return this;
237     }
238 
setTargetActivity(String targetActivity)239     public ParsedActivity setTargetActivity(String targetActivity) {
240         this.targetActivity = TextUtils.safeIntern(targetActivity);
241         return this;
242     }
243 
setParentActivity(String parentActivity)244     public ParsedActivity setParentActivity(String parentActivity) {
245         this.parentActivityName = TextUtils.safeIntern(parentActivity);
246         return this;
247     }
248 
setPermission(String permission)249     public ParsedActivity setPermission(String permission) {
250         // Empty string must be converted to null
251         this.permission = TextUtils.isEmpty(permission) ? null : permission.intern();
252         return this;
253     }
254 
toString()255     public String toString() {
256         StringBuilder sb = new StringBuilder(128);
257         sb.append("Activity{");
258         sb.append(Integer.toHexString(System.identityHashCode(this)));
259         sb.append(' ');
260         ComponentName.appendShortString(sb, getPackageName(), getName());
261         sb.append('}');
262         return sb.toString();
263     }
264 
265     @Override
describeContents()266     public int describeContents() {
267         return 0;
268     }
269 
270     @Override
writeToParcel(Parcel dest, int flags)271     public void writeToParcel(Parcel dest, int flags) {
272         super.writeToParcel(dest, flags);
273         dest.writeInt(this.theme);
274         dest.writeInt(this.uiOptions);
275         dest.writeString(this.targetActivity);
276         dest.writeString(this.parentActivityName);
277         dest.writeString(this.taskAffinity);
278         dest.writeInt(this.privateFlags);
279         sForInternedString.parcel(this.permission, dest, flags);
280         dest.writeInt(this.launchMode);
281         dest.writeInt(this.documentLaunchMode);
282         dest.writeInt(this.maxRecents);
283         dest.writeInt(this.configChanges);
284         dest.writeInt(this.softInputMode);
285         dest.writeInt(this.persistableMode);
286         dest.writeInt(this.lockTaskLaunchMode);
287         dest.writeInt(this.screenOrientation);
288         dest.writeInt(this.resizeMode);
289         dest.writeValue(this.maxAspectRatio);
290         dest.writeValue(this.minAspectRatio);
291         dest.writeBoolean(this.supportsSizeChanges);
292         dest.writeString(this.requestedVrComponent);
293         dest.writeInt(this.rotationAnimation);
294         dest.writeInt(this.colorMode);
295         dest.writeBundle(this.metaData);
296 
297         if (windowLayout != null) {
298             dest.writeInt(1);
299             windowLayout.writeToParcel(dest);
300         } else {
301             dest.writeBoolean(false);
302         }
303     }
304 
ParsedActivity()305     public ParsedActivity() {
306     }
307 
ParsedActivity(Parcel in)308     protected ParsedActivity(Parcel in) {
309         super(in);
310         this.theme = in.readInt();
311         this.uiOptions = in.readInt();
312         this.targetActivity = in.readString();
313         this.parentActivityName = in.readString();
314         this.taskAffinity = in.readString();
315         this.privateFlags = in.readInt();
316         this.permission = sForInternedString.unparcel(in);
317         this.launchMode = in.readInt();
318         this.documentLaunchMode = in.readInt();
319         this.maxRecents = in.readInt();
320         this.configChanges = in.readInt();
321         this.softInputMode = in.readInt();
322         this.persistableMode = in.readInt();
323         this.lockTaskLaunchMode = in.readInt();
324         this.screenOrientation = in.readInt();
325         this.resizeMode = in.readInt();
326         this.maxAspectRatio = (Float) in.readValue(Float.class.getClassLoader());
327         this.minAspectRatio = (Float) in.readValue(Float.class.getClassLoader());
328         this.supportsSizeChanges = in.readBoolean();
329         this.requestedVrComponent = in.readString();
330         this.rotationAnimation = in.readInt();
331         this.colorMode = in.readInt();
332         this.metaData = in.readBundle();
333         if (in.readBoolean()) {
334             windowLayout = new ActivityInfo.WindowLayout(in);
335         }
336     }
337 
338     public static final Parcelable.Creator<ParsedActivity> CREATOR = new Creator<ParsedActivity>() {
339         @Override
340         public ParsedActivity createFromParcel(Parcel source) {
341             return new ParsedActivity(source);
342         }
343 
344         @Override
345         public ParsedActivity[] newArray(int size) {
346             return new ParsedActivity[size];
347         }
348     };
349 
getTheme()350     public int getTheme() {
351         return theme;
352     }
353 
getUiOptions()354     public int getUiOptions() {
355         return uiOptions;
356     }
357 
358     @Nullable
getTargetActivity()359     public String getTargetActivity() {
360         return targetActivity;
361     }
362 
363     @Nullable
getParentActivityName()364     public String getParentActivityName() {
365         return parentActivityName;
366     }
367 
368     @Nullable
getTaskAffinity()369     public String getTaskAffinity() {
370         return taskAffinity;
371     }
372 
getPrivateFlags()373     public int getPrivateFlags() {
374         return privateFlags;
375     }
376 
377     @Nullable
getPermission()378     public String getPermission() {
379         return permission;
380     }
381 
getLaunchMode()382     public int getLaunchMode() {
383         return launchMode;
384     }
385 
getDocumentLaunchMode()386     public int getDocumentLaunchMode() {
387         return documentLaunchMode;
388     }
389 
getMaxRecents()390     public int getMaxRecents() {
391         return maxRecents;
392     }
393 
getConfigChanges()394     public int getConfigChanges() {
395         return configChanges;
396     }
397 
getSoftInputMode()398     public int getSoftInputMode() {
399         return softInputMode;
400     }
401 
getPersistableMode()402     public int getPersistableMode() {
403         return persistableMode;
404     }
405 
getLockTaskLaunchMode()406     public int getLockTaskLaunchMode() {
407         return lockTaskLaunchMode;
408     }
409 
getScreenOrientation()410     public int getScreenOrientation() {
411         return screenOrientation;
412     }
413 
getResizeMode()414     public int getResizeMode() {
415         return resizeMode;
416     }
417 
418     @Nullable
getMaxAspectRatio()419     public Float getMaxAspectRatio() {
420         return maxAspectRatio;
421     }
422 
423     @Nullable
getMinAspectRatio()424     public Float getMinAspectRatio() {
425         return minAspectRatio;
426     }
427 
getSupportsSizeChanges()428     public boolean getSupportsSizeChanges() {
429         return supportsSizeChanges;
430     }
431 
432     @Nullable
getRequestedVrComponent()433     public String getRequestedVrComponent() {
434         return requestedVrComponent;
435     }
436 
getRotationAnimation()437     public int getRotationAnimation() {
438         return rotationAnimation;
439     }
440 
getColorMode()441     public int getColorMode() {
442         return colorMode;
443     }
444 
445     @Nullable
getWindowLayout()446     public ActivityInfo.WindowLayout getWindowLayout() {
447         return windowLayout;
448     }
449 }
450