Loading core/java/android/hardware/display/DisplayManagerInternal.java +9 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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. * Loading core/java/android/window/DisplayWindowPolicyController.java 0 → 100644 +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); } } services/core/java/com/android/server/display/DisplayManagerService.java +38 −2 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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>(); Loading Loading @@ -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 " Loading Loading @@ -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(); } Loading Loading @@ -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); Loading Loading @@ -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); Loading Loading @@ -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"); Loading Loading @@ -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); } Loading Loading @@ -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 Loading services/core/java/com/android/server/wm/DisplayContent.java +16 −0 Original line number Diff line number Diff line Loading @@ -218,6 +218,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; Loading Loading @@ -696,6 +697,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; Loading Loading @@ -2739,6 +2748,9 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp if (newDisplayInfo != null) { mDisplayInfo.copyFrom(newDisplayInfo); } mDisplayWindowPolicyController = displayManagerInternal.getDisplayWindowPolicyController(mDisplayId); } updateBaseDisplayMetrics(mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight, Loading Loading @@ -3420,6 +3432,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 Loading Loading
core/java/android/hardware/display/DisplayManagerInternal.java +9 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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. * Loading
core/java/android/window/DisplayWindowPolicyController.java 0 → 100644 +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); } }
services/core/java/com/android/server/display/DisplayManagerService.java +38 −2 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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>(); Loading Loading @@ -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 " Loading Loading @@ -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(); } Loading Loading @@ -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); Loading Loading @@ -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); Loading Loading @@ -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"); Loading Loading @@ -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); } Loading Loading @@ -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 Loading
services/core/java/com/android/server/wm/DisplayContent.java +16 −0 Original line number Diff line number Diff line Loading @@ -218,6 +218,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; Loading Loading @@ -696,6 +697,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; Loading Loading @@ -2739,6 +2748,9 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp if (newDisplayInfo != null) { mDisplayInfo.copyFrom(newDisplayInfo); } mDisplayWindowPolicyController = displayManagerInternal.getDisplayWindowPolicyController(mDisplayId); } updateBaseDisplayMetrics(mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight, Loading Loading @@ -3420,6 +3432,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 Loading