Add type to DisplayViewport
Refactor DisplayViewport to treat internal, external, and virtual
display viewports more equally. Now stored in single array, and mLocked
contains the most up-to-date copy of these. Still enforce the
requirement that there can only be 1 internal and 1 external viewport.
We should remove this requirement in the future.
Bug: 111108021
Test: atest DisplayManagerServiceTest
Change-Id: I6fca9725f6e4180063c86f3c2bc34906ac1d0024
diff --git a/services/core/java/com/android/server/display/DisplayDevice.java b/services/core/java/com/android/server/display/DisplayDevice.java
index 2405925..7bfe9ce 100644
--- a/services/core/java/com/android/server/display/DisplayDevice.java
+++ b/services/core/java/com/android/server/display/DisplayDevice.java
@@ -19,7 +19,6 @@
import android.graphics.Rect;
import android.hardware.display.DisplayViewport;
import android.os.IBinder;
-import android.view.Display;
import android.view.Surface;
import android.view.SurfaceControl;
@@ -224,6 +223,8 @@
DisplayDeviceInfo info = getDisplayDeviceInfoLocked();
viewport.deviceWidth = isRotated ? info.height : info.width;
viewport.deviceHeight = isRotated ? info.width : info.height;
+
+ viewport.uniqueId = info.uniqueId;
}
/**
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 0eff7f5..e70460a 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -17,15 +17,14 @@
package com.android.server.display;
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR;
+import static android.hardware.display.DisplayManager
+ .VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD;
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY;
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_CAN_SHOW_WITH_INSECURE_KEYGUARD;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.DumpUtils;
-import com.android.internal.util.IndentingPrintWriter;
+import static android.hardware.display.DisplayViewport.VIEWPORT_EXTERNAL;
+import static android.hardware.display.DisplayViewport.VIEWPORT_INTERNAL;
+import static android.hardware.display.DisplayViewport.VIEWPORT_VIRTUAL;
import android.Manifest;
import android.annotation.NonNull;
@@ -45,8 +44,8 @@
import android.hardware.display.Curve;
import android.hardware.display.DisplayManagerGlobal;
import android.hardware.display.DisplayManagerInternal;
-import android.hardware.display.DisplayViewport;
import android.hardware.display.DisplayManagerInternal.DisplayTransactionListener;
+import android.hardware.display.DisplayViewport;
import android.hardware.display.IDisplayManager;
import android.hardware.display.IDisplayManagerCallback;
import android.hardware.display.IVirtualDisplayCallback;
@@ -83,14 +82,17 @@
import android.view.Surface;
import android.view.SurfaceControl;
-import com.android.internal.util.Preconditions;
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.DumpUtils;
+import com.android.internal.util.IndentingPrintWriter;
import com.android.server.AnimationThread;
import com.android.server.DisplayThread;
import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.UiThread;
-import com.android.server.wm.WindowManagerInternal;
import com.android.server.wm.SurfaceAnimationThread;
+import com.android.server.wm.WindowManagerInternal;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -256,9 +258,8 @@
// Viewports of the default display and the display that should receive touch
// 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<>();
+ @GuardedBy("mSyncRoot")
+ private final ArrayList<DisplayViewport> mViewports = new ArrayList<>();
// Persistent data store for all internal settings maintained by the display manager service.
private final PersistentDataStore mPersistentDataStore = new PersistentDataStore();
@@ -272,9 +273,7 @@
// Temporary viewports, used when sending new viewport information to the
// 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<>();
+ private final ArrayList<DisplayViewport> mTempViewports = new ArrayList<>();
// The default color mode for default displays. Overrides the usual
// Display.Display.COLOR_MODE_DEFAULT for displays with the
@@ -1255,9 +1254,7 @@
}
private void clearViewportsLocked() {
- mDefaultViewport.valid = false;
- mExternalTouchViewport.valid = false;
- mVirtualTouchViewports.clear();
+ mViewports.clear();
}
private void configureDisplayLocked(SurfaceControl.Transaction t, DisplayDevice device) {
@@ -1287,40 +1284,89 @@
}
display.configureDisplayLocked(t, device, info.state == Display.STATE_OFF);
- // Update the viewports if needed.
- if (!mDefaultViewport.valid
- && (info.flags & DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY) != 0) {
- setViewportLocked(mDefaultViewport, display, device);
+ // Update the corresponding viewport.
+ DisplayViewport internalViewport = getInternalViewportLocked();
+ if ((info.flags & DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY) != 0) {
+ populateViewportLocked(internalViewport, display, device);
}
- if (!mExternalTouchViewport.valid
- && info.touch == DisplayDeviceInfo.TOUCH_EXTERNAL) {
- setViewportLocked(mExternalTouchViewport, display, device);
+ DisplayViewport externalViewport = getExternalViewportLocked();
+ if (info.touch == DisplayDeviceInfo.TOUCH_EXTERNAL) {
+ populateViewportLocked(externalViewport, display, device);
+ } else if (!externalViewport.valid) {
+ // TODO (b/116850516) move this logic into InputReader
+ externalViewport.copyFrom(internalViewport);
+ externalViewport.type = DisplayViewport.VIEWPORT_EXTERNAL;
}
if (info.touch == DisplayDeviceInfo.TOUCH_VIRTUAL && !TextUtils.isEmpty(info.uniqueId)) {
- final DisplayViewport viewport = getVirtualTouchViewportLocked(info.uniqueId);
- setViewportLocked(viewport, display, device);
+ final DisplayViewport viewport = getVirtualViewportLocked(info.uniqueId);
+ populateViewportLocked(viewport, display, device);
}
}
- /** Gets the virtual device viewport or creates it if not yet created. */
- private DisplayViewport getVirtualTouchViewportLocked(@NonNull String uniqueId) {
+ /** Get the virtual device viewport that has the specified uniqueId.
+ * If such viewport does not exist, create it. */
+ private DisplayViewport getVirtualViewportLocked(@NonNull String uniqueId) {
DisplayViewport viewport;
- final int count = mVirtualTouchViewports.size();
+ final int count = mViewports.size();
for (int i = 0; i < count; i++) {
- viewport = mVirtualTouchViewports.get(i);
+ viewport = mViewports.get(i);
if (uniqueId.equals(viewport.uniqueId)) {
+ if (viewport.type != VIEWPORT_VIRTUAL) {
+ Slog.wtf(TAG, "Found a viewport with uniqueId '" + uniqueId
+ + "' but it has type " + DisplayViewport.typeToString(viewport.type)
+ + " (expected VIRTUAL)");
+ continue;
+ }
return viewport;
}
}
viewport = new DisplayViewport();
viewport.uniqueId = uniqueId;
- mVirtualTouchViewports.add(viewport);
+ viewport.type = VIEWPORT_VIRTUAL;
+ mViewports.add(viewport);
return viewport;
}
- private static void setViewportLocked(DisplayViewport viewport,
+ private DisplayViewport getInternalViewportLocked() {
+ return getViewportByTypeLocked(VIEWPORT_INTERNAL);
+ }
+
+ private DisplayViewport getExternalViewportLocked() {
+ return getViewportByTypeLocked(VIEWPORT_EXTERNAL);
+ }
+
+ /**
+ * Get internal or external viewport. Create it if does not currently exist.
+ * @param viewportType - either INTERNAL or EXTERNAL
+ * @return the viewport with the requested type
+ */
+ private DisplayViewport getViewportByTypeLocked(int viewportType) {
+ // Only allow a single INTERNAL or EXTERNAL viewport, which makes this function possible.
+ // TODO (b/116824030) allow multiple EXTERNAL viewports and remove this function.
+ // Creates the viewport if none exists.
+ if (viewportType != VIEWPORT_INTERNAL && viewportType != VIEWPORT_EXTERNAL) {
+ Slog.wtf(TAG, "Cannot call getViewportByTypeLocked for type "
+ + DisplayViewport.typeToString(viewportType));
+ return null;
+ }
+ DisplayViewport viewport;
+ final int count = mViewports.size();
+ for (int i = 0; i < count; i++) {
+ viewport = mViewports.get(i);
+ if (viewport.type == viewportType) {
+ return viewport;
+ }
+ }
+
+ viewport = new DisplayViewport();
+ viewport.type = viewportType;
+ mViewports.add(viewport);
+ return viewport;
+ }
+
+ private static void populateViewportLocked(DisplayViewport viewport,
LogicalDisplay display, DisplayDevice device) {
viewport.valid = true;
viewport.displayId = display.getDisplayIdLocked();
@@ -1400,9 +1446,7 @@
pw.println(" mPendingTraversal=" + mPendingTraversal);
pw.println(" mGlobalDisplayState=" + Display.stateToString(mGlobalDisplayState));
pw.println(" mNextNonDefaultDisplayId=" + mNextNonDefaultDisplayId);
- pw.println(" mDefaultViewport=" + mDefaultViewport);
- pw.println(" mExternalTouchViewport=" + mExternalTouchViewport);
- pw.println(" mVirtualTouchViewports=" + mVirtualTouchViewports);
+ pw.println(" mViewports=" + mViewports);
pw.println(" mDefaultDisplayDefaultColorMode=" + mDefaultDisplayDefaultColorMode);
pw.println(" mSingleDisplayDemoMode=" + mSingleDisplayDemoMode);
pw.println(" mWifiDisplayScanRequestCount=" + mWifiDisplayScanRequestCount);
@@ -1522,18 +1566,19 @@
break;
case MSG_UPDATE_VIEWPORT: {
+ final boolean changed;
synchronized (mSyncRoot) {
- mTempDefaultViewport.copyFrom(mDefaultViewport);
- mTempExternalTouchViewport.copyFrom(mExternalTouchViewport);
- if (!mTempVirtualTouchViewports.equals(mVirtualTouchViewports)) {
- mTempVirtualTouchViewports.clear();
- for (DisplayViewport d : mVirtualTouchViewports) {
- mTempVirtualTouchViewports.add(d.makeCopy());
- }
+ changed = !mTempViewports.equals(mViewports);
+ if (changed) {
+ mTempViewports.clear();
+ for (DisplayViewport d : mViewports) {
+ mTempViewports.add(d.makeCopy());
+ }
}
}
- mInputManagerInternal.setDisplayViewports(mTempDefaultViewport,
- mTempExternalTouchViewport, mTempVirtualTouchViewports);
+ if (changed) {
+ mInputManagerInternal.setDisplayViewports(mTempViewports);
+ }
break;
}
diff --git a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
index 6111c23..244c764 100644
--- a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
@@ -19,13 +19,13 @@
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR;
import static android.hardware.display.DisplayManager
.VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD;
-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 static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_ROTATES_WITH_CONTENT;
import static android.hardware.display.DisplayManager
.VIRTUAL_DISPLAY_FLAG_DESTROY_CONTENT_ON_REMOVAL;
+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_ROTATES_WITH_CONTENT;
+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;
@@ -33,10 +33,10 @@
import android.media.projection.IMediaProjectionCallback;
import android.os.Handler;
import android.os.IBinder;
-import android.os.SystemProperties;
import android.os.IBinder.DeathRecipient;
import android.os.Message;
import android.os.RemoteException;
+import android.os.SystemProperties;
import android.util.ArrayMap;
import android.util.Slog;
import android.view.Display;
@@ -60,7 +60,8 @@
static final boolean DEBUG = false;
// Unique id prefix for virtual displays
- private static final String UNIQUE_ID_PREFIX = "virtual:";
+ @VisibleForTesting
+ static final String UNIQUE_ID_PREFIX = "virtual:";
private final ArrayMap<IBinder, VirtualDisplayDevice> mVirtualDisplayDevices =
new ArrayMap<IBinder, VirtualDisplayDevice>();
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index 0f28439..5bd095d 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -16,9 +16,6 @@
package com.android.server.input;
-import static android.hardware.display.DisplayViewport.VIEWPORT_INTERNAL;
-import static android.hardware.display.DisplayViewport.VIEWPORT_EXTERNAL;
-
import android.annotation.NonNull;
import android.app.IInputForwarder;
import android.app.Notification;
@@ -188,13 +185,8 @@
private static native long nativeInit(InputManagerService service,
Context context, MessageQueue messageQueue);
private static native void nativeStart(long ptr);
- private static native void nativeSetVirtualDisplayViewports(long ptr,
+ private static native void nativeSetDisplayViewports(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, String uniqueId);
private static native int nativeGetScanCodeState(long ptr,
int deviceId, int sourceMask, int scanCode);
@@ -409,31 +401,8 @@
nativeReloadDeviceAliases(mPtr);
}
- private void setDisplayViewportsInternal(DisplayViewport defaultViewport,
- DisplayViewport externalTouchViewport,
- List<DisplayViewport> virtualTouchViewports) {
- if (defaultViewport.valid) {
- setDisplayViewport(VIEWPORT_INTERNAL, defaultViewport);
- }
-
- if (externalTouchViewport.valid) {
- setDisplayViewport(VIEWPORT_EXTERNAL, externalTouchViewport);
- } else if (defaultViewport.valid) {
- setDisplayViewport(VIEWPORT_EXTERNAL, defaultViewport);
- }
-
- nativeSetVirtualDisplayViewports(mPtr,
- virtualTouchViewports.toArray(new DisplayViewport[0]));
- }
-
- 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.uniqueId);
+ private void setDisplayViewportsInternal(List<DisplayViewport> viewports) {
+ nativeSetDisplayViewports(mPtr, viewports.toArray(new DisplayViewport[0]));
}
/**
@@ -2203,11 +2172,8 @@
private final class LocalService extends InputManagerInternal {
@Override
- public void setDisplayViewports(DisplayViewport defaultViewport,
- DisplayViewport externalTouchViewport,
- List<DisplayViewport> virtualTouchViewports) {
- setDisplayViewportsInternal(defaultViewport, externalTouchViewport,
- virtualTouchViewports);
+ public void setDisplayViewports(List<DisplayViewport> viewports) {
+ setDisplayViewportsInternal(viewports);
}
@Override
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index becde73..2c01d1d 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -8,6 +8,7 @@
"-Wall",
"-Werror",
"-Wno-unused-parameter",
+ "-Wthread-safety",
"-DEGL_EGLEXT_PROTOTYPES",
"-DGL_GLEXT_PROTOTYPES",
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index 42ade38..a754d2a 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -64,6 +64,8 @@
#include "com_android_server_input_InputWindowHandle.h"
#include "android_hardware_display_DisplayViewport.h"
+#include <vector>
+
#define INDENT " "
using android::base::StringPrintf;
@@ -144,8 +146,8 @@
static jobject getInputApplicationHandleObjLocalRef(JNIEnv* env,
const sp<InputApplicationHandle>& inputApplicationHandle) {
- if (inputApplicationHandle == NULL) {
- return NULL;
+ if (inputApplicationHandle == nullptr) {
+ return nullptr;
}
return static_cast<NativeInputApplicationHandle*>(inputApplicationHandle.get())->
getInputApplicationHandleObjLocalRef(env);
@@ -153,8 +155,8 @@
static jobject getInputWindowHandleObjLocalRef(JNIEnv* env,
const sp<InputWindowHandle>& inputWindowHandle) {
- if (inputWindowHandle == NULL) {
- return NULL;
+ if (inputWindowHandle == nullptr) {
+ return nullptr;
}
return static_cast<NativeInputWindowHandle*>(inputWindowHandle.get())->
getInputWindowHandleObjLocalRef(env);
@@ -182,6 +184,15 @@
loadSystemIconAsSpriteWithPointerIcon(env, contextObj, style, &pointerIcon, outSpriteIcon);
}
+static void updatePointerControllerFromViewport(
+ sp<PointerController> controller, const DisplayViewport* const viewport) {
+ if (controller != nullptr && viewport != nullptr) {
+ const int32_t width = viewport->logicalRight - viewport->logicalLeft;
+ const int32_t height = viewport->logicalBottom - viewport->logicalTop;
+ controller->setDisplayViewport(width, height, viewport->orientation);
+ }
+}
+
enum {
WM_ACTION_PASS_TO_USER = 1,
};
@@ -203,8 +214,7 @@
void dump(std::string& dump);
- void setVirtualDisplayViewports(JNIEnv* env, jobjectArray viewportObjArray);
- void setDisplayViewport(int32_t viewportType, const DisplayViewport& viewport);
+ void setDisplayViewports(JNIEnv* env, jobjectArray viewportObjArray);
status_t registerInputChannel(JNIEnv* env, const sp<InputChannel>& inputChannel,
const sp<InputWindowHandle>& inputWindowHandle, bool monitor);
@@ -277,9 +287,7 @@
Mutex mLock;
struct Locked {
// Display size information.
- DisplayViewport internalViewport;
- DisplayViewport externalViewport;
- Vector<DisplayViewport> virtualViewports;
+ std::vector<DisplayViewport> viewports;
// System UI visibility.
int32_t systemUiVisibility;
@@ -304,7 +312,7 @@
// Input devices to be disabled
SortedVector<int32_t> disabledInputDevices;
- } mLocked;
+ } mLocked GUARDED_BY(mLock);
std::atomic<bool> mInteractive;
@@ -384,8 +392,17 @@
return false;
}
-void NativeInputManager::setVirtualDisplayViewports(JNIEnv* env, jobjectArray viewportObjArray) {
- Vector<DisplayViewport> viewports;
+static const DisplayViewport* findInternalViewport(const std::vector<DisplayViewport>& viewports) {
+ for (const DisplayViewport& v : viewports) {
+ if (v.type == ViewportType::VIEWPORT_INTERNAL) {
+ return &v;
+ }
+ }
+ return nullptr;
+}
+
+void NativeInputManager::setDisplayViewports(JNIEnv* env, jobjectArray viewportObjArray) {
+ std::vector<DisplayViewport> viewports;
if (viewportObjArray) {
jsize length = env->GetArrayLength(viewportObjArray);
@@ -397,57 +414,32 @@
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);
+ ALOGI("Viewport [%d] to add: %s", (int) i, viewport.uniqueId.c_str());
+ viewports.push_back(viewport);
env->DeleteLocalRef(viewportObj);
}
}
+ const DisplayViewport* newInternalViewport = findInternalViewport(viewports);
{
AutoMutex _l(mLock);
- mLocked.virtualViewports = viewports;
+ const DisplayViewport* oldInternalViewport = findInternalViewport(mLocked.viewports);
+ // Internal viewport has changed if there wasn't one earlier, and there is one now, or,
+ // if they are different.
+ const bool internalViewportChanged = (newInternalViewport != nullptr) &&
+ (oldInternalViewport == nullptr || (*newInternalViewport != *newInternalViewport));
+ if (internalViewportChanged) {
+ sp<PointerController> controller = mLocked.pointerController.promote();
+ updatePointerControllerFromViewport(controller, newInternalViewport);
+ }
+ mLocked.viewports = viewports;
}
mInputManager->getReader()->requestRefreshConfiguration(
InputReaderConfiguration::CHANGE_DISPLAY_INFO);
}
-void NativeInputManager::setDisplayViewport(int32_t type, const DisplayViewport& viewport) {
- bool changed = false;
- {
- AutoMutex _l(mLock);
-
- 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 (v != NULL && *v != viewport) {
- changed = true;
- *v = viewport;
-
- if (viewportType == ViewportType::VIEWPORT_INTERNAL) {
- sp<PointerController> controller = mLocked.pointerController.promote();
- if (controller != NULL) {
- controller->setDisplayViewport(
- viewport.logicalRight - viewport.logicalLeft,
- viewport.logicalBottom - viewport.logicalTop,
- viewport.orientation);
- }
- }
- }
- }
-
- if (changed) {
- mInputManager->getReader()->requestRefreshConfiguration(
- InputReaderConfiguration::CHANGE_DISPLAY_INFO);
- }
-}
-
status_t NativeInputManager::registerInputChannel(JNIEnv* /* env */,
const sp<InputChannel>& inputChannel,
const sp<InputWindowHandle>& inputWindowHandle, bool monitor) {
@@ -479,7 +471,7 @@
jsize length = env->GetArrayLength(excludedDeviceNames);
for (jsize i = 0; i < length; i++) {
jstring item = jstring(env->GetObjectArrayElement(excludedDeviceNames, i));
- const char* deviceNameChars = env->GetStringUTFChars(item, NULL);
+ const char* deviceNameChars = env->GetStringUTFChars(item, nullptr);
outConfig->excludedDeviceNames.push_back(deviceNameChars);
env->ReleaseStringUTFChars(item, deviceNameChars);
env->DeleteLocalRef(item);
@@ -526,11 +518,7 @@
outConfig->pointerCapture = mLocked.pointerCapture;
- outConfig->setPhysicalDisplayViewport(ViewportType::VIEWPORT_INTERNAL,
- mLocked.internalViewport);
- outConfig->setPhysicalDisplayViewport(ViewportType::VIEWPORT_EXTERNAL,
- mLocked.externalViewport);
- outConfig->setVirtualDisplayViewports(mLocked.virtualViewports);
+ outConfig->setDisplayViewports(mLocked.viewports);
outConfig->disabledDevices = mLocked.disabledInputDevices;
} // release lock
@@ -541,25 +529,22 @@
AutoMutex _l(mLock);
sp<PointerController> controller = mLocked.pointerController.promote();
- if (controller == NULL) {
+ if (controller == nullptr) {
ensureSpriteControllerLocked();
controller = new PointerController(this, mLooper, mLocked.spriteController);
mLocked.pointerController = controller;
- DisplayViewport& v = mLocked.internalViewport;
- controller->setDisplayViewport(
- v.logicalRight - v.logicalLeft,
- v.logicalBottom - v.logicalTop,
- v.orientation);
+ const DisplayViewport* internalViewport = findInternalViewport(mLocked.viewports);
+ updatePointerControllerFromViewport(controller, internalViewport);
updateInactivityTimeoutLocked(controller);
}
return controller;
}
-void NativeInputManager::ensureSpriteControllerLocked() {
- if (mLocked.spriteController == NULL) {
+void NativeInputManager::ensureSpriteControllerLocked() REQUIRES(mLock) {
+ if (mLocked.spriteController == nullptr) {
JNIEnv* env = jniEnv();
jint layer = env->CallIntMethod(mServiceObj, gServiceClassInfo.getPointerLayer);
if (checkAndClearExceptionFromCallback(env, "getPointerLayer")) {
@@ -575,7 +560,7 @@
size_t count = inputDevices.size();
jobjectArray inputDevicesObjArray = env->NewObjectArray(
- count, gInputDeviceClassInfo.clazz, NULL);
+ count, gInputDeviceClassInfo.clazz, nullptr);
if (inputDevicesObjArray) {
bool error = false;
for (size_t i = 0; i < count; i++) {
@@ -750,7 +735,7 @@
sp<InputWindowHandle> windowHandle =
android_server_InputWindowHandle_getHandle(env, windowHandleObj);
- if (windowHandle != NULL) {
+ if (windowHandle != nullptr) {
windowHandles.push(windowHandle);
}
env->DeleteLocalRef(windowHandleObj);
@@ -803,13 +788,14 @@
mLocked.systemUiVisibility = visibility;
sp<PointerController> controller = mLocked.pointerController.promote();
- if (controller != NULL) {
+ if (controller != nullptr) {
updateInactivityTimeoutLocked(controller);
}
}
}
-void NativeInputManager::updateInactivityTimeoutLocked(const sp<PointerController>& controller) {
+void NativeInputManager::updateInactivityTimeoutLocked(const sp<PointerController>& controller)
+ REQUIRES(mLock) {
bool lightsOut = mLocked.systemUiVisibility & ASYSTEM_UI_VISIBILITY_STATUS_BAR_HIDDEN;
controller->setInactivityTimeout(lightsOut
? PointerController::INACTIVITY_TIMEOUT_SHORT
@@ -894,7 +880,7 @@
void NativeInputManager::setPointerIconType(int32_t iconId) {
AutoMutex _l(mLock);
sp<PointerController> controller = mLocked.pointerController.promote();
- if (controller != NULL) {
+ if (controller != nullptr) {
controller->updatePointerIcon(iconId);
}
}
@@ -902,7 +888,7 @@
void NativeInputManager::reloadPointerIcons() {
AutoMutex _l(mLock);
sp<PointerController> controller = mLocked.pointerController.promote();
- if (controller != NULL) {
+ if (controller != nullptr) {
controller->reloadPointerResources();
}
}
@@ -910,7 +896,7 @@
void NativeInputManager::setCustomPointerIcon(const SpriteIcon& icon) {
AutoMutex _l(mLock);
sp<PointerController> controller = mLocked.pointerController.promote();
- if (controller != NULL) {
+ if (controller != nullptr) {
controller->setCustomPointerIcon(icon);
}
}
@@ -1122,7 +1108,7 @@
gServiceClassInfo.dispatchUnhandledKey,
inputWindowHandleObj, keyEventObj, policyFlags);
if (checkAndClearExceptionFromCallback(env, "dispatchUnhandledKey")) {
- fallbackKeyEventObj = NULL;
+ fallbackKeyEventObj = nullptr;
}
android_view_KeyEvent_recycle(env, keyEventObj);
env->DeleteLocalRef(keyEventObj);
@@ -1235,7 +1221,7 @@
static jlong nativeInit(JNIEnv* env, jclass /* clazz */,
jobject serviceObj, jobject contextObj, jobject messageQueueObj) {
sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
- if (messageQueue == NULL) {
+ if (messageQueue == nullptr) {
jniThrowRuntimeException(env, "MessageQueue is not initialized.");
return 0;
}
@@ -1255,37 +1241,10 @@
}
}
-static void nativeSetVirtualDisplayViewports(JNIEnv* env, jclass /* clazz */, jlong ptr,
+static void nativeSetDisplayViewports(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, jstring uniqueId) {
- NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
-
- DisplayViewport v;
- v.displayId = displayId;
- v.orientation = orientation;
- v.logicalLeft = logicalLeft;
- v.logicalTop = logicalTop;
- v.logicalRight = logicalRight;
- v.logicalBottom = logicalBottom;
- v.physicalLeft = physicalLeft;
- v.physicalTop = physicalTop;
- v.physicalRight = physicalRight;
- v.physicalBottom = physicalBottom;
- v.deviceWidth = deviceWidth;
- v.deviceHeight = deviceHeight;
- if (uniqueId != nullptr) {
- v.uniqueId = ScopedUtfChars(env, uniqueId).c_str();
- }
-
- im->setDisplayViewport(viewportType, v);
+ im->setDisplayViewports(env, viewportObjArray);
}
static jint nativeGetScanCodeState(JNIEnv* /* env */, jclass /* clazz */,
@@ -1316,8 +1275,8 @@
jlong ptr, jint deviceId, jint sourceMask, jintArray keyCodes, jbooleanArray outFlags) {
NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
- int32_t* codes = env->GetIntArrayElements(keyCodes, NULL);
- uint8_t* flags = env->GetBooleanArrayElements(outFlags, NULL);
+ int32_t* codes = env->GetIntArrayElements(keyCodes, nullptr);
+ uint8_t* flags = env->GetBooleanArrayElements(outFlags, nullptr);
jsize numCodes = env->GetArrayLength(keyCodes);
jboolean result;
if (numCodes == env->GetArrayLength(keyCodes)) {
@@ -1356,7 +1315,7 @@
sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env,
inputChannelObj);
- if (inputChannel == NULL) {
+ if (inputChannel == nullptr) {
throwInputChannelNotInitialized(env);
return;
}
@@ -1385,12 +1344,12 @@
sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env,
inputChannelObj);
- if (inputChannel == NULL) {
+ if (inputChannel == nullptr) {
throwInputChannelNotInitialized(env);
return;
}
- android_view_InputChannel_setDisposeCallback(env, inputChannelObj, NULL, NULL);
+ android_view_InputChannel_setDisposeCallback(env, inputChannelObj, nullptr, nullptr);
status_t status = im->unregisterInputChannel(env, inputChannel);
if (status && status != BAD_VALUE) { // ignore already unregistered channel
@@ -1490,7 +1449,7 @@
sp<InputChannel> toChannel =
android_view_InputChannel_getInputChannel(env, toChannelObj);
- if (fromChannel == NULL || toChannel == NULL) {
+ if (fromChannel == nullptr || toChannel == nullptr) {
return JNI_FALSE;
}
@@ -1543,7 +1502,7 @@
}
jlong* patternMillis = static_cast<jlong*>(env->GetPrimitiveArrayCritical(
- patternObj, NULL));
+ patternObj, nullptr));
nsecs_t pattern[patternSize];
for (size_t i = 0; i < patternSize; i++) {
pattern[i] = max(jlong(0), min(patternMillis[i],
@@ -1656,10 +1615,8 @@
(void*) nativeInit },
{ "nativeStart", "(J)V",
(void*) nativeStart },
- { "nativeSetVirtualDisplayViewports", "(J[Landroid/hardware/display/DisplayViewport;)V",
- (void*) nativeSetVirtualDisplayViewports },
- { "nativeSetDisplayViewport", "(JIIIIIIIIIIIIILjava/lang/String;)V",
- (void*) nativeSetDisplayViewport },
+ { "nativeSetDisplayViewports", "(J[Landroid/hardware/display/DisplayViewport;)V",
+ (void*) nativeSetDisplayViewports },
{ "nativeGetScanCodeState", "(JIII)I",
(void*) nativeGetScanCodeState },
{ "nativeGetKeyCodeState", "(JIII)I",
diff --git a/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
index ceee60c..b421280 100644
--- a/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
@@ -16,6 +16,8 @@
package com.android.server.display;
+import static com.android.server.display.VirtualDisplayAdapter.UNIQUE_ID_PREFIX;
+
import android.content.Context;
import android.hardware.display.BrightnessConfiguration;
import android.hardware.display.Curve;
@@ -25,35 +27,48 @@
import android.hardware.input.InputManagerInternal;
import android.os.Handler;
import android.os.IBinder;
-import android.os.UserHandle;
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.view.Display;
+import android.view.DisplayInfo;
import android.view.SurfaceControl;
+import androidx.test.runner.AndroidJUnit4;
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+
import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.display.DisplayDeviceInfo;
import com.android.server.display.DisplayManagerService.SyncRoot;
-import com.android.server.display.VirtualDisplayAdapter.SurfaceControlDisplayFactory;
import com.android.server.lights.LightsManager;
import com.android.server.wm.WindowManagerInternal;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.util.Arrays;
import java.util.List;
-import static org.mockito.Matchers.any;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.mock;
@SmallTest
-public class DisplayManagerServiceTest extends AndroidTestCase {
+@RunWith(AndroidJUnit4.class)
+public class DisplayManagerServiceTest {
private static final int MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS = 1;
private static final long SHORT_DEFAULT_DISPLAY_TIMEOUT_MILLIS = 10;
+ private Context mContext;
+
private final DisplayManagerService.Injector mShortMockedInjector =
new DisplayManagerService.Injector() {
@Override
@@ -86,8 +101,8 @@
@Mock VirtualDisplayAdapter mMockVirtualDisplayAdapter;
@Mock IBinder mMockDisplayToken;
- @Override
- protected void setUp() throws Exception {
+ @Before
+ public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
LocalServices.removeServiceForTest(InputManagerInternal.class);
@@ -96,15 +111,12 @@
LocalServices.addService(WindowManagerInternal.class, mMockWindowManagerInternal);
LocalServices.removeServiceForTest(LightsManager.class);
LocalServices.addService(LightsManager.class, mMockLightsManager);
- super.setUp();
+
+ mContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
}
- @Override
- protected void tearDown() throws Exception {
- super.tearDown();
- }
-
- public void testCreateVirtualDisplay_sentToInputManager() throws Exception {
+ @Test
+ public void testCreateVirtualDisplay_sentToInputManager() {
DisplayManagerService displayManager =
new DisplayManagerService(mContext, mBasicInjector);
registerDefaultDisplays(displayManager);
@@ -115,7 +127,7 @@
DisplayManagerService.BinderService bs = displayManager.new BinderService();
String uniqueId = "uniqueId --- Test";
- String uniqueIdPrefix = "virtual:" + mContext.getPackageName() + ":";
+ String uniqueIdPrefix = UNIQUE_ID_PREFIX + mContext.getPackageName() + ":";
int width = 600;
int height = 800;
int dpi = 320;
@@ -132,19 +144,113 @@
// flush the handler
displayManager.getDisplayHandler().runWithScissors(() -> {}, 0 /* now */);
- ArgumentCaptor<List<DisplayViewport>> virtualViewportCaptor =
- ArgumentCaptor.forClass(List.class);
- verify(mMockInputManagerInternal).setDisplayViewports(
- any(), any(), virtualViewportCaptor.capture());
+ ArgumentCaptor<List<DisplayViewport>> viewportCaptor = ArgumentCaptor.forClass(List.class);
+ verify(mMockInputManagerInternal).setDisplayViewports(viewportCaptor.capture());
+ List<DisplayViewport> viewports = viewportCaptor.getValue();
- 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);
+ // Expect to receive 3 viewports: internal, external, and virtual
+ assertEquals(3, viewports.size());
+
+ DisplayViewport virtualViewport = null;
+ DisplayViewport internalViewport = null;
+ DisplayViewport externalViewport = null;
+ for (int i = 0; i < viewports.size(); i++) {
+ DisplayViewport v = viewports.get(i);
+ switch (v.type) {
+ case DisplayViewport.VIEWPORT_INTERNAL: {
+ internalViewport = v;
+ break;
+ }
+ case DisplayViewport.VIEWPORT_EXTERNAL: {
+ externalViewport = v;
+ break;
+ }
+ case DisplayViewport.VIEWPORT_VIRTUAL: {
+ virtualViewport = v;
+ break;
+ }
+ }
+ }
+ // INTERNAL and EXTERNAL viewports get created upon access
+ assertNotNull(internalViewport);
+ assertNotNull(externalViewport);
+ assertNotNull(virtualViewport);
+
+ // INTERNAL and EXTERNAL
+ assertTrue(internalViewport.valid);
+ assertTrue(externalViewport.valid);
+
+ // VIRTUAL
+ assertEquals(height, virtualViewport.deviceHeight);
+ assertEquals(width, virtualViewport.deviceWidth);
+ assertEquals(uniqueIdPrefix + uniqueId, virtualViewport.uniqueId);
+ assertEquals(displayId, virtualViewport.displayId);
}
+ @Test
+ public void testPhysicalViewports() {
+ DisplayManagerService displayManager =
+ new DisplayManagerService(mContext, mBasicInjector);
+ registerDefaultDisplays(displayManager);
+ displayManager.systemReady(false /* safeMode */, true /* onlyCore */);
+ displayManager.windowManagerAndInputReady();
+
+ // This is effectively the DisplayManager service published to ServiceManager.
+ DisplayManagerService.BinderService bs = displayManager.new BinderService();
+
+ when(mMockAppToken.asBinder()).thenReturn(mMockAppToken);
+
+ final int displayIds[] = bs.getDisplayIds();
+ assertEquals(1, displayIds.length);
+ final int displayId = displayIds[0];
+ DisplayInfo info = bs.getDisplayInfo(displayId);
+ assertEquals(info.type, Display.TYPE_BUILT_IN);
+
+ displayManager.performTraversalInternal(mock(SurfaceControl.Transaction.class));
+
+ // flush the handler
+ displayManager.getDisplayHandler().runWithScissors(() -> {}, 0 /* now */);
+
+ ArgumentCaptor<List<DisplayViewport>> viewportCaptor = ArgumentCaptor.forClass(List.class);
+ verify(mMockInputManagerInternal).setDisplayViewports(viewportCaptor.capture());
+ List<DisplayViewport> viewports = viewportCaptor.getValue();
+
+ // Expect to receive 2 viewports: 1 internal, 1 external
+ assertEquals(2, viewports.size());
+
+ DisplayViewport internalViewport = null;
+ DisplayViewport externalViewport = null;
+ for (int i = 0; i < viewports.size(); i++) {
+ DisplayViewport v = viewports.get(i);
+ switch (v.type) {
+ case DisplayViewport.VIEWPORT_INTERNAL: {
+ internalViewport = v;
+ break;
+ }
+ case DisplayViewport.VIEWPORT_EXTERNAL: {
+ externalViewport = v;
+ break;
+ }
+ default: {
+ fail("Unexpected viewport type: " + DisplayViewport.typeToString(v.type));
+ break;
+ }
+ }
+ }
+ // INTERNAL and EXTERNAL viewports get created upon access
+ assertNotNull(internalViewport);
+ assertNotNull(externalViewport);
+ assertTrue(internalViewport.valid);
+ assertEquals(displayId, internalViewport.displayId);
+
+ // To simplify comparison, override the type for external Viewport
+ // TODO (b/116850516) remove this
+ externalViewport.type = internalViewport.type;
+ assertEquals(internalViewport, externalViewport);
+ externalViewport.type = DisplayViewport.VIEWPORT_EXTERNAL; // undo the changes above
+ }
+
+ @Test
public void testCreateVirtualDisplayRotatesWithContent() throws Exception {
DisplayManagerService displayManager =
new DisplayManagerService(mContext, mBasicInjector);
@@ -178,6 +284,7 @@
/**
* Tests that the virtual display is created along-side the default display.
*/
+ @Test
public void testStartVirtualDisplayWithDefaultDisplay_Succeeds() throws Exception {
DisplayManagerService displayManager =
new DisplayManagerService(mContext, mShortMockedInjector);
@@ -188,6 +295,7 @@
/**
* Tests that we get a Runtime exception when we cannot initialize the default display.
*/
+ @Test
public void testStartVirtualDisplayWithDefDisplay_NoDefaultDisplay() throws Exception {
DisplayManagerService displayManager =
new DisplayManagerService(mContext, mShortMockedInjector);
@@ -206,6 +314,7 @@
/**
* Tests that we get a Runtime exception when we cannot initialize the virtual display.
*/
+ @Test
public void testStartVirtualDisplayWithDefDisplay_NoVirtualDisplayAdapter() throws Exception {
DisplayManagerService displayManager = new DisplayManagerService(mContext,
new DisplayManagerService.Injector() {
@@ -232,6 +341,7 @@
/**
* Tests that an exception is raised for too dark a brightness configuration.
*/
+ @Test
public void testTooDarkBrightnessConfigurationThrowException() {
DisplayManagerService displayManager =
new DisplayManagerService(mContext, mShortMockedInjector);
@@ -266,6 +376,7 @@
/**
* Tests that no exception is raised for not too dark a brightness configuration.
*/
+ @Test
public void testBrightEnoughBrightnessConfigurationDoesNotThrowException() {
DisplayManagerService displayManager =
new DisplayManagerService(mContext, mShortMockedInjector);
@@ -279,6 +390,7 @@
/**
* Tests that null brightness configurations are alright.
*/
+ @Test
public void testNullBrightnessConfiguration() {
DisplayManagerService displayManager =
new DisplayManagerService(mContext, mShortMockedInjector);