Add uniqueId to Virtual Display and pass through to inputflinger (1/2)
This CL adds: 1) Adds uniqueId (protected via system/sig permission) to virtual displays. 2) Add support for N virtual display viewports into inputflinger. 3) Set the virtual display's viewports in inputflinger if it has the uniqueId value set to non-null. (a) Moving the new viewport from java to native inputflinger and (b) adding "uniqueId" value to viewports makes up the great majority of this change. 4) From the inputflinger side, we also read in a new value from the input device configuration files called 'touch.displayId'. 5) When touch.displayId and the virtual display's uniqueId match, inputflinger links the two. Test: Start VR and ensure that the virtual viewport shows up when running 'adb shell dump input". Run a VR app, and ensure that the virtual input device is associated with the new virtual viewport. Test: com.android.server.display.DisplayManagerServiceTest Bug: 36051620 Change-Id: Ic2117eb8e19f7f3c59687160591f8bc6692c1f12 Merged-In: Ic2117eb8e19f7f3c59687160591f8bc6692c1f12
This commit is contained in:
@@ -251,6 +251,15 @@ public final class DisplayManager {
|
||||
*/
|
||||
public static final int VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD = 1 << 5;
|
||||
|
||||
/**
|
||||
* Virtual display flag: Specifies that the virtual display can be associated with a
|
||||
* touchpad device that matches its uniqueId.
|
||||
*
|
||||
* @see #createVirtualDisplay
|
||||
* @hide
|
||||
*/
|
||||
public static final int VIRTUAL_DISPLAY_FLAG_SUPPORTS_TOUCH = 1 << 6;
|
||||
|
||||
/** @hide */
|
||||
public DisplayManager(Context context) {
|
||||
mContext = context;
|
||||
@@ -542,16 +551,17 @@ public final class DisplayManager {
|
||||
public VirtualDisplay createVirtualDisplay(@NonNull String name,
|
||||
int width, int height, int densityDpi, @Nullable Surface surface, int flags,
|
||||
@Nullable VirtualDisplay.Callback callback, @Nullable Handler handler) {
|
||||
return createVirtualDisplay(null,
|
||||
name, width, height, densityDpi, surface, flags, callback, handler);
|
||||
return createVirtualDisplay(null /* projection */, name, width, height, densityDpi, surface,
|
||||
flags, callback, handler, null /* uniqueId */);
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public VirtualDisplay createVirtualDisplay(@Nullable MediaProjection projection,
|
||||
@NonNull String name, int width, int height, int densityDpi, @Nullable Surface surface,
|
||||
int flags, @Nullable VirtualDisplay.Callback callback, @Nullable Handler handler) {
|
||||
int flags, @Nullable VirtualDisplay.Callback callback, @Nullable Handler handler,
|
||||
@Nullable String uniqueId) {
|
||||
return mGlobal.createVirtualDisplay(mContext, projection,
|
||||
name, width, height, densityDpi, surface, flags, callback, handler);
|
||||
name, width, height, densityDpi, surface, flags, callback, handler, uniqueId);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -383,7 +383,7 @@ public final class DisplayManagerGlobal {
|
||||
|
||||
public VirtualDisplay createVirtualDisplay(Context context, MediaProjection projection,
|
||||
String name, int width, int height, int densityDpi, Surface surface, int flags,
|
||||
VirtualDisplay.Callback callback, Handler handler) {
|
||||
VirtualDisplay.Callback callback, Handler handler, String uniqueId) {
|
||||
if (TextUtils.isEmpty(name)) {
|
||||
throw new IllegalArgumentException("name must be non-null and non-empty");
|
||||
}
|
||||
@@ -397,7 +397,8 @@ public final class DisplayManagerGlobal {
|
||||
int displayId;
|
||||
try {
|
||||
displayId = mDm.createVirtualDisplay(callbackWrapper, projectionToken,
|
||||
context.getPackageName(), name, width, height, densityDpi, surface, flags);
|
||||
context.getPackageName(), name, width, height, densityDpi, surface, flags,
|
||||
uniqueId);
|
||||
} catch (RemoteException ex) {
|
||||
throw ex.rethrowFromSystemServer();
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package android.hardware.display;
|
||||
|
||||
import android.graphics.Rect;
|
||||
import android.text.TextUtils;
|
||||
|
||||
/**
|
||||
* Describes how the pixels of physical display device reflects the content of
|
||||
@@ -52,6 +53,9 @@ public final class DisplayViewport {
|
||||
public int deviceWidth;
|
||||
public int deviceHeight;
|
||||
|
||||
// The ID used to uniquely identify this display.
|
||||
public String uniqueId;
|
||||
|
||||
public void copyFrom(DisplayViewport viewport) {
|
||||
valid = viewport.valid;
|
||||
displayId = viewport.displayId;
|
||||
@@ -60,6 +64,49 @@ public final class DisplayViewport {
|
||||
physicalFrame.set(viewport.physicalFrame);
|
||||
deviceWidth = viewport.deviceWidth;
|
||||
deviceHeight = viewport.deviceHeight;
|
||||
uniqueId = viewport.uniqueId;
|
||||
}
|
||||
|
||||
public DisplayViewport makeCopy() {
|
||||
DisplayViewport dv = new DisplayViewport();
|
||||
dv.copyFrom(this);
|
||||
return dv;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (o == this) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(o instanceof DisplayViewport)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
DisplayViewport other = (DisplayViewport) o;
|
||||
return valid == other.valid &&
|
||||
displayId == other.displayId &&
|
||||
orientation == other.orientation &&
|
||||
logicalFrame.equals(other.logicalFrame) &&
|
||||
physicalFrame.equals(other.physicalFrame) &&
|
||||
deviceWidth == other.deviceWidth &&
|
||||
deviceHeight == other.deviceHeight &&
|
||||
TextUtils.equals(uniqueId, other.uniqueId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result += prime * result + (valid ? 1 : 0);
|
||||
result += prime * result + displayId;
|
||||
result += prime * result + orientation;
|
||||
result += prime * result + logicalFrame.hashCode();
|
||||
result += prime * result + physicalFrame.hashCode();
|
||||
result += prime * result + deviceWidth;
|
||||
result += prime * result + deviceHeight;
|
||||
result += prime * result + uniqueId.hashCode();
|
||||
return result;
|
||||
}
|
||||
|
||||
// For debugging purposes.
|
||||
@@ -67,6 +114,7 @@ public final class DisplayViewport {
|
||||
public String toString() {
|
||||
return "DisplayViewport{valid=" + valid
|
||||
+ ", displayId=" + displayId
|
||||
+ ", uniqueId='" + uniqueId + "'"
|
||||
+ ", orientation=" + orientation
|
||||
+ ", logicalFrame=" + logicalFrame
|
||||
+ ", physicalFrame=" + physicalFrame
|
||||
|
||||
@@ -66,7 +66,7 @@ interface IDisplayManager {
|
||||
// MediaProjection token for certain combinations of flags.
|
||||
int createVirtualDisplay(in IVirtualDisplayCallback callback,
|
||||
in IMediaProjection projectionToken, String packageName, String name,
|
||||
int width, int height, int densityDpi, in Surface surface, int flags);
|
||||
int width, int height, int densityDpi, in Surface surface, int flags, String uniqueId);
|
||||
|
||||
// No permissions required, but must be same Uid as the creator.
|
||||
void resizeVirtualDisplay(in IVirtualDisplayCallback token,
|
||||
|
||||
@@ -22,6 +22,8 @@ import android.view.InputEvent;
|
||||
import android.view.inputmethod.InputMethodInfo;
|
||||
import android.view.inputmethod.InputMethodSubtype;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Input manager local system service interface.
|
||||
*
|
||||
@@ -35,7 +37,7 @@ public abstract class InputManagerInternal {
|
||||
* by the input system. The input system must copy this information to retain it.
|
||||
*/
|
||||
public abstract void setDisplayViewports(DisplayViewport defaultViewport,
|
||||
DisplayViewport externalTouchViewport);
|
||||
DisplayViewport externalTouchViewport, List<DisplayViewport> virtualTouchViewports);
|
||||
|
||||
/**
|
||||
* Called by the power manager to tell the input manager whether it should start
|
||||
|
||||
@@ -162,6 +162,7 @@ LOCAL_SRC_FILES:= \
|
||||
android_hardware_camera2_legacy_LegacyCameraDevice.cpp \
|
||||
android_hardware_camera2_legacy_PerfMeasurement.cpp \
|
||||
android_hardware_camera2_DngCreator.cpp \
|
||||
android_hardware_display_DisplayViewport.cpp \
|
||||
android_hardware_HardwareBuffer.cpp \
|
||||
android_hardware_Radio.cpp \
|
||||
android_hardware_SensorManager.cpp \
|
||||
|
||||
120
core/jni/android_hardware_display_DisplayViewport.cpp
Normal file
120
core/jni/android_hardware_display_DisplayViewport.cpp
Normal file
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "DisplayViewport-JNI"
|
||||
|
||||
#include "JNIHelp.h"
|
||||
#include "core_jni_helpers.h"
|
||||
|
||||
#include <android_hardware_display_DisplayViewport.h>
|
||||
#include <android_runtime/AndroidRuntime.h>
|
||||
#include <android_runtime/Log.h>
|
||||
#include <utils/Log.h>
|
||||
|
||||
#include <ScopedUtfChars.h>
|
||||
|
||||
namespace android {
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
static struct {
|
||||
jclass clazz;
|
||||
|
||||
jfieldID displayId;
|
||||
jfieldID orientation;
|
||||
jfieldID logicalFrame;
|
||||
jfieldID physicalFrame;
|
||||
jfieldID deviceWidth;
|
||||
jfieldID deviceHeight;
|
||||
jfieldID uniqueId;
|
||||
} gDisplayViewportClassInfo;
|
||||
|
||||
static struct {
|
||||
jfieldID left;
|
||||
jfieldID top;
|
||||
jfieldID right;
|
||||
jfieldID bottom;
|
||||
} gRectClassInfo;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
status_t android_hardware_display_DisplayViewport_toNative(JNIEnv* env, jobject viewportObj,
|
||||
DisplayViewport* viewport) {
|
||||
viewport->displayId = env->GetIntField(viewportObj, gDisplayViewportClassInfo.displayId);
|
||||
viewport->orientation = env->GetIntField(viewportObj, gDisplayViewportClassInfo.orientation);
|
||||
viewport->deviceWidth = env->GetIntField(viewportObj, gDisplayViewportClassInfo.deviceWidth);
|
||||
viewport->deviceHeight = env->GetIntField(viewportObj, gDisplayViewportClassInfo.deviceHeight);
|
||||
|
||||
jstring uniqueId =
|
||||
jstring(env->GetObjectField(viewportObj, gDisplayViewportClassInfo.uniqueId));
|
||||
if (uniqueId != nullptr) {
|
||||
viewport->uniqueId.setTo(ScopedUtfChars(env, uniqueId).c_str());
|
||||
}
|
||||
|
||||
jobject logicalFrameObj =
|
||||
env->GetObjectField(viewportObj, gDisplayViewportClassInfo.logicalFrame);
|
||||
viewport->logicalLeft = env->GetIntField(logicalFrameObj, gRectClassInfo.left);
|
||||
viewport->logicalTop = env->GetIntField(logicalFrameObj, gRectClassInfo.top);
|
||||
viewport->logicalRight = env->GetIntField(logicalFrameObj, gRectClassInfo.right);
|
||||
viewport->logicalBottom = env->GetIntField(logicalFrameObj, gRectClassInfo.bottom);
|
||||
|
||||
jobject physicalFrameObj =
|
||||
env->GetObjectField(viewportObj, gDisplayViewportClassInfo.physicalFrame);
|
||||
viewport->physicalLeft = env->GetIntField(physicalFrameObj, gRectClassInfo.left);
|
||||
viewport->physicalTop = env->GetIntField(physicalFrameObj, gRectClassInfo.top);
|
||||
viewport->physicalRight = env->GetIntField(physicalFrameObj, gRectClassInfo.right);
|
||||
viewport->physicalBottom = env->GetIntField(physicalFrameObj, gRectClassInfo.bottom);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
int register_android_hardware_display_DisplayViewport(JNIEnv* env) {
|
||||
jclass clazz = FindClassOrDie(env, "android/hardware/display/DisplayViewport");
|
||||
gDisplayViewportClassInfo.clazz = MakeGlobalRefOrDie(env, clazz);
|
||||
|
||||
gDisplayViewportClassInfo.displayId = GetFieldIDOrDie(env,
|
||||
gDisplayViewportClassInfo.clazz, "displayId", "I");
|
||||
|
||||
gDisplayViewportClassInfo.orientation = GetFieldIDOrDie(env,
|
||||
gDisplayViewportClassInfo.clazz, "orientation", "I");
|
||||
|
||||
gDisplayViewportClassInfo.deviceWidth = GetFieldIDOrDie(env,
|
||||
gDisplayViewportClassInfo.clazz, "deviceWidth", "I");
|
||||
|
||||
gDisplayViewportClassInfo.deviceHeight = GetFieldIDOrDie(env,
|
||||
gDisplayViewportClassInfo.clazz, "deviceHeight", "I");
|
||||
|
||||
gDisplayViewportClassInfo.logicalFrame = GetFieldIDOrDie(env,
|
||||
gDisplayViewportClassInfo.clazz, "logicalFrame", "Landroid/graphics/Rect;");
|
||||
|
||||
gDisplayViewportClassInfo.physicalFrame = GetFieldIDOrDie(env,
|
||||
gDisplayViewportClassInfo.clazz, "physicalFrame", "Landroid/graphics/Rect;");
|
||||
|
||||
gDisplayViewportClassInfo.uniqueId = GetFieldIDOrDie(env,
|
||||
gDisplayViewportClassInfo.clazz, "uniqueId", "Ljava/lang/String;");
|
||||
|
||||
clazz = FindClassOrDie(env, "android/graphics/Rect");
|
||||
gRectClassInfo.left = GetFieldIDOrDie(env, clazz, "left", "I");
|
||||
gRectClassInfo.top = GetFieldIDOrDie(env, clazz, "top", "I");
|
||||
gRectClassInfo.right = GetFieldIDOrDie(env, clazz, "right", "I");
|
||||
gRectClassInfo.bottom = GetFieldIDOrDie(env, clazz, "bottom", "I");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
34
core/jni/android_hardware_display_DisplayViewport.h
Normal file
34
core/jni/android_hardware_display_DisplayViewport.h
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _ANDROID_HARDWARE_DISPLAY_DISPLAYVIEWPORT_H
|
||||
#define _ANDROID_HARDWARE_DISPLAY_DISPLAYVIEWPORT_H
|
||||
|
||||
#include "jni.h"
|
||||
#include <input/DisplayViewport.h>
|
||||
#include <utils/Errors.h>
|
||||
#include <utils/threads.h>
|
||||
|
||||
namespace android {
|
||||
|
||||
/* Copies the contents of a DVM DisplayViewport object to a native DisplayViewport instance.
|
||||
* Returns non-zero on error. */
|
||||
extern status_t android_hardware_display_DisplayViewport_toNative(JNIEnv* env, jobject eventObj,
|
||||
DisplayViewport* viewport);
|
||||
|
||||
} // namespace android
|
||||
|
||||
#endif // _ANDROID_HARDWARE_DISPLAY_DISPLAYVIEWPORT_H
|
||||
@@ -104,7 +104,8 @@ public final class MediaProjection {
|
||||
int flags = isSecure ? DisplayManager.VIRTUAL_DISPLAY_FLAG_SECURE : 0;
|
||||
return dm.createVirtualDisplay(this, name, width, height, dpi, surface,
|
||||
flags | DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR |
|
||||
DisplayManager.VIRTUAL_DISPLAY_FLAG_PRESENTATION, callback, handler);
|
||||
DisplayManager.VIRTUAL_DISPLAY_FLAG_PRESENTATION, callback, handler,
|
||||
null /* uniqueId */);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -134,8 +135,8 @@ public final class MediaProjection {
|
||||
int width, int height, int dpi, int flags, @Nullable Surface surface,
|
||||
@Nullable VirtualDisplay.Callback callback, @Nullable Handler handler) {
|
||||
DisplayManager dm = (DisplayManager) mContext.getSystemService(Context.DISPLAY_SERVICE);
|
||||
return dm.createVirtualDisplay(
|
||||
this, name, width, height, dpi, surface, flags, callback, handler);
|
||||
return dm.createVirtualDisplay(this, name, width, height, dpi, surface, flags, callback,
|
||||
handler, null /* uniqueId */);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -40,6 +40,8 @@ class Vr2dDisplay {
|
||||
private int mVirtualDisplayWidth;
|
||||
private int mVirtualDisplayDpi;
|
||||
private final static int STOP_VIRTUAL_DISPLAY_DELAY_MILLIS = 2000;
|
||||
private final static String UNIQUE_DISPLAY_ID = "277f1a09-b88d-4d1e-8716-796f114d080b";
|
||||
private final static String DISPLAY_NAME = "VR 2D Display";
|
||||
|
||||
private final static String DEBUG_ACTION_SET_MODE =
|
||||
"com.android.server.vr.Vr2dDisplay.SET_MODE";
|
||||
@@ -268,9 +270,11 @@ class Vr2dDisplay {
|
||||
return;
|
||||
}
|
||||
|
||||
mVirtualDisplay = mDisplayManager.createVirtualDisplay("VR 2D Display",
|
||||
mVirtualDisplayWidth, mVirtualDisplayHeight, mVirtualDisplayDpi,
|
||||
null /* Surface */, 0 /* flags */);
|
||||
int flags = DisplayManager.VIRTUAL_DISPLAY_FLAG_SUPPORTS_TOUCH;
|
||||
mVirtualDisplay = mDisplayManager.createVirtualDisplay(null /* projection */,
|
||||
DISPLAY_NAME, mVirtualDisplayWidth, mVirtualDisplayHeight, mVirtualDisplayDpi,
|
||||
null /* surface */, flags, null /* callback */, null /* handler */,
|
||||
UNIQUE_DISPLAY_ID);
|
||||
|
||||
if (mVirtualDisplay != null) {
|
||||
mActivityManagerInternal.setVr2dDisplayId(
|
||||
|
||||
@@ -4978,10 +4978,11 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
|
||||
|
||||
VirtualActivityDisplay(int width, int height, int density) {
|
||||
DisplayManagerGlobal dm = DisplayManagerGlobal.getInstance();
|
||||
mVirtualDisplay = dm.createVirtualDisplay(mService.mContext, null,
|
||||
VIRTUAL_DISPLAY_BASE_NAME, width, height, density, null,
|
||||
mVirtualDisplay = dm.createVirtualDisplay(mService.mContext, null /* projection */,
|
||||
VIRTUAL_DISPLAY_BASE_NAME, width, height, density, null /* surface */,
|
||||
DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC |
|
||||
DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY, null, null);
|
||||
DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY, null /* callback */,
|
||||
null /* handler */, null /* uniqueId */);
|
||||
|
||||
init(mVirtualDisplay.getDisplay());
|
||||
|
||||
|
||||
@@ -112,6 +112,13 @@ final class DisplayDeviceInfo {
|
||||
*/
|
||||
public static final int TOUCH_EXTERNAL = 2;
|
||||
|
||||
/**
|
||||
* Touch attachment: Touch input is via an input device matching {@link VirtualDisplay}'s
|
||||
* uniqueId.
|
||||
* @hide
|
||||
*/
|
||||
public static final int TOUCH_VIRTUAL = 3;
|
||||
|
||||
/**
|
||||
* Diff result: The {@link #state} fields differ.
|
||||
*/
|
||||
@@ -391,6 +398,8 @@ final class DisplayDeviceInfo {
|
||||
return "INTERNAL";
|
||||
case TOUCH_EXTERNAL:
|
||||
return "EXTERNAL";
|
||||
case TOUCH_VIRTUAL:
|
||||
return "VIRTUAL";
|
||||
default:
|
||||
return Integer.toString(touch);
|
||||
}
|
||||
|
||||
@@ -23,10 +23,12 @@ import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_SECUR
|
||||
import static android.hardware.display.DisplayManager
|
||||
.VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.util.DumpUtils;
|
||||
import com.android.internal.util.IndentingPrintWriter;
|
||||
|
||||
import android.Manifest;
|
||||
import android.annotation.NonNull;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.hardware.SensorManager;
|
||||
@@ -213,6 +215,7 @@ public final class DisplayManagerService extends SystemService {
|
||||
// input from an external source. Used by the input system.
|
||||
private final DisplayViewport mDefaultViewport = new DisplayViewport();
|
||||
private final DisplayViewport mExternalTouchViewport = new DisplayViewport();
|
||||
private final ArrayList<DisplayViewport> mVirtualTouchViewports = new ArrayList<>();
|
||||
|
||||
// Persistent data store for all internal settings maintained by the display manager service.
|
||||
private final PersistentDataStore mPersistentDataStore = new PersistentDataStore();
|
||||
@@ -228,6 +231,7 @@ public final class DisplayManagerService extends SystemService {
|
||||
// input system. May be used outside of the lock but only on the handler thread.
|
||||
private final DisplayViewport mTempDefaultViewport = new DisplayViewport();
|
||||
private final DisplayViewport mTempExternalTouchViewport = new DisplayViewport();
|
||||
private final ArrayList<DisplayViewport> mTempVirtualTouchViewports = new ArrayList<>();
|
||||
|
||||
// The default color mode for default displays. Overrides the usual
|
||||
// Display.Display.COLOR_MODE_DEFAULT for displays with the
|
||||
@@ -242,8 +246,16 @@ public final class DisplayManagerService extends SystemService {
|
||||
// Lists of UIDs that are present on the displays. Maps displayId -> array of UIDs.
|
||||
private final SparseArray<IntArray> mDisplayAccessUIDs = new SparseArray<>();
|
||||
|
||||
private final Injector mInjector;
|
||||
|
||||
public DisplayManagerService(Context context) {
|
||||
this(context, new Injector());
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
DisplayManagerService(Context context, Injector injector) {
|
||||
super(context);
|
||||
mInjector = injector;
|
||||
mContext = context;
|
||||
mHandler = new DisplayManagerHandler(DisplayThread.get().getLooper());
|
||||
mUiHandler = UiThread.getHandler();
|
||||
@@ -326,6 +338,11 @@ public final class DisplayManagerService extends SystemService {
|
||||
mHandler.sendEmptyMessage(MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
Handler getDisplayHandler() {
|
||||
return mHandler;
|
||||
}
|
||||
|
||||
private void registerDisplayTransactionListenerInternal(
|
||||
DisplayTransactionListener listener) {
|
||||
// List is self-synchronized copy-on-write.
|
||||
@@ -363,7 +380,8 @@ public final class DisplayManagerService extends SystemService {
|
||||
}
|
||||
}
|
||||
|
||||
private void performTraversalInTransactionFromWindowManagerInternal() {
|
||||
@VisibleForTesting
|
||||
void performTraversalInTransactionFromWindowManagerInternal() {
|
||||
synchronized (mSyncRoot) {
|
||||
if (!mPendingTraversal) {
|
||||
return;
|
||||
@@ -601,8 +619,8 @@ public final class DisplayManagerService extends SystemService {
|
||||
}
|
||||
|
||||
private int createVirtualDisplayInternal(IVirtualDisplayCallback callback,
|
||||
IMediaProjection projection, int callingUid, String packageName,
|
||||
String name, int width, int height, int densityDpi, Surface surface, int flags) {
|
||||
IMediaProjection projection, int callingUid, String packageName, String name, int width,
|
||||
int height, int densityDpi, Surface surface, int flags, String uniqueId) {
|
||||
synchronized (mSyncRoot) {
|
||||
if (mVirtualDisplayAdapter == null) {
|
||||
Slog.w(TAG, "Rejecting request to create private virtual display "
|
||||
@@ -611,8 +629,8 @@ public final class DisplayManagerService extends SystemService {
|
||||
}
|
||||
|
||||
DisplayDevice device = mVirtualDisplayAdapter.createVirtualDisplayLocked(
|
||||
callback, projection, callingUid, packageName,
|
||||
name, width, height, densityDpi, surface, flags);
|
||||
callback, projection, callingUid, packageName, name, width, height, densityDpi,
|
||||
surface, flags, uniqueId);
|
||||
if (device == null) {
|
||||
return -1;
|
||||
}
|
||||
@@ -702,8 +720,8 @@ public final class DisplayManagerService extends SystemService {
|
||||
}
|
||||
|
||||
private void registerVirtualDisplayAdapterLocked() {
|
||||
mVirtualDisplayAdapter = new VirtualDisplayAdapter(
|
||||
mSyncRoot, mContext, mHandler, mDisplayAdapterListener);
|
||||
mVirtualDisplayAdapter = mInjector.getVirtualDisplayAdapter(mSyncRoot, mContext, mHandler,
|
||||
mDisplayAdapterListener);
|
||||
registerDisplayAdapterLocked(mVirtualDisplayAdapter);
|
||||
}
|
||||
|
||||
@@ -995,6 +1013,7 @@ public final class DisplayManagerService extends SystemService {
|
||||
private void clearViewportsLocked() {
|
||||
mDefaultViewport.valid = false;
|
||||
mExternalTouchViewport.valid = false;
|
||||
mVirtualTouchViewports.clear();
|
||||
}
|
||||
|
||||
private void configureDisplayInTransactionLocked(DisplayDevice device) {
|
||||
@@ -1033,6 +1052,28 @@ public final class DisplayManagerService extends SystemService {
|
||||
&& info.touch == DisplayDeviceInfo.TOUCH_EXTERNAL) {
|
||||
setViewportLocked(mExternalTouchViewport, display, device);
|
||||
}
|
||||
|
||||
if (info.touch == DisplayDeviceInfo.TOUCH_VIRTUAL && !TextUtils.isEmpty(info.uniqueId)) {
|
||||
final DisplayViewport viewport = getVirtualTouchViewportLocked(info.uniqueId);
|
||||
setViewportLocked(viewport, display, device);
|
||||
}
|
||||
}
|
||||
|
||||
/** Gets the virtual device viewport or creates it if not yet created. */
|
||||
private DisplayViewport getVirtualTouchViewportLocked(@NonNull String uniqueId) {
|
||||
DisplayViewport viewport;
|
||||
final int count = mVirtualTouchViewports.size();
|
||||
for (int i = 0; i < count; i++) {
|
||||
viewport = mVirtualTouchViewports.get(i);
|
||||
if (uniqueId.equals(viewport.uniqueId)) {
|
||||
return viewport;
|
||||
}
|
||||
}
|
||||
|
||||
viewport = new DisplayViewport();
|
||||
viewport.uniqueId = uniqueId;
|
||||
mVirtualTouchViewports.add(viewport);
|
||||
return viewport;
|
||||
}
|
||||
|
||||
private static void setViewportLocked(DisplayViewport viewport,
|
||||
@@ -1113,6 +1154,7 @@ public final class DisplayManagerService extends SystemService {
|
||||
pw.println(" mNextNonDefaultDisplayId=" + mNextNonDefaultDisplayId);
|
||||
pw.println(" mDefaultViewport=" + mDefaultViewport);
|
||||
pw.println(" mExternalTouchViewport=" + mExternalTouchViewport);
|
||||
pw.println(" mVirtualTouchViewports=" + mVirtualTouchViewports);
|
||||
pw.println(" mDefaultDisplayDefaultColorMode=" + mDefaultDisplayDefaultColorMode);
|
||||
pw.println(" mSingleDisplayDemoMode=" + mSingleDisplayDemoMode);
|
||||
pw.println(" mWifiDisplayScanRequestCount=" + mWifiDisplayScanRequestCount);
|
||||
@@ -1171,6 +1213,14 @@ public final class DisplayManagerService extends SystemService {
|
||||
public static final class SyncRoot {
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
static class Injector {
|
||||
VirtualDisplayAdapter getVirtualDisplayAdapter(SyncRoot syncRoot, Context context,
|
||||
Handler handler, DisplayAdapter.Listener displayAdapterListener) {
|
||||
return new VirtualDisplayAdapter(syncRoot, context, handler, displayAdapterListener);
|
||||
}
|
||||
}
|
||||
|
||||
private final class DisplayManagerHandler extends Handler {
|
||||
public DisplayManagerHandler(Looper looper) {
|
||||
super(looper, null, true /*async*/);
|
||||
@@ -1199,9 +1249,15 @@ public final class DisplayManagerService extends SystemService {
|
||||
synchronized (mSyncRoot) {
|
||||
mTempDefaultViewport.copyFrom(mDefaultViewport);
|
||||
mTempExternalTouchViewport.copyFrom(mExternalTouchViewport);
|
||||
if (!mTempVirtualTouchViewports.equals(mVirtualTouchViewports)) {
|
||||
mTempVirtualTouchViewports.clear();
|
||||
for (DisplayViewport d : mVirtualTouchViewports) {
|
||||
mTempVirtualTouchViewports.add(d.makeCopy());
|
||||
}
|
||||
}
|
||||
}
|
||||
mInputManagerInternal.setDisplayViewports(
|
||||
mTempDefaultViewport, mTempExternalTouchViewport);
|
||||
mInputManagerInternal.setDisplayViewports(mTempDefaultViewport,
|
||||
mTempExternalTouchViewport, mTempVirtualTouchViewports);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1264,7 +1320,8 @@ public final class DisplayManagerService extends SystemService {
|
||||
}
|
||||
}
|
||||
|
||||
private final class BinderService extends IDisplayManager.Stub {
|
||||
@VisibleForTesting
|
||||
final class BinderService extends IDisplayManager.Stub {
|
||||
/**
|
||||
* Returns information about the specified logical display.
|
||||
*
|
||||
@@ -1458,7 +1515,8 @@ public final class DisplayManagerService extends SystemService {
|
||||
@Override // Binder call
|
||||
public int createVirtualDisplay(IVirtualDisplayCallback callback,
|
||||
IMediaProjection projection, String packageName, String name,
|
||||
int width, int height, int densityDpi, Surface surface, int flags) {
|
||||
int width, int height, int densityDpi, Surface surface, int flags,
|
||||
String uniqueId) {
|
||||
final int callingUid = Binder.getCallingUid();
|
||||
if (!validatePackageName(callingUid, packageName)) {
|
||||
throw new SecurityException("packageName must match the calling uid");
|
||||
@@ -1520,8 +1578,8 @@ public final class DisplayManagerService extends SystemService {
|
||||
|
||||
final long token = Binder.clearCallingIdentity();
|
||||
try {
|
||||
return createVirtualDisplayInternal(callback, projection, callingUid,
|
||||
packageName, name, width, height, densityDpi, surface, flags);
|
||||
return createVirtualDisplayInternal(callback, projection, callingUid, packageName,
|
||||
name, width, height, densityDpi, surface, flags, uniqueId);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(token);
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import static android.hardware.display.DisplayManager
|
||||
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_PRESENTATION;
|
||||
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC;
|
||||
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_SECURE;
|
||||
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_SUPPORTS_TOUCH;
|
||||
|
||||
import android.content.Context;
|
||||
import android.hardware.display.IVirtualDisplayCallback;
|
||||
@@ -39,6 +40,8 @@ import android.view.Display;
|
||||
import android.view.Surface;
|
||||
import android.view.SurfaceControl;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.util.Iterator;
|
||||
|
||||
@@ -48,7 +51,8 @@ import java.util.Iterator;
|
||||
* Display adapters are guarded by the {@link DisplayManagerService.SyncRoot} lock.
|
||||
* </p>
|
||||
*/
|
||||
final class VirtualDisplayAdapter extends DisplayAdapter {
|
||||
@VisibleForTesting
|
||||
public class VirtualDisplayAdapter extends DisplayAdapter {
|
||||
static final String TAG = "VirtualDisplayAdapter";
|
||||
static final boolean DEBUG = false;
|
||||
|
||||
@@ -57,27 +61,42 @@ final class VirtualDisplayAdapter extends DisplayAdapter {
|
||||
|
||||
private final ArrayMap<IBinder, VirtualDisplayDevice> mVirtualDisplayDevices =
|
||||
new ArrayMap<IBinder, VirtualDisplayDevice>();
|
||||
private Handler mHandler;
|
||||
private final Handler mHandler;
|
||||
private final SurfaceControlDisplayFactory mSurfaceControlDisplayFactory;
|
||||
|
||||
// Called with SyncRoot lock held.
|
||||
public VirtualDisplayAdapter(DisplayManagerService.SyncRoot syncRoot,
|
||||
Context context, Handler handler, Listener listener) {
|
||||
this(syncRoot, context, handler, listener,
|
||||
(String name, boolean secure) -> SurfaceControl.createDisplay(name, secure));
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
VirtualDisplayAdapter(DisplayManagerService.SyncRoot syncRoot,
|
||||
Context context, Handler handler, Listener listener,
|
||||
SurfaceControlDisplayFactory surfaceControlDisplayFactory) {
|
||||
super(syncRoot, context, handler, listener, TAG);
|
||||
mHandler = handler;
|
||||
mSurfaceControlDisplayFactory = surfaceControlDisplayFactory;
|
||||
}
|
||||
|
||||
public DisplayDevice createVirtualDisplayLocked(IVirtualDisplayCallback callback,
|
||||
IMediaProjection projection, int ownerUid, String ownerPackageName,
|
||||
String name, int width, int height, int densityDpi, Surface surface, int flags) {
|
||||
IMediaProjection projection, int ownerUid, String ownerPackageName, String name,
|
||||
int width, int height, int densityDpi, Surface surface, int flags, String uniqueId) {
|
||||
boolean secure = (flags & VIRTUAL_DISPLAY_FLAG_SECURE) != 0;
|
||||
IBinder appToken = callback.asBinder();
|
||||
IBinder displayToken = SurfaceControl.createDisplay(name, secure);
|
||||
IBinder displayToken = mSurfaceControlDisplayFactory.createDisplay(name, secure);
|
||||
final String baseUniqueId =
|
||||
UNIQUE_ID_PREFIX + ownerPackageName + "," + ownerUid + "," + name + ",";
|
||||
final int uniqueIndex = getNextUniqueIndex(baseUniqueId);
|
||||
if (uniqueId == null) {
|
||||
uniqueId = baseUniqueId + uniqueIndex;
|
||||
} else {
|
||||
uniqueId = UNIQUE_ID_PREFIX + ownerPackageName + ":" + uniqueId;
|
||||
}
|
||||
VirtualDisplayDevice device = new VirtualDisplayDevice(displayToken, appToken,
|
||||
ownerUid, ownerPackageName, name, width, height, densityDpi, surface, flags,
|
||||
new Callback(callback, mHandler), baseUniqueId + uniqueIndex, uniqueIndex);
|
||||
new Callback(callback, mHandler), uniqueId, uniqueIndex);
|
||||
|
||||
mVirtualDisplayDevices.put(appToken, device);
|
||||
|
||||
@@ -341,7 +360,8 @@ final class VirtualDisplayAdapter extends DisplayAdapter {
|
||||
mInfo.flags |= DisplayDeviceInfo.FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD;
|
||||
}
|
||||
mInfo.type = Display.TYPE_VIRTUAL;
|
||||
mInfo.touch = DisplayDeviceInfo.TOUCH_NONE;
|
||||
mInfo.touch = ((mFlags & VIRTUAL_DISPLAY_FLAG_SUPPORTS_TOUCH) == 0) ?
|
||||
DisplayDeviceInfo.TOUCH_NONE : DisplayDeviceInfo.TOUCH_VIRTUAL;
|
||||
mInfo.state = mSurface != null ? Display.STATE_ON : Display.STATE_OFF;
|
||||
mInfo.ownerUid = mOwnerUid;
|
||||
mInfo.ownerPackageName = mOwnerPackageName;
|
||||
@@ -407,4 +427,9 @@ final class VirtualDisplayAdapter extends DisplayAdapter {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public interface SurfaceControlDisplayFactory {
|
||||
public IBinder createDisplay(String name, boolean secure);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -190,11 +190,13 @@ public class InputManagerService extends IInputManager.Stub
|
||||
private static native long nativeInit(InputManagerService service,
|
||||
Context context, MessageQueue messageQueue);
|
||||
private static native void nativeStart(long ptr);
|
||||
private static native void nativeSetDisplayViewport(long ptr, boolean external,
|
||||
private static native void nativeSetVirtualDisplayViewports(long ptr,
|
||||
DisplayViewport[] viewports);
|
||||
private static native void nativeSetDisplayViewport(long ptr, int viewportType,
|
||||
int displayId, int rotation,
|
||||
int logicalLeft, int logicalTop, int logicalRight, int logicalBottom,
|
||||
int physicalLeft, int physicalTop, int physicalRight, int physicalBottom,
|
||||
int deviceWidth, int deviceHeight);
|
||||
int deviceWidth, int deviceHeight, String uniqueId);
|
||||
|
||||
private static native int nativeGetScanCodeState(long ptr,
|
||||
int deviceId, int sourceMask, int scanCode);
|
||||
@@ -289,6 +291,11 @@ public class InputManagerService extends IInputManager.Stub
|
||||
/** Switch code: Camera lens cover. When set the lens is covered. */
|
||||
public static final int SW_CAMERA_LENS_COVER = 0x09;
|
||||
|
||||
// Viewport constants defined in InputReader.h.
|
||||
public static final int VIEWPORT_DEFAULT = 1;
|
||||
public static final int VIEWPORT_EXTERNAL = 2;
|
||||
public static final int VIEWPORT_VIRTUAL = 3;
|
||||
|
||||
public static final int SW_LID_BIT = 1 << SW_LID;
|
||||
public static final int SW_TABLET_MODE_BIT = 1 << SW_TABLET_MODE;
|
||||
public static final int SW_KEYPAD_SLIDE_BIT = 1 << SW_KEYPAD_SLIDE;
|
||||
@@ -406,26 +413,30 @@ public class InputManagerService extends IInputManager.Stub
|
||||
}
|
||||
|
||||
private void setDisplayViewportsInternal(DisplayViewport defaultViewport,
|
||||
DisplayViewport externalTouchViewport) {
|
||||
DisplayViewport externalTouchViewport,
|
||||
List<DisplayViewport> virtualTouchViewports) {
|
||||
if (defaultViewport.valid) {
|
||||
setDisplayViewport(false, defaultViewport);
|
||||
setDisplayViewport(VIEWPORT_DEFAULT, defaultViewport);
|
||||
}
|
||||
|
||||
if (externalTouchViewport.valid) {
|
||||
setDisplayViewport(true, externalTouchViewport);
|
||||
setDisplayViewport(VIEWPORT_EXTERNAL, externalTouchViewport);
|
||||
} else if (defaultViewport.valid) {
|
||||
setDisplayViewport(true, defaultViewport);
|
||||
setDisplayViewport(VIEWPORT_EXTERNAL, defaultViewport);
|
||||
}
|
||||
|
||||
nativeSetVirtualDisplayViewports(mPtr,
|
||||
virtualTouchViewports.toArray(new DisplayViewport[0]));
|
||||
}
|
||||
|
||||
private void setDisplayViewport(boolean external, DisplayViewport viewport) {
|
||||
nativeSetDisplayViewport(mPtr, external,
|
||||
private void setDisplayViewport(int viewportType, DisplayViewport viewport) {
|
||||
nativeSetDisplayViewport(mPtr, viewportType,
|
||||
viewport.displayId, viewport.orientation,
|
||||
viewport.logicalFrame.left, viewport.logicalFrame.top,
|
||||
viewport.logicalFrame.right, viewport.logicalFrame.bottom,
|
||||
viewport.physicalFrame.left, viewport.physicalFrame.top,
|
||||
viewport.physicalFrame.right, viewport.physicalFrame.bottom,
|
||||
viewport.deviceWidth, viewport.deviceHeight);
|
||||
viewport.deviceWidth, viewport.deviceHeight, viewport.uniqueId);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2296,9 +2307,11 @@ public class InputManagerService extends IInputManager.Stub
|
||||
|
||||
private final class LocalService extends InputManagerInternal {
|
||||
@Override
|
||||
public void setDisplayViewports(
|
||||
DisplayViewport defaultViewport, DisplayViewport externalTouchViewport) {
|
||||
setDisplayViewportsInternal(defaultViewport, externalTouchViewport);
|
||||
public void setDisplayViewports(DisplayViewport defaultViewport,
|
||||
DisplayViewport externalTouchViewport,
|
||||
List<DisplayViewport> virtualTouchViewports) {
|
||||
setDisplayViewportsInternal(defaultViewport, externalTouchViewport,
|
||||
virtualTouchViewports);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -57,6 +57,7 @@
|
||||
#include "com_android_server_power_PowerManagerService.h"
|
||||
#include "com_android_server_input_InputApplicationHandle.h"
|
||||
#include "com_android_server_input_InputWindowHandle.h"
|
||||
#include "android_hardware_display_DisplayViewport.h"
|
||||
|
||||
#define INDENT " "
|
||||
|
||||
@@ -190,7 +191,8 @@ public:
|
||||
|
||||
void dump(String8& dump);
|
||||
|
||||
void setDisplayViewport(bool external, const DisplayViewport& viewport);
|
||||
void setVirtualDisplayViewports(JNIEnv* env, jobjectArray viewportObjArray);
|
||||
void setDisplayViewport(int32_t viewportType, const DisplayViewport& viewport);
|
||||
|
||||
status_t registerInputChannel(JNIEnv* env, const sp<InputChannel>& inputChannel,
|
||||
const sp<InputWindowHandle>& inputWindowHandle, bool monitor);
|
||||
@@ -264,6 +266,7 @@ private:
|
||||
// Display size information.
|
||||
DisplayViewport internalViewport;
|
||||
DisplayViewport externalViewport;
|
||||
Vector<DisplayViewport> virtualViewports;
|
||||
|
||||
// System UI visibility.
|
||||
int32_t systemUiVisibility;
|
||||
@@ -365,17 +368,53 @@ bool NativeInputManager::checkAndClearExceptionFromCallback(JNIEnv* env, const c
|
||||
return false;
|
||||
}
|
||||
|
||||
void NativeInputManager::setDisplayViewport(bool external, const DisplayViewport& viewport) {
|
||||
void NativeInputManager::setVirtualDisplayViewports(JNIEnv* env, jobjectArray viewportObjArray) {
|
||||
Vector<DisplayViewport> viewports;
|
||||
|
||||
if (viewportObjArray) {
|
||||
jsize length = env->GetArrayLength(viewportObjArray);
|
||||
for (jsize i = 0; i < length; i++) {
|
||||
jobject viewportObj = env->GetObjectArrayElement(viewportObjArray, i);
|
||||
if (! viewportObj) {
|
||||
break; // found null element indicating end of used portion of the array
|
||||
}
|
||||
|
||||
DisplayViewport viewport;
|
||||
android_hardware_display_DisplayViewport_toNative(env, viewportObj, &viewport);
|
||||
ALOGI("Viewport [%d] to add: %s", (int) length, viewport.uniqueId.c_str());
|
||||
viewports.push(viewport);
|
||||
|
||||
env->DeleteLocalRef(viewportObj);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
AutoMutex _l(mLock);
|
||||
mLocked.virtualViewports = viewports;
|
||||
}
|
||||
|
||||
mInputManager->getReader()->requestRefreshConfiguration(
|
||||
InputReaderConfiguration::CHANGE_DISPLAY_INFO);
|
||||
}
|
||||
|
||||
void NativeInputManager::setDisplayViewport(int32_t type, const DisplayViewport& viewport) {
|
||||
bool changed = false;
|
||||
{
|
||||
AutoMutex _l(mLock);
|
||||
|
||||
DisplayViewport& v = external ? mLocked.externalViewport : mLocked.internalViewport;
|
||||
if (v != viewport) {
|
||||
changed = true;
|
||||
v = viewport;
|
||||
ViewportType viewportType = static_cast<ViewportType>(type);
|
||||
DisplayViewport* v = NULL;
|
||||
if (viewportType == ViewportType::VIEWPORT_EXTERNAL) {
|
||||
v = &mLocked.externalViewport;
|
||||
} else if (viewportType == ViewportType::VIEWPORT_INTERNAL) {
|
||||
v = &mLocked.internalViewport;
|
||||
}
|
||||
|
||||
if (!external) {
|
||||
if (v != NULL && *v != viewport) {
|
||||
changed = true;
|
||||
*v = viewport;
|
||||
|
||||
if (viewportType == ViewportType::VIEWPORT_INTERNAL) {
|
||||
sp<PointerController> controller = mLocked.pointerController.promote();
|
||||
if (controller != NULL) {
|
||||
controller->setDisplayViewport(
|
||||
@@ -468,8 +507,11 @@ void NativeInputManager::getReaderConfiguration(InputReaderConfiguration* outCon
|
||||
|
||||
outConfig->pointerCapture = mLocked.pointerCapture;
|
||||
|
||||
outConfig->setDisplayInfo(false /*external*/, mLocked.internalViewport);
|
||||
outConfig->setDisplayInfo(true /*external*/, mLocked.externalViewport);
|
||||
outConfig->setPhysicalDisplayViewport(ViewportType::VIEWPORT_INTERNAL,
|
||||
mLocked.internalViewport);
|
||||
outConfig->setPhysicalDisplayViewport(ViewportType::VIEWPORT_EXTERNAL,
|
||||
mLocked.externalViewport);
|
||||
outConfig->setVirtualDisplayViewports(mLocked.virtualViewports);
|
||||
} // release lock
|
||||
}
|
||||
|
||||
@@ -1153,11 +1195,17 @@ static void nativeStart(JNIEnv* env, jclass /* clazz */, jlong ptr) {
|
||||
}
|
||||
}
|
||||
|
||||
static void nativeSetDisplayViewport(JNIEnv* /* env */, jclass /* clazz */, jlong ptr,
|
||||
jboolean external, jint displayId, jint orientation,
|
||||
static void nativeSetVirtualDisplayViewports(JNIEnv* env, jclass /* clazz */, jlong ptr,
|
||||
jobjectArray viewportObjArray) {
|
||||
NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
|
||||
im->setVirtualDisplayViewports(env, viewportObjArray);
|
||||
}
|
||||
|
||||
static void nativeSetDisplayViewport(JNIEnv* env, jclass /* clazz */, jlong ptr,
|
||||
jint viewportType, jint displayId, jint orientation,
|
||||
jint logicalLeft, jint logicalTop, jint logicalRight, jint logicalBottom,
|
||||
jint physicalLeft, jint physicalTop, jint physicalRight, jint physicalBottom,
|
||||
jint deviceWidth, jint deviceHeight) {
|
||||
jint deviceWidth, jint deviceHeight, jstring uniqueId) {
|
||||
NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
|
||||
|
||||
DisplayViewport v;
|
||||
@@ -1173,7 +1221,11 @@ static void nativeSetDisplayViewport(JNIEnv* /* env */, jclass /* clazz */, jlon
|
||||
v.physicalBottom = physicalBottom;
|
||||
v.deviceWidth = deviceWidth;
|
||||
v.deviceHeight = deviceHeight;
|
||||
im->setDisplayViewport(external, v);
|
||||
if (uniqueId != nullptr) {
|
||||
v.uniqueId.setTo(ScopedUtfChars(env, uniqueId).c_str());
|
||||
}
|
||||
|
||||
im->setDisplayViewport(viewportType, v);
|
||||
}
|
||||
|
||||
static jint nativeGetScanCodeState(JNIEnv* /* env */, jclass /* clazz */,
|
||||
@@ -1514,7 +1566,9 @@ static const JNINativeMethod gInputManagerMethods[] = {
|
||||
(void*) nativeInit },
|
||||
{ "nativeStart", "(J)V",
|
||||
(void*) nativeStart },
|
||||
{ "nativeSetDisplayViewport", "(JZIIIIIIIIIIII)V",
|
||||
{ "nativeSetVirtualDisplayViewports", "(J[Landroid/hardware/display/DisplayViewport;)V",
|
||||
(void*) nativeSetVirtualDisplayViewports },
|
||||
{ "nativeSetDisplayViewport", "(JIIIIIIIIIIIIILjava/lang/String;)V",
|
||||
(void*) nativeSetDisplayViewport },
|
||||
{ "nativeGetScanCodeState", "(JIII)I",
|
||||
(void*) nativeGetScanCodeState },
|
||||
|
||||
@@ -47,6 +47,7 @@ int register_android_server_Watchdog(JNIEnv* env);
|
||||
int register_android_server_HardwarePropertiesManagerService(JNIEnv* env);
|
||||
int register_android_server_SyntheticPasswordManager(JNIEnv* env);
|
||||
int register_android_server_GraphicsStatsService(JNIEnv* env);
|
||||
int register_android_hardware_display_DisplayViewport(JNIEnv* env);
|
||||
};
|
||||
|
||||
using namespace android;
|
||||
@@ -89,6 +90,7 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
|
||||
register_android_server_storage_AppFuse(env);
|
||||
register_android_server_SyntheticPasswordManager(env);
|
||||
register_android_server_GraphicsStatsService(env);
|
||||
register_android_hardware_display_DisplayViewport(env);
|
||||
|
||||
return JNI_VERSION_1_4;
|
||||
}
|
||||
|
||||
@@ -191,7 +191,7 @@
|
||||
</application>
|
||||
|
||||
<instrumentation
|
||||
android:name="android.support.test.runner.AndroidJUnitRunner"
|
||||
android:targetPackage="com.android.frameworks.servicestests"
|
||||
android:label="Frameworks Services Tests" />
|
||||
android:name="android.support.test.runner.AndroidJUnitRunner"
|
||||
android:targetPackage="com.android.frameworks.servicestests"
|
||||
android:label="Frameworks Services Tests" />
|
||||
</manifest>
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* 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 com.android.server.display;
|
||||
|
||||
import android.content.Context;
|
||||
import android.hardware.display.DisplayManager;
|
||||
import android.hardware.display.DisplayViewport;
|
||||
import android.hardware.display.IVirtualDisplayCallback;
|
||||
import android.hardware.input.InputManagerInternal;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.test.AndroidTestCase;
|
||||
import android.test.suitebuilder.annotation.SmallTest;
|
||||
import android.view.SurfaceControl;
|
||||
import android.view.WindowManagerInternal;
|
||||
|
||||
import com.android.server.LocalServices;
|
||||
import com.android.server.display.DisplayManagerService.SyncRoot;
|
||||
import com.android.server.display.VirtualDisplayAdapter.SurfaceControlDisplayFactory;
|
||||
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@SmallTest
|
||||
public class DisplayManagerServiceTest extends AndroidTestCase {
|
||||
private Handler mHandler;
|
||||
private DisplayManagerService mDisplayManager;
|
||||
@Mock InputManagerInternal mMockInputManagerInternal;
|
||||
@Mock IVirtualDisplayCallback.Stub mMockAppToken;
|
||||
@Mock WindowManagerInternal mMockWindowManagerInternal;
|
||||
@Mock VirtualDisplayAdapter mMockVirtualDisplayAdapter;
|
||||
@Mock IBinder mMockDisplayToken;
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mDisplayManager = new DisplayManagerService(mContext,
|
||||
new DisplayManagerService.Injector() {
|
||||
@Override
|
||||
VirtualDisplayAdapter getVirtualDisplayAdapter(SyncRoot syncRoot, Context context,
|
||||
Handler handler, DisplayAdapter.Listener displayAdapterListener) {
|
||||
return new VirtualDisplayAdapter(syncRoot, context, handler, displayAdapterListener,
|
||||
(String name, boolean secure) -> mMockDisplayToken);
|
||||
}
|
||||
});
|
||||
mHandler = mDisplayManager.getDisplayHandler();
|
||||
|
||||
LocalServices.removeServiceForTest(InputManagerInternal.class);
|
||||
LocalServices.addService(InputManagerInternal.class, mMockInputManagerInternal);
|
||||
LocalServices.removeServiceForTest(WindowManagerInternal.class);
|
||||
LocalServices.addService(WindowManagerInternal.class, mMockWindowManagerInternal);
|
||||
|
||||
mDisplayManager.systemReady(false /* safeMode */, false /* onlyCore */);
|
||||
mDisplayManager.windowManagerAndInputReady();
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
public void testCreateVirtualDisplay_sentToInputManager() throws Exception {
|
||||
// This is effectively the DisplayManager service published to ServiceManager.
|
||||
DisplayManagerService.BinderService bs = mDisplayManager.new BinderService();
|
||||
|
||||
String uniqueId = "uniqueId --- Test";
|
||||
String uniqueIdPrefix = "virtual:" + mContext.getPackageName() + ":";
|
||||
int width = 600;
|
||||
int height = 800;
|
||||
int dpi = 320;
|
||||
int flags = DisplayManager.VIRTUAL_DISPLAY_FLAG_SUPPORTS_TOUCH;
|
||||
|
||||
when(mMockAppToken.asBinder()).thenReturn(mMockAppToken);
|
||||
int displayId = bs.createVirtualDisplay(mMockAppToken /* callback */,
|
||||
null /* projection */, "com.android.frameworks.servicestests",
|
||||
"Test Virtual Display", width, height, dpi, null /* surface */, flags /* flags */,
|
||||
uniqueId);
|
||||
|
||||
mDisplayManager.performTraversalInTransactionFromWindowManagerInternal();
|
||||
|
||||
// flush the handler
|
||||
mHandler.runWithScissors(() -> {}, 0 /* now */);
|
||||
|
||||
ArgumentCaptor<List<DisplayViewport>> virtualViewportCaptor =
|
||||
ArgumentCaptor.forClass(List.class);
|
||||
verify(mMockInputManagerInternal).setDisplayViewports(
|
||||
any(), any(), virtualViewportCaptor.capture());
|
||||
|
||||
assertEquals(1, virtualViewportCaptor.getValue().size());
|
||||
DisplayViewport dv = virtualViewportCaptor.getValue().get(0);
|
||||
assertEquals(height, dv.deviceHeight);
|
||||
assertEquals(width, dv.deviceWidth);
|
||||
assertEquals(uniqueIdPrefix + uniqueId, dv.uniqueId);
|
||||
assertEquals(displayId, dv.displayId);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user