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