From 368bc1659f64c83fb074b2885eec64d02661d3ab Mon Sep 17 00:00:00 2001 From: yxc3 Date: Fri, 25 Jul 2025 10:38:20 +0800 Subject: [PATCH] add fill mode interface Signed-off-by: yxc3 --- .../avscreen_capture_napi.cpp | 26 +++---- .../avscreen_capture/avscreen_capture_napi.h | 2 +- .../screencapture/native_avscreen_capture.cpp | 13 ++++ interfaces/inner_api/native/screen_capture.h | 4 +- interfaces/kits/c/native_avscreen_capture.h | 12 ++++ .../kits/c/native_avscreen_capture_base.h | 18 +++++ .../ipc/screen_capture_service_proxy.cpp | 19 ++--- .../ipc/screen_capture_service_stub.cpp | 18 ++--- .../server/screen_capture_server.cpp | 18 ++--- test/unittest/resources/ohos_test.xml | 4 ++ .../capi/include/screen_capture_capi_mock.h | 1 + .../capi/src/screen_capture_capi_mock.cpp | 8 ++- .../include/screen_capture_native_mock.h | 1 + .../native/src/screen_capture_native_mock.cpp | 6 ++ .../screen_capture_test/screen_capture_mock.h | 1 + .../src/screen_capture_unit_test_strategy.cpp | 72 +++++++++++++++++++ 16 files changed, 180 insertions(+), 43 deletions(-) diff --git a/frameworks/js/avscreen_capture/avscreen_capture_napi.cpp b/frameworks/js/avscreen_capture/avscreen_capture_napi.cpp index 83763a287..68f7fa429 100644 --- a/frameworks/js/avscreen_capture/avscreen_capture_napi.cpp +++ b/frameworks/js/avscreen_capture/avscreen_capture_napi.cpp @@ -115,7 +115,7 @@ napi_value AVScreenCaptureNapi::Constructor(napi_env env, napi_callback_info inf MEDIA_LOGE("failed to CreateScreenCaptureCb"); return result; } - + (void)jsScreenCapture->screenCapture_->SetScreenCaptureCallback(jsScreenCapture->screenCaptureCb_); status = napi_wrap(env, jsThis, reinterpret_cast(jsScreenCapture), @@ -189,7 +189,7 @@ RetInfo GetReturnInfo(int32_t errCode, const std::string &operate, const std::st MEDIA_LOGE("failed to %{public}s, param %{public}s, errCode = %{public}d", operate.c_str(), param.c_str(), errCode); MediaServiceExtErrCodeAPI9 err = MSErrorToExtErrorAPI9(static_cast(errCode)); - + std::string message; if (err == MSERR_EXT_API9_INVALID_PARAMETER) { message = MSExtErrorAPI9ToString(err, param, "") + add; @@ -828,8 +828,8 @@ int32_t AVScreenCaptureNapi::GetVideoCaptureInfo(std::unique_ptrAVScreenCaptureSignError( ret, "getScreenCaptureFillMode", "screenCaptureFillMode"), ret)); - videoConfig.screenCaptureFillMode = GetScreenCaptureFillMode(fillMode); - MEDIA_LOGI("input screenCaptureFillMode %{public}d", videoConfig.screenCaptureFillMode); + SetScreenCaptureFillMode(asyncCtx->config_.strategy, fillMode); + MEDIA_LOGI("input screenCaptureFillMode %{public}d", asyncCtx->config_.strategy.fillMode); return MSERR_OK; } @@ -979,21 +979,23 @@ VideoCodecFormat AVScreenCaptureNapi::GetVideoCodecFormat(const int32_t &preset) return codecFormat; } -AVScreenCaptureFillMode AVScreenCaptureNapi::GetScreenCaptureFillMode(const int32_t &fillMode) +int32_t AVScreenCaptureNapi::SetScreenCaptureFillMode(ScreenCaptureStrategy &strategy, const int32_t &fillMode) { - MEDIA_LOGI("AVScreenCaptureNapi::GetScreenCaptureFillMode in!"); + MEDIA_LOGI("AVScreenCaptureNapi::SetScreenCaptureFillMode in!"); const std::map intToFillMode = { { 0, AVScreenCaptureFillMode::PRESERVE_ASPECT_RATIO }, { 1, AVScreenCaptureFillMode::SCALE_TO_FILL } }; - AVScreenCaptureFillMode screenCaptureFillMode = AVScreenCaptureFillMode::PRESERVE_ASPECT_RATIO; auto iter = intToFillMode.find(fillMode); + int32_t ret = MSERR_INVALID_VAL; if (iter != intToFillMode.end()) { - screenCaptureFillMode = iter->second; + strategy.fillMode = iter->second; + strategy.setByUser = true; + ret = MSERR_OK; } - MEDIA_LOGI("AVScreenCaptureNapi::GetScreenCaptureFillMode succeed, screenCaptureFillMode: %{public}d", - screenCaptureFillMode); - return screenCaptureFillMode; + MEDIA_LOGI("AVScreenCaptureNapi::SetScreenCaptureFillMode succeed, screenCaptureFillMode: %{public}d", + static_cast(strategy.fillMode)); + return ret; } void AVScreenCaptureNapi::ErrorCallback(int32_t errCode, const std::string &operate, const std::string &add) @@ -1052,7 +1054,7 @@ std::shared_ptr> AVScreenCaptureNapi::GetPromiseTask( auto memberFunc = itFunc->second; CHECK_AND_RETURN_RET_LOG(memberFunc != nullptr, ret, "memberFunc is nullptr!"); ret = (napi->*memberFunc)(); - + MEDIA_LOGI("%{public}s End", option.c_str()); return ret; }); diff --git a/frameworks/js/avscreen_capture/avscreen_capture_napi.h b/frameworks/js/avscreen_capture/avscreen_capture_napi.h index 166e4c529..96b964a62 100644 --- a/frameworks/js/avscreen_capture/avscreen_capture_napi.h +++ b/frameworks/js/avscreen_capture/avscreen_capture_napi.h @@ -140,7 +140,7 @@ private: static int32_t CheckAudioSampleRate(const int32_t &audioSampleRate); static int32_t CheckAudioChannelCount(const int32_t &audioChannelCount); static napi_status GetWindowIDsVectorParams(std::vector &windowIDsVec, napi_env env, napi_value* args); - static AVScreenCaptureFillMode GetScreenCaptureFillMode(const int32_t &fillMode); + static int32_t SetScreenCaptureFillMode(ScreenCaptureStrategy &strategy, const int32_t &fillMode); static napi_value ThrowCustomError(napi_env env, int32_t errorCode, const char* errorMessage); AVScreenCaptureNapi(); diff --git a/frameworks/native/capi/screencapture/native_avscreen_capture.cpp b/frameworks/native/capi/screencapture/native_avscreen_capture.cpp index 9b6385f5f..9b955f712 100644 --- a/frameworks/native/capi/screencapture/native_avscreen_capture.cpp +++ b/frameworks/native/capi/screencapture/native_avscreen_capture.cpp @@ -1371,4 +1371,17 @@ OH_AVSCREEN_CAPTURE_ErrCode OH_AVScreenCapture_StrategyForPickerPopUp( : AVScreenCapturePickerPopUp::SCREEN_CAPTURE_PICKER_POPUP_DISABLE; MEDIA_LOGD("OH_AVScreenCapture_StrategyForPickerPopUp E"); return AV_SCREEN_CAPTURE_ERR_OK; +} + +OH_AVSCREEN_CAPTURE_ErrCode OH_AVScreenCapture_StrategyForFillMode( + OH_AVScreenCapture_CaptureStrategy *strategy, OH_AVScreenCapture_FillMode mode) +{ + CHECK_AND_RETURN_RET_LOG(strategy != nullptr, AV_SCREEN_CAPTURE_ERR_INVALID_VAL, "input strategy is nullptr"); + CHECK_AND_RETURN_RET_LOG(mode == OH_AVScreenCapture_FillMode::OH_SCREENCAPTURE_FILLMODE_ASPECT_SCALE_FIT || + mode == OH_AVScreenCapture_FillMode::OH_SCREENCAPTURE_FILLMODE_SCALE_TO_FILL, + AV_SCREEN_CAPTURE_ERR_INVALID_VAL, "input mode is invalid"); + struct ScreenCaptureStrategyObject *strategyObj = reinterpret_cast(strategy); + CHECK_AND_RETURN_RET_LOG(strategyObj != nullptr, AV_SCREEN_CAPTURE_ERR_INVALID_VAL, "strategyObj is nullptr"); + strategyObj->strategy.fillMode = static_cast(mode); + return AV_SCREEN_CAPTURE_ERR_OK; } \ No newline at end of file diff --git a/interfaces/inner_api/native/screen_capture.h b/interfaces/inner_api/native/screen_capture.h index b1dd168e6..539f25a6c 100644 --- a/interfaces/inner_api/native/screen_capture.h +++ b/interfaces/inner_api/native/screen_capture.h @@ -149,7 +149,7 @@ enum AVScreenCaptureParamValidationState : int32_t { VALIDATION_INVALID, }; -enum AVScreenCaptureFillMode { +enum AVScreenCaptureFillMode : int32_t { PRESERVE_ASPECT_RATIO = 0, SCALE_TO_FILL = 1, }; @@ -192,6 +192,7 @@ struct ScreenCaptureStrategy { bool enableBFrame = false; bool setByUser = false; AVScreenCapturePickerPopUp pickerPopUp = AVScreenCapturePickerPopUp::SCREEN_CAPTURE_PICKER_POPUP_DEFAULT; + AVScreenCaptureFillMode fillMode = AVScreenCaptureFillMode::PRESERVE_ASPECT_RATIO; }; struct VideoCaptureInfo { @@ -201,7 +202,6 @@ struct VideoCaptureInfo { int32_t videoFrameHeight = 0; VideoSourceType videoSource = VideoSourceType::VIDEO_SOURCE_BUTT; AVScreenCaptureParamValidationState state = AVScreenCaptureParamValidationState::VALIDATION_IGNORE; - AVScreenCaptureFillMode screenCaptureFillMode = AVScreenCaptureFillMode::PRESERVE_ASPECT_RATIO; }; struct VideoEncInfo { diff --git a/interfaces/kits/c/native_avscreen_capture.h b/interfaces/kits/c/native_avscreen_capture.h index 30e1c2c0d..0de2e42a5 100644 --- a/interfaces/kits/c/native_avscreen_capture.h +++ b/interfaces/kits/c/native_avscreen_capture.h @@ -582,6 +582,18 @@ OH_AVSCREEN_CAPTURE_ErrCode OH_AVScreenCapture_StrategyForBFramesEncoding( */ OH_AVSCREEN_CAPTURE_ErrCode OH_AVScreenCapture_StrategyForPickerPopUp( OH_AVScreenCapture_CaptureStrategy *strategy, bool value); + +/** + * @brief Set the fill mode of the captured image in the target area + * @param {OH_AVScreenCapture_CaptureStrategy*} strategy Pointer to an OH_AVScreenCapture_CaptureStrategy instance + * @param {OH_AVScreenCapture_FillMode} mode Value of the captured image fill mode + * @return Function result code. + * {@link AV_SCREEN_CAPTURE_ERR_OK} if the execution is successful. + * {@link AV_SCREEN_CAPTURE_ERR_INVALID_VAL} strategy value is nullptr. + * @since 20 + */ +OH_AVSCREEN_CAPTURE_ErrCode OH_AVScreenCapture_StrategyForFillMode( + OH_AVScreenCapture_CaptureStrategy *strategy, OH_AVScreenCapture_FillMode mode); #ifdef __cplusplus } #endif diff --git a/interfaces/kits/c/native_avscreen_capture_base.h b/interfaces/kits/c/native_avscreen_capture_base.h index 976f7562a..f88931093 100644 --- a/interfaces/kits/c/native_avscreen_capture_base.h +++ b/interfaces/kits/c/native_avscreen_capture_base.h @@ -496,6 +496,24 @@ typedef enum OH_AVScreenCaptureContentChangedEvent_Enum { OH_SCREEN_CAPTURE_CONTENT_UNAVAILABLE = 2, } OH_AVScreenCaptureContentChangedEvent; +/** + * @brief content fill mode. + * + * @since 20 + */ +typedef enum OH_AVScreenCapture_FillMode { + /** + * Keep the original image aspect ratio to match the target + * image size. If the ratio is inconsistent, there may be black edges. + */ + OH_SCREENCAPTURE_FILLMODE_ASPECT_SCALE_FIT = 0, + /** + * The image is stretched to match the target output size. + * If the ratios are inconsistent, the image will be deformed. + */ + OH_SCREENCAPTURE_FILLMODE_SCALE_TO_FILL = 1, +} OH_AVScreenCapture_FillMode; + /** * @brief When state of OH_AVScreenCapture is changed, the function pointer will be called. * @syscap SystemCapability.Multimedia.Media.AVScreenCapture diff --git a/services/services/screen_capture/ipc/screen_capture_service_proxy.cpp b/services/services/screen_capture/ipc/screen_capture_service_proxy.cpp index 05d6e2f23..5ac4c5c32 100644 --- a/services/services/screen_capture/ipc/screen_capture_service_proxy.cpp +++ b/services/services/screen_capture/ipc/screen_capture_service_proxy.cpp @@ -190,7 +190,7 @@ int32_t ScreenCaptureServiceProxy::SetAndCheckSaLimit(OHOS::AudioStandard::AppIn int error = Remote()->SendRequest(SET_CHECK_SA_LIMIT, data, reply, option); CHECK_AND_RETURN_RET_LOG(error == MSERR_OK, MSERR_INVALID_OPERATION, "SetAndCheckSaLimit failed, error: %{public}d", error); - + return reply.ReadInt32(); } @@ -275,7 +275,7 @@ int32_t ScreenCaptureServiceProxy::InitVideoCap(VideoCaptureInfo videoInfo) } } token = data.WriteInt32(videoInfo.videoFrameWidth) && data.WriteInt32(videoInfo.videoFrameHeight) && - data.WriteInt32(videoInfo.videoSource) && data.WriteInt32(videoInfo.screenCaptureFillMode); + data.WriteInt32(videoInfo.videoSource); CHECK_AND_RETURN_RET_LOG(token, MSERR_INVALID_OPERATION, "Failed to write videoinfo!"); int error = Remote()->SendRequest(INIT_VIDEO_CAP, data, reply, option); @@ -543,28 +543,28 @@ int32_t ScreenCaptureServiceProxy::ShowCursor(bool showCursor) "ShowCursor failed, error: %{public}d", error); return reply.ReadInt32(); } - + int32_t ScreenCaptureServiceProxy::UpdateSurface(sptr surface) { MessageParcel data; MessageParcel reply; MessageOption option; - + bool token = data.WriteInterfaceToken(ScreenCaptureServiceProxy::GetDescriptor()); CHECK_AND_RETURN_RET_LOG(token, MSERR_INVALID_OPERATION, "Failed to write descriptor!"); - + CHECK_AND_RETURN_RET_LOG(surface != nullptr, MSERR_INVALID_VAL, "surface is nullptr"); sptr producer = surface->GetProducer(); CHECK_AND_RETURN_RET_LOG(producer != nullptr, MSERR_INVALID_VAL, "producer is nullptr"); - + sptr object = producer->AsObject(); bool res = data.WriteRemoteObject(object); CHECK_AND_RETURN_RET_LOG(res, MSERR_INVALID_OPERATION, "UpdateSurface failed to write remote object!"); - + int error = Remote()->SendRequest(UPDATE_SURFACE, data, reply, option); CHECK_AND_RETURN_RET_LOG( error == MSERR_OK, MSERR_INVALID_OPERATION, "UpdateSurface failed, error: %{public}d", error); - + return reply.ReadInt32(); } @@ -635,7 +635,8 @@ int32_t ScreenCaptureServiceProxy::SetScreenCaptureStrategy(ScreenCaptureStrateg token = data.WriteBool(strategy.enableDeviceLevelCapture) && data.WriteBool(strategy.keepCaptureDuringCall) && data.WriteInt32(strategy.strategyForPrivacyMaskMode) && data.WriteBool(strategy.canvasFollowRotation) && - data.WriteBool(strategy.enableBFrame) && data.WriteInt32(static_cast(strategy.pickerPopUp)); + data.WriteBool(strategy.enableBFrame) && data.WriteInt32(static_cast(strategy.pickerPopUp)) && + data.WriteInt32(static_cast(strategy.fillMode)); CHECK_AND_RETURN_RET_LOG(token, MSERR_INVALID_OPERATION, "Failed to write strategy!"); int error = Remote()->SendRequest(SET_STRATEGY, data, reply, option); diff --git a/services/services/screen_capture/ipc/screen_capture_service_stub.cpp b/services/services/screen_capture/ipc/screen_capture_service_stub.cpp index 8ca3fc717..9beafb668 100644 --- a/services/services/screen_capture/ipc/screen_capture_service_stub.cpp +++ b/services/services/screen_capture/ipc/screen_capture_service_stub.cpp @@ -207,11 +207,11 @@ int32_t ScreenCaptureServiceStub::StartScreenCaptureWithSurface(sptr su return screenCaptureServer_->StartScreenCaptureWithSurface(surface, isPrivacyAuthorityEnabled); } - + int32_t ScreenCaptureServiceStub::UpdateSurface(sptr surface) { CHECK_AND_RETURN_RET_LOG(screenCaptureServer_ != nullptr, MSERR_INVALID_STATE, "screen capture server is nullptr"); - + return screenCaptureServer_->UpdateSurface(surface); } @@ -552,7 +552,6 @@ int32_t ScreenCaptureServiceStub::InitVideoCap(MessageParcel &data, MessageParce videoInfo.videoFrameWidth = data.ReadInt32(); videoInfo.videoFrameHeight = data.ReadInt32(); videoInfo.videoSource = static_cast(data.ReadInt32()); - videoInfo.screenCaptureFillMode = static_cast(data.ReadInt32()); int32_t ret = InitVideoCap(videoInfo); reply.WriteInt32(ret); return MSERR_OK; @@ -576,7 +575,7 @@ int32_t ScreenCaptureServiceStub::StartScreenCaptureWithSurface(MessageParcel &d sptr object = data.ReadRemoteObject(); CHECK_AND_RETURN_RET_LOG(object != nullptr, MSERR_NO_MEMORY, "ScreenCaptureServiceProxy StartScreenCaptureWithSurface object is nullptr"); - + sptr producer = iface_cast(object); CHECK_AND_RETURN_RET_LOG(producer != nullptr, MSERR_NO_MEMORY, "failed to convert object to producer"); @@ -588,21 +587,21 @@ int32_t ScreenCaptureServiceStub::StartScreenCaptureWithSurface(MessageParcel &d reply.WriteInt32(ret); return MSERR_OK; } - + int32_t ScreenCaptureServiceStub::UpdateSurface(MessageParcel &data, MessageParcel &reply) { CHECK_AND_RETURN_RET_LOG(screenCaptureServer_ != nullptr, MSERR_INVALID_STATE, "screen capture server is nullptr"); - + sptr object = data.ReadRemoteObject(); CHECK_AND_RETURN_RET_LOG( object != nullptr, MSERR_NO_MEMORY, "ScreenCaptureServiceProxy UpdateSurface object is nullptr"); - + sptr producer = iface_cast(object); CHECK_AND_RETURN_RET_LOG(producer != nullptr, MSERR_NO_MEMORY, "failed to convert object to producer"); - + sptr surface = Surface::CreateSurfaceAsProducer(producer); CHECK_AND_RETURN_RET_LOG(surface != nullptr, MSERR_NO_MEMORY, "failed to create surface"); - + int32_t ret = UpdateSurface(surface); reply.WriteInt32(ret); return MSERR_OK; @@ -720,6 +719,7 @@ int32_t ScreenCaptureServiceStub::SetScreenCaptureStrategy(MessageParcel &data, strategy.canvasFollowRotation = data.ReadBool(); strategy.enableBFrame = data.ReadBool(); strategy.pickerPopUp = static_cast(data.ReadInt32()); + strategy.fillMode = static_cast(data.ReadInt32()); int32_t ret = SetScreenCaptureStrategy(strategy); reply.WriteInt32(ret); return MSERR_OK; diff --git a/services/services/screen_capture/server/screen_capture_server.cpp b/services/services/screen_capture/server/screen_capture_server.cpp index 8229ce2d8..265b7f197 100644 --- a/services/services/screen_capture/server/screen_capture_server.cpp +++ b/services/services/screen_capture/server/screen_capture_server.cpp @@ -917,7 +917,7 @@ int32_t ScreenCaptureServer::HandlePopupWindowCase(Json::Value& root, const std: std::string choice = "false"; GetChoiceFromJson(root, content, std::string("choice"), choice); GetValueFromJson(root, content, std::string("checkBoxSelected"), checkBoxSelected_); - + systemPrivacyProtectionSwitch_ = checkBoxSelected_; appPrivacyProtectionSwitch_ = checkBoxSelected_; MEDIA_LOGI("ReportAVScreenCaptureUserChoice checkBoxSelected: %{public}d", checkBoxSelected_); @@ -958,7 +958,7 @@ int32_t ScreenCaptureServer::HandleStreamDataCase(Json::Value& root, const std:: appPrivacyProtectionSwitch_); GetValueFromJson(root, content, std::string("systemPrivacyProtectionSwitch"), systemPrivacyProtectionSwitch_); - + SystemPrivacyProtected(virtualScreenId_, systemPrivacyProtectionSwitch_); AppPrivacyProtected(virtualScreenId_, appPrivacyProtectionSwitch_); @@ -1408,9 +1408,8 @@ int32_t ScreenCaptureServer::CheckAudioCapInfo(AudioCaptureInfo &audioCapInfo) int32_t ScreenCaptureServer::CheckVideoCapInfo(VideoCaptureInfo &videoCapInfo) { MEDIA_LOGD("CheckVideoCapInfo start, videoFrameWidth:%{public}d, videoFrameHeight:%{public}d, " - "videoSource:%{public}d, state:%{public}d, screenCaptureFillMode:%{public}d.", videoCapInfo.videoFrameWidth, - videoCapInfo.videoFrameHeight, videoCapInfo.videoSource, videoCapInfo.state, - videoCapInfo.screenCaptureFillMode); + "videoSource:%{public}d, state:%{public}d.", videoCapInfo.videoFrameWidth, + videoCapInfo.videoFrameHeight, videoCapInfo.videoSource, videoCapInfo.state); if (videoCapInfo.videoFrameWidth == 0 && videoCapInfo.videoFrameHeight == 0) { MEDIA_LOGD("videoCap IGNORED width:%{public}d, height:%{public}d, source:%{public}d, state:%{public}d", videoCapInfo.videoFrameWidth, videoCapInfo.videoFrameHeight, videoCapInfo.videoSource, videoCapInfo.state); @@ -3868,7 +3867,7 @@ int32_t ScreenCaptureServer::SetScreenScaleMode() CHECK_AND_RETURN_RET_LOG(virtualScreenId_ != SCREEN_ID_INVALID, MSERR_INVALID_VAL, "SetScreenScaleMode failed virtual screen not init"); auto ret = ScreenManager::GetInstance().SetVirtualMirrorScreenScaleMode( - virtualScreenId_, GetScreenScaleMode(captureConfig_.videoInfo.videoCapInfo.screenCaptureFillMode)); + virtualScreenId_, GetScreenScaleMode(captureConfig_.strategy.fillMode)); if (ret != DMError::DM_OK) { MEDIA_LOGW("SetScreenScaleMode failed, ret: %{public}d", ret); return static_cast(ret); @@ -4264,10 +4263,11 @@ int32_t ScreenCaptureServer::SetScreenCaptureStrategy(ScreenCaptureStrategy stra CHECK_AND_RETURN_RET_LOG(captureState_ < AVScreenCaptureState::POPUP_WINDOW, MSERR_INVALID_STATE, "strategy can not be modified after screen capture started"); MEDIA_LOGI("SetScreenCaptureStrategy enableDeviceLevelCapture: %{public}d, keepCaptureDuringCall: %{public}d," - "strategyForPrivacyMaskMode: %{public}d, canvasFollowRotation: %{public}d, enableBFrame: %{public}d," - "pickerPopUp: %{public}d", + "strategyForPrivacyMaskMode: %{public}d, canvasFollowRotation: %{public}d, enableBFrame: %{public}d," + "pickerPopUp: %{public}d, fillMode: %{public}d", strategy.enableDeviceLevelCapture, strategy.keepCaptureDuringCall, strategy.strategyForPrivacyMaskMode, - strategy.canvasFollowRotation, strategy.enableBFrame, static_cast(strategy.pickerPopUp)); + strategy.canvasFollowRotation, strategy.enableBFrame, static_cast(strategy.pickerPopUp), + static_cast(strategy.fillMode)); captureConfig_.strategy = strategy; return MSERR_OK; } diff --git a/test/unittest/resources/ohos_test.xml b/test/unittest/resources/ohos_test.xml index 4defd6749..cb37b6bd4 100644 --- a/test/unittest/resources/ohos_test.xml +++ b/test/unittest/resources/ohos_test.xml @@ -408,6 +408,8 @@