blob: 8345ba657c2d3c80df8fbe4f0bc96e0740b023cf [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.
65 * @param options The {@link ActivityOptions} specified for the activity.
66 * @param result The resulting bounds. If no bounds are set, {@link Rect#isEmpty()} will be
67 * true.
68 */
69 void calculateBounds(TaskRecord task, WindowLayout layout, ActivityRecord activity,
70 ActivityOptions options, Rect result) {
71 result.setEmpty();
72
73 // We start at the last registered {@link LaunchingBoundsPositioner} as this represents
74 // The positioner closest to the product level. Moving back through the list moves closer to
75 // the platform logic.
76 for (int i = mPositioners.size() - 1; i >= 0; --i) {
77 mTmpResult.setEmpty();
78 mTmpCurrent.set(result);
79 final LaunchingBoundsPositioner positioner = mPositioners.get(i);
80
81 switch(positioner.onCalculateBounds(task, layout, activity, options, mTmpCurrent,
82 mTmpResult)) {
83 case RESULT_SKIP:
84 // Do not apply any results when we are told to skip
85 continue;
86 case RESULT_DONE:
87 // Set result and return immediately.
88 result.set(mTmpResult);
89 return;
90 case RESULT_CONTINUE:
91 // Set result and continue
92 result.set(mTmpResult);
93 break;
94 }
95 }
96 }
97
98 /**
99 * A convenience method for laying out a task.
100 * @return {@code true} if bounds were set on the task. {@code false} otherwise.
101 */
102 boolean layoutTask(TaskRecord task, WindowLayout layout) {
103 calculateBounds(task, layout, null /*activity*/, null /*options*/, mTmpRect);
104
105 if (mTmpRect.isEmpty()) {
106 return false;
107 }
108
109 task.updateOverrideConfiguration(mTmpRect);
110
111 return true;
112 }
113
114 /**
115 * Adds a positioner to participate in future bounds calculation. Note that the last registered
116 * {@link LaunchingBoundsPositioner} will be the first to calculate the bounds.
117 */
118 void registerPositioner(LaunchingBoundsPositioner positioner) {
119 if (mPositioners.contains(positioner)) {
120 return;
121 }
122
123 mPositioners.add(positioner);
124 }
125
126 /**
127 * An interface implemented by those wanting to participate in bounds calculation.
128 */
129 interface LaunchingBoundsPositioner {
130 @Retention(RetentionPolicy.SOURCE)
131 @IntDef({RESULT_SKIP, RESULT_DONE, RESULT_CONTINUE})
132 @interface Result {}
133
134 // Returned when the positioner does not want to influence the bounds calculation
135 int RESULT_SKIP = 0;
136 // Returned when the positioner has changed the bounds and would like its results to be the
137 // final bounds applied.
138 int RESULT_DONE = 1;
139 // Returned when the positioner has changed the bounds but is okay with other positioners
140 // influencing the bounds.
141 int RESULT_CONTINUE = 2;
142
143 /**
144 * Called when asked to calculate bounds.
145 * @param task The {@link TaskRecord} currently being positioned.
146 * @param layout The specified {@link WindowLayout}.
147 * @param activity The {@link ActivityRecord} currently being positioned.
148 * @param options The {@link ActivityOptions} specified for the activity.
149 * @param current The current bounds. This can differ from the initial bounds as it
150 * represents the modified bounds up to this point.
151 * @param result The {@link Rect} which the positioner should return its modified bounds.
152 * Any merging of the current bounds should be already applied to this
153 * value as well before returning.
154 * @return A {@link Result} representing the result of the bounds calculation.
155 */
156 @Result
157 int onCalculateBounds(TaskRecord task, WindowLayout layout, ActivityRecord activity,
158 ActivityOptions options, Rect current, Rect result);
159 }
160}