• 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 package com.android.wm.shell.shared.split;
17 
18 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
19 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
20 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
21 import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
22 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
23 
24 import android.annotation.IntDef;
25 
26 import com.android.wm.shell.shared.TransitionUtil;
27 
28 /** Helper utility class of methods and constants that are available to be imported in Launcher. */
29 public class SplitScreenConstants {
30     /** Duration used for every split fade-in or fade-out. */
31     public static final int FADE_DURATION = 133;
32     /** Duration where we keep an app veiled to allow it to redraw itself behind the scenes. */
33     public static final int VEIL_DELAY_DURATION = 300;
34 
35     /** Key for passing in widget intents when invoking split from launcher workspace. */
36     public static final String KEY_EXTRA_WIDGET_INTENT = "key_extra_widget_intent";
37 
38     ///////////////
39     // IMPORTANT for the following SPLIT_POSITION and SNAP_TO constants:
40     // These int values must not be changed -- they are persisted to user-defined app pairs, and
41     // will break things if changed.
42     //
43 
44     /**
45      * Split position isn't specified normally meaning to use what ever it is currently set to.
46      */
47     public static final int SPLIT_POSITION_UNDEFINED = -1;
48 
49     /**
50      * Specifies that a split is positioned at the top half of the screen if
51      * in portrait mode or at the left half of the screen if in landscape mode.
52      */
53     public static final int SPLIT_POSITION_TOP_OR_LEFT = 0;
54 
55     /**
56      * Specifies that a split is positioned at the bottom half of the screen if
57      * in portrait mode or at the right half of the screen if in landscape mode.
58      */
59     public static final int SPLIT_POSITION_BOTTOM_OR_RIGHT = 1;
60 
61     /**
62      * Deprecated and will be replaced fully by @SplitIndex. With support for 3+ apps in split,
63      * existing references to top/left and bottom/right will be replaced by INDEX_0 and INDEX_1
64      * respectively. For now they can be used interchangeably, the underlying ints are the same.
65      */
66     @IntDef(prefix = {"SPLIT_POSITION_"}, value = {
67             SPLIT_POSITION_UNDEFINED,
68             SPLIT_POSITION_TOP_OR_LEFT,
69             SPLIT_POSITION_BOTTOM_OR_RIGHT,
70     })
71     public @interface SplitPosition {
72     }
73 
74     // These SPLIT_INDEX constants will be used in the same way as the above SPLIT_POSITION ints,
75     // but scalable to n apps. Eventually, SPLIT_POSITION can be deprecated and only the below
76     // will be used.
77     public static final int SPLIT_INDEX_UNDEFINED = -1;
78     public static final int SPLIT_INDEX_0 = 0;
79     public static final int SPLIT_INDEX_1 = 1;
80     public static final int SPLIT_INDEX_2 = 2;
81     public static final int SPLIT_INDEX_3 = 3;
82 
83     @IntDef(prefix = {"SPLIT_INDEX_"}, value = {
84             SPLIT_INDEX_UNDEFINED,
85             SPLIT_INDEX_0,
86             SPLIT_INDEX_1,
87             SPLIT_INDEX_2,
88             SPLIT_INDEX_3
89     })
90     public @interface SplitIndex {
91     }
92 
93     /**
94      * Return the @SplitIndex constant for a given integer index. @SplitIndex is the replacement
95      * for @SplitPosition, and will be used interchangeably with @SplitPosition to support 3+ apps
96      * in split.
97      */
getIndex(int i)98     public static int getIndex(int i) {
99         return switch (i) {
100             case 0 -> SPLIT_INDEX_0;
101             case 1 -> SPLIT_INDEX_1;
102             case 2 -> SPLIT_INDEX_2;
103             case 3 -> SPLIT_INDEX_3;
104             default -> SPLIT_INDEX_UNDEFINED;
105         };
106     }
107 
108     /** Signifies that user is currently not in split screen. */
109     public static final int NOT_IN_SPLIT = -1;
110 
111     /**
112      * A snap target for two apps, where the split is 33-66. With FLAG_ENABLE_FLEXIBLE_SPLIT,
113      * only used on tablets.
114      */
115     public static final int SNAP_TO_2_33_66 = 0;
116 
117     /** A snap target for two apps, where the split is 50-50.  */
118     public static final int SNAP_TO_2_50_50 = 1;
119 
120     /**
121      * A snap target for two apps, where the split is 66-33. With FLAG_ENABLE_FLEXIBLE_SPLIT,
122      * only used on tablets.
123      */
124     public static final int SNAP_TO_2_66_33 = 2;
125 
126     /**
127      * A snap target for two apps, where the split is 90-10. The "10" app extends off the screen,
128      * and is actually the same size as the onscreen app, but the visible portion takes up 10% of
129      * the screen. With FLAG_ENABLE_FLEXIBLE_SPLIT, used on phones and foldables.
130      */
131     public static final int SNAP_TO_2_90_10 = 3;
132 
133     /**
134      * A snap target for two apps, where the split is 10-90. The "10" app extends off the screen,
135      * and is actually the same size as the onscreen app, but the visible portion takes up 10% of
136      * the screen. With FLAG_ENABLE_FLEXIBLE_SPLIT, used on phones and foldables.
137      */
138     public static final int SNAP_TO_2_10_90 = 4;
139 
140     /**
141      * A snap target for three apps, where the split is 33-33-33. With FLAG_ENABLE_FLEXIBLE_SPLIT,
142      * only used on tablets.
143      */
144     public static final int SNAP_TO_3_33_33_33 = 5;
145 
146     /**
147      * A snap target for three apps, where the split is 45-45-10. The "10" app extends off the
148      * screen, and is actually the same size as the onscreen apps, but the visible portion takes
149      * up 10% of the screen. With FLAG_ENABLE_FLEXIBLE_SPLIT, only used on unfolded foldables.
150      */
151     public static final int SNAP_TO_3_45_45_10 = 6;
152 
153     /**
154      * A snap target for three apps, where the split is 10-45-45. The "10" app extends off the
155      * screen, and is actually the same size as the onscreen apps, but the visible portion takes
156      * up 10% of the screen. With FLAG_ENABLE_FLEXIBLE_SPLIT, only used on unfolded foldables.
157      */
158     public static final int SNAP_TO_3_10_45_45 = 7;
159 
160     /**
161      * These snap targets are used for split pairs in a stable, non-transient state. They may be
162      * persisted in Launcher when the user saves an app pair. They are a subset of
163      * {@link SnapPosition}.
164      */
165     @IntDef(prefix = { "SNAP_TO_" }, value = {
166             SNAP_TO_2_33_66,
167             SNAP_TO_2_50_50,
168             SNAP_TO_2_66_33,
169             SNAP_TO_2_90_10,
170             SNAP_TO_2_10_90,
171             SNAP_TO_3_33_33_33,
172             SNAP_TO_3_45_45_10,
173             SNAP_TO_3_10_45_45,
174     })
175     public @interface PersistentSnapPosition {}
176 
177     /**
178      * These are all the valid "states" that split screen can be in. It's the set of
179      * {@link PersistentSnapPosition} + {@link #NOT_IN_SPLIT}.
180      */
181     @IntDef(value = {
182             NOT_IN_SPLIT, // user is not in split screen
183             SNAP_TO_NONE, // in "free snap mode," where apps are fully resizable
184             SNAP_TO_2_33_66,
185             SNAP_TO_2_50_50,
186             SNAP_TO_2_66_33,
187             SNAP_TO_2_90_10,
188             SNAP_TO_2_10_90,
189             SNAP_TO_3_33_33_33,
190             SNAP_TO_3_45_45_10,
191             SNAP_TO_3_10_45_45,
192     })
193     public @interface SplitScreenState {}
194 
195     /** Converts a {@link SplitScreenState} to a human-readable string. */
stateToString(@plitScreenState int state)196     public static String stateToString(@SplitScreenState int state) {
197         return switch (state) {
198             case NOT_IN_SPLIT -> "NOT_IN_SPLIT";
199             case SNAP_TO_NONE -> "SNAP_TO_NONE";
200             case SNAP_TO_2_33_66 -> "SNAP_TO_2_33_66";
201             case SNAP_TO_2_50_50 -> "SNAP_TO_2_50_50";
202             case SNAP_TO_2_66_33 -> "SNAP_TO_2_66_33";
203             case SNAP_TO_2_90_10 -> "SNAP_TO_2_90_10";
204             case SNAP_TO_2_10_90 -> "SNAP_TO_2_10_90";
205             case SNAP_TO_3_33_33_33 -> "SNAP_TO_3_33_33_33";
206             case SNAP_TO_3_45_45_10 -> "SNAP_TO_3_45_45_10";
207             case SNAP_TO_3_10_45_45 -> "SNAP_TO_3_10_45_45";
208             default -> "UNKNOWN";
209         };
210     }
211 
212     /**
213      * Checks if the snapPosition in question is a {@link PersistentSnapPosition}.
214      */
215     public static boolean isPersistentSnapPosition(@SnapPosition int snapPosition) {
216         return snapPosition == SNAP_TO_2_33_66
217                 || snapPosition == SNAP_TO_2_50_50
218                 || snapPosition == SNAP_TO_2_66_33
219                 || snapPosition == SNAP_TO_2_90_10
220                 || snapPosition == SNAP_TO_2_10_90
221                 || snapPosition == SNAP_TO_3_33_33_33
222                 || snapPosition == SNAP_TO_3_45_45_10
223                 || snapPosition == SNAP_TO_3_10_45_45;
224     }
225 
226     /** The divider doesn't snap to any target and is freely placeable. */
227     public static final int SNAP_TO_NONE = 10;
228 
229     /** If the divider reaches this value, the left/top task should be dismissed. */
230     public static final int SNAP_TO_START_AND_DISMISS = 11;
231 
232     /** If the divider reaches this value, the right/bottom task should be dismissed. */
233     public static final int SNAP_TO_END_AND_DISMISS = 12;
234 
235     /** A snap target positioned near the screen edge for a minimized task */
236     public static final int SNAP_TO_MINIMIZE = 13;
237 
238     @IntDef(prefix = { "SNAP_TO_" }, value = {
239             SNAP_TO_2_33_66,
240             SNAP_TO_2_50_50,
241             SNAP_TO_2_66_33,
242             SNAP_TO_2_90_10,
243             SNAP_TO_2_10_90,
244             SNAP_TO_3_33_33_33,
245             SNAP_TO_3_45_45_10,
246             SNAP_TO_3_10_45_45,
247             SNAP_TO_NONE,
248             SNAP_TO_START_AND_DISMISS,
249             SNAP_TO_END_AND_DISMISS,
250             SNAP_TO_MINIMIZE,
251     })
252     public @interface SnapPosition {}
253 
254     ///////////////
255 
256     public static final int[] CONTROLLED_ACTIVITY_TYPES = {ACTIVITY_TYPE_STANDARD};
257     public static final int[] CONTROLLED_WINDOWING_MODES =
258             {WINDOWING_MODE_FULLSCREEN, WINDOWING_MODE_UNDEFINED};
259     public static final int[] CONTROLLED_WINDOWING_MODES_WHEN_ACTIVE =
260             {WINDOWING_MODE_FULLSCREEN, WINDOWING_MODE_UNDEFINED, WINDOWING_MODE_MULTI_WINDOW,
261             WINDOWING_MODE_FREEFORM};
262 
263     /** Flag applied to a transition change to identify it as a divider bar for animation. */
264     public static final int FLAG_IS_DIVIDER_BAR = TransitionUtil.FLAG_IS_DIVIDER_BAR;
265     public static final int FLAG_IS_DIM_LAYER = TransitionUtil.FLAG_IS_DIM_LAYER;
266 
267     public static final String splitPositionToString(@SplitPosition int pos) {
268         switch (pos) {
269             case SPLIT_POSITION_UNDEFINED:
270                 return "SPLIT_POSITION_UNDEFINED";
271             case SPLIT_POSITION_TOP_OR_LEFT:
272                 return "SPLIT_POSITION_TOP_OR_LEFT";
273             case SPLIT_POSITION_BOTTOM_OR_RIGHT:
274                 return "SPLIT_POSITION_BOTTOM_OR_RIGHT";
275             default:
276                 return "UNKNOWN";
277         }
278     }
279 }
280