Merge "Add flag to guard WM Extensions for all devices" into main
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index c127a43..1e3e81f 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -93,8 +93,12 @@
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
 import android.annotation.TestApi;
+import android.app.ActivityTaskManager;
+import android.app.ActivityThread;
 import android.app.KeyguardManager;
 import android.app.Presentation;
+import android.compat.annotation.ChangeId;
+import android.compat.annotation.EnabledSince;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.ClipData;
 import android.content.ComponentName;
@@ -1416,23 +1420,71 @@
     public static final String PARCEL_KEY_SHORTCUTS_ARRAY = "shortcuts_array";
 
     /**
-     * Whether the device supports the WindowManager Extensions.
-     * OEMs can enable this by having their device config to inherit window_extensions.mk, such as:
+     * Whether the WindowManager Extensions - Activity Embedding feature should be guarded by
+     * the app's target SDK on Android 15.
+     *
+     * WindowManager Extensions are only required for foldable and large screen before Android 15,
+     * so we want to guard the Activity Embedding feature since it can have app compat impact on
+     * devices with a compact size display.
+     *
+     * <p>If {@code true}, the feature is only enabled if the app's target SDK is Android 15 or
+     * above.
+     *
+     * <p>If {@code false}, the feature is enabled for all apps.
+     *
+     * <p>The default value is {@code true}. OEMs can set to {@code false} by having their device
+     * config to inherit window_extensions.mk. This is also required for large screen devices.
      * <pre>
      * $(call inherit-product, $(SRC_TARGET_DIR)/product/window_extensions.mk)
      * </pre>
+     *
      * @hide
      */
