* Copyright (C) 2025 Huawei Device Co., Ltd.
* 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 "window_adapter.h"
#include <chrono>
#include <cinttypes>
#include <ranges>
#include <thread>
#include "global.h"
#include "ipc_skeleton.h"
#include "os_account_adapter.h"
#include "variant_util.h"
#include "window.h"
#include "wm_common.h"
namespace OHOS {
namespace MiscServices {
using namespace OHOS::Rosen;
using WMError = OHOS::Rosen::WMError;
using namespace std::chrono_literals;
WindowAdapter::~WindowAdapter()
{
}
WindowAdapter &WindowAdapter::GetInstance()
{
static WindowAdapter windowAdapter;
return windowAdapter;
}
void WindowAdapter::GetFocusInfo(OHOS::Rosen::FocusChangeInfo &focusInfo, int32_t userId, uint64_t displayId)
{
#ifdef SCENE_BOARD_ENABLE
WindowManagerLite::GetInstance(userId).GetFocusWindowInfo(focusInfo, displayId);
#else
WindowManager::GetInstance(userId).GetFocusWindowInfo(focusInfo, displayId);
#endif
}
bool WindowAdapter::ListWindowInfo(std::vector<sptr<OHOS::Rosen::WindowInfo>> &windowInfos, int32_t userId)
{
#ifdef SCENE_BOARD_ENABLE
WindowInfoOption option;
WMError ret = WindowManagerLite::GetInstance(userId).ListWindowInfo(option, windowInfos);
if (ret != WMError::WM_OK) {
IMSA_HILOGE("ListWindowInfo failed, ret: %{public}d", ret);
return false;
}
return true;
#else
IMSA_HILOGE("capability not supported");
return false;
#endif
}
uint64_t WindowAdapter::GetDisplayIdByToken(sptr<IRemoteObject> abilityToken, int32_t userId)
{
#ifdef SCENE_BOARD_ENABLE
OHOS::Rosen::MainWindowInfo info;
WMError ret = WindowManagerLite::GetInstance(userId).GetMainWindowInfoByToken(abilityToken, info);
if (ret != WMError::WM_OK) {
IMSA_HILOGE("GetMainWindowInfoByToken failed, ret: %{public}d", ret);
return DEFAULT_DISPLAY_ID;
}
IMSA_HILOGI("GetMainWindowInfoByToken, displayId: %{public}" PRIu64 "", info.displayId_);
return info.displayId_;
#else
IMSA_HILOGE("capability not supported");
return DEFAULT_DISPLAY_ID;
#endif
}
uint64_t WindowAdapter::GetDisplayIdByWindowId(int32_t callingWindowId, int32_t userId)
{
#ifdef SCENE_BOARD_ENABLE
if (callingWindowId == DEFAULT_DISPLAY_ID) {
FocusChangeInfo info;
WindowManagerLite::GetInstance(userId).GetFocusWindowInfo(info);
callingWindowId = info.windowId_;
}
std::vector<sptr<WindowInfo>> windowInfos;
if (!ListWindowInfo(windowInfos, userId)) {
return DEFAULT_DISPLAY_ID;
}
auto iter = std::find_if(windowInfos.begin(), windowInfos.end(), [&callingWindowId](const auto &windowInfo) {
if (windowInfo == nullptr) {
return false;
}
return windowInfo->windowMetaInfo.windowId == callingWindowId;
});
if (iter == windowInfos.end()) {
IMSA_HILOGE("not found window info with windowId: %{public}d", callingWindowId);
return DEFAULT_DISPLAY_ID;
}
auto callingDisplayId = (*iter)->windowDisplayInfo.displayId;
IMSA_HILOGD("window windowId: %{public}d, displayId: %{public}" PRIu64 "", callingWindowId, callingDisplayId);
return callingDisplayId;
#else
IMSA_HILOGI("capability not supported");
return DEFAULT_DISPLAY_ID;
#endif
}
uint64_t WindowAdapter::GetDisplayIdWithCorrect(int32_t windowId, uint64_t displayId, int32_t userId)
{
uint64_t displayIdOut = DEFAULT_DISPLAY_ID;
#ifdef SCENE_BOARD_ENABLE
if (windowId == DEFAULT_WINDOW_ID) {
return displayIdOut;
}
std::vector<sptr<WindowInfo>> windowInfos;
if (!ListWindowInfo(windowInfos, userId)) {
return displayIdOut;
}
auto iter = std::find_if(windowInfos.begin(), windowInfos.end(), [&windowId](const auto &windowInfo) {
return windowInfo != nullptr && windowInfo->windowMetaInfo.windowId == windowId;
});
if (iter == windowInfos.end()) {
IMSA_HILOGE("not found windowId:%{public}d, displayId:%{public}" PRIu64 ".", windowId, displayId);
if (windowId == SCB_ROOT_WINDOW_ID) {
displayIdOut = displayId;
}
return displayIdOut;
}
displayIdOut = (*iter)->windowDisplayInfo.displayId;
IMSA_HILOGD("find windowId:%{public}d, displayId:%{public}" PRIu64 ".", windowId, displayIdOut);
return displayIdOut;
#else
IMSA_HILOGI("capability not supported");
return displayIdOut;
#endif
}
uint64_t WindowAdapter::GetDisplayIdByPid(int64_t callingPid, int32_t userId)
{
#ifdef SCENE_BOARD_ENABLE
std::vector<sptr<WindowInfo>> windowInfos;
if (!ListWindowInfo(windowInfos, userId)) {
return DEFAULT_DISPLAY_ID;
}
auto iter = std::find_if(windowInfos.begin(), windowInfos.end(), [&callingPid](const auto &windowInfo) {
if (windowInfo == nullptr) {
return false;
}
return windowInfo->windowMetaInfo.pid == callingPid;
});
if (iter == windowInfos.end()) {
IMSA_HILOGE("not found window info with pid: %{public}" PRId64 "", callingPid);
return DEFAULT_DISPLAY_ID;
}
auto callingDisplayId = (*iter)->windowDisplayInfo.displayId;
IMSA_HILOGD("window pid: %{public}" PRId64 ", displayId: %{public}" PRIu64 "", callingPid, callingDisplayId);
return callingDisplayId;
#else
IMSA_HILOGI("capability not supported");
return DEFAULT_DISPLAY_ID;
#endif
}
bool WindowAdapter::GetDisplayId(int64_t callingPid, uint64_t &displayId, int32_t userId)
{
displayId = DEFAULT_DISPLAY_ID;
#ifdef SCENE_BOARD_ENABLE
std::vector<sptr<WindowInfo>> windowInfos;
if (!ListWindowInfo(windowInfos, userId)) {
return false;
}
auto iter = std::find_if(windowInfos.begin(), windowInfos.end(), [&callingPid](const auto &windowInfo) {
if (windowInfo == nullptr) {
return false;
}
return windowInfo->windowMetaInfo.pid == callingPid;
});
if (iter == windowInfos.end()) {
IMSA_HILOGE("not found window info with pid: %{public}" PRId64 "", callingPid);
return false;
}
auto callingDisplayId = (*iter)->windowDisplayInfo.displayId;
IMSA_HILOGD("window pid: %{public}" PRId64 ", displayId: %{public}" PRIu64 "", callingPid, callingDisplayId);
displayId = callingDisplayId;
return true;
#else
IMSA_HILOGI("capability not supported");
return true;
#endif
}
int32_t WindowAdapter::StoreAllDisplayGroupInfos(int32_t userId)
{
#ifdef SCENE_BOARD_ENABLE
std::unordered_map<uint64_t, uint64_t> displayGroupIds;
std::vector<FocusChangeInfo> focusWindowInfos;
auto ret = GetAllDisplayGroupInfos(displayGroupIds, focusWindowInfos, userId);
if (ret != ErrorCode::NO_ERROR) {
IMSA_HILOGE("GetAllGroupInfo failed, ret: %{public}d", ret);
return ret;
}
#else
IMSA_HILOGI("capability not supported");
#endif
return ErrorCode::NO_ERROR;
}
int32_t WindowAdapter::GetAllFocusWindowInfos(std::vector<FocusChangeInfo> &focusWindowInfos, int32_t userId)
{
std::unordered_map<uint64_t, uint64_t> displayGroupIds;
auto ret = GetAllDisplayGroupInfos(displayGroupIds, focusWindowInfos, userId);
if (ret != ErrorCode::NO_ERROR) {
IMSA_HILOGE("GetAllGroupInfo failed, ret: %{public}d", ret);
return ret;
}
for (const auto &[key, value] : displayGroupIds) {
IMSA_HILOGD("display:%{public}" PRIu64 "/%{public}" PRIu64 ".", key, value);
}
for (const auto &info : focusWindowInfos) {
IMSA_HILOGD("user: %{public}d, focus:%{public}d/%{public}" PRIu64 "/%{public}" PRIu64 "/%{public}d", userId,
info.windowId_, info.displayGroupId_, info.realDisplayId_, info.pid_);
}
return ErrorCode::NO_ERROR;
}
int32_t WindowAdapter::GetDisplayGroupId(uint64_t displayId, int32_t userId, uint64_t &displayGroupId)
{
IMSA_HILOGD("userId %{public}d, by displayId run in:%{public}" PRIu64 ".", userId, displayId);
std::lock_guard<std::mutex> lock(displayGroupIdsLock_);
auto userIter = displayGroupIds_.find(userId);
if (userIter == displayGroupIds_.end()) {
IMSA_HILOGE("user %{public}d not found", userId);
return ErrorCode::ERROR_USER_NOT_EXIST;
}
auto userDisplayGroupIds = userIter->second;
auto groupIter = userDisplayGroupIds.find(displayId);
if (groupIter == userDisplayGroupIds.end()) {
IMSA_HILOGE("display %{public}" PRIu64 " not found", displayId);
return ErrorCode::ERROR_INVALID_DISPLAYID;
}
displayGroupId = groupIter->second;
IMSA_HILOGD(
"userId %{public}d, by displayId:%{public}" PRIu64 "/%{public}" PRIu64 ".", userId, displayId, displayGroupId);
return ErrorCode::NO_ERROR;
}
int32_t WindowAdapter::GetDisplayGroupIdWithRetry(uint64_t displayId, int32_t userId, uint64_t &displayGroupId)
{
int32_t ret = GetDisplayGroupId(displayId, userId, displayGroupId);
if (ret != ErrorCode::NO_ERROR) {
if (displayId == DEFAULT_DISPLAY_ID) {
displayGroupId = DEFAULT_DISPLAY_GROUP_ID;
return ErrorCode::NO_ERROR;
}
std::unordered_map<uint64_t, uint64_t> displayGroupIds;
std::vector<FocusChangeInfo> focusWindowInfos;
GetAllDisplayGroupInfos(displayGroupIds, focusWindowInfos, userId);
ret = GetDisplayGroupId(displayId, userId, displayGroupId);
}
IMSA_HILOGD("GetDisplayGroupIdWithRetry returning, ret: %{public}d, displayId: %{public}" PRIu64 \
", userId: %{public}d, displayGroupId: %{public}" PRIu64 "", ret, displayId, userId, displayGroupId);
return ret;
}
bool WindowAdapter::IsDisplayGroupIdExist(uint64_t displayGroupId, int32_t userId)
{
if (displayGroupId == DEFAULT_DISPLAY_GROUP_ID) {
return true;
}
IMSA_HILOGD("displayGroupId:%{public}" PRIu64 ".", displayGroupId);
std::lock_guard<std::mutex> lock(displayGroupIdsLock_);
auto userIter = displayGroupIds_.find(userId);
if (userIter == displayGroupIds_.end()) {
IMSA_HILOGE("user %{public}d not found", userId);
return false;
}
auto displayGroupIds = userIter->second;
auto iter = std::find_if(displayGroupIds.begin(), displayGroupIds.end(),
[displayGroupId](const std::pair<uint64_t, uint64_t> &pair) { return pair.second == displayGroupId; });
return iter != displayGroupIds.end();
}
bool WindowAdapter::IsDisplayIdExist(uint64_t displayId, int32_t userId)
{
if (displayId == DEFAULT_DISPLAY_ID) {
return true;
}
IMSA_HILOGD("displayId:%{public}" PRIu64 ".", displayId);
std::lock_guard<std::mutex> lock(displayGroupIdsLock_);
auto iter = displayGroupIds_.find(userId);
if (iter == displayGroupIds_.end()) {
IMSA_HILOGE("user %{public}d not found", userId);
return false;
}
auto displayGroupIds = iter->second;
return displayGroupIds.find(displayId) != displayGroupIds.end();
}
bool WindowAdapter::IsDefaultDisplayGroup(uint64_t displayId, int32_t userId)
{
uint64_t displayGroupId = DEFAULT_DISPLAY_GROUP_ID;
int32_t ret = GetDisplayGroupIdWithRetry(displayId, userId, displayGroupId);
if (ret != ErrorCode::NO_ERROR) {
IMSA_HILOGE("GetDisplayGroupIdWithRetry failed, ret: %{public}d", ret);
return false;
}
return displayGroupId == DEFAULT_DISPLAY_GROUP_ID;
}
int32_t WindowAdapter::GetDisplayGroupId(uint32_t windowId, int32_t userId)
{
IMSA_HILOGD("by windowId run in:%{public}d.", windowId);
auto displayId = GetDisplayIdByWindowId(windowId, userId);
uint64_t displayGroupId = DEFAULT_DISPLAY_GROUP_ID;
int32_t ret = GetDisplayGroupIdWithRetry(displayId, userId, displayGroupId);
IMSA_HILOGD("GetDisplayGroupId by windowId: %{public}d, ret: %{public}d, displayGroupId: %{public}" PRIu64 "",
windowId, ret, displayGroupId);
return ret;
}
int32_t WindowAdapter::GetAllDisplayGroupInfos(std::unordered_map<uint64_t, uint64_t> &displayGroupIds,
std::vector<FocusChangeInfo> &focusWindowInfos, int32_t userId)
{
#ifdef SCENE_BOARD_ENABLE
std::vector<sptr<FocusChangeInfo>> focusWindowInfoPtr;
WindowManagerLite::GetInstance(userId).GetAllGroupInfo(displayGroupIds, focusWindowInfoPtr);
for (const auto &info : focusWindowInfoPtr) {
if (info != nullptr) {
focusWindowInfos.push_back(*info);
}
}
std::sort(focusWindowInfos.begin(), focusWindowInfos.end(),
[](const FocusChangeInfo &a, const FocusChangeInfo &b) { return a.realDisplayId_ < b.realDisplayId_; });
GetInstance().SetDisplayGroupIds(displayGroupIds, userId);
return ErrorCode::NO_ERROR;
#else
return ErrorCode::NO_ERROR;
#endif
}
void WindowAdapter::SetDisplayGroupIds(const std::unordered_map<uint64_t, uint64_t> &displayGroupIds, int32_t userId)
{
std::lock_guard<std::mutex> lock(displayGroupIdsLock_);
displayGroupIds_[userId] = displayGroupIds;
}
void WindowAdapter::OnDisplayGroupInfoChanged(uint64_t displayId, uint64_t displayGroupId, bool isAdd, int32_t userId)
{
IMSA_HILOGI("display change:%{public}" PRIu64 "/%{public}" PRIu64 "/%{public}d.", displayId,
displayGroupId, isAdd);
std::lock_guard<std::mutex> lock(displayGroupIdsLock_);
if (isAdd) {
displayGroupIds_[userId][displayId] = displayGroupId;
return;
}
auto userIter = displayGroupIds_.find(userId);
if (userIter == displayGroupIds_.end()) {
IMSA_HILOGE("user %{public}d not found", userId);
return;
}
auto &displayGroupIds = userIter->second;
displayGroupIds.erase(displayId);
}
int32_t WindowAdapter::RegisterAllGroupInfoChangedListener(int32_t userId)
{
#ifdef SCENE_BOARD_ENABLE
sptr<IAllGroupInfoChangedListener> listener = new (std::nothrow) AllGroupInfoChangedListenerImpl(userId);
if (listener == nullptr) {
IMSA_HILOGE("failed to create listener");
return ErrorCode::ERROR_IMSA_MALLOC_FAILED;
}
auto wmErr = WindowManagerLite::GetInstance(userId).RegisterAllGroupInfoChangedListener(listener);
IMSA_HILOGI("register AllGroupInfoChangedListener ret: %{public}d", wmErr);
if (wmErr != WMError::WM_OK) {
return ErrorCode::ERROR_WINDOW_MANAGER;
}
return ErrorCode::NO_ERROR;
#else
return ErrorCode::NO_ERROR;
#endif
}
int32_t WindowAdapter::RegisterWindowDisplayIdChangedListener(const WindowDisplayChangeHandler &handler, int32_t userId)
{
#ifdef SCENE_BOARD_ENABLE
sptr<IWindowInfoChangedListener> listener = new (std::nothrow) WindowDisplayChangedListenerImpl(handler);
if (listener == nullptr) {
IMSA_HILOGE("failed to create listener");
return ErrorCode::ERROR_IMSA_MALLOC_FAILED;
}
std::unordered_set<WindowInfoKey> observedInfo;
observedInfo.insert(WindowInfoKey::DISPLAY_ID);
listener->AddInterestInfo(WindowInfoKey::WINDOW_ID);
auto wmErr = WindowManagerLite::GetInstance(userId).RegisterWindowInfoChangeCallback(observedInfo, listener);
IMSA_HILOGI("register WindowInfoChangeListener ret: %{public}d", wmErr);
if (wmErr != WMError::WM_OK) {
return ErrorCode::ERROR_WINDOW_MANAGER;
}
return ErrorCode::NO_ERROR;
#else
return ErrorCode::NO_ERROR;
#endif
}
void WindowAdapter::WindowDisplayChangedListenerImpl::OnWindowInfoChanged(const WindowInfoList &windowInfoList)
{
#ifdef SCENE_BOARD_ENABLE
if (windowInfoList.empty()) {
IMSA_HILOGE("windowInfoList is empty");
return;
}
auto userId = OsAccountAdapter::GetOsAccountLocalIdFromUid(IPCSkeleton::GetCallingUid());
IMSA_HILOGI("user:%{public}d windowInfoList size is:%{public}zu.", userId, windowInfoList.size());
uint64_t displayId = 0;
uint32_t windowId = 0;
for (const auto &infoMap : windowInfoList) {
auto displayIdIter = infoMap.find(WindowInfoKey::DISPLAY_ID);
if (displayIdIter == infoMap.end()) {
IMSA_HILOGE("displayId not find.");
continue;
}
auto windowIdIter = infoMap.find(WindowInfoKey::WINDOW_ID);
if (windowIdIter == infoMap.end()) {
IMSA_HILOGE("windowId not find.");
continue;
}
if (!VariantUtil::GetValue(displayIdIter->second, displayId)) {
IMSA_HILOGE("displayId type is error.");
continue;
}
if (!VariantUtil::GetValue(windowIdIter->second, windowId)) {
IMSA_HILOGE("windowId type is error.");
continue;
}
if (handler_ != nullptr) {
handler_(userId, windowId, displayId);
}
}
#endif
}
}
}