blob: c762f7f4a507e344b52a4a4bca5f8dffb32af592 [file] [log] [blame]
Bryce Leedacefc42017-10-10 12:56:02 -07001/*
2 * Copyright (C) 2017 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
17package com.android.server.am;
18
19import android.annotation.IntDef;
20import android.app.ActivityOptions;
21import android.content.pm.ActivityInfo.WindowLayout;
22import android.graphics.Rect;
23
24import java.lang.annotation.Retention;
25import java.lang.annotation.RetentionPolicy;
26import java.util.ArrayList;
27import java.util.List;
28
29import static com.android.server.am.LaunchingBoundsController.LaunchingBoundsPositioner.RESULT_CONTINUE;
30import static com.android.server.am.LaunchingBoundsController.LaunchingBoundsPositioner.RESULT_DONE;
31import static com.android.server.am.LaunchingBoundsController.LaunchingBoundsPositioner.RESULT_SKIP;
32
33/**
34 * {@link LaunchingBoundsController} calculates the launch bounds by coordinating between registered
35 * {@link LaunchingBoundsPositioner}.
36 */
37class LaunchingBoundsController {
38 private final List<LaunchingBoundsPositioner> mPositioners = new ArrayList<>();
39
40 // Temporary {@link Rect} for calculations. This is kept separate from {@code mTmpCurrent} and
41 // {@code mTmpResult} to prevent clobbering values.
42 private final Rect mTmpRect = new Rect();
43
44 private final Rect mTmpCurrent = new Rect();
45 private final Rect mTmpResult = new Rect();
46
47 /**
48 * Creates a {@link LaunchingBoundsController} with default registered
49 * {@link LaunchingBoundsPositioner}s.
50 */
51 void registerDefaultPositioners(ActivityStackSupervisor supervisor) {
52 // {@link LaunchingTaskPositioner} handles window layout preferences.
53 registerPositioner(new LaunchingTaskPositioner());
54
55 // {@link LaunchingActivityPositioner} is the most specific positioner and thus should be
56 // registered last (applied first) out of the defaults.
57 registerPositioner(new LaunchingActivityPositioner(supervisor));
58 }
59
60 /**
61 * Returns the position calculated by the registered positioners
62 * @param task The {@link TaskRecord} currently being positioned.
63 * @param layout The specified {@link WindowLayout}.
64 * @param activity The {@link ActivityRecord} currently being positioned.
Bryce Leee4ad7452017-10-26 08:44:04 -070065 * @param source The {@link ActivityRecord} from which activity was started from.
Bryce Leedacefc42017-10-10 12:56:02 -070066 * @param options The {@link ActivityOptions} specified for the activity.
67 * @param result The resulting bounds. If no bounds are set, {@link Rect#isEmpty()} will be
Bryce Leee4ad7452017-10-26 08:44:04 -070068 * {@code true}.
Bryce Leedacefc42017-10-10 12:56:02 -070069 */
70 void calculateBounds(TaskRecord task, WindowLayout layout, ActivityRecord activity,
Bryce Leee4ad7452017-10-26 08:44:04 -070071 ActivityRecord source, ActivityOptions options, Rect result) {
Bryce Leedacefc42017-10-10 12:56:02 -070072 result.setEmpty();
73
74 // We start at the last registered {@link LaunchingBoundsPositioner} as this represents
75 // The positioner closest to the product level. Moving back through the list moves closer to
76 // the platform logic.
77 for (int i = mPositioners.size() - 1; i >= 0; --i) {
78 mTmpResult.setEmpty();
79 mTmpCurrent.set(result);
80 final LaunchingBoundsPositioner positioner = mPositioners.get(i);
81
Bryce Leee4ad7452017-10-26 08:44:04 -070082 switch(positioner.onCalculateBounds(task, layout, activity, source, options,
83 mTmpCurrent, mTmpResult)) {
Bryce Leedacefc42017-10-10 12:56:02 -070084 case RESULT_SKIP:
85 // Do not apply any results when we are told to skip
86 continue;
87 case RESULT_DONE:
88 // Set result and return immediately.
89 result.set(mTmpResult);
90 return;
91 case RESULT_CONTINUE:
92 // Set result and continue
93 result.set(mTmpResult);
94 break;
95 }
96 }
97 }
98
99 /**
100 * A convenience method for laying out a task.
101 * @return {@code true} if bounds were set on the task. {@code false} otherwise.
102 */
103 boolean layoutTask(TaskRecord task, WindowLayout layout) {
Bryce Leee4ad7452017-10-26 08:44:04 -0700104 calculateBounds(task, layout, null /*activity*/, null /*source*/, null /*options*/,
105 mTmpRect);
Bryce Leedacefc42017-10-10 12:56:02 -0700106
107 if (mTmpRect.isEmpty()) {
108 return false;
109 }
110
111 task.updateOverrideConfiguration(mTmpRect);
112
113 return true;
114 }
115
116 /**
117 * Adds a positioner to participate in future bounds calculation. Note that the last registered
118 * {@link LaunchingBoundsPositioner} will be the first to calculate the bounds.
119 */
120 void registerPositioner(LaunchingBoundsPositioner positioner) {
121 if (mPositioners.contains(positioner)) {
122 return;
123 }
124
125 mPositioners.add(positioner);
126 }
127
128 /**
129 * An interface implemented by those wanting to participate in bounds calculation.
130 */
131 interface LaunchingBoundsPositioner {
132 @Retention(RetentionPolicy.SOURCE)
133 @IntDef({RESULT_SKIP, RESULT_DONE, RESULT_CONTINUE})
134 @interface Result {}
135
136 // Returned when the positioner does not want to influence the bounds calculation
137 int RESULT_SKIP = 0;
138 // Returned when the positioner has changed the bounds and would like its results to be the
139 // final bounds applied.
140 int RESULT_DONE = 1;
141 // Returned when the positioner has changed the bounds but is okay with other positioners
142 // influencing the bounds.
143 int RESULT_CONTINUE = 2;
144
145 /**
146 * Called when asked to calculate bounds.
147 * @param task The {@link TaskRecord} currently being positioned.
148 * @param layout The specified {@link WindowLayout}.
149 * @param activity The {@link ActivityRecord} currently being positioned.
Bryce Leee4ad7452017-10-26 08:44:04 -0700150 * @param source The {@link ActivityRecord} activity was started from.
Bryce Leedacefc42017-10-10 12:56:02 -0700151 * @param options The {@link ActivityOptions} specified for the activity.
152 * @param current The current bounds. This can differ from the initial bounds as it
153 * represents the modified bounds up to this point.
154 * @param result The {@link Rect} which the positioner should return its modified bounds.
155 * Any merging of the current bounds should be already applied to this
156 * value as well before returning.
Bryce Leee4ad7452017-10-26 08:44:04 -0700157 * @return A {@link Result} representing the result of the bounds calculation.
Bryce Leedacefc42017-10-10 12:56:02 -0700158 */
159 @Result
160 int onCalculateBounds(TaskRecord task, WindowLayout layout, ActivityRecord activity,
Bryce Leee4ad7452017-10-26 08:44:04 -0700161 ActivityRecord source, ActivityOptions options, Rect current, Rect result);
Bryce Leedacefc42017-10-10 12:56:02 -0700162 }
163}