-    boolean WINDOW_EXTENSIONS_ENABLED =
+    boolean ACTIVITY_EMBEDDING_GUARD_WITH_ANDROID_15 = SystemProperties.getBoolean(
+            "persist.wm.extensions.activity_embedding_guard_with_android_15", true);
+
+    /**
+     * For devices with {@link #ACTIVITY_EMBEDDING_GUARD_WITH_ANDROID_15} as {@code true},
+     * the Activity Embedding feature is enabled if the app's target SDK is Android 15+.
+     *
+     * @see #ACTIVITY_EMBEDDING_GUARD_WITH_ANDROID_15
+     * @hide
+     */
+    @ChangeId
+    @EnabledSince(targetSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM)
+    long ENABLE_ACTIVITY_EMBEDDING_FOR_ANDROID_15 = 306666082L;
+
+    /**
+     * Whether the device contains the WindowManager Extensions shared library.
+     * This is enabled for all devices through window_extensions_base.mk, but can be dropped if the
+     * device doesn't support multi window.
+     *
+     * <p>Note: Large screen devices must also inherit window_extensions.mk to enable the Activity
+     * Embedding feature by default for all apps.
+     *
+     * @see #ACTIVITY_EMBEDDING_GUARD_WITH_ANDROID_15
+     * @hide
+     */
+    boolean HAS_WINDOW_EXTENSIONS_ON_DEVICE =
             SystemProperties.getBoolean("persist.wm.extensions.enabled", false);
 
     /**
-     * @see #WINDOW_EXTENSIONS_ENABLED
+     * Whether the WindowManager Extensions are enabled.
+     * If {@code false}, the WM Jetpack will report most of its features as disabled.
+     * @see #HAS_WINDOW_EXTENSIONS_ON_DEVICE
      * @hide
      */
     @TestApi
     static boolean hasWindowExtensionsEnabled() {
-        return WINDOW_EXTENSIONS_ENABLED;
+        return HAS_WINDOW_EXTENSIONS_ON_DEVICE
+                && ActivityTaskManager.supportsMultiWindow(ActivityThread.currentApplication())
+                // Since enableWmExtensionsForAllFlag, HAS_WINDOW_EXTENSIONS_ON_DEVICE is now true
+                // on all devices by default as a build file property.
+                // Until finishing flag ramp up, only return true when
+                // ACTIVITY_EMBEDDING_GUARD_WITH_ANDROID_15 is false, which is set per device by
+                // OEMs.
+                && (Flags.enableWmExtensionsForAllFlag()
+                || !ACTIVITY_EMBEDDING_GUARD_WITH_ANDROID_15);
     }
 
     /**
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 7af1965..5297006 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -400,7 +400,7 @@
         // WindowManager Extensions is an optional shared library that is required for WindowManager
         // Jetpack to fully function. Since it is a widely used library, preload it to improve apps
         // startup performance.
-        if (WindowManager.hasWindowExtensionsEnabled()) {
+        if (WindowManager.HAS_WINDOW_EXTENSIONS_ON_DEVICE) {
             final String systemExtFrameworkPath =
                     new File(Environment.getSystemExtDirectory(), "framework").getPath();
             libs.add(new SharedLibraryInfo(
diff --git a/core/tests/coretests/src/android/view/WindowManagerTests.java b/core/tests/coretests/src/android/view/WindowManagerTests.java
new file mode 100644
index 0000000..c5a9d48
--- /dev/null
+++ b/core/tests/coretests/src/android/view/WindowManagerTests.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import static com.android.window.flags.Flags.FLAG_ENABLE_WM_EXTENSIONS_FOR_ALL_FLAG;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
+
+import android.platform.test.annotations.Presubmit;
+import android.platform.test.flag.junit.SetFlagsRule;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Tests for the {@link WindowManager}.
+ *
+ * Build/Install/Run:
+ *  atest FrameworksCoreTests:WindowManagerTests
+ */
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+@Presubmit
+public class WindowManagerTests {
+
+    @Rule
+    public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+
+    @Test
+    public void testHasWindowExtensionsEnabled_flagDisabled() {
+        mSetFlagsRule.disableFlags(FLAG_ENABLE_WM_EXTENSIONS_FOR_ALL_FLAG);
+
+        // Before FLAG_ENABLE_WM_EXTENSIONS_FOR_ALL_FLAG, Extensions are always bundled with AE.
+        assertEquals(isActivityEmbeddingEnableForAll(),
+                WindowManager.hasWindowExtensionsEnabled());
+    }
+
+    @Test
+    public void testHasWindowExtensionsEnabled_flagEnabled() {
+        mSetFlagsRule.enableFlags(FLAG_ENABLE_WM_EXTENSIONS_FOR_ALL_FLAG);
+
+        // Extensions should be enabled on all devices.
+        assertTrue(WindowManager.hasWindowExtensionsEnabled());
+    }
+
+    @Test
+    public void testActivityEmbeddingAvailability() {
+        assumeTrue(isActivityEmbeddingEnableForAll());
+
+        // AE can only be enabled when extensions is enabled.
+        assertTrue(WindowManager.hasWindowExtensionsEnabled());
+    }
+
+    private static boolean isActivityEmbeddingEnableForAll() {
+        return !WindowManager.ACTIVITY_EMBEDDING_GUARD_WITH_ANDROID_15;
+    }
+}
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/WindowExtensionsImpl.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/WindowExtensionsImpl.java
index 6714263..9756278 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/WindowExtensionsImpl.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/WindowExtensionsImpl.java
@@ -16,15 +16,19 @@
 
 package androidx.window.extensions;
 
-import android.app.ActivityTaskManager;
+import static android.view.WindowManager.ACTIVITY_EMBEDDING_GUARD_WITH_ANDROID_15;
+import static android.view.WindowManager.ENABLE_ACTIVITY_EMBEDDING_FOR_ANDROID_15;
+
 import android.app.ActivityThread;
 import android.app.Application;
+import android.app.compat.CompatChanges;
 import android.content.Context;
 import android.hardware.devicestate.DeviceStateManager;
 import android.util.Log;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
 import androidx.window.common.DeviceStateManagerFoldingFeatureProducer;
 import androidx.window.common.RawFoldingFeatureProducer;
 import androidx.window.extensions.area.WindowAreaComponent;
@@ -38,25 +42,38 @@
 
 
 /**
- * The reference implementation of {@link WindowExtensions} that implements the initial API version.
+ * The reference implementation of {@link WindowExtensions} that implements the latest WindowManager
+ * Extensions APIs.
  */
