blob: 9e93e1455f2c48fc1449b691c20677430b89830f [file] [log] [blame]
/*
* Copyright (C) 2020 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.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import android.content.res.Resources;
import android.text.TextUtils;
import com.android.server.wm.DisplayContent.TaskContainers;
/**
* Policy that manages DisplayAreas.
*/
public abstract class DisplayAreaPolicy {
protected final WindowManagerService mWmService;
protected final DisplayContent mContent;
/**
* The root DisplayArea. Attach all DisplayAreas to this area (directly or indirectly).
*/
protected final DisplayArea.Root mRoot;
/**
* The IME container. The IME's windows are automatically added to this container.
*/
protected final DisplayArea<? extends WindowContainer> mImeContainer;
/**
* The Tasks container. Tasks etc. are automatically added to this container.
*/
protected final TaskContainers mTaskContainers;
/**
* Construct a new {@link DisplayAreaPolicy}
*
* @param wmService the window manager service instance
* @param content the display content for which the policy applies
* @param root the root display area under which the policy operates
* @param imeContainer the ime container that the policy must attach
* @param taskContainers the task container that the policy must attach
*
* @see #attachDisplayAreas()
*/
protected DisplayAreaPolicy(WindowManagerService wmService,
DisplayContent content, DisplayArea.Root root,
DisplayArea<? extends WindowContainer> imeContainer, TaskContainers taskContainers) {
mWmService = wmService;
mContent = content;
mRoot = root;
mImeContainer = imeContainer;
mTaskContainers = taskContainers;
}
/**
* Called to ask the policy to set up the DisplayArea hierarchy. At a minimum this must:
*
* - attach mImeContainer to mRoot (or one of its descendants)
* - attach mTaskStacks to mRoot (or one of its descendants)
*
* Additionally, this is the right place to set up any other DisplayAreas as desired.
*/
public abstract void attachDisplayAreas();
/**
* Called to ask the policy to attach the given WindowToken to the DisplayArea hierarchy.
*
* This must attach the token to mRoot (or one of its descendants).
*/
public abstract void addWindow(WindowToken token);
/**
* Default policy that has no special features.
*/
public static class Default extends DisplayAreaPolicy {
public Default(WindowManagerService wmService, DisplayContent content,
DisplayArea.Root root,
DisplayArea<? extends WindowContainer> imeContainer,
TaskContainers taskContainers) {
super(wmService, content, root, imeContainer, taskContainers);
}
private final DisplayArea.Tokens mBelow = new DisplayArea.Tokens(mWmService,
DisplayArea.Type.BELOW_TASKS, "BelowTasks");
private final DisplayArea<DisplayArea> mAbove = new DisplayArea<>(mWmService,
DisplayArea.Type.ABOVE_TASKS, "AboveTasks");
private final DisplayArea.Tokens mAboveBelowIme = new DisplayArea.Tokens(mWmService,
DisplayArea.Type.ABOVE_TASKS, "AboveTasksBelowIme");
private final DisplayArea.Tokens mAboveAboveIme = new DisplayArea.Tokens(mWmService,
DisplayArea.Type.ABOVE_TASKS, "AboveTasksAboveIme");
@Override
public void attachDisplayAreas() {
mRoot.addChild(mBelow, 0);
mRoot.addChild(mTaskContainers, 1);
mRoot.addChild(mAbove, 2);
mAbove.addChild(mAboveBelowIme, 0);
mAbove.addChild(mImeContainer, 1);
mAbove.addChild(mAboveAboveIme, 2);
}
@Override
public void addWindow(WindowToken token) {
switch (DisplayArea.Type.typeOf(token)) {
case ABOVE_TASKS:
if (token.getWindowLayerFromType()
< mWmService.mPolicy.getWindowLayerFromTypeLw(TYPE_INPUT_METHOD)) {
mAboveBelowIme.addChild(token);
} else {
mAboveAboveIme.addChild(token);
}
break;
case BELOW_TASKS:
mBelow.addChild(token);
break;
default:
throw new IllegalArgumentException("don't know how to sort " + token);
}
}
/** Provider for {@link DisplayAreaPolicy.Default platform-default display area policy}. */
static class Provider implements DisplayAreaPolicy.Provider {
@Override
public DisplayAreaPolicy instantiate(WindowManagerService wmService,
DisplayContent content, DisplayArea.Root root,
DisplayArea<? extends WindowContainer> imeContainer,
TaskContainers taskContainers) {
return new DisplayAreaPolicy.Default(wmService, content, root, imeContainer,
taskContainers);
}
}
}
/**
* Provider for {@link DisplayAreaPolicy} instances.
*
* By implementing this interface and overriding the
* {@code config_deviceSpecificDisplayAreaPolicyProvider}, a device-specific implementations
* of {@link DisplayAreaPolicy} can be supplied.
*/
public interface Provider {
/**
* Instantiate a new DisplayAreaPolicy.
*
* @see DisplayAreaPolicy#DisplayAreaPolicy
*/
DisplayAreaPolicy instantiate(WindowManagerService wmService,
DisplayContent content, DisplayArea.Root root,
DisplayArea<? extends WindowContainer> imeContainer,
TaskContainers taskContainers);
/**
* Instantiate the device-specific {@link Provider}.
*/
static Provider fromResources(Resources res) {
String name = res.getString(
com.android.internal.R.string.config_deviceSpecificDisplayAreaPolicyProvider);
if (TextUtils.isEmpty(name)) {
return new DisplayAreaPolicy.Default.Provider();
}
try {
return (Provider) Class.forName(name).newInstance();
} catch (ReflectiveOperationException | ClassCastException e) {
throw new IllegalStateException("Couldn't instantiate class " + name
+ " for config_deviceSpecificDisplayAreaPolicyProvider:"
+ " make sure it has a public zero-argument constructor"
+ " and implements DisplayAreaPolicy.Provider", e);
}
}
}
}