Activity 启动政策

Activity 启动行为由应用的 AndroidManifest.xml 文件中的启动模式、intent 标志以及调用方提供的 ActivityOptions 定义。使用 ActivityOption#setLaunchDisplayId(int) 以指定 Activity 启动的目标显示屏。

  • 默认情况下,Activity 在与调用方相同的显示屏上启动。例如,从启动器启动的新 Activity 实例应放置在同一显示屏上,而无需额外的标志或选项。请务必为启动使用正确的上下文(Activity 与 Application)。
  • 如果启动操作是从未与特定显示屏关联的来源(例如从 shell 或 Application 上下文)执行的,则 Activity 将放置在用户上次与之互动的设备上的顶部显示屏上,或上次 Activity 从该显示屏启动。
  • 启动 Activity 的 Intent 可以解析为系统中现有的 Activity 实例。在这种情况下,如果没有提供其他标志,Activity 会在上次使用的同一显示屏上浮出。如果使用 ActivityOptions#setTargetDisplayId() 指定了目标显示屏,则 Activity 会移至该显示屏(如果安全和其他限制允许)。

安全限制

为防止恶意应用通过从其创建的虚拟显示屏表面读取用户敏感信息来盗用这些信息,在 Android 10 中,应用只能在其创建的虚拟显示屏上启动自己的 Activity。但是

  • 具有 INTERNAL_SYSTEM_WINDOW 权限的系统组件可以在任何显示屏上启动。
  • 具有 ACTIVITY_EMBEDDING 权限的调用方可以启动来自其他应用的 Activity,这些应用具有 ActivityInfo.FLAG_ALLOW_EMBEDDED 标志。
  • 仅允许所有者或该显示屏上存在的 Activity 在私有显示屏上启动 Activity。

类似的限制适用于向显示屏添加窗口。

Android 10 包含 ActivityManager#isActivityStartAllowedOnDisplay(Context context, int displayId, Intent intent) 方法,用于在尝试在显示屏上启动应用之前检查该应用的安全限制。在 Android 9(及更低版本)中,受限的启动结果会抛出 SecurityException

大多数安全限制都在 ActivityStackSupervisor#isCallerAllowedToLaunchOnDisplay() 方法中应用。