!41809 【mediaQuery】解决on回调中重入on或off引起appfreeze的问题

Merge pull request !41809 from 冯纪拓/media_pls
This commit is contained in:
openharmony_ci 2024-09-01 10:54:51 +00:00 committed by Gitee
commit e8d8451d04
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F

View File

@ -13,10 +13,20 @@
* limitations under the License.
*/
#include <algorithm>
#include <map>
#include <mutex>
#include <set>
#include <vector>
#include "napi/native_api.h"
#include "napi/native_common.h"
#include "napi/native_node_api.h"
#include "bridge/common/media_query/media_queryer.h"
#include "bridge/common/utils/engine_helper.h"
#include "bridge/js_frontend/engine/common/js_engine.h"
#include "core/common/container.h"
namespace OHOS::Ace::Napi {
namespace {
@ -76,20 +86,52 @@ public:
static void OnNapiCallback(JsEngine* jsEngine)
{
MediaQueryer queryer;
std::set<std::unique_ptr<MediaQueryListener>> delayDeleteListenerSets;
std::lock_guard<std::mutex> lock(mutex_);
std::set<napi_ref> delayDeleteCallbacks;
std::vector<MediaQueryListener*> copyListeners;
{
std::lock_guard<std::mutex> lock(mutex_);
auto& currentListeners = listenerSets_[AceType::WeakClaim(jsEngine)];
copyListeners.insert(copyListeners.end(), currentListeners.begin(), currentListeners.end());
}
struct Leave {
~Leave()
{
if (delayDeleteEnv_) {
for (auto& cbRef : *delayDeleteCallbacks_) {
napi_delete_reference(delayDeleteEnv_, cbRef);
}
}
delayDeleteEnv_ = nullptr;
delayDeleteCallbacks_ = nullptr;
delayDeleteListenerSets_ = nullptr;
}
} leave;
delayDeleteCallbacks_ = &delayDeleteCallbacks;
delayDeleteListenerSets_ = &delayDeleteListenerSets;
for (auto listener : listenerSets_[AceType::WeakClaim(jsEngine)]) {
TriggerAllCallbacks(copyListeners);
}
static void TriggerAllCallbacks(std::vector<MediaQueryListener*>& copyListeners)
{
MediaQueryer queryer;
for (auto& listener : copyListeners) {
auto json = MediaQueryInfo::GetMediaQueryJsonInfo();
listener->matches_ = queryer.MatchCondition(listener->media_, json);
for (auto& cbRef : listener->cbList_) {
std::set<napi_ref> delayDeleteCallbacks;
std::vector<napi_ref> copyCallbacks;
{
std::lock_guard<std::mutex> lock(mutex_);
auto& currentCallbacks = listener->cbList_;
copyCallbacks.insert(copyCallbacks.end(), currentCallbacks.begin(), currentCallbacks.end());
}
for (const auto& cbRef : copyCallbacks) {
if (delayDeleteCallbacks_->find(cbRef) != delayDeleteCallbacks_->end()) {
continue;
}
napi_handle_scope scope = nullptr;
napi_open_handle_scope(listener->env_, &scope);
if (scope == nullptr) {
@ -159,17 +201,29 @@ public:
return nullptr;
}
if (argc == 1) {
for (auto& item : listener->cbList_) {
napi_delete_reference(listener->env_, item);
if (delayDeleteCallbacks_) {
delayDeleteEnv_ = env;
for (auto& item : listener->cbList_) {
(*delayDeleteCallbacks_).emplace(item);
}
} else {
for (auto& item : listener->cbList_) {
napi_delete_reference(listener->env_, item);
}
}
listener->cbList_.clear();
} else {
NAPI_ASSERT(env, (argc == 2 && listener != nullptr && cb != nullptr), "Invalid arguments");
auto iter = listener->FindCbList(cb);
if (iter != listener->cbList_.end()) {
napi_delete_reference(listener->env_, *iter);
listener->cbList_.erase(iter);
if (delayDeleteCallbacks_) {
delayDeleteEnv_ = env;
(*delayDeleteCallbacks_).emplace(*iter);
} else {
napi_delete_reference(listener->env_, *iter);
}
}
listener->cbList_.erase(iter);
}
return nullptr;
}
@ -290,10 +344,14 @@ private:
napi_env env_ = nullptr;
std::list<napi_ref> cbList_;
static std::set<std::unique_ptr<MediaQueryListener>>* delayDeleteListenerSets_;
static napi_env delayDeleteEnv_;
static std::set<napi_ref>* delayDeleteCallbacks_;
static std::map<WeakPtr<JsEngine>, std::set<MediaQueryListener*>> listenerSets_;
static std::mutex mutex_;
};
std::set<std::unique_ptr<MediaQueryListener>>* MediaQueryListener::delayDeleteListenerSets_;
napi_env MediaQueryListener::delayDeleteEnv_ = nullptr;
std::set<napi_ref>* MediaQueryListener::delayDeleteCallbacks_;
std::map<WeakPtr<JsEngine>, std::set<MediaQueryListener*>> MediaQueryListener::listenerSets_;
std::mutex MediaQueryListener::mutex_;