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
16 #include <ani.h>
17 #include <array>
18 #include <iostream>
19 #include <vector>
20 #include "print_log.h"
21 #include "print_constant.h"
22 #include "print_entry.h"
23 #include "print_callback.h"
24
25 using namespace OHOS::Print;
AniStringToStdString(ani_env * env,ani_string aniStr)26 static std::string AniStringToStdString(ani_env *env, ani_string aniStr)
27 {
28 ani_size strSize;
29 env->String_GetUTF8Size(aniStr, &strSize);
30
31 std::vector<char> buffer(strSize + 1);
32 char* utf8Buffer = buffer.data();
33
34 ani_size bytesWritten = 0;
35 env->String_GetUTF8(aniStr, utf8Buffer, strSize + 1, &bytesWritten);
36
37 utf8Buffer[bytesWritten] = '\0';
38 std::string content = std::string(utf8Buffer);
39 return content;
40 }
41
PrintAsyncCallback(ani_env * env,ani_object object,ani_object arrayObj)42 static ani_int PrintAsyncCallback([[maybe_unused]] ani_env *env,
43 [[maybe_unused]] ani_object object, ani_object arrayObj)
44 {
45 PRINT_HILOGI("enter PrintAsyncCallback");
46 ani_double length;
47 ani_status status = ANI_ERROR;
48 status = env->Object_GetPropertyByName_Double(arrayObj, "length", &length);
49 if (status != ANI_OK) {
50 PRINT_HILOGE("Object_GetPropertyByName_Double fail, status = %{public}u", status);
51 return status;
52 }
53 std::vector<std::string> files;
54 for (int i = 0; i < int(length); i++) {
55 ani_ref stringEntryRef;
56 status = env->Object_CallMethodByName_Ref(arrayObj, "$_get",
57 "I:Lstd/core/Object;", &stringEntryRef, (ani_int)i);
58 if (status != ANI_OK) {
59 PRINT_HILOGE("Object_CallMethodByName_Ref fail, status = %{public}u", status);
60 return status;
61 }
62 files.emplace_back(AniStringToStdString(env, static_cast<ani_string>(stringEntryRef)));
63 }
64 for (const auto &file : files) {
65 PRINT_HILOGD("Array String Content: = %{private}s", file.c_str());
66 }
67
68 int32_t ret = PrintEntry::GetInstance()->StartPrint(files);
69 if (ret != E_PRINT_NONE) {
70 PRINT_HILOGE("StartPrint error, ret = %{public}d", ret);
71 status = ANI_ERROR;
72 }
73 return status;
74 }
75
On(ani_env * env,ani_object object,ani_string string_object)76 static ani_int On([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object object, ani_string string_object)
77 {
78 PRINT_HILOGI("enter On");
79 ani_size strSize;
80 env->String_GetUTF8Size(string_object, &strSize);
81
82 std::vector<char> buffer(strSize + 1); // +1 for null terminator
83 char* utf8Buffer = buffer.data();
84
85 ani_size bytesWritten = 0;
86 env->String_GetUTF8(string_object, utf8Buffer, strSize + 1, &bytesWritten);
87
88 utf8Buffer[bytesWritten] = '\0';
89 std::string content = std::string(utf8Buffer);
90 PRINT_HILOGD("CallMeWithOptionalString Get = %{public}s", content.c_str());
91 int32_t ret = PrintEntry::GetInstance()->On(content);
92 if (ret != E_PRINT_NONE) {
93 PRINT_HILOGE("On error, ret = %{public}d", ret);
94 return ANI_ERROR;
95 }
96 return ANI_OK;
97 }
98
Off(ani_env * env,ani_object object,ani_string string_object)99 static ani_int Off([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object object, ani_string string_object)
100 {
101 PRINT_HILOGI("enter Off");
102 ani_size strSize;
103 env->String_GetUTF8Size(string_object, &strSize);
104
105 std::vector<char> buffer(strSize + 1); // +1 for null terminator
106 char* utf8Buffer = buffer.data();
107
108 ani_size bytesWritten = 0;
109 env->String_GetUTF8(string_object, utf8Buffer, strSize + 1, &bytesWritten);
110
111 utf8Buffer[bytesWritten] = '\0';
112 std::string content = std::string(utf8Buffer);
113 PRINT_HILOGD("CallMeWithOptionalString Get = %{public}s", content.c_str());
114 int32_t ret = PrintEntry::GetInstance()->Off(content);
115 if (ret != E_PRINT_NONE) {
116 PRINT_HILOGE("Off error, ret = %{public}d", ret);
117 return ANI_ERROR;
118 }
119 return ANI_OK;
120 }
121
ANI_Constructor(ani_vm * vm,uint32_t * result)122 ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result)
123 {
124 PRINT_HILOGI("enter ANI_Constructor");
125 uint32_t status = 0;
126 ani_env *env;
127 if (ANI_OK != vm->GetEnv(ANI_VERSION_1, &env)) {
128 PRINT_HILOGE("Unsupported ANI_VERSION_1, status = %{public}u", status);
129 return ANI_ERROR;
130 }
131
132 ani_class cls;
133 const char* CLASS_NAME_PRINTANI = "L@ohos/print/printAni;";
134 status = env->FindClass(CLASS_NAME_PRINTANI, &cls);
135 if (status != ANI_OK) {
136 PRINT_HILOGE("Not found className = %{public}s, status = %{public}u", CLASS_NAME_PRINTANI, status);
137 return static_cast<ani_status>(status);
138 }
139
140 std::array methods = {
141 ani_native_function {"printAsyncCallback", nullptr, reinterpret_cast<void *>(PrintAsyncCallback)},
142 ani_native_function {"on", nullptr, reinterpret_cast<void *>(On)},
143 ani_native_function {"off", nullptr, reinterpret_cast<void *>(Off)},
144 };
145 PRINT_HILOGD("Start bind native methods to = %{public}s", CLASS_NAME_PRINTANI);
146
147 status = env->Class_BindNativeMethods(cls, methods.data(), methods.size());
148 if (status != ANI_OK) {
149 PRINT_HILOGE("Cannot bind native methods to %{public}s, status = %{public}u", CLASS_NAME_PRINTANI, status);
150 return ANI_INVALID_ARGS;
151 };
152 PRINT_HILOGD("Finish bind native methods to = %{public}s", CLASS_NAME_PRINTANI);
153
154 *result = ANI_VERSION_1;
155 return ANI_OK;
156 }