Loading services/core/java/com/android/server/wm/ActivityRecord.java +1 −5 Original line number Diff line number Diff line Loading @@ -10890,12 +10890,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A * Whether we should send fake focus when the activity is resumed. This is done because some * game engines wait to get focus before drawing the content of the app. */ // TODO(b/263593361): Explore enabling compat fake focus for freeform. // TODO(b/263592337): Explore enabling compat fake focus for fullscreen, e.g. for when // covered with bubbles. boolean shouldSendCompatFakeFocus() { return mLetterboxUiController.shouldSendFakeFocus() && inMultiWindowMode() && !inPinnedWindowingMode() && !inFreeformWindowingMode(); return mAppCompatController.getAppCompatFocusOverrides().shouldSendFakeFocus(); } boolean canCaptureSnapshot() { Loading services/core/java/com/android/server/wm/AppCompatController.java +5 −0 Original line number Diff line number Diff line Loading @@ -94,4 +94,9 @@ class AppCompatController { } return null; } @NonNull AppCompatFocusOverrides getAppCompatFocusOverrides() { return mAppCompatOverrides.getAppCompatFocusOverrides(); } } services/core/java/com/android/server/wm/AppCompatFocusOverrides.java 0 → 100644 +68 −0 Original line number Diff line number Diff line /* * 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 com.android.server.wm; import static android.content.pm.ActivityInfo.OVERRIDE_ENABLE_COMPAT_FAKE_FOCUS; import static android.view.WindowManager.PROPERTY_COMPAT_ENABLE_FAKE_FOCUS; import static com.android.server.wm.AppCompatUtils.isChangeEnabled; import android.annotation.NonNull; import com.android.server.wm.utils.OptPropFactory; /** * Encapsulates app compat focus policy. */ class AppCompatFocusOverrides { @NonNull final ActivityRecord mActivityRecord; @NonNull private final OptPropFactory.OptProp mFakeFocusOptProp; AppCompatFocusOverrides(@NonNull ActivityRecord activityRecord, @NonNull AppCompatConfiguration appCompatConfiguration, @NonNull OptPropFactory optPropBuilder) { mActivityRecord = activityRecord; mFakeFocusOptProp = optPropBuilder.create(PROPERTY_COMPAT_ENABLE_FAKE_FOCUS, appCompatConfiguration::isCompatFakeFocusEnabled); } /** * Whether sending compat fake focus for split screen resumed activities is enabled. Needed * because some game engines wait to get focus before drawing the content of the app which isn't * guaranteed by default in multi-window modes. * * <p>This treatment is enabled when the following conditions are met: * <ul> * <li>Flag gating the treatment is enabled * <li>Component property is NOT set to false * <li>Component property is set to true or per-app override is enabled * </ul> */ boolean shouldSendFakeFocus() { // TODO(b/263593361): Explore enabling compat fake focus for freeform. // TODO(b/263592337): Explore enabling compat fake focus for fullscreen, e.g. for when // covered with bubbles. return mFakeFocusOptProp.shouldEnableWithOverrideAndProperty( isChangeEnabled(mActivityRecord, OVERRIDE_ENABLE_COMPAT_FAKE_FOCUS)) && mActivityRecord.inMultiWindowMode() && !mActivityRecord.inPinnedWindowingMode() && !mActivityRecord.inFreeformWindowingMode(); } } services/core/java/com/android/server/wm/AppCompatOverrides.java +10 −35 Original line number Diff line number Diff line Loading @@ -18,17 +18,12 @@ package com.android.server.wm; import static android.content.pm.ActivityInfo.FORCE_NON_RESIZE_APP; import static android.content.pm.ActivityInfo.FORCE_RESIZE_APP; import static android.content.pm.ActivityInfo.OVERRIDE_ENABLE_COMPAT_FAKE_FOCUS; import static android.content.pm.ActivityInfo.OVERRIDE_RESPECT_REQUESTED_ORIENTATION; import static android.content.pm.ActivityInfo.OVERRIDE_USE_DISPLAY_LANDSCAPE_NATURAL_ORIENTATION; import static android.content.res.Configuration.ORIENTATION_LANDSCAPE; import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_DISPLAY_ORIENTATION_OVERRIDE; import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_ORIENTATION_OVERRIDE; import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_RESIZEABLE_ACTIVITY_OVERRIDES; import static android.view.WindowManager.PROPERTY_COMPAT_ENABLE_FAKE_FOCUS; import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM; import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME; import android.annotation.NonNull; Loading @@ -39,16 +34,9 @@ import com.android.server.wm.utils.OptPropFactory; */ public class AppCompatOverrides { private static final String TAG = TAG_WITH_CLASS_NAME ? "AppCompatOverrides" : TAG_ATM; @NonNull private final AppCompatConfiguration mAppCompatConfiguration; @NonNull private final ActivityRecord mActivityRecord; @NonNull private final OptPropFactory.OptProp mFakeFocusOptProp; @NonNull private final OptPropFactory.OptProp mAllowOrientationOverrideOptProp; @NonNull Loading @@ -61,26 +49,25 @@ public class AppCompatOverrides { private final AppCompatCameraOverrides mAppCompatCameraOverrides; @NonNull private final AppCompatAspectRatioOverrides mAppCompatAspectRatioOverrides; @NonNull private final AppCompatFocusOverrides mAppCompatFocusOverrides; AppCompatOverrides(@NonNull ActivityRecord activityRecord, @NonNull AppCompatConfiguration appCompatConfiguration, @NonNull OptPropFactory optPropBuilder) { mAppCompatConfiguration = appCompatConfiguration; mActivityRecord = activityRecord; mAppCompatCameraOverrides = new AppCompatCameraOverrides(mActivityRecord, mAppCompatConfiguration, optPropBuilder); appCompatConfiguration, optPropBuilder); mAppCompatOrientationOverrides = new AppCompatOrientationOverrides(mActivityRecord, mAppCompatConfiguration, optPropBuilder, mAppCompatCameraOverrides); appCompatConfiguration, optPropBuilder, mAppCompatCameraOverrides); // TODO(b/341903757) Remove BooleanSuppliers after fixing dependency with reachability. mAppCompatAspectRatioOverrides = new AppCompatAspectRatioOverrides(activityRecord, mAppCompatConfiguration, optPropBuilder, appCompatConfiguration, optPropBuilder, activityRecord.mLetterboxUiController::isDisplayFullScreenAndInPosture, activityRecord.mLetterboxUiController::getHorizontalPositionMultiplier); mFakeFocusOptProp = optPropBuilder.create(PROPERTY_COMPAT_ENABLE_FAKE_FOCUS, mAppCompatConfiguration::isCompatFakeFocusEnabled); mAppCompatFocusOverrides = new AppCompatFocusOverrides(mActivityRecord, appCompatConfiguration, optPropBuilder); mAllowOrientationOverrideOptProp = optPropBuilder.create( PROPERTY_COMPAT_ALLOW_ORIENTATION_OVERRIDE); Loading Loading @@ -114,21 +101,9 @@ public class AppCompatOverrides { return mAppCompatAspectRatioOverrides; } /** * Whether sending compat fake focus for split screen resumed activities is enabled. Needed * because some game engines wait to get focus before drawing the content of the app which isn't * guaranteed by default in multi-window modes. * * <p>This treatment is enabled when the following conditions are met: * <ul> * <li>Flag gating the treatment is enabled * <li>Component property is NOT set to false * <li>Component property is set to true or per-app override is enabled * </ul> */ boolean shouldSendFakeFocus() { return mFakeFocusOptProp.shouldEnableWithOverrideAndProperty( isCompatChangeEnabled(OVERRIDE_ENABLE_COMPAT_FAKE_FOCUS)); @NonNull AppCompatFocusOverrides getAppCompatFocusOverrides() { return mAppCompatFocusOverrides; } boolean isAllowOrientationOverrideOptOut() { Loading services/core/java/com/android/server/wm/AppCompatUtils.java +9 −0 Original line number Diff line number Diff line Loading @@ -73,4 +73,13 @@ class AppCompatUtils { static boolean isInVrUiMode(Configuration config) { return (config.uiMode & UI_MODE_TYPE_MASK) == UI_MODE_TYPE_VR_HEADSET; } /** * @param activityRecord The {@link ActivityRecord} for the app package. * @param overrideChangeId The per-app override identifier. * @return {@code true} if the per-app override is enable for the given activity. */ static boolean isChangeEnabled(@NonNull ActivityRecord activityRecord, long overrideChangeId) { return activityRecord.info.isChangeEnabled(overrideChangeId); } } Loading
services/core/java/com/android/server/wm/ActivityRecord.java +1 −5 Original line number Diff line number Diff line Loading @@ -10890,12 +10890,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A * Whether we should send fake focus when the activity is resumed. This is done because some * game engines wait to get focus before drawing the content of the app. */ // TODO(b/263593361): Explore enabling compat fake focus for freeform. // TODO(b/263592337): Explore enabling compat fake focus for fullscreen, e.g. for when // covered with bubbles. boolean shouldSendCompatFakeFocus() { return mLetterboxUiController.shouldSendFakeFocus() && inMultiWindowMode() && !inPinnedWindowingMode() && !inFreeformWindowingMode(); return mAppCompatController.getAppCompatFocusOverrides().shouldSendFakeFocus(); } boolean canCaptureSnapshot() { Loading
services/core/java/com/android/server/wm/AppCompatController.java +5 −0 Original line number Diff line number Diff line Loading @@ -94,4 +94,9 @@ class AppCompatController { } return null; } @NonNull AppCompatFocusOverrides getAppCompatFocusOverrides() { return mAppCompatOverrides.getAppCompatFocusOverrides(); } }
services/core/java/com/android/server/wm/AppCompatFocusOverrides.java 0 → 100644 +68 −0 Original line number Diff line number Diff line /* * 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 com.android.server.wm; import static android.content.pm.ActivityInfo.OVERRIDE_ENABLE_COMPAT_FAKE_FOCUS; import static android.view.WindowManager.PROPERTY_COMPAT_ENABLE_FAKE_FOCUS; import static com.android.server.wm.AppCompatUtils.isChangeEnabled; import android.annotation.NonNull; import com.android.server.wm.utils.OptPropFactory; /** * Encapsulates app compat focus policy. */ class AppCompatFocusOverrides { @NonNull final ActivityRecord mActivityRecord; @NonNull private final OptPropFactory.OptProp mFakeFocusOptProp; AppCompatFocusOverrides(@NonNull ActivityRecord activityRecord, @NonNull AppCompatConfiguration appCompatConfiguration, @NonNull OptPropFactory optPropBuilder) { mActivityRecord = activityRecord; mFakeFocusOptProp = optPropBuilder.create(PROPERTY_COMPAT_ENABLE_FAKE_FOCUS, appCompatConfiguration::isCompatFakeFocusEnabled); } /** * Whether sending compat fake focus for split screen resumed activities is enabled. Needed * because some game engines wait to get focus before drawing the content of the app which isn't * guaranteed by default in multi-window modes. * * <p>This treatment is enabled when the following conditions are met: * <ul> * <li>Flag gating the treatment is enabled * <li>Component property is NOT set to false * <li>Component property is set to true or per-app override is enabled * </ul> */ boolean shouldSendFakeFocus() { // TODO(b/263593361): Explore enabling compat fake focus for freeform. // TODO(b/263592337): Explore enabling compat fake focus for fullscreen, e.g. for when // covered with bubbles. return mFakeFocusOptProp.shouldEnableWithOverrideAndProperty( isChangeEnabled(mActivityRecord, OVERRIDE_ENABLE_COMPAT_FAKE_FOCUS)) && mActivityRecord.inMultiWindowMode() && !mActivityRecord.inPinnedWindowingMode() && !mActivityRecord.inFreeformWindowingMode(); } }
services/core/java/com/android/server/wm/AppCompatOverrides.java +10 −35 Original line number Diff line number Diff line Loading @@ -18,17 +18,12 @@ package com.android.server.wm; import static android.content.pm.ActivityInfo.FORCE_NON_RESIZE_APP; import static android.content.pm.ActivityInfo.FORCE_RESIZE_APP; import static android.content.pm.ActivityInfo.OVERRIDE_ENABLE_COMPAT_FAKE_FOCUS; import static android.content.pm.ActivityInfo.OVERRIDE_RESPECT_REQUESTED_ORIENTATION; import static android.content.pm.ActivityInfo.OVERRIDE_USE_DISPLAY_LANDSCAPE_NATURAL_ORIENTATION; import static android.content.res.Configuration.ORIENTATION_LANDSCAPE; import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_DISPLAY_ORIENTATION_OVERRIDE; import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_ORIENTATION_OVERRIDE; import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_RESIZEABLE_ACTIVITY_OVERRIDES; import static android.view.WindowManager.PROPERTY_COMPAT_ENABLE_FAKE_FOCUS; import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM; import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME; import android.annotation.NonNull; Loading @@ -39,16 +34,9 @@ import com.android.server.wm.utils.OptPropFactory; */ public class AppCompatOverrides { private static final String TAG = TAG_WITH_CLASS_NAME ? "AppCompatOverrides" : TAG_ATM; @NonNull private final AppCompatConfiguration mAppCompatConfiguration; @NonNull private final ActivityRecord mActivityRecord; @NonNull private final OptPropFactory.OptProp mFakeFocusOptProp; @NonNull private final OptPropFactory.OptProp mAllowOrientationOverrideOptProp; @NonNull Loading @@ -61,26 +49,25 @@ public class AppCompatOverrides { private final AppCompatCameraOverrides mAppCompatCameraOverrides; @NonNull private final AppCompatAspectRatioOverrides mAppCompatAspectRatioOverrides; @NonNull private final AppCompatFocusOverrides mAppCompatFocusOverrides; AppCompatOverrides(@NonNull ActivityRecord activityRecord, @NonNull AppCompatConfiguration appCompatConfiguration, @NonNull OptPropFactory optPropBuilder) { mAppCompatConfiguration = appCompatConfiguration; mActivityRecord = activityRecord; mAppCompatCameraOverrides = new AppCompatCameraOverrides(mActivityRecord, mAppCompatConfiguration, optPropBuilder); appCompatConfiguration, optPropBuilder); mAppCompatOrientationOverrides = new AppCompatOrientationOverrides(mActivityRecord, mAppCompatConfiguration, optPropBuilder, mAppCompatCameraOverrides); appCompatConfiguration, optPropBuilder, mAppCompatCameraOverrides); // TODO(b/341903757) Remove BooleanSuppliers after fixing dependency with reachability. mAppCompatAspectRatioOverrides = new AppCompatAspectRatioOverrides(activityRecord, mAppCompatConfiguration, optPropBuilder, appCompatConfiguration, optPropBuilder, activityRecord.mLetterboxUiController::isDisplayFullScreenAndInPosture, activityRecord.mLetterboxUiController::getHorizontalPositionMultiplier); mFakeFocusOptProp = optPropBuilder.create(PROPERTY_COMPAT_ENABLE_FAKE_FOCUS, mAppCompatConfiguration::isCompatFakeFocusEnabled); mAppCompatFocusOverrides = new AppCompatFocusOverrides(mActivityRecord, appCompatConfiguration, optPropBuilder); mAllowOrientationOverrideOptProp = optPropBuilder.create( PROPERTY_COMPAT_ALLOW_ORIENTATION_OVERRIDE); Loading Loading @@ -114,21 +101,9 @@ public class AppCompatOverrides { return mAppCompatAspectRatioOverrides; } /** * Whether sending compat fake focus for split screen resumed activities is enabled. Needed * because some game engines wait to get focus before drawing the content of the app which isn't * guaranteed by default in multi-window modes. * * <p>This treatment is enabled when the following conditions are met: * <ul> * <li>Flag gating the treatment is enabled * <li>Component property is NOT set to false * <li>Component property is set to true or per-app override is enabled * </ul> */ boolean shouldSendFakeFocus() { return mFakeFocusOptProp.shouldEnableWithOverrideAndProperty( isCompatChangeEnabled(OVERRIDE_ENABLE_COMPAT_FAKE_FOCUS)); @NonNull AppCompatFocusOverrides getAppCompatFocusOverrides() { return mAppCompatFocusOverrides; } boolean isAllowOrientationOverrideOptOut() { Loading
services/core/java/com/android/server/wm/AppCompatUtils.java +9 −0 Original line number Diff line number Diff line Loading @@ -73,4 +73,13 @@ class AppCompatUtils { static boolean isInVrUiMode(Configuration config) { return (config.uiMode & UI_MODE_TYPE_MASK) == UI_MODE_TYPE_VR_HEADSET; } /** * @param activityRecord The {@link ActivityRecord} for the app package. * @param overrideChangeId The per-app override identifier. * @return {@code true} if the per-app override is enable for the given activity. */ static boolean isChangeEnabled(@NonNull ActivityRecord activityRecord, long overrideChangeId) { return activityRecord.info.isChangeEnabled(overrideChangeId); } }