blob: 66c65e226bce250f41f8a9a0d7cf96afd0a1e8c5 [file] [log] [blame]
Robert Carr8a2f9132019-11-11 15:03:15 -08001/*
2 * Copyright (C) 2019 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.WindowConfiguration.WINDOWING_MODE_PINNED;
Robert Carr00c0dbe2020-01-24 15:30:24 -080020import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
Robert Carr8a2f9132019-11-11 15:03:15 -080021
22import android.os.IBinder;
23import android.os.RemoteException;
24import android.util.Slog;
25import android.view.ITaskOrganizer;
26import android.view.SurfaceControl;
27
28import java.util.ArrayList;
29import java.util.HashMap;
30
31/**
32 * Stores the TaskOrganizers associated with a given windowing mode and
33 * their associated state.
34 */
35class TaskOrganizerController {
36 private static final String TAG = "TaskOrganizerController";
37
38 private WindowManagerGlobalLock mGlobalLock;
39
40 private class DeathRecipient implements IBinder.DeathRecipient {
41 int mWindowingMode;
42 ITaskOrganizer mTaskOrganizer;
43
44 DeathRecipient(ITaskOrganizer organizer, int windowingMode) {
45 mTaskOrganizer = organizer;
46 mWindowingMode = windowingMode;
47 }
48
49 @Override
50 public void binderDied() {
51 synchronized (mGlobalLock) {
52 final TaskOrganizerState state = mTaskOrganizerStates.get(mTaskOrganizer);
53 for (int i = 0; i < state.mOrganizedTasks.size(); i++) {
54 state.mOrganizedTasks.get(i).taskOrganizerDied();
55 }
56 mTaskOrganizerStates.remove(mTaskOrganizer);
57 if (mTaskOrganizersForWindowingMode.get(mWindowingMode) == mTaskOrganizer) {
58 mTaskOrganizersForWindowingMode.remove(mWindowingMode);
59 }
60 }
61 }
62 };
63
64 class TaskOrganizerState {
65 ITaskOrganizer mOrganizer;
66 DeathRecipient mDeathRecipient;
67
68 ArrayList<Task> mOrganizedTasks = new ArrayList<>();
69
70 void addTask(Task t) {
71 mOrganizedTasks.add(t);
72 }
73
74 void removeTask(Task t) {
75 mOrganizedTasks.remove(t);
76 }
77
78 TaskOrganizerState(ITaskOrganizer organizer, DeathRecipient deathRecipient) {
79 mOrganizer = organizer;
80 mDeathRecipient = deathRecipient;
81 }
82 };
83
84
85 final HashMap<Integer, TaskOrganizerState> mTaskOrganizersForWindowingMode = new HashMap();
86 final HashMap<ITaskOrganizer, TaskOrganizerState> mTaskOrganizerStates = new HashMap();
87
88 final HashMap<Integer, ITaskOrganizer> mTaskOrganizersByPendingSyncId = new HashMap();
89
90 final ActivityTaskManagerService mService;
91
92 TaskOrganizerController(ActivityTaskManagerService atm, WindowManagerGlobalLock lock) {
93 mService = atm;
94 mGlobalLock = lock;
95 }
96
97 private void clearIfNeeded(int windowingMode) {
98 final TaskOrganizerState oldState = mTaskOrganizersForWindowingMode.get(windowingMode);
99 if (oldState != null) {
100 oldState.mOrganizer.asBinder().unlinkToDeath(oldState.mDeathRecipient, 0);
101 }
102 }
103
104 /**
105 * Register a TaskOrganizer to manage tasks as they enter the given windowing mode.
106 * If there was already a TaskOrganizer for this windowing mode it will be evicted
107 * and receive taskVanished callbacks in the process.
108 */
109 void registerTaskOrganizer(ITaskOrganizer organizer, int windowingMode) {
Robert Carr00c0dbe2020-01-24 15:30:24 -0800110 if (windowingMode != WINDOWING_MODE_PINNED &&
111 windowingMode != WINDOWING_MODE_MULTI_WINDOW) {
Robert Carr8a2f9132019-11-11 15:03:15 -0800112 throw new UnsupportedOperationException(
Robert Carr00c0dbe2020-01-24 15:30:24 -0800113 "As of now only Pinned and Multiwindow windowing modes are"
114 + " supported for registerTaskOrganizer");
Robert Carr8a2f9132019-11-11 15:03:15 -0800115
116 }
117 clearIfNeeded(windowingMode);
118 DeathRecipient dr = new DeathRecipient(organizer, windowingMode);
119 try {
120 organizer.asBinder().linkToDeath(dr, 0);
121 } catch (RemoteException e) {
122 Slog.e(TAG, "TaskOrganizer failed to register death recipient");
123 }
124
125 final TaskOrganizerState state = new TaskOrganizerState(organizer, dr);
126 mTaskOrganizersForWindowingMode.put(windowingMode, state);
127
128 mTaskOrganizerStates.put(organizer, state);
129 }
130
131 ITaskOrganizer getTaskOrganizer(int windowingMode) {
132 final TaskOrganizerState state = mTaskOrganizersForWindowingMode.get(windowingMode);
133 if (state == null) {
134 return null;
135 }
136 return state.mOrganizer;
137 }
138
139 private void sendTaskAppeared(ITaskOrganizer organizer, Task task) {
140 try {
141 organizer.taskAppeared(task.getRemoteToken(), task.getTaskInfo());
142 } catch (Exception e) {
143 Slog.e(TAG, "Exception sending taskAppeared callback" + e);
144 }
145 }
146
147 private void sendTaskVanished(ITaskOrganizer organizer, Task task) {
148 try {
149 organizer.taskVanished(task.getRemoteToken());
150 } catch (Exception e) {
151 Slog.e(TAG, "Exception sending taskVanished callback" + e);
152 }
153 }
154
155 void onTaskAppeared(ITaskOrganizer organizer, Task task) {
156 TaskOrganizerState state = mTaskOrganizerStates.get(organizer);
157
158 state.addTask(task);
159 sendTaskAppeared(organizer, task);
160 }
161
162 void onTaskVanished(ITaskOrganizer organizer, Task task) {
163 final TaskOrganizerState state = mTaskOrganizerStates.get(organizer);
164 sendTaskVanished(organizer, task);
165
166 // This could trigger TaskAppeared for other tasks in the same stack so make sure
167 // we do this AFTER sending taskVanished.
168 state.removeTask(task);
169 }
170}