1 /*
2  * Copyright (C) 2022 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 com.android.wm.shell.shared;
18 
19 import android.annotation.NonNull;
20 import android.content.Context;
21 import android.os.SystemProperties;
22 
23 import com.android.internal.R;
24 import com.android.internal.annotations.VisibleForTesting;
25 import com.android.window.flags.Flags;
26 
27 /**
28  * Constants for desktop mode feature
29  */
30 public class DesktopModeStatus {
31 
32     /**
33      * Flag to indicate whether task resizing is veiled.
34      */
35     private static final boolean IS_VEILED_RESIZE_ENABLED = SystemProperties.getBoolean(
36             "persist.wm.debug.desktop_veiled_resizing", true);
37 
38     /**
39      * Flag to indicate is moving task to another display is enabled.
40      */
41     public static final boolean IS_DISPLAY_CHANGE_ENABLED = SystemProperties.getBoolean(
42             "persist.wm.debug.desktop_change_display", false);
43 
44     /**
45      * Flag to indicate whether to apply shadows to windows in desktop mode.
46      */
47     private static final boolean USE_WINDOW_SHADOWS = SystemProperties.getBoolean(
48             "persist.wm.debug.desktop_use_window_shadows", true);
49 
50     /**
51      * Flag to indicate whether to apply shadows to the focused window in desktop mode.
52      *
53      * Note: this flag is only relevant if USE_WINDOW_SHADOWS is false.
54      */
55     private static final boolean USE_WINDOW_SHADOWS_FOCUSED_WINDOW = SystemProperties.getBoolean(
56             "persist.wm.debug.desktop_use_window_shadows_focused_window", false);
57 
58     /**
59      * Flag to indicate whether to use rounded corners for windows in desktop mode.
60      */
61     private static final boolean USE_ROUNDED_CORNERS = SystemProperties.getBoolean(
62             "persist.wm.debug.desktop_use_rounded_corners", true);
63 
64     /**
65      * Flag to indicate whether to restrict desktop mode to supported devices.
66      */
67     private static final boolean ENFORCE_DEVICE_RESTRICTIONS = SystemProperties.getBoolean(
68             "persist.wm.debug.desktop_mode_enforce_device_restrictions", true);
69 
70     /** Whether the desktop density override is enabled. */
71     public static final boolean DESKTOP_DENSITY_OVERRIDE_ENABLED =
72             SystemProperties.getBoolean("persist.wm.debug.desktop_mode_density_enabled", false);
73 
74     /** Override density for tasks when they're inside the desktop. */
75     public static final int DESKTOP_DENSITY_OVERRIDE =
76             SystemProperties.getInt("persist.wm.debug.desktop_mode_density", 284);
77 
78     /** The minimum override density allowed for tasks inside the desktop. */
79     private static final int DESKTOP_DENSITY_MIN = 100;
80 
81     /** The maximum override density allowed for tasks inside the desktop. */
82     private static final int DESKTOP_DENSITY_MAX = 1000;
83 
84     /**
85      * Default value for {@code MAX_TASK_LIMIT}.
86      */
87     @VisibleForTesting
88     public static final int DEFAULT_MAX_TASK_LIMIT = 4;
89 
90     // TODO(b/335131008): add a config-overlay field for the max number of tasks in Desktop Mode
91     /**
92      * Flag declaring the maximum number of Tasks to show in Desktop Mode at any one time.
93      *
94      * <p> The limit does NOT affect Picture-in-Picture, Bubbles, or System Modals (like a screen
95      * recording window, or Bluetooth pairing window).
96      */
97     private static final int MAX_TASK_LIMIT = SystemProperties.getInt(
98             "persist.wm.debug.desktop_max_task_limit", DEFAULT_MAX_TASK_LIMIT);
99 
100     /**
101      * Return {@code true} if desktop windowing is enabled. Only to be used for testing. Callers
102      * should use {@link #canEnterDesktopMode(Context)} to query the state of desktop windowing.
103      */
104     @VisibleForTesting
isEnabled()105     public static boolean isEnabled() {
106         return Flags.enableDesktopWindowingMode();
107     }
108 
109     /**
110      * Return {@code true} if veiled resizing is active. If false, fluid resizing is used.
111      */
isVeiledResizeEnabled()112     public static boolean isVeiledResizeEnabled() {
113         return IS_VEILED_RESIZE_ENABLED;
114     }
115 
116     /**
117      * Return whether to use window shadows.
118      *
119      * @param isFocusedWindow whether the window to apply shadows to is focused
120      */
useWindowShadow(boolean isFocusedWindow)121     public static boolean useWindowShadow(boolean isFocusedWindow) {
122         return USE_WINDOW_SHADOWS
123             || (USE_WINDOW_SHADOWS_FOCUSED_WINDOW && isFocusedWindow);
124     }
125 
126     /**
127      * Return whether to use rounded corners for windows.
128      */
useRoundedCorners()129     public static boolean useRoundedCorners() {
130         return USE_ROUNDED_CORNERS;
131     }
132 
133     /**
134      * Return {@code true} if desktop mode should be restricted to supported devices.
135      */
136     @VisibleForTesting
enforceDeviceRestrictions()137     public static boolean enforceDeviceRestrictions() {
138         return ENFORCE_DEVICE_RESTRICTIONS;
139     }
140 
141     /**
142      * Return the maximum limit on the number of Tasks to show in Desktop Mode at any one time.
143      */
getMaxTaskLimit()144     public static int getMaxTaskLimit() {
145         return MAX_TASK_LIMIT;
146     }
147 
148     /**
149      * Return {@code true} if the current device supports desktop mode.
150      */
151     @VisibleForTesting
isDesktopModeSupported(@onNull Context context)152     public static boolean isDesktopModeSupported(@NonNull Context context) {
153         return context.getResources().getBoolean(R.bool.config_isDesktopModeSupported);
154     }
155 
156     /**
157      * Return {@code true} if desktop mode is enabled and can be entered on the current device.
158      */
canEnterDesktopMode(@onNull Context context)159     public static boolean canEnterDesktopMode(@NonNull Context context) {
160         return (!enforceDeviceRestrictions() || isDesktopModeSupported(context)) && isEnabled();
161     }
162 
163     /**
164      * Return {@code true} if the override desktop density is enabled and valid.
165      */
useDesktopOverrideDensity()166     public static boolean useDesktopOverrideDensity() {
167         return isDesktopDensityOverrideEnabled() && isValidDesktopDensityOverrideSet();
168     }
169 
170     /**
171      * Return {@code true} if the override desktop density is enabled.
172      */
isDesktopDensityOverrideEnabled()173     private static boolean isDesktopDensityOverrideEnabled() {
174         return DESKTOP_DENSITY_OVERRIDE_ENABLED;
175     }
176 
177     /**
178      * Return {@code true} if the override desktop density is set and within a valid range.
179      */
isValidDesktopDensityOverrideSet()180     private static boolean isValidDesktopDensityOverrideSet() {
181         return DESKTOP_DENSITY_OVERRIDE >= DESKTOP_DENSITY_MIN
182                 && DESKTOP_DENSITY_OVERRIDE <= DESKTOP_DENSITY_MAX;
183     }
184 }
185