1/*
2 * Copyright (c) 2021 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 "hdc_connect.h"
17#include "hdc_jdwp.h"
18#include "parameter.h"
19
20namespace Hdc {
21
22std::unique_ptr<ConnectManagement> g_connectManagement = nullptr;
23static HdcJdwpSimulator *g_clsHdcJdwpSimulator = nullptr;
24
25void ConnectManagement::SetProcessName(const std::string &processName)
26{
27    processName_ = processName;
28}
29
30std::string ConnectManagement::GetProcessName() const
31{
32    return processName_;
33}
34
35void ConnectManagement::SetPkgName(const std::string &pkgName)
36{
37    pkgName_ = pkgName;
38}
39
40std::string ConnectManagement::GetPkgName() const
41{
42    return pkgName_;
43}
44
45void ConnectManagement::SetDebug(bool isDebug)
46{
47    isDebug_ = isDebug;
48}
49
50bool ConnectManagement::GetDebug() const
51{
52    return isDebug_;
53}
54
55void ConnectManagement::SetCallback(Callback cb)
56{
57    cb_ = cb;
58}
59
60Callback ConnectManagement::GetCallback() const
61{
62    return cb_;
63}
64
65static void GetDevItem(const char *key, std::string &out, const char *preDefine = nullptr)
66{
67    constexpr int len = 512;
68    char buf[len] = "";
69    if (memset_s(buf, len, 0, len) != EOK) {
70        HILOG_WARN(LOG_CORE, "memset_s failed");
71        return;
72    }
73    auto res = GetParameter(key, preDefine, buf, len);
74    if (res <= 0) {
75        return;
76    }
77    out = buf;
78}
79
80static bool IsDeveloperMode()
81{
82    std::string developerMode;
83    GetDevItem("const.security.developermode.state", developerMode);
84    return developerMode == "true";
85}
86
87void FreeInstance()
88{
89    if (g_clsHdcJdwpSimulator == nullptr) {
90        return;
91    }
92    g_clsHdcJdwpSimulator->Disconnect();
93    delete g_clsHdcJdwpSimulator;
94    g_clsHdcJdwpSimulator = nullptr;
95}
96
97void Stop(int signo)
98{
99    FreeInstance();
100    _exit(0);
101}
102
103void StopConnect()
104{
105    if (!IsDeveloperMode()) {
106        HILOG_INFO(LOG_CORE, "non developer mode not to stop connect");
107        return;
108    }
109#ifdef JS_JDWP_CONNECT
110    FreeInstance();
111#endif // JS_JDWP_CONNECT
112}
113
114void* HdcConnectRun(void* pkgContent)
115{
116    if (signal(SIGINT, Stop) == SIG_ERR) {
117        HILOG_FATAL(LOG_CORE, "jdwp_process signal fail.");
118    }
119    int ret = pthread_setname_np(pthread_self(), "OS_hdcRegister");
120    if (ret != 0) {
121        HILOG_FATAL(LOG_CORE, "set Thread name failed.");
122    }
123    std::string processName = static_cast<ConnectManagement*>(pkgContent)->GetProcessName();
124    std::string pkgName = static_cast<ConnectManagement*>(pkgContent)->GetPkgName();
125    bool isDebug = static_cast<ConnectManagement*>(pkgContent)->GetDebug();
126    Callback cb = static_cast<ConnectManagement*>(pkgContent)->GetCallback();
127    g_clsHdcJdwpSimulator = new (std::nothrow) HdcJdwpSimulator(processName, pkgName, isDebug, cb);
128    if (!g_clsHdcJdwpSimulator->Connect()) {
129        HILOG_FATAL(LOG_CORE, "Connect fail.");
130        return nullptr;
131    }
132    return nullptr;
133}
134
135void StartConnect(const std::string& processName, const std::string& pkgName, bool isDebug, Callback cb)
136{
137    if (!IsDeveloperMode()) {
138        HILOG_INFO(LOG_CORE, "non developer mode not to start connect");
139        return;
140    }
141    if (g_clsHdcJdwpSimulator != nullptr) {
142        return;
143    }
144    pthread_t tid;
145    g_connectManagement = std::make_unique<ConnectManagement>();
146    g_connectManagement->SetProcessName(processName);
147    g_connectManagement->SetPkgName(pkgName);
148    g_connectManagement->SetDebug(isDebug);
149    g_connectManagement->SetCallback(cb);
150    if (pthread_create(&tid, nullptr, &HdcConnectRun, static_cast<void*>(g_connectManagement.get())) != 0) {
151        HILOG_FATAL(LOG_CORE, "pthread_create fail!");
152        return;
153    }
154}
155} // namespace Hdc
156