diff options
author | 2017-04-12 15:31:20 -0700 | |
---|---|---|
committer | 2017-04-17 14:23:08 -0700 | |
commit | cdf9ce7229e791fe345b0860fe32433f15c95db8 (patch) | |
tree | e738b602eca8cbb6417947fe09be7ee970e140e4 | |
parent | a609bbc9c4e1614eca7e70cb90739486f745e5c7 (diff) |
Make VR mode virtual display properties customizable
Currently the virtual display created in VR mode is of fixed size. This
may not work for all the devices. Add APIs to make the resolution and
DPI adjustable from VrCore.
Bug: 37260266
Test: Sample reflection which works - cl/153039188
Test: adb shell set-persistent-vr-mode-enabled true
adb shell vr set-compatibility-display-properties 500 500 500
adb shell dumpsys display
>> DisplayDeviceInfo{"VR 2D Display":
uniqueId="virtual:android,1000,VR 2D Display,0", 500 x 500, modeId
6, defaultModeId 6, supportedModes [{id=6, width=500, height=500,
fps=60.0}], colorMode 0, supportedColorModes [0], HdrCapabilities
null, density 500, 500.0 x 500.0 dpi, appVsyncOff 0, presDeadline
16666666, touch NONE, rotation 0, type VIRTUAL, state ON, owner
android (uid 1000), FLAG_PRIVATE, FLAG_NEVER_BLANK,
FLAG_OWN_CONTENT_ONLY}
Change-Id: Ibb2d03b7f7f8f62fcce97fcc2b373ae3f09cef01
Signed-off-by: Karthik Ravi Shankar <karthikrs@google.com>
7 files changed, 291 insertions, 11 deletions
diff --git a/core/java/android/app/CompatibilityDisplayProperties.aidl b/core/java/android/app/CompatibilityDisplayProperties.aidl new file mode 100644 index 000000000000..626a63e05819 --- /dev/null +++ b/core/java/android/app/CompatibilityDisplayProperties.aidl @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2017 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.app; + +/** @hide */ +parcelable CompatibilityDisplayProperties; diff --git a/core/java/android/app/CompatibilityDisplayProperties.java b/core/java/android/app/CompatibilityDisplayProperties.java new file mode 100644 index 000000000000..9a9bc2c40d94 --- /dev/null +++ b/core/java/android/app/CompatibilityDisplayProperties.java @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2017 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.app; + +import android.content.ComponentName; +import android.os.Parcel; +import android.os.Parcelable; + +import java.io.PrintWriter; + +/** + * Display properties to be used by VR mode when creating a virtual display. + * + * @hide + */ +public class CompatibilityDisplayProperties implements Parcelable { + + /** + * The actual width, height and dpi. + */ + private final int mWidth; + private final int mHeight; + private final int mDpi; + + public CompatibilityDisplayProperties(int width, int height, int dpi) { + mWidth = width; + mHeight = height; + mDpi = dpi; + } + + @Override + public int hashCode() { + int result = getWidth(); + result = 31 * result + getHeight(); + result = 31 * result + getDpi(); + return result; + } + + @Override + public String toString() { + return "CompatibilityDisplayProperties{" + + "mWidth=" + mWidth + + ", mHeight=" + mHeight + + ", mDpi=" + mDpi + + "}"; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + CompatibilityDisplayProperties that = (CompatibilityDisplayProperties) o; + + if (getWidth() != that.getWidth()) return false; + if (getHeight() != that.getHeight()) return false; + return getDpi() == that.getDpi(); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(mWidth); + dest.writeInt(mHeight); + dest.writeInt(mDpi); + } + + public static final Parcelable.Creator<CompatibilityDisplayProperties> CREATOR + = new Parcelable.Creator<CompatibilityDisplayProperties>() { + @Override + public CompatibilityDisplayProperties createFromParcel(Parcel source) { + return new CompatibilityDisplayProperties(source); + } + + @Override + public CompatibilityDisplayProperties[] newArray(int size) { + return new CompatibilityDisplayProperties[size]; + } + }; + + private CompatibilityDisplayProperties(Parcel source) { + mWidth = source.readInt(); + mHeight = source.readInt(); + mDpi = source.readInt(); + } + + public void dump(PrintWriter pw, String prefix) { + pw.println(prefix + "CompatibilityDisplayProperties:"); + pw.println(prefix + " width=" + mWidth); + pw.println(prefix + " height=" + mHeight); + pw.println(prefix + " dpi=" + mDpi); + } + + public int getWidth() { + return mWidth; + } + + public int getHeight() { + return mHeight; + } + + public int getDpi() { + return mDpi; + } +} diff --git a/core/java/android/app/VrManager.java b/core/java/android/app/VrManager.java index 4dd578e7deab..878c8c38516d 100644 --- a/core/java/android/app/VrManager.java +++ b/core/java/android/app/VrManager.java @@ -45,6 +45,26 @@ public class VrManager { } /** + * Sets the resolution and DPI of the compatibility virtual display used to display 2D + * applications in VR mode. + * + * <p>Requires {@link android.Manifest.permission#ACCESS_VR_MANAGER} permission.</p> + * + * @param {@link android.app.CompatibilityDisplayProperties} properties to be set to the + * virtual display for 2D applications in VR mode. + * + * {@hide} + */ + public void setCompatibilityDisplayProperties( + CompatibilityDisplayProperties compatDisplayProp) { + try { + mService.setCompatibilityDisplayProperties(compatDisplayProp); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + } + + /** * Initiate connection for system controller data. * * @param fd Controller data file descriptor. diff --git a/core/java/android/service/vr/IVrManager.aidl b/core/java/android/service/vr/IVrManager.aidl index 6eea07d33c40..8b2d0c6293e8 100644 --- a/core/java/android/service/vr/IVrManager.aidl +++ b/core/java/android/service/vr/IVrManager.aidl @@ -16,6 +16,7 @@ package android.service.vr; +import android.app.CompatibilityDisplayProperties; import android.service.vr.IVrStateCallbacks; import android.service.vr.IPersistentVrStateCallbacks; @@ -67,6 +68,18 @@ interface IVrManager { void setPersistentVrModeEnabled(in boolean enabled); /** + * Sets the resolution and DPI of the compatibility virtual display used to display + * 2D applications in VR mode. + * + * <p>Requires {@link android.Manifest.permission#ACCESS_VR_MANAGER} permission.</p> + * + * @param compatDisplayProperties Compatibitlity display properties to be set for + * the VR virtual display + */ + void setCompatibilityDisplayProperties( + in CompatibilityDisplayProperties compatDisplayProperties); + + /** * Return current virtual display id. * * @return {@link android.view.Display.INVALID_DISPLAY} if there is no virtual display diff --git a/services/core/java/com/android/server/vr/CompatibilityDisplay.java b/services/core/java/com/android/server/vr/CompatibilityDisplay.java index ee615fd6fde4..9e7012750ff5 100644 --- a/services/core/java/com/android/server/vr/CompatibilityDisplay.java +++ b/services/core/java/com/android/server/vr/CompatibilityDisplay.java @@ -3,6 +3,7 @@ package com.android.server.vr; import static android.view.Display.INVALID_DISPLAY; import android.app.ActivityManagerInternal; +import android.app.CompatibilityDisplayProperties; import android.app.Service; import android.content.BroadcastReceiver; import android.content.Context; @@ -35,9 +36,9 @@ class CompatibilityDisplay { private final static boolean DEBUG = false; // TODO: Go over these values and figure out what is best - private final static int HEIGHT = 1800; - private final static int WIDTH = 1400; - private final static int DPI = 320; + private int mVirtualDisplayHeight; + private int mVirtualDisplayWidth; + private int mVirtualDisplayDpi; private final static int STOP_VIRTUAL_DISPLAY_DELAY_MILLIS = 2000; private final static String DEBUG_ACTION_SET_MODE = @@ -49,6 +50,28 @@ class CompatibilityDisplay { private final static String DEBUG_EXTRA_SURFACE = "com.android.server.vr.CompatibilityDisplay.EXTRA_SURFACE"; + /** + * The default width of the VR virtual display + */ + public static final int DEFAULT_VR_DISPLAY_WIDTH = 1400; + + /** + * The default height of the VR virtual display + */ + public static final int DEFAULT_VR_DISPLAY_HEIGHT = 1800; + + /** + * The default height of the VR virtual dpi. + */ + public static final int DEFAULT_VR_DISPLAY_DPI = 320; + + /** + * The minimum height, width and dpi of VR virtual display. + */ + public static final int MIN_VR_DISPLAY_WIDTH = 1; + public static final int MIN_VR_DISPLAY_HEIGHT = 1; + public static final int MIN_VR_DISPLAY_DPI = 1; + private final ActivityManagerInternal mActivityManagerInternal; private final DisplayManager mDisplayManager; private final IVrManager mVrManager; @@ -81,6 +104,9 @@ class CompatibilityDisplay { mDisplayManager = displayManager; mActivityManagerInternal = activityManagerInternal; mVrManager = vrManager; + mVirtualDisplayWidth = DEFAULT_VR_DISPLAY_WIDTH; + mVirtualDisplayHeight = DEFAULT_VR_DISPLAY_HEIGHT; + mVirtualDisplayDpi = DEFAULT_VR_DISPLAY_DPI; } /** @@ -165,6 +191,47 @@ class CompatibilityDisplay { } /** + * Sets the resolution and DPI of the compatibility virtual display used to display + * 2D applications in VR mode. + * + * <p>Requires {@link android.Manifest.permission#ACCESS_VR_MANAGER} permission.</p> + * + * @param compatDisplayProperties Properties of the virtual display for 2D applications + * in VR mode. + */ + public void setVirtualDisplayProperties(CompatibilityDisplayProperties compatDisplayProperties) { + synchronized(mVdLock) { + if (DEBUG) { + Log.i(TAG, "VD setVirtualDisplayProperties: res = " + + compatDisplayProperties.getWidth() + "X" + compatDisplayProperties.getHeight() + + ", dpi = " + compatDisplayProperties.getDpi()); + } + + if (compatDisplayProperties.getWidth() < MIN_VR_DISPLAY_WIDTH || + compatDisplayProperties.getHeight() < MIN_VR_DISPLAY_HEIGHT || + compatDisplayProperties.getDpi() < MIN_VR_DISPLAY_DPI) { + throw new IllegalArgumentException ( + "Illegal argument: height, width, dpi cannot be negative. res = " + + compatDisplayProperties.getWidth() + "X" + compatDisplayProperties.getHeight() + + ", dpi = " + compatDisplayProperties.getDpi()); + } + + mVirtualDisplayWidth = compatDisplayProperties.getWidth(); + mVirtualDisplayHeight = compatDisplayProperties.getHeight(); + mVirtualDisplayDpi = compatDisplayProperties.getDpi(); + + if (mVirtualDisplay != null) { + mVirtualDisplay.resize(mVirtualDisplayWidth, mVirtualDisplayHeight, + mVirtualDisplayDpi); + ImageReader oldImageReader = mImageReader; + mImageReader = null; + startImageReader(); + oldImageReader.close(); + } + } + } + + /** * Returns the virtual display ID if one currently exists, otherwise returns * {@link INVALID_DISPLAY_ID}. * @@ -175,7 +242,7 @@ class CompatibilityDisplay { if (mVirtualDisplay != null) { int virtualDisplayId = mVirtualDisplay.getDisplay().getDisplayId(); if (DEBUG) { - Log.e(TAG, "VD id: " + virtualDisplayId); + Log.i(TAG, "VD id: " + virtualDisplayId); } return virtualDisplayId; } @@ -202,8 +269,9 @@ class CompatibilityDisplay { return; } - mVirtualDisplay = mDisplayManager.createVirtualDisplay("VR 2D Display", WIDTH, HEIGHT, - DPI, null /* Surface */, 0 /* flags */); + mVirtualDisplay = mDisplayManager.createVirtualDisplay("VR 2D Display", + mVirtualDisplayWidth, mVirtualDisplayHeight, mVirtualDisplayDpi, + null /* Surface */, 0 /* flags */); if (mVirtualDisplay != null) { mActivityManagerInternal.setVrCompatibilityDisplayId( @@ -215,9 +283,7 @@ class CompatibilityDisplay { } } - if (DEBUG) { - Log.d(TAG, "VD created: " + mVirtualDisplay); - } + Log.i(TAG, "VD created: " + mVirtualDisplay); } /** @@ -279,8 +345,10 @@ class CompatibilityDisplay { */ private void startImageReader() { if (mImageReader == null) { - mImageReader = ImageReader.newInstance(WIDTH, HEIGHT, PixelFormat.RGBA_8888, - 2 /* maxImages */); + mImageReader = ImageReader.newInstance(mVirtualDisplayWidth, mVirtualDisplayHeight, + PixelFormat.RGBA_8888, 2 /* maxImages */); + Log.i(TAG, "VD startImageReader: res = " + mVirtualDisplayWidth + "X" + + mVirtualDisplayHeight + ", dpi = " + mVirtualDisplayDpi); } synchronized (mVdLock) { setSurfaceLocked(mImageReader.getSurface()); diff --git a/services/core/java/com/android/server/vr/VrManagerInternal.java b/services/core/java/com/android/server/vr/VrManagerInternal.java index 358861d0c9c4..63c61955bcd7 100644 --- a/services/core/java/com/android/server/vr/VrManagerInternal.java +++ b/services/core/java/com/android/server/vr/VrManagerInternal.java @@ -16,6 +16,7 @@ package com.android.server.vr; import android.annotation.NonNull; +import android.app.CompatibilityDisplayProperties; import android.content.ComponentName; import android.service.vr.IPersistentVrStateCallbacks; @@ -82,6 +83,18 @@ public abstract class VrManagerInternal { public abstract int hasVrPackage(@NonNull ComponentName packageName, int userId); /** + * Sets the resolution and DPI of the compatibility virtual display used to display + * 2D applications in VR mode. + * + * <p>Requires {@link android.Manifest.permission#ACCESS_VR_MANAGER} permission.</p> + * + * @param compatDisplayProp Properties of the virtual display for 2D applications + * in VR mode. + */ + public abstract void setCompatibilityDisplayProperties( + CompatibilityDisplayProperties compatDisplayProp); + + /** * Sets the persistent VR mode state of a device. When a device is in persistent VR mode it will * remain in VR mode even if the foreground does not specify Vr mode being enabled. Mainly used * by VR viewers to indicate that a device is placed in a VR viewer. diff --git a/services/core/java/com/android/server/vr/VrManagerService.java b/services/core/java/com/android/server/vr/VrManagerService.java index cc089184d2ed..39a157355fe6 100644 --- a/services/core/java/com/android/server/vr/VrManagerService.java +++ b/services/core/java/com/android/server/vr/VrManagerService.java @@ -21,6 +21,7 @@ import android.Manifest; import android.app.ActivityManagerInternal; import android.app.ActivityManager; import android.app.AppOpsManager; +import android.app.CompatibilityDisplayProperties; import android.app.NotificationManager; import android.annotation.NonNull; import android.content.ComponentName; @@ -427,6 +428,13 @@ public class VrManagerService extends SystemService implements EnabledComponentC } @Override + public void setCompatibilityDisplayProperties( + CompatibilityDisplayProperties compatDisplayProp) { + enforceCallerPermission(Manifest.permission.RESTRICTED_VR_ACCESS); + VrManagerService.this.setCompatibilityDisplayProperties(compatDisplayProp); + } + + @Override public int getCompatibilityDisplayId() { return VrManagerService.this.getCompatibilityDisplayId(); } @@ -541,6 +549,12 @@ public class VrManagerService extends SystemService implements EnabledComponentC } @Override + public void setCompatibilityDisplayProperties( + CompatibilityDisplayProperties compatDisplayProp) { + VrManagerService.this.setCompatibilityDisplayProperties(compatDisplayProp); + } + + @Override public int getCompatibilityDisplayId() { return VrManagerService.this.getCompatibilityDisplayId(); } @@ -1106,6 +1120,15 @@ public class VrManagerService extends SystemService implements EnabledComponentC } } + public void setCompatibilityDisplayProperties( + CompatibilityDisplayProperties compatDisplayProp) { + if (mCompatibilityDisplay != null) { + mCompatibilityDisplay.setVirtualDisplayProperties(compatDisplayProp); + return; + } + Slog.w(TAG, "CompatibilityDisplay is null!"); + } + private int getCompatibilityDisplayId() { if (mCompatibilityDisplay != null) { return mCompatibilityDisplay.getVirtualDisplayId(); |