blob: 2fb98690f661e28ada3a72f5a7bc91eb0c1f7d93 [file] [log] [blame]
/*
* Copyright (C) 2022 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 android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.WindowConfiguration;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.os.Process;
import android.os.UserHandle;
import android.util.ArraySet;
import android.util.Slog;
import android.window.DisplayWindowPolicyController;
import java.io.PrintWriter;
import java.util.List;
class DisplayWindowPolicyControllerHelper {
private static final String TAG = "DisplayWindowPolicyControllerHelper";
private final DisplayContent mDisplayContent;
/**
* The policy controller of the windows that can be displayed on the virtual display.
*
* @see DisplayWindowPolicyController
*/
@Nullable
private DisplayWindowPolicyController mDisplayWindowPolicyController;
/**
* The top non-finishing activity of this display.
*/
private ActivityRecord mTopRunningActivity = null;
/**
* All the uids of non-finishing activity on this display.
* @see DisplayWindowPolicyController#onRunningAppsChanged(ArraySet)
*/
private ArraySet<Integer> mRunningUid = new ArraySet<>();
DisplayWindowPolicyControllerHelper(DisplayContent displayContent) {
mDisplayContent = displayContent;
mDisplayWindowPolicyController = mDisplayContent.mWmService.mDisplayManagerInternal
.getDisplayWindowPolicyController(mDisplayContent.mDisplayId);
}
/**
* Return {@code true} if there is DisplayWindowPolicyController.
*/
public boolean hasController() {
return mDisplayWindowPolicyController != null;
}
/**
* @see DisplayWindowPolicyController#canContainActivities(List, int)
*/
public boolean canContainActivities(@NonNull List<ActivityInfo> activities,
@WindowConfiguration.WindowingMode int windowingMode) {
if (mDisplayWindowPolicyController == null) {
for (int i = activities.size() - 1; i >= 0; i--) {
final ActivityInfo aInfo = activities.get(i);
if (aInfo.requiredDisplayCategory != null) {
Slog.e(TAG,
String.format("Activity with requiredDisplayCategory='%s' cannot be"
+ " displayed on display %d because that display does"
+ " not have a matching category",
aInfo.requiredDisplayCategory, mDisplayContent.mDisplayId));
return false;
}
}
return true;
}
return mDisplayWindowPolicyController.canContainActivities(activities, windowingMode);
}
/**
* @see DisplayWindowPolicyController#canActivityBeLaunched(ActivityInfo, int, int, boolean)
*/
public boolean canActivityBeLaunched(ActivityInfo activityInfo,
Intent intent, @WindowConfiguration.WindowingMode int windowingMode,
int launchingFromDisplayId, boolean isNewTask) {
if (mDisplayWindowPolicyController == null) {
if (activityInfo.requiredDisplayCategory != null) {
Slog.e(TAG,
String.format("Activity with requiredDisplayCategory='%s' cannot be"
+ " launched on display %d because that display does"
+ " not have a matching category",
activityInfo.requiredDisplayCategory, mDisplayContent.mDisplayId));
return false;
}
return true;
}
return mDisplayWindowPolicyController.canActivityBeLaunched(activityInfo, intent,
windowingMode, launchingFromDisplayId, isNewTask);
}
/**
* @see DisplayWindowPolicyController#keepActivityOnWindowFlagsChanged(ActivityInfo, int, int)
*/
boolean keepActivityOnWindowFlagsChanged(ActivityInfo aInfo, int flagChanges,
int privateFlagChanges, int flagValues, int privateFlagValues) {
if (mDisplayWindowPolicyController == null) {
return true;
}
if (!mDisplayWindowPolicyController.isInterestedWindowFlags(
flagChanges, privateFlagChanges)) {
return true;
}
return mDisplayWindowPolicyController.keepActivityOnWindowFlagsChanged(
aInfo, flagValues, privateFlagValues);
}
/** Update the top activity and the uids of non-finishing activity */
void onRunningActivityChanged() {
if (mDisplayWindowPolicyController == null) {
return;
}
// Update top activity.
ActivityRecord topActivity = mDisplayContent.getTopActivity(false /* includeFinishing */,
true /* includeOverlays */);
if (topActivity != mTopRunningActivity) {
mTopRunningActivity = topActivity;
if (topActivity == null) {
mDisplayWindowPolicyController.onTopActivityChanged(null, Process.INVALID_UID,
UserHandle.USER_NULL);
} else {
mDisplayWindowPolicyController.onTopActivityChanged(
topActivity.info.getComponentName(), topActivity.info.applicationInfo.uid,
topActivity.mUserId);
}
}
// Update running uid.
final boolean[] notifyChanged = {false};
ArraySet<Integer> runningUids = new ArraySet<>();
mDisplayContent.forAllActivities((r) -> {
if (!r.finishing) {
notifyChanged[0] |= runningUids.add(r.getUid());
}
});
// We need to compare the size because if it is the following case, we can't know the
// existence of 3 in the forAllActivities() loop.
// Old set: 1,2,3
// New set: 1,2
if (notifyChanged[0] || (mRunningUid.size() != runningUids.size())) {
mRunningUid = runningUids;
mDisplayWindowPolicyController.onRunningAppsChanged(runningUids);
}
}
/**
* @see DisplayWindowPolicyController#isWindowingModeSupported(int)
*/
public final boolean isWindowingModeSupported(
@WindowConfiguration.WindowingMode int windowingMode) {
if (mDisplayWindowPolicyController == null) {
return true;
}
return mDisplayWindowPolicyController.isWindowingModeSupported(windowingMode);
}
/**
* @see DisplayWindowPolicyController#canShowTasksInHostDeviceRecents()
*/
public final boolean canShowTasksInHostDeviceRecents() {
if (mDisplayWindowPolicyController == null) {
return true;
}
return mDisplayWindowPolicyController.canShowTasksInHostDeviceRecents();
}
/**
* @see DisplayWindowPolicyController#isEnteringPipAllowed(int)
*/
public final boolean isEnteringPipAllowed(int uid) {
if (mDisplayWindowPolicyController == null) {
return true;
}
return mDisplayWindowPolicyController.isEnteringPipAllowed(uid);
}
void dump(String prefix, PrintWriter pw) {
if (mDisplayWindowPolicyController != null) {
pw.println();
mDisplayWindowPolicyController.dump(prefix, pw);
}
}
}