| John Reck | 283bb46 | 2018-12-13 16:40:14 -0800 | [diff] [blame] | 1 | /* | 
|  | 2 | * Copyright (C) 2018 The Android Open Source Project | 
|  | 3 | * | 
|  | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | 5 | * you may not use this file except in compliance with the License. | 
|  | 6 | * You may obtain a copy of the License at | 
|  | 7 | * | 
|  | 8 | *      http://www.apache.org/licenses/LICENSE-2.0 | 
|  | 9 | * | 
|  | 10 | * Unless required by applicable law or agreed to in writing, software | 
|  | 11 | * distributed under the License is distributed on an "AS IS" BASIS, | 
|  | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | 13 | * See the License for the specific language governing permissions and | 
|  | 14 | * limitations under the License. | 
|  | 15 | */ | 
|  | 16 |  | 
|  | 17 | #include "WebViewFunctorManager.h" | 
|  | 18 |  | 
|  | 19 | #include <private/hwui/WebViewFunctor.h> | 
|  | 20 | #include "Properties.h" | 
| Huihong Luo | 054b8d3 | 2021-02-24 18:48:12 -0800 | [diff] [blame] | 21 | #include "renderthread/CanvasContext.h" | 
| Bo Liu | 1b0278c | 2019-01-03 16:36:24 -0800 | [diff] [blame] | 22 | #include "renderthread/RenderThread.h" | 
| John Reck | 283bb46 | 2018-12-13 16:40:14 -0800 | [diff] [blame] | 23 |  | 
|  | 24 | #include <log/log.h> | 
|  | 25 | #include <utils/Trace.h> | 
|  | 26 | #include <atomic> | 
|  | 27 |  | 
|  | 28 | namespace android::uirenderer { | 
|  | 29 |  | 
| Vasiliy Telezhnikov | 6b23764 | 2020-11-12 18:14:58 -0500 | [diff] [blame] | 30 | namespace { | 
|  | 31 | class ScopedCurrentFunctor { | 
|  | 32 | public: | 
|  | 33 | ScopedCurrentFunctor(WebViewFunctor* functor) { | 
|  | 34 | ALOG_ASSERT(!sCurrentFunctor); | 
|  | 35 | ALOG_ASSERT(functor); | 
|  | 36 | sCurrentFunctor = functor; | 
|  | 37 | } | 
|  | 38 | ~ScopedCurrentFunctor() { | 
|  | 39 | ALOG_ASSERT(sCurrentFunctor); | 
|  | 40 | sCurrentFunctor = nullptr; | 
|  | 41 | } | 
|  | 42 |  | 
|  | 43 | static ASurfaceControl* getSurfaceControl() { | 
|  | 44 | ALOG_ASSERT(sCurrentFunctor); | 
|  | 45 | return sCurrentFunctor->getSurfaceControl(); | 
|  | 46 | } | 
|  | 47 | static void mergeTransaction(ASurfaceTransaction* transaction) { | 
|  | 48 | ALOG_ASSERT(sCurrentFunctor); | 
|  | 49 | sCurrentFunctor->mergeTransaction(transaction); | 
|  | 50 | } | 
|  | 51 |  | 
|  | 52 | private: | 
|  | 53 | static WebViewFunctor* sCurrentFunctor; | 
|  | 54 | }; | 
|  | 55 |  | 
|  | 56 | WebViewFunctor* ScopedCurrentFunctor::sCurrentFunctor = nullptr; | 
|  | 57 | }  // namespace | 
|  | 58 |  | 
| John Reck | 283bb46 | 2018-12-13 16:40:14 -0800 | [diff] [blame] | 59 | RenderMode WebViewFunctor_queryPlatformRenderMode() { | 
|  | 60 | auto pipelineType = Properties::getRenderPipelineType(); | 
|  | 61 | switch (pipelineType) { | 
|  | 62 | case RenderPipelineType::SkiaGL: | 
|  | 63 | return RenderMode::OpenGL_ES; | 
|  | 64 | case RenderPipelineType::SkiaVulkan: | 
|  | 65 | return RenderMode::Vulkan; | 
|  | 66 | default: | 
|  | 67 | LOG_ALWAYS_FATAL("Unknown render pipeline type: %d", (int)pipelineType); | 
|  | 68 | } | 
|  | 69 | } | 
|  | 70 |  | 
| Bo Liu | d6668e7 | 2018-12-14 19:37:41 -0800 | [diff] [blame] | 71 | int WebViewFunctor_create(void* data, const WebViewFunctorCallbacks& prototype, | 
|  | 72 | RenderMode functorMode) { | 
| John Reck | 283bb46 | 2018-12-13 16:40:14 -0800 | [diff] [blame] | 73 | if (functorMode != RenderMode::OpenGL_ES && functorMode != RenderMode::Vulkan) { | 
|  | 74 | ALOGW("Unknown rendermode %d", (int)functorMode); | 
|  | 75 | return -1; | 
|  | 76 | } | 
|  | 77 | if (functorMode == RenderMode::Vulkan && | 
|  | 78 | WebViewFunctor_queryPlatformRenderMode() != RenderMode::Vulkan) { | 
|  | 79 | ALOGW("Unable to map from GLES platform to a vulkan functor"); | 
|  | 80 | return -1; | 
|  | 81 | } | 
| Bo Liu | d6668e7 | 2018-12-14 19:37:41 -0800 | [diff] [blame] | 82 | return WebViewFunctorManager::instance().createFunctor(data, prototype, functorMode); | 
| John Reck | 283bb46 | 2018-12-13 16:40:14 -0800 | [diff] [blame] | 83 | } | 
|  | 84 |  | 
|  | 85 | void WebViewFunctor_release(int functor) { | 
|  | 86 | WebViewFunctorManager::instance().releaseFunctor(functor); | 
|  | 87 | } | 
|  | 88 |  | 
|  | 89 | static std::atomic_int sNextId{1}; | 
|  | 90 |  | 
| Bo Liu | d6668e7 | 2018-12-14 19:37:41 -0800 | [diff] [blame] | 91 | WebViewFunctor::WebViewFunctor(void* data, const WebViewFunctorCallbacks& callbacks, | 
|  | 92 | RenderMode functorMode) | 
|  | 93 | : mData(data) { | 
| John Reck | 283bb46 | 2018-12-13 16:40:14 -0800 | [diff] [blame] | 94 | mFunctor = sNextId++; | 
|  | 95 | mCallbacks = callbacks; | 
|  | 96 | mMode = functorMode; | 
|  | 97 | } | 
|  | 98 |  | 
|  | 99 | WebViewFunctor::~WebViewFunctor() { | 
|  | 100 | destroyContext(); | 
|  | 101 |  | 
|  | 102 | ATRACE_NAME("WebViewFunctor::onDestroy"); | 
| Huihong Luo | 9c5158f7 | 2021-07-23 12:35:59 -0700 | [diff] [blame] | 103 | if (mSurfaceControl) { | 
|  | 104 | removeOverlays(); | 
|  | 105 | } | 
| Bo Liu | d6668e7 | 2018-12-14 19:37:41 -0800 | [diff] [blame] | 106 | mCallbacks.onDestroyed(mFunctor, mData); | 
| John Reck | 283bb46 | 2018-12-13 16:40:14 -0800 | [diff] [blame] | 107 | } | 
|  | 108 |  | 
|  | 109 | void WebViewFunctor::sync(const WebViewSyncData& syncData) const { | 
|  | 110 | ATRACE_NAME("WebViewFunctor::sync"); | 
| Bo Liu | d6668e7 | 2018-12-14 19:37:41 -0800 | [diff] [blame] | 111 | mCallbacks.onSync(mFunctor, mData, syncData); | 
| John Reck | 283bb46 | 2018-12-13 16:40:14 -0800 | [diff] [blame] | 112 | } | 
|  | 113 |  | 
| Huihong Luo | ec68b7c | 2021-06-25 21:54:16 -0700 | [diff] [blame] | 114 | void WebViewFunctor::onRemovedFromTree() { | 
|  | 115 | ATRACE_NAME("WebViewFunctor::onRemovedFromTree"); | 
|  | 116 | if (mSurfaceControl) { | 
|  | 117 | removeOverlays(); | 
|  | 118 | } | 
|  | 119 | } | 
|  | 120 |  | 
| Vasiliy Telezhnikov | 372a21b | 2021-11-17 13:50:56 -0500 | [diff] [blame] | 121 | bool WebViewFunctor::prepareRootSurfaceControl() { | 
|  | 122 | if (!Properties::enableWebViewOverlays) return false; | 
|  | 123 |  | 
|  | 124 | renderthread::CanvasContext* activeContext = renderthread::CanvasContext::getActiveContext(); | 
|  | 125 | if (!activeContext) return false; | 
|  | 126 |  | 
|  | 127 | ASurfaceControl* rootSurfaceControl = activeContext->getSurfaceControl(); | 
|  | 128 | if (!rootSurfaceControl) return false; | 
|  | 129 |  | 
|  | 130 | int32_t rgid = activeContext->getSurfaceControlGenerationId(); | 
|  | 131 | if (mParentSurfaceControlGenerationId != rgid) { | 
|  | 132 | reparentSurfaceControl(rootSurfaceControl); | 
|  | 133 | mParentSurfaceControlGenerationId = rgid; | 
|  | 134 | } | 
|  | 135 |  | 
|  | 136 | return true; | 
|  | 137 | } | 
|  | 138 |  | 
| John Reck | 283bb46 | 2018-12-13 16:40:14 -0800 | [diff] [blame] | 139 | void WebViewFunctor::drawGl(const DrawGlInfo& drawInfo) { | 
|  | 140 | ATRACE_NAME("WebViewFunctor::drawGl"); | 
|  | 141 | if (!mHasContext) { | 
|  | 142 | mHasContext = true; | 
|  | 143 | } | 
| Vasiliy Telezhnikov | 6b23764 | 2020-11-12 18:14:58 -0500 | [diff] [blame] | 144 | ScopedCurrentFunctor currentFunctor(this); | 
|  | 145 |  | 
|  | 146 | WebViewOverlayData overlayParams = { | 
| Vasiliy Telezhnikov | 6b23764 | 2020-11-12 18:14:58 -0500 | [diff] [blame] | 147 | .overlaysMode = OverlaysMode::Disabled, | 
|  | 148 | .getSurfaceControl = currentFunctor.getSurfaceControl, | 
|  | 149 | .mergeTransaction = currentFunctor.mergeTransaction, | 
|  | 150 | }; | 
| Huihong Luo | 054b8d3 | 2021-02-24 18:48:12 -0800 | [diff] [blame] | 151 |  | 
| Vasiliy Telezhnikov | 372a21b | 2021-11-17 13:50:56 -0500 | [diff] [blame] | 152 | if (!drawInfo.isLayer && prepareRootSurfaceControl()) { | 
|  | 153 | overlayParams.overlaysMode = OverlaysMode::Enabled; | 
| Huihong Luo | 054b8d3 | 2021-02-24 18:48:12 -0800 | [diff] [blame] | 154 | } | 
|  | 155 |  | 
| Vasiliy Telezhnikov | 6b23764 | 2020-11-12 18:14:58 -0500 | [diff] [blame] | 156 | mCallbacks.gles.draw(mFunctor, mData, drawInfo, overlayParams); | 
| John Reck | 283bb46 | 2018-12-13 16:40:14 -0800 | [diff] [blame] | 157 | } | 
|  | 158 |  | 
| Bo Liu | 7b8c1eb | 2019-01-08 20:17:55 -0800 | [diff] [blame] | 159 | void WebViewFunctor::initVk(const VkFunctorInitParams& params) { | 
|  | 160 | ATRACE_NAME("WebViewFunctor::initVk"); | 
|  | 161 | if (!mHasContext) { | 
|  | 162 | mHasContext = true; | 
|  | 163 | } else { | 
|  | 164 | return; | 
|  | 165 | } | 
|  | 166 | mCallbacks.vk.initialize(mFunctor, mData, params); | 
|  | 167 | } | 
|  | 168 |  | 
|  | 169 | void WebViewFunctor::drawVk(const VkFunctorDrawParams& params) { | 
|  | 170 | ATRACE_NAME("WebViewFunctor::drawVk"); | 
| Vasiliy Telezhnikov | 6b23764 | 2020-11-12 18:14:58 -0500 | [diff] [blame] | 171 | ScopedCurrentFunctor currentFunctor(this); | 
|  | 172 |  | 
|  | 173 | WebViewOverlayData overlayParams = { | 
| Vasiliy Telezhnikov | 6b23764 | 2020-11-12 18:14:58 -0500 | [diff] [blame] | 174 | .overlaysMode = OverlaysMode::Disabled, | 
|  | 175 | .getSurfaceControl = currentFunctor.getSurfaceControl, | 
|  | 176 | .mergeTransaction = currentFunctor.mergeTransaction, | 
|  | 177 | }; | 
| Huihong Luo | 054b8d3 | 2021-02-24 18:48:12 -0800 | [diff] [blame] | 178 |  | 
| Vasiliy Telezhnikov | 372a21b | 2021-11-17 13:50:56 -0500 | [diff] [blame] | 179 | if (!params.is_layer && prepareRootSurfaceControl()) { | 
|  | 180 | overlayParams.overlaysMode = OverlaysMode::Enabled; | 
|  | 181 | } | 
|  | 182 |  | 
| Vasiliy Telezhnikov | 6b23764 | 2020-11-12 18:14:58 -0500 | [diff] [blame] | 183 | mCallbacks.vk.draw(mFunctor, mData, params, overlayParams); | 
| Bo Liu | 7b8c1eb | 2019-01-08 20:17:55 -0800 | [diff] [blame] | 184 | } | 
|  | 185 |  | 
|  | 186 | void WebViewFunctor::postDrawVk() { | 
|  | 187 | ATRACE_NAME("WebViewFunctor::postDrawVk"); | 
|  | 188 | mCallbacks.vk.postDraw(mFunctor, mData); | 
|  | 189 | } | 
|  | 190 |  | 
| John Reck | 283bb46 | 2018-12-13 16:40:14 -0800 | [diff] [blame] | 191 | void WebViewFunctor::destroyContext() { | 
|  | 192 | if (mHasContext) { | 
|  | 193 | mHasContext = false; | 
|  | 194 | ATRACE_NAME("WebViewFunctor::onContextDestroyed"); | 
| Bo Liu | d6668e7 | 2018-12-14 19:37:41 -0800 | [diff] [blame] | 195 | mCallbacks.onContextDestroyed(mFunctor, mData); | 
| Bo Liu | 1b0278c | 2019-01-03 16:36:24 -0800 | [diff] [blame] | 196 |  | 
|  | 197 | // grContext may be null in unit tests. | 
|  | 198 | auto* grContext = renderthread::RenderThread::getInstance().getGrContext(); | 
|  | 199 | if (grContext) grContext->resetContext(); | 
| John Reck | 283bb46 | 2018-12-13 16:40:14 -0800 | [diff] [blame] | 200 | } | 
|  | 201 | } | 
|  | 202 |  | 
| Vasiliy Telezhnikov | 6b23764 | 2020-11-12 18:14:58 -0500 | [diff] [blame] | 203 | void WebViewFunctor::removeOverlays() { | 
|  | 204 | ScopedCurrentFunctor currentFunctor(this); | 
|  | 205 | mCallbacks.removeOverlays(mFunctor, mData, currentFunctor.mergeTransaction); | 
| Huihong Luo | 054b8d3 | 2021-02-24 18:48:12 -0800 | [diff] [blame] | 206 | if (mSurfaceControl) { | 
| Huihong Luo | ec68b7c | 2021-06-25 21:54:16 -0700 | [diff] [blame] | 207 | reparentSurfaceControl(nullptr); | 
| Huihong Luo | 054b8d3 | 2021-02-24 18:48:12 -0800 | [diff] [blame] | 208 | auto funcs = renderthread::RenderThread::getInstance().getASurfaceControlFunctions(); | 
|  | 209 | funcs.releaseFunc(mSurfaceControl); | 
|  | 210 | mSurfaceControl = nullptr; | 
|  | 211 | } | 
| Vasiliy Telezhnikov | 6b23764 | 2020-11-12 18:14:58 -0500 | [diff] [blame] | 212 | } | 
|  | 213 |  | 
|  | 214 | ASurfaceControl* WebViewFunctor::getSurfaceControl() { | 
| Huihong Luo | 054b8d3 | 2021-02-24 18:48:12 -0800 | [diff] [blame] | 215 | ATRACE_NAME("WebViewFunctor::getSurfaceControl"); | 
|  | 216 | if (mSurfaceControl != nullptr) return mSurfaceControl; | 
|  | 217 |  | 
|  | 218 | renderthread::CanvasContext* activeContext = renderthread::CanvasContext::getActiveContext(); | 
|  | 219 | LOG_ALWAYS_FATAL_IF(activeContext == nullptr, "Null active canvas context!"); | 
|  | 220 |  | 
|  | 221 | ASurfaceControl* rootSurfaceControl = activeContext->getSurfaceControl(); | 
|  | 222 | LOG_ALWAYS_FATAL_IF(rootSurfaceControl == nullptr, "Null root surface control!"); | 
|  | 223 |  | 
|  | 224 | auto funcs = renderthread::RenderThread::getInstance().getASurfaceControlFunctions(); | 
| Huihong Luo | 540fdf8 | 2021-06-25 13:59:39 -0700 | [diff] [blame] | 225 | mParentSurfaceControlGenerationId = activeContext->getSurfaceControlGenerationId(); | 
| Huihong Luo | 054b8d3 | 2021-02-24 18:48:12 -0800 | [diff] [blame] | 226 | mSurfaceControl = funcs.createFunc(rootSurfaceControl, "Webview Overlay SurfaceControl"); | 
|  | 227 | ASurfaceTransaction* transaction = funcs.transactionCreateFunc(); | 
| Huihong Luo | 34f42fd | 2021-05-03 14:47:36 -0700 | [diff] [blame] | 228 | activeContext->prepareSurfaceControlForWebview(); | 
|  | 229 | funcs.transactionSetZOrderFunc(transaction, mSurfaceControl, -1); | 
| Huihong Luo | 054b8d3 | 2021-02-24 18:48:12 -0800 | [diff] [blame] | 230 | funcs.transactionSetVisibilityFunc(transaction, mSurfaceControl, | 
|  | 231 | ASURFACE_TRANSACTION_VISIBILITY_SHOW); | 
|  | 232 | funcs.transactionApplyFunc(transaction); | 
|  | 233 | funcs.transactionDeleteFunc(transaction); | 
|  | 234 | return mSurfaceControl; | 
| Vasiliy Telezhnikov | 6b23764 | 2020-11-12 18:14:58 -0500 | [diff] [blame] | 235 | } | 
|  | 236 |  | 
|  | 237 | void WebViewFunctor::mergeTransaction(ASurfaceTransaction* transaction) { | 
| Huihong Luo | 054b8d3 | 2021-02-24 18:48:12 -0800 | [diff] [blame] | 238 | ATRACE_NAME("WebViewFunctor::mergeTransaction"); | 
|  | 239 | if (transaction == nullptr) return; | 
| Huihong Luo | ec68b7c | 2021-06-25 21:54:16 -0700 | [diff] [blame] | 240 | bool done = false; | 
| Huihong Luo | 054b8d3 | 2021-02-24 18:48:12 -0800 | [diff] [blame] | 241 | renderthread::CanvasContext* activeContext = renderthread::CanvasContext::getActiveContext(); | 
| Huihong Luo | ec68b7c | 2021-06-25 21:54:16 -0700 | [diff] [blame] | 242 | // activeContext might be null when called from mCallbacks.removeOverlays() | 
|  | 243 | if (activeContext != nullptr) { | 
|  | 244 | done = activeContext->mergeTransaction(transaction, mSurfaceControl); | 
|  | 245 | } | 
| Huihong Luo | 054b8d3 | 2021-02-24 18:48:12 -0800 | [diff] [blame] | 246 | if (!done) { | 
|  | 247 | auto funcs = renderthread::RenderThread::getInstance().getASurfaceControlFunctions(); | 
|  | 248 | funcs.transactionApplyFunc(transaction); | 
|  | 249 | } | 
| Vasiliy Telezhnikov | 6b23764 | 2020-11-12 18:14:58 -0500 | [diff] [blame] | 250 | } | 
|  | 251 |  | 
| Huihong Luo | 540fdf8 | 2021-06-25 13:59:39 -0700 | [diff] [blame] | 252 | void WebViewFunctor::reparentSurfaceControl(ASurfaceControl* parent) { | 
|  | 253 | ATRACE_NAME("WebViewFunctor::reparentSurfaceControl"); | 
|  | 254 | if (mSurfaceControl == nullptr) return; | 
|  | 255 |  | 
|  | 256 | auto funcs = renderthread::RenderThread::getInstance().getASurfaceControlFunctions(); | 
|  | 257 | ASurfaceTransaction* transaction = funcs.transactionCreateFunc(); | 
|  | 258 | funcs.transactionReparentFunc(transaction, mSurfaceControl, parent); | 
|  | 259 | mergeTransaction(transaction); | 
|  | 260 | funcs.transactionDeleteFunc(transaction); | 
|  | 261 | } | 
|  | 262 |  | 
| John Reck | 283bb46 | 2018-12-13 16:40:14 -0800 | [diff] [blame] | 263 | WebViewFunctorManager& WebViewFunctorManager::instance() { | 
|  | 264 | static WebViewFunctorManager sInstance; | 
|  | 265 | return sInstance; | 
|  | 266 | } | 
|  | 267 |  | 
| John Reck | faa1b0a | 2021-05-13 10:28:38 -0400 | [diff] [blame] | 268 | static void validateCallbacks(const WebViewFunctorCallbacks& callbacks) { | 
|  | 269 | // TODO: Should we do a stack peek to see if this is really webview? | 
|  | 270 | LOG_ALWAYS_FATAL_IF(callbacks.onSync == nullptr, "onSync is null"); | 
|  | 271 | LOG_ALWAYS_FATAL_IF(callbacks.onContextDestroyed == nullptr, "onContextDestroyed is null"); | 
|  | 272 | LOG_ALWAYS_FATAL_IF(callbacks.onDestroyed == nullptr, "onDestroyed is null"); | 
|  | 273 | LOG_ALWAYS_FATAL_IF(callbacks.removeOverlays == nullptr, "removeOverlays is null"); | 
|  | 274 | switch (auto mode = WebViewFunctor_queryPlatformRenderMode()) { | 
|  | 275 | case RenderMode::OpenGL_ES: | 
|  | 276 | LOG_ALWAYS_FATAL_IF(callbacks.gles.draw == nullptr, "gles.draw is null"); | 
|  | 277 | break; | 
|  | 278 | case RenderMode::Vulkan: | 
|  | 279 | LOG_ALWAYS_FATAL_IF(callbacks.vk.initialize == nullptr, "vk.initialize is null"); | 
|  | 280 | LOG_ALWAYS_FATAL_IF(callbacks.vk.draw == nullptr, "vk.draw is null"); | 
|  | 281 | LOG_ALWAYS_FATAL_IF(callbacks.vk.postDraw == nullptr, "vk.postDraw is null"); | 
|  | 282 | break; | 
|  | 283 | default: | 
|  | 284 | LOG_ALWAYS_FATAL("unknown platform mode? %d", (int)mode); | 
|  | 285 | break; | 
|  | 286 | } | 
|  | 287 | } | 
|  | 288 |  | 
| Bo Liu | d6668e7 | 2018-12-14 19:37:41 -0800 | [diff] [blame] | 289 | int WebViewFunctorManager::createFunctor(void* data, const WebViewFunctorCallbacks& callbacks, | 
| John Reck | 283bb46 | 2018-12-13 16:40:14 -0800 | [diff] [blame] | 290 | RenderMode functorMode) { | 
| John Reck | faa1b0a | 2021-05-13 10:28:38 -0400 | [diff] [blame] | 291 | validateCallbacks(callbacks); | 
| Bo Liu | d6668e7 | 2018-12-14 19:37:41 -0800 | [diff] [blame] | 292 | auto object = std::make_unique<WebViewFunctor>(data, callbacks, functorMode); | 
| John Reck | 283bb46 | 2018-12-13 16:40:14 -0800 | [diff] [blame] | 293 | int id = object->id(); | 
|  | 294 | auto handle = object->createHandle(); | 
|  | 295 | { | 
|  | 296 | std::lock_guard _lock{mLock}; | 
|  | 297 | mActiveFunctors.push_back(std::move(handle)); | 
|  | 298 | mFunctors.push_back(std::move(object)); | 
|  | 299 | } | 
|  | 300 | return id; | 
|  | 301 | } | 
|  | 302 |  | 
|  | 303 | void WebViewFunctorManager::releaseFunctor(int functor) { | 
|  | 304 | sp<WebViewFunctor::Handle> toRelease; | 
|  | 305 | { | 
|  | 306 | std::lock_guard _lock{mLock}; | 
|  | 307 | for (auto iter = mActiveFunctors.begin(); iter != mActiveFunctors.end(); iter++) { | 
|  | 308 | if ((*iter)->id() == functor) { | 
|  | 309 | toRelease = std::move(*iter); | 
|  | 310 | mActiveFunctors.erase(iter); | 
|  | 311 | break; | 
|  | 312 | } | 
|  | 313 | } | 
|  | 314 | } | 
|  | 315 | } | 
|  | 316 |  | 
|  | 317 | void WebViewFunctorManager::onContextDestroyed() { | 
|  | 318 | // WARNING: SKETCHY | 
|  | 319 | // Because we know that we always remove from mFunctors on RenderThread, the same | 
|  | 320 | // thread that always invokes onContextDestroyed, we know that the functor pointers | 
|  | 321 | // will remain valid without the lock held. | 
|  | 322 | // However, we won't block new functors from being added in the meantime. | 
|  | 323 | mLock.lock(); | 
|  | 324 | const size_t size = mFunctors.size(); | 
|  | 325 | WebViewFunctor* toDestroyContext[size]; | 
|  | 326 | for (size_t i = 0; i < size; i++) { | 
|  | 327 | toDestroyContext[i] = mFunctors[i].get(); | 
|  | 328 | } | 
|  | 329 | mLock.unlock(); | 
|  | 330 | for (size_t i = 0; i < size; i++) { | 
|  | 331 | toDestroyContext[i]->destroyContext(); | 
|  | 332 | } | 
|  | 333 | } | 
|  | 334 |  | 
|  | 335 | void WebViewFunctorManager::destroyFunctor(int functor) { | 
|  | 336 | std::unique_ptr<WebViewFunctor> toRelease; | 
|  | 337 | { | 
|  | 338 | std::lock_guard _lock{mLock}; | 
|  | 339 | for (auto iter = mFunctors.begin(); iter != mFunctors.end(); iter++) { | 
|  | 340 | if ((*iter)->id() == functor) { | 
|  | 341 | toRelease = std::move(*iter); | 
|  | 342 | mFunctors.erase(iter); | 
|  | 343 | break; | 
|  | 344 | } | 
|  | 345 | } | 
|  | 346 | } | 
|  | 347 | } | 
|  | 348 |  | 
|  | 349 | sp<WebViewFunctor::Handle> WebViewFunctorManager::handleFor(int functor) { | 
|  | 350 | std::lock_guard _lock{mLock}; | 
|  | 351 | for (auto& iter : mActiveFunctors) { | 
|  | 352 | if (iter->id() == functor) { | 
|  | 353 | return iter; | 
|  | 354 | } | 
|  | 355 | } | 
|  | 356 | return nullptr; | 
|  | 357 | } | 
|  | 358 |  | 
| Bo Liu | d6668e7 | 2018-12-14 19:37:41 -0800 | [diff] [blame] | 359 | }  // namespace android::uirenderer |