• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include <hitrace_meter.h>
16 #include <algorithm>
17 
18 #include "ani.h"
19 #include "display_ani_listener.h"
20 #include "display_ani.h"
21 #include "display_ani_manager.h"
22 #include "display_info.h"
23 #include "display.h"
24 #include "singleton_container.h"
25 #include "display_manager.h"
26 #include "window_manager_hilog.h"
27 #include "dm_common.h"
28 #include "display_ani_utils.h"
29 #include "refbase.h"
30 #include "ani_err_utils.h"
31 
32 namespace OHOS {
33 namespace Rosen {
34 
DisplayManagerAni()35 DisplayManagerAni::DisplayManagerAni()
36 {
37 }
38 
initDisplayManagerAni(ani_namespace displayNameSpace,ani_env * env)39 ani_status DisplayManagerAni::initDisplayManagerAni(ani_namespace displayNameSpace, ani_env* env)
40 {
41     TLOGI(WmsLogTag::DMS, "[ANI]");
42     ani_function setObjFunc = nullptr;
43     ani_status ret = env->Namespace_FindFunction(displayNameSpace, "setDisplayMgrRef", "J:V", &setObjFunc);
44     if (ret != ANI_OK) {
45         TLOGE(WmsLogTag::DMS, "[ANI] find setNativeObj func fail %{public}u", ret);
46         return ret;
47     }
48     std::unique_ptr<DisplayManagerAni> aniDisplayManager = std::make_unique<DisplayManagerAni>();
49     ret = env->Function_Call_Void(setObjFunc, aniDisplayManager.release());
50     if (ret != ANI_OK) {
51         TLOGE(WmsLogTag::DMS, "[ANI] find setNativeObj func fail %{public}u", ret);
52         return ret;
53     }
54     return ret;
55 }
56 
getFoldDisplayModeAni(ani_env * env)57 ani_int DisplayManagerAni::getFoldDisplayModeAni(ani_env* env)
58 {
59     auto mode = SingletonContainer::Get<DisplayManager>().GetFoldDisplayMode();
60     TLOGI(WmsLogTag::DMS, "[ANI]" PRIu64", getFoldDisplayMode = %{public}u", mode);
61     return static_cast<ani_int>(mode);
62 }
63 
isFoldableAni(ani_env * env)64 ani_boolean DisplayManagerAni::isFoldableAni(ani_env* env)
65 {
66     bool foldable = SingletonContainer::Get<DisplayManager>().IsFoldable();
67     TLOGI(WmsLogTag::DMS, "[ANI]" PRIu64", isFoldable = %{public}u", foldable);
68     return static_cast<ani_boolean>(foldable);
69 }
70 
getFoldStatus(ani_env * env)71 ani_int DisplayManagerAni::getFoldStatus(ani_env* env)
72 {
73     auto status = SingletonContainer::Get<DisplayManager>().GetFoldStatus();
74     TLOGI(WmsLogTag::DMS, "[ANI]" PRIu64", getFoldStatus = %{public}u", status);
75     return static_cast<ani_int>(status);
76 }
77 
getCurrentFoldCreaseRegion(ani_env * env,ani_object obj,ani_long nativeObj)78 void DisplayManagerAni::getCurrentFoldCreaseRegion(ani_env* env, ani_object obj, ani_long nativeObj)
79 {
80     DisplayManagerAni* displayManagerAni = reinterpret_cast<DisplayManagerAni*>(nativeObj);
81     if (displayManagerAni != nullptr) {
82         displayManagerAni->onGetCurrentFoldCreaseRegion(env, obj);
83     } else {
84         TLOGI(WmsLogTag::DMS, "[ANI] null ptr");
85     }
86 }
87 
onGetCurrentFoldCreaseRegion(ani_env * env,ani_object obj)88 void DisplayManagerAni::onGetCurrentFoldCreaseRegion(ani_env* env, ani_object obj)
89 {
90     TLOGI(WmsLogTag::DMS, "[ANI] getCurrentFoldCreaseRegion begin instance");
91     sptr<FoldCreaseRegion> region = SingletonContainer::Get<DisplayManager>().GetCurrentFoldCreaseRegion();
92     if (region == nullptr) {
93         return;
94     }
95     TLOGI(WmsLogTag::DMS, "[ANI] SingletonContainer getCurrentFoldCreaseRegion");
96     uint64_t displayId = region->GetDisplayId();
97     std::vector<DMRect> rects = region->GetCreaseRects();
98     if (rects.size() == 0) {
99         return;
100     }
101     TLOGI(WmsLogTag::DMS, "[ANI] DisplayManager getCurrentFoldCreaseRegion success %{public}d", (int)displayId);
102     if (ANI_OK != env->Object_SetFieldByName_Double(obj, "<property>displayId", (ani_double)displayId)) {
103         TLOGE(WmsLogTag::DMS, "[ANI] set displayId field fail");
104     }
105     ani_ref creaseRectsObj{};
106     if (ANI_OK != env->Object_GetFieldByName_Ref(obj, "<property>creaseRects", &creaseRectsObj)) {
107         TLOGE(WmsLogTag::DMS, "[ANI] get ani_array len fail");
108     }
109     ani_double length;
110     if (ANI_OK != env->Object_GetPropertyByName_Double(static_cast<ani_object>(creaseRectsObj), "length", &length)) {
111         TLOGE(WmsLogTag::DMS, "[ANI] get ani_array len fail");
112     }
113     TLOGI(WmsLogTag::DMS, "[ANI] set CurrentFoldCreaseRegion property begin");
114     for (size_t i = 0; i < std::min(int(length), static_cast<int>(rects.size())); i++) {
115         ani_ref currentCrease;
116         if (ANI_OK != env->Object_CallMethodByName_Ref(static_cast<ani_object>(creaseRectsObj),
117             "$_get", "I:Lstd/core/Object;", &currentCrease, (ani_int)i)) {
118             TLOGE(WmsLogTag::DMS, "[ANI] get ani_array index %{public}u fail", (ani_int)i);
119         }
120         TLOGI(WmsLogTag::DMS, "current i: %{public}u", (ani_int)i);
121         DisplayAniUtils::convertRect(rects[i], static_cast<ani_object>(currentCrease), env);
122     }
123 }
124 
getAllDisplaysAni(ani_env * env,ani_object arrayObj)125 void DisplayManagerAni::getAllDisplaysAni(ani_env* env, ani_object arrayObj)
126 {
127     TLOGI(WmsLogTag::DMS, "[ANI] getAllDisplaysAni start");
128     std::vector<sptr<Display>> displays = SingletonContainer::Get<DisplayManager>().GetAllDisplays();
129     if (displays.empty()) {
130         AniErrUtils::ThrowBusinessError(env, DmErrorCode::DM_ERROR_INVALID_SCREEN, "");
131     }
132     ani_double length;
133     if (ANI_OK != env->Object_GetPropertyByName_Double(arrayObj, "length", &length)) {
134         TLOGE(WmsLogTag::DMS, "[ANI] get ani_array len fail");
135     }
136 
137     for (int i = 0; i < std::min(int(length), static_cast<int>(displays.size())); i++) {
138         ani_ref currentDisplay;
139         if (ANI_OK != env->Object_CallMethodByName_Ref(arrayObj, "$_get", "I:Lstd/core/Object;",
140             &currentDisplay, (ani_int)i)) {
141             TLOGE(WmsLogTag::DMS, "[ANI] get ani_array index %{public}u fail", (ani_int)i);
142         }
143         TLOGI(WmsLogTag::DMS, "current i: %{public}d", i);
144         DisplayAniUtils::cvtDisplay(displays[i], env, static_cast<ani_object>(currentDisplay));
145     }
146     TLOGI(WmsLogTag::DMS, "[ANI] getAllDisplaysAni end");
147 }
148 
getDisplayByIdSyncAni(ani_env * env,ani_object obj,ani_double displayId)149 void DisplayManagerAni::getDisplayByIdSyncAni(ani_env* env, ani_object obj, ani_double displayId)
150 {
151     TLOGE(WmsLogTag::DMS, "[ANI] getDisplayByIdSyncAni begin");
152     if (displayId < 0) {
153         TLOGE(WmsLogTag::DMS, "[ANI] Invalid displayId, less than 0");
154         return;
155     }
156     sptr<Display> display = SingletonContainer::Get<DisplayManager>().GetDisplayById(static_cast<DisplayId>(displayId));
157     if (display == nullptr) {
158         TLOGE(WmsLogTag::DMS, "[ANI] Display null");
159         AniErrUtils::ThrowBusinessError(env, DmErrorCode::DM_ERROR_SYSTEM_INNORMAL, "");
160         return;
161     }
162     DisplayAniUtils::cvtDisplay(display, env, obj);
163 }
164 
getDefaultDisplaySyncAni(ani_env * env,ani_object obj)165 void DisplayManagerAni::getDefaultDisplaySyncAni(ani_env* env, ani_object obj)
166 {
167     sptr<Display> display = SingletonContainer::Get<DisplayManager>().GetDefaultDisplaySync(true);
168     if (display == nullptr) {
169         TLOGE(WmsLogTag::DMS, "[ANI] Display null");
170         return;
171     }
172     TLOGI(WmsLogTag::DMS, "[ANI] getDefaultDisplaySyncAni");
173     DisplayAniUtils::cvtDisplay(display, env, obj);
174     return;
175 }
176 
registerCallback(ani_env * env,ani_string type,ani_ref callback,ani_long nativeObj)177 void DisplayManagerAni::registerCallback(ani_env* env, ani_string type,
178     ani_ref callback, ani_long nativeObj)
179 {
180     DisplayManagerAni* displayManagerAni = reinterpret_cast<DisplayManagerAni*>(nativeObj);
181     if (displayManagerAni != nullptr) {
182         displayManagerAni->onRegisterCallback(env, type, callback);
183     } else {
184         TLOGI(WmsLogTag::DMS, "[ANI] null ptr");
185     }
186 }
187 
onRegisterCallback(ani_env * env,ani_string type,ani_ref callback)188 void DisplayManagerAni::onRegisterCallback(ani_env* env, ani_string type, ani_ref callback)
189 {
190     std::string typeString;
191     DisplayAniUtils::GetStdString(env, type, typeString);
192     ani_ref cbRef{};
193     if (env->GlobalReference_Create(callback, &cbRef) != ANI_OK) {
194         TLOGE(WmsLogTag::DMS, "[ANI] create global ref fail");
195         return;
196     }
197     if (IsCallbackRegistered(env, typeString, cbRef)) {
198         TLOGI(WmsLogTag::DMS, "[ANI] type %{public}s callback already registered!", typeString.c_str());
199         return;
200     }
201     TLOGI(WmsLogTag::DMS, "[ANI] onRegisterCallback");
202     std::lock_guard<std::mutex> lock(mtx_);
203     ani_boolean callbackUndefined = 0;
204     env->Reference_IsUndefined(cbRef, &callbackUndefined);
205     DmErrorCode ret;
206     if (callbackUndefined) {
207         std::string errMsg = "[ANI] failed to register display listener with type, cbk null or undefined";
208         TLOGE(WmsLogTag::DMS, "callbackNull or undefined");
209         AniErrUtils::ThrowBusinessError(env, DmErrorCode::DM_ERROR_INVALID_PARAM, errMsg);
210         return;
211     }
212     sptr<DisplayAniListener> displayAniListener = new(std::nothrow) DisplayAniListener(env);
213     if (displayAniListener == nullptr) {
214         TLOGE(WmsLogTag::DMS, "[ANI]displayListener is nullptr");
215         AniErrUtils::ThrowBusinessError(env, DMError::DM_ERROR_INVALID_PARAM, "displayListener is nullptr");
216         return;
217     }
218     displayAniListener->AddCallback(typeString, cbRef);
219     displayAniListener->SetMainEventHandler();
220 
221     ret = processRegisterCallback(env, typeString, displayAniListener);
222     if (ret != DmErrorCode::DM_OK) {
223         TLOGE(WmsLogTag::DMS, "[ANI] register display listener with type, errcode: %{public}d", ret);
224         std::string errMsg = "Failed to register display listener with type";
225         AniErrUtils::ThrowBusinessError(env, DmErrorCode::DM_ERROR_INVALID_PARAM, errMsg);
226         return;
227     }
228     // add listener to map
229     jsCbMap_[typeString][cbRef] = displayAniListener;
230 }
231 
IsCallbackRegistered(ani_env * env,const std::string & type,ani_ref callback)232 bool DisplayManagerAni::IsCallbackRegistered(ani_env* env, const std::string& type, ani_ref callback)
233 {
234     std::lock_guard<std::mutex> lock(mtx_);
235     if (jsCbMap_.empty() || jsCbMap_.find(type) == jsCbMap_.end()) {
236         TLOGI(WmsLogTag::DMS, "method %{public}s not registered!", type.c_str());
237         return false;
238     }
239 
240     for (const auto& iter : jsCbMap_[type]) {
241         ani_boolean isEquals = false;
242         env->Reference_StrictEquals(callback, iter.first, &isEquals);
243         if (isEquals) {
244             TLOGE(WmsLogTag::DMS, "callback already registered!");
245             return true;
246         }
247     }
248     return false;
249 }
250 
processRegisterCallback(ani_env * env,std::string & typeStr,sptr<DisplayAniListener> displayAniListener)251 DmErrorCode DisplayManagerAni::processRegisterCallback(ani_env* env, std::string& typeStr,
252     sptr<DisplayAniListener> displayAniListener)
253 {
254     DmErrorCode ret = DmErrorCode::DM_ERROR_INVALID_PARAM;
255     if (typeStr == EVENT_ADD || typeStr == EVENT_REMOVE || typeStr == EVENT_CHANGE) {
256         TLOGI(WmsLogTag::DMS, "processRegisterCallback %{public}s", typeStr.c_str());
257         ret = DM_JS_TO_ERROR_CODE_MAP.at(
258             SingletonContainer::Get<DisplayManager>().RegisterDisplayListener(displayAniListener));
259     } else if (typeStr == EVENT_FOLD_STATUS_CHANGED) {
260         ret = DM_JS_TO_ERROR_CODE_MAP.at(
261             SingletonContainer::Get<DisplayManager>().RegisterFoldStatusListener(displayAniListener));
262     } else if (typeStr == EVENT_DISPLAY_MODE_CHANGED) {
263         ret = DM_JS_TO_ERROR_CODE_MAP.at(
264             SingletonContainer::Get<DisplayManager>().RegisterDisplayModeListener(displayAniListener));
265     }
266     return ret;
267 }
268 
unRegisterCallback(ani_env * env,ani_string type,ani_long nativeObj,ani_ref callback)269 void DisplayManagerAni::unRegisterCallback(ani_env* env, ani_string type,
270     ani_long nativeObj, ani_ref callback)
271 {
272     TLOGI(WmsLogTag::DMS, "[ANI] unRegisterCallback begin");
273     DisplayManagerAni* displayManagerAni = reinterpret_cast<DisplayManagerAni*>(nativeObj);
274     if (displayManagerAni != nullptr) {
275         displayManagerAni->onUnRegisterCallback(env, type, callback);
276     } else {
277         TLOGI(WmsLogTag::DMS, "[ANI] null ptr");
278     }
279 }
280 
onUnRegisterCallback(ani_env * env,ani_string type,ani_ref callback)281 void DisplayManagerAni::onUnRegisterCallback(ani_env* env, ani_string type, ani_ref callback)
282 {
283     TLOGI(WmsLogTag::DMS, "[ANI] onUnRegisterCallback begin");
284     ani_ref cbRef{};
285     if (env->GlobalReference_Create(callback, &cbRef) != ANI_OK) {
286         TLOGE(WmsLogTag::DMS, "[ANI] create global ref fail");
287         return;
288     }
289     std::string typeString;
290     DisplayAniUtils::GetStdString(env, type, typeString);
291     std::lock_guard<std::mutex> lock(mtx_);
292     ani_boolean callbackNull = 0;
293     env->Reference_IsUndefined(cbRef, &callbackNull);
294     DmErrorCode ret;
295     if (callbackNull) {
296         TLOGI(WmsLogTag::DMS, "[ANI] onUnRegisterCallback for all");
297         ret = DM_JS_TO_ERROR_CODE_MAP.at(UnregisterAllDisplayListenerWithType(typeString));
298     } else {
299         TLOGI(WmsLogTag::DMS, "[ANI] onUnRegisterCallback with type");
300         ret = DM_JS_TO_ERROR_CODE_MAP.at(UnRegisterDisplayListenerWithType(typeString, env, cbRef));
301     }
302 
303     if (ret != DmErrorCode::DM_OK) {
304         DmErrorCode errCode = DmErrorCode::DM_ERROR_INVALID_PARAM;
305         if (ret == DmErrorCode::DM_ERROR_NOT_SYSTEM_APP) {
306             errCode = ret;
307         }
308         std::string errMsg = "[ANI] failed to unregister display listener with type";
309         TLOGE(WmsLogTag::DMS, "[ANI] failed to unregister display listener with type");
310         AniErrUtils::ThrowBusinessError(env, DMError::DM_ERROR_INVALID_PARAM, errMsg);
311     }
312 }
313 
UnRegisterDisplayListenerWithType(std::string type,ani_env * env,ani_ref callback)314 DMError DisplayManagerAni::UnRegisterDisplayListenerWithType(std::string type, ani_env* env, ani_ref callback)
315 {
316     if (jsCbMap_.empty() || jsCbMap_.find(type) == jsCbMap_.end()) {
317         TLOGI(WmsLogTag::DMS, "[ANI] methodName %{public}s not registered!", type.c_str());
318         return DMError::DM_OK;
319     }
320     DMError ret = DMError::DM_OK;
321     for (auto it = jsCbMap_[type].begin(); it != jsCbMap_[type].end(); it++) {
322         bool isEquals = it->second->IsAniCallBackExist(env, type, callback);
323         TLOGI(WmsLogTag::DMS, "[ANI] isEquals %{public}u", isEquals);
324         if (isEquals) {
325             TLOGI(WmsLogTag::DMS, "[ANI] isEquals check begin");
326             it->second->RemoveCallback(env, type, callback);
327             if (type == EVENT_ADD || type == EVENT_REMOVE || type == EVENT_CHANGE) {
328                 TLOGI(WmsLogTag::DMS, "[ANI] start to unregis display event listener! event = %{public}s",
329                     type.c_str());
330                 sptr<DisplayManager::IDisplayListener> thisListener(it->second);
331                 ret = SingletonContainer::Get<DisplayManager>().UnregisterDisplayListener(thisListener);
332             } else if (type == EVENT_FOLD_STATUS_CHANGED) {
333                 TLOGI(WmsLogTag::DMS, "[ANI] start to unregis FoldStatusListener event listener! event = %{public}s",
334                     type.c_str());
335                 sptr<DisplayManager::IFoldStatusListener> thisListener(it->second);
336                 ret = SingletonContainer::Get<DisplayManager>().UnregisterFoldStatusListener(thisListener);
337                 TLOGI(WmsLogTag::DMS, "[ANI] UnRegisterDisplayListener foldStatusChange success");
338             } else if (type == EVENT_DISPLAY_MODE_CHANGED) {
339                 TLOGI(WmsLogTag::DMS, "[ANI] start to unregis foldDisplayModeChange event listener! event = %{public}s",
340                     type.c_str());
341                 sptr<DisplayManager::IDisplayModeListener> thisListener(it->second);
342                 ret = SingletonContainer::Get<DisplayManager>().UnregisterDisplayModeListener(thisListener);
343                 TLOGI(WmsLogTag::DMS, "[ANI] UnRegisterDisplayListener foldDisplayModeChange success");
344             }
345             jsCbMap_[type].erase(it);
346             break;
347         }
348     }
349     return ret;
350 }
351 
UnregisterAllDisplayListenerWithType(std::string type)352 DMError DisplayManagerAni::UnregisterAllDisplayListenerWithType(std::string type)
353 {
354     TLOGI(WmsLogTag::DMS, "[ANI] UnregisterAllDisplayListenerWithType begin");
355     if (jsCbMap_.empty() || jsCbMap_.find(type) == jsCbMap_.end()) {
356         TLOGI(WmsLogTag::DMS, "[ANI] UnregisterAllDisplayListenerWithType methodName %{public}s not registered!",
357             type.c_str());
358         return DMError::DM_OK;
359     }
360     DMError ret = DMError::DM_OK;
361     for (auto it = jsCbMap_[type].begin(); it != jsCbMap_[type].end();) {
362         it->second->RemoveAllCallback();
363         if (type == EVENT_ADD || type == EVENT_REMOVE || type == EVENT_CHANGE) {
364             sptr<DisplayManager::IDisplayListener> thisListener(it->second);
365             ret = SingletonContainer::Get<DisplayManager>().UnregisterDisplayListener(thisListener);
366         } else if (type == EVENT_FOLD_STATUS_CHANGED) {
367             sptr<DisplayManager::IFoldStatusListener> thisListener(it->second);
368             ret = SingletonContainer::Get<DisplayManager>().UnregisterFoldStatusListener(thisListener);
369         } else if (type == EVENT_DISPLAY_MODE_CHANGED) {
370             sptr<DisplayManager::IDisplayModeListener> thisListener(it->second);
371             ret = SingletonContainer::Get<DisplayManager>().UnregisterDisplayModeListener(thisListener);
372         }
373         jsCbMap_[type].erase(it++);
374         TLOGI(WmsLogTag::DMS, "[ANI] UnregisterAllDisplayListenerWithType end");
375     }
376     jsCbMap_.erase(type);
377     return ret;
378 }
379 }
380 }