Merge changes from topics "cursor_type_hotspot", "set_viewport_in_input_reader"

* changes:
  PointerController: Add guards to ensure display is valid
  Move setDisplayViewport to InputReader.
  Stop loading animation for addtional cursor type.
  Add cursor type and hotspot to surface metadata.
This commit is contained in:
Treehugger Robot
2020-05-29 19:23:45 +00:00
committed by Gerrit Code Review
12 changed files with 464 additions and 56 deletions

View File

@@ -483,11 +483,8 @@ static void nativeSetMetadata(JNIEnv* env, jclass clazz, jlong transactionObj,
auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
std::vector<uint8_t> byteData(parcel->dataSize());
memcpy(byteData.data(), parcel->data(), parcel->dataSize());
SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl*>(nativeObject);
transaction->setMetadata(ctrl, id, std::move(byteData));
transaction->setMetadata(ctrl, id, *parcel);
}
static void nativeSetColor(JNIEnv* env, jclass clazz, jlong transactionObj,

View File

@@ -20,6 +20,7 @@ cc_library_shared {
],
shared_libs: [
"libbinder",
"libcutils",
"liblog",
"libutils",

View File

@@ -257,19 +257,24 @@ void PointerController::unfade(Transition transition) {
void PointerController::setPresentation(Presentation presentation) {
AutoMutex _l(mLock);
if (presentation == PRESENTATION_POINTER && mLocked.additionalMouseResources.empty()) {
mPolicy->loadAdditionalMouseResources(&mLocked.additionalMouseResources,
&mLocked.animationResources, mLocked.viewport.displayId);
if (mLocked.presentation == presentation) {
return;
}
if (mLocked.presentation != presentation) {
mLocked.presentation = presentation;
mLocked.presentationChanged = true;
mLocked.presentation = presentation;
mLocked.presentationChanged = true;
if (presentation != PRESENTATION_SPOT) {
fadeOutAndReleaseAllSpotsLocked();
if (!mLocked.viewport.isValid()) {
return;
}
if (presentation == PRESENTATION_POINTER) {
if (mLocked.additionalMouseResources.empty()) {
mPolicy->loadAdditionalMouseResources(&mLocked.additionalMouseResources,
&mLocked.animationResources,
mLocked.viewport.displayId);
}
fadeOutAndReleaseAllSpotsLocked();
updatePointerLocked();
}
}
@@ -291,6 +296,9 @@ void PointerController::setSpots(const PointerCoords* spotCoords,
#endif
AutoMutex _l(mLock);
if (!mLocked.viewport.isValid()) {
return;
}
std::vector<Spot*> newSpots;
std::map<int32_t, std::vector<Spot*>>::const_iterator iter =
@@ -337,6 +345,9 @@ void PointerController::clearSpots() {
#endif
AutoMutex _l(mLock);
if (!mLocked.viewport.isValid()) {
return;
}
fadeOutAndReleaseAllSpotsLocked();
}
@@ -758,6 +769,10 @@ void PointerController::fadeOutAndReleaseAllSpotsLocked() {
}
void PointerController::loadResourcesLocked() REQUIRES(mLock) {
if (!mLocked.viewport.isValid()) {
return;
}
mPolicy->loadPointerResources(&mResources, mLocked.viewport.displayId);
mPolicy->loadPointerIcon(&mLocked.pointerIcon, mLocked.viewport.displayId);

View File

@@ -100,6 +100,7 @@ public:
virtual int32_t getDisplayId() const;
virtual void fade(Transition transition);
virtual void unfade(Transition transition);
virtual void setDisplayViewport(const DisplayViewport& viewport);
virtual void setPresentation(Presentation presentation);
virtual void setSpots(const PointerCoords* spotCoords,
@@ -108,7 +109,6 @@ public:
void updatePointerIcon(int32_t iconId);
void setCustomPointerIcon(const SpriteIcon& icon);
void setDisplayViewport(const DisplayViewport& viewport);
void setInactivityTimeout(InactivityTimeout inactivityTimeout);
void reloadPointerResources();

View File

@@ -245,7 +245,8 @@ void SpriteController::doUpdateSprites() {
if (update.state.surfaceControl != NULL && (becomingVisible || becomingHidden
|| (wantSurfaceVisibleAndDrawn && (update.state.dirty & (DIRTY_ALPHA
| DIRTY_POSITION | DIRTY_TRANSFORMATION_MATRIX | DIRTY_LAYER
| DIRTY_VISIBILITY | DIRTY_HOTSPOT | DIRTY_DISPLAY_ID))))) {
| DIRTY_VISIBILITY | DIRTY_HOTSPOT | DIRTY_DISPLAY_ID
| DIRTY_ICON_STYLE))))) {
needApplyTransaction = true;
if (wantSurfaceVisibleAndDrawn
@@ -274,6 +275,21 @@ void SpriteController::doUpdateSprites() {
update.state.transformationMatrix.dtdy);
}
if (wantSurfaceVisibleAndDrawn
&& (becomingVisible
|| (update.state.dirty & (DIRTY_HOTSPOT | DIRTY_ICON_STYLE)))) {
Parcel p;
p.writeInt32(update.state.icon.style);
p.writeFloat(update.state.icon.hotSpotX);
p.writeFloat(update.state.icon.hotSpotY);
// Pass cursor metadata in the sprite surface so that when Android is running as a
// client OS (e.g. ARC++) the host OS can get the requested cursor metadata and
// update mouse cursor in the host OS.
t.setMetadata(
update.state.surfaceControl, METADATA_MOUSE_CURSOR, p);
}
int32_t surfaceLayer = mOverlayLayer + update.state.layer;
if (wantSurfaceVisibleAndDrawn
&& (becomingVisible || (update.state.dirty & DIRTY_LAYER))) {
@@ -397,9 +413,14 @@ void SpriteController::SpriteImpl::setIcon(const SpriteIcon& icon) {
} else {
dirty = DIRTY_BITMAP;
}
if (mLocked.state.icon.style != icon.style) {
mLocked.state.icon.style = icon.style;
dirty |= DIRTY_ICON_STYLE;
}
} else if (mLocked.state.icon.isValid()) {
mLocked.state.icon.bitmap.reset();
dirty = DIRTY_BITMAP | DIRTY_HOTSPOT;
dirty = DIRTY_BITMAP | DIRTY_HOTSPOT | DIRTY_ICON_STYLE;
} else {
return; // setting to invalid icon and already invalid so nothing to do
}

View File

@@ -55,11 +55,12 @@ struct SpriteTransformationMatrix {
* Icon that a sprite displays, including its hotspot.
*/
struct SpriteIcon {
inline SpriteIcon() : hotSpotX(0), hotSpotY(0) { }
inline SpriteIcon(const SkBitmap& bitmap, float hotSpotX, float hotSpotY) :
bitmap(bitmap), hotSpotX(hotSpotX), hotSpotY(hotSpotY) { }
inline SpriteIcon() : style(0), hotSpotX(0), hotSpotY(0) { }
inline SpriteIcon(const SkBitmap& bitmap, int32_t style, float hotSpotX, float hotSpotY) :
bitmap(bitmap), style(style), hotSpotX(hotSpotX), hotSpotY(hotSpotY) { }
SkBitmap bitmap;
int32_t style;
float hotSpotX;
float hotSpotY;
@@ -69,11 +70,12 @@ struct SpriteIcon {
bitmap.readPixels(bitmapCopy.info(), bitmapCopy.getPixels(), bitmapCopy.rowBytes(),
0, 0);
}
return SpriteIcon(bitmapCopy, hotSpotX, hotSpotY);
return SpriteIcon(bitmapCopy, style, hotSpotX, hotSpotY);
}
inline void reset() {
bitmap.reset();
style = 0;
hotSpotX = 0;
hotSpotY = 0;
}
@@ -149,15 +151,15 @@ public:
SpriteController(const sp<Looper>& looper, int32_t overlayLayer);
/* Creates a new sprite, initially invisible. */
sp<Sprite> createSprite();
virtual sp<Sprite> createSprite();
/* Opens or closes a transaction to perform a batch of sprite updates as part of
* a single operation such as setPosition and setAlpha. It is not necessary to
* open a transaction when updating a single property.
* Calls to openTransaction() nest and must be matched by an equal number
* of calls to closeTransaction(). */
void openTransaction();
void closeTransaction();
virtual void openTransaction();
virtual void closeTransaction();
private:
enum {
@@ -174,6 +176,7 @@ private:
DIRTY_VISIBILITY = 1 << 5,
DIRTY_HOTSPOT = 1 << 6,
DIRTY_DISPLAY_ID = 1 << 7,
DIRTY_ICON_STYLE = 1 << 8,
};
/* Describes the state of a sprite.

7
libs/input/TEST_MAPPING Normal file
View File

@@ -0,0 +1,7 @@
{
"presubmit": [
{
"name": "libinputservice_test"
}
]
}

View File

@@ -0,0 +1,45 @@
// Copyright (C) 2019 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.
cc_test {
name: "libinputservice_test",
srcs: [
"PointerController_test.cpp",
],
shared_libs: [
"libinputservice",
"libgui",
"libhwui",
"libutils",
],
static_libs: [
"libgmock",
"libgtest",
],
header_libs: [
"libbase_headers",
"libinputflinger_headers",
],
include_dirs: [
"frameworks/base/libs",
],
cflags: [
"-Wall",
"-Werror",
"-Wextra",
],
test_suites: [
"general-tests",
],
}

View File

@@ -0,0 +1,262 @@
/*
* Copyright (C) 2019 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.
*/
#include "mocks/MockSprite.h"
#include "mocks/MockSpriteController.h"
#include <input/PointerController.h>
#include <input/SpriteController.h>
#include <atomic>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <thread>
namespace android {
enum TestCursorType {
CURSOR_TYPE_DEFAULT = 0,
CURSOR_TYPE_HOVER,
CURSOR_TYPE_TOUCH,
CURSOR_TYPE_ANCHOR,
CURSOR_TYPE_ADDITIONAL,
CURSOR_TYPE_ADDITIONAL_ANIM,
CURSOR_TYPE_CUSTOM = -1,
};
using ::testing::AllOf;
using ::testing::Field;
using ::testing::Mock;
using ::testing::NiceMock;
using ::testing::Return;
using ::testing::Test;
std::pair<float, float> getHotSpotCoordinatesForType(int32_t type) {
return std::make_pair(type * 10, type * 10 + 5);
}
class MockPointerControllerPolicyInterface : public PointerControllerPolicyInterface {
public:
virtual void loadPointerIcon(SpriteIcon* icon, int32_t displayId) override;
virtual void loadPointerResources(PointerResources* outResources, int32_t displayId) override;
virtual void loadAdditionalMouseResources(std::map<int32_t, SpriteIcon>* outResources,
std::map<int32_t, PointerAnimation>* outAnimationResources, int32_t displayId) override;
virtual int32_t getDefaultPointerIconId() override;
virtual int32_t getCustomPointerIconId() override;
bool allResourcesAreLoaded();
bool noResourcesAreLoaded();
private:
void loadPointerIconForType(SpriteIcon* icon, int32_t cursorType);
bool pointerIconLoaded{false};
bool pointerResourcesLoaded{false};
bool additionalMouseResourcesLoaded{false};
};
void MockPointerControllerPolicyInterface::loadPointerIcon(SpriteIcon* icon, int32_t) {
loadPointerIconForType(icon, CURSOR_TYPE_DEFAULT);
pointerIconLoaded = true;
}
void MockPointerControllerPolicyInterface::loadPointerResources(PointerResources* outResources,
int32_t) {
loadPointerIconForType(&outResources->spotHover, CURSOR_TYPE_HOVER);
loadPointerIconForType(&outResources->spotTouch, CURSOR_TYPE_TOUCH);
loadPointerIconForType(&outResources->spotAnchor, CURSOR_TYPE_ANCHOR);
pointerResourcesLoaded = true;
}
void MockPointerControllerPolicyInterface::loadAdditionalMouseResources(
std::map<int32_t, SpriteIcon>* outResources,
std::map<int32_t, PointerAnimation>* outAnimationResources,
int32_t) {
SpriteIcon icon;
PointerAnimation anim;
// CURSOR_TYPE_ADDITIONAL doesn't have animation resource.
int32_t cursorType = CURSOR_TYPE_ADDITIONAL;
loadPointerIconForType(&icon, cursorType);
(*outResources)[cursorType] = icon;
// CURSOR_TYPE_ADDITIONAL_ANIM has animation resource.
cursorType = CURSOR_TYPE_ADDITIONAL_ANIM;
loadPointerIconForType(&icon, cursorType);
anim.animationFrames.push_back(icon);
anim.durationPerFrame = 10;
(*outResources)[cursorType] = icon;
(*outAnimationResources)[cursorType] = anim;
additionalMouseResourcesLoaded = true;
}
int32_t MockPointerControllerPolicyInterface::getDefaultPointerIconId() {
return CURSOR_TYPE_DEFAULT;
}
int32_t MockPointerControllerPolicyInterface::getCustomPointerIconId() {
return CURSOR_TYPE_CUSTOM;
}
bool MockPointerControllerPolicyInterface::allResourcesAreLoaded() {
return pointerIconLoaded && pointerResourcesLoaded && additionalMouseResourcesLoaded;
}
bool MockPointerControllerPolicyInterface::noResourcesAreLoaded() {
return !(pointerIconLoaded || pointerResourcesLoaded || additionalMouseResourcesLoaded);
}
void MockPointerControllerPolicyInterface::loadPointerIconForType(SpriteIcon* icon, int32_t type) {
icon->style = type;
std::pair<float, float> hotSpot = getHotSpotCoordinatesForType(type);
icon->hotSpotX = hotSpot.first;
icon->hotSpotY = hotSpot.second;
}
class PointerControllerTest : public Test {
protected:
PointerControllerTest();
~PointerControllerTest();
void ensureDisplayViewportIsSet();
sp<MockSprite> mPointerSprite;
sp<MockPointerControllerPolicyInterface> mPolicy;
sp<MockSpriteController> mSpriteController;
sp<PointerController> mPointerController;
private:
void loopThread();
std::atomic<bool> mRunning = true;
class MyLooper : public Looper {
public:
MyLooper() : Looper(false) {}
~MyLooper() = default;
};
sp<MyLooper> mLooper;
std::thread mThread;
};
PointerControllerTest::PointerControllerTest() : mPointerSprite(new NiceMock<MockSprite>),
mLooper(new MyLooper), mThread(&PointerControllerTest::loopThread, this) {
mSpriteController = new NiceMock<MockSpriteController>(mLooper);
mPolicy = new MockPointerControllerPolicyInterface();
EXPECT_CALL(*mSpriteController, createSprite())
.WillOnce(Return(mPointerSprite));
mPointerController = new PointerController(mPolicy, mLooper, mSpriteController);
}
PointerControllerTest::~PointerControllerTest() {
mRunning.store(false, std::memory_order_relaxed);
mThread.join();
}
void PointerControllerTest::ensureDisplayViewportIsSet() {
DisplayViewport viewport;
viewport.displayId = ADISPLAY_ID_DEFAULT;
viewport.logicalRight = 1600;
viewport.logicalBottom = 1200;
viewport.physicalRight = 800;
viewport.physicalBottom = 600;
viewport.deviceWidth = 400;
viewport.deviceHeight = 300;
mPointerController->setDisplayViewport(viewport);
// The first call to setDisplayViewport should trigger the loading of the necessary resources.
EXPECT_TRUE(mPolicy->allResourcesAreLoaded());
}
void PointerControllerTest::loopThread() {
Looper::setForThread(mLooper);
while (mRunning.load(std::memory_order_relaxed)) {
mLooper->pollOnce(100);
}
}
TEST_F(PointerControllerTest, useDefaultCursorTypeByDefault) {
ensureDisplayViewportIsSet();
mPointerController->unfade(PointerController::TRANSITION_IMMEDIATE);
std::pair<float, float> hotspot = getHotSpotCoordinatesForType(CURSOR_TYPE_DEFAULT);
EXPECT_CALL(*mPointerSprite, setVisible(true));
EXPECT_CALL(*mPointerSprite, setAlpha(1.0f));
EXPECT_CALL(*mPointerSprite, setIcon(
AllOf(
Field(&SpriteIcon::style, CURSOR_TYPE_DEFAULT),
Field(&SpriteIcon::hotSpotX, hotspot.first),
Field(&SpriteIcon::hotSpotY, hotspot.second))));
mPointerController->reloadPointerResources();
}
TEST_F(PointerControllerTest, updatePointerIcon) {
ensureDisplayViewportIsSet();
mPointerController->unfade(PointerController::TRANSITION_IMMEDIATE);
int32_t type = CURSOR_TYPE_ADDITIONAL;
std::pair<float, float> hotspot = getHotSpotCoordinatesForType(type);
EXPECT_CALL(*mPointerSprite, setVisible(true));
EXPECT_CALL(*mPointerSprite, setAlpha(1.0f));
EXPECT_CALL(*mPointerSprite, setIcon(
AllOf(
Field(&SpriteIcon::style, type),
Field(&SpriteIcon::hotSpotX, hotspot.first),
Field(&SpriteIcon::hotSpotY, hotspot.second))));
mPointerController->updatePointerIcon(type);
}
TEST_F(PointerControllerTest, setCustomPointerIcon) {
ensureDisplayViewportIsSet();
mPointerController->unfade(PointerController::TRANSITION_IMMEDIATE);
int32_t style = CURSOR_TYPE_CUSTOM;
float hotSpotX = 15;
float hotSpotY = 20;
SpriteIcon icon;
icon.style = style;
icon.hotSpotX = hotSpotX;
icon.hotSpotY = hotSpotY;
EXPECT_CALL(*mPointerSprite, setVisible(true));
EXPECT_CALL(*mPointerSprite, setAlpha(1.0f));
EXPECT_CALL(*mPointerSprite, setIcon(
AllOf(
Field(&SpriteIcon::style, style),
Field(&SpriteIcon::hotSpotX, hotSpotX),
Field(&SpriteIcon::hotSpotY, hotSpotY))));
mPointerController->setCustomPointerIcon(icon);
}
TEST_F(PointerControllerTest, doesNotGetResourcesBeforeSettingViewport) {
mPointerController->setPresentation(PointerController::PRESENTATION_POINTER);
mPointerController->setSpots(nullptr, nullptr, BitSet32(), -1);
mPointerController->clearSpots();
mPointerController->setPosition(1.0f, 1.0f);
mPointerController->move(1.0f, 1.0f);
mPointerController->unfade(PointerController::TRANSITION_IMMEDIATE);
mPointerController->fade(PointerController::TRANSITION_IMMEDIATE);
EXPECT_TRUE(mPolicy->noResourcesAreLoaded());
ensureDisplayViewportIsSet();
}
} // namespace android

View File

@@ -0,0 +1,41 @@
/*
* Copyright (C) 2019 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 _MOCK_SPRITE_H
#define _MOCK_SPRITE_H
#include <input/SpriteController.h>
#include <gmock/gmock.h>
namespace android {
class MockSprite : public Sprite {
public:
virtual ~MockSprite() = default;
MOCK_METHOD(void, setIcon, (const SpriteIcon& icon), (override));
MOCK_METHOD(void, setVisible, (bool), (override));
MOCK_METHOD(void, setPosition, (float, float), (override));
MOCK_METHOD(void, setLayer, (int32_t), (override));
MOCK_METHOD(void, setAlpha, (float), (override));
MOCK_METHOD(void, setTransformationMatrix, (const SpriteTransformationMatrix&), (override));
MOCK_METHOD(void, setDisplayId, (int32_t), (override));
};
} // namespace android
#endif // _MOCK_SPRITE_H

View File

@@ -0,0 +1,39 @@
/*
* Copyright (C) 2019 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 _MOCK_SPRITE_CONTROLLER_H
#define _MOCK_SPRITE_CONTROLLER_H
#include "MockSprite.h"
#include <input/SpriteController.h>
namespace android {
class MockSpriteController : public SpriteController {
public:
MockSpriteController(sp<Looper> looper) : SpriteController(looper, 0) {}
~MockSpriteController() {}
MOCK_METHOD(sp<Sprite>, createSprite, (), (override));
MOCK_METHOD(void, openTransaction, (), (override));
MOCK_METHOD(void, closeTransaction, (), (override));
};
} // namespace android
#endif // _MOCK_SPRITE_CONTROLLER_H

View File

@@ -166,6 +166,7 @@ static void loadSystemIconAsSpriteWithPointerIcon(JNIEnv* env, jobject contextOb
outPointerIcon->bitmap.readPixels(bitmapCopy->info(), bitmapCopy->getPixels(),
bitmapCopy->rowBytes(), 0, 0);
}
outSpriteIcon->style = outPointerIcon->style;
outSpriteIcon->hotSpotX = outPointerIcon->hotSpotX;
outSpriteIcon->hotSpotY = outPointerIcon->hotSpotY;
}
@@ -318,7 +319,6 @@ private:
void updateInactivityTimeoutLocked();
void handleInterceptActions(jint wmActions, nsecs_t when, uint32_t& policyFlags);
void ensureSpriteControllerLocked();
const DisplayViewport* findDisplayViewportLocked(int32_t displayId);
int32_t getPointerDisplayId();
void updatePointerDisplayLocked();
static bool checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName);
@@ -396,16 +396,6 @@ bool NativeInputManager::checkAndClearExceptionFromCallback(JNIEnv* env, const c
return false;
}
const DisplayViewport* NativeInputManager::findDisplayViewportLocked(int32_t displayId)
REQUIRES(mLock) {
for (const DisplayViewport& v : mLocked.viewports) {
if (v.displayId == displayId) {
return &v;
}
}
return nullptr;
}
void NativeInputManager::setDisplayViewports(JNIEnv* env, jobjectArray viewportObjArray) {
std::vector<DisplayViewport> viewports;
@@ -554,6 +544,8 @@ void NativeInputManager::getReaderConfiguration(InputReaderConfiguration* outCon
outConfig->setDisplayViewports(mLocked.viewports);
outConfig->defaultPointerDisplayId = mLocked.pointerDisplayId;
outConfig->disabledDevices = mLocked.disabledInputDevices;
} // release lock
}
@@ -571,8 +563,6 @@ sp<PointerControllerInterface> NativeInputManager::obtainPointerController(int32
updateInactivityTimeoutLocked();
}
updatePointerDisplayLocked();
return controller;
}
@@ -587,23 +577,6 @@ int32_t NativeInputManager::getPointerDisplayId() {
return pointerDisplayId;
}
void NativeInputManager::updatePointerDisplayLocked() REQUIRES(mLock) {
ATRACE_CALL();
sp<PointerController> controller = mLocked.pointerController.promote();
if (controller != nullptr) {
const DisplayViewport* viewport = findDisplayViewportLocked(mLocked.pointerDisplayId);
if (viewport == nullptr) {
ALOGW("Can't find pointer display viewport, fallback to default display.");
viewport = findDisplayViewportLocked(ADISPLAY_ID_DEFAULT);
}
if (viewport != nullptr) {
controller->setDisplayViewport(*viewport);
}
}
}
void NativeInputManager::ensureSpriteControllerLocked() REQUIRES(mLock) {
if (mLocked.spriteController == nullptr) {
JNIEnv* env = jniEnv();
@@ -1252,7 +1225,8 @@ void NativeInputManager::loadPointerIcon(SpriteIcon* icon, int32_t displayId) {
status_t status = android_view_PointerIcon_load(env, pointerIconObj.get(),
displayContext.get(), &pointerIcon);
if (!status && !pointerIcon.isNullIcon()) {
*icon = SpriteIcon(pointerIcon.bitmap, pointerIcon.hotSpotX, pointerIcon.hotSpotY);
*icon = SpriteIcon(
pointerIcon.bitmap, pointerIcon.style, pointerIcon.hotSpotX, pointerIcon.hotSpotY);
} else {
*icon = SpriteIcon();
}
@@ -1293,10 +1267,12 @@ void NativeInputManager::loadAdditionalMouseResources(std::map<int32_t, SpriteIc
milliseconds_to_nanoseconds(pointerIcon.durationPerFrame);
animationData.animationFrames.reserve(numFrames);
animationData.animationFrames.push_back(SpriteIcon(
pointerIcon.bitmap, pointerIcon.hotSpotX, pointerIcon.hotSpotY));
pointerIcon.bitmap, pointerIcon.style,
pointerIcon.hotSpotX, pointerIcon.hotSpotY));
for (size_t i = 0; i < numFrames - 1; ++i) {
animationData.animationFrames.push_back(SpriteIcon(
pointerIcon.bitmapFrames[i], pointerIcon.hotSpotX, pointerIcon.hotSpotY));
pointerIcon.bitmapFrames[i], pointerIcon.style,
pointerIcon.hotSpotX, pointerIcon.hotSpotY));
}
}
}
@@ -1732,6 +1708,7 @@ static void nativeSetCustomPointerIcon(JNIEnv* env, jclass /* clazz */,
pointerIcon.bitmap.readPixels(spriteInfo, spriteIcon.bitmap.getPixels(),
spriteIcon.bitmap.rowBytes(), 0, 0);
}
spriteIcon.style = pointerIcon.style;
spriteIcon.hotSpotX = pointerIcon.hotSpotX;
spriteIcon.hotSpotY = pointerIcon.hotSpotY;
im->setCustomPointerIcon(spriteIcon);