-public class WindowExtensionsImpl implements WindowExtensions {
+class WindowExtensionsImpl implements WindowExtensions {
 
     private static final String TAG = "WindowExtensionsImpl";
+
+    /**
+     * The min version of the WM Extensions that must be supported in the current platform version.
+     */
+    @VisibleForTesting
+    static final int EXTENSIONS_VERSION_CURRENT_PLATFORM = 5;
+
     private final Object mLock = new Object();
     private volatile DeviceStateManagerFoldingFeatureProducer mFoldingFeatureProducer;
     private volatile WindowLayoutComponentImpl mWindowLayoutComponent;
     private volatile SplitController mSplitController;
     private volatile WindowAreaComponent mWindowAreaComponent;
 
-    public WindowExtensionsImpl() {
-        Log.i(TAG, "Initializing Window Extensions.");
+    private final int mVersion = EXTENSIONS_VERSION_CURRENT_PLATFORM;
+    private final boolean mIsActivityEmbeddingEnabled;
+
+    WindowExtensionsImpl() {
+        mIsActivityEmbeddingEnabled = isActivityEmbeddingEnabled();
+        Log.i(TAG, "Initializing Window Extensions, vendor API level=" + mVersion
+                + ", activity embedding enabled=" + mIsActivityEmbeddingEnabled);
     }
 
     // TODO(b/241126279) Introduce constants to better version functionality
     @Override
     public int getVendorApiLevel() {
-        return 5;
+        return mVersion;
     }
 
     @NonNull
@@ -74,8 +91,8 @@
         if (mFoldingFeatureProducer == null) {
             synchronized (mLock) {
                 if (mFoldingFeatureProducer == null) {
-                    Context context = getApplication();
-                    RawFoldingFeatureProducer foldingFeatureProducer =
+                    final Context context = getApplication();
+                    final RawFoldingFeatureProducer foldingFeatureProducer =
                             new RawFoldingFeatureProducer(context);
                     mFoldingFeatureProducer =
                             new DeviceStateManagerFoldingFeatureProducer(context,
@@ -91,8 +108,8 @@
         if (mWindowLayoutComponent == null) {
             synchronized (mLock) {
                 if (mWindowLayoutComponent == null) {
-                    Context context = getApplication();
-                    DeviceStateManagerFoldingFeatureProducer producer =
+                    final Context context = getApplication();
+                    final DeviceStateManagerFoldingFeatureProducer producer =
                             getFoldingFeatureProducer();
                     mWindowLayoutComponent = new WindowLayoutComponentImpl(context, producer);
                 }
@@ -102,29 +119,35 @@
     }
 
     /**
-     * Returns a reference implementation of {@link WindowLayoutComponent} if available,
-     * {@code null} otherwise. The implementation must match the API level reported in
-     * {@link WindowExtensions#getWindowLayoutComponent()}.
+     * Returns a reference implementation of the latest {@link WindowLayoutComponent}.
+     *
+     * The implementation must match the API level reported in
+     * {@link WindowExtensions#getVendorApiLevel()}.
+     *
      * @return {@link WindowLayoutComponent} OEM implementation
      */
+    @NonNull
     @Override
     public WindowLayoutComponent getWindowLayoutComponent() {
         return getWindowLayoutComponentImpl();
     }
 
     /**
-     * Returns a reference implementation of {@link ActivityEmbeddingComponent} if available,
-     * {@code null} otherwise. The implementation must match the API level reported in
-     * {@link WindowExtensions#getWindowLayoutComponent()}.
+     * Returns a reference implementation of the latest {@link ActivityEmbeddingComponent} if the
+     * device supports this feature, {@code null} otherwise.
+     *
+     * The implementation must match the API level reported in
+     * {@link WindowExtensions#getVendorApiLevel()}.
+     *
      * @return {@link ActivityEmbeddingComponent} OEM implementation.
      */
     @Nullable
+    @Override
     public ActivityEmbeddingComponent getActivityEmbeddingComponent() {
+        if (!mIsActivityEmbeddingEnabled) {
+            return null;
+        }
         if (mSplitController == null) {
-            if (!ActivityTaskManager.supportsMultiWindow(getApplication())) {
-                // Disable AE for device that doesn't support multi window.
-                return null;
-            }
             synchronized (mLock) {
                 if (mSplitController == null) {
                     mSplitController = new SplitController(
@@ -138,21 +161,35 @@
     }
 
     /**
-     * Returns a reference implementation of {@link WindowAreaComponent} if available,
-     * {@code null} otherwise. The implementation must match the API level reported in
-     * {@link WindowExtensions#getWindowAreaComponent()}.
+     * Returns a reference implementation of the latest {@link WindowAreaComponent}
+     *
+     * The implementation must match the API level reported in
+     * {@link WindowExtensions#getVendorApiLevel()}.
+     *
      * @return {@link WindowAreaComponent} OEM implementation.
      */
+    @Nullable
+    @Override
     public WindowAreaComponent getWindowAreaComponent() {
         if (mWindowAreaComponent == null) {
             synchronized (mLock) {
                 if (mWindowAreaComponent == null) {
-                    Context context = ActivityThread.currentApplication();
-                    mWindowAreaComponent =
-                            new WindowAreaComponentImpl(context);
+                    final Context context = getApplication();
+                    mWindowAreaComponent = new WindowAreaComponentImpl(context);
                 }
             }
         }
         return mWindowAreaComponent;
     }
+
+    @VisibleForTesting
+    static boolean isActivityEmbeddingEnabled() {
+        if (!ACTIVITY_EMBEDDING_GUARD_WITH_ANDROID_15) {
+            // Device enables it for all apps without targetSDK check.
+            // This must be true for all large screen devices.
+            return true;
+        }
+        // Use compat framework to guard the feature with targetSDK 15.
+        return CompatChanges.isChangeEnabled(ENABLE_ACTIVITY_EMBEDDING_FOR_ANDROID_15);
+    }
 }
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/WindowExtensionsProvider.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/WindowExtensionsProvider.java
index f9e1f07..b0a0c4d 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/WindowExtensionsProvider.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/WindowExtensionsProvider.java
@@ -17,13 +17,19 @@
 package androidx.window.extensions;
 
 import android.annotation.NonNull;
+import android.view.WindowManager;
+
+import androidx.annotation.Nullable;
+import androidx.window.extensions.area.WindowAreaComponent;
+import androidx.window.extensions.embedding.ActivityEmbeddingComponent;
+import androidx.window.extensions.layout.WindowLayoutComponent;
 
 /**
  * Provides the OEM implementation of {@link WindowExtensions}.
  */
 public class WindowExtensionsProvider {
 
-    private static final WindowExtensions sWindowExtensions = new WindowExtensionsImpl();
+    private static volatile WindowExtensions sWindowExtensions;
 
     /**
      * Returns the OEM implementation of {@link WindowExtensions}. This method is implemented in
@@ -33,6 +39,44 @@
      */
     @NonNull
     public static WindowExtensions getWindowExtensions() {
+        if (sWindowExtensions == null) {
+            synchronized (WindowExtensionsProvider.class) {
+                if (sWindowExtensions == null) {
+                    sWindowExtensions = WindowManager.hasWindowExtensionsEnabled()
+                            ? new WindowExtensionsImpl()
+                            : new DisabledWindowExtensions();
+                }
+            }
+        }
         return sWindowExtensions;
     }
+
+    /**
+     * The stub version to return when the WindowManager Extensions is disabled
+     * @see WindowManager#hasWindowExtensionsEnabled
+     */
+    private static class DisabledWindowExtensions implements WindowExtensions {
+        @Override
+        public int getVendorApiLevel() {
+            return 0;
+        }
+
+        @Nullable
+        @Override
+        public WindowLayoutComponent getWindowLayoutComponent() {
+            return null;
+        }
+
+        @Nullable
+        @Override
+        public ActivityEmbeddingComponent getActivityEmbeddingComponent() {
+            return null;
+        }
+
+        @Nullable
+        @Override
+        public WindowAreaComponent getWindowAreaComponent() {
+            return null;
+        }
+    }
 }
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
index 1abda42..0cc4b1f 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
@@ -88,7 +88,7 @@
 import androidx.window.common.CommonFoldingFeature;
 import androidx.window.common.DeviceStateManagerFoldingFeatureProducer;
 import androidx.window.common.EmptyLifecycleCallbacksAdapter;
-import androidx.window.extensions.WindowExtensionsImpl;
+import androidx.window.extensions.WindowExtensions;
 import androidx.window.extensions.core.util.function.Consumer;
 import androidx.window.extensions.core.util.function.Function;
 import androidx.window.extensions.core.util.function.Predicate;
@@ -410,7 +410,7 @@
      * Registers the split organizer callback to notify about changes to active splits.
      *
      * @deprecated Use {@link #setSplitInfoCallback(Consumer)} starting with
-     * {@link WindowExtensionsImpl#getVendorApiLevel()} 2.
+     * {@link WindowExtensions#getVendorApiLevel()} 2.
      */
     @Deprecated
     @Override
@@ -423,7 +423,7 @@
     /**
      * Registers the split organizer callback to notify about changes to active splits.
      *
-     * @since {@link WindowExtensionsImpl#getVendorApiLevel()} 2
+     * @since {@link WindowExtensions#getVendorApiLevel()} 2
      */
     @Override
     public void setSplitInfoCallback(Consumer<List<SplitInfo>> callback) {
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/WindowExtensionsTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/WindowExtensionsTest.java
index f471af0..4267749 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/WindowExtensionsTest.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/WindowExtensionsTest.java
@@ -16,12 +16,15 @@
 
 package androidx.window.extensions;
 
-import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+import static androidx.window.extensions.WindowExtensionsImpl.EXTENSIONS_VERSION_CURRENT_PLATFORM;
 
 import static com.google.common.truth.Truth.assertThat;
 
-import android.app.ActivityTaskManager;
+import static org.junit.Assume.assumeFalse;
+import static org.junit.Assume.assumeTrue;
+
 import android.platform.test.annotations.Presubmit;
+import android.view.WindowManager;
 
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.SmallTest;
@@ -42,25 +45,61 @@
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 public class WindowExtensionsTest {
+
     private WindowExtensions mExtensions;
+    private int mVersion;
 
     @Before
     public void setUp() {
         mExtensions = WindowExtensionsProvider.getWindowExtensions();
+        mVersion = mExtensions.getVendorApiLevel();
     }
 
     @Test
-    public void testGetWindowLayoutComponent() {
+    public void testGetVendorApiLevel_extensionsEnabled_matchesCurrentVersion() {
+        assumeTrue(WindowManager.hasWindowExtensionsEnabled());
+        assertThat(mVersion).isEqualTo(EXTENSIONS_VERSION_CURRENT_PLATFORM);
+    }
+
+    @Test
+    public void testGetVendorApiLevel_extensionsDisabled_returnsZero() {
+        assumeFalse(WindowManager.hasWindowExtensionsEnabled());
+        assertThat(mVersion).isEqualTo(0);
+    }
+
+    @Test
+    public void testGetWindowLayoutComponent_extensionsEnabled_returnsImplementation() {
+        assumeTrue(WindowManager.hasWindowExtensionsEnabled());
         assertThat(mExtensions.getWindowLayoutComponent()).isNotNull();
     }
 
     @Test
-    public void testGetActivityEmbeddingComponent() {
-        if (ActivityTaskManager.supportsMultiWindow(getInstrumentation().getContext())) {
-            assertThat(mExtensions.getActivityEmbeddingComponent()).isNotNull();
-        } else {
-            assertThat(mExtensions.getActivityEmbeddingComponent()).isNull();
-        }
+    public void testGetWindowLayoutComponent_extensionsDisabled_returnsNull() {
+        assumeFalse(WindowManager.hasWindowExtensionsEnabled());
+        assertThat(mExtensions.getWindowLayoutComponent()).isNull();
+    }
+    @Test
+    public void testGetActivityEmbeddingComponent_featureDisabled_returnsNull() {
+        assumeFalse(WindowExtensionsImpl.isActivityEmbeddingEnabled());
+        assertThat(mExtensions.getActivityEmbeddingComponent()).isNull();
+    }
+
+    @Test
+    public void testGetActivityEmbeddingComponent_featureEnabled_returnsImplementation() {
+        assumeTrue(WindowExtensionsImpl.isActivityEmbeddingEnabled());
+        assertThat(mExtensions.getActivityEmbeddingComponent()).isNotNull();
+    }
+
+    @Test
+    public void testGetWindowAreaComponent_extensionsEnabled_returnsImplementation() {
+        assumeTrue(WindowManager.hasWindowExtensionsEnabled());
+        assertThat(mExtensions.getWindowAreaComponent()).isNotNull();
+    }
+
+    @Test
+    public void testGetWindowAreaComponent_extensionsDisabled_returnsNull() {
+        assumeFalse(WindowManager.hasWindowExtensionsEnabled());
+        assertThat(mExtensions.getWindowAreaComponent()).isNull();
     }
 
     @Test
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 6fa6957..23f9743 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -118,6 +118,7 @@
 import static android.view.Display.INVALID_DISPLAY;
 import static android.view.Surface.ROTATION_270;
 import static android.view.Surface.ROTATION_90;
+import static android.view.WindowManager.ACTIVITY_EMBEDDING_GUARD_WITH_ANDROID_15;
 import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD;
 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
@@ -125,10 +126,12 @@
 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
 import static android.view.WindowManager.PROPERTY_ACTIVITY_EMBEDDING_SPLITS_ENABLED;
 import static android.view.WindowManager.PROPERTY_ALLOW_UNTRUSTED_ACTIVITY_EMBEDDING_STATE_SHARING;
+import static android.view.WindowManager.ENABLE_ACTIVITY_EMBEDDING_FOR_ANDROID_15;
 import static android.view.WindowManager.TRANSIT_CLOSE;
 import static android.view.WindowManager.TRANSIT_FLAG_OPEN_BEHIND;
 import static android.view.WindowManager.TRANSIT_OLD_UNSET;
 import static android.view.WindowManager.TRANSIT_RELAUNCH;
+import static android.view.WindowManager.hasWindowExtensionsEnabled;
 import static android.window.TransitionInfo.FLAGS_IS_OCCLUDED_NO_ANIMATION;
 import static android.window.TransitionInfo.FLAG_IS_OCCLUDED;
 import static android.window.TransitionInfo.FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT;
@@ -282,6 +285,7 @@
 import android.app.WindowConfiguration;
 import android.app.admin.DevicePolicyManager;
 import android.app.assist.ActivityId;
+import android.app.compat.CompatChanges;
 import android.app.servertransaction.ActivityConfigurationChangeItem;
 import android.app.servertransaction.ActivityLifecycleItem;
 import android.app.servertransaction.ActivityRelaunchItem;
@@ -2266,16 +2270,7 @@
 
         mActivityRecordInputSink = new ActivityRecordInputSink(this, sourceRecord);
 
-        boolean appActivityEmbeddingEnabled = false;
-        try {
-            appActivityEmbeddingEnabled = WindowManager.hasWindowExtensionsEnabled()
-                    && mAtmService.mContext.getPackageManager()
-                            .getProperty(PROPERTY_ACTIVITY_EMBEDDING_SPLITS_ENABLED, packageName)
-                            .getBoolean();
-        } catch (PackageManager.NameNotFoundException e) {
-            // No such property name.
-        }
-        mAppActivityEmbeddingSplitsEnabled = appActivityEmbeddingEnabled;
+        mAppActivityEmbeddingSplitsEnabled = isAppActivityEmbeddingSplitsEnabled();
         mAllowUntrustedEmbeddingStateSharing = getAllowUntrustedEmbeddingStateSharingProperty();
 
         mOptInOnBackInvoked = WindowOnBackInvokedDispatcher
@@ -2294,6 +2289,28 @@
         mCallerState = new ActivityCallerState(mAtmService);
     }
 
+    private boolean isAppActivityEmbeddingSplitsEnabled() {
+        if (!hasWindowExtensionsEnabled()) {
+            // WM Extensions disabled.
+            return false;
+        }
+        if (ACTIVITY_EMBEDDING_GUARD_WITH_ANDROID_15 && !CompatChanges.isChangeEnabled(
+                ENABLE_ACTIVITY_EMBEDDING_FOR_ANDROID_15,
+                info.packageName,
+                UserHandle.getUserHandleForUid(getUid()))) {
+            // Activity Embedding is guarded with Android 15+, but this app is not qualified.
+            return false;
+        }
+        try {
+            return mAtmService.mContext.getPackageManager()
+                    .getProperty(PROPERTY_ACTIVITY_EMBEDDING_SPLITS_ENABLED, packageName)
+                    .getBoolean();
+        } catch (PackageManager.NameNotFoundException e) {
+            // No such property name.
+            return false;
+        }
+    }
+
     /**
      * Generate the task affinity with uid and activity launch mode. For b/35954083, Limit task
      * affinity to uid to avoid issues associated with sharing affinity across uids.