blob: 51142b1d2eb19843ae45e951a269fa566ddf80ba [file] [log] [blame]
Evan Rosky0037e5f2019-11-05 10:26:24 -08001/*
2 * Copyright (C) 2020 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.wm;
18
19import static android.app.ActivityTaskManager.INVALID_TASK_ID;
20import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
21import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
22import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
23
24import android.app.ActivityManager;
25import android.app.TaskInfo;
26import android.app.WindowConfiguration;
27import android.content.Intent;
28import android.content.pm.ActivityInfo;
29import android.content.pm.ApplicationInfo;
30import android.content.res.Configuration;
31import android.graphics.Rect;
32import android.os.IBinder;
33import android.util.Slog;
Evan Rosky0037e5f2019-11-05 10:26:24 -080034
35import java.util.ArrayList;
36import java.util.Comparator;
Evan Roskyf64f5da2020-03-16 13:47:48 -070037import java.util.function.Consumer;
Evan Rosky0037e5f2019-11-05 10:26:24 -080038
39/**
40 * A Tile. Right now this acts as a proxy for manipulating non-child stacks. Eventually, this
41 * can become an actual parent.
42 */
43// TODO(task-hierarchy): Remove when tasks can nest >2 or when single tasks can handle their
44// own lifecycles.
45public class TaskTile extends ActivityStack {
46 private static final String TAG = "TaskTile";
47 final ArrayList<WindowContainer> mChildren = new ArrayList<>();
48
49 private static ActivityInfo createEmptyActivityInfo() {
50 ActivityInfo info = new ActivityInfo();
51 info.applicationInfo = new ApplicationInfo();
52 return info;
53 }
54
55 TaskTile(ActivityTaskManagerService atmService, int id, int windowingMode) {
56 super(atmService, id, new Intent() /*intent*/, null /*affinityIntent*/, null /*affinity*/,
57 null /*rootAffinity*/, null /*realActivity*/, null /*origActivity*/,
58 false /*rootWasReset*/, false /*autoRemoveRecents*/, false /*askedCompatMode*/,
59 0 /*userId*/, 0 /*effectiveUid*/, null /*lastDescription*/,
60 System.currentTimeMillis(), true /*neverRelinquishIdentity*/,
61 new ActivityManager.TaskDescription(), id, INVALID_TASK_ID, INVALID_TASK_ID,
62 0 /*taskAffiliationColor*/, 0 /*callingUid*/, "" /*callingPackage*/,
Philip P. Moltmannee295092020-02-10 08:46:26 -080063 null /*callingFeatureId*/, RESIZE_MODE_RESIZEABLE,
64 false /*supportsPictureInPicture*/, false /*_realActivitySuspended*/,
65 false /*userSetupComplete*/, INVALID_MIN_SIZE, INVALID_MIN_SIZE,
66 createEmptyActivityInfo(), null /*voiceSession*/, null /*voiceInteractor*/,
67 null /*stack*/);
Evan Rosky0037e5f2019-11-05 10:26:24 -080068 getRequestedOverrideConfiguration().windowConfiguration.setWindowingMode(windowingMode);
69 }
70
71 @Override
72 void onDisplayChanged(DisplayContent dc) {
73 mDisplayContent = null;
74 if (dc != null) {
75 dc.getPendingTransaction().merge(getPendingTransaction());
76 }
77 mDisplayContent = dc;
78 // Virtual parent, so don't notify children.
79 }
80
Evan Roskyaf9f27c2020-02-18 18:58:35 +000081 @Override
82 TaskTile asTile() {
83 return this;
Evan Rosky0037e5f2019-11-05 10:26:24 -080084 }
85
86 @Override
87 protected void addChild(WindowContainer child, Comparator<WindowContainer> comparator) {
88 throw new RuntimeException("Improper use of addChild() on Tile");
89 }
90
91 @Override
92 void addChild(WindowContainer child, int index) {
93 mChildren.add(child);
94 if (child instanceof ActivityStack) {
95 ((ActivityStack) child).setTile(this);
96 }
97 mAtmService.mTaskOrganizerController.dispatchTaskInfoChanged(
98 this, false /* force */);
99 }
100
101 @Override
102 void removeChild(WindowContainer child) {
103 if (child instanceof ActivityStack) {
104 ((ActivityStack) child).setTile(null);
105 }
106 mChildren.remove(child);
107 mAtmService.mTaskOrganizerController.dispatchTaskInfoChanged(
108 this, false /* force */);
109 }
110
111 void removeAllChildren() {
112 for (int i = mChildren.size() - 1; i >= 0; --i) {
113 final WindowContainer child = mChildren.get(i);
114 if (child instanceof ActivityStack) {
115 ((ActivityStack) child).setTile(null);
116 }
117 }
118 mChildren.clear();
119 mAtmService.mTaskOrganizerController.dispatchTaskInfoChanged(
120 this, false /* force */);
121 }
122
123 @Override
124 protected int getChildCount() {
125 // Currently 0 as this isn't a proper hierarchy member yet.
126 return 0;
127 }
128
129 @Override
130 public void setWindowingMode(/*@WindowConfiguration.WindowingMode*/ int windowingMode) {
131 Configuration c = new Configuration(getRequestedOverrideConfiguration());
132 c.windowConfiguration.setWindowingMode(windowingMode);
133 onRequestedOverrideConfigurationChanged(c);
134 }
135
136 @Override
137 public void onConfigurationChanged(Configuration newParentConfig) {
138 super.onConfigurationChanged(newParentConfig);
139 for (int i = mChildren.size() - 1; i >= 0; --i) {
140 final WindowContainer child = mChildren.get(i);
141 child.onConfigurationChanged(child.getParent().getConfiguration());
142 }
143 }
144
Evan Roskyf64f5da2020-03-16 13:47:48 -0700145 void forAllTileActivities(Consumer<ActivityRecord> callback) {
146 for (int i = mChildren.size() - 1; i >= 0; --i) {
147 mChildren.get(i).forAllActivities(callback, true /* traverseTopToBottom */);
148 }
149 }
150
Evan Rosky0037e5f2019-11-05 10:26:24 -0800151 /**
152 * Until this can be part of the hierarchy, the Stack level can use this utility during
153 * resolveOverrideConfig to simulate inheritance.
154 */
155 void updateResolvedConfig(Configuration inOutResolvedConfig) {
156 Rect resolveBounds = inOutResolvedConfig.windowConfiguration.getBounds();
Evan Rosky05ec8862020-02-28 19:37:04 -0800157 if (resolveBounds.isEmpty()) {
Evan Rosky0037e5f2019-11-05 10:26:24 -0800158 resolveBounds.set(getRequestedOverrideBounds());
159 }
160 int stackMode = inOutResolvedConfig.windowConfiguration.getWindowingMode();
161 if (stackMode == WindowConfiguration.WINDOWING_MODE_UNDEFINED
162 || stackMode == WindowConfiguration.WINDOWING_MODE_FULLSCREEN) {
163 // Also replace FULLSCREEN because we interpret FULLSCREEN as "fill parent"
164 inOutResolvedConfig.windowConfiguration.setWindowingMode(
165 getRequestedOverrideWindowingMode());
166 }
167 if (inOutResolvedConfig.smallestScreenWidthDp
168 == Configuration.SMALLEST_SCREEN_WIDTH_DP_UNDEFINED) {
169 inOutResolvedConfig.smallestScreenWidthDp =
170 getRequestedOverrideConfiguration().smallestScreenWidthDp;
171 }
Evan Rosky05ec8862020-02-28 19:37:04 -0800172 if (inOutResolvedConfig.screenWidthDp == Configuration.SCREEN_WIDTH_DP_UNDEFINED) {
173 inOutResolvedConfig.screenWidthDp = getRequestedOverrideConfiguration().screenWidthDp;
174 }
175 if (inOutResolvedConfig.screenHeightDp == Configuration.SCREEN_HEIGHT_DP_UNDEFINED) {
176 inOutResolvedConfig.screenHeightDp = getRequestedOverrideConfiguration().screenHeightDp;
177 }
178 Rect resolveAppBounds = inOutResolvedConfig.windowConfiguration.getAppBounds();
179 if (resolveAppBounds == null || resolveAppBounds.isEmpty()) {
180 inOutResolvedConfig.windowConfiguration.setAppBounds(
181 getRequestedOverrideConfiguration().windowConfiguration.getAppBounds());
182 }
Evan Rosky0037e5f2019-11-05 10:26:24 -0800183 }
184
185 @Override
186 void fillTaskInfo(TaskInfo info) {
187 super.fillTaskInfo(info);
188 WindowContainer top = null;
189 // Check mChildren.isEmpty directly because hasChild() -> getChildCount() always returns 0
190 if (!mChildren.isEmpty()) {
191 // Find the top-most root task which is a virtual child of this Tile. Because this is a
192 // virtual parent, the mChildren order here isn't changed during hierarchy operations.
193 WindowContainer parent = mChildren.get(0).getParent();
194 for (int i = parent.getChildCount() - 1; i >= 0; --i) {
195 if (mChildren.contains(parent.getChildAt(i))) {
196 top = parent.getChildAt(i);
197 break;
198 }
199 }
200 }
201 final Task topTask = top == null ? null : top.getTopMostTask();
202 boolean isResizable = topTask == null || topTask.isResizeable();
203 info.resizeMode = isResizable ? RESIZE_MODE_RESIZEABLE : RESIZE_MODE_UNRESIZEABLE;
204 info.topActivityType = top == null ? ACTIVITY_TYPE_UNDEFINED : top.getActivityType();
Evan Rosky0037e5f2019-11-05 10:26:24 -0800205 }
206
207 @Override
208 void removeImmediately() {
209 removeAllChildren();
210 super.removeImmediately();
211 }
212
Evan Roskyaf9f27c2020-02-18 18:58:35 +0000213 @Override
214 void taskOrganizerDied() {
215 super.taskOrganizerDied();
216 removeImmediately();
217 }
218
Evan Rosky0037e5f2019-11-05 10:26:24 -0800219 static TaskTile forToken(IBinder token) {
220 try {
Wale Ogunwaledec34082020-03-22 09:45:00 -0700221 return (TaskTile) ((RemoteToken) token).getContainer();
Evan Rosky0037e5f2019-11-05 10:26:24 -0800222 } catch (ClassCastException e) {
223 Slog.w(TAG, "Bad tile token: " + token, e);
224 return null;
225 }
226 }
227}