1/*
2 * Copyright (c) 2023 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
16#include <ctime>
17
18#include "system_event_wrapper.h"
19
20#include "bundle_constants.h"
21#include "common_event_manager.h"
22#include "common_event_subscriber.h"
23#include "common_event_support.h"
24
25#include "asset_log.h"
26
27namespace {
28using namespace OHOS::AppExecFwk::Constants;
29using namespace OHOS::EventFwk;
30
31const char * const APP_ID = "appId";
32const char * const COMMON_EVENT_RESTORE_START = "usual.event.RESTORE_START";
33const char * const COMMON_EVENT_USER_PIN_CREATED = "USER_PIN_CREATED_EVENT";
34const char * const BUNDLE_NAME = "bundleName";
35const char * const PERMISSION_MANAGE_USER_IDM = "ohos.permission.MANAGE_USER_IDM";
36
37void HandlePackageRemoved(const OHOS::AAFwk::Want &want, bool isSandBoxApp, OnPackageRemoved onPackageRemoved)
38{
39    int userId = want.GetIntParam(USER_ID, INVALID_USERID);
40    std::string appId = want.GetStringParam(APP_ID);
41    int appIndex = isSandBoxApp ? want.GetIntParam(SANDBOX_APP_INDEX, -1) : 0;
42    if (appId.empty() || userId == INVALID_USERID || appIndex == -1) {
43        LOGE("[FATAL]Get removed owner info failed, userId=%{public}d, appId=%{public}s, appIndex=%{public}d",
44            userId, appId.c_str(), appIndex);
45        return;
46    }
47
48    std::string owner = appId + '_' + std::to_string(appIndex);
49    std::string bundleName = want.GetBundle();
50    if (onPackageRemoved != nullptr) {
51        onPackageRemoved(userId, reinterpret_cast<const uint8_t *>(owner.c_str()), owner.size(),
52            reinterpret_cast<const uint8_t *>(bundleName.c_str()), appIndex);
53    }
54    LOGI("[INFO]Receive event: PACKAGE_REMOVED, userId=%{public}d, appId=%{public}s, appIndex=%{public}d, ",
55        userId, appId.c_str(), appIndex);
56}
57
58void HandleAppRestore(const OHOS::AAFwk::Want &want, OnAppRestore onAppRestore)
59{
60    if (onAppRestore != nullptr) {
61        int userId = want.GetIntParam(USER_ID, INVALID_USERID);
62        std::string bundleName = want.GetStringParam(BUNDLE_NAME);
63
64        int appIndex = want.GetIntParam(SANDBOX_APP_INDEX, -1);
65        if (appIndex == -1) {
66            LOGI("[INFO]Get app restore info failed, default as index 0.");
67            appIndex = 0;
68        }
69
70        onAppRestore(userId, reinterpret_cast<const uint8_t *>(bundleName.c_str()), appIndex);
71        LOGI("[INFO]Receive event: RESTORE_START.");
72    }
73}
74
75class SystemEventHandler : public CommonEventSubscriber {
76public:
77    explicit SystemEventHandler(const CommonEventSubscribeInfo &subscribeInfo, const EventCallBack eventCallBack)
78        : CommonEventSubscriber(subscribeInfo), eventCallBack(eventCallBack) {}
79    ~SystemEventHandler() = default;
80    void OnReceiveEvent(const CommonEventData &data) override
81    {
82        long startTime = std::clock();
83        auto want = data.GetWant();
84        std::string action = want.GetAction();
85        if (action == CommonEventSupport::COMMON_EVENT_PACKAGE_REMOVED) {
86            HandlePackageRemoved(want, false, this->eventCallBack.onPackageRemoved);
87        } else if (action == CommonEventSupport::COMMON_EVENT_SANDBOX_PACKAGE_REMOVED) {
88            HandlePackageRemoved(want, true, this->eventCallBack.onPackageRemoved);
89        } else if (action == CommonEventSupport::COMMON_EVENT_USER_REMOVED) {
90            int userId = data.GetCode();
91            if (this->eventCallBack.onUserRemoved != nullptr) {
92                this->eventCallBack.onUserRemoved(userId);
93            }
94            LOGI("[INFO] Receive event: USER_REMOVED, userId=%{public}d", userId);
95        } else if (action == CommonEventSupport::COMMON_EVENT_SCREEN_OFF) {
96            if (this->eventCallBack.onScreenOff != nullptr) {
97                this->eventCallBack.onScreenOff();
98            }
99            LOGI("[INFO]Receive event: SCREEN_OFF, start_time: %{public}ld", startTime);
100        } else if (action == CommonEventSupport::COMMON_EVENT_CHARGING) {
101            if (this->eventCallBack.onCharging != nullptr) {
102                this->eventCallBack.onCharging();
103            }
104            LOGI("[INFO]Receive event: CHARGING, start_time: %{public}ld", startTime);
105        } else if (action == COMMON_EVENT_RESTORE_START) {
106            HandleAppRestore(want, this->eventCallBack.onAppRestore);
107        } else if (action == CommonEventSupport::COMMON_EVENT_USER_UNLOCKED) {
108            if (this->eventCallBack.onUserUnlocked != nullptr) {
109                int userId = data.GetCode();
110
111                this->eventCallBack.onUserUnlocked(userId);
112            }
113            LOGI("[INFO]Receive event: USER_UNLOCKED, start_time: %{public}ld", startTime);
114        } else if (action == COMMON_EVENT_USER_PIN_CREATED) {
115            if (this->eventCallBack.onUserUnlocked != nullptr) {
116                int userId = data.GetCode();
117                this->eventCallBack.onUserUnlocked(userId);
118            }
119            LOGI("[INFO]Receive event: USER_PIN_CREATED_EVENT, start_time: %{public}ld", startTime);
120        } else {
121            LOGW("[WARNING]Receive unknown event: %{public}s", action.c_str());
122        }
123    }
124private:
125    const EventCallBack eventCallBack;
126};
127
128std::shared_ptr<SystemEventHandler> g_eventHandler = nullptr;
129std::shared_ptr<SystemEventHandler> g_pinEventHandler = nullptr;
130bool SubscribePinEvent(const EventCallBack eventCallBack)
131{
132    MatchingSkills matchingSkills;
133    matchingSkills.AddEvent(COMMON_EVENT_USER_PIN_CREATED);
134    CommonEventSubscribeInfo info(matchingSkills);
135    info.SetPermission(PERMISSION_MANAGE_USER_IDM);
136    if (g_pinEventHandler == nullptr) {
137        g_pinEventHandler = std::shared_ptr<SystemEventHandler>(
138            new (std::nothrow) SystemEventHandler(info, eventCallBack));
139        if (g_pinEventHandler == nullptr) {
140            LOGE("[FATAL]Asset pin event handler is nullptr.");
141            return false;
142        }
143    }
144
145    return CommonEventManager::SubscribeCommonEvent(g_pinEventHandler);
146}
147
148bool UnSubscribePinEvent(void)
149{
150    if (g_pinEventHandler == nullptr) {
151        LOGW("Asset pin event handler is nullptr, no need to unsubscribe.");
152        return false;
153    }
154
155    bool res = CommonEventManager::UnSubscribeCommonEvent(g_pinEventHandler);
156    g_pinEventHandler = nullptr;
157    return res;
158}
159
160}
161
162bool SubscribeSystemEvent(const EventCallBack eventCallBack)
163{
164    bool ret = SubscribePinEvent(eventCallBack);
165    LOGI("Subscribe pin event result: %d", ret);
166
167    MatchingSkills matchingSkills;
168    matchingSkills.AddEvent(CommonEventSupport::COMMON_EVENT_PACKAGE_REMOVED);
169    matchingSkills.AddEvent(CommonEventSupport::COMMON_EVENT_SANDBOX_PACKAGE_REMOVED);
170    matchingSkills.AddEvent(CommonEventSupport::COMMON_EVENT_USER_REMOVED);
171    matchingSkills.AddEvent(CommonEventSupport::COMMON_EVENT_SCREEN_OFF);
172    matchingSkills.AddEvent(CommonEventSupport::COMMON_EVENT_CHARGING);
173    matchingSkills.AddEvent(CommonEventSupport::COMMON_EVENT_USER_UNLOCKED);
174    matchingSkills.AddEvent(COMMON_EVENT_RESTORE_START);
175    CommonEventSubscribeInfo info(matchingSkills);
176    if (g_eventHandler == nullptr) {
177        g_eventHandler = std::shared_ptr<SystemEventHandler>(
178            new (std::nothrow) SystemEventHandler(info, eventCallBack));
179        if (g_eventHandler == nullptr) {
180            LOGE("[FATAL]Asset system event handler is nullptr.");
181            return false;
182        }
183    }
184
185    return CommonEventManager::SubscribeCommonEvent(g_eventHandler);
186}
187
188bool UnSubscribeSystemEvent(void)
189{
190    bool ret = UnSubscribePinEvent();
191    LOGI("UnSubscribe pin event result: %d", ret);
192
193    if (g_eventHandler == nullptr) {
194        LOGW("Asset system event handler is nullptr, no need to unsubscribe.");
195        return false;
196    }
197
198    bool res = CommonEventManager::UnSubscribeCommonEvent(g_eventHandler);
199    g_eventHandler = nullptr;
200    return res;
201}
202