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 "knuckle_drawing_manager.h"
17
18#ifdef OHOS_BUILD_ENABLE_NEW_KNUCKLE_DYNAMIC
19#include "animation/rs_particle_params.h"
20#endif // OHOS_BUILD_ENABLE_NEW_KNUCKLE_DYNAMIC
21#include "image/bitmap.h"
22#include "image_source.h"
23#include "image_type.h"
24#include "image_utils.h"
25#ifndef USE_ROSEN_DRAWING
26#include "pipeline/rs_recording_canvas.h"
27#else
28#include "ui/rs_canvas_drawing_node.h"
29#endif // USE_ROSEN_DRAWING
30
31#include "define_multimodal.h"
32#include "i_multimodal_input_connect.h"
33#include "mmi_log.h"
34#include "parameters.h"
35#include "setting_datashare.h"
36#ifdef OHOS_BUILD_ENABLE_NEW_KNUCKLE_DYNAMIC
37#include "timer_manager.h"
38#endif // OHOS_BUILD_ENABLE_NEW_KNUCKLE_DYNAMIC
39#include "touch_drawing_manager.h"
40
41#undef MMI_LOG_TAG
42#define MMI_LOG_TAG "KnuckleDrawingManager"
43
44namespace OHOS {
45namespace MMI {
46namespace {
47constexpr int32_t DEFAULT_VALUE { -1 };
48constexpr int32_t MAX_POINTER_NUM { 5 };
49constexpr int32_t MID_POINT { 2 };
50constexpr int32_t POINT_INDEX0 { 0 };
51constexpr int32_t POINT_INDEX1 { 1 };
52constexpr int32_t POINT_INDEX2 { 2 };
53constexpr int32_t POINT_INDEX3 { 3 };
54constexpr int32_t POINT_INDEX4 { 4 };
55constexpr int32_t PAINT_STROKE_WIDTH { 10 };
56constexpr int32_t PAINT_PATH_RADIUS { 10 };
57constexpr int64_t DOUBLE_CLICK_INTERVAL_TIME_SLOW { 450000 };
58[[ maybe_unused ]] constexpr int64_t WAIT_DOUBLE_CLICK_INTERVAL_TIME { 100000 };
59constexpr float DOUBLE_CLICK_DISTANCE_LONG_CONFIG { 96.0f };
60[[ maybe_unused ]] constexpr float VPR_CONFIG { 3.25f };
61constexpr int32_t POW_SQUARE { 2 };
62constexpr int32_t ROTATION_ANGLE_0 { 0 };
63constexpr int32_t ROTATION_ANGLE_90 { 90 };
64constexpr int32_t ROTATION_ANGLE_180 { 180 };
65constexpr int32_t ROTATION_ANGLE_270 { 270 };
66constexpr uint64_t FOLD_SCREEN_MAIN_ID { 5 };
67const int32_t ROTATE_POLICY = system::GetIntParameter("const.window.device.rotate_policy", 0);
68const std::string FOLDABLE = system::GetParameter("const.window.foldabledevice.rotate_policy", "");
69constexpr int32_t WINDOW_ROTATE { 0 };
70constexpr int32_t SCREEN_ROTATE { 1 };
71constexpr int32_t FOLDABLE_DEVICE { 2 };
72constexpr char FOLDABLE_ROTATE { '0' };
73constexpr int32_t SUBSCRIPT_TWO { 2 };
74constexpr int32_t SUBSCRIPT_ZERO { 0 };
75constexpr std::string_view SCREEN_READING { "accessibility_screenreader_enabled" };
76constexpr std::string_view SCREEN_READ_ENABLE { "1" };
77constexpr int32_t POINTER_NUMBER_TO_DRAW { 10 };
78#ifdef OHOS_BUILD_ENABLE_NEW_KNUCKLE_DYNAMIC
79constexpr int64_t PARTICLE_LIFE_TIME { 700 };
80constexpr int32_t PARTICLE_COUNT { -1 };
81constexpr int32_t DEFAULT_EMIT_RATE { 0 };
82constexpr int32_t EMIT_RATE { 400 };
83constexpr int32_t PATH_SIZE_EIGHT { 8 };
84constexpr int32_t MAX_PATH_SIZE { 50 };
85constexpr int32_t MAX_PATH_LENGTH { 500 };
86constexpr float PARTICLE_RADIUS { 5.0f };
87constexpr float DEFAULT_PARTICLE_POSITION_X { 0.0f };
88constexpr float DEFAULT_PARTICLE_POSITION_Y { 0.0f };
89constexpr float DEFAULT_EMIT_SIZE_RANGE_BEGIN { 0.0f };
90constexpr float DEFAULT_EMIT_SIZE_RANGE_END { 0.0f };
91constexpr float EMIT_SIZE_RANGE_BEGIN { 80.0f };
92constexpr float EMIT_SIZE_RANGE_END { 80.0f };
93constexpr float EMIT_VELOCITY_VALUE_RANGE_BEGIN { 50.0f };
94constexpr float EMIT_VELOCITY_VALUE_RANGE_END { 100.0f };
95constexpr float EMIT_VELOCITY_ANGLE_RANGE_BEGIN { -180.0f };
96constexpr float EMIT_VELOCITY_ANGLE_RANGE_END { 180.0f };
97constexpr float EMIT_OPACITY_RANGE_BEGIN { 0.3f };
98constexpr float EMIT_OPACITY_RANGE_END { 1.0f };
99constexpr float EMIT_SCALE_RANGE_BEGIN { 0.3f };
100constexpr float EMIT_SCALE_RANGE_END { 1.0f };
101constexpr float EMIT_SCALE_CHANGE_RANGE_BEGIN { 1.0f };
102constexpr float EMIT_SCALE_CHANGE_RANGE_END { 0.0f };
103constexpr float SCALE_CHANGE_VELOCITY_RANGE_BEGIN { -1.0f };
104constexpr float SCALE_CHANGE_VELOCITY_RANGE_END { -1.0f };
105constexpr int32_t SCALE_CHANGE_START_MILLIS { 0 };
106constexpr int32_t SCALE_CHANGE_END_MILLIS { 700 };
107constexpr float ALPHA_RANGE_BEGIN { 1.0f };
108constexpr float ALPHA_RANGE_END { 0.0f };
109constexpr float EMIT_RADIUS { 40.0f };
110constexpr float TRACK_FILTER_SCALAR { 20.0f };
111constexpr int32_t TRACK_PATH_LENGTH_400 { 400 };
112constexpr int32_t TRACK_PATH_LENGTH_500 { 500 };
113constexpr int32_t TRACK_PATH_LENGTH_900 { 900 };
114constexpr int32_t TRACK_PATH_LENGTH_1000 { 1000 };
115constexpr int32_t TRACK_PATH_LENGTH_1400 { 1400 };
116constexpr int32_t TRACK_PATH_LENGTH_1500 { 1500 };
117constexpr int32_t TRACK_PATH_LENGTH_1900 { 1900 };
118constexpr int32_t TRACK_PATH_LENGTH_2000 { 2000 };
119constexpr uint32_t TRACK_COLOR_BLUE { 0xFF1ED0EE };
120constexpr uint32_t TRACK_COLOR_BLUE_R { 0x1E };
121constexpr uint32_t TRACK_COLOR_BLUE_G { 0xD0 };
122constexpr uint32_t TRACK_COLOR_BLUE_B { 0xEE };
123constexpr uint32_t TRACK_COLOR_PINK { 0xFFFF42D2 };
124constexpr uint32_t TRACK_COLOR_PINK_R { 0xFF };
125constexpr uint32_t TRACK_COLOR_PINK_G { 0x42 };
126constexpr uint32_t TRACK_COLOR_PINK_B { 0xD2 };
127constexpr uint32_t TRACK_COLOR_ORANGE_RED { 0xFFFF7B47 };
128constexpr uint32_t TRACK_COLOR_ORANGE_RED_R { 0xFF };
129constexpr uint32_t TRACK_COLOR_ORANGE_RED_G { 0x7B };
130constexpr uint32_t TRACK_COLOR_ORANGE_RED_B { 0x47 };
131constexpr uint32_t TRACK_COLOR_YELLOW { 0xFFFFC628 };
132constexpr uint32_t TRACK_COLOR_YELLOW_R { 0xFF };
133constexpr uint32_t TRACK_COLOR_YELLOW_G { 0xC6 };
134constexpr uint32_t TRACK_COLOR_YELLOW_B { 0x28 };
135constexpr uint32_t ALPHA_ZERO { 0xFF };
136constexpr float TRACK_WIDTH_TEN { 10.0f };
137constexpr float TRACK_WIDTH_THIRTY { 30.0f };
138constexpr float COLOR_TRANSITIONS_LENGTH { 400.0f };
139constexpr int32_t PROTOCOL_DURATION { 200 };
140#endif // OHOS_BUILD_ENABLE_NEW_KNUCKLE_DYNAMIC
141} // namespace
142
143KnuckleDrawingManager::KnuckleDrawingManager()
144{
145#ifdef OHOS_BUILD_ENABLE_NEW_KNUCKLE_DYNAMIC
146    paint_.SetColor(Rosen::Drawing::Color::COLOR_WHITE);
147#else
148    paint_.SetColor(Rosen::Drawing::Color::COLOR_CYAN);
149#endif // OHOS_BUILD_ENABLE_NEW_KNUCKLE_DYNAMIC
150    paint_.SetAntiAlias(true);
151    float outerCircleTransparency = 1.0f;
152    paint_.SetAlphaF(outerCircleTransparency);
153    paint_.SetWidth(PAINT_STROKE_WIDTH);
154    paint_.SetStyle(Rosen::Drawing::Paint::PaintStyle::PAINT_STROKE);
155    paint_.SetJoinStyle(Rosen::Drawing::Pen::JoinStyle::ROUND_JOIN);
156    paint_.SetCapStyle(Rosen::Drawing::Pen::CapStyle::ROUND_CAP);
157    paint_.SetPathEffect(Rosen::Drawing::PathEffect::CreateCornerPathEffect(PAINT_PATH_RADIUS));
158    displayInfo_.x = 0;
159    displayInfo_.y = 0;
160    displayInfo_.id = 0;
161    displayInfo_.dpi = 0;
162    displayInfo_.width = 0;
163    displayInfo_.height = 0;
164    displayInfo_.direction = Direction::DIRECTION0;
165    displayInfo_.displayDirection = Direction::DIRECTION0;
166}
167
168void KnuckleDrawingManager::KnuckleDrawHandler(std::shared_ptr<PointerEvent> touchEvent)
169{
170    CALL_DEBUG_ENTER;
171    CHKPV(touchEvent);
172    if (!IsSingleKnuckle(touchEvent)) {
173        return;
174    }
175    CreateObserver();
176    int32_t touchAction = touchEvent->GetPointerAction();
177    if (IsValidAction(touchAction) && IsSingleKnuckleDoubleClick(touchEvent)) {
178        int32_t displayId = touchEvent->GetTargetDisplayId();
179        CreateTouchWindow(displayId);
180        StartTouchDraw(touchEvent);
181    }
182}
183
184bool KnuckleDrawingManager::IsSingleKnuckle(std::shared_ptr<PointerEvent> touchEvent)
185{
186    CALL_DEBUG_ENTER;
187    CHKPF(touchEvent);
188    int32_t id = touchEvent->GetPointerId();
189    PointerEvent::PointerItem item;
190    touchEvent->GetPointerItem(id, item);
191    if (item.GetToolType() != PointerEvent::TOOL_TYPE_KNUCKLE ||
192        touchEvent->GetPointerIds().size() != 1 || isRotate_) {
193        MMI_HILOGD("Touch tool type is:%{public}d", item.GetToolType());
194        if (!pointerInfos_.empty()) {
195            DestoryWindow();
196        } else if (isRotate_) {
197            isRotate_ = false;
198            if (item.GetToolType() == PointerEvent::TOOL_TYPE_KNUCKLE) {
199                return true;
200            }
201        }
202        return false;
203    }
204    MMI_HILOGD("Touch tool type is single knuckle");
205    return true;
206}
207
208bool KnuckleDrawingManager::IsSingleKnuckleDoubleClick(std::shared_ptr<PointerEvent> touchEvent)
209{
210    CALL_DEBUG_ENTER;
211    CHKPF(touchEvent);
212    int32_t touchAction = touchEvent->GetPointerAction();
213    if (touchAction == PointerEvent::POINTER_ACTION_DOWN) {
214        pointerNum_ = 0;
215        firstDownTime_ = touchEvent->GetActionTime();
216        int64_t intervalTime = touchEvent->GetActionTime() - lastUpTime_;
217        bool isTimeIntervalReady = intervalTime > 0 && intervalTime <= DOUBLE_CLICK_INTERVAL_TIME_SLOW;
218        int32_t id = touchEvent->GetPointerId();
219        PointerEvent::PointerItem pointerItem;
220        touchEvent->GetPointerItem(id, pointerItem);
221        auto displayXY = TOUCH_DRAWING_MGR->CalcDrawCoordinate(displayInfo_, pointerItem);
222        float downToPrevDownDistance = static_cast<float>(sqrt(pow(lastDownPointer_.x - displayXY.first, POW_SQUARE) +
223            pow(lastDownPointer_.y - displayXY.second, POW_SQUARE)));
224        bool isDistanceReady = downToPrevDownDistance < DOUBLE_CLICK_DISTANCE_LONG_CONFIG * POW_SQUARE;
225        if (isTimeIntervalReady && isDistanceReady) {
226            return false;
227        }
228        lastDownPointer_.x = displayXY.first;
229        lastDownPointer_.y = displayXY.second;
230    } else if (touchAction == PointerEvent::POINTER_ACTION_UP) {
231        lastUpTime_ = touchEvent->GetActionTime();
232    }
233    return true;
234}
235
236bool KnuckleDrawingManager::IsValidAction(const int32_t action)
237{
238    CALL_DEBUG_ENTER;
239    if (screenReadState_.state == SCREEN_READ_ENABLE) {
240        DestoryWindow();
241    }
242    if (action == PointerEvent::POINTER_ACTION_DOWN || action == PointerEvent::POINTER_ACTION_PULL_DOWN ||
243        (action == PointerEvent::POINTER_ACTION_MOVE && (!pointerInfos_.empty())) ||
244        (action == PointerEvent::POINTER_ACTION_PULL_MOVE && (!pointerInfos_.empty())) ||
245        action == PointerEvent::POINTER_ACTION_UP || action == PointerEvent::POINTER_ACTION_PULL_UP) {
246        return true;
247    }
248    MMI_HILOGE("Action is not down or move or up, action:%{public}d", action);
249    return false;
250}
251
252void KnuckleDrawingManager::UpdateDisplayInfo(const DisplayInfo& displayInfo)
253{
254    CALL_DEBUG_ENTER;
255    if (displayInfo_.direction != displayInfo.direction) {
256        MMI_HILOGD("DisplayInfo direction change");
257        isRotate_ = true;
258    }
259    scaleW_ = displayInfo.width > displayInfo.height ? displayInfo.width : displayInfo.height;
260    scaleH_ = displayInfo.width > displayInfo.height ? displayInfo.width : displayInfo.height;
261    displayInfo_ = displayInfo;
262}
263
264void KnuckleDrawingManager::StartTouchDraw(std::shared_ptr<PointerEvent> touchEvent)
265{
266    CALL_DEBUG_ENTER;
267    CHKPV(touchEvent);
268    int32_t ret = DrawGraphic(touchEvent);
269    if (ret != RET_OK) {
270        MMI_HILOGD("Can't get enough pointers to draw");
271        return;
272    }
273    Rosen::RSTransaction::FlushImplicitTransaction();
274}
275
276void KnuckleDrawingManager::RotationCanvasNode(
277    std::shared_ptr<Rosen::RSCanvasNode> canvasNode, const DisplayInfo& displayInfo)
278{
279    CALL_DEBUG_ENTER;
280    CHKPV(canvasNode);
281    if (displayInfo.direction == Direction::DIRECTION90) {
282        canvasNode->SetRotation(ROTATION_ANGLE_270);
283        canvasNode->SetTranslateX(0);
284    } else if (displayInfo.direction == Direction::DIRECTION270) {
285        canvasNode->SetRotation(ROTATION_ANGLE_90);
286        canvasNode->SetTranslateX(-std::fabs(displayInfo.width - displayInfo.height));
287    } else if (displayInfo.direction == Direction::DIRECTION180) {
288        canvasNode->SetRotation(ROTATION_ANGLE_180);
289        canvasNode->SetTranslateX(-std::fabs(displayInfo.width - displayInfo.height));
290    } else {
291        canvasNode->SetRotation(ROTATION_ANGLE_0);
292        canvasNode->SetTranslateX(0);
293    }
294    canvasNode->SetTranslateY(0);
295}
296
297bool KnuckleDrawingManager::CheckRotatePolicy(const DisplayInfo& displayInfo)
298{
299    CALL_DEBUG_ENTER;
300    bool isNeedRotate = false;
301    switch (ROTATE_POLICY) {
302        case WINDOW_ROTATE:
303            isNeedRotate = true;
304            break;
305        case SCREEN_ROTATE:
306            break;
307        case FOLDABLE_DEVICE: {
308            MMI_HILOGI("FOLDABLE:%{public}s", FOLDABLE.c_str());
309            if ((displayInfo.displayMode == DisplayMode::MAIN && FOLDABLE[SUBSCRIPT_ZERO] == FOLDABLE_ROTATE) ||
310                (displayInfo.displayMode == DisplayMode::FULL && FOLDABLE[SUBSCRIPT_TWO] == FOLDABLE_ROTATE)) {
311                isNeedRotate = true;
312            }
313            break;
314        }
315        default:
316            MMI_HILOGW("Unknown ROTATE_POLICY:%{public}d", ROTATE_POLICY);
317            break;
318    }
319    return isNeedRotate;
320}
321
322#ifdef OHOS_BUILD_ENABLE_NEW_KNUCKLE_DYNAMIC
323void KnuckleDrawingManager::InitParticleEmitter()
324{
325    CALL_DEBUG_ENTER;
326    Rosen::Vector2f position = {DEFAULT_PARTICLE_POSITION_X, DEFAULT_PARTICLE_POSITION_Y};
327    Rosen::Vector2f emitSize = {DEFAULT_EMIT_SIZE_RANGE_BEGIN, DEFAULT_EMIT_SIZE_RANGE_END};
328    Rosen::Range<int64_t> lifeTime = {PARTICLE_LIFE_TIME, PARTICLE_LIFE_TIME};
329    std::shared_ptr<Rosen::RSImage> image = std::make_shared<Rosen::RSImage>();
330    Rosen::EmitterConfig emitterConfig(
331        DEFAULT_EMIT_RATE, Rosen::ShapeType::CIRCLE, position, emitSize, PARTICLE_COUNT, lifeTime,
332        Rosen::ParticleType::POINTS, PARTICLE_RADIUS, image, Rosen::Vector2f());
333
334    Rosen::Range<float> velocityValue = {EMIT_VELOCITY_VALUE_RANGE_BEGIN, EMIT_VELOCITY_VALUE_RANGE_END};
335    Rosen::Range<float> velocityAngle = {EMIT_VELOCITY_ANGLE_RANGE_BEGIN, EMIT_VELOCITY_ANGLE_RANGE_END};
336    Rosen::ParticleVelocity velocity(velocityValue, velocityAngle);
337
338    std::vector<Rosen::Change<Rosen::RSColor>> valColorChangeOverLife;
339    Rosen::RSColor rsColorRangeBegin(Rosen::Drawing::Color::COLOR_WHITE);
340    Rosen::RSColor rsColorRangeEnd(Rosen::Drawing::Color::COLOR_WHITE);
341    Rosen::Range<Rosen::RSColor> colorVal = {rsColorRangeBegin, rsColorRangeEnd};
342    Rosen::ParticleColorParaType color(
343        colorVal, Rosen::DistributionType::UNIFORM, Rosen::ParticleUpdator::NONE, Rosen::Range<float>(),
344        Rosen::Range<float>(), Rosen::Range<float>(), Rosen::Range<float>(), valColorChangeOverLife);
345
346    std::vector<Rosen::Change<float>> opacityChangeOverLifes;
347    Rosen::Range<float> opacityVal = {EMIT_OPACITY_RANGE_BEGIN, EMIT_OPACITY_RANGE_END};
348    Rosen::ParticleParaType<float> opacity(
349        opacityVal, Rosen::ParticleUpdator::NONE, Rosen::Range<float>(), opacityChangeOverLifes);
350
351    Rosen::RSAnimationTimingCurve rSAnimationTimingCurve(Rosen::RSAnimationTimingCurve::LINEAR);
352    Rosen::Change<float> scaleChange
353        (EMIT_SCALE_CHANGE_RANGE_BEGIN, EMIT_SCALE_CHANGE_RANGE_END, SCALE_CHANGE_START_MILLIS, SCALE_CHANGE_END_MILLIS,
354        rSAnimationTimingCurve);
355    std::vector<Rosen::Change<float>> scaleChangeOverLifes;
356    scaleChangeOverLifes.emplace_back(scaleChange);
357    Rosen::Range<float> scaleVal = {EMIT_SCALE_RANGE_BEGIN, EMIT_SCALE_RANGE_END};
358    Rosen::Range<float> scaleChangeVelocity = {SCALE_CHANGE_VELOCITY_RANGE_BEGIN, SCALE_CHANGE_VELOCITY_RANGE_END};
359    Rosen::ParticleParaType<float> scale(
360        scaleVal, Rosen::ParticleUpdator::CURVE, scaleChangeVelocity, scaleChangeOverLifes);
361
362    Rosen::ParticleAcceleration acceleration;
363    Rosen::ParticleParaType<float> spin;
364
365    Rosen::ParticleParams params(emitterConfig, velocity, acceleration, color, opacity, scale, spin);
366    std::vector<Rosen::ParticleParams> particleParams;
367    particleParams.push_back(params);
368    brushCanvasNode_->SetParticleParams(particleParams);
369}
370
371void KnuckleDrawingManager::CreateTouchWindow(const int32_t displayId)
372{
373    CALL_DEBUG_ENTER;
374    if (surfaceNode_ != nullptr) {
375        MMI_HILOGD("surfaceNode_ is already exist");
376        return;
377    }
378    Rosen::RSSurfaceNodeConfig surfaceNodeConfig;
379    surfaceNodeConfig.SurfaceNodeName = "knuckle window";
380    Rosen::RSSurfaceNodeType surfaceNodeType = Rosen::RSSurfaceNodeType::SELF_DRAWING_WINDOW_NODE;
381    surfaceNode_ = Rosen::RSSurfaceNode::Create(surfaceNodeConfig, surfaceNodeType);
382
383    CHKPV(surfaceNode_);
384    surfaceNode_->SetSkipLayer(true);
385    surfaceNode_->SetFrameGravity(Rosen::Gravity::RESIZE_ASPECT_FILL);
386    surfaceNode_->SetPositionZ(Rosen::RSSurfaceNode::POINTER_WINDOW_POSITION_Z);
387    surfaceNode_->SetBounds(0, 0, scaleW_, scaleH_);
388    surfaceNode_->SetFrame(0, 0, scaleW_, scaleH_);
389
390#ifndef USE_ROSEN_DRAWING
391    surfaceNode_->SetBackgroundColor(SK_ColorTRANSPARENT);
392#else
393    surfaceNode_->SetBackgroundColor(Rosen::Drawing::Color::COLOR_TRANSPARENT);
394#endif // USE_ROSEN_DRAWING
395
396    screenId_ = static_cast<uint64_t>(displayId);
397    surfaceNode_->SetRotation(0);
398    CreateBrushWorkCanvasNode();
399    CreateTrackCanvasNode();
400    surfaceNode_->AddChild(trackCanvasNode_, DEFAULT_VALUE);
401    surfaceNode_->AddChild(brushCanvasNode_, DEFAULT_VALUE);
402    if (displayInfo_.displayMode == DisplayMode::MAIN) {
403        screenId_ = FOLD_SCREEN_MAIN_ID;
404    }
405    MMI_HILOGI("screenId_: %{public}" PRIu64, screenId_);
406    surfaceNode_->AttachToDisplay(screenId_);
407    if (CheckRotatePolicy(displayInfo_)) {
408        RotationCanvasNode(brushCanvasNode_, displayInfo_);
409        RotationCanvasNode(trackCanvasNode_, displayInfo_);
410    }
411    brushCanvasNode_->ResetSurface(scaleW_, scaleH_);
412    trackCanvasNode_->ResetSurface(scaleW_, scaleH_);
413    InitParticleEmitter();
414    Rosen::RSTransaction::FlushImplicitTransaction();
415}
416#else
417void KnuckleDrawingManager::CreateTouchWindow(const int32_t displayId)
418{
419    CALL_DEBUG_ENTER;
420    if (surfaceNode_ != nullptr) {
421        MMI_HILOGD("surfaceNode_ is already exist");
422        return;
423    }
424    Rosen::RSSurfaceNodeConfig surfaceNodeConfig;
425    surfaceNodeConfig.SurfaceNodeName = "knuckle window";
426    Rosen::RSSurfaceNodeType surfaceNodeType = Rosen::RSSurfaceNodeType::SELF_DRAWING_WINDOW_NODE;
427    surfaceNode_ = Rosen::RSSurfaceNode::Create(surfaceNodeConfig, surfaceNodeType);
428
429    CHKPV(surfaceNode_);
430    surfaceNode_->SetSkipLayer(true);
431    surfaceNode_->SetFrameGravity(Rosen::Gravity::RESIZE_ASPECT_FILL);
432    surfaceNode_->SetPositionZ(Rosen::RSSurfaceNode::POINTER_WINDOW_POSITION_Z);
433    surfaceNode_->SetBounds(0, 0, scaleW_, scaleH_);
434    surfaceNode_->SetFrame(0, 0, scaleW_, scaleH_);
435
436#ifndef USE_ROSEN_DRAWING
437    surfaceNode_->SetBackgroundColor(SK_ColorTRANSPARENT);
438#else
439    surfaceNode_->SetBackgroundColor(Rosen::Drawing::Color::COLOR_TRANSPARENT);
440#endif // USE_ROSEN_DRAWING
441
442    screenId_ = static_cast<uint64_t>(displayId);
443    surfaceNode_->SetRotation(0);
444    CreateCanvasNode();
445    surfaceNode_->AddChild(canvasNode_, DEFAULT_VALUE);
446    if (displayInfo_.displayMode == DisplayMode::MAIN) {
447        screenId_ = FOLD_SCREEN_MAIN_ID;
448    }
449    MMI_HILOGI("screenId_: %{public}" PRIu64, screenId_);
450    surfaceNode_->AttachToDisplay(screenId_);
451    if (CheckRotatePolicy(displayInfo_)) {
452        RotationCanvasNode(canvasNode_, displayInfo_);
453    }
454    canvasNode_->ResetSurface(scaleW_, scaleH_);
455    Rosen::RSTransaction::FlushImplicitTransaction();
456}
457#endif // OHOS_BUILD_ENABLE_NEW_KNUCKLE_DYNAMIC
458
459#ifdef OHOS_BUILD_ENABLE_NEW_KNUCKLE_DYNAMIC
460void KnuckleDrawingManager::CreateBrushWorkCanvasNode()
461{
462    brushCanvasNode_ = Rosen::RSCanvasDrawingNode::Create();
463    CHKPV(brushCanvasNode_);
464    brushCanvasNode_->SetBounds(0, 0, scaleW_, scaleH_);
465    brushCanvasNode_->SetFrame(0, 0, scaleW_, scaleH_);
466
467#ifndef USE_ROSEN_DRAWING
468    brushCanvasNode_->SetBackgroundColor(SK_ColorTRANSPARENT);
469#else
470    brushCanvasNode_->SetBackgroundColor(Rosen::Drawing::Color::COLOR_TRANSPARENT);
471#endif // USE_ROSEN_DRAWING
472    brushCanvasNode_->SetCornerRadius(1);
473    brushCanvasNode_->SetPositionZ(Rosen::RSSurfaceNode::POINTER_WINDOW_POSITION_Z);
474    brushCanvasNode_->SetRotation(0);
475    brushCanvasNode_->SetAlpha(ALPHA_RANGE_BEGIN);
476}
477
478void KnuckleDrawingManager::CreateTrackCanvasNode()
479{
480    trackCanvasNode_ = Rosen::RSCanvasDrawingNode::Create();
481    CHKPV(trackCanvasNode_);
482    trackCanvasNode_->SetBounds(0, 0, scaleW_, scaleH_);
483    trackCanvasNode_->SetFrame(0, 0, scaleW_, scaleH_);
484
485#ifndef USE_ROSEN_DRAWING
486    trackCanvasNode_->SetBackgroundColor(SK_ColorTRANSPARENT);
487#else
488    trackCanvasNode_->SetBackgroundColor(Rosen::Drawing::Color::COLOR_TRANSPARENT);
489#endif // USE_ROSEN_DRAWING
490    trackCanvasNode_->SetCornerRadius(1);
491    trackCanvasNode_->SetPositionZ(Rosen::RSSurfaceNode::POINTER_WINDOW_POSITION_Z);
492    trackCanvasNode_->SetRotation(0);
493    trackCanvasNode_->SetAlpha(ALPHA_RANGE_BEGIN);
494}
495#else
496void KnuckleDrawingManager::CreateCanvasNode()
497{
498    canvasNode_ = Rosen::RSCanvasDrawingNode::Create();
499    CHKPV(canvasNode_);
500    canvasNode_->SetBounds(0, 0, scaleW_, scaleH_);
501    canvasNode_->SetFrame(0, 0, scaleW_, scaleH_);
502
503#ifndef USE_ROSEN_DRAWING
504    canvasNode_->SetBackgroundColor(SK_ColorTRANSPARENT);
505#else
506    canvasNode_->SetBackgroundColor(Rosen::Drawing::Color::COLOR_TRANSPARENT);
507#endif // USE_ROSEN_DRAWING
508    canvasNode_->SetCornerRadius(1);
509    canvasNode_->SetPositionZ(Rosen::RSSurfaceNode::POINTER_WINDOW_POSITION_Z);
510    canvasNode_->SetRotation(0);
511}
512#endif // OHOS_BUILD_ENABLE_NEW_KNUCKLE_DYNAMIC
513
514int32_t KnuckleDrawingManager::GetPointerPos(std::shared_ptr<PointerEvent> touchEvent)
515{
516    CHKPR(touchEvent, RET_ERR);
517    if (touchEvent->GetPointerAction() == PointerEvent::POINTER_ACTION_UP) {
518        isActionUp_ = true;
519        return RET_OK;
520    }
521    PointerInfo pointerInfo;
522    int32_t pointerId = touchEvent->GetPointerId();
523    PointerEvent::PointerItem pointerItem;
524    if (!touchEvent->GetPointerItem(pointerId, pointerItem)) {
525        MMI_HILOGE("Can't find pointer item, pointer:%{public}d", pointerId);
526        return RET_ERR;
527    }
528    auto displayXY = TOUCH_DRAWING_MGR->CalcDrawCoordinate(displayInfo_, pointerItem);
529    pointerInfo.x = displayXY.first;
530    pointerInfo.y = displayXY.second;
531    pointerInfos_.push_back(pointerInfo);
532    pointerNum_++;
533
534    if (pointerInfos_.size() == MAX_POINTER_NUM) {
535        pointerInfos_[POINT_INDEX3].x = (pointerInfos_[POINT_INDEX2].x + pointerInfos_[POINT_INDEX4].x) / MID_POINT;
536        pointerInfos_[POINT_INDEX3].y = (pointerInfos_[POINT_INDEX2].y + pointerInfos_[POINT_INDEX4].y) / MID_POINT;
537    } else {
538        MMI_HILOGD("Can't get enough pointers to draw");
539        return RET_ERR;
540    }
541    return RET_OK;
542}
543
544#ifdef OHOS_BUILD_ENABLE_NEW_KNUCKLE_DYNAMIC
545void KnuckleDrawingManager::UpdateEmitter()
546{
547    CALL_DEBUG_ENTER;
548    CHKPV(brushCanvasNode_);
549    std::optional<Rosen::Vector2f> position = std::nullopt;
550    position = {pointerInfos_[POINT_INDEX1].x - EMIT_RADIUS, pointerInfos_[POINT_INDEX1].y - EMIT_RADIUS};
551    std::optional<Rosen::Vector2f> emitSize = std::nullopt;
552    emitSize = {EMIT_SIZE_RANGE_BEGIN, EMIT_SIZE_RANGE_END};
553    std::optional<int32_t> emitRate = std::nullopt;
554    emitRate = EMIT_RATE;
555    auto updater = std::make_shared<Rosen::EmitterUpdater>(
556        0, position, emitSize, emitRate);
557    std::vector<std::shared_ptr<Rosen::EmitterUpdater>> paras;
558    paras.push_back(updater);
559    brushCanvasNode_->SetEmitterUpdater(paras);
560}
561
562uint32_t KnuckleDrawingManager::GetDeltaColor(uint32_t deltaSource, uint32_t deltaTarget)
563{
564    CALL_DEBUG_ENTER;
565    if (deltaTarget > deltaSource) {
566        MMI_HILOGE("Invalid deltaSource or deltaTarget");
567        return 0;
568    } else {
569        return deltaSource - deltaTarget;
570    }
571}
572
573uint32_t KnuckleDrawingManager::DrawTrackColorBlue(int32_t pathValue)
574{
575    CALL_DEBUG_ENTER;
576    if (((static_cast<int32_t>(pathLength_) / TRACK_PATH_LENGTH_2000) != 0) &&
577        (pathValue < TRACK_PATH_LENGTH_400)) {
578        uint32_t deltaR = GetDeltaColor(TRACK_COLOR_YELLOW_R, TRACK_COLOR_BLUE_R);
579        uint32_t deltaG = GetDeltaColor(TRACK_COLOR_BLUE_G, TRACK_COLOR_YELLOW_G);
580        uint32_t deltaB = GetDeltaColor(TRACK_COLOR_BLUE_B, TRACK_COLOR_YELLOW_B);
581        float pathLength = path_.GetLength(false);
582        trackColorR_ -= deltaR * pathLength / COLOR_TRANSITIONS_LENGTH;
583        trackColorG_ += deltaG * pathLength / COLOR_TRANSITIONS_LENGTH;
584        trackColorB_ += deltaB * pathLength / COLOR_TRANSITIONS_LENGTH;
585        uint32_t colorQuad = Rosen::Drawing::Color::ColorQuadSetARGB(
586            ALPHA_ZERO, trackColorR_, trackColorG_, trackColorB_);
587        return colorQuad;
588    } else {
589        trackColorR_ = TRACK_COLOR_BLUE_R;
590        trackColorG_ = TRACK_COLOR_BLUE_G;
591        trackColorB_ = TRACK_COLOR_BLUE_B;
592        return TRACK_COLOR_BLUE;
593    }
594}
595
596uint32_t KnuckleDrawingManager::DrawTrackColorPink(int32_t pathValue)
597{
598    CALL_DEBUG_ENTER;
599    if (pathValue < TRACK_PATH_LENGTH_900) {
600        uint32_t deltaR = GetDeltaColor(TRACK_COLOR_PINK_R, TRACK_COLOR_BLUE_R);
601        uint32_t deltaG = GetDeltaColor(TRACK_COLOR_BLUE_G, TRACK_COLOR_PINK_G);
602        uint32_t deltaB = GetDeltaColor(TRACK_COLOR_BLUE_B, TRACK_COLOR_PINK_B);
603        float pathLength = path_.GetLength(false);
604        trackColorR_ += deltaR * pathLength / COLOR_TRANSITIONS_LENGTH;
605        trackColorG_ -= deltaG * pathLength / COLOR_TRANSITIONS_LENGTH;
606        trackColorB_ -= deltaB * pathLength / COLOR_TRANSITIONS_LENGTH;
607        uint32_t colorQuad = Rosen::Drawing::Color::ColorQuadSetARGB(
608            ALPHA_ZERO, trackColorR_, trackColorG_, trackColorB_);
609        return colorQuad;
610    } else {
611        trackColorR_ = TRACK_COLOR_PINK_R;
612        trackColorG_ = TRACK_COLOR_PINK_G;
613        trackColorB_ = TRACK_COLOR_PINK_B;
614        return TRACK_COLOR_PINK;
615    }
616}
617
618uint32_t KnuckleDrawingManager::DrawTrackColorOrangeRed(int32_t pathValue)
619{
620    CALL_DEBUG_ENTER;
621    if (pathValue < TRACK_PATH_LENGTH_1400) {
622        uint32_t deltaR = GetDeltaColor(TRACK_COLOR_ORANGE_RED_R, TRACK_COLOR_PINK_R);
623        uint32_t deltaG = GetDeltaColor(TRACK_COLOR_ORANGE_RED_G, TRACK_COLOR_PINK_G);
624        uint32_t deltaB = GetDeltaColor(TRACK_COLOR_PINK_B, TRACK_COLOR_ORANGE_RED_B);
625        float pathLength = path_.GetLength(false);
626        trackColorR_ += deltaR * pathLength / COLOR_TRANSITIONS_LENGTH;
627        trackColorG_ += deltaG * pathLength / COLOR_TRANSITIONS_LENGTH;
628        trackColorB_ -= deltaB * pathLength / COLOR_TRANSITIONS_LENGTH;
629        uint32_t colorQuad = Rosen::Drawing::Color::ColorQuadSetARGB(
630            ALPHA_ZERO, trackColorR_, trackColorG_, trackColorB_);
631        return colorQuad;
632    } else {
633        trackColorR_ = TRACK_COLOR_ORANGE_RED_R;
634        trackColorG_ = TRACK_COLOR_ORANGE_RED_G;
635        trackColorB_ = TRACK_COLOR_ORANGE_RED_B;
636        return TRACK_COLOR_ORANGE_RED;
637    }
638}
639
640uint32_t KnuckleDrawingManager::DrawTrackColorYellow(int32_t pathValue)
641{
642    CALL_DEBUG_ENTER;
643    if (pathValue < TRACK_PATH_LENGTH_1900) {
644        uint32_t deltaR = GetDeltaColor(TRACK_COLOR_YELLOW_R, TRACK_COLOR_ORANGE_RED_R);
645        uint32_t deltaG = GetDeltaColor(TRACK_COLOR_YELLOW_G, TRACK_COLOR_ORANGE_RED_G);
646        uint32_t deltaB = GetDeltaColor(TRACK_COLOR_ORANGE_RED_B, TRACK_COLOR_YELLOW_B);
647        float pathLength = path_.GetLength(false);
648        trackColorR_ += deltaR * pathLength / COLOR_TRANSITIONS_LENGTH;
649        trackColorG_ += deltaG * pathLength / COLOR_TRANSITIONS_LENGTH;
650        trackColorB_ -= deltaB * pathLength / COLOR_TRANSITIONS_LENGTH;
651        uint32_t colorQuad = Rosen::Drawing::Color::ColorQuadSetARGB(
652            ALPHA_ZERO, trackColorR_, trackColorG_, trackColorB_);
653        return colorQuad;
654    } else {
655        trackColorR_ = TRACK_COLOR_YELLOW_R;
656        trackColorG_ = TRACK_COLOR_YELLOW_G;
657        trackColorB_ = TRACK_COLOR_YELLOW_B;
658        return TRACK_COLOR_YELLOW;
659    }
660}
661
662void KnuckleDrawingManager::DrawTrackCanvas()
663{
664    CALL_DEBUG_ENTER;
665    CHKPV(trackCanvasNode_);
666#ifndef USE_ROSEN_DRAWING
667    auto trackCanvas = static_cast<Rosen::RSRecordingCanvas *>(trackCanvasNode_->
668        BeginRecording(scaleW_, scaleH_));
669#else
670    auto trackCanvas = static_cast<Rosen::Drawing::RecordingCanvas *>(trackCanvasNode_->
671        BeginRecording(scaleW_, scaleH_));
672#endif // USE_ROSEN_DRAWING
673    CHKPV(trackCanvas);
674    pathLength_ += path_.GetLength(false);
675    int32_t pathValue = static_cast<int32_t>(pathLength_) % TRACK_PATH_LENGTH_2000;
676    Rosen::Drawing::Pen pen;
677
678    if (pathValue < TRACK_PATH_LENGTH_500) {
679        pen.SetColor(DrawTrackColorBlue(pathValue));
680    } else if (pathValue < TRACK_PATH_LENGTH_1000) {
681        pen.SetColor(DrawTrackColorPink(pathValue));
682    } else if (pathValue < TRACK_PATH_LENGTH_1500) {
683        pen.SetColor(DrawTrackColorOrangeRed(pathValue));
684    } else {
685        pen.SetColor(DrawTrackColorYellow(pathValue));
686    }
687    pen.SetWidth(PAINT_STROKE_WIDTH);
688    Rosen::Drawing::Filter filter;
689    filter.SetMaskFilter(
690        Rosen::Drawing::MaskFilter::CreateBlurMaskFilter(Rosen::Drawing::BlurType::OUTER, TRACK_FILTER_SCALAR));
691    pen.SetFilter(filter);
692    trackCanvas->AttachPen(pen);
693    trackCanvas->DrawPath(path_);
694    trackCanvas->DetachPen();
695
696    trackCanvas->AttachPaint(paint_);
697    trackCanvas->DrawPath(path_);
698    trackCanvas->DetachPaint();
699    trackCanvasNode_->FinishRecording();
700}
701
702void KnuckleDrawingManager::DrawBrushCanvas()
703{
704    if (pathInfos_.size() >= PATH_SIZE_EIGHT) {
705        brushPathLength_ += path_.GetLength(false);
706        float pathLength = pathInfos_[0].GetLength(false);
707        if (((brushPathLength_ - pathLength) > MAX_PATH_LENGTH) || (pathInfos_.size() >= MAX_PATH_SIZE)) {
708            pathInfos_.erase(pathInfos_.begin());
709            brushPathLength_ -= pathLength;
710        }
711        pathInfos_.emplace_back(path_);
712        CHKPV(brushCanvasNode_);
713        brushCanvasNode_->ResetSurface(scaleW_, scaleH_);
714
715#ifndef USE_ROSEN_DRAWING
716        auto canvas = static_cast<Rosen::RSRecordingCanvas *>(brushCanvasNode_->
717            BeginRecording(scaleW_, scaleH_));
718#else
719        auto canvas = static_cast<Rosen::Drawing::RecordingCanvas *>(brushCanvasNode_->
720            BeginRecording(scaleW_, scaleH_));
721#endif // USE_ROSEN_DRAWING
722        CHKPV(canvas);
723        for (size_t i = 0; (i < pathInfos_.size()) && (pathInfos_.size() != 1); ++i) {
724            Rosen::Drawing::Paint paint;
725            paint.SetAntiAlias(true);
726            paint.SetStyle(Rosen::Drawing::Paint::PaintStyle::PAINT_STROKE);
727            paint.SetJoinStyle(Rosen::Drawing::Pen::JoinStyle::ROUND_JOIN);
728            paint.SetCapStyle(Rosen::Drawing::Pen::CapStyle::ROUND_CAP);
729
730            paint.SetWidth(TRACK_WIDTH_THIRTY / (pathInfos_.size() - 1) * i + TRACK_WIDTH_TEN);
731            paint.SetColor(Rosen::Drawing::Color::COLOR_WHITE);
732            canvas->AttachPaint(paint);
733            canvas->DrawPath(pathInfos_[i]);
734            canvas->DetachPaint();
735        }
736        brushCanvasNode_->FinishRecording();
737    } else {
738        pathInfos_.emplace_back(path_);
739        brushPathLength_ += path_.GetLength(false);
740    }
741}
742
743void KnuckleDrawingManager::ActionUpAnimation()
744{
745    CALL_DEBUG_ENTER;
746    CHKPV(trackCanvasNode_);
747    Rosen::RSAnimationTimingProtocol protocol;
748    protocol.SetDuration(PROTOCOL_DURATION);
749    protocol.SetRepeatCount(1);
750    auto animate = Rosen::RSNode::Animate(
751        protocol,
752        Rosen::RSAnimationTimingCurve::LINEAR,
753        [this]() {
754            trackCanvasNode_->SetAlpha(ALPHA_RANGE_END);
755        });
756    Rosen::RSTransaction::FlushImplicitTransaction();
757}
758
759int32_t KnuckleDrawingManager::DrawGraphic(std::shared_ptr<PointerEvent> touchEvent)
760{
761    CALL_DEBUG_ENTER;
762    CHKPR(touchEvent, RET_ERR);
763    if (GetPointerPos(touchEvent) != RET_OK) {
764        MMI_HILOGD("GetPointerPos failed");
765        return RET_ERR;
766    }
767    if (!isActionUp_) {
768        UpdateEmitter();
769        path_.MoveTo(pointerInfos_[POINT_INDEX0].x, pointerInfos_[POINT_INDEX0].y);
770        path_.CubicTo(pointerInfos_[POINT_INDEX1].x, pointerInfos_[POINT_INDEX1].y,
771            pointerInfos_[POINT_INDEX2].x, pointerInfos_[POINT_INDEX2].y,
772            pointerInfos_[POINT_INDEX3].x, pointerInfos_[POINT_INDEX3].y);
773        pointerInfos_.erase(pointerInfos_.begin(), pointerInfos_.begin() + POINT_INDEX3);
774        if (pointerNum_ < POINTER_NUMBER_TO_DRAW) {
775            MMI_HILOGE("Pointer number not enough to draw");
776            return RET_ERR;
777        }
778        DrawTrackCanvas();
779        DrawBrushCanvas();
780    } else {
781        MMI_HILOGE("The isActionUp_ is true");
782        isActionUp_ = false;
783        pathInfos_.clear();
784        pathLength_ = 0.0f;
785        brushPathLength_ = 0.0f;
786        trackColorR_ = 0x00;
787        trackColorG_ = 0x00;
788        trackColorB_ = 0x00;
789        if (ClearBrushCanvas() != RET_OK) {
790            MMI_HILOGE("ClearBrushCanvas failed");
791            return RET_ERR;
792        }
793        ActionUpAnimation();
794        int32_t repeatTime = 1;
795        int32_t timerId = TimerMgr->AddTimer(PROTOCOL_DURATION, repeatTime, [this]() {
796            DestoryWindow();
797        });
798        if (timerId < 0) {
799            MMI_HILOGE("Add timer failed, timerId:%{public}d", timerId);
800            DestoryWindow();
801        }
802        return RET_OK;
803    }
804    path_.Reset();
805    return RET_OK;
806}
807#else
808int32_t KnuckleDrawingManager::DrawGraphic(std::shared_ptr<PointerEvent> touchEvent)
809{
810    CALL_DEBUG_ENTER;
811    CHKPR(touchEvent, RET_ERR);
812    CHKPR(canvasNode_, RET_ERR);
813    if (GetPointerPos(touchEvent) != RET_OK) {
814        MMI_HILOGD("GetPointerPos failed");
815        return RET_ERR;
816    }
817    if (!isActionUp_) {
818        path_.MoveTo(pointerInfos_[POINT_INDEX0].x, pointerInfos_[POINT_INDEX0].y);
819        path_.CubicTo(pointerInfos_[POINT_INDEX1].x, pointerInfos_[POINT_INDEX1].y,
820            pointerInfos_[POINT_INDEX2].x, pointerInfos_[POINT_INDEX2].y,
821            pointerInfos_[POINT_INDEX3].x, pointerInfos_[POINT_INDEX3].y);
822        pointerInfos_.erase(pointerInfos_.begin(), pointerInfos_.begin() + POINT_INDEX3);
823        if (pointerNum_ < POINTER_NUMBER_TO_DRAW) {
824            return RET_ERR;
825        }
826#ifndef USE_ROSEN_DRAWING
827        auto canvas = static_cast<Rosen::RSRecordingCanvas *>(canvasNode_->
828            BeginRecording(scaleW_, scaleH_));
829#else
830        auto canvas = static_cast<Rosen::Drawing::RecordingCanvas *>(canvasNode_->
831            BeginRecording(scaleW_, scaleH_));
832#endif // USE_ROSEN_DRAWING
833        CHKPR(canvas, RET_ERR);
834        canvas->AttachPaint(paint_);
835        canvas->DrawPath(path_);
836        canvas->DetachPaint();
837    } else {
838        MMI_HILOGD("isActionUp_ is true");
839        isActionUp_ = false;
840        return DestoryWindow();
841    }
842    path_.Reset();
843    canvasNode_->FinishRecording();
844    return RET_OK;
845}
846#endif // OHOS_BUILD_ENABLE_NEW_KNUCKLE_DYNAMIC
847
848#ifdef OHOS_BUILD_ENABLE_NEW_KNUCKLE_DYNAMIC
849int32_t KnuckleDrawingManager::ClearTrackCanvas()
850{
851    CALL_DEBUG_ENTER;
852    CHKPR(trackCanvasNode_, RET_ERR);
853#ifndef USE_ROSEN_DRAWING
854    auto trackCanvas = static_cast<Rosen::RSRecordingCanvas *>(trackCanvasNode_->
855        BeginRecording(scaleW_, scaleH_));
856#else
857    auto trackCanvas = static_cast<Rosen::Drawing::RecordingCanvas *>(trackCanvasNode_->
858        BeginRecording(scaleW_, scaleH_));
859#endif // USE_ROSEN_DRAWING
860    CHKPR(trackCanvas, RET_ERR);
861    trackCanvas->Clear();
862    trackCanvasNode_->FinishRecording();
863    CHKPR(surfaceNode_, RET_ERR);
864    surfaceNode_->RemoveChild(trackCanvasNode_);
865    trackCanvasNode_->ResetSurface(scaleW_, scaleH_);
866    trackCanvasNode_.reset();
867    return RET_OK;
868}
869
870int32_t KnuckleDrawingManager::ClearBrushCanvas()
871{
872    CALL_DEBUG_ENTER;
873    CHKPR(brushCanvasNode_, RET_ERR);
874#ifndef USE_ROSEN_DRAWING
875    auto brushCanvas = static_cast<Rosen::RSRecordingCanvas *>(brushCanvasNode_->
876        BeginRecording(scaleW_, scaleH_));
877#else
878    auto brushCanvas = static_cast<Rosen::Drawing::RecordingCanvas *>(brushCanvasNode_->
879        BeginRecording(scaleW_, scaleH_));
880#endif // USE_ROSEN_DRAWING
881    CHKPR(brushCanvas, RET_ERR);
882    brushCanvas->Clear();
883    brushCanvasNode_->FinishRecording();
884    CHKPR(surfaceNode_, RET_ERR);
885    surfaceNode_->RemoveChild(brushCanvasNode_);
886    brushCanvasNode_->ResetSurface(scaleW_, scaleH_);
887    brushCanvasNode_.reset();
888    return RET_OK;
889}
890#endif // OHOS_BUILD_ENABLE_NEW_KNUCKLE_DYNAMIC
891
892#ifdef OHOS_BUILD_ENABLE_NEW_KNUCKLE_DYNAMIC
893int32_t KnuckleDrawingManager::DestoryWindow()
894{
895    CALL_DEBUG_ENTER;
896    pointerInfos_.clear();
897    path_.Reset();
898    ClearBrushCanvas();
899    if (ClearTrackCanvas() != RET_OK) {
900        MMI_HILOGE("ClearTrackCanvas failed");
901        return RET_ERR;
902    }
903    CHKPR(surfaceNode_, RET_ERR);
904    surfaceNode_->DetachToDisplay(screenId_);
905    surfaceNode_.reset();
906    Rosen::RSTransaction::FlushImplicitTransaction();
907    return RET_OK;
908}
909#else
910int32_t KnuckleDrawingManager::DestoryWindow()
911{
912    CALL_DEBUG_ENTER;
913    pointerInfos_.clear();
914    path_.Reset();
915    CHKPR(canvasNode_, RET_ERR);
916#ifndef USE_ROSEN_DRAWING
917    auto canvas = static_cast<Rosen::RSRecordingCanvas *>(canvasNode_->
918        BeginRecording(scaleW_, scaleH_));
919#else
920    auto canvas = static_cast<Rosen::Drawing::RecordingCanvas *>(canvasNode_->
921        BeginRecording(scaleW_, scaleH_));
922#endif // USE_ROSEN_DRAWING
923    CHKPR(canvas, RET_ERR);
924    canvas->Clear();
925    canvasNode_->FinishRecording();
926    CHKPR(surfaceNode_, RET_ERR);
927    surfaceNode_->DetachToDisplay(screenId_);
928    surfaceNode_->RemoveChild(canvasNode_);
929    canvasNode_->ResetSurface(scaleW_, scaleH_);
930    canvasNode_.reset();
931    surfaceNode_.reset();
932    Rosen::RSTransaction::FlushImplicitTransaction();
933    return RET_OK;
934}
935#endif // OHOS_BUILD_ENABLE_NEW_KNUCKLE_DYNAMIC
936
937void KnuckleDrawingManager::CreateObserver()
938{
939    CALL_DEBUG_ENTER;
940    if (!hasScreenReadObserver_) {
941        screenReadState_.switchName = SCREEN_READING;
942        CreateScreenReadObserver(screenReadState_);
943    }
944    MMI_HILOGD("screenReadState_.state: %{public}s", screenReadState_.state.c_str());
945}
946
947template <class T>
948void KnuckleDrawingManager::CreateScreenReadObserver(T &item)
949{
950    CALL_DEBUG_ENTER;
951    SettingObserver::UpdateFunc updateFunc = [&item](const std::string& key) {
952        auto ret = SettingDataShare::GetInstance(MULTIMODAL_INPUT_SERVICE_ID)
953            .GetStringValue(key, item.state);
954        if (ret != RET_OK) {
955            MMI_HILOGE("Get value from setting date fail");
956            return;
957        }
958        MMI_HILOGI("key: %{public}s, state: %{public}s", key.c_str(), item.state.c_str());
959    };
960    sptr<SettingObserver> statusObserver = SettingDataShare::GetInstance(MULTIMODAL_INPUT_SERVICE_ID)
961        .CreateObserver(item.switchName, updateFunc);
962    ErrCode ret = SettingDataShare::GetInstance(MULTIMODAL_INPUT_SERVICE_ID).
963        RegisterObserver(statusObserver);
964    if (ret != ERR_OK) {
965        MMI_HILOGE("Register setting observer failed, ret=%{public}d", ret);
966        statusObserver = nullptr;
967        return;
968    }
969    hasScreenReadObserver_ = true;
970}
971
972std::string KnuckleDrawingManager::GetScreenReadState()
973{
974    return screenReadState_.state;
975}
976} // namespace MMI
977} // namespace OHOS