summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/api/current.txt1
-rw-r--r--core/java/android/companion/virtual/flags/flags.aconfig7
-rw-r--r--core/java/android/hardware/display/DisplayManagerGlobal.java8
-rw-r--r--core/java/android/hardware/display/IDisplayManager.aidl3
-rw-r--r--core/java/android/hardware/display/VirtualDisplay.java23
-rw-r--r--services/core/java/com/android/server/display/DisplayManagerService.java35
-rw-r--r--services/core/java/com/android/server/display/VirtualDisplayAdapter.java4
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerInternal.java11
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java20
9 files changed, 112 insertions, 0 deletions
diff --git a/core/api/current.txt b/core/api/current.txt
index 44a6c6b2803b..8134dab1768b 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -20355,6 +20355,7 @@ package android.hardware.display {
method public android.view.Surface getSurface();
method public void release();
method public void resize(int, int, int);
+ method @FlaggedApi("android.companion.virtualdevice.flags.virtual_display_rotation_api") public void setRotation(int);
method public void setSurface(android.view.Surface);
}
diff --git a/core/java/android/companion/virtual/flags/flags.aconfig b/core/java/android/companion/virtual/flags/flags.aconfig
index cd8082c1e27d..3865e9b23e9a 100644
--- a/core/java/android/companion/virtual/flags/flags.aconfig
+++ b/core/java/android/companion/virtual/flags/flags.aconfig
@@ -82,3 +82,10 @@ flag {
purpose: PURPOSE_BUGFIX
}
}
+
+flag {
+ namespace: "virtual_devices"
+ name: "virtual_display_rotation_api"
+ description: "API for on-demand rotation of virtual displays"
+ bug: "291748430"
+}
diff --git a/core/java/android/hardware/display/DisplayManagerGlobal.java b/core/java/android/hardware/display/DisplayManagerGlobal.java
index 85197221e651..3dbc3d213d4f 100644
--- a/core/java/android/hardware/display/DisplayManagerGlobal.java
+++ b/core/java/android/hardware/display/DisplayManagerGlobal.java
@@ -812,6 +812,14 @@ public final class DisplayManagerGlobal {
}
}
+ void setVirtualDisplayRotation(IVirtualDisplayCallback token, @Surface.Rotation int rotation) {
+ try {
+ mDm.setVirtualDisplayRotation(token, rotation);
+ } catch (RemoteException ex) {
+ throw ex.rethrowFromSystemServer();
+ }
+ }
+
/**
* Gets the stable device display size, in pixels.
*/
diff --git a/core/java/android/hardware/display/IDisplayManager.aidl b/core/java/android/hardware/display/IDisplayManager.aidl
index b7c02b0d0720..9f33f3b8f36e 100644
--- a/core/java/android/hardware/display/IDisplayManager.aidl
+++ b/core/java/android/hardware/display/IDisplayManager.aidl
@@ -117,6 +117,9 @@ interface IDisplayManager {
// No permissions required but must be same Uid as the creator.
void setVirtualDisplayState(in IVirtualDisplayCallback token, boolean isOn);
+ // No permissions required but must be same Uid as the creator.
+ void setVirtualDisplayRotation(in IVirtualDisplayCallback token, int rotation);
+
// Get a stable metric for the device's display size. No permissions required.
Point getStableDisplaySize();
diff --git a/core/java/android/hardware/display/VirtualDisplay.java b/core/java/android/hardware/display/VirtualDisplay.java
index 051ce636484c..6cc938f5e6f8 100644
--- a/core/java/android/hardware/display/VirtualDisplay.java
+++ b/core/java/android/hardware/display/VirtualDisplay.java
@@ -15,6 +15,7 @@
*/
package android.hardware.display;
+import android.annotation.FlaggedApi;
import android.view.Display;
import android.view.Surface;
@@ -122,6 +123,28 @@ public final class VirtualDisplay {
}
}
+ /**
+ * Sets the rotation of the virtual display.
+ *
+ * @param rotation the new rotation of the display. May be one of {@link Surface#ROTATION_0},
+ * {@link Surface#ROTATION_90}, {@link Surface#ROTATION_180}, {@link Surface#ROTATION_270}.
+ * Upon creation, the rotation of the virtual display is always {@link Surface#ROTATION_0}.
+ */
+ @FlaggedApi(android.companion.virtualdevice.flags.Flags.FLAG_VIRTUAL_DISPLAY_ROTATION_API)
+ public void setRotation(@Surface.Rotation int rotation) {
+ if (!android.companion.virtualdevice.flags.Flags.virtualDisplayRotationApi()) {
+ return;
+ }
+ if (rotation != Surface.ROTATION_0 && rotation != Surface.ROTATION_90
+ && rotation != Surface.ROTATION_180 && rotation != Surface.ROTATION_270) {
+ throw new IllegalArgumentException(
+ "Invalid virtual display rotation value: " + rotation);
+ }
+ if (mToken != null && mDisplay.getRotation() != rotation) {
+ mGlobal.setVirtualDisplayRotation(mToken, rotation);
+ }
+ }
+
@Override
public String toString() {
return "VirtualDisplay{display=" + mDisplay + ", token=" + mToken
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index e686779e4ccd..2064ba0ce4d1 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -1939,6 +1939,27 @@ public final class DisplayManagerService extends SystemService {
}
}
+ private void setVirtualDisplayRotationInternal(IBinder appToken,
+ @Surface.Rotation int rotation) {
+ int displayId;
+ synchronized (mSyncRoot) {
+ if (mVirtualDisplayAdapter == null) {
+ return;
+ }
+ DisplayDevice device = mVirtualDisplayAdapter.getDisplayDevice(appToken);
+ if (device == null) {
+ return;
+ }
+ LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(device);
+ if (display == null) {
+ return;
+ }
+ displayId = display.getDisplayIdLocked();
+ }
+ mWindowManagerInternal.setNonDefaultDisplayRotation(
+ displayId, rotation, /* caller= */ "Virtual Display");
+ }
+
private void registerDefaultDisplayAdapters() {
// Register default display adapters.
synchronized (mSyncRoot) {
@@ -4179,6 +4200,20 @@ public final class DisplayManagerService extends SystemService {
}
@Override // Binder call
+ public void setVirtualDisplayRotation(IVirtualDisplayCallback callback,
+ @Surface.Rotation int rotation) {
+ if (!android.companion.virtualdevice.flags.Flags.virtualDisplayRotationApi()) {
+ return;
+ }
+ final long token = Binder.clearCallingIdentity();
+ try {
+ setVirtualDisplayRotationInternal(callback.asBinder(), rotation);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ @Override // Binder call
public void dump(@NonNull FileDescriptor fd, @NonNull final PrintWriter pw, String[] args) {
if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
diff --git a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
index 1a5c79fada55..962acc701878 100644
--- a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
@@ -213,6 +213,10 @@ public class VirtualDisplayAdapter extends DisplayAdapter {
}
}
+ DisplayDevice getDisplayDevice(IBinder appToken) {
+ return mVirtualDisplayDevices.get(appToken);
+ }
+
/**
* Generates a virtual display's unique identifier.
*
diff --git a/services/core/java/com/android/server/wm/WindowManagerInternal.java b/services/core/java/com/android/server/wm/WindowManagerInternal.java
index a42cb09f5500..2ea1cf88447a 100644
--- a/services/core/java/com/android/server/wm/WindowManagerInternal.java
+++ b/services/core/java/com/android/server/wm/WindowManagerInternal.java
@@ -44,6 +44,7 @@ import android.view.IWindow;
import android.view.InputChannel;
import android.view.MagnificationSpec;
import android.view.RemoteAnimationTarget;
+import android.view.Surface;
import android.view.SurfaceControl;
import android.view.SurfaceControlViewHost;
import android.view.WindowInfo;
@@ -817,6 +818,16 @@ public abstract class WindowManagerInternal {
public abstract Context getTopFocusedDisplayUiContext();
/**
+ * Sets the rotation of a non-default display.
+ *
+ * @param displayId The id of the display
+ * @param rotation The new rotation value.
+ * @param caller The requester of the rotation change, used for bookkeeping.
+ */
+ public abstract void setNonDefaultDisplayRotation(int displayId, @Surface.Rotation int rotation,
+ @NonNull String caller);
+
+ /**
* Sets whether the relevant display content can host the relevant home activity and wallpaper.
*
* @param displayUniqueId The unique ID of the display. Note that the display may not yet be
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 72ec05847973..a6d0b63b26ad 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -8357,6 +8357,26 @@ public class WindowManagerService extends IWindowManager.Stub
}
@Override
+ public void setNonDefaultDisplayRotation(int displayId, @Surface.Rotation int rotation,
+ @NonNull String caller) {
+ if (displayId == Display.DEFAULT_DISPLAY || displayId == Display.INVALID_DISPLAY) {
+ Slog.w(TAG, "Cannot set rotation for display with id: " + displayId);
+ return;
+ }
+ synchronized (mGlobalLock) {
+ final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
+ if (displayContent == null) {
+ Slog.w(TAG, "Cannot set rotation for display " + displayId
+ + " due to missing DisplayContent");
+ return;
+ }
+ displayContent.getDisplayRotation().setUserRotation(
+ displayContent.getDisplayRotation().getUserRotationMode(), rotation,
+ caller);
+ }
+ }
+
+ @Override
public void setHomeSupportedOnDisplay(String displayUniqueId, int displayType,
boolean supported) {
final long origId = Binder.clearCallingIdentity();