diff options
Diffstat (limited to 'libs')
| -rw-r--r-- | libs/androidfw/include/androidfw/ResourceTypes.h | 4 | ||||
| -rw-r--r-- | libs/hwui/Android.bp | 1 | ||||
| -rw-r--r-- | libs/hwui/Readback.cpp | 2 | ||||
| -rw-r--r-- | libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp | 5 | ||||
| -rw-r--r-- | libs/hwui/renderthread/RenderProxy.cpp | 8 | ||||
| -rw-r--r-- | libs/hwui/renderthread/RenderProxy.h | 2 | ||||
| -rw-r--r-- | libs/hwui/renderthread/RenderThread.cpp | 40 | ||||
| -rw-r--r-- | libs/hwui/renderthread/RenderThread.h | 5 | ||||
| -rw-r--r-- | libs/hwui/renderthread/VulkanManager.cpp | 69 | ||||
| -rw-r--r-- | libs/hwui/renderthread/VulkanManager.h | 23 | ||||
| -rw-r--r-- | libs/hwui/tests/common/TestUtils.cpp | 2 | ||||
| -rw-r--r-- | libs/hwui/tests/unit/RenderThreadTests.cpp | 29 | ||||
| -rw-r--r-- | libs/hwui/thread/ThreadBase.h | 2 | ||||
| -rw-r--r-- | libs/incident/proto/android/os/header.proto | 5 | ||||
| -rw-r--r-- | libs/input/PointerController.cpp | 124 | ||||
| -rw-r--r-- | libs/input/PointerController.h | 14 |
16 files changed, 223 insertions, 112 deletions
diff --git a/libs/androidfw/include/androidfw/ResourceTypes.h b/libs/androidfw/include/androidfw/ResourceTypes.h index 742813e58129..875b90b7ac65 100644 --- a/libs/androidfw/include/androidfw/ResourceTypes.h +++ b/libs/androidfw/include/androidfw/ResourceTypes.h @@ -1647,6 +1647,10 @@ struct ResTable_overlayable_policy_header // The overlay must reside of the product partition or must have existed on the product // partition before an upgrade to overlay these resources. POLICY_PRODUCT_PARTITION = 0x00000008, + + // The overlay must be signed with the same signature as the actor of the target resource, + // which can be separate or the same as the target package with the resource. + POLICY_SIGNATURE = 0x00000010, }; uint32_t policy_flags; diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp index 0335a7c6bd7d..793dd8d39376 100644 --- a/libs/hwui/Android.bp +++ b/libs/hwui/Android.bp @@ -318,6 +318,7 @@ cc_test { "tests/unit/RenderNodeDrawableTests.cpp", "tests/unit/RenderNodeTests.cpp", "tests/unit/RenderPropertiesTests.cpp", + "tests/unit/RenderThreadTests.cpp", "tests/unit/ShaderCacheTests.cpp", "tests/unit/SkiaBehaviorTests.cpp", "tests/unit/SkiaDisplayListTests.cpp", diff --git a/libs/hwui/Readback.cpp b/libs/hwui/Readback.cpp index 76c56609ef47..2ffda839c210 100644 --- a/libs/hwui/Readback.cpp +++ b/libs/hwui/Readback.cpp @@ -107,7 +107,7 @@ CopyResult Readback::copyImageInto(const sk_sp<SkImage>& image, Matrix4& texTran if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaGL) { mRenderThread.requireGlContext(); } else { - mRenderThread.vulkanManager().initialize(); + mRenderThread.requireVkContext(); } if (!image.get()) { return CopyResult::UnknownError; diff --git a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp index 15f53f286261..87cffb52c150 100644 --- a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp +++ b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp @@ -120,7 +120,7 @@ bool SkiaVulkanPipeline::swapBuffers(const Frame& frame, bool drew, const SkRect } DeferredLayerUpdater* SkiaVulkanPipeline::createTextureLayer() { - mVkManager.initialize(); + mRenderThread.requireVkContext(); return new DeferredLayerUpdater(mRenderThread.renderState()); } @@ -136,8 +136,9 @@ bool SkiaVulkanPipeline::setSurface(ANativeWindow* surface, SwapBehavior swapBeh setSurfaceColorProperties(colorMode); if (surface) { + mRenderThread.requireVkContext(); mVkSurface = mVkManager.createSurface(surface, colorMode, mSurfaceColorSpace, - mSurfaceColorType); + mSurfaceColorType, mRenderThread.getGrContext()); } return mVkSurface != nullptr; diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp index 720c60362a55..34f76d9b3579 100644 --- a/libs/hwui/renderthread/RenderProxy.cpp +++ b/libs/hwui/renderthread/RenderProxy.cpp @@ -381,6 +381,14 @@ void RenderProxy::releaseVDAtlasEntries() { }); } +void RenderProxy::preload() { + // Create RenderThread object and start the thread. Then preload Vulkan/EGL driver. + auto& thread = RenderThread::getInstance(); + thread.queue().post([&thread]() { + thread.preload(); + }); +} + } /* namespace renderthread */ } /* namespace uirenderer */ } /* namespace android */ diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h index 6e1bfd74528a..a1a5551722bc 100644 --- a/libs/hwui/renderthread/RenderProxy.h +++ b/libs/hwui/renderthread/RenderProxy.h @@ -131,6 +131,8 @@ public: ANDROID_API static void disableVsync(); + ANDROID_API static void preload(); + static void repackVectorDrawableAtlas(); static void releaseVDAtlasEntries(); diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp index 3904ed20fd77..08edd20c0a0d 100644 --- a/libs/hwui/renderthread/RenderThread.cpp +++ b/libs/hwui/renderthread/RenderThread.cpp @@ -41,6 +41,7 @@ #include <utils/Condition.h> #include <utils/Log.h> #include <utils/Mutex.h> +#include <thread> namespace android { namespace uirenderer { @@ -173,11 +174,8 @@ void RenderThread::initThreadLocals() { initializeDisplayEventReceiver(); mEglManager = new EglManager(); mRenderState = new RenderState(*this); - mVkManager = new VulkanManager(*this); + mVkManager = new VulkanManager(); mCacheManager = new CacheManager(mDisplayInfo); - if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaVulkan) { - mVkManager->initialize(); - } } void RenderThread::requireGlContext() { @@ -195,8 +193,7 @@ void RenderThread::requireGlContext() { LOG_ALWAYS_FATAL_IF(!glInterface.get()); GrContextOptions options; - options.fPreferExternalImagesOverES3 = true; - options.fDisableDistanceFieldPaths = true; + initGrContextOptions(options); auto glesVersion = reinterpret_cast<const char*>(glGetString(GL_VERSION)); auto size = glesVersion ? strlen(glesVersion) : -1; cacheManager().configureContext(&options, glesVersion, size); @@ -205,6 +202,25 @@ void RenderThread::requireGlContext() { setGrContext(grContext); } +void RenderThread::requireVkContext() { + if (mVkManager->hasVkContext()) { + return; + } + mVkManager->initialize(); + GrContextOptions options; + initGrContextOptions(options); + // TODO: get a string describing the SPIR-V compiler version and use it here + cacheManager().configureContext(&options, nullptr, 0); + sk_sp<GrContext> grContext = mVkManager->createContext(options); + LOG_ALWAYS_FATAL_IF(!grContext.get()); + setGrContext(grContext); +} + +void RenderThread::initGrContextOptions(GrContextOptions& options) { + options.fPreferExternalImagesOverES3 = true; + options.fDisableDistanceFieldPaths = true; +} + void RenderThread::destroyRenderingContext() { mFunctorManager.onContextDestroyed(); if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaGL) { @@ -328,6 +344,7 @@ void RenderThread::requestVsync() { bool RenderThread::threadLoop() { setpriority(PRIO_PROCESS, 0, PRIORITY_DISPLAY); + Looper::setForThread(mLooper); if (gOnStartHook) { gOnStartHook("RenderThread"); } @@ -390,6 +407,17 @@ bool RenderThread::isCurrent() { return gettid() == getInstance().getTid(); } +void RenderThread::preload() { + std::thread eglInitThread([]() { + //TODO: don't load EGL drivers for Vulkan, when HW bitmap uploader is refactored. + eglGetDisplay(EGL_DEFAULT_DISPLAY); + }); + eglInitThread.detach(); + if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaVulkan) { + requireVkContext(); + } +} + } /* namespace renderthread */ } /* namespace uirenderer */ } /* namespace android */ diff --git a/libs/hwui/renderthread/RenderThread.h b/libs/hwui/renderthread/RenderThread.h index b18292820c6b..329b4b99c911 100644 --- a/libs/hwui/renderthread/RenderThread.h +++ b/libs/hwui/renderthread/RenderThread.h @@ -112,8 +112,11 @@ public: void dumpGraphicsMemory(int fd); void requireGlContext(); + void requireVkContext(); void destroyRenderingContext(); + void preload(); + /** * isCurrent provides a way to query, if the caller is running on * the render thread. @@ -122,6 +125,8 @@ public: */ static bool isCurrent(); + static void initGrContextOptions(GrContextOptions& options); + protected: virtual bool threadLoop() override; diff --git a/libs/hwui/renderthread/VulkanManager.cpp b/libs/hwui/renderthread/VulkanManager.cpp index 90397fddf618..3b43f1297597 100644 --- a/libs/hwui/renderthread/VulkanManager.cpp +++ b/libs/hwui/renderthread/VulkanManager.cpp @@ -55,11 +55,7 @@ static void free_features_extensions_structs(const VkPhysicalDeviceFeatures2& fe #define GET_INST_PROC(F) m##F = (PFN_vk##F)vkGetInstanceProcAddr(mInstance, "vk" #F) #define GET_DEV_PROC(F) m##F = (PFN_vk##F)vkGetDeviceProcAddr(mDevice, "vk" #F) -VulkanManager::VulkanManager(RenderThread& thread) : mRenderThread(thread) {} - void VulkanManager::destroy() { - mRenderThread.setGrContext(nullptr); - // We don't need to explicitly free the command buffer since it automatically gets freed when we // delete the VkCommandPool below. mDummyCB = VK_NULL_HANDLE; @@ -333,29 +329,10 @@ void VulkanManager::initialize() { LOG_ALWAYS_FATAL_IF(mEnumerateInstanceVersion(&instanceVersion)); LOG_ALWAYS_FATAL_IF(instanceVersion < VK_MAKE_VERSION(1, 1, 0)); - GrVkExtensions extensions; - this->setupDevice(extensions, mPhysicalDeviceFeatures2); + this->setupDevice(mExtensions, mPhysicalDeviceFeatures2); mGetDeviceQueue(mDevice, mGraphicsQueueIndex, 0, &mGraphicsQueue); - auto getProc = [] (const char* proc_name, VkInstance instance, VkDevice device) { - if (device != VK_NULL_HANDLE) { - return vkGetDeviceProcAddr(device, proc_name); - } - return vkGetInstanceProcAddr(instance, proc_name); - }; - - GrVkBackendContext backendContext; - backendContext.fInstance = mInstance; - backendContext.fPhysicalDevice = mPhysicalDevice; - backendContext.fDevice = mDevice; - backendContext.fQueue = mGraphicsQueue; - backendContext.fGraphicsQueueIndex = mGraphicsQueueIndex; - backendContext.fMaxAPIVersion = mAPIVersion; - backendContext.fVkExtensions = &extensions; - backendContext.fDeviceFeatures2 = &mPhysicalDeviceFeatures2; - backendContext.fGetProc = std::move(getProc); - // create the command pool for the command buffers if (VK_NULL_HANDLE == mCommandPool) { VkCommandPoolCreateInfo commandPoolInfo; @@ -376,22 +353,35 @@ void VulkanManager::initialize() { } LOG_ALWAYS_FATAL_IF(mDummyCB == VK_NULL_HANDLE); - mGetDeviceQueue(mDevice, mPresentQueueIndex, 0, &mPresentQueue); - GrContextOptions options; - options.fDisableDistanceFieldPaths = true; - // TODO: get a string describing the SPIR-V compiler version and use it here - mRenderThread.cacheManager().configureContext(&options, nullptr, 0); - sk_sp<GrContext> grContext(GrContext::MakeVulkan(backendContext, options)); - LOG_ALWAYS_FATAL_IF(!grContext.get()); - mRenderThread.setGrContext(grContext); - if (Properties::enablePartialUpdates && Properties::useBufferAge) { mSwapBehavior = SwapBehavior::BufferAge; } } +sk_sp<GrContext> VulkanManager::createContext(const GrContextOptions& options) { + auto getProc = [] (const char* proc_name, VkInstance instance, VkDevice device) { + if (device != VK_NULL_HANDLE) { + return vkGetDeviceProcAddr(device, proc_name); + } + return vkGetInstanceProcAddr(instance, proc_name); + }; + + GrVkBackendContext backendContext; + backendContext.fInstance = mInstance; + backendContext.fPhysicalDevice = mPhysicalDevice; + backendContext.fDevice = mDevice; + backendContext.fQueue = mGraphicsQueue; + backendContext.fGraphicsQueueIndex = mGraphicsQueueIndex; + backendContext.fMaxAPIVersion = mAPIVersion; + backendContext.fVkExtensions = &mExtensions; + backendContext.fDeviceFeatures2 = &mPhysicalDeviceFeatures2; + backendContext.fGetProc = std::move(getProc); + + return GrContext::MakeVulkan(backendContext, options); +} + VkFunctorInitParams VulkanManager::getVkFunctorInitParams() const { return VkFunctorInitParams{ .instance = mInstance, @@ -470,8 +460,9 @@ SkSurface* VulkanManager::getBackbufferSurface(VulkanSurface** surfaceOut) { ColorMode colorMode = surface->mColorMode; sk_sp<SkColorSpace> colorSpace = surface->mColorSpace; SkColorType colorType = surface->mColorType; + GrContext* grContext = surface->mGrContext; destroySurface(surface); - *surfaceOut = createSurface(window, colorMode, colorSpace, colorType); + *surfaceOut = createSurface(window, colorMode, colorSpace, colorType, grContext); surface = *surfaceOut; if (!surface) { return nullptr; @@ -650,7 +641,7 @@ void VulkanManager::createBuffers(VulkanSurface* surface, VkFormat format, VkExt VulkanSurface::ImageInfo& imageInfo = surface->mImageInfos[i]; imageInfo.mSurface = SkSurface::MakeFromBackendRenderTarget( - mRenderThread.getGrContext(), backendRT, kTopLeft_GrSurfaceOrigin, + surface->mGrContext, backendRT, kTopLeft_GrSurfaceOrigin, surface->mColorType, surface->mColorSpace, &props); } @@ -880,15 +871,15 @@ bool VulkanManager::createSwapchain(VulkanSurface* surface) { VulkanSurface* VulkanManager::createSurface(ANativeWindow* window, ColorMode colorMode, sk_sp<SkColorSpace> surfaceColorSpace, - SkColorType surfaceColorType) { - initialize(); - + SkColorType surfaceColorType, + GrContext* grContext) { + LOG_ALWAYS_FATAL_IF(!hasVkContext(), "Not initialized"); if (!window) { return nullptr; } VulkanSurface* surface = new VulkanSurface(colorMode, window, surfaceColorSpace, - surfaceColorType); + surfaceColorType, grContext); VkAndroidSurfaceCreateInfoKHR surfaceCreateInfo; memset(&surfaceCreateInfo, 0, sizeof(VkAndroidSurfaceCreateInfoKHR)); diff --git a/libs/hwui/renderthread/VulkanManager.h b/libs/hwui/renderthread/VulkanManager.h index 1fe6c65b35b8..95c9630fb728 100644 --- a/libs/hwui/renderthread/VulkanManager.h +++ b/libs/hwui/renderthread/VulkanManager.h @@ -22,6 +22,8 @@ #endif #include <vulkan/vulkan.h> +#include <GrContextOptions.h> +#include <vk/GrVkExtensions.h> #include <SkSurface.h> #include <ui/Fence.h> #include <utils/StrongPointer.h> @@ -39,9 +41,9 @@ class RenderThread; class VulkanSurface { public: VulkanSurface(ColorMode colorMode, ANativeWindow* window, sk_sp<SkColorSpace> colorSpace, - SkColorType colorType) + SkColorType colorType, GrContext* grContext) : mColorMode(colorMode), mNativeWindow(window), mColorSpace(colorSpace), - mColorType(colorType) {} + mColorType(colorType), mGrContext(grContext) {} sk_sp<SkSurface> getBackBufferSurface() { return mBackbuffer; } @@ -93,6 +95,7 @@ private: SkColorType mColorType; VkSurfaceTransformFlagBitsKHR mTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; SkMatrix mPreTransform; + GrContext* mGrContext; }; // This class contains the shared global Vulkan objects, such as VkInstance, VkDevice and VkQueue, @@ -100,6 +103,9 @@ private: // windowing contexts. The VulkanManager must be initialized before use. class VulkanManager { public: + explicit VulkanManager() {} + ~VulkanManager() { destroy(); } + // Sets up the vulkan context that is shared amonst all clients of the VulkanManager. This must // be call once before use of the VulkanManager. Multiple calls after the first will simiply // return. @@ -112,7 +118,8 @@ public: // VulkanSurface object which is returned. VulkanSurface* createSurface(ANativeWindow* window, ColorMode colorMode, sk_sp<SkColorSpace> surfaceColorSpace, - SkColorType surfaceColorType); + SkColorType surfaceColorType, + GrContext* grContext); // Destroy the VulkanSurface and all associated vulkan objects. void destroySurface(VulkanSurface* surface); @@ -143,12 +150,9 @@ public: // Returned pointers are owned by VulkanManager. VkFunctorInitParams getVkFunctorInitParams() const; -private: - friend class RenderThread; - - explicit VulkanManager(RenderThread& thread); - ~VulkanManager() { destroy(); } + sk_sp<GrContext> createContext(const GrContextOptions& options); +private: // Sets up the VkInstance and VkDevice objects. Also fills out the passed in // VkPhysicalDeviceFeatures struct. void setupDevice(GrVkExtensions&, VkPhysicalDeviceFeatures2&); @@ -231,8 +235,6 @@ private: VkPtr<PFN_vkWaitForFences> mWaitForFences; VkPtr<PFN_vkResetFences> mResetFences; - RenderThread& mRenderThread; - VkInstance mInstance = VK_NULL_HANDLE; VkPhysicalDevice mPhysicalDevice = VK_NULL_HANDLE; VkDevice mDevice = VK_NULL_HANDLE; @@ -256,6 +258,7 @@ private: BufferAge, }; SwapBehavior mSwapBehavior = SwapBehavior::Discard; + GrVkExtensions mExtensions; }; } /* namespace renderthread */ diff --git a/libs/hwui/tests/common/TestUtils.cpp b/libs/hwui/tests/common/TestUtils.cpp index a9f651d38a06..e8ba15fe92af 100644 --- a/libs/hwui/tests/common/TestUtils.cpp +++ b/libs/hwui/tests/common/TestUtils.cpp @@ -100,7 +100,7 @@ void TestUtils::TestTask::run() { // RenderState only valid once RenderThread is running, so queried here renderthread::RenderThread& renderThread = renderthread::RenderThread::getInstance(); if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaVulkan) { - renderThread.vulkanManager().initialize(); + renderThread.requireVkContext(); } else { renderThread.requireGlContext(); } diff --git a/libs/hwui/tests/unit/RenderThreadTests.cpp b/libs/hwui/tests/unit/RenderThreadTests.cpp new file mode 100644 index 000000000000..af8ae7841af2 --- /dev/null +++ b/libs/hwui/tests/unit/RenderThreadTests.cpp @@ -0,0 +1,29 @@ +/* + * 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 <gtest/gtest.h> + +#include "tests/common/TestUtils.h" +#include <utils/Looper.h> + +using namespace android; +using namespace android::uirenderer; +using namespace android::uirenderer::renderthread; + +RENDERTHREAD_TEST(RenderThread, isLooper) { + ASSERT_TRUE(Looper::getForThread() != nullptr); +} + diff --git a/libs/hwui/thread/ThreadBase.h b/libs/hwui/thread/ThreadBase.h index 8cdcc46b97fb..0289d3fd2ef7 100644 --- a/libs/hwui/thread/ThreadBase.h +++ b/libs/hwui/thread/ThreadBase.h @@ -68,10 +68,12 @@ protected: void processQueue() { mQueue.process(); } virtual bool threadLoop() override { + Looper::setForThread(mLooper); while (!exitPending()) { waitForWork(); processQueue(); } + Looper::setForThread(nullptr); return false; } diff --git a/libs/incident/proto/android/os/header.proto b/libs/incident/proto/android/os/header.proto index a84dc48b8b34..d463f87055b3 100644 --- a/libs/incident/proto/android/os/header.proto +++ b/libs/incident/proto/android/os/header.proto @@ -37,4 +37,9 @@ message IncidentHeaderProto { optional int64 id = 2; // The unique id of the statsd config. } optional StatsdConfigKey config_key = 3; + + // Details about the trigger. com.android.os.AlertTriggerDetails + // Only use bytes type here to avoid indirect dependency on atoms.proto + // And this header passes through incidentd without incidentd parsing it. + optional bytes trigger_details = 4; } diff --git a/libs/input/PointerController.cpp b/libs/input/PointerController.cpp index d742cc34b57e..733b866d9c4c 100644 --- a/libs/input/PointerController.cpp +++ b/libs/input/PointerController.cpp @@ -115,10 +115,14 @@ PointerController::~PointerController() { mLocked.pointerSprite.clear(); - for (size_t i = 0; i < mLocked.spots.size(); i++) { - delete mLocked.spots.itemAt(i); + for (auto& it : mLocked.spotsByDisplay) { + const std::vector<Spot*>& spots = it.second; + size_t numSpots = spots.size(); + for (size_t i = 0; i < numSpots; i++) { + delete spots[i]; + } } - mLocked.spots.clear(); + mLocked.spotsByDisplay.clear(); mLocked.recycledSprites.clear(); } @@ -271,22 +275,30 @@ void PointerController::setPresentation(Presentation presentation) { } void PointerController::setSpots(const PointerCoords* spotCoords, - const uint32_t* spotIdToIndex, BitSet32 spotIdBits) { + const uint32_t* spotIdToIndex, BitSet32 spotIdBits, int32_t displayId) { #if DEBUG_POINTER_UPDATES ALOGD("setSpots: idBits=%08x", spotIdBits.value); for (BitSet32 idBits(spotIdBits); !idBits.isEmpty(); ) { uint32_t id = idBits.firstMarkedBit(); idBits.clearBit(id); const PointerCoords& c = spotCoords[spotIdToIndex[id]]; - ALOGD(" spot %d: position=(%0.3f, %0.3f), pressure=%0.3f", id, + ALOGD(" spot %d: position=(%0.3f, %0.3f), pressure=%0.3f, displayId=%" PRId32 ".", id, c.getAxisValue(AMOTION_EVENT_AXIS_X), c.getAxisValue(AMOTION_EVENT_AXIS_Y), - c.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE)); + c.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE), + displayId); } #endif AutoMutex _l(mLock); + std::vector<Spot*> newSpots; + std::map<int32_t, std::vector<Spot*>>::const_iterator iter = + mLocked.spotsByDisplay.find(displayId); + if (iter != mLocked.spotsByDisplay.end()) { + newSpots = iter->second; + } + mSpriteController->openTransaction(); // Add or move spots for fingers that are down. @@ -298,17 +310,17 @@ void PointerController::setSpots(const PointerCoords* spotCoords, float x = c.getAxisValue(AMOTION_EVENT_AXIS_X); float y = c.getAxisValue(AMOTION_EVENT_AXIS_Y); - Spot* spot = getSpotLocked(id); + Spot* spot = getSpot(id, newSpots); if (!spot) { - spot = createAndAddSpotLocked(id); + spot = createAndAddSpotLocked(id, newSpots); } - spot->updateSprite(&icon, x, y); + spot->updateSprite(&icon, x, y, displayId); } // Remove spots for fingers that went up. - for (size_t i = 0; i < mLocked.spots.size(); i++) { - Spot* spot = mLocked.spots.itemAt(i); + for (size_t i = 0; i < newSpots.size(); i++) { + Spot* spot = newSpots[i]; if (spot->id != Spot::INVALID_ID && !spotIdBits.hasBit(spot->id)) { fadeOutAndReleaseSpotLocked(spot); @@ -316,6 +328,7 @@ void PointerController::setSpots(const PointerCoords* spotCoords, } mSpriteController->closeTransaction(); + mLocked.spotsByDisplay[displayId] = newSpots; } void PointerController::clearSpots() { @@ -539,21 +552,33 @@ bool PointerController::doFadingAnimationLocked(nsecs_t timestamp) { } // Animate spots that are fading out and being removed. - for (size_t i = 0; i < mLocked.spots.size();) { - Spot* spot = mLocked.spots.itemAt(i); - if (spot->id == Spot::INVALID_ID) { - spot->alpha -= float(frameDelay) / SPOT_FADE_DURATION; - if (spot->alpha <= 0) { - mLocked.spots.removeAt(i); - releaseSpotLocked(spot); - continue; - } else { - spot->sprite->setAlpha(spot->alpha); - keepAnimating = true; + for(auto it = mLocked.spotsByDisplay.begin(); it != mLocked.spotsByDisplay.end();) { + std::vector<Spot*>& spots = it->second; + size_t numSpots = spots.size(); + for (size_t i = 0; i < numSpots;) { + Spot* spot = spots[i]; + if (spot->id == Spot::INVALID_ID) { + spot->alpha -= float(frameDelay) / SPOT_FADE_DURATION; + if (spot->alpha <= 0) { + spots.erase(spots.begin() + i); + releaseSpotLocked(spot); + numSpots--; + continue; + } else { + spot->sprite->setAlpha(spot->alpha); + keepAnimating = true; + } } + ++i; + } + + if (spots.size() == 0) { + it = mLocked.spotsByDisplay.erase(it); + } else { + ++it; } - ++i; } + return keepAnimating; } @@ -655,47 +680,49 @@ void PointerController::updatePointerLocked() REQUIRES(mLock) { mSpriteController->closeTransaction(); } -PointerController::Spot* PointerController::getSpotLocked(uint32_t id) { - for (size_t i = 0; i < mLocked.spots.size(); i++) { - Spot* spot = mLocked.spots.itemAt(i); +PointerController::Spot* PointerController::getSpot(uint32_t id, const std::vector<Spot*>& spots) { + for (size_t i = 0; i < spots.size(); i++) { + Spot* spot = spots[i]; if (spot->id == id) { return spot; } } - return NULL; + + return nullptr; } -PointerController::Spot* PointerController::createAndAddSpotLocked(uint32_t id) { +PointerController::Spot* PointerController::createAndAddSpotLocked(uint32_t id, + std::vector<Spot*>& spots) { // Remove spots until we have fewer than MAX_SPOTS remaining. - while (mLocked.spots.size() >= MAX_SPOTS) { - Spot* spot = removeFirstFadingSpotLocked(); + while (spots.size() >= MAX_SPOTS) { + Spot* spot = removeFirstFadingSpotLocked(spots); if (!spot) { - spot = mLocked.spots.itemAt(0); - mLocked.spots.removeAt(0); + spot = spots[0]; + spots.erase(spots.begin()); } releaseSpotLocked(spot); } // Obtain a sprite from the recycled pool. sp<Sprite> sprite; - if (! mLocked.recycledSprites.isEmpty()) { - sprite = mLocked.recycledSprites.top(); - mLocked.recycledSprites.pop(); + if (! mLocked.recycledSprites.empty()) { + sprite = mLocked.recycledSprites.back(); + mLocked.recycledSprites.pop_back(); } else { sprite = mSpriteController->createSprite(); } // Return the new spot. Spot* spot = new Spot(id, sprite); - mLocked.spots.push(spot); + spots.push_back(spot); return spot; } -PointerController::Spot* PointerController::removeFirstFadingSpotLocked() { - for (size_t i = 0; i < mLocked.spots.size(); i++) { - Spot* spot = mLocked.spots.itemAt(i); +PointerController::Spot* PointerController::removeFirstFadingSpotLocked(std::vector<Spot*>& spots) { + for (size_t i = 0; i < spots.size(); i++) { + Spot* spot = spots[i]; if (spot->id == Spot::INVALID_ID) { - mLocked.spots.removeAt(i); + spots.erase(spots.begin() + i); return spot; } } @@ -706,7 +733,7 @@ void PointerController::releaseSpotLocked(Spot* spot) { spot->sprite->clearIcon(); if (mLocked.recycledSprites.size() < MAX_RECYCLED_SPRITES) { - mLocked.recycledSprites.push(spot->sprite); + mLocked.recycledSprites.push_back(spot->sprite); } delete spot; @@ -720,9 +747,13 @@ void PointerController::fadeOutAndReleaseSpotLocked(Spot* spot) { } void PointerController::fadeOutAndReleaseAllSpotsLocked() { - for (size_t i = 0; i < mLocked.spots.size(); i++) { - Spot* spot = mLocked.spots.itemAt(i); - fadeOutAndReleaseSpotLocked(spot); + for (auto& it : mLocked.spotsByDisplay) { + const std::vector<Spot*>& spots = it.second; + size_t numSpots = spots.size(); + for (size_t i = 0; i < numSpots; i++) { + Spot* spot = spots[i]; + fadeOutAndReleaseSpotLocked(spot); + } } } @@ -743,12 +774,13 @@ void PointerController::loadResourcesLocked() REQUIRES(mLock) { // --- PointerController::Spot --- -void PointerController::Spot::updateSprite(const SpriteIcon* icon, float x, float y) { +void PointerController::Spot::updateSprite(const SpriteIcon* icon, float x, float y, + int32_t displayId) { sprite->setLayer(Sprite::BASE_LAYER_SPOT + id); sprite->setAlpha(alpha); sprite->setTransformationMatrix(SpriteTransformationMatrix(scale, 0.0f, 0.0f, scale)); sprite->setPosition(x, y); - + sprite->setDisplayId(displayId); this->x = x; this->y = y; diff --git a/libs/input/PointerController.h b/libs/input/PointerController.h index be057867890d..52305b8244a6 100644 --- a/libs/input/PointerController.h +++ b/libs/input/PointerController.h @@ -103,7 +103,7 @@ public: virtual void setPresentation(Presentation presentation); virtual void setSpots(const PointerCoords* spotCoords, - const uint32_t* spotIdToIndex, BitSet32 spotIdBits); + const uint32_t* spotIdToIndex, BitSet32 spotIdBits, int32_t displayId); virtual void clearSpots(); void updatePointerIcon(int32_t iconId); @@ -133,7 +133,7 @@ private: : id(id), sprite(sprite), alpha(1.0f), scale(1.0f), x(0.0f), y(0.0f), lastIcon(NULL) { } - void updateSprite(const SpriteIcon* icon, float x, float y); + void updateSprite(const SpriteIcon* icon, float x, float y, int32_t displayId); private: const SpriteIcon* lastIcon; @@ -180,8 +180,8 @@ private: int32_t buttonState; - Vector<Spot*> spots; - Vector<sp<Sprite> > recycledSprites; + std::map<int32_t /* displayId */, std::vector<Spot*>> spotsByDisplay; + std::vector<sp<Sprite> > recycledSprites; } mLocked GUARDED_BY(mLock); bool getBoundsLocked(float* outMinX, float* outMinY, float* outMaxX, float* outMaxY) const; @@ -200,9 +200,9 @@ private: void removeInactivityTimeoutLocked(); void updatePointerLocked(); - Spot* getSpotLocked(uint32_t id); - Spot* createAndAddSpotLocked(uint32_t id); - Spot* removeFirstFadingSpotLocked(); + Spot* getSpot(uint32_t id, const std::vector<Spot*>& spots); + Spot* createAndAddSpotLocked(uint32_t id, std::vector<Spot*>& spots); + Spot* removeFirstFadingSpotLocked(std::vector<Spot*>& spots); void releaseSpotLocked(Spot* spot); void fadeOutAndReleaseSpotLocked(Spot* spot); void fadeOutAndReleaseAllSpotsLocked(); |