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