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>
This commit is contained in:
Karthik Ravi Shankar
2017-04-12 15:31:20 -07:00
parent a609bbc9c4
commit cdf9ce7229
7 changed files with 291 additions and 11 deletions

View File

@@ -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;

View File

@@ -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;
}
}

View File

@@ -44,6 +44,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.
*

View File

@@ -16,6 +16,7 @@
package android.service.vr;
import android.app.CompatibilityDisplayProperties;
import android.service.vr.IVrStateCallbacks;
import android.service.vr.IPersistentVrStateCallbacks;
@@ -66,6 +67,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.
*

View File

@@ -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;
}
/**
@@ -164,6 +190,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());

View File

@@ -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;
@@ -81,6 +82,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

View File

@@ -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;
@@ -426,6 +427,13 @@ public class VrManagerService extends SystemService implements EnabledComponentC
VrManagerService.this.setPersistentVrModeEnabled(enabled);
}
@Override
public void setCompatibilityDisplayProperties(
CompatibilityDisplayProperties compatDisplayProp) {
enforceCallerPermission(Manifest.permission.RESTRICTED_VR_ACCESS);
VrManagerService.this.setCompatibilityDisplayProperties(compatDisplayProp);
}
@Override
public int getCompatibilityDisplayId() {
return VrManagerService.this.getCompatibilityDisplayId();
@@ -540,6 +548,12 @@ public class VrManagerService extends SystemService implements EnabledComponentC
VrManagerService.this.setPersistentVrModeEnabled(enabled);
}
@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();