Loading libs/gui/tests/EndToEndNativeInputTest.cpp +88 −13 Original line number Original line Diff line number Diff line Loading @@ -220,7 +220,7 @@ public: t.apply(true); t.apply(true); } } void requestFocus() { void requestFocus(int displayId = ADISPLAY_ID_DEFAULT) { SurfaceComposerClient::Transaction t; SurfaceComposerClient::Transaction t; FocusRequest request; FocusRequest request; request.token = mInputInfo.token; request.token = mInputInfo.token; Loading @@ -228,7 +228,7 @@ public: request.focusedToken = nullptr; request.focusedToken = nullptr; request.focusedWindowName = ""; request.focusedWindowName = ""; request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC); request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC); request.displayId = 0; request.displayId = displayId; t.setFocusedWindow(request); t.setFocusedWindow(request); t.apply(true); t.apply(true); } } Loading @@ -255,11 +255,6 @@ private: mInputInfo.touchableRegion.orSelf(Rect(0, 0, width, height)); mInputInfo.touchableRegion.orSelf(Rect(0, 0, width, height)); // TODO: Fill in from SF? mInputInfo.ownerPid = 11111; mInputInfo.ownerUid = 11111; mInputInfo.displayId = 0; InputApplicationInfo aInfo; InputApplicationInfo aInfo; aInfo.token = new BBinder(); aInfo.token = new BBinder(); aInfo.name = "Test app info"; aInfo.name = "Test app info"; Loading Loading @@ -373,23 +368,33 @@ public: int32_t mBufferPostDelay; int32_t mBufferPostDelay; }; }; void injectTap(int x, int y) { void injectTapOnDisplay(int x, int y, int displayId) { char *buf1, *buf2; char *buf1, *buf2, *bufDisplayId; asprintf(&buf1, "%d", x); asprintf(&buf1, "%d", x); asprintf(&buf2, "%d", y); asprintf(&buf2, "%d", y); asprintf(&bufDisplayId, "%d", displayId); if (fork() == 0) { if (fork() == 0) { execlp("input", "input", "tap", buf1, buf2, NULL); execlp("input", "input", "-d", bufDisplayId, "tap", buf1, buf2, NULL); } } } } void injectKey(uint32_t keycode) { void injectTap(int x, int y) { char *buf1; injectTapOnDisplay(x, y, ADISPLAY_ID_DEFAULT); } void injectKeyOnDisplay(uint32_t keycode, int displayId) { char *buf1, *bufDisplayId; asprintf(&buf1, "%d", keycode); asprintf(&buf1, "%d", keycode); asprintf(&bufDisplayId, "%d", displayId); if (fork() == 0) { if (fork() == 0) { execlp("input", "input", "keyevent", buf1, NULL); execlp("input", "input", "-d", bufDisplayId, "keyevent", buf1, NULL); } } } } void injectKey(uint32_t keycode) { injectKeyOnDisplay(keycode, ADISPLAY_ID_NONE); } TEST_F(InputSurfacesTest, can_receive_input) { TEST_F(InputSurfacesTest, can_receive_input) { std::unique_ptr<InputSurface> surface = makeSurface(100, 100); std::unique_ptr<InputSurface> surface = makeSurface(100, 100); surface->showAt(100, 100); surface->showAt(100, 100); Loading Loading @@ -946,4 +951,74 @@ TEST_F(InputSurfacesTest, drop_input_policy) { injectKey(AKEYCODE_V); injectKey(AKEYCODE_V); EXPECT_EQ(surface->consumeEvent(100), nullptr); EXPECT_EQ(surface->consumeEvent(100), nullptr); } } class MultiDisplayTests : public InputSurfacesTest { public: MultiDisplayTests() : InputSurfacesTest() { ProcessState::self()->startThreadPool(); } void TearDown() { if (mVirtualDisplay) { SurfaceComposerClient::destroyDisplay(mVirtualDisplay); } InputSurfacesTest::TearDown(); } void createDisplay(int32_t width, int32_t height, bool isSecure, ui::LayerStack layerStack) { sp<IGraphicBufferConsumer> consumer; BufferQueue::createBufferQueue(&mProducer, &consumer); consumer->setConsumerName(String8("Virtual disp consumer")); consumer->setDefaultBufferSize(width, height); mVirtualDisplay = SurfaceComposerClient::createDisplay(String8("VirtualDisplay"), isSecure); SurfaceComposerClient::Transaction t; t.setDisplaySurface(mVirtualDisplay, mProducer); t.setDisplayFlags(mVirtualDisplay, 0x01 /* DisplayDevice::eReceivesInput */); t.setDisplayLayerStack(mVirtualDisplay, layerStack); t.apply(true); } sp<IBinder> mVirtualDisplay; sp<IGraphicBufferProducer> mProducer; }; TEST_F(MultiDisplayTests, drop_input_for_secure_layer_on_nonsecure_display) { ui::LayerStack layerStack = ui::LayerStack::fromValue(42); createDisplay(1000, 1000, false /*isSecure*/, layerStack); std::unique_ptr<InputSurface> surface = makeSurface(100, 100); surface->doTransaction([&](auto &t, auto &sc) { t.setFlags(sc, layer_state_t::eLayerSecure, layer_state_t::eLayerSecure); t.setLayerStack(sc, layerStack); }); surface->showAt(100, 100); injectTap(101, 101); EXPECT_EQ(surface->consumeEvent(100), nullptr); surface->requestFocus(layerStack.id); surface->assertFocusChange(true); injectKeyOnDisplay(AKEYCODE_V, layerStack.id); EXPECT_EQ(surface->consumeEvent(100), nullptr); } TEST_F(MultiDisplayTests, dont_drop_input_for_secure_layer_on_secure_display) { ui::LayerStack layerStack = ui::LayerStack::fromValue(42); createDisplay(1000, 1000, true /*isSecure*/, layerStack); std::unique_ptr<InputSurface> surface = makeSurface(100, 100); surface->doTransaction([&](auto &t, auto &sc) { t.setFlags(sc, layer_state_t::eLayerSecure, layer_state_t::eLayerSecure); t.setLayerStack(sc, layerStack); }); surface->showAt(100, 100); injectTapOnDisplay(101, 101, layerStack.id); EXPECT_NE(surface->consumeEvent(), nullptr); EXPECT_NE(surface->consumeEvent(), nullptr); surface->requestFocus(layerStack.id); surface->assertFocusChange(true); injectKeyOnDisplay(AKEYCODE_V, layerStack.id); surface->expectKey(AKEYCODE_V); } } // namespace android::test } // namespace android::test services/surfaceflinger/Layer.cpp +8 −2 Original line number Original line Diff line number Diff line Loading @@ -2154,7 +2154,7 @@ void Layer::writeToProtoCommonState(LayerProto* layerInfo, LayerVector::StateSet if (traceFlags & SurfaceTracing::TRACE_INPUT) { if (traceFlags & SurfaceTracing::TRACE_INPUT) { WindowInfo info; WindowInfo info; if (useDrawing) { if (useDrawing) { info = fillInputInfo(ui::Transform()); info = fillInputInfo(ui::Transform(), /* displayIsSecure */ true); } else { } else { info = state.inputInfo; info = state.inputInfo; } } Loading Loading @@ -2356,7 +2356,7 @@ void Layer::handleDropInputMode(gui::WindowInfo& info) const { } } } } WindowInfo Layer::fillInputInfo(const ui::Transform& displayTransform) { WindowInfo Layer::fillInputInfo(const ui::Transform& displayTransform, bool displayIsSecure) { if (!hasInputInfo()) { if (!hasInputInfo()) { mDrawingState.inputInfo.name = getName(); mDrawingState.inputInfo.name = getName(); mDrawingState.inputInfo.ownerUid = mOwnerUid; mDrawingState.inputInfo.ownerUid = mOwnerUid; Loading Loading @@ -2385,6 +2385,12 @@ WindowInfo Layer::fillInputInfo(const ui::Transform& displayTransform) { fillTouchOcclusionMode(info); fillTouchOcclusionMode(info); handleDropInputMode(info); handleDropInputMode(info); // If the window will be blacked out on a display because the display does not have the secure // flag and the layer has the secure flag set, then drop input. if (!displayIsSecure && isSecure()) { info.inputFeatures |= WindowInfo::Feature::DROP_INPUT; } auto cropLayer = mDrawingState.touchableRegionCrop.promote(); auto cropLayer = mDrawingState.touchableRegionCrop.promote(); if (info.replaceTouchableRegionWithCrop) { if (info.replaceTouchableRegionWithCrop) { const Rect bounds(cropLayer ? cropLayer->mScreenBounds : mScreenBounds); const Rect bounds(cropLayer ? cropLayer->mScreenBounds : mScreenBounds); Loading services/surfaceflinger/Layer.h +1 −1 Original line number Original line Diff line number Diff line Loading @@ -854,7 +854,7 @@ public: bool getPremultipledAlpha() const; bool getPremultipledAlpha() const; void setInputInfo(const gui::WindowInfo& info); void setInputInfo(const gui::WindowInfo& info); gui::WindowInfo fillInputInfo(const ui::Transform& displayTransform); gui::WindowInfo fillInputInfo(const ui::Transform& displayTransform, bool displayIsSecure); /** /** * Returns whether this layer has an explicitly set input-info. * Returns whether this layer has an explicitly set input-info. Loading services/surfaceflinger/SurfaceFlinger.cpp +11 −8 Original line number Original line Diff line number Diff line Loading @@ -3089,16 +3089,19 @@ void SurfaceFlinger::notifyWindowInfos() { mDrawingState.traverseInReverseZOrder([&](Layer* layer) { mDrawingState.traverseInReverseZOrder([&](Layer* layer) { if (!layer->needsInputInfo()) return; if (!layer->needsInputInfo()) return; const DisplayDevice* display = nullptr; const DisplayDevice* display = ON_MAIN_THREAD(getDisplayWithInputByLayer(layer)).get(); if (enablePerWindowInputRotation()) { ui::Transform displayTransform = ui::Transform(); display = ON_MAIN_THREAD(getDisplayWithInputByLayer(layer)).get(); } if (enablePerWindowInputRotation()) { // When calculating the screen bounds we ignore the transparent region since it may // When calculating the screen bounds we ignore the transparent region since it may // result in an unwanted offset. // result in an unwanted offset. const auto it = displayTransforms.find(display); const auto it = displayTransforms.find(display); windowInfos.push_back( if (it != displayTransforms.end()) { layer->fillInputInfo(it != displayTransforms.end() ? it->second : ui::Transform())); displayTransform = it->second; } } const bool displayIsSecure = !display || display->isSecure(); windowInfos.push_back(layer->fillInputInfo(displayTransform, displayIsSecure)); }); }); mWindowInfosListenerInvoker->windowInfosChanged(windowInfos, displayInfos, mWindowInfosListenerInvoker->windowInfosChanged(windowInfos, displayInfos, mInputWindowCommands.syncInputWindows); mInputWindowCommands.syncInputWindows); Loading Loading
libs/gui/tests/EndToEndNativeInputTest.cpp +88 −13 Original line number Original line Diff line number Diff line Loading @@ -220,7 +220,7 @@ public: t.apply(true); t.apply(true); } } void requestFocus() { void requestFocus(int displayId = ADISPLAY_ID_DEFAULT) { SurfaceComposerClient::Transaction t; SurfaceComposerClient::Transaction t; FocusRequest request; FocusRequest request; request.token = mInputInfo.token; request.token = mInputInfo.token; Loading @@ -228,7 +228,7 @@ public: request.focusedToken = nullptr; request.focusedToken = nullptr; request.focusedWindowName = ""; request.focusedWindowName = ""; request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC); request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC); request.displayId = 0; request.displayId = displayId; t.setFocusedWindow(request); t.setFocusedWindow(request); t.apply(true); t.apply(true); } } Loading @@ -255,11 +255,6 @@ private: mInputInfo.touchableRegion.orSelf(Rect(0, 0, width, height)); mInputInfo.touchableRegion.orSelf(Rect(0, 0, width, height)); // TODO: Fill in from SF? mInputInfo.ownerPid = 11111; mInputInfo.ownerUid = 11111; mInputInfo.displayId = 0; InputApplicationInfo aInfo; InputApplicationInfo aInfo; aInfo.token = new BBinder(); aInfo.token = new BBinder(); aInfo.name = "Test app info"; aInfo.name = "Test app info"; Loading Loading @@ -373,23 +368,33 @@ public: int32_t mBufferPostDelay; int32_t mBufferPostDelay; }; }; void injectTap(int x, int y) { void injectTapOnDisplay(int x, int y, int displayId) { char *buf1, *buf2; char *buf1, *buf2, *bufDisplayId; asprintf(&buf1, "%d", x); asprintf(&buf1, "%d", x); asprintf(&buf2, "%d", y); asprintf(&buf2, "%d", y); asprintf(&bufDisplayId, "%d", displayId); if (fork() == 0) { if (fork() == 0) { execlp("input", "input", "tap", buf1, buf2, NULL); execlp("input", "input", "-d", bufDisplayId, "tap", buf1, buf2, NULL); } } } } void injectKey(uint32_t keycode) { void injectTap(int x, int y) { char *buf1; injectTapOnDisplay(x, y, ADISPLAY_ID_DEFAULT); } void injectKeyOnDisplay(uint32_t keycode, int displayId) { char *buf1, *bufDisplayId; asprintf(&buf1, "%d", keycode); asprintf(&buf1, "%d", keycode); asprintf(&bufDisplayId, "%d", displayId); if (fork() == 0) { if (fork() == 0) { execlp("input", "input", "keyevent", buf1, NULL); execlp("input", "input", "-d", bufDisplayId, "keyevent", buf1, NULL); } } } } void injectKey(uint32_t keycode) { injectKeyOnDisplay(keycode, ADISPLAY_ID_NONE); } TEST_F(InputSurfacesTest, can_receive_input) { TEST_F(InputSurfacesTest, can_receive_input) { std::unique_ptr<InputSurface> surface = makeSurface(100, 100); std::unique_ptr<InputSurface> surface = makeSurface(100, 100); surface->showAt(100, 100); surface->showAt(100, 100); Loading Loading @@ -946,4 +951,74 @@ TEST_F(InputSurfacesTest, drop_input_policy) { injectKey(AKEYCODE_V); injectKey(AKEYCODE_V); EXPECT_EQ(surface->consumeEvent(100), nullptr); EXPECT_EQ(surface->consumeEvent(100), nullptr); } } class MultiDisplayTests : public InputSurfacesTest { public: MultiDisplayTests() : InputSurfacesTest() { ProcessState::self()->startThreadPool(); } void TearDown() { if (mVirtualDisplay) { SurfaceComposerClient::destroyDisplay(mVirtualDisplay); } InputSurfacesTest::TearDown(); } void createDisplay(int32_t width, int32_t height, bool isSecure, ui::LayerStack layerStack) { sp<IGraphicBufferConsumer> consumer; BufferQueue::createBufferQueue(&mProducer, &consumer); consumer->setConsumerName(String8("Virtual disp consumer")); consumer->setDefaultBufferSize(width, height); mVirtualDisplay = SurfaceComposerClient::createDisplay(String8("VirtualDisplay"), isSecure); SurfaceComposerClient::Transaction t; t.setDisplaySurface(mVirtualDisplay, mProducer); t.setDisplayFlags(mVirtualDisplay, 0x01 /* DisplayDevice::eReceivesInput */); t.setDisplayLayerStack(mVirtualDisplay, layerStack); t.apply(true); } sp<IBinder> mVirtualDisplay; sp<IGraphicBufferProducer> mProducer; }; TEST_F(MultiDisplayTests, drop_input_for_secure_layer_on_nonsecure_display) { ui::LayerStack layerStack = ui::LayerStack::fromValue(42); createDisplay(1000, 1000, false /*isSecure*/, layerStack); std::unique_ptr<InputSurface> surface = makeSurface(100, 100); surface->doTransaction([&](auto &t, auto &sc) { t.setFlags(sc, layer_state_t::eLayerSecure, layer_state_t::eLayerSecure); t.setLayerStack(sc, layerStack); }); surface->showAt(100, 100); injectTap(101, 101); EXPECT_EQ(surface->consumeEvent(100), nullptr); surface->requestFocus(layerStack.id); surface->assertFocusChange(true); injectKeyOnDisplay(AKEYCODE_V, layerStack.id); EXPECT_EQ(surface->consumeEvent(100), nullptr); } TEST_F(MultiDisplayTests, dont_drop_input_for_secure_layer_on_secure_display) { ui::LayerStack layerStack = ui::LayerStack::fromValue(42); createDisplay(1000, 1000, true /*isSecure*/, layerStack); std::unique_ptr<InputSurface> surface = makeSurface(100, 100); surface->doTransaction([&](auto &t, auto &sc) { t.setFlags(sc, layer_state_t::eLayerSecure, layer_state_t::eLayerSecure); t.setLayerStack(sc, layerStack); }); surface->showAt(100, 100); injectTapOnDisplay(101, 101, layerStack.id); EXPECT_NE(surface->consumeEvent(), nullptr); EXPECT_NE(surface->consumeEvent(), nullptr); surface->requestFocus(layerStack.id); surface->assertFocusChange(true); injectKeyOnDisplay(AKEYCODE_V, layerStack.id); surface->expectKey(AKEYCODE_V); } } // namespace android::test } // namespace android::test
services/surfaceflinger/Layer.cpp +8 −2 Original line number Original line Diff line number Diff line Loading @@ -2154,7 +2154,7 @@ void Layer::writeToProtoCommonState(LayerProto* layerInfo, LayerVector::StateSet if (traceFlags & SurfaceTracing::TRACE_INPUT) { if (traceFlags & SurfaceTracing::TRACE_INPUT) { WindowInfo info; WindowInfo info; if (useDrawing) { if (useDrawing) { info = fillInputInfo(ui::Transform()); info = fillInputInfo(ui::Transform(), /* displayIsSecure */ true); } else { } else { info = state.inputInfo; info = state.inputInfo; } } Loading Loading @@ -2356,7 +2356,7 @@ void Layer::handleDropInputMode(gui::WindowInfo& info) const { } } } } WindowInfo Layer::fillInputInfo(const ui::Transform& displayTransform) { WindowInfo Layer::fillInputInfo(const ui::Transform& displayTransform, bool displayIsSecure) { if (!hasInputInfo()) { if (!hasInputInfo()) { mDrawingState.inputInfo.name = getName(); mDrawingState.inputInfo.name = getName(); mDrawingState.inputInfo.ownerUid = mOwnerUid; mDrawingState.inputInfo.ownerUid = mOwnerUid; Loading Loading @@ -2385,6 +2385,12 @@ WindowInfo Layer::fillInputInfo(const ui::Transform& displayTransform) { fillTouchOcclusionMode(info); fillTouchOcclusionMode(info); handleDropInputMode(info); handleDropInputMode(info); // If the window will be blacked out on a display because the display does not have the secure // flag and the layer has the secure flag set, then drop input. if (!displayIsSecure && isSecure()) { info.inputFeatures |= WindowInfo::Feature::DROP_INPUT; } auto cropLayer = mDrawingState.touchableRegionCrop.promote(); auto cropLayer = mDrawingState.touchableRegionCrop.promote(); if (info.replaceTouchableRegionWithCrop) { if (info.replaceTouchableRegionWithCrop) { const Rect bounds(cropLayer ? cropLayer->mScreenBounds : mScreenBounds); const Rect bounds(cropLayer ? cropLayer->mScreenBounds : mScreenBounds); Loading
services/surfaceflinger/Layer.h +1 −1 Original line number Original line Diff line number Diff line Loading @@ -854,7 +854,7 @@ public: bool getPremultipledAlpha() const; bool getPremultipledAlpha() const; void setInputInfo(const gui::WindowInfo& info); void setInputInfo(const gui::WindowInfo& info); gui::WindowInfo fillInputInfo(const ui::Transform& displayTransform); gui::WindowInfo fillInputInfo(const ui::Transform& displayTransform, bool displayIsSecure); /** /** * Returns whether this layer has an explicitly set input-info. * Returns whether this layer has an explicitly set input-info. Loading
services/surfaceflinger/SurfaceFlinger.cpp +11 −8 Original line number Original line Diff line number Diff line Loading @@ -3089,16 +3089,19 @@ void SurfaceFlinger::notifyWindowInfos() { mDrawingState.traverseInReverseZOrder([&](Layer* layer) { mDrawingState.traverseInReverseZOrder([&](Layer* layer) { if (!layer->needsInputInfo()) return; if (!layer->needsInputInfo()) return; const DisplayDevice* display = nullptr; const DisplayDevice* display = ON_MAIN_THREAD(getDisplayWithInputByLayer(layer)).get(); if (enablePerWindowInputRotation()) { ui::Transform displayTransform = ui::Transform(); display = ON_MAIN_THREAD(getDisplayWithInputByLayer(layer)).get(); } if (enablePerWindowInputRotation()) { // When calculating the screen bounds we ignore the transparent region since it may // When calculating the screen bounds we ignore the transparent region since it may // result in an unwanted offset. // result in an unwanted offset. const auto it = displayTransforms.find(display); const auto it = displayTransforms.find(display); windowInfos.push_back( if (it != displayTransforms.end()) { layer->fillInputInfo(it != displayTransforms.end() ? it->second : ui::Transform())); displayTransform = it->second; } } const bool displayIsSecure = !display || display->isSecure(); windowInfos.push_back(layer->fillInputInfo(displayTransform, displayIsSecure)); }); }); mWindowInfosListenerInvoker->windowInfosChanged(windowInfos, displayInfos, mWindowInfosListenerInvoker->windowInfosChanged(windowInfos, displayInfos, mInputWindowCommands.syncInputWindows); mInputWindowCommands.syncInputWindows); Loading