1/*
2 * Copyright (c) 2024 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 "oobe_datashare_utils.h"
17#include "res_sched_log.h"
18#include "oobe_manager.h"
19#include <functional>
20#include <vector>
21#include "ipc_skeleton.h"
22
23namespace OHOS {
24namespace ResourceSchedule {
25std::recursive_mutex OOBEManager::mutex_;
26std::vector<std::shared_ptr<IOOBETask>> OOBEManager::oobeTasks_;
27std::vector<std::function<void()>> OOBEManager::dataShareFunctions_;
28sptr<OOBEManager::ResDataAbilityObserver> OOBEManager::observer_ = nullptr;
29namespace {
30const std::string KEYWORD = "basic_statement_agreed";
31} // namespace
32
33OOBEManager::OOBEManager()
34{
35    Initialize();
36}
37
38OOBEManager::~OOBEManager()
39{
40    RESSCHED_LOGI("OOBEManager has been deconstructed");
41}
42
43OOBEManager& OOBEManager::GetInstance()
44{
45    static OOBEManager instance;
46    return instance;
47}
48
49bool OOBEManager::GetOOBValue()
50{
51    std::lock_guard<std::recursive_mutex> lock(mutex_);
52    return g_oobeValue;
53}
54
55ErrCode OOBEManager::RegisterObserver(const std::string& key, const ResDataAbilityObserver::UpdateFunc& func)
56{
57    std::lock_guard<std::recursive_mutex> lock(mutex_);
58    if (!DataShareUtils::GetInstance().GetDataShareReadyFlag()) {
59        RESSCHED_LOGE("RegisterObserver: dataShare is not ready!");
60        std::function dataShareFunction = [key, func, this]() {
61            ReRegisterObserver(key, func);
62        };
63        dataShareFunctions_.push_back(dataShareFunction);
64        return ERR_NO_INIT;
65    }
66
67    std::string callingIdentity = IPCSkeleton::ResetCallingIdentity();
68    auto uri = DataShareUtils::GetInstance().AssembleUri(key);
69    auto helper = DataShareUtils::GetInstance().CreateDataShareHelper();
70    if (helper == nullptr) {
71        IPCSkeleton::SetCallingIdentity(callingIdentity);
72        RESSCHED_LOGE("RegisterObserver: helper does not created!");
73        return ERR_NO_INIT;
74    }
75    if (observer_ != nullptr) {
76        RESSCHED_LOGE("Secondary RegisterObserver!");
77        UnregisterObserver();
78    }
79    observer_ = new (std::nothrow)ResDataAbilityObserver();
80    if (observer_ == nullptr) {
81        IPCSkeleton::SetCallingIdentity(callingIdentity);
82        return ERR_INVALID_OPERATION;
83    }
84    observer_->SetUpdateFunc(func);
85    helper->RegisterObserver(uri, observer_);
86    DataShareUtils::GetInstance().ReleaseDataShareHelper(helper);
87    IPCSkeleton::SetCallingIdentity(callingIdentity);
88    RESSCHED_LOGI("succeed to register observer of uri=%{public}s", uri.ToString().c_str());
89    return ERR_OK;
90}
91
92void OOBEManager::ReRegisterObserver(const std::string& key, const ResDataAbilityObserver::UpdateFunc& func)
93{
94    int resultValue = 0;
95    ResourceSchedule::DataShareUtils::GetInstance().GetValue(key, resultValue);
96    if (resultValue != 0) {
97        func();
98        return;
99    }
100    RegisterObserver(key, func);
101}
102
103ErrCode OOBEManager::UnregisterObserver()
104{
105    std::string callingIdentity = IPCSkeleton::ResetCallingIdentity();
106    auto uri = DataShareUtils::GetInstance().AssembleUri(KEYWORD);
107    auto helper = DataShareUtils::GetInstance().CreateDataShareHelper();
108    if (helper == nullptr) {
109        IPCSkeleton::SetCallingIdentity(callingIdentity);
110        RESSCHED_LOGE("UnregisterObserver: helper does not created!");
111        return ERR_NO_INIT;
112    }
113    helper->UnregisterObserver(uri, observer_);
114    DataShareUtils::GetInstance().ReleaseDataShareHelper(helper);
115    observer_ = nullptr;
116    IPCSkeleton::SetCallingIdentity(callingIdentity);
117    RESSCHED_LOGI("succeed to register observer of uri=%{public}s", uri.ToString().c_str());
118    return ERR_OK;
119}
120
121void OOBEManager::ResDataAbilityObserver::OnChange()
122{
123    if (update_) {
124        update_();
125    }
126}
127
128void OOBEManager::ResDataAbilityObserver::SetUpdateFunc(const UpdateFunc& func)
129{
130    update_ = func;
131}
132
133void OOBEManager::Initialize()
134{
135    int resultValue = 0;
136    ResourceSchedule::DataShareUtils::GetInstance().GetValue(KEYWORD, resultValue);
137    if (resultValue != 0) {
138        g_oobeValue = true;
139    }
140}
141
142bool OOBEManager::SubmitTask(const std::shared_ptr<IOOBETask>& task)
143{
144    std::lock_guard<std::recursive_mutex> lock(mutex_);
145    if (task == nullptr) {
146        RESSCHED_LOGE("Bad task passed!");
147        return false;
148    }
149    if (g_oobeValue) {
150        task->ExcutingTask();
151        return true;
152    }
153    oobeTasks_.push_back(task);
154    return true;
155}
156
157void OOBEManager::StartListen()
158{
159    int resultValue = 0;
160    ResourceSchedule::DataShareUtils::GetInstance().GetValue(KEYWORD, resultValue);
161    if (resultValue != 0) {
162        std::lock_guard<std::recursive_mutex> lock(mutex_);
163        g_oobeValue = true;
164        for (auto task : oobeTasks_) {
165            task->ExcutingTask();
166        }
167        return;
168    }
169    OOBEManager::ResDataAbilityObserver::UpdateFunc updateFunc = [&]() {
170        int result = 0;
171        ResourceSchedule::DataShareUtils::GetInstance().GetValue(KEYWORD, result);
172        if (result != 0) {
173            RESSCHED_LOGI("User consent authorization!");
174            std::lock_guard<std::recursive_mutex> lock(mutex_);
175            g_oobeValue = true;
176            for (auto task : oobeTasks_) {
177                task->ExcutingTask();
178            }
179        } else {
180            RESSCHED_LOGI("User does not consent authorization!");
181            g_oobeValue = false;
182        }
183    };
184    RegisterObserver(KEYWORD, updateFunc);
185}
186
187void OOBEManager::OnReceiveDataShareReadyCallBack()
188{
189    std::lock_guard<std::recursive_mutex> lock(mutex_);
190    for (auto function : dataShareFunctions_) {
191        function();
192    }
193    dataShareFunctions_.clear();
194}
195} // namespace ResourceSchedule
196} // namespace OHOS
197