• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 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.window;
18 
19 import android.annotation.Nullable;
20 import android.os.SystemProperties;
21 import android.util.Log;
22 
23 import com.android.window.flags.Flags;
24 
25 import java.util.function.BooleanSupplier;
26 
27 /**
28  * Checks Desktop Experience flag state.
29  *
30  * <p>This enum provides a centralized way to control the behavior of flags related to desktop
31  * experience features which are aiming for developer preview before their release. It allows
32  * developer option to override the default behavior of these flags.
33  *
34  * <p>The flags here will be controlled by the {@code
35  * persist.wm.debug.desktop_experience_devopts} system property.
36  *
37  * <p>NOTE: Flags should only be added to this enum when they have received Product and UX alignment
38  * that the feature is ready for developer preview, otherwise just do a flag check.
39  *
40  * @hide
41  */
42 public enum DesktopExperienceFlags {
43     // go/keep-sorted start
44     ACTIVITY_EMBEDDING_SUPPORT_FOR_CONNECTED_DISPLAYS(
45             Flags::activityEmbeddingSupportForConnectedDisplays, false),
46     BASE_DENSITY_FOR_EXTERNAL_DISPLAYS(
47             com.android.server.display.feature.flags.Flags::baseDensityForExternalDisplays, true),
48     CONNECTED_DISPLAYS_CURSOR(com.android.input.flags.Flags::connectedDisplaysCursor, true),
49     DISPLAY_TOPOLOGY(com.android.server.display.feature.flags.Flags::displayTopology, true),
50     ENABLE_BUG_FIXES_FOR_SECONDARY_DISPLAY(Flags::enableBugFixesForSecondaryDisplay, true),
51     ENABLE_CONNECTED_DISPLAYS_DND(Flags::enableConnectedDisplaysDnd, false),
52     ENABLE_CONNECTED_DISPLAYS_PIP(Flags::enableConnectedDisplaysPip, false),
53     ENABLE_CONNECTED_DISPLAYS_WALLPAPER(
54             android.app.Flags::enableConnectedDisplaysWallpaper, false),
55     ENABLE_CONNECTED_DISPLAYS_WINDOW_DRAG(Flags::enableConnectedDisplaysWindowDrag, true),
56     ENABLE_DISPLAY_CONTENT_MODE_MANAGEMENT(
57             com.android.server.display.feature.flags.Flags::enableDisplayContentModeManagement,
58             true),
59     ENABLE_DISPLAY_DISCONNECT_INTERACTION(Flags::enableDisplayDisconnectInteraction, false),
60     ENABLE_DISPLAY_FOCUS_IN_SHELL_TRANSITIONS(Flags::enableDisplayFocusInShellTransitions, true),
61     ENABLE_DISPLAY_RECONNECT_INTERACTION(Flags::enableDisplayReconnectInteraction, false),
62     ENABLE_DISPLAY_WINDOWING_MODE_SWITCHING(Flags::enableDisplayWindowingModeSwitching, true),
63     ENABLE_DRAG_TO_MAXIMIZE(Flags::enableDragToMaximize, true),
64     ENABLE_DYNAMIC_RADIUS_COMPUTATION_BUGFIX(Flags::enableDynamicRadiusComputationBugfix, false),
65     ENABLE_KEYBOARD_SHORTCUTS_TO_SWITCH_DESKS(Flags::keyboardShortcutsToSwitchDesks, false),
66     ENABLE_MOVE_TO_NEXT_DISPLAY_SHORTCUT(Flags::enableMoveToNextDisplayShortcut, true),
67     ENABLE_MULTIDISPLAY_TRACKPAD_BACK_GESTURE(Flags::enableMultidisplayTrackpadBackGesture, false),
68     ENABLE_MULTIPLE_DESKTOPS_BACKEND(Flags::enableMultipleDesktopsBackend, false),
69     ENABLE_MULTIPLE_DESKTOPS_FRONTEND(Flags::enableMultipleDesktopsFrontend, false),
70     ENABLE_PERSISTING_DISPLAY_SIZE_FOR_CONNECTED_DISPLAYS(
71             Flags::enablePersistingDisplaySizeForConnectedDisplays, false),
72     ENABLE_PER_DISPLAY_DESKTOP_WALLPAPER_ACTIVITY(Flags::enablePerDisplayDesktopWallpaperActivity,
73             false),
74     ENABLE_PER_DISPLAY_PACKAGE_CONTEXT_CACHE_IN_STATUSBAR_NOTIF(
75             Flags::enablePerDisplayPackageContextCacheInStatusbarNotif, false),
76     ENABLE_PROJECTED_DISPLAY_DESKTOP_MODE(Flags::enableProjectedDisplayDesktopMode, false),
77     ENABLE_TASKBAR_CONNECTED_DISPLAYS(Flags::enableTaskbarConnectedDisplays, true),
78     ENTER_DESKTOP_BY_DEFAULT_ON_FREEFORM_DISPLAYS(Flags::enterDesktopByDefaultOnFreeformDisplays,
79             true),
80     FORM_FACTOR_BASED_DESKTOP_FIRST_SWITCH(Flags::formFactorBasedDesktopFirstSwitch, false),
81     REPARENT_WINDOW_TOKEN_API(Flags::reparentWindowTokenApi, true)
82     // go/keep-sorted end
83     ;
84 
85     /**
86      * Flag class, to be used in case the enum cannot be used because the flag is not accessible.
87      *
88      * <p>This class will still use the process-wide cache.
89      */
90     public static class DesktopExperienceFlag {
91         // Function called to obtain aconfig flag value.
92         private final BooleanSupplier mFlagFunction;
93         // Whether the flag state should be affected by developer option.
94         private final boolean mShouldOverrideByDevOption;
95 
DesktopExperienceFlag(BooleanSupplier flagFunction, boolean shouldOverrideByDevOption)96         public DesktopExperienceFlag(BooleanSupplier flagFunction,
97                 boolean shouldOverrideByDevOption) {
98             this.mFlagFunction = flagFunction;
99             this.mShouldOverrideByDevOption = shouldOverrideByDevOption;
100         }
101 
102         /**
103          * Determines state of flag based on the actual flag and desktop experience developer option
104          * overrides.
105          */
isTrue()106         public boolean isTrue() {
107             return isFlagTrue(mFlagFunction, mShouldOverrideByDevOption);
108         }
109     }
110 
111     private static final String TAG = "DesktopExperienceFlags";
112     // Function called to obtain aconfig flag value.
113     private final BooleanSupplier mFlagFunction;
114     // Whether the flag state should be affected by developer option.
115     private final boolean mShouldOverrideByDevOption;
116 
117     // Local cache for toggle override, which is initialized once on its first access. It needs to
118     // be refreshed only on reboots as overridden state is expected to take effect on reboots.
119     @Nullable
120     private static Boolean sCachedToggleOverride;
121 
122     public static final String SYSTEM_PROPERTY_NAME = "persist.wm.debug.desktop_experience_devopts";
123 
DesktopExperienceFlags(BooleanSupplier flagFunction, boolean shouldOverrideByDevOption)124     DesktopExperienceFlags(BooleanSupplier flagFunction, boolean shouldOverrideByDevOption) {
125         this.mFlagFunction = flagFunction;
126         this.mShouldOverrideByDevOption = shouldOverrideByDevOption;
127     }
128 
129     /**
130      * Determines state of flag based on the actual flag and desktop experience developer option
131      * overrides.
132      */
isTrue()133     public boolean isTrue() {
134         return isFlagTrue(mFlagFunction, mShouldOverrideByDevOption);
135     }
136 
isFlagTrue( BooleanSupplier flagFunction, boolean shouldOverrideByDevOption)137     private static boolean isFlagTrue(
138             BooleanSupplier flagFunction, boolean shouldOverrideByDevOption) {
139         if (shouldOverrideByDevOption
140                 && Flags.showDesktopExperienceDevOption()
141                 && getToggleOverride()) {
142             return true;
143         }
144         return flagFunction.getAsBoolean();
145     }
146 
getToggleOverride()147     private static boolean getToggleOverride() {
148         // If cached, return it
149         if (sCachedToggleOverride != null) {
150             return sCachedToggleOverride;
151         }
152 
153         // Otherwise, fetch and cache it
154         boolean override = getToggleOverrideFromSystem();
155         sCachedToggleOverride = override;
156         Log.d(TAG, "Toggle override initialized to: " + override);
157         return override;
158     }
159 
160     /** Returns the {@link ToggleOverride} from the system property.. */
getToggleOverrideFromSystem()161     private static boolean getToggleOverrideFromSystem() {
162         return SystemProperties.getBoolean(SYSTEM_PROPERTY_NAME, false);
163     }
164 }
165