blob: 283be401067769bbda52bb517b95b4d7435292c9 [file] [log] [blame]
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.wm;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Slog;
import android.view.ITaskOrganizer;
import android.view.SurfaceControl;
import java.util.ArrayList;
import java.util.HashMap;
/**
* Stores the TaskOrganizers associated with a given windowing mode and
* their associated state.
*/
class TaskOrganizerController {
private static final String TAG = "TaskOrganizerController";
private WindowManagerGlobalLock mGlobalLock;
private class DeathRecipient implements IBinder.DeathRecipient {
int mWindowingMode;
ITaskOrganizer mTaskOrganizer;
DeathRecipient(ITaskOrganizer organizer, int windowingMode) {
mTaskOrganizer = organizer;
mWindowingMode = windowingMode;
}
@Override
public void binderDied() {
synchronized (mGlobalLock) {
final TaskOrganizerState state = mTaskOrganizerStates.get(mTaskOrganizer);
for (int i = 0; i < state.mOrganizedTasks.size(); i++) {
state.mOrganizedTasks.get(i).taskOrganizerDied();
}
mTaskOrganizerStates.remove(mTaskOrganizer);
if (mTaskOrganizersForWindowingMode.get(mWindowingMode) == mTaskOrganizer) {
mTaskOrganizersForWindowingMode.remove(mWindowingMode);
}
}
}
};
class TaskOrganizerState {
ITaskOrganizer mOrganizer;
DeathRecipient mDeathRecipient;
ArrayList<Task> mOrganizedTasks = new ArrayList<>();
void addTask(Task t) {
mOrganizedTasks.add(t);
}
void removeTask(Task t) {
mOrganizedTasks.remove(t);
}
TaskOrganizerState(ITaskOrganizer organizer, DeathRecipient deathRecipient) {
mOrganizer = organizer;
mDeathRecipient = deathRecipient;
}
};
final HashMap<Integer, TaskOrganizerState> mTaskOrganizersForWindowingMode = new HashMap();
final HashMap<ITaskOrganizer, TaskOrganizerState> mTaskOrganizerStates = new HashMap();
final HashMap<Integer, ITaskOrganizer> mTaskOrganizersByPendingSyncId = new HashMap();
final ActivityTaskManagerService mService;
TaskOrganizerController(ActivityTaskManagerService atm, WindowManagerGlobalLock lock) {
mService = atm;
mGlobalLock = lock;
}
private void clearIfNeeded(int windowingMode) {
final TaskOrganizerState oldState = mTaskOrganizersForWindowingMode.get(windowingMode);
if (oldState != null) {
oldState.mOrganizer.asBinder().unlinkToDeath(oldState.mDeathRecipient, 0);
}
}
/**
* Register a TaskOrganizer to manage tasks as they enter the given windowing mode.
* If there was already a TaskOrganizer for this windowing mode it will be evicted
* and receive taskVanished callbacks in the process.
*/
void registerTaskOrganizer(ITaskOrganizer organizer, int windowingMode) {
if (windowingMode != WINDOWING_MODE_PINNED) {
throw new UnsupportedOperationException(
"As of now only Pinned windowing mode is supported for registerTaskOrganizer");
}
clearIfNeeded(windowingMode);
DeathRecipient dr = new DeathRecipient(organizer, windowingMode);
try {
organizer.asBinder().linkToDeath(dr, 0);
} catch (RemoteException e) {
Slog.e(TAG, "TaskOrganizer failed to register death recipient");
}
final TaskOrganizerState state = new TaskOrganizerState(organizer, dr);
mTaskOrganizersForWindowingMode.put(windowingMode, state);
mTaskOrganizerStates.put(organizer, state);
}
ITaskOrganizer getTaskOrganizer(int windowingMode) {
final TaskOrganizerState state = mTaskOrganizersForWindowingMode.get(windowingMode);
if (state == null) {
return null;
}
return state.mOrganizer;
}
private void sendTaskAppeared(ITaskOrganizer organizer, Task task) {
try {
organizer.taskAppeared(task.getRemoteToken(), task.getTaskInfo());
} catch (Exception e) {
Slog.e(TAG, "Exception sending taskAppeared callback" + e);
}
}
private void sendTaskVanished(ITaskOrganizer organizer, Task task) {
try {
organizer.taskVanished(task.getRemoteToken());
} catch (Exception e) {
Slog.e(TAG, "Exception sending taskVanished callback" + e);
}
}
void onTaskAppeared(ITaskOrganizer organizer, Task task) {
TaskOrganizerState state = mTaskOrganizerStates.get(organizer);
state.addTask(task);
sendTaskAppeared(organizer, task);
}
void onTaskVanished(ITaskOrganizer organizer, Task task) {
final TaskOrganizerState state = mTaskOrganizerStates.get(organizer);
sendTaskVanished(organizer, task);
// This could trigger TaskAppeared for other tasks in the same stack so make sure
// we do this AFTER sending taskVanished.
state.removeTask(task);
}
}