Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f068982d authored by Chilun's avatar Chilun
Browse files

Introduce DisplayWindowPolicyController for display across devices

A controller to control the policies of the windows that can be
displayed on the virtual display.

Also migrate task event callbacks.

Bug: 201712607
Test: manual
Change-Id: I4accd76beda6829cd1b33ad50c0860405ae10678
parent 70ba2506
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ import android.view.Display;
import android.view.DisplayInfo;
import android.view.SurfaceControl;
import android.view.SurfaceControl.Transaction;
import android.window.DisplayWindowPolicyController;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -378,6 +379,14 @@ public abstract class DisplayManagerInternal {
     */
    public abstract void onEarlyInteractivityChange(boolean interactive);

    /**
     * Get {@link DisplayWindowPolicyController} associated to the {@link DisplayInfo#displayId}
     *
     * @param displayId The id of the display.
     * @return The associated {@link DisplayWindowPolicyController}.
     */
    public abstract DisplayWindowPolicyController getDisplayWindowPolicyController(int displayId);

    /**
     * Describes the requested power state of the display.
     *
+84 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 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 android.window;

import android.annotation.NonNull;
import android.content.ComponentName;
import android.content.pm.ActivityInfo;

import java.io.PrintWriter;
import java.util.List;

/**
 * Abstract class to control the policies of the windows that can be displayed on the virtual
 * display.
 *
 * @hide
 */
public abstract class DisplayWindowPolicyController {
    /**
     * The window flags that we are interested in.
     * @see android.view.WindowManager.LayoutParams
     * @see #keepActivityOnWindowFlagsChanged
     */
    private int mWindowFlags;

    /**
     * Returns {@code true} if the given window flags contain the flags that we're interested in.
     */
    public final boolean isInterestedWindowFlags(int windowFlags) {
        return (mWindowFlags & windowFlags) != 0;
    }

    /**
     * Sets the window flags that we’re interested in and expected
     * #keepActivityOnWindowFlagsChanged to be called if any changes.
     */
    public final void setInterestedWindowFlags(int windowFlags) {
        mWindowFlags = windowFlags;
    }

    /**
     * Returns {@code true} if the given activities can be displayed on this virtual display.
     */
    public abstract boolean canContainActivities(@NonNull List<ActivityInfo> activities);

    /**
     * Called when an Activity window is layouted with the new changes where contains the
     * window flags that we’re interested in.
     * Returns {@code false} if the Activity cannot remain on the display and the activity task will
     * be moved back to default display.
     */
    public abstract boolean keepActivityOnWindowFlagsChanged(
            ActivityInfo activityInfo, int windowFlags);

    /**
     * This is called when the top activity of the display is changed.
     */
    public void onTopActivityChanged(ComponentName topActivity, int uid) {}

    /**
     * This is called when the apps that contains running activities on the display has changed.
     */
    public void onRunningAppsChanged(int[] runningUids) {}

    /** Dump debug data */
    public void dump(String prefix, final PrintWriter pw) {
        pw.println(prefix + "DisplayWindowPolicyController{" + super.toString() + "}");
        pw.println(prefix + "  mWindowFlags=" + mWindowFlags);
    }
}
+38 −2
Original line number Diff line number Diff line
@@ -110,6 +110,7 @@ import android.view.DisplayEventReceiver;
import android.view.DisplayInfo;
import android.view.Surface;
import android.view.SurfaceControl;
import android.window.DisplayWindowPolicyController;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
@@ -239,6 +240,10 @@ public final class DisplayManagerService extends SystemService {
    public final SparseArray<CallbackRecord> mCallbacks =
            new SparseArray<CallbackRecord>();

    /** All {@link DisplayWindowPolicyController}s indexed by {@link DisplayInfo#displayId}. */
    final SparseArray<DisplayWindowPolicyController> mDisplayWindowPolicyController =
            new SparseArray<>();

    // List of all currently registered display adapters.
    private final ArrayList<DisplayAdapter> mDisplayAdapters = new ArrayList<DisplayAdapter>();

@@ -1117,7 +1122,8 @@ public final class DisplayManagerService extends SystemService {

    private int createVirtualDisplayInternal(IVirtualDisplayCallback callback,
            IMediaProjection projection, int callingUid, String packageName, Surface surface,
            int flags, VirtualDisplayConfig virtualDisplayConfig) {
            int flags, VirtualDisplayConfig virtualDisplayConfig,
            DisplayWindowPolicyController controller) {
        synchronized (mSyncRoot) {
            if (mVirtualDisplayAdapter == null) {
                Slog.w(TAG, "Rejecting request to create private virtual display "
@@ -1145,6 +1151,9 @@ public final class DisplayManagerService extends SystemService {

            final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(device);
            if (display != null) {
                if (controller != null) {
                    mDisplayWindowPolicyController.put(display.getDisplayIdLocked(), controller);
                }
                return display.getDisplayIdLocked();
            }

@@ -1188,6 +1197,10 @@ public final class DisplayManagerService extends SystemService {
            DisplayDevice device =
                    mVirtualDisplayAdapter.releaseVirtualDisplayLocked(appToken);
            if (device != null) {
                final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(device);
                if (display != null) {
                    mDisplayWindowPolicyController.delete(display.getDisplayIdLocked());
                }
                // TODO: multi-display - handle virtual displays the same as other display adapters.
                mDisplayDeviceRepo.onDisplayDeviceEvent(device,
                        DisplayAdapter.DISPLAY_DEVICE_EVENT_REMOVED);
@@ -2139,6 +2152,15 @@ public final class DisplayManagerService extends SystemService {
            }
            pw.println();
            mPersistentDataStore.dump(pw);

            final int displayWindowPolicyControllerCount = mDisplayWindowPolicyController.size();
            pw.println();
            pw.println("Display Window Policy Controllers: size="
                    + displayWindowPolicyControllerCount);
            for (int i = 0; i < displayWindowPolicyControllerCount; i++) {
                pw.print("Display " + mDisplayWindowPolicyController.keyAt(i) + ":");
                mDisplayWindowPolicyController.valueAt(i).dump("  ", pw);
            }
        }
        pw.println();
        mDisplayModeDirector.dump(pw);
@@ -2704,6 +2726,13 @@ public final class DisplayManagerService extends SystemService {
        @Override // Binder call
        public int createVirtualDisplay(VirtualDisplayConfig virtualDisplayConfig,
                IVirtualDisplayCallback callback, IMediaProjection projection, String packageName) {
            return createVirtualDisplay(virtualDisplayConfig, callback, projection, packageName,
                    null /* controller */);
        }

        public int createVirtualDisplay(VirtualDisplayConfig virtualDisplayConfig,
                IVirtualDisplayCallback callback, IMediaProjection projection, String packageName,
                DisplayWindowPolicyController controller) {
            final int callingUid = Binder.getCallingUid();
            if (!validatePackageName(callingUid, packageName)) {
                throw new SecurityException("packageName must match the calling uid");
@@ -2803,7 +2832,7 @@ public final class DisplayManagerService extends SystemService {
            final long token = Binder.clearCallingIdentity();
            try {
                return createVirtualDisplayInternal(callback, projection, callingUid, packageName,
                        surface, flags, virtualDisplayConfig);
                        surface, flags, virtualDisplayConfig, controller);
            } finally {
                Binder.restoreCallingIdentity(token);
            }
@@ -3624,6 +3653,13 @@ public final class DisplayManagerService extends SystemService {
        public void onEarlyInteractivityChange(boolean interactive) {
            mLogicalDisplayMapper.onEarlyInteractivityChange(interactive);
        }

        @Override
        public DisplayWindowPolicyController getDisplayWindowPolicyController(int displayId) {
            synchronized (mSyncRoot) {
                return mDisplayWindowPolicyController.get(displayId);
            }
        }
    }

    class DesiredDisplayModeSpecsObserver
+16 −0
Original line number Diff line number Diff line
@@ -217,6 +217,7 @@ import android.view.WindowInsets;
import android.view.WindowManager;
import android.view.WindowManager.DisplayImePolicy;
import android.view.WindowManagerPolicyConstants.PointerEventListener;
import android.window.DisplayWindowPolicyController;
import android.window.IDisplayAreaOrganizer;

import com.android.internal.annotations.VisibleForTesting;
@@ -694,6 +695,14 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
    // well and thus won't change the top resumed / focused record
    boolean mDontMoveToTop;

    /**
     * The policy controller of the windows that can be displayed on the virtual display.
     *
     * @see DisplayWindowPolicyController
     */
    @Nullable
    DisplayWindowPolicyController mDisplayWindowPolicyController;

    private final Consumer<WindowState> mUpdateWindowsForAnimator = w -> {
        WindowStateAnimator winAnimator = w.mWinAnimator;
        final ActivityRecord activity = w.mActivityRecord;
@@ -2737,6 +2746,9 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
            if (newDisplayInfo != null) {
                mDisplayInfo.copyFrom(newDisplayInfo);
            }

            mDisplayWindowPolicyController =
                    displayManagerInternal.getDisplayWindowPolicyController(mDisplayId);
        }

        updateBaseDisplayMetrics(mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight,
@@ -3418,6 +3430,10 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
        mInputMonitor.dump(pw, "  ");
        pw.println();
        mInsetsStateController.dump(prefix, pw);
        if (mDisplayWindowPolicyController != null) {
            pw.println();
            mDisplayWindowPolicyController.dump(prefix, pw);
        }
    }

    @Override