From 4d1d1f35d5dbcee17e75fb444e5ae5b6a27d72c5 Mon Sep 17 00:00:00 2001 From: zhaoyuan17 Date: Tue, 28 Sep 2021 23:33:05 +0800 Subject: [PATCH] fix codex Signed-off-by: zhaoyuan17 --- frameworks/kits/ability/native/BUILD.gn | 2 + .../kits/ability/native/include/ability.h | 10 - .../ability/native/include/ability_context.h | 3 + ...bility_distributed_connect_callback_stub.h | 59 + .../ability_distributed_connection.h | 56 + .../distributed/distributed_client.h | 3 + .../kits/ability/native/src/ability.cpp | 37 +- .../ability/native/src/ability_context.cpp | 54 +- .../ability/native/src/ability_thread.cpp | 16 - ...lity_distributed_connect_callback_stub.cpp | 89 + .../ability_distributed_connection.cpp | 49 + .../distributed/distributed_client.cpp | 33 + .../data_ability_helper_module_test.cpp | 64 +- ...ability_distributed_connection_interface.h | 62 + .../napi_data_ability_helper.cpp | 38 +- .../inner/napi_common/napi_common_ability.cpp | 26 +- .../inner/napi_common/napi_common_util.cpp | 93 - .../inner/napi_common/napi_common_util.h | 8 - sa_profile/182.xml | 27 + sa_profile/BUILD.gn | 5 +- .../src/bundlemgr/mock_bundle_manager.cpp | 4 +- .../ability_dump_test/ability_dump_test.cpp | 4 + .../ability_with_applications_test.cpp | 6 +- .../abilityms_appms_test.cpp | 5 + .../phone/lifecycle_test/lifecycle_test.cpp | 9 +- tools/BUILD.gn | 10 +- tools/LICENSE | 177 + tools/OAT.xml | 68 + tools/README_zh.md | 320 ++ tools/aafwk.gni | 21 + tools/figures/aafwk.png | Bin 0 -> 22892 bytes .../page-ability-lifecycle-callbacks.png | Bin 0 -> 50304 bytes tools/figures/page-ability-lifecycle.png | Bin 0 -> 14658 bytes .../service-ability-lifecycle-callbacks.jpg | Bin 0 -> 113334 bytes tools/figures/service-ability-lifecycle.png | Bin 0 -> 12214 bytes tools/frameworks/kits/ability/native/BUILD.gn | 228 + .../kits/ability/native/include/ability.h | 1449 +++++++ .../ability/native/include/ability_context.h | 732 ++++ .../native/include/ability_event_interface.h | 34 + .../ability/native/include/ability_handler.h | 43 + .../ability/native/include/ability_impl.h | 437 ++ .../native/include/ability_impl_factory.h | 38 + .../ability/native/include/ability_keyevent.h | 52 + .../native/include/ability_lifecycle.h | 91 + .../include/ability_lifecycle_callbacks.h | 87 + .../include/ability_lifecycle_executor.h | 54 + .../include/ability_lifecycle_interface.h | 37 + .../include/ability_lifecycle_observer.h | 100 + .../ability_lifecycle_observer_interface.h | 101 + .../ability/native/include/ability_loader.h | 112 + .../native/include/ability_local_record.h | 124 + .../include/ability_post_event_timeout.h | 54 + .../ability/native/include/ability_process.h | 50 + .../ability/native/include/ability_state.h | 89 + .../ability/native/include/ability_thread.h | 442 ++ .../native/include/ability_touchevent.h | 51 + .../ability/native/include/ability_window.h | 119 + ...bility_distributed_connect_callback_stub.h | 59 + .../ability_distributed_connection.h | 56 + .../distributed/continuation_handler.h | 81 + .../distributed/continuation_manager.h | 123 + .../distributed/continuation_scheduler.h | 51 + .../continuation_scheduler_interface.h | 44 + .../distributed/continuation_scheduler_stub.h | 47 + .../distribute_schedule_handler_interface.h | 51 + .../distributed/distributed_client.h | 63 + .../distributed/distributed_errors.h | 48 + .../continuation/distributed/progress_state.h | 28 + .../reverse_continuation_scheduler_primary.h | 56 + ...tion_scheduler_primary_handler_interface.h | 32 + ...continuation_scheduler_primary_interface.h | 51 + ...rse_continuation_scheduler_primary_proxy.h | 47 + ...erse_continuation_scheduler_primary_stub.h | 55 + ...reverse_continuation_scheduler_recipient.h | 43 + .../reverse_continuation_scheduler_replica.h | 53 + ...tion_scheduler_replica_handler_interface.h | 34 + ...continuation_scheduler_replica_interface.h | 42 + ...rse_continuation_scheduler_replica_proxy.h | 42 + ...erse_continuation_scheduler_replica_stub.h | 49 + .../kits/ability_continuation_interface.h | 40 + .../continuation_device_callback_interface.h | 47 + .../continuation_register_manager_interface.h | 109 + .../continuation/kits/continuation_state.h | 45 + .../continuation/kits/device_connect_state.h | 39 + .../continuation/kits/request_callback.h | 38 + .../connect_callback_proxy.h | 51 + .../connect_callback_stub.h | 49 + .../continuation_connector.h | 154 + .../continuation_device_callback_proxy.h | 55 + .../continuation_register_manager.h | 81 + .../continuation_register_manager_proxy.h | 173 + .../continuation_request.h | 32 + .../remote_register_service_proxy.h | 70 + .../remote_register_service_stub.h | 46 + .../native/include/data_ability_helper.h | 327 ++ .../native/include/data_ability_impl.h | 200 + .../native/include/data_ability_operation.h | 168 + .../include/data_ability_operation_builder.h | 100 + .../native/include/data_ability_result.h | 107 + .../ability/native/include/data_uri_utils.h | 96 + .../native/include/dummy_ability_package.h | 29 + .../include/dummy_component_container.h | 28 + .../native/include/dummy_continuation_state.h | 29 + .../include/dummy_data_ability_predicates.h | 43 + .../include/dummy_notification_request.h | 28 + .../ability/native/include/dummy_result_set.h | 40 + .../native/include/dummy_values_bucket.h | 50 + .../native/include/form_js_event_handler.h | 62 + .../native/include/form_provider_client.h | 159 + .../include/iability_lifecycle_callback.h | 73 + .../ability/native/include/ipc_singleton.h | 70 + .../native/include/mission_information.h | 35 + .../native/include/page_ability_impl.h | 95 + .../native/include/service_ability_impl.h | 52 + .../kits/ability/native/src/ability.cpp | 2953 +++++++++++++ .../ability/native/src/ability_context.cpp | 1341 ++++++ .../ability/native/src/ability_handler.cpp | 32 + .../kits/ability/native/src/ability_impl.cpp | 777 ++++ .../native/src/ability_impl_factory.cpp | 75 + .../ability/native/src/ability_keyevent.cpp | 82 + .../ability/native/src/ability_lifecycle.cpp | 170 + .../native/src/ability_lifecycle_executor.cpp | 42 + .../native/src/ability_lifecycle_observer.cpp | 97 + .../ability/native/src/ability_loader.cpp | 76 + .../native/src/ability_local_record.cpp | 136 + .../native/src/ability_post_event_timeout.cpp | 89 + .../ability/native/src/ability_process.cpp | 231 + .../ability/native/src/ability_thread.cpp | 1164 +++++ .../ability/native/src/ability_touchevent.cpp | 68 + .../ability/native/src/ability_window.cpp | 313 ++ ...lity_distributed_connect_callback_stub.cpp | 89 + .../ability_distributed_connection.cpp | 49 + .../distributed/continuation_handler.cpp | 345 ++ .../distributed/continuation_manager.cpp | 576 +++ .../distributed/continuation_scheduler.cpp | 120 + .../continuation_scheduler_stub.cpp | 76 + .../distributed/distributed_client.cpp | 184 + ...reverse_continuation_scheduler_primary.cpp | 107 + ...e_continuation_scheduler_primary_proxy.cpp | 88 + ...se_continuation_scheduler_primary_stub.cpp | 100 + ...verse_continuation_scheduler_recipient.cpp | 34 + ...reverse_continuation_scheduler_replica.cpp | 123 + ...e_continuation_scheduler_replica_proxy.cpp | 112 + ...se_continuation_scheduler_replica_stub.cpp | 79 + .../connect_callback_proxy.cpp | 68 + .../connect_callback_stub.cpp | 74 + .../continuation_connector.cpp | 273 ++ .../continuation_device_callback_proxy.cpp | 57 + .../continuation_register_manager.cpp | 122 + .../continuation_register_manager_proxy.cpp | 301 ++ .../remote_register_service_proxy.cpp | 168 + .../remote_register_service_stub.cpp | 136 + .../native/src/data_ability_helper.cpp | 1111 +++++ .../ability/native/src/data_ability_impl.cpp | 335 ++ .../native/src/data_ability_operation.cpp | 490 +++ .../src/data_ability_operation_builder.cpp | 149 + .../native/src/data_ability_result.cpp | 181 + .../ability/native/src/data_uri_utils.cpp | 218 + .../src/dummy_data_ability_predicates.cpp | 67 + .../dummy_data_ability_predicates_discard.cpp | 14 + .../ability/native/src/dummy_result_set.cpp | 67 + .../native/src/dummy_result_set_discard.cpp | 14 + .../native/src/dummy_values_bucket.cpp | 67 + .../src/dummy_values_bucket_discard.cpp | 14 + .../native/src/form_js_event_handler.cpp | 145 + .../native/src/form_provider_client.cpp | 467 ++ .../native/src/mission_information.cpp | 50 + .../ability/native/src/page_ability_impl.cpp | 192 + .../native/src/service_ability_impl.cpp | 74 + .../kits/ability/native/src/task_handler.cpp | 31 + .../native/src/task_handler_client.cpp | 77 + .../kits/ability/native/test/BUILD.gn | 980 +++++ .../test/mock/include/bundle_mgr_interface.h | 263 ++ .../native/test/mock/include/mock_ability.cpp | 438 ++ .../test/mock/include/mock_ability_impl.h | 89 + .../include/mock_ability_manager_client.cpp | 144 + .../include/mock_ability_manager_client.h | 132 + ...manager_client_for_data_ability_observer.h | 119 + ...mock_ability_manager_client_interface1.cpp | 369 ++ .../mock_ability_manager_client_interface1.h | 134 + .../include/mock_ability_manager_clientex.cpp | 229 + .../include/mock_ability_manager_service.cpp | 201 + .../include/mock_ability_manager_service.h | 172 + .../mock_ability_scheduler_for_observer.h | 66 + .../test/mock/include/mock_ability_thread.h | 38 + ...read_for_ability_on_configuration_update.h | 57 + .../test/mock/include/mock_ability_token.h | 60 + .../test/mock/include/mock_bundle_manager.cpp | 114 + .../test/mock/include/mock_bundle_manager.h | 442 ++ .../mock/include/mock_bundle_manager_form.cpp | 171 + .../mock/include/mock_bundle_manager_form.h | 471 ++ .../test/mock/include/mock_data_ability.h | 114 + .../mock/include/mock_data_ability_impl.cpp | 84 + .../test/mock/include/mock_form_mgr_service.h | 236 + .../include/mock_form_supply_callback.cpp | 59 + .../mock/include/mock_form_supply_callback.h | 56 + .../mock/include/mock_lifecycle_observer.h | 133 + .../test/mock/include/mock_page_ability.h | 172 + .../include/mock_replace_ability_impl.cpp | 203 + .../mock_resourceManager_interface1.cpp | 285 ++ .../include/mock_resourceManager_interface1.h | 107 + .../test/mock/include/mock_service_ability.h | 76 + .../test/mock/include/sys_mgr_client_mock.cpp | 51 + ...bility_context_for_task_dispacher_test.cpp | 221 + .../ability_context_interface1_test.cpp | 722 ++++ .../test/unittest/ability_context_test.cpp | 578 +++ .../unittest/ability_impl_active_test.cpp | 354 ++ .../test/unittest/ability_impl_test.cpp | 1344 ++++++ .../ability_lifecycle_executor_test.cpp | 166 + .../test/unittest/ability_lifecycle_test.cpp | 368 ++ .../test/unittest/ability_permission_test.cpp | 200 + .../native/test/unittest/ability_test.cpp | 851 ++++ .../ability_thread_dataability_test.cpp | 410 ++ ...ad_for_ability_on_configuration_update.cpp | 130 + .../test/unittest/ability_thread_test.cpp | 691 +++ .../unittest/data_ability_helper_test.cpp | 781 ++++ ...data_ability_impl_file_secondpart_test.cpp | 167 + .../unittest/data_ability_impl_file_test.cpp | 339 ++ .../test/unittest/data_ability_impl_test.cpp | 270 ++ .../unittest/data_ability_operation_test.cpp | 728 ++++ .../unittest/data_ability_result_test.cpp | 279 ++ .../test/unittest/data_uri_utils_test.cpp | 148 + .../test/unittest/form_ability_test.cpp | 1259 ++++++ .../test/unittest/form_host_client_test.cpp | 157 + .../unittest/form_provider_client_test.cpp | 509 +++ .../native/test/unittest/pac_map_test.cpp | 747 ++++ .../test/unittest/page_ability_impl_test.cpp | 683 +++ .../unittest/service_ability_impl_test.cpp | 211 + .../unittest/task_handler_client_test.cpp | 97 + .../cpp/src/ohos/aafwk/base/array_wrapper.cpp | 387 ++ .../base/cpp/src/ohos/aafwk/base/base.cpp | 78 + .../cpp/src/ohos/aafwk/base/base_object.cpp | 199 + .../cpp/src/ohos/aafwk/base/bool_wrapper.cpp | 64 + .../cpp/src/ohos/aafwk/base/byte_wrapper.cpp | 65 + .../src/ohos/aafwk/base/double_wrapper.cpp | 65 + .../cpp/src/ohos/aafwk/base/float_wrapper.cpp | 65 + .../cpp/src/ohos/aafwk/base/int_wrapper.cpp | 65 + .../cpp/src/ohos/aafwk/base/long_wrapper.cpp | 65 + .../cpp/src/ohos/aafwk/base/short_wrapper.cpp | 65 + .../src/ohos/aafwk/base/string_wrapper.cpp | 60 + .../ohos/aafwk/base/user_object_wrapper.cpp | 134 + .../cpp/src/ohos/aafwk/base/zchar_wrapper.cpp | 160 + tools/frameworks/kits/base/cpp/test/BUILD.gn | 60 + .../cpp/test/unittest/common/base_test.cpp | 1110 +++++ .../src/ohos/aafwk/content/extra_params.cpp | 264 ++ .../cpp/src/ohos/aafwk/content/intent.cpp | 904 ++++ .../src/ohos/aafwk/content/intent_filter.cpp | 137 + .../src/ohos/aafwk/content/intent_params.cpp | 475 ++ .../cpp/src/ohos/aafwk/content/operation.cpp | 393 ++ .../ohos/aafwk/content/operation_builder.cpp | 115 + .../cpp/src/ohos/aafwk/content/pac_map.cpp | 1783 ++++++++ .../ohos/aafwk/content/patterns_matcher.cpp | 208 + .../cpp/src/ohos/aafwk/content/skills.cpp | 1066 +++++ .../cpp/src/ohos/aafwk/content/want.cpp | 1893 ++++++++ .../src/ohos/aafwk/content/want_params.cpp | 1274 ++++++ .../aafwk/content/want_params_wrapper.cpp | 153 + .../ohos/aafwk/content/want_params_wrapper.h | 66 + .../frameworks/kits/content/cpp/test/BUILD.gn | 351 ++ .../unittest/common/intent_filter_test.cpp | 462 ++ .../common/intent_parameters_test.cpp | 2322 ++++++++++ .../test/unittest/common/operation_test.cpp | 339 ++ .../unittest/common/patterns_matcher_test.cpp | 174 + .../cpp/test/unittest/common/skills_test.cpp | 906 ++++ .../test/unittest/common/want_params_test.cpp | 141 + .../common/want_params_wrapper_test.cpp | 339 ++ .../cpp/test/unittest/common/want_test.cpp | 3830 +++++++++++++++++ tools/frameworks/kits/test/BUILD.gn | 292 ++ .../mock/AMS/mock_ability_manager_client.cpp | 229 + .../mock/AMS/mock_ability_manager_service.cpp | 238 + .../mock/AMS/mock_ability_manager_service.h | 137 + .../mock_serviceability_manager_service.cpp | 209 + .../AMS/mock_serviceability_manager_service.h | 150 + .../mock/DemoAbility/demo_ability_test.cpp | 207 + .../test/mock/DemoAbility/demo_ability_test.h | 55 + .../test/mock/DemoAbility/mock_ability_test.h | 135 + .../DemoAbility/mock_lifecycle_observer.cpp | 61 + .../DemoAbility/mock_lifecycle_observer.h | 50 + .../mock_ability_hancle_for_data_observer.h | 37 + .../mock_ability_manager_client.h | 80 + .../mock_ability_thread_for_data_observer.h | 68 + .../cpp/abilitytest/ability_context_test.cpp | 248 ++ .../cpp/abilitytest/ability_test.cpp | 1065 +++++ .../data_ability_helper_module_test.cpp | 682 +++ .../data_ability_operation_module_test.cpp | 152 + tools/interfaces/innerkits/BUILD.gn | 22 + .../innerkits/ability_manager/BUILD.gn | 103 + .../ability_manager_headers.gni | 39 + .../include/aafwk_dummy_configuration.h | 73 + .../ability_connect_callback_interface.h | 62 + .../include/ability_connect_callback_stub.h | 59 + .../include/ability_manager_client.h | 427 ++ .../include/ability_manager_errors.h | 312 ++ .../include/ability_manager_interface.h | 617 +++ .../include/ability_mission_info.h | 48 + .../include/ability_record_info.h | 67 + .../include/ability_scheduler_interface.h | 358 ++ .../include/ability_start_setting.h | 109 + .../include/ability_window_configuration.h | 48 + .../ability_manager/include/caller_info.h | 42 + ...ability_distributed_connection_interface.h | 62 + .../continuation/connect_callback_interface.h | 55 + .../remote_register_service_interface.h | 78 + .../ability_manager/include/image_info.h | 75 + .../include/lifecycle_state_info.h | 57 + .../include/mission_description_info.h | 39 + .../ability_manager/include/mission_option.h | 57 + .../include/mission_record_info.h | 40 + .../include/mission_snapshot_info.h | 39 + .../include/mission_stack_info.h | 40 + .../ability_manager/include/sender_info.h | 42 + .../ability_manager/include/stack_info.h | 40 + .../ability_manager/include/stack_setting.h | 50 + .../ability_manager/include/task_handler.h | 41 + .../include/task_handler_client.h | 44 + .../include/want_receiver_interface.h | 39 + .../include/want_sender_info.h | 45 + .../include/want_sender_interface.h | 37 + .../ability_manager/include/wants_info.h | 38 + tools/interfaces/innerkits/base/BUILD.gn | 60 + .../include/ohos/aafwk/base/array_wrapper.h | 97 + .../base/include/ohos/aafwk/base/base_def.h | 156 + .../include/ohos/aafwk/base/base_interfaces.h | 213 + .../include/ohos/aafwk/base/base_object.h | 95 + .../base/include/ohos/aafwk/base/base_types.h | 55 + .../include/ohos/aafwk/base/bool_wrapper.h | 53 + .../include/ohos/aafwk/base/byte_wrapper.h | 53 + .../include/ohos/aafwk/base/double_wrapper.h | 53 + .../include/ohos/aafwk/base/float_wrapper.h | 53 + .../include/ohos/aafwk/base/int_wrapper.h | 53 + .../include/ohos/aafwk/base/ipc_singleton.h | 72 + .../include/ohos/aafwk/base/light_refbase.h | 66 + .../include/ohos/aafwk/base/long_wrapper.h | 53 + .../include/ohos/aafwk/base/short_wrapper.h | 53 + .../include/ohos/aafwk/base/string_wrapper.h | 53 + .../ohos/aafwk/base/user_object_base.h | 131 + .../ohos/aafwk/base/user_object_wrapper.h | 55 + .../include/ohos/aafwk/base/zchar_wrapper.h | 89 + .../innerkits/dataobs_manager/BUILD.gn | 61 + .../dataobs_manager_headers.gni | 23 + .../include/data_ability_observer_interface.h | 42 + .../include/data_ability_observer_stub.h | 71 + .../include/dataobs_mgr_client.h | 83 + .../include/dataobs_mgr_errors.h | 52 + .../include/dataobs_mgr_interface.h | 82 + tools/interfaces/innerkits/intent/BUILD.gn | 73 + .../include/ohos/aafwk/content/intent.h | 142 + .../ohos/aafwk/content/intent_filter.h | 66 + .../ohos/aafwk/content/intent_params.h | 80 + tools/interfaces/innerkits/want/BUILD.gn | 81 + .../include/ohos/aafwk/content/extra_params.h | 202 + .../include/ohos/aafwk/content/match_type.h | 29 + .../include/ohos/aafwk/content/operation.h | 205 + .../ohos/aafwk/content/operation_builder.h | 88 + .../want/include/ohos/aafwk/content/pac_map.h | 563 +++ .../ohos/aafwk/content/patterns_matcher.h | 121 + .../want/include/ohos/aafwk/content/skills.h | 511 +++ .../want/include/ohos/aafwk/content/want.h | 804 ++++ .../include/ohos/aafwk/content/want_params.h | 179 + .../kits/js/@ohos.ability.dataUriUtils.d.ts | 60 + .../kits/js/@ohos.ability.featureAbility.d.ts | 150 + .../kits/js/@ohos.ability.formmanager.d.ts | 292 ++ .../js/@ohos.ability.particleAbility.d.ts | 64 + .../kits/js/@ohos.ability.wantConstant.d.ts | 341 ++ .../kits/js/@ohos.app.abilityManager.d.ts | 90 + tools/interfaces/kits/js/@ohos.bundle.d.ts | 347 ++ .../kits/js/ability/abilityResult.d.ts | 37 + .../kits/js/ability/connectOptions.d.ts | 52 + .../kits/js/ability/dataAbilityHelper.d.ts | 224 + .../kits/js/ability/dataAbilityOperation.d.ts | 107 + .../js/ability/startAbilityParameter.d.ts | 50 + tools/interfaces/kits/js/ability/want.d.ts | 105 + .../kits/js/app/abilityMissionInfo.d.ts | 57 + .../kits/js/app/activeProcessInfo.d.ts | 52 + .../kits/js/app/activeServiceAbilityInfo.d.ts | 55 + tools/interfaces/kits/js/app/context.d.ts | 105 + .../interfaces/kits/js/app/memoryMapInfo.d.ts | 63 + .../kits/js/app/missionSnapshot.d.ts | 37 + .../kits/js/app/processErrorInfo.d.ts | 56 + .../kits/js/app/splitMissionInfo.d.ts | 47 + .../kits/js/app/systemMemoryAttr.d.ts | 44 + .../kits/js/bundle/abilityInfo.d.ts | 244 ++ .../kits/js/bundle/applicationInfo.d.ts | 138 + .../interfaces/kits/js/bundle/bundleInfo.d.ts | 237 + .../kits/js/bundle/bundleInstaller.d.ts | 107 + .../kits/js/bundle/customizeData.d.ts | 37 + .../kits/js/bundle/elementName.d.ts | 71 + .../kits/js/bundle/hapModuleInfo.d.ts | 116 + .../interfaces/kits/js/bundle/moduleInfo.d.ts | 43 + .../kits/js/bundle/moduleUsageRecord.d.ts | 103 + .../kits/js/bundle/shortcutInfo.d.ts | 107 + tools/interfaces/kits/napi/BUILD.gn | 26 + .../kits/napi/aafwk/abilityManager/BUILD.gn | 57 + .../abilityManager/napi_ability_manager.cpp | 1869 ++++++++ .../abilityManager/napi_ability_manager.h | 141 + .../aafwk/abilityManager/native_module.cpp | 85 + .../kits/napi/aafwk/dataUriUtils/BUILD.gn | 55 + .../dataUriUtils/napi_data_uri_utils.cpp | 202 + .../aafwk/dataUriUtils/napi_data_uri_utils.h | 74 + .../napi/aafwk/dataUriUtils/native_module.cpp | 58 + .../kits/napi/aafwk/featureAbility/BUILD.gn | 74 + .../aafwk/featureAbility/feature_ability.cpp | 1558 +++++++ .../aafwk/featureAbility/feature_ability.h | 361 ++ .../feature_ability_constant.cpp | 76 + .../featureAbility/feature_ability_constant.h | 36 + .../aafwk/featureAbility/napi_context.cpp | 2962 +++++++++++++ .../napi/aafwk/featureAbility/napi_context.h | 116 + .../napi_data_ability_helper.cpp | 3204 ++++++++++++++ .../featureAbility/napi_data_ability_helper.h | 478 ++ .../napi_data_ability_operation.cpp | 222 + .../napi_data_ability_operation.h | 75 + .../aafwk/featureAbility/native_module.cpp | 66 + .../kits/napi/aafwk/formManager/BUILD.gn | 47 + .../aafwk/formManager/napi_form_manager.cpp | 2657 ++++++++++++ .../aafwk/formManager/napi_form_manager.h | 189 + .../napi/aafwk/formManager/native_module.cpp | 75 + .../napi/aafwk/inner/napi_common/BUILD.gn | 56 + .../napi_common/feature_ability_common.h | 351 ++ .../aafwk/inner/napi_common/napi_common.h | 23 + .../inner/napi_common/napi_common_ability.cpp | 3443 +++++++++++++++ .../inner/napi_common/napi_common_ability.h | 249 ++ .../inner/napi_common/napi_common_data.h | 118 + .../inner/napi_common/napi_common_error.h | 32 + .../inner/napi_common/napi_common_util.cpp | 1116 +++++ .../inner/napi_common/napi_common_util.h | 242 ++ .../inner/napi_common/napi_common_want.cpp | 925 ++++ .../inner/napi_common/napi_common_want.h | 42 + .../kits/napi/aafwk/particleAbility/BUILD.gn | 57 + .../aafwk/particleAbility/native_module.cpp | 57 + .../particleAbility/particle_ability.cpp | 213 + .../aafwk/particleAbility/particle_ability.h | 36 + .../kits/napi/aafwk/wantConstant/BUILD.gn | 52 + .../napi/aafwk/wantConstant/native_module.cpp | 58 + .../napi/aafwk/wantConstant/want_constant.cpp | 120 + .../napi/aafwk/wantConstant/want_constant.h | 37 + tools/ohos.build | 90 + tools/sa_profile/180.xml | 27 + tools/sa_profile/182.xml | 27 + tools/sa_profile/BUILD.gn | 20 + tools/services/BUILD.gn | 28 + tools/services/abilitymgr/BUILD.gn | 102 + tools/services/abilitymgr/abilitymgr.gni | 67 + .../abilitymgr/include/ability_config.h | 53 + .../include/ability_connect_callback_proxy.h | 62 + .../include/ability_connect_manager.h | 417 ++ .../include/ability_event_handler.h | 54 + .../include/ability_manager_proxy.h | 454 ++ .../include/ability_manager_service.h | 649 +++ .../abilitymgr/include/ability_manager_stub.h | 108 + .../abilitymgr/include/ability_record.h | 747 ++++ .../include/ability_scheduler_proxy.h | 289 ++ .../include/ability_scheduler_stub.h | 89 + .../include/ability_stack_manager.h | 699 +++ .../include/ability_token_interface.h | 33 + .../abilitymgr/include/ability_token_proxy.h | 42 + .../abilitymgr/include/ability_token_stub.h | 54 + .../abilitymgr/include/ability_util.h | 178 + .../include/ams_configuration_parameter.h | 80 + .../abilitymgr/include/app_scheduler.h | 204 + .../abilitymgr/include/configuration_holder.h | 61 + .../abilitymgr/include/connection_record.h | 145 + .../include/data_ability_caller_recipient.h | 40 + .../abilitymgr/include/data_ability_manager.h | 66 + .../abilitymgr/include/data_ability_record.h | 74 + .../include/kernal_system_app_manager.h | 167 + .../abilitymgr/include/lifecycle_deal.h | 65 + .../include/lock_mission_container.h | 53 + .../abilitymgr/include/mission_record.h | 244 ++ .../abilitymgr/include/mission_stack.h | 179 + .../include/pending_want_common_event.h | 46 + .../abilitymgr/include/pending_want_key.h | 70 + .../abilitymgr/include/pending_want_manager.h | 176 + .../abilitymgr/include/pending_want_record.h | 68 + .../abilitymgr/include/power_storage.h | 46 + .../include/resume_mission_container.h | 42 + .../abilitymgr/include/sa_mgr_client.h | 47 + .../abilitymgr/include/want_receiver_proxy.h | 42 + .../abilitymgr/include/want_receiver_stub.h | 43 + .../abilitymgr/include/want_sender_proxy.h | 42 + .../abilitymgr/include/want_sender_stub.h | 42 + .../services/abilitymgr/include/window_info.h | 40 + .../resource/ams_service_config.json | 8 + .../src/aafwk_dummy_configuration.cpp | 95 + .../src/ability_connect_callback_stub.cpp | 154 + .../src/ability_connect_manager.cpp | 876 ++++ .../abilitymgr/src/ability_event_handler.cpp | 80 + .../abilitymgr/src/ability_manager_client.cpp | 542 +++ .../abilitymgr/src/ability_manager_proxy.cpp | 1338 ++++++ .../src/ability_manager_service.cpp | 1605 +++++++ .../abilitymgr/src/ability_manager_stub.cpp | 793 ++++ .../abilitymgr/src/ability_mission_info.cpp | 87 + .../abilitymgr/src/ability_record.cpp | 1109 +++++ .../abilitymgr/src/ability_record_info.cpp | 79 + .../src/ability_scheduler_proxy.cpp | 953 ++++ .../abilitymgr/src/ability_scheduler_stub.cpp | 579 +++ .../abilitymgr/src/ability_stack_manager.cpp | 3454 +++++++++++++++ .../abilitymgr/src/ability_start_setting.cpp | 179 + .../abilitymgr/src/ability_token_stub.cpp | 34 + .../src/ams_configuration_parameter.cpp | 91 + .../services/abilitymgr/src/app_scheduler.cpp | 184 + tools/services/abilitymgr/src/caller_info.cpp | 66 + .../abilitymgr/src/configuration_holder.cpp | 89 + .../abilitymgr/src/connection_record.cpp | 213 + .../src/data_ability_caller_recipient.cpp | 40 + .../abilitymgr/src/data_ability_manager.cpp | 491 +++ .../abilitymgr/src/data_ability_record.cpp | 560 +++ tools/services/abilitymgr/src/image_info.cpp | 80 + .../src/kernal_system_app_manager.cpp | 393 ++ .../abilitymgr/src/lifecycle_deal.cpp | 112 + .../abilitymgr/src/lifecycle_state_info.cpp | 87 + .../abilitymgr/src/lock_mission_container.cpp | 116 + .../src/mission_description_info.cpp | 54 + .../abilitymgr/src/mission_option.cpp | 94 + .../abilitymgr/src/mission_record.cpp | 349 ++ .../abilitymgr/src/mission_record_info.cpp | 65 + .../abilitymgr/src/mission_snapshot_info.cpp | 54 + .../services/abilitymgr/src/mission_stack.cpp | 302 ++ .../abilitymgr/src/mission_stack_info.cpp | 64 + .../src/pending_want_common_event.cpp | 44 + .../abilitymgr/src/pending_want_key.cpp | 121 + .../abilitymgr/src/pending_want_manager.cpp | 425 ++ .../abilitymgr/src/pending_want_record.cpp | 150 + .../services/abilitymgr/src/power_storage.cpp | 54 + .../src/resume_mission_container.cpp | 68 + .../services/abilitymgr/src/sa_mgr_client.cpp | 54 + tools/services/abilitymgr/src/sender_info.cpp | 87 + tools/services/abilitymgr/src/stack_info.cpp | 62 + .../services/abilitymgr/src/stack_setting.cpp | 55 + .../abilitymgr/src/want_receiver_proxy.cpp | 80 + .../abilitymgr/src/want_receiver_stub.cpp | 89 + .../abilitymgr/src/want_sender_info.cpp | 78 + .../abilitymgr/src/want_sender_proxy.cpp | 55 + .../abilitymgr/src/want_sender_stub.cpp | 66 + tools/services/abilitymgr/src/wants_info.cpp | 57 + tools/services/abilitymgr/test/BUILD.gn | 166 + tools/services/abilitymgr/test/mock/BUILD.gn | 35 + .../test/mock/appmgr_test_service/BUILD.gn | 57 + .../include/appmgr_test_service.h | 73 + .../src/appmgr_test_service.cpp | 177 + .../mock/include/mock_app_manager_client.h | 48 + .../test/mock/include/mock_app_mgr_client.h | 49 + .../mock/include/mock_configuration_holder.h | 52 + .../abilitymgr/test/mock/libs/aakit/BUILD.gn | 56 + .../libs/aakit/include/ability_scheduler.h | 106 + .../include/mock_ability_connect_callback.h | 37 + .../mock/libs/aakit/src/ability_scheduler.cpp | 136 + .../src/mock_ability_connect_callback.cpp | 40 + .../ability_scheduler_mock.h | 145 + .../test/mock/libs/appexecfwk_core/BUILD.gn | 85 + .../include/appmgr/app_mgr_client.h | 177 + .../include/appmgr/app_mgr_interface.h | 160 + .../include/appmgr/app_process_data.h | 60 + .../include/appmgr/app_state_callback_host.h | 63 + .../include/appmgr/iapp_state_callback.h | 53 + .../include/bundlemgr/bundle_mgr_interface.h | 263 ++ .../include/bundlemgr/mock_bundle_manager.h | 289 ++ .../src/appmgr/app_mgr_client.cpp | 117 + .../src/appmgr/app_state_callback_host.cpp | 59 + .../src/appmgr/app_state_callback_proxy.cpp | 40 + .../src/appmgr/mock_app_scheduler.cpp | 129 + .../src/bundlemgr/mock_bundle_manager.cpp | 211 + .../abilitymgr/test/mock/libs/sa_mgr/BUILD.gn | 44 + .../libs/sa_mgr/src/sa_mgr_client_mock.cpp | 47 + .../libs/system_ability_mock/system_ability.h | 71 + .../BUILD.gn | 69 + .../ability_connect_callback_proxy_test.cpp | 101 + .../mock_ability_connect_callback_stub.h | 53 + .../BUILD.gn | 70 + .../ability_connect_callback_stub_test.cpp | 164 + .../mock_ability_connect_callback_stub.h | 53 + .../ability_connect_manage_test/BUILD.gn | 65 + .../ability_connect_manage_test.cpp | 1382 ++++++ .../unittest/phone/ability_dump_test/BUILD.gn | 69 + .../ability_dump_test/ability_dump_test.cpp | 516 +++ .../phone/ability_manager_proxy_test/BUILD.gn | 68 + .../ability_manager_proxy_test.cpp | 716 +++ .../ability_manager_stub_mock.h | 304 ++ .../ability_manager_service_test/BUILD.gn | 66 + .../ability_manager_service_test.cpp | 2596 +++++++++++ .../phone/ability_manager_stub_test/BUILD.gn | 67 + .../ability_manager_stub_impl_mock.h | 287 ++ .../ability_manager_stub_test.cpp | 449 ++ .../phone/ability_manager_test/BUILD.gn | 86 + .../ability_manager_stub_mock.h | 100 + .../ability_manager_test.cpp | 330 ++ .../iservice_registry.cpp | 46 + .../system_ability_manager.cpp | 299 ++ .../system_ability_manager_stub.cpp | 155 + .../phone/ability_record_test/BUILD.gn | 65 + .../ability_record_test.cpp | 727 ++++ .../ability_scheduler_proxy_test/BUILD.gn | 68 + .../ability_scheduler_proxy_test.cpp | 281 ++ .../ability_scheduler_stub_test/BUILD.gn | 65 + .../ability_schedule_stub_mock.h | 136 + .../ability_scheduler_stub_test.cpp | 220 + .../phone/ability_service_start_test/BUILD.gn | 67 + .../ability_service_start_test.cpp | 158 + .../phone/ability_stack_manager_test/BUILD.gn | 69 + .../ability_stack_manager_test.cpp | 3157 ++++++++++++++ .../phone/ability_token_proxy_test/BUILD.gn | 65 + .../ability_token_proxy_test.cpp | 58 + .../phone/ability_token_stub_test/BUILD.gn | 65 + .../ability_token_stub_test.cpp | 72 + .../ability_with_applications_test/BUILD.gn | 68 + .../ability_with_applications_test.cpp | 362 ++ .../mock_ability_scheduler.cpp | 125 + .../phone/abilityms_appms_test/BUILD.gn | 68 + .../abilityms_appms_test.cpp | 284 ++ .../phone/app_scheduler_test/BUILD.gn | 67 + .../app_scheduler_test/app_scheduler_test.cpp | 468 ++ .../app_state_call_back_mock.h | 38 + .../phone/configuration_holder_test/BUILD.gn | 69 + .../configuration_holder_test.cpp | 123 + .../phone/connection_record_test/BUILD.gn | 66 + .../connection_record_test.cpp | 329 ++ .../phone/data_ability_manager_test/BUILD.gn | 75 + .../data_ability_manager_test.cpp | 482 +++ .../phone/data_ability_record_test/BUILD.gn | 73 + .../data_ability_record_test.cpp | 944 ++++ .../test/unittest/phone/info_test/BUILD.gn | 67 + .../unittest/phone/info_test/info_test.cpp | 311 ++ .../kernal_system_app_manager_test/BUILD.gn | 68 + .../kernal_system_app_manager_test.cpp | 638 +++ .../phone/lifecycle_deal_test/BUILD.gn | 67 + .../lifecycle_deal_test.cpp | 223 + .../unittest/phone/lifecycle_test/BUILD.gn | 67 + .../phone/lifecycle_test/lifecycle_test.cpp | 578 +++ .../lifecycle_test/lifecycle_test_base.h | 99 + .../phone/mission_record_test/BUILD.gn | 65 + .../mission_record_test.cpp | 387 ++ .../phone/mission_stack_test/BUILD.gn | 65 + .../mission_stack_test/mission_stack_test.cpp | 507 +++ .../phone/pending_want_key_test/BUILD.gn | 60 + .../pending_want_key_test.cpp | 197 + .../phone/pending_want_manager_test/BUILD.gn | 64 + .../pending_want_manager_test.cpp | 875 ++++ .../phone/pending_want_record_test/BUILD.gn | 64 + .../pending_want_record_test.cpp | 633 +++ .../resume_mission_container_test/BUILD.gn | 63 + .../resume_mission_container_test.cpp | 169 + .../unittest/phone/sender_info_test/BUILD.gn | 64 + .../sender_info_test/sender_info_test.cpp | 103 + .../phone/terminate_ability_test/BUILD.gn | 68 + .../terminate_ability_test.cpp | 797 ++++ .../phone/want_receiver_proxy_test/BUILD.gn | 65 + .../want_receiver_proxy_test.cpp | 91 + .../want_receiver_stub_mock.h | 49 + .../phone/want_receiver_stub_test/BUILD.gn | 66 + .../want_receiver_stub_impl_mock.h | 58 + .../want_receiver_stub_test.cpp | 208 + .../phone/want_sender_info_test/BUILD.gn | 64 + .../want_sender_info_test.cpp | 113 + .../phone/want_sender_proxy_test/BUILD.gn | 65 + .../want_sender_proxy_test.cpp | 71 + .../want_sender_stub_mock.h | 47 + .../phone/want_sender_stub_test/BUILD.gn | 66 + .../want_sender_stub_impl_mock.h | 56 + .../want_sender_stub_test.cpp | 154 + .../unittest/phone/wants_info_test/BUILD.gn | 65 + .../phone/wants_info_test/wants_info_test.cpp | 93 + .../unittest/phone/window_info_test/BUILD.gn | 53 + .../window_info_test/window_info_test.cpp | 66 + tools/services/common/BUILD.gn | 31 + tools/services/common/include/hilog_wrapper.h | 83 + tools/services/dataobsmgr/BUILD.gn | 70 + tools/services/dataobsmgr/dataobsms.gni | 22 + .../include/data_ability_observer_proxy.h | 42 + .../dataobsmgr/include/dataobs_mgr_inner.h | 74 + .../dataobsmgr/include/dataobs_mgr_proxy.h | 75 + .../dataobsmgr/include/dataobs_mgr_service.h | 74 + .../dataobsmgr/include/dataobs_mgr_stub.h | 50 + .../src/data_ability_observer_proxy.cpp | 61 + .../src/data_ability_observer_stub.cpp | 82 + .../dataobsmgr/src/dataobs_mgr_client.cpp | 133 + .../dataobsmgr/src/dataobs_mgr_inner.cpp | 257 ++ .../dataobsmgr/src/dataobs_mgr_proxy.cpp | 125 + .../dataobsmgr/src/dataobs_mgr_service.cpp | 213 + .../dataobsmgr/src/dataobs_mgr_stub.cpp | 112 + tools/services/dataobsmgr/test/BUILD.gn | 26 + .../libs/system_ability_mock/system_ability.h | 73 + .../data_ability_observer_proxy_test/BUILD.gn | 53 + .../data_ability_observer_proxy_test.cpp | 67 + .../mock_data_obs_manager_onchange_callback.h | 54 + .../data_ability_observer_stub_test/BUILD.gn | 53 + .../data_ability_observer_stub_test.cpp | 94 + .../mock_data_obs_manager_onchange_callback.h | 54 + .../phone/dataobs_mgr_client_test/BUILD.gn | 57 + .../dataobs_mgr_client_test.cpp | 129 + .../mock_data_obs_manager_onchange_callback.h | 54 + .../mock_dataobs_mgr_client.h | 69 + .../mock_dataobs_mgr_service.h | 111 + .../phone/dataobs_mgr_inner_test/BUILD.gn | 53 + .../dataobs_mgr_inner_test.cpp | 175 + .../mock_data_ability_observer_stub.h | 51 + .../phone/dataobs_mgr_proxy_test/BUILD.gn | 53 + .../dataobs_mgr_proxy_test.cpp | 128 + .../mock_data_obs_mgr_stub.h | 54 + .../phone/dataobs_mgr_service_test/BUILD.gn | 54 + .../dataobs_mgr_service_test.cpp | 195 + .../mock_data_ability_observer_stub.h | 35 + .../phone/dataobs_mgr_stub_test/BUILD.gn | 53 + .../dataobs_mgr_stub_test.cpp | 214 + .../mock_data_obs_mgr_stub.h | 53 + tools/services/test/BUILD.gn | 45 + .../include/mock_ability_connect_callback.h | 40 + .../mock_ability_connect_callback_stub.h | 53 + .../mock/include/mock_ability_manager_proxy.h | 84 + .../mock/include/mock_ability_mgr_service.h | 109 + .../mock/include/mock_ability_scheduler.h | 112 + .../include/mock_ability_scheduler_stub.h | 57 + .../test/mock/include/mock_app_mgr_client.h | 44 + .../test/mock/include/mock_app_scheduler.h | 46 + .../test/mock/include/mock_bundle_mgr.h | 360 ++ .../test/mock/include/mock_compled_callback.h | 29 + .../services/test/mock/include/mock_context.h | 101 + .../test/mock/include/mock_want_receiver.h | 35 + .../test/mock/include/system_ability.h | 68 + .../test/mock/src/mock_app_mgr_client.cpp | 44 + .../test/mock/src/mock_bundle_mgr.cpp | 174 + .../ability_mgr_service_test/BUILD.gn | 118 + .../ability_mgr_module_test.cpp | 1688 ++++++++ .../moduletest/ability_record_test/BUILD.gn | 121 + .../ability_record_module_test.cpp | 711 +++ .../moduletest/ability_stack_test/BUILD.gn | 117 + .../ability_stack_module_test.cpp | 3610 ++++++++++++++++ .../test/moduletest/dump_module_test/BUILD.gn | 71 + .../dump_module_test/dump_module_test.cpp | 664 +++ .../ipc_ability_connect_test/BUILD.gn | 50 + .../ipc_ability_connect_module_test.cpp | 110 + .../moduletest/ipc_ability_mgr_test/BUILD.gn | 55 + .../ipc_ability_mgr_module_test.cpp | 612 +++ .../ipc_ability_scheduler_test/BUILD.gn | 74 + .../ipc_ability_scheduler_module_test.cpp | 560 +++ .../moduletest/module_test_dump_util/BUILD.gn | 37 + .../module_test_dump_util.cpp | 163 + .../module_test_dump_util.h | 104 + .../panding_want_manager_test/BUILD.gn | 88 + .../panding_want_manager_test.cpp | 734 ++++ .../tools/aa/dataAbilityBundleForDump.hap | Bin 0 -> 20734 bytes .../tools/aa/pageAbilityBundleForDump.hap | Bin 0 -> 20613 bytes .../tools/aa/pageAbilityBundleForStart.hap | Bin 0 -> 20626 bytes .../tools/aa/serviceAbilityBundleForStart.hap | Bin 0 -> 108920 bytes .../tools/aa/serviceAbilityBundleForStop.hap | Bin 0 -> 108917 bytes tools/test/resource/tools/ohos_test.xml | 35 + tools/zip/include/checked_cast.h | 34 +- tools/zip/include/zip_reader.h | 10 +- tools/zip/kits/js/@ohos.zlib.d.ts | 30 +- tools/zip/kits/napi/napi_zlib.cpp | 32 +- tools/zip/src/zip_internal.cpp | 16 +- tools/zip/src/zip_writer.cpp | 6 - 749 files changed, 167233 insertions(+), 295 deletions(-) create mode 100644 frameworks/kits/ability/native/include/continuation/distributed/ability_distributed_connect_callback_stub.h create mode 100644 frameworks/kits/ability/native/include/continuation/distributed/ability_distributed_connection.h create mode 100644 frameworks/kits/ability/native/src/continuation/distributed/ability_distributed_connect_callback_stub.cpp create mode 100644 frameworks/kits/ability/native/src/continuation/distributed/ability_distributed_connection.cpp create mode 100644 interfaces/innerkits/ability_manager/include/continuation/ability_distributed_connection_interface.h create mode 100644 sa_profile/182.xml create mode 100644 tools/LICENSE create mode 100644 tools/OAT.xml create mode 100755 tools/README_zh.md create mode 100644 tools/aafwk.gni create mode 100755 tools/figures/aafwk.png create mode 100755 tools/figures/page-ability-lifecycle-callbacks.png create mode 100755 tools/figures/page-ability-lifecycle.png create mode 100755 tools/figures/service-ability-lifecycle-callbacks.jpg create mode 100755 tools/figures/service-ability-lifecycle.png create mode 100755 tools/frameworks/kits/ability/native/BUILD.gn create mode 100755 tools/frameworks/kits/ability/native/include/ability.h create mode 100755 tools/frameworks/kits/ability/native/include/ability_context.h create mode 100644 tools/frameworks/kits/ability/native/include/ability_event_interface.h create mode 100644 tools/frameworks/kits/ability/native/include/ability_handler.h create mode 100644 tools/frameworks/kits/ability/native/include/ability_impl.h create mode 100644 tools/frameworks/kits/ability/native/include/ability_impl_factory.h create mode 100644 tools/frameworks/kits/ability/native/include/ability_keyevent.h create mode 100644 tools/frameworks/kits/ability/native/include/ability_lifecycle.h create mode 100644 tools/frameworks/kits/ability/native/include/ability_lifecycle_callbacks.h create mode 100644 tools/frameworks/kits/ability/native/include/ability_lifecycle_executor.h create mode 100644 tools/frameworks/kits/ability/native/include/ability_lifecycle_interface.h create mode 100644 tools/frameworks/kits/ability/native/include/ability_lifecycle_observer.h create mode 100644 tools/frameworks/kits/ability/native/include/ability_lifecycle_observer_interface.h create mode 100644 tools/frameworks/kits/ability/native/include/ability_loader.h create mode 100644 tools/frameworks/kits/ability/native/include/ability_local_record.h create mode 100644 tools/frameworks/kits/ability/native/include/ability_post_event_timeout.h create mode 100755 tools/frameworks/kits/ability/native/include/ability_process.h create mode 100644 tools/frameworks/kits/ability/native/include/ability_state.h create mode 100644 tools/frameworks/kits/ability/native/include/ability_thread.h create mode 100644 tools/frameworks/kits/ability/native/include/ability_touchevent.h create mode 100644 tools/frameworks/kits/ability/native/include/ability_window.h create mode 100644 tools/frameworks/kits/ability/native/include/continuation/distributed/ability_distributed_connect_callback_stub.h create mode 100644 tools/frameworks/kits/ability/native/include/continuation/distributed/ability_distributed_connection.h create mode 100644 tools/frameworks/kits/ability/native/include/continuation/distributed/continuation_handler.h create mode 100644 tools/frameworks/kits/ability/native/include/continuation/distributed/continuation_manager.h create mode 100644 tools/frameworks/kits/ability/native/include/continuation/distributed/continuation_scheduler.h create mode 100644 tools/frameworks/kits/ability/native/include/continuation/distributed/continuation_scheduler_interface.h create mode 100644 tools/frameworks/kits/ability/native/include/continuation/distributed/continuation_scheduler_stub.h create mode 100644 tools/frameworks/kits/ability/native/include/continuation/distributed/distribute_schedule_handler_interface.h create mode 100644 tools/frameworks/kits/ability/native/include/continuation/distributed/distributed_client.h create mode 100644 tools/frameworks/kits/ability/native/include/continuation/distributed/distributed_errors.h create mode 100644 tools/frameworks/kits/ability/native/include/continuation/distributed/progress_state.h create mode 100644 tools/frameworks/kits/ability/native/include/continuation/distributed/reverse_continuation_scheduler_primary.h create mode 100644 tools/frameworks/kits/ability/native/include/continuation/distributed/reverse_continuation_scheduler_primary_handler_interface.h create mode 100644 tools/frameworks/kits/ability/native/include/continuation/distributed/reverse_continuation_scheduler_primary_interface.h create mode 100644 tools/frameworks/kits/ability/native/include/continuation/distributed/reverse_continuation_scheduler_primary_proxy.h create mode 100644 tools/frameworks/kits/ability/native/include/continuation/distributed/reverse_continuation_scheduler_primary_stub.h create mode 100644 tools/frameworks/kits/ability/native/include/continuation/distributed/reverse_continuation_scheduler_recipient.h create mode 100644 tools/frameworks/kits/ability/native/include/continuation/distributed/reverse_continuation_scheduler_replica.h create mode 100644 tools/frameworks/kits/ability/native/include/continuation/distributed/reverse_continuation_scheduler_replica_handler_interface.h create mode 100644 tools/frameworks/kits/ability/native/include/continuation/distributed/reverse_continuation_scheduler_replica_interface.h create mode 100644 tools/frameworks/kits/ability/native/include/continuation/distributed/reverse_continuation_scheduler_replica_proxy.h create mode 100644 tools/frameworks/kits/ability/native/include/continuation/distributed/reverse_continuation_scheduler_replica_stub.h create mode 100644 tools/frameworks/kits/ability/native/include/continuation/kits/ability_continuation_interface.h create mode 100644 tools/frameworks/kits/ability/native/include/continuation/kits/continuation_device_callback_interface.h create mode 100644 tools/frameworks/kits/ability/native/include/continuation/kits/continuation_register_manager_interface.h create mode 100644 tools/frameworks/kits/ability/native/include/continuation/kits/continuation_state.h create mode 100644 tools/frameworks/kits/ability/native/include/continuation/kits/device_connect_state.h create mode 100644 tools/frameworks/kits/ability/native/include/continuation/kits/request_callback.h create mode 100644 tools/frameworks/kits/ability/native/include/continuation/remote_register_service/connect_callback_proxy.h create mode 100644 tools/frameworks/kits/ability/native/include/continuation/remote_register_service/connect_callback_stub.h create mode 100644 tools/frameworks/kits/ability/native/include/continuation/remote_register_service/continuation_connector.h create mode 100644 tools/frameworks/kits/ability/native/include/continuation/remote_register_service/continuation_device_callback_proxy.h create mode 100644 tools/frameworks/kits/ability/native/include/continuation/remote_register_service/continuation_register_manager.h create mode 100644 tools/frameworks/kits/ability/native/include/continuation/remote_register_service/continuation_register_manager_proxy.h create mode 100644 tools/frameworks/kits/ability/native/include/continuation/remote_register_service/continuation_request.h create mode 100644 tools/frameworks/kits/ability/native/include/continuation/remote_register_service/remote_register_service_proxy.h create mode 100644 tools/frameworks/kits/ability/native/include/continuation/remote_register_service/remote_register_service_stub.h create mode 100644 tools/frameworks/kits/ability/native/include/data_ability_helper.h create mode 100644 tools/frameworks/kits/ability/native/include/data_ability_impl.h create mode 100644 tools/frameworks/kits/ability/native/include/data_ability_operation.h create mode 100644 tools/frameworks/kits/ability/native/include/data_ability_operation_builder.h create mode 100644 tools/frameworks/kits/ability/native/include/data_ability_result.h create mode 100644 tools/frameworks/kits/ability/native/include/data_uri_utils.h create mode 100644 tools/frameworks/kits/ability/native/include/dummy_ability_package.h create mode 100644 tools/frameworks/kits/ability/native/include/dummy_component_container.h create mode 100644 tools/frameworks/kits/ability/native/include/dummy_continuation_state.h create mode 100644 tools/frameworks/kits/ability/native/include/dummy_data_ability_predicates.h create mode 100644 tools/frameworks/kits/ability/native/include/dummy_notification_request.h create mode 100644 tools/frameworks/kits/ability/native/include/dummy_result_set.h create mode 100644 tools/frameworks/kits/ability/native/include/dummy_values_bucket.h create mode 100755 tools/frameworks/kits/ability/native/include/form_js_event_handler.h create mode 100755 tools/frameworks/kits/ability/native/include/form_provider_client.h create mode 100644 tools/frameworks/kits/ability/native/include/iability_lifecycle_callback.h create mode 100644 tools/frameworks/kits/ability/native/include/ipc_singleton.h create mode 100644 tools/frameworks/kits/ability/native/include/mission_information.h create mode 100644 tools/frameworks/kits/ability/native/include/page_ability_impl.h create mode 100644 tools/frameworks/kits/ability/native/include/service_ability_impl.h create mode 100755 tools/frameworks/kits/ability/native/src/ability.cpp create mode 100755 tools/frameworks/kits/ability/native/src/ability_context.cpp create mode 100644 tools/frameworks/kits/ability/native/src/ability_handler.cpp create mode 100644 tools/frameworks/kits/ability/native/src/ability_impl.cpp create mode 100644 tools/frameworks/kits/ability/native/src/ability_impl_factory.cpp create mode 100644 tools/frameworks/kits/ability/native/src/ability_keyevent.cpp create mode 100644 tools/frameworks/kits/ability/native/src/ability_lifecycle.cpp create mode 100644 tools/frameworks/kits/ability/native/src/ability_lifecycle_executor.cpp create mode 100644 tools/frameworks/kits/ability/native/src/ability_lifecycle_observer.cpp create mode 100644 tools/frameworks/kits/ability/native/src/ability_loader.cpp create mode 100644 tools/frameworks/kits/ability/native/src/ability_local_record.cpp create mode 100644 tools/frameworks/kits/ability/native/src/ability_post_event_timeout.cpp create mode 100755 tools/frameworks/kits/ability/native/src/ability_process.cpp create mode 100644 tools/frameworks/kits/ability/native/src/ability_thread.cpp create mode 100644 tools/frameworks/kits/ability/native/src/ability_touchevent.cpp create mode 100755 tools/frameworks/kits/ability/native/src/ability_window.cpp create mode 100644 tools/frameworks/kits/ability/native/src/continuation/distributed/ability_distributed_connect_callback_stub.cpp create mode 100644 tools/frameworks/kits/ability/native/src/continuation/distributed/ability_distributed_connection.cpp create mode 100755 tools/frameworks/kits/ability/native/src/continuation/distributed/continuation_handler.cpp create mode 100644 tools/frameworks/kits/ability/native/src/continuation/distributed/continuation_manager.cpp create mode 100644 tools/frameworks/kits/ability/native/src/continuation/distributed/continuation_scheduler.cpp create mode 100644 tools/frameworks/kits/ability/native/src/continuation/distributed/continuation_scheduler_stub.cpp create mode 100755 tools/frameworks/kits/ability/native/src/continuation/distributed/distributed_client.cpp create mode 100644 tools/frameworks/kits/ability/native/src/continuation/distributed/reverse_continuation_scheduler_primary.cpp create mode 100644 tools/frameworks/kits/ability/native/src/continuation/distributed/reverse_continuation_scheduler_primary_proxy.cpp create mode 100644 tools/frameworks/kits/ability/native/src/continuation/distributed/reverse_continuation_scheduler_primary_stub.cpp create mode 100644 tools/frameworks/kits/ability/native/src/continuation/distributed/reverse_continuation_scheduler_recipient.cpp create mode 100644 tools/frameworks/kits/ability/native/src/continuation/distributed/reverse_continuation_scheduler_replica.cpp create mode 100755 tools/frameworks/kits/ability/native/src/continuation/distributed/reverse_continuation_scheduler_replica_proxy.cpp create mode 100644 tools/frameworks/kits/ability/native/src/continuation/distributed/reverse_continuation_scheduler_replica_stub.cpp create mode 100644 tools/frameworks/kits/ability/native/src/continuation/remote_register_service/connect_callback_proxy.cpp create mode 100644 tools/frameworks/kits/ability/native/src/continuation/remote_register_service/connect_callback_stub.cpp create mode 100644 tools/frameworks/kits/ability/native/src/continuation/remote_register_service/continuation_connector.cpp create mode 100644 tools/frameworks/kits/ability/native/src/continuation/remote_register_service/continuation_device_callback_proxy.cpp create mode 100644 tools/frameworks/kits/ability/native/src/continuation/remote_register_service/continuation_register_manager.cpp create mode 100644 tools/frameworks/kits/ability/native/src/continuation/remote_register_service/continuation_register_manager_proxy.cpp create mode 100644 tools/frameworks/kits/ability/native/src/continuation/remote_register_service/remote_register_service_proxy.cpp create mode 100644 tools/frameworks/kits/ability/native/src/continuation/remote_register_service/remote_register_service_stub.cpp create mode 100644 tools/frameworks/kits/ability/native/src/data_ability_helper.cpp create mode 100644 tools/frameworks/kits/ability/native/src/data_ability_impl.cpp create mode 100644 tools/frameworks/kits/ability/native/src/data_ability_operation.cpp create mode 100644 tools/frameworks/kits/ability/native/src/data_ability_operation_builder.cpp create mode 100644 tools/frameworks/kits/ability/native/src/data_ability_result.cpp create mode 100644 tools/frameworks/kits/ability/native/src/data_uri_utils.cpp create mode 100644 tools/frameworks/kits/ability/native/src/dummy_data_ability_predicates.cpp create mode 100644 tools/frameworks/kits/ability/native/src/dummy_data_ability_predicates_discard.cpp create mode 100644 tools/frameworks/kits/ability/native/src/dummy_result_set.cpp create mode 100644 tools/frameworks/kits/ability/native/src/dummy_result_set_discard.cpp create mode 100644 tools/frameworks/kits/ability/native/src/dummy_values_bucket.cpp create mode 100644 tools/frameworks/kits/ability/native/src/dummy_values_bucket_discard.cpp create mode 100644 tools/frameworks/kits/ability/native/src/form_js_event_handler.cpp create mode 100755 tools/frameworks/kits/ability/native/src/form_provider_client.cpp create mode 100644 tools/frameworks/kits/ability/native/src/mission_information.cpp create mode 100755 tools/frameworks/kits/ability/native/src/page_ability_impl.cpp create mode 100644 tools/frameworks/kits/ability/native/src/service_ability_impl.cpp create mode 100644 tools/frameworks/kits/ability/native/src/task_handler.cpp create mode 100644 tools/frameworks/kits/ability/native/src/task_handler_client.cpp create mode 100755 tools/frameworks/kits/ability/native/test/BUILD.gn create mode 100644 tools/frameworks/kits/ability/native/test/mock/include/bundle_mgr_interface.h create mode 100644 tools/frameworks/kits/ability/native/test/mock/include/mock_ability.cpp create mode 100644 tools/frameworks/kits/ability/native/test/mock/include/mock_ability_impl.h create mode 100755 tools/frameworks/kits/ability/native/test/mock/include/mock_ability_manager_client.cpp create mode 100644 tools/frameworks/kits/ability/native/test/mock/include/mock_ability_manager_client.h create mode 100644 tools/frameworks/kits/ability/native/test/mock/include/mock_ability_manager_client_for_data_ability_observer.h create mode 100644 tools/frameworks/kits/ability/native/test/mock/include/mock_ability_manager_client_interface1.cpp create mode 100644 tools/frameworks/kits/ability/native/test/mock/include/mock_ability_manager_client_interface1.h create mode 100755 tools/frameworks/kits/ability/native/test/mock/include/mock_ability_manager_clientex.cpp create mode 100644 tools/frameworks/kits/ability/native/test/mock/include/mock_ability_manager_service.cpp create mode 100755 tools/frameworks/kits/ability/native/test/mock/include/mock_ability_manager_service.h create mode 100644 tools/frameworks/kits/ability/native/test/mock/include/mock_ability_scheduler_for_observer.h create mode 100644 tools/frameworks/kits/ability/native/test/mock/include/mock_ability_thread.h create mode 100644 tools/frameworks/kits/ability/native/test/mock/include/mock_ability_thread_for_ability_on_configuration_update.h create mode 100644 tools/frameworks/kits/ability/native/test/mock/include/mock_ability_token.h create mode 100644 tools/frameworks/kits/ability/native/test/mock/include/mock_bundle_manager.cpp create mode 100644 tools/frameworks/kits/ability/native/test/mock/include/mock_bundle_manager.h create mode 100644 tools/frameworks/kits/ability/native/test/mock/include/mock_bundle_manager_form.cpp create mode 100644 tools/frameworks/kits/ability/native/test/mock/include/mock_bundle_manager_form.h create mode 100644 tools/frameworks/kits/ability/native/test/mock/include/mock_data_ability.h create mode 100644 tools/frameworks/kits/ability/native/test/mock/include/mock_data_ability_impl.cpp create mode 100755 tools/frameworks/kits/ability/native/test/mock/include/mock_form_mgr_service.h create mode 100644 tools/frameworks/kits/ability/native/test/mock/include/mock_form_supply_callback.cpp create mode 100644 tools/frameworks/kits/ability/native/test/mock/include/mock_form_supply_callback.h create mode 100644 tools/frameworks/kits/ability/native/test/mock/include/mock_lifecycle_observer.h create mode 100644 tools/frameworks/kits/ability/native/test/mock/include/mock_page_ability.h create mode 100644 tools/frameworks/kits/ability/native/test/mock/include/mock_replace_ability_impl.cpp create mode 100644 tools/frameworks/kits/ability/native/test/mock/include/mock_resourceManager_interface1.cpp create mode 100644 tools/frameworks/kits/ability/native/test/mock/include/mock_resourceManager_interface1.h create mode 100644 tools/frameworks/kits/ability/native/test/mock/include/mock_service_ability.h create mode 100644 tools/frameworks/kits/ability/native/test/mock/include/sys_mgr_client_mock.cpp create mode 100644 tools/frameworks/kits/ability/native/test/unittest/ability_context_for_task_dispacher_test.cpp create mode 100644 tools/frameworks/kits/ability/native/test/unittest/ability_context_interface1_test.cpp create mode 100644 tools/frameworks/kits/ability/native/test/unittest/ability_context_test.cpp create mode 100644 tools/frameworks/kits/ability/native/test/unittest/ability_impl_active_test.cpp create mode 100644 tools/frameworks/kits/ability/native/test/unittest/ability_impl_test.cpp create mode 100644 tools/frameworks/kits/ability/native/test/unittest/ability_lifecycle_executor_test.cpp create mode 100644 tools/frameworks/kits/ability/native/test/unittest/ability_lifecycle_test.cpp create mode 100755 tools/frameworks/kits/ability/native/test/unittest/ability_permission_test.cpp create mode 100755 tools/frameworks/kits/ability/native/test/unittest/ability_test.cpp create mode 100644 tools/frameworks/kits/ability/native/test/unittest/ability_thread_dataability_test.cpp create mode 100644 tools/frameworks/kits/ability/native/test/unittest/ability_thread_for_ability_on_configuration_update.cpp create mode 100644 tools/frameworks/kits/ability/native/test/unittest/ability_thread_test.cpp create mode 100644 tools/frameworks/kits/ability/native/test/unittest/data_ability_helper_test.cpp create mode 100644 tools/frameworks/kits/ability/native/test/unittest/data_ability_impl_file_secondpart_test.cpp create mode 100644 tools/frameworks/kits/ability/native/test/unittest/data_ability_impl_file_test.cpp create mode 100644 tools/frameworks/kits/ability/native/test/unittest/data_ability_impl_test.cpp create mode 100644 tools/frameworks/kits/ability/native/test/unittest/data_ability_operation_test.cpp create mode 100644 tools/frameworks/kits/ability/native/test/unittest/data_ability_result_test.cpp create mode 100644 tools/frameworks/kits/ability/native/test/unittest/data_uri_utils_test.cpp create mode 100755 tools/frameworks/kits/ability/native/test/unittest/form_ability_test.cpp create mode 100644 tools/frameworks/kits/ability/native/test/unittest/form_host_client_test.cpp create mode 100644 tools/frameworks/kits/ability/native/test/unittest/form_provider_client_test.cpp create mode 100755 tools/frameworks/kits/ability/native/test/unittest/pac_map_test.cpp create mode 100644 tools/frameworks/kits/ability/native/test/unittest/page_ability_impl_test.cpp create mode 100644 tools/frameworks/kits/ability/native/test/unittest/service_ability_impl_test.cpp create mode 100644 tools/frameworks/kits/ability/native/test/unittest/task_handler_client_test.cpp create mode 100644 tools/frameworks/kits/base/cpp/src/ohos/aafwk/base/array_wrapper.cpp create mode 100755 tools/frameworks/kits/base/cpp/src/ohos/aafwk/base/base.cpp create mode 100644 tools/frameworks/kits/base/cpp/src/ohos/aafwk/base/base_object.cpp create mode 100644 tools/frameworks/kits/base/cpp/src/ohos/aafwk/base/bool_wrapper.cpp create mode 100644 tools/frameworks/kits/base/cpp/src/ohos/aafwk/base/byte_wrapper.cpp create mode 100644 tools/frameworks/kits/base/cpp/src/ohos/aafwk/base/double_wrapper.cpp create mode 100644 tools/frameworks/kits/base/cpp/src/ohos/aafwk/base/float_wrapper.cpp create mode 100644 tools/frameworks/kits/base/cpp/src/ohos/aafwk/base/int_wrapper.cpp create mode 100644 tools/frameworks/kits/base/cpp/src/ohos/aafwk/base/long_wrapper.cpp create mode 100644 tools/frameworks/kits/base/cpp/src/ohos/aafwk/base/short_wrapper.cpp create mode 100644 tools/frameworks/kits/base/cpp/src/ohos/aafwk/base/string_wrapper.cpp create mode 100755 tools/frameworks/kits/base/cpp/src/ohos/aafwk/base/user_object_wrapper.cpp create mode 100644 tools/frameworks/kits/base/cpp/src/ohos/aafwk/base/zchar_wrapper.cpp create mode 100644 tools/frameworks/kits/base/cpp/test/BUILD.gn create mode 100644 tools/frameworks/kits/base/cpp/test/unittest/common/base_test.cpp create mode 100755 tools/frameworks/kits/content/cpp/src/ohos/aafwk/content/extra_params.cpp create mode 100644 tools/frameworks/kits/content/cpp/src/ohos/aafwk/content/intent.cpp create mode 100644 tools/frameworks/kits/content/cpp/src/ohos/aafwk/content/intent_filter.cpp create mode 100755 tools/frameworks/kits/content/cpp/src/ohos/aafwk/content/intent_params.cpp create mode 100755 tools/frameworks/kits/content/cpp/src/ohos/aafwk/content/operation.cpp create mode 100644 tools/frameworks/kits/content/cpp/src/ohos/aafwk/content/operation_builder.cpp create mode 100755 tools/frameworks/kits/content/cpp/src/ohos/aafwk/content/pac_map.cpp create mode 100755 tools/frameworks/kits/content/cpp/src/ohos/aafwk/content/patterns_matcher.cpp create mode 100755 tools/frameworks/kits/content/cpp/src/ohos/aafwk/content/skills.cpp create mode 100755 tools/frameworks/kits/content/cpp/src/ohos/aafwk/content/want.cpp create mode 100755 tools/frameworks/kits/content/cpp/src/ohos/aafwk/content/want_params.cpp create mode 100755 tools/frameworks/kits/content/cpp/src/ohos/aafwk/content/want_params_wrapper.cpp create mode 100755 tools/frameworks/kits/content/cpp/src/ohos/aafwk/content/want_params_wrapper.h create mode 100755 tools/frameworks/kits/content/cpp/test/BUILD.gn create mode 100644 tools/frameworks/kits/content/cpp/test/unittest/common/intent_filter_test.cpp create mode 100644 tools/frameworks/kits/content/cpp/test/unittest/common/intent_parameters_test.cpp create mode 100755 tools/frameworks/kits/content/cpp/test/unittest/common/operation_test.cpp create mode 100755 tools/frameworks/kits/content/cpp/test/unittest/common/patterns_matcher_test.cpp create mode 100755 tools/frameworks/kits/content/cpp/test/unittest/common/skills_test.cpp create mode 100644 tools/frameworks/kits/content/cpp/test/unittest/common/want_params_test.cpp create mode 100755 tools/frameworks/kits/content/cpp/test/unittest/common/want_params_wrapper_test.cpp create mode 100755 tools/frameworks/kits/content/cpp/test/unittest/common/want_test.cpp create mode 100755 tools/frameworks/kits/test/BUILD.gn create mode 100755 tools/frameworks/kits/test/mock/AMS/mock_ability_manager_client.cpp create mode 100644 tools/frameworks/kits/test/mock/AMS/mock_ability_manager_service.cpp create mode 100644 tools/frameworks/kits/test/mock/AMS/mock_ability_manager_service.h create mode 100644 tools/frameworks/kits/test/mock/AMS/mock_serviceability_manager_service.cpp create mode 100644 tools/frameworks/kits/test/mock/AMS/mock_serviceability_manager_service.h create mode 100644 tools/frameworks/kits/test/mock/DemoAbility/demo_ability_test.cpp create mode 100644 tools/frameworks/kits/test/mock/DemoAbility/demo_ability_test.h create mode 100644 tools/frameworks/kits/test/mock/DemoAbility/mock_ability_test.h create mode 100644 tools/frameworks/kits/test/mock/DemoAbility/mock_lifecycle_observer.cpp create mode 100644 tools/frameworks/kits/test/mock/DemoAbility/mock_lifecycle_observer.h create mode 100644 tools/frameworks/kits/test/mock/DemoObServer/mock_ability_hancle_for_data_observer.h create mode 100644 tools/frameworks/kits/test/mock/DemoObServer/mock_ability_manager_client.h create mode 100644 tools/frameworks/kits/test/mock/DemoObServer/mock_ability_thread_for_data_observer.h create mode 100644 tools/frameworks/kits/test/moduletest/cpp/abilitytest/ability_context_test.cpp create mode 100755 tools/frameworks/kits/test/moduletest/cpp/abilitytest/ability_test.cpp create mode 100644 tools/frameworks/kits/test/moduletest/cpp/abilitytest/data_ability_helper_module_test.cpp create mode 100644 tools/frameworks/kits/test/moduletest/cpp/abilitytest/data_ability_operation_module_test.cpp create mode 100644 tools/interfaces/innerkits/BUILD.gn create mode 100755 tools/interfaces/innerkits/ability_manager/BUILD.gn create mode 100644 tools/interfaces/innerkits/ability_manager/ability_manager_headers.gni create mode 100644 tools/interfaces/innerkits/ability_manager/include/aafwk_dummy_configuration.h create mode 100644 tools/interfaces/innerkits/ability_manager/include/ability_connect_callback_interface.h create mode 100644 tools/interfaces/innerkits/ability_manager/include/ability_connect_callback_stub.h create mode 100644 tools/interfaces/innerkits/ability_manager/include/ability_manager_client.h create mode 100644 tools/interfaces/innerkits/ability_manager/include/ability_manager_errors.h create mode 100644 tools/interfaces/innerkits/ability_manager/include/ability_manager_interface.h create mode 100644 tools/interfaces/innerkits/ability_manager/include/ability_mission_info.h create mode 100644 tools/interfaces/innerkits/ability_manager/include/ability_record_info.h create mode 100644 tools/interfaces/innerkits/ability_manager/include/ability_scheduler_interface.h create mode 100644 tools/interfaces/innerkits/ability_manager/include/ability_start_setting.h create mode 100644 tools/interfaces/innerkits/ability_manager/include/ability_window_configuration.h create mode 100644 tools/interfaces/innerkits/ability_manager/include/caller_info.h create mode 100644 tools/interfaces/innerkits/ability_manager/include/continuation/ability_distributed_connection_interface.h create mode 100644 tools/interfaces/innerkits/ability_manager/include/continuation/connect_callback_interface.h create mode 100644 tools/interfaces/innerkits/ability_manager/include/continuation/remote_register_service_interface.h create mode 100644 tools/interfaces/innerkits/ability_manager/include/image_info.h create mode 100644 tools/interfaces/innerkits/ability_manager/include/lifecycle_state_info.h create mode 100644 tools/interfaces/innerkits/ability_manager/include/mission_description_info.h create mode 100644 tools/interfaces/innerkits/ability_manager/include/mission_option.h create mode 100644 tools/interfaces/innerkits/ability_manager/include/mission_record_info.h create mode 100644 tools/interfaces/innerkits/ability_manager/include/mission_snapshot_info.h create mode 100644 tools/interfaces/innerkits/ability_manager/include/mission_stack_info.h create mode 100644 tools/interfaces/innerkits/ability_manager/include/sender_info.h create mode 100644 tools/interfaces/innerkits/ability_manager/include/stack_info.h create mode 100644 tools/interfaces/innerkits/ability_manager/include/stack_setting.h create mode 100644 tools/interfaces/innerkits/ability_manager/include/task_handler.h create mode 100644 tools/interfaces/innerkits/ability_manager/include/task_handler_client.h create mode 100644 tools/interfaces/innerkits/ability_manager/include/want_receiver_interface.h create mode 100644 tools/interfaces/innerkits/ability_manager/include/want_sender_info.h create mode 100644 tools/interfaces/innerkits/ability_manager/include/want_sender_interface.h create mode 100644 tools/interfaces/innerkits/ability_manager/include/wants_info.h create mode 100755 tools/interfaces/innerkits/base/BUILD.gn create mode 100644 tools/interfaces/innerkits/base/include/ohos/aafwk/base/array_wrapper.h create mode 100644 tools/interfaces/innerkits/base/include/ohos/aafwk/base/base_def.h create mode 100755 tools/interfaces/innerkits/base/include/ohos/aafwk/base/base_interfaces.h create mode 100644 tools/interfaces/innerkits/base/include/ohos/aafwk/base/base_object.h create mode 100644 tools/interfaces/innerkits/base/include/ohos/aafwk/base/base_types.h create mode 100644 tools/interfaces/innerkits/base/include/ohos/aafwk/base/bool_wrapper.h create mode 100644 tools/interfaces/innerkits/base/include/ohos/aafwk/base/byte_wrapper.h create mode 100644 tools/interfaces/innerkits/base/include/ohos/aafwk/base/double_wrapper.h create mode 100644 tools/interfaces/innerkits/base/include/ohos/aafwk/base/float_wrapper.h create mode 100644 tools/interfaces/innerkits/base/include/ohos/aafwk/base/int_wrapper.h create mode 100644 tools/interfaces/innerkits/base/include/ohos/aafwk/base/ipc_singleton.h create mode 100644 tools/interfaces/innerkits/base/include/ohos/aafwk/base/light_refbase.h create mode 100644 tools/interfaces/innerkits/base/include/ohos/aafwk/base/long_wrapper.h create mode 100644 tools/interfaces/innerkits/base/include/ohos/aafwk/base/short_wrapper.h create mode 100644 tools/interfaces/innerkits/base/include/ohos/aafwk/base/string_wrapper.h create mode 100755 tools/interfaces/innerkits/base/include/ohos/aafwk/base/user_object_base.h create mode 100755 tools/interfaces/innerkits/base/include/ohos/aafwk/base/user_object_wrapper.h create mode 100644 tools/interfaces/innerkits/base/include/ohos/aafwk/base/zchar_wrapper.h create mode 100644 tools/interfaces/innerkits/dataobs_manager/BUILD.gn create mode 100644 tools/interfaces/innerkits/dataobs_manager/dataobs_manager_headers.gni create mode 100644 tools/interfaces/innerkits/dataobs_manager/include/data_ability_observer_interface.h create mode 100644 tools/interfaces/innerkits/dataobs_manager/include/data_ability_observer_stub.h create mode 100644 tools/interfaces/innerkits/dataobs_manager/include/dataobs_mgr_client.h create mode 100644 tools/interfaces/innerkits/dataobs_manager/include/dataobs_mgr_errors.h create mode 100644 tools/interfaces/innerkits/dataobs_manager/include/dataobs_mgr_interface.h create mode 100644 tools/interfaces/innerkits/intent/BUILD.gn create mode 100644 tools/interfaces/innerkits/intent/include/ohos/aafwk/content/intent.h create mode 100644 tools/interfaces/innerkits/intent/include/ohos/aafwk/content/intent_filter.h create mode 100644 tools/interfaces/innerkits/intent/include/ohos/aafwk/content/intent_params.h create mode 100755 tools/interfaces/innerkits/want/BUILD.gn create mode 100644 tools/interfaces/innerkits/want/include/ohos/aafwk/content/extra_params.h create mode 100755 tools/interfaces/innerkits/want/include/ohos/aafwk/content/match_type.h create mode 100644 tools/interfaces/innerkits/want/include/ohos/aafwk/content/operation.h create mode 100644 tools/interfaces/innerkits/want/include/ohos/aafwk/content/operation_builder.h create mode 100755 tools/interfaces/innerkits/want/include/ohos/aafwk/content/pac_map.h create mode 100644 tools/interfaces/innerkits/want/include/ohos/aafwk/content/patterns_matcher.h create mode 100755 tools/interfaces/innerkits/want/include/ohos/aafwk/content/skills.h create mode 100755 tools/interfaces/innerkits/want/include/ohos/aafwk/content/want.h create mode 100755 tools/interfaces/innerkits/want/include/ohos/aafwk/content/want_params.h create mode 100644 tools/interfaces/kits/js/@ohos.ability.dataUriUtils.d.ts create mode 100644 tools/interfaces/kits/js/@ohos.ability.featureAbility.d.ts create mode 100644 tools/interfaces/kits/js/@ohos.ability.formmanager.d.ts create mode 100644 tools/interfaces/kits/js/@ohos.ability.particleAbility.d.ts create mode 100644 tools/interfaces/kits/js/@ohos.ability.wantConstant.d.ts create mode 100644 tools/interfaces/kits/js/@ohos.app.abilityManager.d.ts create mode 100644 tools/interfaces/kits/js/@ohos.bundle.d.ts create mode 100644 tools/interfaces/kits/js/ability/abilityResult.d.ts create mode 100644 tools/interfaces/kits/js/ability/connectOptions.d.ts create mode 100644 tools/interfaces/kits/js/ability/dataAbilityHelper.d.ts create mode 100644 tools/interfaces/kits/js/ability/dataAbilityOperation.d.ts create mode 100644 tools/interfaces/kits/js/ability/startAbilityParameter.d.ts create mode 100644 tools/interfaces/kits/js/ability/want.d.ts create mode 100755 tools/interfaces/kits/js/app/abilityMissionInfo.d.ts create mode 100755 tools/interfaces/kits/js/app/activeProcessInfo.d.ts create mode 100755 tools/interfaces/kits/js/app/activeServiceAbilityInfo.d.ts create mode 100755 tools/interfaces/kits/js/app/context.d.ts create mode 100755 tools/interfaces/kits/js/app/memoryMapInfo.d.ts create mode 100755 tools/interfaces/kits/js/app/missionSnapshot.d.ts create mode 100755 tools/interfaces/kits/js/app/processErrorInfo.d.ts create mode 100755 tools/interfaces/kits/js/app/splitMissionInfo.d.ts create mode 100755 tools/interfaces/kits/js/app/systemMemoryAttr.d.ts create mode 100644 tools/interfaces/kits/js/bundle/abilityInfo.d.ts create mode 100644 tools/interfaces/kits/js/bundle/applicationInfo.d.ts create mode 100644 tools/interfaces/kits/js/bundle/bundleInfo.d.ts create mode 100644 tools/interfaces/kits/js/bundle/bundleInstaller.d.ts create mode 100644 tools/interfaces/kits/js/bundle/customizeData.d.ts create mode 100644 tools/interfaces/kits/js/bundle/elementName.d.ts create mode 100644 tools/interfaces/kits/js/bundle/hapModuleInfo.d.ts create mode 100644 tools/interfaces/kits/js/bundle/moduleInfo.d.ts create mode 100644 tools/interfaces/kits/js/bundle/moduleUsageRecord.d.ts create mode 100644 tools/interfaces/kits/js/bundle/shortcutInfo.d.ts create mode 100644 tools/interfaces/kits/napi/BUILD.gn create mode 100644 tools/interfaces/kits/napi/aafwk/abilityManager/BUILD.gn create mode 100644 tools/interfaces/kits/napi/aafwk/abilityManager/napi_ability_manager.cpp create mode 100644 tools/interfaces/kits/napi/aafwk/abilityManager/napi_ability_manager.h create mode 100644 tools/interfaces/kits/napi/aafwk/abilityManager/native_module.cpp create mode 100755 tools/interfaces/kits/napi/aafwk/dataUriUtils/BUILD.gn create mode 100644 tools/interfaces/kits/napi/aafwk/dataUriUtils/napi_data_uri_utils.cpp create mode 100644 tools/interfaces/kits/napi/aafwk/dataUriUtils/napi_data_uri_utils.h create mode 100644 tools/interfaces/kits/napi/aafwk/dataUriUtils/native_module.cpp create mode 100755 tools/interfaces/kits/napi/aafwk/featureAbility/BUILD.gn create mode 100755 tools/interfaces/kits/napi/aafwk/featureAbility/feature_ability.cpp create mode 100755 tools/interfaces/kits/napi/aafwk/featureAbility/feature_ability.h create mode 100644 tools/interfaces/kits/napi/aafwk/featureAbility/feature_ability_constant.cpp create mode 100644 tools/interfaces/kits/napi/aafwk/featureAbility/feature_ability_constant.h create mode 100755 tools/interfaces/kits/napi/aafwk/featureAbility/napi_context.cpp create mode 100755 tools/interfaces/kits/napi/aafwk/featureAbility/napi_context.h create mode 100644 tools/interfaces/kits/napi/aafwk/featureAbility/napi_data_ability_helper.cpp create mode 100644 tools/interfaces/kits/napi/aafwk/featureAbility/napi_data_ability_helper.h create mode 100644 tools/interfaces/kits/napi/aafwk/featureAbility/napi_data_ability_operation.cpp create mode 100644 tools/interfaces/kits/napi/aafwk/featureAbility/napi_data_ability_operation.h create mode 100644 tools/interfaces/kits/napi/aafwk/featureAbility/native_module.cpp create mode 100644 tools/interfaces/kits/napi/aafwk/formManager/BUILD.gn create mode 100644 tools/interfaces/kits/napi/aafwk/formManager/napi_form_manager.cpp create mode 100755 tools/interfaces/kits/napi/aafwk/formManager/napi_form_manager.h create mode 100755 tools/interfaces/kits/napi/aafwk/formManager/native_module.cpp create mode 100755 tools/interfaces/kits/napi/aafwk/inner/napi_common/BUILD.gn create mode 100644 tools/interfaces/kits/napi/aafwk/inner/napi_common/feature_ability_common.h create mode 100755 tools/interfaces/kits/napi/aafwk/inner/napi_common/napi_common.h create mode 100755 tools/interfaces/kits/napi/aafwk/inner/napi_common/napi_common_ability.cpp create mode 100755 tools/interfaces/kits/napi/aafwk/inner/napi_common/napi_common_ability.h create mode 100755 tools/interfaces/kits/napi/aafwk/inner/napi_common/napi_common_data.h create mode 100755 tools/interfaces/kits/napi/aafwk/inner/napi_common/napi_common_error.h create mode 100755 tools/interfaces/kits/napi/aafwk/inner/napi_common/napi_common_util.cpp create mode 100755 tools/interfaces/kits/napi/aafwk/inner/napi_common/napi_common_util.h create mode 100755 tools/interfaces/kits/napi/aafwk/inner/napi_common/napi_common_want.cpp create mode 100755 tools/interfaces/kits/napi/aafwk/inner/napi_common/napi_common_want.h create mode 100755 tools/interfaces/kits/napi/aafwk/particleAbility/BUILD.gn create mode 100755 tools/interfaces/kits/napi/aafwk/particleAbility/native_module.cpp create mode 100755 tools/interfaces/kits/napi/aafwk/particleAbility/particle_ability.cpp create mode 100755 tools/interfaces/kits/napi/aafwk/particleAbility/particle_ability.h create mode 100644 tools/interfaces/kits/napi/aafwk/wantConstant/BUILD.gn create mode 100644 tools/interfaces/kits/napi/aafwk/wantConstant/native_module.cpp create mode 100644 tools/interfaces/kits/napi/aafwk/wantConstant/want_constant.cpp create mode 100644 tools/interfaces/kits/napi/aafwk/wantConstant/want_constant.h create mode 100755 tools/ohos.build create mode 100644 tools/sa_profile/180.xml create mode 100644 tools/sa_profile/182.xml create mode 100644 tools/sa_profile/BUILD.gn create mode 100644 tools/services/BUILD.gn create mode 100644 tools/services/abilitymgr/BUILD.gn create mode 100644 tools/services/abilitymgr/abilitymgr.gni create mode 100644 tools/services/abilitymgr/include/ability_config.h create mode 100644 tools/services/abilitymgr/include/ability_connect_callback_proxy.h create mode 100644 tools/services/abilitymgr/include/ability_connect_manager.h create mode 100644 tools/services/abilitymgr/include/ability_event_handler.h create mode 100644 tools/services/abilitymgr/include/ability_manager_proxy.h create mode 100644 tools/services/abilitymgr/include/ability_manager_service.h create mode 100644 tools/services/abilitymgr/include/ability_manager_stub.h create mode 100644 tools/services/abilitymgr/include/ability_record.h create mode 100644 tools/services/abilitymgr/include/ability_scheduler_proxy.h create mode 100644 tools/services/abilitymgr/include/ability_scheduler_stub.h create mode 100644 tools/services/abilitymgr/include/ability_stack_manager.h create mode 100644 tools/services/abilitymgr/include/ability_token_interface.h create mode 100644 tools/services/abilitymgr/include/ability_token_proxy.h create mode 100644 tools/services/abilitymgr/include/ability_token_stub.h create mode 100644 tools/services/abilitymgr/include/ability_util.h create mode 100644 tools/services/abilitymgr/include/ams_configuration_parameter.h create mode 100644 tools/services/abilitymgr/include/app_scheduler.h create mode 100644 tools/services/abilitymgr/include/configuration_holder.h create mode 100644 tools/services/abilitymgr/include/connection_record.h create mode 100644 tools/services/abilitymgr/include/data_ability_caller_recipient.h create mode 100644 tools/services/abilitymgr/include/data_ability_manager.h create mode 100644 tools/services/abilitymgr/include/data_ability_record.h create mode 100644 tools/services/abilitymgr/include/kernal_system_app_manager.h create mode 100644 tools/services/abilitymgr/include/lifecycle_deal.h create mode 100644 tools/services/abilitymgr/include/lock_mission_container.h create mode 100644 tools/services/abilitymgr/include/mission_record.h create mode 100644 tools/services/abilitymgr/include/mission_stack.h create mode 100644 tools/services/abilitymgr/include/pending_want_common_event.h create mode 100644 tools/services/abilitymgr/include/pending_want_key.h create mode 100644 tools/services/abilitymgr/include/pending_want_manager.h create mode 100644 tools/services/abilitymgr/include/pending_want_record.h create mode 100644 tools/services/abilitymgr/include/power_storage.h create mode 100644 tools/services/abilitymgr/include/resume_mission_container.h create mode 100644 tools/services/abilitymgr/include/sa_mgr_client.h create mode 100644 tools/services/abilitymgr/include/want_receiver_proxy.h create mode 100644 tools/services/abilitymgr/include/want_receiver_stub.h create mode 100644 tools/services/abilitymgr/include/want_sender_proxy.h create mode 100644 tools/services/abilitymgr/include/want_sender_stub.h create mode 100644 tools/services/abilitymgr/include/window_info.h create mode 100644 tools/services/abilitymgr/resource/ams_service_config.json create mode 100644 tools/services/abilitymgr/src/aafwk_dummy_configuration.cpp create mode 100644 tools/services/abilitymgr/src/ability_connect_callback_stub.cpp create mode 100644 tools/services/abilitymgr/src/ability_connect_manager.cpp create mode 100644 tools/services/abilitymgr/src/ability_event_handler.cpp create mode 100644 tools/services/abilitymgr/src/ability_manager_client.cpp create mode 100644 tools/services/abilitymgr/src/ability_manager_proxy.cpp create mode 100644 tools/services/abilitymgr/src/ability_manager_service.cpp create mode 100644 tools/services/abilitymgr/src/ability_manager_stub.cpp create mode 100644 tools/services/abilitymgr/src/ability_mission_info.cpp create mode 100644 tools/services/abilitymgr/src/ability_record.cpp create mode 100644 tools/services/abilitymgr/src/ability_record_info.cpp create mode 100644 tools/services/abilitymgr/src/ability_scheduler_proxy.cpp create mode 100644 tools/services/abilitymgr/src/ability_scheduler_stub.cpp create mode 100644 tools/services/abilitymgr/src/ability_stack_manager.cpp create mode 100644 tools/services/abilitymgr/src/ability_start_setting.cpp create mode 100644 tools/services/abilitymgr/src/ability_token_stub.cpp create mode 100644 tools/services/abilitymgr/src/ams_configuration_parameter.cpp create mode 100644 tools/services/abilitymgr/src/app_scheduler.cpp create mode 100644 tools/services/abilitymgr/src/caller_info.cpp create mode 100644 tools/services/abilitymgr/src/configuration_holder.cpp create mode 100644 tools/services/abilitymgr/src/connection_record.cpp create mode 100644 tools/services/abilitymgr/src/data_ability_caller_recipient.cpp create mode 100644 tools/services/abilitymgr/src/data_ability_manager.cpp create mode 100644 tools/services/abilitymgr/src/data_ability_record.cpp create mode 100644 tools/services/abilitymgr/src/image_info.cpp create mode 100644 tools/services/abilitymgr/src/kernal_system_app_manager.cpp create mode 100644 tools/services/abilitymgr/src/lifecycle_deal.cpp create mode 100644 tools/services/abilitymgr/src/lifecycle_state_info.cpp create mode 100644 tools/services/abilitymgr/src/lock_mission_container.cpp create mode 100644 tools/services/abilitymgr/src/mission_description_info.cpp create mode 100644 tools/services/abilitymgr/src/mission_option.cpp create mode 100644 tools/services/abilitymgr/src/mission_record.cpp create mode 100644 tools/services/abilitymgr/src/mission_record_info.cpp create mode 100644 tools/services/abilitymgr/src/mission_snapshot_info.cpp create mode 100644 tools/services/abilitymgr/src/mission_stack.cpp create mode 100644 tools/services/abilitymgr/src/mission_stack_info.cpp create mode 100644 tools/services/abilitymgr/src/pending_want_common_event.cpp create mode 100644 tools/services/abilitymgr/src/pending_want_key.cpp create mode 100644 tools/services/abilitymgr/src/pending_want_manager.cpp create mode 100644 tools/services/abilitymgr/src/pending_want_record.cpp create mode 100644 tools/services/abilitymgr/src/power_storage.cpp create mode 100644 tools/services/abilitymgr/src/resume_mission_container.cpp create mode 100644 tools/services/abilitymgr/src/sa_mgr_client.cpp create mode 100644 tools/services/abilitymgr/src/sender_info.cpp create mode 100644 tools/services/abilitymgr/src/stack_info.cpp create mode 100644 tools/services/abilitymgr/src/stack_setting.cpp create mode 100644 tools/services/abilitymgr/src/want_receiver_proxy.cpp create mode 100644 tools/services/abilitymgr/src/want_receiver_stub.cpp create mode 100644 tools/services/abilitymgr/src/want_sender_info.cpp create mode 100644 tools/services/abilitymgr/src/want_sender_proxy.cpp create mode 100644 tools/services/abilitymgr/src/want_sender_stub.cpp create mode 100644 tools/services/abilitymgr/src/wants_info.cpp create mode 100644 tools/services/abilitymgr/test/BUILD.gn create mode 100644 tools/services/abilitymgr/test/mock/BUILD.gn create mode 100755 tools/services/abilitymgr/test/mock/appmgr_test_service/BUILD.gn create mode 100644 tools/services/abilitymgr/test/mock/appmgr_test_service/include/appmgr_test_service.h create mode 100644 tools/services/abilitymgr/test/mock/appmgr_test_service/src/appmgr_test_service.cpp create mode 100644 tools/services/abilitymgr/test/mock/include/mock_app_manager_client.h create mode 100644 tools/services/abilitymgr/test/mock/include/mock_app_mgr_client.h create mode 100644 tools/services/abilitymgr/test/mock/include/mock_configuration_holder.h create mode 100755 tools/services/abilitymgr/test/mock/libs/aakit/BUILD.gn create mode 100644 tools/services/abilitymgr/test/mock/libs/aakit/include/ability_scheduler.h create mode 100644 tools/services/abilitymgr/test/mock/libs/aakit/include/mock_ability_connect_callback.h create mode 100644 tools/services/abilitymgr/test/mock/libs/aakit/src/ability_scheduler.cpp create mode 100644 tools/services/abilitymgr/test/mock/libs/aakit/src/mock_ability_connect_callback.cpp create mode 100755 tools/services/abilitymgr/test/mock/libs/ability_scheduler_mock/ability_scheduler_mock.h create mode 100644 tools/services/abilitymgr/test/mock/libs/appexecfwk_core/BUILD.gn create mode 100644 tools/services/abilitymgr/test/mock/libs/appexecfwk_core/include/appmgr/app_mgr_client.h create mode 100644 tools/services/abilitymgr/test/mock/libs/appexecfwk_core/include/appmgr/app_mgr_interface.h create mode 100644 tools/services/abilitymgr/test/mock/libs/appexecfwk_core/include/appmgr/app_process_data.h create mode 100644 tools/services/abilitymgr/test/mock/libs/appexecfwk_core/include/appmgr/app_state_callback_host.h create mode 100644 tools/services/abilitymgr/test/mock/libs/appexecfwk_core/include/appmgr/iapp_state_callback.h create mode 100644 tools/services/abilitymgr/test/mock/libs/appexecfwk_core/include/bundlemgr/bundle_mgr_interface.h create mode 100755 tools/services/abilitymgr/test/mock/libs/appexecfwk_core/include/bundlemgr/mock_bundle_manager.h create mode 100644 tools/services/abilitymgr/test/mock/libs/appexecfwk_core/src/appmgr/app_mgr_client.cpp create mode 100644 tools/services/abilitymgr/test/mock/libs/appexecfwk_core/src/appmgr/app_state_callback_host.cpp create mode 100644 tools/services/abilitymgr/test/mock/libs/appexecfwk_core/src/appmgr/app_state_callback_proxy.cpp create mode 100644 tools/services/abilitymgr/test/mock/libs/appexecfwk_core/src/appmgr/mock_app_scheduler.cpp create mode 100644 tools/services/abilitymgr/test/mock/libs/appexecfwk_core/src/bundlemgr/mock_bundle_manager.cpp create mode 100644 tools/services/abilitymgr/test/mock/libs/sa_mgr/BUILD.gn create mode 100644 tools/services/abilitymgr/test/mock/libs/sa_mgr/src/sa_mgr_client_mock.cpp create mode 100644 tools/services/abilitymgr/test/mock/libs/system_ability_mock/system_ability.h create mode 100644 tools/services/abilitymgr/test/unittest/phone/ability_connect_callback_proxy_test/BUILD.gn create mode 100644 tools/services/abilitymgr/test/unittest/phone/ability_connect_callback_proxy_test/ability_connect_callback_proxy_test.cpp create mode 100644 tools/services/abilitymgr/test/unittest/phone/ability_connect_callback_proxy_test/mock_ability_connect_callback_stub.h create mode 100644 tools/services/abilitymgr/test/unittest/phone/ability_connect_callback_stub_test/BUILD.gn create mode 100644 tools/services/abilitymgr/test/unittest/phone/ability_connect_callback_stub_test/ability_connect_callback_stub_test.cpp create mode 100644 tools/services/abilitymgr/test/unittest/phone/ability_connect_callback_stub_test/mock_ability_connect_callback_stub.h create mode 100644 tools/services/abilitymgr/test/unittest/phone/ability_connect_manage_test/BUILD.gn create mode 100644 tools/services/abilitymgr/test/unittest/phone/ability_connect_manage_test/ability_connect_manage_test.cpp create mode 100644 tools/services/abilitymgr/test/unittest/phone/ability_dump_test/BUILD.gn create mode 100644 tools/services/abilitymgr/test/unittest/phone/ability_dump_test/ability_dump_test.cpp create mode 100644 tools/services/abilitymgr/test/unittest/phone/ability_manager_proxy_test/BUILD.gn create mode 100644 tools/services/abilitymgr/test/unittest/phone/ability_manager_proxy_test/ability_manager_proxy_test.cpp create mode 100755 tools/services/abilitymgr/test/unittest/phone/ability_manager_proxy_test/ability_manager_stub_mock.h create mode 100644 tools/services/abilitymgr/test/unittest/phone/ability_manager_service_test/BUILD.gn create mode 100644 tools/services/abilitymgr/test/unittest/phone/ability_manager_service_test/ability_manager_service_test.cpp create mode 100644 tools/services/abilitymgr/test/unittest/phone/ability_manager_stub_test/BUILD.gn create mode 100755 tools/services/abilitymgr/test/unittest/phone/ability_manager_stub_test/ability_manager_stub_impl_mock.h create mode 100644 tools/services/abilitymgr/test/unittest/phone/ability_manager_stub_test/ability_manager_stub_test.cpp create mode 100644 tools/services/abilitymgr/test/unittest/phone/ability_manager_test/BUILD.gn create mode 100644 tools/services/abilitymgr/test/unittest/phone/ability_manager_test/ability_manager_stub_mock.h create mode 100644 tools/services/abilitymgr/test/unittest/phone/ability_manager_test/ability_manager_test.cpp create mode 100644 tools/services/abilitymgr/test/unittest/phone/ability_manager_test/iservice_registry.cpp create mode 100644 tools/services/abilitymgr/test/unittest/phone/ability_manager_test/system_ability_manager.cpp create mode 100644 tools/services/abilitymgr/test/unittest/phone/ability_manager_test/system_ability_manager_stub.cpp create mode 100644 tools/services/abilitymgr/test/unittest/phone/ability_record_test/BUILD.gn create mode 100755 tools/services/abilitymgr/test/unittest/phone/ability_record_test/ability_record_test.cpp create mode 100644 tools/services/abilitymgr/test/unittest/phone/ability_scheduler_proxy_test/BUILD.gn create mode 100644 tools/services/abilitymgr/test/unittest/phone/ability_scheduler_proxy_test/ability_scheduler_proxy_test.cpp create mode 100644 tools/services/abilitymgr/test/unittest/phone/ability_scheduler_stub_test/BUILD.gn create mode 100644 tools/services/abilitymgr/test/unittest/phone/ability_scheduler_stub_test/ability_schedule_stub_mock.h create mode 100644 tools/services/abilitymgr/test/unittest/phone/ability_scheduler_stub_test/ability_scheduler_stub_test.cpp create mode 100644 tools/services/abilitymgr/test/unittest/phone/ability_service_start_test/BUILD.gn create mode 100644 tools/services/abilitymgr/test/unittest/phone/ability_service_start_test/ability_service_start_test.cpp create mode 100644 tools/services/abilitymgr/test/unittest/phone/ability_stack_manager_test/BUILD.gn create mode 100644 tools/services/abilitymgr/test/unittest/phone/ability_stack_manager_test/ability_stack_manager_test.cpp create mode 100644 tools/services/abilitymgr/test/unittest/phone/ability_token_proxy_test/BUILD.gn create mode 100644 tools/services/abilitymgr/test/unittest/phone/ability_token_proxy_test/ability_token_proxy_test.cpp create mode 100644 tools/services/abilitymgr/test/unittest/phone/ability_token_stub_test/BUILD.gn create mode 100644 tools/services/abilitymgr/test/unittest/phone/ability_token_stub_test/ability_token_stub_test.cpp create mode 100644 tools/services/abilitymgr/test/unittest/phone/ability_with_applications_test/BUILD.gn create mode 100755 tools/services/abilitymgr/test/unittest/phone/ability_with_applications_test/ability_with_applications_test.cpp create mode 100644 tools/services/abilitymgr/test/unittest/phone/ability_with_applications_test/mock_ability_scheduler.cpp create mode 100644 tools/services/abilitymgr/test/unittest/phone/abilityms_appms_test/BUILD.gn create mode 100644 tools/services/abilitymgr/test/unittest/phone/abilityms_appms_test/abilityms_appms_test.cpp create mode 100644 tools/services/abilitymgr/test/unittest/phone/app_scheduler_test/BUILD.gn create mode 100644 tools/services/abilitymgr/test/unittest/phone/app_scheduler_test/app_scheduler_test.cpp create mode 100644 tools/services/abilitymgr/test/unittest/phone/app_scheduler_test/app_state_call_back_mock.h create mode 100644 tools/services/abilitymgr/test/unittest/phone/configuration_holder_test/BUILD.gn create mode 100644 tools/services/abilitymgr/test/unittest/phone/configuration_holder_test/configuration_holder_test.cpp create mode 100644 tools/services/abilitymgr/test/unittest/phone/connection_record_test/BUILD.gn create mode 100644 tools/services/abilitymgr/test/unittest/phone/connection_record_test/connection_record_test.cpp create mode 100644 tools/services/abilitymgr/test/unittest/phone/data_ability_manager_test/BUILD.gn create mode 100644 tools/services/abilitymgr/test/unittest/phone/data_ability_manager_test/data_ability_manager_test.cpp create mode 100644 tools/services/abilitymgr/test/unittest/phone/data_ability_record_test/BUILD.gn create mode 100644 tools/services/abilitymgr/test/unittest/phone/data_ability_record_test/data_ability_record_test.cpp create mode 100644 tools/services/abilitymgr/test/unittest/phone/info_test/BUILD.gn create mode 100755 tools/services/abilitymgr/test/unittest/phone/info_test/info_test.cpp create mode 100644 tools/services/abilitymgr/test/unittest/phone/kernal_system_app_manager_test/BUILD.gn create mode 100755 tools/services/abilitymgr/test/unittest/phone/kernal_system_app_manager_test/kernal_system_app_manager_test.cpp create mode 100644 tools/services/abilitymgr/test/unittest/phone/lifecycle_deal_test/BUILD.gn create mode 100644 tools/services/abilitymgr/test/unittest/phone/lifecycle_deal_test/lifecycle_deal_test.cpp create mode 100644 tools/services/abilitymgr/test/unittest/phone/lifecycle_test/BUILD.gn create mode 100755 tools/services/abilitymgr/test/unittest/phone/lifecycle_test/lifecycle_test.cpp create mode 100644 tools/services/abilitymgr/test/unittest/phone/lifecycle_test/lifecycle_test_base.h create mode 100644 tools/services/abilitymgr/test/unittest/phone/mission_record_test/BUILD.gn create mode 100644 tools/services/abilitymgr/test/unittest/phone/mission_record_test/mission_record_test.cpp create mode 100644 tools/services/abilitymgr/test/unittest/phone/mission_stack_test/BUILD.gn create mode 100644 tools/services/abilitymgr/test/unittest/phone/mission_stack_test/mission_stack_test.cpp create mode 100644 tools/services/abilitymgr/test/unittest/phone/pending_want_key_test/BUILD.gn create mode 100644 tools/services/abilitymgr/test/unittest/phone/pending_want_key_test/pending_want_key_test.cpp create mode 100644 tools/services/abilitymgr/test/unittest/phone/pending_want_manager_test/BUILD.gn create mode 100644 tools/services/abilitymgr/test/unittest/phone/pending_want_manager_test/pending_want_manager_test.cpp create mode 100644 tools/services/abilitymgr/test/unittest/phone/pending_want_record_test/BUILD.gn create mode 100644 tools/services/abilitymgr/test/unittest/phone/pending_want_record_test/pending_want_record_test.cpp create mode 100644 tools/services/abilitymgr/test/unittest/phone/resume_mission_container_test/BUILD.gn create mode 100644 tools/services/abilitymgr/test/unittest/phone/resume_mission_container_test/resume_mission_container_test.cpp create mode 100644 tools/services/abilitymgr/test/unittest/phone/sender_info_test/BUILD.gn create mode 100644 tools/services/abilitymgr/test/unittest/phone/sender_info_test/sender_info_test.cpp create mode 100644 tools/services/abilitymgr/test/unittest/phone/terminate_ability_test/BUILD.gn create mode 100755 tools/services/abilitymgr/test/unittest/phone/terminate_ability_test/terminate_ability_test.cpp create mode 100644 tools/services/abilitymgr/test/unittest/phone/want_receiver_proxy_test/BUILD.gn create mode 100644 tools/services/abilitymgr/test/unittest/phone/want_receiver_proxy_test/want_receiver_proxy_test.cpp create mode 100644 tools/services/abilitymgr/test/unittest/phone/want_receiver_proxy_test/want_receiver_stub_mock.h create mode 100644 tools/services/abilitymgr/test/unittest/phone/want_receiver_stub_test/BUILD.gn create mode 100644 tools/services/abilitymgr/test/unittest/phone/want_receiver_stub_test/want_receiver_stub_impl_mock.h create mode 100644 tools/services/abilitymgr/test/unittest/phone/want_receiver_stub_test/want_receiver_stub_test.cpp create mode 100644 tools/services/abilitymgr/test/unittest/phone/want_sender_info_test/BUILD.gn create mode 100644 tools/services/abilitymgr/test/unittest/phone/want_sender_info_test/want_sender_info_test.cpp create mode 100644 tools/services/abilitymgr/test/unittest/phone/want_sender_proxy_test/BUILD.gn create mode 100644 tools/services/abilitymgr/test/unittest/phone/want_sender_proxy_test/want_sender_proxy_test.cpp create mode 100644 tools/services/abilitymgr/test/unittest/phone/want_sender_proxy_test/want_sender_stub_mock.h create mode 100644 tools/services/abilitymgr/test/unittest/phone/want_sender_stub_test/BUILD.gn create mode 100644 tools/services/abilitymgr/test/unittest/phone/want_sender_stub_test/want_sender_stub_impl_mock.h create mode 100644 tools/services/abilitymgr/test/unittest/phone/want_sender_stub_test/want_sender_stub_test.cpp create mode 100644 tools/services/abilitymgr/test/unittest/phone/wants_info_test/BUILD.gn create mode 100644 tools/services/abilitymgr/test/unittest/phone/wants_info_test/wants_info_test.cpp create mode 100644 tools/services/abilitymgr/test/unittest/phone/window_info_test/BUILD.gn create mode 100644 tools/services/abilitymgr/test/unittest/phone/window_info_test/window_info_test.cpp create mode 100644 tools/services/common/BUILD.gn create mode 100644 tools/services/common/include/hilog_wrapper.h create mode 100644 tools/services/dataobsmgr/BUILD.gn create mode 100644 tools/services/dataobsmgr/dataobsms.gni create mode 100644 tools/services/dataobsmgr/include/data_ability_observer_proxy.h create mode 100644 tools/services/dataobsmgr/include/dataobs_mgr_inner.h create mode 100644 tools/services/dataobsmgr/include/dataobs_mgr_proxy.h create mode 100644 tools/services/dataobsmgr/include/dataobs_mgr_service.h create mode 100644 tools/services/dataobsmgr/include/dataobs_mgr_stub.h create mode 100644 tools/services/dataobsmgr/src/data_ability_observer_proxy.cpp create mode 100644 tools/services/dataobsmgr/src/data_ability_observer_stub.cpp create mode 100644 tools/services/dataobsmgr/src/dataobs_mgr_client.cpp create mode 100644 tools/services/dataobsmgr/src/dataobs_mgr_inner.cpp create mode 100644 tools/services/dataobsmgr/src/dataobs_mgr_proxy.cpp create mode 100644 tools/services/dataobsmgr/src/dataobs_mgr_service.cpp create mode 100644 tools/services/dataobsmgr/src/dataobs_mgr_stub.cpp create mode 100644 tools/services/dataobsmgr/test/BUILD.gn create mode 100644 tools/services/dataobsmgr/test/mock/libs/system_ability_mock/system_ability.h create mode 100644 tools/services/dataobsmgr/test/unittest/phone/data_ability_observer_proxy_test/BUILD.gn create mode 100644 tools/services/dataobsmgr/test/unittest/phone/data_ability_observer_proxy_test/data_ability_observer_proxy_test.cpp create mode 100644 tools/services/dataobsmgr/test/unittest/phone/data_ability_observer_proxy_test/mock_data_obs_manager_onchange_callback.h create mode 100644 tools/services/dataobsmgr/test/unittest/phone/data_ability_observer_stub_test/BUILD.gn create mode 100644 tools/services/dataobsmgr/test/unittest/phone/data_ability_observer_stub_test/data_ability_observer_stub_test.cpp create mode 100644 tools/services/dataobsmgr/test/unittest/phone/data_ability_observer_stub_test/mock_data_obs_manager_onchange_callback.h create mode 100644 tools/services/dataobsmgr/test/unittest/phone/dataobs_mgr_client_test/BUILD.gn create mode 100644 tools/services/dataobsmgr/test/unittest/phone/dataobs_mgr_client_test/dataobs_mgr_client_test.cpp create mode 100644 tools/services/dataobsmgr/test/unittest/phone/dataobs_mgr_client_test/mock_data_obs_manager_onchange_callback.h create mode 100644 tools/services/dataobsmgr/test/unittest/phone/dataobs_mgr_client_test/mock_dataobs_mgr_client.h create mode 100644 tools/services/dataobsmgr/test/unittest/phone/dataobs_mgr_client_test/mock_dataobs_mgr_service.h create mode 100644 tools/services/dataobsmgr/test/unittest/phone/dataobs_mgr_inner_test/BUILD.gn create mode 100644 tools/services/dataobsmgr/test/unittest/phone/dataobs_mgr_inner_test/dataobs_mgr_inner_test.cpp create mode 100644 tools/services/dataobsmgr/test/unittest/phone/dataobs_mgr_inner_test/mock_data_ability_observer_stub.h create mode 100644 tools/services/dataobsmgr/test/unittest/phone/dataobs_mgr_proxy_test/BUILD.gn create mode 100644 tools/services/dataobsmgr/test/unittest/phone/dataobs_mgr_proxy_test/dataobs_mgr_proxy_test.cpp create mode 100644 tools/services/dataobsmgr/test/unittest/phone/dataobs_mgr_proxy_test/mock_data_obs_mgr_stub.h create mode 100644 tools/services/dataobsmgr/test/unittest/phone/dataobs_mgr_service_test/BUILD.gn create mode 100644 tools/services/dataobsmgr/test/unittest/phone/dataobs_mgr_service_test/dataobs_mgr_service_test.cpp create mode 100644 tools/services/dataobsmgr/test/unittest/phone/dataobs_mgr_service_test/mock_data_ability_observer_stub.h create mode 100644 tools/services/dataobsmgr/test/unittest/phone/dataobs_mgr_stub_test/BUILD.gn create mode 100644 tools/services/dataobsmgr/test/unittest/phone/dataobs_mgr_stub_test/dataobs_mgr_stub_test.cpp create mode 100644 tools/services/dataobsmgr/test/unittest/phone/dataobs_mgr_stub_test/mock_data_obs_mgr_stub.h create mode 100755 tools/services/test/BUILD.gn create mode 100644 tools/services/test/mock/include/mock_ability_connect_callback.h create mode 100644 tools/services/test/mock/include/mock_ability_connect_callback_stub.h create mode 100644 tools/services/test/mock/include/mock_ability_manager_proxy.h create mode 100644 tools/services/test/mock/include/mock_ability_mgr_service.h create mode 100644 tools/services/test/mock/include/mock_ability_scheduler.h create mode 100644 tools/services/test/mock/include/mock_ability_scheduler_stub.h create mode 100644 tools/services/test/mock/include/mock_app_mgr_client.h create mode 100644 tools/services/test/mock/include/mock_app_scheduler.h create mode 100644 tools/services/test/mock/include/mock_bundle_mgr.h create mode 100644 tools/services/test/mock/include/mock_compled_callback.h create mode 100644 tools/services/test/mock/include/mock_context.h create mode 100644 tools/services/test/mock/include/mock_want_receiver.h create mode 100644 tools/services/test/mock/include/system_ability.h create mode 100644 tools/services/test/mock/src/mock_app_mgr_client.cpp create mode 100755 tools/services/test/mock/src/mock_bundle_mgr.cpp create mode 100755 tools/services/test/moduletest/ability_mgr_service_test/BUILD.gn create mode 100644 tools/services/test/moduletest/ability_mgr_service_test/ability_mgr_module_test.cpp create mode 100755 tools/services/test/moduletest/ability_record_test/BUILD.gn create mode 100644 tools/services/test/moduletest/ability_record_test/ability_record_module_test.cpp create mode 100755 tools/services/test/moduletest/ability_stack_test/BUILD.gn create mode 100644 tools/services/test/moduletest/ability_stack_test/ability_stack_module_test.cpp create mode 100644 tools/services/test/moduletest/dump_module_test/BUILD.gn create mode 100755 tools/services/test/moduletest/dump_module_test/dump_module_test.cpp create mode 100644 tools/services/test/moduletest/ipc_ability_connect_test/BUILD.gn create mode 100644 tools/services/test/moduletest/ipc_ability_connect_test/ipc_ability_connect_module_test.cpp create mode 100755 tools/services/test/moduletest/ipc_ability_mgr_test/BUILD.gn create mode 100644 tools/services/test/moduletest/ipc_ability_mgr_test/ipc_ability_mgr_module_test.cpp create mode 100755 tools/services/test/moduletest/ipc_ability_scheduler_test/BUILD.gn create mode 100644 tools/services/test/moduletest/ipc_ability_scheduler_test/ipc_ability_scheduler_module_test.cpp create mode 100644 tools/services/test/moduletest/module_test_dump_util/BUILD.gn create mode 100644 tools/services/test/moduletest/module_test_dump_util/module_test_dump_util.cpp create mode 100644 tools/services/test/moduletest/module_test_dump_util/module_test_dump_util.h create mode 100755 tools/services/test/moduletest/panding_want_manager_test/BUILD.gn create mode 100644 tools/services/test/moduletest/panding_want_manager_test/panding_want_manager_test.cpp create mode 100644 tools/test/resource/tools/aa/dataAbilityBundleForDump.hap create mode 100644 tools/test/resource/tools/aa/pageAbilityBundleForDump.hap create mode 100644 tools/test/resource/tools/aa/pageAbilityBundleForStart.hap create mode 100644 tools/test/resource/tools/aa/serviceAbilityBundleForStart.hap create mode 100644 tools/test/resource/tools/aa/serviceAbilityBundleForStop.hap create mode 100644 tools/test/resource/tools/ohos_test.xml diff --git a/frameworks/kits/ability/native/BUILD.gn b/frameworks/kits/ability/native/BUILD.gn index 29a8cc3fd15..4e914c3226d 100755 --- a/frameworks/kits/ability/native/BUILD.gn +++ b/frameworks/kits/ability/native/BUILD.gn @@ -128,6 +128,8 @@ ohos_shared_library("abilitykit_native") { # "//foundation/aafwk/standard/interfaces/kits/napi/aafwk/inner/napi_common/napi_common_ability.cpp", # "//foundation/aafwk/standard/interfaces/kits/napi/aafwk/inner/napi_common/napi_common_util.cpp", # "//foundation/aafwk/standard/interfaces/kits/napi/aafwk/inner/napi_common/napi_common_want.cpp", + "${SUBSYSTEM_DIR}/src/continuation/distributed/ability_distributed_connect_callback_stub.cpp", + "${SUBSYSTEM_DIR}/src/continuation/distributed/ability_distributed_connection.cpp", "${SUBSYSTEM_DIR}/src/continuation/distributed/continuation_handler.cpp", "${SUBSYSTEM_DIR}/src/continuation/distributed/continuation_manager.cpp", "${SUBSYSTEM_DIR}/src/continuation/distributed/continuation_scheduler.cpp", diff --git a/frameworks/kits/ability/native/include/ability.h b/frameworks/kits/ability/native/include/ability.h index d04b3b215c6..b4cfea6aef5 100755 --- a/frameworks/kits/ability/native/include/ability.h +++ b/frameworks/kits/ability/native/include/ability.h @@ -696,16 +696,6 @@ public: */ virtual void SetMainRoute(const std::string &entry) final; - /** - * @brief Migrates this ability to another device on the same distributed network in a reversible way that allows - * this ability to be migrated back to the local device through reverseContinueAbility(). If there are multiple - * candidate devices, a pop-up will be displayed for users to choose the desired one. The ability to migrate and its - * ability slices must implement the IAbilityContinuation interface. Otherwise, an exception is thrown, indicating - * that the ability does not support migration. - * - */ - virtual void ContinueAbilityReversibly() final; - /** * @brief Migrates this ability to the given device on the same distributed network in a reversible way that allows * this ability to be migrated back to the local device through reverseContinueAbility(). The ability to migrate and diff --git a/frameworks/kits/ability/native/include/ability_context.h b/frameworks/kits/ability/native/include/ability_context.h index dbabf997695..121de7fe2c2 100755 --- a/frameworks/kits/ability/native/include/ability_context.h +++ b/frameworks/kits/ability/native/include/ability_context.h @@ -16,6 +16,8 @@ #ifndef FOUNDATION_APPEXECFWK_OHOS_ABILITY_CONTEXT_H #define FOUNDATION_APPEXECFWK_OHOS_ABILITY_CONTEXT_H +#include + #include "context_container.h" #include "data_ability_helper.h" #include "distributed_sched_interface.h" @@ -722,6 +724,7 @@ protected: std::string callingDeviceId_; std::string callingBundleName_; std::string callingAbilityName_; + std::map, sptr> abilityConnectionMap_; }; } // namespace AppExecFwk diff --git a/frameworks/kits/ability/native/include/continuation/distributed/ability_distributed_connect_callback_stub.h b/frameworks/kits/ability/native/include/continuation/distributed/ability_distributed_connect_callback_stub.h new file mode 100644 index 00000000000..eb432d3f339 --- /dev/null +++ b/frameworks/kits/ability/native/include/continuation/distributed/ability_distributed_connect_callback_stub.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_ABILITY_DISTRIBUTE_CONNECT_CALLBACK_STUB_H +#define OHOS_AAFWK_ABILITY_DISTRIBUTE_CONNECT_CALLBACK_STUB_H + +#include +#include + +#include "ability_distributed_connection_interface.h" +#include "nocopyable.h" + +namespace OHOS { +namespace AAFwk { +/** + * @class AbilityDistributedConnectionStub + * AbilityDistributeConnect Stub. + */ +class AbilityDistributedConnectionStub : public IRemoteStub { +public: + AbilityDistributedConnectionStub(); + virtual ~AbilityDistributedConnectionStub(); + + virtual int OnRemoteRequest( + uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override; + +private: + DISALLOW_COPY_AND_MOVE(AbilityDistributedConnectionStub); +}; + +/** + * @class AbilityDistriubuteConnectCallbackRecipient + * AbilityDistriubuteConnectCallbackRecipient notices IRemoteBroker died. + */ +class AbilityDistriubuteConnectCallbackRecipient : public IRemoteObject::DeathRecipient { +public: + using RemoteDiedHandler = std::function &)>; + AbilityDistriubuteConnectCallbackRecipient(RemoteDiedHandler handler); + virtual ~AbilityDistriubuteConnectCallbackRecipient(); + virtual void OnRemoteDied(const wptr &remote); + +private: + RemoteDiedHandler handler_; +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_ABILITY_DISTRIBUTE_CONNECT_CALLBACK_STUB_H diff --git a/frameworks/kits/ability/native/include/continuation/distributed/ability_distributed_connection.h b/frameworks/kits/ability/native/include/continuation/distributed/ability_distributed_connection.h new file mode 100644 index 00000000000..61c2528ae4d --- /dev/null +++ b/frameworks/kits/ability/native/include/continuation/distributed/ability_distributed_connection.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_ABILITY_DISTRIBUTE_CONNECT_CALLBACK_H +#define OHOS_AAFWK_ABILITY_DISTRIBUTE_CONNECT_CALLBACK_H + +#include "ability_connect_callback_interface.h" +#include "ability_distributed_connect_callback_stub.h" + +namespace OHOS { +namespace AAFwk { +/** + * @class AbilityDistributedConnection + * AbilityDistributeConnect. + */ +class AbilityDistributedConnection : public AbilityDistributedConnectionStub { +public: + AbilityDistributedConnection(const sptr &conn); + ~AbilityDistributedConnection() = default; + + /** + * OnAbilityDistributeConnectDone, AbilityMs notify caller ability the result of connect. + * + * @param element, service ability's ElementName. + * @param remoteObject,.the session proxy of service ability. + * @param resultCode, ERR_OK on success, others on failure. + */ + virtual void OnAbilityConnectDone( + const AppExecFwk::ElementName &element, const sptr &remoteObject, int resultCode) override; + + /** + * OnAbilityDistributeDisconnectDone, AbilityMs notify caller ability the result of disconnect. + * + * @param element, service ability's ElementName. + * @param resultCode, ERR_OK on success, others on failure. + */ + virtual void OnAbilityDisconnectDone(const AppExecFwk::ElementName &element, int resultCode) override; + +private: + sptr conn_; +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_ABILITY_DISTRIBUTE_CONNECT_CALLBACK_H \ No newline at end of file diff --git a/frameworks/kits/ability/native/include/continuation/distributed/distributed_client.h b/frameworks/kits/ability/native/include/continuation/distributed/distributed_client.h index ce91aeea42e..286ccb2cf2f 100644 --- a/frameworks/kits/ability/native/include/continuation/distributed/distributed_client.h +++ b/frameworks/kits/ability/native/include/continuation/distributed/distributed_client.h @@ -42,6 +42,9 @@ public: ErrCode StartRemoteAbility(const Want &want, const AppExecFwk::AbilityInfo &abilityInfo, int32_t requestCode); ErrCode StartContinuation( const Want &want, const AppExecFwk::AbilityInfo &abilityInfo, const sptr &abilityToken); + ErrCode ConnectRemoteAbility( + const Want &want, const AppExecFwk::AbilityInfo &abilityInfo, const sptr &connect); + ErrCode DisconnectRemoteAbility(const sptr &connect); ErrCode NotifyCompleteContinuation( const std::u16string &devId, int32_t sessionId, bool isSuccess, const sptr &reverseScheduler); ErrCode RegisterAbilityToken(const sptr &token, const sptr &appThread); diff --git a/frameworks/kits/ability/native/src/ability.cpp b/frameworks/kits/ability/native/src/ability.cpp index c9da6f9f3d1..771b0bdc641 100755 --- a/frameworks/kits/ability/native/src/ability.cpp +++ b/frameworks/kits/ability/native/src/ability.cpp @@ -171,19 +171,6 @@ void Ability::OnStart(const Want &want) abilityInfo_->bundleName.c_str(), abilityInfo_->name.c_str(), winType); - - if (setting_ != nullptr) { - auto windowMode = static_cast( - std::atoi(setting_->GetProperty(AbilityStartSetting::WINDOW_MODE_KEY).c_str())); - APP_LOGI("%{public}s windowMode : %{public}d", __func__, windowMode); - if (windowMode == AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_FLOATING) { - APP_LOGI("%{public}s begin SetWindowMode : WINDOW_MODE_FREE.", __func__); - config->SetWindowType(WINDOW_TYPE_FLOAT); - APP_LOGI("%{public}s end SetWindowMode : WINDOW_MODE_FREE.", __func__); - } - } else { - APP_LOGI("Ability::OnStart setting_ == nullptr."); - } SetUIContent(config); if (abilityWindow_ != nullptr) { @@ -1169,23 +1156,6 @@ void Ability::ContinueAbilityReversibly(const std::string &deviceId) continuationManager_->ContinueAbility(true, deviceId); } -/** - * @brief Migrates this ability to another device on the same distributed network in a reversible way that allows this - * ability to be migrated back to the local device through reverseContinueAbility(). If there are multiple candidate - * devices, a pop-up will be displayed for users to choose the desired one. The ability to migrate and its ability - * slices must implement the IAbilityContinuation interface. Otherwise, an exception is thrown, indicating that the - * ability does not support migration. - * - */ -void Ability::ContinueAbilityReversibly() -{ - if (!VerifySupportForContinuation()) { - APP_LOGE("Ability::ContinueAbilityReversibly failed. VerifySupportForContinuation faled"); - return; - } - continuationManager_->ContinueAbility(true, ""); -} - /** * @brief public final String getOriginalDeviceId​() throws UnsupportedOperationException * Obtains the ID of the source device from which this ability is migrated. @@ -2097,7 +2067,7 @@ void Ability::CleanFormResource(const int64_t formId) { APP_LOGI("%{public}s called.", __func__); // compatible with int form id - int64_t cleanId {-1L}; + int64_t cleanId{-1L}; for (auto param : userReqParams_) { uint64_t unsignedFormId = static_cast(formId); uint64_t unsignedParamFirst = static_cast(param.first); @@ -2382,9 +2352,8 @@ void Ability::OnDeathReceived() { std::lock_guard lock(formLock); want = userReqRaram.second; - if (want.GetBoolParam(Constants::PARAM_FORM_TEMPORARY_KEY, false) - && std::find(lostedTempForms.begin(), lostedTempForms.end(), - formId) == lostedTempForms.end()) { + if (want.GetBoolParam(Constants::PARAM_FORM_TEMPORARY_KEY, false) && + std::find(lostedTempForms.begin(), lostedTempForms.end(), formId) == lostedTempForms.end()) { lostedTempForms.emplace_back(formId); continue; } diff --git a/frameworks/kits/ability/native/src/ability_context.cpp b/frameworks/kits/ability/native/src/ability_context.cpp index 38fd5442d85..f019febeca7 100755 --- a/frameworks/kits/ability/native/src/ability_context.cpp +++ b/frameworks/kits/ability/native/src/ability_context.cpp @@ -14,7 +14,9 @@ */ #include "ability_context.h" +#include "ability_distributed_connection.h" #include "ability_manager_client.h" +#include "distributed_client.h" #include "app_log_wrapper.h" #include "resource_manager.h" #include "bundle_constants.h" @@ -236,14 +238,37 @@ bool AbilityContext::ConnectAbility(const Want &want, const sptr abilityInfo = GetAbilityInfo(); + if (abilityInfo == nullptr) { + APP_LOGE("AbilityContext::ConnectAbility info == nullptr"); + return false; + } + if (AppExecFwk::AbilityType::PAGE != type && AppExecFwk::AbilityType::SERVICE != type) { APP_LOGE("AbilityContext::ConnectAbility AbilityType = %{public}d", type); return false; } - APP_LOGI("%{public}s begin ams->ConnectAbility", __func__); - ErrCode ret = AAFwk::AbilityManagerClient::GetInstance()->ConnectAbility(want, conn, token_); - APP_LOGI("%{public}s end ams->ConnectAbility, ret=%{public}d", __func__, ret); + ErrCode ret = ERR_OK; + if (want.GetOperation().GetDeviceId() == "") { + APP_LOGI("%{public}s begin ams->ConnectAbilityLocal", __func__); + ret = AAFwk::AbilityManagerClient::GetInstance()->ConnectAbility(want, conn, token_); + } else { + APP_LOGI("%{public}s begin ams->ConnectAbilityRemote", __func__); + auto pos = abilityConnectionMap_.find(conn); + if (pos != abilityConnectionMap_.end()) { + APP_LOGI("%{public}s begin ams->ConnectAbilityHasDistributedConnection", __func__); + return false; + } else { + APP_LOGI("%{public}s begin ams->ConnectAbilitySetDistributedConnection", __func__); + sptr distributedConnection = new AbilityDistributedConnection(conn); + abilityConnectionMap_.emplace(conn, distributedConnection); + ret = DistributedClient::GetInstance()->ConnectRemoteAbility(want, *abilityInfo, distributedConnection); + } + } + + APP_LOGI("%{public}s end ConnectAbility, ret=%{public}d", __func__, ret); bool value = ((ret == ERR_OK) ? true : false); if (!value) { APP_LOGE("AbilityContext::ConnectAbility ErrorCode = %{public}d", ret); @@ -254,12 +279,12 @@ bool AbilityContext::ConnectAbility(const Want &want, const sptr &conn) { - APP_LOGD("AbilityContext::DisconnectAbility begin"); + APP_LOGI("%{public}s begin.", __func__); AppExecFwk::AbilityType type = GetAbilityInfoType(); if (AppExecFwk::AbilityType::PAGE != type && AppExecFwk::AbilityType::SERVICE != type) { @@ -267,9 +292,18 @@ void AbilityContext::DisconnectAbility(const sptr &co return; } - APP_LOGI("%{public}s begin ams->DisconnectAbility", __func__); - ErrCode ret = AAFwk::AbilityManagerClient::GetInstance()->DisconnectAbility(conn); - APP_LOGI("%{public}s end ams->ConnectAbility, ret=%{public}d", __func__, ret); + ErrCode ret = ERR_OK; + auto pos = abilityConnectionMap_.find(conn); + if (pos != abilityConnectionMap_.end()) { + APP_LOGI("%{public}s begin ams->DisconnectAbilityRemote", __func__); + ret = DistributedClient::GetInstance()->DisconnectRemoteAbility(pos->second); + abilityConnectionMap_.erase(conn); + } else { + APP_LOGI("%{public}s begin ams->DisconnectAbilityLocal", __func__); + ret = AAFwk::AbilityManagerClient::GetInstance()->DisconnectAbility(conn); + } + + APP_LOGI("%{public}s end ams->DisconnectAbility, ret=%{public}d", __func__, ret); if (ret != ERR_OK) { APP_LOGE("AbilityContext::DisconnectAbility error"); } @@ -833,7 +867,7 @@ void AbilityContext::AttachBaseContext(const std::shared_ptr &base) ContextContainer::AttachBaseContext(base); APP_LOGI("AbilityContext::AttachBaseContext. End."); } - + /** * @brief Obtains the absolute path to the application-specific cache directory * on the primary external or shared storage device. diff --git a/frameworks/kits/ability/native/src/ability_thread.cpp b/frameworks/kits/ability/native/src/ability_thread.cpp index 5fd1ef2c143..e08ae0a2e28 100644 --- a/frameworks/kits/ability/native/src/ability_thread.cpp +++ b/frameworks/kits/ability/native/src/ability_thread.cpp @@ -869,22 +869,6 @@ void AbilityThread::NotifyMultiWinModeChanged(int32_t winModeKey, bool flag) return; } - if (flag) { - // true: normal windowMode -> free windowMode - if (winModeKey == MULTI_WINDOW_DISPLAY_FLOATING) { - APP_LOGI("NotifyMultiWinModeChanged.SetWindowMode:WINDOW_MODE_FREE begin."); - window->SetWindowType(WINDOW_TYPE_FLOAT); - APP_LOGI("NotifyMultiWinModeChanged.SetWindowMode:WINDOW_MODE_FREE end."); - } else { - APP_LOGI("NotifyMultiWinModeChanged.key:%{public}d", winModeKey); - } - } else { - // false: free windowMode -> normal windowMode - APP_LOGI("NotifyMultiWinModeChanged.SetWindowMode:WINDOW_MODE_TOP begin."); - window->SetWindowType(WINDOW_TYPE_NORMAL); - APP_LOGI("NotifyMultiWinModeChanged.SetWindowMode:WINDOW_MODE_TOP end."); - } - return; } diff --git a/frameworks/kits/ability/native/src/continuation/distributed/ability_distributed_connect_callback_stub.cpp b/frameworks/kits/ability/native/src/continuation/distributed/ability_distributed_connect_callback_stub.cpp new file mode 100644 index 00000000000..482aa036902 --- /dev/null +++ b/frameworks/kits/ability/native/src/continuation/distributed/ability_distributed_connect_callback_stub.cpp @@ -0,0 +1,89 @@ + +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ability_distributed_connect_callback_stub.h" + +#include "hilog_wrapper.h" +#include "ipc_types.h" +#include "message_parcel.h" +#include "want.h" + +namespace OHOS { +namespace AAFwk { +AbilityDistributedConnectionStub::AbilityDistributedConnectionStub() +{} + +AbilityDistributedConnectionStub::~AbilityDistributedConnectionStub() +{} + +int AbilityDistributedConnectionStub::OnRemoteRequest( + uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) +{ + std::u16string descriptor = AbilityDistributedConnectionStub::GetDescriptor(); + std::u16string remoteDescriptor = data.ReadInterfaceToken(); + if (descriptor != remoteDescriptor) { + HILOG_INFO("Local descriptor is not equal to remote"); + return ERR_INVALID_STATE; + } + + auto element = data.ReadParcelable(); + switch (code) { + case IAbilityDistributedConnection::ON_ABILITY_DISTRIBUTE_CONNECT_DONE: { + if (element == nullptr) { + HILOG_ERROR("callback stub receive element is nullptr"); + return ERR_INVALID_VALUE; + } + auto remoteObject = data.ReadRemoteObject(); + auto resultCode = data.ReadInt32(); + OnAbilityConnectDone(*element, remoteObject, resultCode); + delete element; + return NO_ERROR; + } + case IAbilityDistributedConnection::ON_ABILITY_DISTRIBUTE_DISCONNECT_DONE: { + if (element == nullptr) { + HILOG_ERROR("callback stub receive element is nullptr"); + return ERR_INVALID_VALUE; + } + auto resultCode = data.ReadInt32(); + OnAbilityDisconnectDone(*element, resultCode); + delete element; + return NO_ERROR; + } + default: { + if (element != nullptr) { + delete element; + } + return IPCObjectStub::OnRemoteRequest(code, data, reply, option); + } + } +} + +void AbilityDistriubuteConnectCallbackRecipient::OnRemoteDied(const wptr &__attribute__((unused)) remote) +{ + HILOG_ERROR("On remote died."); + if (handler_) { + handler_(remote); + } +} + +AbilityDistriubuteConnectCallbackRecipient::AbilityDistriubuteConnectCallbackRecipient(RemoteDiedHandler handler) + : handler_(handler) +{} + +AbilityDistriubuteConnectCallbackRecipient::~AbilityDistriubuteConnectCallbackRecipient() +{} +} // namespace AAFwk +} // namespace OHOS diff --git a/frameworks/kits/ability/native/src/continuation/distributed/ability_distributed_connection.cpp b/frameworks/kits/ability/native/src/continuation/distributed/ability_distributed_connection.cpp new file mode 100644 index 00000000000..bef0906c3f1 --- /dev/null +++ b/frameworks/kits/ability/native/src/continuation/distributed/ability_distributed_connection.cpp @@ -0,0 +1,49 @@ + +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ability_distributed_connection.h" +#include "hilog_wrapper.h" + +namespace OHOS { +namespace AAFwk { +AbilityDistributedConnection::AbilityDistributedConnection(const sptr &conn) +{ + HILOG_INFO("%{public}s called.", __func__); + conn_ = conn; +} + +void AbilityDistributedConnection::OnAbilityConnectDone( + const AppExecFwk::ElementName &element, const sptr &remoteObject, int resultCode) +{ + HILOG_INFO("%{public}s called.", __func__); + if (conn_ == nullptr) { + HILOG_INFO("%{public}s conn_ == nullptr.", __func__); + return; + } + conn_->OnAbilityConnectDone(element, remoteObject, resultCode); +} + +void AbilityDistributedConnection::OnAbilityDisconnectDone(const AppExecFwk::ElementName &element, int resultCode) +{ + HILOG_INFO("%{public}s called.", __func__); + if (conn_ == nullptr) { + HILOG_INFO("%{public}s conn_ == nullptr.", __func__); + return; + } + conn_->OnAbilityDisconnectDone(element, resultCode); +} +} // namespace AAFwk +} // namespace OHOS diff --git a/frameworks/kits/ability/native/src/continuation/distributed/distributed_client.cpp b/frameworks/kits/ability/native/src/continuation/distributed/distributed_client.cpp index 3a11fcf6977..6cf08519507 100755 --- a/frameworks/kits/ability/native/src/continuation/distributed/distributed_client.cpp +++ b/frameworks/kits/ability/native/src/continuation/distributed/distributed_client.cpp @@ -99,6 +99,39 @@ ErrCode DistributedClient::StartContinuation( return dmsProxy_->StartContinuation(want, abilityInfo, abilityToken); } +ErrCode DistributedClient::ConnectRemoteAbility( + const Want &want, const AppExecFwk::AbilityInfo &abilityInfo, const sptr &connect) +{ + APP_LOGI("%{public}s called", __func__); + if (remoteObject_ == nullptr) { + ErrCode err = Connect(); + if (err != ERR_OK) { + return DISTRIBUTED_ABILITY_SERVICE_NOT_CONNECTED; + } + } + if (connect == nullptr) { + return INCOMING_PARAMETER_POINTER_IS_NULL; + } + + return dmsProxy_->ConnectRemoteAbility(want, abilityInfo, connect); +} + +ErrCode DistributedClient::DisconnectRemoteAbility(const sptr &connect) +{ + APP_LOGI("%{public}s called", __func__); + if (remoteObject_ == nullptr) { + ErrCode err = Connect(); + if (err != ERR_OK) { + return DISTRIBUTED_ABILITY_SERVICE_NOT_CONNECTED; + } + } + if (connect == nullptr) { + return INCOMING_PARAMETER_POINTER_IS_NULL; + } + + return dmsProxy_->DisconnectRemoteAbility(connect); +} + ErrCode DistributedClient::NotifyCompleteContinuation( const std::u16string &devId, int32_t sessionId, bool isSuccess, const sptr &reverseScheduler) { diff --git a/frameworks/kits/test/moduletest/cpp/abilitytest/data_ability_helper_module_test.cpp b/frameworks/kits/test/moduletest/cpp/abilitytest/data_ability_helper_module_test.cpp index ef536e3baaa..4438b5e5305 100644 --- a/frameworks/kits/test/moduletest/cpp/abilitytest/data_ability_helper_module_test.cpp +++ b/frameworks/kits/test/moduletest/cpp/abilitytest/data_ability_helper_module_test.cpp @@ -240,23 +240,25 @@ HWTEST_F(DataAbilityHelperTest, AaFwk_DataAbilityHelper_OpenFile_Test_0100, Func int fd = dataAbilityHelper->OpenFile(urivalue, mode); EXPECT_NE(fd, -1); - std::string result = "123456"; - FILE *file = nullptr; - file = fdopen(fd, "r"); - EXPECT_NE(file, nullptr); - - if (file != nullptr) { - int strSize = 7; - std::string str(""); - str.resize(strSize); - if (!feof(file)) { - fgets(&str[0], strSize, file); + if (fd > 0) { + std::string result = "123456"; + FILE *file = nullptr; + file = fdopen(fd, "r"); + EXPECT_NE(file, nullptr); + + if (file != nullptr) { + int strSize = 7; + std::string str(""); + str.resize(strSize); + if (!feof(file)) { + fgets(&str[0], strSize, file); + } + string stringstr(str); + EXPECT_STREQ(stringstr.c_str(), result.c_str()); + fclose(file); + system("rm /dataability_openfile_test.txt"); } - string stringstr(str); - EXPECT_STREQ(stringstr.c_str(), result.c_str()); } - fclose(file); - system("rm /dataability_openfile_test.txt"); GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_OpenFile_Test_0100 end"; } @@ -280,23 +282,25 @@ HWTEST_F(DataAbilityHelperTest, AaFwk_DataAbilityHelper_OpenFile_Test_0200, Func int fd = dataAbilityHelper->OpenFile(urivalue, mode); EXPECT_NE(fd, -1); - std::string result = "123456"; - FILE *file = nullptr; - file = fdopen(fd, "r"); - EXPECT_NE(file, nullptr); - - if (file != nullptr) { - int strSize = 7; - std::string str(""); - str.resize(strSize); - if (!feof(file)) { - fgets(&str[0], strSize, file); + if (fd > 0) { + std::string result = "123456"; + FILE *file = nullptr; + file = fdopen(fd, "r"); + EXPECT_NE(file, nullptr); + + if (file != nullptr) { + int strSize = 7; + std::string str(""); + str.resize(strSize); + if (!feof(file)) { + fgets(&str[0], strSize, file); + } + string stringstr(str); + EXPECT_STREQ(stringstr.c_str(), result.c_str()); + fclose(file); + system("rm /dataability_openfile_test.txt"); } - string stringstr(str); - EXPECT_STREQ(stringstr.c_str(), result.c_str()); } - fclose(file); - system("rm /dataability_openfile_test.txt"); GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_OpenFile_Test_0200 end"; } diff --git a/interfaces/innerkits/ability_manager/include/continuation/ability_distributed_connection_interface.h b/interfaces/innerkits/ability_manager/include/continuation/ability_distributed_connection_interface.h new file mode 100644 index 00000000000..f5a17384fce --- /dev/null +++ b/interfaces/innerkits/ability_manager/include/continuation/ability_distributed_connection_interface.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_ABILITY_DISTRIBUTE_CONNECT_CALLBACK_INTERFACE_H +#define OHOS_AAFWK_ABILITY_DISTRIBUTE_CONNECT_CALLBACK_INTERFACE_H + +#include "want.h" +#include "element_name.h" + +#include "iremote_broker.h" + +namespace OHOS { +namespace AAFwk { +/** + * @class IAbilityDistributedConnection + * IAbilityDistributedConnection is used to notify caller ability that connect or disconnect is complete. + */ +class IAbilityDistributedConnection : public OHOS::IRemoteBroker { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"ohos.abilityshell.DistributedConnection"); + + /** + * OnAbilityDistributeConnectDone, AbilityMs notify caller ability the result of connect. + * + * @param element, service ability's ElementName. + * @param remoteObject,.the session proxy of service ability. + * @param resultCode, ERR_OK on success, others on failure. + */ + virtual void OnAbilityConnectDone( + const AppExecFwk::ElementName &element, const sptr &remoteObject, int resultCode) = 0; + + /** + * OnAbilityDistributeDisconnectDone, AbilityMs notify caller ability the result of disconnect. + * + * @param element, service ability's ElementName. + * @param resultCode, ERR_OK on success, others on failure. + */ + virtual void OnAbilityDisconnectDone(const AppExecFwk::ElementName &element, int resultCode) = 0; + + enum { + // ipc id for OnAbilityDistributeConnectDone + ON_ABILITY_DISTRIBUTE_CONNECT_DONE = 0, + + // ipc id for OnAbilityDistributeDisConnectDone + ON_ABILITY_DISTRIBUTE_DISCONNECT_DONE + }; +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_ABILITY_CONNECT_CALLBACK_INTERFACE_H diff --git a/interfaces/kits/napi/aafwk/featureAbility/napi_data_ability_helper.cpp b/interfaces/kits/napi/aafwk/featureAbility/napi_data_ability_helper.cpp index 59a9208c849..8bc0572b92a 100644 --- a/interfaces/kits/napi/aafwk/featureAbility/napi_data_ability_helper.cpp +++ b/interfaces/kits/napi/aafwk/featureAbility/napi_data_ability_helper.cpp @@ -450,6 +450,7 @@ napi_value NAPI_NotifyChange(napi_env env, napi_callback_info info) } ret = WrapVoidToJS(env); } + HILOG_INFO("%{public}s,end", __func__); return ret; } @@ -722,6 +723,11 @@ napi_value RegisterAsync( RegisterExecuteCB, [](napi_env env, napi_status status, void *data) { HILOG_INFO("NAPI_Register, main event thread complete."); + DAHelperOnOffCB *onCB = static_cast(data); + if (onCB != nullptr) { + delete onCB; + onCB = nullptr; + } }, (void *)onCB, &onCB->cbBase.asyncWork)); @@ -886,6 +892,10 @@ void UnRegisterCompleteCB(napi_env env, napi_status status, void *data) DAHelperOnOffCB *offCB = static_cast(data); if (offCB == nullptr || offCB->dataAbilityHelper == nullptr) { HILOG_ERROR("NAPI_UnRegister, param is null."); + if (offCB != nullptr) { + delete offCB; + offCB = nullptr; + } return; } if (offCB->cbBase.cbInfo.callback != nullptr) { @@ -950,6 +960,10 @@ void UnRegisterCompleteCB(napi_env env, napi_status status, void *data) HILOG_ERROR("NAPI_UnRegister, error: uri is null."); } } + if (offCB != nullptr) { + delete offCB; + offCB = nullptr; + } } void NAPIDataAbilityObserver::SetEnv(const napi_env &env) @@ -999,22 +1013,28 @@ void NAPIDataAbilityObserver::OnChange() [](uv_work_t *work, int status) { HILOG_INFO("OnChange, uv_queue_work"); // JS Thread - DAHelperOnOffCB *event = (DAHelperOnOffCB *)work->data; + DAHelperOnOffCB *onCB = (DAHelperOnOffCB *)work->data; napi_value result[ARGS_TWO] = {0}; - result[PARAM0] = GetCallbackErrorValue(event->cbBase.cbInfo.env, NO_ERROR); + result[PARAM0] = GetCallbackErrorValue(onCB->cbBase.cbInfo.env, NO_ERROR); napi_value callback = 0; napi_value undefined = 0; - napi_get_undefined(event->cbBase.cbInfo.env, &undefined); + napi_get_undefined(onCB->cbBase.cbInfo.env, &undefined); napi_value callResult = 0; - napi_get_reference_value(event->cbBase.cbInfo.env, event->cbBase.cbInfo.callback, &callback); + napi_get_reference_value(onCB->cbBase.cbInfo.env, onCB->cbBase.cbInfo.callback, &callback); - napi_call_function(event->cbBase.cbInfo.env, undefined, callback, ARGS_TWO, &result[PARAM0], &callResult); - if (event->cbBase.cbInfo.callback != nullptr) { - napi_delete_reference(event->cbBase.cbInfo.env, event->cbBase.cbInfo.callback); + napi_call_function(onCB->cbBase.cbInfo.env, undefined, callback, ARGS_TWO, &result[PARAM0], &callResult); + if (onCB->cbBase.cbInfo.callback != nullptr) { + napi_delete_reference(onCB->cbBase.cbInfo.env, onCB->cbBase.cbInfo.callback); + } + if (onCB != nullptr) { + delete onCB; + onCB = nullptr; + } + if (work != nullptr) { + delete work; + work = nullptr; } - delete event; - delete work; }); if (rev != 0) { if (onCB != nullptr) { diff --git a/interfaces/kits/napi/aafwk/inner/napi_common/napi_common_ability.cpp b/interfaces/kits/napi/aafwk/inner/napi_common/napi_common_ability.cpp index 0b8dd0148ba..d70985df33c 100755 --- a/interfaces/kits/napi/aafwk/inner/napi_common/napi_common_ability.cpp +++ b/interfaces/kits/napi/aafwk/inner/napi_common/napi_common_ability.cpp @@ -3148,8 +3148,16 @@ void NAPIAbilityConnection::SetDisconnectCBRef(const napi_ref &ref) void UvWorkOnAbilityConnectDone(uv_work_t *work, int status) { HILOG_INFO("UvWorkOnAbilityConnectDone, uv_queue_work"); + if (work == nullptr) { + HILOG_ERROR("UvWorkOnAbilityConnectDone, work is null"); + return; + } // JS Thread ConnectAbilityCB *connectAbilityCB = static_cast(work->data); + if (connectAbilityCB == nullptr) { + HILOG_ERROR("UvWorkOnAbilityConnectDone, connectAbilityCB is null"); + return; + } napi_value result[ARGS_TWO] = {0}; result[PARAM0] = WrapElementName(connectAbilityCB->cbBase.cbInfo.env, connectAbilityCB->abilityConnectionCB.elementName); @@ -3235,8 +3243,16 @@ void NAPIAbilityConnection::OnAbilityConnectDone( void UvWorkOnAbilityDisconnectDone(uv_work_t *work, int status) { HILOG_INFO("UvWorkOnAbilityDisconnectDone, uv_queue_work"); + if (work == nullptr) { + HILOG_ERROR("UvWorkOnAbilityDisconnectDone, work is null"); + return; + } // JS Thread ConnectAbilityCB *connectAbilityCB = static_cast(work->data); + if (connectAbilityCB == nullptr) { + HILOG_ERROR("UvWorkOnAbilityDisconnectDone, connectAbilityCB is null"); + return; + } napi_value result = nullptr; result = WrapElementName(connectAbilityCB->cbBase.cbInfo.env, connectAbilityCB->abilityConnectionCB.elementName); @@ -3347,13 +3363,17 @@ napi_value NAPI_AcquireDataAbilityHelperCommon(napi_env env, napi_callback_info } napi_value global = nullptr; - NAPI_CALL(env, napi_get_global(env, &global)); + napi_get_global(env, &global); napi_value abilityObj = nullptr; - NAPI_CALL(env, napi_get_named_property(env, global, "ability", &abilityObj)); + napi_get_named_property(env, global, "ability", &abilityObj); Ability *ability = nullptr; - NAPI_CALL(env, napi_get_value_external(env, abilityObj, (void **)&ability)); + napi_get_value_external(env, abilityObj, (void **)&ability); if (ability == nullptr) { HILOG_ERROR("%{public}s, ability == nullptr", __func__); + if (dataAbilityHelperCB != nullptr) { + delete dataAbilityHelperCB; + dataAbilityHelperCB = nullptr; + } return WrapVoidToJS(env); } diff --git a/interfaces/kits/napi/aafwk/inner/napi_common/napi_common_util.cpp b/interfaces/kits/napi/aafwk/inner/napi_common/napi_common_util.cpp index d47cec7a13a..d3166b17b16 100755 --- a/interfaces/kits/napi/aafwk/inner/napi_common/napi_common_util.cpp +++ b/interfaces/kits/napi/aafwk/inner/napi_common/napi_common_util.cpp @@ -1088,28 +1088,6 @@ void CompletePromiseCallbackWork(napi_env env, napi_status status, void *data) asyncCallbackInfo = nullptr; } -std::vector ConvertStrVector(napi_env env, napi_value value, size_t strMax) -{ - uint32_t arrLen = 0; - napi_get_array_length(env, value, &arrLen); - if (arrLen == 0) { - return {}; - } - std::vector result; - char *buf = new char[strMax + 1]; - size_t len = 0; - for (size_t i = 0; i < arrLen; ++i) { - napi_value element = nullptr; - napi_get_element(env, value, i, &element); - len = 0; - napi_get_value_string_utf8(env, element, buf, strMax, &len); - buf[len] = 0; - result.push_back(buf); - } - delete[] buf; - return result; -} - std::vector ConvertU8Vector(napi_env env, napi_value jsValue) { bool isTypedArray = false; @@ -1134,76 +1112,5 @@ std::vector ConvertU8Vector(napi_env env, napi_value jsValue) return result; } -napi_value ConvertJSValue(napi_env env, std::vector &value) -{ - napi_value jsValue; - napi_status status = napi_create_array_with_length(env, value.size(), &jsValue); - if (status != napi_ok) { - return nullptr; - } - - for (size_t i = 0; i < value.size(); ++i) { - napi_set_element(env, jsValue, i, ConvertJSValue(env, value[i])); - } - return jsValue; -} - -napi_value ConvertJSValue(napi_env env, std::string &value) -{ - napi_value jsValue; - napi_status status = napi_create_string_utf8(env, value.c_str(), value.size(), &jsValue); - if (status != napi_ok) { - return nullptr; - } - return jsValue; -} - -napi_value ConvertJSValue(napi_env env, std::vector &value) -{ - napi_value jsValue = nullptr; - void *native = nullptr; - napi_value buffer = nullptr; - napi_status status = napi_create_arraybuffer(env, value.size(), &native, &buffer); - if (status != napi_ok) { - return nullptr; - } - (void)memcpy_s(native, value.size(), value.data(), value.size()); - status = napi_create_typedarray(env, napi_uint8_array, value.size(), buffer, 0, &jsValue); - if (status != napi_ok) { - return nullptr; - } - return jsValue; -} - -napi_value ConvertJSValue(napi_env env, int32_t value) -{ - napi_value jsValue; - napi_status status = napi_create_int32(env, value, &jsValue); - if (status != napi_ok) { - return nullptr; - } - return jsValue; -} - -napi_value ConvertJSValue(napi_env env, int64_t value) -{ - napi_value jsValue; - napi_status status = napi_create_int64(env, value, &jsValue); - if (status != napi_ok) { - return nullptr; - } - return jsValue; -} - -napi_value ConvertJSValue(napi_env env, double value) -{ - napi_value jsValue; - napi_status status = napi_create_double(env, value, &jsValue); - if (status != napi_ok) { - return nullptr; - } - return jsValue; -} - } // namespace AppExecFwk } // namespace OHOS diff --git a/interfaces/kits/napi/aafwk/inner/napi_common/napi_common_util.h b/interfaces/kits/napi/aafwk/inner/napi_common/napi_common_util.h index fe2a151e66a..3844f23d4e3 100755 --- a/interfaces/kits/napi/aafwk/inner/napi_common/napi_common_util.h +++ b/interfaces/kits/napi/aafwk/inner/napi_common/napi_common_util.h @@ -235,16 +235,8 @@ void CompleteAsyncCallbackWork(napi_env env, napi_status status, void *data); */ void CompletePromiseCallbackWork(napi_env env, napi_status status, void *data); -std::vector ConvertStrVector(napi_env env, napi_value value, size_t strMax); std::vector ConvertU8Vector(napi_env env, napi_value jsValue); -napi_value ConvertJSValue(napi_env env, std::vector &value); -napi_value ConvertJSValue(napi_env env, std::string &value); -napi_value ConvertJSValue(napi_env env, std::vector &value); -napi_value ConvertJSValue(napi_env env, int32_t value); -napi_value ConvertJSValue(napi_env env, int64_t value); -napi_value ConvertJSValue(napi_env env, double value); - } // namespace AppExecFwk } // namespace OHOS #endif // OHOS_APPEXECFWK_NAPI_COMMON_UTIL_H diff --git a/sa_profile/182.xml b/sa_profile/182.xml new file mode 100644 index 00000000000..fe3de304b92 --- /dev/null +++ b/sa_profile/182.xml @@ -0,0 +1,27 @@ + + + + foundation + + 182 + /system/lib64/libdataobsms.z.so + + + true + false + 1 + + diff --git a/sa_profile/BUILD.gn b/sa_profile/BUILD.gn index 666374e66f4..018d522a310 100644 --- a/sa_profile/BUILD.gn +++ b/sa_profile/BUILD.gn @@ -14,7 +14,10 @@ import("//build/ohos/sa_profile/sa_profile.gni") ohos_sa_profile("aafwk_sa_profile") { - sources = [ "180.xml" ] + sources = [ + "180.xml", + "182.xml", + ] part_name = "aafwk_standard" } diff --git a/services/abilitymgr/test/mock/libs/appexecfwk_core/src/bundlemgr/mock_bundle_manager.cpp b/services/abilitymgr/test/mock/libs/appexecfwk_core/src/bundlemgr/mock_bundle_manager.cpp index 2b7e1827e88..e0dd69a1c91 100644 --- a/services/abilitymgr/test/mock/libs/appexecfwk_core/src/bundlemgr/mock_bundle_manager.cpp +++ b/services/abilitymgr/test/mock/libs/appexecfwk_core/src/bundlemgr/mock_bundle_manager.cpp @@ -104,13 +104,11 @@ bool BundleMgrService::QueryAbilityInfo(const AAFwk::Want &want, AbilityInfo &ab if (CheckWantEntity(want, abilityInfo)) { return true; } - ElementName elementTemp = want.GetElement(); std::string abilityNameTemp = elementTemp.GetAbilityName(); std::string bundleNameTemp = elementTemp.GetBundleName(); abilityInfo.deviceId = elementTemp.GetDeviceID(); abilityInfo.visible = true; - if (bundleNameTemp.empty() || abilityNameTemp.empty()) { return false; } @@ -132,7 +130,7 @@ bool BundleMgrService::QueryAbilityInfo(const AAFwk::Want &want, AbilityInfo &ab abilityInfo.deviceId = elementTemp.GetDeviceID(); abilityInfo.applicationInfo.bundleName = elementTemp.GetBundleName(); abilityInfo.applicationInfo.name = "hello"; - if (want.HasEntity(Want::ENTITY_HOME) && want.GetAction() == Want::ACTION_HOME) { + if (elementTemp.GetAbilityName().find("com.ohos.launcher.MainAbility") != std::string::npos) { abilityInfo.applicationInfo.isLauncherApp = true; } else { abilityInfo.applicationInfo.isLauncherApp = false; diff --git a/services/abilitymgr/test/unittest/phone/ability_dump_test/ability_dump_test.cpp b/services/abilitymgr/test/unittest/phone/ability_dump_test/ability_dump_test.cpp index 4fef160867b..70c42ba74ca 100644 --- a/services/abilitymgr/test/unittest/phone/ability_dump_test/ability_dump_test.cpp +++ b/services/abilitymgr/test/unittest/phone/ability_dump_test/ability_dump_test.cpp @@ -141,6 +141,10 @@ void AbilityDumpTest::TearDown() void AbilityDumpTest::StartAbilityes() { + EXPECT_TRUE(g_abilityMs->currentStackManager_); + auto currentTopAbilityRecord = g_abilityMs->currentStackManager_->GetCurrentTopAbility(); + EXPECT_TRUE(currentTopAbilityRecord); + currentTopAbilityRecord->SetAbilityState(AbilityState::ACTIVE); startAbility6(); startAbility1(); startAbility2(); diff --git a/services/abilitymgr/test/unittest/phone/ability_with_applications_test/ability_with_applications_test.cpp b/services/abilitymgr/test/unittest/phone/ability_with_applications_test/ability_with_applications_test.cpp index fd4929cded3..e19ca54bad8 100755 --- a/services/abilitymgr/test/unittest/phone/ability_with_applications_test/ability_with_applications_test.cpp +++ b/services/abilitymgr/test/unittest/phone/ability_with_applications_test/ability_with_applications_test.cpp @@ -274,7 +274,7 @@ HWTEST_F(AbilityWithApplicationsTest, Teminate_Ability_With_Applications_001, Te } if (topAbility) { - EXPECT_EQ("com.ix.hiworld", topAbility->GetAbilityInfo().applicationName); + EXPECT_EQ("com.ohos.launcher", topAbility->GetAbilityInfo().applicationName); EXPECT_EQ(INACTIVATING, topAbility->GetAbilityState()); } @@ -350,10 +350,10 @@ HWTEST_F(AbilityWithApplicationsTest, Teminate_Ability_With_Applications_002, Te EXPECT_EQ(0, result); auto missionstack = stackmgr->GetCurrentMissionStack(); - EXPECT_EQ(1, missionstack->GetMissionStackId()); + EXPECT_EQ(0, missionstack->GetMissionStackId()); topAbility = missionstack->GetTopAbilityRecord(); EXPECT_TRUE(topAbility != nullptr); - EXPECT_EQ("com.ix.test1", topAbility->GetAbilityInfo().applicationName); + EXPECT_EQ("com.ohos.launcher", topAbility->GetAbilityInfo().applicationName); AbilityRequest request; abilityMs_->GetStackManager()->GetTargetMissionStack(request)->RemoveAll(); GTEST_LOG_(INFO) << "Teminate_Ability_With_Applications_002 end"; diff --git a/services/abilitymgr/test/unittest/phone/abilityms_appms_test/abilityms_appms_test.cpp b/services/abilitymgr/test/unittest/phone/abilityms_appms_test/abilityms_appms_test.cpp index 240a2899780..91cd0b715e4 100644 --- a/services/abilitymgr/test/unittest/phone/abilityms_appms_test/abilityms_appms_test.cpp +++ b/services/abilitymgr/test/unittest/phone/abilityms_appms_test/abilityms_appms_test.cpp @@ -105,6 +105,7 @@ void AbilityMsAppmsTest::SetUp(void) DelayedSingleton::GetInstance()->Init(callback_); DelayedSingleton::GetInstance()->OnStart(); + WaitUntilTaskFinished(); startAbility(); GTEST_LOG_(INFO) << "SetUp"; } @@ -143,6 +144,10 @@ void AbilityMsAppmsTest::startAbility() ApplicationInfo applicationInfo; auto abilityMs_ = DelayedSingleton::GetInstance(); + EXPECT_TRUE(abilityMs_->currentStackManager_); + auto currentTopAbilityRecord = abilityMs_->currentStackManager_->GetCurrentTopAbility(); + EXPECT_TRUE(currentTopAbilityRecord); + currentTopAbilityRecord->SetAbilityState(AbilityState::ACTIVE); ElementName element("device", "com.ix.hiworld", "luncherAbility"); want.SetElement(element); abilityMs_->StartAbility(want); diff --git a/services/abilitymgr/test/unittest/phone/lifecycle_test/lifecycle_test.cpp b/services/abilitymgr/test/unittest/phone/lifecycle_test/lifecycle_test.cpp index 3b0875dfc5e..965b5ab12a5 100755 --- a/services/abilitymgr/test/unittest/phone/lifecycle_test/lifecycle_test.cpp +++ b/services/abilitymgr/test/unittest/phone/lifecycle_test/lifecycle_test.cpp @@ -126,6 +126,12 @@ void LifecycleTest::TearDown(void) bool LifecycleTest::StartLauncherAbility() { + auto stackManager = aams_->GetStackManager(); + EXPECT_TRUE(stackManager); + auto topAbility = stackManager->GetCurrentTopAbility(); + EXPECT_TRUE(topAbility); + topAbility->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + ElementName element("device", "com.ix.hiWord", "LauncherAbility"); Want want; want.AddEntity(Want::FLAG_HOME_INTENT_FROM_SYSTEM); @@ -137,8 +143,7 @@ bool LifecycleTest::StartLauncherAbility() GTEST_LOG_(ERROR) << "fail to start Launcher ability"; return false; } - auto stackManager = aams_->GetStackManager(); - EXPECT_TRUE(stackManager); + launcherAbilityRecord_ = (stackManager->GetCurrentTopAbility()); EXPECT_TRUE(launcherAbilityRecord_); if (launcherAbilityRecord_) { diff --git a/tools/BUILD.gn b/tools/BUILD.gn index fae5277f0ab..11f42d3ff1e 100755 --- a/tools/BUILD.gn +++ b/tools/BUILD.gn @@ -9,14 +9,6 @@ # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and -# limitations under the License. +# limitations under the License. import("//build/ohos.gni") -import("//foundation/aafwk/standard/aafwk.gni") - -group("tools_target") { - deps = [ - "aa:tools_aa", - "zip:tools_zip", - ] -} diff --git a/tools/LICENSE b/tools/LICENSE new file mode 100644 index 00000000000..4a459866a57 --- /dev/null +++ b/tools/LICENSE @@ -0,0 +1,177 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS \ No newline at end of file diff --git a/tools/OAT.xml b/tools/OAT.xml new file mode 100644 index 00000000000..96a1658a6bd --- /dev/null +++ b/tools/OAT.xml @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + diff --git a/tools/README_zh.md b/tools/README_zh.md new file mode 100755 index 00000000000..c7546e31fc9 --- /dev/null +++ b/tools/README_zh.md @@ -0,0 +1,320 @@ +# 元能力子系统 + +## 简介 + +**元能力子系统**实现对Ability的运行及生命周期进行统一的调度和管理,应用进程能够支撑多个Ability,Ability具有跨应用进程间和同一进程内调用的能力。Ability管理服务统一调度和管理应用中各Ability,并对Ability的生命周期变更进行管理。 + +![](figures/aafwk.png) + +**元能力子系统架构图说明:** + +- **Ability Kit**为Ability的运行提供基础的运行环境支撑。Ability是系统调度应用的最小单元,是能够完成一个独立功能的组件,一个应用可以包含一个或多个Ability。Ability分为FA(Feature Ability)和PA(Particle Ability)两种类,其中FA支持Page Ability,PA支持Service Ability和Data Ability。 + +- **Ability管理服务(AbilityManagerService)**:用于协调各Ability运行关系、及对生命周期进行调度的系统服务。 + - Ability栈管理模块(AbilityStackManager)负责维护各个Ability之间跳转的先后关系。 + - 连接管理模块(AbilityConnectManager)是Ability管理服务对Service类型Ability连接管理的模块。 + - 数据管理模块(DataAbilityManager)是Ability管理服务对Data类型Ability管理的模块。 + - App管理服务调度模块(AppScheduler)提供Ability管理服务对用户程序管理服务进行调度管理的能力。 + - Ability调度模块(AbilityScheduler)提供对Ability进行调度管理的能力。 + - 生命周期调度模块(LifecycleDeal)是Ability管理服务对Ability的生命周期事件进行管理调度的模块。 + +**Ability生命周期介绍**(Ability Life Cycle)是Ability被调度到INACTIVE、ACTIVE、BACKGROUND等各个状态的统称(主要涉及PageAbility类型和ServiceAbility类型的Ability)。 + + - **PageAbility类型的Ability生命周期流转如下图所示** + +![PageAbility-Lifecycle](figures/page-ability-lifecycle.png) + + + + - **ServiceAbility类型的Ability生命周期流转如下图所示** + +![ServiceAbility-Lifecycle](figures/service-ability-lifecycle.png) + +**Ability生命周期状态说明:** + + - **UNINITIALIZED**:未初始状态,为临时状态,Ability被创建后会由UNINITIALIZED状态进入INITIAL状态。 + + - **INITIAL**:初始化状态,也表示停止状态,表示当前Ability未运行,Ability被启动后由INITIAL态进入INACTIVE状态。 + + - **INACTIVE**:未激活状态,表示当前窗口已显示但是无焦点状态,由于Window暂未支持焦点的概念,当前状态与ACTIVE一致。 + + - **ACTIVE**:前台激活状态,表示当前窗口已显示,并获取焦点,Ability在退到后台之前先由ACTIVE状态进入INACTIVE状态。 + + - **BACKGROUND**: 后台状态,表示当前Ability退到后台,Ability在被销毁后由BACKGROUND状态进入INITIAL状态,或者重新被激活后由BACKGROUND状态进入ACTIVE状态。 + +**PageAbility类型Ability生命周期回调如下图所示:** + +![PageAbility-Lifecycel-Callbacks](figures/page-ability-lifecycle-callbacks.png) + + + +**ServiceAbility类型Ability生命周期回调如下图所示:** + +![Service-Ability-Lifecycle-Callbacks](figures/service-ability-lifecycle-callbacks.jpg) + + + +## 目录 + +``` +foundation/ +└──foundation/aafwk/standard +   ├── frameworks +   │   └── kits +   │   └── ability # AbilityKit实现的核心代码 +   ├── interfaces +   │   └── innerkits +   │      └── want # Ability之间交互的信息载体的对外接口 + └── services + ├── abilitymgr # Ability管理服务框架代码 +   ├── common # 日志组件目录 +   ├── test # 测试目录 +   └── tools # aa命令代码目录 +``` + +## 使用说明 +### 启动Abiltiy +启动新的ability(callback形式) + +* startAbility参数描述 + +| 名称 | 读写属性 | 类型 | 必填 | 描述 | +| --------- | -------- | --------------------- | ---- | ------------------- | +| parameter | 读写 | StartAbilityParameter | 是 | 表示被启动的Ability | +| callback | 只读 | AsyncCallback | 是 | 被指定的回调方法 | + +- StartAbilityParameter类型说明 + +| 名称 | 读写属性 | 类型 | 必填 | 描述 | +| ------------------- | -------- | ------ | ---- | ---------------------------------- | +| want | 读写 | want | 是 | 表示需要包含有关目标启动能力的信息 | +| abilityStartSetting | 只读 | string | 否 | 指示启动能力中使用的特殊启动设置 | + +- want类型说明 + +| 名称 | 读写属性 | 类型 | 必填 | 描述 | +| ----------- | -------- | -------------------- | ---- | -------------------------- | +| deviceId | 读写 | string | 否 | 设备id | +| bundleName | 读写 | string | 否 | Bundle名 | +| abilityName | 读写 | string | 否 | Ability 名 | +| uri | 读写 | string | 否 | 请求中URI的描述 | +| type | 读写 | string | 否 | Want中类型的说明 | +| flags | 读写 | number | 否 | Want中标志的选项,必填 | +| action | 读写 | string | 否 | Want中对操作的描述 | +| parameters | 读写 | {[key: string]: any} | 否 | Want中WantParams对象的描述 | +| entities | 读写 | string | 否 | 对象中实体的描述 | + +* 返回值 + + void + +* 示例 + +```javascript +import featureAbility from '@ohos.ability.featureAbility' +function addSlotsCallBack(err) { + console.info("==========================>startAbility=======================>"); +} +featureAbility.startAbility( + { + want: + { + action: "", + entities: [""], + type: "", + options: { + // indicates the grant to perform read operations on the URI + authReadUriPermission: true, + // indicates the grant to perform write operations on the URI + authWriteUriPermission: true, + // support forward intent result to origin ability + abilityForwardResult: true, + // used for marking the ability start-up is triggered by continuation + abilityContinuation: true, + // specifies whether a component does not belong to ohos + notOhosComponent: true, + // specifies whether an ability is started + abilityFormEnabled: true, + // indicates the grant for possible persisting on the URI. + authPersistableUriPermission: true, + // indicates the grant for possible persisting on the URI. + authPrefixUriPermission: true, + // support distributed scheduling system start up multiple devices + abilitySliceMultiDevice: true, + // indicates that an ability using the service template is started regardless of whether the + // host application has been started. + startForegroundAbility: true, + // install the specified ability if it's not installed. + installOnDemand: true, + // return result to origin ability slice + abilitySliceForwardResult: true, + // install the specified ability with background mode if it's not installed. + installWithBackgroundMode: true + }, + deviceId: "", + bundleName: "com.example.startability", + abilityName: "com.example.startability.MainAbility", + uri: "" + }, + }, + ); +) +``` +启动新的ability(Promise形式) +* startAbility参数描述 + +| 名称 | 读写属性 | 类型 | 必填 | 描述 | +| --------- | -------- | --------------------- | ---- | ------------------- | +| parameter | 读写 | StartAbilityParameter | 是 | 表示被启动的Ability | + +- StartAbilityParameter类型说明 + +| 名称 | 读写属性 | 类型 | 必填 | 描述 | +| ------------------- | -------- | ------ | ---- | ---------------------------------- | +| want | 读写 | want | 是 | 表示需要包含有关目标启动能力的信息 | +| abilityStartSetting | 只读 | string | 否 | 指示启动能力中使用的特殊启动设置 | + +- want类型说明 + +| 名称 | 读写属性 | 类型 | 必填 | 描述 | +| ----------- | -------- | -------------------- | ---- | -------------------------- | +| deviceId | 读写 | string | 否 | 设备id | +| bundleName | 读写 | string | 否 | Bundle名 | +| abilityName | 读写 | string | 否 | Ability 名字 | +| uri | 读写 | string | 否 | 请求中URI的描述 | +| type | 读写 | string | 否 | Want中类型的说明 | +| flags | 读写 | number | 否 | Want中标志的选项,必填 | +| action | 读写 | string | 否 | Want中对操作的描述 | +| parameters | 读写 | {[key: string]: any} | 否 | Want中WantParams对象的描述 | +| entities | 读写 | string | 否 | 对象中实体的描述 | + +* 返回值 + + void + +* 示例 + +```javascript +import featureAbility from '@ohos.ability.featureAbility' +featureAbility.startAbility( + { + want: + { + action: "action.system.home", + entities: ["entity.system.home"], + type: "MIMETYPE", + options: { + // indicates the grant to perform read operations on the URI + authReadUriPermission: true, + // indicates the grant to perform write operations on the URI + authWriteUriPermission: true, + // support forward intent result to origin ability + abilityForwardResult: true, + // used for marking the ability start-up is triggered by continuation + abilityContinuation: true, + // specifies whether a component does not belong to ohos + notOhosComponent: true, + // specifies whether an ability is started + abilityFormEnabled: true, + // indicates the grant for possible persisting on the URI. + authPersistableUriPermission: true, + // indicates the grant for possible persisting on the URI. + authPrefixUriPermission: true, + // support distributed scheduling system start up multiple devices + abilitySliceMultiDevice: true, + // indicates that an ability using the service template is started regardless of whether the + // host application has been started. + startForegroundAbility: true, + // install the specified ability if it's not installed. + installOnDemand: true, + // return result to origin ability slice + abilitySliceForwardResult: true, + // install the specified ability with background mode if it's not installed. + installWithBackgroundMode: true + }, + deviceId: "", + bundleName: "com.example.startability", + abilityName: "com.example.startability.MainAbility", + uri: "" + }, + } + ).then((void) => { + console.info("==========================>startAbility=======================>"); +}); +``` + +### 停止Ability + +设置page ability返回给被调用方的结果代码和数据,并销毁此page ability(callback形式) + +* 参数描述 + +| 名称 | 读写属性 | 类型 | 必填 | 描述 | +| -------- | -------- | -------------------- | ---- | ---------------- | +| callback | 只读 | AsyncCallback\ | 是 | 被指定的回调方法 | + +* 返回值 + + void + +* 示例 + +```javascript +import featureAbility from '@ohos.ability.featureability'; +function terminateSelfCallBack(err) { + console.info("==========================>terminateSelfCallBack=======================>"); +} +featureAbility.terminateSelf() +``` + +设置page ability返回给被调用方的结果代码和数据,并销毁此page ability(Promise形式) + +* 参数描述 + + Null + +* 返回值 + +* void + +* 示例 + +```javascript +import featureAbility from '@ohos.ability.featureability'; +featureAbility.terminateSelf().then((void) => { console.info("==========================>terminateSelfCallBack=======================>"); +}); +``` + + +## **aa命令** + +**aa help** + +| 命令 | 描述 | +| ------- | ------------------ | +| aa help | 显示aa命令帮助信息 | + +**aa start** + +| 命令 | 描述 | +| --------------------------------------------------------- | ------------------------ | +| aa start [-d ] -a -b | 启动ability,设备ID 可空 | + +``` +示例: +aa start -d 12345 -a com.ohos.app.MainAbility -b com.ohos.app +``` + +**aa dump** + +| 命令 | 描述 | +| ---------- | --------------------- | +| aa dump -a | 打印栈中的Ability信息 | + +## 相关仓 +元能力子系统 + +appexecfwk_standard + +**aafwk_standard** + diff --git a/tools/aafwk.gni b/tools/aafwk.gni new file mode 100644 index 00000000000..53a5209d703 --- /dev/null +++ b/tools/aafwk.gni @@ -0,0 +1,21 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +aafwk_path = "//foundation/aafwk/standard" +appexecfwk_path = "//foundation/appexecfwk/standard" + +services_path = "${aafwk_path}/services" + +kits_path = "${aafwk_path}/frameworks/kits" + +innerkits_path = "${aafwk_path}/interfaces/innerkits" diff --git a/tools/figures/aafwk.png b/tools/figures/aafwk.png new file mode 100755 index 0000000000000000000000000000000000000000..9c984fd666ab4ff18cdfb5e2035f06342249fd4a GIT binary patch literal 22892 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 literal 0 HcmV?d00001 diff --git a/tools/figures/page-ability-lifecycle.png b/tools/figures/page-ability-lifecycle.png new file mode 100755 index 0000000000000000000000000000000000000000..d4fff2a49bf103cb5d8763f271c847fc1b711723 GIT binary patch literal 14658 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,e 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 literal 0 HcmV?d00001 diff --git a/tools/figures/service-ability-lifecycle.png b/tools/figures/service-ability-lifecycle.png new file mode 100755 index 0000000000000000000000000000000000000000..66c11ca4db7900696c064461cb7f774bfcd48d49 GIT binary patch literal 12214 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 D8{d|J literal 0 HcmV?d00001 diff --git a/tools/frameworks/kits/ability/native/BUILD.gn b/tools/frameworks/kits/ability/native/BUILD.gn new file mode 100755 index 00000000000..4e914c3226d --- /dev/null +++ b/tools/frameworks/kits/ability/native/BUILD.gn @@ -0,0 +1,228 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") +SUBSYSTEM_DIR = "//foundation/aafwk/standard/frameworks/kits/ability/native" +SUBSYSTEM_APPEXEXFWK_DIR = "//foundation/appexecfwk/standard" +INNERKITS_PATH = "//foundation/aafwk/standard/interfaces/innerkits" + +config("ability_config") { + visibility = [ ":*" ] + include_dirs = [ + "${INNERKITS_PATH}/base/include", + "//utils/native/base/include", + "${SUBSYSTEM_DIR}/include", + "${SUBSYSTEM_APPEXEXFWK_DIR}/kits/appkit/native/app/include", + "${SUBSYSTEM_APPEXEXFWK_DIR}/interfaces/innerkits/appexecfwk_core/include/appmgr", + "${INNERKITS_PATH}/want/include/ohos/aafwk/content", + "${INNERKITS_PATH}/ability_manager/include", + "//foundation/aafwk/standard/services/abilitymgr/include", + "//foundation/appexecfwk/standard/common/log/include", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_core/include/bundlemgr", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base/include/", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_core/include/formmgr", + "//foundation/appexecfwk/standard/kits/appkit/native/app/include", + "//foundation/appexecfwk/standard/interfaces/innerkits/fmskit/native/include", + "//foundation/distributedschedule/dmsfwk/services/dtbschedmgr/include", + "//base/global/resmgr_standard/interfaces/innerkits/include", + "//foundation/aafwk/standard/interfaces/kits/napi/aafwk/featureAbility", + "//foundation/ace/napi/interfaces/kits", + "//third_party/node/src", + "//foundation/communication/ipc/interfaces/innerkits/ipc_core/include", + "//foundation/aafwk/standard/frameworks/kits/ability/native/include/continuation/remote_register_service", + "//foundation/aafwk/standard/frameworks/kits/ability/native/include/continuation/distributed", + "//foundation/aafwk/standard/interfaces/innerkits/ability_manager/include/continuation", + "//foundation/aafwk/standard/frameworks/kits/ability/native/include/continuation/kits", + "//base/security/permission/interfaces/innerkits/permission_standard/permissionsdk/main/cpp/include", + "//foundation/appexecfwk/standard/interfaces/innerkits/task_dispatcher/include/dispatcher", + "//foundation/appexecfwk/standard/interfaces/innerkits/task_dispatcher/include/task", + "//foundation/appexecfwk/standard/interfaces/innerkits/task_dispatcher/include/threading", + "//foundation/appexecfwk/standard/kits/appkit/native/app/include/task", + "//foundation/aafwk/standard/interfaces/kits/napi/aafwk/inner/napi_common", + ] + + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + defines = [ + "APP_LOG_TAG = \"Ability\"", + "LOG_DOMAIN = 0xD002200", + ] +} + +config("ability_public_config") { + visibility = [ ":*" ] + include_dirs = [ + "${INNERKITS_PATH}/base/include", + "//foundation/appexecfwk/standard/kits/appkit/native/app/include", + "${SUBSYSTEM_DIR}/include", + "//third_party/libuv/include", + "//foundation/aafwk/standard/interfaces/innerkits/base/include/ohos/aafwk/base", + "//foundation/aafwk/standard/frameworks/kits/ability/native/include/continuation/remote_register_service", + "//foundation/aafwk/standard/frameworks/kits/ability/native/include/continuation/distributed", + "//foundation/aafwk/standard/interfaces/innerkits/ability_manager/include/continuation", + "//base/global/resmgr_standard/interfaces/innerkits/include", + "//foundation/aafwk/standard/frameworks/kits/ability/native/include/continuation/kits", + "//foundation/appexecfwk/standard/interfaces/innerkits/fmskit/native/include", + ] +} + +ohos_shared_library("abilitykit_native") { + include_dirs = [ + "//foundation/distributeddatamgr/appdatamgr/frameworks/jskitsimpl/native_rdb", + "//foundation/distributeddatamgr/appdatamgr/frameworks/jskitsimpl/common", + "//foundation/distributeddatamgr/appdatamgr/frameworks/jskitsimpl/native_dataability", + ] + cflags = [ + #"-DMMI_COMPILE" + ] + + sources = [ + "${SUBSYSTEM_APPEXEXFWK_DIR}/interfaces/innerkits/appexecfwk_core/src/appmgr/process_info.cpp", + "${SUBSYSTEM_DIR}/src/ability.cpp", + "${SUBSYSTEM_DIR}/src/ability_context.cpp", + "${SUBSYSTEM_DIR}/src/ability_handler.cpp", + "${SUBSYSTEM_DIR}/src/ability_impl.cpp", + "${SUBSYSTEM_DIR}/src/ability_impl_factory.cpp", + "${SUBSYSTEM_DIR}/src/ability_keyevent.cpp", + "${SUBSYSTEM_DIR}/src/ability_lifecycle.cpp", + "${SUBSYSTEM_DIR}/src/ability_lifecycle_executor.cpp", + "${SUBSYSTEM_DIR}/src/ability_loader.cpp", + "${SUBSYSTEM_DIR}/src/ability_local_record.cpp", + "${SUBSYSTEM_DIR}/src/ability_post_event_timeout.cpp", + "${SUBSYSTEM_DIR}/src/ability_process.cpp", + "${SUBSYSTEM_DIR}/src/ability_thread.cpp", + "${SUBSYSTEM_DIR}/src/ability_touchevent.cpp", + "${SUBSYSTEM_DIR}/src/ability_window.cpp", + "${SUBSYSTEM_DIR}/src/data_ability_helper.cpp", + "${SUBSYSTEM_DIR}/src/data_ability_impl.cpp", + "${SUBSYSTEM_DIR}/src/data_ability_operation.cpp", + "${SUBSYSTEM_DIR}/src/data_ability_operation_builder.cpp", + "${SUBSYSTEM_DIR}/src/data_ability_result.cpp", + "${SUBSYSTEM_DIR}/src/data_uri_utils.cpp", + + #"${SUBSYSTEM_DIR}/src/dummy_data_ability_predicates.cpp", + #"${SUBSYSTEM_DIR}/src/dummy_result_set.cpp", + #"${SUBSYSTEM_DIR}/src/dummy_values_bucket.cpp", + "${SUBSYSTEM_DIR}/src/form_js_event_handler.cpp", + "${SUBSYSTEM_DIR}/src/form_provider_client.cpp", + "${SUBSYSTEM_DIR}/src/mission_information.cpp", + "${SUBSYSTEM_DIR}/src/page_ability_impl.cpp", + "${SUBSYSTEM_DIR}/src/service_ability_impl.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/ability_start_setting.cpp", + + # "//foundation/aafwk/standard/interfaces/kits/napi/aafwk/featureAbility/feature_ability.cpp", + # "//foundation/aafwk/standard/interfaces/kits/napi/aafwk/featureAbility/napi_context.cpp", + # "//foundation/aafwk/standard/interfaces/kits/napi/aafwk/featureAbility/napi_data_ability_helper.cpp", + # "//foundation/aafwk/standard/interfaces/kits/napi/aafwk/inner/napi_common/napi_common_ability.cpp", + # "//foundation/aafwk/standard/interfaces/kits/napi/aafwk/inner/napi_common/napi_common_util.cpp", + # "//foundation/aafwk/standard/interfaces/kits/napi/aafwk/inner/napi_common/napi_common_want.cpp", + "${SUBSYSTEM_DIR}/src/continuation/distributed/ability_distributed_connect_callback_stub.cpp", + "${SUBSYSTEM_DIR}/src/continuation/distributed/ability_distributed_connection.cpp", + "${SUBSYSTEM_DIR}/src/continuation/distributed/continuation_handler.cpp", + "${SUBSYSTEM_DIR}/src/continuation/distributed/continuation_manager.cpp", + "${SUBSYSTEM_DIR}/src/continuation/distributed/continuation_scheduler.cpp", + "${SUBSYSTEM_DIR}/src/continuation/distributed/continuation_scheduler_stub.cpp", + "${SUBSYSTEM_DIR}/src/continuation/distributed/distributed_client.cpp", + "${SUBSYSTEM_DIR}/src/continuation/distributed/reverse_continuation_scheduler_primary.cpp", + "${SUBSYSTEM_DIR}/src/continuation/distributed/reverse_continuation_scheduler_primary_proxy.cpp", + "${SUBSYSTEM_DIR}/src/continuation/distributed/reverse_continuation_scheduler_primary_stub.cpp", + "${SUBSYSTEM_DIR}/src/continuation/distributed/reverse_continuation_scheduler_recipient.cpp", + "${SUBSYSTEM_DIR}/src/continuation/distributed/reverse_continuation_scheduler_replica.cpp", + "${SUBSYSTEM_DIR}/src/continuation/distributed/reverse_continuation_scheduler_replica_proxy.cpp", + "${SUBSYSTEM_DIR}/src/continuation/distributed/reverse_continuation_scheduler_replica_stub.cpp", + "${SUBSYSTEM_DIR}/src/continuation/remote_register_service/connect_callback_proxy.cpp", + "${SUBSYSTEM_DIR}/src/continuation/remote_register_service/connect_callback_stub.cpp", + "${SUBSYSTEM_DIR}/src/continuation/remote_register_service/continuation_connector.cpp", + "${SUBSYSTEM_DIR}/src/continuation/remote_register_service/continuation_device_callback_proxy.cpp", + "${SUBSYSTEM_DIR}/src/continuation/remote_register_service/continuation_register_manager.cpp", + "${SUBSYSTEM_DIR}/src/continuation/remote_register_service/continuation_register_manager_proxy.cpp", + "${SUBSYSTEM_DIR}/src/continuation/remote_register_service/remote_register_service_proxy.cpp", + "${SUBSYSTEM_DIR}/src/continuation/remote_register_service/remote_register_service_stub.cpp", + "//foundation/appexecfwk/standard/kits/appkit/native/app/src/application_context.cpp", + "//foundation/appexecfwk/standard/kits/appkit/native/app/src/context_container.cpp", + "//foundation/appexecfwk/standard/kits/appkit/native/app/src/context_deal.cpp", + "//foundation/appexecfwk/standard/kits/appkit/native/app/src/sys_mgr_client.cpp", + "//foundation/distributeddatamgr/appdatamgr/frameworks/jskitsimpl/common/js_utils.cpp", + + #"//foundation/distributeddatamgr/appdatamgr/frameworks/jskitsimpl/native_rdb/napi_rdb_predicates.cpp", + "//foundation/distributeddatamgr/appdatamgr/frameworks/jskitsimpl/native_dataability/napi_data_ability_predicates.cpp", + "//foundation/distributeddatamgr/appdatamgr/frameworks/jskitsimpl/native_rdb/napi_result_set.cpp", + ] + configs = [ ":ability_config" ] + public_configs = [ ":ability_public_config" ] + + deps = [ + "${INNERKITS_PATH}/base:base", + "${INNERKITS_PATH}/want:want", + "//base/security/permission/interfaces/innerkits/permission_standard/permissionsdk:libpermissionsdk_standard", + "//foundation/aafwk/standard/interfaces/innerkits/ability_manager:ability_manager", + "//foundation/aafwk/standard/interfaces/innerkits/dataobs_manager:dataobs_manager", + "//foundation/ace/napi:ace_napi", + "//foundation/appexecfwk/standard/common:libappexecfwk_common", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_core:appexecfwk_core", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/appexecfwk/standard/interfaces/innerkits/task_dispatcher:appkit_dispatcher_td", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy:samgr_proxy", + "//utils/native/base:utils", + ] + + external_deps = [ + "appexecfwk_standard:fmskit_native", + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + "native_appdatamgr:native_appdatafwk", + "native_appdatamgr:native_dataability", + "native_appdatamgr:native_rdb", + + #"multimodalinput_base:libmmi-util", + #"multimodalinput_base:libmmi-client", + #"multimodalinput_base:mmi_event", + ] + + public_deps = [ + "//base/global/resmgr_standard/frameworks/resmgr:global_resmgr", + "//foundation/distributedschedule/dmsfwk/services/dtbschedmgr:distributedschedsvr", + "//foundation/graphic/standard:libwmclient", + ] + + subsystem_name = "aafwk" + part_name = "aafwk_standard" +} + +ohos_shared_library("dummy_classes") { + sources = [ + "${SUBSYSTEM_DIR}/src/dummy_data_ability_predicates_discard.cpp", + "${SUBSYSTEM_DIR}/src/dummy_result_set_discard.cpp", + "${SUBSYSTEM_DIR}/src/dummy_values_bucket_discard.cpp", + ] + + configs = [ ":ability_config" ] + public_configs = [ ":ability_public_config" ] + + deps = [ + "//foundation/appexecfwk/standard/common:libappexecfwk_common", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] + + subsystem_name = "aafwk" + part_name = "aafwk_standard" +} diff --git a/tools/frameworks/kits/ability/native/include/ability.h b/tools/frameworks/kits/ability/native/include/ability.h new file mode 100755 index 00000000000..b4cfea6aef5 --- /dev/null +++ b/tools/frameworks/kits/ability/native/include/ability.h @@ -0,0 +1,1449 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_APPEXECFWK_OHOS_ABILITY_H +#define FOUNDATION_APPEXECFWK_OHOS_ABILITY_H + +#include "iremote_object.h" +#include "ability_context.h" +#include "ability_event_interface.h" +#include +#include +#include +#include "context.h" +#include "want.h" +#include "dummy_component_container.h" +#include "pac_map.h" +#include "dummy_notification_request.h" +#include "continuation_state.h" +#include "dummy_ability_package.h" +#include "dummy_configuration.h" +#include "aafwk_dummy_configuration.h" +#include "continuation_handler.h" +#include "ability_window.h" +#include "ability_lifecycle_interface.h" +#include "ability_lifecycle_executor.h" +#include "ability_continuation_interface.h" + +#include "form_callback_interface.h" +#include "form_constants.h" +#include "form_death_callback.h" +#include "form_provider_info.h" +#include "form_info.h" + +#ifndef MMI_COMPILE +#include "key_event.h" +#include "touch_event.h" +#endif + +using Uri = OHOS::Uri; + +namespace OHOS { +namespace NativeRdb { +class AbsSharedResultSet; +class DataAbilityPredicates; +class ValuesBucket; +} // namespace NativeRdb +#ifdef MMI_COMPILE +class KeyEvent; +class TouchEvent; +#endif +namespace AppExecFwk { +class DataAbilityResult; +class DataAbilityOperation; +class AbilityPostEventTimeout; +class OHOSApplication; +class AbilityHandler; +class AbilityWindow; +class ILifeCycle; +class ContinuationManager; +class ContinuationRegisterManager; +class IContinuationRegisterManager; +class Ability : public IAbilityEvent, + public ILifeCycle, + public AbilityContext, + public FormCallbackInterface, + public IAbilityContinuation, + public std::enable_shared_from_this { +public: + friend class PageAbilityImpl; + + Ability() = default; + virtual ~Ability() = default; + + /** + * @brief Destroys ability. + * + * @param want Indicates the want containing information about TerminateAbility + * + * @return Returns the result of TerminateAbility + */ + using AbilityContext::TerminateAbility; + int TerminateAbility(Want &want); + + /** + * @brief By binding an action, you can set different action parameters in Intent to present different initial + * pages. You must register actions in the profile file. + * + * @param action Indicates the action to bind. + * + * @param entry Indicates the entry, which is the fully qualified name of your AbilitySlice class. + * + * @return Returns the result of AddActionRoute + */ + virtual void AddActionRoute(const std::string &action, const std::string &entry) final; + + /** + * @brief Sets the background color of the window in RGB color mode. + * + * @param red The value ranges from 0 to 255. + * + * @param green The value ranges from 0 to 255. + * + * @param blue The value ranges from 0 to 255. + * + * @return Returns the result of SetWindowBackgroundColor + */ + virtual int SetWindowBackgroundColor(int red, int green, int blue) final; + + /** + * @brief Destroys this Page or Service ability. + * After a Page or Service ability performs all operations, it can use this method to destroy itself + * to free up memory. This method can be called only after the ability is initialized. + */ + virtual void TerminateAbility() final; + + /** + * @brief Obtains the Lifecycle object of the current ability. + * + * @return Returns the Lifecycle object. + */ + virtual std::shared_ptr GetLifecycle() override final; + + /** + * @brief Obtains a resource manager. + * + * @return Returns a ResourceManager object. + */ + std::shared_ptr GetResourceManager() const override; + + /** + * @brief Inflates UI controls by using ComponentContainer. + * You can create a ComponentContainer instance that contains multiple components. + * + * @param componentContainer Indicates a set of customized components. + */ + virtual void SetUIContent(const ComponentContainer &componentContainer); + + /** + * @brief Inflates layout resources by using the layout resource ID. + * + * @param layoutRes Indicates the layout resource ID, which cannot be a negative number. + */ + virtual void SetUIContent(int layoutRes) final; + + /** + * Start other ability for result. + * + * @param want information of other ability + * @param requestCode request code for abilityMS to return result + */ + virtual void StartAbilityForResult(const Want &want, int requestCode) final; + + /** + * Starts an ability with specific start settings and returns the execution result when the ability is destroyed. + * When the ability is destroyed, onAbilityResult(int,int,ohos.aafwk.content.Want) is called and the returned + * requestCode is transferred to the current method. The given requestCode is customized and cannot be a negative + * number. + * + * @param want Indicates the ability to start. + * @param requestCode Indicates the request code returned after the ability is started. You can define the request + * code to identify the results returned by abilities. The value ranges from 0 to 65535. + * @param abilityStartSetting Indicates the setting ability used to start. + */ + virtual void StartAbilityForResult( + const Want &want, int requestCode, AbilityStartSetting abilityStartSetting) final; + + /** + * Starts a new ability with specific start settings. + * A Page or Service ability uses this method to start a specific ability. + * The system locates the target ability from installed abilities based on + * the value of the intent parameter and then starts it. You can specify the + * ability to start using the intent parameter. + * + * @param want Indicates the ability to start. + * @param abilityStartSetting Indicates the setting ability used to start. + */ + void StartAbility(const Want &want, AbilityStartSetting abilityStartSetting); + + // lifecycle callback + virtual void Init(const std::shared_ptr &abilityInfo, + const std::shared_ptr &application, std::shared_ptr &handler, + const sptr &token); + + /** + * @brief Called when this ability is started. You must override this function if you want to perform some + * initialization operations during ability startup. + * + * This function can be called only once in the entire lifecycle of an ability. + * @param Want Indicates the {@link Want} structure containing startup information about the ability. + */ + virtual void OnStart(const Want &want); + + /** + * @brief Called when this ability enters the STATE_STOP state. + * + * The ability in the STATE_STOP is being destroyed. + * You can override this function to implement your own processing logic. + */ + virtual void OnStop(); + + /** + * @brief Called when this ability enters the STATE_ACTIVE state. + * + * The ability in the STATE_ACTIVE state is visible and has focus. + * You can override this function to implement your own processing logic. + * + * @param Want Indicates the {@link Want} structure containing activation information about the ability. + */ + virtual void OnActive(); + + /** + * @brief Called when this ability enters the STATE_INACTIVE state. + * + * STATE_INACTIVE is an instantaneous state. The ability in this state may be visible but does not have + * focus.You can override this function to implement your own processing logic. + */ + virtual void OnInactive(); + + /** + * @brief Called when this ability enters the STATE_FOREGROUND state. + * + * + * The ability in the STATE_FOREGROUND state is visible. + * You can override this function to implement your own processing logic. + */ + virtual void OnForeground(const Want &want); + + /** + * @brief Called when this ability enters the STATE_BACKGROUND state. + * + * + * The ability in the STATE_BACKGROUND state is invisible. + * You can override this function to implement your own processing logic. + */ + virtual void OnBackground(); + + /** + * @brief Called when a key is pressed. When any component in the Ability gains focus, the key-down event for + * the component will be handled first. This callback will not be invoked if the callback triggered for the + * key-down event of the component returns true. The default implementation of this callback does nothing + * and returns false. + * + * @param keyCode Indicates the code of the key pressed. + * @param keyEvent Indicates the key-down event. + * + * @return Returns true if this event is handled and will not be passed further; returns false if this event + * is not handled and should be passed to other handlers. + */ + virtual bool OnKeyDown(int keyCode, const KeyEvent &keyEvent); + + /** + * @brief Called when a key is released. When any component in the Ability gains focus, the key-up event for + * the component will be handled first. This callback will not be invoked if the callback triggered for the + * key-up event of the component returns true. The default implementation of this callback does nothing and + * returns false. + * + * @param keyCode Indicates the code of the key released. + * @param keyEvent Indicates the key-up event. + * + * @return Returns true if this event is handled and will not be passed further; returns false if this event + * is not handled and should be passed to other handlers. + */ + virtual bool OnKeyUp(int keyCode, const KeyEvent &keyEvent); + + /** + * @brief Called when a touch event is dispatched to this ability. The default implementation of this callback + * does nothing and returns false. + * + * @param event Indicates information about the touch event. + * + * @return Returns true if the event is handled; returns false otherwise. + */ + virtual bool OnTouchEvent(const TouchEvent &touchEvent); + + /** + * @brief Called when this Service ability is connected for the first time. + * + * You can override this function to implement your own processing logic. + * + * @param want Indicates the {@link Want} structure containing connection information about the Service ability. + * @return Returns a pointer to the sid of the connected Service ability. + */ + virtual sptr OnConnect(const Want &want); + + /** + * @brief Called when all abilities connected to this Service ability are disconnected. + * + * You can override this function to implement your own processing logic. + * + */ + virtual void OnDisconnect(const Want &want); + + /** + * @brief Inflates UI controls by using ComponentContainer. + * You can create a ComponentContainer instance that contains multiple components. + * + * @param componentContainer Indicates the component layout defined by the user. + * @param context Indicates the context to use. + * @param typeFlag Indicates the window type. + */ + virtual void SetUIContent( + const ComponentContainer &componentContainer, std::shared_ptr &context, int typeFlag); + + /** + * @brief Inflates layout resources by using the layout resource ID. + * + * @param layoutRes Indicates the layout resource ID, which cannot be a negative number. + * @param context Indicates the context to use. + * @param typeFlag Indicates the window type. + */ + virtual void SetUIContent(int layoutRes, std::shared_ptr &context, int typeFlag); + + /** + * @brief Called when this ability gains or loses window focus. + * + * @param hasFocus Specifies whether this ability has focus. + */ + virtual void OnWindowFocusChanged(bool hasFocus); + + /** + * @brief Called when this ability is moved to or removed from the top of the stack. + * + * @param topActive Specifies whether this ability is moved to or removed from the top of the stack. The value true + * indicates that it is moved to the top, and false indicates that it is removed from the top of the stack. + */ + virtual void OnTopActiveAbilityChanged(bool topActive); + + /** + * @brief Inflates UI controls by using WindowConfig. + * + * @param config Indicates the window config defined by the user. + */ + virtual void SetUIContent(const sptr &config); + + /** + * @brief Get the window belong to the ability. + * + * @return Returns a Window object pointer. + */ + virtual const sptr GetWindow(); + + /** + * @brief Checks whether the main window of this ability has window focus. + * + * @return Returns true if this ability currently has window focus; returns false otherwise. + */ + bool HasWindowFocus(); + + /** + * @brief Called when a key is lone pressed. + * + * @param keyCode Indicates the code of the key long pressed. + * @param keyEvent Indicates the key-long-press event. + * + * @return Returns true if this event is handled and will not be passed further; returns false if this event + * is not handled and should be passed to other handlers. + */ + virtual bool OnKeyPressAndHold(int keyCode, const std::shared_ptr &keyEvent); + + /** + * @brief Called back after permissions are requested by using + * AbilityContext.requestPermissionsFromUser(java.lang.String[],int). + * + * @param requestCode Indicates the request code passed to this method from + * AbilityContext.requestPermissionsFromUser(java.lang.String[],int). + * @param permissions Indicates the list of permissions requested by using + * AbilityContext.requestPermissionsFromUser(java.lang.String[],int). This parameter cannot be null. + * @param grantResults Indicates the granting results of the corresponding permissions requested using + * AbilityContext.requestPermissionsFromUser(java.lang.String[],int). The value 0 indicates that a + * permission is granted, and the value -1 indicates not. + * + */ + virtual void OnRequestPermissionsFromUserResult( + int requestCode, const std::vector &permissions, const std::vector &grantResults); + + /** + * @brief Called when this ability is about to leave the foreground and enter the background due to a user + * operation, for example, when the user touches the Home key. + * + */ + virtual void OnLeaveForeground(); + + /** + * @brief Obtains the MIME type matching the data specified by the URI of the Data ability. This method should be + * implemented by a Data ability. Data abilities supports general data types, including text, HTML, and JPEG. + * + * @param uri Indicates the URI of the data. + * + * @return Returns the MIME type that matches the data specified by uri. + */ + virtual std::string GetType(const Uri &uri); + + /** + * @brief Inserts a data record into the database. This method should be implemented by a Data ability. + * + * @param uri Indicates the position where the data is to insert. + * @param value Indicates the data to insert. + * + * @return Returns the index of the newly inserted data record. + */ + virtual int Insert(const Uri &uri, const NativeRdb::ValuesBucket &value); + + /** + * @brief Called when the system configuration is updated. + * + * @param configuration Indicates the updated configuration information. + */ + virtual void OnConfigurationUpdated(const Configuration &configuration); + + /** + * @brief Called when the system configuration is updated. + * + * @param level Indicates the memory trim level, which shows the current memory usage status. + * + */ + virtual void OnMemoryLevel(int level); + + /** + * @brief This is like openFile, open a file that need to be able to return sub-sections of files,often assets + * inside of their .hap. + * + * @param uri Indicates the path of the file to open. + * @param mode Indicates the file open mode, which can be "r" for read-only access, "w" for write-only access + * (erasing whatever data is currently in the file), "wt" for write access that truncates any existing file, + * "wa" for write-only access to append to any existing data, "rw" for read and write access on any existing + * data, or "rwt" for read and write access that truncates any existing file. + * + * @return Returns the RawFileDescriptor object containing file descriptor. + */ + virtual int OpenRawFile(const Uri &uri, const std::string &mode); + + /** + * @brief Updates one or more data records in the database. This method should be implemented by a Data ability. + * + * @param uri Indicates the database table storing the data to update. + * @param value Indicates the data to update. This parameter can be null. + * @param predicates Indicates filter criteria. If this parameter is null, all data records will be updated by + * default. + * + * @return Returns the number of data records updated. + */ + virtual int Update( + const Uri &uri, const NativeRdb::ValuesBucket &value, const NativeRdb::DataAbilityPredicates &predicates); + + /** + * @brief get application witch the ability belong + * + * @return Returns the application ptr + */ + std::shared_ptr GetApplication(); + + /** + * @brief Obtains the class name in this ability name, without the prefixed bundle name. + * + * @return Returns the class name of this ability. + */ + std::string GetAbilityName(); + + /** + * @brief OChecks whether the current ability is being destroyed. + * An ability is being destroyed if you called terminateAbility() on it or someone else requested to destroy it. + * + * @return Returns true if the current ability is being destroyed; returns false otherwise. + */ + bool IsTerminating(); + + /** + * @brief Called when startAbilityForResult(ohos.aafwk.content.Want,int) is called to start an ability and the + * result is returned. This method is called only on Page abilities. You can start a new ability to perform some + * calculations and use setResult (int,ohos.aafwk.content.Want) to return the calculation result. Then the system + * calls back the current method to use the returned data to execute its own logic. + * + * @param requestCode Indicates the request code returned after the ability is started. You can define the request + * code to identify the results returned by abilities. The value ranges from 0 to 65535. + * @param resultCode Indicates the result code returned after the ability is started. You can define the result code + * to identify an error. + * @param resultData Indicates the data returned after the ability is started. You can define the data returned. The + * value can be null. + * + */ + virtual void OnAbilityResult(int requestCode, int resultCode, const Want &resultData); + + /** + * @brief Called back when the Back key is pressed. + * The default implementation destroys the ability. You can override this method. + * + */ + virtual void OnBackPressed() override; + + /** + * @brief Called when the launch mode of an ability is set to singleInstance. This happens when you re-launch an + * ability that has been at the top of the ability stack. + * + * @param want Indicates the new Want containing information about the ability. + */ + virtual void OnNewWant(const Want &want); + + /** + * @brief Restores data and states of an ability when it is restored by the system. This method should be + * implemented by a Page ability. This method is called if an ability was destroyed at a certain time due to + * resource reclaim or was unexpectedly destroyed and the onSaveAbilityState(ohos.utils.PacMap) method was called to + * save its user data and states. Generally, this method is called after the onStart(ohos.aafwk.content.Want) + * method. + * + * @param inState Indicates the PacMap object used for storing data and states. This parameter can not be null. + * + */ + virtual void OnRestoreAbilityState(const PacMap &inState); + + /** + * @brief Saves temporary data and states of this ability. This method should be implemented by a Page ability. + * This method is called when the system determines that the ability may be destroyed in an unexpected situation, + * for example, when the screen orientation changes or the user touches the Home key. Generally, this method is used + * only to save temporary states. + * + * @param outState Indicates the PacMap object used for storing user data and states. This parameter cannot be + * null. + * + */ + virtual void OnSaveAbilityState(PacMap &outState); + + /** + * @brief Called every time a key, touch, or trackball event is dispatched to this ability. + * You can override this callback method if you want to know that the user has interacted with + * the device in a certain way while this ability is running. This method, together with onLeaveForeground(), + * is designed to help abilities intelligently manage status bar notifications. Specifically, they help + * abilities determine when to cancel a notification. + * + */ + virtual void OnEventDispatch(); + + /** + * @brief Sets the want object that can be obtained by calling getWant(). + * + * @param Want information of other ability + */ + void SetWant(const AAFwk::Want &want); + + /** + * @brief Obtains the Want object that starts this ability. + * + * @return Returns the Want object that starts this ability. + */ + std::shared_ptr GetWant(); + + /** + * @brief Sets the result code and data to be returned by this Page ability to the caller. + * When a Page ability is destroyed, the caller overrides the AbilitySlice#onAbilityResult(int, int, Want) method to + * receive the result set in the current method. This method can be called only after the ability has been + * initialized. + * + * @param resultCode Indicates the result code returned after the ability is destroyed. You can define the result + * code to identify an error. + * @param resultData Indicates the data returned after the ability is destroyed. You can define the data returned. + * This parameter can be null. + */ + virtual void SetResult(int resultCode, const Want &resultData) final; + + /** + * @brief Sets the type of audio whose volume will be adjusted by the volume button. + * + * @param volumeType Indicates the AudioManager.AudioVolumeType to set. + */ + virtual void SetVolumeTypeAdjustedByKey(int volumeType); + + /** + * @brief Called back when Service is started. + * This method can be called only by Service. You can use the StartAbility(ohos.aafwk.content.Want) method to start + * Service. Then the system calls back the current method to use the transferred want parameter to execute its own + * logic. + * + * @param want Indicates the want of Service to start. + * @param restart Indicates the startup mode. The value true indicates that Service is restarted after being + * destroyed, and the value false indicates a normal startup. + * @param startId Indicates the number of times the Service ability has been started. The startId is incremented by + * 1 every time the ability is started. For example, if the ability has been started for six times, the value of + * startId is 6. + */ + virtual void OnCommand(const AAFwk::Want &want, bool restart, int startId); + + /** + * @brief dump ability info + * + * @param extra dump ability info + */ + virtual void Dump(const std::string &extra); + + /** + * @brief Keeps this Service ability in the background and displays a notification bar. + * To use this method, you need to request the ohos.permission.KEEP_BACKGROUND_RUNNING permission from the system. + * The ohos.permission.KEEP_BACKGROUND_RUNNING permission is of the normal level. + * This method can be called only by Service abilities after the onStart(ohos.aafwk.content.Want) method is called. + * + * @param id Identifies the notification bar information. + * @param notificationRequest Indicates the NotificationRequest instance containing information for displaying a + * notification bar. + */ + virtual void KeepBackgroundRunning(int id, const NotificationRequest ¬ificationRequest) final; + + /** + * @brief Cancels background running of this ability to free up system memory. + * This method can be called only by Service abilities when the onStop() method is called. + * + */ + virtual void CancelBackgroundRunning() final; + + /** + * @brief Converts the given uri that refer to the Data ability into a normalized URI. A normalized URI can be used + * across devices, persisted, backed up, and restored. It can refer to the same item in the Data ability even if the + * context has changed. If you implement URI normalization for a Data ability, you must also implement + * denormalizeUri(ohos.utils.net.Uri) to enable URI denormalization. After this feature is enabled, URIs passed to + * any method that is called on the Data ability must require normalization verification and denormalization. The + * default implementation of this method returns null, indicating that this Data ability does not support URI + * normalization. + * + * @param uri Indicates the Uri object to normalize. + * + * @return Returns the normalized Uri object if the Data ability supports URI normalization; returns null otherwise. + */ + virtual Uri NormalizeUri(const Uri &uri); + + /** + * @brief Deletes one or more data records. This method should be implemented by a Data ability. + * + * @param uri Indicates the database table storing the data to delete. + * @param predicates Indicates filter criteria. If this parameter is null, all data records will be deleted by + * default. + * + * @return Returns the number of data records deleted. + */ + virtual int Delete(const Uri &uri, const NativeRdb::DataAbilityPredicates &predicates); + + /** + * @brief Obtains the MIME type of files. This method should be implemented by a Data ability. + * + * @param uri Indicates the path of the files to obtain. + * @param mimeTypeFilter Indicates the MIME type of the files to obtain. This parameter cannot be set to null. + * 1. * / *: Obtains all types supported by a Data ability. + * 2. image/ *: Obtains files whose main type is image of any subtype. + * 3. * /jpg: Obtains files whose subtype is JPG of any main type. + * + * @return Returns the MIME type of the matched files; returns null if there is no type that matches the Data + * ability. + */ + virtual std::vector GetFileTypes(const Uri &uri, const std::string &mimeTypeFilter); + + /** + * @brief Opens a file. This method should be implemented by a Data ability. + * + * @param uri Indicates the path of the file to open. + * @param mode Indicates the open mode, which can be "r" for read-only access, "w" for write-only access + * (erasing whatever data is currently in the file), "wt" for write access that truncates any existing file, + * "wa" for write-only access to append to any existing data, "rw" for read and write access on any existing data, + * or "rwt" for read and write access that truncates any existing file. + * + * @return Returns the FileDescriptor object of the file descriptor. + */ + virtual int OpenFile(const Uri &uri, const std::string &mode); + + /** + * @brief Queries one or more data records in the database. This method should be implemented by a Data ability. + * + * @param uri Indicates the database table storing the data to query. + * @param columns Indicates the columns to be queried, in array, for example, {"name","age"}. You should define the + * processing logic when this parameter is null. + * @param predicates Indicates filter criteria. If this parameter is null, all data records will be queried by + * default. + * + * @return Returns the queried data. + */ + virtual std::shared_ptr Query( + const Uri &uri, const std::vector &columns, const NativeRdb::DataAbilityPredicates &predicates); + + /** + * @brief Sets the main route for this ability. + * + * The main route, also called main entry, refers to the default AbilitySlice to present for this ability. + * This function should be called only on Feature Abilities. If this function is not called in the + * {@link OnStart(const Want &want)} function for a Feature Ability, the Feature Ability will fail to start. + * + * @param entry Indicates the main entry, which is the class name of the AbilitySlice instance to start. + * + * @return Returns the result of SetMainRoute + */ + virtual void SetMainRoute(const std::string &entry) final; + + /** + * @brief Migrates this ability to the given device on the same distributed network in a reversible way that allows + * this ability to be migrated back to the local device through reverseContinueAbility(). The ability to migrate and + * its ability slices must implement the IAbilityContinuation interface. Otherwise, an exception is thrown, + * indicating that the ability does not support migration. + * + * @param deviceId Indicates the ID of the target device where this ability will be migrated to. If this parameter + * is null, this method has the same effect as ContinueAbilityReversibly(). + * + */ + virtual void ContinueAbilityReversibly(const std::string &deviceId) final; + + /** + * @brief Obtains the ID of the source device from which this ability is migrated. + * + * @return Returns the source device ID. + */ + virtual std::string GetOriginalDeviceId() final; + + /** + * @brief Obtains the migration state of this ability. + * @return Returns the migration state. + */ + virtual ContinuationState GetContinuationState() final; + + /** + * @brief Obtains the singleton AbilityPackage object to which this ability belongs. + * + * @return Returns the singleton AbilityPackage object to which this ability belongs. + */ + virtual std::shared_ptr GetAbilityPackage(); + + /** + * @brief Converts the given normalized uri generated by normalizeUri(ohos.utils.net.Uri) into a denormalized one. + * The default implementation of this method returns the original URI passed to it. + * + * @param uri uri Indicates the Uri object to denormalize. + * + * @return Returns the denormalized Uri object if the denormalization is successful; returns the original Uri passed + * to this method if there is nothing to do; returns null if the data identified by the original Uri cannot be found + * in the current environment. + */ + virtual Uri DenormalizeUri(const Uri &uri); + + /** + * @brief Reloads data in the database. + * + * @param uri Indicates the position where the data is to reload. This parameter is mandatory. + * @param extras Indicates the PacMap object containing the additional parameters to be passed in this call. This + * parameter can be null. If a custom Sequenceable object is put in the PacMap object and will be transferred across + * processes, you must call BasePacMap.setClassLoader(ClassLoader) to set a class loader for the custom object. + * + * @return Returns true if the data is successfully reloaded; returns false otherwise. + */ + virtual bool Reload(const Uri &uri, const PacMap &extras); + + /** + * @brief Inserts multiple data records into the database. + * + * @param uri Indicates the path of the data to operate. + * @param values Indicates the data records to insert. + * + * @return Returns the number of data records inserted. + */ + virtual int BatchInsert(const Uri &uri, const std::vector &values); + + /** + * @brief Obtains the type of audio whose volume is adjusted by the volume button. + * + * @return Returns the AudioManager.AudioVolumeType. + */ + int GetVolumeTypeAdjustedByKey(); + + /** + * @brief Obtains the lifecycle state of this ability. + * + * @return Returns the lifecycle state of this ability. + */ + virtual AbilityLifecycleExecutor::LifecycleState GetState() final; + + /** + * @brief A Page or Service ability uses this method to start a specific ability. The system locates the target + * ability from installed abilities based on the value of the intent parameter and then starts it. You can specify + * the ability to start using the intent parameter. + * + * @param intent Indicates the ability to start. + */ + using AbilityContext::StartAbility; + virtual void StartAbility(const Want &want) final; + + /** + * @brief Connects the current ability to an ability using the AbilityInfo.AbilityType.SERVICE template. + * + * @param want Indicates the want containing information about the ability to connect + * + * @param conn Indicates the callback object when the target ability is connected. + * + * @return True means success and false means failure + */ + bool ConnectAbility(const Want &want, const sptr &conn) override; + + /** + * @brief Disconnects the current ability from an ability + * + * @param conn Indicates the IAbilityConnection callback object passed by connectAbility after the connection + * is set up. The IAbilityConnection object uniquely identifies a connection between two abilities. + */ + void DisconnectAbility(const sptr &conn) override; + + /** + * @brief Destroys another ability that uses the AbilityInfo.AbilityType.SERVICE template. + * The current ability using either the AbilityInfo.AbilityType.SERVICE or AbilityInfo.AbilityType.PAGE + * template can call this method to destroy another ability that uses the AbilityInfo.AbilityType.SERVICE + * template. The current ability itself can be destroyed by calling the terminateAbility() method. + * + * @param want Indicates the Want containing information about the ability to destroy. + * + * @return Returns true if the ability is destroyed successfully; returns false otherwise. + */ + bool StopAbility(const AAFwk::Want &want) override; + + /** + * @brief Posts a scheduled Runnable task to a new non-UI thread. + * The task posted via this method will be executed in a new thread, which allows you to perform certain + * time-consuming operations. To use this method, you must also override the supportHighPerformanceUI() method. + * Additionally, the usage of this method must comply with the following constraints: 1、This method can only be + * used to initialize the component tree in parallel mode. 2、The task can only be processed during system cold + * start. 3、If the parallel loading mechanism is used, the component tree-related operations to be performed in + * onActive() and onStop() of the ability slice must also be added to the parallel thread. 4、You must run + * setUIContent(ohos.agp.components.ComponentContainer) to unlock the UI thread and wait until the component tree is + * ready. 5、Other time-consuming operations, such as I/O and network processing, cannot be added to the parallel + * task queue. + * + * @param task Indicates the Runnable task to post. + * + * @param delayTime Indicates the number of milliseconds after which the task will be executed. + * + * @return - + */ + void PostTask(std::function task, long delayTime); + + /** + * @brief Called to set caller information for the application. The default implementation returns null. + * + * @return Returns the caller information. + */ + virtual Uri OnSetCaller(); + + /** + * @brief Call this when your ability should be closed and the mission should be completely removed as a part of + * finishing the root ability of the mission. + */ + void TerminateAndRemoveMission() override; + + /** + * @brief Create a PostEvent timeout task. The default delay is 5000ms + * + * @return Return a smart pointer to a timeout object + */ + std::shared_ptr CreatePostEventTimeouter(std::string taskstr); + + /** + * Releases an obtained form by its ID. + * + *

After this method is called, the form won't be available for use by the application, but the Form Manager + * Service still keeps the cache information about the form, so that the application can quickly obtain it based on + * the {@code formId}.

+ *

Permission: {@link ohos.security.SystemPermission#REQUIRE_FORM}

+ * + * @param formId Indicates the form ID. + * @return Returns {@code true} if the form is successfully released; returns {@code false} otherwise. + * + *
    + *
  • The passed {@code formId} is invalid. Its value must be larger than 0.
  • + *
  • The specified form has not been added by the application.
  • + *
  • An error occurred when connecting to the Form Manager Service.
  • + *
  • The application is not granted with the {@link ohos.security.SystemPermission#REQUIRE_FORM} permission.
  • + *
  • The form has been obtained by another application and cannot be released by the current application.
  • + *
  • The form is being restored.
  • + *
+ */ + bool ReleaseForm(const int64_t formId); + + /** + * @brief Releases an obtained form by its ID. + * + *

After this method is called, the form won't be available for use by the application, if isReleaseCache is + * false, this method is same as {@link #releaseForm(int)}, otherwise the Form Manager Service still store this + * form in the cache.

+ *

Permission: {@link ohos.security.SystemPermission#REQUIRE_FORM}

+ * + * @param formId Indicates the form ID. + * @param isReleaseCache Indicates whether to clear cache in service. + * @return Returns {@code true} if the form is successfully released; returns {@code false} otherwise. + * + *
    + *
  • The passed {@code formId} is invalid. Its value must be larger than 0.
  • + *
  • The specified form has not been added by the application.
  • + *
  • An error occurred when connecting to the Form Manager Service.
  • + *
  • The application is not granted with the {@link ohos.security.SystemPermission#REQUIRE_FORM} permission.
  • + *
  • The form has been obtained by another application and cannot be released by the current application.
  • + *
  • The form is being restored.
  • + *
+ */ + bool ReleaseForm(const int64_t formId, const bool isReleaseCache); + + /** + * @brief Deletes an obtained form by its ID. + * + *

After this method is called, the form won't be available for use by the application and the Form Manager + * Service no longer keeps the cache information about the form.

+ *

Permission: {@link ohos.security.SystemPermission#REQUIRE_FORM}

+ * + * @param formId Indicates the form ID. + * @return Returns {@code true} if the form is successfully deleted; returns {@code false} otherwise. + * + *
    + *
  • The passed {@code formId} is invalid. Its value must be larger than 0.
  • + *
  • The specified form has not been added by the application.
  • + *
  • An error occurred when connecting to the Form Manager Service.
  • + *
  • The application is not granted with the {@link ohos.security.SystemPermission#REQUIRE_FORM} permission.
  • + *
  • The form has been obtained by another application and cannot be deleted by the current application.
  • + *
  • The form is being restored.
  • + *
+ */ + bool DeleteForm(const int64_t formId); + + /** + * @brief The form callback. + */ + class FormCallback { + public: + static const int32_t OHOS_FORM_ACQUIRE_SUCCESS = 0; + static const int32_t OHOS_FORM_UPDATE_SUCCESS = 0; + static const int32_t OHOS_FORM_PREVIEW_FAILURE = 1; + static const int32_t OHOS_FORM_RESTORE_FAILURE = 2; + + /** + * @brief Called to notify the application that the {@code FormJsInfo} instance has been obtained after + * the application called the asynchronous method {@link Ability#acquireForm(Want, FormCallback)}. + * The application must present the form information on a specific page in this callback. + * + * @param result Specifies whether the asynchronous form acquisition process is successful. + * {@link FormCallback#OHOS_FORM_ACQUIRE_SUCCESS} indicates that the form + * is successfully obtained, and other values indicate that the process fails. + * @param formJsInfo Indicates the obtained {@code FormJsInfo} instance. + */ + virtual void OnAcquired(const int32_t result, const FormJsInfo &formJsInfo) const = 0; + + /** + * @brief Called to notify the application that the {@code FormJsInfo} instance has been obtained after + * the application called the asynchronous method {@link Ability#acquireForm(Want, FormCallback)}. + * The application must present the form information on a specific page in this callback. + * + * @param result Specifies whether the asynchronous form acquisition process is successful. + * {@link FormCallback#OHOS_FORM_UPDATE_SUCCESS} indicates that the form is + * successfully obtained, and other values indicate that the process fails. + * @param formJsInfo Indicates the obtained {@code FormJsInfo} instance. + */ + virtual void OnUpdate(const int32_t result, const FormJsInfo &formJsInfo) const = 0; + + /** + * @brief Called to notify the application that the {@code Form} provider has been uninstalled and the + * corresponding + * {@code Form} instance is no longer available. + * + * @param formId Indicates the ID of the {@code Form} instance provided by the uninstalled form provider. + */ + virtual void OnFormUninstall(const int64_t formId) const = 0; + }; + + /** + * @brief Obtains a specified form that matches the application bundle name, module name, form name, and + * other related information specified in the passed {@code Want}. + * + *

This method is asynchronous. After the {@link FormJsInfo} instance is obtained. + * + * @param formId Indicates the form ID. + * @param want Indicates the detailed information about the form to be obtained, including the bundle name, + * module name, ability name, form name, form id, tempForm flag, form dimension, and form customize data. + * @param callback Indicates the callback to be invoked whenever the {@link FormJsInfo} instance is obtained. + * @return Returns {@code true} if the request is successfully initiated; returns {@code false} otherwise. + */ + bool AcquireForm(const int64_t formId, const Want &want, const std::shared_ptr callback); + + /** + * @brief Updates the content of a specified JS form. + * + *

This method is called by a form provider to update JS form data as needed. + * + * @param formId Indicates the form ID. + * @param formProviderData The data used to update the JS form displayed on the client. + * @return Returns {@code true} if the request is successfully initiated; returns {@code false} otherwise. + */ + bool UpdateForm(const int64_t formId, const FormProviderData &formProviderData); + + /** + * @brief Cast temp form with formId. + * + * @param formId Indicates the form's ID. + * + * @return Returns {@code true} if the form is successfully casted; returns {@code false} otherwise. + */ + bool CastTempForm(const int64_t formId); + + /** + * @brief Sends a notification to the form framework to make the specified forms visible. + * + *

After this method is successfully called, {@link Ability#OnVisibilityChanged(std::map)} + * will be called to notify the form provider of the form visibility change event.

+ * + * @param formIds Indicates the IDs of the forms to be made visible. + * @return Returns {@code true} if the request is successfully initiated; returns {@code false} otherwise. + */ + bool NotifyVisibleForms(const std::vector &formIds); + + /** + * @brief Sends a notification to the form framework to make the specified forms invisible. + * + *

After this method is successfully called, {@link Ability#OnVisibilityChanged(std::map)} + * will be called to notify the form provider of the form visibility change event.

+ * + * @param formIds Indicates the IDs of the forms to be made invisible. + * @return Returns {@code true} if the request is successfully initiated; returns {@code false} otherwise. + */ + bool NotifyInvisibleForms(const std::vector &formIds); + + /** + * @brief Set form next refresh time. + * + *

This method is called by a form provider to set refresh time. + * + * @param formId Indicates the ID of the form to set refresh time. + * @param nextTime Indicates the next time gap now in seconds, can not be litter than 300 seconds. + * @return Returns {@code true} if seting succeed; returns {@code false} otherwise. + */ + + bool SetFormNextRefreshTime(const int64_t formId, const int64_t nextTime); + + /** + * @brief Update form. + * + * @param formJsInfo Indicates the obtained {@code FormJsInfo} instance. + */ + void ProcessFormUpdate(const FormJsInfo &formJsInfo) override; + + /** + * @brief Uninstall form. + * + * @param formId Indicates the ID of the form to uninstall. + */ + void ProcessFormUninstall(const int64_t formId) override; + + /** + * @brief Called to reacquire form and update the form host after the death callback is received. + * + */ + void OnDeathReceived() override; + + /** + * @brief Called to return a FormProviderInfo object. + * + *

You must override this method if your ability will serve as a form provider to provide a form for clients. + * The default implementation returns nullptr.

+ * + * @param want Indicates the detailed information for creating a FormProviderInfo. + * The Want object must include the form ID, form name of the form, + * which can be obtained from Ability#PARAM_FORM_IDENTITY_KEY, + * Ability#PARAM_FORM_NAME_KEY, and Ability#PARAM_FORM_DIMENSION_KEY, + * respectively. Such form information must be managed as persistent data for further form + * acquisition, update, and deletion. + * + * @return Returns the created FormProviderInfo object. + */ + virtual FormProviderInfo OnCreate(const Want &want); + + /** + * @brief Called to notify the form provider that a specified form has been deleted. Override this method if + * you want your application, as the form provider, to be notified of form deletion. + * + * @param formId Indicates the ID of the deleted form. + * @return None. + */ + virtual void OnDelete(const int64_t formId); + + /** + * @brief Called when the form provider is notified that a temporary form is successfully converted to + * a normal form. + * + * @param formId Indicates the ID of the form. + * @return None. + */ + virtual void OnCastTemptoNormal(const int64_t formId); + + /** + * @brief Called to notify the form provider to update a specified form. + * + * @param formId Indicates the ID of the form to update. + * @return none. + */ + virtual void OnUpdate(const int64_t formId); + + /** + * @brief Called when the form provider receives form events from the fms. + * + * @param formEventsMap Indicates the form events occurred. The key in the Map object indicates the form ID, + * and the value indicates the event type, which can be either FORM_VISIBLE + * or FORM_INVISIBLE. FORM_VISIBLE means that the form becomes visible, + * and FORM_INVISIBLE means that the form becomes invisible. + * @return none. + */ + virtual void OnVisibilityChanged(const std::map &formEventsMap); + /** + * @brief Called to notify the form provider to update a specified form. + * + * @param formId Indicates the ID of the form to update. + * @param message Form event message. + */ + virtual void OnTriggerEvent(const int64_t formId, const std::string &message); + /** + * @brief Requests for form data update. + * + * This method must be called when the application has detected that a system setting item (such as the language, + * resolution, or screen orientation) being listened for has changed. Upon receiving the update request, the form + * provider automatically updates the form data (if there is any update) through the form framework, with the update + * process being unperceivable by the application. + * + * @param formId Indicates the ID of the form to update. + * @return Returns true if the update request is successfully initiated, returns false otherwise. + */ + bool RequestForm(const int64_t formId); + + /** + * @brief Requests for form data update, by passing a set of parameters (using Want) to the form provider. + * + * This method must be called when the application has detected that a system setting item (such as the language, + * resolution, or screen orientation) being listened for has changed. Upon receiving the update request, the form + * provider automatically updates the form data (if there is any update) through the form framework, with the update + * process being unperceivable by the application. + * + * @param formId Indicates the ID of the form to update. + * @param want Indicates a set of parameters to be transparently passed to the form provider. + * @return Returns true if the update request is successfully initiated, returns false otherwise. + */ + bool RequestForm(const int64_t formId, const Want &want); + /** + * @brief Enable form update. + * + * @param formIds formIds of hostclient. + */ + bool EnableUpdateForm(const std::vector &formIds); + + /** + * @brief Disable form update. + * + * @param formIds formIds of hostclient. + */ + bool DisableUpdateForm(const std::vector &formIds); + + /** + * @brief Check form manager service ready. + * + * @return Returns true if form manager service ready; returns false otherwise. + */ + bool CheckFMSReady(); + + /** + * @brief Get All FormsInfo. + * + * @param formInfos Returns the forms' information of all forms provided. + * @return Returns true if the request is successfully initiated; returns false otherwise. + */ + bool GetAllFormsInfo(std::vector &formInfos); + + /** + * @brief Get forms info by application name. + * + * @param bundleName Application name. + * @param formInfos Returns the forms' information of the specify application name. + * @return Returns true if the request is successfully initiated; returns false otherwise. + */ + bool GetFormsInfoByApp(std::string &bundleName, std::vector &formInfos); + + /** + * @brief Get forms info by application name and module name. + * + * @param bundleName Application name. + * @param moduleName Module name of hap. + * @param formInfos Returns the forms' information of the specify application name and module name. + * @return Returns true if the request is successfully initiated; returns false otherwise. + */ + bool GetFormsInfoByModule(std::string &bundleName, std::string &moduleName, std::vector &formInfos); + + /** + * @brief Acquire a bundle manager, if it not existed, + * @return returns the bundle manager ipc object, or nullptr for failed. + */ + sptr GetBundleMgr(); + + /** + * @brief check permission of bundle, if it not existed. + * @return returns the permission is vaild, or false for failed. + */ + bool CheckPermission(); + + /** + * @brief Permission check. + * @param bundleName bundleName. + * @return Returns true on success, false on failure. + */ + bool CheckFormPermission(const std::string &bundleName) const; + + /** + * @brief Add the bundle manager instance for debug. + * @param bundleManager the bundle manager ipc object. + */ + void SetBundleManager(const sptr &bundleManager); + + /** + * @brief You can use the IContinuationRegisterManager object to interact with the Device+ control center, + * including registering and unregistering the ability to migrate, updating the device connection state, and + * showing the list of devices that can be selected for ability migration. + * + * @return Returns true if the migration request is successful; returns false otherwise. + */ + std::weak_ptr GetContinuationRegisterManager(); + + /** + * @brief Migrates this ability to the given device on the same distributed network. The ability to migrate and its + * ability slices must implement the IAbilityContinuation interface. + * + * @param deviceId Indicates the ID of the target device where this ability will be migrated to. If this parameter + * is null, this method has the same effect as continueAbility(). + * + */ + virtual void ContinueAbility(const std::string &deviceId) final; + + /** + * @brief Callback function to ask the user whether to start the migration . + * + * @return If the user allows migration, it returns true; otherwise, it returns false. + */ + virtual bool OnStartContinuation() override; + + /** + * @brief Performs batch operations on the database. + * + * @param operations Indicates a list of database operations on the database. + * @return Returns the result of each operation, in array. + */ + virtual std::vector> ExecuteBatch( + const std::vector> &operations); + + /** + * @brief Executes an operation among the batch operations to be executed. + * + * @param operation Indicates the operation to execute. + * @param results Indicates a set of results of the batch operations. + * @param index Indicates the index of the current operation result in the batch operation results. + */ + void ExecuteOperation(std::shared_ptr &operation, + std::vector> &results, int index); + + /** + * @brief Save user data of local Ability generated at runtime. + * + * @param saveData Indicates the user data to be saved. + * @return If the data is saved successfully, it returns true; otherwise, it returns false. + */ + virtual bool OnSaveData(WantParams &saveData) override; + + /** + * @brief After creating the Ability on the remote device, + * immediately restore the user data saved during the migration of the Ability on the remote device. + * @param restoreData Indicates the user data to be restored. + * @return If the data is restored successfully, it returns true; otherwise, it returns false . + */ + virtual bool OnRestoreData(WantParams &restoreData) override; + + /** + * @brief This function can be used to implement the processing logic after the migration is completed. + * + * @param result Migration result code. 0 means the migration was successful, -1 means the migration failed. + * @return None. + */ + virtual void OnCompleteContinuation(int result) override; + + /** + * @brief Used to notify the local Ability that the remote Ability has been destroyed. + * + * @return None. + */ + virtual void OnRemoteTerminated() override; + +protected: + /** + * @brief Acquire a form provider remote object. + * @return Returns form provider remote object. + */ + sptr GetFormRemoteObject(); + +private: + std::shared_ptr ParsePredictionArgsReference( + std::vector> &results, std::shared_ptr &operation, + int numRefs); + + std::shared_ptr ParseValuesBucketReference( + std::vector> &results, std::shared_ptr &operation, + int numRefs); + + int ChangeRef2Value(std::vector> &results, int numRefs, int index); + + bool CheckAssertQueryResult(std::shared_ptr &queryResult, + std::shared_ptr &&valuesBucket); + + friend class AbilityImpl; + bool VerifySupportForContinuation(); + void HandleCreateAsContinuation(const Want &want); + bool IsFlagExists(unsigned int flag, unsigned int flagSet); + /** + * @brief Set the start ability setting. + * @param setting the start ability setting. + */ + void SetStartAbilitySetting(std::shared_ptr setting); + +private: + std::shared_ptr continuationHandler_ = nullptr; + std::shared_ptr continuationManager_ = nullptr; + std::shared_ptr continuationRegisterManager_ = nullptr; + std::shared_ptr abilityInfo_ = nullptr; + std::shared_ptr context_ = nullptr; + std::shared_ptr handler_ = nullptr; + std::shared_ptr lifecycle_ = nullptr; + std::shared_ptr abilityLifecycleExecutor_ = nullptr; + std::shared_ptr application_ = nullptr; + std::vector types_; + std::shared_ptr abilityWindow_ = nullptr; + std::shared_ptr setWant_ = nullptr; + sptr reverseContinuationSchedulerReplica_ = nullptr; + std::shared_ptr setting_ = nullptr; + bool bWindowFocus_ = false; + + static const std::string SYSTEM_UI; + static const std::string STATUS_BAR; + static const std::string NAVIGATION_BAR; + sptr providerRemoteObject_ = nullptr; + // Keep consistent with DMS defines. Used to callback to DMS. + static const std::string DMS_SESSION_ID; + + // The originating deviceId passed by DMS using intent param. + static const std::string DMS_ORIGIN_DEVICE_ID; + + // If session id cannot get from intent, assign it as default. + static const int DEFAULT_DMS_SESSION_ID; + + std::vector lostedByReconnectTempForms_; + std::map> appCallbacks_; + std::map userReqParams_; + sptr iBundleMgr_; + + static const int32_t OHOS_FORM_ACQUIRE_FORM = 0; + static const int32_t OHOS_FORM_UPDATE_FORM = 1; + + static const int32_t DELETE_FORM = 3; + static const int32_t ENABLE_FORM_UPDATE = 5; + static const int32_t DISABLE_FORM_UPDATE = 6; + static const int32_t RELEASE_FORM = 8; + static const int32_t RELEASE_CACHED_FORM = 9; + static const int64_t MIN_NEXT_TIME = 5; + +private: + /** + * @brief Delete or release form with formId. + * + * @param formId Indicates the form's ID. + * @param deleteType Indicates the type of delete or release. + * @return Returns {@code true} if the form is successfully deleted; returns {@code false} otherwise. + */ + bool DeleteForm(const int64_t formId, const int32_t deleteType); + + /** + * @brief Clean form resource with formId. + * + * @param formId Indicates the form's ID. + */ + void CleanFormResource(const int64_t formId); + + /** + * @brief Handle acquire result of the obtained form instance. + * + * @param want Indicates the detailed information about the form to be obtained, including the bundle name, + * module name, ability name, form name, form id, tempForm flag, form dimension, and form customize data. + * @param formJsInfo Indicates the obtained {@code FormJsInfo} instance. + * @param callback Indicates the callback to be invoked whenever the {@link FormJsInfo} instance is obtained. + */ + void HandleAcquireResult( + const Want &want, + const FormJsInfo &formJsInfo, + const std::shared_ptr callback + ); + + /** + * @brief Handle acquire message of the obtained form instance. + * + * @param msgCode Indicates the code of message type. + * @param formJsInfo Indicates the obtained {@code FormJsInfo} instance. + */ + void HandleFormMessage(const int32_t msgCode, const FormJsInfo &formJsInfo); + + /** + * @brief Notify the forms visibility change event. + * + * @param formIds Indicates the IDs of the forms to be made visible or invisible. + * @param eventType Indicates the form events occurred. FORM_VISIBLE means that the form becomes visible, + * and FORM_INVISIBLE means that the form becomes invisible. + * @return none. + */ + bool NotifyWhetherVisibleForms(const std::vector &formIds, int32_t eventType); + + /** + * @brief Check the param of want. + * + * @param formId Indicates the form's ID. + * @param want Indicates the detailed information about the form to be obtained, including the bundle name, + * module name, ability name, form name, form id, tempForm flag, form dimension, and form customize data. + * @return Returns {@code true} if the check result is ok; returns {@code false} ng. + */ + bool CheckWantValid(const int64_t formId, const Want &want); + + /** + * @brief Handle enable/disable form update. + * + * @param formIds Indicates the IDs of the forms to be made visible. + * @param updateType Update type. + * @return Returns true if the result is ok; returns false otherwise. + */ + bool LifecycleUpdate(std::vector formIds, int32_t updateType); + + /** + * @brief Reacquire a specified form when the death callback is received. + * + * @param formId Indicates the form ID. + * @param want Indicates the detailed information about the form to be obtained. + * @return Returns true if the request is successfully initiated; returns false otherwise. + */ + bool ReAcquireForm(const int64_t formId, const Want &want); +}; + +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_APPEXECFWK_OHOS_ABILITY_H diff --git a/tools/frameworks/kits/ability/native/include/ability_context.h b/tools/frameworks/kits/ability/native/include/ability_context.h new file mode 100755 index 00000000000..121de7fe2c2 --- /dev/null +++ b/tools/frameworks/kits/ability/native/include/ability_context.h @@ -0,0 +1,732 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_APPEXECFWK_OHOS_ABILITY_CONTEXT_H +#define FOUNDATION_APPEXECFWK_OHOS_ABILITY_CONTEXT_H + +#include + +#include "context_container.h" +#include "data_ability_helper.h" +#include "distributed_sched_interface.h" +#include "distributed_sched_proxy.h" + +namespace OHOS { +namespace AppExecFwk { +class AbilityContext : public ContextContainer { +public: + AbilityContext() = default; + virtual ~AbilityContext() = default; + + /** + * Attaches a Context object to the current ability. + * Generally, this method is called after Ability is loaded to provide the application context for the current + * ability. + * + * @param base Indicates a Context object. + */ + void AttachBaseContext(const std::shared_ptr &base); + + /** + * @brief Obtains the absolute path to the application-specific cache directory + * on the primary external or shared storage device. + * + * @return Returns the absolute path to the application-specific cache directory on the external or + * shared storage device; returns null if the external or shared storage device is temporarily unavailable. + */ + std::string GetExternalCacheDir() override; + + /** + * @brief Obtains the absolute path to the directory for storing files for the application on the + * primary external or shared storage device. + * + * @param type Indicates the type of the file directory to return + * + * @return Returns the absolute path to the application file directory on the external or shared storage + * device; returns null if the external or shared storage device is temporarily unavailable. + */ + std::string GetExternalFilesDir(std::string &type) override; + + /** + * @brief Obtains the directory for storing files for the application on the device's internal storage. + * + * @return Returns the application file directory. + */ + std::string GetFilesDir() override; + + /** + * @brief Obtains the absolute path which app created and will be excluded from automatic backup to remote storage. + * The returned path maybe changed if the application is moved to an adopted storage device. + * + * @return The path of the directory holding application files that will not be automatically backed up to remote + * storage. + */ + std::string GetNoBackupFilesDir() override; + + /** + * @brief Remove permissions for all users who have access to specific permissions + * + * @param permission Indicates the permission to unauth. This parameter cannot be null. + * @param uri Indicates the URI to unauth. This parameter cannot be null. + * @param uid Indicates the UID of the unauth to check. + * + */ + void UnauthUriPermission(const std::string &permission, const Uri &uri, int uid) override; + + /** + * @brief Obtains the distributed file path. + * If the distributed file path does not exist, the system creates one and returns the created path. This method is + * applicable only to the context of an ability rather than that of an application. + * + * @return Returns the distributed file. + */ + std::string GetDistributedDir() override; + + /** + * @brief Sets the pattern of this Context based on the specified pattern ID. + * + * @param patternId Indicates the resource ID of the pattern to set. + */ + void SetPattern(int patternId) override; + + /** + * @brief Obtains the Context object of this ability. + * + * @return Returns the Context object of this ability. + */ + std::shared_ptr GetAbilityPackageContext() override; + + /** + * @brief Obtains the name of the current process. + * + * @return Returns the current process name. + */ + std::string GetProcessName() override; + + /** + * @brief InitResourceManager + * + * @param bundleInfo BundleInfo + */ + void InitResourceManager(BundleInfo &bundleInfo, std::shared_ptr &deal); + + /** + * @brief Starts a new ability. + * An ability using the AbilityInfo.AbilityType.SERVICE or AbilityInfo.AbilityType.PAGE template uses this method + * to start a specific ability. The system locates the target ability from installed abilities based on the value + * of the want parameter and then starts it. You can specify the ability to start using the want parameter. + * + * @param want Indicates the Want containing information about the target ability to start. + * + * @param requestCode Indicates the request code returned after the ability using the AbilityInfo.AbilityType.PAGE + * template is started. You can define the request code to identify the results returned by abilities. The value + * ranges from 0 to 65535. This parameter takes effect only on abilities using the AbilityInfo.AbilityType.PAGE + * template. + * + */ + using ContextContainer::StartAbility; + void StartAbility(const AAFwk::Want &Want, int requestCode) override; + + /** + * @brief Starts a new ability with special ability start setting. + * + * @param want Indicates the Want containing information about the target ability to start. + * @param requestCode Indicates the request code returned after the ability is started. You can define the request + * code to identify the results returned by abilities. The value ranges from 0 to 65535. + * @param abilityStartSetting Indicates the special start setting used in starting ability. + * + */ + void StartAbility(const Want &want, int requestCode, const AbilityStartSetting &abilityStartSetting) override; + + /** + * @brief Destroys another ability you had previously started by calling Ability.startAbilityForResult + * (ohos.aafwk.content.Want, int, ohos.aafwk.ability.startsetting.AbilityStartSetting) with the same requestCode + * passed. + * + * @param requestCode Indicates the request code passed for starting the ability. + * + */ + void TerminateAbility(int requestCode) override; + + /** + * @brief Destroys the current ability. + * + */ + void TerminateAbility() override; + + /** + * @brief Obtains the bundle name of the ability that called the current ability. + * You can use the obtained bundle name to check whether the calling ability is allowed to receive the data you will + * send. If you did not use Ability.startAbilityForResult(ohos.aafwk.content.Want, int, + * ohos.aafwk.ability.startsetting.AbilityStartSetting) to start the calling ability, null is returned. + * + * @return Returns the bundle name of the calling ability; returns null if no calling ability is available. + */ + std::string GetCallingBundle() override; + + /** + * @brief Obtains the ohos.bundle.ElementName object of the current ability. + * + * @return Returns the ohos.bundle.ElementName object of the current ability. + */ + std::shared_ptr GetElementName(); + + /** + * @brief Obtains the ElementName of the ability that called the current ability. + * + * @return Returns the ElementName of the calling ability; returns null if no calling ability is available. + */ + std::shared_ptr GetCallingAbility(); + + /** + * @brief Connects the current ability to an ability using the AbilityInfo.AbilityType.SERVICE template. + * + * @param want Indicates the want containing information about the ability to connect + * + * @param conn Indicates the callback object when the target ability is connected. + * + * @return True means success and false means failure + */ + bool ConnectAbility(const Want &want, const sptr &conn) override; + + /** + * @brief Disconnects the current ability from an ability + * + * @param conn Indicates the IAbilityConnection callback object passed by connectAbility after the connection + * is set up. The IAbilityConnection object uniquely identifies a connection between two abilities. + */ + void DisconnectAbility(const sptr &conn) override; + + /** + * @brief Destroys another ability that uses the AbilityInfo.AbilityType.SERVICE template. + * The current ability using either the AbilityInfo.AbilityType.SERVICE or AbilityInfo.AbilityType.PAGE + * template can call this method to destroy another ability that uses the AbilityInfo.AbilityType.SERVICE + * template. The current ability itself can be destroyed by calling the terminateAbility() method. + * + * @param want Indicates the Want containing information about the ability to destroy. + * + * @return Returns true if the ability is destroyed successfully; returns false otherwise. + */ + virtual bool StopAbility(const AAFwk::Want &want) override; + + /** + * @brief Obtains information about the current application. The returned application information includes basic + * information such as the application name and application permissions. + * + * @return Returns the ApplicationInfo for the current application. + */ + std::shared_ptr GetApplicationInfo() const override; + + /** + * @brief Obtains the application-specific cache directory on the device's internal storage. The system + * automatically deletes files from the cache directory if disk space is required elsewhere on the device. + * Older files are always deleted first. + * + * @return Returns the application-specific cache directory. + */ + std::string GetCacheDir() override; + + /** + * @brief Obtains the application-specific code-cache directory on the device's internal storage. + * The system will delete any files stored in this location both when your specific application is upgraded, + * and when the entire platform is upgraded. + * + * @return Returns the application-specific code-cache directory. + */ + std::string GetCodeCacheDir() override; + + /** + * @brief Obtains the local database path. + * If the local database path does not exist, the system creates one and returns the created path. + * + * @return Returns the local database file. + */ + std::string GetDatabaseDir() override; + + /** + * @brief Obtains the absolute path where all private data files of this application are stored. + * + * @return Returns the absolute path storing all private data files of this application. + */ + std::string GetDataDir() override; + + /** + * @brief Obtains the directory for storing custom data files of the application. + * You can use the returned File object to create and access files in this directory. The files + * can be accessible only by the current application. + * + * @param name Indicates the name of the directory to retrieve. This directory is created as part + * of your application data. + * @param mode Indicates the file operating mode. The value can be 0 or a combination of MODE_PRIVATE. + * + * @return Returns a File object for the requested directory. + */ + std::string GetDir(const std::string &name, int mode) override; + + /** + * @brief Obtains an IBundleMgr instance. + * You can use this instance to obtain information about the application bundle. + * + * @return Returns an IBundleMgr instance. + */ + sptr GetBundleManager() const override; + + /** + * @brief Obtains the path of the package containing the current ability. The returned path contains the resources, + * source code, and configuration files of a module. + * + * @return Returns the path of the package file. + */ + std::string GetBundleCodePath() override; + + /** + * @brief Obtains the bundle name of the current ability. + * + * @return Returns the bundle name of the current ability. + */ + std::string GetBundleName() override; + + /** + * @brief Obtains the path of the OHOS Ability Package (HAP} containing this ability. + * + * @return Returns the path of the HAP containing this ability. + */ + std::string GetBundleResourcePath() override; + + /** + * @brief Obtains the Context object of the application. + * + * @return Returns the Context object of the application. + */ + std::shared_ptr GetApplicationContext() const override; + + /** + * @brief Obtains the Context object of the application. + * + * @return Returns the Context object of the application. + */ + std::shared_ptr GetContext() override; + + /** + * @brief Obtains an ability manager. + * The ability manager provides information about running processes and memory usage of an application. + * + * @return Returns an IAbilityManager instance. + */ + sptr GetAbilityManager() override; + + /** + * Called when getting the ProcessInfo + * + * @return ProcessInfo + */ + std::shared_ptr GetProcessInfo() const override; + + /** + * @brief Obtains the type of this application. + * + * @return Returns system if this application is a system application; + * returns normal if it is released in official AppGallery; + * returns other if it is released by a third-party vendor; + * returns an empty string if the query fails. + */ + std::string GetAppType() override; + + /** + * @brief Obtains information about the current ability. + * The returned information includes the class name, bundle name, and other information about the current ability. + * + * @return Returns the AbilityInfo object for the current ability. + */ + const std::shared_ptr GetAbilityInfo() override; + + /** + * @brief Obtains the HapModuleInfo object of the application. + * + * @return Returns the HapModuleInfo object of the application. + */ + std::shared_ptr GetHapModuleInfo() override; + + /** + * @brief Creates a Context object for an application with the given bundle name. + * + * @param bundleName Indicates the bundle name of the application. + * + * @param flag Indicates the flag for creating a Context object. It can be 0, any of + * the following values, or any combination of the following values: CONTEXT_IGNORE_SECURITY, + * CONTEXT_INCLUDE_CODE, and CONTEXT_RESTRICTED. The value 0 indicates that there is no restriction + * on creating contexts for applications. + * + * @return Returns a Context object created for the specified application. + */ + std::shared_ptr CreateBundleContext(std::string bundleName, int flag); + + /** + * @brief Obtains a resource manager. + * + * @return Returns a ResourceManager object. + */ + std::shared_ptr GetResourceManager() const override; + + /** + * @brief Checks whether the current process has the given permission. + * You need to call requestPermissionsFromUser(java.lang.std::string[],int) to request a permission only + * if the current process does not have the specific permission. + * + * @param permission Indicates the permission to check. This parameter cannot be null. + * + * @return Returns 0 (IBundleManager.PERMISSION_GRANTED) if the current process has the permission; + * returns -1 (IBundleManager.PERMISSION_DENIED) otherwise. + */ + virtual int VerifySelfPermission(const std::string &permission) override; + + /** + * @brief Checks whether the calling process for inter-process communication has the given permission. + * The calling process is not the current process. + * + * @param permission Indicates the permission to check. This parameter cannot be null. + * + * @return Returns 0 (IBundleManager.PERMISSION_GRANTED) if the calling process has the permission; + * returns -1 (IBundleManager.PERMISSION_DENIED) otherwise. + */ + virtual int VerifyCallingPermission(const std::string &permission) override; + + /** + * @brief Confirms with the permission management module to check whether a request prompt is required for granting + * a certain permission. You need to call the current method to check whether a prompt is required before calling + * requestPermissionsFromUser(java.lang.String[],int) to request a permission. If a prompt is not required, + * permission request will not be initiated. + * + * @param requestCode Indicates the permission to be queried. This parameter cannot be null. + * + * @return Returns true if the current application does not have the permission and the user does not turn off + * further requests; returns false if the current application already has the permission, the permission is rejected + * by the system, or the permission is denied by the user and the user has turned off further requests. + */ + virtual bool CanRequestPermission(const std::string &permission) override; + + /** + * @brief When there is a remote call to check whether the remote has permission, otherwise check whether it has + * permission + * + * @param permissions Indicates the list of permissions to be requested. This parameter cannot be null. + * @return Returns 0 (IBundleManager.PERMISSION_GRANTED) if the current process has the permission; + * returns -1 (IBundleManager.PERMISSION_DENIED) otherwise. + */ + virtual int VerifyCallingOrSelfPermission(const std::string &permission) override; + + /** + * @brief Query whether the application of the specified PID and UID has been granted a certain permission + * + * @param permissions Indicates the list of permissions to be requested. This parameter cannot be null. + * @param pid Process id + * @param uid + * @return Returns 0 (IBundleManager.PERMISSION_GRANTED) if the current process has the permission; + * returns -1 (IBundleManager.PERMISSION_DENIED) otherwise. + */ + virtual int VerifyPermission(const std::string &permission, int pid, int uid) override; + + /** + * @brief Requests certain permissions from the system. + * This method is called for permission request. This is an asynchronous method. When it is executed, + * the Ability.onRequestPermissionsFromUserResult(int, String[], int[]) method will be called back. + * + * @param permissions Indicates the list of permissions to be requested. This parameter cannot be null. + * @param requestCode Indicates the request code to be passed to the Ability.onRequestPermissionsFromUserResult(int, + * String[], int[]) callback method. This code cannot be a negative number. + */ + virtual void RequestPermissionsFromUser(std::vector &permissions, int requestCode) override; + + /** + * @brief Deletes the specified private file associated with the application. + * + * @param fileName Indicates the name of the file to delete. The file name cannot contain path separators. + * + * @return Returns true if the file is deleted successfully; returns false otherwise. + */ + bool DeleteFile(const std::string &fileName) override; + + /** + * @brief Set deviceId/bundleName/abilityName of the calling ability + * + * @param deviceId deviceId of the calling ability + * + * @param bundleName bundleName of the calling ability + * + * @param abilityName abilityName of the calling ability + */ + void SetCallingContext(const std::string &deviceId, const std::string &bundleName, const std::string &abilityName); + + /** + * @brief Obtains information about the caller of this ability. + * + * @return Returns the caller information. + */ + Uri GetCaller() override; + + /** + * @brief Get the string of this Context based on the specified resource ID. + * + * @param resId Indicates the resource ID of the string to get. + * + * @return Returns the string of this Context. + */ + std::string GetString(int resId) override; + + /** + * @brief Get the string array of this Context based on the specified resource ID. + * + * @param resId Indicates the resource ID of the string array to get. + * + * @return Returns the string array of this Context. + */ + std::vector GetStringArray(int resId) override; + + /** + * @brief Get the integer array of this Context based on the specified resource ID. + * + * @param resId Indicates the resource ID of the integer array to get. + * + * @return Returns the integer array of this Context. + */ + std::vector GetIntArray(int resId) override; + + /** + * @brief Obtains the theme of this Context. + * + * @return theme Returns the theme of this Context. + */ + std::map GetTheme() override; + + /** + * @brief Sets the theme of this Context based on the specified theme ID. + * + * @param themeId Indicates the resource ID of the theme to set. + */ + void SetTheme(int themeId) override; + + /** + * @brief Obtains the pattern of this Context. + * + * @return getPattern in interface Context + */ + std::map GetPattern() override; + + /** + * @brief Get the color of this Context based on the specified resource ID. + * + * @param resId Indicates the resource ID of the color to get. + * + * @return Returns the color value of this Context. + */ + int GetColor(int resId) override; + + /** + * @brief Obtains the theme id of this {@code Context}. + * + * @return int Returns the theme id of this {@code Context}. + */ + int GetThemeId() override; + + /** + * @brief + * Destroys this Service ability if the number of times it has been started equals the number represented by the + * given {@code startId}. This method is the same as calling {@link #terminateAbility} to destroy this Service + * ability, except that this method helps you avoid destroying it if a client has requested a Service + * ability startup in {@link ohos.aafwk.ability.Ability#onCommand} but you are unaware of it. + * + * @param startId Indicates the number of startup times of this Service ability passed to + * {@link ohos.aafwk.ability.Ability#onCommand}. The {@code startId} is + * incremented by 1 every time this ability is started. For example, + * if this ability has been started for six times, the value of {@code startId} is {@code 6}. + * + * @return Returns {@code true} if the {@code startId} matches the number of startup times + * and this Service ability will be destroyed; returns {@code false} otherwise. + */ + bool TerminateAbilityResult(int startId) override; + + /** + * @brief Obtains the current display orientation of this ability. + * + * @return Returns the current display orientation. + */ + int GetDisplayOrientation() override; + + /** + * @brief Obtains the path storing the preference file of the application. + * If the preference file path does not exist, the system creates one and returns the created path. + * + * @return Returns the preference file path . + */ + std::string GetPreferencesDir() override; + + /** + * @brief Set color mode + * + * @param the value of color mode. + */ + void SetColorMode(int mode) override; + + /** + * @brief Obtains color mode. + * + * @return Returns the color mode value. + */ + int GetColorMode() override; + + /** + * @brief Obtains the unique ID of the mission containing this ability. + * + * @return Returns the unique mission ID. + */ + int GetMissionId() override; + + /** + * @brief Call this when your ability should be closed and the mission should be completely removed as a part of + * finishing the root ability of the mission. + */ + void TerminateAndRemoveMission() override; + + /** + * @brief Starts multiple abilities. + * + * @param wants Indicates the Want containing information array about the target ability to start. + */ + void StartAbilities(const std::vector &wants) override; + + /** + * @brief Checks whether this ability is the first ability in a mission. + * + * @return Returns true is first in Mission. + */ + bool IsFirstInMission() override; + + /** + * @brief Obtains a task dispatcher that is bound to the UI thread. + * + * @return Returns the task dispatcher that is bound to the UI thread. + */ + std::shared_ptr GetUITaskDispatcher() final override; + + /** + * @brief Obtains a task dispatcher that is bound to the application main thread. + * + * @return Returns the task dispatcher that is bound to the application main thread. + */ + std::shared_ptr GetMainTaskDispatcher() override; + + /** + * @brief Creates a parallel task dispatcher with a specified priority. + * + * @param name Indicates the task dispatcher name. This parameter is used to locate problems. + * @param priority Indicates the priority of all tasks dispatched by the parallel task dispatcher. + * + * @return Returns a parallel task dispatcher. + */ + std::shared_ptr CreateParallelTaskDispatcher( + const std::string &name, const TaskPriority &priority) override; + + /** + * @brief Creates a serial task dispatcher with a specified priority. + * + * @param name Indicates the task dispatcher name. This parameter is used to locate problems. + * @param priority Indicates the priority of all tasks dispatched by the created task dispatcher. + * + * @return Returns a serial task dispatcher. + */ + std::shared_ptr CreateSerialTaskDispatcher( + const std::string &name, const TaskPriority &priority) override; + + /** + * @brief Obtains a global task dispatcher with a specified priority. + * + * @param priority Indicates the priority of all tasks dispatched by the global task dispatcher. + * + * @return Returns a global task dispatcher. + */ + std::shared_ptr GetGlobalTaskDispatcher(const TaskPriority &priority) override; + + /** + * @brief Requires that tasks associated with a given capability token be moved to the background + * + * @param nonFirst If nonfirst is false and not the lowest ability of the mission, you cannot move mission to end + * + * @return Returns true on success, others on failure. + */ + bool MoveMissionToEnd(bool nonFirst) override; + + /** + * @brief Sets the application to start its ability in lock mission mode. + */ + void LockMission() override; + + /** + * @brief Unlocks this ability by exiting the lock mission mode. + */ + void UnlockMission() override; + + /** + * @brief Sets description information about the mission containing this ability. + * + * @param MissionInformation Indicates the object containing information about the + * mission. This parameter cannot be null. + * @return Returns true on success, others on failure. + */ + bool SetMissionInformation(const MissionInformation &missionInformation) override; + + friend DataAbilityHelper; + +public: + static int ABILITY_CONTEXT_DEFAULT_REQUEST_CODE; + +private: + /** + * @brief Get Current Ability Type + * + * @return Current Ability Type + */ + AppExecFwk::AbilityType GetAbilityInfoType(); + void GetPermissionDes(const std::string &permissionName, std::string &des); + + /** + * @brief Check whether it wants to operate a remote ability + * + * @param want Indicates the Want containing information about the ability to start. + * + * @return return true if it wamts to operate a remote ability, ohterwise return false. + */ + bool CheckIfOperateRemote(const Want &want); + + /** + * @brief Obtains a distributedSchedService. + * + * @return Returns an IDistributedSched proxy. + */ + std::shared_ptr GetDistributedSchedServiceProxy(); + +protected: + sptr GetToken() override; + sptr token_; + AAFwk::Want resultWant_; + int resultCode_ = -1; + std::string callingDeviceId_; + std::string callingBundleName_; + std::string callingAbilityName_; + std::map, sptr> abilityConnectionMap_; +}; + +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_APPEXECFWK_OHOS_ABILITY_CONTEXT_H diff --git a/tools/frameworks/kits/ability/native/include/ability_event_interface.h b/tools/frameworks/kits/ability/native/include/ability_event_interface.h new file mode 100644 index 00000000000..0d694c464cd --- /dev/null +++ b/tools/frameworks/kits/ability/native/include/ability_event_interface.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_APPEXECFWK_OHOS_ABILITY_EVENT_INTERFACE_H +#define FOUNDATION_APPEXECFWK_OHOS_ABILITY_EVENT_INTERFACE_H + +namespace OHOS { +namespace AppExecFwk { +class IAbilityEvent { +public: + IAbilityEvent() = default; + virtual ~IAbilityEvent() = default; + + /** + * @brief Called back when the Back key is pressed. + * + */ + virtual void OnBackPressed() = 0; +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_APPEXECFWK_OHOS_ABILITY_EVENT_INTERFACE_H \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/include/ability_handler.h b/tools/frameworks/kits/ability/native/include/ability_handler.h new file mode 100644 index 00000000000..22c5e4fe1c0 --- /dev/null +++ b/tools/frameworks/kits/ability/native/include/ability_handler.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_APPEXECFWK_ABILITY_HANDLER_H +#define FOUNDATION_APPEXECFWK_ABILITY_HANDLER_H + +#include "ability_thread.h" +#include "event_handler.h" +#include "refbase.h" + +namespace OHOS { +namespace AppExecFwk { +class AbilityThread; +class AbilityHandler : public EventHandler { +public: + AbilityHandler(const std::shared_ptr &runner, const sptr &server); + ~AbilityHandler() = default; + + /** + * Process the event. Developers should override this method. + * + * @param event The event should be processed. + */ + void ProcessEvent(const InnerEvent::Pointer &event) override; + +private: + sptr server_; +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_APPEXECFWK_ABILITY_HANDLER_H \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/include/ability_impl.h b/tools/frameworks/kits/ability/native/include/ability_impl.h new file mode 100644 index 00000000000..eb3a50955ae --- /dev/null +++ b/tools/frameworks/kits/ability/native/include/ability_impl.h @@ -0,0 +1,437 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_APPEXECFWK_OHOS_ABILITY_IMPL_H +#define FOUNDATION_APPEXECFWK_OHOS_ABILITY_IMPL_H + +#include "ability.h" +#include "ability_state.h" +#include "iability_lifecycle_callback.h" +#include "context.h" +#include "application_impl.h" +#include "ability_local_record.h" +#include "ability_handler.h" +#include "ability_manager_client.h" +#include "ability_manager_interface.h" +#include "dummy_component_container.h" +#include "dummy_values_bucket.h" +#include "dummy_data_ability_predicates.h" +#include "dummy_result_set.h" + +#ifdef MMI_COMPILE +#include "key_events.h" +#include "touch_events.h" +#include "ability_keyevent.h" +#include "ability_touchevent.h" +#else +#include "key_event.h" +#include "touch_event.h" +#endif + +namespace OHOS { +namespace AppExecFwk { +class Ability; +class AbilityHandler; +class ApplicationImpl; +class AbilityLocalRecord; +class AbilityLifecycleCallbacks; +class OHOSApplication; +class AbilityImpl : public std::enable_shared_from_this { +public: + AbilityImpl() = default; + virtual ~AbilityImpl() = default; + virtual void Init(std::shared_ptr &application, const std::shared_ptr &record, + std::shared_ptr &ability, std::shared_ptr &handler, const sptr &token, + std::shared_ptr &contextDeal); + + /** + * @brief Connect the ability. and Calling information back to Ability. + * + * @param want The Want object to connect to. + * + */ + sptr ConnectAbility(const Want &want); + + /** + * @brief Disconnects the connected object. + * + * @param want The Want object to disconnect to. + */ + void DisconnectAbility(const Want &want); + + /** + * @brief Command the ability. and Calling information back to Ability. + * + * @param want The Want object to command to. + * + * * @param restart Indicates the startup mode. The value true indicates that Service is restarted after being + * destroyed, and the value false indicates a normal startup. + * + * @param startId Indicates the number of times the Service ability has been started. The startId is incremented + * by 1 every time the ability is started. For example, if the ability has been started for six times, the value + * of startId is 6. + */ + void CommandAbility(const Want &want, bool restart, int startId); + + /** + * @brief Gets the current Ability status. + * + */ + int GetCurrentState(); + + /** + * @brief Save data and states of an ability when it is restored by the system. and Calling information back to + * Ability. This method should be implemented by a Page ability. + * @param instate The Want object to connect to. + * + */ + void DispatchSaveAbilityState(PacMap &outState); + + /** + * @brief Restores data and states of an ability when it is restored by the system. and Calling information back + * to Ability. This method should be implemented by a Page ability. + * @param instate The Want object to connect to. + * + */ + void DispatchRestoreAbilityState(const PacMap &inState); + + // Page Service Ability has different AbilityTransaction + virtual void HandleAbilityTransaction(const Want &want, const AAFwk::LifeCycleStateInfo &targetState); + + /** + * @brief Execution the KeyDown callback of the ability + * @param keyCode Indicates the code of the key pressed. + * @param keyEvent Indicates the key-down event. + * + * @return Returns true if this event is handled and will not be passed further; returns false if this event is + * not handled and should be passed to other handlers. + * + */ + virtual bool DoKeyDown(int keyCode, const KeyEvent &keyEvent); + + /** + * @brief Execution the KeyUp callback of the ability + * @param keyCode Indicates the code of the key released. + * @param keyEvent Indicates the key-up event. + * + * @return Returns true if this event is handled and will not be passed further; returns false if this event is + * not handled and should be passed to other handlers. + * + */ + virtual bool DoKeyUp(int keyCode, const KeyEvent &keyEvent); + + /** + * @brief Called when a touch event is dispatched to this ability. The default implementation of this callback + * does nothing and returns false. + * @param touchEvent Indicates information about the touch event. + * + * @return Returns true if the event is handled; returns false otherwise. + * + */ + virtual bool DoTouchEvent(const TouchEvent &touchEvent); + + /** + * @brief Send the result code and data to be returned by this Page ability to the caller. + * When a Page ability is destroyed, the caller overrides the AbilitySlice#onAbilityResult(int, int, Want) + * method to receive the result set in the current method. This method can be called only after the ability has + * been initialized. + * + * @param requestCode Indicates the request code. + * @param resultCode Indicates the result code returned after the ability is destroyed. You can define the + * result code to identify an error. + * @param resultData Indicates the data returned after the ability is destroyed. You can define the data + * returned. This parameter can be null. + */ + void SendResult(int requestCode, int resultCode, const Want &resultData); + + /** + * @brief Called when the launch mode of an ability is set to singleInstance. This happens when you re-launch + * an ability that has been at the top of the ability stack. + * + * @param want Indicates the new Want containing information about the ability. + */ + void NewWant(const Want &want); + + /** + * @brief Obtains the MIME types of files supported. + * + * @param uri Indicates the path of the files to obtain. + * @param mimeTypeFilter Indicates the MIME types of the files to obtain. This parameter cannot be null. + * + * @return Returns the matched MIME types. If there is no match, null is returned. + */ + virtual std::vector GetFileTypes(const Uri &uri, const std::string &mimeTypeFilter); + + /** + * @brief Opens a file in a specified remote path. + * + * @param uri Indicates the path of the file to open. + * @param mode Indicates the file open mode, which can be "r" for read-only access, "w" for write-only access + * (erasing whatever data is currently in the file), "wt" for write access that truncates any existing file, + * "wa" for write-only access to append to any existing data, "rw" for read and write access on any existing + * data, or "rwt" for read and write access that truncates any existing file. + * + * @return Returns the file descriptor. + */ + virtual int OpenFile(const Uri &uri, const std::string &mode); + + /** + * @brief This is like openFile, open a file that need to be able to return sub-sections of files,often assets + * inside of their .hap. + * + * @param uri Indicates the path of the file to open. + * @param mode Indicates the file open mode, which can be "r" for read-only access, "w" for write-only access + * (erasing whatever data is currently in the file), "wt" for write access that truncates any existing file, + * "wa" for write-only access to append to any existing data, "rw" for read and write access on any existing + * data, or "rwt" for read and write access that truncates any existing file. + * + * @return Returns the RawFileDescriptor object containing file descriptor. + */ + virtual int OpenRawFile(const Uri &uri, const std::string &mode); + + /** + * @brief Inserts a single data record into the database. + * + * @param uri Indicates the path of the data to operate. + * @param value Indicates the data record to insert. If this parameter is null, a blank row will be inserted. + * + * @return Returns the index of the inserted data record. + */ + virtual int Insert(const Uri &uri, const NativeRdb::ValuesBucket &value); + + /** + * @brief Updates data records in the database. + * + * @param uri Indicates the path of data to update. + * @param value Indicates the data to update. This parameter can be null. + * @param predicates Indicates filter criteria. You should define the processing logic when this parameter is + * null. + * + * @return Returns the number of data records updated. + */ + virtual int Update(const Uri &uri, const NativeRdb::ValuesBucket &value, const NativeRdb::DataAbilityPredicates &predicates); + + /** + * @brief Deletes one or more data records from the database. + * + * @param uri Indicates the path of the data to operate. + * @param predicates Indicates filter criteria. You should define the processing logic when this parameter is + * null. + * + * @return Returns the number of data records deleted. + */ + virtual int Delete(const Uri &uri, const NativeRdb::DataAbilityPredicates &predicates); + + /** + * @brief Deletes one or more data records from the database. + * + * @param uri Indicates the path of data to query. + * @param columns Indicates the columns to query. If this parameter is null, all columns are queried. + * @param predicates Indicates filter criteria. You should define the processing logic when this parameter is + * null. + * + * @return Returns the query result. + */ + virtual std::shared_ptr Query( + const Uri &uri, std::vector &columns, const NativeRdb::DataAbilityPredicates &predicates); + + /** + * @brief Obtains the MIME type matching the data specified by the URI of the Data ability. This method should + * be implemented by a Data ability. Data abilities supports general data types, including text, HTML, and JPEG. + * + * @param uri Indicates the URI of the data. + * + * @return Returns the MIME type that matches the data specified by uri. + */ + virtual std::string GetType(const Uri &uri); + + /** + * @brief Reloads data in the database. + * + * @param uri Indicates the position where the data is to reload. This parameter is mandatory. + * @param extras Indicates the PacMap object containing the additional parameters to be passed in this call. + * This parameter can be null. If a custom Sequenceable object is put in the PacMap object and will be + * transferred across processes, you must call BasePacMap.setClassLoader(ClassLoader) to set a class loader for + * the custom object. + * + * @return Returns true if the data is successfully reloaded; returns false otherwise. + */ + virtual bool Reload(const Uri &uri, const PacMap &extras); + + /** + * @brief Inserts multiple data records into the database. + * + * @param uri Indicates the path of the data to operate. + * @param values Indicates the data records to insert. + * + * @return Returns the number of data records inserted. + */ + virtual int BatchInsert(const Uri &uri, const std::vector &values); + + /** + * @brief Set deviceId/bundleName/abilityName of the calling ability + * + * @param deviceId deviceId of the calling ability + * + * @param deviceId bundleName of the calling ability + * + * @param deviceId abilityName of the calling ability + */ + void SetCallingContext(const std::string &deviceId, const std::string &bundleName, const std::string &abilityName); + + /** + * @brief Converts the given uri that refer to the Data ability into a normalized URI. A normalized URI can be used + * across devices, persisted, backed up, and restored. It can refer to the same item in the Data ability even if the + * context has changed. If you implement URI normalization for a Data ability, you must also implement + * denormalizeUri(ohos.utils.net.Uri) to enable URI denormalization. After this feature is enabled, URIs passed to + * any method that is called on the Data ability must require normalization verification and denormalization. The + * default implementation of this method returns null, indicating that this Data ability does not support URI + * normalization. + * + * @param uri Indicates the Uri object to normalize. + * + * @return Returns the normalized Uri object if the Data ability supports URI normalization; returns null otherwise. + */ + virtual Uri NormalizeUri(const Uri &uri); + + /** + * @brief Converts the given normalized uri generated by normalizeUri(ohos.utils.net.Uri) into a denormalized one. + * The default implementation of this method returns the original URI passed to it. + * + * @param uri uri Indicates the Uri object to denormalize. + * + * @return Returns the denormalized Uri object if the denormalization is successful; returns the original Uri passed + * to this method if there is nothing to do; returns null if the data identified by the original Uri cannot be found + * in the current environment. + */ + virtual Uri DenormalizeUri(const Uri &uri); + + /** + * @brief ScheduleUpdateConfiguration, scheduling update configuration. + */ + void ScheduleUpdateConfiguration(const AAFwk::DummyConfiguration &config); + + /** + * @brief Create a PostEvent timeout task. The default delay is 5000ms + * + * @return Return a smart pointer to a timeout object + */ + std::shared_ptr CreatePostEventTimeouter(std::string taskstr); + + virtual std::vector> ExecuteBatch(const std::vector> &operations); + +protected: + /** + * @brief Toggles the lifecycle status of Ability to AAFwk::ABILITY_STATE_INACTIVE. And notifies the application + * that it belongs to of the lifecycle status. + * + * @param want The Want object to switch the life cycle. + */ + void Start(const Want &want); + + /** + * @brief Toggles the lifecycle status of Ability to AAFwk::ABILITY_STATE_INITIAL. And notifies the application + * that it belongs to of the lifecycle status. + * + */ + void Stop(); + + /** + * @brief Toggles the lifecycle status of Ability to AAFwk::ABILITY_STATE_ACTIVE. And notifies the application + * that it belongs to of the lifecycle status. + * + */ + void Active(); + + /** + * @brief Toggles the lifecycle status of Ability to AAFwk::ABILITY_STATE_INACTIVE. And notifies the application + * that it belongs to of the lifecycle status. + * + */ + void Inactive(); + + /** + * @brief Toggles the lifecycle status of Ability to AAFwk::ABILITY_STATE_INACTIVE. And notifies the application + * that it belongs to of the lifecycle status. + * + * @param want The Want object to switch the life cycle. + */ + void Foreground(const Want &want); + + /** + * @brief Toggles the lifecycle status of Ability to AAFwk::ABILITY_STATE_BACKGROUND. And notifies the + * application that it belongs to of the lifecycle status. + * + */ + void Background(); + + /** + * @brief SerUriString + */ + void SerUriString(const std::string &uri); + + /** + * @brief Set the LifeCycleStateInfo to the deal. + * + * @param info the info to set. + */ + void SetLifeCycleStateInfo(const AAFwk::LifeCycleStateInfo &info); + + /** + * @brief Check if it needs to restore the data to the ability. + * + * @return Return true if success, otherwise return false. + */ + bool CheckAndRestore(); + + int lifecycleState_ = AAFwk::ABILITY_STATE_INITIAL; + sptr token_; + std::shared_ptr ability_; + +private: + typedef enum { + START, + INACTIVE, + ACTIVE, + BACKGROUND, + FOREGROUND, + STOP, + } Action; + + std::shared_ptr abilityLifecycleCallbacks_; + std::shared_ptr applactionImpl_; + std::shared_ptr contextDeal_; + +private: + /** + * @brief Multimodal Events Register. + */ + void MMIRegister(); + + /** + * @brief Multimodal Events UnRegister. + */ + void MMIUnRegister(); + +#ifdef MMI_COMPILE + sptr abilityKeyEventHandle_ = nullptr; + sptr abilityTouchEventHandle_ = nullptr; +#endif + bool hasSaveData_ = false; + PacMap restoreData_; +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_APPEXECFWK_OHOS_ABILITY_IMPL_H \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/include/ability_impl_factory.h b/tools/frameworks/kits/ability/native/include/ability_impl_factory.h new file mode 100644 index 00000000000..0945cb0c6c0 --- /dev/null +++ b/tools/frameworks/kits/ability/native/include/ability_impl_factory.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_APPEXECFWK_OHOS_ABILITY_IMPL_FACTORY_H +#define FOUNDATION_APPEXECFWK_OHOS_ABILITY_IMPL_FACTORY_H + +#include "ability_impl.h" +#include "singleton.h" + +namespace OHOS { +namespace AppExecFwk { +class AbilityImplFactory { + DECLARE_DELAYED_SINGLETON(AbilityImplFactory) +public: + /** + * @brief Create impl object based on abilitytype + * + * @param type AbilityType:PAGE/SERVICE/PROVIDER + * + * @return AbilityImpl object + */ + std::shared_ptr MakeAbilityImplObject(const std::shared_ptr &info); +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_APPEXECFWK_OHOS_ABILITY_IMPL_FACTORY_H \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/include/ability_keyevent.h b/tools/frameworks/kits/ability/native/include/ability_keyevent.h new file mode 100644 index 00000000000..532f78b732a --- /dev/null +++ b/tools/frameworks/kits/ability/native/include/ability_keyevent.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_APPEXECFWK_OHOS_ABILITY_KEYEVENT_HANDLE_H +#define FOUNDATION_APPEXECFWK_OHOS_ABILITY_KEYEVENT_HANDLE_H + +#include + +#ifdef MMI_COMPILE +#include "multimodal_events_handler.h" +#include "key_events_handler.h" +#endif + +namespace OHOS { +namespace AppExecFwk { +class AbilityImpl; + +#ifdef MMI_COMPILE +class AbilityKeyEventHandle : public MMI::KeyEventHandler { +#else +class AbilityKeyEventHandle { +#endif + +public: + AbilityKeyEventHandle(const std::shared_ptr &ability); + ~AbilityKeyEventHandle(); + +#ifdef MMI_COMPILE + /** + * @brief Called back when on key. + */ + virtual bool OnKey(const KeyEvent& keyEvent) override; +#endif + +private: + std::shared_ptr abilityImpl_ = nullptr; +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_APPEXECFWK_OHOS_ABILITY_KEYEVENT_HANDLE_H \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/include/ability_lifecycle.h b/tools/frameworks/kits/ability/native/include/ability_lifecycle.h new file mode 100644 index 00000000000..58498e40cf3 --- /dev/null +++ b/tools/frameworks/kits/ability/native/include/ability_lifecycle.h @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_APPEXECFWK_OHOS_ABILITY_LIFECYCLE_H +#define FOUNDATION_APPEXECFWK_OHOS_ABILITY_LIFECYCLE_H + +#include +#include +#include +#include +#include +#include "want.h" + +namespace OHOS { +namespace AppExecFwk { +using Want = OHOS::AAFwk::Want; +class ILifecycleObserver; +class LifeCycle { +public: + LifeCycle() = default; + virtual ~LifeCycle() = default; + + enum Event { ON_ACTIVE, ON_BACKGROUND, ON_FOREGROUND, ON_INACTIVE, ON_START, ON_STOP, UNDEFINED }; + + /** + * @brief Obtains the current lifecycle event. + * Lifecycle events drive lifecycle state changes. Therefore, you are able to know the lifecycle state + * once you obtain the lifecycle event. For example, if the ON_ACTIVE event is received, the ability or + * ability slice is in the ACTIVE state; if the ON_FOREGROUND event is received, the ability or ability + * slice is changing from the BACKGROUND state to INACTIVE. + * + * @return Returns the current lifecycle event. + */ + LifeCycle::Event GetLifecycleState(); + + /** + * @brief Adds a lifecycle observer. + * The observer will be notified of lifecycle changes. + * + * @param observer Indicates the lifecycle observer, either LifecycleObserver or LifecycleStateObserver. + * The value cannot be null. + * + */ + void AddObserver(const std::shared_ptr &observer); + + /** + * @brief While Ability's lifecycle changes, dispatch lifecycle event. + * + * @param event Lifecycle state. + * @param want Indicates the Want containing information about the target ability to change lifecycle state. + */ + void DispatchLifecycle(const LifeCycle::Event &event, const Want &want); + + /** + * @brief While Ability's lifecycle changes, dispatch lifecycle event. + * + * @param event Lifecycle state. + * @param want Indicates the Want containing information about the target ability to change lifecycle state. + */ + void DispatchLifecycle(const LifeCycle::Event &event); + + /** + * @brief Removes a lifecycle observer. + * You are advised to call this method if you no longer need to listen to lifecycle changes. This reduces the + * performance loss caused by observing lifecycle changes. + * + * @param observer Indicates the lifecycle observer, either LifecycleObserver or LifecycleStateObserver. + * The value cannot be null. + */ + void RemoveObserver(const std::shared_ptr &observer); + +private: + LifeCycle::Event state_ = UNDEFINED; + + std::list> callbacks_; +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_APPEXECFWK_OHOS_ABILITY_LIFECYCLE_H \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/include/ability_lifecycle_callbacks.h b/tools/frameworks/kits/ability/native/include/ability_lifecycle_callbacks.h new file mode 100644 index 00000000000..7b31fa3aa77 --- /dev/null +++ b/tools/frameworks/kits/ability/native/include/ability_lifecycle_callbacks.h @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_APPEXECFWK_OHOS_ABILITY_LIFECYCLE_CALLBACK_H +#define FOUNDATION_APPEXECFWK_OHOS_ABILITY_LIFECYCLE_CALLBACK_H + +#include "pac_map.h" + +namespace OHOS { +namespace AppExecFwk { +class Ability; +class AbilityLifecycleCallbacks { +public: + AbilityLifecycleCallbacks() = default; + virtual ~AbilityLifecycleCallbacks() = default; + + /** + * + * Will be called when the given ability calls Ability->onStart + * + * @param Ability Indicates the ability object that calls the onStart() method. + */ + virtual void OnAbilityStart(const std::shared_ptr &ability) = 0; + + /** + * + * Will be called when the given ability calls Ability->onInactive + * + * @param Ability Indicates the Ability object that calls the onInactive() method. + */ + virtual void OnAbilityInactive(const std::shared_ptr &ability) = 0; + + /** + * + * Will be called when the given ability calls Ability->onBackground + * + * @param Ability Indicates the Ability object that calls the onBackground() method. + */ + virtual void OnAbilityBackground(const std::shared_ptr &ability) = 0; + + /** + * + * Will be called when the given ability calls Ability->onForeground + * + * @param Ability Indicates the Ability object that calls the onForeground() method. + */ + virtual void OnAbilityForeground(const std::shared_ptr &ability) = 0; + + /** + * + * Will be called when the given ability calls Ability->onActive + * + * @param Ability Indicates the Ability object that calls the onActive() method. + */ + virtual void OnAbilityActive(const std::shared_ptr &ability) = 0; + + /** + * + * Will be called when the given ability calls Ability->onStop + * + * @param Ability Indicates the Ability object that calls the onStop() method. + */ + virtual void OnAbilityStop(const std::shared_ptr &ability) = 0; + + /** + * + * Will be Called when an ability calls Ability#onSaveAbilityState(PacMap). + * + * @param outState Indicates the PacMap object passed to the onSaveAbilityState() callback. + */ + virtual void OnAbilitySaveState(const PacMap &outState) = 0; +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_APPEXECFWK_OHOS_ABILITY_LIFECYCLE_CALLBACK_H \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/include/ability_lifecycle_executor.h b/tools/frameworks/kits/ability/native/include/ability_lifecycle_executor.h new file mode 100644 index 00000000000..600fdee4d7e --- /dev/null +++ b/tools/frameworks/kits/ability/native/include/ability_lifecycle_executor.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_APPEXECFWK_OHOS_ABILITY_LIFECYCLE_EXECUTOR_H +#define FOUNDATION_APPEXECFWK_OHOS_ABILITY_LIFECYCLE_EXECUTOR_H + +namespace OHOS { +namespace AppExecFwk { +class AbilityLifecycleExecutor { +public: + AbilityLifecycleExecutor() = default; + virtual ~AbilityLifecycleExecutor() = default; + enum LifecycleState { + ACTIVE, + BACKGROUND, + INACTIVE, + INITIAL, + UNINITIALIZED, + }; + + /** + * @brief While Ability's lifecycle changes, dispatch lifecycle state. + * + * @param state Lifecycle state. + */ + void DispatchLifecycleState(const AbilityLifecycleExecutor::LifecycleState &state); + + /** + * @brief Obtains the int value of the ability lifecycle state represented by the + * AbilityLifecycleExecutor.LifecycleState enum constant. + * + * @return return Returns the int value of the ability lifecycle state represented + * by the AbilityLifecycleExecutor.LifecycleState enum constant. + */ + int GetState(); + +private: + AbilityLifecycleExecutor::LifecycleState state_ = UNINITIALIZED; +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_APPEXECFWK_OHOS_ABILITY_LIFECYCLE_EXECUTOR_H \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/include/ability_lifecycle_interface.h b/tools/frameworks/kits/ability/native/include/ability_lifecycle_interface.h new file mode 100644 index 00000000000..79ffbd1f348 --- /dev/null +++ b/tools/frameworks/kits/ability/native/include/ability_lifecycle_interface.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_APPEXECFWK_OHOS_ABILITY_LIFECYCLE_INTERFACE_H +#define FOUNDATION_APPEXECFWK_OHOS_ABILITY_LIFECYCLE_INTERFACE_H + +#include "ability_lifecycle.h" + +namespace OHOS { +namespace AppExecFwk { +class ILifeCycle { +public: + ILifeCycle() = default; + virtual ~ILifeCycle() = default; + + /** + * @brief Obtains the Lifecycle object of an Ability + * + * @return Returns the Lifecycle object. + */ + virtual std::shared_ptr GetLifecycle() = 0; +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_APPEXECFWK_OHOS_ABILITY_LIFECYCLE_INTERFACE_H \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/include/ability_lifecycle_observer.h b/tools/frameworks/kits/ability/native/include/ability_lifecycle_observer.h new file mode 100644 index 00000000000..25a66fef203 --- /dev/null +++ b/tools/frameworks/kits/ability/native/include/ability_lifecycle_observer.h @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_APPEXECFWK_OHOS_LIFECYCLE_OBSERVER_INTERFACE_H +#define FOUNDATION_APPEXECFWK_OHOS_LIFECYCLE_OBSERVER_INTERFACE_H + +#include "ability_lifecycle_observer_interface.h" + +namespace OHOS { +namespace AppExecFwk { +using Want = OHOS::AAFwk::Want; +class LifecycleObserver : public ILifecycleObserver { +public: + LifecycleObserver() = default; + virtual ~LifecycleObserver() = default; + + /** + * @brief Called back in response to an ON_ACTIVE event. + * When an ON_ACTIVE event is received, the ability or ability slice is in the foreground and is interactive. + */ + virtual void OnActive(); + + /** + * @brief Called back in response to an ON_BACKGROUND event. + * When an ON_BACKGROUND event is received, the ability or ability slice is invisible. You are advised to + * suspend the threads related to this ability or ability slice and clear resources for more system memory. + * + */ + virtual void OnBackground(); + + /** + * @brief Called back in response to an ON_FOREGROUND event, where information for the + * ability or ability slice to go back to the ACTIVE state is carried in the want parameter. + * When an ON_FOREGROUND event is received, the ability or ability slice returns to the foreground. You can use + * this method to implement re-initialization or adjust the UI display by using the want parameter. + * + * @param want Indicates the information for the ability or ability slice to go back to the ACTIVE state. + */ + virtual void OnForeground(const Want &want); + + /** + * @brief Called back in response to an ON_INACTIVE event. + * When an ON_INACTIVE event is received, the ability or ability slice is in the INACTIVE state. INACTIVE is an + * intermediate state before the state changes to ACTIVE or BACKGROUND. In this state, the UI may be visible but is + * not interactive. You are advised not to use this method to invoke complex service logic. + * + */ + virtual void OnInactive(); + + /** + * @brief Called back in response to an ON_START event, where the startup information + * is carried in the want parameter. + * This method initializes an Ability or AbilitySlice and is called back only once during the entire lifecycle. + * You are advised to implement some initialization logic using this method, for example, you can initialize a + * timer or define some global objects. + * + * @param want Indicates the startup information. + */ + virtual void OnStart(const Want &want); + + /** + * @brief Called back in response to an ON_STOP event. + * This method is called back when the lifecycle of the ability or ability slice is destroyed. You can reclaim + * resources using this method. + * + */ + virtual void OnStop(); + + /** + * @brief Called back in response to a lifecycle change. This method is triggered by a registered LifecycleObserver + * each time the lifecycle state changes. + * + * @param event Indicates the lifecycle event. + * @param want Indicates the state change information. + */ + virtual void OnStateChanged(Lifecycle::Event event, const Want &want); + + /** + * @brief Called back in response to a lifecycle change. This method is triggered by a registered LifecycleObserver + * each time the lifecycle state changes. + * + * @param event Indicates the lifecycle event. + */ + virtual void OnStateChanged(LifeCycle::Event event); +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_APPEXECFWK_OHOS_LIFECYCLE_OBSERVER_INTERFACE_H \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/include/ability_lifecycle_observer_interface.h b/tools/frameworks/kits/ability/native/include/ability_lifecycle_observer_interface.h new file mode 100644 index 00000000000..35d72e7b37b --- /dev/null +++ b/tools/frameworks/kits/ability/native/include/ability_lifecycle_observer_interface.h @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_APPEXECFWK_OHOS_LIFECYCLE_OBSERVER_INTERFACE_H +#define FOUNDATION_APPEXECFWK_OHOS_LIFECYCLE_OBSERVER_INTERFACE_H + +#include "want.h" +#include "ability_lifecycle.h" + +namespace OHOS { +namespace AppExecFwk { +using Want = OHOS::AAFwk::Want; +class ILifecycleObserver { +public: + ILifecycleObserver() = default; + virtual ~ILifecycleObserver() = default; + + /** + * @brief Called back in response to an ON_ACTIVE event. + * When an ON_ACTIVE event is received, the ability or ability slice is in the foreground and is interactive. + */ + virtual void OnActive() = 0; + + /** + * @brief Called back in response to an ON_BACKGROUND event. + * When an ON_BACKGROUND event is received, the ability or ability slice is invisible. You are advised to + * suspend the threads related to this ability or ability slice and clear resources for more system memory. + * + */ + virtual void OnBackground() = 0; + + /** + * @brief Called back in response to an ON_FOREGROUND event, where information for the + * ability or ability slice to go back to the ACTIVE state is carried in the want parameter. + * When an ON_FOREGROUND event is received, the ability or ability slice returns to the foreground. You can use + * this method to implement re-initialization or adjust the UI display by using the want parameter. + * + * @param want Indicates the information for the ability or ability slice to go back to the ACTIVE state. + */ + virtual void OnForeground(const Want &want) = 0; + + /** + * @brief Called back in response to an ON_INACTIVE event. + * When an ON_INACTIVE event is received, the ability or ability slice is in the INACTIVE state. INACTIVE is an + * intermediate state before the state changes to ACTIVE or BACKGROUND. In this state, the UI may be visible but is + * not interactive. You are advised not to use this method to invoke complex service logic. + * + */ + virtual void OnInactive() = 0; + + /** + * @brief Called back in response to an ON_START event, where the startup information + * is carried in the want parameter. + * This method initializes an Ability or AbilitySlice and is called back only once during the entire lifecycle. + * You are advised to implement some initialization logic using this method, for example, you can initialize a + * timer or define some global objects. + * + * @param want Indicates the startup information. + */ + virtual void OnStart(const Want &want) = 0; + + /** + * @brief Called back in response to an ON_STOP event. + * This method is called back when the lifecycle of the ability or ability slice is destroyed. You can reclaim + * resources using this method. + * + */ + virtual void OnStop() = 0; + + /** + * @brief Called back in response to a lifecycle change. This method is triggered by a registered LifecycleObserver + * each time the lifecycle state changes. + * + * @param event Indicates the lifecycle event. + * @param want Indicates the state change information. + */ + virtual void OnStateChanged(LifeCycle::Event event, const Want &want) = 0; + + /** + * @brief Called back in response to a lifecycle change. This method is triggered by a registered LifecycleObserver + * each time the lifecycle state changes. + * + * @param event Indicates the lifecycle event. + */ + virtual void OnStateChanged(LifeCycle::Event event) = 0; +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_APPEXECFWK_OHOS_LIFECYCLE_OBSERVER_INTERFACE_H \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/include/ability_loader.h b/tools/frameworks/kits/ability/native/include/ability_loader.h new file mode 100644 index 00000000000..58d9f49f582 --- /dev/null +++ b/tools/frameworks/kits/ability/native/include/ability_loader.h @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_APPEXECFWK_OHOS_ABILITY_LOADER_H +#define FOUNDATION_APPEXECFWK_OHOS_ABILITY_LOADER_H + +#include "ability.h" +#include "ohos_application.h" +#include +#include +#include + +namespace OHOS { +namespace AppExecFwk { +using CreateAblity = std::function; +#ifdef ABILITY_WINDOW_SUPPORT +using CreateSlice = std::function; +#endif +/** + * @brief Declares functions for registering the class names of {@link Ability} and {@link AbilitySlice} with the + * ability management framework. + * + * After creating your own {@link Ability} and {@link AbilitySlice} child classes, you should register their class + * names with the ability management framework so that the application can start Ability instances created in + * the background. + * + * @since 1 + * @version 1 + */ +class AbilityLoader { +public: + static AbilityLoader &GetInstance(); + + ~AbilityLoader() = default; + + /** + * @brief Register Ability Info + * + * @param abilityName ability classname + * @param createFunc Constructor address + */ + void RegisterAbility(const std::string &abilityName, const CreateAblity &createFunc); + + /** + * @brief Get Ability address + * + * @param abilityName ability classname + * + * @return return Ability address + */ + Ability *GetAbilityByName(const std::string &abilityName); + +#ifdef ABILITY_WINDOW_SUPPORT + void RegisterAbilitySlice(const std::string &sliceName, const CreateSlice &createFunc); + AbilitySlice *GetAbilitySliceByName(const std::string &sliceName); +#endif + +private: + AbilityLoader() = default; + AbilityLoader(const AbilityLoader &) = delete; + AbilityLoader &operator=(const AbilityLoader &) = delete; + AbilityLoader(AbilityLoader &&) = delete; + AbilityLoader &operator=(AbilityLoader &&) = delete; + + std::unordered_map abilities_; +}; +/** + * @brief Registers the class name of an {@link Ability} child class. + * + * After implementing your own {@link Ability} class, you should call this function so that the ability management + * framework can create Ability instances when loading your Ability class. + * + * @param className Indicates the {@link Ability} class name to register. + */ +#define REGISTER_AA(className) \ + __attribute__((constructor)) void RegisterAA##className() \ + { \ + AbilityLoader::GetInstance().RegisterAbility( \ + #className, []()->Ability * { return new (std::nothrow) className; }); \ + } + +/** + * @brief Registers the class name of an {@link AbilitySlice} child class. + * + * After implementing your own {@link AbilitySlice} class, you should call this function so that the ability + * management framework can create AbilitySlice instances when loading your AbilitySlice class. + * + * @param className Indicates the {@link AbilitySlice} class name to register. + */ +#ifdef ABILITY_WINDOW_SUPPORT +#define REGISTER_AS(className) \ + __attribute((constructor)) void RegisterAS##className() \ + { \ + AbilityLoader::GetInstance().RegisterAbilitySlice( \ + #className, []()->AbilitySlice * { return new (std::nothrow) className; }); +} +#endif +} // namespace OHOS +} // OHOS +#endif // FOUNDATION_APPEXECFWK_OHOS_ABILITY_LOADER_H \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/include/ability_local_record.h b/tools/frameworks/kits/ability/native/include/ability_local_record.h new file mode 100644 index 00000000000..cc5b8c29d0a --- /dev/null +++ b/tools/frameworks/kits/ability/native/include/ability_local_record.h @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_APPEXECFWK_ABILITY_ITEM_H +#define FOUNDATION_APPEXECFWK_ABILITY_ITEM_H + +#include + +#include "iremote_object.h" +#include "event_runner.h" +#include "ability_info.h" +#include "application_info.h" +#include "refbase.h" +namespace OHOS { +namespace AppExecFwk { +class AbilityThread; +class AbilityImpl; +class AbilityLocalRecord { +public: + /** + * + * default constructor + * + */ + AbilityLocalRecord(const std::shared_ptr &info, const sptr &token); + + /** + * + * @default Destructor + * + */ + virtual ~AbilityLocalRecord(); + + /** + * @description: Get an AbilityInfo in an ability. + * + * @return Returns a pointer to abilityinfo. + */ + const std::shared_ptr &GetAbilityInfo(); + + /** + * @description: Get an EventHandler in an ability. + * + * @return Returns a pointer to EventHandler + */ + const std::shared_ptr &GetEventHandler(); + + /** + * @description: Set an EventHandler in an ability. + * @param handler EventHandler object + * @return None. + */ + void SetEventHandler(const std::shared_ptr &handler); + + /** + * @description: Get an EventRunner in an ability. + * + * @return Returns a pointer to EventRunner + */ + const std::shared_ptr &GetEventRunner(); + + /** + * @description: Set an EventRunner in an ability. + * @param runner EventHandler object + * @return None. + */ + void SetEventRunner(const std::shared_ptr &runner); + + /** + * @description: Gets the identity of the ability + * @return return the identity of the ability. + */ + const sptr &GetToken(); + + /** + * @description: Get an AbilityImpl in an ability. + * + * @return Returns AbilityImpl pointer + */ + const std::shared_ptr &GetAbilityImpl(); + + /** + * @description: Set an AbilityImpl in an ability. + * @param abilityImpl AbilityImpl object + * @return None. + */ + void SetAbilityImpl(const std::shared_ptr &abilityImpl); + + /** + * @description: Obtains the information based on ability thread. + * @return return AbilityThread Pointer + */ + const sptr &GetAbilityThread(); + + /** + * @description: Set an AbilityThread in an ability. + * @param abilityThread AbilityThread object + * @return None. + */ + void SetAbilityThread(const sptr &abilityThread); + +private: + std::shared_ptr abilityInfo_; + sptr token_; + std::shared_ptr runner_; + std::shared_ptr handler_; + std::shared_ptr abilityImpl_; // store abilityImpl + sptr abilityThread_; +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_APPEXECFWK_ABILITY_ITEM_H diff --git a/tools/frameworks/kits/ability/native/include/ability_post_event_timeout.h b/tools/frameworks/kits/ability/native/include/ability_post_event_timeout.h new file mode 100644 index 00000000000..d18d53b52aa --- /dev/null +++ b/tools/frameworks/kits/ability/native/include/ability_post_event_timeout.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_APPEXECFWK_OHOS_ABILITY_POST_EVENT_TIMEOUT_H +#define FOUNDATION_APPEXECFWK_OHOS_ABILITY_POST_EVENT_TIMEOUT_H + +#include +#include +#include +#include + +namespace OHOS { +namespace AppExecFwk { + +class AbilityHandler; +class AbilityPostEventTimeout : public std::enable_shared_from_this { +private: + // default delaytime is 5000ms + static const int64_t defalutDelayTime; + +public: + AbilityPostEventTimeout(std::string str, std::shared_ptr &eventHandler); + ~AbilityPostEventTimeout(); + + void TimingBegin(int64_t delaytime = defalutDelayTime); + void TimeEnd(); + +protected: + void TimeOutProc(); + +private: + std::string task_; + std::shared_ptr handler_; + std::mutex mtx_; + bool taskExec_; + + static std::atomic allocationId_; +}; + +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_APPEXECFWK_OHOS_ABILITY_POST_EVENT_TIMEOUT_H \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/include/ability_process.h b/tools/frameworks/kits/ability/native/include/ability_process.h new file mode 100755 index 00000000000..e8a4bb40235 --- /dev/null +++ b/tools/frameworks/kits/ability/native/include/ability_process.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_APPEXECFWK_OHOS_ABILITY_PROCESS_H +#define FOUNDATION_APPEXECFWK_OHOS_ABILITY_PROCESS_H + +#include +#include "feature_ability.h" +#include "napi_context.h" + +namespace OHOS { +namespace AppExecFwk { +/** + * @class AbilityProcess + * Provides the feature ability function. + */ +class AbilityProcess { +public: + AbilityProcess(); + virtual ~AbilityProcess(); + static std::shared_ptr GetInstance(); + + void StartAbility(Ability *ability, CallAbilityParam param, CallbackInfo callbackInfo); + void OnAbilityResult(Ability *ability, int requestCode, int resultCode, const Want &resultData); + + void RequestPermissionsFromUser(Ability *ability, CallAbilityPermissionParam ¶m, CallbackInfo callbackInfo); + void OnRequestPermissionsFromUserResult(Ability *ability, int requestCode, + const std::vector &permissions, const std::vector &grantResults); + +private: + static std::mutex mutex_; + static std::shared_ptr instance_; + static std::map> abilityResultMap_; + static std::map> abilityRequestPermissionsForUserMap_; +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_APPEXECFWK_OHOS_ABILITY_PROCESS_H \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/include/ability_state.h b/tools/frameworks/kits/ability/native/include/ability_state.h new file mode 100644 index 00000000000..9db57a18a0a --- /dev/null +++ b/tools/frameworks/kits/ability/native/include/ability_state.h @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @addtogroup AbilityKit + * @{ + * + * @brief Provides ability-related functions, including ability lifecycle callbacks and functions for connecting to + * or disconnecting from AAs. + * + * Abilities are classified into Feature Abilities (FAs) and Atomic Abilities (AAs). FAs support the Page template, + * and AAs support the Service template. An ability using the Page template is called Page ability for short and that + * using the Service template is called Service ability. + * + * @since 1 + * @version 1 + */ + +/** + * @file ability_state.h + * + * @brief Declares ability-related functions, including ability lifecycle callbacks and functions for connecting to + * or disconnecting from AAs. + * As the fundamental unit of OpenHarmony, abilities are classified into Feature Abilities (FAs) and Atomic + * Abilities (AAs). FAs support the Page template, and AAs support the Service template. An ability using the Page + * template is called Page ability for short and that using the Service template is called Service ability. + * + * @since 1 + * @version 1 + */ +#ifndef OHOS_ABILITY_STATE_H +#define OHOS_ABILITY_STATE_H + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif /* __cplusplus */ +/** + * @brief Enumerates all lifecycle states that an ability will go through over the course of its lifetime. + * + * @since 1 + * @version 1 + */ +typedef enum { + /** + * Initial state: An ability is in this state after it is initialized or stopped. + */ + STATE_INITIAL, + + /** + * Inactive state: An ability is in this state when it is switched to the foreground but is not interactive. + */ + STATE_INACTIVE, + + /** + * Active state: An ability is in this state when it is switched to the foreground and is interactive. + */ + STATE_ACTIVE, + + /** + * Background state: An ability is in this state after it returns to the background. + */ + STATE_BACKGROUND, + STATE_SUSPENDED, + STATE_INACTIVATING, + STATE_ACTIVATING, + STATE_MOVING_BACKGROUND, + STATE_TERMINATING, +} State; +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif /* __cplusplus */ + +#endif // OHOS_ABILITY_STATE_H diff --git a/tools/frameworks/kits/ability/native/include/ability_thread.h b/tools/frameworks/kits/ability/native/include/ability_thread.h new file mode 100644 index 00000000000..3fac0f47b38 --- /dev/null +++ b/tools/frameworks/kits/ability/native/include/ability_thread.h @@ -0,0 +1,442 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_APPEXECFWK_ABILITY_THREAD_H +#define FOUNDATION_APPEXECFWK_ABILITY_THREAD_H + +#include "want.h" +#include "ability_manager_client.h" +#include "ability_manager_interface.h" +#include "ability_impl.h" +#include "ability.h" +#include "ability_local_record.h" +#include "context.h" +#include "ohos_application.h" +#include "ability_scheduler_stub.h" +#include "pac_map.h" +#include "ohos/aafwk/base/ipc_singleton.h" +#include "dummy_values_bucket.h" +#include "dummy_data_ability_predicates.h" +#include "dummy_result_set.h" + +namespace OHOS { +namespace AppExecFwk { +using AbilitySchedulerStub = OHOS::AAFwk::AbilitySchedulerStub; +using LifeCycleStateInfo = OHOS::AAFwk::LifeCycleStateInfo; +using DummyConfiguration = OHOS::AAFwk::DummyConfiguration; +class AbilityImpl; +class Ability; +class AbilityHandler; +class AbilityLocalRecord; +class ApplicationImpl; +class OHOSApplication; +class AbilityHandler; +class AbilityThread : public AbilitySchedulerStub { +public: + /** + * @brief Default constructor used to create a AbilityThread instance. + */ + AbilityThread(); + ~AbilityThread(); + + /** + * @description: Attach The ability thread to the main process. + * @param application Indicates the main process. + * @param abilityRecord Indicates the abilityRecord. + * @param mainRunner The runner which main_thread holds. + */ + static void AbilityThreadMain(std::shared_ptr &application, + const std::shared_ptr &abilityRecord, const std::shared_ptr &mainRunner); + + /** + * @description: Attach The ability thread to the main process. + * @param application Indicates the main process. + * @param abilityRecord Indicates the abilityRecord. + */ + static void AbilityThreadMain( + std::shared_ptr &application, const std::shared_ptr &abilityRecord); + + /** + * @description: Attach The ability thread to the main process. + * @param application Indicates the main process. + * @param abilityRecord Indicates the abilityRecord. + * @param mainRunner The runner which main_thread holds. + */ + void Attach(std::shared_ptr &application, const std::shared_ptr &abilityRecord, + const std::shared_ptr &mainRunner); + + /** + * @description: Attach The ability thread to the main process. + * @param application Indicates the main process. + * @param abilityRecord Indicates the abilityRecord. + */ + void Attach( + std::shared_ptr &application, const std::shared_ptr &abilityRecord); + + /** + * @description: Provide operating system AbilityTransaction information to the observer + * @param want Indicates the structure containing Transaction information about the ability. + * @param lifeCycleStateInfo Indicates the lifecycle state. + */ + void ScheduleAbilityTransaction(const Want &want, const LifeCycleStateInfo &targetState); + + /** + * @description: Provide operating system ConnectAbility information to the observer + * @param want Indicates the structure containing connect information about the ability. + */ + void ScheduleConnectAbility(const Want &want); + + /** + * @description: Provide operating system ConnectAbility information to the observer + * @return None + */ + void ScheduleDisconnectAbility(const Want &want); + + /** + * @description: Provide operating system CommandAbility information to the observer + * + * @param want The Want object to command to. + * + * * @param restart Indicates the startup mode. The value true indicates that Service is restarted after being + * destroyed, and the value false indicates a normal startup. + * + * @param startId Indicates the number of times the Service ability has been started. The startId is incremented by + * 1 every time the ability is started. For example, if the ability has been started for six times, the value of + * startId is 6. + */ + void ScheduleCommandAbility(const Want &want, bool restart, int startId); + + /** + * @description: Provide operating system SaveabilityState information to the observer + * @param state Indicates save ability state used to dispatch. + */ + void ScheduleSaveAbilityState(PacMap &state); + + /** + * @description: Provide operating system RestoreAbilityState information to the observer + * @param state Indicates resotre ability state used to dispatchRestoreAbilityState. + */ + void ScheduleRestoreAbilityState(const PacMap &state); + + /** + * @brief ScheduleUpdateConfiguration, scheduling update configuration. + */ + void ScheduleUpdateConfiguration(const DummyConfiguration &config); + + /** + * @brief Send the result code and data to be returned by this Page ability to the caller. + * When a Page ability is destroyed, the caller overrides the AbilitySlice#onAbilityResult(int, int, Want) method to + * receive the result set in the current method. This method can be called only after the ability has been + * initialized. + * + * @param requestCode Indicates the request code for send. + * @param resultCode Indicates the result code returned after the ability is destroyed. You can define the result + * code to identify an error. + * @param want Indicates the data returned after the ability is destroyed. You can define the data returned. This + * parameter can be null. + */ + void SendResult(int requestCode, int resultCode, const Want &resultData); + + /** + * @brief Obtains the MIME types of files supported. + * + * @param uri Indicates the path of the files to obtain. + * @param mimeTypeFilter Indicates the MIME types of the files to obtain. This parameter cannot be null. + * + * @return Returns the matched MIME types. If there is no match, null is returned. + */ + std::vector GetFileTypes(const Uri &uri, const std::string &mimeTypeFilter); + + /** + * @brief Opens a file in a specified remote path. + * + * @param uri Indicates the path of the file to open. + * @param mode Indicates the file open mode, which can be "r" for read-only access, "w" for write-only access + * (erasing whatever data is currently in the file), "wt" for write access that truncates any existing file, + * "wa" for write-only access to append to any existing data, "rw" for read and write access on any existing data, + * or "rwt" for read and write access that truncates any existing file. + * + * @return Returns the file descriptor. + */ + int OpenFile(const Uri &uri, const std::string &mode); + + /** + * @brief This is like openFile, open a file that need to be able to return sub-sections of files,often assets + * inside of their .hap. + * + * @param uri Indicates the path of the file to open. + * @param mode Indicates the file open mode, which can be "r" for read-only access, "w" for write-only access + * (erasing whatever data is currently in the file), "wt" for write access that truncates any existing file, + * "wa" for write-only access to append to any existing data, "rw" for read and write access on any existing + * data, or "rwt" for read and write access that truncates any existing file. + * + * @return Returns the RawFileDescriptor object containing file descriptor. + */ + int OpenRawFile(const Uri &uri, const std::string &mode); + + /** + * @brief Inserts a single data record into the database. + * + * @param uri Indicates the path of the data to operate. + * @param value Indicates the data record to insert. If this parameter is null, a blank row will be inserted. + * + * @return Returns the index of the inserted data record. + */ + int Insert(const Uri &uri, const NativeRdb::ValuesBucket &value); + + /** + * @brief Updates data records in the database. + * + * @param uri Indicates the path of data to update. + * @param value Indicates the data to update. This parameter can be null. + * @param predicates Indicates filter criteria. You should define the processing logic when this parameter is null. + * + * @return Returns the number of data records updated. + */ + int Update(const Uri &uri, const NativeRdb::ValuesBucket &value, const NativeRdb::DataAbilityPredicates &predicates); + + /** + * @brief Deletes one or more data records from the database. + * + * @param uri Indicates the path of the data to operate. + * @param predicates Indicates filter criteria. You should define the processing logic when this parameter is null. + * + * @return Returns the number of data records deleted. + */ + int Delete(const Uri &uri, const NativeRdb::DataAbilityPredicates &predicates); + + /** + * @brief Deletes one or more data records from the database. + * + * @param uri Indicates the path of data to query. + * @param columns Indicates the columns to query. If this parameter is null, all columns are queried. + * @param predicates Indicates filter criteria. You should define the processing logic when this parameter is null. + * + * @return Returns the query result. + */ + std::shared_ptr Query( + const Uri &uri, std::vector &columns, const NativeRdb::DataAbilityPredicates &predicates); + + /** + * @brief Obtains the MIME type matching the data specified by the URI of the Data ability. This method should be + * implemented by a Data ability. Data abilities supports general data types, including text, HTML, and JPEG. + * + * @param uri Indicates the URI of the data. + * + * @return Returns the MIME type that matches the data specified by uri. + */ + std::string GetType(const Uri &uri); + + /** + * @brief Reloads data in the database. + * + * @param uri Indicates the position where the data is to reload. This parameter is mandatory. + * @param extras Indicates the PacMap object containing the additional parameters to be passed in this call. This + * parameter can be null. If a custom Sequenceable object is put in the PacMap object and will be transferred across + * processes, you must call BasePacMap.setClassLoader(ClassLoader) to set a class loader for the custom object. + * + * @return Returns true if the data is successfully reloaded; returns false otherwise. + */ + bool Reload(const Uri &uri, const PacMap &extras); + + /** + * @brief Inserts multiple data records into the database. + * + * @param uri Indicates the path of the data to operate. + * @param values Indicates the data records to insert. + * + * @return Returns the number of data records inserted. + */ + int BatchInsert(const Uri &uri, const std::vector &values); + + /** + * @brief notify multi window mode changed. + * + * @param winModeKey Indicates ability Window display mode. + * @param flag Indicates this ability has been enter this mode. + */ + void NotifyMultiWinModeChanged(int32_t winModeKey, bool flag); + + /** + * @brief notify this ability is top active ability. + * + * @param flag true: Indicates this ability is top active ability + */ + void NotifyTopActiveAbilityChanged(bool flag); + + /** + * @brief Converts the given uri that refer to the Data ability into a normalized URI. A normalized URI can be used + * across devices, persisted, backed up, and restored. It can refer to the same item in the Data ability even if the + * context has changed. If you implement URI normalization for a Data ability, you must also implement + * denormalizeUri(ohos.utils.net.Uri) to enable URI denormalization. After this feature is enabled, URIs passed to + * any method that is called on the Data ability must require normalization verification and denormalization. The + * default implementation of this method returns null, indicating that this Data ability does not support URI + * normalization. + * + * @param uri Indicates the Uri object to normalize. + * + * @return Returns the normalized Uri object if the Data ability supports URI normalization; returns null otherwise. + */ + Uri NormalizeUri(const Uri &uri); + + /** + * @brief Converts the given normalized uri generated by normalizeUri(ohos.utils.net.Uri) into a denormalized one. + * The default implementation of this method returns the original URI passed to it. + * + * @param uri uri Indicates the Uri object to denormalize. + * + * @return Returns the denormalized Uri object if the denormalization is successful; returns the original Uri passed + * to this method if there is nothing to do; returns null if the data identified by the original Uri cannot be found + * in the current environment. + */ + Uri DenormalizeUri(const Uri &uri); + + /** + * @brief Registers an observer to DataObsMgr specified by the given Uri. + * + * @param uri, Indicates the path of the data to operate. + * @param dataObserver, Indicates the IDataAbilityObserver object. + */ + bool HandleRegisterObserver(const Uri &uri, const sptr &dataObserver); + + + /** + * @brief Deregisters an observer used for DataObsMgr specified by the given Uri. + * + * @param uri, Indicates the path of the data to operate. + * @param dataObserver, Indicates the IDataAbilityObserver object. + */ + bool HandleUnregisterObserver(const Uri &uri, const sptr &dataObserver); + + /** + * @brief Notifies the registered observers of a change to the data resource specified by Uri. + * + * @param uri, Indicates the path of the data to operate. + */ + bool HandleNotifyChange(const Uri &uri); + + /** + * @brief Registers an observer to DataObsMgr specified by the given Uri. + * + * @param uri, Indicates the path of the data to operate. + * @param dataObserver, Indicates the IDataAbilityObserver object. + */ + bool ScheduleRegisterObserver(const Uri &uri, const sptr &dataObserver); + + /** + * @brief Deregisters an observer used for DataObsMgr specified by the given Uri. + * + * @param uri, Indicates the path of the data to operate. + * @param dataObserver, Indicates the IDataAbilityObserver object. + */ + bool ScheduleUnregisterObserver(const Uri &uri, const sptr &dataObserver); + + /** + * @brief Notifies the registered observers of a change to the data resource specified by Uri. + * + * @param uri, Indicates the path of the data to operate. + */ + bool ScheduleNotifyChange(const Uri &uri); + + /** + * @brief Access authority verification. + * + * @return Returns true on success, others on failure. + */ + bool CheckObsPermission(); + + std::vector> ExecuteBatch(const std::vector> &operations); +private: + /** + * @description: Create the abilityname. + * + * @param abilityRecord Indicates the abilityRecord. + * + * @return Returns the abilityname. + * + */ + std::string CreateAbilityName(const std::shared_ptr &abilityRecord); + + /** + * @description: Create and init contextDeal. + * + * @param application Indicates the main process. + * @param abilityRecord Indicates the abilityRecord. + * @param abilityObject Indicates the abilityObject. + * + * @return Returns the contextDeal. + * + */ + std::shared_ptr CreateAndInitContextDeal(std::shared_ptr &application, + const std::shared_ptr &abilityRecord, const std::shared_ptr &abilityObject); + + /** + * @description: Handle the life cycle of Ability. + * @param want Indicates the structure containing lifecycle information about the ability. + * @param lifeCycleStateInfo Indicates the lifeCycleStateInfo. + */ + void HandleAbilityTransaction(const Want &want, const LifeCycleStateInfo &lifeCycleStateInfo); + + /** + * @description: Handle the current connection of Ability. + * @param want Indicates the structure containing connection information about the ability. + */ + void HandleConnectAbility(const Want &want); + + /** + * @description: Handle the current disconnection of Ability. + */ + void HandleDisconnectAbility(const Want &want); + + /** + * @brief Handle the current commadn of Ability. + * + * @param want The Want object to command to. + * + * * @param restart Indicates the startup mode. The value true indicates that Service is restarted after being + * destroyed, and the value false indicates a normal startup. + * + * @param startId Indicates the number of times the Service ability has been started. The startId is incremented by + * 1 every time the ability is started. For example, if the ability has been started for six times, the value of + * startId is 6. + */ + void HandleCommandAbility(const Want &want, bool restart, int startId); + + /** + * @description: Handle the SaveAbility state. + * @param state Indicates save ability state used to dispatchSaveAbilityState. + */ + void HandleSaveAbilityState(PacMap &state); + + /** + * @description: Handle the restoreAbility state. + * @param state Indicates save ability state used to dispatchRestoreAbilityState. + */ + void HandleRestoreAbilityState(const PacMap &state); + + /* + * @brief Handle the scheduling update configuration. + */ + void HandleUpdateConfiguration(const DummyConfiguration &config); + + std::shared_ptr abilityImpl_ = nullptr; + sptr token_; + std::shared_ptr currentAbility_ = nullptr; + std::shared_ptr abilityHandler_ = nullptr; + std::shared_ptr runner_ = nullptr; +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_APPEXECFWK_ABILITY_THREAD_H \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/include/ability_touchevent.h b/tools/frameworks/kits/ability/native/include/ability_touchevent.h new file mode 100644 index 00000000000..b7ab7e029d1 --- /dev/null +++ b/tools/frameworks/kits/ability/native/include/ability_touchevent.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_APPEXECFWK_OHOS_ABILITY_TOUCHEVENT_HANDLE_H +#define FOUNDATION_APPEXECFWK_OHOS_ABILITY_TOUCHEVENT_HANDLE_H + +#include + +#ifdef MMI_COMPILE +#include "multimodal_events_handler.h" +#include "touch_events_handler.h" +#endif + +namespace OHOS { +namespace AppExecFwk { +class AbilityImpl; + +#ifdef MMI_COMPILE +class AbilityTouchEventHandle : public MMI::TouchEventHandler { +#else +class AbilityTouchEventHandle { +#endif +public: + AbilityTouchEventHandle(std::shared_ptr ability); + virtual ~AbilityTouchEventHandle(); + +#ifdef MMI_COMPILE + /** + * @brief Called back when on touch. + */ + virtual bool OnTouch(const TouchEvent& touchEvent) override; +#endif + +private: + std::shared_ptr abilityImpl_ = nullptr; +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_APPEXECFWK_OHOS_ABILITY_TOUCHEVENT_HANDLE_H \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/include/ability_window.h b/tools/frameworks/kits/ability/native/include/ability_window.h new file mode 100644 index 00000000000..cccdb31b2bb --- /dev/null +++ b/tools/frameworks/kits/ability/native/include/ability_window.h @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_ABILITY_WINDOW_H +#define OHOS_ABILITY_WINDOW_H + +#include "window_manager.h" + +#include +#include "nocopyable.h" + +namespace OHOS { +namespace AppExecFwk { +class IAbilityEvent; +class Ability; +class AbilityHandler; +class AbilityWindow : public NoCopyable { +public: + AbilityWindow(); + virtual ~AbilityWindow(); + + /** + * @brief Init the AbilityWindow object. + * + * @param handler The EventHandler of the Ability the AbilityWindow belong. + */ + void Init(std::shared_ptr &handler, std::shared_ptr ability); + + /** + * @brief Sets the window config for the host ability to create window. + * + * @param config Indicates window config. + */ + bool SetWindowConfig(const sptr &config); + + /** + * @brief Called when the KeyEvent sent. + * + * @param KeyEvent the key event. + * + * @return Returns true if the listener has processed the event; returns false otherwise. + * + */ + bool OnKeyEvent(KeyEvent event); + + /** + * @brief Called back when the Back key is pressed. + * + * @param ability The ability receive the event. + * + * @return Returns true if the listener has processed the event; returns false otherwise. + * + */ + bool OnBackPressed(std::shared_ptr &ability); + + /** + * @brief Called when this ability is started. + * + */ + void OnPostAbilityStart(); + + /** + * @brief Called when this ability is activated. + * + */ + void OnPostAbilityActive(); + + /** + * @brief Called when this ability is inactivated. + * + */ + void OnPostAbilityInactive(); + + /** + * @brief Called when this ability is background. + * + */ + void OnPostAbilityBackground(); + + /** + * @brief Called when this ability is foreground. + * + */ + void OnPostAbilityForeground(); + + /** + * @brief Called when this ability is stopped. + * + */ + void OnPostAbilityStop(); + + /** + * @brief Get the window belong to the ability. + * + * @return Returns a Window object pointer. + */ + const sptr GetWindow(); + +private: + std::shared_ptr handler_ = nullptr; + std::weak_ptr ability_; + sptr windowNew_; + bool isWindowAttached = false; +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif // OHOS_ABILITY_WINDOW_H \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/include/continuation/distributed/ability_distributed_connect_callback_stub.h b/tools/frameworks/kits/ability/native/include/continuation/distributed/ability_distributed_connect_callback_stub.h new file mode 100644 index 00000000000..eb432d3f339 --- /dev/null +++ b/tools/frameworks/kits/ability/native/include/continuation/distributed/ability_distributed_connect_callback_stub.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_ABILITY_DISTRIBUTE_CONNECT_CALLBACK_STUB_H +#define OHOS_AAFWK_ABILITY_DISTRIBUTE_CONNECT_CALLBACK_STUB_H + +#include +#include + +#include "ability_distributed_connection_interface.h" +#include "nocopyable.h" + +namespace OHOS { +namespace AAFwk { +/** + * @class AbilityDistributedConnectionStub + * AbilityDistributeConnect Stub. + */ +class AbilityDistributedConnectionStub : public IRemoteStub { +public: + AbilityDistributedConnectionStub(); + virtual ~AbilityDistributedConnectionStub(); + + virtual int OnRemoteRequest( + uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override; + +private: + DISALLOW_COPY_AND_MOVE(AbilityDistributedConnectionStub); +}; + +/** + * @class AbilityDistriubuteConnectCallbackRecipient + * AbilityDistriubuteConnectCallbackRecipient notices IRemoteBroker died. + */ +class AbilityDistriubuteConnectCallbackRecipient : public IRemoteObject::DeathRecipient { +public: + using RemoteDiedHandler = std::function &)>; + AbilityDistriubuteConnectCallbackRecipient(RemoteDiedHandler handler); + virtual ~AbilityDistriubuteConnectCallbackRecipient(); + virtual void OnRemoteDied(const wptr &remote); + +private: + RemoteDiedHandler handler_; +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_ABILITY_DISTRIBUTE_CONNECT_CALLBACK_STUB_H diff --git a/tools/frameworks/kits/ability/native/include/continuation/distributed/ability_distributed_connection.h b/tools/frameworks/kits/ability/native/include/continuation/distributed/ability_distributed_connection.h new file mode 100644 index 00000000000..61c2528ae4d --- /dev/null +++ b/tools/frameworks/kits/ability/native/include/continuation/distributed/ability_distributed_connection.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_ABILITY_DISTRIBUTE_CONNECT_CALLBACK_H +#define OHOS_AAFWK_ABILITY_DISTRIBUTE_CONNECT_CALLBACK_H + +#include "ability_connect_callback_interface.h" +#include "ability_distributed_connect_callback_stub.h" + +namespace OHOS { +namespace AAFwk { +/** + * @class AbilityDistributedConnection + * AbilityDistributeConnect. + */ +class AbilityDistributedConnection : public AbilityDistributedConnectionStub { +public: + AbilityDistributedConnection(const sptr &conn); + ~AbilityDistributedConnection() = default; + + /** + * OnAbilityDistributeConnectDone, AbilityMs notify caller ability the result of connect. + * + * @param element, service ability's ElementName. + * @param remoteObject,.the session proxy of service ability. + * @param resultCode, ERR_OK on success, others on failure. + */ + virtual void OnAbilityConnectDone( + const AppExecFwk::ElementName &element, const sptr &remoteObject, int resultCode) override; + + /** + * OnAbilityDistributeDisconnectDone, AbilityMs notify caller ability the result of disconnect. + * + * @param element, service ability's ElementName. + * @param resultCode, ERR_OK on success, others on failure. + */ + virtual void OnAbilityDisconnectDone(const AppExecFwk::ElementName &element, int resultCode) override; + +private: + sptr conn_; +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_ABILITY_DISTRIBUTE_CONNECT_CALLBACK_H \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/include/continuation/distributed/continuation_handler.h b/tools/frameworks/kits/ability/native/include/continuation/distributed/continuation_handler.h new file mode 100644 index 00000000000..455fb9d8eae --- /dev/null +++ b/tools/frameworks/kits/ability/native/include/continuation/distributed/continuation_handler.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_AAFWK_STANDARD_FRAMEWORKS_KITS_ABILITY_NATIVE_INCLUDE_CONTINUATION_DISTRIBUTED_CONTINUATION_HANDLER_H +#define FOUNDATION_AAFWK_STANDARD_FRAMEWORKS_KITS_ABILITY_NATIVE_INCLUDE_CONTINUATION_DISTRIBUTED_CONTINUATION_HANDLER_H + +#include + +#include "distribute_schedule_handler_interface.h" +#include "continuation_manager.h" +#include "distributed_client.h" +#include "reverse_continuation_scheduler_primary_proxy.h" +#include "reverse_continuation_scheduler_replica_proxy.h" +#include "reverse_continuation_scheduler_primary_stub.h" +#include "ability.h" +#include "want_params.h" +#include "want.h" +#include "reverse_continuation_scheduler_recipient.h" +#include "reverse_continuation_scheduler_replica_interface.h" +#include "reverse_continuation_scheduler_primary_interface.h" +#include "reverse_continuation_scheduler_primary_handler_interface.h" +#include "reverse_continuation_scheduler_replica_handler_interface.h" +#include "iremote_broker.h" + +using Want = OHOS::AAFwk::Want; +using Ability = OHOS::AppExecFwk::Ability; +namespace OHOS { +namespace AppExecFwk { +class ContinuationHandler : public IDistributeScheduleHandler, + public IReverseContinuationSchedulerPrimaryHandler, + public IReverseContinuationSchedulerReplicaHandler { +public: + ContinuationHandler(std::weak_ptr &continuationManager, std::weak_ptr &ability); + virtual ~ContinuationHandler() = default; + virtual bool HandleStartContinuation(const sptr &token, const std::string &deviceId) override; + virtual void HandleReceiveRemoteScheduler(const sptr &remoteReplica) override; + virtual void HandleCompleteContinuation(int result) override; + virtual void PassPrimary(const sptr &Primary) override; + virtual bool ReverseContinuation() override; + virtual void NotifyReverseResult(int reverseResult) override; + virtual bool ContinuationBack(const Want &want) override; + virtual void NotifyReplicaTerminated() override; + void NotifyTerminationToPrimary(); + void SetReversible(bool reversible); + void SetAbilityInfo(std::shared_ptr &abilityInfo); + void SetPrimaryStub(const sptr &Primary); + bool ReverseContinueAbility(); + + static const std::string ORIGINAL_DEVICE_ID; + +private: + void OnReplicaDied(const wptr &remote); + void ClearDeviceInfo(std::shared_ptr &abilityInfo); + void CleanUpAfterReverse(); + Want SetWantParams(const WantParams &wantParams); + + std::shared_ptr abilityInfo_ = nullptr; + std::weak_ptr ability_; + std::weak_ptr continuationManager_; + bool reversible_ = false; + sptr remoteReplicaProxy_ = nullptr; + sptr remotePrimaryProxy_ = nullptr; + sptr remotePrimaryStub_ = nullptr; + sptr schedulerDeathRecipient_ = nullptr; +}; + +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_AAFWK_STANDARD_FRAMEWORKS_KITS_ABILITY_NATIVE_INCLUDE_CONTINUATION_DISTRIBUTED_CONTINUATION_HANDLER_H \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/include/continuation/distributed/continuation_manager.h b/tools/frameworks/kits/ability/native/include/continuation/distributed/continuation_manager.h new file mode 100644 index 00000000000..95da91fac58 --- /dev/null +++ b/tools/frameworks/kits/ability/native/include/continuation/distributed/continuation_manager.h @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_APPEXECFWK_OHOS_CONTINUATION_MANAGER_H +#define FOUNDATION_APPEXECFWK_OHOS_CONTINUATION_MANAGER_H + +#include +#include +#include "continuation_state.h" +#include "continuation_scheduler.h" +#include "ability_info.h" +#include "event_handler.h" +#include "iremote_object.h" +#include "want.h" + +using OHOS::AAFwk::WantParams; +namespace OHOS { +namespace AppExecFwk { +class Ability; +class ContinuationHandler; +class IAbilityContinuation; +class ContinuationManager : public std::enable_shared_from_this { +public: + ContinuationManager(); + virtual ~ContinuationManager() = default; + + bool Init(const std::shared_ptr &ability, const sptr &continueToken, + const std::shared_ptr &abilityInfo, + const std::shared_ptr &continuationHandler); + + ContinuationState GetContinuationState(); + + std::string GetOriginalDeviceId(); + + void ContinueAbility(bool reversible, const std::string &deviceId); + + bool ReverseContinueAbility(); + + bool StartContinuation(); + + bool SaveData(WantParams &saveData); + + bool RestoreData(const WantParams &restoreData, bool reversible, const std::string &originalDeviceId); + + void NotifyCompleteContinuation( + const std::string &originDeviceId, int sessionId, bool success, const sptr &reverseScheduler); + + void CompleteContinuation(int result); + + bool RestoreFromRemote(const WantParams &restoreData); + + bool NotifyRemoteTerminated(); + + bool UnregisterAbilityTokenIfNeed(); + +private: + enum ProgressState { INITIAL, WAITING_SCHEDULE, IN_PROGRESS }; + + bool CheckContinuationIllegal(); + + bool HandleContinueAbility(bool reversible, const std::string &deviceId); + + ProgressState GetProcessState(); + + void ChangeProcessState(const ProgressState &newState); + + void RestoreStateWhenTimeout(long timeoutInMs, const ProgressState &preState); + + void InitMainHandlerIfNeed(); + + bool CheckAbilityToken(); + + bool UnregisterAbilityToken(const sptr &token); + + bool RegisterAbilityTokenIfNeed(const sptr &token); + + bool RegisterAbilityToken(const sptr &token); + + void InitDistSchedulerHost(); + + void CheckDmsInterfaceResult(int result, const std::string &interfaceName); + + bool DoScheduleStartContinuation(); + + bool DoScheduleSaveData(WantParams &saveData); + + bool DoScheduleRestoreData(const WantParams &restoreData); + + bool DoRestoreFromRemote(const WantParams &restoreData); + + sptr distSchedulerHost_ = nullptr; + sptr continueToken_ = nullptr; + std::weak_ptr ability_; + std::weak_ptr abilityInfo_; + ProgressState progressState_ = ProgressState::INITIAL; + bool reversible_ = false; + bool tokenRegistered_ = false; + ContinuationState continuationState_ = ContinuationState::LOCAL_RUNNING; + std::string originalDeviceId_; + std::weak_ptr continuationHandler_; + std::shared_ptr mainHandler_ = nullptr; + std::mutex lock_; + std::mutex lockForRegist_; + + static const int TIMEOUT_MS_WAIT_DMS_SCHEDULE_START_CONTINUATION; + static const int TIMEOUT_MS_WAIT_DMS_NOTIFY_CONTINUATION_COMPLETE; + static const int TIMEOUT_MS_WAIT_REMOTE_NOTIFY_BACK; +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_APPEXECFWK_OHOS_CONTINUATION_MANAGER_H \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/include/continuation/distributed/continuation_scheduler.h b/tools/frameworks/kits/ability/native/include/continuation/distributed/continuation_scheduler.h new file mode 100644 index 00000000000..26d7e52f3fb --- /dev/null +++ b/tools/frameworks/kits/ability/native/include/continuation/distributed/continuation_scheduler.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_AAFWK_STANDARD_FRAMEWORKS_KITS_ABILITY_NATIVE_INCLUDE_CONTINUATION_DISTRIBUTED_CONTINUATION_SCHEDULE_FOR_DMS_H +#define FOUNDATION_AAFWK_STANDARD_FRAMEWORKS_KITS_ABILITY_NATIVE_INCLUDE_CONTINUATION_DISTRIBUTED_CONTINUATION_SCHEDULE_FOR_DMS_H + +#include +#include +#include + +#include "distribute_schedule_handler_interface.h" +#include "continuation_scheduler_stub.h" +#include "event_handler.h" +#include "iremote_object.h" +#include "iremote_stub.h" + +namespace OHOS { +namespace AppExecFwk { +class ContinuationScheduler : public ContinuationSchedulerStub { + +public: + ContinuationScheduler( + std::weak_ptr &callback, std::shared_ptr &mainHandler); + ~ContinuationScheduler() = default; + void ReceiveReplicaScheduler(const sptr &remoteReplica); + void ScheduleCompleteContinuation(int result); + +private: + void HandleReceiveReplicaScheduler(const sptr &remoteReplica); + void HandleCompleteContinuation(int result); + bool GetCallback(std::shared_ptr &callback); + + static std::mutex mutex_; + std::shared_ptr mainHandler_; + std::weak_ptr callback_; +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_AAFWK_STANDARD_FRAMEWORKS_KITS_ABILITY_NATIVE_INCLUDE_CONTINUATION_DISTRIBUTED_CONTINUATION_SCHEDULE_FOR_DMS_H \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/include/continuation/distributed/continuation_scheduler_interface.h b/tools/frameworks/kits/ability/native/include/continuation/distributed/continuation_scheduler_interface.h new file mode 100644 index 00000000000..acc7b80bc1a --- /dev/null +++ b/tools/frameworks/kits/ability/native/include/continuation/distributed/continuation_scheduler_interface.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_AAFWK_STANDARD_FRAMEWORKS_KITS_ABILITY_NATIVE_INCLUDE_CONTINUATION_DISTRIBUTED_CONTINUATION_SCHEDULE_FOR_DMS_INTERFACE_H +#define FOUNDATION_AAFWK_STANDARD_FRAMEWORKS_KITS_ABILITY_NATIVE_INCLUDE_CONTINUATION_DISTRIBUTED_CONTINUATION_SCHEDULE_FOR_DMS_INTERFACE_H + +#include + +#include "iremote_broker.h" + +namespace OHOS { +namespace AppExecFwk { +class IContinuationScheduler : public OHOS::IRemoteBroker { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"ohos.abilityshell.ContinuationScheduler"); + /** + * @brief Receive a scheduler which could handle reverse continuation. + * Remote side will pass an scheduler before continuation completed if this continuation is + * reversible. This method will not be called if this continuation is not reversible. + * @param remoteReplica A scheduler to handle reverse continuation request. + */ + virtual void ReceiveReplicaScheduler(const sptr &remoteReplica) = 0; + + /** + * @brief Called by DMS when the continuing device finished. + * @param result Zero indicate the continuation is success, otherwise integer less than zero. + */ + virtual void ScheduleCompleteContinuation(int result) = 0; +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_AAFWK_STANDARD_FRAMEWORKS_KITS_ABILITY_NATIVE_INCLUDE_CONTINUATION_DISTRIBUTED_CONTINUATION_SCHEDULE_FOR_DMS_INTERFACE_H \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/include/continuation/distributed/continuation_scheduler_stub.h b/tools/frameworks/kits/ability/native/include/continuation/distributed/continuation_scheduler_stub.h new file mode 100644 index 00000000000..6abb10cfda3 --- /dev/null +++ b/tools/frameworks/kits/ability/native/include/continuation/distributed/continuation_scheduler_stub.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_AAFWK_STANDARD_FRAMEWORKS_KITS_ABILITY_NATIVE_INCLUDE_CONTINUATION_DISTRIBUTED_CONTINUATION_SCHEDULE_FOR_DMS_STUB_H +#define FOUNDATION_AAFWK_STANDARD_FRAMEWORKS_KITS_ABILITY_NATIVE_INCLUDE_CONTINUATION_DISTRIBUTED_CONTINUATION_SCHEDULE_FOR_DMS_STUB_H + +#include +#include +#include "continuation_scheduler_interface.h" +#include "iremote_stub.h" +#include "iremote_object.h" + +namespace OHOS { +namespace AppExecFwk { +class ContinuationSchedulerStub : public IRemoteStub { +public: + ContinuationSchedulerStub(); + ~ContinuationSchedulerStub(); + virtual int OnRemoteRequest( + uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override; + +private: + int ReceiveReplicaSchedulerInner(MessageParcel &data, MessageParcel &reply); + int ScheduleCompleteContinuationInner(MessageParcel &data, MessageParcel &reply); + using RequestFuncType = int (ContinuationSchedulerStub::*)(MessageParcel &data, MessageParcel &reply); + std::map requestFuncMap_; + + enum { + SCHEDULE_COMPLETE_CONTINUATION = 1, + RECEIVE_REPLICA_SCHEDULER = 2, + }; +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_AAFWK_STANDARD_FRAMEWORKS_KITS_ABILITY_NATIVE_INCLUDE_CONTINUATION_DISTRIBUTED_CONTINUATION_SCHEDULE_FOR_DMS_STUB_H \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/include/continuation/distributed/distribute_schedule_handler_interface.h b/tools/frameworks/kits/ability/native/include/continuation/distributed/distribute_schedule_handler_interface.h new file mode 100644 index 00000000000..da19f2caad0 --- /dev/null +++ b/tools/frameworks/kits/ability/native/include/continuation/distributed/distribute_schedule_handler_interface.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_AAFWK_STANDARD_FRAMEWORKS_KITS_ABILITY_NATIVE_INCLUDE_CONTINUATION_DISTRIBUTED_DISTRIBUTE_SCHEDULE_HANDLER_INTERFACE_H +#define FOUNDATION_AAFWK_STANDARD_FRAMEWORKS_KITS_ABILITY_NATIVE_INCLUDE_CONTINUATION_DISTRIBUTED_DISTRIBUTE_SCHEDULE_HANDLER_INTERFACE_H + +#include + +#include "iremote_broker.h" + +namespace OHOS { +namespace AppExecFwk { +class IDistributeScheduleHandler { +public: + /** + * @brief Handle continuation from DMS. + * @param token The token + * @param deviceId The device identifier. This value doesn't matter. + * @return zero if success. + */ + virtual bool HandleStartContinuation(const sptr &token, const std::string &deviceId) = 0; + + /** + * @brief Called by DMS when the migrate device finished. + * @param result Zero indicate the continuation is success, otherwise integer less than zero. + */ + virtual void HandleCompleteContinuation(int result) = 0; + + /** + * @brief Receive a scheduler which could handle reverse continuation. + * Remote side will pass an scheduler before continuation completed if this continuation is + * reversible. This method will not be called if this continuation is not reversible. + * @param remoteReplica A scheduler to handle reverse continuation request. + */ + virtual void HandleReceiveRemoteScheduler(const sptr &remoteReplica) = 0; +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_AAFWK_STANDARD_FRAMEWORKS_KITS_ABILITY_NATIVE_INCLUDE_CONTINUATION_DISTRIBUTED_DISTRIBUTE_SCHEDULE_HANDLER_INTERFACE_H \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/include/continuation/distributed/distributed_client.h b/tools/frameworks/kits/ability/native/include/continuation/distributed/distributed_client.h new file mode 100644 index 00000000000..286ccb2cf2f --- /dev/null +++ b/tools/frameworks/kits/ability/native/include/continuation/distributed/distributed_client.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_AAFWK_STANDARD_FRAMEWORKS_KITS_ABILITY_NATIVE_INCLUDE_CONTINUATION_DISTRIBUTED_CLIENT_H +#define FOUNDATION_AAFWK_STANDARD_FRAMEWORKS_KITS_ABILITY_NATIVE_INCLUDE_CONTINUATION_DISTRIBUTED_CLIENT_H + + +#include +#include + +#include "ability.h" +#include "ability_info.h" +#include "want_params.h" +#include "want.h" +#include "iremote_broker.h" +#include "distributed_errors.h" + +#include "distributed_sched_proxy.h" + +namespace OHOS { +namespace AppExecFwk { +using namespace OHOS::DistributedSchedule; + +class DistributedClient { +public: + DistributedClient(); + virtual ~DistributedClient(); + static std::shared_ptr GetInstance(); + ErrCode Connect(); + ErrCode StartRemoteAbility(const Want &want, const AppExecFwk::AbilityInfo &abilityInfo, int32_t requestCode); + ErrCode StartContinuation( + const Want &want, const AppExecFwk::AbilityInfo &abilityInfo, const sptr &abilityToken); + ErrCode ConnectRemoteAbility( + const Want &want, const AppExecFwk::AbilityInfo &abilityInfo, const sptr &connect); + ErrCode DisconnectRemoteAbility(const sptr &connect); + ErrCode NotifyCompleteContinuation( + const std::u16string &devId, int32_t sessionId, bool isSuccess, const sptr &reverseScheduler); + ErrCode RegisterAbilityToken(const sptr &token, const sptr &appThread); + ErrCode UnregisterAbilityToken(const sptr &token, const sptr &appThread); + +private: + static std::mutex mutex_; + static std::shared_ptr instance_; + sptr remoteObject_; + + std::shared_ptr dmsProxy_; +}; + +} // namespace AppExecFwk +} // namespace OHOS +#endif \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/include/continuation/distributed/distributed_errors.h b/tools/frameworks/kits/ability/native/include/continuation/distributed/distributed_errors.h new file mode 100644 index 00000000000..87c236ab3e9 --- /dev/null +++ b/tools/frameworks/kits/ability/native/include/continuation/distributed/distributed_errors.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_AAFWK_STANDARD_FRAMEWORKS_KITS_ABILITY_NATIVE_INCLUDE_CONTINUATION_DISTRIBUTED_ERRORS_H +#define FOUNDATION_AAFWK_STANDARD_FRAMEWORKS_KITS_ABILITY_NATIVE_INCLUDE_CONTINUATION_DISTRIBUTED_ERRORS_H + +#include "errors.h" + +namespace OHOS { +namespace AppExecFwk { +enum DistributedModule { + DISTRIBUTED_MODULE_SERVICE = 0x00, +}; + +// time error offset, used only in this file. +constexpr ErrCode AAFWK_DISTRIBUTED_SERVICE_ERR_OFFSET = ErrCodeOffset(SUBSYS_AAFWK, DISTRIBUTED_MODULE_SERVICE); + +enum { + // 2097152 + GET_SYSTEM_ABILITY_SERVICE_FAILED = AAFWK_DISTRIBUTED_SERVICE_ERR_OFFSET, + // 2097153 + GET_DISTRIBUTED_ABILITY_SERVICE_FAILED, + // 2097154 + DISTRIBUTED_ABILITY_SERVICE_NOT_CONNECTED, + // 2097155 + INCOMING_PARAMETER_POINTER_IS_NULL, + /** + * Result(2097156) for StartAbility: An error of the Want could not be resolved + * to app info from BMS or DistributedMS. + */ + ABILITY_FAILED_RESTORE_DATA, + +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif // SERVICES_INCLUDE_TIME_COMMON_H \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/include/continuation/distributed/progress_state.h b/tools/frameworks/kits/ability/native/include/continuation/distributed/progress_state.h new file mode 100644 index 00000000000..84b91ff9ed1 --- /dev/null +++ b/tools/frameworks/kits/ability/native/include/continuation/distributed/progress_state.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef FOUNDATION_APPEXECFWK_OHOS_PROGRESS_STATE_H +#define FOUNDATION_APPEXECFWK_OHOS_PROGRESS_STATE_H +namespace OHOS { +namespace AppExecFwk { + +enum class ProgressState { + INITIAL = 0, + WAITING_SCHEDULE = 1, + IN_PROGRESS = 2, +}; +using PROGRESS_STATE = enum ProgressState; +} +} +#endif // FOUNDATION_APPEXECFWK_OHOS_PROGRESS_STATE_H \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/include/continuation/distributed/reverse_continuation_scheduler_primary.h b/tools/frameworks/kits/ability/native/include/continuation/distributed/reverse_continuation_scheduler_primary.h new file mode 100644 index 00000000000..9f1d74bbf19 --- /dev/null +++ b/tools/frameworks/kits/ability/native/include/continuation/distributed/reverse_continuation_scheduler_primary.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef OHOS_APPEXECFWK_REVERSE_CONTINUATION_SCHEDULER_PRIMARY_H +#define OHOS_APPEXECFWK_REVERSE_CONTINUATION_SCHEDULER_PRIMARY_H + +#include +#include "reverse_continuation_scheduler_primary_handler_interface.h" +#include "reverse_continuation_scheduler_primary_stub.h" +#include "ability_handler.h" + +namespace OHOS { +namespace AppExecFwk { + +class ReverseContinuationSchedulerPrimary : public ReverseContinuationSchedulerPrimaryStub { +public: + ReverseContinuationSchedulerPrimary( + const std::weak_ptr &continuationHandler, + const std::shared_ptr &mainHandler); + virtual ~ReverseContinuationSchedulerPrimary() = default; + + /** + * @brief Replica call this method when it terminated. + */ + void NotifyReplicaTerminated() override; + + /** + * @brief Replica call this method to notify primary go on. + * + * @param want Contains data to be restore. + * @return True if success, otherwise false. + */ + bool ContinuationBack(const AAFwk::Want &want) override; + +private: + void HandlerNotifyReplicaTerminated(); + void HandlerContinuationBack(const AAFwk::Want &want); + + std::weak_ptr continuationHandler_; + const std::shared_ptr mainHandler_; +}; + +} // namespace AppExecFwk +} // namespace OHOS +#endif /* OHOS_APPEXECFWK_REVERSE_CONTINUATION_SCHEDULER_PRIMARY_H */ \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/include/continuation/distributed/reverse_continuation_scheduler_primary_handler_interface.h b/tools/frameworks/kits/ability/native/include/continuation/distributed/reverse_continuation_scheduler_primary_handler_interface.h new file mode 100644 index 00000000000..278f4339aa9 --- /dev/null +++ b/tools/frameworks/kits/ability/native/include/continuation/distributed/reverse_continuation_scheduler_primary_handler_interface.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_APPEXECFWK_REVERSE_CONTINUATION_SCHEDULER_PRIMARY_HANDLER_INTERFACE_H +#define OHOS_APPEXECFWK_REVERSE_CONTINUATION_SCHEDULER_PRIMARY_HANDLER_INTERFACE_H + +#include +#include "want.h" + +namespace OHOS { +namespace AppExecFwk { +class IReverseContinuationSchedulerPrimaryHandler { +public: + virtual void NotifyReplicaTerminated() = 0; + + virtual bool ContinuationBack(const AAFwk::Want &want) = 0; +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif // OHOS_APPEXECFWK_REVERSE_CONTINUATION_SCHEDULER_PRIMARY_HANDLER_INTERFACE_H \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/include/continuation/distributed/reverse_continuation_scheduler_primary_interface.h b/tools/frameworks/kits/ability/native/include/continuation/distributed/reverse_continuation_scheduler_primary_interface.h new file mode 100644 index 00000000000..ce879c9ff4f --- /dev/null +++ b/tools/frameworks/kits/ability/native/include/continuation/distributed/reverse_continuation_scheduler_primary_interface.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef OHOS_APPEXECFWK_REVERSE_CONTINUATION_SCHEDULER_PRIMARY_INTERFACE_H +#define OHOS_APPEXECFWK_REVERSE_CONTINUATION_SCHEDULER_PRIMARY_INTERFACE_H + +#include "want.h" +#include "iremote_broker.h" + +namespace OHOS { +namespace AppExecFwk { + +class IReverseContinuationSchedulerPrimary : public IRemoteBroker { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"ohos.appexecfwk.ReverseContinuationSchedulerPrimary"); + IReverseContinuationSchedulerPrimary() = default; + virtual ~IReverseContinuationSchedulerPrimary() = default; + + /** + * @brief Replica call this method when it terminated. + */ + virtual void NotifyReplicaTerminated() = 0; + + /** + * @brief Replica call this method to notify primary go on. + * + * @param want Contains data to be restore. + * @return True if success, otherwise false. + */ + virtual bool ContinuationBack(const AAFwk::Want &want) = 0; + + enum { + NOTIFY_REPLICA_TERMINATED = 1, + CONTINUATION_BACK, + }; +}; + +} // namespace AppExecFwk +} // namespace OHOS +#endif /* OHOS_APPEXECFWK_REVERSE_CONTINUATION_SCHEDULER_PRIMARY_INTERFACE_H */ \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/include/continuation/distributed/reverse_continuation_scheduler_primary_proxy.h b/tools/frameworks/kits/ability/native/include/continuation/distributed/reverse_continuation_scheduler_primary_proxy.h new file mode 100644 index 00000000000..82e0fb70d2b --- /dev/null +++ b/tools/frameworks/kits/ability/native/include/continuation/distributed/reverse_continuation_scheduler_primary_proxy.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef OHOS_APPEXECFWK_REVERSE_CONTINUATION_SCHEDULER_PRIMARY_PROXY_H +#define OHOS_APPEXECFWK_REVERSE_CONTINUATION_SCHEDULER_PRIMARY_PROXY_H + +#include +#include "iremote_object.h" +#include "iremote_proxy.h" +#include "reverse_continuation_scheduler_primary_interface.h" + +namespace OHOS { +namespace AppExecFwk { + +class ReverseContinuationSchedulerPrimaryProxy : public IRemoteProxy { +public: + ReverseContinuationSchedulerPrimaryProxy(const sptr &remoteObject); + virtual ~ReverseContinuationSchedulerPrimaryProxy() = default; + + /** + * @brief Replica call this method when it terminated. + */ + void NotifyReplicaTerminated() override; + + /** + * @brief Replica call this method to notify primary go on. + * + * @param want Contains data to be restore. + * @return True if success, otherwise false. + */ + bool ContinuationBack(const AAFwk::Want &want) override; +}; + +} // namespace AppExecFwk +} // namespace OHOS +#endif /* OHOS_APPEXECFWK_REVERSE_CONTINUATION_SCHEDULER_PRIMARY_PROXY_H */ \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/include/continuation/distributed/reverse_continuation_scheduler_primary_stub.h b/tools/frameworks/kits/ability/native/include/continuation/distributed/reverse_continuation_scheduler_primary_stub.h new file mode 100644 index 00000000000..896f6016e28 --- /dev/null +++ b/tools/frameworks/kits/ability/native/include/continuation/distributed/reverse_continuation_scheduler_primary_stub.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef OHOS_APPEXECFWK_REVERSE_CONTINUATION_SCHEDULER_PRIMARY_STUB_H +#define OHOS_APPEXECFWK_REVERSE_CONTINUATION_SCHEDULER_PRIMARY_STUB_H + +#include "iremote_stub.h" +#include "reverse_continuation_scheduler_primary_interface.h" + +namespace OHOS { +namespace AppExecFwk { + +class ReverseContinuationSchedulerPrimaryStub : public IRemoteStub { +public: + ReverseContinuationSchedulerPrimaryStub(); + virtual ~ReverseContinuationSchedulerPrimaryStub(); + + /** + * @brief Sets an entry for receiving requests. + * + * @param code Indicates the service request code sent from the peer end. + * @param data Indicates the MessageParcel object sent from the peer end. + * @param reply Indicates the response message object sent from the remote service. The local service writes the + * response data to the MessageParcel object. + * @param option Indicates whether the operation is synchronous or asynchronous. + * @return ERR_NONE if success, otherwise false. + */ + virtual int OnRemoteRequest( + uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override; + +private: + int NotifyReplicaTerminatedInner(MessageParcel &data, MessageParcel &reply); + int ContinuationBackInner(MessageParcel &data, MessageParcel &reply); + + static const std::string DESCRIPTOR; + +private: + using RequestFuncType = int (ReverseContinuationSchedulerPrimaryStub::*)(MessageParcel &data, MessageParcel &reply); + std::map requestFuncMap_; +}; + +} // namespace AppExecFwk +} // namespace OHOS +#endif /* OHOS_APPEXECFWK_REVERSE_CONTINUATION_SCHEDULER_PRIMARY_STUB_H */ \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/include/continuation/distributed/reverse_continuation_scheduler_recipient.h b/tools/frameworks/kits/ability/native/include/continuation/distributed/reverse_continuation_scheduler_recipient.h new file mode 100644 index 00000000000..682ead38e09 --- /dev/null +++ b/tools/frameworks/kits/ability/native/include/continuation/distributed/reverse_continuation_scheduler_recipient.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_AAFWK_STANDARD_FRAMEWORKS_KITS_ABILITY_NATIVE_INCLUDE_CONTINUATION_RECIPIENT_H +#define FOUNDATION_AAFWK_STANDARD_FRAMEWORKS_KITS_ABILITY_NATIVE_INCLUDE_CONTINUATION_RECIPIENT_H + +#include +#include + +#include "iremote_object.h" +#include "iremote_stub.h" + +namespace OHOS { +namespace AppExecFwk { +class ReverseContinuationSchedulerRecipient : public IRemoteObject::DeathRecipient { +public: + using RemoteDiedHandler = std::function &)>; + + explicit ReverseContinuationSchedulerRecipient(RemoteDiedHandler handler); + + virtual ~ReverseContinuationSchedulerRecipient(); + + virtual void OnRemoteDied(const wptr &remote); + +private: + RemoteDiedHandler handler_; +}; + +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_AAFWK_STANDARD_FRAMEWORKS_KITS_ABILITY_NATIVE_INCLUDE_CONTINUATION_RECIPIENT_H \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/include/continuation/distributed/reverse_continuation_scheduler_replica.h b/tools/frameworks/kits/ability/native/include/continuation/distributed/reverse_continuation_scheduler_replica.h new file mode 100644 index 00000000000..bad82a034ef --- /dev/null +++ b/tools/frameworks/kits/ability/native/include/continuation/distributed/reverse_continuation_scheduler_replica.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_APPEXECFWK_REVERSE_CONTINUATION_SCHEDULER_REPLICA_H +#define OHOS_APPEXECFWK_REVERSE_CONTINUATION_SCHEDULER_REPLICA_H + +#include +#include "ability_handler.h" +#include "iremote_object.h" +#include "reverse_continuation_scheduler_replica_handler_interface.h" +#include "reverse_continuation_scheduler_replica_stub.h" + +namespace OHOS { +namespace AppExecFwk { +class ReverseContinuationSchedulerReplica : public ReverseContinuationSchedulerReplicaStub { +public: + ReverseContinuationSchedulerReplica(const std::shared_ptr &mainHandler, + const std::weak_ptr &replicaHandler); + + virtual ~ReverseContinuationSchedulerReplica() = default; + + void PassPrimary(const sptr &primary); + + bool ReverseContinuation(); + + void NotifyReverseResult(int reverseResult); + +private: + void HandlerPassPrimary(const sptr &primary); + + bool HandlerReverseContinuation(); + + void HandlerNotifyReverseResult(int reverseResult); + +private: + std::shared_ptr mainHandler_; + std::weak_ptr replicaHandler_; +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/include/continuation/distributed/reverse_continuation_scheduler_replica_handler_interface.h b/tools/frameworks/kits/ability/native/include/continuation/distributed/reverse_continuation_scheduler_replica_handler_interface.h new file mode 100644 index 00000000000..d6aabc4c16e --- /dev/null +++ b/tools/frameworks/kits/ability/native/include/continuation/distributed/reverse_continuation_scheduler_replica_handler_interface.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_APPEXECFWK_REVERSE_CONTINUATION_SCHEDULER_REPLICA_HANDLER_INTERFACE_H +#define OHOS_APPEXECFWK_REVERSE_CONTINUATION_SCHEDULER_REPLICA_HANDLER_INTERFACE_H + +#include +#include "iremote_object.h" + +namespace OHOS { +namespace AppExecFwk { +class IReverseContinuationSchedulerReplicaHandler { +public: + virtual void PassPrimary(const sptr &primary) = 0; + + virtual bool ReverseContinuation() = 0; + + virtual void NotifyReverseResult(int reverseResult) = 0; +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif // OHOS_APPEXECFWK_REVERSE_CONTINUATION_SCHEDULER_REPLICA_HANDLER_INTERFACE_H \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/include/continuation/distributed/reverse_continuation_scheduler_replica_interface.h b/tools/frameworks/kits/ability/native/include/continuation/distributed/reverse_continuation_scheduler_replica_interface.h new file mode 100644 index 00000000000..4907d3f95ad --- /dev/null +++ b/tools/frameworks/kits/ability/native/include/continuation/distributed/reverse_continuation_scheduler_replica_interface.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_APPEXECFWK_REVERSE_CONTINUATION_SCHEDULER_REPLICA_INTERFACE_H +#define OHOS_APPEXECFWK_REVERSE_CONTINUATION_SCHEDULER_REPLICA_INTERFACE_H + +#include +#include "iremote_object.h" + +namespace OHOS { +namespace AppExecFwk { +class IReverseContinuationSchedulerReplica : public IRemoteBroker { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"ohos.appexecfwk.IReverseContinuationSchedulerReplica"); + + virtual void PassPrimary(const sptr &primary) = 0; + + virtual bool ReverseContinuation() = 0; + + virtual void NotifyReverseResult(int reverseResult) = 0; + + enum class Message { + PASS_PRIMARY = 1, + REVERSE_CONTINUATION, + NOTIFY_REVERSE_RESULT, + }; +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/include/continuation/distributed/reverse_continuation_scheduler_replica_proxy.h b/tools/frameworks/kits/ability/native/include/continuation/distributed/reverse_continuation_scheduler_replica_proxy.h new file mode 100644 index 00000000000..edda7cec13b --- /dev/null +++ b/tools/frameworks/kits/ability/native/include/continuation/distributed/reverse_continuation_scheduler_replica_proxy.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_APPEXECFWK_REVERSE_CONTINUATION_SCHEDULER_REPLICA_INTERFACE_PROXY_H +#define OHOS_APPEXECFWK_REVERSE_CONTINUATION_SCHEDULER_REPLICA_INTERFACE_PROXY_H + +#include +#include "iremote_object.h" +#include "iremote_proxy.h" + +#include "reverse_continuation_scheduler_replica_interface.h" + +namespace OHOS { +namespace AppExecFwk { +class ReverseContinuationSchedulerReplicaProxy : public IRemoteProxy { +public: + explicit ReverseContinuationSchedulerReplicaProxy(const sptr &remoteObject); + virtual ~ReverseContinuationSchedulerReplicaProxy(){}; + + virtual void PassPrimary(const sptr &primary) override; + + virtual bool ReverseContinuation() override; + + virtual void NotifyReverseResult(int reverseResult) override; + + virtual sptr AsObject() override; +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/include/continuation/distributed/reverse_continuation_scheduler_replica_stub.h b/tools/frameworks/kits/ability/native/include/continuation/distributed/reverse_continuation_scheduler_replica_stub.h new file mode 100644 index 00000000000..e08a96aadb1 --- /dev/null +++ b/tools/frameworks/kits/ability/native/include/continuation/distributed/reverse_continuation_scheduler_replica_stub.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_APPEXECFWK_REVERSE_CONTINUATION_SCHEDULER_REPLICA_INTERFACE_STUB_H +#define OHOS_APPEXECFWK_REVERSE_CONTINUATION_SCHEDULER_REPLICA_INTERFACE_STUB_H + +#include "iremote_stub.h" +#include "event_handler.h" + +#include "reverse_continuation_scheduler_replica_interface.h" + +namespace OHOS { +namespace AppExecFwk { +class ReverseContinuationSchedulerReplicaStub : public IRemoteStub { +public: + ReverseContinuationSchedulerReplicaStub(); + virtual ~ReverseContinuationSchedulerReplicaStub(); + + virtual int OnRemoteRequest( + uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override; + + int32_t PassPrimaryInner(MessageParcel &data, MessageParcel &reply); + + int32_t ReverseContinuationInner(MessageParcel &data, MessageParcel &reply); + + int32_t NotifyReverseResultInner(MessageParcel &data, MessageParcel &reply); + +private: + using ReverseContinuationSchedulerReplicaFunc = int32_t (ReverseContinuationSchedulerReplicaStub::*)( + MessageParcel &data, MessageParcel &reply); + std::map continuationFuncMap_; + + DISALLOW_COPY_AND_MOVE(ReverseContinuationSchedulerReplicaStub); +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/include/continuation/kits/ability_continuation_interface.h b/tools/frameworks/kits/ability/native/include/continuation/kits/ability_continuation_interface.h new file mode 100644 index 00000000000..e7eba0bf2e9 --- /dev/null +++ b/tools/frameworks/kits/ability/native/include/continuation/kits/ability_continuation_interface.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_APPEXECFWK_OHOS_ABILITY_CONTINUATION_INTERFACE_H +#define FOUNDATION_APPEXECFWK_OHOS_ABILITY_CONTINUATION_INTERFACE_H + +#include "want_params.h" + +namespace OHOS { +namespace AppExecFwk { +class IAbilityContinuation { +public: + IAbilityContinuation() = default; + virtual ~IAbilityContinuation() = default; + + virtual bool OnStartContinuation() = 0; + + virtual bool OnSaveData(WantParams &saveData) = 0; + + virtual bool OnRestoreData(WantParams &restoreData) = 0; + + virtual void OnCompleteContinuation(int result) = 0; + + virtual void OnRemoteTerminated() = 0; +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_APPEXECFWK_OHOS_ABILITY_CONTINUATION_INTERFACE_H \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/include/continuation/kits/continuation_device_callback_interface.h b/tools/frameworks/kits/ability/native/include/continuation/kits/continuation_device_callback_interface.h new file mode 100644 index 00000000000..908c23f007d --- /dev/null +++ b/tools/frameworks/kits/ability/native/include/continuation/kits/continuation_device_callback_interface.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef FOUNDATION_APPEXECFWK_OHOS_CONTINUATION_DEVICE_CALLBACK_INTERFACE_H +#define FOUNDATION_APPEXECFWK_OHOS_CONTINUATION_DEVICE_CALLBACK_INTERFACE_H + +#include + +namespace OHOS { +namespace AppExecFwk { +class IContinuationDeviceCallback { +public: + IContinuationDeviceCallback() = default; + virtual ~IContinuationDeviceCallback() = default; + /** + * Called when the user selects a device from the candidate device list. + * You can implement your own processing logic in this callback to initiate the ability migration process. + * + * @param deviceId Indicates the ID of the selected device. + * @param deviceType Indicates the type of the selected device, which can be + * {@link ExtraParams#DEVICETYPE_SMART_PHONE}, {@link ExtraParams#DEVICETYPE_SMART_PAD}, + * {@link ExtraParams#DEVICETYPE_SMART_WATCH}, or {@link ExtraParams#DEVICETYPE_SMART_TV}. + */ + virtual void OnDeviceConnectDone(const std::string &deviceId, const std::string &deviceType) = 0; + + /** + * Called when the Device+ control center disconnects from a specified device. + * You can implement your own processing logic in this callback, such as notifying the user of the disconnection. + * + * @param deviceId Indicates the ID of the disconnected device. + */ + virtual void OnDeviceDisconnectDone(const std::string &deviceId) = 0; +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_APPEXECFWK_OHOS_CONTINUATION_DEVICE_CALLBACK_INTERFACE_H \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/include/continuation/kits/continuation_register_manager_interface.h b/tools/frameworks/kits/ability/native/include/continuation/kits/continuation_register_manager_interface.h new file mode 100644 index 00000000000..d45b24e5155 --- /dev/null +++ b/tools/frameworks/kits/ability/native/include/continuation/kits/continuation_register_manager_interface.h @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef FOUNDATION_APPEXECFWK_OHOS_CONTINUATION_REGISTER_MANAGER_INTERFACE_H +#define FOUNDATION_APPEXECFWK_OHOS_CONTINUATION_REGISTER_MANAGER_INTERFACE_H +#include +#include +#include "extra_params.h" + +namespace OHOS { +namespace AppExecFwk { + +class IContinuationDeviceCallback; +class RequestCallback; +class IContinuationRegisterManager { +public: + IContinuationRegisterManager() = default; + virtual ~IContinuationRegisterManager() = default; + /** + * @brief Registers an ability to be migrated with the Device+ control center and obtains the registration token + * assigned to the ability. + * + *

You can use {@link IContinuationDeviceCallback} to listen for the device connection state changes after the + * user selects a device for ability migration and implement your own processing logic. When the device is + * connected, {@link IContinuationDeviceCallback#onDeviceConnectDone} is called to initiate the ability migration + * process; when the device is disconnected, {@link IContinuationDeviceCallback#onDeviceDisconnectDone} is called + * to perform related operations, for example, notify the user of the disconnection. In addition, you can obtain + * the registration token via {@link RequestCallback#onResult}. + *

To use this method, you must dynamically request the {@code ohos.permission.DISTRIBUTED_DATASYNC} permission + * from the user. The {@code ohos.permission.DISTRIBUTED_DATASYNC} permission is of the {@code user_grant} level. + * + * @param bundleName Indicates the bundle name of the application whose ability is to be migrated. + * @param parameter Indicates the {@link ExtraParams} object containing the extra parameters used to filter + * the list of available devices. This parameter can be null. + * @param deviceCallback Indicates the callback to be invoked when the connection state of the selected device + * changes. + * @param requestCallback Indicates the callback to be invoked when the Device+ service is connected. + * @return none + */ + virtual void Register(const std::string &bundleName, const ExtraParams ¶meter, + const std::shared_ptr &deviceCallback, + const std::shared_ptr &requestCallback) = 0; + + /** + * @brief Unregisters a specified ability from the Device+ control center based on the token obtained during ability + * registration. + * + * @param token Indicates the registration token of the ability. + * @param requestCallback Indicates the callback to be invoked when the Device+ service is connected. + * This parameter can be null. + * @return none + */ + virtual void Unregister(int token, const std::shared_ptr &requestCallback) = 0; + + /** + * @brief Updates the connection state of the device where the specified ability is successfully migrated. + * + *

After the migration is successful, you can call this method in the UI thread to update the connection state + * of the migrated ability and the device connection state on the screen showing available devices. + * + * @param token Indicates the registration token of the ability. + * @param deviceId Indicates the ID of the device whose connection state is to be updated. + * @param status Indicates the connection state to update, which can be {@link DeviceConnectState#FAILURE}, + * {@link DeviceConnectState#IDLE}, {@link DeviceConnectState#CONNECTING}, {@link DeviceConnectState#CONNECTED}, + * or {@link DeviceConnectState#DIS_CONNECTING}. + * @param requestCallback Indicates the callback to be invoked when the Device+ service is connected. + * This parameter can be null. + * @return none + */ + virtual void UpdateConnectStatus(int token, const std::string &deviceId, int status, + const std::shared_ptr &requestCallback) = 0; + + /** + * @brief Shows the list of devices that can be selected for ability migration on the distributed network. + * + * @param token Indicates the registration token of the ability. + * @param parameter Indicates the {@link ExtraParams} object containing the extra parameters used to filter + * the list of available devices. This parameter can be null. + * @param requestCallback Indicates the callback to be invoked when the Device+ service is connected. + * This parameter can be null. + * @return none + */ + virtual void ShowDeviceList( + int token, const ExtraParams ¶meter, const std::shared_ptr &requestCallback) = 0; + + /** + * @brief Disconnects from the Device+ control center. + * + *

This method can be called when you want to stop migrating an ability. + * + * @param none + * @return none + */ + virtual void Disconnect() = 0; +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_APPEXECFWK_OHOS_CONTINUATION_REGISTER_MANAGER_INTERFACE_H \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/include/continuation/kits/continuation_state.h b/tools/frameworks/kits/ability/native/include/continuation/kits/continuation_state.h new file mode 100644 index 00000000000..e0fd7d8a498 --- /dev/null +++ b/tools/frameworks/kits/ability/native/include/continuation/kits/continuation_state.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef FOUNDATION_APPEXECFWK_OHOS_CONTINUATION_STATE_H +#define FOUNDATION_APPEXECFWK_OHOS_CONTINUATION_STATE_H +namespace OHOS { +namespace AppExecFwk { + +/** + * Enumerates the migration states of an {@link Ability} that has implemented {@link IAbilityContinuation} + * and is in a reversible migration process that allows the ability to be migrated back. + * + *

The following example describes state changes in a migration process: + *

The initial state of {@code FooAbility} on device A is {@link #LOCAL_RUNNING}. If it is migrated to + * device B in a reversible way, its state on device A becomes {@link #REMOTE_RUNNING} and that on device + * B becomes {@link #REPLICA_RUNNING}. If it is migrated to device B in a non-reversible way, its states + * on both devices are {@link #LOCAL_RUNNING}. + * + * @Syscap {@link SystemCapability.Aafwk#ABILITY} + */ +enum class ContinuationState { + // Indicates that the ability is running on the local device. + LOCAL_RUNNING = 0, + + // Indicates that the ability has been migrated to another device. + REMOTE_RUNNING = 1, + + // Indicates that the ability was migrated from another device to the current device. + REPLICA_RUNNING = 2, +}; +using DEVICE_CONNECT_STATE = enum ContinuationState; +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_APPEXECFWK_OHOS_CONTINUATION_STATE_H \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/include/continuation/kits/device_connect_state.h b/tools/frameworks/kits/ability/native/include/continuation/kits/device_connect_state.h new file mode 100644 index 00000000000..1e990e88b69 --- /dev/null +++ b/tools/frameworks/kits/ability/native/include/continuation/kits/device_connect_state.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef FOUNDATION_APPEXECFWK_OHOS_DEVICE_CONNECT_STATE_H +#define FOUNDATION_APPEXECFWK_OHOS_DEVICE_CONNECT_STATE_H +namespace OHOS { +namespace AppExecFwk { +enum class DeviceConnectState { + + // Indicates that the device fails to be connected. + FAILURE = -1, + + // Indicates that the device is in the initial state or is disconnected. + IDLE = 0, + + // Indicates that the device is being connected. + CONNECTING = 1, + + // Indicates that the device is connected. + CONNECTED = 2, + + // Indicates that the device is being disconnected. + DIS_CONNECTING = 3 +}; +using DEVICE_CONNECT_STATE = enum DeviceConnectState; +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_APPEXECFWK_OHOS_DEVICE_CONNECT_STATE_H \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/include/continuation/kits/request_callback.h b/tools/frameworks/kits/ability/native/include/continuation/kits/request_callback.h new file mode 100644 index 00000000000..6bfb8dd3607 --- /dev/null +++ b/tools/frameworks/kits/ability/native/include/continuation/kits/request_callback.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef FOUNDATION_APPEXECFWK_OHOS_REQUEST_CALLBACK_H +#define FOUNDATION_APPEXECFWK_OHOS_REQUEST_CALLBACK_H +namespace OHOS { +namespace AppExecFwk { +class RequestCallback { +public: + RequestCallback() = default; + virtual ~RequestCallback() = default; + /** + * @brief Called when the Device+ control center is successfully connected. + * + *

If this callback is invoked for the {@link IContinuationRegisterManager#register} method, + * the return value is the registration token assigned to the particular ability after it is successfully + * registered with the Device+ control center. + * + * @param result Indicates the result returned if the connection is successful. {@code -1} indicates that + * the connection fails. + * @return none + */ + virtual void OnResult(int result) = 0; +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_APPEXECFWK_OHOS_REQUEST_CALLBACK_H diff --git a/tools/frameworks/kits/ability/native/include/continuation/remote_register_service/connect_callback_proxy.h b/tools/frameworks/kits/ability/native/include/continuation/remote_register_service/connect_callback_proxy.h new file mode 100644 index 00000000000..9b02875f0a2 --- /dev/null +++ b/tools/frameworks/kits/ability/native/include/continuation/remote_register_service/connect_callback_proxy.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef FOUNDATION_APPEXECFWK_OHOS_CONNECT_CALLBACK_PROXY_H +#define FOUNDATION_APPEXECFWK_OHOS_CONNECT_CALLBACK_PROXY_H +#include +#include "connect_callback_interface.h" +#include "iremote_proxy.h" + +using string = std::string; +using IRemoteObject = OHOS::IRemoteObject; + +namespace OHOS { +namespace AppExecFwk { +/** + * interface for device connect callback. + */ +class ConnectCallbackProxy : public IRemoteProxy { +public: + /** + * @brief Remote device sends connection request. + * @param deviceId indicators id of connection device. + * @param deviceType indicators type of connection device. + * @return none + */ + virtual void Connect(const string &deviceId, const string &deviceType) override; + /** + * @brief Remote device sends disconnection request. + * @param deviceId indicators id of disconnection device. + * @return none + */ + virtual void Disconnect(const string &deviceId) override; + +private: + void RemoteRequest(MessageParcel &data, int commandDisconnect); +}; + +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_APPEXECFWK_OHOS_ICONNECT_CALLBACK_H diff --git a/tools/frameworks/kits/ability/native/include/continuation/remote_register_service/connect_callback_stub.h b/tools/frameworks/kits/ability/native/include/continuation/remote_register_service/connect_callback_stub.h new file mode 100644 index 00000000000..ea9f8892d45 --- /dev/null +++ b/tools/frameworks/kits/ability/native/include/continuation/remote_register_service/connect_callback_stub.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef FOUNDATION_APPEXECFWK_OHOS_CONNECT_CALLBACK_STUB_H +#define FOUNDATION_APPEXECFWK_OHOS_CONNECT_CALLBACK_STUB_H +#include +#include +#include "connect_callback_interface.h" +#include "iremote_stub.h" + +using string = std::string; + +namespace OHOS { +namespace AppExecFwk { +class ConnectCallbackStub : public IRemoteStub { +public: + ConnectCallbackStub(); + virtual ~ConnectCallbackStub() = default; + /** + * @brief Remote device sends connection or disconnection request. + * @param Code indicators code of the connection or disconnection request function. + * @param data indicators receives the message object. + * @param reply indicators reply the message object. + * @return none + */ + virtual int OnRemoteRequest( + uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override; + +private: + int ConnectInner(MessageParcel &data, MessageParcel &reply); + int DisconnectInner(MessageParcel &data, MessageParcel &reply); + using ConnectCallbackFunc = int (ConnectCallbackStub::*)(MessageParcel &data, MessageParcel &reply); + std::map memberFuncMap_; +}; + +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_APPEXECFWK_OHOS_CONNECT_CALLBACK_STUB_H \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/include/continuation/remote_register_service/continuation_connector.h b/tools/frameworks/kits/ability/native/include/continuation/remote_register_service/continuation_connector.h new file mode 100644 index 00000000000..c2768df710a --- /dev/null +++ b/tools/frameworks/kits/ability/native/include/continuation/remote_register_service/continuation_connector.h @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_APPEXECFWK_CONTINUATION_CONNECTOR_H +#define FOUNDATION_APPEXECFWK_CONTINUATION_CONNECTOR_H + +#include +#include +#include +#include +#include + +#include "iremote_broker.h" +#include "element_name.h" +#include "refbase.h" +#include "context.h" +#include "extra_params.h" +#include "continuation_request.h" +#include "ability_connect_callback_stub.h" +#include "continuation/kits/continuation_device_callback_interface.h" +#include "continuation/remote_register_service_interface.h" + +namespace OHOS { +namespace AppExecFwk { +class ContinuationConnector : public AAFwk::AbilityConnectionStub { +public: + ContinuationConnector(const std::weak_ptr &context); + virtual ~ContinuationConnector() = default; + + /** + * @brief get singleton of Class ContinuationConnector + * + * @param context: the running context for appcontext + * + * @return The singleton of ContinuationConnector + */ + static sptr GetInstance(const std::weak_ptr &context); + + /** + * @brief This method is called back to receive the connection result after an ability calls the + * Ability#connectAbility(Intent, IAbilityConnection) method to connect it to a Service ability. + * + * @param element: Indicates information about the connected Service ability. + * @param remote: Indicates the remote proxy object of the Service ability. + * @param resultCode: Indicates the connection result code. The value 0 indicates a successful connection, and any + * other value indicates a connection failure. + */ + void OnAbilityConnectDone( + const AppExecFwk::ElementName &element, const sptr &remoteObject, int resultCode) override; + + /** + * @brief This method is called back to receive the disconnection result after the connected Service ability crashes + * or is killed. If the Service ability exits unexpectedly, all its connections are disconnected, and each ability + * previously connected to it will call onAbilityDisconnectDone. + * + * @param element: Indicates information about the disconnected Service ability. + * @param resultCode: Indicates the disconnection result code. The value 0 indicates a successful disconnection, and + * any other value indicates a disconnection failure. + */ + void OnAbilityDisconnectDone(const AppExecFwk::ElementName &element, int resultCode) override; + + /** + * @brief bind remote ability of RemoteRegisterService. + * + * @param request: request for continuation. + */ + void BindRemoteRegisterAbility(const std::shared_ptr &request); + + /** + * @brief unbind remote ability of RemoteRegisterService. + */ + void UnbindRemoteRegisterAbility(); + + /** + * @brief check whether connected to remote register service. + * + * @return bool true if connected, otherwise false. + */ + bool IsAbilityConnected(); + + /** + * @brief unregister to control center continuation register service. + * + * @param token token from register return value. + * + * @return bool result of unregister. + */ + bool Unregister(int token); + + /** + * @brief notify continuation status to control center continuation register service. + * + * @param token token from register. + * @param deviceId device id. + * @param status device status. + * + * @return bool result of updateConnectStatus. + */ + bool UpdateConnectStatus(int token, const std::string &deviceId, int status); + + /** + * @brief notify control center continuation register service to show device list. + * + * @param token token from register + * @param parameter filter with supported device list. + * @return bool result of showDeviceList. + */ + bool ShowDeviceList(int token, const AppExecFwk::ExtraParams ¶meter); + + /** + * @brief register to control center continuation register service. + * + * @param context ability context. + * @param bundleName bundle name of ability. + * @param parameter filter with supported device list. + * @param callback callback for device connect and disconnect. + * + * @return int token. + */ + int Register(std::weak_ptr &context, const std::string bundleName, + const AppExecFwk::ExtraParams ¶meter, std::shared_ptr &callback); + +private: + /** + * @brief bind remote ability of RemoteRegisterService. + */ + inline void BindRemoteRegisterAbility(); + +private: + static const std::string CONNECTOR_DEVICE_ID; + static const std::string CONNECTOR_ABILITY_NAME; + static const std::string CONNECTOR_BUNDLE_NAME; + static sptr instance_; + static std::mutex mutex_; + std::weak_ptr context_; + std::vector> continuationRequestList_; + std::atomic isConnected_ = {false}; + sptr remoteRegisterService_; +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_APPEXECFWK_CONTINUATION_CONNECTOR_H \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/include/continuation/remote_register_service/continuation_device_callback_proxy.h b/tools/frameworks/kits/ability/native/include/continuation/remote_register_service/continuation_device_callback_proxy.h new file mode 100644 index 00000000000..80fcab23348 --- /dev/null +++ b/tools/frameworks/kits/ability/native/include/continuation/remote_register_service/continuation_device_callback_proxy.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef FOUNDATION_APPEXECFWK_OHOS_CONTINUATION_DEVICE_CALLBACK_PROXY_H +#define FOUNDATION_APPEXECFWK_OHOS_CONTINUATION_DEVICE_CALLBACK_PROXY_H +#include +#include "connect_callback_stub.h" +#include "continuation_device_callback_interface.h" + +namespace OHOS { +namespace AppExecFwk { +class ContinuationDeviceCallbackProxy : public ConnectCallbackStub { +public: + /** + * A constructor used to create a {@link ohos.aafwk.ability.continuation.ContinuationDeviceCallbackProxy} instance. + */ + ContinuationDeviceCallbackProxy(std::shared_ptr &callback); + /** + * A destructor used to release a {@link ohos.aafwk.ability.continuation.ContinuationDeviceCallbackProxy} instance. + */ + virtual ~ContinuationDeviceCallbackProxy(); + + /** + * @brief After the connection of continuationdevice is completed, call back the function. + * @param deviceId indicates the continuation device ID. + * @param deviceType indicators he continuation device deviceType. + * @return none. + */ + virtual void Connect(const std::string &deviceId, const std::string &deviceType) override; + + /** + * @brief When the continuationdevice is disconnected, call back the function. + * @param deviceId indicates the continuation device ID. + * @param deviceType indicators he continuation device deviceType. + * @return none. + */ + virtual void Disconnect(const std::string &deviceId) override; + +private: + std::weak_ptr callback_; +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/include/continuation/remote_register_service/continuation_register_manager.h b/tools/frameworks/kits/ability/native/include/continuation/remote_register_service/continuation_register_manager.h new file mode 100644 index 00000000000..4de320acdea --- /dev/null +++ b/tools/frameworks/kits/ability/native/include/continuation/remote_register_service/continuation_register_manager.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef FOUNDATION_APPEXECFWK_OHOS_CONTINUATION_REGISTER_MANAGER_H +#define FOUNDATION_APPEXECFWK_OHOS_CONTINUATION_REGISTER_MANAGER_H + +#include +#include "continuation_register_manager_interface.h" + +namespace OHOS { +namespace AppExecFwk { +class ContinuationRegisterManagerProxy; +class ContinuationRegisterManager : public IContinuationRegisterManager { +public: + ContinuationRegisterManager() = default; + virtual ~ContinuationRegisterManager() = default; + + void Init(const std::shared_ptr &continuationRegisterManagerProxy); + /** + * register to controlcenter continuation register service. + * + * @param bundleName bundlename of ability. + * @param parameter filter with supported device list. + * @param callback callback for device connect and disconnect. + * @param requestCallback callback for this request, -1 means failed, otherwise is register token. + */ + virtual void Register(const std::string &bundleName, const ExtraParams ¶meter, + const std::shared_ptr &deviceCallback, + const std::shared_ptr &requestCallback) override; + + /** + * unregister to controlcenter continuation register service. + * + * @param token token from register return value. + * @param requestCallback callback for this request, -1 means failed, otherwise succeeded. + */ + virtual void Unregister(int token, const std::shared_ptr &requestCallback) override; + + /** + * notify continuation status to controlcenter continuation register service. + * + * @param token token from register. + * @param deviceId deviceid. + * @param status device status. + * @param requestCallback callback for this request, -1 means failed, otherwise successed. + */ + virtual void UpdateConnectStatus(int token, const std::string &deviceId, int status, + const std::shared_ptr &requestCallback) override; + + /** + * notify controlcenter continuation register service to show device list. + * + * @param token token from register + * @param parameter filter with supported device list. + * @param requestCallback callback for this request, -1 means failed, otherwise successed. + */ + virtual void ShowDeviceList( + int token, const ExtraParams ¶meter, const std::shared_ptr &requestCallback) override; + + /** + * disconnect to controlcenter continuation register service. + */ + virtual void Disconnect(void) override; + +private: + std::shared_ptr continuationRegisterManagerProxy_ = nullptr; +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_APPEXECFWK_OHOS_CONTINUATION_REGISTER_MANAGER_H \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/include/continuation/remote_register_service/continuation_register_manager_proxy.h b/tools/frameworks/kits/ability/native/include/continuation/remote_register_service/continuation_register_manager_proxy.h new file mode 100644 index 00000000000..eb6da029848 --- /dev/null +++ b/tools/frameworks/kits/ability/native/include/continuation/remote_register_service/continuation_register_manager_proxy.h @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef FOUNDATION_APPEXECFWK_OHOS_CONTINUATION_REGISTER_MANAGER_PROXY_H +#define FOUNDATION_APPEXECFWK_OHOS_CONTINUATION_REGISTER_MANAGER_PROXY_H + +#include +#include "continuation_register_manager_interface.h" +#include "continuation_request.h" +#include "continuation_connector.h" + +namespace OHOS { +namespace AppExecFwk { + +class ContinuationConnector; +class Context; +class IContinuationDeviceCallback; +class RequestCallback; + +class ContinuationRequestBase : public ContinuationRequest { +public: + ContinuationRequestBase() = default; + virtual ~ContinuationRequestBase() = default; + + void SetContext(const std::weak_ptr &context) + { + context_ = context; + } + + void SetContinuationConnector(const sptr &continuatinConnector) + { + continuatinConnector_ = continuatinConnector; + } + + void SetRequestCallback(const std::shared_ptr &requestCallback) + { + requestCallback_ = requestCallback; + } + +protected: + std::weak_ptr context_; + sptr continuatinConnector_; + std::shared_ptr requestCallback_ = nullptr; +}; + +class ContinuationRequestRegister : public ContinuationRequestBase { +public: + ContinuationRequestRegister(const std::string &bundleName, const ExtraParams ¶meter, + const std::shared_ptr &deviceCallback); + virtual ~ContinuationRequestRegister() = default; + virtual void Execute() override; + +private: + ExtraParams parameter_; + std::shared_ptr deviceCallback_ = nullptr; + std::string bundleName_ = ""; +}; + +class ContinuationRequestUnRegister : public ContinuationRequestBase { +public: + ContinuationRequestUnRegister(int token); + virtual ~ContinuationRequestUnRegister() = default; + virtual void Execute() override; + +private: + int token_ = 0; +}; + +class ContinuationRequestUpdateConnectStatus : public ContinuationRequestBase { +public: + ContinuationRequestUpdateConnectStatus(int token, const std::string &deviceId, int status); + virtual ~ContinuationRequestUpdateConnectStatus() = default; + virtual void Execute() override; + +private: + int token_ = 0; + std::string deviceId_ = ""; + int status_; +}; + +class ContinuationRequestShowDeviceList : public ContinuationRequestBase { +public: + ContinuationRequestShowDeviceList(int token, const ExtraParams ¶meter); + virtual ~ContinuationRequestShowDeviceList() = default; + virtual void Execute() override; + +private: + int token_ = 0; + ExtraParams parameter_; +}; + +class ContinuationRegisterManagerProxy : public IContinuationRegisterManager { +public: + ContinuationRegisterManagerProxy(const std::weak_ptr &context); + virtual ~ContinuationRegisterManagerProxy(); + + /** + * Registers an ability to be migrated with the Device+ control center and obtains the registration token assigned + * to the ability. + * + * @param bundleName Indicates the bundle name of the application whose ability is to be migrated. + * @param parameter Indicates the {@link ExtraParams} object containing the extra parameters used to filter + * the list of available devices. This parameter can be null. + * @param deviceCallback Indicates the callback to be invoked when the connection state of the selected device + * changes. + * @param requestCallback Indicates the callback to be invoked when the Device+ service is connected. + */ + virtual void Register(const std::string &bundleName, const ExtraParams ¶meter, + const std::shared_ptr &deviceCallback, + const std::shared_ptr &requestCallback) override; + + /** + * Unregisters a specified ability from the Device+ control center based on the token obtained during ability + * registration. + * + * @param token Indicates the registration token of the ability. + * @param requestCallback Indicates the callback to be invoked when the Device+ service is connected. + * This parameter can be null. + */ + virtual void Unregister(int token, const std::shared_ptr &requestCallback) override; + + /** + * Updates the connection state of the device where the specified ability is successfully migrated. + * + * @param token Indicates the registration token of the ability. + * @param deviceId Indicates the ID of the device whose connection state is to be updated. + * @param status Indicates the connection state to update, which can be {@link DeviceConnectState#FAILURE}, + * {@link DeviceConnectState#IDLE}, {@link DeviceConnectState#CONNECTING}, {@link DeviceConnectState#CONNECTED}, + * or {@link DeviceConnectState#DIS_CONNECTING}. + * @param requestCallback Indicates the callback to be invoked when the Device+ service is connected. + * This parameter can be null. + */ + virtual void UpdateConnectStatus(int token, const std::string &deviceId, int status, + const std::shared_ptr &requestCallback) override; + + /** + * Shows the list of devices that can be selected for ability migration on the distributed network. + * + * @param token Indicates the registration token of the ability. + * @param parameter Indicates the {@link ExtraParams} object containing the extra parameters used to filter + * the list of available devices. This parameter can be null. + * @param requestCallback Indicates the callback to be invoked when the Device+ service is connected. + * This parameter can be null. + */ + virtual void ShowDeviceList( + int token, const ExtraParams ¶meter, const std::shared_ptr &requestCallback) override; + + /** + * Disconnects from the Device+ control center. + */ + virtual void Disconnect(void) override; + +private: + std::weak_ptr context_; + std::weak_ptr applicationContext_; + sptr continuatinConnector_; + + void SendRequest(const std::weak_ptr &context, const std::shared_ptr &request); +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_APPEXECFWK_OHOS_CONTINUATION_REGISTER_MANAGER_PROXY_H \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/include/continuation/remote_register_service/continuation_request.h b/tools/frameworks/kits/ability/native/include/continuation/remote_register_service/continuation_request.h new file mode 100644 index 00000000000..55b2223bab2 --- /dev/null +++ b/tools/frameworks/kits/ability/native/include/continuation/remote_register_service/continuation_request.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef FOUNDATION_APPEXECFWK_OHOS_CONTINUATIONREQUEST_H +#define FOUNDATION_APPEXECFWK_OHOS_CONTINUATIONREQUEST_H +namespace OHOS { +namespace AppExecFwk { +class ContinuationRequest { +public: + ContinuationRequest() = default; + virtual ~ContinuationRequest() = default; + /** + * @brief Pending request will be execute when connected ability. + * @param none + * @return none + */ + virtual void Execute() = 0; +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_APPEXECFWK_OHOS_CONTINUATIONREQUEST_H diff --git a/tools/frameworks/kits/ability/native/include/continuation/remote_register_service/remote_register_service_proxy.h b/tools/frameworks/kits/ability/native/include/continuation/remote_register_service/remote_register_service_proxy.h new file mode 100644 index 00000000000..cb2d772c548 --- /dev/null +++ b/tools/frameworks/kits/ability/native/include/continuation/remote_register_service/remote_register_service_proxy.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_APPEXECFWK_OHOS_REMOTE_REGISTER_SERVICE_PROXY_H +#define FOUNDATION_APPEXECFWK_OHOS_REMOTE_REGISTER_SERVICE_PROXY_H + +#include "remote_register_service_interface.h" +#include +#include +#include "message_parcel.h" +#include "iremote_proxy.h" + +namespace OHOS { +namespace AppExecFwk { + +class RemoteRegisterServiceProxy : public IRemoteProxy { +public: + explicit RemoteRegisterServiceProxy(const sptr &impl) : IRemoteProxy(impl) + {} + virtual ~RemoteRegisterServiceProxy() = default; + + /** + * register to controlcenter continuation register service. + * + * @param bundleName bundlename of ability. + * @param extras filter with supported device list. + * @param callback callback for device connect and disconnect. + */ + virtual int Register(const std::string &bundleName, const sptr &token, const ExtraParams &extras, + const sptr &callback) override; + + /** + * unregister to controlcenter continuation register service. + * + * @param registerToken token from register return value. + */ + virtual bool Unregister(int registerToken) override; + + /** + * notify continuation status to controlcenter continuation register service. + * + * @param registerToken token from register. + * @param deviceId deviceid. + * @param status device status. + */ + virtual bool UpdateConnectStatus(int registerToken, const std::string &deviceId, int status) override; + + /** + * notify controlcenter continuation register service to show device list. + * + * @param registerToken token from register + * @param extras filter with supported device list. + */ + virtual bool ShowDeviceList(int registerToken, const ExtraParams &extras) override; +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_APPEXECFWK_OHOS_REMOTE_REGISTER_SERVICE_PROXY_H diff --git a/tools/frameworks/kits/ability/native/include/continuation/remote_register_service/remote_register_service_stub.h b/tools/frameworks/kits/ability/native/include/continuation/remote_register_service/remote_register_service_stub.h new file mode 100644 index 00000000000..a34bca577d1 --- /dev/null +++ b/tools/frameworks/kits/ability/native/include/continuation/remote_register_service/remote_register_service_stub.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_APPEXECFWK_OHOS_REMOTE_REGISTER_SERVICE_STUB_H +#define FOUNDATION_APPEXECFWK_OHOS_REMOTE_REGISTER_SERVICE_STUB_H + +#include "remote_register_service_interface.h" +#include +#include +#include +#include "message_parcel.h" + +namespace OHOS { +namespace AppExecFwk { + +class RemoteRegisterServiceStub : public IRemoteStub { +public: + RemoteRegisterServiceStub(); + virtual ~RemoteRegisterServiceStub(); + virtual int OnRemoteRequest( + uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override; + +private: + int RegisterInner(MessageParcel &data, MessageParcel &reply); + int UnregisterInner(MessageParcel &data, MessageParcel &reply); + int UpdateConnectStatusInner(MessageParcel &data, MessageParcel &reply); + int ShowDeviceListInner(MessageParcel &data, MessageParcel &reply); + + using RequestRegisterFuncType = int (RemoteRegisterServiceStub::*)(MessageParcel &data, MessageParcel &reply); + std::map requestFuncMap_; +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_APPEXECFWK_OHOS_REMOTE_REGISTER_SERVICE_STUB_H diff --git a/tools/frameworks/kits/ability/native/include/data_ability_helper.h b/tools/frameworks/kits/ability/native/include/data_ability_helper.h new file mode 100644 index 00000000000..390976d5f3b --- /dev/null +++ b/tools/frameworks/kits/ability/native/include/data_ability_helper.h @@ -0,0 +1,327 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_APPEXECFWK_OHOS_DATA_ABILITY_HELPER_H +#define FOUNDATION_APPEXECFWK_OHOS_DATA_ABILITY_HELPER_H + +#include +#include +#include + +#include "context.h" +#include "uri.h" + +using Uri = OHOS::Uri; + +namespace OHOS { +namespace NativeRdb { +class AbsSharedResultSet; +class DataAbilityPredicates; +class ValuesBucket; +} // namespace NativeRdb +namespace AppExecFwk { +using string = std::string; +class DataAbilityResult; +class DataAbilityOperation; +class PacMap; +class IDataAbilityObserver; +class DataAbilityHelper final : public std::enable_shared_from_this { +public: + ~DataAbilityHelper() = default; + + /** + * @brief Creates a DataAbilityHelper instance without specifying the Uri based on the given Context. + * + * @param context Indicates the Context object on OHOS. + * + * @return Returns the created DataAbilityHelper instance where Uri is not specified. + */ + static std::shared_ptr Creator(const std::shared_ptr &context); + + /** + * @brief Creates a DataAbilityHelper instance with the Uri specified based on the given Context. + * + * @param context Indicates the Context object on OHOS. + * @param uri Indicates the database table or disk file to operate. + * + * @return Returns the created DataAbilityHelper instance with a specified Uri. + */ + static std::shared_ptr Creator( + const std::shared_ptr &context, const std::shared_ptr &uri); + + /** + * @brief You can use this method to specify the Uri of the data to operate and set the binding relationship + * between the ability using the Data template (Data ability for short) and the associated client process in + * a DataAbilityHelper instance. + * + * @param context Indicates the Context object on OHOS. + * @param uri Indicates the database table or disk file to operate. + * @param tryBind Specifies whether the exit of the corresponding Data ability process causes the exit of the + * client process. + * + * @return Returns the created DataAbilityHelper instance. + */ + static std::shared_ptr Creator( + const std::shared_ptr &context, const std::shared_ptr &uri, const bool tryBind); + + /** + * @brief Creates a DataAbilityHelper instance without specifying the Uri based. + * + * @param token Indicates the System token. + * + * @return Returns the created DataAbilityHelper instance where Uri is not specified. + */ + static std::shared_ptr Creator(const sptr &token); + + /** + * @brief You can use this method to specify the Uri of the data to operate and set the binding relationship + * between the ability using the Data template (Data ability for short) and the associated client process in + * a DataAbilityHelper instance. + * + * @param token Indicates the System token. + * @param uri Indicates the database table or disk file to operate. + * + * @return Returns the created DataAbilityHelper instance. + */ + static std::shared_ptr Creator( + const sptr &token, const std::shared_ptr &uri); + + /** + * @brief Releases the client resource of the Data ability. + * You should call this method to releases client resource after the data operations are complete. + * + * @return Returns true if the resource is successfully released; returns false otherwise. + */ + bool Release(); + /** + * @brief Obtains the MIME types of files supported. + * + * @param uri Indicates the path of the files to obtain. + * @param mimeTypeFilter Indicates the MIME types of the files to obtain. This parameter cannot be null. + * + * @return Returns the matched MIME types. If there is no match, null is returned. + */ + std::vector GetFileTypes(Uri &uri, const std::string &mimeTypeFilter); + + /** + * @brief Opens a file in a specified remote path. + * + * @param uri Indicates the path of the file to open. + * @param mode Indicates the file open mode, which can be "r" for read-only access, "w" for write-only access + * (erasing whatever data is currently in the file), "wt" for write access that truncates any existing file, + * "wa" for write-only access to append to any existing data, "rw" for read and write access on any existing data, + * or "rwt" for read and write access that truncates any existing file. + * + * @return Returns the file descriptor. + */ + int OpenFile(Uri &uri, const std::string &mode); + + /** + * @brief This is like openFile, open a file that need to be able to return sub-sections of files,often assets + * inside of their .hap. + * + * @param uri Indicates the path of the file to open. + * @param mode Indicates the file open mode, which can be "r" for read-only access, "w" for write-only access + * (erasing whatever data is currently in the file), "wt" for write access that truncates any existing file, + * "wa" for write-only access to append to any existing data, "rw" for read and write access on any existing + * data, or "rwt" for read and write access that truncates any existing file. + * + * @return Returns the RawFileDescriptor object containing file descriptor. + */ + int OpenRawFile(Uri &uri, const std::string &mode); + + /** + * @brief Inserts a single data record into the database. + * + * @param uri Indicates the path of the data to operate. + * @param value Indicates the data record to insert. If this parameter is null, a blank row will be inserted. + * + * @return Returns the index of the inserted data record. + */ + int Insert(Uri &uri, const NativeRdb::ValuesBucket &value); + + /** + * @brief Updates data records in the database. + * + * @param uri Indicates the path of data to update. + * @param value Indicates the data to update. This parameter can be null. + * @param predicates Indicates filter criteria. You should define the processing logic when this parameter is null. + * + * @return Returns the number of data records updated. + */ + int Update(Uri &uri, const NativeRdb::ValuesBucket &value, const NativeRdb::DataAbilityPredicates &predicates); + + /** + * @brief Deletes one or more data records from the database. + * + * @param uri Indicates the path of the data to operate. + * @param predicates Indicates filter criteria. You should define the processing logic when this parameter is null. + * + * @return Returns the number of data records deleted. + */ + int Delete(Uri &uri, const NativeRdb::DataAbilityPredicates &predicates); + + /** + * @brief Deletes one or more data records from the database. + * + * @param uri Indicates the path of data to query. + * @param columns Indicates the columns to query. If this parameter is null, all columns are queried. + * @param predicates Indicates filter criteria. You should define the processing logic when this parameter is null. + * + * @return Returns the query result. + */ + std::shared_ptr Query( + Uri &uri, std::vector &columns, const NativeRdb::DataAbilityPredicates &predicates); + + /** + * @brief Obtains the MIME type matching the data specified by the URI of the Data ability. This method should be + * implemented by a Data ability. Data abilities supports general data types, including text, HTML, and JPEG. + * + * @param uri Indicates the URI of the data. + * + * @return Returns the MIME type that matches the data specified by uri. + */ + std::string GetType(Uri &uri); + + /** + * @brief Reloads data in the database. + * + * @param uri Indicates the position where the data is to reload. This parameter is mandatory. + * @param extras Indicates the PacMap object containing the additional parameters to be passed in this call. This + * parameter can be null. If a custom Sequenceable object is put in the PacMap object and will be transferred across + * processes, you must call BasePacMap.setClassLoader(ClassLoader) to set a class loader for the custom object. + * + * @return Returns true if the data is successfully reloaded; returns false otherwise. + */ + bool Reload(Uri &uri, const PacMap &extras); + + /** + * @brief Inserts multiple data records into the database. + * + * @param uri Indicates the path of the data to operate. + * @param values Indicates the data records to insert. + * + * @return Returns the number of data records inserted. + */ + int BatchInsert(Uri &uri, const std::vector &values); + + /** + * @brief Registers an observer to DataObsMgr specified by the given Uri. + * + * @param uri, Indicates the path of the data to operate. + * @param dataObserver, Indicates the IDataAbilityObserver object. + */ + void RegisterObserver(const Uri &uri, const sptr &dataObserver); + + /** + * @brief Deregisters an observer used for DataObsMgr specified by the given Uri. + * + * @param uri, Indicates the path of the data to operate. + * @param dataObserver, Indicates the IDataAbilityObserver object. + */ + void UnregisterObserver(const Uri &uri, const sptr &dataObserver); + + /** + * @brief Notifies the registered observers of a change to the data resource specified by Uri. + * + * @param uri, Indicates the path of the data to operate. + */ + void NotifyChange(const Uri &uri); + + /** + * @brief Converts the given uri that refer to the Data ability into a normalized URI. A normalized URI can be used + * across devices, persisted, backed up, and restored. It can refer to the same item in the Data ability even if the + * context has changed. If you implement URI normalization for a Data ability, you must also implement + * denormalizeUri(ohos.utils.net.Uri) to enable URI denormalization. After this feature is enabled, URIs passed to + * any method that is called on the Data ability must require normalization verification and denormalization. The + * default implementation of this method returns null, indicating that this Data ability does not support URI + * normalization. + * + * @param uri Indicates the Uri object to normalize. + * + * @return Returns the normalized Uri object if the Data ability supports URI normalization; returns null otherwise. + */ + Uri NormalizeUri(Uri &uri); + + /** + * @brief Converts the given normalized uri generated by normalizeUri(ohos.utils.net.Uri) into a denormalized one. + * The default implementation of this method returns the original URI passed to it. + * + * @param uri uri Indicates the Uri object to denormalize. + * + * @return Returns the denormalized Uri object if the denormalization is successful; returns the original Uri passed + * to this method if there is nothing to do; returns null if the data identified by the original Uri cannot be found + * in the current environment. + */ + Uri DenormalizeUri(Uri &uri); + + /** + * @brief Performs batch operations on the database. + * + * @param uri Indicates the path of data to operate. + * @param operations Indicates a list of database operations on the database. + * @return Returns the result of each operation, in array. + */ + std::vector> ExecuteBatch( + const Uri &uri, const std::vector> &operations); + +private: + DataAbilityHelper(const std::shared_ptr &context, const std::shared_ptr &uri, + const sptr &dataAbilityProxy, bool tryBind = false); + DataAbilityHelper(const std::shared_ptr &context); + DataAbilityHelper(const sptr &token, const std::shared_ptr &uri, + const sptr &dataAbilityProxy); + DataAbilityHelper(const sptr &token); + + void AddDataAbilityDeathRecipient(const sptr &token); + void OnSchedulerDied(const wptr &remote); + + bool CheckUriParam(const Uri &uri); + bool CheckOhosUri(const Uri &uri); + + sptr token_; + std::weak_ptr context_; + std::shared_ptr uri_ = nullptr; + bool tryBind_ = false; + bool isSystemCaller_ = false; + sptr dataAbilityProxy_ = nullptr; + std::mutex lock_; + static std::mutex oplock_; + + sptr callerDeathRecipient_ = nullptr; // caller binderDied Recipient + + std::map, sptr> registerMap_; + + std::map, std::string> uriMap_; + +}; + +class DataAbilityDeathRecipient : public IRemoteObject::DeathRecipient { +public: + using RemoteDiedHandler = std::function &)>; + + explicit DataAbilityDeathRecipient(RemoteDiedHandler handler); + + virtual ~DataAbilityDeathRecipient(); + + virtual void OnRemoteDied(const wptr &remote); + +private: + RemoteDiedHandler handler_; +}; + +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_APPEXECFWK_OHOS_DATA_ABILITY_HELPER_H \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/include/data_ability_impl.h b/tools/frameworks/kits/ability/native/include/data_ability_impl.h new file mode 100644 index 00000000000..e9f48c43abf --- /dev/null +++ b/tools/frameworks/kits/ability/native/include/data_ability_impl.h @@ -0,0 +1,200 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_APPEXECFWK_OHOS_DATA_ABILITY_IMPL_H +#define FOUNDATION_APPEXECFWK_OHOS_DATA_ABILITY_IMPL_H + +#include "ability_impl.h" + +namespace OHOS { +namespace NativeRdb { +class DataAbilityPredicates; +class ValuesBucket; +} // namespace NativeRdb +namespace AppExecFwk { +class DataAbilityImpl final : public AbilityImpl { +public: + /** + * @brief Constructor. + * + */ + DataAbilityImpl() = default; + + /** + * @brief Destructor. + * + */ + ~DataAbilityImpl() = default; + + /** + * @brief Handling the life cycle switching of PageAbility. + * + * @param want Indicates the structure containing information about the ability. + * @param targetState The life cycle state to switch to. + * + */ + void HandleAbilityTransaction(const Want &want, const AAFwk::LifeCycleStateInfo &targetState); + + /** + * @brief Obtains the MIME types of files supported. + * + * @param uri Indicates the path of the files to obtain. + * @param mimeTypeFilter Indicates the MIME types of the files to obtain. This parameter cannot be null. + * + * @return Returns the matched MIME types. If there is no match, null is returned. + */ + std::vector GetFileTypes(const Uri &uri, const std::string &mimeTypeFilter); + + /** + * @brief Opens a file in a specified remote path. + * + * @param uri Indicates the path of the file to open. + * @param mode Indicates the file open mode, which can be "r" for read-only access, "w" for write-only access + * (erasing whatever data is currently in the file), "wt" for write access that truncates any existing file, + * "wa" for write-only access to append to any existing data, "rw" for read and write access on any existing data, + * or "rwt" for read and write access that truncates any existing file. + * + * @return Returns the file descriptor. + */ + int OpenFile(const Uri &uri, const std::string &mode); + + /** + * @brief This is like openFile, open a file that need to be able to return sub-sections of files,often assets + * inside of their .hap. + * + * @param uri Indicates the path of the file to open. + * @param mode Indicates the file open mode, which can be "r" for read-only access, "w" for write-only access + * (erasing whatever data is currently in the file), "wt" for write access that truncates any existing file, + * "wa" for write-only access to append to any existing data, "rw" for read and write access on any existing + * data, or "rwt" for read and write access that truncates any existing file. + * + * @return Returns the RawFileDescriptor object containing file descriptor. + */ + int OpenRawFile(const Uri &uri, const std::string &mode); + + /** + * @brief Inserts a single data record into the database. + * + * @param uri Indicates the path of the data to operate. + * @param value Indicates the data record to insert. If this parameter is null, a blank row will be inserted. + * + * @return Returns the index of the inserted data record. + */ + int Insert(const Uri &uri, const NativeRdb::ValuesBucket &value); + + /** + * @brief Updates data records in the database. + * + * @param uri Indicates the path of data to update. + * @param value Indicates the data to update. This parameter can be null. + * @param predicates Indicates filter criteria. You should define the processing logic when this parameter is null. + * + * @return Returns the number of data records updated. + */ + int Update( + const Uri &uri, const NativeRdb::ValuesBucket &value, const NativeRdb::DataAbilityPredicates &predicates); + + /** + * @brief Deletes one or more data records from the database. + * + * @param uri Indicates the path of the data to operate. + * @param predicates Indicates filter criteria. You should define the processing logic when this parameter is null. + * + * @return Returns the number of data records deleted. + */ + int Delete(const Uri &uri, const NativeRdb::DataAbilityPredicates &predicates); + + /** + * @brief Deletes one or more data records from the database. + * + * @param uri Indicates the path of data to query. + * @param columns Indicates the columns to query. If this parameter is null, all columns are queried. + * @param predicates Indicates filter criteria. You should define the processing logic when this parameter is null. + * + * @return Returns the query result. + */ + std::shared_ptr Query( + const Uri &uri, std::vector &columns, const NativeRdb::DataAbilityPredicates &predicates); + + /** + * @brief Obtains the MIME type matching the data specified by the URI of the Data ability. This method should be + * implemented by a Data ability. Data abilities supports general data types, including text, HTML, and JPEG. + * + * @param uri Indicates the URI of the data. + * + * @return Returns the MIME type that matches the data specified by uri. + */ + std::string GetType(const Uri &uri); + + /** + * @brief Reloads data in the database. + * + * @param uri Indicates the position where the data is to reload. This parameter is mandatory. + * @param extras Indicates the PacMap object containing the additional parameters to be passed in this call. This + * parameter can be null. If a custom Sequenceable object is put in the PacMap object and will be transferred across + * processes, you must call BasePacMap.setClassLoader(ClassLoader) to set a class loader for the custom object. + * + * @return Returns true if the data is successfully reloaded; returns false otherwise. + */ + bool Reload(const Uri &uri, const PacMap &extras); + + /** + * @brief Inserts multiple data records into the database. + * + * @param uri Indicates the path of the data to operate. + * @param values Indicates the data records to insert. + * + * @return Returns the number of data records inserted. + */ + int BatchInsert(const Uri &uri, const std::vector &values); + + /** + * @brief Converts the given uri that refer to the Data ability into a normalized URI. A normalized URI can be used + * across devices, persisted, backed up, and restored. It can refer to the same item in the Data ability even if the + * context has changed. If you implement URI normalization for a Data ability, you must also implement + * denormalizeUri(ohos.utils.net.Uri) to enable URI denormalization. After this feature is enabled, URIs passed to any + * method that is called on the Data ability must require normalization verification and denormalization. The default + * implementation of this method returns null, indicating that this Data ability does not support URI normalization. + * + * @param uri Indicates the Uri object to normalize. + * + * @return Returns the normalized Uri object if the Data ability supports URI normalization; returns null otherwise. + */ + Uri NormalizeUri(const Uri &uri); + + /** + * @brief Converts the given normalized uri generated by normalizeUri(ohos.utils.net.Uri) into a denormalized one. + * The default implementation of this method returns the original URI passed to it. + * + * @param uri uri Indicates the Uri object to denormalize. + * + * @return Returns the denormalized Uri object if the denormalization is successful; returns the original Uri passed to + * this method if there is nothing to do; returns null if the data identified by the original Uri cannot be found in the + * current environment. + */ + Uri DenormalizeUri(const Uri &uri); + + /** + * @brief Performs batch operations on the database. + * + * @param operations Indicates a list of database operations on the database. + * @return Returns the result of each operation, in array. + */ + std::vector> ExecuteBatch( + const std::vector> &operations); +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_APPEXECFWK_OHOS_DATA_ABILITY_IMPL_H \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/include/data_ability_operation.h b/tools/frameworks/kits/ability/native/include/data_ability_operation.h new file mode 100644 index 00000000000..57a9c13e412 --- /dev/null +++ b/tools/frameworks/kits/ability/native/include/data_ability_operation.h @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_APPEXECFWK_OHOS_DATA_ABILITY_OPERATION_H +#define FOUNDATION_APPEXECFWK_OHOS_DATA_ABILITY_OPERATION_H + +#include +#include +#include "data_ability_operation_builder.h" +#include "uri.h" +#include "parcel.h" + +using Uri = OHOS::Uri; + +namespace OHOS { +namespace NativeRdb { +class DataAbilityPredicates; +class ValuesBucket; +} +namespace AppExecFwk { +class DataAbilityOperationBuilder; +class DataAbilityOperation final : public Parcelable, public std::enable_shared_from_this { +public: + ~DataAbilityOperation(); + + DataAbilityOperation( + const std::shared_ptr &dataAbilityOperation, const std::shared_ptr &withUri); + DataAbilityOperation(Parcel &in); + DataAbilityOperation(const std::shared_ptr &builder); + DataAbilityOperation(); + /** + * @brief Creates an operation for inserting data. + * @param uri Indicates the path of data to operate. + * @return Returns an insert DataAbilityOperationBuilder object. + */ + static std::shared_ptr NewInsertBuilder(const std::shared_ptr &uri); + /** + * @brief Creates an operation for updating data. + * @param uri Indicates the path of data to operate. + * @return Returns an update DataAbilityOperationBuilder object. + */ + static std::shared_ptr NewUpdateBuilder(const std::shared_ptr &uri); + /** + * @brief Creates an operation for deleting data. + * @param uri Indicates the path of data to operate. + * @return Returns an delete DataAbilityOperationBuilder object. + */ + static std::shared_ptr NewDeleteBuilder(const std::shared_ptr &uri); + /** + * @brief Creates an operation for asserting data. + * @param uri Indicates the path of data to operate. + * @return Returns an assert DataAbilityOperationBuilder object. + */ + static std::shared_ptr NewAssertBuilder(const std::shared_ptr &uri); + /** + * @brief Obtains the value of the type attribute included in this DataAbilityOperation. + * @return Returns the type included in this DataAbilityOperation. + */ + int GetType() const; + /** + * @brief Obtains the value of the uri attribute included in this DataAbilityOperation. + * @return Returns the uri included in this DataAbilityOperation. + */ + std::shared_ptr GetUri() const; + /** + * @brief Obtains the value of the valuesBucket attribute included in this DataAbilityOperation. + * @return Returns the valuesBucket included in this DataAbilityOperation. + */ + std::shared_ptr GetValuesBucket() const; + /** + * @brief Obtains the value of the expectedCount attribute included in this DataAbilityOperation. + * @return Returns the expectedCount included in this DataAbilityOperation. + */ + int GetExpectedCount() const; + /** + * @brief Obtains the value of the dataAbilityPredicates attribute included in this DataAbilityOperation. + * @return Returns the dataAbilityPredicates included in this DataAbilityOperation. + */ + std::shared_ptr GetDataAbilityPredicates() const; + /** + * @brief Obtains the value of the valuesBucketReferences attribute included in this DataAbilityOperation. + * @return Returns the valuesBucketReferences included in this DataAbilityOperation. + */ + std::shared_ptr GetValuesBucketReferences() const; + /** + * @brief Obtains the value of the dataAbilityPredicatesBackReferences attribute included in this + * DataAbilityOperation. + * @return Returns the dataAbilityPredicatesBackReferences included in this DataAbilityOperation. + */ + std::map GetDataAbilityPredicatesBackReferences() const; + /** + * @brief Checks whether an insert operation is created. + * @return Returns true if it is an insert operation; returns false otherwise. + */ + bool IsInsertOperation() const; + /** + * @brief Checks whether an delete operation is created. + * @return Returns true if it is an delete operation; returns false otherwise. + */ + bool IsDeleteOperation() const; + /** + * @brief Checks whether an update operation is created. + * @return Returns true if it is an update operation; returns false otherwise. + */ + bool IsUpdateOperation() const; + /** + * @brief Checks whether an assert operation is created. + * @return Returns true if it is an assert operation; returns false otherwise. + */ + bool IsAssertOperation() const; + /** + * @brief Checks whether an operation can be interrupted. + * @return Returns true if the operation can be interrupted; returns false otherwise. + */ + bool IsInterruptionAllowed() const; + + bool operator==(const DataAbilityOperation &other) const; + DataAbilityOperation &operator=(const DataAbilityOperation &other); + bool Marshalling(Parcel &out) const; + static DataAbilityOperation *Unmarshalling(Parcel &in); + + /** + * @brief Creates a DataAbilityOperation instance based on the given Parcel object + * @param in Indicates the Parcel object. + * @return Returns the DataAbilityOperation object. + */ + static std::shared_ptr CreateFromParcel(Parcel &in); + +public: + static constexpr int TYPE_INSERT = 1; + static constexpr int TYPE_UPDATE = 2; + static constexpr int TYPE_DELETE = 3; + static constexpr int TYPE_ASSERT = 4; + +private: + void PutMap(Parcel &in); + bool ReadFromParcel(Parcel &in); + +private: + // no object in parcel + static constexpr int VALUE_NULL = 0; + // object exist in parcel + static constexpr int VALUE_OBJECT = 1; + static constexpr int REFERENCE_THRESHOLD = 3 * 1024 * 1024; + int type_ = -1; + int expectedCount_ = 0; + bool interrupted_ = false; + std::shared_ptr uri_ = nullptr; + std::shared_ptr valuesBucket_ = nullptr; + std::shared_ptr dataAbilityPredicates_ = nullptr; + std::shared_ptr valuesBucketReferences_ = nullptr; + std::map dataAbilityPredicatesBackReferences_; +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_APPEXECFWK_OHOS_DATA_ABILITY_OPERATION_H \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/include/data_ability_operation_builder.h b/tools/frameworks/kits/ability/native/include/data_ability_operation_builder.h new file mode 100644 index 00000000000..19b63a72aaf --- /dev/null +++ b/tools/frameworks/kits/ability/native/include/data_ability_operation_builder.h @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_APPEXECFWK_OHOS_DATA_ABILITY_OPERATION_BUILDER_H +#define FOUNDATION_APPEXECFWK_OHOS_DATA_ABILITY_OPERATION_BUILDER_H + +#include +#include +#include "data_ability_operation.h" +#include "uri.h" +#include "parcel.h" + +using Uri = OHOS::Uri; +namespace OHOS { +namespace NativeRdb { +class DataAbilityPredicates; +class ValuesBucket; +} +namespace AppExecFwk { +class DataAbilityOperation; +class DataAbilityOperationBuilder final : public std::enable_shared_from_this { + friend class DataAbilityOperation; + +public: + DataAbilityOperationBuilder(const int type, const std::shared_ptr &uri); + ~DataAbilityOperationBuilder(); + /** + * @brief Creates a DataAbilityOperation object. + * @return Returns the DataAbilityOperation object. + */ + std::shared_ptr Build(); + /** + * @brief Sets the data records to be inserted or updated. + * @param values Indicates the data values to be set. + * @return Returns a DataAbilityOperationBuilder object containing the given values parameter. + */ + std::shared_ptr WithValuesBucket(std::shared_ptr &values); + /** + * @brief Sets filter criteria used for deleting updating or assert query data. + * @param predicates Indicates the filter criteria to set. If this parameter is null, all data records will be + * operated by default. + * @return Returns an object containing the given filter criteria. + */ + std::shared_ptr WithPredicates(std::shared_ptr &predicates); + /** + * @brief Sets the expected number of rows to update ,delete or assert query. + * @param count Indicates the expected number of rows to update or delete. + * @return Returns a DataAbilityOperationBuilder object containing the given count parameter. + */ + std::shared_ptr WithExpectedCount(int count); + /** + * @brief Adds a back reference to be used as a filter criterion in withPredicates(DataAbilityPredicates). + * @param requestArgIndex Indicates the index referencing the predicate parameter whose value is to be replaced. + * @param previousResult Indicates the index referencing the historical DataAbilityResult used to replace the value + * of the specified predicate parameter. + * @return Returns a DataAbilityOperationBuilder object containing the given requestArgIndex and previousResult + * parameters. + */ + std::shared_ptr WithPredicatesBackReference(int requestArgIndex, int previousResult); + /** + * @brief Adds a back reference to be used in withValuesBucket(ValuesBucket). + * @param backReferences Indicates the ValuesBucket object containing a set of key-value pairs. In each pair, the + * key specifies the value to be updated and the value specifies the index referencing the DataAbilityResult used to + * replace the specified value. This parameter cannot be null. + * @return Returns a DataAbilityOperationBuilder object containing the given backReferences parameter. + */ + std::shared_ptr WithValueBackReferences(std::shared_ptr &backReferences); + /** + * @brief Sets an interrupt flag bit for a batch operation, which can be insert, update, delete, or assert. + * @param interrupted Specifies whether a batch operation can be interrupted. The value true indicates that the + * operation can be interrupted, and false indicates the opposite. + * @return Returns a DataAbilityOperationBuilder object containing the given interrupted parameter. + */ + std::shared_ptr WithInterruptionAllowed(bool interrupted); + +private: + int type_; + int expectedCount_; + bool interrupted_; + std::shared_ptr uri_; + std::shared_ptr valuesBucket_; + std::shared_ptr dataAbilityPredicates_; + std::shared_ptr valuesBucketReferences_; + std::map dataAbilityPredicatesBackReferences_; +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_APPEXECFWK_OHOS_DATA_ABILITY_OPERATION_BUILDER_H \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/include/data_ability_result.h b/tools/frameworks/kits/ability/native/include/data_ability_result.h new file mode 100644 index 00000000000..465a1f445ef --- /dev/null +++ b/tools/frameworks/kits/ability/native/include/data_ability_result.h @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_APPEXECFWK_OHOS_DATA_ABILITY_RESULT_H +#define FOUNDATION_APPEXECFWK_OHOS_DATA_ABILITY_RESULT_H + +#include "uri.h" +#include "parcel.h" + +using Uri = OHOS::Uri; + +namespace OHOS { +namespace AppExecFwk { +class DataAbilityResult final : public Parcelable { +public: + /** + * @brief A constructor used to create a DataAbilityResult instance + * with the input parameter count specified. + */ + DataAbilityResult(int count); + + /** + * @brief A constructor used to create a DataAbilityResult instance + * with the input parameter uri specified + */ + DataAbilityResult(const Uri &uri); + + /** + * @brief A constructor used to create a DataAbilityResult instance + * with a Parcel object specified. + */ + DataAbilityResult(Parcel &parcel); + + /** + * @brief A constructor used to create a DataAbilityResult instance + * with input parameters uri, count, and failure specified. + */ + DataAbilityResult(const Uri &uri, int count); + + ~DataAbilityResult(); + + /** + * @brief Obtains the Uri object corresponding to the operation. + * @return Obtains the Uri object corresponding to the operation. + */ + Uri GetUri(); + + /** + * @brief Obtains the number of rows affected by the operation. + * @return Returns the number of rows affected by the operation. + */ + int GetCount(); + + /** + * @brief Prints out a string containing the class object information. + * @return Returns object information. + */ + std::string ToString(); + + /** + * @brief Marshals a DataAbilityResult object into a Parcel. + * @param parcel Indicates the Parcel object for marshalling. + * @return Returns true if the marshalling is successful; returns false otherwise. + */ + virtual bool Marshalling(Parcel &parcel) const; + + /** + * @brief Unmarshals a DataAbilityResult object from a Parcel. + * @param parcel Indicates the Parcel object for unmarshalling. + * @return Returns true if the unmarshalling is successful; returns false otherwise. + */ + static DataAbilityResult *Unmarshalling(Parcel &parcel); + + /** + * @brief Creates a DataAbilityResult instance based on the given Parcel object. + * Used to transfer DataAbilityResult object using Parcel. + * @param parcel Indicates the Parcel object. + * @return Returns the DataAbilityResult object. + */ + static DataAbilityResult *CreateFromParcel(Parcel &parcel); + +private: + Uri uri_; + int count_; + + bool ReadFromParcel(Parcel &parcel); + // no object in parcel + static constexpr int VALUE_NULL = -1; + // object exist in parcel + static constexpr int VALUE_OBJECT = 1; + +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_APPEXECFWK_OHOS_DATA_ABILITY_RESULT_H \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/include/data_uri_utils.h b/tools/frameworks/kits/ability/native/include/data_uri_utils.h new file mode 100644 index 00000000000..d6123e95831 --- /dev/null +++ b/tools/frameworks/kits/ability/native/include/data_uri_utils.h @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DATA_URI_UTIL_H +#define DATA_URI_UTIL_H + +#include +#include "uri.h" + +using string = std::string; +using Uri = OHOS::Uri; + +namespace OHOS { +namespace AppExecFwk { +class DataUriUtils final { +public: + /** + * @brief Default constructor of DataUriUtils class + * @return None + */ + DataUriUtils(); + + /** + * @brief Default deconstructor of DataUriUtils class + * @return None + */ + ~DataUriUtils(); + + /** + * @brief Attaches the given ID to the end of the path component of the given URI. + * @param dataUri based on RFC 2396( Uniform Resource Identifier ). + * @param id + * @return Uri( scheme://authority/path1/path2/path3/updateIDNumber....) + */ + static Uri AttachId(const Uri &dataUri, long long id); + + /** + * @brief Obtains the ID attached to the end of the path component of the given URI. + * @param dataUri based on RFC 2396( Uniform Resource Identifier ). + * @return long ID + */ + static long long GetId(const Uri &dataUri); + + /** + * @brief Deletes the ID from the end of the path component of the given URI. + * @param dataUri based on RFC 2396( Uniform Resource Identifier ). + * @return long ID + */ + static Uri DeleteId(const Uri &dataUri); + + /** + * @brief Updates the ID in the specified dataUri + * @param dataUri based on RFC 2396( Uniform Resource Identifier ). + * @param id indiates Update attached to the end of the path component of the given URI + * @return Uri return is the URI after path is updated + */ + static Uri UpdateId(const Uri &dataUri, long long id); + + /** + * @brief Does the end path of the path component of the given URI have an ID attached to it? + * @param dataUri based on RFC 2396( Uniform Resource Identifier ). + * @return bool + */ + static bool IsAttachedId(const Uri &dataUri); + +private: + /** + * @brief Determine whether the string content is a numeric string + * @param str indicates stirng. + * @return bool + */ + static bool IsNumber(const string &str); + + /** + * @brief Determine whether the string content is a numeric string + * @param dataUri indicates Uri object + * @return Uri return is the URI after path is updated + */ + static Uri UriUpateLastPath(const Uri &dataUri, const string &updateLastPath); +}; +} // namespace AppExecFwk +} // namespace OHOS + +#endif diff --git a/tools/frameworks/kits/ability/native/include/dummy_ability_package.h b/tools/frameworks/kits/ability/native/include/dummy_ability_package.h new file mode 100644 index 00000000000..20ffecce1f1 --- /dev/null +++ b/tools/frameworks/kits/ability/native/include/dummy_ability_package.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_APPEXECFWK_OHOS_ABILITYPACKAGE_H +#define FOUNDATION_APPEXECFWK_OHOS_ABILITYPACKAGE_H + +namespace OHOS { +namespace AppExecFwk { +class AbilityPackage { +public: + AbilityPackage() = default; + + ~AbilityPackage() = default; +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_APPEXECFWK_OHOS_ABILITYPACKAGE_H \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/include/dummy_component_container.h b/tools/frameworks/kits/ability/native/include/dummy_component_container.h new file mode 100644 index 00000000000..45fbe4231d3 --- /dev/null +++ b/tools/frameworks/kits/ability/native/include/dummy_component_container.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_APPEXECFWK_OHOS_DUMMY_COMPONENT_CONTAINER_H +#define FOUNDATION_APPEXECFWK_OHOS_DUMMY_COMPONENT_CONTAINER_H + +namespace OHOS { +namespace AppExecFwk { +class ComponentContainer { +public: + ComponentContainer() = default; + ~ComponentContainer() = default; +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_APPEXECFWK_OHOS_DUMMY_COMPONENT_CONTAINER_H \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/include/dummy_continuation_state.h b/tools/frameworks/kits/ability/native/include/dummy_continuation_state.h new file mode 100644 index 00000000000..2f79ae6b891 --- /dev/null +++ b/tools/frameworks/kits/ability/native/include/dummy_continuation_state.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_APPEXECFWK_OHOS_CONTINUATIONTATE_H +#define FOUNDATION_APPEXECFWK_OHOS_CONTINUATIONTATE_H + +namespace OHOS { +namespace AppExecFwk { +class ContinuationState { +public: + ContinuationState() = default; + + ~ContinuationState() = default; +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_APPEXECFWK_OHOS_CONTINUATIONTATE_H \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/include/dummy_data_ability_predicates.h b/tools/frameworks/kits/ability/native/include/dummy_data_ability_predicates.h new file mode 100644 index 00000000000..a0dc7bf2d3e --- /dev/null +++ b/tools/frameworks/kits/ability/native/include/dummy_data_ability_predicates.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_APPEXECFWK_OHOS_DATAABILITYPREDICATES_H +#define FOUNDATION_APPEXECFWK_OHOS_DATAABILITYPREDICATES_H + +#include +#include + +#include "nocopyable.h" +#include "parcel.h" + +namespace OHOS { +namespace AppExecFwk { +class DataAbilityPredicates : public Parcelable { +public: + DataAbilityPredicates() = default; + DataAbilityPredicates(const std::string &testInf); + ~DataAbilityPredicates() = default; + DataAbilityPredicates(const Parcel &parcel){}; + + bool ReadFromParcel(Parcel &parcel); + virtual bool Marshalling(Parcel &parcel) const override; + static DataAbilityPredicates *Unmarshalling(Parcel &parcel); + +private: + std::string testInf_; +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_APPEXECFWK_OHOS_DATAABILITYPREDICATES_H \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/include/dummy_notification_request.h b/tools/frameworks/kits/ability/native/include/dummy_notification_request.h new file mode 100644 index 00000000000..ffbaa59135c --- /dev/null +++ b/tools/frameworks/kits/ability/native/include/dummy_notification_request.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_APPEXECFWK_OHOS_NOTIFICATIONREQUEST_H +#define FOUNDATION_APPEXECFWK_OHOS_NOTIFICATIONREQUEST_H + +namespace OHOS { +namespace AppExecFwk { +class NotificationRequest { +public: + NotificationRequest() = default; + ~NotificationRequest() = default; +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_APPEXECFWK_OHOS_NOTIFICATIONREQUEST_H \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/include/dummy_result_set.h b/tools/frameworks/kits/ability/native/include/dummy_result_set.h new file mode 100644 index 00000000000..d8bf158f44a --- /dev/null +++ b/tools/frameworks/kits/ability/native/include/dummy_result_set.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_APPEXECFWK_OHOS_RESULTSET_H +#define FOUNDATION_APPEXECFWK_OHOS_RESULTSET_H + +#include +#include + +#include "nocopyable.h" +#include "parcel.h" + +namespace OHOS { +namespace AppExecFwk { +class ResultSet : public Parcelable { +public: + ResultSet() = default; + ResultSet(const std::string &testInf); + ~ResultSet() = default; + + bool ReadFromParcel(Parcel &parcel); + virtual bool Marshalling(Parcel &parcel) const override; + static ResultSet *Unmarshalling(Parcel &parcel); + std::string testInf_; +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_APPEXECFWK_OHOS_RESULTSET_H \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/include/dummy_values_bucket.h b/tools/frameworks/kits/ability/native/include/dummy_values_bucket.h new file mode 100644 index 00000000000..8f6515bcf9e --- /dev/null +++ b/tools/frameworks/kits/ability/native/include/dummy_values_bucket.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_APPEXECFWK_OHOS_VALUESBUCKER_H +#define FOUNDATION_APPEXECFWK_OHOS_VALUESBUCKER_H + +#include +#include + +#include "nocopyable.h" +#include "parcel.h" + +namespace OHOS { +namespace AppExecFwk { +class ValuesBucket : public Parcelable { +public: + ValuesBucket() = default; + ValuesBucket(const std::string &testInf); + ~ValuesBucket() = default; + ValuesBucket(const Parcel &parcel){}; + + bool ReadFromParcel(Parcel &parcel); + virtual bool Marshalling(Parcel &parcel) const override; + static ValuesBucket *Unmarshalling(Parcel &parcel); + + bool IsEmpty() + { + return false; + }; + + void PutValues(std::shared_ptr &other){}; + +private: + std::string testInf_; +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_APPEXECFWK_OHOS_VALUESBUCKER_H \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/include/form_js_event_handler.h b/tools/frameworks/kits/ability/native/include/form_js_event_handler.h new file mode 100755 index 00000000000..8c70f8dc1ec --- /dev/null +++ b/tools/frameworks/kits/ability/native/include/form_js_event_handler.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_APPEXECFWK_OHOS_FORM_JS_EVENT_HANDLER_H +#define FOUNDATION_APPEXECFWK_OHOS_FORM_JS_EVENT_HANDLER_H + +#include +#include "ability.h" +#include "event_handler.h" + +namespace OHOS { +namespace AppExecFwk { +class FormJsEventHandler : public EventHandler { +public: + FormJsEventHandler(const std::shared_ptr &runner, + const std::shared_ptr& ability, const FormJsInfo& formJsInfo); + ~FormJsEventHandler() = default; + + /** + * Process the event. Developers should override this method. + * + * @param event The event should be processed. + */ + void ProcessEvent(const InnerEvent::Pointer &event) override; + + enum { + FORM_ROUTE_EVENT = 100, + FORM_MESSAGE_EVENT, + }; +private: + /** + * @brief Process js router event. + * @param want Indicates the event to be processed. + */ + void ProcessRouterEvent(Want &want); + + /** + * @brief Process js message event. + * @param want Indicates the event to be processed. + */ + void ProcessMessageEvent(const Want &want); + bool IsSystemApp() const; + +private: + FormJsInfo formJsInfo_; + std::shared_ptr ability_; +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_APPEXECFWK_OHOS_FORM_JS_EVENT_HANDLER_H diff --git a/tools/frameworks/kits/ability/native/include/form_provider_client.h b/tools/frameworks/kits/ability/native/include/form_provider_client.h new file mode 100755 index 00000000000..95899bbdddf --- /dev/null +++ b/tools/frameworks/kits/ability/native/include/form_provider_client.h @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_APPEXECFWK_OHOS_FORM_PROVIDER_CLIENT_H +#define FOUNDATION_APPEXECFWK_OHOS_FORM_PROVIDER_CLIENT_H + +#include +#include +#include +#include "ability.h" +#include "form_constants.h" +#include "form_provider_info.h" +#include "form_provider_stub.h" + +namespace OHOS { +namespace AppExecFwk { +/** + * @class FormProviderStub + * The service of the form provider. + */ +class FormProviderClient : public FormProviderStub { +public: + FormProviderClient() = default; + virtual ~FormProviderClient() = default; + + /** + * @brief Acquire to give back an ProviderFormInfo. This is sync API. + * @param formId The Id of the form. + * @param want Indicates the {@link Want} structure containing form info. + * @param callerToken Caller ability token. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int AcquireProviderFormInfo( + const int64_t formId, + const Want &want, + const sptr &callerToken) override; + + /** + * @brief Notify provider when the form was deleted. + * + * @param formId The Id of the form. + * @param want Indicates the structure containing form info. + * @param callerToken Caller ability token. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int NotifyFormDelete( + const int64_t formId, + const Want &want, + const sptr &callerToken) override; + + /** + * @brief Notify provider when the form was deleted. + * + * @param formIds The id list of forms. + * @param want Indicates the structure containing form info. + * @param callerToken Caller ability token. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int NotifyFormsDelete( + const std::vector &formIds, + const Want &want, + const sptr &callerToken) override; + + /** + * @brief Notify provider when the form need update. + * + * @param formId The Id of the form. + * @param want Indicates the structure containing form info. + * @param callerToken Caller ability token. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int NotifyFormUpdate( + const int64_t formId, + const Want &want, + const sptr &callerToken) override; + + /** + * @brief Event notify when change the form visible. + * + * @param formIds The vector of form ids. + * @param formVisibleType The form visible type, including FORM_VISIBLE and FORM_INVISIBLE. + * @param want Indicates the structure containing form info. + * @param callerToken Caller ability token. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int EventNotify(const std::vector &formIds, const int32_t formVisibleType, const Want &want, + const sptr &callerToken) override; + + /** + * @brief Notify provider when the temp form was cast to normal form. + * + * @param formId The Id of the form to update. + * @param want Indicates the structure containing form info. + * @param callerToken Caller ability token. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int NotifyFormCastTempForm( + const int64_t formId, + const Want &want, + const sptr &callerToken) override; + /** + * @brief Fire message event to form provider. + * @param formId The Id of the from. + * @param message Event message. + * @param want The want of the request. + * @param callerToken Form provider proxy object. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int FireFormEvent( + const int64_t formId, + const std::string &message, + const Want &want, + const sptr &callerToken) override; + /** + * @brief Set the owner ability of the form provider client. + * + * @param ability The owner ability of the form provider client. + * @return none. + */ + void SetOwner(const std::shared_ptr ability); + + /** + * @brief Clear the owner ability of the form provider client. + * + * @param ability The owner ability of the form provider client. + * @return none. + */ + void ClearOwner(const std::shared_ptr ability); + +private: + std::shared_ptr GetOwner(); + bool CheckIsSystemApp() const; + int HandleAcquire( + const FormProviderInfo &formProviderInfo, + const Want &newWant, + const sptr &callerToken); + int HandleDisconnect(const Want &want, const sptr &callerToken); + +private: + DISALLOW_COPY_AND_MOVE(FormProviderClient); + mutable std::mutex abilityMutex_; + std::weak_ptr owner_; +}; + +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_APPEXECFWK_OHOS_FORM_PROVIDER_CLIENT_H diff --git a/tools/frameworks/kits/ability/native/include/iability_lifecycle_callback.h b/tools/frameworks/kits/ability/native/include/iability_lifecycle_callback.h new file mode 100644 index 00000000000..3ef3c495dd1 --- /dev/null +++ b/tools/frameworks/kits/ability/native/include/iability_lifecycle_callback.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_APPEXECFWK_OHOS_IABILITY_LIFECYCLE_CALLBACK_H +#define FOUNDATION_APPEXECFWK_OHOS_IABILITY_LIFECYCLE_CALLBACK_H + +namespace OHOS { +namespace AppExecFwk { +class IAbilityLifecycleCallback { +public: + /** + * + * Will be called when Ability start + * + * @param want Want for AbilitySliceManager + */ + virtual void OnAbilityStart(const Want &want) = 0; + + /** + * + * Will be called when Ability stop + */ + virtual void OnAbilityStop() = 0; + + /** + * + * Will be called when Ability active + */ + virtual void OnAbilityActive() = 0; + + /** + * + * Will be called when Ability inactive + */ + virtual void OnAbilityInactive() = 0; + + /** + * + * Will be called when Ability foreground + * + * @param want Want for AbilitySliceManager + */ + virtual void OnAbilityForeground(const Want &want) = 0; + + /** + * + * Will be called when Ability to background + */ + virtual void OnAbilityBackground() = 0; + + /** + * Will be called to receive result from other ability + * + * @param requestCode request code of ability result + * @param want ability result from other ability + */ + virtual void OnAbilityResult(int requestCode, const Want &want) = 0; +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_APPEXECFWK_OHOS_IABILITY_LIFECYCLE_CALLBACK_H diff --git a/tools/frameworks/kits/ability/native/include/ipc_singleton.h b/tools/frameworks/kits/ability/native/include/ipc_singleton.h new file mode 100644 index 00000000000..fe36d161a84 --- /dev/null +++ b/tools/frameworks/kits/ability/native/include/ipc_singleton.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_IPCSINGLETON_H +#define OHOS_AAFWK_IPCSINGLETON_H + +#include "nocopyable.h" +#include +#include + +namespace OHOS { +#define DECLARE_DELAYED_IPCSINGLETON(MyClass) \ +public: \ + ~MyClass(); \ + \ +private: \ + friend DelayedIPCSingleton; \ + MyClass(); + +template +class DelayedIPCSingleton : public NoCopyable { +public: + static sptr GetInstance() + { + if (instance_ == nullptr) { + std::lock_guard lock(mutex_); + if (instance_ == nullptr) { + sptr temp(new T); + instance_ = temp; + } + } + + return instance_; + }; + static void DestroyInstance(); + +private: + static sptr instance_; + static std::mutex mutex_; +}; + +template +sptr DelayedIPCSingleton::instance_ = nullptr; + +template +std::mutex DelayedIPCSingleton::mutex_; + +template +void DelayedIPCSingleton::DestroyInstance() +{ + std::lock_guard lock(mutex_); + if (instance_ != nullptr) { + instance_.reset(); + instance_ = nullptr; + } +} +} // namespace OHOS +#endif // OHOS_AAFWK_IPCSINGLETON_H \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/include/mission_information.h b/tools/frameworks/kits/ability/native/include/mission_information.h new file mode 100644 index 00000000000..d79e55f3809 --- /dev/null +++ b/tools/frameworks/kits/ability/native/include/mission_information.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_APPEXECFWK_OHOS_MISSION_INFORMATION_H +#define FOUNDATION_APPEXECFWK_OHOS_MISSION_INFORMATION_H + +#include + +#include "parcel.h" + +namespace OHOS { +namespace AppExecFwk { +struct MissionInformation : public Parcelable { + std::string label; + std::string iconPath; + + bool ReadFromParcel(Parcel &parcel); + virtual bool Marshalling(Parcel &parcel) const override; + static MissionInformation *Unmarshalling(Parcel &parcel); +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_APPEXECFWK_OHOS_MISSION_INFORMATION_H \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/include/page_ability_impl.h b/tools/frameworks/kits/ability/native/include/page_ability_impl.h new file mode 100644 index 00000000000..99b5238fc98 --- /dev/null +++ b/tools/frameworks/kits/ability/native/include/page_ability_impl.h @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_APPEXECFWK_OHOS_PAGE_ABILITY_IMPL_H +#define FOUNDATION_APPEXECFWK_OHOS_PAGE_ABILITY_IMPL_H + +#include "ability_impl.h" + +namespace OHOS { +namespace AppExecFwk { +class Ability; +class AbilityHandler; +class AbilityLocalRecord; +class AbilityImpl; +class PageAbilityImpl final : public AbilityImpl { +public: + /** + * @brief Constructor. + * + */ + PageAbilityImpl() = default; + + /** + * @brief Destructor. + * + */ + ~PageAbilityImpl() = default; + + /** + * @brief Handling the life cycle switching of PageAbility. + * + * @param want Indicates the structure containing information about the ability. + * @param targetState The life cycle state to switch to. + * + */ + void HandleAbilityTransaction(const Want &want, const AAFwk::LifeCycleStateInfo &targetState); + + /** + * @brief Handling the life cycle switching of PageAbility in switch. + * + * @param want Indicates the structure containing information about the ability. + * @param targetState The life cycle state to switch to. + * + * @return return true if the lifecycle transaction successfully, otherwise return false. + * + */ + bool AbilityTransaction(const Want &want, const AAFwk::LifeCycleStateInfo &targetState); + + /** + * @brief Execution the KeyDown callback of the ability + * @param keyCode Indicates the code of the key pressed. + * @param keyEvent Indicates the key-down event. + * + * @return Returns true if this event is handled and will not be passed further; returns false if this event is + * not handled and should be passed to other handlers. + * + */ + bool DoKeyDown(int keyCode, const KeyEvent &keyEvent); + + /** + * @brief Execution the KeyUp callback of the ability + * @param keyCode Indicates the code of the key released. + * @param keyEvent Indicates the key-up event. + * + * @return Returns true if this event is handled and will not be passed further; returns false if this event is + * not handled and should be passed to other handlers. + * + */ + bool DoKeyUp(int keyCode, const KeyEvent &keyEvent); + + /** + * @brief Called when a touch event is dispatched to this ability. The default implementation of this callback + * does nothing and returns false. + * @param touchEvent Indicates information about the touch event. + * + * @return Returns true if the event is handled; returns false otherwise. + * + */ + bool DoTouchEvent(const TouchEvent &touchEvent); +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_APPEXECFWK_OHOS_PAGE_ABILITY_IMPL_H \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/include/service_ability_impl.h b/tools/frameworks/kits/ability/native/include/service_ability_impl.h new file mode 100644 index 00000000000..10292e408f3 --- /dev/null +++ b/tools/frameworks/kits/ability/native/include/service_ability_impl.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_APPEXECFWK_OHOS_SERVICE_ABILITY_IMPL_H +#define FOUNDATION_APPEXECFWK_OHOS_SERVICE_ABILITY_IMPL_H + +#include "ability_impl.h" + +namespace OHOS { +namespace AppExecFwk { +class Ability; +class AbilityHandler; +class AbilityLocalRecord; +class AbilityImpl; +class ServiceAbilityImpl final : public AbilityImpl { +public: + /** + * @brief Constructor. + * + */ + ServiceAbilityImpl() = default; + + /** + * @brief Destructor. + * + */ + ~ServiceAbilityImpl() = default; + + /** + * @brief Handling the life cycle switching of PageAbility. + * + * @param want Indicates the structure containing information about the ability. + * @param targetState The life cycle state to switch to. + * + */ + void HandleAbilityTransaction(const Want &want, const AAFwk::LifeCycleStateInfo &targetState); +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_APPEXECFWK_OHOS_SERVICE_ABILITY_IMPL_H diff --git a/tools/frameworks/kits/ability/native/src/ability.cpp b/tools/frameworks/kits/ability/native/src/ability.cpp new file mode 100755 index 00000000000..771b0bdc641 --- /dev/null +++ b/tools/frameworks/kits/ability/native/src/ability.cpp @@ -0,0 +1,2953 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include "ability.h" +#include "ability_loader.h" +#include "app_log_wrapper.h" +#include "display_type.h" +#include "form_provider_client.h" +#include "if_system_ability_manager.h" +#include "iservice_registry.h" +#include "system_ability_definition.h" +#include "task_handler_client.h" +#include "ohos_application.h" +#include "continuation_manager.h" +#include "continuation_register_manager.h" +#include "continuation_register_manager_proxy.h" +#include "reverse_continuation_scheduler_primary.h" +#include "reverse_continuation_scheduler_replica.h" +#include "reverse_continuation_scheduler_replica_handler_interface.h" +#include "string_wrapper.h" +#include "permission/permission.h" +#include "permission/permission_kit.h" +#include "abs_shared_result_set.h" +#include "data_ability_predicates.h" +#include "values_bucket.h" +#include "ability_post_event_timeout.h" +#include "data_ability_result.h" +#include "data_ability_operation.h" +#include "data_uri_utils.h" + +#ifdef MMI_COMPILE +#include "key_events.h" +#include "touch_events.h" +#else +#include "key_event.h" +#include "touch_event.h" +#endif +#include "form_host_client.h" +#include "form_mgr.h" +#include "ipc_skeleton.h" + +namespace OHOS { +namespace AppExecFwk { +using PermissionKit = OHOS::Security::Permission::PermissionKit; +using PermissionState = OHOS::Security::Permission::PermissionState; + +REGISTER_AA(Ability) +const std::string Ability::SYSTEM_UI("com.ohos.systemui"); +const std::string Ability::STATUS_BAR("com.ohos.systemui.statusbar.MainAbility"); +const std::string Ability::NAVIGATION_BAR("com.ohos.systemui.navigationbar.MainAbility"); +const std::string DEVICE_MANAGER_BUNDLE_NAME = "com.ohos.devicemanagerui"; +const std::string DEVICE_MANAGER_NAME = "com.ohos.devicemanagerui.MainAbility"; +const std::string Ability::DMS_SESSION_ID("sessionId"); +const std::string Ability::DMS_ORIGIN_DEVICE_ID("deviceId"); +const int Ability::DEFAULT_DMS_SESSION_ID(0); +const std::string PERMISSION_REQUIRE_FORM = "ohos.permission.REQUIRE_FORM"; + +static std::mutex formLock; + +constexpr int64_t SEC_TO_MILLISEC = 1000; +constexpr int64_t MILLISEC_TO_NANOSEC = 1000000; + +void Ability::Init(const std::shared_ptr &abilityInfo, const std::shared_ptr &application, + std::shared_ptr &handler, const sptr &token) +{ + APP_LOGI("%{public}s begin.", __func__); + abilityInfo_ = abilityInfo; + handler_ = handler; + AbilityContext::token_ = token; + + // page ability only. + if (abilityInfo_->type == AbilityType::PAGE) { + abilityWindow_ = std::make_shared(); + + if (abilityWindow_ != nullptr) { + APP_LOGI("%{public}s begin abilityWindow_->Init", __func__); + abilityWindow_->Init(handler_, shared_from_this()); + APP_LOGI("%{public}s end abilityWindow_->Init", __func__); + } + continuationManager_ = std::make_shared(); + std::weak_ptr ability = shared_from_this(); + std::weak_ptr continuationManager = continuationManager_; + continuationHandler_ = std::make_shared(continuationManager, ability); + if (!continuationManager_->Init(shared_from_this(), GetToken(), GetAbilityInfo(), continuationHandler_)) { + continuationManager_.reset(); + } else { + std::weak_ptr continuationHandler = continuationHandler_; + sptr Primary = sptr( + new (std::nothrow) ReverseContinuationSchedulerPrimary(continuationHandler, handler_)); + if (Primary == nullptr) { + APP_LOGE("Ability::Init failed,Primary create failed"); + } else { + continuationHandler_->SetPrimaryStub(Primary); + continuationHandler_->SetAbilityInfo(abilityInfo_); + } + } + } + lifecycle_ = std::make_shared(); + abilityLifecycleExecutor_ = std::make_shared(); + if (abilityLifecycleExecutor_ != nullptr) { + abilityLifecycleExecutor_->DispatchLifecycleState(AbilityLifecycleExecutor::LifecycleState::INITIAL); + } else { + APP_LOGE("%{public}s abilityLifecycleExecutor_ make failed.", __func__); + } + + application_ = application; + APP_LOGI("%{public}s end.", __func__); +} + +/** + * @brief Obtains a resource manager. + * + * @return Returns a ResourceManager object. + */ +std::shared_ptr Ability::GetResourceManager() const +{ + return AbilityContext::GetResourceManager(); +} + +/** + * Will be called when ability start. You should override this function + * + * @param want ability start information + */ +void Ability::OnStart(const Want &want) +{ + APP_LOGI("%{public}s begin.", __func__); + if (abilityInfo_ == nullptr) { + APP_LOGE("Ability::OnStart falied abilityInfo_ is nullptr."); + return; + } + + if (abilityInfo_->type == AppExecFwk::AbilityType::PAGE) { + sptr config = WindowOption::Get(); + + OHOS::WindowType winType = OHOS::WindowType::WINDOW_TYPE_NORMAL; + if (abilityInfo_->bundleName == SYSTEM_UI) { + if (abilityInfo_->name == STATUS_BAR) { + winType = OHOS::WindowType::WINDOW_TYPE_STATUS_BAR; + } + if (abilityInfo_->name == NAVIGATION_BAR) { + winType = OHOS::WindowType::WINDOW_TYPE_NAVI_BAR; + } + } + if (abilityInfo_->bundleName == OHOS_REQUEST_PERMISSION_BUNDLENAME && + abilityInfo_->name == OHOS_REQUEST_PERMISSION_ABILITY_NAME) { + winType = OHOS::WindowType::WINDOW_TYPE_ALARM_SCREEN; + } + + if (abilityInfo_->bundleName == DEVICE_MANAGER_BUNDLE_NAME && abilityInfo_->name == DEVICE_MANAGER_NAME) { + winType = OHOS::WindowType::WINDOW_TYPE_ALARM_SCREEN; + } + + config->SetWindowType(winType); + APP_LOGI("Ability::OnStart bundleName:%{public}s abilityName:%{public}s: set config.type = %{public}d", + abilityInfo_->bundleName.c_str(), + abilityInfo_->name.c_str(), + winType); + SetUIContent(config); + + if (abilityWindow_ != nullptr) { + APP_LOGI("%{public}s begin abilityWindow_->OnPostAbilityStart.", __func__); + abilityWindow_->OnPostAbilityStart(); + APP_LOGI("%{public}s end abilityWindow_->OnPostAbilityStart.", __func__); + } + } + + SetWant(want); + if (abilityLifecycleExecutor_ == nullptr) { + APP_LOGE("Ability::OnStart error. abilityLifecycleExecutor_ == nullptr."); + return; + } + abilityLifecycleExecutor_->DispatchLifecycleState(AbilityLifecycleExecutor::LifecycleState::INACTIVE); + + if (lifecycle_ == nullptr) { + APP_LOGE("Ability::OnStart error. lifecycle_ == nullptr."); + return; + } + lifecycle_->DispatchLifecycle(LifeCycle::Event::ON_START, want); + APP_LOGI("%{public}s end.", __func__); +} + +/** + * @brief Called when this ability enters the STATE_STOP state. + * + * The ability in the STATE_STOP is being destroyed. + * You can override this function to implement your own processing logic. + */ +void Ability::OnStop() +{ + APP_LOGI("%{public}s begin.", __func__); + if (continuationManager_ != nullptr) { + continuationManager_->UnregisterAbilityTokenIfNeed(); + } else { + APP_LOGE("%{public}s continuationManager_ is nullptr.", __func__); + } + + if (abilityWindow_ != nullptr && abilityInfo_->type == AppExecFwk::AbilityType::PAGE) { + APP_LOGI("%{public}s begin abilityWindow_->OnPostAbilityStop.", __func__); + abilityWindow_->OnPostAbilityStop(); + APP_LOGI("%{public}s end abilityWindow_->OnPostAbilityStop.", __func__); + } + if (abilityLifecycleExecutor_ == nullptr) { + APP_LOGE("Ability::OnStop error. abilityLifecycleExecutor_ == nullptr."); + return; + } + abilityLifecycleExecutor_->DispatchLifecycleState(AbilityLifecycleExecutor::LifecycleState::INITIAL); + + if (lifecycle_ == nullptr) { + APP_LOGE("Ability::OnStop error. lifecycle_ == nullptr."); + return; + } + lifecycle_->DispatchLifecycle(LifeCycle::Event::ON_STOP); + APP_LOGI("%{public}s end.", __func__); +} + +/** + * @brief Called when this ability enters the STATE_ACTIVE state. + * + * The ability in the STATE_ACTIVE state is visible and has focus. + * You can override this function to implement your own processing logic. + * + * @param Want Indicates the {@link Want} structure containing activation information about the ability. + */ +void Ability::OnActive() +{ + APP_LOGI("%{public}s begin.", __func__); + if (abilityWindow_ != nullptr) { + APP_LOGI("%{public}s begin abilityWindow_->OnPostAbilityActive.", __func__); + abilityWindow_->OnPostAbilityActive(); + APP_LOGI("%{public}s end abilityWindow_->OnPostAbilityActive.", __func__); + } + bWindowFocus_ = true; + if (abilityLifecycleExecutor_ == nullptr) { + APP_LOGE("Ability::OnActive error. abilityLifecycleExecutor_ == nullptr."); + return; + } + abilityLifecycleExecutor_->DispatchLifecycleState(AbilityLifecycleExecutor::LifecycleState::ACTIVE); + + if (lifecycle_ == nullptr) { + APP_LOGE("Ability::OnActive error. lifecycle_ == nullptr."); + return; + } + lifecycle_->DispatchLifecycle(LifeCycle::Event::ON_ACTIVE); + APP_LOGI("%{public}s end.", __func__); +} + +/** + * @brief Called when this ability enters the STATE_INACTIVE state. + * + * STATE_INACTIVE is an instantaneous state. The ability in this state may be visible but does not have + * focus.You can override this function to implement your own processing logic. + */ +void Ability::OnInactive() +{ + APP_LOGI("%{public}s begin.", __func__); + if (abilityWindow_ != nullptr && abilityInfo_->type == AppExecFwk::AbilityType::PAGE) { + APP_LOGI("%{public}s begin abilityWindow_->OnPostAbilityInactive.", __func__); + abilityWindow_->OnPostAbilityInactive(); + APP_LOGI("%{public}s end abilityWindow_->OnPostAbilityInactive.", __func__); + } + bWindowFocus_ = false; + if (abilityLifecycleExecutor_ == nullptr) { + APP_LOGE("Ability::OnInactive error. abilityLifecycleExecutor_ == nullptr."); + return; + } + abilityLifecycleExecutor_->DispatchLifecycleState(AbilityLifecycleExecutor::LifecycleState::INACTIVE); + + if (lifecycle_ == nullptr) { + APP_LOGE("Ability::OnInactive error. lifecycle_ == nullptr."); + return; + } + lifecycle_->DispatchLifecycle(LifeCycle::Event::ON_INACTIVE); + APP_LOGI("%{public}s end.", __func__); +} + +/** + * @brief Called when this ability enters the STATE_FOREGROUND state. + * + * + * The ability in the STATE_FOREGROUND state is visible. + * You can override this function to implement your own processing logic. + */ +void Ability::OnForeground(const Want &want) +{ + APP_LOGI("%{public}s begin.", __func__); + if (abilityWindow_ != nullptr) { + APP_LOGI("%{public}s begin abilityWindow_->OnPostAbilityForeground.", __func__); + abilityWindow_->OnPostAbilityForeground(); + APP_LOGI("%{public}s end abilityWindow_->OnPostAbilityForeground.", __func__); + } + + if (abilityLifecycleExecutor_ == nullptr) { + APP_LOGE("Ability::OnForeground error. abilityLifecycleExecutor_ == nullptr."); + return; + } + abilityLifecycleExecutor_->DispatchLifecycleState(AbilityLifecycleExecutor::LifecycleState::INACTIVE); + + if (lifecycle_ == nullptr) { + APP_LOGE("Ability::OnForeground error. lifecycle_ == nullptr."); + return; + } + lifecycle_->DispatchLifecycle(LifeCycle::Event::ON_FOREGROUND, want); + APP_LOGI("%{public}s end.", __func__); +} + +/** + * @brief Called when this ability enters the STATE_BACKGROUND state. + * + * + * The ability in the STATE_BACKGROUND state is invisible. + * You can override this function to implement your own processing logic. + */ +void Ability::OnBackground() +{ + APP_LOGI("%{public}s begin.", __func__); + if (abilityWindow_ != nullptr && abilityInfo_->type == AppExecFwk::AbilityType::PAGE) { + APP_LOGI("%{public}s begin abilityWindow_->OnPostAbilityBackground.", __func__); + abilityWindow_->OnPostAbilityBackground(); + APP_LOGI("%{public}s end abilityWindow_->OnPostAbilityBackground.", __func__); + } + + if (abilityLifecycleExecutor_ == nullptr) { + APP_LOGE("Ability::OnBackground error. abilityLifecycleExecutor_ == nullptr."); + return; + } + abilityLifecycleExecutor_->DispatchLifecycleState(AbilityLifecycleExecutor::LifecycleState::BACKGROUND); + + if (lifecycle_ == nullptr) { + APP_LOGE("Ability::OnBackground error. lifecycle_ == nullptr."); + return; + } + lifecycle_->DispatchLifecycle(LifeCycle::Event::ON_BACKGROUND); + APP_LOGI("%{public}s end.", __func__); +} + +/** + * @brief Called when this Service ability is connected for the first time. + * + * You can override this function to implement your own processing logic. + * + * @param want Indicates the {@link Want} structure containing connection information about the Service ability. + * @return Returns a pointer to the sid of the connected Service ability. + */ +sptr Ability::OnConnect(const Want &want) +{ + APP_LOGI("%{public}s begin.", __func__); + if (abilityLifecycleExecutor_ == nullptr) { + APP_LOGE("Ability::OnConnect error. abilityLifecycleExecutor_ == nullptr."); + return nullptr; + } + abilityLifecycleExecutor_->DispatchLifecycleState(AbilityLifecycleExecutor::LifecycleState::ACTIVE); + + if (lifecycle_ == nullptr) { + APP_LOGE("Ability::OnConnect error. lifecycle_ == nullptr."); + return nullptr; + } + lifecycle_->DispatchLifecycle(LifeCycle::Event::ON_ACTIVE); + APP_LOGI("%{public}s end.", __func__); + return nullptr; +} + +/** + * @brief Called when all abilities connected to this Service ability are disconnected. + * + * You can override this function to implement your own processing logic. + * + */ +void Ability::OnDisconnect(const Want &want) +{} + +/** + * Start other ability for result. + * + * @param want information of other ability + * @param requestCode request code for abilityMS to return result + */ +void Ability::StartAbilityForResult(const Want &want, int requestCode) +{ + APP_LOGI("%{public}s begin.", __func__); + if (abilityInfo_ == nullptr) { + APP_LOGE("Ability::StartAbilityForResult abilityInfo_ == nullptr"); + return; + } + APP_LOGI("Ability::StartAbilityForResult called type = %{public}d", abilityInfo_->type); + if (abilityInfo_->type == AppExecFwk::AbilityType::PAGE) { + AbilityContext::StartAbility(want, requestCode); + } + APP_LOGI("%{public}s end.", __func__); +} + +/** + * Starts an ability with specific start settings and returns the execution result when the ability is destroyed. + * When the ability is destroyed, onAbilityResult(int,int,ohos.aafwk.content.Want) is called and the returned + * requestCode is transferred to the current method. The given requestCode is customized and cannot be a negative + * number. + * + * @param want Indicates the ability to start. + * @param requestCode Indicates the request code returned after the ability is started. You can define the request code + * to identify the results returned by abilities. The value ranges from 0 to 65535. + * @param abilityStartSetting Indicates the setting ability used to start. + */ +void Ability::StartAbilityForResult(const Want &want, int requestCode, AbilityStartSetting abilityStartSetting) +{ + APP_LOGI("%{public}s begin.", __func__); + if (abilityInfo_ == nullptr) { + APP_LOGE("Ability::StartAbilityForResult abilityInfo_ == nullptr"); + return; + } + APP_LOGI("Ability::StartAbilityForResult called type = %{public}d", abilityInfo_->type); + if (abilityInfo_->type == AppExecFwk::AbilityType::PAGE) { + AbilityContext::StartAbility(want, requestCode, abilityStartSetting); + } + APP_LOGI("%{public}s end.", __func__); +} + +/** + * Starts a new ability with specific start settings. + * A Page or Service ability uses this method to start a specific ability. + * The system locates the target ability from installed abilities based on + * the value of the intent parameter and then starts it. You can specify the + * ability to start using the intent parameter. + * + * @param want Indicates the ability to start. + * @param abilityStartSetting Indicates the setting ability used to start. + */ +void Ability::StartAbility(const Want &want, AbilityStartSetting abilityStartSetting) +{ + APP_LOGI("%{public}s beign.", __func__); + if (abilityInfo_ == nullptr) { + APP_LOGE("Ability::StartAbility abilityInfo_ == nullptr"); + return; + } + APP_LOGI("Ability::StartAbility called type = %{public}d", abilityInfo_->type); + if (abilityInfo_->type == AppExecFwk::AbilityType::PAGE || abilityInfo_->type == AppExecFwk::AbilityType::SERVICE) { + AbilityContext::StartAbility(want, -1, abilityStartSetting); + } + APP_LOGI("%{public}s end.", __func__); +} + +/** + * @brief Called when a key is pressed. When any component in the Ability gains focus, the key-down event for + * the component will be handled first. This callback will not be invoked if the callback triggered for the + * key-down event of the component returns true. The default implementation of this callback does nothing + * and returns false. + * + * @param keyCode Indicates the code of the key pressed. + * @param keyEvent Indicates the key-down event. + * + * @return Returns true if this event is handled and will not be passed further; returns false if this event + * is not handled and should be passed to other handlers. + */ +bool Ability::OnKeyDown(int keyCode, const KeyEvent &keyEvent) +{ + APP_LOGI("Ability::OnKeyDown called"); + APP_LOGI("Ability::OnKeyDown keyCode: %{public}d.", keyCode); + return false; +} + +/** + * @brief Called when a key is released. When any component in the Ability gains focus, the key-up event for + * the component will be handled first. This callback will not be invoked if the callback triggered for the + * key-up event of the component returns true. The default implementation of this callback does nothing and + * returns false. + * + * @param keyCode Indicates the code of the key released. + * @param keyEvent Indicates the key-up event. + * + * @return Returns true if this event is handled and will not be passed further; returns false if this event + * is not handled and should be passed to other handlers. + */ +bool Ability::OnKeyUp(int keyCode, const KeyEvent &keyEvent) +{ + APP_LOGI("Ability::OnKeyUp called"); + APP_LOGI("Ability::OnKeyUp keyCode: %{public}d.", keyCode); + switch (keyCode) { +#ifdef MMI_COMPILE + case OHOS::KeyEventEnum::KEY_BACK: +#else + case KeyEvent::CODE_BACK: +#endif + APP_LOGI("Ability::OnKey Back key pressed."); + OnBackPressed(); + return true; + default: + break; + } + return false; +} + +/** + * @brief Called when a touch event is dispatched to this ability. The default implementation of this callback + * does nothing and returns false. + * + * @param event Indicates information about the touch event. + * + * @return Returns true if the event is handled; returns false otherwise. + */ +bool Ability::OnTouchEvent(const TouchEvent &touchEvent) +{ + APP_LOGI("Ability::OnTouchEvent called"); + APP_LOGI("Ability::OnTouchEvent action: %{public}d phase: %{public}d", + const_cast(touchEvent).GetAction(), + const_cast(touchEvent).GetPhase()); + return false; +} + +/** + * @brief Inflates UI controls by using ComponentContainer. + * You can create a ComponentContainer instance that contains multiple components. + * + * @param componentContainer Indicates a set of customized components. + */ +void Ability::SetUIContent(const ComponentContainer &componentContainer) +{} + +/** + * @brief Inflates layout resources by using the layout resource ID. + * + * @param layoutRes Indicates the layout resource ID, which cannot be a negative number. + */ +void Ability::SetUIContent(int layoutRes) +{} + +/** + * @brief Inflates UI controls by using ComponentContainer. + * You can create a ComponentContainer instance that contains multiple components. + * + * @param componentContainer Indicates the component layout defined by the user. + * @param context Indicates the context to use. + * @param typeFlag Indicates the window type. + */ +void Ability::SetUIContent( + const ComponentContainer &componentContainer, std::shared_ptr &context, int typeFlag) +{} + +/** + * @brief Inflates layout resources by using the layout resource ID. + * + * @param layoutRes Indicates the layout resource ID, which cannot be a negative number. + * @param context Indicates the context to use. + * @param typeFlag Indicates the window type. + */ +void Ability::SetUIContent(int layoutRes, std::shared_ptr &context, int typeFlag) +{} + +/** + * @brief Inflates UI controls by using WindowConfig. + * + * @param config Indicates the window config defined by the user. + */ +void Ability::SetUIContent(const sptr &config) +{ + if (abilityWindow_ == nullptr) { + APP_LOGE("Ability::SetUIContent abilityWindow_ is nullptr"); + return; + } + + APP_LOGI("%{public}s beign abilityWindow_->SetWindowConfig.", __func__); + abilityWindow_->SetWindowConfig(config); + APP_LOGI("%{public}s end abilityWindow_->SetWindowConfig.", __func__); +} + +/** + * @brief Get the window belong to the ability. + * + * @return Returns a IWindowsManager object pointer. + */ +const sptr Ability::GetWindow() +{ + if (abilityWindow_ != nullptr) { + return abilityWindow_->GetWindow(); + } else { + APP_LOGI("%{public}s abilityWindow_ is nullptr.", __func__); + return nullptr; + } +} + +/** + * @brief Obtains the type of audio whose volume is adjusted by the volume button. + * + * @return Returns the AudioManager.AudioVolumeType. + */ +int Ability::GetVolumeTypeAdjustedByKey() +{ + return 0; +} + +/** + * @brief Checks whether the main window of this ability has window focus. + * + * @return Returns true if this ability currently has window focus; returns false otherwise. + */ +bool Ability::HasWindowFocus() +{ + if (abilityInfo_ == nullptr) { + APP_LOGI("Ability::HasWindowFocus abilityInfo_ == nullptr"); + return false; + } + + if (abilityInfo_->type == AppExecFwk::AbilityType::PAGE) { + return bWindowFocus_; + } + + return false; +} + +/** + * @brief Called when a key is lone pressed. + * + * @param keyCode Indicates the code of the key long pressed. + * @param keyEvent Indicates the key-long-press event. + * + * @return Returns true if this event is handled and will not be passed further; returns false if this event + * is not handled and should be passed to other handlers. + */ +bool Ability::OnKeyPressAndHold(int keyCode, const std::shared_ptr &keyEvent) +{ + return false; +} + +/** + * @brief Called back after permissions are requested by using + * AbilityContext.requestPermissionsFromUser(java.lang.String[],int). + * + * @param requestCode Indicates the request code passed to this method from + * AbilityContext.requestPermissionsFromUser(java.lang.String[],int). + * @param permissions Indicates the list of permissions requested by using + * AbilityContext.requestPermissionsFromUser(java.lang.String[],int). This parameter cannot be null. + * @param grantResults Indicates the granting results of the corresponding permissions requested using + * AbilityContext.requestPermissionsFromUser(java.lang.String[],int). The value 0 indicates that a + * permission is granted, and the value -1 indicates not. + * + */ +void Ability::OnRequestPermissionsFromUserResult( + int requestCode, const std::vector &permissions, const std::vector &grantResults) +{} + +/** + * @brief Called when this ability is about to leave the foreground and enter the background due to a user operation, + * for example, when the user touches the Home key. + * + */ +void Ability::OnLeaveForeground() +{} + +/** + * @brief Obtains the MIME type matching the data specified by the URI of the Data ability. This method should be + * implemented by a Data ability. Data abilities supports general data types, including text, HTML, and JPEG. + * + * @param uri Indicates the URI of the data. + * + * @return Returns the MIME type that matches the data specified by uri. + */ +std::string Ability::GetType(const Uri &uri) +{ + return ""; +} + +/** + * @brief Inserts a data record into the database. This method should be implemented by a Data ability. + * + * @param uri Indicates the position where the data is to insert. + * @param value Indicates the data to insert. + * + * @return Returns the index of the newly inserted data record. + */ +int Ability::Insert(const Uri &uri, const NativeRdb::ValuesBucket &value) +{ + return 0; +} + +/** + * @brief Called when the system configuration is updated. + * + * @param configuration Indicates the updated configuration information. + */ +void Ability::OnConfigurationUpdated(const Configuration &configuration) +{} + +/** + * @brief Called when the system configuration is updated. + * + * @param level Indicates the memory trim level, which shows the current memory usage status. + * + */ +void Ability::OnMemoryLevel(int level) +{} + +/** + * @brief This is like openFile, open a file that need to be able to return sub-sections of files,often assets + * inside of their .hap. + * + * @param uri Indicates the path of the file to open. + * @param mode Indicates the file open mode, which can be "r" for read-only access, "w" for write-only access + * (erasing whatever data is currently in the file), "wt" for write access that truncates any existing file, + * "wa" for write-only access to append to any existing data, "rw" for read and write access on any existing + * data, or "rwt" for read and write access that truncates any existing file. + * + * @return Returns the RawFileDescriptor object containing file descriptor. + */ +int Ability::OpenRawFile(const Uri &uri, const std::string &mode) +{ + return -1; +} + +/** + * @brief Updates one or more data records in the database. This method should be implemented by a Data ability. + * + * @param uri Indicates the database table storing the data to update. + * @param value Indicates the data to update. This parameter can be null. + * @param predicates Indicates filter criteria. If this parameter is null, all data records will be updated by default. + * + * @return Returns the number of data records updated. + */ +int Ability::Update( + const Uri &uri, const NativeRdb::ValuesBucket &value, const NativeRdb::DataAbilityPredicates &predicates) +{ + return 0; +} + +/** + * @brief get application witch the ability belong + * + * @return Returns the application ptr + */ +std::shared_ptr Ability::GetApplication() +{ + APP_LOGI("%{public}s begin.", __func__); + if (application_ == nullptr) { + APP_LOGE("Ability::GetApplication error. application_ == nullptr."); + return nullptr; + } + APP_LOGI("%{public}s end.", __func__); + return application_; +} + +/** + * @brief Obtains the class name in this ability name, without the prefixed bundle name. + * + * @return Returns the class name of this ability. + */ +std::string Ability::GetAbilityName() +{ + if (abilityInfo_ == nullptr) { + APP_LOGE("Ability::GetAbilityName abilityInfo_ is nullptr"); + return ""; + } + + return abilityInfo_->name; +} + +/** + * @brief OChecks whether the current ability is being destroyed. + * An ability is being destroyed if you called terminateAbility() on it or someone else requested to destroy it. + * + * @return Returns true if the current ability is being destroyed; returns false otherwise. + */ +bool Ability::IsTerminating() +{ + return false; +} + +/** + * @brief Called when startAbilityForResult(ohos.aafwk.content.Want,int) is called to start an ability and the result is + * returned. This method is called only on Page abilities. You can start a new ability to perform some calculations and + * use setResult (int,ohos.aafwk.content.Want) to return the calculation result. Then the system calls back the current + * method to use the returned data to execute its own logic. + * + * @param requestCode Indicates the request code returned after the ability is started. You can define the request code + * to identify the results returned by abilities. The value ranges from 0 to 65535. + * @param resultCode Indicates the result code returned after the ability is started. You can define the result code to + * identify an error. + * @param resultData Indicates the data returned after the ability is started. You can define the data returned. The + * value can be null. + * + */ +void Ability::OnAbilityResult(int requestCode, int resultCode, const Want &want) +{} + +/** + * @brief Called back when the Back key is pressed. + * The default implementation destroys the ability. You can override this method. + * + */ +void Ability::OnBackPressed() +{ + APP_LOGI("%{public}s begin.", __func__); + if (abilityInfo_ == nullptr) { + APP_LOGE("Ability::OnBackPressed abilityInfo_ is nullptr"); + return; + } + + if (abilityInfo_->isLauncherAbility == false) { + APP_LOGI("Ability::OnBackPressed the ability is not Launcher"); + TerminateAbility(); + } + APP_LOGI("%{public}s end.", __func__); +} + +/** + * @brief Called when the launch mode of an ability is set to singleInstance. This happens when you re-launch an + * ability that has been at the top of the ability stack. + * + * @param want Indicates the new Want containing information about the ability. + */ +void Ability::OnNewWant(const Want &want) +{ + APP_LOGI("Ability::OnNewWant called"); +} + +/** + * @brief Restores data and states of an ability when it is restored by the system. This method should be implemented by + * a Page ability. This method is called if an ability was destroyed at a certain time due to resource reclaim or was + * unexpectedly destroyed and the onSaveAbilityState(ohos.utils.PacMap) method was called to save its user data and + * states. Generally, this method is called after the onStart(ohos.aafwk.content.Want) method. + * + * @param inState Indicates the PacMap object used for storing data and states. This parameter can not be null. + * + */ +void Ability::OnRestoreAbilityState(const PacMap &inState) +{ + APP_LOGI("Ability::OnRestoreAbilityState called"); +} + +/** + * @brief Saves temporary data and states of this ability. This method should be implemented by a Page ability. + * This method is called when the system determines that the ability may be destroyed in an unexpected situation, for + * example, when the screen orientation changes or the user touches the Home key. Generally, this method is used only to + * save temporary states. + * + * @param outState Indicates the PacMap object used for storing user data and states. This parameter cannot be null. + * + */ +void Ability::OnSaveAbilityState(PacMap &outState) +{ + APP_LOGI("Ability::OnSaveAbilityState called"); +} + +/** + * @brief Called every time a key, touch, or trackball event is dispatched to this ability. + * You can override this callback method if you want to know that the user has interacted with + * the device in a certain way while this ability is running. This method, together with onLeaveForeground(), + * is designed to help abilities intelligently manage status bar notifications. Specifically, they help + * abilities determine when to cancel a notification. + * + */ +void Ability::OnEventDispatch() +{} + +/** + * @brief Sets the want object that can be obtained by calling getWant(). + * @param Want information of other ability + */ +void Ability::SetWant(const AAFwk::Want &want) +{ + setWant_ = std::make_shared(want); +} + +/** + * @brief Obtains the Want object that starts this ability. + * + * @return Returns the Want object that starts this ability. + */ +std::shared_ptr Ability::GetWant() +{ + return setWant_; +} + +/** + * @brief Sets the result code and data to be returned by this Page ability to the caller. + * When a Page ability is destroyed, the caller overrides the AbilitySlice#onAbilityResult(int, int, Want) method to + * receive the result set in the current method. This method can be called only after the ability has been initialized. + * + * @param resultCode Indicates the result code returned after the ability is destroyed. You can define the result code + * to identify an error. + * @param resultData Indicates the data returned after the ability is destroyed. You can define the data returned. This + * parameter can be null. + */ +void Ability::SetResult(int resultCode, const Want &resultData) +{ + APP_LOGI("%{public}s begin.", __func__); + if (abilityInfo_ == nullptr) { + APP_LOGE("Ability::SetResult abilityInfo_ == nullptr"); + return; + } + APP_LOGI("Ability::SetResult called type = %{public}d", abilityInfo_->type); + if (abilityInfo_->type == AppExecFwk::AbilityType::PAGE) { + AbilityContext::resultWant_ = resultData; + AbilityContext::resultCode_ = resultCode; + } + APP_LOGI("%{public}s end.", __func__); +} + +/** + * @brief Sets the type of audio whose volume will be adjusted by the volume button. + * + * @param volumeType Indicates the AudioManager.AudioVolumeType to set. + */ +void Ability::SetVolumeTypeAdjustedByKey(int volumeType) +{} + +/** + * @brief Called back when Service is started. + * This method can be called only by Service. You can use the StartAbility(ohos.aafwk.content.Want) method to start + * Service. Then the system calls back the current method to use the transferred want parameter to execute its own + * logic. + * + * @param want Indicates the want of Service to start. + * @param restart Indicates the startup mode. The value true indicates that Service is restarted after being destroyed, + * and the value false indicates a normal startup. + * @param startId Indicates the number of times the Service ability has been started. The startId is incremented by 1 + * every time the ability is started. For example, if the ability has been started for six times, the value of startId + * is 6. + */ +void Ability::OnCommand(const AAFwk::Want &want, bool restart, int startId) +{ + APP_LOGI("%{public}s begin restart=%{public}s,startId=%{public}d.", __func__, restart ? "true" : "false", startId); + if (abilityLifecycleExecutor_ == nullptr) { + APP_LOGE("Ability::OnCommand error. abilityLifecycleExecutor_ == nullptr."); + return; + } + abilityLifecycleExecutor_->DispatchLifecycleState(AbilityLifecycleExecutor::LifecycleState::ACTIVE); + + if (lifecycle_ == nullptr) { + APP_LOGE("Ability::OnCommand error. lifecycle_ == nullptr."); + return; + } + lifecycle_->DispatchLifecycle(LifeCycle::Event::ON_ACTIVE); + APP_LOGI("%{public}s end.", __func__); +} + +/** + * @brief dump ability info + * + * @param extra dump ability info + */ +void Ability::Dump(const std::string &extra) +{ + APP_LOGI("Ability::Dump called"); + // abilityInfo + APP_LOGI("==============AbilityInfo=============="); + if (abilityInfo_ != nullptr) { + APP_LOGI("abilityInfo: package: %{public}s", abilityInfo_->package.c_str()); + APP_LOGI("abilityInfo: name: %{public}s", abilityInfo_->name.c_str()); + APP_LOGI("abilityInfo: label: %{public}s", abilityInfo_->label.c_str()); + APP_LOGI("abilityInfo: description: %{public}s", abilityInfo_->description.c_str()); + APP_LOGI("abilityInfo: iconPath: %{public}s", abilityInfo_->iconPath.c_str()); + APP_LOGI("abilityInfo: visible: %{public}d", abilityInfo_->visible); + APP_LOGI("abilityInfo: kind: %{public}s", abilityInfo_->kind.c_str()); + APP_LOGI("abilityInfo: type: %{public}d", abilityInfo_->type); + APP_LOGI("abilityInfo: orientation: %{public}d", abilityInfo_->orientation); + APP_LOGI("abilityInfo: launchMode: %{public}d", abilityInfo_->launchMode); + for (auto permission : abilityInfo_->permissions) { + APP_LOGI("abilityInfo: permission: %{public}s", permission.c_str()); + } + APP_LOGI("abilityInfo: bundleName: %{public}s", abilityInfo_->bundleName.c_str()); + APP_LOGI("abilityInfo: applicationName: %{public}s", abilityInfo_->applicationName.c_str()); + } else { + APP_LOGI("abilityInfo is nullptr"); + } + + // lifecycle_Event + APP_LOGI("==============lifecycle_Event=============="); + if (lifecycle_ != nullptr) { + APP_LOGI("lifecycle_Event: launchMode: %{public}d", lifecycle_->GetLifecycleState()); + } else { + APP_LOGI("lifecycle is nullptr"); + } + + // lifecycle_State + APP_LOGI("==============lifecycle_State=============="); + if (abilityLifecycleExecutor_ != nullptr) { + APP_LOGI("lifecycle_State: launchMode: %{public}d", abilityLifecycleExecutor_->GetState()); + } else { + APP_LOGI("abilityLifecycleExecutor is nullptr"); + } + + // applicationInfo + APP_LOGI("==============applicationInfo=============="); + std::shared_ptr ApplicationInfoPtr = GetApplicationInfo(); + if (ApplicationInfoPtr != nullptr) { + APP_LOGI("applicationInfo: name: %{public}s", ApplicationInfoPtr->name.c_str()); + APP_LOGI("applicationInfo: bundleName: %{public}s", ApplicationInfoPtr->bundleName.c_str()); + } else { + APP_LOGI("ApplicationInfoPtr is nullptr"); + } +} + +/** + * @brief Keeps this Service ability in the background and displays a notification bar. + * To use this method, you need to request the ohos.permission.KEEP_BACKGROUND_RUNNING permission from the system. + * The ohos.permission.KEEP_BACKGROUND_RUNNING permission is of the normal level. + * This method can be called only by Service abilities after the onStart(ohos.aafwk.content.Want) method is called. + * + * @param id Identifies the notification bar information. + * @param notificationRequest Indicates the NotificationRequest instance containing information for displaying a + * notification bar. + */ +void Ability::KeepBackgroundRunning(int id, const NotificationRequest ¬ificationRequest) +{} + +/** + * @brief Cancels background running of this ability to free up system memory. + * This method can be called only by Service abilities when the onStop() method is called. + * + */ +void Ability::CancelBackgroundRunning() +{} + +/** + * @brief Converts the given uri that refer to the Data ability into a normalized URI. A normalized URI can be used + * across devices, persisted, backed up, and restored. It can refer to the same item in the Data ability even if the + * context has changed. If you implement URI normalization for a Data ability, you must also implement + * denormalizeUri(ohos.utils.net.Uri) to enable URI denormalization. After this feature is enabled, URIs passed to any + * method that is called on the Data ability must require normalization verification and denormalization. The default + * implementation of this method returns null, indicating that this Data ability does not support URI normalization. + * + * @param uri Indicates the Uri object to normalize. + * + * @return Returns the normalized Uri object if the Data ability supports URI normalization; returns null otherwise. + */ +Uri Ability::NormalizeUri(const Uri &uri) +{ + return uri; +} + +/** + * @brief Deletes one or more data records. This method should be implemented by a Data ability. + * + * @param uri Indicates the database table storing the data to delete. + * @param predicates Indicates filter criteria. If this parameter is null, all data records will be deleted by default. + * + * @return Returns the number of data records deleted. + */ +int Ability::Delete(const Uri &uri, const NativeRdb::DataAbilityPredicates &predicates) +{ + return 0; +} + +/** + * @brief Obtains the MIME type of files. This method should be implemented by a Data ability. + * + * @param uri Indicates the path of the files to obtain. + * @param mimeTypeFilter Indicates the MIME type of the files to obtain. This parameter cannot be set to null. + * 1. * / *: Obtains all types supported by a Data ability. + * 2. image/ *: Obtains files whose main type is image of any subtype. + * 3. * /jpg: Obtains files whose subtype is JPG of any main type. + * + * @return Returns the MIME type of the matched files; returns null if there is no type that matches the Data ability. + */ +std::vector Ability::GetFileTypes(const Uri &uri, const std::string &mimeTypeFilter) +{ + return types_; +} + +/** + * @brief Opens a file. This method should be implemented by a Data ability. + * + * @param uri Indicates the path of the file to open. + * @param mode Indicates the open mode, which can be "r" for read-only access, "w" for write-only access + * (erasing whatever data is currently in the file), "wt" for write access that truncates any existing file, + * "wa" for write-only access to append to any existing data, "rw" for read and write access on any existing data, + * or "rwt" for read and write access that truncates any existing file. + * + * @return Returns the FileDescriptor object of the file descriptor. + */ +int Ability::OpenFile(const Uri &uri, const std::string &mode) +{ + return -1; +} + +/** + * @brief Queries one or more data records in the database. This method should be implemented by a Data ability. + * + * @param uri Indicates the database table storing the data to query. + * @param columns Indicates the columns to be queried, in array, for example, {"name","age"}. You should define the + * processing logic when this parameter is null. + * @param predicates Indicates filter criteria. If this parameter is null, all data records will be queried by default. + * + * @return Returns the queried data. + */ +std::shared_ptr Ability::Query( + const Uri &uri, const std::vector &columns, const NativeRdb::DataAbilityPredicates &predicates) +{ + return nullptr; +} + +/** + * @brief Reloads data in the database. + * The default implementation of this method returns false. You must implement this method in the child class + * of your Data Ability if you want to use it. + * + * @param uri Indicates the position where the data is to reload. + * @param extras Indicates the additional parameters contained in the PacMap object to be passed in this call. + * + * @return Returns true if the data is successfully reloaded; returns false otherwise. + */ +bool Ability::Reload(const Uri &uri, const PacMap &extras) +{ + return false; +} + +/** + * @brief Inserts multiple data records into the database. + * + * @param uri Indicates the path of the data to operate. + * @param values Indicates the data records to insert. + * + * @return Returns the number of data records inserted. + */ +int Ability::BatchInsert(const Uri &uri, const std::vector &values) +{ + APP_LOGI("%{public}s begin.", __func__); + int amount = 0; + for (auto it = values.begin(); it != values.end(); it++) { + if (Insert(uri, *it) >= 0) { + amount++; + } + } + APP_LOGI("%{public}s end, amount=%{public}d", __func__, amount); + return amount; +} + +/** + * @brief Migrates this ability to the given device on the same distributed network in a reversible way that allows this + * ability to be migrated back to the local device through reverseContinueAbility(). The ability to migrate and its + * ability slices must implement the IAbilityContinuation interface. Otherwise, an exception is thrown, indicating that + * the ability does not support migration. + * + * @param deviceId Indicates the ID of the target device where this ability will be migrated to. If this parameter is + * null, this method has the same effect as ContinueAbilityReversibly(). + * + */ +void Ability::ContinueAbilityReversibly(const std::string &deviceId) +{ + if (!VerifySupportForContinuation()) { + APP_LOGE("Ability::ContinueAbilityReversibly(deviceId) failed. VerifySupportForContinuation faled"); + return; + } + continuationManager_->ContinueAbility(true, deviceId); +} + +/** + * @brief public final String getOriginalDeviceId​() throws UnsupportedOperationException + * Obtains the ID of the source device from which this ability is migrated. + * + * @return Returns the source device ID. + */ +std::string Ability::GetOriginalDeviceId() +{ + return ""; +} + +/** + * @brief Obtains the migration state of this ability. + * @return Returns the migration state. + * + * @return Returns the source device ID. + */ +ContinuationState Ability::GetContinuationState() +{ + if (!VerifySupportForContinuation()) { + APP_LOGE("Ability::GetContinuationState failed. VerifySupportForContinuation faled"); + return ContinuationState::LOCAL_RUNNING; + } + return continuationManager_->GetContinuationState(); +} + +/** + * @brief Obtains the singleton AbilityPackage object to which this ability belongs. + * + * @return Returns the singleton AbilityPackage object to which this ability belongs. + */ +std::shared_ptr Ability::GetAbilityPackage() +{ + return nullptr; +} + +/** + * @brief Converts the given normalized uri generated by normalizeUri(ohos.utils.net.Uri) into a denormalized one. + * The default implementation of this method returns the original URI passed to it. + * + * @param uri uri Indicates the Uri object to denormalize. + * + * @return Returns the denormalized Uri object if the denormalization is successful; returns the original Uri passed to + * this method if there is nothing to do; returns null if the data identified by the original Uri cannot be found in the + * current environment. + */ +Uri Ability::DenormalizeUri(const Uri &uri) +{ + return uri; +} + +/** + * @brief Obtains the Lifecycle object of the current ability. + * + * @return Returns the Lifecycle object. + */ +std::shared_ptr Ability::GetLifecycle() +{ + APP_LOGI("Ability::GetLifecycle called"); + return lifecycle_; +} + +/** + * @brief Obtains the lifecycle state of this ability. + * + * @return Returns the lifecycle state of this ability. + */ +AbilityLifecycleExecutor::LifecycleState Ability::GetState() +{ + APP_LOGI("Ability::GetState called"); + + if (abilityLifecycleExecutor_ == nullptr) { + APP_LOGE("Ability::GetState error. abilityLifecycleExecutor_ == nullptr."); + return AbilityLifecycleExecutor::LifecycleState::UNINITIALIZED; + } + + return (AbilityLifecycleExecutor::LifecycleState)abilityLifecycleExecutor_->GetState(); +} + +/** + * @brief A Page or Service ability uses this method to start a specific ability. The system locates the target ability + * from installed abilities based on the value of the intent parameter and then starts it. You can specify the ability + * to start using the intent parameter. + * + * @param intent Indicates the ability to start. + */ +void Ability::StartAbility(const Want &want) +{ + APP_LOGI("%{public}s begin.", __func__); + AbilityContext::StartAbility(want, -1); + APP_LOGI("%{public}s end.", __func__); +} + +/** + * @brief Destroys this Page or Service ability. + * After a Page or Service ability performs all operations, it can use this method to destroy itself + * to free up memory. This method can be called only after the ability is initialized. + */ +void Ability::TerminateAbility() +{ + APP_LOGI("%{public}s begin.", __func__); + AbilityContext::TerminateAbility(); + APP_LOGI("%{public}s end.", __func__); +} + +/** + * @brief Destroys ability. + * + * @param want Indicates the want containing information about TerminateAbility + * + * @return Returns the result of TerminateAbility + */ +int Ability::TerminateAbility(Want &want) +{ + return -1; +} + +/** + * @brief Sets the main route for this ability. + * + * The main route, also called main entry, refers to the default AbilitySlice to present for this ability. + * This function should be called only on Feature Abilities. If this function is not called in the + * {@link OnStart(const Want &want)} function for a Feature Ability, the Feature Ability will fail to start. + * + * @param entry Indicates the main entry, which is the class name of the AbilitySlice instance to start. + * + * @return Returns the result of SetMainRouter + */ +void Ability::SetMainRoute(const std::string &entry) +{} + +/** + * @brief By binding an action, you can set different action parameters in Intent to present different initial pages. + * You must register actions in the profile file. + * + * @param action Indicates the action to bind. + * + * @param entry Indicates the entry, which is the fully qualified name of your AbilitySlice class. + * + * @return Returns the result of AddActionRoute + */ +void Ability::AddActionRoute(const std::string &action, const std::string &entry) +{} + +/** + * @brief Sets the background color of the window in RGB color mode. + * + * @param red The value ranges from 0 to 255. + * + * @param green The value ranges from 0 to 255. + * + * @param blue The value ranges from 0 to 255. + * + * @return Returns the result of SetWindowBackgroundColor + */ +int Ability::SetWindowBackgroundColor(int red, int green, int blue) +{ + return -1; +} + +/** + * @brief Connects the current ability to an ability using the AbilityInfo.AbilityType.SERVICE template. + * + * @param want Indicates the want containing information about the ability to connect + * + * @param conn Indicates the callback object when the target ability is connected. + * + * @return True means success and false means failure + */ +bool Ability::ConnectAbility(const Want &want, const sptr &conn) +{ + return AbilityContext::ConnectAbility(want, conn); +} + +/** + * @brief Disconnects the current ability from an ability + * + * @param conn Indicates the IAbilityConnection callback object passed by connectAbility after the connection + * is set up. The IAbilityConnection object uniquely identifies a connection between two abilities. + */ +void Ability::DisconnectAbility(const sptr &conn) +{ + return AbilityContext::DisconnectAbility(conn); +} + +/** + * @brief Destroys another ability that uses the AbilityInfo.AbilityType.SERVICE template. + * The current ability using either the AbilityInfo.AbilityType.SERVICE or AbilityInfo.AbilityType.PAGE + * template can call this method to destroy another ability that uses the AbilityInfo.AbilityType.SERVICE + * template. The current ability itself can be destroyed by calling the terminateAbility() method. + * + * @param want Indicates the Want containing information about the ability to destroy. + * + * @return Returns true if the ability is destroyed successfully; returns false otherwise. + */ +bool Ability::StopAbility(const AAFwk::Want &want) +{ + return AbilityContext::StopAbility(want); +} + +/** + * @brief Posts a scheduled Runnable task to a new non-UI thread. + * The task posted via this method will be executed in a new thread, which allows you to perform certain time-consuming + * operations. To use this method, you must also override the supportHighPerformanceUI() method. + * + * @param task Indicates the Runnable task to post. + * + * @param delayTime Indicates the number of milliseconds after which the task will be executed. + * + * @return - + */ +void Ability::PostTask(std::function task, long delayTime) +{ + APP_LOGI("%{public}s begin.", __func__); + TaskHandlerClient::GetInstance()->PostTask(task, delayTime); + APP_LOGI("%{public}s end.", __func__); +} + +/** + * @brief You can use the IContinuationRegisterManager object to interact with the Device+ control center, + * including registering and unregistering the ability to migrate, updating the device connection state, and + * showing the list of devices that can be selected for ability migration. + * + * @return Returns true if the migration request is successful; returns false otherwise. + */ +std::weak_ptr Ability::GetContinuationRegisterManager() +{ + if (abilityInfo_ != nullptr) { + if ((abilityInfo_->type == AbilityType::PAGE) && (continuationRegisterManager_ == nullptr)) { + std::weak_ptr context = shared_from_this(); + std::shared_ptr continuationRegisterManagerProxy = + std::make_shared(context); + continuationRegisterManager_ = std::make_shared(); + continuationRegisterManager_->Init(continuationRegisterManagerProxy); + } + } + std::weak_ptr continuationRegisterManager = + std::weak_ptr(continuationRegisterManager_); + return continuationRegisterManager; +} + +/** + * @brief Migrates this ability to the given device on the same distributed network. The ability to migrate and its + * ability slices must implement the IAbilityContinuation interface. + * + * @param deviceId Indicates the ID of the target device where this ability will be migrated to. If this parameter + * is null, this method has the same effect as continueAbility(). + * + */ +void Ability::ContinueAbility(const std::string &deviceId) +{ + if (deviceId.empty()) { + APP_LOGE("Ability::ContinueAbility(deviceId) failed. deviceId is empty"); + return; + } + + if (!VerifySupportForContinuation()) { + APP_LOGE("Ability::ContinueAbility(deviceId) failed. VerifySupportForContinuation faled"); + return; + } + continuationManager_->ContinueAbility(false, deviceId); +} + +/** + * @brief Callback function to ask the user whether to start the migration . + * + * @return If the user allows migration, it returns true; otherwise, it returns false. + */ +bool Ability::OnStartContinuation() +{ + return false; +} + +/** + * @brief Save user data of local Ability generated at runtime. + * + * @param saveData Indicates the user data to be saved. + * @return If the data is saved successfully, it returns true; otherwise, it returns false. + */ +bool Ability::OnSaveData(WantParams &saveData) +{ + return false; +} + +/** + * @brief After creating the Ability on the remote device, + * immediately restore the user data saved during the migration of the Ability on the remote device. + * @param restoreData Indicates the user data to be restored. + * @return If the data is restored successfully, it returns true; otherwise, it returns false . + */ +bool Ability::OnRestoreData(WantParams &restoreData) +{ + return false; +} + +/** + * @brief This function can be used to implement the processing logic after the migration is completed. + * + * @param result Migration result code. 0 means the migration was successful, -1 means the migration failed. + * @return None. + */ +void Ability::OnCompleteContinuation(int result) +{} + +/** + * @brief Used to notify the local Ability that the remote Ability has been destroyed. + * + * @return None. + */ +void Ability::OnRemoteTerminated() +{} +bool Ability::VerifySupportForContinuation() +{ + if (continuationManager_ == nullptr) { + APP_LOGE("Ability::VerifySupportForContinuation failed. continuationManager_ is nullptr"); + return false; + } + return true; +} + +void Ability::HandleCreateAsContinuation(const Want &want) +{ + if (!IsFlagExists(Want::FLAG_ABILITY_CONTINUATION, want.GetFlags())) { + APP_LOGI("Ability::HandleCreateAsContinuation return. This not continuated ability"); + return; + } + + // check whether it needs reversible + bool reversible = false; + reversible = IsFlagExists(Want::FLAG_ABILITY_CONTINUATION_REVERSIBLE, want.GetFlags()); + if (!VerifySupportForContinuation()) { + APP_LOGE("Ability::HandleCreateAsContinuation failed. VerifySupportForContinuation failed"); + return; + } + bool success = continuationManager_->RestoreData( + want.GetParams(), reversible, want.GetStringParam(ContinuationHandler::ORIGINAL_DEVICE_ID)); + + if (success && reversible) { + // Register this ability to receive reverse continuation callback. + std::weak_ptr ReplicaHandler = continuationHandler_; + reverseContinuationSchedulerReplica_ = sptr( + new (std::nothrow) ReverseContinuationSchedulerReplica(handler_, ReplicaHandler)); + + if (reverseContinuationSchedulerReplica_ == nullptr) { + APP_LOGE("Ability::HandleCreateAsContinuation failed, create reverseContinuationSchedulerReplica failed"); + return; + } + } + + int sessionId = want.GetIntParam(DMS_SESSION_ID, DEFAULT_DMS_SESSION_ID); + std::string originDeviceId = want.GetStringParam(DMS_ORIGIN_DEVICE_ID); + APP_LOGE("Ability::HandleCreateAsContinuationoriginDeviceId: %{public}s", originDeviceId.c_str()); + continuationManager_->NotifyCompleteContinuation( + originDeviceId, sessionId, success, reverseContinuationSchedulerReplica_); +} +bool Ability::IsFlagExists(unsigned int flag, unsigned int flagSet) +{ + return (flag & flagSet) == flag; +} + +/** + * @brief Called when this ability gains or loses window focus. + * + * @param hasFocus Specifies whether this ability has focus. + */ +void Ability::OnWindowFocusChanged(bool hasFocus) +{} + +/** + * @brief Called when this ability is moved to or removed from the top of the stack. + * + * @param topActive Specifies whether this ability is moved to or removed from the top of the stack. The value true + * indicates that it is moved to the top, and false indicates that it is removed from the top of the stack. + */ +void Ability::OnTopActiveAbilityChanged(bool topActive) +{} + +/** + * @brief Called to set caller information for the application. The default implementation returns null. + * + * @return Returns the caller information. + */ +Uri Ability::OnSetCaller() +{ + return Uri(""); +} + +/** + * @brief Call this when your ability should be closed and the mission should be completely removed as a part of + * finishing the root ability of the mission. + */ +void Ability::TerminateAndRemoveMission() +{ + APP_LOGI("%{public}s begin.", __func__); + auto state = GetState(); + if (state > AbilityLifecycleExecutor::LifecycleState::INITIAL) { + APP_LOGI("Ability::TerminateAndRemoveMission the GetState retval is %d", state); + return; + } + AbilityContext::TerminateAndRemoveMission(); + APP_LOGI("%{public}s end.", __func__); +} + +/** + * @brief Create a PostEvent timeout task. The default delay is 5000ms + * + * @return Return a smart pointer to a timeout object + */ +std::shared_ptr Ability::CreatePostEventTimeouter(std::string taskstr) +{ + return std::make_shared(taskstr, handler_); +} + +/** + * Releases an obtained form by its ID. + * + *

After this method is called, the form won't be available for use by the application, but the Form Manager + * Service still keeps the cache information about the form, so that the application can quickly obtain it based on + * the {@code formId}.

+ *

Permission: {@link ohos.security.SystemPermission#REQUIRE_FORM}

+ * + * @param formId Indicates the form ID. + * @return Returns {@code true} if the form is successfully released; returns {@code false} otherwise. + * + *
    + *
  • The passed {@code formId} is invalid. Its value must be larger than 0.
  • + *
  • The specified form has not been added by the application.
  • + *
  • An error occurred when connecting to the Form Manager Service.
  • + *
  • The application is not granted with the {@link ohos.security.SystemPermission#REQUIRE_FORM} permission.
  • + *
  • The form has been obtained by another application and cannot be released by the current application.
  • + *
  • The form is being restored.
  • + *
+ */ +bool Ability::ReleaseForm(const int64_t formId) +{ + APP_LOGI("%{public}s called.", __func__); + // release form by formId and do not release cache + return ReleaseForm(formId, false); +} + +/** + * Releases an obtained form by its ID. + * + *

After this method is called, the form won't be available for use by the application, if isReleaseCache is + * false, this method is same as {@link #releaseForm(int)}, otherwise the Form Manager Service still store this + * form in the cache.

+ *

Permission: {@link ohos.security.SystemPermission#REQUIRE_FORM}

+ * + * @param formId Indicates the form ID. + * @param isReleaseCache Indicates whether to clear cache in service. + * @return Returns {@code true} if the form is successfully released; returns {@code false} otherwise. + * + *
    + *
  • The passed {@code formId} is invalid. Its value must be larger than 0.
  • + *
  • The specified form has not been added by the application.
  • + *
  • An error occurred when connecting to the Form Manager Service.
  • + *
  • The application is not granted with the {@link ohos.security.SystemPermission#REQUIRE_FORM} permission.
  • + *
  • The form has been obtained by another application and cannot be released by the current application.
  • + *
  • The form is being restored.
  • + *
+ */ +bool Ability::ReleaseForm(const int64_t formId, const bool isReleaseCache) +{ + APP_LOGI("%{public}s called.", __func__); + // release form with formId and specifies whether to release the cache + return DeleteForm(formId, isReleaseCache ? RELEASE_CACHED_FORM : RELEASE_FORM); +} + +/** + * Deletes an obtained form by its ID. + * + *

After this method is called, the form won't be available for use by the application and the Form Manager + * Service no longer keeps the cache information about the form.

+ *

Permission: {@link ohos.security.SystemPermission#REQUIRE_FORM}

+ * + * @param formId Indicates the form ID. + * @return Returns {@code true} if the form is successfully deleted; returns {@code false} otherwise. + * + *
    + *
  • The passed {@code formId} is invalid. Its value must be larger than 0.
  • + *
  • The specified form has not been added by the application.
  • + *
  • An error occurred when connecting to the Form Manager Service.
  • + *
  • The application is not granted with the {@link ohos.security.SystemPermission#REQUIRE_FORM} permission.
  • + *
  • The form has been obtained by another application and cannot be deleted by the current application.
  • + *
  • The form is being restored.
  • + *
+ */ +bool Ability::DeleteForm(const int64_t formId) +{ + APP_LOGI("%{public}s called.", __func__); + // delete form with formId + return DeleteForm(formId, DELETE_FORM); +} + +/** + * @brief Cast temp form with formId. + * + * @param formId Indicates the form's ID. + * + * @return Returns {@code true} if the form is successfully casted; returns {@code false} otherwise. + */ +bool Ability::CastTempForm(const int64_t formId) +{ + APP_LOGI("%{public}s start", __func__); + if (formId <= 0) { + APP_LOGE("%{public}s error, passing in form id can't be negative.", __func__); + return false; + } + + APP_LOGI("%{public}s, castTempForm begin of temp form %{public}" PRId64, __func__, formId); + bool result = FormMgr::GetInstance().CastTempForm(formId, FormHostClient::GetInstance()); + + if (!result) { + APP_LOGE("%{public}s error, some internal server occurs, error code is %{public}d.", __func__, result); + return false; + } + + userReqParams_[formId].SetParam(Constants::PARAM_FORM_TEMPORARY_KEY, false); + + APP_LOGI("%{public}s end", __func__); + return true; +} + +/** + * @brief Obtains a specified form that matches the application bundle name, module name, form name, and + * other related information specified in the passed {@code Want}. + * + *

This method is asynchronous. After the {@link FormJsInfo} instance is obtained. + * + * @param formId Indicates the form ID. + * @param want Indicates the detailed information about the form to be obtained, including the bundle name, + * module name, ability name, form name, form id, tempForm flag, form dimension, and form customize data. + * @param callback Indicates the callback to be invoked whenever the {@link FormJsInfo} instance is obtained. + * @return Returns {@code true} if the request is successfully initiated; returns {@code false} otherwise. + */ +bool Ability::AcquireForm(const int64_t formId, const Want &want, const std::shared_ptr callback) +{ + APP_LOGI("%{public}s called.", __func__); + struct timespec ts; + clock_gettime(CLOCK_REALTIME, &ts); + long currentTime = ts.tv_sec * SEC_TO_MILLISEC + ts.tv_nsec / MILLISEC_TO_NANOSEC; + APP_LOGI("%{public}s begin, current time: %{public}ld", __func__, currentTime); + + // check fms recover status + if (FormMgr::GetRecoverStatus() == Constants::IN_RECOVERING) { + APP_LOGE("%{public}s error, form is in recover status, can't do action on form.", __func__); + return false; + } + + // check form id + APP_LOGD("%{public}s, param of formId %{public}" PRId64 ".", __func__, formId); + if (formId < 0) { + APP_LOGE("%{public}s error, form id should not be negative.", __func__); + return false; + } + + // check param of want + if (!CheckWantValid(formId, want)) { + APP_LOGE("%{public}s error, failed to check param of want.", __func__); + return false; + }; + + ElementName elementName = want.GetElement(); + std::string bundleName = elementName.GetBundleName(); + std::string abilityName = elementName.GetAbilityName(); + APP_LOGI("%{public}s, begin to acquire form, bundleName is %{public}s, abilityName is %{public}s, formId is " + "%{public}" PRId64 ".", + __func__, + bundleName.c_str(), + abilityName.c_str(), + formId); + + // hostClient init + sptr formHostClient = FormHostClient::GetInstance(); + if (formHostClient == nullptr) { + APP_LOGE("%{public}s error, formHostClient == nullptr.", __func__); + return false; + } + + // acquire form request to fms + FormJsInfo formJsInfo; + if (FormMgr::GetInstance().AddForm(formId, want, formHostClient, formJsInfo) != ERR_OK) { + APP_LOGE("%{public}s error, acquire form for fms failed.", __func__); + return false; + } + APP_LOGI("%{public}s, end to acquire form, the formId returned from the fms is %{public}" PRId64 ".", + __func__, + formJsInfo.formId); + + // check for form presence in hostForms + if (formHostClient->ContainsForm(formJsInfo.formId)) { + APP_LOGE("%{public}s error, form has already acquired, do not support acquire twice.", __func__); + return false; + } + + // add ability of form to hostForms + std::shared_ptr thisAbility = this->shared_from_this(); + formHostClient->AddForm(thisAbility, formJsInfo.formId); + // post the async task of handleAcquireResult + PostTask([this, want, formJsInfo, callback]() { HandleAcquireResult(want, formJsInfo, callback); }, 0L); + // the acquire form is successfully + return true; +} + +/** + * @brief Updates the content of a specified JS form. + * + *

This method is called by a form provider to update JS form data as needed. + * + * @param formId Indicates the form ID. + * @param formProviderData The data used to update the JS form displayed on the client. + * @return Returns {@code true} if the request is successfully initiated; returns {@code false} otherwise. + */ +bool Ability::UpdateForm(const int64_t formId, const FormProviderData &formProviderData) +{ + APP_LOGI("%{public}s called.", __func__); + // check fms recover status + if (FormMgr::GetRecoverStatus() == Constants::IN_RECOVERING) { + APP_LOGE("%{public}s error, form is in recover status, can't do action on form.", __func__); + return false; + } + + // check formId + if (formId <= 0) { + APP_LOGE("%{public}s error, the passed in formId can't be negative or zero.", __func__); + return false; + } + + // check formProviderData + if (formProviderData.GetDataString().empty()) { + APP_LOGE("%{public}s error, the formProviderData is null.", __func__); + return false; + } + + // update form request to fms + if (FormMgr::GetInstance().UpdateForm(formId, abilityInfo_->bundleName, formProviderData) != ERR_OK) { + APP_LOGE("%{public}s error, update form for fms failed.", __func__); + return false; + } + + // the update form is successfully + return true; +} + +/** + * @brief Sends a notification to the form framework to make the specified forms visible. + * + *

After this method is successfully called, {@link Ability#OnVisibilityChanged(std::map)} + * will be called to notify the form provider of the form visibility change event.

+ * + * @param formIds Indicates the IDs of the forms to be made visible. + * @return Returns {@code true} if the request is successfully initiated; returns {@code false} otherwise. + */ +bool Ability::NotifyVisibleForms(const std::vector &formIds) +{ + APP_LOGI("%{public}s called.", __func__); + return NotifyWhetherVisibleForms(formIds, Constants::FORM_VISIBLE); +} + +/** + * @brief Sends a notification to the form framework to make the specified forms invisible. + * + *

After this method is successfully called, {@link Ability#OnVisibilityChanged(std::map)} + * will be called to notify the form provider of the form visibility change event.

+ * + * @param formIds Indicates the IDs of the forms to be made invisible. + * @return Returns {@code true} if the request is successfully initiated; returns {@code false} otherwise. + */ +bool Ability::NotifyInvisibleForms(const std::vector &formIds) +{ + APP_LOGI("%{public}s called.", __func__); + return NotifyWhetherVisibleForms(formIds, Constants::FORM_INVISIBLE); +} + +/** + * @brief Set form next refresh time. + * + *

This method is called by a form provider to set refresh time. + * + * @param formId Indicates the ID of the form to set refresh time. + * @param nextTime Indicates the next time gap now in seconds, can not be litter than 300 seconds. + * @return Returns {@code true} if seting succeed; returns {@code false} otherwise. + */ +bool Ability::SetFormNextRefreshTime(const int64_t formId, const int64_t nextTime) +{ + APP_LOGI("%{public}s called.", __func__); + if (nextTime < MIN_NEXT_TIME) { + APP_LOGE("next time litte than 300 seconds."); + return false; + } + + if (FormMgr::GetInstance().GetRecoverStatus() == Constants::IN_RECOVERING) { + APP_LOGE("%{public}s, formManager is in recovering", __func__); + return false; + } + + int result = FormMgr::GetInstance().SetNextRefreshTime(formId, nextTime); + if (result != ERR_OK) { + APP_LOGE("%{public}s, internal error:[%{public}d]", __func__, result); + return false; + } + + return true; +} +/** + * @brief Requests for form data update. + * + * This method must be called when the application has detected that a system setting item (such as the language, + * resolution, or screen orientation) being listened for has changed. Upon receiving the update request, the form + * provider automatically updates the form data (if there is any update) through the form framework, with the update + * process being unperceivable by the application. + * + * @param formId Indicates the ID of the form to update. + * @return Returns true if the update request is successfully initiated, returns false otherwise. + */ +bool Ability::RequestForm(const int64_t formId) +{ + APP_LOGI("%{public}s called.", __func__); + Want want; + return RequestForm(formId, want); +} + +/** + * @brief Update form. + * + * @param formJsInfo Indicates the obtained {@code FormJsInfo} instance. + */ +void Ability::ProcessFormUpdate(const FormJsInfo &formJsInfo) +{ + APP_LOGI("%{public}s called.", __func__); + // post the async task of handleFormMessage + int32_t msgCode = OHOS_FORM_UPDATE_FORM; + PostTask([this, msgCode, formJsInfo]() { HandleFormMessage(msgCode, formJsInfo); }, 0L); +} +/** + * @brief Uninstall form. + * + * @param formId Indicates the ID of the form to uninstall. + */ +void Ability::ProcessFormUninstall(const int64_t formId) +{ + APP_LOGI("%{public}s start.", __func__); + // check formId + if (formId <= 0) { + APP_LOGE("%{public}s error, the passed in formId can't be negative or zero.", __func__); + return; + } + + std::shared_ptr formCallback = nullptr; + { + std::lock_guard lock(formLock); + // get callback iterator by formId + std::map>::iterator appCallbackIterator = appCallbacks_.find(formId); + + // call the callback function when you need to be notified + if (appCallbackIterator == appCallbacks_.end()) { + APP_LOGE("%{public}s failed, callback not find, formId: %{public}" PRId64 ".", __func__, formId); + return; + } + formCallback = appCallbackIterator->second; + CleanFormResource(formId); + } + if (formCallback == nullptr) { + APP_LOGE("%{public}s failed, callback is nullptr.", __func__); + return; + } + + formCallback->OnFormUninstall(formId); + + APP_LOGI("%{public}s end.", __func__); +} + +/** + * @brief Called to return a FormProviderInfo object. + * + *

You must override this method if your ability will serve as a form provider to provide a form for clients. + * The default implementation returns nullptr.

+ * + * @param want Indicates the detailed information for creating a FormProviderInfo. + * The Want object must include the form ID, form name of the form, + * which can be obtained from Ability#PARAM_FORM_IDENTITY_KEY, + * Ability#PARAM_FORM_NAME_KEY, and Ability#PARAM_FORM_DIMENSION_KEY, + * respectively. Such form information must be managed as persistent data for further form + * acquisition, update, and deletion. + * + * @return Returns the created FormProviderInfo object. + */ +FormProviderInfo Ability::OnCreate(const Want &want) +{ + APP_LOGI("%{public}s called.", __func__); + FormProviderInfo formProviderInfo; + return formProviderInfo; +} + +/** + * @brief Called to notify the form provider that a specified form has been deleted. Override this method if + * you want your application, as the form provider, to be notified of form deletion. + * + * @param formId Indicates the ID of the deleted form. + * @return None. + */ +void Ability::OnDelete(const int64_t formId) +{} + +/** + * @brief Called to notify the form provider to update a specified form. + * + * @param formId Indicates the ID of the form to update. + * @return none. + */ +void Ability::OnUpdate(const int64_t formId) +{} + +/** + * @brief Called when the form provider is notified that a temporary form is successfully converted to a normal form. + * + * @param formId Indicates the ID of the form. + * @return None. + */ +void Ability::OnCastTemptoNormal(const int64_t formId) +{} + +/** + * @brief Called when the form provider receives form events from the fms. + * + * @param formEventsMap Indicates the form events occurred. The key in the Map object indicates the form ID, + * and the value indicates the event type, which can be either FORM_VISIBLE + * or FORM_INVISIBLE. FORM_VISIBLE means that the form becomes visible, + * and FORM_INVISIBLE means that the form becomes invisible. + * @return none. + */ +void Ability::OnVisibilityChanged(const std::map &formEventsMap) +{} +/** + * @brief Called to notify the form provider to update a specified form. + * + * @param formId Indicates the ID of the form to update. + * @param message Form event message. + */ +void Ability::OnTriggerEvent(const int64_t formId, const std::string &message) +{} +/** + * @brief Delete or release form with formId. + * + * @param formId Indicates the form's ID. + * @param deleteType Indicates the type of delete or release. + * @return Returns {@code true} if the form is successfully deleted; returns {@code false} otherwise. + */ +bool Ability::DeleteForm(const int64_t formId, const int32_t deleteType) +{ + APP_LOGI("%{public}s called.", __func__); + // check fms recover status + if (FormMgr::GetRecoverStatus() == Constants::IN_RECOVERING) { + APP_LOGE("%{public}s error, form is in recover status, can't do action on form.", __func__); + return false; + } + // check formId + if (formId <= 0) { + APP_LOGE("%{public}s error, the passed in formId can't be negative or zero.", __func__); + return false; + } + + APP_LOGI("%{public}s, delete form begin, formId is %{public}" PRId64 " and deleteType is %{public}d.", + __func__, + formId, + deleteType); + { + // form lock + std::lock_guard lock(formLock); + // clean form resource when form is temp form + if (std::find(lostedByReconnectTempForms_.begin(), lostedByReconnectTempForms_.end(), formId) != + lostedByReconnectTempForms_.end()) { + CleanFormResource(formId); + // the delete temp form is successfully + return true; + } + } + + // hostClient init + sptr formHostClient = FormHostClient::GetInstance(); + // delete or release request to fms + int result; + if (deleteType == DELETE_FORM) { + result = FormMgr::GetInstance().DeleteForm(formId, formHostClient); + } else { + result = FormMgr::GetInstance().ReleaseForm( + formId, formHostClient, (deleteType == RELEASE_CACHED_FORM) ? true : false); + } + if (result != ERR_OK) { + APP_LOGE("%{public}s error, some internal server occurs, error code is %{public}d.", __func__, result); + return false; + } + { + // form lock + std::lock_guard lock(formLock); + // clean form resource + CleanFormResource(formId); + } + // the delete form is successfully + return true; +} + +/** + * @brief Clean form resource with formId. + * + * @param formId Indicates the form's ID. + */ +void Ability::CleanFormResource(const int64_t formId) +{ + APP_LOGI("%{public}s called.", __func__); + // compatible with int form id + int64_t cleanId{-1L}; + for (auto param : userReqParams_) { + uint64_t unsignedFormId = static_cast(formId); + uint64_t unsignedParamFirst = static_cast(param.first); + if ((unsignedParamFirst & 0x00000000ffffffffL) == (unsignedFormId & 0x00000000ffffffffL)) { + cleanId = param.first; + break; + } + } + if (cleanId == -1L) { + return; + } + + APP_LOGD("%{public}s. clean id is %{public}" PRId64 ".", __func__, cleanId); + // remove wantParam, callback and lostedByReconnectTempForms + appCallbacks_.erase(cleanId); + userReqParams_.erase(cleanId); + auto tempForm = std::find(lostedByReconnectTempForms_.begin(), lostedByReconnectTempForms_.end(), cleanId); + if (tempForm != lostedByReconnectTempForms_.end()) { + lostedByReconnectTempForms_.erase(tempForm); + } + + // remove ability + std::shared_ptr thisAbility = this->shared_from_this(); + FormHostClient::GetInstance()->RemoveForm(thisAbility, cleanId); + + // unregister death callback when appCallbacks is empty + if (appCallbacks_.empty()) { + std::shared_ptr thisAbility = this->shared_from_this(); + FormMgr::GetInstance().UnRegisterDeathCallback(thisAbility); + } + APP_LOGI("%{public}s end.", __func__); +} + +/** + * @brief Handle acquire result of the obtained form instance. + * + * @param want Indicates the detailed information about the form to be obtained, including the bundle name, + * module name, ability name, form name, form id, tempForm flag, form dimension, and form customize data. + * @param formJsInfo Indicates the obtained {@code FormJsInfo} instance. + * @param callback Indicates the callback to be invoked whenever the {@link FormJsInfo} instance is obtained. + */ +void Ability::HandleAcquireResult( + const Want &want, const FormJsInfo &formJsInfo, const std::shared_ptr callback) +{ + APP_LOGI("%{public}s called.", __func__); + { + // form lock + std::lock_guard lock(formLock); + + // register death when userReqParams is empty + if (userReqParams_.empty()) { + std::shared_ptr thisAbility = this->shared_from_this(); + FormMgr::GetInstance().RegisterDeathCallback(thisAbility); + } + + // save wantParam and callback + userReqParams_.insert(std::make_pair(formJsInfo.formId, want)); + appCallbacks_.insert(std::make_pair(formJsInfo.formId, callback)); + } + + struct timespec ts; + clock_gettime(CLOCK_REALTIME, &ts); + long currentTime = ts.tv_sec * SEC_TO_MILLISEC + ts.tv_nsec / MILLISEC_TO_NANOSEC; + APP_LOGI("%{public}s, AcquireForm end, current time: %{public}ld", __func__, currentTime); + + // handle acquire message of the obtained form instance + callback->OnAcquired(FormCallback::OHOS_FORM_ACQUIRE_SUCCESS, formJsInfo); +} + +/** + * @brief Handle acquire message of the obtained form instance. + * + * @param msgCode Indicates the code of message type. + * @param formJsInfo Indicates the obtained {@code FormJsInfo} instance. + */ +void Ability::HandleFormMessage(const int32_t msgCode, const FormJsInfo &formJsInfo) +{ + APP_LOGI("%{public}s called.", __func__); + std::shared_ptr formCallback = nullptr; + { + std::lock_guard lock(formLock); + // get callback iterator by formId + std::map>::iterator appCallbackIterator = + appCallbacks_.find(formJsInfo.formId); + + // call the callback function when you need to be notified + if (appCallbackIterator == appCallbacks_.end()) { + APP_LOGE("%{public}s failed, callback not find, formId: %{public}" PRId64 ".", __func__, formJsInfo.formId); + return; + } + formCallback = appCallbackIterator->second; + } + if (formCallback == nullptr) { + APP_LOGE("%{public}s failed, callback is nullptr.", __func__); + return; + } + + APP_LOGI("%{public}s, call user implement of form %{public}" PRId64 ".", __func__, formJsInfo.formId); + + if (msgCode == OHOS_FORM_ACQUIRE_FORM) { + formCallback->OnAcquired(FormCallback::OHOS_FORM_ACQUIRE_SUCCESS, formJsInfo); + } else { + formCallback->OnUpdate(FormCallback::OHOS_FORM_UPDATE_SUCCESS, formJsInfo); + } +} + +/** + * @brief Notify the forms visibility change event. + * + * @param formIds Indicates the IDs of the forms to be made visible or invisible. + * @param eventType Indicates the form events occurred. FORM_VISIBLE means that the form becomes visible, + * and FORM_INVISIBLE means that the form becomes invisible. + * @return Returns {@code true} if the request is successfully initiated; returns {@code false} otherwise. + */ +bool Ability::NotifyWhetherVisibleForms(const std::vector &formIds, int32_t eventType) +{ + APP_LOGI("%{public}s called.", __func__); + if (formIds.empty() || formIds.size() > Constants::MAX_VISIBLE_NOTIFY_LIST) { + APP_LOGE("%{public}s, formIds is empty or exceed 32.", __func__); + return false; + } + + if (FormMgr::GetRecoverStatus() == Constants::IN_RECOVERING) { + APP_LOGE("%{public}s error, form is in recover status, can't do action on form.", __func__); + return false; + } + + int resultCode = + FormMgr::GetInstance().NotifyWhetherVisibleForms(formIds, FormHostClient::GetInstance(), eventType); + if (resultCode != ERR_OK) { + APP_LOGE("%{public}s error, internal error occurs, error code:%{public}d.", __func__, resultCode); + return false; + } + return true; +} + +/** + * @brief Check the param of want. + * + * @param formId Indicates the form's ID. + * @param want Indicates the detailed information about the form to be obtained, including the bundle name, + * module name, ability name, form name, form id, tempForm flag, form dimension, and form customize data. + * @return Returns {@code true} if the check result is ok; returns {@code false} ng. + */ +bool Ability::CheckWantValid(const int64_t formId, const Want &want) +{ + APP_LOGI("%{public}s called.", __func__); + // get want parameters + int32_t formDimension = want.GetIntParam(Constants::PARAM_FORM_DIMENSION_KEY, 1); + std::string moduleName = want.GetStringParam(Constants::PARAM_MODULE_NAME_KEY); + + ElementName elementName = want.GetElement(); + std::string bundleName = elementName.GetBundleName(); + std::string abilityName = elementName.GetAbilityName(); + + bool tempFormFlg = want.GetBoolParam(Constants::PARAM_FORM_TEMPORARY_KEY, false); + + APP_LOGD("%{public}s, param of formDimension %{public}d in want.", __func__, formDimension); + APP_LOGD("%{public}s, param of moduleName %{public}s in want.", __func__, moduleName.c_str()); + APP_LOGD("%{public}s, param of bundleName %{public}s in want.", __func__, bundleName.c_str()); + APP_LOGD("%{public}s, param of abilityName %{public}s in want.", __func__, abilityName.c_str()); + APP_LOGD("%{public}s, param of tempFormFlg %{public}d in want.", __func__, tempFormFlg); + + // check want parameters + if (bundleName.empty() || abilityName.empty() || moduleName.empty()) { + APP_LOGE("%{public}s error, bundleName or abilityName or moduleName is not set in want.", __func__); + return false; + } + if (FormHostClient::GetInstance()->ContainsForm(formId)) { + APP_LOGE("%{public}s error, form has already acquired, do not support acquire twice.", __func__); + return false; + } + if (formDimension <= 0) { + APP_LOGE("%{public}s error, dimension should not be zero or negative in want.", __func__); + return false; + } + if (tempFormFlg && formId != 0) { + APP_LOGE("%{public}s error, can not select form id when acquire temporary form.", __func__); + return false; + } + + // the check is successfully + return true; +} + +/** + * @brief Enable form update. + * + * @param formIds FormIds of hostclient. + */ +bool Ability::EnableUpdateForm(const std::vector &formIds) +{ + APP_LOGI("%{public}s called.", __func__); + return LifecycleUpdate(formIds, ENABLE_FORM_UPDATE); +} + +/** + * @brief Disable form update. + * + * @param formIds FormIds of hostclient. + */ +bool Ability::DisableUpdateForm(const std::vector &formIds) +{ + APP_LOGI("%{public}s called.", __func__); + return LifecycleUpdate(formIds, DISABLE_FORM_UPDATE); +} + +bool Ability::LifecycleUpdate(std::vector formIds, int32_t updateType) +{ + if (FormMgr::GetRecoverStatus() == Constants::IN_RECOVERING) { + APP_LOGE("%{public}s error, form is in recover status, can't do action on form.", __func__); + return false; + } + + // hostClient init + sptr formHostClient = FormHostClient::GetInstance(); + if (formHostClient == nullptr) { + APP_LOGE("%{public}s error, formHostClient == nullptr.", __func__); + return false; + } + + int result = FormMgr::GetInstance().LifecycleUpdate(formIds, formHostClient, updateType); + if (result != ERR_OK) { + APP_LOGE("%{public}s error, internal error.", __func__); + return false; + } + + return true; +} + +/** + * @brief Requests for form data update, by passing a set of parameters (using Want) to the form provider. + * + * This method must be called when the application has detected that a system setting item (such as the language, + * resolution, or screen orientation) being listened for has changed. Upon receiving the update request, the form + * provider automatically updates the form data (if there is any update) through the form framework, with the update + * process being unperceivable by the application. + * + * @param formId Indicates the ID of the form to update. + * @param want Indicates a set of parameters to be transparently passed to the form provider. + * @return Returns true if the update request is successfully initiated, returns false otherwise. + */ +bool Ability::RequestForm(const int64_t formId, const Want &want) +{ + APP_LOGI("%{public}s called.", __func__); + if (formId <= 0) { + APP_LOGE("%{public}s error, The passed formid is invalid. Its value must be larger than 0.", __func__); + return false; + } + + if (FormMgr::GetRecoverStatus() == Constants::IN_RECOVERING) { + APP_LOGE("%{public}s error, form is in recover status, can't do action on form.", __func__); + return false; + } + + // requestForm request to fms + int resultCode = FormMgr::GetInstance().RequestForm(formId, FormHostClient::GetInstance(), want); + if (resultCode != ERR_OK) { + APP_LOGE("%{public}s error, failed to notify the form service that the form user's lifecycle is updated, error " + "code is %{public}d.", + __func__, + resultCode); + return false; + } + + return true; +} + +/** + * @brief Called to reacquire form and update the form host after the death callback is received. + * + */ +void Ability::OnDeathReceived() +{ + APP_LOGI("%{public}s called.", __func__); + int64_t formId; + std::map &userReqParams = userReqParams_; + std::vector &lostedTempForms = lostedByReconnectTempForms_; + for (const auto &userReqRaram : userReqParams) { + formId = userReqRaram.first; + Want want; + { + std::lock_guard lock(formLock); + want = userReqRaram.second; + if (want.GetBoolParam(Constants::PARAM_FORM_TEMPORARY_KEY, false) && + std::find(lostedTempForms.begin(), lostedTempForms.end(), formId) == lostedTempForms.end()) { + lostedTempForms.emplace_back(formId); + continue; + } + } + + bool result = ReAcquireForm(formId, want); + if (!result) { + APP_LOGI("%{public}s error, reacquire form failed, formId:%{public}" PRId64 ".", __func__, formId); + std::shared_ptr formCallback = nullptr; + { + std::lock_guard lock(formLock); + // get callback iterator by formId + std::map>::iterator appCallbackIterator = + appCallbacks_.find(formId); + + if (appCallbackIterator == appCallbacks_.end()) { + APP_LOGW("%{public}s error, lack of form callback for form, formId:%{public}" PRId64 ".", + __func__, + formId); + continue; + } + formCallback = appCallbackIterator->second; + } + if (formCallback == nullptr) { + APP_LOGW("%{public}s failed, callback is nullptr.", __func__); + continue; + } + + FormJsInfo formJsInfo; + formJsInfo.formId = formId; + formCallback->OnAcquired(FormCallback::OHOS_FORM_RESTORE_FAILURE, formJsInfo); + } + } +} + +/** + * @brief Reacquire a specified form when the death callback is received. + * + * @param formId Indicates the form ID. + * @param want Indicates the detailed information about the form to be obtained. + * @return Returns true if the request is successfully initiated; returns false otherwise. + */ +bool Ability::ReAcquireForm(const int64_t formId, const Want &want) +{ + APP_LOGI("%{public}s called.", __func__); + + // get the form host client + sptr formHostClient = FormHostClient::GetInstance(); + if (formHostClient == nullptr) { + APP_LOGE("%{public}s error, formHostClient is nullptr, formId:%{public}" PRId64 ".", __func__, formId); + return false; + } + + // reacquire form + FormJsInfo formJsInfo; + if (FormMgr::GetInstance().AddForm(formId, want, formHostClient, formJsInfo) != ERR_OK || formJsInfo.formId <= 0 || + formJsInfo.formId != formId) { + APP_LOGE("%{public}s error, fms reacquire form failed, formId:%{public}" PRId64 ".", __func__, formId); + return false; + } + + // handle update message of the obtained form instance. + ProcessFormUpdate(formJsInfo); + + return true; +} + +/** + * @brief Check form manager service ready. + * + * @return Returns true if form manager service ready; returns false otherwise. + */ +bool Ability::CheckFMSReady() +{ + APP_LOGI("%{public}s called.", __func__); + + sptr systemAbilityManager = + SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + auto remoteObject = systemAbilityManager->GetSystemAbility(FORM_MGR_SERVICE_ID); + if (remoteObject == nullptr) { + APP_LOGI("%{public}s, form manager service is not ready.", __func__); + return false; + } + + return true; +} + +/** + * @brief Get All FormsInfo. + * + * @param formInfos Returns the forms' information of all forms provided. + * @return Returns true if the request is successfully initiated; returns false otherwise. + */ +bool Ability::GetAllFormsInfo(std::vector &formInfos) +{ + APP_LOGI("%{public}s called.", __func__); + sptr iBundleMgr = GetBundleMgr(); + if (iBundleMgr == nullptr) { + APP_LOGE("%{public}s error, failed to get IBundleMgr.", __func__); + return false; + } + + if (!CheckPermission()) { + return false; + } + + return iBundleMgr->GetAllFormsInfo(formInfos); +} + +/** + * @brief Get forms info by application name. + * + * @param bundleName Application name. + * @param formInfos Returns the forms' information of the specify application name. + * @return Returns true if the request is successfully initiated; returns false otherwise. + */ +bool Ability::GetFormsInfoByApp(std::string &bundleName, std::vector &formInfos) +{ + APP_LOGI("%{public}s called.", __func__); + bool IsGetFormsInfoByApp = false; + if (bundleName.empty()) { + APP_LOGW("save info fail, empty bundle name"); + IsGetFormsInfoByApp = false; + } + + sptr iBundleMgr = GetBundleMgr(); + if (iBundleMgr == nullptr) { + APP_LOGE("%{public}s error, failed to get IBundleMgr.", __func__); + return IsGetFormsInfoByApp; + } + + if (!CheckPermission()) { + return IsGetFormsInfoByApp; + } + + IsGetFormsInfoByApp = iBundleMgr->GetFormsInfoByApp(bundleName, formInfos); + if (formInfos.size() == 0) { + return IsGetFormsInfoByApp; + } + + return IsGetFormsInfoByApp; +} + +/** + * @brief Get forms info by application name and module name. + * + * @param bundleName Application name. + * @param moduleName Module name of hap. + * @param formInfos Returns the forms' information of the specify application name and module name. + * @return Returns true if the request is successfully initiated; returns false otherwise. + */ +bool Ability::GetFormsInfoByModule(std::string &bundleName, std::string &moduleName, std::vector &formInfos) +{ + APP_LOGI("%{public}s called.", __func__); + bool IsGetFormsInfoByModule = false; + if (bundleName.empty() || moduleName.empty()) { + APP_LOGW("save info fail, empty bundle name"); + return IsGetFormsInfoByModule; + } + + sptr iBundleMgr = GetBundleMgr(); + if (iBundleMgr == nullptr) { + APP_LOGE("%{public}s error, failed to get IBundleMgr.", __func__); + return IsGetFormsInfoByModule; + } + + if (!CheckPermission()) { + return IsGetFormsInfoByModule; + } + + IsGetFormsInfoByModule = iBundleMgr->GetFormsInfoByModule(bundleName, moduleName, formInfos); + if (formInfos.size() == 0) { + IsGetFormsInfoByModule = false; + } + return IsGetFormsInfoByModule; +} + +/** + * @brief Acquire a bundle manager, if it not existed. + * @return returns the bundle manager ipc object, or nullptr for failed. + */ +sptr Ability::GetBundleMgr() +{ + APP_LOGI("%{public}s called.", __func__); + if (iBundleMgr_ == nullptr) { + sptr systemAbilityManager = + SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + auto remoteObject = systemAbilityManager->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID); + if (remoteObject == nullptr) { + APP_LOGE("%{public}s error, failed to get bundle manager service.", __func__); + return nullptr; + } + + iBundleMgr_ = iface_cast(remoteObject); + if (iBundleMgr_ == nullptr) { + APP_LOGE("%{public}s error, failed to get bundle manager service", __func__); + return nullptr; + } + } + + return iBundleMgr_; +} + +/** + * @brief check permission of bundle, if it not existed. + * @return returns the permission is vaild, or false for failed. + */ +bool Ability::CheckPermission() +{ + APP_LOGI("%{public}s called.", __func__); + return true; +} + +bool Ability::CheckFormPermission(const std::string &bundleName) const +{ + APP_LOGI("%{public}s called.", __func__); + + int result = PermissionKit::VerifyPermission(bundleName, Constants::PERMISSION_REQUIRE_FORM, 0); + if (result != PermissionState::PERMISSION_GRANTED) { + APP_LOGW("permission = %{public}s, bundleName = %{public}s, result = %{public}d", + Constants::PERMISSION_REQUIRE_FORM.c_str(), + bundleName.c_str(), + result); + } + return result == PermissionState::PERMISSION_GRANTED; +} +/** + * @brief Add the bundle manager instance for debug. + * @param bundleManager the bundle manager ipc object. + */ +void Ability::SetBundleManager(const sptr &bundleManager) +{ + APP_LOGI("%{public}s called.", __func__); + + iBundleMgr_ = bundleManager; +} + +/** + * @brief Acquire a form provider remote object. + * @return Returns form provider remote object. + */ +sptr Ability::GetFormRemoteObject() +{ + APP_LOGI("%{public}s start", __func__); + if (providerRemoteObject_ == nullptr) { + sptr providerClient = new (std::nothrow) FormProviderClient(); + std::shared_ptr thisAbility = this->shared_from_this(); + if (thisAbility == nullptr) { + APP_LOGE("%{public}s failed, thisAbility is nullptr", __func__); + } + providerClient->SetOwner(thisAbility); + providerRemoteObject_ = providerClient->AsObject(); + } + APP_LOGI("%{public}s end", __func__); + return providerRemoteObject_; +} + +/** + * @brief Set the start ability setting. + * @param setting the start ability setting. + */ +void Ability::SetStartAbilitySetting(std::shared_ptr setting) +{ + APP_LOGI("%{public}s called.", __func__); + setting_ = setting; +} + +std::vector> Ability::ExecuteBatch( + const std::vector> &operations) +{ + APP_LOGI("Ability::ExecuteBatch start"); + std::vector> results; + if (abilityInfo_ == nullptr) { + APP_LOGE("Ability::ExecuteBatch abilityInfo is nullptr"); + return results; + } + if (abilityInfo_->type != AppExecFwk::AbilityType::DATA) { + APP_LOGE("Ability::ExecuteBatch data ability type failed, current type: %{public}d", abilityInfo_->type); + return results; + } + size_t len = operations.size(); + APP_LOGI("Ability::ExecuteBatch operation is nullptr, len %{public}zu", len); + for (size_t i = 0; i < len; i++) { + std::shared_ptr operation = operations[i]; + if (operation == nullptr) { + APP_LOGI("Ability::ExecuteBatch operation is nullptr, create DataAbilityResult"); + results.push_back(std::make_shared(0)); + continue; + } + ExecuteOperation(operation, results, i); + } + APP_LOGI("Ability::ExecuteBatch end"); + return results; +} +void Ability::ExecuteOperation(std::shared_ptr &operation, + std::vector> &results, int index) +{ + APP_LOGI("Ability::ExecuteOperation start, index=%{public}d", index); + if (abilityInfo_->type != AppExecFwk::AbilityType::DATA) { + APP_LOGE("Ability::ExecuteOperation data ability type failed, current type: %{public}d", abilityInfo_->type); + return; + } + if (index < 0) { + APP_LOGE( + "Ability::ExecuteOperation operation result index should not below zero, current index: %{public}d", index); + return; + } + if (operation == nullptr) { + APP_LOGI("Ability::ExecuteOperation operation is nullptr, create DataAbilityResult"); + results.push_back(std::make_shared(0)); + return; + } + + int numRows = 0; + std::shared_ptr valuesBucket = ParseValuesBucketReference(results, operation, index); + std::shared_ptr predicates = + ParsePredictionArgsReference(results, operation, index); + if (operation->IsInsertOperation()) { + APP_LOGI("Ability::ExecuteOperation IsInsertOperation"); + numRows = Insert(*(operation->GetUri().get()), *valuesBucket); + } else if (operation->IsDeleteOperation()) { + APP_LOGI("Ability::ExecuteOperation IsDeleteOperation"); + numRows = Delete(*(operation->GetUri().get()), *predicates); + } else if (operation->IsUpdateOperation()) { + APP_LOGI("Ability::ExecuteOperation IsUpdateOperation"); + numRows = Update(*(operation->GetUri().get()), *valuesBucket, *predicates); + } else if (operation->IsAssertOperation()) { + APP_LOGI("Ability::ExecuteOperation IsAssertOperation"); + std::vector columns; + std::shared_ptr queryResult = + Query(*(operation->GetUri().get()), columns, *predicates); + if (queryResult == nullptr) { + APP_LOGE("Ability::ExecuteOperation Query retval is nullptr"); + results.push_back(std::make_shared(0)); + return; + } + if (queryResult->GetRowCount(numRows) != 0) { + APP_LOGE("Ability::ExecuteOperation queryResult->GetRowCount(numRows) != E_OK"); + } + if (!CheckAssertQueryResult(queryResult, operation->GetValuesBucket())) { + if (queryResult != nullptr) { + queryResult->Close(); + } + APP_LOGE("Query Result is not equal to expected value."); + } + + if (queryResult != nullptr) { + queryResult->Close(); + } + } else { + APP_LOGE("Ability::ExecuteOperation Expected bad type %{public}d", operation->GetType()); + } + if (operation->GetExpectedCount() != numRows) { + APP_LOGE("Ability::ExecuteOperation Expected %{public}d rows but actual %{public}d", + operation->GetExpectedCount(), + numRows); + } else { + results.push_back(std::make_shared(numRows)); + } +} + +std::shared_ptr Ability::ParsePredictionArgsReference( + std::vector> &results, std::shared_ptr &operation, + int numRefs) +{ + if (operation == nullptr) { + APP_LOGE("Ability::ParsePredictionArgsReference intpur is nullptr"); + return nullptr; + } + + std::map predicatesBackReferencesMap = operation->GetDataAbilityPredicatesBackReferences(); + if (predicatesBackReferencesMap.empty()) { + return operation->GetDataAbilityPredicates(); + } + + std::vector strPredicatesList; + strPredicatesList.clear(); + std::shared_ptr predicates = operation->GetDataAbilityPredicates(); + if (predicates == nullptr) { + APP_LOGI("Ability::ParsePredictionArgsReference operation->GetDataAbilityPredicates is nullptr"); + } else { + APP_LOGI("Ability::ParsePredictionArgsReference operation->GetDataAbilityPredicates isn`t nullptr"); + std::vector strPredicatesList = predicates->GetWhereArgs(); + } + + if (strPredicatesList.empty()) { + APP_LOGE("Ability::ParsePredictionArgsReference operation->GetDataAbilityPredicates()->GetWhereArgs()" + "error strList is empty()"); + } + + for (auto iterMap : predicatesBackReferencesMap) { + APP_LOGI("Ability::ParsePredictionArgsReference predicatesBackReferencesMap first:%{public}d second:%{public}d", + iterMap.first, + iterMap.second); + int tempCount = ChangeRef2Value(results, numRefs, iterMap.second); + if (tempCount < 0) { + APP_LOGE("Ability::ParsePredictionArgsReference tempCount:%{public}d", tempCount); + continue; + } + std::string strPredicates = std::to_string(tempCount); + APP_LOGI("Ability::ParsePredictionArgsReference strPredicates:%{public}s", strPredicates.c_str()); + strPredicatesList.push_back(strPredicates); + APP_LOGI("Ability::ParsePredictionArgsReference push_back done"); + } + + predicates->SetWhereArgs(strPredicatesList); + + return predicates; +} + +std::shared_ptr Ability::ParseValuesBucketReference( + std::vector> &results, std::shared_ptr &operation, + int numRefs) +{ + NativeRdb::ValuesBucket retValueBucket; + if (operation == nullptr) { + APP_LOGE("Ability::ParseValuesBucketReference intpur is nullptr"); + return nullptr; + } + + if (operation->GetValuesBucketReferences() == nullptr) { + return operation->GetValuesBucket(); + } + + retValueBucket.Clear(); + if (operation->GetValuesBucket() == nullptr) { + APP_LOGI("Ability::ParseValuesBucketReference operation->GetValuesBucket is nullptr"); + } else { + APP_LOGI("Ability::ParseValuesBucketReference operation->GetValuesBucket is nullptr"); + retValueBucket = *operation->GetValuesBucket(); + } + + std::map valuesMapReferences; + operation->GetValuesBucketReferences()->GetAll(valuesMapReferences); + + for (auto itermap : valuesMapReferences) { + std::string key = itermap.first; + NativeRdb::ValueObject obj; + if (!operation->GetValuesBucketReferences()->GetObject(key, obj)) { + APP_LOGE("Ability::ParseValuesBucketReference operation->GetValuesBucketReferences()->GetObject error"); + continue; + } + switch (obj.GetType()) { + case NativeRdb::ValueObjectType::TYPE_INT: { + int val = 0; + if (obj.GetInt(val) != 0) { + APP_LOGE("Ability::ParseValuesBucketReference ValueObject->GetInt() error"); + break; + } + APP_LOGI("Ability::ParseValuesBucketReference retValueBucket->PutInt(%{public}s, %{public}d)", + key.c_str(), + val); + retValueBucket.PutInt(key, val); + } break; + case NativeRdb::ValueObjectType::TYPE_DOUBLE: { + double val = 0.0; + if (obj.GetDouble(val) != 0) { + APP_LOGE("Ability::ParseValuesBucketReference ValueObject->GetDouble() error"); + break; + } + APP_LOGI("Ability::ParseValuesBucketReference retValueBucket->PutDouble(%{public}s, %{public}f)", + key.c_str(), + val); + retValueBucket.PutDouble(key, val); + } break; + case NativeRdb::ValueObjectType::TYPE_STRING: { + std::string val = ""; + if (obj.GetString(val) != 0) { + APP_LOGE("Ability::ParseValuesBucketReference ValueObject->GetString() error"); + break; + } + APP_LOGI("Ability::ParseValuesBucketReference retValueBucket->PutString(%{public}s, %{public}s)", + key.c_str(), + val.c_str()); + retValueBucket.PutString(key, val); + } break; + case NativeRdb::ValueObjectType::TYPE_BLOB: { + std::vector val; + if (obj.GetBlob(val) != 0) { + APP_LOGE("Ability::ParseValuesBucketReference ValueObject->GetBlob() error"); + break; + } + APP_LOGI("Ability::ParseValuesBucketReference retValueBucket->PutBlob(%{public}s, %{public}zu)", + key.c_str(), + val.size()); + retValueBucket.PutBlob(key, val); + } break; + case NativeRdb::ValueObjectType::TYPE_BOOL: { + bool val = false; + if (obj.GetBool(val) != 0) { + APP_LOGE("Ability::ParseValuesBucketReference ValueObject->GetBool() error"); + break; + } + APP_LOGI("Ability::ParseValuesBucketReference retValueBucket->PutBool(%{public}s, %{public}s)", + key.c_str(), + val ? "true" : "false"); + retValueBucket.PutBool(key, val); + } break; + default: { + APP_LOGI("Ability::ParseValuesBucketReference retValueBucket->PutNull(%{public}s)", key.c_str()); + retValueBucket.PutNull(key); + } break; + } + } + + std::map valuesMap; + retValueBucket.GetAll(valuesMap); + + return std::make_shared(valuesMap); +} + +int Ability::ChangeRef2Value(std::vector> &results, int numRefs, int index) +{ + int retval = -1; + if (index >= numRefs) { + APP_LOGE("Ability::ChangeRef2Value index >= numRefs"); + return retval; + } + + if (index >= static_cast(results.size())) { + APP_LOGE("Ability::ChangeRef2Value index:%{public}d >= results.size():%{public}zu", index, results.size()); + return retval; + } + + std::shared_ptr refResult = results[index]; + if (refResult == nullptr) { + APP_LOGE("Ability::ChangeRef2Value No.%{public}d refResult is null", index); + return retval; + } + + if (refResult->GetUri().ToString().empty()) { + retval = refResult->GetCount(); + } else { + retval = DataUriUtils::GetId(refResult->GetUri()); + } + + return retval; +} + +bool Ability::CheckAssertQueryResult(std::shared_ptr &queryResult, + std::shared_ptr &&valuesBucket) +{ + if (queryResult == nullptr) { + APP_LOGE("Ability::CheckAssertQueryResult intput queryResult is null"); + return true; + } + + if (valuesBucket == nullptr) { + APP_LOGE("Ability::CheckAssertQueryResult intput valuesBucket is null"); + return true; + } + + std::map valuesMap; + valuesBucket->GetAll(valuesMap); + if (valuesMap.empty()) { + APP_LOGE("Ability::CheckAssertQueryResult valuesMap is empty"); + return true; + } + int count = 0; + if (queryResult->GetRowCount(count) != 0) { + APP_LOGE("Ability::CheckAssertQueryResult GetRowCount is 0"); + return true; + } + + for (auto iterMap : valuesMap) { + std::string strObject; + if (iterMap.second.GetString(strObject) != 0) { + APP_LOGE("Ability::CheckAssertQueryResult GetString strObject is error"); + continue; + } + if (strObject.empty()) { + APP_LOGE("Ability::CheckAssertQueryResult strObject is empty"); + continue; + } + for (int i = 0; i < count; ++i) { + std::string strName; + if (queryResult->GetString(i, strName) != 0) { + APP_LOGE("Ability::CheckAssertQueryResult GetString strName is error"); + continue; + } + if (strName.empty()) { + APP_LOGE("Ability::CheckAssertQueryResult strName is empty"); + continue; + } + if (strName.c_str() == strObject.c_str()) { + APP_LOGE("Ability::CheckAssertQueryResult strName same to strObject"); + continue; + } + + return false; + } + } + + return true; +} +} // namespace AppExecFwk +} // namespace OHOS diff --git a/tools/frameworks/kits/ability/native/src/ability_context.cpp b/tools/frameworks/kits/ability/native/src/ability_context.cpp new file mode 100755 index 00000000000..f019febeca7 --- /dev/null +++ b/tools/frameworks/kits/ability/native/src/ability_context.cpp @@ -0,0 +1,1341 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ability_context.h" +#include "ability_distributed_connection.h" +#include "ability_manager_client.h" +#include "distributed_client.h" +#include "app_log_wrapper.h" +#include "resource_manager.h" +#include "bundle_constants.h" +#include "iservice_registry.h" +#include "system_ability_definition.h" +#include "sys_mgr_client.h" + +namespace OHOS { +namespace AppExecFwk { + +int AbilityContext::ABILITY_CONTEXT_DEFAULT_REQUEST_CODE(0); + +/** + * @brief Starts a new ability. + * An ability using the AbilityInfo.AbilityType.SERVICE or AbilityInfo.AbilityType.PAGE template uses this method + * to start a specific ability. The system locates the target ability from installed abilities based on the value + * of the want parameter and then starts it. You can specify the ability to start using the want parameter. + * + * @param want Indicates the Want containing information about the target ability to start. + * + * @param requestCode Indicates the request code returned after the ability using the AbilityInfo.AbilityType.PAGE + * template is started. You can define the request code to identify the results returned by abilities. The value + * ranges from 0 to 65535. This parameter takes effect only on abilities using the AbilityInfo.AbilityType.PAGE + * template. + * + */ +void AbilityContext::StartAbility(const AAFwk::Want &want, int requestCode) +{ + APP_LOGI("%{public}s begin.", __func__); + APP_LOGI("AbilityContext::StartAbility called, requestCode = %{public}d", requestCode); + + AppExecFwk::AbilityType type = GetAbilityInfoType(); + if (type != AppExecFwk::AbilityType::PAGE && type != AppExecFwk::AbilityType::SERVICE) { + APP_LOGE("AbilityContext::StartAbility AbilityType = %{public}d", type); + return; + } + + if (CheckIfOperateRemote(want)) { + APP_LOGI("%{public}s. Start calling GetDistributedSchedServiceProxy.", __func__); + std::shared_ptr dms = GetDistributedSchedServiceProxy(); + APP_LOGI("%{public}s. End calling GetDistributedSchedServiceProxy.", __func__); + if (dms != nullptr) { + AppExecFwk::AbilityInfo abilityInfo; + APP_LOGI("AbilityContext::StartAbility. try to StartRemoteAbility"); + want.DumpInfo(0); + int result = dms->StartRemoteAbility(want, abilityInfo, requestCode); + if (result != ERR_NONE) { + APP_LOGE("AbilityContext::StartAbility start remote ability failed, the result is %{public}d", result); + } + } else { + APP_LOGE("AbilityContext::StartAbility failed. It wants to start a remote ability, but failed to get dms."); + return; + } + } else { + APP_LOGI("%{public}s. Start calling ams->StartAbility.", __func__); + ErrCode err = AAFwk::AbilityManagerClient::GetInstance()->StartAbility(want, token_, requestCode); + APP_LOGI("%{public}s. End calling ams->StartAbility. ret=%{public}d", __func__, err); + if (err != ERR_OK) { + APP_LOGE("AbilityContext::StartAbility is failed %{public}d", err); + } + } + APP_LOGI("%{public}s end.", __func__); +} + +/** + * @brief Starts a new ability with special ability start setting. + * + * @param want Indicates the Want containing information about the target ability to start. + * @param requestCode Indicates the request code returned after the ability is started. You can define the request code + * to identify the results returned by abilities. The value ranges from 0 to 65535. + * @param abilityStartSetting Indicates the special start setting used in starting ability. + * + */ +void AbilityContext::StartAbility(const Want &want, int requestCode, const AbilityStartSetting &abilityStartSetting) +{ + APP_LOGI("%{public}s begin.", __func__); + AppExecFwk::AbilityType type = GetAbilityInfoType(); + if (AppExecFwk::AbilityType::PAGE != type && AppExecFwk::AbilityType::SERVICE != type) { + APP_LOGE("AbilityContext::StartAbility AbilityType = %{public}d", type); + return; + } + + APP_LOGI("%{public}s. Start calling ams->StartAbility.", __func__); + ErrCode err = + AAFwk::AbilityManagerClient::GetInstance()->StartAbility(want, abilityStartSetting, token_, requestCode); + APP_LOGI("%{public}s. End calling ams->StartAbility. ret=%{public}d", __func__, err); + if (err != ERR_OK) { + APP_LOGE("AbilityContext::StartAbility is failed %{public}d", err); + } + + APP_LOGI("%{public}s end.", __func__); +} + +/** + * @brief Destroys another ability you had previously started by calling Ability.startAbilityForResult + * (ohos.aafwk.content.Want, int, ohos.aafwk.ability.startsetting.AbilityStartSetting) with the same requestCode passed. + * + * @param requestCode Indicates the request code passed for starting the ability. + * + */ +void AbilityContext::TerminateAbility(int requestCode) +{ + APP_LOGI("%{public}s begin.", __func__); + ErrCode err = AAFwk::AbilityManagerClient::GetInstance()->TerminateAbility(token_, requestCode); + if (err != ERR_OK) { + APP_LOGE("AbilityContext::TerminateAbility is failed %{public}d", err); + } + APP_LOGI("%{public}s end.", __func__); +} + +/** + * @brief Destroys the current ability. + * + */ +void AbilityContext::TerminateAbility() +{ + APP_LOGI("%{public}s begin.", __func__); + std::shared_ptr info = GetAbilityInfo(); + if (info == nullptr) { + APP_LOGE("AbilityContext::TerminateAbility info == nullptr"); + return; + } + + ErrCode err = ERR_OK; + + switch (info->type) { + case AppExecFwk::AbilityType::PAGE: + APP_LOGI("%{public}s begin ams->TerminateAbility for PAGE.", __func__); + err = AAFwk::AbilityManagerClient::GetInstance()->TerminateAbility(token_, resultCode_, &resultWant_); + APP_LOGI("%{public}s end ams->TerminateAbility for PAGE, ret=%{public}d", __func__, err); + break; + case AppExecFwk::AbilityType::SERVICE: + APP_LOGI("%{public}s begin ams->TerminateAbility for SERVICE.", __func__); + err = AAFwk::AbilityManagerClient::GetInstance()->TerminateAbility(token_, -1, nullptr); + APP_LOGI("%{public}s end ams->TerminateAbility for SERVICE, ret=%{public}d", __func__, err); + break; + default: + APP_LOGE("AbilityContext::TerminateAbility info type error is %{public}d", info->type); + break; + } + + if (err != ERR_OK) { + APP_LOGE("AbilityContext::TerminateAbility is failed %{public}d", err); + } + APP_LOGI("%{public}s end.", __func__); +} + +/** + * @brief Obtains the bundle name of the ability that called the current ability. + * You can use the obtained bundle name to check whether the calling ability is allowed to receive the data you will + * send. If you did not use Ability.startAbilityForResult(ohos.aafwk.content.Want, int, + * ohos.aafwk.ability.startsetting.AbilityStartSetting) to start the calling ability, null is returned. + * + * @return Returns the bundle name of the calling ability; returns null if no calling ability is available. + */ +std::string AbilityContext::GetCallingBundle() +{ + return callingBundleName_; +} + +/** + * @brief Obtains the ohos.bundle.ElementName object of the current ability. + * + * @return Returns the ohos.bundle.ElementName object of the current ability. + */ +std::shared_ptr AbilityContext::GetElementName() +{ + APP_LOGI("%{public}s begin.", __func__); + std::shared_ptr info = GetAbilityInfo(); + if (info == nullptr) { + APP_LOGE("AbilityContext::GetElementName info == nullptr"); + return nullptr; + } + + std::shared_ptr elementName = std::make_shared(); + if (elementName == nullptr) { + APP_LOGE("AbilityContext::GetElementName elementName == nullptr"); + return nullptr; + } + elementName->SetAbilityName(info->name); + elementName->SetBundleName(info->bundleName); + elementName->SetDeviceID(info->deviceId); + APP_LOGI("%{public}s end.", __func__); + return elementName; +} + +/** + * @brief Obtains the ElementName of the ability that called the current ability. + * + * @return Returns the ElementName of the calling ability; returns null if no calling ability is available. + */ +std::shared_ptr AbilityContext::GetCallingAbility() +{ + APP_LOGI("%{public}s begin.", __func__); + std::shared_ptr elementName = std::make_shared(); + + if (elementName == nullptr) { + APP_LOGE("AbilityContext::GetElementName elementName == nullptr"); + return nullptr; + } + elementName->SetAbilityName(callingAbilityName_); + elementName->SetBundleName(callingBundleName_); + elementName->SetDeviceID(callingDeviceId_); + APP_LOGI("%{public}s end.", __func__); + return elementName; +} + +/** + * @brief Connects the current ability to an ability + * + * @param want Indicates the want containing information about the ability to connect + * + * @param conn Indicates the callback object when the target ability is connected. + * + * @return True means success and false means failure + */ +bool AbilityContext::ConnectAbility(const Want &want, const sptr &conn) +{ + APP_LOGI("%{public}s begin.", __func__); + + AppExecFwk::AbilityType type = GetAbilityInfoType(); + + std::shared_ptr abilityInfo = GetAbilityInfo(); + if (abilityInfo == nullptr) { + APP_LOGE("AbilityContext::ConnectAbility info == nullptr"); + return false; + } + + if (AppExecFwk::AbilityType::PAGE != type && AppExecFwk::AbilityType::SERVICE != type) { + APP_LOGE("AbilityContext::ConnectAbility AbilityType = %{public}d", type); + return false; + } + + ErrCode ret = ERR_OK; + if (want.GetOperation().GetDeviceId() == "") { + APP_LOGI("%{public}s begin ams->ConnectAbilityLocal", __func__); + ret = AAFwk::AbilityManagerClient::GetInstance()->ConnectAbility(want, conn, token_); + } else { + APP_LOGI("%{public}s begin ams->ConnectAbilityRemote", __func__); + auto pos = abilityConnectionMap_.find(conn); + if (pos != abilityConnectionMap_.end()) { + APP_LOGI("%{public}s begin ams->ConnectAbilityHasDistributedConnection", __func__); + return false; + } else { + APP_LOGI("%{public}s begin ams->ConnectAbilitySetDistributedConnection", __func__); + sptr distributedConnection = new AbilityDistributedConnection(conn); + abilityConnectionMap_.emplace(conn, distributedConnection); + ret = DistributedClient::GetInstance()->ConnectRemoteAbility(want, *abilityInfo, distributedConnection); + } + } + + APP_LOGI("%{public}s end ConnectAbility, ret=%{public}d", __func__, ret); + bool value = ((ret == ERR_OK) ? true : false); + if (!value) { + APP_LOGE("AbilityContext::ConnectAbility ErrorCode = %{public}d", ret); + } + APP_LOGI("%{public}s end.", __func__); + return value; +} + +/** + * + * @param conn Indicates the IAbilityDisConnection callback object passed by disconnectAbility after the disconnection + * is set up. The IAbilityDisConnection object uniquely identifies a disconnection between two abilities. + */ +void AbilityContext::DisconnectAbility(const sptr &conn) +{ + APP_LOGI("%{public}s begin.", __func__); + + AppExecFwk::AbilityType type = GetAbilityInfoType(); + if (AppExecFwk::AbilityType::PAGE != type && AppExecFwk::AbilityType::SERVICE != type) { + APP_LOGE("AbilityContext::DisconnectAbility AbilityType = %{public}d", type); + return; + } + + ErrCode ret = ERR_OK; + auto pos = abilityConnectionMap_.find(conn); + if (pos != abilityConnectionMap_.end()) { + APP_LOGI("%{public}s begin ams->DisconnectAbilityRemote", __func__); + ret = DistributedClient::GetInstance()->DisconnectRemoteAbility(pos->second); + abilityConnectionMap_.erase(conn); + } else { + APP_LOGI("%{public}s begin ams->DisconnectAbilityLocal", __func__); + ret = AAFwk::AbilityManagerClient::GetInstance()->DisconnectAbility(conn); + } + + APP_LOGI("%{public}s end ams->DisconnectAbility, ret=%{public}d", __func__, ret); + if (ret != ERR_OK) { + APP_LOGE("AbilityContext::DisconnectAbility error"); + } + APP_LOGD("AbilityContext::DisconnectAbility end"); +} + +/** + * @brief Destroys another ability that uses the AbilityInfo.AbilityType.SERVICE template. + * The current ability using either the AbilityInfo.AbilityType.SERVICE or AbilityInfo.AbilityType.PAGE + * template can call this method to destroy another ability that uses the AbilityInfo.AbilityType.SERVICE + * template. The current ability itself can be destroyed by calling the terminateAbility() method. + * + * @param want Indicates the Want containing information about the ability to destroy. + * + * @return Returns true if the ability is destroyed successfully; returns false otherwise. + */ +bool AbilityContext::StopAbility(const AAFwk::Want &want) +{ + APP_LOGI("%{public}s begin.", __func__); + AppExecFwk::AbilityType type = GetAbilityInfoType(); + if (AppExecFwk::AbilityType::PAGE != type && AppExecFwk::AbilityType::SERVICE != type) { + APP_LOGE("AbilityContext::StopAbility AbilityType = %{public}d", type); + return false; + } + + APP_LOGI("%{public}s begin ams->StopServiceAbility", __func__); + ErrCode err = AAFwk::AbilityManagerClient::GetInstance()->StopServiceAbility(want); + APP_LOGI("%{public}s end ams->StopServiceAbility, ret=%{public}d", __func__, err); + if (err != ERR_OK) { + APP_LOGE("AbilityContext::StopAbility is failed %{public}d", err); + return false; + } + + APP_LOGI("%{public}s end.", __func__); + return true; +} + +sptr AbilityContext::GetToken() +{ + return token_; +} + +/** + * @brief Obtains information about the current application. The returned application information includes basic + * information such as the application name and application permissions. + * + * @return Returns the ApplicationInfo for the current application. + */ +std::shared_ptr AbilityContext::GetApplicationInfo() const +{ + return ContextContainer::GetApplicationInfo(); +} + +/** + * @brief Obtains the application-specific cache directory on the device's internal storage. The system + * automatically deletes files from the cache directory if disk space is required elsewhere on the device. + * Older files are always deleted first. + * + * @return Returns the application-specific cache directory. + */ +std::string AbilityContext::GetCacheDir() +{ + return ContextContainer::GetCacheDir(); +} + +/** + * @brief Obtains the application-specific code-cache directory on the device's internal storage. + * The system will delete any files stored in this location both when your specific application is upgraded, + * and when the entire platform is upgraded. + * + * @return Returns the application-specific code-cache directory. + */ +std::string AbilityContext::GetCodeCacheDir() +{ + return ContextContainer::GetCodeCacheDir(); +} + +/** + * @brief Obtains the local database path. + * If the local database path does not exist, the system creates one and returns the created path. + * + * @return Returns the local database file. + */ +std::string AbilityContext::GetDatabaseDir() +{ + return ContextContainer::GetDatabaseDir(); +} + +/** + * @brief Obtains the absolute path where all private data files of this application are stored. + * + * @return Returns the absolute path storing all private data files of this application. + */ +std::string AbilityContext::GetDataDir() +{ + return ContextContainer::GetDataDir(); +} + +/** + * @brief Obtains the directory for storing custom data files of the application. + * You can use the returned File object to create and access files in this directory. The files + * can be accessible only by the current application. + * + * @param name Indicates the name of the directory to retrieve. This directory is created as part + * of your application data. + * @param mode Indicates the file operating mode. The value can be 0 or a combination of MODE_PRIVATE. + * + * @return Returns a File object for the requested directory. + */ +std::string AbilityContext::GetDir(const std::string &name, int mode) +{ + return ContextContainer::GetDir(name, mode); +} + +/** + * @brief Obtains an IBundleMgr instance. + * You can use this instance to obtain information about the application bundle. + * + * @return Returns an IBundleMgr instance. + */ +sptr AbilityContext::GetBundleManager() const +{ + return ContextContainer::GetBundleManager(); +} + +/** + * @brief Obtains the path of the package containing the current ability. The returned path contains the resources, + * source code, and configuration files of a module. + * + * @return Returns the path of the package file. + */ +std::string AbilityContext::GetBundleCodePath() +{ + return ContextContainer::GetBundleCodePath(); +} + +/** + * @brief Obtains the bundle name of the current ability. + * + * @return Returns the bundle name of the current ability. + */ +std::string AbilityContext::GetBundleName() +{ + return ContextContainer::GetBundleName(); +} + +/** + * @brief Obtains the path of the OHOS Ability Package (HAP} containing this ability. + * + * @return Returns the path of the HAP containing this ability. + */ +std::string AbilityContext::GetBundleResourcePath() +{ + return ContextContainer::GetBundleResourcePath(); +} + +/** + * @brief Obtains the Context object of the application. + * + * @return Returns the Context object of the application. + */ +std::shared_ptr AbilityContext::GetApplicationContext() const +{ + return ContextContainer::GetApplicationContext(); +} + +/** + * @brief Obtains the Context object of the application. + * + * @return Returns the Context object of the application. + */ +std::shared_ptr AbilityContext::GetContext() +{ + return ContextContainer::GetContext(); +} + +/** + * @brief Obtains an ability manager. + * The ability manager provides information about running processes and memory usage of an application. + * + * @return Returns an IAbilityManager instance. + */ +sptr AbilityContext::GetAbilityManager() +{ + return ContextContainer::GetAbilityManager(); +} + +/** + * Called when getting the ProcessInfo + * + * @return ProcessInfo + */ +std::shared_ptr AbilityContext::GetProcessInfo() const +{ + return ContextContainer::GetProcessInfo(); +} + +/** + * @brief Obtains the type of this application. + * + * @return Returns system if this application is a system application; + * returns normal if it is released in official AppGallery; + * returns other if it is released by a third-party vendor; + * returns an empty string if the query fails. + */ +std::string AbilityContext::GetAppType() +{ + return ContextContainer::GetAppType(); +} + +/** + * @brief Obtains information about the current ability. + * The returned information includes the class name, bundle name, and other information about the current ability. + * + * @return Returns the AbilityInfo object for the current ability. + */ +const std::shared_ptr AbilityContext::GetAbilityInfo() +{ + return ContextContainer::GetAbilityInfo(); +} + +/** + * @brief Obtains the HapModuleInfo object of the application. + * + * @return Returns the HapModuleInfo object of the application. + */ +std::shared_ptr AbilityContext::GetHapModuleInfo() +{ + return ContextContainer::GetHapModuleInfo(); +} + +/** + * @brief Get Current Ability Type + * + * @return Current Ability Type + */ +AppExecFwk::AbilityType AbilityContext::GetAbilityInfoType() +{ + std::shared_ptr info = GetAbilityInfo(); + if (info == nullptr) { + APP_LOGE("AbilityContext::GetAbilityInfoType info == nullptr"); + return AppExecFwk::AbilityType::UNKNOWN; + } + + return info->type; +} + +/** + * @brief Creates a Context object for an application with the given bundle name. + * + * @param bundleName Indicates the bundle name of the application. + * + * @param flag Indicates the flag for creating a Context object. It can be 0, any of + * the following values, or any combination of the following values: CONTEXT_IGNORE_SECURITY, + * CONTEXT_INCLUDE_CODE, and CONTEXT_RESTRICTED. The value 0 indicates that there is no restriction + * on creating contexts for applications. + * + * @return Returns a Context object created for the specified application. + */ +std::shared_ptr AbilityContext::CreateBundleContext(std::string bundleName, int flag) +{ + return ContextContainer::CreateBundleContext(bundleName, flag); +} + +/** + * @brief Obtains a resource manager. + * + * @return Returns a ResourceManager object. + */ +std::shared_ptr AbilityContext::GetResourceManager() const +{ + APP_LOGI("%{public}s begin.", __func__); + std::shared_ptr appcontext = GetApplicationContext(); + if (appcontext == nullptr) { + APP_LOGE("AbilityContext::GetResourceManager appcontext is nullptr"); + return nullptr; + } + + APP_LOGI("%{public}s begin appcontext->GetResourceManager.", __func__); + std::shared_ptr resourceManager = appcontext->GetResourceManager(); + APP_LOGI("%{public}s end appcontext->GetResourceManager.", __func__); + if (resourceManager == nullptr) { + APP_LOGE("AbilityContext::GetResourceManager resourceManager is nullptr"); + return nullptr; + } + APP_LOGI("%{public}s end.", __func__); + return resourceManager; +} + +/** + * @brief Checks whether the current process has the given permission. + * You need to call requestPermissionsFromUser(java.lang.std::string[],int) to request a permission only + * if the current process does not have the specific permission. + * + * @param permission Indicates the permission to check. This parameter cannot be null. + * + * @return Returns 0 (IBundleManager.PERMISSION_GRANTED) if the current process has the permission; + * returns -1 (IBundleManager.PERMISSION_DENIED) otherwise. + */ +int AbilityContext::VerifySelfPermission(const std::string &permission) +{ + APP_LOGI("%{public}s begin. permission=%{public}s", __func__, permission.c_str()); + if (permission.empty()) { + APP_LOGE("VerifySelfPermission permission invalid"); + return AppExecFwk::Constants::PERMISSION_NOT_GRANTED; + } + + std::string bundle_name = GetBundleName(); + if (bundle_name.empty()) { + APP_LOGE("VerifySelfPermission failed to get bundle name error"); + return AppExecFwk::Constants::PERMISSION_NOT_GRANTED; + } + + sptr ptr = GetBundleManager(); + if (ptr == nullptr) { + APP_LOGE("VerifySelfPermission failed to get bundle manager service"); + return AppExecFwk::Constants::PERMISSION_NOT_GRANTED; + } + + APP_LOGI("%{public}s start bms->CheckPermission. bundle_name=%{public}s", __func__, bundle_name.c_str()); + int ret = ptr->CheckPermission(bundle_name, permission); + APP_LOGI("%{public}s end bms->CheckPermission, ret=%{public}d", __func__, ret); + APP_LOGI("%{public}s end.", __func__); + return ret; +} + +/** + * @brief Checks whether the calling process for inter-process communication has the given permission. + * The calling process is not the current process. + * + * @param permission Indicates the permission to check. This parameter cannot be null. + * + * @return Returns 0 (IBundleManager.PERMISSION_GRANTED) if the calling process has the permission; + * returns -1 (IBundleManager.PERMISSION_DENIED) otherwise. + */ +int AbilityContext::VerifyCallingPermission(const std::string &permission) +{ + APP_LOGI("%{public}s begin. permission=%{public}s", __func__, permission.c_str()); + if (permission.empty()) { + APP_LOGE("VerifyCallingPermission permission invalid"); + return AppExecFwk::Constants::PERMISSION_NOT_GRANTED; + } + + std::string bundle_name = GetCallingBundle(); + if (bundle_name.empty()) { + APP_LOGE("VerifyCallingPermission failed to get bundle name by uid"); + return AppExecFwk::Constants::PERMISSION_NOT_GRANTED; + } + + sptr ptr = GetBundleManager(); + if (ptr == nullptr) { + APP_LOGE("VerifyCallingPermission failed to get bundle manager service"); + return AppExecFwk::Constants::PERMISSION_NOT_GRANTED; + } + + APP_LOGI("%{public}s start bms->CheckPermission. bundle_name=%{public}s", __func__, bundle_name.c_str()); + int ret = ptr->CheckPermission(bundle_name, permission); + APP_LOGI("%{public}s end bms->CheckPermission, ret=%{public}d", __func__, ret); + APP_LOGI("%{public}s end.", __func__); + return ret; +} + +/** + * @brief Confirms with the permission management module to check whether a request prompt is required for granting a + * certain permission. You need to call the current method to check whether a prompt is required before calling + * requestPermissionsFromUser(java.lang.String[],int) to request a permission. If a prompt is not required, permission + * request will not be initiated. + * + * @param requestCode Indicates the permission to be queried. This parameter cannot be null. + * + * @return Returns true if the current application does not have the permission and the user does not turn off further + * requests; returns false if the current application already has the permission, the permission is rejected by the + * system, or the permission is denied by the user and the user has turned off further requests. + */ +bool AbilityContext::CanRequestPermission(const std::string &permission) +{ + APP_LOGI("%{public}s begin. permission=%{public}s", __func__, permission.c_str()); + if (permission.empty()) { + APP_LOGE("CanRequestPermission permission invalid"); + return true; + } + + std::string bundle_name = GetBundleName(); + if (bundle_name.empty()) { + APP_LOGE("CanRequestPermission failed to get bundle name error"); + return true; + } + + sptr ptr = GetBundleManager(); + if (ptr == nullptr) { + APP_LOGE("CanRequestPermission failed to get bundle manager service"); + return true; + } + + APP_LOGI("%{public}s start bms->CanRequestPermission. bundle_name=%{public}s", __func__, bundle_name.c_str()); + bool ret = ptr->CanRequestPermission(bundle_name, permission, 0); + APP_LOGI("%{public}s end bms->CanRequestPermission, ret=%{public}s", __func__, ret ? "true" : "false"); + APP_LOGI("%{public}s end.", __func__); + return ret; +} + +/** + * @brief When there is a remote call to check whether the remote has permission, otherwise check whether it has + * permission + * + * @param permissions Indicates the list of permissions to be requested. This parameter cannot be null. + * @return Returns 0 (IBundleManager.PERMISSION_GRANTED) if the current process has the permission; + * returns -1 (IBundleManager.PERMISSION_DENIED) otherwise. + */ +int AbilityContext::VerifyCallingOrSelfPermission(const std::string &permission) +{ + return VerifySelfPermission(permission); +} + +/** + * @brief Query whether the application of the specified PID and UID has been granted a certain permission + * + * @param permissions Indicates the list of permissions to be requested. This parameter cannot be null. + * @param pid Process id + * @param uid + * @return Returns 0 (IBundleManager.PERMISSION_GRANTED) if the current process has the permission; + * returns -1 (IBundleManager.PERMISSION_DENIED) otherwise. + */ +int AbilityContext::VerifyPermission(const std::string &permission, int pid, int uid) +{ + APP_LOGI("%{public}s begin. permission=%{public}s, pid=%{public}d, uid=%{public}d", + __func__, + permission.c_str(), + pid, + uid); + if (permission.empty()) { + APP_LOGE("VerifyPermission permission invalid"); + return AppExecFwk::Constants::PERMISSION_NOT_GRANTED; + } + + sptr ptr = GetBundleManager(); + if (ptr == nullptr) { + APP_LOGE("VerifyPermission failed to get bundle manager service"); + return AppExecFwk::Constants::PERMISSION_NOT_GRANTED; + } + + std::string bundle_name; + if (!ptr->GetBundleNameForUid(uid, bundle_name)) { + APP_LOGE("VerifyPermission failed to get bundle name by uid"); + return AppExecFwk::Constants::PERMISSION_NOT_GRANTED; + } + + APP_LOGI("%{public}s start bms->CheckPermission. bundle_name=%{public}s", __func__, bundle_name.c_str()); + int ret = ptr->CheckPermission(bundle_name, permission); + APP_LOGI("%{public}s end bms->CheckPermission, ret=%{public}d", __func__, ret); + APP_LOGI("%{public}s end.", __func__); + return ret; +} + +void AbilityContext::GetPermissionDes(const std::string &permissionName, std::string &des) +{ + sptr ptr = GetBundleManager(); + if (ptr == nullptr) { + APP_LOGE("GetPermissionDes failed to get bundle manager service"); + return; + } + + PermissionDef permissionDef; + APP_LOGI("%{public}s start bms->GetPermissionDef. permissionName=%{public}s", __func__, permissionName.c_str()); + if (ptr->GetPermissionDef(permissionName, permissionDef)) { + des = permissionDef.description; + } + APP_LOGI("%{public}s end bms->GetPermissionDef.", __func__); +} + +/** + * @brief Requests certain permissions from the system. + * This method is called for permission request. This is an asynchronous method. When it is executed, + * the Ability.onRequestPermissionsFromUserResult(int, String[], int[]) method will be called back. + * + * @param permissions Indicates the list of permissions to be requested. This parameter cannot be null. + * @param requestCode Indicates the request code to be passed to the Ability.onRequestPermissionsFromUserResult(int, + * String[], int[]) callback method. This code cannot be a negative number. + */ +void AbilityContext::RequestPermissionsFromUser(std::vector &permissions, int requestCode) +{ + APP_LOGI("%{public}s begin.", __func__); + if (permissions.size() == 0) { + APP_LOGE("AbilityContext::RequestPermissionsFromUser permissions is empty"); + return; + } + + if (requestCode < 0) { + APP_LOGE("AbilityContext::RequestPermissionsFromUser requestCode should be >= 0"); + return; + } + + std::vector permissionDes; + std::string des; + for (size_t i = 0; i < permissions.size(); i++) { + des = ""; + GetPermissionDes(permissions[i], des); + permissionDes.push_back(des); + } + + AAFwk::Want want; + want.SetElementName(OHOS_REQUEST_PERMISSION_BUNDLENAME, OHOS_REQUEST_PERMISSION_ABILITY_NAME); + + want.SetParam(OHOS_REQUEST_PERMISSION_KEY, OHOS_REQUEST_PERMISSION_VALUE); + want.SetParam(OHOS_REQUEST_PERMISSIONS_LIST, permissions); + want.SetParam(OHOS_REQUEST_PERMISSIONS_DES_LIST, permissionDes); + want.SetParam(OHOS_REQUEST_CALLER_BUNDLERNAME, GetBundleName()); + + StartAbility(want, requestCode); + APP_LOGI("%{public}s end.", __func__); +} + +/* @brief Deletes the specified private file associated with the application. + * + * @param fileName Indicates the name of the file to delete. The file name cannot contain path separators. + * + * @return Returns true if the file is deleted successfully; returns false otherwise. + */ +bool AbilityContext::DeleteFile(const std::string &fileName) +{ + return ContextContainer::DeleteFile(fileName); +} + +/** + * @brief Set deviceId/bundleName/abilityName of the calling ability + * + * @param deviceId deviceId of the calling ability + * + * @param deviceId bundleName of the calling ability + * + * @param deviceId abilityName of the calling ability + */ +void AbilityContext::SetCallingContext( + const std::string &deviceId, const std::string &bundleName, const std::string &abilityName) +{ + callingDeviceId_ = deviceId; + callingBundleName_ = bundleName; + callingAbilityName_ = abilityName; +} + +/** + * @brief Obtains information about the caller of this ability. + * + * @return Returns the caller information. + */ +Uri AbilityContext::GetCaller() +{ + return ContextContainer::GetCaller(); +} + +/** + * Attaches a Context object to the current ability. + * Generally, this method is called after Ability is loaded to provide the application context for the current + * ability. + * + * @param base Indicates a Context object. + */ +void AbilityContext::AttachBaseContext(const std::shared_ptr &base) +{ + APP_LOGI("AbilityContext::AttachBaseContext. Start."); + ContextContainer::AttachBaseContext(base); + APP_LOGI("AbilityContext::AttachBaseContext. End."); +} + +/** + * @brief Obtains the absolute path to the application-specific cache directory + * on the primary external or shared storage device. + * + * @return Returns the absolute path to the application-specific cache directory on the external or + * shared storage device; returns null if the external or shared storage device is temporarily unavailable. + */ +std::string AbilityContext::GetExternalCacheDir() +{ + return ContextContainer::GetExternalCacheDir(); +} + +/** + * @brief Obtains the absolute path to the directory for storing files for the application on the + * primary external or shared storage device. + * + * @param type Indicates the type of the file directory to return + * + * @return Returns the absolute path to the application file directory on the external or shared storage + * device; returns null if the external or shared storage device is temporarily unavailable. + */ +std::string AbilityContext::GetExternalFilesDir(std::string &type) +{ + return ContextContainer::GetExternalFilesDir(type); +} + +/** + * @brief Obtains the directory for storing files for the application on the device's internal storage. + * + * @return Returns the application file directory. + */ +std::string AbilityContext::GetFilesDir() +{ + return ContextContainer::GetFilesDir(); +} + +/** + * @brief Obtains the absolute path which app created and will be excluded from automatic backup to remote storage. + * The returned path maybe changed if the application is moved to an adopted storage device. + * + * @return The path of the directory holding application files that will not be automatically backed up to remote + * storage. + */ +std::string AbilityContext::GetNoBackupFilesDir() +{ + return ContextContainer::GetNoBackupFilesDir(); +} + +/** + * @brief Remove permissions for all users who have access to specific permissions + * + * @param permission Indicates the permission to unauth. This parameter cannot be null. + * @param uri Indicates the URI to unauth. This parameter cannot be null. + * @param uid Indicates the UID of the unauth to check. + * + */ +void AbilityContext::UnauthUriPermission(const std::string &permission, const Uri &uri, int uid) +{ + ContextContainer::UnauthUriPermission(permission, uri, uid); +} + +/** + * @brief Obtains the distributed file path. + * If the distributed file path does not exist, the system creates one and returns the created path. This method is + * applicable only to the context of an ability rather than that of an application. + * + * @return Returns the distributed file. + */ +std::string AbilityContext::GetDistributedDir() +{ + return ContextContainer::GetDistributedDir(); +} + +/** + * @brief Sets the pattern of this Context based on the specified pattern ID. + * + * @param patternId Indicates the resource ID of the pattern to set. + */ +void AbilityContext::SetPattern(int patternId) +{ + ContextContainer::SetPattern(patternId); +} + +/** + * @brief Obtains the Context object of this ability. + * + * @return Returns the Context object of this ability. + */ +std::shared_ptr AbilityContext::GetAbilityPackageContext() +{ + return ContextContainer::GetAbilityPackageContext(); +} + +/** + * @brief Obtains the name of the current process. + * + * @return Returns the current process name. + */ +std::string AbilityContext::GetProcessName() +{ + return ContextContainer::GetProcessName(); +} + +/** + * @brief InitResourceManager + * + * @param bundleInfo BundleInfo + */ +void AbilityContext::InitResourceManager(BundleInfo &bundleInfo, std::shared_ptr &deal) +{ + ContextContainer::InitResourceManager(bundleInfo, deal); +} + +/** + * @brief Get the string of this Context based on the specified resource ID. + * + * @param resId Indicates the resource ID of the string to get. + * + * @return Returns the string of this Context. + */ +std::string AbilityContext::GetString(int resId) +{ + return ContextContainer::GetString(resId); +} + +/** + * @brief Get the string array of this Context based on the specified resource ID. + * + * @param resId Indicates the resource ID of the string array to get. + * + * @return Returns the string array of this Context. + */ +std::vector AbilityContext::GetStringArray(int resId) +{ + return ContextContainer::GetStringArray(resId); +} + +/** + * @brief Get the integer array of this Context based on the specified resource ID. + * + * @param resId Indicates the resource ID of the integer array to get. + * + * @return Returns the integer array of this Context. + */ +std::vector AbilityContext::GetIntArray(int resId) +{ + return ContextContainer::GetIntArray(resId); +} + +/** + * @brief Obtains the theme of this Context. + * + * @return theme Returns the theme of this Context. + */ +std::map AbilityContext::GetTheme() +{ + return ContextContainer::GetTheme(); +} + +/** + * @brief Sets the theme of this Context based on the specified theme ID. + * + * @param themeId Indicates the resource ID of the theme to set. + */ +void AbilityContext::SetTheme(int themeId) +{ + ContextContainer::SetTheme(themeId); +} + +/** + * @brief Obtains the pattern of this Context. + * + * @return getPattern in interface Context + */ +std::map AbilityContext::GetPattern() +{ + return ContextContainer::GetPattern(); +} + +/** + * @brief Get the color of this Context based on the specified resource ID. + * + * @param resId Indicates the resource ID of the color to get. + * + * @return Returns the color value of this Context. + */ +int AbilityContext::GetColor(int resId) +{ + return ContextContainer::GetColor(resId); +} + +/** + * @brief Obtains the theme id of this Context. + * + * @return int Returns the theme id of this Context. + */ +int AbilityContext::GetThemeId() +{ + return ContextContainer::GetThemeId(); +} + +/** + * @brief + * Destroys this Service ability if the number of times it has been started equals the number represented by the + * given {@code startId}. This method is the same as calling {@link #terminateAbility} to destroy this Service + * ability, except that this method helps you avoid destroying it if a client has requested a Service + * ability startup in {@link ohos.aafwk.ability.Ability#onCommand} but you are unaware of it. + * + * @param startId Indicates the number of startup times of this Service ability passed to + * {@link ohos.aafwk.ability.Ability#onCommand}. The {@code startId} is + * incremented by 1 every time this ability is started. For example, + * if this ability has been started for six times, the value of {@code startId} is {@code 6}. + * + * @return Returns {@code true} if the {@code startId} matches the number of startup times + * and this Service ability will be destroyed; returns {@code false} otherwise. + */ +bool AbilityContext::TerminateAbilityResult(int startId) +{ + APP_LOGI("%{public}s begin.", __func__); + auto abilityClient = AAFwk::AbilityManagerClient::GetInstance(); + if (abilityClient == nullptr) { + APP_LOGE("AbilityContext::TerminateAbilityResult abilityClient is nullptr"); + return false; + } + + APP_LOGI("%{public}s begin ams->TerminateAbilityResult, startId=%{public}d.", __func__, startId); + ErrCode errval = abilityClient->TerminateAbilityResult(token_, startId); + APP_LOGI("%{public}s end ams->TerminateAbilityResult, ret=%{public}d.", __func__, errval); + if (errval != ERR_OK) { + APP_LOGE("AbilityContext::TerminateAbilityResult TerminateAbilityResult retval is %d", errval); + } + + APP_LOGI("%{public}s end.", __func__); + return (errval == ERR_OK) ? true : false; +} + +/** + * @brief Obtains the current display orientation of this ability. + * + * @return Returns the current display orientation. + */ +int AbilityContext::GetDisplayOrientation() +{ + return ContextContainer::GetDisplayOrientation(); +} + +/** + * @brief Obtains the path storing the preference file of the application. + * If the preference file path does not exist, the system creates one and returns the created path. + * + * @return Returns the preference file path . + */ +std::string AbilityContext::GetPreferencesDir() +{ + return ContextContainer::GetPreferencesDir(); +} + +/** + * @brief Set color mode + * + * @param the value of color mode. + */ +void AbilityContext::SetColorMode(int mode) +{ + ContextContainer::SetColorMode(mode); +} + +/** + * @brief Obtains color mode. + * + * @return Returns the color mode value. + */ +int AbilityContext::GetColorMode() +{ + return ContextContainer::GetColorMode(); +} + +/** + * @brief Obtains the unique ID of the mission containing this ability. + * + * @return Returns the unique mission ID. + */ +int AbilityContext::GetMissionId() +{ + return ContextContainer::GetMissionId(); +} + +/** + * @brief Call this when your ability should be closed and the mission should be completely removed as a part of + * finishing the root ability of the mission. + */ +void AbilityContext::TerminateAndRemoveMission() +{ + ContextContainer::TerminateAndRemoveMission(); +} + +/** + * @brief Starts multiple abilities. + * + * @param wants Indicates the Want containing information array about the target ability to start. + */ +void AbilityContext::StartAbilities(const std::vector &wants) +{ + APP_LOGI("%{public}s begin.", __func__); + for (auto want : wants) { + StartAbility(want, ABILITY_CONTEXT_DEFAULT_REQUEST_CODE); + } + APP_LOGI("%{public}s end.", __func__); +} + +/** + * @brief Checks whether this ability is the first ability in a mission. + * + * @return Returns true is first in Mission. + */ +bool AbilityContext::IsFirstInMission() +{ + APP_LOGI("%{public}s begin.", __func__); + auto abilityClient = AAFwk::AbilityManagerClient::GetInstance(); + if (abilityClient == nullptr) { + APP_LOGE("AbilityContext::IsFirstInMission abilityClient is nullptr"); + return false; + } + APP_LOGI("%{public}s begin ams->IsFirstInMission.", __func__); + ErrCode errval = abilityClient->IsFirstInMission(token_); + APP_LOGI("%{public}s end ams->IsFirstInMission, ret=%{public}d", __func__, errval); + if (errval != ERR_OK) { + APP_LOGE("AbilityContext::IsFirstInMission IsFirstInMission retval is %d", errval); + } + APP_LOGI("%{public}s end.", __func__); + + return (errval == ERR_OK) ? true : false; +} + +/** + * @brief Check whether it wants to operate a remote ability + * + * @param want Indicates the Want containing information about the ability to start. + * + * @return return true if it wamts to operate a remote ability, ohterwise return false. + */ +bool AbilityContext::CheckIfOperateRemote(const Want &want) +{ + if (want.GetElement().GetDeviceID() != "") { + return true; + } + return false; +} + +/** + * @brief Obtains a distributedSchedService. + * + * @return Returns an IDistributedSched proxy. + */ +std::shared_ptr AbilityContext::GetDistributedSchedServiceProxy() +{ + APP_LOGI("%{public}s begin.", __func__); + auto remoteObject = OHOS::DelayedSingleton::GetInstance()->GetSystemAbility(DISTRIBUTED_SCHED_SA_ID); + if (remoteObject == nullptr) { + APP_LOGE("failed to get dms service"); + return nullptr; + } + + APP_LOGI("get dms proxy success."); + std::shared_ptr proxy = nullptr; + proxy = std::make_shared(remoteObject); + APP_LOGI("%{public}s end.", __func__); + return proxy; +} + +/** + * @brief Obtains a task dispatcher that is bound to the UI thread. + * + * @return Returns the task dispatcher that is bound to the UI thread. + */ +std::shared_ptr AbilityContext::GetUITaskDispatcher() +{ + return ContextContainer::GetUITaskDispatcher(); +} + +/** + * @brief Obtains a task dispatcher that is bound to the application main thread. + * + * @return Returns the task dispatcher that is bound to the application main thread. + */ +std::shared_ptr AbilityContext::GetMainTaskDispatcher() +{ + return ContextContainer::GetMainTaskDispatcher(); +} +/** + * @brief Creates a parallel task dispatcher with a specified priority. + * + * @param name Indicates the task dispatcher name. This parameter is used to locate problems. + * @param priority Indicates the priority of all tasks dispatched by the parallel task dispatcher. + * + * @return Returns a parallel task dispatcher. + */ +std::shared_ptr AbilityContext::CreateParallelTaskDispatcher( + const std::string &name, const TaskPriority &priority) +{ + return ContextContainer::CreateParallelTaskDispatcher(name, priority); +} + +/** + * @brief Creates a serial task dispatcher with a specified priority. + * + * @param name Indicates the task dispatcher name. This parameter is used to locate problems. + * @param priority Indicates the priority of all tasks dispatched by the created task dispatcher. + * + * @return Returns a serial task dispatcher. + */ +std::shared_ptr AbilityContext::CreateSerialTaskDispatcher( + const std::string &name, const TaskPriority &priority) +{ + return ContextContainer::CreateSerialTaskDispatcher(name, priority); +} + +/** + * @brief Obtains a global task dispatcher with a specified priority. + * + * @param priority Indicates the priority of all tasks dispatched by the global task dispatcher. + * + * @return Returns a global task dispatcher. + */ +std::shared_ptr AbilityContext::GetGlobalTaskDispatcher(const TaskPriority &priority) +{ + return ContextContainer::GetGlobalTaskDispatcher(priority); +} + +/** + * @brief Requires that tasks associated with a given capability token be moved to the background + * + * @param nonFirst If nonfirst is false and not the lowest ability of the mission, you cannot move mission to end + * + * @return Returns true on success, others on failure. + */ +bool AbilityContext::MoveMissionToEnd(bool nonFirst) +{ + return ContextContainer::MoveMissionToEnd(nonFirst); +} + +/** + * @brief Sets the application to start its ability in lock mission mode. + */ +void AbilityContext::LockMission() +{ + ContextContainer::LockMission(); +} + +/** + * @brief Unlocks this ability by exiting the lock mission mode. + */ +void AbilityContext::UnlockMission() +{ + ContextContainer::UnlockMission(); +} + +/** + * @brief Sets description information about the mission containing this ability. + * + * @param MissionInformation Indicates the object containing information about the + * mission. This parameter cannot be null. + * @return Returns true on success, others on failure. + */ +bool AbilityContext::SetMissionInformation(const MissionInformation &missionInformation) +{ + return ContextContainer::SetMissionInformation(missionInformation); +} + +} // namespace AppExecFwk +} // namespace OHOS diff --git a/tools/frameworks/kits/ability/native/src/ability_handler.cpp b/tools/frameworks/kits/ability/native/src/ability_handler.cpp new file mode 100644 index 00000000000..9a1ecd067b4 --- /dev/null +++ b/tools/frameworks/kits/ability/native/src/ability_handler.cpp @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ability_handler.h" + +namespace OHOS { +namespace AppExecFwk { +AbilityHandler::AbilityHandler(const std::shared_ptr &runner, const sptr &server) + : EventHandler(runner), server_(server) +{} + +/** + * Process the event. Developers should override this method. + * + * @param event The event should be processed. + */ +void AbilityHandler::ProcessEvent([[maybe_unused]] const InnerEvent::Pointer &event) +{} +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/src/ability_impl.cpp b/tools/frameworks/kits/ability/native/src/ability_impl.cpp new file mode 100644 index 00000000000..1126bd8e857 --- /dev/null +++ b/tools/frameworks/kits/ability/native/src/ability_impl.cpp @@ -0,0 +1,777 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ability_impl.h" +#include "app_log_wrapper.h" +#include "data_ability_predicates.h" +#include "values_bucket.h" +#include "ability_keyevent.h" +#include "ability_touchevent.h" + +namespace OHOS { +namespace AppExecFwk { +void AbilityImpl::Init(std::shared_ptr &application, const std::shared_ptr &record, + std::shared_ptr &ability, std::shared_ptr &handler, const sptr &token, + std::shared_ptr &contextDeal) +{ + APP_LOGI("AbilityImpl::init begin"); + + if ((token == nullptr) || (application == nullptr) || (handler == nullptr) || (record == nullptr) || + ability == nullptr || contextDeal == nullptr) { + APP_LOGE("AbilityImpl::init failed, token is nullptr, application is nullptr, handler is nullptr, record is " + "nullptr, ability is nullptr, contextDeal is nullptr"); + return; + } + + token_ = record->GetToken(); + record->SetAbilityImpl(shared_from_this()); + ability_ = ability; + ability_->Init(record->GetAbilityInfo(), application, handler, token); + lifecycleState_ = AAFwk::ABILITY_STATE_INITIAL; + abilityLifecycleCallbacks_ = application; + contextDeal_ = contextDeal; + + // Multimodal Events +#ifdef MMI_COMPILE + abilityKeyEventHandle_ = sptr(new (std::nothrow) AbilityKeyEventHandle(shared_from_this())); + abilityTouchEventHandle_ = + sptr(new (std::nothrow) AbilityTouchEventHandle(shared_from_this())); +#endif + + APP_LOGI("AbilityImpl::init end"); +} + +/** + * @brief Toggles the lifecycle status of Ability to AAFwk::ABILITY_STATE_INACTIVE. And notifies the application + * that it belongs to of the lifecycle status. + * + * @param want The Want object to switch the life cycle. + */ +void AbilityImpl::Start(const Want &want) +{ + APP_LOGI("%{public}s begin.", __func__); + if (ability_ == nullptr || abilityLifecycleCallbacks_ == nullptr) { + APP_LOGE("AbilityImpl::Start ability_ or abilityLifecycleCallbacks_ is nullptr"); + return; + } + + if (ability_->GetAbilityInfo()->type == AbilityType::PAGE) { + ability_->HandleCreateAsContinuation(want); + } + + APP_LOGI("AbilityImpl::Start"); + ability_->OnStart(want); + if (ability_->GetAbilityInfo()->type == AbilityType::DATA) { + lifecycleState_ = AAFwk::ABILITY_STATE_ACTIVE; + } else { + lifecycleState_ = AAFwk::ABILITY_STATE_INACTIVE; + } + + abilityLifecycleCallbacks_->OnAbilityStart(ability_); + + // Multimodal Events Register + MMIRegister(); + APP_LOGI("%{public}s end.", __func__); +} + +/** + * @brief Toggles the lifecycle status of Ability to AAFwk::ABILITY_STATE_INITIAL. And notifies the application + * that it belongs to of the lifecycle status. + * + */ +void AbilityImpl::Stop() +{ + APP_LOGI("%{public}s begin.", __func__); + if (ability_ == nullptr || abilityLifecycleCallbacks_ == nullptr) { + APP_LOGE("AbilityImpl::Stop ability_ or abilityLifecycleCallbacks_ is nullptr"); + return; + } + + APP_LOGI("AbilityImpl::Stop"); + ability_->OnStop(); + lifecycleState_ = AAFwk::ABILITY_STATE_INITIAL; + abilityLifecycleCallbacks_->OnAbilityStop(ability_); + + // Multimodal Events UnRegister + MMIUnRegister(); + APP_LOGI("%{public}s end.", __func__); +} + +/** + * @brief Toggles the lifecycle status of Ability to AAFwk::ABILITY_STATE_ACTIVE. And notifies the application + * that it belongs to of the lifecycle status. + * + */ +void AbilityImpl::Active() +{ + APP_LOGI("%{public}s begin.", __func__); + if (ability_ == nullptr || abilityLifecycleCallbacks_ == nullptr) { + APP_LOGE("AbilityImpl::Active ability_ or abilityLifecycleCallbacks_ is nullptr"); + return; + } + + APP_LOGI("AbilityImpl::Active"); + ability_->OnActive(); + + if ((lifecycleState_ == AAFwk::ABILITY_STATE_INACTIVE) && (ability_->GetAbilityInfo()->type == AbilityType::PAGE)) { + ability_->OnTopActiveAbilityChanged(true); + ability_->OnWindowFocusChanged(true); + } + + lifecycleState_ = AAFwk::ABILITY_STATE_ACTIVE; + abilityLifecycleCallbacks_->OnAbilityActive(ability_); + APP_LOGI("%{public}s end.", __func__); +} + +/** + * @brief Toggles the lifecycle status of Ability to AAFwk::ABILITY_STATE_INACTIVE. And notifies the application + * that it belongs to of the lifecycle status. + * + */ +void AbilityImpl::Inactive() +{ + APP_LOGI("%{public}s begin.", __func__); + if (ability_ == nullptr || abilityLifecycleCallbacks_ == nullptr) { + APP_LOGE("AbilityImpl::Inactive ability_ or abilityLifecycleCallbacks_ is nullptr"); + return; + } + + APP_LOGI("AbilityImpl::Inactive"); + ability_->OnInactive(); + + if ((lifecycleState_ == AAFwk::ABILITY_STATE_ACTIVE) && (ability_->GetAbilityInfo()->type == AbilityType::PAGE)) { + ability_->OnTopActiveAbilityChanged(false); + ability_->OnWindowFocusChanged(false); + } + + lifecycleState_ = AAFwk::ABILITY_STATE_INACTIVE; + abilityLifecycleCallbacks_->OnAbilityInactive(ability_); + APP_LOGI("%{public}s end.", __func__); +} + +/** + * @brief Toggles the lifecycle status of Ability to AAFwk::ABILITY_STATE_INACTIVE. And notifies the application + * that it belongs to of the lifecycle status. + * + * @param want The Want object to switch the life cycle. + */ +void AbilityImpl::Foreground(const Want &want) +{ + APP_LOGI("%{public}s begin.", __func__); + if (ability_ == nullptr || abilityLifecycleCallbacks_ == nullptr) { + APP_LOGE("AbilityImpl::Foreground ability_ or abilityLifecycleCallbacks_ is nullptr"); + return; + } + + APP_LOGI("AbilityImpl::Foreground"); + ability_->OnForeground(want); + lifecycleState_ = AAFwk::ABILITY_STATE_INACTIVE; + abilityLifecycleCallbacks_->OnAbilityForeground(ability_); + APP_LOGI("%{public}s end.", __func__); +} + +/** + * @brief Toggles the lifecycle status of Ability to AAFwk::ABILITY_STATE_BACKGROUND. And notifies the application + * that it belongs to of the lifecycle status. + * + */ +void AbilityImpl::Background() +{ + APP_LOGI("%{public}s begin.", __func__); + if (ability_ == nullptr || abilityLifecycleCallbacks_ == nullptr) { + APP_LOGE("AbilityImpl::Background ability_ or abilityLifecycleCallbacks_ is nullptr"); + return; + } + + APP_LOGI("AbilityImpl::Background"); + ability_->OnLeaveForeground(); + ability_->OnBackground(); + lifecycleState_ = AAFwk::ABILITY_STATE_BACKGROUND; + abilityLifecycleCallbacks_->OnAbilityBackground(ability_); + APP_LOGI("%{public}s end.", __func__); +} + +/** + * @brief Save data and states of an ability when it is restored by the system. and Calling information back to Ability. + * This method should be implemented by a Page ability. + * @param instate The Want object to connect to. + * + */ +void AbilityImpl::DispatchSaveAbilityState(PacMap &outState) +{ + APP_LOGI("%{public}s begin.", __func__); + if (ability_ == nullptr || abilityLifecycleCallbacks_ == nullptr) { + APP_LOGE("AbilityImpl::DispatchSaveAbilityState ability_ or abilityLifecycleCallbacks_ is nullptr"); + return; + } + + APP_LOGI("AbilityImpl::DispatchSaveAbilityState"); + ability_->OnSaveAbilityState(outState); + abilityLifecycleCallbacks_->OnAbilitySaveState(outState); + APP_LOGI("%{public}s end.", __func__); +} + +/** + * @brief Restores data and states of an ability when it is restored by the system. and Calling information back to + * Ability. This method should be implemented by a Page ability. + * @param instate The Want object to connect to. + * + */ +void AbilityImpl::DispatchRestoreAbilityState(const PacMap &inState) +{ + APP_LOGI("%{public}s begin.", __func__); + if (ability_ == nullptr) { + APP_LOGE("AbilityImpl::DispatchRestoreAbilityState ability_ is nullptr"); + return; + } + + hasSaveData_ = true; + restoreData_ = inState; + APP_LOGI("%{public}s end.", __func__); +} + +void AbilityImpl::HandleAbilityTransaction(const Want &want, const AAFwk::LifeCycleStateInfo &targetState) +{} + +/** + * @brief Connect the ability. and Calling information back to Ability. + * + * @param want The Want object to connect to. + * + */ +sptr AbilityImpl::ConnectAbility(const Want &want) +{ + APP_LOGI("%{public}s begin.", __func__); + if (ability_ == nullptr) { + APP_LOGE("AbilityImpl::ConnectAbility ability_ is nullptr"); + return nullptr; + } + + APP_LOGI("AbilityImpl:: ConnectAbility"); + sptr object = ability_->OnConnect(want); + lifecycleState_ = AAFwk::ABILITY_STATE_ACTIVE; + abilityLifecycleCallbacks_->OnAbilityActive(ability_); + APP_LOGI("%{public}s end.", __func__); + + return object; +} + +/** + * @brief Disconnects the connected object. + * + * @param want The Want object to disconnect to. + */ +void AbilityImpl::DisconnectAbility(const Want &want) +{ + APP_LOGI("%{public}s begin.", __func__); + if (ability_ == nullptr) { + APP_LOGE("AbilityImpl::DisconnectAbility ability_ is nullptr"); + return; + } + + ability_->OnDisconnect(want); + APP_LOGI("%{public}s end.", __func__); +} + +/** + * @brief Command the ability. and Calling information back to Ability. + * + * @param want The Want object to command to. + * + * * @param restart Indicates the startup mode. The value true indicates that Service is restarted after being + * destroyed, and the value false indicates a normal startup. + * + * @param startId Indicates the number of times the Service ability has been started. The startId is incremented by 1 + * every time the ability is started. For example, if the ability has been started for six times, the value of startId + * is 6. + */ +void AbilityImpl::CommandAbility(const Want &want, bool restart, int startId) +{ + APP_LOGI("%{public}s begin.", __func__); + if (ability_ == nullptr) { + APP_LOGE("AbilityImpl::CommandAbility ability_ is nullptr"); + return; + } + + APP_LOGI("AbilityImpl:: CommandAbility"); + ability_->OnCommand(want, restart, startId); + lifecycleState_ = AAFwk::ABILITY_STATE_ACTIVE; + abilityLifecycleCallbacks_->OnAbilityActive(ability_); + APP_LOGI("%{public}s end.", __func__); +} + +/** + * @brief Gets the current Ability status. + * + */ +int AbilityImpl::GetCurrentState() +{ + return lifecycleState_; +} + +/** + * @brief Execution the KeyDown callback of the ability + * @param keyCode Indicates the code of the key pressed. + * @param keyEvent Indicates the key-down event. + * + * @return Returns true if this event is handled and will not be passed further; returns false if this event is + * not handled and should be passed to other handlers. + * + */ +bool AbilityImpl::DoKeyDown(int keyCode, const KeyEvent &keyEvent) +{ + APP_LOGI("AbilityImpl::DoKeyDown called"); + return false; +} + +/** + * @brief Execution the KeyUp callback of the ability + * @param keyCode Indicates the code of the key released. + * @param keyEvent Indicates the key-up event. + * + * @return Returns true if this event is handled and will not be passed further; returns false if this event is + * not handled and should be passed to other handlers. + * + */ +bool AbilityImpl::DoKeyUp(int keyCode, const KeyEvent &keyEvent) +{ + APP_LOGI("AbilityImpl::DoKeyUp called"); + return false; +} + +/** + * @brief Called when a touch event is dispatched to this ability. The default implementation of this callback + * does nothing and returns false. + * @param touchEvent Indicates information about the touch event. + * + * @return Returns true if the event is handled; returns false otherwise. + * + */ +bool AbilityImpl::DoTouchEvent(const TouchEvent &touchEvent) +{ + APP_LOGI("AbilityImpl::DoTouchEvent called"); + return false; +} + +/** + * @brief Send the result code and data to be returned by this Page ability to the caller. + * When a Page ability is destroyed, the caller overrides the AbilitySlice#onAbilityResult(int, int, Want) method to + * receive the result set in the current method. This method can be called only after the ability has been initialized. + * + * @param requestCode Indicates the request code. + * @param resultCode Indicates the result code returned after the ability is destroyed. You can define the result code + * to identify an error. + * @param resultData Indicates the data returned after the ability is destroyed. You can define the data returned. This + * parameter can be null. + */ +void AbilityImpl::SendResult(int requestCode, int resultCode, const Want &resultData) +{ + APP_LOGI("%{public}s begin.", __func__); + if (ability_ == nullptr) { + APP_LOGE("AbilityImpl::SendResult ability_ is nullptr"); + return; + } + + if (resultData.HasParameter(OHOS_RESULT_PERMISSION_KEY) && resultData.HasParameter(OHOS_RESULT_PERMISSIONS_LIST) && + resultData.HasParameter(OHOS_RESULT_CALLER_BUNDLERNAME)) { + + if (resultCode > 0) { + std::vector permissions = resultData.GetStringArrayParam(OHOS_RESULT_PERMISSIONS_LIST); + std::vector grantYes = resultData.GetStringArrayParam(OHOS_RESULT_PERMISSIONS_LIST_YES); + std::vector grantNo = resultData.GetStringArrayParam(OHOS_RESULT_PERMISSIONS_LIST_NO); + std::vector grantResult; + int intOK = 0; + for (size_t i = 0; i < permissions.size(); i++) { + intOK = 0; + for (size_t j = 0; j < grantYes.size(); j++) { + if (permissions[i] == grantYes[j]) { + intOK = 1; + break; + } + } + grantResult.push_back(intOK); + } + APP_LOGI("%{public}s begin OnRequestPermissionsFromUserResult.", __func__); + ability_->OnRequestPermissionsFromUserResult(requestCode, permissions, grantResult); + APP_LOGI("%{public}s end OnRequestPermissionsFromUserResult.", __func__); + } else { + APP_LOGI("%{public}s user cancel permissions.", __func__); + } + } else { + ability_->OnAbilityResult(requestCode, resultCode, resultData); + } + APP_LOGI("%{public}s end.", __func__); +} + +/** + * @brief Called when the launch mode of an ability is set to singleInstance. This happens when you re-launch + * an ability that has been at the top of the ability stack. + * + * @param want Indicates the new Want containing information about the ability. + */ +void AbilityImpl::NewWant(const Want &want) +{ + APP_LOGI("%{public}s begin.", __func__); + if (ability_ == nullptr) { + APP_LOGE("AbilityImpl::NewWant ability_ is nullptr"); + return; + } + ability_->SetWant(want); + ability_->OnNewWant(want); + APP_LOGI("%{public}s end.", __func__); +} + +/** + * @brief Obtains the MIME types of files supported. + * + * @param uri Indicates the path of the files to obtain. + * @param mimeTypeFilter Indicates the MIME types of the files to obtain. This parameter cannot be null. + * + * @return Returns the matched MIME types. If there is no match, null is returned. + */ +std::vector AbilityImpl::GetFileTypes(const Uri &uri, const std::string &mimeTypeFilter) +{ + std::vector types; + return types; +} + +/** + * @brief Opens a file in a specified remote path. + * + * @param uri Indicates the path of the file to open. + * @param mode Indicates the file open mode, which can be "r" for read-only access, "w" for write-only access + * (erasing whatever data is currently in the file), "wt" for write access that truncates any existing file, + * "wa" for write-only access to append to any existing data, "rw" for read and write access on any existing data, + * or "rwt" for read and write access that truncates any existing file. + * + * @return Returns the file descriptor. + */ +int AbilityImpl::OpenFile(const Uri &uri, const std::string &mode) +{ + return -1; +} + +/** + * @brief This is like openFile, open a file that need to be able to return sub-sections of files,often assets + * inside of their .hap. + * + * @param uri Indicates the path of the file to open. + * @param mode Indicates the file open mode, which can be "r" for read-only access, "w" for write-only access + * (erasing whatever data is currently in the file), "wt" for write access that truncates any existing file, + * "wa" for write-only access to append to any existing data, "rw" for read and write access on any existing + * data, or "rwt" for read and write access that truncates any existing file. + * + * @return Returns the RawFileDescriptor object containing file descriptor. + */ +int AbilityImpl::OpenRawFile(const Uri &uri, const std::string &mode) +{ + return -1; +} + +/** + * @brief Inserts a single data record into the database. + * + * @param uri Indicates the path of the data to operate. + * @param value Indicates the data record to insert. If this parameter is null, a blank row will be inserted. + * + * @return Returns the index of the inserted data record. + */ +int AbilityImpl::Insert(const Uri &uri, const NativeRdb::ValuesBucket &value) +{ + return -1; +} + +/** + * @brief Updates data records in the database. + * + * @param uri Indicates the path of data to update. + * @param value Indicates the data to update. This parameter can be null. + * @param predicates Indicates filter criteria. You should define the processing logic when this parameter is null. + * + * @return Returns the number of data records updated. + */ +int AbilityImpl::Update( + const Uri &uri, const NativeRdb::ValuesBucket &value, const NativeRdb::DataAbilityPredicates &predicates) +{ + return -1; +} + +/** + * @brief Deletes one or more data records from the database. + * + * @param uri Indicates the path of the data to operate. + * @param predicates Indicates filter criteria. You should define the processing logic when this parameter is null. + * + * @return Returns the number of data records deleted. + */ +int AbilityImpl::Delete(const Uri &uri, const NativeRdb::DataAbilityPredicates &predicates) +{ + return -1; +} + +/** + * @brief Deletes one or more data records from the database. + * + * @param uri Indicates the path of data to query. + * @param columns Indicates the columns to query. If this parameter is null, all columns are queried. + * @param predicates Indicates filter criteria. You should define the processing logic when this parameter is null. + * + * @return Returns the query result. + */ +std::shared_ptr AbilityImpl::Query( + const Uri &uri, std::vector &columns, const NativeRdb::DataAbilityPredicates &predicates) +{ + return nullptr; +} + +/** + * @brief Obtains the MIME type matching the data specified by the URI of the Data ability. This method should be + * implemented by a Data ability. Data abilities supports general data types, including text, HTML, and JPEG. + * + * @param uri Indicates the URI of the data. + * + * @return Returns the MIME type that matches the data specified by uri. + */ +std::string AbilityImpl::GetType(const Uri &uri) +{ + return ""; +} + +/** + * @brief Reloads data in the database. + * + * @param uri Indicates the position where the data is to reload. This parameter is mandatory. + * @param extras Indicates the PacMap object containing the additional parameters to be passed in this call. This + * parameter can be null. If a custom Sequenceable object is put in the PacMap object and will be transferred across + * processes, you must call BasePacMap.setClassLoader(ClassLoader) to set a class loader for the custom object. + * + * @return Returns true if the data is successfully reloaded; returns false otherwise. + */ +bool AbilityImpl::Reload(const Uri &uri, const PacMap &extras) +{ + return false; +} + +/** + * @brief Inserts multiple data records into the database. + * + * @param uri Indicates the path of the data to operate. + * @param values Indicates the data records to insert. + * + * @return Returns the number of data records inserted. + */ +int AbilityImpl::BatchInsert(const Uri &uri, const std::vector &values) +{ + return -1; +} + +/** + * @brief SerUriString + */ +void AbilityImpl::SerUriString(const std::string &uri) +{ + APP_LOGI("%{public}s begin.", __func__); + if (contextDeal_ == nullptr) { + APP_LOGE("AbilityImpl::SerUriString contextDeal_ is nullptr"); + return; + } + contextDeal_->SerUriString(uri); + APP_LOGI("%{public}s end.", __func__); +} + +/** + * @brief Set the LifeCycleStateInfo to the deal. + * + * @param info the info to set. + */ +void AbilityImpl::SetLifeCycleStateInfo(const AAFwk::LifeCycleStateInfo &info) +{ + if (contextDeal_ == nullptr) { + APP_LOGE("AbilityImpl::SetLifeCycleStateInfo contextDeal_ is nullptr"); + return; + } + contextDeal_->SetLifeCycleStateInfo(info); +} + +/** + * @brief Check if it needs to restore the data to the ability. + * + * @return Return true if need and success, otherwise return false. + */ +bool AbilityImpl::CheckAndRestore() +{ + APP_LOGI("AbilityImpl::CheckAndRestore called start"); + if (!hasSaveData_) { + APP_LOGE("AbilityImpl::CheckAndRestore hasSaveData_ is false"); + return false; + } + + if (ability_ == nullptr) { + APP_LOGE("AbilityImpl::CheckAndRestore ability_ is nullptr"); + return false; + } + + APP_LOGI("AbilityImpl::CheckAndRestore ready to restore"); + ability_->OnRestoreAbilityState(restoreData_); + + APP_LOGI("AbilityImpl::CheckAndRestore called end"); + return true; +} + +/** + * @brief Set deviceId/bundleName/abilityName of the calling ability + * + * @param deviceId deviceId of the calling ability + * + * @param deviceId bundleName of the calling ability + * + * @param deviceId abilityName of the calling ability + */ +void AbilityImpl::SetCallingContext( + const std::string &deviceId, const std::string &bundleName, const std::string &abilityName) +{ + if (ability_ != nullptr) { + ability_->SetCallingContext(deviceId, bundleName, abilityName); + } +} + +/** + * @brief Converts the given uri that refer to the Data ability into a normalized URI. A normalized URI can be used + * across devices, persisted, backed up, and restored. It can refer to the same item in the Data ability even if the + * context has changed. If you implement URI normalization for a Data ability, you must also implement + * denormalizeUri(ohos.utils.net.Uri) to enable URI denormalization. After this feature is enabled, URIs passed to any + * method that is called on the Data ability must require normalization verification and denormalization. The default + * implementation of this method returns null, indicating that this Data ability does not support URI normalization. + * + * @param uri Indicates the Uri object to normalize. + * + * @return Returns the normalized Uri object if the Data ability supports URI normalization; returns null otherwise. + */ +Uri AbilityImpl::NormalizeUri(const Uri &uri) +{ + return uri; +} + +/** + * @brief Converts the given normalized uri generated by normalizeUri(ohos.utils.net.Uri) into a denormalized one. + * The default implementation of this method returns the original URI passed to it. + * + * @param uri uri Indicates the Uri object to denormalize. + * + * @return Returns the denormalized Uri object if the denormalization is successful; returns the original Uri passed to + * this method if there is nothing to do; returns null if the data identified by the original Uri cannot be found in the + * current environment. + */ +Uri AbilityImpl::DenormalizeUri(const Uri &uri) +{ + return uri; +} + +/* + * @brief ScheduleUpdateConfiguration, scheduling update configuration. + */ +void AbilityImpl::ScheduleUpdateConfiguration(const AAFwk::DummyConfiguration &config) +{ + APP_LOGI("%{public}s begin.", __func__); + if (ability_ == nullptr) { + APP_LOGE("AbilityImpl::ScheduleUpdateConfiguration ability_ is nullptr"); + } + + Configuration configtest; + ability_->OnConfigurationUpdated(configtest); + APP_LOGI("%{public}s end.", __func__); +} +/** + * @brief Multimodal Events Register. + */ +void AbilityImpl::MMIRegister() +{ +#ifdef MMI_COMPILE + APP_LOGI("%{public}s called.", __func__); + int32_t ret = 0; + int32_t windowID = 0; + if (ability_->GetAbilityInfo()->type == AppExecFwk::AbilityType::PAGE) { + if (ability_->GetWindow() != nullptr) { + windowID = ability_->GetWindow()->GetWindowID(); + } + } + + // register keyEvent + ret = MMIEventHdl->RegisterStandardizedEventHandle(token_, windowID, abilityKeyEventHandle_); + APP_LOGI("MMIRegister :token:%{public}p windowID:%{public}d", token_.GetRefPtr(), windowID); + APP_LOGI("MMIRegister :keyEventHandler:%{public}p", abilityKeyEventHandle_.GetRefPtr()); + APP_LOGI("MMIRegister :RegisterkeyEventHandler ret:%{public}d", ret); + + // register touchEvent + ret = MMIEventHdl->RegisterStandardizedEventHandle(token_, windowID, abilityTouchEventHandle_); + APP_LOGI("MMIRegister :token:%{public}p windowID:%{public}d", token_.GetRefPtr(), windowID); + APP_LOGI("MMIRegister :touchEventHandler:%{public}p", abilityTouchEventHandle_.GetRefPtr()); + APP_LOGI("MMIRegister :RegistertouchEventHandler ret:%{public}d", ret); +#endif +} + +/** + * @brief Multimodal Events UnRegister. + */ +void AbilityImpl::MMIUnRegister() +{ +#ifdef MMI_COMPILE + APP_LOGI("%{public}s called.", __func__); + int32_t ret = 0; + int32_t windowID = 0; + if (ability_->GetAbilityInfo()->type == AppExecFwk::AbilityType::PAGE) { + if (ability_->GetWindow() != nullptr) { + windowID = ability_->GetWindow()->GetWindowID(); + } + } + // unregister keyEvent + ret = MMIEventHdl->UnregisterStandardizedEventHandle(token_, windowID, abilityKeyEventHandle_); + APP_LOGI("MMIUnRegister :token:%{public}p windowID:%{public}d", token_.GetRefPtr(), windowID); + APP_LOGI("MMIUnRegister :keyEventHandler:%{public}p", abilityKeyEventHandle_.GetRefPtr()); + APP_LOGI("MMIUnRegister :UnRegisterkeyEventHandler ret:%{public}d", ret); + + // unregister touchEvent + ret = MMIEventHdl->UnregisterStandardizedEventHandle(token_, windowID, abilityTouchEventHandle_); + APP_LOGI("MMIUnRegister :token:%{public}p windowID:%{public}d", token_.GetRefPtr(), windowID); + APP_LOGI("MMIUnRegister :touchEventHandler:%{public}p", abilityTouchEventHandle_.GetRefPtr()); + APP_LOGI("MMIUnRegister :UnRegistertouchEventHandler ret:%{public}d", ret); +#endif +} + +/** + * @brief Create a PostEvent timeout task. The default delay is 5000ms + * + * @return Return a smart pointer to a timeout object + */ +std::shared_ptr AbilityImpl::CreatePostEventTimeouter(std::string taskstr) +{ + if (ability_ == nullptr) { + APP_LOGE("AbilityImpl::CreatePostEventTimeouter ability_ is nullptr"); + return nullptr; + } + + return ability_->CreatePostEventTimeouter(taskstr); +} + +std::vector> AbilityImpl::ExecuteBatch( + const std::vector> &operations) +{ + APP_LOGI("AbilityImpl::ExecuteBatch"); + std::vector> results; + return results; +} + +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/src/ability_impl_factory.cpp b/tools/frameworks/kits/ability/native/src/ability_impl_factory.cpp new file mode 100644 index 00000000000..b08a8bd8731 --- /dev/null +++ b/tools/frameworks/kits/ability/native/src/ability_impl_factory.cpp @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ability_impl_factory.h" +#include "app_log_wrapper.h" +#include "data_ability_impl.h" +#include "page_ability_impl.h" +#include "service_ability_impl.h" + +namespace OHOS { +namespace AppExecFwk { +/** + * + * default constructor + * + */ +AbilityImplFactory::AbilityImplFactory() +{} + +/** + * + * default Destructor + * + */ +AbilityImplFactory::~AbilityImplFactory() +{} + +/** + * @brief Create impl object based on abilitytype + * + * @param type AbilityType:PAGE/SERVICE/PROVIDER + * + * @return AbilityImpl object + */ +std::shared_ptr AbilityImplFactory::MakeAbilityImplObject(const std::shared_ptr &info) +{ + if (info == nullptr) { + APP_LOGE("AbilityImplFactory::MakeAbilityImplObject is error nullptr == info "); + return nullptr; + } + + std::shared_ptr abilityImpl = nullptr; + APP_LOGI("AbilityImplFactory::MakeAbilityImplObject type:%{public}d", info->type); + + switch (info->type) { + case AppExecFwk::AbilityType::PAGE: + abilityImpl = std::make_shared(); + break; + case AppExecFwk::AbilityType::SERVICE: + abilityImpl = std::make_shared(); + break; + case AppExecFwk::AbilityType::DATA: + abilityImpl = std::make_shared(); + break; + default: + APP_LOGE("AbilityImplFactory::MakeAbilityImplObject is error"); + break; + } + + return abilityImpl; +} +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/src/ability_keyevent.cpp b/tools/frameworks/kits/ability/native/src/ability_keyevent.cpp new file mode 100644 index 00000000000..f56205b9de9 --- /dev/null +++ b/tools/frameworks/kits/ability/native/src/ability_keyevent.cpp @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ability_keyevent.h" +#include "ability_impl.h" +#include "app_log_wrapper.h" +#include "ability_post_event_timeout.h" + +namespace OHOS { +namespace AppExecFwk { +AbilityKeyEventHandle::AbilityKeyEventHandle(const std::shared_ptr &abilityImpl) + : abilityImpl_(abilityImpl) +{ + APP_LOGI("AbilityKeyEventHandle is created"); +} + +AbilityKeyEventHandle::~AbilityKeyEventHandle() +{ + APP_LOGI("AbilityKeyEventHandle is destroyed"); +} + +#ifdef MMI_COMPILE +/** + * @brief Called back when on key. + */ +bool AbilityKeyEventHandle::OnKey(const KeyEvent &keyEvent) +{ + APP_LOGI("AbilityKeyEventHandle::OnKey called."); + bool ret = false; + if (abilityImpl_ == nullptr) { + APP_LOGE("AbilityImpl::OnKey abilityImpl_ is nullptr. KeyCode %{public}d.", keyEvent.GetKeyCode()); + return ret; + } + + if (keyEvent.IsKeyDown()) { + std::string taskHead("OnKey"); + std::string taskCode = std::to_string(keyEvent.GetKeyCode()); + std::string taskTail("Down"); + auto timeOut = abilityImpl_->CreatePostEventTimeouter(taskHead + taskCode + taskTail); + if (timeOut == nullptr) { + APP_LOGW("AbilityKeyEventHandle::OnKeyDown timeouter Create return nullptr"); + ret = abilityImpl_->DoKeyDown(keyEvent.GetKeyCode(), keyEvent); + } else { + timeOut->TimingBegin(); + ret = abilityImpl_->DoKeyDown(keyEvent.GetKeyCode(), keyEvent); + timeOut->TimeEnd(); + } + APP_LOGI("AbilityImpl::OnKeyDown keyCode: %{public}d.", keyEvent.GetKeyCode()); + } else { + std::string taskHead("OnKey"); + std::string taskCode = std::to_string(keyEvent.GetKeyCode()); + std::string taskTail("Up"); + auto timeOut = abilityImpl_->CreatePostEventTimeouter(taskHead + taskCode + taskTail); + if (timeOut == nullptr) { + APP_LOGW("AbilityKeyEventHandle::OnKeyUp timeouter Create return nullptr"); + ret = abilityImpl_->DoKeyUp(keyEvent.GetKeyCode(), keyEvent); + } else { + timeOut->TimingBegin(); + ret = abilityImpl_->DoKeyUp(keyEvent.GetKeyCode(), keyEvent); + timeOut->TimeEnd(); + } + APP_LOGI("AbilityImpl::DoKeyUp keyCode: %{public}d.", keyEvent.GetKeyCode()); + } + + APP_LOGI("AbilityKeyEventHandle::OnKey called end. return %{public}s", ret ? "true" : "false"); + return ret; +} +#endif +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/src/ability_lifecycle.cpp b/tools/frameworks/kits/ability/native/src/ability_lifecycle.cpp new file mode 100644 index 00000000000..f8d39c93754 --- /dev/null +++ b/tools/frameworks/kits/ability/native/src/ability_lifecycle.cpp @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ability_lifecycle_observer_interface.h" +#include "app_log_wrapper.h" + +namespace OHOS { +namespace AppExecFwk { +/** + * @brief Obtains the current lifecycle event. + * Lifecycle events drive lifecycle state changes. Therefore, you are able to know the lifecycle state + * once you obtain the lifecycle event. For example, if the ON_ACTIVE event is received, the ability or + * ability slice is in the ACTIVE state; if the ON_FOREGROUND event is received, the ability or ability + * slice is changing from the BACKGROUND state to INACTIVE. + * + * @return Returns the current lifecycle event. + */ +LifeCycle::Event LifeCycle::GetLifecycleState() +{ + APP_LOGI("LifeCycle::GetLifecycleState: called"); + return state_; +} + +/** + * @brief Adds a lifecycle observer. + * The observer will be notified of lifecycle changes. + * + * @param observer Indicates the lifecycle observer, either LifecycleObserver or LifecycleStateObserver. + * The value cannot be null. + * + */ +void LifeCycle::AddObserver(const std::shared_ptr &observer) +{ + APP_LOGI("LifeCycle::AddObserver: called"); + + if (observer == nullptr) { + APP_LOGI("LifeCycle::AddObserver: observer is null"); + return; + } + + callbacks_.emplace_back(observer); +} + +/** + * @brief While Ability's lifecycle changes, dispatch lifecycle event. + * + * @param event Lifecycle state. + * @param want Indicates the Want containing information about the target ability to change lifecycle state. + */ +void LifeCycle::DispatchLifecycle(const LifeCycle::Event &event, const Want &want) +{ + APP_LOGI("LifeCycle::DispatchLifecycle: called"); + + if ((event != LifeCycle::Event::ON_FOREGROUND) && (event != LifeCycle::Event::ON_START)) { + APP_LOGE("event value error: event is %{public}d", event); + return; + } + + state_ = event; + if (callbacks_.size() != 0) { + for (auto &callback : callbacks_) { + switch (event) { + case ON_FOREGROUND: { + if (callback != nullptr) { + callback->OnForeground(want); + } + break; + } + case ON_START: { + if (callback != nullptr) { + callback->OnStart(want); + } + break; + } + default: + break; + } + if (callback != nullptr) { + callback->OnStateChanged(event, want); + } + } + } +} + +/** + * @brief While Ability's lifecycle changes, dispatch lifecycle event. + * + * @param event Lifecycle state. + */ +void LifeCycle::DispatchLifecycle(const LifeCycle::Event &event) +{ + APP_LOGI("LifeCycle::DispatchLifecycle: called"); + + if ((event != LifeCycle::Event::ON_ACTIVE) && (event != LifeCycle::Event::ON_BACKGROUND) && + (event != LifeCycle::Event::ON_INACTIVE) && (event != LifeCycle::Event::ON_STOP)) { + APP_LOGE("event value error: event is %{public}d", event); + return; + } + + state_ = event; + if (callbacks_.size() != 0) { + for (auto &callback : callbacks_) { + switch (event) { + case ON_ACTIVE: { + if (callback != nullptr) { + callback->OnActive(); + } + break; + } + case ON_BACKGROUND: { + if (callback != nullptr) { + callback->OnBackground(); + } + break; + } + case ON_INACTIVE: { + if (callback != nullptr) { + callback->OnInactive(); + } + break; + } + case ON_STOP: { + if (callback != nullptr) { + callback->OnStop(); + } + break; + } + default: + break; + } + if (callback != nullptr) { + callback->OnStateChanged(event); + } + } + } +} + +/** + * @brief Removes a lifecycle observer. + * You are advised to call this method if you no longer need to listen to lifecycle changes. This reduces the + * performance loss caused by observing lifecycle changes. + * + * @param observer Indicates the lifecycle observer, either LifecycleObserver or LifecycleStateObserver. + * The value cannot be null. + */ +void LifeCycle::RemoveObserver(const std::shared_ptr &observer) +{ + APP_LOGI("LifeCycle::RemoveObserver: called"); + + if (observer == nullptr) { + APP_LOGI("LifeCycle::RemoveObserver: observer is null"); + return; + } + + callbacks_.remove(observer); +} +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/src/ability_lifecycle_executor.cpp b/tools/frameworks/kits/ability/native/src/ability_lifecycle_executor.cpp new file mode 100644 index 00000000000..d14ac37789a --- /dev/null +++ b/tools/frameworks/kits/ability/native/src/ability_lifecycle_executor.cpp @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ability_lifecycle_executor.h" + +namespace OHOS { +namespace AppExecFwk { +/** + * @brief While Ability's lifecycle changes, dispatch lifecycle state. + * + * @param state Lifecycle state. + */ +void AbilityLifecycleExecutor::DispatchLifecycleState(const AbilityLifecycleExecutor::LifecycleState &state) +{ + state_ = state; +} + +/** + * @brief Obtains the int value of the ability lifecycle state represented by the + * AbilityLifecycleExecutor.LifecycleState enum constant. + * + * @return return Returns the int value of the ability lifecycle state represented + * by the AbilityLifecycleExecutor.LifecycleState enum constant. + */ +int AbilityLifecycleExecutor::GetState() +{ + return state_; +} +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/src/ability_lifecycle_observer.cpp b/tools/frameworks/kits/ability/native/src/ability_lifecycle_observer.cpp new file mode 100644 index 00000000000..9c9b3d04766 --- /dev/null +++ b/tools/frameworks/kits/ability/native/src/ability_lifecycle_observer.cpp @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ability_lifecycle_observer.h" + +namespace OHOS { +namespace AppExecFwk { +/** + * @brief Called back in response to an ON_ACTIVE event. + * When an ON_ACTIVE event is received, the ability or ability slice is in the foreground and is interactive. + */ +void LifecycleObserver::OnActive() +{} + +/** + * @brief Called back in response to an ON_BACKGROUND event. + * When an ON_BACKGROUND event is received, the ability or ability slice is invisible. You are advised to + * suspend the threads related to this ability or ability slice and clear resources for more system memory. + * + */ +void LifecycleObserver::OnBackground() +{} + +/** + * @brief Called back in response to an ON_FOREGROUND event, where information for the + * ability or ability slice to go back to the ACTIVE state is carried in the want parameter. + * When an ON_FOREGROUND event is received, the ability or ability slice returns to the foreground. You can use + * this method to implement re-initialization or adjust the UI display by using the want parameter. + * + * @param want Indicates the information for the ability or ability slice to go back to the ACTIVE state. + */ +void LifecycleObserver::OnForeground(const Want &want) +{} + +/** + * @brief Called back in response to an ON_INACTIVE event. + * When an ON_INACTIVE event is received, the ability or ability slice is in the INACTIVE state. INACTIVE is an + * intermediate state before the state changes to ACTIVE or BACKGROUND. In this state, the UI may be visible but is + * not interactive. You are advised not to use this method to invoke complex service logic. + * + */ +void LifecycleObserver::OnInactive() +{} + +/** + * @brief Called back in response to an ON_START event, where the startup information + * is carried in the want parameter. + * This method initializes an Ability or AbilitySlice and is called back only once during the entire lifecycle. + * You are advised to implement some initialization logic using this method, for example, you can initialize a + * timer or define some global objects. + * + * @param want Indicates the startup information. + */ +void LifecycleObserver::OnStart(const Want &want) +{} + +/** + * @brief Called back in response to an ON_STOP event. + * This method is called back when the lifecycle of the ability or ability slice is destroyed. You can reclaim + * resources using this method. + * + */ +void LifecycleObserver::OnStop() +{} + +/** + * @brief Called back in response to a lifecycle change. This method is triggered by a registered LifecycleObserver + * each time the lifecycle state changes. + * + * @param event Indicates the lifecycle event. + * @param want Indicates the state change information. + */ +void LifecycleObserver::OnStateChanged(Lifecycle::Event event, const Want &want) +{} + +/** + * @brief Called back in response to a lifecycle change. This method is triggered by a registered LifecycleObserver + * each time the lifecycle state changes. + * + * @param event Indicates the lifecycle event. + */ +virtual void LifecycleObserver::OnStateChanged(LifeCycle::Event event) +{} +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/src/ability_loader.cpp b/tools/frameworks/kits/ability/native/src/ability_loader.cpp new file mode 100644 index 00000000000..9ab26530532 --- /dev/null +++ b/tools/frameworks/kits/ability/native/src/ability_loader.cpp @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ability_loader.h" +#include "app_log_wrapper.h" + +namespace OHOS { +namespace AppExecFwk { +AbilityLoader &AbilityLoader::GetInstance() +{ + static AbilityLoader abilityLoader; + return abilityLoader; +} + +/** + * @brief Register Ability Info + * + * @param abilityName ability classname + * @param createFunc Constructor address + */ +void AbilityLoader::RegisterAbility(const std::string &abilityName, const CreateAblity &createFunc) +{ + abilities_.emplace(abilityName, createFunc); + APP_LOGD("AbilityLoader::RegisterAbility:%{public}s", abilityName.c_str()); +} + +/** + * @brief Get Ability address + * + * @param abilityName ability classname + * + * @return return Ability address + */ +Ability *AbilityLoader::GetAbilityByName(const std::string &abilityName) +{ + auto it = abilities_.find(abilityName); + if (it != abilities_.end()) { + return it->second(); + } else { + APP_LOGE("AbilityLoader::GetAbilityByName failed:%{public}s", abilityName.c_str()); + } + return nullptr; +} + +#ifdef ABILITY_WINDOW_SUPPORT +void AbilityLoader::RegisterAbilitySlice(const std::string &sliceName, const CreateSlice &createFunc) +{ + slices_.emplace(sliceName, createFunc); + HILOG_INFO(HILOG_MODULE_APP, "RegisterAbilitySlice %s", sliceName.c_str()); +} + +AbilitySlice *AbilityLoader::GetAbilitySliceByName(const std::string &sliceName) +{ + auto it = slices_.find(sliceName); + if (it != slices_.end()) { + return it->second(); + } else { + HILOG_ERROR(HILOG_MODULE_APP, "GetAbilitySliceByName failed: %s", sliceName.c_str()); + return nullptr; + } +} +#endif +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/src/ability_local_record.cpp b/tools/frameworks/kits/ability/native/src/ability_local_record.cpp new file mode 100644 index 00000000000..ed9b424898e --- /dev/null +++ b/tools/frameworks/kits/ability/native/src/ability_local_record.cpp @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ability_local_record.h" +#include "ability_impl.h" + +namespace OHOS { +namespace AppExecFwk { +/** + * + * default constructor + * + */ +AbilityLocalRecord::AbilityLocalRecord(const std::shared_ptr &info, const sptr &token) + : abilityInfo_(info), token_(token) +{} + +/** + * + * @default Destructor + * + */ +AbilityLocalRecord::~AbilityLocalRecord() +{} + +/** + * @description: Get an AbilityInfo in an ability. + * + * @return Returns a pointer to abilityinfo + */ +const std::shared_ptr &AbilityLocalRecord::GetAbilityInfo() +{ + return abilityInfo_; +} + +/** + * @description: Get an EventHandler in an ability. + * + * @return Returns a pointer to EventHandler + */ +const std::shared_ptr &AbilityLocalRecord::GetEventHandler() +{ + return handler_; +} + +/** + * @description: Set an EventHandler in an ability. + * @param handler EventHandler object + * @return None. + */ +void AbilityLocalRecord::SetEventHandler(const std::shared_ptr &handler) +{ + handler_ = handler; +} + +/** + * @description: Get an EventRunner in an ability. + * + * @return Returns a pointer to EventRunner + */ +const std::shared_ptr &AbilityLocalRecord::GetEventRunner() +{ + return runner_; +} + +/** + * @description: Set an EventRunner in an ability. + * @param runner EventHandler object + * @return None. + */ +void AbilityLocalRecord::SetEventRunner(const std::shared_ptr &runner) +{ + runner_ = runner; +} + +/** + * @description: Gets the identity of the ability + * @return return the identity of the ability. + */ +const sptr &AbilityLocalRecord::GetToken() +{ + return token_; +} + +/** + * @description: Get an AbilityImpl in an ability. + * + * @return Returns AbilityImpl pointer + */ +const std::shared_ptr &AbilityLocalRecord::GetAbilityImpl() +{ + return abilityImpl_; +} + +/** + * @description: Set an AbilityImpl in an ability. + * @param abilityImpl AbilityImpl object + * @return None. + */ +void AbilityLocalRecord::SetAbilityImpl(const std::shared_ptr &abilityImpl) +{ + abilityImpl_ = abilityImpl; +} + +/** + * @description: Obtains the information based on ability thread. + * @return return AbilityThread Pointer + */ +const sptr &AbilityLocalRecord::GetAbilityThread() +{ + return abilityThread_; +} + +/** + * @description: Set an AbilityThread in an ability. + * @param abilityThread AbilityThread object + * @return None. + */ +void AbilityLocalRecord::SetAbilityThread(const sptr &abilityThread) +{ + abilityThread_ = abilityThread; +} +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/src/ability_post_event_timeout.cpp b/tools/frameworks/kits/ability/native/src/ability_post_event_timeout.cpp new file mode 100644 index 00000000000..55779e44954 --- /dev/null +++ b/tools/frameworks/kits/ability/native/src/ability_post_event_timeout.cpp @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "app_log_wrapper.h" +#include "ability_post_event_timeout.h" + +// #include "event_handler.h" +#include "ability_handler.h" + +namespace OHOS { +namespace AppExecFwk { + +const int64_t AbilityPostEventTimeout::defalutDelayTime = 5000; + +std::atomic AbilityPostEventTimeout::allocationId_ = 0; + +AbilityPostEventTimeout::AbilityPostEventTimeout(std::string str, std::shared_ptr &eventHandler) +{ + uint32_t taskId = allocationId_++; + std::string strId = std::to_string(taskId); + task_ = str + strId; + taskExec_ = false; + handler_ = eventHandler; + APP_LOGI("AbilityPostEventTimeout::AbilityPostEventTimeout() call %{public}s", task_.c_str()); +} +AbilityPostEventTimeout::~AbilityPostEventTimeout() +{ + APP_LOGI("AbilityPostEventTimeout::~AbilityPostEventTimeout() call %{public}s", task_.c_str()); + handler_.reset(); +} + +void AbilityPostEventTimeout::TimingBegin(int64_t delaytime) +{ + APP_LOGI("AbilityPostEventTimeout::TimingBegin() call %{public}s", task_.c_str()); + if (handler_ == nullptr) { + APP_LOGE("AbilityPostEventTimeout::TimingBegin %{public}s handler_ is nullptr", task_.c_str()); + return; + } + + auto task = [timeOutTask = shared_from_this()]() { timeOutTask->TimeOutProc(); }; + handler_->PostTask(task, task_, delaytime); +} +void AbilityPostEventTimeout::TimeEnd() +{ + APP_LOGI("AbilityPostEventTimeout::TimeEnd() call %{public}s", task_.c_str()); + if (handler_ == nullptr) { + APP_LOGE("AbilityPostEventTimeout::TimeEnd %{public}s handler_ is nullptr", task_.c_str()); + return; + } + + std::lock_guard lck(mtx_); + if (!taskExec_) { + taskExec_ = true; + handler_->RemoveTask(task_); + } +} + +void AbilityPostEventTimeout::TimeOutProc() +{ + APP_LOGI("AbilityPostEventTimeout::TimeOutProc() call %{public}s", task_.c_str()); + if (handler_ == nullptr) { + APP_LOGE("AbilityPostEventTimeout::TimeEnd %{public}s handler_ is nullptr", task_.c_str()); + return; + } + + std::lock_guard lck(mtx_); + if (!taskExec_) { + taskExec_ = true; + APP_LOGW("TimeOutProc %{public}s Event TimeOut", task_.c_str()); + handler_->RemoveTask(task_); + } else { + APP_LOGW("AbilityPostEventTimeout::TimeOutProc Exec Failed, The Event is %{public}s", task_.c_str()); + } +} + +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/src/ability_process.cpp b/tools/frameworks/kits/ability/native/src/ability_process.cpp new file mode 100755 index 00000000000..88a68530f2a --- /dev/null +++ b/tools/frameworks/kits/ability/native/src/ability_process.cpp @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ability_process.h" +#include "app_log_wrapper.h" +#include +namespace OHOS { +namespace AppExecFwk { +static void *g_handle = nullptr; +constexpr char SHARED_LIBRARY_FEATURE_ABILITY[] = "/system/lib/module/ability/libfeatureability.z.so"; +constexpr char FUNC_CALL_ON_ABILITY_RESULT[] = "CallOnAbilityResult"; +using NAPICallOnAbilityResult = void (*)(int requestCode, int resultCode, const Want &resultData, CallbackInfo cb); +constexpr char FUNC_CALL_ON_REQUEST_PERMISSIONS_FROM_USERRESULT[] = "CallOnRequestPermissionsFromUserResult"; +using NAPICallOnRequestPermissionsFromUserResult = void (*)(int requestCode, + const std::vector &permissions, const std::vector &grantResults, CallbackInfo callbackInfo); + +std::shared_ptr AbilityProcess::instance_ = nullptr; +std::map> AbilityProcess::abilityResultMap_; +std::map> AbilityProcess::abilityRequestPermissionsForUserMap_; +std::mutex AbilityProcess::mutex_; +std::shared_ptr AbilityProcess::GetInstance() +{ + if (instance_ == nullptr) { + std::lock_guard lock_l(mutex_); + if (instance_ == nullptr) { + instance_ = std::make_shared(); + } + } + return instance_; +} + +AbilityProcess::AbilityProcess() +{} + +AbilityProcess::~AbilityProcess() +{} + +void AbilityProcess::StartAbility(Ability *ability, CallAbilityParam param, CallbackInfo callback) +{ + APP_LOGI("AbilityProcess::StartAbility begin"); + if (ability == nullptr) { + APP_LOGE("AbilityProcess::StartAbility ability is nullptr"); + return; + } + + if (param.forResultOption == true) { + if (param.setting == nullptr) { + APP_LOGI("%{public}s param.setting == nullptr call StartAbilityForResult.", __func__); + ability->StartAbilityForResult(param.want, param.requestCode); + } else { + APP_LOGI("%{public}s param.setting != nullptr call StartAbilityForResult.", __func__); + ability->StartAbilityForResult(param.want, param.requestCode, *(param.setting)); + } + + std::lock_guard lock_l(mutex_); + + std::map map; + auto it = abilityResultMap_.find(ability); + if (it == abilityResultMap_.end()) { + APP_LOGI("AbilityProcess::StartAbility ability: %{public}p is not in the abilityResultMap_", ability); + } else { + APP_LOGI("AbilityProcess::StartAbility ability: %{public}p is in the abilityResultMap_", ability); + map = it->second; + } + + map[param.requestCode] = callback; + abilityResultMap_[ability] = map; + } else { + if (param.setting == nullptr) { + APP_LOGI("%{public}s param.setting == nullptr call StartAbility.", __func__); + ability->StartAbility(param.want); + } else { + APP_LOGI("%{public}s param.setting != nullptr call StartAbility.", __func__); + ability->StartAbility(param.want, *(param.setting)); + } + } + APP_LOGI("AbilityProcess::StartAbility end"); +} + +void AbilityProcess::OnAbilityResult(Ability *ability, int requestCode, int resultCode, const Want &resultData) +{ + APP_LOGI("AbilityProcess::OnAbilityResult begin"); + + std::lock_guard lock_l(mutex_); + + auto it = abilityResultMap_.find(ability); + if (it == abilityResultMap_.end()) { + APP_LOGE("AbilityProcess::OnAbilityResult ability: %{public}p is not in the abilityResultMap", ability); + return; + } + std::map map = it->second; + + auto callback = map.find(requestCode); + if (callback == map.end()) { + APP_LOGE("AbilityProcess::OnAbilityResult requestCode: %{public}d is not in the map", requestCode); + return; + } + CallbackInfo callbackInfo = callback->second; + + // start open featureability lib + if (g_handle == nullptr) { + g_handle = dlopen(SHARED_LIBRARY_FEATURE_ABILITY, RTLD_LAZY); + if (g_handle == nullptr) { + APP_LOGE("%{public}s, dlopen failed %{public}s. %{public}s", + __func__, + SHARED_LIBRARY_FEATURE_ABILITY, + dlerror()); + return; + } + } + + // get function + auto func = reinterpret_cast(dlsym(g_handle, FUNC_CALL_ON_ABILITY_RESULT)); + if (func == nullptr) { + APP_LOGE("%{public}s, dlsym failed %{public}s. %{public}s", __func__, FUNC_CALL_ON_ABILITY_RESULT, dlerror()); + dlclose(g_handle); + g_handle = nullptr; + return; + } + func(requestCode, resultCode, resultData, callbackInfo); + + map.erase(requestCode); + + abilityResultMap_[ability] = map; + APP_LOGI("AbilityProcess::OnAbilityResult end"); +} + +void AbilityProcess::RequestPermissionsFromUser( + Ability *ability, CallAbilityPermissionParam ¶m, CallbackInfo callbackInfo) +{ + APP_LOGI("AbilityProcess::RequestPermissionsFromUser begin"); + if (ability == nullptr) { + APP_LOGE("AbilityProcess::RequestPermissionsFromUser ability is nullptr"); + return; + } + + ability->RequestPermissionsFromUser(param.permission_list, param.requestCode); + + { + std::lock_guard lock_l(mutex_); + std::map map; + auto it = abilityRequestPermissionsForUserMap_.find(ability); + if (it == abilityRequestPermissionsForUserMap_.end()) { + APP_LOGI("AbilityProcess::RequestPermissionsFromUser ability: %{public}p is not in the " + "abilityRequestPermissionsForUserMap_", + ability); + } else { + APP_LOGI("AbilityProcess::RequestPermissionsFromUser ability: %{public}p is in the " + "abilityRequestPermissionsForUserMap_", + ability); + map = it->second; + } + + map[param.requestCode] = callbackInfo; + abilityRequestPermissionsForUserMap_[ability] = map; + } + APP_LOGI("AbilityProcess::RequestPermissionsFromUser end"); +} + +void AbilityProcess::OnRequestPermissionsFromUserResult(Ability *ability, int requestCode, + const std::vector &permissions, const std::vector &grantResults) +{ + APP_LOGI("AbilityProcess::OnRequestPermissionsFromUserResult begin"); + if (ability == nullptr) { + APP_LOGE("AbilityProcess::OnRequestPermissionsFromUserResult ability is nullptr"); + return; + } + + std::lock_guard lock_l(mutex_); + + auto it = abilityRequestPermissionsForUserMap_.find(ability); + if (it == abilityRequestPermissionsForUserMap_.end()) { + APP_LOGE("AbilityProcess::OnRequestPermissionsFromUserResult ability: %{public}p is not in the " + "abilityRequestPermissionsForUserMap_", + ability); + return; + } + std::map map = it->second; + + auto callback = map.find(requestCode); + if (callback == map.end()) { + APP_LOGE("AbilityProcess::OnRequestPermissionsFromUserResult requestCode: %{public}d is not in the map", + requestCode); + return; + } + CallbackInfo callbackInfo = callback->second; + + // start open featureability lib + if (g_handle == nullptr) { + g_handle = dlopen(SHARED_LIBRARY_FEATURE_ABILITY, RTLD_LAZY); + if (g_handle == nullptr) { + APP_LOGE("%{public}s, dlopen failed %{public}s. %{public}s", + __func__, + SHARED_LIBRARY_FEATURE_ABILITY, + dlerror()); + return; + } + } + + // get function + auto func = reinterpret_cast( + dlsym(g_handle, FUNC_CALL_ON_REQUEST_PERMISSIONS_FROM_USERRESULT)); + if (func == nullptr) { + APP_LOGE("%{public}s, dlsym failed %{public}s. %{public}s", + __func__, + FUNC_CALL_ON_REQUEST_PERMISSIONS_FROM_USERRESULT, + dlerror()); + dlclose(g_handle); + g_handle = nullptr; + return; + } + func(requestCode, permissions, grantResults, callbackInfo); + map.erase(requestCode); + + abilityRequestPermissionsForUserMap_[ability] = map; + APP_LOGI("AbilityProcess::OnRequestPermissionsFromUserResult end"); +} +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/src/ability_thread.cpp b/tools/frameworks/kits/ability/native/src/ability_thread.cpp new file mode 100644 index 00000000000..e08ae0a2e28 --- /dev/null +++ b/tools/frameworks/kits/ability/native/src/ability_thread.cpp @@ -0,0 +1,1164 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ability_thread.h" +#include +#include "ohos_application.h" +#include "ability_loader.h" +#include "ability_state.h" +#include "ability_impl_factory.h" +#include "page_ability_impl.h" +#include "application_impl.h" +#include "app_log_wrapper.h" +#include "context_deal.h" +#include "abs_shared_result_set.h" +#include "data_ability_predicates.h" +#include "values_bucket.h" +#include "dataobs_mgr_client.h" + +namespace OHOS { +namespace AppExecFwk { +using AbilityManagerClient = OHOS::AAFwk::AbilityManagerClient; +using DataObsMgrClient = OHOS::AAFwk::DataObsMgrClient; +constexpr static char ACE_ABILITY_NAME[] = "AceAbility"; +constexpr static char ACE_SERVICE_ABILITY_NAME[] = "AceServiceAbility"; +constexpr static char ACE_DATA_ABILITY_NAME[] = "AceDataAbility"; +constexpr static char ACE_FORM_ABILITY_NAME[] = "AceFormAbility"; + +/** + * @brief Default constructor used to create a AbilityThread instance. + */ +AbilityThread::AbilityThread() + : abilityImpl_(nullptr), token_(nullptr), currentAbility_(nullptr), abilityHandler_(nullptr), runner_(nullptr) +{} + +AbilityThread::~AbilityThread() +{ + DelayedSingleton::DestroyInstance(); +} + +/** + * @description: Attach The ability thread to the main process. + * + * @param abilityRecord Indicates the abilityRecord. + * + * @return Returns the abilityName. + * + */ +std::string AbilityThread::CreateAbilityName(const std::shared_ptr &abilityRecord) +{ + std::string abilityName; + APP_LOGI("AbilityThread::CreateAbilityName begin"); + if (abilityRecord == nullptr) { + APP_LOGE("AbilityThread::CreateAbilityName failed,abilityRecord is nullptr"); + return abilityName; + } + + std::shared_ptr abilityInfo = abilityRecord->GetAbilityInfo(); + if (abilityInfo == nullptr) { + APP_LOGE("AbilityThread::ability attach failed,abilityInfo is nullptr"); + return abilityName; + } + + APP_LOGI("AbilityThread::ability attach the ability type is %{public}d", abilityInfo->type); + APP_LOGI("AbilityThread::ability attach the ability is Native %{public}d", abilityInfo->isNativeAbility); + + if (abilityInfo->isNativeAbility == false) { + if (abilityInfo->type == AbilityType::PAGE) { + abilityName = ACE_ABILITY_NAME; + } else if (abilityInfo->type == AbilityType::SERVICE) { + if (abilityInfo->formEnabled == true) { + abilityName = ACE_FORM_ABILITY_NAME; + } else { + abilityName = ACE_SERVICE_ABILITY_NAME; + } + } else if (abilityInfo->type == AbilityType::DATA) { + abilityName = ACE_DATA_ABILITY_NAME; + } else { + abilityName = abilityInfo->name; + } + } else { + abilityName = abilityInfo->name; + } + + APP_LOGI("AbilityThread::CreateAbilityName end"); + return abilityName; +} + +/** + * @description: Create and init contextDeal. + * + * @param application Indicates the main process. + * @param abilityRecord Indicates the abilityRecord. + * @param abilityObject Indicates the abilityObject. + * + * @return Returns the contextDeal. + * + */ +std::shared_ptr AbilityThread::CreateAndInitContextDeal(std::shared_ptr &application, + const std::shared_ptr &abilityRecord, const std::shared_ptr &abilityObject) +{ + APP_LOGI("AbilityThread::CreateAndInitContextDeal begin"); + std::shared_ptr contextDeal = nullptr; + APP_LOGI("AbilityThread::CreateAndInitContextDeal called"); + if ((application == nullptr) || (abilityRecord == nullptr) || (abilityObject == nullptr)) { + APP_LOGE("AbilityThread::ability attach failed,context or record or abilityObject is nullptr"); + return contextDeal; + } + + contextDeal = std::make_shared(); + if (contextDeal == nullptr) { + APP_LOGE("AbilityThread::ability attach failed,contextDeal is nullptr"); + return contextDeal; + } + + contextDeal->SetAbilityInfo(abilityRecord->GetAbilityInfo()); + contextDeal->SetApplicationInfo(application->GetApplicationInfo()); + contextDeal->SetProcessInfo(application->GetProcessInfo()); + + std::shared_ptr tmpContext = application->GetApplicationContext(); + contextDeal->SetApplicationContext(tmpContext); + + contextDeal->SetBundleCodePath(abilityRecord->GetAbilityInfo()->codePath); + contextDeal->SetContext(abilityObject); + contextDeal->SetRunner(abilityHandler_->GetEventRunner()); + APP_LOGI("AbilityThread::CreateAndInitContextDeal end"); + return contextDeal; +} + +/** + * @description: Attach The ability thread to the main process. + * @param application Indicates the main process. + * @param abilityRecord Indicates the abilityRecord. + * @param mainRunner The runner which main_thread holds. + */ +void AbilityThread::Attach(std::shared_ptr &application, + const std::shared_ptr &abilityRecord, const std::shared_ptr &mainRunner) +{ + APP_LOGI("AbilityThread::Attach begin"); + if ((application == nullptr) || (abilityRecord == nullptr) || (mainRunner == nullptr)) { + APP_LOGE("AbilityThread::ability attach failed,context or record is nullptr"); + return; + } + + // 1.new AbilityHandler + std::string abilityName = CreateAbilityName(abilityRecord); + abilityHandler_ = std::make_shared(mainRunner, this); + if (abilityHandler_ == nullptr) { + APP_LOGE("AbilityThread::ability attach failed,abilityHandler_ is nullptr"); + return; + } + + // 2.new ability + auto ability = AbilityLoader::GetInstance().GetAbilityByName(abilityName); + if (ability == nullptr) { + APP_LOGE("AbilityThread::ability attach failed,load ability failed"); + return; + } + + APP_LOGI("AbilityThread::new ability success."); + currentAbility_.reset(ability); + token_ = abilityRecord->GetToken(); + abilityRecord->SetEventHandler(abilityHandler_); + abilityRecord->SetEventRunner(mainRunner); + abilityRecord->SetAbilityThread(this); + std::shared_ptr abilityObject = currentAbility_; + std::shared_ptr contextDeal = CreateAndInitContextDeal(application, abilityRecord, abilityObject); + ability->AttachBaseContext(contextDeal); + + // 3.new abilityImpl + abilityImpl_ = + DelayedSingleton::GetInstance()->MakeAbilityImplObject(abilityRecord->GetAbilityInfo()); + if (abilityImpl_ == nullptr) { + APP_LOGE("AbilityThread::ability abilityImpl_ == nullptr"); + return; + } + APP_LOGI("AbilityThread::Attach before abilityImpl_->Init"); + abilityImpl_->Init(application, abilityRecord, currentAbility_, abilityHandler_, token_, contextDeal); + APP_LOGI("AbilityThread::Attach after abilityImpl_->Init"); + // 4. ability attach : ipc + APP_LOGI("AbilityThread::Attach before AttachAbilityThread"); + ErrCode err = AbilityManagerClient::GetInstance()->AttachAbilityThread(this, token_); + APP_LOGI("AbilityThread::Attach after AttachAbilityThread"); + if (err != ERR_OK) { + APP_LOGE("AbilityThread:: attach success faile err = %{public}d", err); + return; + } + + APP_LOGI("AbilityThread::Attach end"); +} + +/** + * @description: Attach The ability thread to the main process. + * @param application Indicates the main process. + * @param abilityRecord Indicates the abilityRecord. + */ +void AbilityThread::Attach( + std::shared_ptr &application, const std::shared_ptr &abilityRecord) +{ + APP_LOGI("AbilityThread::Attach begin"); + if ((application == nullptr) || (abilityRecord == nullptr)) { + APP_LOGE("AbilityThread::ability attach failed,context or record is nullptr"); + return; + } + // 1.new AbilityHandler + std::string abilityName = CreateAbilityName(abilityRecord); + runner_ = EventRunner::Create(abilityName); + if (runner_ == nullptr) { + APP_LOGE("AbilityThread::ability attach failed,create runner failed"); + return; + } + abilityHandler_ = std::make_shared(runner_, this); + if (abilityHandler_ == nullptr) { + APP_LOGE("AbilityThread::ability attach failed,abilityHandler_ is nullptr"); + return; + } + + // 2.new ability + auto ability = AbilityLoader::GetInstance().GetAbilityByName(abilityName); + if (ability == nullptr) { + APP_LOGE("AbilityThread::ability attach failed,load ability failed"); + return; + } + + APP_LOGI("AbilityThread::new ability success."); + currentAbility_.reset(ability); + token_ = abilityRecord->GetToken(); + abilityRecord->SetEventHandler(abilityHandler_); + abilityRecord->SetEventRunner(runner_); + abilityRecord->SetAbilityThread(this); + std::shared_ptr abilityObject = currentAbility_; + std::shared_ptr contextDeal = CreateAndInitContextDeal(application, abilityRecord, abilityObject); + ability->AttachBaseContext(contextDeal); + + // 3.new abilityImpl + abilityImpl_ = + DelayedSingleton::GetInstance()->MakeAbilityImplObject(abilityRecord->GetAbilityInfo()); + if (abilityImpl_ == nullptr) { + APP_LOGE("AbilityThread::ability abilityImpl_ == nullptr"); + return; + } + APP_LOGI("AbilityThread::Attach before abilityImpl_->Init"); + abilityImpl_->Init(application, abilityRecord, currentAbility_, abilityHandler_, token_, contextDeal); + APP_LOGI("AbilityThread::Attach after abilityImpl_->Init"); + // 4. ability attach : ipc + APP_LOGI("AbilityThread::Attach before AttachAbilityThread"); + ErrCode err = AbilityManagerClient::GetInstance()->AttachAbilityThread(this, token_); + APP_LOGI("AbilityThread::Attach after AttachAbilityThread"); + if (err != ERR_OK) { + APP_LOGE("AbilityThread:: attach success faile err = %{public}d", err); + return; + } + + APP_LOGI("AbilityThread::Attach end"); +} + +/** + * @description: Handle the life cycle of Ability. + * @param want Indicates the structure containing lifecycle information about the ability. + * @param lifeCycleStateInfo Indicates the lifeCycleStateInfo. + */ +void AbilityThread::HandleAbilityTransaction(const Want &want, const LifeCycleStateInfo &lifeCycleStateInfo) +{ + APP_LOGI("AbilityThread::HandleAbilityTransaction begin"); + if (abilityImpl_ == nullptr) { + APP_LOGE("AbilityThread::HandleAbilityTransaction abilityImpl_ == nullptr"); + return; + } + + APP_LOGI("AbilityThread::HandleAbilityTransaction before abilityImpl_->SetCallingContext"); + abilityImpl_->SetCallingContext(lifeCycleStateInfo.caller.deviceId, + lifeCycleStateInfo.caller.bundleName, + lifeCycleStateInfo.caller.abilityName); + APP_LOGI("AbilityThread::HandleAbilityTransaction after abilityImpl_->SetCallingContext"); + APP_LOGI("AbilityThread::HandleAbilityTransaction before abilityImpl_->HandleAbilityTransaction"); + abilityImpl_->HandleAbilityTransaction(want, lifeCycleStateInfo); + APP_LOGI("AbilityThread::HandleAbilityTransaction after abilityImpl_->HandleAbilityTransaction"); + APP_LOGI("AbilityThread::HandleAbilityTransaction end"); +} + +/** + * @description: Handle the current connection of Ability. + * @param want Indicates the structure containing connection information about the ability. + */ +void AbilityThread::HandleConnectAbility(const Want &want) +{ + APP_LOGI("AbilityThread::HandleConnectAbility begin"); + if (abilityImpl_ == nullptr) { + APP_LOGE("AbilityThread::HandleConnectAbility abilityImpl_ == nullptr"); + return; + } + + APP_LOGI("AbilityThread::HandleConnectAbility before abilityImpl_->ConnectAbility"); + sptr service = abilityImpl_->ConnectAbility(want); + APP_LOGI("AbilityThread::HandleConnectAbility after abilityImpl_->ConnectAbility"); + APP_LOGI("AbilityThread::HandleConnectAbility before ScheduleConnectAbilityDone"); + ErrCode err = AbilityManagerClient::GetInstance()->ScheduleConnectAbilityDone(token_, service); + APP_LOGI("AbilityThread::HandleConnectAbility after ScheduleConnectAbilityDone"); + if (err != ERR_OK) { + APP_LOGE("AbilityThread:: HandleConnectAbility faile err = %{public}d", err); + } + APP_LOGI("AbilityThread::HandleConnectAbility end"); +} + +/** + * @description: Handle the current disconnection of Ability. + */ +void AbilityThread::HandleDisconnectAbility(const Want &want) +{ + APP_LOGI("AbilityThread::HandleDisconnectAbility begin"); + if (abilityImpl_ == nullptr) { + APP_LOGE("AbilityThread::HandleDisconnectAbility abilityImpl_ == nullptr"); + return; + } + + APP_LOGI("AbilityThread::HandleDisconnectAbility before abilityImpl_->DisconnectAbility"); + abilityImpl_->DisconnectAbility(want); + APP_LOGI("AbilityThread::HandleDisconnectAbility after abilityImpl_->DisconnectAbility"); + APP_LOGI("AbilityThread::HandleDisconnectAbility before ScheduleDisconnectAbilityDone"); + ErrCode err = AbilityManagerClient::GetInstance()->ScheduleDisconnectAbilityDone(token_); + APP_LOGI("AbilityThread::HandleDisconnectAbility after ScheduleDisconnectAbilityDone"); + if (err != ERR_OK) { + APP_LOGE("AbilityThread:: HandleDisconnectAbility faile err = %{public}d", err); + } + APP_LOGI("AbilityThread::HandleDisconnectAbility end"); +} + +/** + * @brief Handle the current commadn of Ability. + * + * @param want The Want object to command to. + * + * * @param restart Indicates the startup mode. The value true indicates that Service is restarted after being + * destroyed, and the value false indicates a normal startup. + * + * @param startId Indicates the number of times the Service ability has been started. The startId is incremented by 1 + * every time the ability is started. For example, if the ability has been started for six times, the value of startId + * is 6. + */ +void AbilityThread::HandleCommandAbility(const Want &want, bool restart, int startId) +{ + APP_LOGI("AbilityThread::HandleCommandAbility begin"); + APP_LOGI("AbilityThread::HandleCommandAbility before abilityImpl_->CommandAbility"); + abilityImpl_->CommandAbility(want, restart, startId); + APP_LOGI("AbilityThread::HandleCommandAbility after abilityImpl_->CommandAbility"); + APP_LOGI("AbilityThread::HandleCommandAbility before ScheduleCommandAbilityDone"); + ErrCode err = AbilityManagerClient::GetInstance()->ScheduleCommandAbilityDone(token_); + APP_LOGI("AbilityThread::HandleCommandAbility after ScheduleCommandAbilityDone"); + if (err != ERR_OK) { + APP_LOGE("AbilityThread:: HandleCommandAbility faile err = %{public}d", err); + } + APP_LOGI("AbilityThread::HandleCommandAbility end"); +} + +/** + * @description: Handle the SaveAbility state. + * @param state Indicates save ability state used to dispatchSaveAbilityState. + */ +void AbilityThread::HandleSaveAbilityState(PacMap &state) +{ + APP_LOGI("AbilityThread::HandleSaveAbilityState begin"); + if (abilityImpl_ == nullptr) { + APP_LOGE("AbilityThread::HandleSaveAbilityState abilityImpl_ == nullptr"); + return; + } + + APP_LOGI("AbilityThread::HandleSaveAbilityState before abilityImpl_->DispatchSaveAbilityState"); + abilityImpl_->DispatchSaveAbilityState(state); + APP_LOGI("AbilityThread::HandleSaveAbilityState after abilityImpl_->DispatchSaveAbilityState"); + APP_LOGI("AbilityThread::HandleSaveAbilityState end"); +} + +/** + * @description: Handle the restoreAbility state. + * @param state Indicates save ability state used to dispatchRestoreAbilityState. + */ +void AbilityThread::HandleRestoreAbilityState(const PacMap &state) +{ + APP_LOGI("AbilityThread::HandleRestoreAbilityState begin"); + if (abilityImpl_ == nullptr) { + APP_LOGE("AbilityThread::HandleRestoreAbilityState abilityImpl_ == nullptr"); + return; + } + + APP_LOGI("AbilityThread::HandleRestoreAbilityState before abilityImpl_->DispatchRestoreAbilityState"); + abilityImpl_->DispatchRestoreAbilityState(state); + APP_LOGI("AbilityThread::HandleRestoreAbilityState after abilityImpl_->DispatchRestoreAbilityState"); + APP_LOGI("AbilityThread::HandleRestoreAbilityState end"); +} + +/** + * @description: Provide operating system SaveabilityState information to the observer + * @param state Indicates save ability state used to dispatch. + */ +void AbilityThread::ScheduleSaveAbilityState(PacMap &state) +{ + APP_LOGI("AbilityThread::ScheduleSaveAbilityState begin"); + if (abilityImpl_ == nullptr) { + APP_LOGE("AbilityThread::ScheduleSaveAbilityState abilityImpl_ == nullptr"); + return; + } + + APP_LOGI("AbilityThread::ScheduleSaveAbilityState before abilityImpl_->DispatchSaveAbilityState"); + abilityImpl_->DispatchSaveAbilityState(state); + APP_LOGI("AbilityThread::ScheduleSaveAbilityState after abilityImpl_->DispatchSaveAbilityState"); + APP_LOGI("AbilityThread::ScheduleSaveAbilityState end"); +} + +/** + * @description: Provide operating system RestoreAbilityState information to the observer + * @param state Indicates resotre ability state used to dispatchRestoreAbilityState. + */ +void AbilityThread::ScheduleRestoreAbilityState(const PacMap &state) +{ + APP_LOGI("AbilityThread::ScheduleRestoreAbilityState begin"); + if (abilityImpl_ == nullptr) { + APP_LOGE("AbilityThread::ScheduleRestoreAbilityState abilityImpl_ == nullptr"); + return; + } + APP_LOGI("AbilityThread::ScheduleRestoreAbilityState before abilityImpl_->DispatchRestoreAbilityState"); + abilityImpl_->DispatchRestoreAbilityState(state); + APP_LOGI("AbilityThread::ScheduleRestoreAbilityState after abilityImpl_->DispatchRestoreAbilityState"); + APP_LOGI("AbilityThread::ScheduleRestoreAbilityState end"); +} + +/* + * @brief ScheduleUpdateConfiguration, scheduling update configuration. + */ +void AbilityThread::ScheduleUpdateConfiguration(const DummyConfiguration &config) +{ + APP_LOGI("AbilityThread::ScheduleUpdateConfiguration begin"); + if (abilityImpl_ == nullptr) { + APP_LOGE("AbilityThread::ScheduleUpdateConfiguration abilityImpl_ is nullptr"); + return; + } + + auto task = [abilitThread = this, config]() { abilitThread->HandleUpdateConfiguration(config); }; + + if (abilityHandler_ == nullptr) { + APP_LOGE("AbilityThread::ScheduleUpdateConfiguration abilityHandler_ is nullptr"); + return; + } + + bool ret = abilityHandler_->PostTask(task); + if (!ret) { + APP_LOGE("AbilityThread::ScheduleUpdateConfiguration PostTask error"); + } + APP_LOGI("AbilityThread::ScheduleUpdateConfiguration end"); +} + +/* + * @brief Handle the scheduling update configuration. + */ +void AbilityThread::HandleUpdateConfiguration(const DummyConfiguration &config) +{ + APP_LOGI("AbilityThread::HandleUpdateConfiguration begin"); + if (abilityImpl_ == nullptr) { + APP_LOGE("AbilityThread::HandleUpdateConfiguration abilityImpl_ is nullptr"); + return; + } + + APP_LOGI("AbilityThread::HandleUpdateConfiguration before abilityImpl_->ScheduleUpdateConfiguration"); + abilityImpl_->ScheduleUpdateConfiguration(config); + APP_LOGI("AbilityThread::HandleUpdateConfiguration after abilityImpl_->ScheduleUpdateConfiguration"); + APP_LOGI("AbilityThread::HandleUpdateConfiguration end"); +} + +/** + * @description: Provide operating system AbilityTransaction information to the observer + * @param want Indicates the structure containing Transaction information about the ability. + * @param lifeCycleStateInfo Indicates the lifecycle state. + */ +void AbilityThread::ScheduleAbilityTransaction(const Want &want, const LifeCycleStateInfo &lifeCycleStateInfo) +{ + APP_LOGI("ScheduleAbilityTransaction begin: targeState = %{public}d, isNewWant = %{public}d", + lifeCycleStateInfo.state, + lifeCycleStateInfo.isNewWant); + + want.DumpInfo(0); + + if ((token_ == nullptr) || abilityImpl_ == nullptr) { + APP_LOGE("ScheduleAbilityTransaction::failed"); + return; + } + auto task = [abilityThread = this, want, lifeCycleStateInfo]() { + abilityThread->HandleAbilityTransaction(want, lifeCycleStateInfo); + }; + + if (abilityHandler_ == nullptr) { + APP_LOGE("AbilityThread::ScheduleAbilityTransaction abilityHandler_ == nullptr"); + return; + } + + bool ret = abilityHandler_->PostTask(task); + if (!ret) { + APP_LOGE("AbilityThread::ScheduleAbilityTransaction PostTask error"); + } + APP_LOGI("ScheduleAbilityTransaction end"); +} + +/** + * @description: Provide operating system ConnectAbility information to the observer + * @param want Indicates the structure containing connect information about the ability. + */ +void AbilityThread::ScheduleConnectAbility(const Want &want) +{ + APP_LOGI("AbilityThread::ScheduleConnectAbility begin"); + auto task = [abilityThread = this, want]() { abilityThread->HandleConnectAbility(want); }; + + if (abilityHandler_ == nullptr) { + APP_LOGE("AbilityThread::ScheduleConnectAbility abilityHandler_ == nullptr"); + return; + } + + bool ret = abilityHandler_->PostTask(task); + if (!ret) { + APP_LOGE("AbilityThread::ScheduleConnectAbility PostTask error"); + } + APP_LOGI("AbilityThread::ScheduleConnectAbility end"); +} + +/** + * @description: Provide operating system ConnectAbility information to the observer + * @return None + */ +void AbilityThread::ScheduleDisconnectAbility(const Want &want) +{ + APP_LOGI("AbilityThread::ScheduleDisconnectAbility begin"); + auto task = [abilityThread = this, want]() { abilityThread->HandleDisconnectAbility(want); }; + + if (abilityHandler_ == nullptr) { + APP_LOGE("AbilityThread::ScheduleDisconnectAbility abilityHandler_ == nullptr"); + return; + } + + bool ret = abilityHandler_->PostTask(task); + if (!ret) { + APP_LOGE("AbilityThread::ScheduleDisconnectAbility PostTask error"); + } + APP_LOGI("AbilityThread::ScheduleDisconnectAbility end"); +} + +/** + * @description: Provide operating system CommandAbility information to the observer + * + * @param want The Want object to command to. + * + * * @param restart Indicates the startup mode. The value true indicates that Service is restarted after being + * destroyed, and the value false indicates a normal startup. + * + * @param startId Indicates the number of times the Service ability has been started. The startId is incremented by 1 + * every time the ability is started. For example, if the ability has been started for six times, the value of startId + * is 6. + */ +void AbilityThread::ScheduleCommandAbility(const Want &want, bool restart, int startId) +{ + APP_LOGI("AbilityThread::ScheduleCommandAbility begin"); + auto task = [abilityThread = this, want, restart, startId]() { + abilityThread->HandleCommandAbility(want, restart, startId); + }; + + if (abilityHandler_ == nullptr) { + APP_LOGE("AbilityThread::ScheduleCommandAbility abilityHandler_ == nullptr"); + return; + } + + bool ret = abilityHandler_->PostTask(task); + if (!ret) { + APP_LOGE("AbilityThread::ScheduleCommandAbility PostTask error"); + } + APP_LOGI("AbilityThread::ScheduleCommandAbility end"); +} + +/** + * @brief Send the result code and data to be returned by this Page ability to the caller. + * When a Page ability is destroyed, the caller overrides the AbilitySlice#onAbilityResult(int, int, Want) method to + * receive the result set in the current method. This method can be called only after the ability has been initialized. + * + * @param requestCode Indicates the request code for send. + * @param resultCode Indicates the result code returned after the ability is destroyed. You can define the result code + * to identify an error. + * @param want Indicates the data returned after the ability is destroyed. You can define the data returned. This + * parameter can be null. + */ +void AbilityThread::SendResult(int requestCode, int resultCode, const Want &want) +{ + APP_LOGI("AbilityThread::SendResult begin"); + if (abilityImpl_ == nullptr) { + APP_LOGE("AbilityThread::SendResult abilityImpl_ == nullptr"); + return; + } + + if (requestCode != -1) { + APP_LOGI("AbilityThread::SendResult before abilityImpl_->SendResult"); + abilityImpl_->SendResult(requestCode, resultCode, want); + APP_LOGI("AbilityThread::SendResult after abilityImpl_->SendResult"); + } + APP_LOGI("AbilityThread::SendResult end"); +} + +/** + * @brief Obtains the MIME types of files supported. + * + * @param uri Indicates the path of the files to obtain. + * @param mimeTypeFilter Indicates the MIME types of the files to obtain. This parameter cannot be null. + * + * @return Returns the matched MIME types. If there is no match, null is returned. + */ +std::vector AbilityThread::GetFileTypes(const Uri &uri, const std::string &mimeTypeFilter) +{ + APP_LOGI("AbilityThread::GetFileTypes begin"); + std::vector types; + if (abilityImpl_ == nullptr) { + APP_LOGE("AbilityThread::GetFileTypes abilityImpl_ is nullptr"); + return types; + } + + APP_LOGI("AbilityThread::GetFileTypes before abilityImpl_->GetFileTypes"); + types = abilityImpl_->GetFileTypes(uri, mimeTypeFilter); + APP_LOGI("AbilityThread::GetFileTypes after abilityImpl_->GetFileTypes"); + APP_LOGI("AbilityThread::GetFileTypes end"); + return types; +} + +/** + * @brief Opens a file in a specified remote path. + * + * @param uri Indicates the path of the file to open. + * @param mode Indicates the file open mode, which can be "r" for read-only access, "w" for write-only access + * (erasing whatever data is currently in the file), "wt" for write access that truncates any existing file, + * "wa" for write-only access to append to any existing data, "rw" for read and write access on any existing data, + * or "rwt" for read and write access that truncates any existing file. + * + * @return Returns the file descriptor. + */ +int AbilityThread::OpenFile(const Uri &uri, const std::string &mode) +{ + APP_LOGI("AbilityThread::OpenFile begin"); + int fd = -1; + if (abilityImpl_ == nullptr) { + APP_LOGE("AbilityThread::OpenFile abilityImpl_ is nullptr"); + return fd; + } + + APP_LOGI("AbilityThread::OpenFile before abilityImpl_->OpenFile"); + fd = abilityImpl_->OpenFile(uri, mode); + APP_LOGI("AbilityThread::OpenFile after abilityImpl_->OpenFile"); + APP_LOGI("AbilityThread::OpenFile end"); + return fd; +} + +/** + * @brief This is like openFile, open a file that need to be able to return sub-sections of files,often assets + * inside of their .hap. + * + * @param uri Indicates the path of the file to open. + * @param mode Indicates the file open mode, which can be "r" for read-only access, "w" for write-only access + * (erasing whatever data is currently in the file), "wt" for write access that truncates any existing file, + * "wa" for write-only access to append to any existing data, "rw" for read and write access on any existing + * data, or "rwt" for read and write access that truncates any existing file. + * + * @return Returns the RawFileDescriptor object containing file descriptor. + */ +int AbilityThread::OpenRawFile(const Uri &uri, const std::string &mode) +{ + APP_LOGI("AbilityThread::OpenRawFile begin"); + int fd = -1; + if (abilityImpl_ == nullptr) { + APP_LOGE("AbilityThread::OpenRawFile abilityImpl_ is nullptr"); + return fd; + } + + APP_LOGI("AbilityThread::OpenRawFile before abilityImpl_->OpenRawFile"); + fd = abilityImpl_->OpenRawFile(uri, mode); + APP_LOGI("AbilityThread::OpenRawFile after abilityImpl_->OpenRawFile"); + APP_LOGI("AbilityThread::OpenRawFile end"); + return fd; +} + +/** + * @brief Inserts a single data record into the database. + * + * @param uri Indicates the path of the data to operate. + * @param value Indicates the data record to insert. If this parameter is null, a blank row will be inserted. + * + * @return Returns the index of the inserted data record. + */ +int AbilityThread::Insert(const Uri &uri, const NativeRdb::ValuesBucket &value) +{ + APP_LOGI("AbilityThread::Insert begin"); + int index = -1; + if (abilityImpl_ == nullptr) { + APP_LOGE("AbilityThread::Insert abilityImpl_ is nullptr"); + return index; + } + + APP_LOGI("AbilityThread::Insert before abilityImpl_->Insert"); + index = abilityImpl_->Insert(uri, value); + APP_LOGI("AbilityThread::Insert after abilityImpl_->Insert"); + APP_LOGI("AbilityThread::Insert end"); + return index; +} + +/** + * @brief Updates data records in the database. + * + * @param uri Indicates the path of data to update. + * @param value Indicates the data to update. This parameter can be null. + * @param predicates Indicates filter criteria. You should define the processing logic when this parameter is null. + * + * @return Returns the number of data records updated. + */ +int AbilityThread::Update( + const Uri &uri, const NativeRdb::ValuesBucket &value, const NativeRdb::DataAbilityPredicates &predicates) +{ + APP_LOGI("AbilityThread::Update begin"); + int index = -1; + if (abilityImpl_ == nullptr) { + APP_LOGE("AbilityThread::Update abilityImpl_ is nullptr"); + return index; + } + + APP_LOGI("AbilityThread::Update before abilityImpl_->Update"); + index = abilityImpl_->Update(uri, value, predicates); + APP_LOGI("AbilityThread::Update after abilityImpl_->Update"); + APP_LOGI("AbilityThread::Update end"); + return index; +} + +/** + * @brief Deletes one or more data records from the database. + * + * @param uri Indicates the path of the data to operate. + * @param predicates Indicates filter criteria. You should define the processing logic when this parameter is null. + * + * @return Returns the number of data records deleted. + */ +int AbilityThread::Delete(const Uri &uri, const NativeRdb::DataAbilityPredicates &predicates) +{ + APP_LOGI("AbilityThread::Delete begin"); + int index = -1; + if (abilityImpl_ == nullptr) { + APP_LOGE("AbilityThread::Delete abilityImpl_ is nullptr"); + return index; + } + APP_LOGI("AbilityThread::Delete before abilityImpl_->Delete"); + index = abilityImpl_->Delete(uri, predicates); + APP_LOGI("AbilityThread::Delete after abilityImpl_->Delete"); + APP_LOGI("AbilityThread::Delete end"); + return index; +} + +/** + * @brief Deletes one or more data records from the database. + * + * @param uri Indicates the path of data to query. + * @param columns Indicates the columns to query. If this parameter is null, all columns are queried. + * @param predicates Indicates filter criteria. You should define the processing logic when this parameter is null. + * + * @return Returns the query result. + */ +std::shared_ptr AbilityThread::Query( + const Uri &uri, std::vector &columns, const NativeRdb::DataAbilityPredicates &predicates) +{ + APP_LOGI("AbilityThread::Query begin"); + std::shared_ptr resultSet = nullptr; + if (abilityImpl_ == nullptr) { + APP_LOGE("AbilityThread::Query abilityImpl_ is nullptr"); + return resultSet; + } + + APP_LOGI("AbilityThread::Query before abilityImpl_->Query"); + resultSet = abilityImpl_->Query(uri, columns, predicates); + APP_LOGI("AbilityThread::Query after abilityImpl_->Query"); + APP_LOGI("AbilityThread::Query end"); + return resultSet; +} + +/** + * @brief Obtains the MIME type matching the data specified by the URI of the Data ability. This method should be + * implemented by a Data ability. Data abilities supports general data types, including text, HTML, and JPEG. + * + * @param uri Indicates the URI of the data. + * + * @return Returns the MIME type that matches the data specified by uri. + */ +std::string AbilityThread::GetType(const Uri &uri) +{ + APP_LOGI("AbilityThread::GetType begin"); + std::string type; + if (abilityImpl_ == nullptr) { + APP_LOGE("AbilityThread::GetType abilityImpl_ is nullptr"); + return type; + } + + APP_LOGI("AbilityThread::GetType before abilityImpl_->GetType"); + type = abilityImpl_->GetType(uri); + APP_LOGI("AbilityThread::GetType after abilityImpl_->GetType"); + APP_LOGI("AbilityThread::GetType end"); + return type; +} + +/** + * @brief Reloads data in the database. + * + * @param uri Indicates the position where the data is to reload. This parameter is mandatory. + * @param extras Indicates the PacMap object containing the additional parameters to be passed in this call. This + * parameter can be null. If a custom Sequenceable object is put in the PacMap object and will be transferred across + * processes, you must call BasePacMap.setClassLoader(ClassLoader) to set a class loader for the custom object. + * + * @return Returns true if the data is successfully reloaded; returns false otherwise. + */ +bool AbilityThread::Reload(const Uri &uri, const PacMap &extras) +{ + APP_LOGI("AbilityThread::Reload begin"); + bool ret = false; + if (abilityImpl_ == nullptr) { + APP_LOGE("AbilityThread::Reload abilityImpl_ is nullptr"); + return ret; + } + APP_LOGI("AbilityThread::Reload before abilityImpl_->Reload"); + ret = abilityImpl_->Reload(uri, extras); + APP_LOGI("AbilityThread::Reload after abilityImpl_->Reload"); + APP_LOGI("AbilityThread::Reload end"); + return ret; +} + +/** + * @brief Inserts multiple data records into the database. + * + * @param uri Indicates the path of the data to operate. + * @param values Indicates the data records to insert. + * + * @return Returns the number of data records inserted. + */ +int AbilityThread::BatchInsert(const Uri &uri, const std::vector &values) +{ + APP_LOGI("AbilityThread::BatchInsert begin"); + int ret = -1; + if (abilityImpl_ == nullptr) { + APP_LOGE("AbilityThread::BatchInsert​ abilityImpl_ is nullptr"); + return ret; + } + + APP_LOGI("AbilityThread::BatchInsert before abilityImpl_->BatchInsert"); + ret = abilityImpl_->BatchInsert(uri, values); + APP_LOGI("AbilityThread::BatchInsert after abilityImpl_->BatchInsert"); + APP_LOGI("AbilityThread::BatchInsert end"); + return ret; +} + +void AbilityThread::NotifyMultiWinModeChanged(int32_t winModeKey, bool flag) +{ + APP_LOGI("NotifyMultiWinModeChanged.key:%{public}d,flag:%{public}d", winModeKey, flag); + sptr window = currentAbility_->GetWindow(); + if (window == nullptr) { + APP_LOGE("NotifyMultiWinModeChanged window == nullptr"); + return; + } + + return; +} + +void AbilityThread::NotifyTopActiveAbilityChanged(bool flag) +{ + APP_LOGI("NotifyTopActiveAbilityChanged,flag:%{public}d", flag); + sptr window = currentAbility_->GetWindow(); + if (window == nullptr) { + APP_LOGE("NotifyMultiWinModeChanged window == nullptr"); + return; + } + if (flag) { + window->SwitchTop(); + } + return; +} + +/** + * @description: Attach The ability thread to the main process. + * @param application Indicates the main process. + * @param abilityRecord Indicates the abilityRecord. + * @param mainRunner The runner which main_thread holds. + */ +void AbilityThread::AbilityThreadMain(std::shared_ptr &application, + const std::shared_ptr &abilityRecord, const std::shared_ptr &mainRunner) +{ + APP_LOGI("AbilityThread::AbilityThreadMain begin"); + sptr thread = sptr(new (std::nothrow) AbilityThread()); + if (thread == nullptr) { + APP_LOGE("AbilityThread::AbilityThreadMain failed,thread is nullptr"); + return; + } + thread->Attach(application, abilityRecord, mainRunner); + APP_LOGI("AbilityThread::AbilityThreadMain end"); +} + +/** + * @description: Attach The ability thread to the main process. + * @param application Indicates the main process. + * @param abilityRecord Indicates the abilityRecord. + */ +void AbilityThread::AbilityThreadMain( + std::shared_ptr &application, const std::shared_ptr &abilityRecord) +{ + APP_LOGI("AbilityThread::AbilityThreadMain begin"); + sptr thread = sptr(new (std::nothrow) AbilityThread()); + if (thread == nullptr) { + APP_LOGE("AbilityThread::AbilityThreadMain failed,thread is nullptr"); + return; + } + thread->Attach(application, abilityRecord); + APP_LOGI("AbilityThread::AbilityThreadMain end"); +} +/** + * @brief Converts the given uri that refer to the Data ability into a normalized URI. A normalized URI can be used + * across devices, persisted, backed up, and restored. It can refer to the same item in the Data ability even if the + * context has changed. If you implement URI normalization for a Data ability, you must also implement + * denormalizeUri(ohos.utils.net.Uri) to enable URI denormalization. After this feature is enabled, URIs passed to any + * method that is called on the Data ability must require normalization verification and denormalization. The default + * implementation of this method returns null, indicating that this Data ability does not support URI normalization. + * + * @param uri Indicates the Uri object to normalize. + * + * @return Returns the normalized Uri object if the Data ability supports URI normalization; returns null otherwise. + */ +Uri AbilityThread::NormalizeUri(const Uri &uri) +{ + APP_LOGI("AbilityThread::NormalizeUri begin"); + Uri urivalue(""); + if (abilityImpl_ == nullptr) { + APP_LOGE("DataAbilityHelper::normalizeUri failed dataAbility == nullptr"); + return urivalue; + } + + APP_LOGI("AbilityThread::NormalizeUri before abilityImpl_->NormalizeUri"); + urivalue = abilityImpl_->NormalizeUri(uri); + APP_LOGI("AbilityThread::NormalizeUri after abilityImpl_->NormalizeUri"); + APP_LOGI("AbilityThread::NormalizeUri end"); + return urivalue; +} + +/** + * @brief Converts the given normalized uri generated by normalizeUri(ohos.utils.net.Uri) into a denormalized one. + * The default implementation of this method returns the original URI passed to it. + * + * @param uri uri Indicates the Uri object to denormalize. + * + * @return Returns the denormalized Uri object if the denormalization is successful; returns the original Uri passed to + * this method if there is nothing to do; returns null if the data identified by the original Uri cannot be found in the + * current environment. + */ +Uri AbilityThread::DenormalizeUri(const Uri &uri) +{ + APP_LOGI("AbilityThread::DenormalizeUri begin"); + Uri urivalue(""); + if (abilityImpl_ == nullptr) { + APP_LOGE("DataAbilityHelper::denormalizeUri failed dataAbility == nullptr"); + return urivalue; + } + + APP_LOGI("AbilityThread::DenormalizeUri before abilityImpl_->DenormalizeUri"); + urivalue = abilityImpl_->DenormalizeUri(uri); + APP_LOGI("AbilityThread::DenormalizeUri after abilityImpl_->DenormalizeUri"); + APP_LOGI("AbilityThread::DenormalizeUri end"); + return urivalue; +} + +/** + * @brief Registers an observer to DataObsMgr specified by the given Uri. + * + * @param uri, Indicates the path of the data to operate. + * @param dataObserver, Indicates the IDataAbilityObserver object. + */ +bool AbilityThread::HandleRegisterObserver(const Uri &uri, const sptr &dataObserver) +{ + auto obsMgrClient = DataObsMgrClient::GetInstance(); + if (obsMgrClient == nullptr) { + APP_LOGE("%{public}s obsMgrClient is nullptr", __func__); + return false; + } + + ErrCode ret = obsMgrClient->RegisterObserver(uri, dataObserver); + if (ret != ERR_OK) { + APP_LOGE("%{public}s obsMgrClient->RegisterObserver error return %{public}d", __func__, ret); + return false; + } + return true; +} + +/** + * @brief Deregisters an observer used for DataObsMgr specified by the given Uri. + * + * @param uri, Indicates the path of the data to operate. + * @param dataObserver, Indicates the IDataAbilityObserver object. + */ +bool AbilityThread::HandleUnregisterObserver(const Uri &uri, const sptr &dataObserver) +{ + auto obsMgrClient = DataObsMgrClient::GetInstance(); + if (obsMgrClient == nullptr) { + APP_LOGE("%{public}s obsMgrClient is nullptr", __func__); + return false; + } + + ErrCode ret = obsMgrClient->UnregisterObserver(uri, dataObserver); + if (ret != ERR_OK) { + APP_LOGE("%{public}s obsMgrClient->UnregisterObserver error return %{public}d", __func__, ret); + return false; + } + return true; +} + +/** + * @brief Notifies the registered observers of a change to the data resource specified by Uri. + * + * @param uri, Indicates the path of the data to operate. + */ +bool AbilityThread::HandleNotifyChange(const Uri &uri) +{ + auto obsMgrClient = DataObsMgrClient::GetInstance(); + if (obsMgrClient == nullptr) { + APP_LOGE("%{public}s obsMgrClient is nullptr", __func__); + return false; + } + + ErrCode ret = obsMgrClient->NotifyChange(uri); + if (ret != ERR_OK) { + APP_LOGE("%{public}s obsMgrClient->NotifyChange error return %{public}d", __func__, ret); + return false; + } + return true; +} + +/** + * @brief Access authority verification. + * + * @return Returns true on success, others on failure. + */ +bool AbilityThread::CheckObsPermission() +{ + APP_LOGI("%{public}s CheckObsPermission() run Permission Checkout", __func__); + return true; +} + +/** + * @brief Registers an observer to DataObsMgr specified by the given Uri. + * + * @param uri, Indicates the path of the data to operate. + * @param dataObserver, Indicates the IDataAbilityObserver object. + */ +bool AbilityThread::ScheduleRegisterObserver(const Uri &uri, const sptr &dataObserver) +{ + APP_LOGI("%{public}s called", __func__); + + if (!CheckObsPermission()) { + APP_LOGE("%{public}s CheckObsPermission() return false", __func__); + return false; + } + + auto task = [abilityThread = this, uri, dataObserver]() { + abilityThread->HandleRegisterObserver(uri, dataObserver); + }; + + if (abilityHandler_ == nullptr) { + APP_LOGE("AbilityThread::ScheduleRegisterObserver abilityHandler_ == nullptr"); + return false; + } + + bool ret = abilityHandler_->PostTask(task); + if (!ret) { + APP_LOGE("AbilityThread::ScheduleRegisterObserver PostTask error"); + } + return ret; +} + +/** + * @brief Deregisters an observer used for DataObsMgr specified by the given Uri. + * + * @param uri, Indicates the path of the data to operate. + * @param dataObserver, Indicates the IDataAbilityObserver object. + */ +bool AbilityThread::ScheduleUnregisterObserver(const Uri &uri, const sptr &dataObserver) +{ + APP_LOGI("%{public}s called", __func__); + + if (!CheckObsPermission()) { + APP_LOGE("%{public}s CheckObsPermission() return false", __func__); + return false; + } + + auto task = [abilityThread = this, uri, dataObserver]() { + abilityThread->HandleUnregisterObserver(uri, dataObserver); + }; + + if (abilityHandler_ == nullptr) { + APP_LOGE("AbilityThread::ScheduleUnregisterObserver abilityHandler_ == nullptr"); + return false; + } + + bool ret = abilityHandler_->PostTask(task); + if (!ret) { + APP_LOGE("AbilityThread::ScheduleUnregisterObserver PostTask error"); + } + return ret; +} + +/** + * @brief Notifies the registered observers of a change to the data resource specified by Uri. + * + * @param uri, Indicates the path of the data to operate. + */ +bool AbilityThread::ScheduleNotifyChange(const Uri &uri) +{ + APP_LOGI("%{public}s called", __func__); + + if (!CheckObsPermission()) { + APP_LOGE("%{public}s CheckObsPermission() return false", __func__); + return false; + } + + auto task = [abilityThread = this, uri]() { abilityThread->HandleNotifyChange(uri); }; + + if (abilityHandler_ == nullptr) { + APP_LOGE("AbilityThread::ScheduleNotifyChange abilityHandler_ == nullptr"); + return false; + } + + bool ret = abilityHandler_->PostTask(task); + if (!ret) { + APP_LOGE("AbilityThread::ScheduleNotifyChange PostTask error"); + } + return ret; +} + +std::vector> AbilityThread::ExecuteBatch( + const std::vector> &operations) +{ + + APP_LOGI("AbilityThread::ExecuteBatch start"); + std::vector> results; + if (abilityImpl_ == nullptr) { + APP_LOGE("AbilityThread::ExecuteBatch abilityImpl_ is nullptr"); + results.clear(); + return results; + } + APP_LOGI("AbilityThread::ExecuteBatch before abilityImpl_->ExecuteBatch"); + results = abilityImpl_->ExecuteBatch(operations); + APP_LOGI("AbilityThread::ExecuteBatch after abilityImpl_->ExecuteBatch"); + APP_LOGI("AbilityThread::ExecuteBatch end"); + return results; +} + +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/src/ability_touchevent.cpp b/tools/frameworks/kits/ability/native/src/ability_touchevent.cpp new file mode 100644 index 00000000000..6109b60ae92 --- /dev/null +++ b/tools/frameworks/kits/ability/native/src/ability_touchevent.cpp @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ability_touchevent.h" +#include "ability_impl.h" +#include "app_log_wrapper.h" +#include "ability_post_event_timeout.h" + +namespace OHOS { +namespace AppExecFwk { +AbilityTouchEventHandle::AbilityTouchEventHandle(std::shared_ptr abilityImpl) : abilityImpl_(abilityImpl) +{ + APP_LOGI("AbilityTouchEventHandle is created"); +} + +AbilityTouchEventHandle::~AbilityTouchEventHandle() +{ + APP_LOGI("AbilityTouchEventHandle is destroyed"); +} + +#ifdef MMI_COMPILE +/** + * @brief Called back when on touch. + */ +bool AbilityTouchEventHandle::OnTouch(const TouchEvent &touchEvent) +{ + APP_LOGI("AbilityTouchEventHandle::OnTouch called."); + bool ret = false; + if (abilityImpl_ == nullptr) { + APP_LOGE("AbilityTouchEventHandle::OnTouch abilityImpl_ is nullptr"); + return ret; + } + + std::string taskHead("OnTouch"); + std::string taskCodeAction = std::to_string(touchEvent.GetAction()); + std::string taskCodePhase = std::to_string(touchEvent.GetPhase()); + std::string taskSplit("-"); + auto timeOut = + abilityImpl_->CreatePostEventTimeouter(taskHead + taskCodeAction + taskSplit + taskCodePhase + taskSplit); + if (timeOut == nullptr) { + APP_LOGW("AbilityTouchEventHandle::OnTouch timeouter Create return nullptr"); + ret = abilityImpl_->DoTouchEvent(touchEvent); + } else { + timeOut->TimingBegin(); + ret = abilityImpl_->DoTouchEvent(touchEvent); + timeOut->TimeEnd(); + } + + APP_LOGI("AbilityImpl::DoTouchEvent action: %{public}d phase: %{public}d.", + touchEvent.GetAction(), + touchEvent.GetPhase()); + return ret; +} +#endif +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/src/ability_window.cpp b/tools/frameworks/kits/ability/native/src/ability_window.cpp new file mode 100755 index 00000000000..f1efe6e4e67 --- /dev/null +++ b/tools/frameworks/kits/ability/native/src/ability_window.cpp @@ -0,0 +1,313 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ability_window.h" +#include "ability.h" +#include "ability_handler.h" +#include "app_log_wrapper.h" + +namespace OHOS { +namespace AppExecFwk { +AbilityWindow::AbilityWindow() +{} + +AbilityWindow::~AbilityWindow() +{} + +/** + * @brief Init the AbilityWindow object. + * + * @param handler The EventHandler of the Ability the AbilityWindow belong. + */ +void AbilityWindow::Init(std::shared_ptr &handler, std::shared_ptr ability) +{ + APP_LOGI("%{public}s begin.", __func__); + handler_ = handler; + ability_ = std::weak_ptr(ability); + + auto wmi = WindowManager::GetInstance(); + if (wmi == nullptr) { + APP_LOGE("AbilityWindow::Init WindowManager::GetInstance() is nullptr."); + return; + } + + auto wret = wmi->Init(); + if (wret != WM_OK) { + APP_LOGE("AbilityWindow::Init WindowManager::Init() return %d", wret); + return; + } + APP_LOGI("%{public}s end.", __func__); +} + +/** + * @brief Sets the window config for the host ability to create window. + * + * @param config Indicates window config. + */ +bool AbilityWindow::SetWindowConfig(const sptr &config) +{ + APP_LOGI("%{public}s begin.", __func__); + + APP_LOGI("config width = %{public}d, height = %{public}d.", config->GetWidth(), config->GetHeight()); + APP_LOGI("config pos_x = %{public}d, pos_y = %{public}d, type = %{public}d.", + config->GetX(), + config->GetY(), + config->GetWindowType()); + + auto wmi = WindowManager::GetInstance(); + if (wmi == nullptr) { + APP_LOGE("AbilityWindow::Init WindowManager::GetInstance() is nullptr."); + return false; + } + + APP_LOGI("%{public}s begin wms->CreateWindow.", __func__); + auto retvalCreate = wmi->CreateWindow(windowNew_, config); + APP_LOGI("%{public}s end wms->CreateWindow.", __func__); + if (retvalCreate != WM_OK) { + APP_LOGE("AbilityWindow::SetWindowConfig WindowManager::CreateWindow() return %d", retvalCreate); + return false; + } + + if (windowNew_ == nullptr) { + APP_LOGE("AbilityWindow::SetWindowConfig the window is nullptr."); + return false; + } + + auto callback = [abilityWindow = this](KeyEvent event) -> bool { return abilityWindow->OnKeyEvent(event); }; + APP_LOGI("%{public}s begin windowNew_->RegistOnKeyCb.", __func__); + auto retvalKeyboardKey = windowNew_->OnKey(callback); + APP_LOGI("%{public}s end windowNew_->RegistOnKeyCb.", __func__); + if (retvalKeyboardKey != WM_OK) { + APP_LOGE("AbilityWindow::SetWindowConfig WindowManager::OnKey() return %d", retvalKeyboardKey); + return false; + } + + isWindowAttached = true; + APP_LOGI("%{public}s end.", __func__); + + return true; +} + +/** + * @brief Called when the KeyEvent sent. + * + * @param KeyEvent the key event. + * + * @return Returns true if the listener has processed the event; returns false otherwise. + * + */ +bool AbilityWindow::OnKeyEvent(KeyEvent event) +{ + APP_LOGI("%{public}s begin.", __func__); + + bool ret = false; + std::shared_ptr ability = nullptr; + ability = ability_.lock(); + if (ability == nullptr) { + APP_LOGE("AbilityWindow::OnKeyEvent ability is nullptr."); + return ret; + } + switch (event.GetKeyCode()) { +#ifdef MMI_COMPILE + case OHOS::KeyEventEnum::KEY_BACK: +#else + case KeyEvent::CODE_BACK: +#endif + APP_LOGI("AbilityWindow::OnKeyEvent Back key pressed."); + if (!event.IsKeyDown()) { + ret = OnBackPressed(ability); + } + break; + default: + APP_LOGI("AbilityWindow::OnKeyEvent the key event is %{public}d.", event.GetKeyCode()); + break; + } + APP_LOGI("%{public}s end.", __func__); + return ret; +} + +/** + * @brief Called back when the Back key is pressed. + * + * @param ability The ability receive the event. + * + * @return Returns true if the listener has processed the event; returns false otherwise. + * + */ +bool AbilityWindow::OnBackPressed(std::shared_ptr &ability) +{ + APP_LOGI("%{public}s begin.", __func__); + if (handler_ == nullptr) { + APP_LOGE("AbilityWindow::OnBackPressed handler_ is nullptr."); + return false; + } + auto task = [abilityRun = ability]() { abilityRun->OnBackPressed(); }; + handler_->PostTask(task); + APP_LOGI("%{public}s end.", __func__); + return true; +} + +/** + * @brief Called when this ability is started. + * + */ +void AbilityWindow::OnPostAbilityStart() +{ + APP_LOGI("%{public}s begin.", __func__); + if (!isWindowAttached) { + APP_LOGE("AbilityWindow::OnPostAbilityStart window not attached."); + return; + } + + if (windowNew_ != nullptr) { + APP_LOGI("%{public}s begin windowNew_->Hide.", __func__); + windowNew_->Hide(); + APP_LOGI("%{public}s end windowNew_->Hide.", __func__); + } + + APP_LOGI("%{public}s end.", __func__); +} + +/** + * @brief Called when this ability is activated. + * + */ +void AbilityWindow::OnPostAbilityActive() +{ + APP_LOGI("AbilityWindow::OnPostAbilityActive called."); + if (!isWindowAttached) { + APP_LOGE("AbilityWindow::OnPostAbilityActive window not attached."); + return; + } + + if (windowNew_ != nullptr) { + APP_LOGI("%{public}s begin windowNew_->SwitchTop.", __func__); + windowNew_->SwitchTop(); + APP_LOGI("%{public}s end windowNew_->SwitchTop.", __func__); + + APP_LOGI("%{public}s begin windowNew_->Show.", __func__); + windowNew_->Show(); + APP_LOGI("%{public}s end windowNew_->Show.", __func__); + } + + APP_LOGI("AbilityWindow::OnPostAbilityActive end."); +} + +/** + * @brief Called when this ability is inactivated. + * + */ +void AbilityWindow::OnPostAbilityInactive() +{ + APP_LOGI("AbilityWindow::OnPostAbilityInactive called."); + if (!isWindowAttached) { + APP_LOGE("AbilityWindow::OnPostAbilityInactive window not attached."); + return; + } + + if (windowNew_ != nullptr) { + APP_LOGI("%{public}s begin windowNew_->Hide.", __func__); + windowNew_->Hide(); + APP_LOGI("%{public}s end windowNew_->Hide.", __func__); + } + + APP_LOGI("AbilityWindow::OnPostAbilityInactive end."); +} + +/** + * @brief Called when this ability is background. + * + */ +void AbilityWindow::OnPostAbilityBackground() +{ + APP_LOGI("AbilityWindow::OnPostAbilityBackground called."); + if (!isWindowAttached) { + APP_LOGE("AbilityWindow::OnPostAbilityBackground window not attached."); + return; + } + + if (windowNew_ != nullptr) { + APP_LOGI("%{public}s begin windowNew_->Hide.", __func__); + windowNew_->Hide(); + APP_LOGI("%{public}s end windowNew_->Hide.", __func__); + } + + APP_LOGI("AbilityWindow::OnPostAbilityBackground end."); +} + +/** + * @brief Called when this ability is foreground. + * + */ +void AbilityWindow::OnPostAbilityForeground() +{ + APP_LOGI("AbilityWindow::OnPostAbilityForeground called."); + if (!isWindowAttached) { + APP_LOGE("AbilityWindow::OnPostAbilityForeground window not attached."); + return; + } + + if (windowNew_ != nullptr) { + APP_LOGI("%{public}s begin windowNew_->Show.", __func__); + windowNew_->Show(); + APP_LOGI("%{public}s end windowNew_->Show.", __func__); + } + + APP_LOGI("AbilityWindow::OnPostAbilityForeground end."); +} + +/** + * @brief Called when this ability is stopped. + * + */ +void AbilityWindow::OnPostAbilityStop() +{ + APP_LOGI("AbilityWindow::OnPostAbilityStop called."); + if (!isWindowAttached) { + APP_LOGE("AbilityWindow::OnPostAbilityStop window not attached."); + return; + } + + if (windowNew_ != nullptr) { + int32_t windowID = windowNew_->GetID(); + APP_LOGI("AbilityWindow::widow::DestroyWindow called windowID=%{public}d begin.", windowID); + windowNew_->Destroy(); + APP_LOGI("AbilityWindow::widow::DestroyWindow called windowID=%{public}d end.", windowID); + windowNew_ = nullptr; + APP_LOGI("AbilityWindow::widow:: windowNew_ release end."); + } + + isWindowAttached = false; + APP_LOGI("AbilityWindow::OnPostAbilityStop end."); +} + +/** + * @brief Get the window belong to the ability. + * + * @return Returns a Window object pointer. + */ +const sptr AbilityWindow::GetWindow() +{ + if (!isWindowAttached) { + APP_LOGE("AbilityWindow::GetWindow window not attached."); + } + + if (windowNew_ == nullptr) { + APP_LOGE("AbilityWindow::GetWindow the window is nullptr."); + } + return windowNew_; +} +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/src/continuation/distributed/ability_distributed_connect_callback_stub.cpp b/tools/frameworks/kits/ability/native/src/continuation/distributed/ability_distributed_connect_callback_stub.cpp new file mode 100644 index 00000000000..482aa036902 --- /dev/null +++ b/tools/frameworks/kits/ability/native/src/continuation/distributed/ability_distributed_connect_callback_stub.cpp @@ -0,0 +1,89 @@ + +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ability_distributed_connect_callback_stub.h" + +#include "hilog_wrapper.h" +#include "ipc_types.h" +#include "message_parcel.h" +#include "want.h" + +namespace OHOS { +namespace AAFwk { +AbilityDistributedConnectionStub::AbilityDistributedConnectionStub() +{} + +AbilityDistributedConnectionStub::~AbilityDistributedConnectionStub() +{} + +int AbilityDistributedConnectionStub::OnRemoteRequest( + uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) +{ + std::u16string descriptor = AbilityDistributedConnectionStub::GetDescriptor(); + std::u16string remoteDescriptor = data.ReadInterfaceToken(); + if (descriptor != remoteDescriptor) { + HILOG_INFO("Local descriptor is not equal to remote"); + return ERR_INVALID_STATE; + } + + auto element = data.ReadParcelable(); + switch (code) { + case IAbilityDistributedConnection::ON_ABILITY_DISTRIBUTE_CONNECT_DONE: { + if (element == nullptr) { + HILOG_ERROR("callback stub receive element is nullptr"); + return ERR_INVALID_VALUE; + } + auto remoteObject = data.ReadRemoteObject(); + auto resultCode = data.ReadInt32(); + OnAbilityConnectDone(*element, remoteObject, resultCode); + delete element; + return NO_ERROR; + } + case IAbilityDistributedConnection::ON_ABILITY_DISTRIBUTE_DISCONNECT_DONE: { + if (element == nullptr) { + HILOG_ERROR("callback stub receive element is nullptr"); + return ERR_INVALID_VALUE; + } + auto resultCode = data.ReadInt32(); + OnAbilityDisconnectDone(*element, resultCode); + delete element; + return NO_ERROR; + } + default: { + if (element != nullptr) { + delete element; + } + return IPCObjectStub::OnRemoteRequest(code, data, reply, option); + } + } +} + +void AbilityDistriubuteConnectCallbackRecipient::OnRemoteDied(const wptr &__attribute__((unused)) remote) +{ + HILOG_ERROR("On remote died."); + if (handler_) { + handler_(remote); + } +} + +AbilityDistriubuteConnectCallbackRecipient::AbilityDistriubuteConnectCallbackRecipient(RemoteDiedHandler handler) + : handler_(handler) +{} + +AbilityDistriubuteConnectCallbackRecipient::~AbilityDistriubuteConnectCallbackRecipient() +{} +} // namespace AAFwk +} // namespace OHOS diff --git a/tools/frameworks/kits/ability/native/src/continuation/distributed/ability_distributed_connection.cpp b/tools/frameworks/kits/ability/native/src/continuation/distributed/ability_distributed_connection.cpp new file mode 100644 index 00000000000..bef0906c3f1 --- /dev/null +++ b/tools/frameworks/kits/ability/native/src/continuation/distributed/ability_distributed_connection.cpp @@ -0,0 +1,49 @@ + +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ability_distributed_connection.h" +#include "hilog_wrapper.h" + +namespace OHOS { +namespace AAFwk { +AbilityDistributedConnection::AbilityDistributedConnection(const sptr &conn) +{ + HILOG_INFO("%{public}s called.", __func__); + conn_ = conn; +} + +void AbilityDistributedConnection::OnAbilityConnectDone( + const AppExecFwk::ElementName &element, const sptr &remoteObject, int resultCode) +{ + HILOG_INFO("%{public}s called.", __func__); + if (conn_ == nullptr) { + HILOG_INFO("%{public}s conn_ == nullptr.", __func__); + return; + } + conn_->OnAbilityConnectDone(element, remoteObject, resultCode); +} + +void AbilityDistributedConnection::OnAbilityDisconnectDone(const AppExecFwk::ElementName &element, int resultCode) +{ + HILOG_INFO("%{public}s called.", __func__); + if (conn_ == nullptr) { + HILOG_INFO("%{public}s conn_ == nullptr.", __func__); + return; + } + conn_->OnAbilityDisconnectDone(element, resultCode); +} +} // namespace AAFwk +} // namespace OHOS diff --git a/tools/frameworks/kits/ability/native/src/continuation/distributed/continuation_handler.cpp b/tools/frameworks/kits/ability/native/src/continuation/distributed/continuation_handler.cpp new file mode 100755 index 00000000000..3fc4aa64739 --- /dev/null +++ b/tools/frameworks/kits/ability/native/src/continuation/distributed/continuation_handler.cpp @@ -0,0 +1,345 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "continuation_handler.h" +#include "element_name.h" +#include "distributed_client.h" +#include "app_log_wrapper.h" + +using OHOS::AAFwk::WantParams; +namespace OHOS { +namespace AppExecFwk { +const std::string ContinuationHandler::ORIGINAL_DEVICE_ID("deviceId"); +ContinuationHandler::ContinuationHandler( + std::weak_ptr &continuationManager, std::weak_ptr &ability) +{ + ability_ = ability; + continuationManager_ = continuationManager; +} + +bool ContinuationHandler::HandleStartContinuation(const sptr &token, const std::string &deviceId) +{ + APP_LOGI("%{public}s called begin", __func__); + if (token == nullptr) { + APP_LOGE("ContinuationHandler::HandleStartContinuation token is null."); + return false; + } + if (abilityInfo_ == nullptr) { + APP_LOGE("ContinuationHandler::HandleStartContinuation abilityInfo is null."); + return false; + } + + abilityInfo_->deviceId = deviceId; + + std::shared_ptr continuationManagerTmp = nullptr; + continuationManagerTmp = continuationManager_.lock(); + if (continuationManagerTmp == nullptr) { + APP_LOGE("handleStartContinuation: get continuationManagerTmp is nullptr"); + return false; + } + + // DMS decided to start continuation. Callback to ability. + if (!continuationManagerTmp->StartContinuation()) { + APP_LOGI("handleStartContinuation: Ability rejected."); + APP_LOGI("ID_ABILITY_SHELL_CONTINUE_ABILITY, BundleName = %{public}s, ClassName= %{public}s", + abilityInfo_->bundleName.c_str(), + abilityInfo_->name.c_str()); + return false; + } + + WantParams wantParams; + if (!continuationManagerTmp->SaveData(wantParams)) { + APP_LOGI("handleStartContinuation: ScheduleSaveData failed."); + APP_LOGI("ID_ABILITY_SHELL_CONTINUE_ABILITY, BundleName = %{public}s, ClassName= %{public}s", + abilityInfo_->bundleName.c_str(), + abilityInfo_->name.c_str()); + return false; + } + + Want want = SetWantParams(wantParams); + want.SetElementName(deviceId, abilityInfo_->bundleName, abilityInfo_->name); + + int result = DistributedClient::GetInstance()->StartContinuation(want, *abilityInfo_, token); + if (result != 0) { + APP_LOGE("distClient_.startContinuation failed."); + return false; + } + APP_LOGI("%{public}s called end", __func__); + return true; +} + +void ContinuationHandler::HandleReceiveRemoteScheduler(const sptr &remoteReplica) +{ + APP_LOGI("%{public}s called begin", __func__); + if (remoteReplica == nullptr) { + APP_LOGE("scheduler is nullptr"); + return; + } + + if (remoteReplicaProxy_ != nullptr && schedulerDeathRecipient_ != nullptr) { + auto schedulerObjectTmp = remoteReplicaProxy_->AsObject(); + if (schedulerObjectTmp != nullptr) { + schedulerObjectTmp->RemoveDeathRecipient(schedulerDeathRecipient_); + } + } + + if (schedulerDeathRecipient_ == nullptr) { + schedulerDeathRecipient_ = new (std::nothrow) ReverseContinuationSchedulerRecipient( + std::bind(&ContinuationHandler::OnReplicaDied, this, std::placeholders::_1)); + } + + remoteReplicaProxy_ = iface_cast(remoteReplica); + auto schedulerObject = remoteReplicaProxy_->AsObject(); + if (schedulerObject != nullptr) { + schedulerObject->AddDeathRecipient(schedulerDeathRecipient_); + } + + remoteReplicaProxy_->PassPrimary(remotePrimaryStub_); + APP_LOGI("%{public}s called end", __func__); +} + +void ContinuationHandler::HandleCompleteContinuation(int result) +{ + APP_LOGI("%{public}s called begin", __func__); + std::shared_ptr continuationManagerTmp = nullptr; + continuationManagerTmp = continuationManager_.lock(); + if (continuationManagerTmp == nullptr) { + APP_LOGE("ContinuationHandler::HandleCompleteContinuation: get continuationManagerTmp is nullptr"); + return; + } + + continuationManagerTmp->CompleteContinuation(result); + APP_LOGI("%{public}s called end", __func__); +} + +void ContinuationHandler::SetReversible(bool reversible) +{ + APP_LOGI("%{public}s called", __func__); + reversible_ = reversible; +} + +void ContinuationHandler::SetAbilityInfo(std::shared_ptr &abilityInfo) +{ + APP_LOGI("%{public}s called begin", __func__); + abilityInfo_ = abilityInfo; + APP_LOGI("%{public}s called end", __func__); +} + +void ContinuationHandler::SetPrimaryStub(const sptr &Primary) +{ + APP_LOGI("%{public}s called", __func__); + remotePrimaryStub_ = Primary; +} + +void ContinuationHandler::ClearDeviceInfo(std::shared_ptr &abilityInfo) +{ + APP_LOGI("%{public}s called", __func__); + abilityInfo->deviceId = ""; + abilityInfo->deviceTypes.clear(); +} + +void ContinuationHandler::OnReplicaDied(const wptr &remote) +{ + APP_LOGI("%{public}s called begin", __func__); + if (remoteReplicaProxy_ == nullptr) { + APP_LOGE("BUG: remote death notifies to a unready replica."); + return; + } + + auto object = remote.promote(); + if (!object) { + APP_LOGE("replica on remoteReplica died: null object."); + return; + } + + if (object != remoteReplicaProxy_->AsObject()) { + APP_LOGE("replica on remoteReplica died: remoteReplica is not matches with remote."); + return; + } + + if (remoteReplicaProxy_ != nullptr && schedulerDeathRecipient_ != nullptr) { + auto schedulerObject = remoteReplicaProxy_->AsObject(); + if (schedulerObject != nullptr) { + schedulerObject->RemoveDeathRecipient(schedulerDeathRecipient_); + } + } + remoteReplicaProxy_.clear(); + + NotifyReplicaTerminated(); + APP_LOGI("%{public}s called end", __func__); +} + +void ContinuationHandler::NotifyReplicaTerminated() +{ + APP_LOGI("%{public}s called begin", __func__); + + CleanUpAfterReverse(); + + std::shared_ptr continuationManagerTmp = nullptr; + continuationManagerTmp = continuationManager_.lock(); + if (continuationManagerTmp == nullptr) { + APP_LOGE("ContinuationHandler::NotifyReplicaTerminated: get continuationManagerTmp is nullptr"); + return; + } + APP_LOGI("%{public}s called end", __func__); + continuationManagerTmp->NotifyRemoteTerminated(); +} + +Want ContinuationHandler::SetWantParams(const WantParams &wantParams) +{ + APP_LOGI("%{public}s called begin", __func__); + Want want; + want.SetParams(wantParams); + want.AddFlags(want.FLAG_ABILITY_CONTINUATION); + if (abilityInfo_->launchMode != LaunchMode::STANDARD) { + APP_LOGI("SetWantParams: Clear task."); + } + if (reversible_) { + APP_LOGI("SetWantParams: Reversible."); + want.AddFlags(Want::FLAG_ABILITY_CONTINUATION_REVERSIBLE); + } + ElementName element("", abilityInfo_->bundleName, abilityInfo_->name); + want.SetElement(element); + APP_LOGI("%{public}s called end", __func__); + return want; +} + +void ContinuationHandler::CleanUpAfterReverse() +{ + APP_LOGI("%{public}s called", __func__); + remoteReplicaProxy_ = nullptr; +} + +void ContinuationHandler::PassPrimary(const sptr &Primary) +{ + APP_LOGI("%{public}s called", __func__); + remotePrimaryProxy_ = iface_cast(Primary); +} + +bool ContinuationHandler::ReverseContinuation() +{ + APP_LOGI("%{public}s called begin", __func__); + + if (remotePrimaryProxy_ == nullptr) { + APP_LOGE("ReverseContinuation:remotePrimaryProxy_ not initialized, can not reverse"); + return false; + } + + if (abilityInfo_ == nullptr) { + APP_LOGE("ReverseContinuation: abilityInfo is null"); + return false; + } + + std::shared_ptr continuationManagerTmp = nullptr; + continuationManagerTmp = continuationManager_.lock(); + if (continuationManagerTmp == nullptr) { + APP_LOGE("ReverseContinuation: get continuationManagerTmp is nullptr"); + return false; + } + + if (!continuationManagerTmp->StartContinuation()) { + APP_LOGE("ReverseContinuation: Ability rejected."); + APP_LOGI("ReverseContinuation, BundleName = %{public}s, ClassName= %{public}s", + abilityInfo_->bundleName.c_str(), + abilityInfo_->name.c_str()); + return false; + } + + WantParams wantParams; + if (!continuationManagerTmp->SaveData(wantParams)) { + APP_LOGE("ReverseContinuation: SaveData failed."); + APP_LOGI("ReverseContinuation, BundleName = %{public}s, ClassName= %{public}s", + abilityInfo_->bundleName.c_str(), + abilityInfo_->name.c_str()); + return false; + } + + Want want; + want.SetParams(wantParams); + if (remotePrimaryProxy_->ContinuationBack(want)) { + APP_LOGE("reverseContinuation: ContinuationBack send failed."); + return false; + } + APP_LOGI("%{public}s called end", __func__); + return true; +} + +void ContinuationHandler::NotifyReverseResult(int reverseResult) +{ + APP_LOGI("NotifyReverseResult: Start. result = %{public}d", reverseResult); + if (reverseResult == 0) { + std::shared_ptr ability = nullptr; + ability = ability_.lock(); + if (ability == nullptr) { + APP_LOGE("ContinuationHandler::NotifyReverseResult failed. ability is nullptr"); + return; + } + ability->TerminateAbility(); + } + APP_LOGI("%{public}s called end", __func__); +} + +bool ContinuationHandler::ContinuationBack(const Want &want) +{ + APP_LOGI("%{public}s called begin", __func__); + std::shared_ptr continuationManagerTmp = nullptr; + continuationManagerTmp = continuationManager_.lock(); + if (continuationManagerTmp == nullptr) { + APP_LOGE("ContinuationBack: get continuationManagerTmp is nullptr"); + return false; + } + + int result = 0; + if (!continuationManagerTmp->RestoreFromRemote(want.GetParams())) { + APP_LOGI("ContinuationBack: RestoreFromRemote failed."); + result = ABILITY_FAILED_RESTORE_DATA; + } + + remoteReplicaProxy_->NotifyReverseResult(result); + if (result == 0) { + CleanUpAfterReverse(); + } + APP_LOGI("%{public}s called end", __func__); + return true; +} + +void ContinuationHandler::NotifyTerminationToPrimary() +{ + APP_LOGI("%{public}s called begin", __func__); + if (remotePrimaryProxy_ == nullptr) { + APP_LOGE("NotifyTerminationToPrimary: remotePrimary not initialized, can not notify"); + return; + } + + APP_LOGI("NotifyTerminationToPrimary: Start"); + remotePrimaryProxy_->NotifyReplicaTerminated(); + APP_LOGI("%{public}s called end", __func__); +} + +bool ContinuationHandler::ReverseContinueAbility() +{ + APP_LOGI("%{public}s called begin", __func__); + if (remoteReplicaProxy_ == nullptr) { + APP_LOGE("ReverseContinueAbility: remoteReplica not initialized, can not reverse"); + return false; + } + + APP_LOGI("ReverseContinueAbility: Start"); + bool requestSendSuccess = remoteReplicaProxy_->ReverseContinuation(); + APP_LOGI("%{public}s called end", __func__); + return requestSendSuccess; +} + +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/src/continuation/distributed/continuation_manager.cpp b/tools/frameworks/kits/ability/native/src/continuation/distributed/continuation_manager.cpp new file mode 100644 index 00000000000..0e3a7bf3981 --- /dev/null +++ b/tools/frameworks/kits/ability/native/src/continuation/distributed/continuation_manager.cpp @@ -0,0 +1,576 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "continuation_manager.h" +#include "ability.h" +#include "ability_continuation_interface.h" +#include "continuation_handler.h" +#include "app_log_wrapper.h" +#include "want.h" +#include "continuation_scheduler.h" +#include "distributed_client.h" +#include "string_ex.h" +#include "operation_builder.h" + +namespace OHOS { +namespace AppExecFwk { +const int ContinuationManager::TIMEOUT_MS_WAIT_DMS_SCHEDULE_START_CONTINUATION = 5000; +const int ContinuationManager::TIMEOUT_MS_WAIT_DMS_NOTIFY_CONTINUATION_COMPLETE = 6000; +const int ContinuationManager::TIMEOUT_MS_WAIT_REMOTE_NOTIFY_BACK = 6000; + +ContinuationManager::ContinuationManager() +{ + progressState_ = ProgressState::INITIAL; +} + +bool ContinuationManager::Init(const std::shared_ptr &ability, const sptr &continueToken, + const std::shared_ptr &abilityInfo, const std::shared_ptr &continuationHandler) +{ + APP_LOGI("%{public}s called begin", __func__); + if (ability == nullptr) { + APP_LOGE("ContinuationManager::Init failed. ability is nullptr"); + return false; + } + ability_ = ability; + + std::shared_ptr abilityTmp = nullptr; + abilityTmp = ability_.lock(); + if (abilityTmp == nullptr) { + APP_LOGE("ContinuationManager::Init failed. get ability is nullptr"); + return false; + } + + if (abilityTmp->GetAbilityInfo() == nullptr) { + APP_LOGE("ContinuationManager::Init failed. abilityInfo is nullptr"); + return false; + } + abilityInfo_ = abilityTmp->GetAbilityInfo(); + + if (continueToken == nullptr) { + APP_LOGE("ContinuationManager::Init failed. continueToken is nullptr"); + return false; + } + continueToken_ = continueToken; + + continuationHandler_ = continuationHandler; + APP_LOGI("%{public}s called end", __func__); + return true; +} + +ContinuationState ContinuationManager::GetContinuationState() +{ + return continuationState_; +} + +std::string ContinuationManager::GetOriginalDeviceId() +{ + return originalDeviceId_; +} + +void ContinuationManager::ContinueAbility(bool reversible, const std::string &deviceId) +{ + APP_LOGI("%{public}s called begin", __func__); + if (CheckContinuationIllegal()) { + APP_LOGE("ContinuationManager::ContinueAbility failed. Ability not available to continueAbility."); + return; + } + + if (progressState_ != ProgressState::INITIAL) { + APP_LOGE("ContinuationManager::ContinueAbility failed. Another request in progress. progressState_: %{public}d", + progressState_); + return; + } + + if (continuationState_ != ContinuationState::LOCAL_RUNNING) { + APP_LOGE("ContinuationManager::ContinueAbility failed. Illegal continuation state. Current state is %{public}d", + continuationState_); + return; + } + + if (HandleContinueAbility(reversible, deviceId)) { + reversible_ = reversible; + ChangeProcessState(ProgressState::WAITING_SCHEDULE); + // Wait state change timeout. Restore state + RestoreStateWhenTimeout(TIMEOUT_MS_WAIT_DMS_SCHEDULE_START_CONTINUATION, ProgressState::WAITING_SCHEDULE); + } + APP_LOGI("%{public}s called end", __func__); +} + +bool ContinuationManager::ReverseContinueAbility() +{ + APP_LOGI("%{public}s called begin", __func__); + if (progressState_ != ProgressState::INITIAL) { + APP_LOGE("ContinuationManager::ReverseContinueAbility failed. progressState_ is %{public}d.", progressState_); + return false; + } + + if (continuationState_ != ContinuationState::REMOTE_RUNNING) { + APP_LOGE("ContinuationManager::ReverseContinueAbility failed. continuationState_ is %{public}d.", + continuationState_); + return false; + } + + std::shared_ptr continuationHandler = continuationHandler_.lock(); + if (continuationHandler == nullptr) { + APP_LOGE("ContinuationManager::ReverseContinueAbility failed. continuationHandler_ is nullptr."); + return false; + } + + bool requestSuccess = continuationHandler->ReverseContinueAbility(); + if (requestSuccess) { + ChangeProcessState(ProgressState::WAITING_SCHEDULE); + RestoreStateWhenTimeout(TIMEOUT_MS_WAIT_REMOTE_NOTIFY_BACK, ProgressState::WAITING_SCHEDULE); + } + APP_LOGI("%{public}s called end", __func__); + return requestSuccess; +} + +bool ContinuationManager::StartContinuation() +{ + APP_LOGI("%{public}s called begin", __func__); + ChangeProcessState(ProgressState::IN_PROGRESS); + bool result = DoScheduleStartContinuation(); + if (!result) { + ChangeProcessState(ProgressState::INITIAL); + } + APP_LOGI("%{public}s called end", __func__); + return result; +} + +bool ContinuationManager::SaveData(WantParams &saveData) +{ + APP_LOGI("%{public}s called begin", __func__); + bool result = DoScheduleSaveData(saveData); + if (!result) { + ChangeProcessState(ProgressState::INITIAL); + } else { + RestoreStateWhenTimeout(TIMEOUT_MS_WAIT_DMS_NOTIFY_CONTINUATION_COMPLETE, ProgressState::IN_PROGRESS); + } + APP_LOGI("%{public}s called end", __func__); + return result; +} + +bool ContinuationManager::RestoreData( + const WantParams &restoreData, bool reversible, const std::string &originalDeviceId) +{ + APP_LOGI("%{public}s called begin", __func__); + ChangeProcessState(ProgressState::IN_PROGRESS); + bool result = DoScheduleRestoreData(restoreData); + if (reversible) { + continuationState_ = ContinuationState::REPLICA_RUNNING; + } + originalDeviceId_ = originalDeviceId; + ChangeProcessState(ProgressState::INITIAL); + APP_LOGI("%{public}s called end", __func__); + return result; +} + +void ContinuationManager::NotifyCompleteContinuation( + const std::string &originDeviceId, int sessionId, bool success, const sptr &reverseScheduler) +{ + APP_LOGI("%{public}s called begin", __func__); + InitDistSchedulerHost(); + DistributedClient::GetInstance()->NotifyCompleteContinuation( + Str8ToStr16(originDeviceId), sessionId, success, reverseScheduler); + APP_LOGI("%{public}s called end", __func__); +} + +void ContinuationManager::CompleteContinuation(int result) +{ + APP_LOGI("%{public}s called begin", __func__); + if (CheckContinuationIllegal()) { + APP_LOGE("ContinuationManager::CompleteContinuation failed. Ability not available to complete continuation."); + return; + } + + std::shared_ptr ability = nullptr; + ability = ability_.lock(); + if (ability == nullptr) { + APP_LOGE("ContinuationManager::CheckContinuationIllegal failed. ability is nullptr"); + return; + } + + if (result == 0 && reversible_) { + continuationState_ = ContinuationState::REMOTE_RUNNING; + } + ChangeProcessState(ProgressState::INITIAL); + + ability->OnCompleteContinuation(result); + + if (!reversible_) { + ability->TerminateAbility(); + } + APP_LOGI("%{public}s called end", __func__); +} + +bool ContinuationManager::RestoreFromRemote(const WantParams &restoreData) +{ + APP_LOGI("%{public}s called begin", __func__); + ChangeProcessState(ProgressState::IN_PROGRESS); + bool result = DoRestoreFromRemote(restoreData); + /* + * No matter what the result is, we should reset the status. Because even it fail, we can do + * nothing but let the user send another reverse continuation request again. + */ + ChangeProcessState(ProgressState::INITIAL); + if (result) { + continuationState_ = ContinuationState::LOCAL_RUNNING; + } + APP_LOGI("%{public}s called end", __func__); + return result; +} + +bool ContinuationManager::NotifyRemoteTerminated() +{ + APP_LOGI("%{public}s called begin", __func__); + continuationState_ = ContinuationState::LOCAL_RUNNING; + ChangeProcessState(ProgressState::INITIAL); + + std::shared_ptr ability = nullptr; + ability = ability_.lock(); + if (ability == nullptr) { + APP_LOGE("ContinuationManager::NotifyRemoteTerminated failed. ability is nullptr"); + return false; + } + + ability->OnRemoteTerminated(); + APP_LOGI("%{public}s called end", __func__); + return true; +} + +bool ContinuationManager::CheckContinuationIllegal() +{ + APP_LOGI("%{public}s called begin", __func__); + std::shared_ptr ability = nullptr; + ability = ability_.lock(); + if (ability == nullptr) { + APP_LOGE("ContinuationManager::CheckContinuationIllegal failed. ability is nullptr"); + return false; + } + + if (ability->GetState() >= AbilityLifecycleExecutor::LifecycleState::UNINITIALIZED) { + APP_LOGE("ContinuationManager::CheckContinuationIllegal failed. ability state is wrong: %{public}d", + ability->GetState()); + return true; + } + APP_LOGI("%{public}s called end", __func__); + return false; +} + +bool ContinuationManager::HandleContinueAbility(bool reversible, const std::string &deviceId) +{ + APP_LOGI("%{public}s called begin", __func__); + + if (!CheckAbilityToken()) { + APP_LOGE("ContinuationManager::HandleContinueAbility failed. CheckAbilityToken failed"); + return false; + } + + if (!RegisterAbilityTokenIfNeed(continueToken_)) { + APP_LOGE("ContinuationManager::HandleContinueAbility failed. RegisterAbilityTokenIfNeed failed"); + return false; + } + + sptr continueToken = continueToken_; + std::shared_ptr continuationHandler = continuationHandler_.lock(); + if (continuationHandler == nullptr) { + APP_LOGE("ContinuationManager::HandleContinueAbility failed. continuationHandler is nullptr"); + return false; + } + continuationHandler->SetReversible(reversible); + + auto task = [continuationHandler, continueToken, deviceId]() { + continuationHandler->HandleStartContinuation(continueToken, deviceId); + }; + + if (!mainHandler_->PostTask(task)) { + APP_LOGE("ContinuationManager::HandleContinueAbility failed.PostTask failed"); + return false; + } + + APP_LOGI("%{public}s called end", __func__); + return true; +} + +ContinuationManager::ProgressState ContinuationManager::GetProcessState() +{ + return progressState_; +} + +void ContinuationManager::ChangeProcessState(const ProgressState &newState) +{ + APP_LOGI("%{public}s called begin. progressState_: %{public}d, newState: %{public}d", + __func__, + progressState_, + newState); + + progressState_ = newState; +} + +void ContinuationManager::RestoreStateWhenTimeout(long timeoutInMs, const ProgressState &preState) +{ + APP_LOGI("%{public}s called begin", __func__); + InitMainHandlerIfNeed(); + + auto timeoutTask = [continuationManager = shared_from_this(), preState]() { + APP_LOGI( + "ContinuationManager::RestoreStateWhenTimeout called. preState = %{public}d, currentState = %{public}d.", + preState, + continuationManager->GetProcessState()); + if (preState == continuationManager->GetProcessState()) { + continuationManager->ChangeProcessState(ProgressState::INITIAL); + } + }; + mainHandler_->PostTask(timeoutTask, "Restore_State_When_Timeout", timeoutInMs); + APP_LOGI("%{public}s called end", __func__); +} + +void ContinuationManager::InitMainHandlerIfNeed() +{ + APP_LOGI("%{public}s called begin", __func__); + if (mainHandler_ == nullptr) { + APP_LOGI("Try to init main handler."); + std::lock_guard lock_l(lock_); + if ((mainHandler_ == nullptr) && (EventRunner::GetMainEventRunner() != nullptr)) { + mainHandler_ = std::make_shared(EventRunner::GetMainEventRunner()); + } + } + APP_LOGI("%{public}s called end", __func__); +} + +bool ContinuationManager::CheckAbilityToken() +{ + APP_LOGI("%{public}s called", __func__); + if (continueToken_ == nullptr) { + APP_LOGI("%{public}s called failed", __func__); + return false; + } + APP_LOGI("%{public}s called success", __func__); + return true; +} + +bool ContinuationManager::UnregisterAbilityTokenIfNeed() +{ + APP_LOGI("%{public}s called begin", __func__); + + if (continueToken_ == nullptr) { + APP_LOGE("%{public}s called failed continueToken_ is nullptr", __func__); + return false; + } + + if (!tokenRegistered_) { + APP_LOGI("%{public}s called no need to :Unregister", __func__); + return true; + } + + std::lock_guard lock_l(lockForRegist_); + + if (!tokenRegistered_) { + APP_LOGI("%{public}s called no need to :Unregister", __func__); + return true; + } + + bool unregisterSuccess = UnregisterAbilityToken(continueToken_); + if (unregisterSuccess) { + tokenRegistered_ = false; + } + + APP_LOGI("%{public}s called end", __func__); + return unregisterSuccess; +} + +bool ContinuationManager::UnregisterAbilityToken(const sptr &token) +{ + APP_LOGI("%{public}s called begin", __func__); + int result = -1; + + if (distSchedulerHost_ == nullptr) { + APP_LOGE("%{public}s called failed. distSchedulerHost_ is nullptr", __func__); + return false; + } + + result = DistributedClient::GetInstance()->UnregisterAbilityToken(token, distSchedulerHost_); + if (result != -1) { + std::string interfaceName = "unregisterAbilityToken"; + CheckDmsInterfaceResult(result, interfaceName); + } + + APP_LOGI("%{public}s called end", __func__); + return (result == NO_ERROR); +} + +bool ContinuationManager::RegisterAbilityTokenIfNeed(const sptr &token) +{ + APP_LOGI("%{public}s called begin", __func__); + if (tokenRegistered_) { + return true; + } + + std::lock_guard lock_l(lockForRegist_); + + if (tokenRegistered_) { + return true; + } + + bool registerSuccess = RegisterAbilityToken(token); + if (registerSuccess) { + tokenRegistered_ = true; + } + APP_LOGI("%{public}s called end", __func__); + return registerSuccess; +} + +bool ContinuationManager::RegisterAbilityToken(const sptr &token) +{ + APP_LOGI("%{public}s called begin", __func__); + int result = -1; + + InitDistSchedulerHost(); + + result = DistributedClient::GetInstance()->RegisterAbilityToken(token, distSchedulerHost_); + if (result != -1) { + std::string interfaceName = "registerAbilityToken"; + CheckDmsInterfaceResult(result, interfaceName); + } + APP_LOGI("%{public}s called end", __func__); + return (result == NO_ERROR); +} + +void ContinuationManager::InitDistSchedulerHost() +{ + APP_LOGI("%{public}s called begin", __func__); + if (distSchedulerHost_ == nullptr) { + InitMainHandlerIfNeed(); + std::weak_ptr continuationHandler = continuationHandler_; + distSchedulerHost_ = + sptr(new (std::nothrow) ContinuationScheduler(continuationHandler, mainHandler_)); + if (distSchedulerHost_ == nullptr) { + APP_LOGE("AbilityThread::AbilityThreadMain failed,thread is nullptr"); + return; + } + } + APP_LOGI("%{public}s called end", __func__); +} + +void ContinuationManager::CheckDmsInterfaceResult(int result, const std::string &interfaceName) +{ + APP_LOGI("ContinuationManager::CheckDmsInterfaceResult called. interfaceName: %{public}s, result: %{public}d.", + interfaceName.c_str(), + result); +} + +bool ContinuationManager::DoScheduleStartContinuation() +{ + APP_LOGI("%{public}s called begin", __func__); + if (CheckContinuationIllegal()) { + APP_LOGE( + "ContinuationManager::DoScheduleStartContinuation called. Ability not available to startContinuation."); + return false; + } + + std::shared_ptr ability = nullptr; + ability = ability_.lock(); + if (ability == nullptr) { + APP_LOGE("ContinuationManager::DoScheduleStartContinuation failed. ability is nullptr"); + return false; + } + if (!ability->OnStartContinuation()) { + APP_LOGI("%{public}s called failed to StartContinuation", __func__); + return false; + } + APP_LOGI("%{public}s called end", __func__); + return true; +} + +bool ContinuationManager::DoScheduleSaveData(WantParams &saveData) +{ + APP_LOGI("%{public}s called begin", __func__); + if (CheckContinuationIllegal()) { + APP_LOGE("ContinuationManager::DoScheduleSaveData failed. Ability not available to save data."); + return false; + } + + std::shared_ptr ability = nullptr; + ability = ability_.lock(); + if (ability == nullptr) { + APP_LOGE("ContinuationManager::DoScheduleSaveData failed. ability is nullptr"); + return false; + } + + WantParams abilitySaveData; + bool ret = ability->OnSaveData(abilitySaveData); + for (std::string key : abilitySaveData.KeySet()) { + saveData.SetParam(key, abilitySaveData.GetParam(key).GetRefPtr()); + } + + if (!ret) { + APP_LOGE("ContinuationManager::DoScheduleSaveData failed. Ability save data failed."); + } + APP_LOGI("%{public}s called end", __func__); + return ret; +} + +bool ContinuationManager::DoScheduleRestoreData(const WantParams &restoreData) +{ + APP_LOGI("%{public}s called begin", __func__); + if (CheckContinuationIllegal()) { + APP_LOGE("ContinuationManager::DoScheduleRestoreData failed. Ability not available to restore data."); + return false; + } + + std::shared_ptr ability = nullptr; + ability = ability_.lock(); + if (ability == nullptr) { + APP_LOGE("ContinuationManager::DoScheduleRestoreData failed. ability is nullptr"); + return false; + } + + WantParams abilityRestoreData; + for (std::string key : restoreData.KeySet()) { + abilityRestoreData.SetParam(key, restoreData.GetParam(key).GetRefPtr()); + } + + bool ret = ability->OnRestoreData(abilityRestoreData); + if (!ret) { + APP_LOGE("ContinuationManager::DoScheduleRestoreData failed. Ability restore data failed."); + } + APP_LOGI("%{public}s called end", __func__); + return ret; +} + +bool ContinuationManager::DoRestoreFromRemote(const WantParams &restoreData) +{ + APP_LOGI("%{public}s called begin", __func__); + std::shared_ptr ability = nullptr; + ability = ability_.lock(); + if (ability == nullptr) { + APP_LOGE("ContinuationManager::DoRestoreFromRemote failed. ability is nullptr"); + return false; + } + + WantParams abilityRestoreData; + for (std::string key : restoreData.KeySet()) { + abilityRestoreData.SetParam(key, restoreData.GetParam(key).GetRefPtr()); + } + + bool ret = ability->OnRestoreData(abilityRestoreData); + if (!ret) { + APP_LOGE("ContinuationManager::DoRestoreFromRemote failed. Ability restore data failed."); + } + APP_LOGI("%{public}s called end", __func__); + return ret; +} +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/src/continuation/distributed/continuation_scheduler.cpp b/tools/frameworks/kits/ability/native/src/continuation/distributed/continuation_scheduler.cpp new file mode 100644 index 00000000000..47139fa456f --- /dev/null +++ b/tools/frameworks/kits/ability/native/src/continuation/distributed/continuation_scheduler.cpp @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "continuation_scheduler.h" +#include "app_log_wrapper.h" +namespace OHOS { +namespace AppExecFwk { + +std::mutex ContinuationScheduler::mutex_; +ContinuationScheduler::ContinuationScheduler( + std::weak_ptr &callback, std::shared_ptr &mainHandler) +{ + if (mainHandler == nullptr) { + APP_LOGE("Handler can not be nullptr."); + } + callback_ = callback; + mainHandler_ = mainHandler; +} + +void ContinuationScheduler::ScheduleCompleteContinuation(int result) +{ + APP_LOGI("%{public}s called begin", __func__); + auto task = [continuationScheduler = this, result]() { + continuationScheduler->HandleCompleteContinuation(result); + }; + + std::lock_guard lock(mutex_); + + if (mainHandler_ == nullptr) { + APP_LOGE("ContinuationScheduler::ScheduleCompleteContinuation mainHandler_ == nullptr"); + return; + } + + bool ret = mainHandler_->PostTask(task); + if (!ret) { + APP_LOGE("ContinuationScheduler::ScheduleCompleteContinuation PostTask error"); + return; + } + APP_LOGI("%{public}s called end", __func__); +} + +void ContinuationScheduler::ReceiveReplicaScheduler(const sptr &remoteReplica) +{ + APP_LOGI("%{public}s called begin", __func__); + if (remoteReplica == nullptr) { + APP_LOGE("ContinuationScheduler::ReceiveReplicaScheduler remoteReplica is nullptr"); + return; + } + + auto task = [continuationScheduler = this, remoteReplica]() { + continuationScheduler->HandleReceiveReplicaScheduler(remoteReplica); + }; + + std::lock_guard lock(mutex_); + + if (mainHandler_ == nullptr) { + APP_LOGE("ContinuationScheduler::ReceiveReplicaScheduler mainHandler_ == nullptr"); + return; + } + + bool ret = mainHandler_->PostTask(task); + if (!ret) { + APP_LOGE("ContinuationScheduler::ReceiveReplicaScheduler PostTask error"); + return; + } + APP_LOGI("%{public}s called end", __func__); +} + +void ContinuationScheduler::HandleReceiveReplicaScheduler(const sptr &remoteReplica) +{ + APP_LOGI("%{public}s called begin", __func__); + std::shared_ptr callback = nullptr; + if (GetCallback(callback)) { + callback->HandleReceiveRemoteScheduler(remoteReplica); + return; + } + APP_LOGI("%{public}s called end", __func__); +} + +void ContinuationScheduler::HandleCompleteContinuation(int result) +{ + APP_LOGI("%{public}s called begin", __func__); + std::shared_ptr callback = nullptr; + if (GetCallback(callback)) { + callback->HandleCompleteContinuation(result); + return; + } + APP_LOGI("%{public}s called end", __func__); +} + +bool ContinuationScheduler::GetCallback(std::shared_ptr &callback) +{ + APP_LOGI("%{public}s called begin", __func__); + if (callback != nullptr) { + APP_LOGE("ContinuationScheduler::GetCallback callback is not inited"); + return false; + } + + callback = callback_.lock(); + if (callback == nullptr) { + APP_LOGE("ContinuationScheduler::GetCallback callback get failed"); + return false; + } + APP_LOGI("%{public}s called end", __func__); + return true; +} + +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/src/continuation/distributed/continuation_scheduler_stub.cpp b/tools/frameworks/kits/ability/native/src/continuation/distributed/continuation_scheduler_stub.cpp new file mode 100644 index 00000000000..bbfb0e88aa6 --- /dev/null +++ b/tools/frameworks/kits/ability/native/src/continuation/distributed/continuation_scheduler_stub.cpp @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "continuation_scheduler_stub.h" +#include "ipc_types.h" +#include "string_ex.h" +#include "app_log_wrapper.h" +namespace OHOS { +namespace AppExecFwk { + +ContinuationSchedulerStub::ContinuationSchedulerStub() +{ + requestFuncMap_[SCHEDULE_COMPLETE_CONTINUATION] = + &ContinuationSchedulerStub::ScheduleCompleteContinuationInner; + requestFuncMap_[RECEIVE_REPLICA_SCHEDULER] = &ContinuationSchedulerStub::ReceiveReplicaSchedulerInner; +} + +ContinuationSchedulerStub::~ContinuationSchedulerStub() +{ + requestFuncMap_.clear(); +} + +int ContinuationSchedulerStub::ReceiveReplicaSchedulerInner(MessageParcel &data, MessageParcel &reply) +{ + APP_LOGI("%{public}s called begin", __func__); + auto remoteReplica = data.ReadParcelable(); + ReceiveReplicaScheduler(remoteReplica); + APP_LOGI("%{public}s called end", __func__); + return NO_ERROR; +} + +int ContinuationSchedulerStub::ScheduleCompleteContinuationInner(MessageParcel &data, MessageParcel &reply) +{ + APP_LOGI("%{public}s called begin", __func__); + int result = data.ReadInt32(); + ScheduleCompleteContinuation(result); + APP_LOGI("%{public}s called end", __func__); + return NO_ERROR; +} + +int ContinuationSchedulerStub::OnRemoteRequest( + uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) +{ + APP_LOGI("%{public}s called begin", __func__); + std::u16string descriptor = ContinuationSchedulerStub::GetDescriptor(); + std::u16string remoteDescriptor = data.ReadInterfaceToken(); + if (descriptor != remoteDescriptor) { + APP_LOGI("local descriptor is not equal to remote"); + return ERR_INVALID_STATE; + } + + auto itFunc = requestFuncMap_.find(code); + if (itFunc != requestFuncMap_.end()) { + auto requestFunc = itFunc->second; + if (requestFunc != nullptr) { + return (this->*requestFunc)(data, reply); + } + } + APP_LOGI("ContinuationSchedulerStub::OnRemoteRequest, default case, need check."); + APP_LOGI("%{public}s called end", __func__); + return IPCObjectStub::OnRemoteRequest(code, data, reply, option); +} + +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/src/continuation/distributed/distributed_client.cpp b/tools/frameworks/kits/ability/native/src/continuation/distributed/distributed_client.cpp new file mode 100755 index 00000000000..6cf08519507 --- /dev/null +++ b/tools/frameworks/kits/ability/native/src/continuation/distributed/distributed_client.cpp @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "distributed_client.h" + +#include "app_log_wrapper.h" +#include "if_system_ability_manager.h" +#include "ipc_skeleton.h" +#include "iservice_registry.h" +#include "system_ability_definition.h" + +namespace OHOS { +namespace AppExecFwk { +std::shared_ptr DistributedClient::instance_ = nullptr; +std::mutex DistributedClient::mutex_; + +std::shared_ptr DistributedClient::GetInstance() +{ + if (instance_ == nullptr) { + std::lock_guard lock(mutex_); + if (instance_ == nullptr) { + instance_ = std::make_shared(); + } + } + return instance_; +} + +DistributedClient::DistributedClient() +{} + +DistributedClient::~DistributedClient() +{} + +ErrCode DistributedClient::Connect() +{ + APP_LOGI("%{public}s called begin", __func__); + std::lock_guard lock(mutex_); + + if (remoteObject_ == nullptr) { + sptr systemManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + if (systemManager == nullptr) { + APP_LOGE("%{public}s:fail to get System Ability Manager", __func__); + return GET_SYSTEM_ABILITY_SERVICE_FAILED; + } + remoteObject_ = systemManager->GetSystemAbility(DISTRIBUTED_SCHED_SA_ID); + if (remoteObject_ == nullptr) { + APP_LOGE("%{public}s:fail to get Distributed Ability Service", __func__); + return GET_DISTRIBUTED_ABILITY_SERVICE_FAILED; + } + } + + if (dmsProxy_ == nullptr) { + dmsProxy_ = std::make_shared(remoteObject_); + } + + APP_LOGI("%{public}s called end", __func__); + return ERR_OK; +} + +ErrCode DistributedClient::StartRemoteAbility( + const Want &want, const AppExecFwk::AbilityInfo &abilityInfo, int32_t requestCode) +{ + APP_LOGI("%{public}s called", __func__); + if (remoteObject_ == nullptr) { + ErrCode err = Connect(); + if (err != ERR_OK) { + return DISTRIBUTED_ABILITY_SERVICE_NOT_CONNECTED; + } + } + + return dmsProxy_->StartRemoteAbility(want, abilityInfo, requestCode); +} + +ErrCode DistributedClient::StartContinuation( + const Want &want, const AppExecFwk::AbilityInfo &abilityInfo, const sptr &abilityToken) +{ + APP_LOGI("%{public}s called", __func__); + if (remoteObject_ == nullptr) { + ErrCode err = Connect(); + if (err != ERR_OK) { + return DISTRIBUTED_ABILITY_SERVICE_NOT_CONNECTED; + } + } + if (abilityToken == nullptr) { + return INCOMING_PARAMETER_POINTER_IS_NULL; + } + + return dmsProxy_->StartContinuation(want, abilityInfo, abilityToken); +} + +ErrCode DistributedClient::ConnectRemoteAbility( + const Want &want, const AppExecFwk::AbilityInfo &abilityInfo, const sptr &connect) +{ + APP_LOGI("%{public}s called", __func__); + if (remoteObject_ == nullptr) { + ErrCode err = Connect(); + if (err != ERR_OK) { + return DISTRIBUTED_ABILITY_SERVICE_NOT_CONNECTED; + } + } + if (connect == nullptr) { + return INCOMING_PARAMETER_POINTER_IS_NULL; + } + + return dmsProxy_->ConnectRemoteAbility(want, abilityInfo, connect); +} + +ErrCode DistributedClient::DisconnectRemoteAbility(const sptr &connect) +{ + APP_LOGI("%{public}s called", __func__); + if (remoteObject_ == nullptr) { + ErrCode err = Connect(); + if (err != ERR_OK) { + return DISTRIBUTED_ABILITY_SERVICE_NOT_CONNECTED; + } + } + if (connect == nullptr) { + return INCOMING_PARAMETER_POINTER_IS_NULL; + } + + return dmsProxy_->DisconnectRemoteAbility(connect); +} + +ErrCode DistributedClient::NotifyCompleteContinuation( + const std::u16string &devId, int32_t sessionId, bool isSuccess, const sptr &reverseScheduler) +{ + APP_LOGI("%{public}s called", __func__); + if (remoteObject_ == nullptr) { + ErrCode err = Connect(); + if (err != ERR_OK) { + return DISTRIBUTED_ABILITY_SERVICE_NOT_CONNECTED; + } + } + + // TODO there need a params for reverseScheduler + dmsProxy_->NotifyCompleteContinuation(devId, sessionId, isSuccess); + return 0; +} + +ErrCode DistributedClient::RegisterAbilityToken(const sptr &token, const sptr &appThread) +{ + APP_LOGI("%{public}s called", __func__); + if (remoteObject_ == nullptr) { + ErrCode err = Connect(); + if (err != ERR_OK) { + return DISTRIBUTED_ABILITY_SERVICE_NOT_CONNECTED; + } + } + if (token == nullptr || appThread == nullptr) { + return INCOMING_PARAMETER_POINTER_IS_NULL; + } + + return dmsProxy_->RegisterAbilityToken(token, appThread); +} + +ErrCode DistributedClient::UnregisterAbilityToken( + const sptr &token, const sptr &appThread) +{ + APP_LOGI("%{public}s called", __func__); + if (remoteObject_ == nullptr) { + ErrCode err = Connect(); + if (err != ERR_OK) { + return DISTRIBUTED_ABILITY_SERVICE_NOT_CONNECTED; + } + } + if (token == nullptr || appThread == nullptr) { + return INCOMING_PARAMETER_POINTER_IS_NULL; + } + + return dmsProxy_->UnregisterAbilityToken(token, appThread); +} +} // namespace AppExecFwk +} // namespace OHOS diff --git a/tools/frameworks/kits/ability/native/src/continuation/distributed/reverse_continuation_scheduler_primary.cpp b/tools/frameworks/kits/ability/native/src/continuation/distributed/reverse_continuation_scheduler_primary.cpp new file mode 100644 index 00000000000..d3606b13e67 --- /dev/null +++ b/tools/frameworks/kits/ability/native/src/continuation/distributed/reverse_continuation_scheduler_primary.cpp @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "reverse_continuation_scheduler_primary.h" +#include "app_log_wrapper.h" +#include "continuation_handler.h" + +namespace OHOS { +namespace AppExecFwk { + +ReverseContinuationSchedulerPrimary::ReverseContinuationSchedulerPrimary( + const std::weak_ptr &continuationHandler, + const std::shared_ptr &mainHandler) + : continuationHandler_(continuationHandler), mainHandler_(mainHandler) +{} + +/** + * @brief Replica call this method when it terminated. + */ +void ReverseContinuationSchedulerPrimary::NotifyReplicaTerminated() +{ + APP_LOGI("%{public}s called begin", __func__); + auto task = [reverseContinuationSchedulerPrimary = this]() { + reverseContinuationSchedulerPrimary->HandlerNotifyReplicaTerminated(); + }; + + if (mainHandler_ == nullptr) { + APP_LOGE("ReverseContinuationSchedulerPrimary::NotifyReplicaTerminated mainHandler_ == nullptr"); + return; + } + + bool ret = mainHandler_->PostTask(task); + if (!ret) { + APP_LOGE("ReverseContinuationSchedulerPrimary::NotifyReplicaTerminated PostTask error"); + return; + } + APP_LOGI("%{public}s called end", __func__); +} + +/** + * @brief Replica call this method to notify primary go on. + * + * @param want Contains data to be restore. + * @return True if success, otherwise false. + */ +bool ReverseContinuationSchedulerPrimary::ContinuationBack(const AAFwk::Want &want) +{ + APP_LOGI("%{public}s called begin", __func__); + auto task = [reverseContinuationSchedulerPrimary = this, want]() { + reverseContinuationSchedulerPrimary->HandlerContinuationBack(want); + }; + + if (mainHandler_ == nullptr) { + APP_LOGE("ReverseContinuationSchedulerPrimary::ContinuationBack mainHandler_ == nullptr"); + return false; + } + + bool ret = mainHandler_->PostTask(task); + if (!ret) { + APP_LOGE("ReverseContinuationSchedulerPrimary::ContinuationBack PostTask error"); + return false; + } + APP_LOGI("%{public}s called end", __func__); + return true; +} + +void ReverseContinuationSchedulerPrimary::HandlerNotifyReplicaTerminated() +{ + APP_LOGI("%{public}s called begin", __func__); + std::shared_ptr continuationHandler = nullptr; + continuationHandler = continuationHandler_.lock(); + if (continuationHandler == nullptr) { + APP_LOGE( + "ReverseContinuationSchedulerPrimary::HandlerNotifyReplicaTerminated get continuationHandler is nullptr"); + return; + } + continuationHandler->NotifyReplicaTerminated(); + APP_LOGI("%{public}s called end", __func__); +} + +void ReverseContinuationSchedulerPrimary::HandlerContinuationBack(const AAFwk::Want &want) +{ + APP_LOGI("%{public}s called begin", __func__); + std::shared_ptr continuationHandler = nullptr; + continuationHandler = continuationHandler_.lock(); + if (continuationHandler == nullptr) { + APP_LOGE("ReverseContinuationSchedulerPrimary::HandlerContinuationBack get continuationHandler is nullptr"); + return; + } + continuationHandler->ContinuationBack(want); + APP_LOGI("%{public}s called end", __func__); +} + +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/src/continuation/distributed/reverse_continuation_scheduler_primary_proxy.cpp b/tools/frameworks/kits/ability/native/src/continuation/distributed/reverse_continuation_scheduler_primary_proxy.cpp new file mode 100644 index 00000000000..104cffabb00 --- /dev/null +++ b/tools/frameworks/kits/ability/native/src/continuation/distributed/reverse_continuation_scheduler_primary_proxy.cpp @@ -0,0 +1,88 @@ + +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "reverse_continuation_scheduler_primary_proxy.h" +#include "app_log_wrapper.h" + +namespace OHOS { +namespace AppExecFwk { + +ReverseContinuationSchedulerPrimaryProxy::ReverseContinuationSchedulerPrimaryProxy( + const sptr &remoteObject) + : IRemoteProxy(remoteObject) +{} + +/** + * @brief Replica call this method when it terminated. + */ +void ReverseContinuationSchedulerPrimaryProxy::NotifyReplicaTerminated() +{ + APP_LOGI("%{public}s called begin", __func__); + MessageParcel data; + MessageParcel reply; + MessageOption option(MessageOption::TF_SYNC); + if (!data.WriteInterfaceToken(ReverseContinuationSchedulerPrimaryProxy::GetDescriptor())) { + APP_LOGE("ReverseContinuationSchedulerPrimaryProxy::NotifyReplicaTerminated write interface token failed"); + return; + } + sptr remoteObject = Remote(); + if (remoteObject == nullptr) { + APP_LOGE("ReverseContinuationSchedulerPrimaryProxy::NotifyReplicaTerminated Remote() is nullptr"); + return; + } + if (!remoteObject->SendRequest( + IReverseContinuationSchedulerPrimary::NOTIFY_REPLICA_TERMINATED, data, reply, option)) { + APP_LOGE("ReverseContinuationSchedulerPrimaryProxy::NotifyReplicaTerminated SendRequest return false"); + return; + } + APP_LOGI("%{public}s called end", __func__); +} + +/** + * @brief Replica call this method to notify primary go on. + * + * @param want Contains data to be restore. + * @return True if success, otherwise false. + */ +bool ReverseContinuationSchedulerPrimaryProxy::ContinuationBack(const AAFwk::Want &want) +{ + APP_LOGI("%{public}s called begin", __func__); + MessageParcel data; + MessageParcel reply; + MessageOption option(MessageOption::TF_SYNC); + if (!data.WriteInterfaceToken(ReverseContinuationSchedulerPrimaryProxy::GetDescriptor())) { + APP_LOGE("ReverseContinuationSchedulerPrimaryProxy::ContinuationBack write interface token failed"); + return false; + } + if (!data.WriteParcelable(&want)) { + APP_LOGE("ReverseContinuationSchedulerPrimaryProxy::ContinuationBack fail to WriteParcelable"); + return false; + } + sptr remoteObject = Remote(); + if (remoteObject == nullptr) { + APP_LOGE("ReverseContinuationSchedulerPrimaryProxy::ContinuationBack Remote() is nullptr"); + return false; + } + if (!remoteObject->SendRequest(IReverseContinuationSchedulerPrimary::CONTINUATION_BACK, data, reply, option)) { + APP_LOGE("ReverseContinuationSchedulerPrimaryProxy::ContinuationBack SendRequest return false"); + return false; + } + APP_LOGI("%{public}s called end", __func__); + return true; +} + +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/src/continuation/distributed/reverse_continuation_scheduler_primary_stub.cpp b/tools/frameworks/kits/ability/native/src/continuation/distributed/reverse_continuation_scheduler_primary_stub.cpp new file mode 100644 index 00000000000..09227432229 --- /dev/null +++ b/tools/frameworks/kits/ability/native/src/continuation/distributed/reverse_continuation_scheduler_primary_stub.cpp @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "reverse_continuation_scheduler_primary_stub.h" +#include "ability_scheduler_interface.h" +#include "app_log_wrapper.h" +#include "string_ex.h" + +namespace OHOS { +namespace AppExecFwk { + +const std::string ReverseContinuationSchedulerPrimaryStub::DESCRIPTOR( + "ohos.abilityshell.ReverseContinuationSchedulerMaster"); + +ReverseContinuationSchedulerPrimaryStub::ReverseContinuationSchedulerPrimaryStub() +{ + requestFuncMap_[NOTIFY_REPLICA_TERMINATED] = &ReverseContinuationSchedulerPrimaryStub::NotifyReplicaTerminatedInner; + requestFuncMap_[CONTINUATION_BACK] = &ReverseContinuationSchedulerPrimaryStub::ContinuationBackInner; +} + +ReverseContinuationSchedulerPrimaryStub::~ReverseContinuationSchedulerPrimaryStub() +{ + requestFuncMap_.clear(); +} + +/** + * @brief Sets an entry for receiving requests. + * + * @param code Indicates the service request code sent from the peer end. + * @param data Indicates the MessageParcel object sent from the peer end. + * @param reply Indicates the response message object sent from the remote service. The local service writes the + * response data to the MessageParcel object. + * @param option Indicates whether the operation is synchronous or asynchronous. + * @return ERR_NONE if success, otherwise false. + */ +int ReverseContinuationSchedulerPrimaryStub::OnRemoteRequest( + uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) +{ + APP_LOGI("%{public}s called begin", __func__); + std::u16string touken = data.ReadInterfaceToken(); + std::u16string descripor = Str8ToStr16(DESCRIPTOR); + if (descripor != touken) { + APP_LOGE("ReverseContinuationSchedulerPrimaryStub::OnRemoteRequest failed, DESCRIPTOR != touken"); + return -1; + } + + auto iter = requestFuncMap_.find(code); + if (iter != requestFuncMap_.end()) { + auto func = iter->second; + if (func != nullptr) { + return (this->*func)(data, reply); + } else { + APP_LOGW("ReverseContinuationSchedulerPrimaryStub::OnRemoteRequest failed, func is nullptr"); + } + } else { + APP_LOGW("ReverseContinuationSchedulerPrimaryStub::OnRemoteRequest failed, iter not find"); + } + APP_LOGI("%{public}s called end", __func__); + return IPCObjectStub::OnRemoteRequest(code, data, reply, option); +} + +int ReverseContinuationSchedulerPrimaryStub::NotifyReplicaTerminatedInner(MessageParcel &data, MessageParcel &reply) +{ + APP_LOGI("%{public}s called begin", __func__); + NotifyReplicaTerminated(); + APP_LOGI("%{public}s called end", __func__); + return 0; +} +int ReverseContinuationSchedulerPrimaryStub::ContinuationBackInner(MessageParcel &data, MessageParcel &reply) +{ + APP_LOGI("%{public}s called begin", __func__); + AAFwk::Want *want = data.ReadParcelable(); + if (want == nullptr) { + APP_LOGE("ReverseContinuationSchedulerPrimaryStub::ContinuationBackInner want is nullptr"); + return -1; + } + + if (!ContinuationBack(*want)) { + APP_LOGE("ReverseContinuationSchedulerPrimaryStub::NotifyReverseaTerminatedInner failed, ContinuationBack() " + "return false"); + return -1; + } + APP_LOGI("%{public}s called end", __func__); + return 0; +} + +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/src/continuation/distributed/reverse_continuation_scheduler_recipient.cpp b/tools/frameworks/kits/ability/native/src/continuation/distributed/reverse_continuation_scheduler_recipient.cpp new file mode 100644 index 00000000000..1d0356faba1 --- /dev/null +++ b/tools/frameworks/kits/ability/native/src/continuation/distributed/reverse_continuation_scheduler_recipient.cpp @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "reverse_continuation_scheduler_recipient.h" + +namespace OHOS { +namespace AppExecFwk { +void ReverseContinuationSchedulerRecipient::OnRemoteDied(const wptr &remote) +{ + if (handler_) { + handler_(remote); + } +} + +ReverseContinuationSchedulerRecipient::ReverseContinuationSchedulerRecipient(RemoteDiedHandler handler) + : handler_(handler) +{} + +ReverseContinuationSchedulerRecipient::~ReverseContinuationSchedulerRecipient() +{} +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/src/continuation/distributed/reverse_continuation_scheduler_replica.cpp b/tools/frameworks/kits/ability/native/src/continuation/distributed/reverse_continuation_scheduler_replica.cpp new file mode 100644 index 00000000000..f7d58af0cae --- /dev/null +++ b/tools/frameworks/kits/ability/native/src/continuation/distributed/reverse_continuation_scheduler_replica.cpp @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "reverse_continuation_scheduler_replica.h" +#include "app_log_wrapper.h" + +namespace OHOS { +namespace AppExecFwk { +ReverseContinuationSchedulerReplica::ReverseContinuationSchedulerReplica( + const std::shared_ptr &mainHandler, + const std::weak_ptr &replicaHandler) +{ + mainHandler_ = mainHandler; + replicaHandler_ = replicaHandler; +} +void ReverseContinuationSchedulerReplica::PassPrimary(const sptr &primary) +{ + APP_LOGI("%{public}s called begin", __func__); + auto task = [reverseContinuationSchedulerReplica = this, primary]() { + reverseContinuationSchedulerReplica->HandlerPassPrimary(primary); + }; + + if (mainHandler_ == nullptr) { + APP_LOGE("ReverseContinuationSchedulerReplica::PassPrimary mainHandler_ == nullptr"); + return; + } + + bool ret = mainHandler_->PostTask(task); + if (!ret) { + APP_LOGE("ReverseContinuationSchedulerReplica::PassPrimary PostTask error"); + } + APP_LOGI("%{public}s called end", __func__); +} +bool ReverseContinuationSchedulerReplica::ReverseContinuation() +{ + APP_LOGI("%{public}s called begin", __func__); + auto task = [reverseContinuationSchedulerReplica = this]() { + reverseContinuationSchedulerReplica->HandlerReverseContinuation(); + }; + + if (mainHandler_ == nullptr) { + APP_LOGE("ReverseContinuationSchedulerReplica::ReverseContinuation mainHandler_ == nullptr"); + return false; + } + + bool ret = mainHandler_->PostTask(task); + if (!ret) { + APP_LOGE("ReverseContinuationSchedulerReplica::ReverseContinuation PostTask error"); + } + APP_LOGI("%{public}s called end", __func__); + return true; +} +void ReverseContinuationSchedulerReplica::NotifyReverseResult(int reverseResult) +{ + APP_LOGI("%{public}s called begin", __func__); + auto task = [reverseContinuationSchedulerReplica = this, reverseResult]() { + reverseContinuationSchedulerReplica->HandlerNotifyReverseResult(reverseResult); + }; + + if (mainHandler_ == nullptr) { + APP_LOGE("ReverseContinuationSchedulerReplica::NotifyReverseResult mainHandler_ == nullptr"); + return; + } + + bool ret = mainHandler_->PostTask(task); + if (!ret) { + APP_LOGE("ReverseContinuationSchedulerReplica::NotifyReverseResult PostTask error"); + } + APP_LOGI("%{public}s called end", __func__); +} + +void ReverseContinuationSchedulerReplica::HandlerPassPrimary(const sptr &primary) +{ + APP_LOGI("%{public}s called begin", __func__); + std::shared_ptr replicaHandlerTmp = nullptr; + replicaHandlerTmp = replicaHandler_.lock(); + if (replicaHandlerTmp == nullptr) { + APP_LOGE("ReverseContinuationSchedulerReplica::PassPrimary get replicaHandlerTmp is nullptr"); + return; + } + replicaHandlerTmp->PassPrimary(primary); + APP_LOGI("%{public}s called end", __func__); +} + +bool ReverseContinuationSchedulerReplica::HandlerReverseContinuation() +{ + APP_LOGI("%{public}s called begin", __func__); + std::shared_ptr replicaHandlerTmp = nullptr; + replicaHandlerTmp = replicaHandler_.lock(); + if (replicaHandlerTmp == nullptr) { + APP_LOGE("ReverseContinuationSchedulerReplica::PassPrimary get replicaHandlerTmp is nullptr"); + return false; + } + APP_LOGI("%{public}s called end", __func__); + return replicaHandlerTmp->ReverseContinuation(); +} + +void ReverseContinuationSchedulerReplica::HandlerNotifyReverseResult(int reverseResult) +{ + APP_LOGI("%{public}s called begin", __func__); + std::shared_ptr replicaHandlerTmp = nullptr; + replicaHandlerTmp = replicaHandler_.lock(); + if (replicaHandlerTmp == nullptr) { + APP_LOGE("ReverseContinuationSchedulerReplica::PassPrimary get replicaHandlerTmp is nullptr"); + return; + } + replicaHandlerTmp->NotifyReverseResult(reverseResult); + APP_LOGI("%{public}s called end", __func__); +} + +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/src/continuation/distributed/reverse_continuation_scheduler_replica_proxy.cpp b/tools/frameworks/kits/ability/native/src/continuation/distributed/reverse_continuation_scheduler_replica_proxy.cpp new file mode 100755 index 00000000000..a5f5a641cc8 --- /dev/null +++ b/tools/frameworks/kits/ability/native/src/continuation/distributed/reverse_continuation_scheduler_replica_proxy.cpp @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "reverse_continuation_scheduler_replica_proxy.h" + +#include "app_log_wrapper.h" + +namespace OHOS { +namespace AppExecFwk { +ReverseContinuationSchedulerReplicaProxy::ReverseContinuationSchedulerReplicaProxy( + const sptr &remoteObject) + : IRemoteProxy(remoteObject) +{} + +sptr ReverseContinuationSchedulerReplicaProxy::AsObject() +{ + sptr remoteObject = Remote(); + + return remoteObject; +} +void ReverseContinuationSchedulerReplicaProxy::PassPrimary(const sptr &primary) +{ + APP_LOGI("%{public}s called begin", __func__); + MessageParcel data; + MessageParcel reply; + MessageOption option(MessageOption::TF_SYNC); + if (!data.WriteInterfaceToken(ReverseContinuationSchedulerReplicaProxy::GetDescriptor())) { + APP_LOGE("ReverseContinuationSchedulerReplicaProxy::PassPrimary write interface token failed"); + return; + } + if (!data.WriteRemoteObject(primary)) { + APP_LOGE("ReverseContinuationSchedulerReplicaProxy::PassPrimary write parcel callback failed"); + return; + } + sptr remoteObject = Remote(); + if (remoteObject == nullptr) { + APP_LOGE("ReverseContinuationSchedulerReplicaProxy::PassPrimary Remote() is NULL"); + return; + } + if (!remoteObject->SendRequest( + static_cast(IReverseContinuationSchedulerReplica::Message::PASS_PRIMARY), data, reply, option)) { + APP_LOGE("ReverseContinuationSchedulerReplicaProxy::PassPrimary SendRequest return false"); + } + APP_LOGI("%{public}s called end", __func__); +} +bool ReverseContinuationSchedulerReplicaProxy::ReverseContinuation() +{ + APP_LOGI("%{public}s called begin", __func__); + MessageParcel data; + MessageParcel reply; + MessageOption option(MessageOption::TF_SYNC); + if (!data.WriteInterfaceToken(ReverseContinuationSchedulerReplicaProxy::GetDescriptor())) { + APP_LOGE("ReverseContinuationSchedulerReplicaProxy::ReverseContinuation write interface token failed"); + return false; + } + sptr remoteObject = Remote(); + if (remoteObject == nullptr) { + APP_LOGE("ReverseContinuationSchedulerReplicaProxy::ReverseContinuation Remote() is nullptr"); + return false; + } + if (!remoteObject->SendRequest( + static_cast(IReverseContinuationSchedulerReplica::Message::REVERSE_CONTINUATION), + data, + reply, + option)) { + APP_LOGE("ReverseContinuationSchedulerReplicaProxy::ReverseContinuation SendRequest return false"); + return false; + } + APP_LOGI("%{public}s called end", __func__); + return true; +} +void ReverseContinuationSchedulerReplicaProxy::NotifyReverseResult(int reverseResult) +{ + APP_LOGI("%{public}s called begin", __func__); + MessageParcel data; + MessageParcel reply; + MessageOption option(MessageOption::TF_SYNC); + if (!data.WriteInterfaceToken(ReverseContinuationSchedulerReplicaProxy::GetDescriptor())) { + APP_LOGE("ReverseContinuationSchedulerReplicaProxy::NotifyReverseResult write interface token failed"); + return; + } + if (!data.WriteInt32(reverseResult)) { + APP_LOGE("ReverseContinuationSchedulerReplicaProxy::NotifyReverseResult write parcel flags failed"); + return; + } + sptr remoteObject = Remote(); + if (remoteObject == nullptr) { + APP_LOGE("ReverseContinuationSchedulerReplicaProxy::NotifyReverseResult Remote() is NULL"); + return; + } + if (!remoteObject->SendRequest( + static_cast(IReverseContinuationSchedulerReplica::Message::NOTIFY_REVERSE_RESULT), + data, + reply, + option)) { + APP_LOGE("ReverseContinuationSchedulerReplicaProxy::NotifyReverseResult SendRequest return false"); + } + APP_LOGI("%{public}s called end", __func__); +} +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/src/continuation/distributed/reverse_continuation_scheduler_replica_stub.cpp b/tools/frameworks/kits/ability/native/src/continuation/distributed/reverse_continuation_scheduler_replica_stub.cpp new file mode 100644 index 00000000000..e37bed205a8 --- /dev/null +++ b/tools/frameworks/kits/ability/native/src/continuation/distributed/reverse_continuation_scheduler_replica_stub.cpp @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "reverse_continuation_scheduler_replica_stub.h" + +#include "app_log_wrapper.h" + +namespace OHOS { +namespace AppExecFwk { +ReverseContinuationSchedulerReplicaStub::ReverseContinuationSchedulerReplicaStub() +{ + continuationFuncMap_[static_cast(IReverseContinuationSchedulerReplica::Message::PASS_PRIMARY)] = + &ReverseContinuationSchedulerReplicaStub::PassPrimaryInner; + continuationFuncMap_[static_cast(IReverseContinuationSchedulerReplica::Message::REVERSE_CONTINUATION)] = + &ReverseContinuationSchedulerReplicaStub::ReverseContinuationInner; + continuationFuncMap_[static_cast(IReverseContinuationSchedulerReplica::Message::NOTIFY_REVERSE_RESULT)] = + &ReverseContinuationSchedulerReplicaStub::NotifyReverseResultInner; +} +ReverseContinuationSchedulerReplicaStub::~ReverseContinuationSchedulerReplicaStub() +{ + continuationFuncMap_.clear(); +} +int32_t ReverseContinuationSchedulerReplicaStub::PassPrimaryInner(MessageParcel &data, MessageParcel &reply) +{ + APP_LOGI("%{public}s called begin", __func__); + const sptr primary = data.ReadParcelable(); + PassPrimary(primary); + APP_LOGI("%{public}s called end", __func__); + return NO_ERROR; +} +int32_t ReverseContinuationSchedulerReplicaStub::ReverseContinuationInner(MessageParcel &data, MessageParcel &reply) +{ + APP_LOGI("%{public}s called begin", __func__); + ReverseContinuation(); + APP_LOGI("%{public}s called end", __func__); + return NO_ERROR; +} +int32_t ReverseContinuationSchedulerReplicaStub::NotifyReverseResultInner(MessageParcel &data, MessageParcel &reply) +{ + APP_LOGI("%{public}s called begin", __func__); + int reverseResult = data.ReadInt32(); + NotifyReverseResult(reverseResult); + APP_LOGI("%{public}s called end", __func__); + return NO_ERROR; +} + +int ReverseContinuationSchedulerReplicaStub::OnRemoteRequest( + uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) +{ + APP_LOGI("%{public}s called begin, code = %{public}d, flags= %{public}d.", __func__, code, option.GetFlags()); + std::u16string remoteDescriptor = data.ReadInterfaceToken(); + if (remoteDescriptor != ReverseContinuationSchedulerReplicaStub::GetDescriptor()) { + APP_LOGE("ReverseContinuationSchedulerReplicaStub::OnRemoteRequest token is invalid"); + return ERR_INVALID_STATE; + } + + auto itFunc = continuationFuncMap_.find(code); + if (itFunc != continuationFuncMap_.end()) { + auto continuationFunc = itFunc->second; + if (continuationFunc != nullptr) { + return (this->*continuationFunc)(data, reply); + } + } + APP_LOGI("%{public}s called end", __func__); + return IPCObjectStub::OnRemoteRequest(code, data, reply, option); +} +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/src/continuation/remote_register_service/connect_callback_proxy.cpp b/tools/frameworks/kits/ability/native/src/continuation/remote_register_service/connect_callback_proxy.cpp new file mode 100644 index 00000000000..a8663b42896 --- /dev/null +++ b/tools/frameworks/kits/ability/native/src/continuation/remote_register_service/connect_callback_proxy.cpp @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "connect_callback_proxy.h" +#include "extra_params.h" +#include "string_ex.h" +#include "app_log_wrapper.h" +namespace OHOS { +namespace AppExecFwk { + +/** + * @brief Remote device sends connection request. + * @param deviceId indicators id of connection device. + * @param deviceType indicators type of connection device. + * @return none + */ +void ConnectCallbackProxy::Connect(const string &deviceId, const string &deviceType) +{ + APP_LOGI("%{public}s called begin", __func__); + MessageParcel data; + if (!data.WriteInterfaceToken(IConnectCallback::GetDescriptor()) || !data.WriteString(deviceId) || + data.WriteString(deviceType)) { + APP_LOGE("%{public}s params is wrong", __func__); + return; + } + RemoteRequest(data, COMMAND_CONNECT); + APP_LOGI("%{public}s called end", __func__); +} +/** + * @brief Remote device sends disconnection request. + * @param deviceId indicators id of disconnection device. + * @return none + */ +void ConnectCallbackProxy::Disconnect(const string &deviceId) +{ + APP_LOGI("%{public}s called begin", __func__); + MessageParcel data; + if (!data.WriteInterfaceToken(IConnectCallback::GetDescriptor()) || !data.WriteString(deviceId)) { + APP_LOGE("%{public}s params is wrong", __func__); + return; + } + RemoteRequest(data, COMMAND_DISCONNECT); + APP_LOGI("%{public}s called end", __func__); +} +void ConnectCallbackProxy::RemoteRequest(MessageParcel &data, int commandDisconnect) +{ + APP_LOGI("%{public}s called begin", __func__); + MessageParcel reply; + MessageOption option; + if (Remote() == nullptr) { + return; + } + Remote()->SendRequest(commandDisconnect, data, reply, option); + APP_LOGI("%{public}s called begin", __func__); +} +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/src/continuation/remote_register_service/connect_callback_stub.cpp b/tools/frameworks/kits/ability/native/src/continuation/remote_register_service/connect_callback_stub.cpp new file mode 100644 index 00000000000..d79449a98b8 --- /dev/null +++ b/tools/frameworks/kits/ability/native/src/continuation/remote_register_service/connect_callback_stub.cpp @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "connect_callback_stub.h" +#include "ipc_types.h" +#include "string_ex.h" +#include "app_log_wrapper.h" + +namespace OHOS { +namespace AppExecFwk { + +ConnectCallbackStub::ConnectCallbackStub() +{ + memberFuncMap_[COMMAND_CONNECT] = &ConnectCallbackStub::ConnectInner; + memberFuncMap_[COMMAND_DISCONNECT] = &ConnectCallbackStub::DisconnectInner; +} + +int ConnectCallbackStub::ConnectInner(MessageParcel &data, MessageParcel &reply) +{ + APP_LOGI("%{public}s called begin", __func__); + string deviceId = Str16ToStr8(data.ReadString16()); + string deviceType = Str16ToStr8(data.ReadString16()); + Connect(deviceId, deviceType); + APP_LOGI("%{public}s called end", __func__); + return OHOS::ERR_NONE; +} + +int ConnectCallbackStub::DisconnectInner(MessageParcel &data, MessageParcel &reply) +{ + APP_LOGI("%{public}s called begin", __func__); + string deviceId = Str16ToStr8(data.ReadString16()); + Disconnect(deviceId); + APP_LOGI("%{public}s called end", __func__); + return OHOS::ERR_NONE; +} +/** + * @brief Remote device sends connection or disconnection request. + * @param Code indicators code of the connection or disconnection request function. + * @param data indicators receives the message object. + * @param reply indicators reply the message object. + * @return none + */ +int ConnectCallbackStub::OnRemoteRequest( + uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) +{ + APP_LOGI("%{public}s called", __func__); + std::u16string token = data.ReadInterfaceToken(); + if (token.compare(IConnectCallback::GetDescriptor()) != 0) { + APP_LOGE("%{public}s Descriptor is wrong", __func__); + return OHOS::ERR_INVALID_REPLY; + } + auto localFuncIt = memberFuncMap_.find(code); + if (localFuncIt != memberFuncMap_.end()) { + auto memberFunc = localFuncIt->second; + if (memberFunc != nullptr) { + return (this->*memberFunc)(data, reply); + } + } + APP_LOGI("ConnectCallbackStub::OnRemoteRequest, default case, need check."); + return IPCObjectStub::OnRemoteRequest(code, data, reply, option); +} +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/src/continuation/remote_register_service/continuation_connector.cpp b/tools/frameworks/kits/ability/native/src/continuation/remote_register_service/continuation_connector.cpp new file mode 100644 index 00000000000..a15b71468ab --- /dev/null +++ b/tools/frameworks/kits/ability/native/src/continuation/remote_register_service/continuation_connector.cpp @@ -0,0 +1,273 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "continuation_connector.h" +#include "app_log_wrapper.h" +#include "remote_register_service_proxy.h" +#include "continuation_device_callback_proxy.h" + +namespace OHOS { +namespace AppExecFwk { + +sptr ContinuationConnector::instance_ = nullptr; +std::mutex ContinuationConnector::mutex_; +const std::string ContinuationConnector::CONNECTOR_DEVICE_ID(""); +const std::string ContinuationConnector::CONNECTOR_BUNDLE_NAME("com.ohos.controlcenter"); +const std::string ContinuationConnector::CONNECTOR_ABILITY_NAME( + "com.ohos.controlcenter.fatransfer.service.FeatureAbilityRegisterService"); + +ContinuationConnector::ContinuationConnector(const std::weak_ptr &context) : context_(context) +{} + +/** + * @brief get singleton of Class ContinuationConnector + * + * @param context: the running context for appcontext + * + * @return The singleton of ContinuationConnector + */ +sptr ContinuationConnector::GetInstance(const std::weak_ptr &context) +{ + if (instance_ == nullptr) { + std::lock_guard lock(mutex_); + if (instance_ == nullptr) { + instance_ = sptr(new (std::nothrow) ContinuationConnector(context)); + } + } + return instance_; +} + +/** + * @brief This method is called back to receive the connection result after an ability calls the + * Ability#connectAbility(Intent, IAbilityConnection) method to connect it to a Service ability. + * + * @param element: Indicates information about the connected Service ability. + * @param remote: Indicates the remote proxy object of the Service ability. + * @param resultCode: Indicates the connection result code. The value 0 indicates a successful connection, and any other + * value indicates a connection failure. + */ +void ContinuationConnector::OnAbilityConnectDone( + const AppExecFwk::ElementName &element, const sptr &remoteObject, int resultCode) +{ + APP_LOGI("%{public}s called begin", __func__); + if (remoteObject == nullptr) { + APP_LOGE("ContinuationConnector::OnAbilityConnectDone failed, remote is nullptr"); + return; + } + remoteRegisterService_ = iface_cast(remoteObject); + if (remoteRegisterService_ == nullptr) { + APP_LOGE("ContinuationConnector::OnAbilityConnectDone failed, remoteRegisterService_ is nullptr"); + return; + } + isConnected_.store(true); + { + std::lock_guard lock(mutex_); + for (auto &iter : continuationRequestList_) { + iter->Execute(); + } + continuationRequestList_.clear(); + } + APP_LOGI("%{public}s called end", __func__); +} + +/** + * @brief This method is called back to receive the disconnection result after the connected Service ability crashes or + * is killed. If the Service ability exits unexpectedly, all its connections are disconnected, and each ability + * previously connected to it will call onAbilityDisconnectDone. + * + * @param element: Indicates information about the disconnected Service ability. + * @param resultCode: Indicates the disconnection result code. The value 0 indicates a successful disconnection, and any + * other value indicates a disconnection failure. + */ +void ContinuationConnector::OnAbilityDisconnectDone(const AppExecFwk::ElementName &element, int resultCode) +{ + APP_LOGI("%{public}s called begin", __func__); + remoteRegisterService_ = nullptr; + isConnected_.store(false); + APP_LOGI("%{public}s called end", __func__); +} + +/** + * @brief bind remote ability of RemoteRegisterService. + * + * @param request: request for continuation. + */ +void ContinuationConnector::BindRemoteRegisterAbility(const std::shared_ptr &request) +{ + APP_LOGI("%{public}s called begin", __func__); + std::shared_ptr tmpcontext = context_.lock(); + if (tmpcontext == nullptr) { + APP_LOGE("ContinuationConnector::BindRemoteRegisterAbility failed, context_.lock is nullptr"); + return; + } + if (request == nullptr) { + APP_LOGE("ContinuationConnector::BindRemoteRegisterAbility failed, request is nullptr"); + return; + } + if (IsAbilityConnected()) { + APP_LOGI("ContinuationConnector::BindRemoteRegisterAbility, remote register bounded"); + request->Execute(); + return; + } + + { + std::lock_guard lock(mutex_); + continuationRequestList_.push_back(request); + } + BindRemoteRegisterAbility(); + APP_LOGI("%{public}s called end", __func__); +} + +/** + * @brief unbind remote ability of RemoteRegisterService. + */ +void ContinuationConnector::UnbindRemoteRegisterAbility() +{ + APP_LOGI("%{public}s called begin", __func__); + std::shared_ptr tmpcontext = context_.lock(); + if (tmpcontext == nullptr) { + APP_LOGE("ContinuationConnector::UnbindRemoteRegisterAbility failed, context_.lock is nullptr"); + return; + } + + tmpcontext->DisconnectAbility(this); + isConnected_.store(false); + remoteRegisterService_ = nullptr; + APP_LOGI("%{public}s called end", __func__); +} + +/** + * @brief check whether connected to remote register service. + * + * @return bool true if connected, otherwise false. + */ +bool ContinuationConnector::IsAbilityConnected() +{ + return isConnected_.load(); +} + +/** + * @brief unregister to control center continuation register service. + * + * @param token token from register return value. + * + * @return bool result of unregister. + */ +bool ContinuationConnector::Unregister(int token) +{ + APP_LOGI("%{public}s called begin", __func__); + if (remoteRegisterService_ == nullptr) { + APP_LOGE("ContinuationConnector::Unregister failed, remoteRegisterService_ is nullptr"); + return false; + } + + APP_LOGI("%{public}s called end", __func__); + return remoteRegisterService_->Unregister(token); +} + +/** + * @brief notify continuation status to control center continuation register service. + * + * @param token token from register. + * @param deviceId device id. + * @param status device status. + * + * @return bool result of updateConnectStatus. + */ +bool ContinuationConnector::UpdateConnectStatus(int token, const std::string &deviceId, int status) +{ + APP_LOGI("%{public}s called begin", __func__); + if (remoteRegisterService_ == nullptr) { + APP_LOGE("ContinuationConnector::UpdateConnectStatus failed, remoteRegisterService_ is nullptr"); + return false; + } + + APP_LOGI("%{public}s called end", __func__); + return remoteRegisterService_->UpdateConnectStatus(token, deviceId, status); +} + +/** + * @brief notify control center continuation register service to show device list. + * + * @param token token from register + * @param parameter filter with supported device list. + * @return bool result of showDeviceList. + */ +bool ContinuationConnector::ShowDeviceList(int token, const AppExecFwk::ExtraParams ¶meter) +{ + APP_LOGI("%{public}s called begin", __func__); + if (remoteRegisterService_ == nullptr) { + APP_LOGE("ContinuationConnector::ShowDeviceList failed, remoteRegisterService_ is nullptr"); + return false; + } + APP_LOGI("%{public}s called end", __func__); + return remoteRegisterService_->ShowDeviceList(token, parameter); +} + +/** + * @brief register to control center continuation register service. + * + * @param context ability context. + * @param bundleName bundle name of ability. + * @param parameter filter with supported device list. + * @param callback callback for device connect and disconnect. + * + * @return int token. + */ +int ContinuationConnector::Register(std::weak_ptr &context, std::string bundleName, + const AppExecFwk::ExtraParams ¶meter, std::shared_ptr &callback) +{ + APP_LOGI("%{public}s called begin", __func__); + std::shared_ptr pcontext = context.lock(); + if (pcontext == nullptr) { + APP_LOGE("ContinuationConnector::Register failed, pcontext is nullptr"); + return -1; + } + if (remoteRegisterService_ == nullptr) { + APP_LOGE("ContinuationConnector::Register failed, remoteRegisterService_ is nullptr"); + return -1; + } + sptr token = pcontext->GetToken(); + if (token == nullptr) { + APP_LOGE("ContinuationConnector::Register failed, token is nullptr"); + return -1; + } + + sptr callBackSptr(new (std::nothrow) ContinuationDeviceCallbackProxy(callback)); + + APP_LOGI("%{public}s called end", __func__); + return remoteRegisterService_->Register(bundleName, token, parameter, callBackSptr); +} + +/** + * @brief bind remote ability of RemoteRegisterService. + */ +void ContinuationConnector::BindRemoteRegisterAbility() +{ + APP_LOGI("%{public}s called begin", __func__); + std::shared_ptr tmpcontext = context_.lock(); + if (tmpcontext == nullptr) { + APP_LOGE("ContinuationConnector::BindRemoteRegisterAbility failed, context_.lock is nullptr"); + return; + } + Want want; + want.SetElementName(CONNECTOR_DEVICE_ID, CONNECTOR_BUNDLE_NAME, CONNECTOR_ABILITY_NAME); + want.AddFlags(Want::FLAG_NOT_OHOS_COMPONENT); + tmpcontext->ConnectAbility(want, this); + APP_LOGI("%{public}s called end", __func__); +} + +} // namespace AppExecFwk +} // namespace OHOS diff --git a/tools/frameworks/kits/ability/native/src/continuation/remote_register_service/continuation_device_callback_proxy.cpp b/tools/frameworks/kits/ability/native/src/continuation/remote_register_service/continuation_device_callback_proxy.cpp new file mode 100644 index 00000000000..7c2298659a6 --- /dev/null +++ b/tools/frameworks/kits/ability/native/src/continuation/remote_register_service/continuation_device_callback_proxy.cpp @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "continuation_device_callback_proxy.h" +#include "app_log_wrapper.h" +namespace OHOS { +namespace AppExecFwk { +/** + * A constructor used to create a {@link ohos.aafwk.ability.continuation.ContinuationDeviceCallbackProxy} instance. + */ +ContinuationDeviceCallbackProxy::ContinuationDeviceCallbackProxy(std::shared_ptr &callback) +{ + callback_ = std::weak_ptr(callback); +} +/** + * A destructor used to release a {@link ohos.aafwk.ability.continuation.ContinuationDeviceCallbackProxy} instance. + */ +ContinuationDeviceCallbackProxy::~ContinuationDeviceCallbackProxy() +{} +void ContinuationDeviceCallbackProxy::Connect(const std::string &deviceId, const std::string &deviceType) +{ + APP_LOGI("%{public}s called begin", __func__); + std::shared_ptr callback = nullptr; + callback = callback_.lock(); + if (callback == nullptr) { + APP_LOGE("%{public}s callback is null", __func__); + return; + } + callback->OnDeviceConnectDone(deviceId, deviceType); + APP_LOGI("%{public}s called end", __func__); +} + +void ContinuationDeviceCallbackProxy::Disconnect(const std::string &deviceId) +{ + APP_LOGI("%{public}s called begin", __func__); + std::shared_ptr callback = nullptr; + callback = callback_.lock(); + if (callback == nullptr) { + APP_LOGE("%{public}s callback is null", __func__); + return; + } + callback->OnDeviceDisconnectDone(deviceId); + APP_LOGI("%{public}s called end", __func__); +} +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/src/continuation/remote_register_service/continuation_register_manager.cpp b/tools/frameworks/kits/ability/native/src/continuation/remote_register_service/continuation_register_manager.cpp new file mode 100644 index 00000000000..3a91e56fa48 --- /dev/null +++ b/tools/frameworks/kits/ability/native/src/continuation/remote_register_service/continuation_register_manager.cpp @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "continuation_register_manager.h" +#include "app_log_wrapper.h" +#include "continuation_register_manager_proxy.h" +#include "continuation_device_callback_interface.h" +#include "extra_params.h" +#include "request_callback.h" + +namespace OHOS { +namespace AppExecFwk { + +void ContinuationRegisterManager::Init( + const std::shared_ptr &continuationRegisterManagerProxy) +{ + continuationRegisterManagerProxy_ = continuationRegisterManagerProxy; +} + +/** + * register to controlcenter continuation register service. + * + * @param bundleName bundlename of ability. + * @param parameter filter with supported device list. + * @param callback callback for device connect and disconnect. + * @param requestCallback callback for this request, -1 means failed, otherwise is register token. + */ +void ContinuationRegisterManager::Register(const std::string &bundleName, const ExtraParams ¶meter, + const std::shared_ptr &deviceCallback, + const std::shared_ptr &requestCallback) +{ + APP_LOGI("%{public}s called begin", __func__); + if (continuationRegisterManagerProxy_ != nullptr) { + continuationRegisterManagerProxy_->Register(bundleName, parameter, deviceCallback, requestCallback); + APP_LOGI("%{public}s called end", __func__); + } else { + APP_LOGE("%{public}s, ContinuationRegisterManagerProxy is null", __func__); + } +} + +/** + * unregister to controlcenter continuation register service. + * + * @param token token from register return value. + * @param requestCallback callback for this request, -1 means failed, otherwise succeeded. + */ +void ContinuationRegisterManager::Unregister(int token, const std::shared_ptr &requestCallback) +{ + APP_LOGI("%{public}s called begin", __func__); + if (continuationRegisterManagerProxy_ != nullptr) { + continuationRegisterManagerProxy_->Unregister(token, requestCallback); + APP_LOGI("%{public}s called end", __func__); + } else { + APP_LOGE("%{public}s, ContinuationRegisterManagerProxy is null", __func__); + } +} + +/** + * notify continuation status to controlcenter continuation register service. + * + * @param token token from register. + * @param deviceId deviceid. + * @param status device status. + * @param requestCallback callback for this request, -1 means failed, otherwise successed. + */ +void ContinuationRegisterManager::UpdateConnectStatus( + int token, const std::string &deviceId, int status, const std::shared_ptr &requestCallback) +{ + APP_LOGI("%{public}s called begin", __func__); + if (continuationRegisterManagerProxy_ != nullptr) { + continuationRegisterManagerProxy_->UpdateConnectStatus(token, deviceId, status, requestCallback); + APP_LOGI("%{public}s called end", __func__); + } else { + APP_LOGE("%{public}s, ContinuationRegisterManagerProxy is null", __func__); + } +} + +/** + * notify controlcenter continuation register service to show device list. + * + * @param token token from register + * @param parameter filter with supported device list. + * @param requestCallback callback for this request, -1 means failed, otherwise successed. + */ +void ContinuationRegisterManager::ShowDeviceList( + int token, const ExtraParams ¶meter, const std::shared_ptr &requestCallback) +{ + APP_LOGI("%{public}s called begin", __func__); + if (continuationRegisterManagerProxy_ != nullptr) { + continuationRegisterManagerProxy_->ShowDeviceList(token, parameter, requestCallback); + APP_LOGI("%{public}s called end", __func__); + } else { + APP_LOGE("%{public}s, ContinuationRegisterManagerProxy is null", __func__); + } +} + +/** + * disconnect to controlcenter continuation register service. + */ +void ContinuationRegisterManager::Disconnect(void) +{ + APP_LOGI("%{public}s called begin", __func__); + if (continuationRegisterManagerProxy_ != nullptr) { + continuationRegisterManagerProxy_->Disconnect(); + APP_LOGI("%{public}s called end", __func__); + } else { + APP_LOGE("%{public}s, ContinuationRegisterManagerProxy is null", __func__); + } +} +} // namespace AppExecFwk +} // namespace OHOS diff --git a/tools/frameworks/kits/ability/native/src/continuation/remote_register_service/continuation_register_manager_proxy.cpp b/tools/frameworks/kits/ability/native/src/continuation/remote_register_service/continuation_register_manager_proxy.cpp new file mode 100644 index 00000000000..1cad17987c9 --- /dev/null +++ b/tools/frameworks/kits/ability/native/src/continuation/remote_register_service/continuation_register_manager_proxy.cpp @@ -0,0 +1,301 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "continuation_register_manager_proxy.h" +#include "app_log_wrapper.h" +#include "continuation_device_callback_interface.h" +#include "request_callback.h" +#include "continuation_request.h" +#include "context.h" +#include "continuation_connector.h" + +namespace OHOS { +namespace AppExecFwk { + +ContinuationRequestRegister::ContinuationRequestRegister(const std::string &bundleName, const ExtraParams ¶meter, + const std::shared_ptr &deviceCallback) +{ + parameter_ = parameter; + deviceCallback_ = deviceCallback; + bundleName_ = bundleName; +} + +void ContinuationRequestRegister::Execute(void) +{ + if (continuatinConnector_ == nullptr) { + APP_LOGE("%{public}s called, continuatinConnector is null", __func__); + return; + } + + int ret = continuatinConnector_->Register(context_, bundleName_, parameter_, deviceCallback_); + if (requestCallback_ != nullptr) { + requestCallback_->OnResult(ret); + APP_LOGI("%{public}s called, ret=%{public}d", __func__, ret); + } else { + APP_LOGE("%{public}s called, requestCallback is null", __func__); + } +} + +ContinuationRequestUnRegister::ContinuationRequestUnRegister(int token) +{ + token_ = token; +} + +void ContinuationRequestUnRegister::Execute(void) +{ + if (continuatinConnector_ == nullptr) { + APP_LOGE("%{public}s called, continuatinConnector is null", __func__); + return; + } + + bool ret = continuatinConnector_->Unregister(token_); + if (requestCallback_ != nullptr) { + requestCallback_->OnResult(ret ? 0 : -1); + APP_LOGI("%{public}s called, ret=%{public}d", __func__, (ret ? 0 : -1)); + } else { + APP_LOGE("%{public}s called, requestCallback is null", __func__); + } +} + +ContinuationRequestUpdateConnectStatus::ContinuationRequestUpdateConnectStatus( + int token, const std::string &deviceId, int status) +{ + token_ = token; + deviceId_ = deviceId; + status_ = status; +} + +void ContinuationRequestUpdateConnectStatus::Execute(void) +{ + if (continuatinConnector_ == nullptr) { + APP_LOGE("%{public}s called, continuatinConnector is null", __func__); + return; + } + + bool ret = continuatinConnector_->UpdateConnectStatus(token_, deviceId_, status_); + if (requestCallback_ != nullptr) { + requestCallback_->OnResult(ret ? 0 : -1); + APP_LOGI("%{public}s called, ret=%{public}d", __func__, (ret ? 0 : -1)); + } else { + APP_LOGE("%{public}s called, requestCallback is null", __func__); + } +} + +ContinuationRequestShowDeviceList::ContinuationRequestShowDeviceList(int token, const ExtraParams ¶meter) +{ + token_ = token; + parameter_ = parameter; +} + +void ContinuationRequestShowDeviceList::Execute(void) +{ + if (continuatinConnector_ == nullptr) { + APP_LOGE("%{public}s called, continuatinConnector is null", __func__); + return; + } + + bool ret = continuatinConnector_->ShowDeviceList(token_, parameter_); + if (requestCallback_ != nullptr) { + requestCallback_->OnResult(ret ? 0 : -1); + APP_LOGI("%{public}s called, ret=%{public}d", __func__, (ret ? 0 : -1)); + } else { + APP_LOGE("%{public}s called, requestCallback is null", __func__); + } +} + +ContinuationRegisterManagerProxy::ContinuationRegisterManagerProxy(const std::weak_ptr &context) +{ + context_ = context; + std::shared_ptr ctx = context_.lock(); + if (ctx != nullptr) { + applicationContext_ = std::weak_ptr(ctx->GetApplicationContext()); + } +} + +ContinuationRegisterManagerProxy::~ContinuationRegisterManagerProxy() +{} + +/** + * Registers an ability to be migrated with the Device+ control center and obtains the registration token assigned + * to the ability. + * + * @param bundleName Indicates the bundle name of the application whose ability is to be migrated. + * @param parameter Indicates the {@link ExtraParams} object containing the extra parameters used to filter + * the list of available devices. This parameter can be null. + * @param deviceCallback Indicates the callback to be invoked when the connection state of the selected device + * changes. + * @param requestCallback Indicates the callback to be invoked when the Device+ service is connected. + */ +void ContinuationRegisterManagerProxy::Register(const std::string &bundleName, const ExtraParams ¶meter, + const std::shared_ptr &deviceCallback, + const std::shared_ptr &requestCallback) +{ + APP_LOGI("%{public}s called", __func__); + + if (context_.lock() == nullptr || applicationContext_.lock() == nullptr) { + APP_LOGE("%{public}s context or applicationContext is null", __func__); + return; + } + + ContinuationRequestRegister *pContinuationRequestRegister = + new (std::nothrow) ContinuationRequestRegister(bundleName, parameter, deviceCallback); + if (pContinuationRequestRegister != nullptr) { + pContinuationRequestRegister->SetContext(context_); + pContinuationRequestRegister->SetContinuationConnector(continuatinConnector_); + pContinuationRequestRegister->SetRequestCallback(requestCallback); + + std::shared_ptr request(pContinuationRequestRegister); + + SendRequest(applicationContext_, request); + } else { + APP_LOGE("%{public}s Create ContinuationRequestRegister failed", __func__); + } +} + +/** + * Unregisters a specified ability from the Device+ control center based on the token obtained during ability + * registration. + * + * @param token Indicates the registration token of the ability. + * @param requestCallback Indicates the callback to be invoked when the Device+ service is connected. + * This parameter can be null. + */ +void ContinuationRegisterManagerProxy::Unregister(int token, const std::shared_ptr &requestCallback) +{ + APP_LOGI("%{public}s called", __func__); + + if (applicationContext_.lock() == nullptr) { + APP_LOGI("%{public}s Context is null", __func__); + return; + } + + ContinuationRequestUnRegister *pContinuationRequestUnRegister = + new (std::nothrow) ContinuationRequestUnRegister(token); + if (pContinuationRequestUnRegister != nullptr) { + pContinuationRequestUnRegister->SetContinuationConnector(continuatinConnector_); + pContinuationRequestUnRegister->SetRequestCallback(requestCallback); + + std::shared_ptr request(pContinuationRequestUnRegister); + + SendRequest(applicationContext_, request); + } else { + APP_LOGE("%{public}s Create ContinuationRequestUnRegister failed", __func__); + } +} + +/** + * Updates the connection state of the device where the specified ability is successfully migrated. + * + * @param token Indicates the registration token of the ability. + * @param deviceId Indicates the ID of the device whose connection state is to be updated. + * @param status Indicates the connection state to update, which can be {@link DeviceConnectState#FAILURE}, + * {@link DeviceConnectState#IDLE}, {@link DeviceConnectState#CONNECTING}, {@link DeviceConnectState#CONNECTED}, + * or {@link DeviceConnectState#DIS_CONNECTING}. + * @param requestCallback Indicates the callback to be invoked when the Device+ service is connected. + * This parameter can be null. + */ +void ContinuationRegisterManagerProxy::UpdateConnectStatus( + int token, const std::string &deviceId, int status, const std::shared_ptr &requestCallback) +{ + APP_LOGI("%{public}s called", __func__); + + if (applicationContext_.lock() == nullptr) { + APP_LOGI("%{public}s Context is null", __func__); + return; + } + + ContinuationRequestUpdateConnectStatus *pContinuationRequestUpdateConnectStatus = + new (std::nothrow) ContinuationRequestUpdateConnectStatus(token, deviceId, status); + + if (pContinuationRequestUpdateConnectStatus != nullptr) { + pContinuationRequestUpdateConnectStatus->SetContinuationConnector(continuatinConnector_); + pContinuationRequestUpdateConnectStatus->SetRequestCallback(requestCallback); + + std::shared_ptr request(pContinuationRequestUpdateConnectStatus); + + SendRequest(applicationContext_, request); + } else { + APP_LOGE("%{public}s Create ContinuationRequestUpdateConnectStatus failed", __func__); + } +} + +/** + * Shows the list of devices that can be selected for ability migration on the distributed network. + * + * @param token Indicates the registration token of the ability. + * @param parameter Indicates the {@link ExtraParams} object containing the extra parameters used to filter + * the list of available devices. This parameter can be null. + * @param requestCallback Indicates the callback to be invoked when the Device+ service is connected. + * This parameter can be null. + */ +void ContinuationRegisterManagerProxy::ShowDeviceList( + int token, const ExtraParams ¶meter, const std::shared_ptr &requestCallback) +{ + APP_LOGI("%{public}s called begin", __func__); + + if (applicationContext_.lock() == nullptr) { + APP_LOGI("%{public}s Context is null", __func__); + return; + } + + ContinuationRequestShowDeviceList *pContinuationRequestShowDeviceList = + new (std::nothrow) ContinuationRequestShowDeviceList(token, parameter); + if (pContinuationRequestShowDeviceList != nullptr) { + pContinuationRequestShowDeviceList->SetContinuationConnector(continuatinConnector_); + pContinuationRequestShowDeviceList->SetRequestCallback(requestCallback); + + std::shared_ptr request(pContinuationRequestShowDeviceList); + + SendRequest(applicationContext_, request); + APP_LOGI("%{public}s called end", __func__); + } else { + APP_LOGE("%{public}s Create ContinuationRequestShowDeviceList failed", __func__); + } +} + +/** + * Disconnects from the Device+ control center. + */ +void ContinuationRegisterManagerProxy::Disconnect(void) +{ + APP_LOGI("%{public}s called begin", __func__); + + if (continuatinConnector_ != nullptr && continuatinConnector_->IsAbilityConnected()) { + continuatinConnector_->UnbindRemoteRegisterAbility(); + } + APP_LOGI("%{public}s called end", __func__); +} + +void ContinuationRegisterManagerProxy::SendRequest( + const std::weak_ptr &context, const std::shared_ptr &request) +{ + APP_LOGI("%{public}s called begin", __func__); + if (request == nullptr) { + APP_LOGE("%{public}s called, request is null", __func__); + return; + } + + if (continuatinConnector_ == nullptr) { + continuatinConnector_ = ContinuationConnector::GetInstance(context); + } + + if (!continuatinConnector_->IsAbilityConnected()) { + continuatinConnector_->BindRemoteRegisterAbility(request); + } else { + request->Execute(); + } + APP_LOGI("%{public}s called end", __func__); +} +} // namespace AppExecFwk +} // namespace OHOS diff --git a/tools/frameworks/kits/ability/native/src/continuation/remote_register_service/remote_register_service_proxy.cpp b/tools/frameworks/kits/ability/native/src/continuation/remote_register_service/remote_register_service_proxy.cpp new file mode 100644 index 00000000000..50c8968db07 --- /dev/null +++ b/tools/frameworks/kits/ability/native/src/continuation/remote_register_service/remote_register_service_proxy.cpp @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "remote_register_service_proxy.h" +#include "app_log_wrapper.h" + +namespace OHOS { +namespace AppExecFwk { + +/** + * register to controlcenter continuation register service. + * + * @param bundleName bundlename of ability. + * @param extras filter with supported device list. + * @param callback callback for device connect and disconnect. + */ +int RemoteRegisterServiceProxy::Register(const std::string &bundleName, const sptr &token, + const ExtraParams &extras, const sptr &callback) +{ + APP_LOGI("%{public}s called", __func__); + + if (bundleName.empty() || token == nullptr || callback == nullptr) { + APP_LOGE("%{public}s param invalid", __func__); + return ERR_INVALID_DATA; + } + + auto remote = Remote(); + if (remote == nullptr) { + APP_LOGE("%{public}s remote is null", __func__); + return ERR_NULL_OBJECT; + } + + MessageParcel data; + if (!data.WriteInterfaceToken(IRemoteRegisterService::GetDescriptor()) || !data.WriteString(bundleName) || + data.WriteRemoteObject(token) || !data.WriteInt32(1) || !extras.Marshalling(data) || + !data.WriteRemoteObject(callback->AsObject())) { + APP_LOGE("%{public}s Failed to write transfer data.", __func__); + return IPC_INVOKER_WRITE_TRANS_ERR; + } + + MessageParcel reply; + MessageOption option; + int result = remote->SendRequest(COMMAND_REGISTER, data, reply, option); + if (result == ERR_NONE) { + APP_LOGI("%{public}s SendRequest ok", __func__); + return reply.ReadInt32(); + } else { + APP_LOGE("%{public}s SendRequest error, result=%{public}d", __func__, result); + return IPC_INVOKER_TRANSLATE_ERR; + } +} + +/** + * unregister to controlcenter continuation register service. + * + * @param registerToken token from register return value. + */ +bool RemoteRegisterServiceProxy::Unregister(int registerToken) +{ + APP_LOGI("%{public}s called", __func__); + + auto remote = Remote(); + if (remote == nullptr) { + APP_LOGE("%{public}s remote is null", __func__); + return false; + } + + MessageParcel data; + if (!data.WriteInterfaceToken(IRemoteRegisterService::GetDescriptor()) || !data.WriteInt32(registerToken)) { + APP_LOGE("%{public}s Failed to write transfer data.", __func__); + return false; + } + + MessageParcel reply; + MessageOption option; + int32_t result = remote->SendRequest(COMMAND_UNREGISTER, data, reply, option); + if (result == ERR_NONE) { + APP_LOGI("%{public}s SendRequest ok", __func__); + return reply.ReadInt32() == ERR_NONE; + } else { + APP_LOGE("%{public}s SendRequest error, result=%{public}d", __func__, result); + return false; + } +} + +/** + * notify continuation status to controlcenter continuation register service. + * + * @param registerToken token from register. + * @param deviceId deviceid. + * @param status device status. + */ +bool RemoteRegisterServiceProxy::UpdateConnectStatus(int registerToken, const std::string &deviceId, int status) +{ + APP_LOGI("%{public}s called", __func__); + + auto remote = Remote(); + if (remote == nullptr) { + APP_LOGE("%{public}s remote is null", __func__); + return false; + } + + MessageParcel data; + if (!data.WriteInterfaceToken(IRemoteRegisterService::GetDescriptor()) || !data.WriteInt32(registerToken) || + !data.WriteString(deviceId) || !data.WriteInt32(status)) { + APP_LOGE("%{public}s Failed to write transfer data.", __func__); + return false; + } + + MessageParcel reply; + MessageOption option; + int32_t result = remote->SendRequest(COMMAND_UPDATE_CONNECT_STATUS, data, reply, option); + if (result == ERR_NONE) { + APP_LOGI("%{public}s SendRequest ok", __func__); + return reply.ReadInt32() == ERR_NONE; + } else { + APP_LOGE("%{public}s SendRequest error, result=%{public}d", __func__, result); + return false; + } +} + +/** + * notify controlcenter continuation register service to show device list. + * + * @param registerToken token from register + * @param extras filter with supported device list. + */ +bool RemoteRegisterServiceProxy::ShowDeviceList(int registerToken, const ExtraParams &extras) +{ + APP_LOGI("%{public}s called", __func__); + + auto remote = Remote(); + if (remote == nullptr) { + APP_LOGE("%{public}s remote is null", __func__); + return false; + } + + MessageParcel data; + if (!data.WriteInterfaceToken(IRemoteRegisterService::GetDescriptor()) || !data.WriteInt32(registerToken) || + !data.WriteInt32(1) || !extras.Marshalling(data)) { + APP_LOGE("%{public}s Failed to write transfer data.", __func__); + return false; + } + + MessageParcel reply; + MessageOption option; + int32_t result = remote->SendRequest(COMMAND_SHOW_DEVICE_LIST, data, reply, option); + if (result == ERR_NONE) { + APP_LOGI("%{public}s SendRequest ok", __func__); + return reply.ReadInt32() == ERR_NONE; + } else { + APP_LOGE("%{public}s SendRequest error, result=%{public}d", __func__, result); + return false; + } +} +} // namespace AppExecFwk +} // namespace OHOS diff --git a/tools/frameworks/kits/ability/native/src/continuation/remote_register_service/remote_register_service_stub.cpp b/tools/frameworks/kits/ability/native/src/continuation/remote_register_service/remote_register_service_stub.cpp new file mode 100644 index 00000000000..fb51bd01a68 --- /dev/null +++ b/tools/frameworks/kits/ability/native/src/continuation/remote_register_service/remote_register_service_stub.cpp @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "remote_register_service_stub.h" +#include "app_log_wrapper.h" + +namespace OHOS { +namespace AppExecFwk { +RemoteRegisterServiceStub::RemoteRegisterServiceStub() +{ + requestFuncMap_[COMMAND_REGISTER] = &RemoteRegisterServiceStub::RegisterInner; + requestFuncMap_[COMMAND_UNREGISTER] = &RemoteRegisterServiceStub::UnregisterInner; + requestFuncMap_[COMMAND_UPDATE_CONNECT_STATUS] = &RemoteRegisterServiceStub::UpdateConnectStatusInner; + requestFuncMap_[COMMAND_SHOW_DEVICE_LIST] = &RemoteRegisterServiceStub::ShowDeviceListInner; +} + +RemoteRegisterServiceStub::~RemoteRegisterServiceStub() +{ + requestFuncMap_.clear(); +} + +int RemoteRegisterServiceStub::OnRemoteRequest( + uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) +{ + APP_LOGI("%{public}s called, cmd=%{public}d, flags=%{public}d", __func__, code, option.GetFlags()); + + std::u16string descriptor = IRemoteRegisterService::GetDescriptor(); + std::u16string remoteDescriptor = data.ReadInterfaceToken(); + if (descriptor != remoteDescriptor) { + APP_LOGI("%{public}s local descriptor is not equal to remote", __func__); + return ERR_INVALID_STATE; + } + + auto itFunc = requestFuncMap_.find(code); + if (itFunc != requestFuncMap_.end()) { + auto requestFunc = itFunc->second; + if (requestFunc != nullptr) { + return (this->*requestFunc)(data, reply); + } + } + + APP_LOGI("%{public}s Not found cmd, need check.", __func__); + return IPCObjectStub::OnRemoteRequest(code, data, reply, option); +} + +int RemoteRegisterServiceStub::RegisterInner(MessageParcel &data, MessageParcel &reply) +{ + APP_LOGI("%{public}s called begin", __func__); + std::string bundleName = data.ReadString(); + sptr token = data.ReadParcelable(); + ExtraParams *pExtras = nullptr; + int32_t extraId = data.ReadInt32(); + if (extraId != 0) { + pExtras = ExtraParams::Unmarshalling(data); + } + if (pExtras == nullptr) { + reply.WriteInt32(ERR_INVALID_DATA); + APP_LOGE("%{public}s Failed to read ExtraParams.", __func__); + return ERR_INVALID_DATA; + } + + sptr object = data.ReadRemoteObject(); + if (object == nullptr) { + delete pExtras; + pExtras = nullptr; + reply.WriteInt32(ERR_NULL_OBJECT); + APP_LOGE("%{public}s Failed to read IConnectCallback.", __func__); + return ERR_NULL_OBJECT; + } + + sptr callback = iface_cast(object); + int result = Register(bundleName, token, *pExtras, callback); + delete pExtras; + pExtras = nullptr; + reply.WriteInt32(result); + APP_LOGI("%{public}s called end", __func__); + return NO_ERROR; +} + +int RemoteRegisterServiceStub::UnregisterInner(MessageParcel &data, MessageParcel &reply) +{ + APP_LOGI("%{public}s called begin", __func__); + int registerToken = data.ReadInt32(); + bool result = Unregister(registerToken); + reply.WriteInt32(result ? ERR_NONE : IPC_STUB_ERR); + APP_LOGI("%{public}s called end", __func__); + return NO_ERROR; +} + +int RemoteRegisterServiceStub::UpdateConnectStatusInner(MessageParcel &data, MessageParcel &reply) +{ + APP_LOGI("%{public}s called begin", __func__); + int registerToken = data.ReadInt32(registerToken); + std::string deviceId = data.ReadString(); + int status = data.ReadInt32(); + bool result = UpdateConnectStatus(registerToken, deviceId, status); + reply.WriteInt32(result ? ERR_NONE : IPC_STUB_ERR); + APP_LOGI("%{public}s called end", __func__); + return NO_ERROR; +} + +int RemoteRegisterServiceStub::ShowDeviceListInner(MessageParcel &data, MessageParcel &reply) +{ + APP_LOGI("%{public}s called begin", __func__); + int registerToken = data.ReadInt32(); + ExtraParams *pExtras = nullptr; + int32_t extraId = data.ReadInt32(); + if (extraId != 0) { + pExtras = ExtraParams::Unmarshalling(data); + } + if (pExtras == nullptr) { + reply.WriteInt32(ERR_INVALID_DATA); + APP_LOGE("%{public}s Failed to read ExtraParams.", __func__); + return ERR_INVALID_DATA; + } + + bool result = ShowDeviceList(registerToken, *pExtras); + delete pExtras; + pExtras = nullptr; + reply.WriteInt32(result ? ERR_NONE : IPC_STUB_ERR); + APP_LOGI("%{public}s called end", __func__); + return NO_ERROR; +} +} // namespace AppExecFwk +} // namespace OHOS diff --git a/tools/frameworks/kits/ability/native/src/data_ability_helper.cpp b/tools/frameworks/kits/ability/native/src/data_ability_helper.cpp new file mode 100644 index 00000000000..46322630ea7 --- /dev/null +++ b/tools/frameworks/kits/ability/native/src/data_ability_helper.cpp @@ -0,0 +1,1111 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "data_ability_helper.h" +#include "ability_thread.h" +#include "ability_scheduler_interface.h" +#include "app_log_wrapper.h" +#include "abs_shared_result_set.h" +#include "data_ability_predicates.h" +#include "values_bucket.h" +#include "data_ability_result.h" +#include "data_ability_operation.h" +#include "data_ability_observer_interface.h" + +namespace OHOS { +namespace AppExecFwk { +std::string SchemeOhos = "dataability"; +std::mutex DataAbilityHelper::oplock_; +using IAbilityScheduler = OHOS::AAFwk::IAbilityScheduler; +using AbilityManagerClient = OHOS::AAFwk::AbilityManagerClient; +DataAbilityHelper::DataAbilityHelper(const std::shared_ptr &context, const std::shared_ptr &uri, + const sptr &dataAbilityProxy, bool tryBind) +{ + APP_LOGI("DataAbilityHelper::DataAbilityHelper start"); + token_ = context->GetToken(); + context_ = std::weak_ptr(context); + uri_ = uri; + tryBind_ = tryBind; + dataAbilityProxy_ = dataAbilityProxy; + APP_LOGI("DataAbilityHelper::DataAbilityHelper end"); +} + +DataAbilityHelper::DataAbilityHelper(const std::shared_ptr &context) +{ + APP_LOGI("DataAbilityHelper::DataAbilityHelper only with context start"); + token_ = context->GetToken(); + context_ = std::weak_ptr(context); + APP_LOGI("DataAbilityHelper::DataAbilityHelper only with context end"); +} + +DataAbilityHelper::DataAbilityHelper(const sptr &token, const std::shared_ptr &uri, + const sptr &dataAbilityProxy) +{ + APP_LOGI("DataAbilityHelper::DataAbilityHelper start"); + token_ = token; + uri_ = uri; + tryBind_ = false; + dataAbilityProxy_ = dataAbilityProxy; + isSystemCaller_ = true; + if (isSystemCaller_ && dataAbilityProxy_) { + AddDataAbilityDeathRecipient(dataAbilityProxy_->AsObject()); + } + APP_LOGI("DataAbilityHelper::DataAbilityHelper end"); +} + +DataAbilityHelper::DataAbilityHelper(const sptr &token) +{ + APP_LOGI("DataAbilityHelper::DataAbilityHelper only with token_start"); + token_ = token; + isSystemCaller_ = true; + APP_LOGI("DataAbilityHelper::DataAbilityHelper only with token end"); +} + +void DataAbilityHelper::AddDataAbilityDeathRecipient(const sptr &token) +{ + APP_LOGI("DataAbilityHelper::AddDataAbilityDeathRecipient start."); + if (token != nullptr && callerDeathRecipient_ != nullptr) { + APP_LOGI("token RemoveDeathRecipient."); + token->RemoveDeathRecipient(callerDeathRecipient_); + } + if (callerDeathRecipient_ == nullptr) { + callerDeathRecipient_ = + new DataAbilityDeathRecipient(std::bind(&DataAbilityHelper::OnSchedulerDied, this, std::placeholders::_1)); + } + if (token != nullptr) { + APP_LOGI("token AddDeathRecipient."); + token->AddDeathRecipient(callerDeathRecipient_); + } + APP_LOGI("DataAbilityHelper::AddDataAbilityDeathRecipient end."); +} + +void DataAbilityHelper::OnSchedulerDied(const wptr &remote) +{ + APP_LOGI("'%{public}s start':", __func__); + std::lock_guard guard(lock_); + auto object = remote.promote(); + object = nullptr; + dataAbilityProxy_ = nullptr; + uri_ = nullptr; + APP_LOGI("DataAbilityHelper::OnSchedulerDied end."); +} + +/** + * @brief Creates a DataAbilityHelper instance without specifying the Uri based on the given Context. + * + * @param context Indicates the Context object on OHOS. + * + * @return Returns the created DataAbilityHelper instance where Uri is not specified. + */ +std::shared_ptr DataAbilityHelper::Creator(const std::shared_ptr &context) +{ + APP_LOGI("DataAbilityHelper::Creator with context start."); + if (context == nullptr) { + APP_LOGE("DataAbilityHelper::Creator (context, uri, tryBind) failed, context == nullptr"); + return nullptr; + } + + DataAbilityHelper *ptrDataAbilityHelper = new (std::nothrow) DataAbilityHelper(context); + if (ptrDataAbilityHelper == nullptr) { + APP_LOGE("DataAbilityHelper::Creator (context) failed, create DataAbilityHelper failed"); + return nullptr; + } + + APP_LOGI("DataAbilityHelper::Creator with context end."); + return std::shared_ptr(ptrDataAbilityHelper); +} + +/** + * @brief Creates a DataAbilityHelper instance with the Uri specified based on the given Context. + * + * @param context Indicates the Context object on OHOS. + * @param uri Indicates the database table or disk file to operate. + * + * @return Returns the created DataAbilityHelper instance with a specified Uri. + */ +std::shared_ptr DataAbilityHelper::Creator( + const std::shared_ptr &context, const std::shared_ptr &uri) +{ + APP_LOGI("DataAbilityHelper::Creator with context uri called."); + return DataAbilityHelper::Creator(context, uri, false); +} + +/** + * @brief You can use this method to specify the Uri of the data to operate and set the binding relationship + * between the ability using the Data template (Data ability for short) and the associated client process in + * a DataAbilityHelper instance. + * + * @param context Indicates the Context object on OHOS. + * @param uri Indicates the database table or disk file to operate. + * @param tryBind Specifies whether the exit of the corresponding Data ability process causes the exit of the + * client process. + * + * @return Returns the created DataAbilityHelper instance. + */ +std::shared_ptr DataAbilityHelper::Creator( + const std::shared_ptr &context, const std::shared_ptr &uri, const bool tryBind) +{ + APP_LOGI("DataAbilityHelper::Creator with context uri tryBind called start."); + if (context == nullptr) { + APP_LOGE("DataAbilityHelper::Creator (context, uri, tryBind) failed, context == nullptr"); + return nullptr; + } + + if (uri == nullptr) { + APP_LOGE("DataAbilityHelper::Creator (context, uri, tryBind) failed, uri == nullptr"); + return nullptr; + } + + if (uri->GetScheme() != SchemeOhos) { + APP_LOGE("DataAbilityHelper::Creator (context, uri, tryBind) failed, the Scheme is not dataability, Scheme: " + "%{public}s", + uri->GetScheme().c_str()); + return nullptr; + } + + APP_LOGI("DataAbilityHelper::Creator before AcquireDataAbility."); + sptr dataAbilityProxy = + AbilityManagerClient::GetInstance()->AcquireDataAbility(*uri.get(), tryBind, context->GetToken()); + if (dataAbilityProxy == nullptr) { + APP_LOGE("DataAbilityHelper::Creator failed get dataAbilityProxy"); + return nullptr; + } + APP_LOGI("DataAbilityHelper::Creator after AcquireDataAbility."); + + DataAbilityHelper *ptrDataAbilityHelper = + new (std::nothrow) DataAbilityHelper(context, uri, dataAbilityProxy, tryBind); + if (ptrDataAbilityHelper == nullptr) { + APP_LOGE("DataAbilityHelper::Creator (context, uri, tryBind) failed, create DataAbilityHelper failed"); + return nullptr; + } + + APP_LOGI("DataAbilityHelper::Creator with context uri tryBind called end."); + return std::shared_ptr(ptrDataAbilityHelper); +} + +/** + * @brief Creates a DataAbilityHelper instance without specifying the Uri based. + * + * @param token Indicates the System token. + * + * @return Returns the created DataAbilityHelper instance where Uri is not specified. + */ +std::shared_ptr DataAbilityHelper::Creator(const sptr &token) +{ + APP_LOGI("DataAbilityHelper::Creator with token start."); + if (token == nullptr) { + APP_LOGE("DataAbilityHelper::Creator (token) failed, token == nullptr"); + return nullptr; + } + + DataAbilityHelper *ptrDataAbilityHelper = new (std::nothrow) DataAbilityHelper(token); + if (ptrDataAbilityHelper == nullptr) { + APP_LOGE("DataAbilityHelper::Creator (token) failed, create DataAbilityHelper failed"); + return nullptr; + } + + APP_LOGI("DataAbilityHelper::Creator with token end."); + return std::shared_ptr(ptrDataAbilityHelper); +} + +/** + * @brief You can use this method to specify the Uri of the data to operate and set the binding relationship + * between the ability using the Data template (Data ability for short) and the associated client process in + * a DataAbilityHelper instance. + * + * @param token Indicates the System token. + * @param uri Indicates the database table or disk file to operate. + * + * @return Returns the created DataAbilityHelper instance. + */ +std::shared_ptr DataAbilityHelper::Creator( + const sptr &token, const std::shared_ptr &uri) +{ + APP_LOGI("DataAbilityHelper::Creator with token uri called start."); + if (token == nullptr) { + APP_LOGE("DataAbilityHelper::Creator (token, uri) failed, token == nullptr"); + return nullptr; + } + + if (uri == nullptr) { + APP_LOGE("DataAbilityHelper::Creator (token, uri) failed, uri == nullptr"); + return nullptr; + } + + if (uri->GetScheme() != SchemeOhos) { + APP_LOGE("DataAbilityHelper::Creator (token, uri) failed, the Scheme is not dataability, Scheme: " + "%{public}s", + uri->GetScheme().c_str()); + return nullptr; + } + + APP_LOGI("DataAbilityHelper::Creator before AcquireDataAbility."); + sptr dataAbilityProxy = + AbilityManagerClient::GetInstance()->AcquireDataAbility(*uri.get(), false, token); + if (dataAbilityProxy == nullptr) { + APP_LOGE("DataAbilityHelper::Creator failed get dataAbilityProxy"); + return nullptr; + } + APP_LOGI("DataAbilityHelper::Creator after AcquireDataAbility."); + + DataAbilityHelper *ptrDataAbilityHelper = new (std::nothrow) DataAbilityHelper(token, uri, dataAbilityProxy); + if (ptrDataAbilityHelper == nullptr) { + APP_LOGE("DataAbilityHelper::Creator (token, uri) failed, create DataAbilityHelper failed"); + return nullptr; + } + + APP_LOGI("DataAbilityHelper::Creator with token uri called end."); + return std::shared_ptr(ptrDataAbilityHelper); +} + +/** + * @brief Releases the client resource of the Data ability. + * You should call this method to releases client resource after the data operations are complete. + * + * @return Returns true if the resource is successfully released; returns false otherwise. + */ +bool DataAbilityHelper::Release() +{ + APP_LOGI("DataAbilityHelper::Release start."); + std::lock_guard guard(lock_); + if (uri_ == nullptr) { + APP_LOGE("DataAbilityHelper::Release failed, uri_ is nullptr"); + return false; + } + + APP_LOGI("DataAbilityHelper::Release before ReleaseDataAbility."); + int err = AbilityManagerClient::GetInstance()->ReleaseDataAbility(dataAbilityProxy_, token_); + if (err != ERR_OK) { + APP_LOGE("DataAbilityHelper::GetFileTypes failed to ReleaseDataAbility err = %{public}d", err); + return false; + } + APP_LOGI("DataAbilityHelper::Release after ReleaseDataAbility."); + dataAbilityProxy_ = nullptr; + uri_.reset(); + APP_LOGI("DataAbilityHelper::Release end."); + return true; +} + +/** + * @brief Obtains the MIME types of files supported. + * + * @param uri Indicates the path of the files to obtain. + * @param mimeTypeFilter Indicates the MIME types of the files to obtain. This parameter cannot be null. + * + * @return Returns the matched MIME types. If there is no match, null is returned. + */ +std::vector DataAbilityHelper::GetFileTypes(Uri &uri, const std::string &mimeTypeFilter) +{ + APP_LOGI("DataAbilityHelper::GetFileTypes start."); + std::lock_guard guard(lock_); + std::vector matchedMIMEs; + if (!CheckUriParam(uri)) { + APP_LOGE("%{public}s called. CheckUriParam uri failed", __func__); + return matchedMIMEs; + } + + if (uri_ == nullptr) { + APP_LOGI("DataAbilityHelper::GetFileTypes before AcquireDataAbility."); + dataAbilityProxy_ = AbilityManagerClient::GetInstance()->AcquireDataAbility(uri, tryBind_, token_); + APP_LOGI("DataAbilityHelper::GetFileTypes after AcquireDataAbility."); + if (dataAbilityProxy_ == nullptr) { + APP_LOGE("DataAbilityHelper::GetFileTypes failed dataAbility == nullptr"); + return matchedMIMEs; + } + if (isSystemCaller_) { + AddDataAbilityDeathRecipient(dataAbilityProxy_->AsObject()); + } + } + + APP_LOGI("DataAbilityHelper::GetFileTypes before dataAbilityProxy_->GetFileTypes."); + matchedMIMEs = dataAbilityProxy_->GetFileTypes(uri, mimeTypeFilter); + APP_LOGI("DataAbilityHelper::GetFileTypes after dataAbilityProxy_->GetFileTypes."); + if (uri_ == nullptr) { + APP_LOGI("DataAbilityHelper::GetFileTypes before ReleaseDataAbility."); + int err = AbilityManagerClient::GetInstance()->ReleaseDataAbility(dataAbilityProxy_, token_); + APP_LOGI("DataAbilityHelper::GetFileTypes after ReleaseDataAbility."); + if (err != ERR_OK) { + APP_LOGE("DataAbilityHelper::GetFileTypes failed to ReleaseDataAbility err = %{public}d", err); + } + dataAbilityProxy_ = nullptr; + } + + APP_LOGI("DataAbilityHelper::GetFileTypes end."); + return matchedMIMEs; +} + +/** + * @brief Opens a file in a specified remote path. + * + * @param uri Indicates the path of the file to open. + * @param mode Indicates the file open mode, which can be "r" for read-only access, "w" for write-only access + * (erasing whatever data is currently in the file), "wt" for write access that truncates any existing file, + * "wa" for write-only access to append to any existing data, "rw" for read and write access on any existing data, + * or "rwt" for read and write access that truncates any existing file. + * + * @return Returns the file descriptor. + */ +int DataAbilityHelper::OpenFile(Uri &uri, const std::string &mode) +{ + APP_LOGI("DataAbilityHelper::OpenFile start."); + std::lock_guard guard(lock_); + int fd = -1; + if (!CheckUriParam(uri)) { + APP_LOGE("%{public}s called. CheckUriParam uri failed", __func__); + return fd; + } + + if (uri_ == nullptr) { + APP_LOGI("DataAbilityHelper::OpenFile before AcquireDataAbility."); + dataAbilityProxy_ = AbilityManagerClient::GetInstance()->AcquireDataAbility(uri, tryBind_, token_); + APP_LOGI("DataAbilityHelper::OpenFile after AcquireDataAbility."); + if (dataAbilityProxy_ == nullptr) { + APP_LOGE("DataAbilityHelper::OpenFile failed dataAbility == nullptr"); + return fd; + } + if (isSystemCaller_) { + AddDataAbilityDeathRecipient(dataAbilityProxy_->AsObject()); + } + } + + APP_LOGI("DataAbilityHelper::OpenFile before dataAbilityProxy_->OpenFile."); + fd = dataAbilityProxy_->OpenFile(uri, mode); + APP_LOGI("DataAbilityHelper::OpenFile after dataAbilityProxy_->OpenFile."); + if (uri_ == nullptr) { + APP_LOGI("DataAbilityHelper::OpenFile before ReleaseDataAbility."); + int err = AbilityManagerClient::GetInstance()->ReleaseDataAbility(dataAbilityProxy_, token_); + APP_LOGI("DataAbilityHelper::OpenFile after ReleaseDataAbility."); + if (err != ERR_OK) { + APP_LOGE("DataAbilityHelper::OpenFile failed to ReleaseDataAbility err = %{public}d", err); + } + dataAbilityProxy_ = nullptr; + } + APP_LOGI("DataAbilityHelper::OpenFile end."); + return fd; +} + +/** + * @brief This is like openFile, open a file that need to be able to return sub-sections of files,often assets + * inside of their .hap. + * + * @param uri Indicates the path of the file to open. + * @param mode Indicates the file open mode, which can be "r" for read-only access, "w" for write-only access + * (erasing whatever data is currently in the file), "wt" for write access that truncates any existing file, + * "wa" for write-only access to append to any existing data, "rw" for read and write access on any existing + * data, or "rwt" for read and write access that truncates any existing file. + * + * @return Returns the RawFileDescriptor object containing file descriptor. + */ +int DataAbilityHelper::OpenRawFile(Uri &uri, const std::string &mode) +{ + APP_LOGI("DataAbilityHelper::OpenRawFile start."); + std::lock_guard guard(lock_); + int fd = -1; + if (!CheckUriParam(uri)) { + APP_LOGE("%{public}s called. CheckUriParam uri failed", __func__); + return fd; + } + + if (uri_ == nullptr) { + APP_LOGI("DataAbilityHelper::OpenRawFile before AcquireDataAbility."); + dataAbilityProxy_ = AbilityManagerClient::GetInstance()->AcquireDataAbility(uri, tryBind_, token_); + APP_LOGI("DataAbilityHelper::OpenRawFile after AcquireDataAbility."); + if (dataAbilityProxy_ == nullptr) { + APP_LOGE("DataAbilityHelper::OpenRawFile failed dataAbility == nullptr"); + return fd; + } + if (isSystemCaller_) { + AddDataAbilityDeathRecipient(dataAbilityProxy_->AsObject()); + } + } + APP_LOGI("DataAbilityHelper::OpenRawFile before dataAbilityProxy_->OpenRawFile."); + fd = dataAbilityProxy_->OpenRawFile(uri, mode); + APP_LOGI("DataAbilityHelper::OpenRawFile after dataAbilityProxy_->OpenRawFile."); + if (uri_ == nullptr) { + APP_LOGI("DataAbilityHelper::OpenRawFile before ReleaseDataAbility."); + int err = AbilityManagerClient::GetInstance()->ReleaseDataAbility(dataAbilityProxy_, token_); + APP_LOGI("DataAbilityHelper::OpenRawFile after ReleaseDataAbility."); + if (err != ERR_OK) { + APP_LOGE("DataAbilityHelper::OpenRawFile failed to ReleaseDataAbility err = %{public}d", err); + } + dataAbilityProxy_ = nullptr; + } + APP_LOGI("DataAbilityHelper::OpenRawFile end."); + return fd; +} + +/** + * @brief Inserts a single data record into the database. + * + * @param uri Indicates the path of the data to operate. + * @param value Indicates the data record to insert. If this parameter is null, a blank row will be inserted. + * + * @return Returns the index of the inserted data record. + */ +int DataAbilityHelper::Insert(Uri &uri, const NativeRdb::ValuesBucket &value) +{ + APP_LOGI("DataAbilityHelper::Insert start."); + std::lock_guard guard(lock_); + int index = -1; + if (!CheckUriParam(uri)) { + APP_LOGE("%{public}s called. CheckUriParam uri failed", __func__); + return index; + } + + if (uri_ == nullptr) { + APP_LOGI("DataAbilityHelper::Insert before AcquireDataAbility."); + dataAbilityProxy_ = AbilityManagerClient::GetInstance()->AcquireDataAbility(uri, tryBind_, token_); + APP_LOGI("DataAbilityHelper::Insert after AcquireDataAbility."); + if (dataAbilityProxy_ == nullptr) { + APP_LOGE("DataAbilityHelper::Insert failed dataAbility == nullptr"); + return index; + } + if (isSystemCaller_) { + AddDataAbilityDeathRecipient(dataAbilityProxy_->AsObject()); + } + } + APP_LOGI("DataAbilityHelper::Insert before dataAbilityProxy_->Insert."); + index = dataAbilityProxy_->Insert(uri, value); + APP_LOGI("DataAbilityHelper::Insert after dataAbilityProxy_->Insert."); + if (uri_ == nullptr) { + APP_LOGI("DataAbilityHelper::Insert before ReleaseDataAbility."); + int err = AbilityManagerClient::GetInstance()->ReleaseDataAbility(dataAbilityProxy_, token_); + APP_LOGI("DataAbilityHelper::Insert after ReleaseDataAbility."); + if (err != ERR_OK) { + APP_LOGE("DataAbilityHelper::Insert failed to ReleaseDataAbility err = %{public}d", err); + } + dataAbilityProxy_ = nullptr; + } + APP_LOGI("DataAbilityHelper::Insert end."); + return index; +} + +/** + * @brief Updates data records in the database. + * + * @param uri Indicates the path of data to update. + * @param value Indicates the data to update. This parameter can be null. + * @param predicates Indicates filter criteria. You should define the processing logic when this parameter is null. + * + * @return Returns the number of data records updated. + */ +int DataAbilityHelper::Update( + Uri &uri, const NativeRdb::ValuesBucket &value, const NativeRdb::DataAbilityPredicates &predicates) +{ + APP_LOGI("DataAbilityHelper::Update start."); + std::lock_guard guard(lock_); + int index = -1; + if (!CheckUriParam(uri)) { + APP_LOGE("%{public}s called. CheckUriParam uri failed", __func__); + return index; + } + + if (uri_ == nullptr) { + APP_LOGI("DataAbilityHelper::Update before AcquireDataAbility."); + dataAbilityProxy_ = AbilityManagerClient::GetInstance()->AcquireDataAbility(uri, tryBind_, token_); + APP_LOGI("DataAbilityHelper::Update after AcquireDataAbility."); + if (dataAbilityProxy_ == nullptr) { + APP_LOGE("DataAbilityHelper::Update failed dataAbility == nullptr"); + return index; + } + if (isSystemCaller_) { + AddDataAbilityDeathRecipient(dataAbilityProxy_->AsObject()); + } + } + APP_LOGI("DataAbilityHelper::Update before dataAbilityProxy_->Update."); + index = dataAbilityProxy_->Update(uri, value, predicates); + APP_LOGI("DataAbilityHelper::Update after dataAbilityProxy_->Update."); + if (uri_ == nullptr) { + APP_LOGI("DataAbilityHelper::Update before ReleaseDataAbility."); + int err = AbilityManagerClient::GetInstance()->ReleaseDataAbility(dataAbilityProxy_, token_); + APP_LOGI("DataAbilityHelper::Update after ReleaseDataAbility."); + if (err != ERR_OK) { + APP_LOGE("DataAbilityHelper::Update failed to ReleaseDataAbility err = %{public}d", err); + } + dataAbilityProxy_ = nullptr; + } + APP_LOGI("DataAbilityHelper::Update end."); + return index; +} + +/** + * @brief Deletes one or more data records from the database. + * + * @param uri Indicates the path of the data to operate. + * @param predicates Indicates filter criteria. You should define the processing logic when this parameter is null. + * + * @return Returns the number of data records deleted. + */ +int DataAbilityHelper::Delete(Uri &uri, const NativeRdb::DataAbilityPredicates &predicates) +{ + APP_LOGI("DataAbilityHelper::Delete start."); + std::lock_guard guard(lock_); + int index = -1; + if (!CheckUriParam(uri)) { + APP_LOGE("%{public}s called. CheckUriParam uri failed", __func__); + return index; + } + + if (uri_ == nullptr) { + APP_LOGI("DataAbilityHelper::Delete before AcquireDataAbility."); + dataAbilityProxy_ = AbilityManagerClient::GetInstance()->AcquireDataAbility(uri, tryBind_, token_); + APP_LOGI("DataAbilityHelper::Delete after AcquireDataAbility."); + if (dataAbilityProxy_ == nullptr) { + APP_LOGE("DataAbilityHelper::Delete failed dataAbility == nullptr"); + return index; + } + if (isSystemCaller_) { + AddDataAbilityDeathRecipient(dataAbilityProxy_->AsObject()); + } + } + APP_LOGI("DataAbilityHelper::Delete before dataAbilityProxy_->Delete."); + index = dataAbilityProxy_->Delete(uri, predicates); + APP_LOGI("DataAbilityHelper::Delete after dataAbilityProxy_->Delete."); + if (uri_ == nullptr) { + APP_LOGI("DataAbilityHelper::Delete before ReleaseDataAbility."); + int err = AbilityManagerClient::GetInstance()->ReleaseDataAbility(dataAbilityProxy_, token_); + APP_LOGI("DataAbilityHelper::Delete after ReleaseDataAbility."); + if (err != ERR_OK) { + APP_LOGE("DataAbilityHelper::Delete failed to ReleaseDataAbility err = %{public}d", err); + } + dataAbilityProxy_ = nullptr; + } + APP_LOGI("DataAbilityHelper::Delete end."); + return index; +} + +/** + * @brief Deletes one or more data records from the database. + * + * @param uri Indicates the path of data to query. + * @param columns Indicates the columns to query. If this parameter is null, all columns are queried. + * @param predicates Indicates filter criteria. You should define the processing logic when this parameter is null. + * + * @return Returns the query result. + */ +std::shared_ptr DataAbilityHelper::Query( + Uri &uri, std::vector &columns, const NativeRdb::DataAbilityPredicates &predicates) +{ + APP_LOGI("DataAbilityHelper::Query start."); + std::lock_guard guard(lock_); + std::shared_ptr resultset = nullptr; + + if (!CheckUriParam(uri)) { + APP_LOGE("%{public}s called. CheckUriParam uri failed", __func__); + return resultset; + } + + if (uri_ == nullptr) { + APP_LOGI("DataAbilityHelper::Query before AcquireDataAbility."); + dataAbilityProxy_ = AbilityManagerClient::GetInstance()->AcquireDataAbility(uri, tryBind_, token_); + APP_LOGI("DataAbilityHelper::Query after AcquireDataAbility."); + if (dataAbilityProxy_ == nullptr) { + APP_LOGE("DataAbilityHelper::Query failed dataAbility == nullptr"); + return resultset; + } + if (isSystemCaller_) { + AddDataAbilityDeathRecipient(dataAbilityProxy_->AsObject()); + } + } + APP_LOGI("DataAbilityHelper::Query before dataAbilityProxy_->Query."); + resultset = dataAbilityProxy_->Query(uri, columns, predicates); + APP_LOGI("DataAbilityHelper::Query after dataAbilityProxy_->Query."); + if (uri_ == nullptr) { + APP_LOGI("DataAbilityHelper::Query before ReleaseDataAbility."); + int err = AbilityManagerClient::GetInstance()->ReleaseDataAbility(dataAbilityProxy_, token_); + APP_LOGI("DataAbilityHelper::Query after ReleaseDataAbility."); + if (err != ERR_OK) { + APP_LOGE("DataAbilityHelper::Query failed to ReleaseDataAbility err = %{public}d", err); + } + dataAbilityProxy_ = nullptr; + } + APP_LOGI("DataAbilityHelper::Query end."); + return resultset; +} + +/** + * @brief Obtains the MIME type matching the data specified by the URI of the Data ability. This method should be + * implemented by a Data ability. Data abilities supports general data types, including text, HTML, and JPEG. + * + * @param uri Indicates the URI of the data. + * + * @return Returns the MIME type that matches the data specified by uri. + */ +std::string DataAbilityHelper::GetType(Uri &uri) +{ + APP_LOGI("DataAbilityHelper::GetType start."); + std::lock_guard guard(lock_); + std::string type; + if (!CheckUriParam(uri)) { + APP_LOGE("%{public}s called. CheckUriParam uri failed", __func__); + return type; + } + + if (uri_ == nullptr) { + APP_LOGI("DataAbilityHelper::GetType before AcquireDataAbility."); + dataAbilityProxy_ = AbilityManagerClient::GetInstance()->AcquireDataAbility(uri, tryBind_, token_); + APP_LOGI("DataAbilityHelper::GetType after AcquireDataAbility."); + if (dataAbilityProxy_ == nullptr) { + APP_LOGE("DataAbilityHelper::GetType failed dataAbility == nullptr"); + return type; + } + if (isSystemCaller_) { + AddDataAbilityDeathRecipient(dataAbilityProxy_->AsObject()); + } + } + APP_LOGI("DataAbilityHelper::GetType before dataAbilityProxy_->GetType."); + type = dataAbilityProxy_->GetType(uri); + APP_LOGI("DataAbilityHelper::GetType after dataAbilityProxy_->GetType."); + if (uri_ == nullptr) { + APP_LOGI("DataAbilityHelper::GetType before ReleaseDataAbility."); + int err = AbilityManagerClient::GetInstance()->ReleaseDataAbility(dataAbilityProxy_, token_); + APP_LOGI("DataAbilityHelper::GetType after ReleaseDataAbility."); + if (err != ERR_OK) { + APP_LOGE("DataAbilityHelper::GetType failed to ReleaseDataAbility err = %{public}d", err); + } + dataAbilityProxy_ = nullptr; + } + APP_LOGI("DataAbilityHelper::GetType end."); + return type; +} + +/** + * @brief Reloads data in the database. + * + * @param uri Indicates the position where the data is to reload. This parameter is mandatory. + * @param extras Indicates the PacMap object containing the additional parameters to be passed in this call. This + * parameter can be null. If a custom Sequenceable object is put in the PacMap object and will be transferred across + * processes, you must call BasePacMap.setClassLoader(ClassLoader) to set a class loader for the custom object. + * + * @return Returns true if the data is successfully reloaded; returns false otherwise. + */ +bool DataAbilityHelper::Reload(Uri &uri, const PacMap &extras) +{ + APP_LOGI("DataAbilityHelper::Reload start."); + std::lock_guard guard(lock_); + bool ret = false; + if (!CheckUriParam(uri)) { + APP_LOGE("%{public}s called. CheckUriParam uri failed", __func__); + return ret; + } + + if (uri_ == nullptr) { + APP_LOGI("DataAbilityHelper::Reload before AcquireDataAbility."); + dataAbilityProxy_ = AbilityManagerClient::GetInstance()->AcquireDataAbility(uri, tryBind_, token_); + APP_LOGI("DataAbilityHelper::Reload after AcquireDataAbility."); + if (dataAbilityProxy_ == nullptr) { + APP_LOGE("DataAbilityHelper::Reload failed dataAbility == nullptr"); + return ret; + } + if (isSystemCaller_) { + AddDataAbilityDeathRecipient(dataAbilityProxy_->AsObject()); + } + } + APP_LOGI("DataAbilityHelper::Reload before dataAbilityProxy_->Reload."); + ret = dataAbilityProxy_->Reload(uri, extras); + APP_LOGI("DataAbilityHelper::Reload after dataAbilityProxy_->Reload."); + if (uri_ == nullptr) { + APP_LOGI("DataAbilityHelper::Reload before ReleaseDataAbility."); + int err = AbilityManagerClient::GetInstance()->ReleaseDataAbility(dataAbilityProxy_, token_); + APP_LOGI("DataAbilityHelper::Reload after ReleaseDataAbility."); + if (err != ERR_OK) { + APP_LOGE("DataAbilityHelper::Reload failed to ReleaseDataAbility err = %{public}d", err); + } + dataAbilityProxy_ = nullptr; + } + APP_LOGI("DataAbilityHelper::Reload end."); + return ret; +} + +/** + * @brief Inserts multiple data records into the database. + * + * @param uri Indicates the path of the data to operate. + * @param values Indicates the data records to insert. + * + * @return Returns the number of data records inserted. + */ +int DataAbilityHelper::BatchInsert(Uri &uri, const std::vector &values) +{ + APP_LOGI("DataAbilityHelper::BatchInsert start."); + std::lock_guard guard(lock_); + int ret = -1; + if (!CheckUriParam(uri)) { + APP_LOGE("%{public}s called. CheckUriParam uri failed", __func__); + return ret; + } + + if (uri_ == nullptr) { + APP_LOGI("DataAbilityHelper::BatchInsert before AcquireDataAbility."); + dataAbilityProxy_ = AbilityManagerClient::GetInstance()->AcquireDataAbility(uri, tryBind_, token_); + APP_LOGI("DataAbilityHelper::BatchInsert after AcquireDataAbility."); + if (dataAbilityProxy_ == nullptr) { + APP_LOGE("DataAbilityHelper::BatchInsert failed dataAbility == nullptr"); + return ret; + } + if (isSystemCaller_) { + AddDataAbilityDeathRecipient(dataAbilityProxy_->AsObject()); + } + } + APP_LOGI("DataAbilityHelper::BatchInsert before dataAbilityProxy_->BatchInsert."); + ret = dataAbilityProxy_->BatchInsert(uri, values); + APP_LOGI("DataAbilityHelper::BatchInsert after dataAbilityProxy_->BatchInsert."); + if (uri_ == nullptr) { + APP_LOGI("DataAbilityHelper::BatchInsert before ReleaseDataAbility."); + int err = AbilityManagerClient::GetInstance()->ReleaseDataAbility(dataAbilityProxy_, token_); + APP_LOGI("DataAbilityHelper::BatchInsert after ReleaseDataAbility."); + if (err != ERR_OK) { + APP_LOGE("DataAbilityHelper::BatchInsert failed to ReleaseDataAbility err = %{public}d", err); + } + dataAbilityProxy_ = nullptr; + } + APP_LOGI("DataAbilityHelper::BatchInsert end."); + return ret; +} + +bool DataAbilityHelper::CheckUriParam(const Uri &uri) +{ + APP_LOGI("DataAbilityHelper::CheckUriParam start."); + Uri checkUri(uri.ToString()); + if (!CheckOhosUri(checkUri)) { + APP_LOGE("DataAbilityHelper::CheckUriParam failed. CheckOhosUri uri failed"); + return false; + } + + if (uri_ != nullptr) { + if (!CheckOhosUri(*uri_)) { + APP_LOGE("DataAbilityHelper::CheckUriParam failed. CheckOhosUri uri_ failed"); + return false; + } + + std::vector checkSegments; + checkUri.GetPathSegments(checkSegments); + + std::vector segments; + uri_->GetPathSegments(segments); + + if (checkSegments[0] != segments[0]) { + APP_LOGE("DataAbilityHelper::CheckUriParam failed. the dataability in uri doesn't equal the one in uri_."); + return false; + } + } + APP_LOGI("DataAbilityHelper::CheckUriParam end."); + return true; +} + +bool DataAbilityHelper::CheckOhosUri(const Uri &uri) +{ + APP_LOGI("DataAbilityHelper::CheckOhosUri start."); + Uri checkUri(uri.ToString()); + if (checkUri.GetScheme() != SchemeOhos) { + APP_LOGE("DataAbilityHelper::CheckOhosUri failed. uri is not a dataability one."); + return false; + } + + std::vector segments; + checkUri.GetPathSegments(segments); + if (segments.empty()) { + APP_LOGE("DataAbilityHelper::CheckOhosUri failed. There is no segments in the uri."); + return false; + } + + if (checkUri.GetPath() == "") { + APP_LOGE("DataAbilityHelper::CheckOhosUri failed. The path in the uri is empty."); + return false; + } + APP_LOGI("DataAbilityHelper::CheckOhosUri end."); + return true; +} + +/** + * @brief Registers an observer to DataObsMgr specified by the given Uri. + * + * @param uri, Indicates the path of the data to operate. + * @param dataObserver, Indicates the IDataAbilityObserver object. + */ +void DataAbilityHelper::RegisterObserver(const Uri &uri, const sptr &dataObserver) +{ + if (!CheckUriParam(uri)) { + APP_LOGE("%{public}s called. CheckUriParam uri failed", __func__); + return; + } + + if (dataObserver == nullptr) { + APP_LOGE("%{public}s called. dataObserver is nullptr", __func__); + return; + } + + Uri tmpUri(uri.ToString()); + + std::lock_guard lock_l(oplock_); + sptr dataAbilityProxy = nullptr; + if (uri_ == nullptr) { + auto dataability = registerMap_.find(dataObserver); + if (dataability == registerMap_.end()) { + dataAbilityProxy = AbilityManagerClient::GetInstance()->AcquireDataAbility(uri, tryBind_, token_); + registerMap_.emplace(dataObserver, dataAbilityProxy); + uriMap_.emplace(dataObserver, tmpUri.GetPath()); + } else { + auto path = uriMap_.find(dataObserver); + if (path->second != tmpUri.GetPath()) { + APP_LOGE("DataAbilityHelper::RegisterObserver failed input uri's path is not equal the one the " + "observer used"); + return; + } + dataAbilityProxy = dataability->second; + } + } else { + dataAbilityProxy = dataAbilityProxy_; + } + + if (dataAbilityProxy == nullptr) { + APP_LOGE("DataAbilityHelper::RegisterObserver failed dataAbility == nullptr"); + registerMap_.erase(dataObserver); + uriMap_.erase(dataObserver); + return; + } + dataAbilityProxy->ScheduleRegisterObserver(uri, dataObserver); +} + +/** + * @brief Deregisters an observer used for DataObsMgr specified by the given Uri. + * + * @param uri, Indicates the path of the data to operate. + * @param dataObserver, Indicates the IDataAbilityObserver object. + */ +void DataAbilityHelper::UnregisterObserver(const Uri &uri, const sptr &dataObserver) +{ + if (!CheckUriParam(uri)) { + APP_LOGE("%{public}s called. CheckUriParam uri failed", __func__); + return; + } + + if (dataObserver == nullptr) { + APP_LOGE("%{public}s called. dataObserver is nullptr", __func__); + return; + } + + Uri tmpUri(uri.ToString()); + std::lock_guard lock_l(oplock_); + sptr dataAbilityProxy = nullptr; + if (uri_ == nullptr) { + auto dataability = registerMap_.find(dataObserver); + if (dataability == registerMap_.end()) { + return; + } + auto path = uriMap_.find(dataObserver); + if (path->second != tmpUri.GetPath()) { + APP_LOGE("DataAbilityHelper::UnregisterObserver failed input uri's path is not equal the one the " + "observer used"); + return; + } + dataAbilityProxy = dataability->second; + } else { + dataAbilityProxy = dataAbilityProxy_; + } + + if (dataAbilityProxy == nullptr) { + APP_LOGE("DataAbilityHelper::RegisterObserver failed dataAbility == nullptr"); + return; + } + + dataAbilityProxy->ScheduleUnregisterObserver(uri, dataObserver); + int err = AbilityManagerClient::GetInstance()->ReleaseDataAbility(dataAbilityProxy, token_); + if (err != ERR_OK) { + APP_LOGE("DataAbilityHelper::RegisterObserver failed to ReleaseDataAbility err = %{public}d", err); + } + registerMap_.erase(dataObserver); + uriMap_.erase(dataObserver); +} + +/** + * @brief Notifies the registered observers of a change to the data resource specified by Uri. + * + * @param uri, Indicates the path of the data to operate. + */ +void DataAbilityHelper::NotifyChange(const Uri &uri) +{ + if (!CheckUriParam(uri)) { + APP_LOGE("%{public}s called. CheckUriParam uri failed", __func__); + return; + } + + if (dataAbilityProxy_ == nullptr) { + dataAbilityProxy_ = AbilityManagerClient::GetInstance()->AcquireDataAbility(uri, tryBind_, token_); + if (dataAbilityProxy_ == nullptr) { + APP_LOGE("DataAbilityHelper::NotifyChange failed dataAbility == nullptr"); + return; + } + } + + dataAbilityProxy_->ScheduleNotifyChange(uri); + + if (uri_ == nullptr) { + int err = AbilityManagerClient::GetInstance()->ReleaseDataAbility(dataAbilityProxy_, token_); + if (err != ERR_OK) { + APP_LOGE("DataAbilityHelper::NotifyChange failed to ReleaseDataAbility err = %{public}d", err); + } + dataAbilityProxy_ = nullptr; + } +} + +/** + * @brief Converts the given uri that refer to the Data ability into a normalized URI. A normalized URI can be used + * across devices, persisted, backed up, and restored. It can refer to the same item in the Data ability even if the + * context has changed. If you implement URI normalization for a Data ability, you must also implement + * denormalizeUri(ohos.utils.net.Uri) to enable URI denormalization. After this feature is enabled, URIs passed to any + * method that is called on the Data ability must require normalization verification and denormalization. The default + * implementation of this method returns null, indicating that this Data ability does not support URI normalization. + * + * @param uri Indicates the Uri object to normalize. + * + * @return Returns the normalized Uri object if the Data ability supports URI normalization; returns null otherwise. + */ +Uri DataAbilityHelper::NormalizeUri(Uri &uri) +{ + APP_LOGI("DataAbilityHelper::NormalizeUri start."); + std::lock_guard guard(lock_); + Uri urivalue(""); + if (!CheckUriParam(uri)) { + APP_LOGE("%{public}s called. CheckUriParam uri failed", __func__); + return urivalue; + } + + if (uri_ == nullptr) { + APP_LOGI("DataAbilityHelper::NormalizeUri before AcquireDataAbility."); + dataAbilityProxy_ = AbilityManagerClient::GetInstance()->AcquireDataAbility(uri, tryBind_, token_); + APP_LOGI("DataAbilityHelper::NormalizeUri after AcquireDataAbility."); + if (dataAbilityProxy_ == nullptr) { + APP_LOGE("DataAbilityHelper::NormalizeUri failed dataAbility == nullptr"); + return urivalue; + } + if (isSystemCaller_) { + AddDataAbilityDeathRecipient(dataAbilityProxy_->AsObject()); + } + } + APP_LOGI("DataAbilityHelper::NormalizeUri before dataAbilityProxy_->NormalizeUri."); + urivalue = dataAbilityProxy_->NormalizeUri(uri); + APP_LOGI("DataAbilityHelper::NormalizeUri after dataAbilityProxy_->NormalizeUri."); + if (uri_ == nullptr) { + APP_LOGI("DataAbilityHelper::NormalizeUri before ReleaseDataAbility."); + int err = AbilityManagerClient::GetInstance()->ReleaseDataAbility(dataAbilityProxy_, token_); + APP_LOGI("DataAbilityHelper::NormalizeUri after ReleaseDataAbility."); + if (err != ERR_OK) { + APP_LOGE("DataAbilityHelper::NormalizeUri failed to ReleaseDataAbility err = %{public}d", err); + } + dataAbilityProxy_ = nullptr; + } + APP_LOGI("DataAbilityHelper::NormalizeUri end."); + return urivalue; +} + +/** + * @brief Converts the given normalized uri generated by normalizeUri(ohos.utils.net.Uri) into a denormalized one. + * The default implementation of this method returns the original URI passed to it. + * + * @param uri uri Indicates the Uri object to denormalize. + * + * @return Returns the denormalized Uri object if the denormalization is successful; returns the original Uri passed to + * this method if there is nothing to do; returns null if the data identified by the original Uri cannot be found in the + * current environment. + */ +Uri DataAbilityHelper::DenormalizeUri(Uri &uri) +{ + APP_LOGI("DataAbilityHelper::DenormalizeUri start."); + std::lock_guard guard(lock_); + Uri urivalue(""); + if (!CheckUriParam(uri)) { + APP_LOGE("%{public}s called. CheckUriParam uri failed", __func__); + return urivalue; + } + + if (uri_ == nullptr) { + APP_LOGI("DataAbilityHelper::DenormalizeUri before AcquireDataAbility."); + dataAbilityProxy_ = AbilityManagerClient::GetInstance()->AcquireDataAbility(uri, tryBind_, token_); + APP_LOGI("DataAbilityHelper::DenormalizeUri after AcquireDataAbility."); + if (dataAbilityProxy_ == nullptr) { + APP_LOGE("DataAbilityHelper::DenormalizeUri failed dataAbility == nullptr"); + return urivalue; + } + if (isSystemCaller_) { + AddDataAbilityDeathRecipient(dataAbilityProxy_->AsObject()); + } + } + APP_LOGI("DataAbilityHelper::DenormalizeUri before dataAbilityProxy_->DenormalizeUri."); + urivalue = dataAbilityProxy_->DenormalizeUri(uri); + APP_LOGI("DataAbilityHelper::DenormalizeUri after dataAbilityProxy_->DenormalizeUri."); + if (uri_ == nullptr) { + APP_LOGI("DataAbilityHelper::DenormalizeUri before ReleaseDataAbility."); + int err = AbilityManagerClient::GetInstance()->ReleaseDataAbility(dataAbilityProxy_, token_); + APP_LOGI("DataAbilityHelper::DenormalizeUri after ReleaseDataAbility."); + if (err != ERR_OK) { + APP_LOGE("DataAbilityHelper::DenormalizeUri failed to ReleaseDataAbility err = %{public}d", err); + } + dataAbilityProxy_ = nullptr; + } + APP_LOGI("DataAbilityHelper::DenormalizeUri end."); + return urivalue; +} + +void DataAbilityDeathRecipient::OnRemoteDied(const wptr &remote) +{ + APP_LOGI("recv DataAbilityDeathRecipient death notice"); + if (handler_) { + handler_(remote); + } + APP_LOGI("DataAbilityHelper::OnRemoteDied end."); +} + +DataAbilityDeathRecipient::DataAbilityDeathRecipient(RemoteDiedHandler handler) : handler_(handler) +{} + +DataAbilityDeathRecipient::~DataAbilityDeathRecipient() +{} +std::vector> DataAbilityHelper::ExecuteBatch( + const Uri &uri, const std::vector> &operations) +{ + APP_LOGI("DataAbilityHelper::ExecuteBatch start"); + std::vector> results; + if (!CheckUriParam(uri)) { + APP_LOGE("DataAbilityHelper::ExecuteBatch. CheckUriParam uri failed"); + return results; + } + if (uri_ == nullptr) { + APP_LOGI("DataAbilityHelper::ExecuteBatch before AcquireDataAbility."); + dataAbilityProxy_ = AbilityManagerClient::GetInstance()->AcquireDataAbility(uri, tryBind_, token_); + APP_LOGI("DataAbilityHelper::ExecuteBatch after AcquireDataAbility."); + if (dataAbilityProxy_ == nullptr) { + APP_LOGE("DataAbilityHelper::ExecuteBatch failed dataAbility == nullptr"); + return results; + } + } + + APP_LOGI("DataAbilityHelper::ExecuteBatch before dataAbilityProxy_->ExecuteBatch."); + results = dataAbilityProxy_->ExecuteBatch(operations); + APP_LOGI("DataAbilityHelper::ExecuteBatch after dataAbilityProxy_->ExecuteBatch."); + if (uri_ == nullptr) { + APP_LOGI("DataAbilityHelper::ExecuteBatch before ReleaseDataAbility."); + int err = AbilityManagerClient::GetInstance()->ReleaseDataAbility(dataAbilityProxy_, token_); + APP_LOGI("DataAbilityHelper::ExecuteBatch after ReleaseDataAbility."); + if (err != ERR_OK) { + APP_LOGE("DataAbilityHelper::ExecuteBatch failed to ReleaseDataAbility err = %{public}d", err); + } + dataAbilityProxy_ = nullptr; + } + APP_LOGI("DataAbilityHelper::ExecuteBatch end"); + return results; +} +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/src/data_ability_impl.cpp b/tools/frameworks/kits/ability/native/src/data_ability_impl.cpp new file mode 100644 index 00000000000..c15ba0827eb --- /dev/null +++ b/tools/frameworks/kits/ability/native/src/data_ability_impl.cpp @@ -0,0 +1,335 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "data_ability_impl.h" +#include "app_log_wrapper.h" +#include "abs_shared_result_set.h" +#include "data_ability_predicates.h" +#include "values_bucket.h" + +namespace OHOS { +namespace AppExecFwk { +using AbilityManagerClient = OHOS::AAFwk::AbilityManagerClient; +/** + * @brief Handling the life cycle switching of PageAbility. + * + * @param want Indicates the structure containing information about the ability. + * @param targetState The life cycle state to switch to. + * + */ +void DataAbilityImpl::HandleAbilityTransaction(const Want &want, const AAFwk::LifeCycleStateInfo &targetState) +{ + APP_LOGI("DataAbilityImpl::sourceState:%{public}d; targetState: %{public}d; isNewWant: %{public}d", + lifecycleState_, + targetState.state, + targetState.isNewWant); + if ((lifecycleState_ == targetState.state) && !targetState.isNewWant) { + APP_LOGE("Org lifeCycleState equals to Dst lifeCycleState."); + return; + } + + switch (targetState.state) { + case AAFwk::ABILITY_STATE_ACTIVE: { + if (lifecycleState_ == AAFwk::ABILITY_STATE_INITIAL) { + SerUriString(targetState.caller.deviceId + "/" + targetState.caller.bundleName + "/" + + targetState.caller.abilityName); + Start(want); + } else { + return; + } + break; + } + default: { + APP_LOGE("DataAbilityImpl::HandleAbilityTransaction state is error"); + return; + break; + } + } + + AbilityManagerClient::GetInstance()->AbilityTransitionDone(token_, targetState.state); +} + +/** + * @brief Obtains the MIME types of files supported. + * + * @param uri Indicates the path of the files to obtain. + * @param mimeTypeFilter Indicates the MIME types of the files to obtain. This parameter cannot be null. + * + * @return Returns the matched MIME types. If there is no match, null is returned. + */ +std::vector DataAbilityImpl::GetFileTypes(const Uri &uri, const std::string &mimeTypeFilter) +{ + std::vector types; + if (ability_ == nullptr) { + APP_LOGE("DataAbilityImpl::GetFileTypes ability_ is nullptr"); + return types; + } + + types = ability_->GetFileTypes(uri, mimeTypeFilter); + return types; +} + +/** + * @brief Opens a file in a specified remote path. + * + * @param uri Indicates the path of the file to open. + * @param mode Indicates the file open mode, which can be "r" for read-only access, "w" for write-only access + * (erasing whatever data is currently in the file), "wt" for write access that truncates any existing file, + * "wa" for write-only access to append to any existing data, "rw" for read and write access on any existing data, + * or "rwt" for read and write access that truncates any existing file. + * + * @return Returns the file descriptor. + */ +int DataAbilityImpl::OpenFile(const Uri &uri, const std::string &mode) +{ + int fd = -1; + if (ability_ == nullptr) { + APP_LOGE("DataAbilityImpl::OpenFile ability_ is nullptr"); + return fd; + } + + fd = ability_->OpenFile(uri, mode); + return fd; +} + +/** + * @brief This is like openFile, open a file that need to be able to return sub-sections of files,often assets + * inside of their .hap. + * + * @param uri Indicates the path of the file to open. + * @param mode Indicates the file open mode, which can be "r" for read-only access, "w" for write-only access + * (erasing whatever data is currently in the file), "wt" for write access that truncates any existing file, + * "wa" for write-only access to append to any existing data, "rw" for read and write access on any existing + * data, or "rwt" for read and write access that truncates any existing file. + * + * @return Returns the RawFileDescriptor object containing file descriptor. + */ +int DataAbilityImpl::OpenRawFile(const Uri &uri, const std::string &mode) +{ + int fd = -1; + if (ability_ == nullptr) { + APP_LOGE("DataAbilityImpl::OpenRawFile ability_ is nullptr"); + return fd; + } + + fd = ability_->OpenRawFile(uri, mode); + return fd; +} + +/** + * @brief Inserts a single data record into the database. + * + * @param uri Indicates the path of the data to operate. + * @param value Indicates the data record to insert. If this parameter is null, a blank row will be inserted. + * + * @return Returns the index of the inserted data record. + */ +int DataAbilityImpl::Insert(const Uri &uri, const NativeRdb::ValuesBucket &value) +{ + int index = -1; + if (ability_ == nullptr) { + APP_LOGE("DataAbilityImpl::Insert ability_ is nullptr"); + return index; + } + + index = ability_->Insert(uri, value); + return index; +} + +/** + * @brief Updates data records in the database. + * + * @param uri Indicates the path of data to update. + * @param value Indicates the data to update. This parameter can be null. + * @param predicates Indicates filter criteria. You should define the processing logic when this parameter is null. + * + * @return Returns the number of data records updated. + */ +int DataAbilityImpl::Update( + const Uri &uri, const NativeRdb::ValuesBucket &value, const NativeRdb::DataAbilityPredicates &predicates) +{ + int index = -1; + if (ability_ == nullptr) { + APP_LOGE("DataAbilityImpl::Update ability_ is nullptr"); + return index; + } + + index = ability_->Update(uri, value, predicates); + return index; +} + +/** + * @brief Deletes one or more data records from the database. + * + * @param uri Indicates the path of the data to operate. + * @param predicates Indicates filter criteria. You should define the processing logic when this parameter is null. + * + * @return Returns the number of data records deleted. + */ +int DataAbilityImpl::Delete(const Uri &uri, const NativeRdb::DataAbilityPredicates &predicates) +{ + int index = -1; + if (ability_ == nullptr) { + APP_LOGE("DataAbilityImpl::Delete ability_ is nullptr"); + return index; + } + + index = ability_->Delete(uri, predicates); + return index; +} + +/** + * @brief Deletes one or more data records from the database. + * + * @param uri Indicates the path of data to query. + * @param columns Indicates the columns to query. If this parameter is null, all columns are queried. + * @param predicates Indicates filter criteria. You should define the processing logic when this parameter is null. + * + * @return Returns the query result. + */ +std::shared_ptr DataAbilityImpl::Query( + const Uri &uri, std::vector &columns, const NativeRdb::DataAbilityPredicates &predicates) +{ + // std::shared_ptr resultSet = nullptr; + if (ability_ == nullptr) { + APP_LOGE("DataAbilityImpl::Query ability_ is nullptr"); + return nullptr; + } + + return ability_->Query(uri, columns, predicates); +} + +/** + * @brief Obtains the MIME type matching the data specified by the URI of the Data ability. This method should be + * implemented by a Data ability. Data abilities supports general data types, including text, HTML, and JPEG. + * + * @param uri Indicates the URI of the data. + * + * @return Returns the MIME type that matches the data specified by uri. + */ +std::string DataAbilityImpl::GetType(const Uri &uri) +{ + std::string type; + if (ability_ == nullptr) { + APP_LOGE("DataAbilityImpl::GetType ability_ is nullptr"); + return type; + } + type = ability_->GetType(uri); + return type; +} + +/** + * @brief Reloads data in the database. + * + * @param uri Indicates the position where the data is to reload. This parameter is mandatory. + * @param extras Indicates the PacMap object containing the additional parameters to be passed in this call. This + * parameter can be null. If a custom Sequenceable object is put in the PacMap object and will be transferred across + * processes, you must call BasePacMap.setClassLoader(ClassLoader) to set a class loader for the custom object. + * + * @return Returns true if the data is successfully reloaded; returns false otherwise. + */ +bool DataAbilityImpl::Reload(const Uri &uri, const PacMap &extras) +{ + bool ret = false; + if (ability_ == nullptr) { + APP_LOGE("DataAbilityImpl::Reload ability_ is nullptr"); + return ret; + } + ret = ability_->Reload(uri, extras); + return ret; +} + +/** + * @brief Inserts multiple data records into the database. + * + * @param uri Indicates the path of the data to operate. + * @param values Indicates the data records to insert. + * + * @return Returns the number of data records inserted. + */ +int DataAbilityImpl::BatchInsert(const Uri &uri, const std::vector &values) +{ + int ret = -1; + if (ability_ == nullptr) { + APP_LOGE("DataAbilityImpl::BatchInsert​ ability_ is nullptr"); + return ret; + } + ret = ability_->BatchInsert(uri, values); + return ret; +} +/** + * @brief Converts the given uri that refer to the Data ability into a normalized URI. A normalized URI can be used + * across devices, persisted, backed up, and restored. It can refer to the same item in the Data ability even if the + * context has changed. If you implement URI normalization for a Data ability, you must also implement + * denormalizeUri(ohos.utils.net.Uri) to enable URI denormalization. After this feature is enabled, URIs passed to any + * method that is called on the Data ability must require normalization verification and denormalization. The default + * implementation of this method returns null, indicating that this Data ability does not support URI normalization. + * + * @param uri Indicates the Uri object to normalize. + * + * @return Returns the normalized Uri object if the Data ability supports URI normalization; returns null otherwise. + */ +Uri DataAbilityImpl::NormalizeUri(const Uri &uri) +{ + Uri urivalue(""); + if (ability_ == nullptr) { + APP_LOGE("DataAbilityImpl::NormalizeUri ability_ is nullptr"); + return urivalue; + } + urivalue = ability_->NormalizeUri(uri); + return urivalue; +} + +/** + * @brief Converts the given uri that refer to the Data ability into a normalized URI. A normalized URI can be used + * across devices, persisted, backed up, and restored. It can refer to the same item in the Data ability even if the + * context has changed. If you implement URI normalization for a Data ability, you must also implement + * denormalizeUri(ohos.utils.net.Uri) to enable URI denormalization. After this feature is enabled, URIs passed to any + * method that is called on the Data ability must require normalization verification and denormalization. The default + * implementation of this method returns null, indicating that this Data ability does not support URI normalization. + * + * @param uri Indicates the Uri object to normalize. + * + * @return Returns the normalized Uri object if the Data ability supports URI normalization; returns null otherwise. + */ +Uri DataAbilityImpl::DenormalizeUri(const Uri &uri) +{ + Uri urivalue(""); + if (ability_ == nullptr) { + APP_LOGE("DataAbilityImpl::DenormalizeUri ability_ is nullptr"); + return urivalue; + } + urivalue = ability_->DenormalizeUri(uri); + return urivalue; +} + +std::vector> DataAbilityImpl::ExecuteBatch( + const std::vector> &operations) +{ + APP_LOGI("DataAbilityImpl::ExecuteBatch start"); + std::vector> results; + if (ability_ == nullptr) { + APP_LOGE("DataAbilityImpl::ExecuteBatch ability_ is nullptr"); + results.clear(); + return results; + } + + results = ability_->ExecuteBatch(operations); + APP_LOGI("DataAbilityImpl::ExecuteBatch end, results size:%{public}zu", results.size()); + return results; +} + +} // namespace AppExecFwk +} // namespace OHOS diff --git a/tools/frameworks/kits/ability/native/src/data_ability_operation.cpp b/tools/frameworks/kits/ability/native/src/data_ability_operation.cpp new file mode 100644 index 00000000000..21c312ba77a --- /dev/null +++ b/tools/frameworks/kits/ability/native/src/data_ability_operation.cpp @@ -0,0 +1,490 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "data_ability_operation.h" +#include "app_log_wrapper.h" +#include "hilog_wrapper.h" +#include "data_ability_predicates.h" +#include "values_bucket.h" + +namespace OHOS { +namespace AppExecFwk { +DataAbilityOperation::DataAbilityOperation( + const std::shared_ptr &dataAbilityOperation, const std::shared_ptr &withUri) +{ + uri_ = withUri; + if (dataAbilityOperation != nullptr) { + type_ = dataAbilityOperation->type_; + valuesBucket_ = dataAbilityOperation->valuesBucket_; + expectedCount_ = dataAbilityOperation->expectedCount_; + dataAbilityPredicates_ = dataAbilityOperation->dataAbilityPredicates_; + valuesBucketReferences_ = dataAbilityOperation->valuesBucketReferences_; + dataAbilityPredicatesBackReferences_ = dataAbilityOperation->dataAbilityPredicatesBackReferences_; + interrupted_ = dataAbilityOperation->interrupted_; + } else { + type_ = 0; + expectedCount_ = 0; + valuesBucket_ = std::make_shared(); + dataAbilityPredicates_ = std::make_shared(); + valuesBucketReferences_ = std::make_shared(); + dataAbilityPredicatesBackReferences_.clear(); + interrupted_ = false; + } +} +DataAbilityOperation::DataAbilityOperation(Parcel &in) +{ + ReadFromParcel(in); +} +DataAbilityOperation::DataAbilityOperation(const std::shared_ptr &builder) +{ + if (builder != nullptr) { + type_ = builder->type_; + uri_ = builder->uri_; + valuesBucket_ = builder->valuesBucket_; + expectedCount_ = builder->expectedCount_; + dataAbilityPredicates_ = builder->dataAbilityPredicates_; + valuesBucketReferences_ = builder->valuesBucketReferences_; + dataAbilityPredicatesBackReferences_ = builder->dataAbilityPredicatesBackReferences_; + interrupted_ = builder->interrupted_; + } +} + +DataAbilityOperation::DataAbilityOperation() +{ + type_ = 0; + uri_ = nullptr; + expectedCount_ = 0; + valuesBucket_ = std::make_shared(); + dataAbilityPredicates_ = std::make_shared(); + valuesBucketReferences_ = std::make_shared(); + dataAbilityPredicatesBackReferences_.clear(); + interrupted_ = false; +} + +DataAbilityOperation::~DataAbilityOperation() +{ + dataAbilityPredicatesBackReferences_.clear(); +} + +bool DataAbilityOperation::operator==(const DataAbilityOperation &other) const +{ + if (type_ != other.type_) { + return false; + } + if ((uri_ != nullptr) && (other.uri_ != nullptr) && (uri_->ToString() != other.uri_->ToString())) { + return false; + } + if (expectedCount_ != other.expectedCount_) { + return false; + } + if (valuesBucket_ != other.valuesBucket_) { + return false; + } + if (dataAbilityPredicates_ != other.dataAbilityPredicates_) { + return false; + } + if (valuesBucketReferences_ != other.valuesBucketReferences_) { + return false; + } + int backReferencesCount = dataAbilityPredicatesBackReferences_.size(); + int otherBackReferencesCount = other.dataAbilityPredicatesBackReferences_.size(); + if (backReferencesCount != otherBackReferencesCount) { + return false; + } + + std::map::const_iterator it = dataAbilityPredicatesBackReferences_.begin(); + while (it != dataAbilityPredicatesBackReferences_.end()) { + std::map::const_iterator otherIt = other.dataAbilityPredicatesBackReferences_.find(it->first); + if (otherIt != other.dataAbilityPredicatesBackReferences_.end()) { + if (otherIt->second != it->second) { + return false; + } + } else { + return false; + } + it++; + } + + if (interrupted_ != other.interrupted_) { + return false; + } + return true; +} + +DataAbilityOperation &DataAbilityOperation::operator=(const DataAbilityOperation &other) +{ + if (this != &other) { + type_ = other.type_; + uri_ = other.uri_; + expectedCount_ = other.expectedCount_; + valuesBucket_ = other.valuesBucket_; + dataAbilityPredicates_ = other.dataAbilityPredicates_; + valuesBucketReferences_ = other.valuesBucketReferences_; + dataAbilityPredicatesBackReferences_ = other.dataAbilityPredicatesBackReferences_; + interrupted_ = other.interrupted_; + } + return *this; +} + +std::shared_ptr DataAbilityOperation::NewInsertBuilder(const std::shared_ptr &uri) +{ + APP_LOGD("DataAbilityOperation::NewInsertBuilder start"); + if (uri == nullptr) { + APP_LOGE("DataAbilityOperation::NewInsertBuilder uri is nullptr"); + return nullptr; + } + std::shared_ptr builder = + std::make_shared(TYPE_INSERT, uri); + APP_LOGD("DataAbilityOperation::NewInsertBuilder end"); + return builder; +} + +std::shared_ptr DataAbilityOperation::NewUpdateBuilder(const std::shared_ptr &uri) +{ + APP_LOGD("DataAbilityOperation::NewUpdateBuilder start"); + if (uri == nullptr) { + APP_LOGE("DataAbilityOperation::NewUpdateBuilder uri is nullptr"); + return nullptr; + } + std::shared_ptr builder = + std::make_shared(TYPE_UPDATE, uri); + APP_LOGD("DataAbilityOperation::NewUpdateBuilder end"); + return builder; +} + +std::shared_ptr DataAbilityOperation::NewDeleteBuilder(const std::shared_ptr &uri) +{ + APP_LOGD("DataAbilityOperation::NewDeleteBuilder start"); + if (uri == nullptr) { + APP_LOGE("DataAbilityOperation::NewDeleteBuilder uri is nullptr"); + return nullptr; + } + std::shared_ptr builder = + std::make_shared(TYPE_DELETE, uri); + APP_LOGD("DataAbilityOperation::NewDeleteBuilder end"); + return builder; +} + +std::shared_ptr DataAbilityOperation::NewAssertBuilder(const std::shared_ptr &uri) +{ + APP_LOGD("DataAbilityOperation::NewAssertBuilder start"); + if (uri == nullptr) { + APP_LOGE("DataAbilityOperation::NewAssertBuilder uri is nullptr"); + return nullptr; + } + std::shared_ptr builder = + std::make_shared(TYPE_ASSERT, uri); + APP_LOGD("DataAbilityOperation::NewAssertBuilder end"); + return builder; +} + +int DataAbilityOperation::GetType() const +{ + APP_LOGD("DataAbilityOperation::GetType"); + return type_; +} + +std::shared_ptr DataAbilityOperation::GetUri() const +{ + APP_LOGD("DataAbilityOperation::GetUri"); + return uri_; +} + +std::shared_ptr DataAbilityOperation::GetValuesBucket() const +{ + APP_LOGD("DataAbilityOperation::GetValuesBucket"); + return valuesBucket_; +} + +int DataAbilityOperation::GetExpectedCount() const +{ + APP_LOGD("DataAbilityOperation::GetExpectedCount"); + return expectedCount_; +} + +std::shared_ptr DataAbilityOperation::GetDataAbilityPredicates() const +{ + APP_LOGD("DataAbilityOperation::GetDataAbilityPredicates"); + return dataAbilityPredicates_; +} + +std::shared_ptr DataAbilityOperation::GetValuesBucketReferences() const +{ + APP_LOGD("DataAbilityOperation::GetValuesBucketReferences"); + return valuesBucketReferences_; +} +std::map DataAbilityOperation::GetDataAbilityPredicatesBackReferences() const +{ + APP_LOGD("DataAbilityOperation::GetDataAbilityPredicatesBackReferences"); + return dataAbilityPredicatesBackReferences_; +} +bool DataAbilityOperation::IsInsertOperation() const +{ + APP_LOGD("DataAbilityOperation::IsInsertOperation:%d", type_ == TYPE_INSERT); + return type_ == TYPE_INSERT; +} +bool DataAbilityOperation::IsUpdateOperation() const +{ + APP_LOGD("DataAbilityOperation::IsUpdateOperation:%d", type_ == TYPE_UPDATE); + return type_ == TYPE_UPDATE; +} +bool DataAbilityOperation::IsDeleteOperation() const +{ + APP_LOGD("DataAbilityOperation::IsDeleteOperation:%d", type_ == TYPE_DELETE); + return type_ == TYPE_DELETE; +} +bool DataAbilityOperation::IsAssertOperation() const +{ + APP_LOGD("DataAbilityOperation::IsAssertOperation:%d", type_ == TYPE_ASSERT); + return type_ == TYPE_ASSERT; +} +bool DataAbilityOperation::IsInterruptionAllowed() const +{ + APP_LOGD("DataAbilityOperation::IsInterruptionAllowed:%d", interrupted_); + return interrupted_; +} +bool DataAbilityOperation::Marshalling(Parcel &out) const +{ + APP_LOGD("DataAbilityOperation::Marshalling start"); + if (!out.WriteInt32(type_)) { + APP_LOGE("DataAbilityOperation::Marshalling WriteInt32(type_) error"); + return false; + } + if (!out.WriteInt32(expectedCount_)) { + APP_LOGE("DataAbilityOperation::Marshalling WriteInt32(VALUE_OBJECT) error"); + return false; + } + + if (!out.WriteBool(interrupted_)) { + APP_LOGE("DataAbilityOperation::Marshalling WriteInt32(VALUE_OBJECT) error"); + return false; + } + + if (uri_ != nullptr) { + if (!out.WriteInt32(VALUE_OBJECT)) { + APP_LOGE("DataAbilityOperation::Marshalling WriteInt32(VALUE_OBJECT) error"); + return false; + } + + if (!out.WriteParcelable(uri_.get())) { + APP_LOGE("DataAbilityOperation::Marshalling WriteInt32(VALUE_OBJECT) error"); + return false; + } + } else { + if (!out.WriteInt32(VALUE_NULL)) { + return false; + } + } + + if (valuesBucket_ != nullptr) { + if (!out.WriteInt32(VALUE_OBJECT)) { + APP_LOGE("DataAbilityOperation::Marshalling WriteInt32(VALUE_OBJECT) error"); + return false; + } + + if (!out.WriteParcelable(valuesBucket_.get())) { + APP_LOGE("DataAbilityOperation::Marshalling WriteInt32(VALUE_OBJECT) error"); + return false; + } + } else { + if (!out.WriteInt32(VALUE_NULL)) { + APP_LOGE("DataAbilityOperation::Marshalling WriteInt32(VALUE_OBJECT) error"); + return false; + } + } + + if (dataAbilityPredicates_ != nullptr) { + if (!out.WriteInt32(VALUE_OBJECT)) { + APP_LOGE("DataAbilityOperation::Marshalling WriteInt32(VALUE_OBJECT) error"); + return false; + } + if (!out.WriteParcelable(dataAbilityPredicates_.get())) { + APP_LOGE("DataAbilityOperation::Marshalling WriteInt32(VALUE_OBJECT) error"); + return false; + } + } else { + if (!out.WriteInt32(VALUE_NULL)) { + return false; + } + } + + if (valuesBucketReferences_ != nullptr) { + if (!out.WriteInt32(VALUE_OBJECT)) { + APP_LOGE("DataAbilityOperation::Marshalling WriteInt32(VALUE_OBJECT) error"); + return false; + } + if (!out.WriteParcelable(valuesBucketReferences_.get())) { + APP_LOGE("DataAbilityOperation::Marshalling WriteInt32(VALUE_OBJECT) error"); + return false; + } + } else { + if (!out.WriteInt32(VALUE_NULL)) { + return false; + } + } + + int referenceSize = 0; + if (!dataAbilityPredicatesBackReferences_.empty()) { + referenceSize = dataAbilityPredicatesBackReferences_.size(); + if (!out.WriteInt32(referenceSize)) { + APP_LOGE("DataAbilityOperation::Marshalling WriteInt32(VALUE_OBJECT) error"); + return false; + } + if (referenceSize >= REFERENCE_THRESHOLD) { + APP_LOGI("DataAbilityOperation::Marshalling referenceSize >= REFERENCE_THRESHOLD"); + return true; + } + for (auto it = dataAbilityPredicatesBackReferences_.begin(); it != dataAbilityPredicatesBackReferences_.end(); + it++) { + + if (!out.WriteInt32(it->first)) { + APP_LOGE("DataAbilityOperation::Marshalling WriteInt32(VALUE_OBJECT) error"); + return false; + } + if (!out.WriteInt32(it->second)) { + APP_LOGE("DataAbilityOperation::Marshalling WriteInt32(VALUE_OBJECT) error"); + return false; + } + } + } else { + APP_LOGD("DataAbilityOperation::Marshalling dataAbilityPredicatesBackReferences_ is empty"); + if (!out.WriteInt32(referenceSize)) { + APP_LOGE("DataAbilityOperation::Marshalling WriteInt32(VALUE_OBJECT) error"); + return false; + } + } + + APP_LOGD("DataAbilityOperation::Marshalling end"); + return true; +} +DataAbilityOperation *DataAbilityOperation::Unmarshalling(Parcel &in) +{ + APP_LOGD("DataAbilityOperation::Unmarshalling start"); + DataAbilityOperation *dataAbilityOperation = new (std::nothrow) DataAbilityOperation(); + if (dataAbilityOperation != nullptr && !dataAbilityOperation->ReadFromParcel(in)) { + APP_LOGE("DataAbilityOperation::Unmarshalling dataAbilityOperation(%p) error", dataAbilityOperation); + delete dataAbilityOperation; + dataAbilityOperation = nullptr; + } + APP_LOGD("DataAbilityOperation::Unmarshalling end"); + return dataAbilityOperation; +} +bool DataAbilityOperation::ReadFromParcel(Parcel &in) +{ + APP_LOGD("DataAbilityOperation::ReadFromParcel start"); + if (!in.ReadInt32(type_)) { + APP_LOGE("DataAbilityOperation::ReadFromParcel ReadInt32(type_) error"); + return false; + } + if (!in.ReadInt32(expectedCount_)) { + APP_LOGE("DataAbilityOperation::ReadFromParcel ReadInt32(empty) error"); + return false; + } + interrupted_ = in.ReadBool(); + + int empty = VALUE_NULL; + if (!in.ReadInt32(empty)) { + APP_LOGE("DataAbilityOperation::ReadFromParcel ReadInt32(empty) error"); + return false; + } + if (empty == VALUE_OBJECT) { + uri_.reset(in.ReadParcelable()); + } else { + uri_.reset(); + } + + empty = VALUE_NULL; + if (!in.ReadInt32(empty)) { + APP_LOGE("DataAbilityOperation::ReadFromParcel ReadInt32(empty) error"); + return false; + } + APP_LOGD("DataAbilityOperation::ReadFromParcel empty is %{public}s", empty == VALUE_OBJECT ? "VALUE_OBJECT" : "VALUE_NULL"); + if (empty == VALUE_OBJECT) { + valuesBucket_.reset(in.ReadParcelable()); + } else { + valuesBucket_.reset(); + } + + empty = VALUE_NULL; + if (!in.ReadInt32(empty)) { + APP_LOGE("DataAbilityOperation::ReadFromParcel ReadInt32(empty) error"); + return false; + } + APP_LOGD("DataAbilityOperation::ReadFromParcel empty is %{public}s", empty == VALUE_OBJECT ? "VALUE_OBJECT" : "VALUE_NULL"); + if (empty == VALUE_OBJECT) { + dataAbilityPredicates_.reset(in.ReadParcelable()); + } else { + dataAbilityPredicates_.reset(); + } + + empty = VALUE_NULL; + if (!in.ReadInt32(empty)) { + APP_LOGE("DataAbilityOperation::ReadFromParcel ReadInt32(empty) error"); + return false; + } + APP_LOGD("DataAbilityOperation::ReadFromParcel empty is %{public}s", empty == VALUE_OBJECT ? "VALUE_OBJECT" : "VALUE_NULL"); + if (empty == VALUE_OBJECT) { + valuesBucketReferences_.reset(in.ReadParcelable()); + } else { + valuesBucketReferences_.reset(); + } + + int referenceSize = 0; + if (!in.ReadInt32(referenceSize)) { + APP_LOGE("DataAbilityOperation::ReadFromParcel end"); + return false; + } + if (referenceSize >= REFERENCE_THRESHOLD) { + APP_LOGI("DataAbilityOperation::ReadFromParcel referenceSize:%{public}d >= REFERENCE_THRESHOLD:%{public}d", referenceSize, REFERENCE_THRESHOLD); + return true; + } + + for (int i = 0; i < REFERENCE_THRESHOLD && i < referenceSize; ++i) { + int first = 0; + int second = 0; + if (!in.ReadInt32(first)) { + APP_LOGE("DataAbilityOperation::ReadFromParcel end"); + return false; + } + if (!in.ReadInt32(second)) { + APP_LOGE("DataAbilityOperation::ReadFromParcel end"); + return false; + } + dataAbilityPredicatesBackReferences_.insert(std::make_pair(first, second)); + } + + APP_LOGD("DataAbilityOperation::ReadFromParcel end"); + return true; +} +std::shared_ptr DataAbilityOperation::CreateFromParcel(Parcel &in) +{ + APP_LOGD("DataAbilityOperation::CreateFromParcel start"); + std::shared_ptr operation = std::make_shared(in); + APP_LOGD("DataAbilityOperation::CreateFromParcel end"); + return operation; +} +void DataAbilityOperation::PutMap(Parcel &in) +{ + APP_LOGD("DataAbilityOperation::PutMap start"); + int count = in.ReadInt32(); + if (count > 0 && count < REFERENCE_THRESHOLD) { + for (int i = 0; i < count; ++i) { + dataAbilityPredicatesBackReferences_.insert(std::make_pair(in.ReadInt32(), in.ReadInt32())); + } + } + APP_LOGD("DataAbilityOperation::PutMap end"); +} +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/src/data_ability_operation_builder.cpp b/tools/frameworks/kits/ability/native/src/data_ability_operation_builder.cpp new file mode 100644 index 00000000000..b47589dea0b --- /dev/null +++ b/tools/frameworks/kits/ability/native/src/data_ability_operation_builder.cpp @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "data_ability_operation_builder.h" +#include "app_log_wrapper.h" +#include "data_ability_predicates.h" +#include "values_bucket.h" + +namespace OHOS { +namespace AppExecFwk { +DataAbilityOperationBuilder::DataAbilityOperationBuilder(const int type, const std::shared_ptr &uri) +{ + type_ = type; + uri_ = uri; + expectedCount_ = 0; + interrupted_ = false; + valuesBucket_ = nullptr; + dataAbilityPredicates_ = nullptr; + valuesBucketReferences_ = nullptr; + dataAbilityPredicatesBackReferences_.clear(); +} +DataAbilityOperationBuilder::~DataAbilityOperationBuilder() +{ + dataAbilityPredicatesBackReferences_.clear(); +} + +std::shared_ptr DataAbilityOperationBuilder::Build() +{ + APP_LOGD("DataAbilityOperationBuilder::Build start"); + if (type_ != DataAbilityOperation::TYPE_UPDATE || (valuesBucket_ != nullptr && !valuesBucket_->IsEmpty())) { + std::shared_ptr operation = std::make_shared(shared_from_this()); + APP_LOGD("DataAbilityOperationBuilder::Build end"); + return operation; + } + APP_LOGE("DataAbilityOperationBuilder::Build return nullptr"); + return nullptr; +} +std::shared_ptr DataAbilityOperationBuilder::WithValuesBucket( + std::shared_ptr &values) +{ + APP_LOGD("DataAbilityOperationBuilder::WithValuesBucket start"); + if (type_ != DataAbilityOperation::TYPE_INSERT && type_ != DataAbilityOperation::TYPE_UPDATE && + type_ != DataAbilityOperation::TYPE_ASSERT) { + APP_LOGE("DataAbilityOperationBuilder::WithValuesBucket only inserts, updates can have values, type=%{public}d", + type_); + return nullptr; + } + + std::map valuesMap; + values->GetAll(valuesMap); + + valuesBucket_.reset(new (std::nothrow) NativeRdb::ValuesBucket(valuesMap)); + APP_LOGD("DataAbilityOperationBuilder::WithValuesBucket end"); + return shared_from_this(); +} + +std::shared_ptr DataAbilityOperationBuilder::WithPredicates( + std::shared_ptr &predicates) +{ + APP_LOGD("DataAbilityOperationBuilder::WithPredicates start"); + if (type_ != DataAbilityOperation::TYPE_DELETE && type_ != DataAbilityOperation::TYPE_UPDATE && + type_ != DataAbilityOperation::TYPE_ASSERT) { + APP_LOGE( + "DataAbilityOperationBuilder::withPredicates only deletes and updates can have selections, type=%{public}d", + type_); + return nullptr; + } + dataAbilityPredicates_ = predicates; + APP_LOGD("DataAbilityOperationBuilder::WithPredicates end"); + return shared_from_this(); +} +std::shared_ptr DataAbilityOperationBuilder::WithExpectedCount(int count) +{ + APP_LOGD("DataAbilityOperationBuilder::WithExpectedCount start"); + APP_LOGI("DataAbilityOperationBuilder::WithExpectedCount expectedCount:%{public}d", count); + if (type_ != DataAbilityOperation::TYPE_UPDATE && type_ != DataAbilityOperation::TYPE_DELETE && + type_ != DataAbilityOperation::TYPE_ASSERT) { + APP_LOGE("DataAbilityOperationBuilder::withExpectedCount only updates, deletes can have expected counts, " + "type=%{public}d", + type_); + return nullptr; + } + expectedCount_ = count; + APP_LOGD("DataAbilityOperationBuilder::WithExpectedCount end"); + return shared_from_this(); +} +std::shared_ptr DataAbilityOperationBuilder::WithPredicatesBackReference( + int requestArgIndex, int previousResult) +{ + APP_LOGD("DataAbilityOperationBuilder::WithPredicatesBackReference start"); + APP_LOGI("DataAbilityOperationBuilder::WithPredicatesBackReference requestArgIndex:%{public}d, " + "previousResult:%{public}d", + requestArgIndex, + previousResult); + if (type_ != DataAbilityOperation::TYPE_UPDATE && type_ != DataAbilityOperation::TYPE_DELETE && + type_ != DataAbilityOperation::TYPE_ASSERT) { + APP_LOGE("DataAbilityOperationBuilder::withPredicatesBackReference only updates, deletes, and asserts can have " + "select back-references, type=%{public}d", + type_); + return nullptr; + } + dataAbilityPredicatesBackReferences_.insert(std::make_pair(requestArgIndex, previousResult)); + APP_LOGD("DataAbilityOperationBuilder::WithPredicatesBackReference end"); + return shared_from_this(); +} +std::shared_ptr DataAbilityOperationBuilder::WithValueBackReferences( + std::shared_ptr &backReferences) +{ + APP_LOGD("DataAbilityOperationBuilder::WithValueBackReferences start"); + if (type_ != DataAbilityOperation::TYPE_INSERT && type_ != DataAbilityOperation::TYPE_UPDATE && + type_ != DataAbilityOperation::TYPE_ASSERT) { + APP_LOGE("DataAbilityOperationBuilder::withValueBackReferences only inserts, updates, and asserts can have " + "value back-references, type=%{public}d", + type_); + return nullptr; + } + valuesBucketReferences_ = backReferences; + APP_LOGD("DataAbilityOperationBuilder::WithValueBackReferences end"); + return shared_from_this(); +} +std::shared_ptr DataAbilityOperationBuilder::WithInterruptionAllowed(bool interrupted) +{ + APP_LOGD("DataAbilityOperationBuilder::WithInterruptionAllowed start"); + APP_LOGI("DataAbilityOperationBuilder::WithInterruptionAllowed interrupted=%{public}d", interrupted); + if (type_ != DataAbilityOperation::TYPE_INSERT && type_ != DataAbilityOperation::TYPE_UPDATE && + type_ != DataAbilityOperation::TYPE_ASSERT && type_ != DataAbilityOperation::TYPE_DELETE) { + APP_LOGE("DataAbilityOperationBuilder::withInterruptionAllowed only inserts, updates, delete, and asserts can " + "have value back-references, type=%{public}d", + type_); + return nullptr; + } + interrupted_ = interrupted; + APP_LOGD("DataAbilityOperationBuilder::WithInterruptionAllowed end"); + return shared_from_this(); +} +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/src/data_ability_result.cpp b/tools/frameworks/kits/ability/native/src/data_ability_result.cpp new file mode 100644 index 00000000000..59784b6ba31 --- /dev/null +++ b/tools/frameworks/kits/ability/native/src/data_ability_result.cpp @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "data_ability_result.h" +#include +#include +#include "parcel_macro.h" + +namespace OHOS { +namespace AppExecFwk { + +/** + * @brief A constructor used to create a DataAbilityResult instance + * with the input parameter count specified. + */ +DataAbilityResult::DataAbilityResult(int count) : uri_("") +{ + count_ = count; +} + +/** + * @brief A constructor used to create a DataAbilityResult instance + * with a Parcel object specified. + */ +DataAbilityResult::DataAbilityResult(Parcel &parcel) : uri_(""), count_(0) +{ + ReadFromParcel(parcel); +} + +/** + * @brief A constructor used to create a DataAbilityResult instance + * with the input parameter uri specified + */ +DataAbilityResult::DataAbilityResult(const Uri &uri) : uri_(uri.ToString()), count_(0) +{} + +/** + * @brief A constructor used to create a DataAbilityResult instance + * with input parameters uri, count, and failure specified. + */ +DataAbilityResult::DataAbilityResult(const Uri &uri, int count) : uri_(uri.ToString()) +{ + count_ = count; +} + +DataAbilityResult::~DataAbilityResult() +{} + +/** + * @brief Obtains the Uri object corresponding to the operation. + * @return Obtains the Uri object corresponding to the operation. + */ +Uri DataAbilityResult::GetUri() +{ + return uri_; +} + +/** + * @brief Obtains the number of rows affected by the operation. + * @return Returns the number of rows affected by the operation. + */ +int DataAbilityResult::GetCount() +{ + return count_; +} + +/** + * @brief Creates a DataAbilityResult instance based on the given Parcel object. + * Used to transfer DataAbilityResult object using Parcel. + * @param parcel Indicates the Parcel object. + * @return Returns the DataAbilityResult object. + */ +DataAbilityResult *DataAbilityResult::CreateFromParcel(Parcel &parcel) +{ + DataAbilityResult *dataAbilityResult = new (std::nothrow) DataAbilityResult(parcel); + if (dataAbilityResult == nullptr) { + APP_LOGE("DataAbilityResult::CreateFromParcel dataAbilityResult is nullptr"); + } + return dataAbilityResult; +} + +/** + * @brief Prints out a string containing the class object information. + * @return Returns object information. + */ +std::string DataAbilityResult::ToString() +{ + std::string stringBuilder = "DataAbilityResult("; + stringBuilder.append("uri=").append(uri_.ToString()).append(" "); + stringBuilder.append("count=").append(std::to_string(count_)).append(" "); + stringBuilder.erase(stringBuilder.length() - 1, 1); + stringBuilder.append(")"); + return stringBuilder; +} + +/** + * @brief Marshals a DataAbilityResult object into a Parcel. + * @param parcel Indicates the Parcel object for marshalling. + * @return Returns true if the marshalling is successful; returns false otherwise. + */ +bool DataAbilityResult::Marshalling(Parcel &parcel) const +{ + // uri_ + if (uri_.ToString().empty()) { + WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(Int32, parcel, VALUE_NULL); + } else { + if (!parcel.WriteInt32(VALUE_OBJECT)) { + return false; + } + if (!parcel.WriteParcelable(&uri_)) { + return false; + } + } + + // count_ + if (!parcel.WriteInt32(count_)) { + return false; + } + + return true; +} + +/** + * @brief Unmarshals a DataAbilityResult object from a Parcel. + * @param parcel Indicates the Parcel object for unmarshalling. + * @return Returns true if the unmarshalling is successful; returns false otherwise. + */ +DataAbilityResult *DataAbilityResult::Unmarshalling(Parcel &parcel) +{ + DataAbilityResult *dataAbilityResult = new (std::nothrow) DataAbilityResult(0); + if (dataAbilityResult != nullptr) { + if (!dataAbilityResult->ReadFromParcel(parcel)) { + delete dataAbilityResult; + dataAbilityResult = nullptr; + } + } + + return dataAbilityResult; +} + +bool DataAbilityResult::ReadFromParcel(Parcel &parcel) +{ + // uri_ + int32_t empty = VALUE_NULL; + if (!parcel.ReadInt32(empty)) { + return false; + } + + if (empty == VALUE_OBJECT) { + auto uri = parcel.ReadParcelable(); + if (uri != nullptr) { + uri_ = *uri; + delete uri; + uri = nullptr; + } else { + return false; + } + } + + // count_ + if (!parcel.ReadInt32(count_)) { + return false; + } + + return true; +} + +} // namespace AppExecFwk +} // namespace OHOS diff --git a/tools/frameworks/kits/ability/native/src/data_uri_utils.cpp b/tools/frameworks/kits/ability/native/src/data_uri_utils.cpp new file mode 100644 index 00000000000..936f36617f6 --- /dev/null +++ b/tools/frameworks/kits/ability/native/src/data_uri_utils.cpp @@ -0,0 +1,218 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "data_uri_utils.h" +#include +#include +#include +#include "securec.h" + +namespace OHOS { +namespace AppExecFwk { + +namespace { +const string EMPTY = ""; +const std::regex INTEGER_REGEX("^[-+]?([0-9]+)([.]([0-9]+))?$"); +const int BUFFER_LEN = 64; +const char *SEPARATOR = "/"; +}; // namespace + +/** + * @brief Default constructor of DataUriUtils class + * @return None + */ +DataUriUtils::DataUriUtils() +{} + +/** + * @brief Default deconstructor of DataUriUtils class + * @return None + */ +DataUriUtils::~DataUriUtils() +{} + +/** + * @brief Attaches the given ID to the end of the path component of the given URI. + * @param dataUri based on RFC 2396( Uniform Resource Identifier ). + * @param id + * @return Uri( scheme://authority/path1/path2/path3/updateIDNumber....) + */ +Uri DataUriUtils::AttachId(const Uri &dataUri, long long id) +{ + // 1. get Path + string path = const_cast(dataUri).GetPath(); + if (path.empty()) { + return dataUri; + } + + string uriString = dataUri.ToString(); + + std::vector pathVector; + const_cast(dataUri).GetPathSegments(pathVector); + if (pathVector.empty()) { + return dataUri; + } + string lastPath = pathVector[pathVector.size() - 1]; + + char longBuffer[BUFFER_LEN] = {0}; + + int ret = sprintf_s(longBuffer, sizeof(longBuffer), "%lld", id); + if (ret == -1) { + return dataUri; + } + // new path string (lastPath+SEPARATOR+number) + string newLastPath(""); + + newLastPath = lastPath + string(SEPARATOR) + string(longBuffer); + + // find "/+lastPath" + string tempLastPath = string(SEPARATOR) + lastPath; + auto lastPathPos = uriString.rfind(tempLastPath); + + uriString.replace(lastPathPos + 1, tempLastPath.size() - 1, newLastPath.c_str()); + return Uri(uriString); +} + +/** + * @brief Obtains the ID attached to the end of the path component of the given URI. + * @param dataUri based on RFC 2396( Uniform Resource Identifier ). + * @return long ID + */ +long long DataUriUtils::GetId(const Uri &dataUri) +{ + // 1. get Path + string path = const_cast(dataUri).GetPath(); + if (path.empty()) { + return -1; + } + std::vector pathVector; + const_cast(dataUri).GetPathSegments(pathVector); + if (pathVector.empty()) { + return -1; + } + string lastPath = pathVector[pathVector.size() - 1]; + if (!IsNumber(lastPath)) { + return -1; + } + return std::atoll(lastPath.c_str()); +} + +/** + * @brief Deletes the ID from the end of the path component of the given URI. + * @param dataUri based on RFC 2396( Uniform Resource Identifier ). + * @return long ID + */ +Uri DataUriUtils::DeleteId(const Uri &dataUri) +{ + return UriUpateLastPath(dataUri, EMPTY); +} + +/** + * @brief Updates the ID in the specified dataUri + * @param dataUri based on RFC 2396( Uniform Resource Identifier ). + * @param id indiates Update attached to the end of the path component of the given URI + * @return Uri return is the URI after path is updated + */ +Uri DataUriUtils::UpdateId(const Uri &dataUri, long long id) +{ + char longBuffer[BUFFER_LEN] = {0}; + int ret = sprintf_s(longBuffer, sizeof(longBuffer), "%lld", id); + if (ret == -1) { + return dataUri; + } + + string newLastPath(""); + newLastPath = string(longBuffer); + + return UriUpateLastPath(dataUri, newLastPath); +} + +/** + * @brief Does the end path of the path component of the given URI have an ID attached to it? + * @param dataUri based on RFC 2396( Uniform Resource Identifier ). + * @return bool + */ +bool DataUriUtils::IsAttachedId(const Uri &dataUri) +{ + // 1. get Path + string path = const_cast(dataUri).GetPath(); + if (path.empty()) { + return false; + } + + std::vector pathVector; + const_cast(dataUri).GetPathSegments(pathVector); + if (pathVector.empty()) { + return false; + } + string lastPath = pathVector[pathVector.size() - 1]; + + return IsNumber(lastPath); +} + +/** + * @brief Determine whether the string content is a numeric string + * @param str indicates stirng. + * @return bool + */ +bool DataUriUtils::IsNumber(const string &str) +{ + return std::regex_match(str, INTEGER_REGEX); +} + +/** + * @brief Determine whether the string content is a numeric string + * @param dataUri indicates Uri object + scheme://authority/path/aaa?query/#fragment + * @return Uri return is the URI after path is updated + */ +Uri DataUriUtils::UriUpateLastPath(const Uri &dataUri, const string &updateLastPath) +{ + std::string strUpdateLastPath; + + if (updateLastPath.size() > 0) { + strUpdateLastPath = SEPARATOR + updateLastPath; + } + + // 1. get Path + string path = const_cast(dataUri).GetPath(); + if (path.empty()) { + return dataUri; + } + + std::vector pathVector; + const_cast(dataUri).GetPathSegments(pathVector); + if (pathVector.empty()) { + return dataUri; + } + string lastPath = pathVector[pathVector.size() - 1]; + if (!IsNumber(lastPath)) { + return dataUri; + } + + string uriString = dataUri.ToString(); + // find "/+lastPath" + int lastPathPos = uriString.rfind(string(SEPARATOR) + lastPath); + if (lastPathPos == -1) { + return dataUri; + } + + // replace "/lastpath"==>"" + uriString.replace(lastPathPos, lastPath.size() + 1, strUpdateLastPath); + + return Uri(uriString); +} + +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/src/dummy_data_ability_predicates.cpp b/tools/frameworks/kits/ability/native/src/dummy_data_ability_predicates.cpp new file mode 100644 index 00000000000..ffd3c70106d --- /dev/null +++ b/tools/frameworks/kits/ability/native/src/dummy_data_ability_predicates.cpp @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "dummy_data_ability_predicates.h" +#include "app_log_wrapper.h" +#include "string_ex.h" + +namespace OHOS { +namespace AppExecFwk { +DataAbilityPredicates::DataAbilityPredicates(const std::string &testInf) : testInf_(testInf) +{} + +/** + * @brief read this Sequenceable object from a Parcel. + * + * @param inParcel Indicates the Parcel object into which the Sequenceable object has been marshaled. + * @return Returns true if read succeeded; returns false otherwise. + */ +bool DataAbilityPredicates::ReadFromParcel(Parcel &parcel) +{ + testInf_ = Str16ToStr8(parcel.ReadString16()); + return true; +} + +/** + * @brief Unmarshals this Sequenceable object from a Parcel. + * + * @param inParcel Indicates the Parcel object into which the Sequenceable object has been marshaled. + */ +DataAbilityPredicates *DataAbilityPredicates::Unmarshalling(Parcel &parcel) +{ + DataAbilityPredicates *dataAbilityPredicates = new (std::nothrow) DataAbilityPredicates(); + if (dataAbilityPredicates && !dataAbilityPredicates->ReadFromParcel(parcel)) { + APP_LOGE("DataAbilityPredicates::Unmarshalling ReadFromParcel failed"); + delete dataAbilityPredicates; + dataAbilityPredicates = nullptr; + } + return dataAbilityPredicates; +} + +/** + * @brief Marshals this Sequenceable object into a Parcel. + * + * @param outParcel Indicates the Parcel object to which the Sequenceable object will be marshaled. + */ +bool DataAbilityPredicates::Marshalling(Parcel &parcel) const +{ + if (!parcel.WriteString16(Str8ToStr16(testInf_))) { + APP_LOGE("dataAbilityPredicates::Marshalling WriteString16 failed"); + return false; + } + return true; +} +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/src/dummy_data_ability_predicates_discard.cpp b/tools/frameworks/kits/ability/native/src/dummy_data_ability_predicates_discard.cpp new file mode 100644 index 00000000000..42970b17fd1 --- /dev/null +++ b/tools/frameworks/kits/ability/native/src/dummy_data_ability_predicates_discard.cpp @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/src/dummy_result_set.cpp b/tools/frameworks/kits/ability/native/src/dummy_result_set.cpp new file mode 100644 index 00000000000..cf329d07b0e --- /dev/null +++ b/tools/frameworks/kits/ability/native/src/dummy_result_set.cpp @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "dummy_result_set.h" +#include "app_log_wrapper.h" +#include "string_ex.h" + +namespace OHOS { +namespace AppExecFwk { +ResultSet::ResultSet(const std::string &testInf) : testInf_(testInf) +{} + +/** + * @brief read this Sequenceable object from a Parcel. + * + * @param inParcel Indicates the Parcel object into which the Sequenceable object has been marshaled. + * @return Returns true if read succeeded; returns false otherwise. + */ +bool ResultSet::ReadFromParcel(Parcel &parcel) +{ + testInf_ = Str16ToStr8(parcel.ReadString16()); + return true; +} + +/** + * @brief Unmarshals this Sequenceable object from a Parcel. + * + * @param inParcel Indicates the Parcel object into which the Sequenceable object has been marshaled. + */ +ResultSet *ResultSet::Unmarshalling(Parcel &parcel) +{ + ResultSet *resultSet = new (std::nothrow) ResultSet(); + if (resultSet && !resultSet->ReadFromParcel(parcel)) { + APP_LOGE("ResultSet::Unmarshalling ReadFromParcel failed"); + delete resultSet; + resultSet = nullptr; + } + return resultSet; +} + +/** + * @brief Marshals this Sequenceable object into a Parcel. + * + * @param outParcel Indicates the Parcel object to which the Sequenceable object will be marshaled. + */ +bool ResultSet::Marshalling(Parcel &parcel) const +{ + if (!parcel.WriteString16(Str8ToStr16(testInf_))) { + APP_LOGE("ResultSet::Marshalling WriteString16 failed"); + return false; + } + return true; +} +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/src/dummy_result_set_discard.cpp b/tools/frameworks/kits/ability/native/src/dummy_result_set_discard.cpp new file mode 100644 index 00000000000..42970b17fd1 --- /dev/null +++ b/tools/frameworks/kits/ability/native/src/dummy_result_set_discard.cpp @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/src/dummy_values_bucket.cpp b/tools/frameworks/kits/ability/native/src/dummy_values_bucket.cpp new file mode 100644 index 00000000000..a1085fca8b5 --- /dev/null +++ b/tools/frameworks/kits/ability/native/src/dummy_values_bucket.cpp @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "dummy_values_bucket.h" +#include "app_log_wrapper.h" +#include "string_ex.h" + +namespace OHOS { +namespace AppExecFwk { +ValuesBucket::ValuesBucket(const std::string &testInf) : testInf_(testInf) +{} + +/** + * @brief read this Sequenceable object from a Parcel. + * + * @param inParcel Indicates the Parcel object into which the Sequenceable object has been marshaled. + * @return Returns true if read succeeded; returns false otherwise. + */ +bool ValuesBucket::ReadFromParcel(Parcel &parcel) +{ + testInf_ = Str16ToStr8(parcel.ReadString16()); + return true; +} + +/** + * @brief Unmarshals this Sequenceable object from a Parcel. + * + * @param inParcel Indicates the Parcel object into which the Sequenceable object has been marshaled. + */ +ValuesBucket *ValuesBucket::Unmarshalling(Parcel &parcel) +{ + ValuesBucket *valuesBucket = new (std::nothrow) ValuesBucket(); + if (valuesBucket && !valuesBucket->ReadFromParcel(parcel)) { + APP_LOGE("ValuesBucket::Unmarshalling ReadFromParcel failed"); + delete valuesBucket; + valuesBucket = nullptr; + } + return valuesBucket; +} + +/** + * @brief Marshals this Sequenceable object into a Parcel. + * + * @param outParcel Indicates the Parcel object to which the Sequenceable object will be marshaled. + */ +bool ValuesBucket::Marshalling(Parcel &parcel) const +{ + if (!parcel.WriteString16(Str8ToStr16(testInf_))) { + APP_LOGE("valuesBucket::Marshalling WriteString16 failed"); + return false; + } + return true; +} +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/src/dummy_values_bucket_discard.cpp b/tools/frameworks/kits/ability/native/src/dummy_values_bucket_discard.cpp new file mode 100644 index 00000000000..42970b17fd1 --- /dev/null +++ b/tools/frameworks/kits/ability/native/src/dummy_values_bucket_discard.cpp @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/src/form_js_event_handler.cpp b/tools/frameworks/kits/ability/native/src/form_js_event_handler.cpp new file mode 100644 index 00000000000..69cc4e5f339 --- /dev/null +++ b/tools/frameworks/kits/ability/native/src/form_js_event_handler.cpp @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "app_log_wrapper.h" +#include "form_constants.h" +#include "form_host_client.h" +#include "form_js_event_handler.h" +#include "form_mgr.h" +#include "ipc_skeleton.h" + +namespace OHOS { +namespace AppExecFwk { +FormJsEventHandler::FormJsEventHandler( + const std::shared_ptr &runner, const std::shared_ptr &ability, const FormJsInfo &formJsInfo) + : EventHandler(runner), formJsInfo_(formJsInfo), ability_(ability) +{ + APP_LOGI("%{public}s called.", __func__); +} + +/** + * Process the event. Developers should override this method. + * + * @param event The event should be processed. + */ +void FormJsEventHandler::ProcessEvent(const InnerEvent::Pointer &event) +{ + APP_LOGI("%{public}s called.", __func__); + if (!event) { + APP_LOGE("%{public}s, param illegal, event is nullptr", __func__); + return; + } + APP_LOGD("%{public}s, inner event id obtained: %u.", __func__, event->GetInnerEventId()); + + switch (event->GetInnerEventId()) { + case FORM_ROUTE_EVENT: { + auto object = event->GetUniqueObject(); + Want want = *object; + ProcessRouterEvent(want); + break; + } + case FORM_MESSAGE_EVENT: { + auto object = event->GetUniqueObject(); + Want want = *object; + ProcessMessageEvent(want); + break; + } + default: { + APP_LOGW("unsupported event."); + break; + } + } +} + +/** + * @brief Process js router event. + * @param want Indicates the event to be processed. + */ +void FormJsEventHandler::ProcessRouterEvent(Want &want) +{ + APP_LOGI("%{public}s called.", __func__); + + if (!IsSystemApp()) { + APP_LOGW("%{public}s, not system application, cannot mixture package router", __func__); + return; + } + if (!want.HasParameter(Constants::PARAM_FORM_ABILITY_NAME_KEY)) { + APP_LOGE("%{public}s, param illegal, abilityName is not exist", __func__); + return; + } + + std::string abilityName = want.GetStringParam(Constants::PARAM_FORM_ABILITY_NAME_KEY); + want.SetElementName(formJsInfo_.bundleName, abilityName); + want.SetParam(Constants::PARAM_FORM_IDENTITY_KEY, std::to_string(formJsInfo_.formId)); + ability_->StartAbility(want); +} +/** + * @brief Process js message event. + * @param want Indicates the event to be processed. + */ +void FormJsEventHandler::ProcessMessageEvent(const Want &want) +{ + APP_LOGI("%{public}s called.", __func__); + + if (!want.HasParameter(Constants::PARAM_FORM_IDENTITY_KEY)) { + APP_LOGE("%{public}s, formid is not exist", __func__); + return; + } + std::string strFormId = want.GetStringParam(Constants::PARAM_FORM_IDENTITY_KEY); + int64_t formId = std::stoll(strFormId); + if (formId <= 0) { + APP_LOGE("%{public}s error, The passed formid is invalid. Its value must be larger than 0.", __func__); + return; + } + + if (!want.HasParameter(Constants::PARAM_MESSAGE_KEY)) { + APP_LOGE("%{public}s, message info is not exist", __func__); + return; + } + + if (FormMgr::GetRecoverStatus() == Constants::IN_RECOVERING) { + APP_LOGE("%{public}s error, form is in recover status, can't do action on form.", __func__); + return; + } + + // requestForm request to fms + int resultCode = FormMgr::GetInstance().MessageEvent(formId, want, FormHostClient::GetInstance()); + if (resultCode != ERR_OK) { + APP_LOGE("%{public}s error, failed to notify the form service that the form user's lifecycle is updated, error " + "code is %{public}d.", + __func__, + resultCode); + return; + } +} + +bool FormJsEventHandler::IsSystemApp() const +{ + APP_LOGI("%{public}s called.", __func__); + + int32_t callingUid = IPCSkeleton::GetCallingUid(); + if (callingUid > Constants::MAX_SYSTEM_APP_UID) { + APP_LOGW("%{public}s warn, callingUid is %{public}d, which is larger than %{public}d.", + __func__, + callingUid, + Constants::MAX_SYSTEM_APP_UID); + return false; + } else { + APP_LOGD("%{public}s, callingUid = %{public}d.", __func__, callingUid); + return true; + } +} +} // namespace AppExecFwk +} // namespace OHOS diff --git a/tools/frameworks/kits/ability/native/src/form_provider_client.cpp b/tools/frameworks/kits/ability/native/src/form_provider_client.cpp new file mode 100755 index 00000000000..413141d7538 --- /dev/null +++ b/tools/frameworks/kits/ability/native/src/form_provider_client.cpp @@ -0,0 +1,467 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "form_provider_client.h" +#include "appexecfwk_errors.h" +#include "app_log_wrapper.h" +#include "form_supply_proxy.h" +#include "ipc_skeleton.h" +#include "permission/permission.h" +#include "permission/permission_kit.h" +#include "string_ex.h" + +namespace OHOS { +namespace AppExecFwk { +using PermissionKit = OHOS::Security::Permission::PermissionKit; +using PermissionState = OHOS::Security::Permission::PermissionState; + +/** + * @brief Acquire to give back an ProviderFormInfo. This is sync API. + * @param formId The Id of the form. + * @param want The want of the form to create. + * @param callerToken Caller ability token. + * @return Returns ERR_OK on success, others on failure. + */ +int FormProviderClient::AcquireProviderFormInfo( + const int64_t formId, + const Want &want, + const sptr &callerToken) +{ + APP_LOGI("%{public}s called.", __func__); + + Want newWant(want); + newWant.SetParam(Constants::ACQUIRE_TYPE, want.GetIntParam(Constants::ACQUIRE_TYPE, 0)); + newWant.SetParam(Constants::FORM_CONNECT_ID, want.GetLongParam(Constants::FORM_CONNECT_ID, 0)); + newWant.SetParam(Constants::FORM_SUPPLY_INFO, want.GetStringParam(Constants::FORM_SUPPLY_INFO)); + newWant.SetParam(Constants::PROVIDER_FLAG, true); + newWant.SetParam(Constants::PARAM_FORM_IDENTITY_KEY, std::to_string(formId)); + std::shared_ptr ownerAbility = GetOwner(); + if (ownerAbility == nullptr) { + APP_LOGE("%{public}s error, ownerAbility is nullptr.", __func__); + FormProviderInfo formProviderInfo; + newWant.SetParam(Constants::PROVIDER_FLAG, ERR_APPEXECFWK_FORM_NO_SUCH_ABILITY); + return HandleAcquire(formProviderInfo, newWant, callerToken); + } + + APP_LOGI("%{public}s come, %{public}s.", __func__, ownerAbility->GetAbilityName().c_str()); + + if (!CheckIsSystemApp()) { + APP_LOGW("%{public}s warn, AcquireProviderFormInfo caller permission denied.", __func__); + FormProviderInfo formProviderInfo; + newWant.SetParam(Constants::PROVIDER_FLAG, ERR_APPEXECFWK_FORM_PERMISSION_DENY); + return HandleAcquire(formProviderInfo, newWant, callerToken); + } + + Want createWant(want); + createWant.SetParam(Constants::PARAM_FORM_IDENTITY_KEY, std::to_string(formId)); + createWant.RemoveParam(Constants::FORM_CONNECT_ID); + createWant.RemoveParam(Constants::ACQUIRE_TYPE); + createWant.RemoveParam(Constants::FORM_SUPPLY_INFO); + FormProviderInfo formProviderInfo = ownerAbility->OnCreate(createWant); + APP_LOGD("%{public}s, formId: %{public}" PRId64 ", data: %{public}s", + __func__, formId, formProviderInfo.GetFormDataString().c_str()); + return HandleAcquire(formProviderInfo, newWant, callerToken); +} + +/** + * @brief Notify provider when the form was deleted. + * @param formId The Id of the form. + * @param want Indicates the structure containing form info. + * @param callerToken Caller ability token. + * @return Returns ERR_OK on success, others on failure. + */ +int FormProviderClient::NotifyFormDelete(const int64_t formId, const Want &want, const sptr &callerToken) +{ + APP_LOGI("%{public}s called.", __func__); + // The error code for business operation. + int errorCode = ERR_OK; + do { + APP_LOGI("%{public}s called.", __func__); + std::shared_ptr ownerAbility = GetOwner(); + if (ownerAbility == nullptr) { + APP_LOGE("%{public}s error, ownerAbility is nullptr.", __func__); + errorCode = ERR_APPEXECFWK_FORM_NO_SUCH_ABILITY; + break; + } + if (!CheckIsSystemApp()) { + APP_LOGW("%{public}s caller permission denied", __func__); + errorCode = ERR_APPEXECFWK_FORM_PERMISSION_DENY; + break; + } + + APP_LOGI("%{public}s come, %{public}s", __func__, ownerAbility->GetAbilityName().c_str()); + ownerAbility->OnDelete(formId); + } while (false); + + // The error code for disconnect. + int disconnectErrorCode = HandleDisconnect(want, callerToken); + if (errorCode != ERR_OK) { + // If errorCode is not ERR_OK,return errorCode. + return errorCode; + } else { + // If errorCode is ERR_OK,return disconnectErrorCode. + if (disconnectErrorCode != ERR_OK) { + APP_LOGE("%{public}s, disconnect error.", __func__); + } + return disconnectErrorCode; + } +} + +/** + * @brief Notify provider when the forms was deleted. + * + * @param formIds The id list of forms. + * @param callerToken Caller ability token. + * @return Returns ERR_OK on success, others on failure. + */ +int FormProviderClient::NotifyFormsDelete( + const std::vector &formIds, + const Want &want, + const sptr &callerToken) +{ + APP_LOGI("%{public}s called.", __func__); + // The error code for business operation. + int errorCode = ERR_OK; + do { + APP_LOGI("%{public}s called.", __func__); + std::shared_ptr ownerAbility = GetOwner(); + if (ownerAbility == nullptr) { + APP_LOGE("%{public}s error, ownerAbility is nullptr.", __func__); + errorCode = ERR_APPEXECFWK_FORM_NO_SUCH_ABILITY; + break; + } + if (!CheckIsSystemApp()) { + APP_LOGW("%{public}s caller permission denied", __func__); + errorCode = ERR_APPEXECFWK_FORM_PERMISSION_DENY; + break; + } + + APP_LOGI("%{public}s come,formIds size=%{public}zu, abilityName:%{public}s", + __func__, formIds.size(), ownerAbility->GetAbilityName().c_str()); + for (int64_t formId : formIds) { + ownerAbility->OnDelete(formId); + } + } while (false); + + // The error code for disconnect. + int disconnectErrorCode = HandleDisconnect(want, callerToken); + if (errorCode != ERR_OK) { + // If errorCode is not ERR_OK,return errorCode. + return errorCode; + } else { + // If errorCode is ERR_OK,return disconnectErrorCode. + if (disconnectErrorCode != ERR_OK) { + APP_LOGE("%{public}s, disconnect error.", __func__); + } + return disconnectErrorCode; + } +} + +/** + * @brief Notify provider when the form need update. + * + * @param formId The Id of the form. + * @param want Indicates the structure containing form info. + * @param callerToken Caller ability token. + * @return Returns ERR_OK on success, others on failure. + */ +int FormProviderClient::NotifyFormUpdate( + const int64_t formId, + const Want &want, + const sptr &callerToken) +{ + APP_LOGI("%{public}s called.", __func__); + + // The error code for business operation. + int errorCode = ERR_OK; + do { + std::shared_ptr ownerAbility = GetOwner(); + if (ownerAbility == nullptr) { + APP_LOGE("%{public}s error, owner ability is nullptr.", __func__); + errorCode = ERR_APPEXECFWK_FORM_NO_SUCH_ABILITY; + break; + } + + if (!CheckIsSystemApp()) { + APP_LOGE("%{public}s warn, caller permission denied.", __func__); + errorCode = ERR_APPEXECFWK_FORM_PERMISSION_DENY; + break; + } + + APP_LOGI("%{public}s come, %{public}s.", __func__, ownerAbility->GetAbilityName().c_str()); + ownerAbility->OnUpdate(formId); + } while (false); + + // The error code for disconnect. + int disconnectErrorCode = HandleDisconnect(want, callerToken); + if (errorCode != ERR_OK) { + // If errorCode is not ERR_OK,return errorCode. + return errorCode; + } else { + // If errorCode is ERR_OK,return disconnectErrorCode. + if (disconnectErrorCode != ERR_OK) { + APP_LOGE("%{public}s, disconnect error.", __func__); + } + return disconnectErrorCode; + } +} + +/** + * @brief Event notify when change the form visible. + * + * @param formIds The vector of form ids. + * @param formVisibleType The form visible type, including FORM_VISIBLE and FORM_INVISIBLE. + * @param want Indicates the structure containing form info. + * @param callerToken Caller ability token. + * @return Returns ERR_OK on success, others on failure. + */ +int FormProviderClient::EventNotify( + const std::vector &formIds, + const int32_t formVisibleType, const Want &want, + const sptr &callerToken) +{ + APP_LOGI("%{public}s called.", __func__); + + // The error code for business operation. + int errorCode = ERR_OK; + do { + std::shared_ptr ownerAbility = GetOwner(); + if (ownerAbility == nullptr) { + APP_LOGE("%{public}s error, owner ability is nullptr.", __func__); + errorCode = ERR_APPEXECFWK_FORM_NO_SUCH_ABILITY; + break; + } + + if (!CheckIsSystemApp()) { + APP_LOGW("%{public}s warn, caller permission denied.", __func__); + errorCode = ERR_APPEXECFWK_FORM_PERMISSION_DENY; + break; + } + + std::map formEventsMap; + for (const auto &formId : formIds) { + formEventsMap.insert(std::make_pair(formId, formVisibleType)); + } + + APP_LOGI("%{public}s come, %{public}s.", __func__, ownerAbility->GetAbilityName().c_str()); + ownerAbility->OnVisibilityChanged(formEventsMap); + } while (false); + + // The error code for disconnect. + int disconnectErrorCode = HandleDisconnect(want, callerToken); + if (errorCode != ERR_OK) { + // If errorCode is not ERR_OK,return errorCode. + return errorCode; + } else { + // If errorCode is ERR_OK,return disconnectErrorCode. + if (disconnectErrorCode != ERR_OK) { + APP_LOGE("%{public}s, disconnect error.", __func__); + } + return disconnectErrorCode; + } +} + +/** + * @brief Notify provider when the temp form was cast to normal form. + * @param formId The Id of the form to update. + * @param want Indicates the structure containing form info. + * @param callerToken Caller ability token. + * @return Returns ERR_OK on success, others on failure. + */ +int FormProviderClient::NotifyFormCastTempForm( + const int64_t formId, + const Want &want, + const sptr &callerToken) +{ + APP_LOGI("%{public}s called.", __func__); + // The error code for business operation. + int errorCode = ERR_OK; + do { + std::shared_ptr ownerAbility = GetOwner(); + if (ownerAbility == nullptr) { + APP_LOGE("%{public}s error, ownerAbility is nullptr.", __func__); + errorCode = ERR_APPEXECFWK_FORM_NO_SUCH_ABILITY; + break; + } + if (!CheckIsSystemApp()) { + APP_LOGW("%{public}s caller permission denied", __func__); + errorCode = ERR_APPEXECFWK_FORM_PERMISSION_DENY; + break; + } + + APP_LOGI("%{public}s come, %{public}s", __func__, ownerAbility->GetAbilityName().c_str()); + ownerAbility->OnCastTemptoNormal(formId); + } while (false); + + // The error code for disconnect. + int disconnectErrorCode = HandleDisconnect(want, callerToken); + if (errorCode != ERR_OK) { + // If errorCode is not ERR_OK,return errorCode. + return errorCode; + } else { + // If errorCode is ERR_OK,return disconnectErrorCode. + if (disconnectErrorCode != ERR_OK) { + APP_LOGE("%{public}s, disconnect error.", __func__); + } + return disconnectErrorCode; + } +} +/** + * @brief Fire message event to form provider. + * @param formId The Id of the from. + * @param message Event message. + * @param want The want of the request. + * @param callerToken Form provider proxy object. + * @return Returns ERR_OK on success, others on failure. + */ +int FormProviderClient::FireFormEvent( + const int64_t formId, + const std::string &message, + const Want &want, + const sptr &callerToken) +{ + APP_LOGI("%{public}s called.", __func__); + // The error code for business operation. + int errorCode = ERR_OK; + do { + std::shared_ptr ownerAbility = GetOwner(); + if (ownerAbility == nullptr) { + APP_LOGE("%{public}s error, ownerAbility is nullptr.", __func__); + errorCode = ERR_APPEXECFWK_FORM_NO_SUCH_ABILITY; + break; + } + if (!CheckIsSystemApp()) { + APP_LOGW("%{public}s caller permission denied", __func__); + errorCode = ERR_APPEXECFWK_FORM_PERMISSION_DENY; + break; + } + + APP_LOGI("%{public}s come, %{public}s", __func__, ownerAbility->GetAbilityName().c_str()); + ownerAbility->OnTriggerEvent(formId, message); + } while (false); + + // The error code for disconnect. + int disconnectErrorCode = HandleDisconnect(want, callerToken); + if (errorCode != ERR_OK) { + // If errorCode is not ERR_OK,return errorCode. + return errorCode; + } else { + // If errorCode is ERR_OK,return disconnectErrorCode. + if (disconnectErrorCode != ERR_OK) { + APP_LOGE("%{public}s, disconnect error.", __func__); + } + return disconnectErrorCode; + } +} +/** + * @brief Set the owner ability of the form provider client. + * + * @param ability The owner ability of the form provider client. + */ +void FormProviderClient::SetOwner(const std::shared_ptr ability) +{ + if (ability == nullptr) { + return; + } + + { + std::lock_guard lock(abilityMutex_); + owner_ = ability; + } +} + +/** + * @brief Clear the owner ability of the form provider client. + * + * @param ability The owner ability of the form provider client. + */ +void FormProviderClient::ClearOwner(const std::shared_ptr ability) +{ + if (ability == nullptr) { + return; + } + + { + std::lock_guard lock(abilityMutex_); + if (!owner_.expired()) { + std::shared_ptr ownerAbility = owner_.lock(); + if (ability == ownerAbility) { + owner_.reset(); + } + } + } +} + +std::shared_ptr FormProviderClient::GetOwner() +{ + std::shared_ptr ownerAbility = nullptr; + { + std::lock_guard lock(abilityMutex_); + if (!owner_.expired()) { + ownerAbility = owner_.lock(); + } + } + return ownerAbility; +} + +bool FormProviderClient::CheckIsSystemApp() const +{ + APP_LOGI("%{public}s called.", __func__); + + int32_t callingUid = IPCSkeleton::GetCallingUid(); + if (callingUid > Constants::MAX_SYSTEM_APP_UID) { + APP_LOGW("%{public}s warn, callingUid is %{public}d, which is larger than %{public}d.", __func__, callingUid, + Constants::MAX_SYSTEM_APP_UID); + return false; + } else { + APP_LOGD("%{public}s, callingUid = %{public}d.", __func__, callingUid); + return true; + } +} + +int FormProviderClient::HandleAcquire( + const FormProviderInfo &formProviderInfo, + const Want &newWant, + const sptr &callerToken) +{ + APP_LOGI("%{public}s start", __func__); + sptr formSupplyClient = iface_cast(callerToken); + if (formSupplyClient == nullptr) { + APP_LOGW("%{public}s warn, IFormSupply is nullptr", __func__); + return ERR_APPEXECFWK_FORM_BIND_PROVIDER_FAILED; + } + formSupplyClient->OnAcquire(formProviderInfo, newWant); + APP_LOGI("%{public}s end", __func__); + return ERR_OK; +} + +int FormProviderClient::HandleDisconnect(const Want &want, const sptr &callerToken) +{ + sptr formSupplyClient = iface_cast(callerToken); + if (formSupplyClient == nullptr) { + APP_LOGW("%{public}s warn, IFormSupply is nullptr", __func__); + return ERR_APPEXECFWK_FORM_BIND_PROVIDER_FAILED; + } + + APP_LOGD("%{public}s come, connectId: %{public}ld.", __func__, + want.GetLongParam(Constants::FORM_CONNECT_ID, 0L)); + + formSupplyClient->OnEventHandle(want); + return ERR_OK; +} +} // namespace AppExecFwk +} // namespace OHOS diff --git a/tools/frameworks/kits/ability/native/src/mission_information.cpp b/tools/frameworks/kits/ability/native/src/mission_information.cpp new file mode 100644 index 00000000000..4b24c1bdeae --- /dev/null +++ b/tools/frameworks/kits/ability/native/src/mission_information.cpp @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "string_ex.h" + +#include "mission_information.h" + +namespace OHOS { +namespace AppExecFwk { +bool MissionInformation::ReadFromParcel(Parcel &parcel) +{ + label = Str16ToStr8(parcel.ReadString16()); + iconPath = Str16ToStr8(parcel.ReadString16()); + + return true; +} +bool MissionInformation::Marshalling(Parcel &parcel) const +{ + parcel.WriteString16(Str8ToStr16(label)); + parcel.WriteString16(Str8ToStr16(iconPath)); + + return true; +} +MissionInformation *MissionInformation::Unmarshalling(Parcel &parcel) +{ + MissionInformation *info = new (std::nothrow) MissionInformation(); + if (info == nullptr) { + return nullptr; + } + + if (!info->ReadFromParcel(parcel)) { + delete info; + info = nullptr; + } + return info; +} +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/src/page_ability_impl.cpp b/tools/frameworks/kits/ability/native/src/page_ability_impl.cpp new file mode 100755 index 00000000000..84244afd5a1 --- /dev/null +++ b/tools/frameworks/kits/ability/native/src/page_ability_impl.cpp @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "page_ability_impl.h" +#include "app_log_wrapper.h" + +namespace OHOS { +namespace AppExecFwk { +using AbilityManagerClient = OHOS::AAFwk::AbilityManagerClient; +/** + * @brief Handling the life cycle switching of PageAbility. + * + * @param want Indicates the structure containing information about the ability. + * @param targetState The life cycle state to switch to. + * + */ +void PageAbilityImpl::HandleAbilityTransaction(const Want &want, const AAFwk::LifeCycleStateInfo &targetState) +{ + APP_LOGI("PageAbilityImpl::HandleAbilityTransaction begin sourceState:%{public}d; targetState: %{public}d; " + "isNewWant: %{public}d", + lifecycleState_, + targetState.state, + targetState.isNewWant); + if ((lifecycleState_ == targetState.state) && !targetState.isNewWant) { + APP_LOGE("Org lifeCycleState equals to Dst lifeCycleState."); + return; + } + + SetLifeCycleStateInfo(targetState); + + if (lifecycleState_ == AAFwk::ABILITY_STATE_INITIAL) { + ability_->SetStartAbilitySetting(targetState.setting); + Start(want); + CheckAndRestore(); + } + + if (lifecycleState_ == AAFwk::ABILITY_STATE_ACTIVE) { + Inactive(); + } + + bool ret = false; + ret = AbilityTransaction(want, targetState); + if (ret) { + APP_LOGI("AbilityThread::HandleAbilityTransaction before AbilityManagerClient->AbilityTransitionDone"); + AbilityManagerClient::GetInstance()->AbilityTransitionDone(token_, targetState.state); + APP_LOGI("AbilityThread::HandleAbilityTransaction after AbilityManagerClient->AbilityTransitionDone"); + } + APP_LOGI("PageAbilityImpl::HandleAbilityTransaction end"); +} + +/** + * @brief Handling the life cycle switching of PageAbility in switch. + * + * @param want Indicates the structure containing information about the ability. + * @param targetState The life cycle state to switch to. + * + * @return return true if the lifecycle transaction successfully, otherwise return false. + * + */ +bool PageAbilityImpl::AbilityTransaction(const Want &want, const AAFwk::LifeCycleStateInfo &targetState) +{ + APP_LOGI("PageAbilityImpl::AbilityTransaction begin"); + bool ret = true; + switch (targetState.state) { + case AAFwk::ABILITY_STATE_INITIAL: { + if (lifecycleState_ == AAFwk::ABILITY_STATE_INACTIVE) { + Background(); + } + Stop(); + break; + } + case AAFwk::ABILITY_STATE_INACTIVE: { + if (lifecycleState_ == AAFwk::ABILITY_STATE_BACKGROUND) { + Foreground(want); + } + break; + } + case AAFwk::ABILITY_STATE_ACTIVE: { + if (lifecycleState_ == AAFwk::ABILITY_STATE_BACKGROUND) { + Foreground(want); + } + if (targetState.isNewWant) { + NewWant(want); + } + SerUriString(targetState.caller.deviceId + "/" + targetState.caller.bundleName + "/" + + targetState.caller.abilityName); + Active(); + break; + } + case AAFwk::ABILITY_STATE_BACKGROUND: { + if (lifecycleState_ == AAFwk::ABILITY_STATE_INACTIVE) { + Background(); + } + break; + } + default: { + ret = false; + APP_LOGE("PageAbilityImpl::HandleAbilityTransaction state error"); + break; + } + } + APP_LOGI("PageAbilityImpl::AbilityTransaction end: retVal = %{public}d", (int)ret); + return ret; +} + +/** + * @brief Execution the KeyDown callback of the ability + * @param keyCode Indicates the code of the key pressed. + * @param keyEvent Indicates the key-down event. + * + * @return Returns true if this event is handled and will not be passed further; returns false if this event is + * not handled and should be passed to other handlers. + * + */ +bool PageAbilityImpl::DoKeyDown(int keyCode, const KeyEvent &keyEvent) +{ + APP_LOGI("PageAbilityImpl::DoKeyDown begin"); + if (ability_ == nullptr) { + APP_LOGE("PageAbilityImpl::DoKeyDown ability_ == nullptr"); + return false; + } + auto abilitInfo = ability_->GetAbilityInfo(); + APP_LOGI("PageAbilityImpl::DoKeyDown called %{public}s And Focus is %{public}s", + abilitInfo->name.c_str(), + ability_->HasWindowFocus() ? "true" : "false"); + + APP_LOGI("PageAbilityImpl::DoKeyDown end"); + return ability_->OnKeyDown(keyCode, keyEvent); +} + +/** + * @brief Execution the KeyUp callback of the ability + * @param keyCode Indicates the code of the key released. + * @param keyEvent Indicates the key-up event. + * + * @return Returns true if this event is handled and will not be passed further; returns false if this event is + * not handled and should be passed to other handlers. + * + */ +bool PageAbilityImpl::DoKeyUp(int keyCode, const KeyEvent &keyEvent) +{ + APP_LOGI("PageAbilityImpl::DoKeyUp begin"); + if (ability_ == nullptr) { + APP_LOGE("PageAbilityImpl::DoKeyUp ability_ == nullptr"); + return false; + } + auto abilitInfo = ability_->GetAbilityInfo(); + APP_LOGI("PageAbilityImpl::DoKeyUp called %{public}s And Focus is %{public}s", + abilitInfo->name.c_str(), + ability_->HasWindowFocus() ? "true" : "false"); + + APP_LOGI("PageAbilityImpl::DoKeyUp end"); + return ability_->OnKeyUp(keyCode, keyEvent); +} + +/** + * @brief Called when a touch event is dispatched to this ability. The default implementation of this callback + * does nothing and returns false. + * @param touchEvent Indicates information about the touch event. + * + * @return Returns true if the event is handled; returns false otherwise. + * + */ +bool PageAbilityImpl::DoTouchEvent(const TouchEvent &touchEvent) +{ + APP_LOGI("PageAbilityImpl::DoTouchEvent begin"); + if (ability_ == nullptr) { + APP_LOGE("PageAbilityImpl::DoTouchEvent ability_ == nullptr"); + return false; + } + auto abilitInfo = ability_->GetAbilityInfo(); + APP_LOGI("PageAbilityImpl::OnTouchEvent called %{public}s And Focus is %{public}s", + abilitInfo->name.c_str(), + ability_->HasWindowFocus() ? "true" : "false"); + + APP_LOGI("PageAbilityImpl::DoTouchEvent end"); + return ability_->OnTouchEvent(touchEvent); +} +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/src/service_ability_impl.cpp b/tools/frameworks/kits/ability/native/src/service_ability_impl.cpp new file mode 100644 index 00000000000..f4de8d11af4 --- /dev/null +++ b/tools/frameworks/kits/ability/native/src/service_ability_impl.cpp @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "service_ability_impl.h" +#include "app_log_wrapper.h" + +namespace OHOS { +namespace AppExecFwk { +using AbilityManagerClient = OHOS::AAFwk::AbilityManagerClient; +/** + * @brief Handling the life cycle switching of PageAbility. + * + * @param want Indicates the structure containing information about the ability. + * @param targetState The life cycle state to switch to. + * + */ +void ServiceAbilityImpl::HandleAbilityTransaction(const Want &want, const AAFwk::LifeCycleStateInfo &targetState) +{ + APP_LOGI("ServiceAbilityImpl::HandleAbilityTransaction begin sourceState:%{public}d; targetState: %{public}d; " + "isNewWant: %{public}d", + lifecycleState_, + targetState.state, + targetState.isNewWant); + if (lifecycleState_ == targetState.state) { + APP_LOGE("Org lifeCycleState equals to Dst lifeCycleState."); + return; + } + + bool ret = true; + + switch (targetState.state) { + case AAFwk::ABILITY_STATE_INITIAL: { + if (lifecycleState_ == AAFwk::ABILITY_STATE_ACTIVE) { + Background(); + Stop(); + } + break; + } + case AAFwk::ABILITY_STATE_INACTIVE: { + if (lifecycleState_ == AAFwk::ABILITY_STATE_INITIAL) { + SerUriString(targetState.caller.deviceId + "/" + targetState.caller.bundleName + "/" + + targetState.caller.abilityName); + Start(want); + } + break; + } + default: { + ret = false; + APP_LOGE("ServiceAbilityImpl::HandleAbilityTransaction state is error"); + break; + } + } + + if (ret) { + APP_LOGI("ServiceAbilityImpl::HandleAbilityTransaction before AbilityManagerClient->AbilityTransitionDone"); + AbilityManagerClient::GetInstance()->AbilityTransitionDone(token_, targetState.state); + APP_LOGI("ServiceAbilityImpl::HandleAbilityTransaction after AbilityManagerClient->AbilityTransitionDone"); + } + APP_LOGI("ServiceAbilityImpl::HandleAbilityTransaction end"); +} +} // namespace AppExecFwk +} // namespace OHOS diff --git a/tools/frameworks/kits/ability/native/src/task_handler.cpp b/tools/frameworks/kits/ability/native/src/task_handler.cpp new file mode 100644 index 00000000000..446aaecb5dd --- /dev/null +++ b/tools/frameworks/kits/ability/native/src/task_handler.cpp @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "task_handler.h" + +namespace OHOS { +namespace AppExecFwk { +TaskHandler::TaskHandler(const std::shared_ptr &runner) : EventHandler(runner) +{} + +/** + * Process the event. Developers should override this method. + * + * @param event The event should be processed. + */ +void TaskHandler::ProcessEvent([[maybe_unused]] const InnerEvent::Pointer &event) +{} +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/src/task_handler_client.cpp b/tools/frameworks/kits/ability/native/src/task_handler_client.cpp new file mode 100644 index 00000000000..ab05faaeef0 --- /dev/null +++ b/tools/frameworks/kits/ability/native/src/task_handler_client.cpp @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "task_handler_client.h" +#include "app_log_wrapper.h" +#include "hilog_wrapper.h" + +namespace OHOS { +namespace AppExecFwk { +std::shared_ptr TaskHandlerClient::instance_ = nullptr; +std::mutex TaskHandlerClient::mutex_; + +std::shared_ptr TaskHandlerClient::GetInstance() +{ + if (instance_ == nullptr) { + std::lock_guard lock_l(mutex_); + if (instance_ == nullptr) { + instance_ = std::make_shared(); + } + } + return instance_; +} + +TaskHandlerClient::TaskHandlerClient() +{} + +TaskHandlerClient::~TaskHandlerClient() +{} + +bool TaskHandlerClient::PostTask(std::function task, long delayTime) +{ + APP_LOGI("TaskHandlerClient::PostTask called"); + + if (taskHandler_ == nullptr) { + if (!CreateRunner()) { + APP_LOGE("TaskHandlerClient::PostTask failed, CreateRunner failed"); + return false; + } + } + + bool ret = taskHandler_->PostTask(task, delayTime, EventQueue::Priority::LOW); + if (!ret) { + APP_LOGE("TaskHandlerClient::PostTask failed, taskHandler_ PostTask failed"); + } + return ret; +} + +bool TaskHandlerClient::CreateRunner() +{ + if (taskHandler_ == nullptr) { + std::shared_ptr runner = EventRunner::Create("TaskRunner"); + if (runner == nullptr) { + APP_LOGE("TaskHandlerClient::CreateRunner failed, runner is nullptr"); + return false; + } + taskHandler_ = std::make_shared(runner); + if (taskHandler_ == nullptr) { + APP_LOGE("TaskHandlerClient::CreateRunner failed, taskHandler_ is nullptr"); + return false; + } + } + return true; +} +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/test/BUILD.gn b/tools/frameworks/kits/ability/native/test/BUILD.gn new file mode 100755 index 00000000000..f9487343eda --- /dev/null +++ b/tools/frameworks/kits/ability/native/test/BUILD.gn @@ -0,0 +1,980 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/test.gni") + +module_output_path = "aafwk_standard/ability_test" + +INNERKITS_PATH = "//foundation/aafwk/standard/interfaces/innerkits" + +############################################################################### +config("module_private_config") { + visibility = [ ":*" ] + include_dirs = [ + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_core/include/appmgr", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_core/include/bundlemgr", + "//foundation/aafwk/standard/interfaces/innerkits/want/include/ohos/aafwk_L2/content", + "//EOSP/communication/libsoftbus/../../../foundation/distributedschedule/dmsfwk/services/dtbschedmgr/include", + "//foundation/aafwk/standard/interfaces/innerkits/want/include/ohos/aafwk_L2/content", + "//foundation/aafwk/standard/frameworks/kits/ability/native/test/mock/include", + "//foundation/appexecfwk/standard/kits/appkit/native/test/mock/include", + "//foundation/aafwk/standard/interfaces/innerkits/ability_manager/include", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy/include", + "//foundation/aafwk/standard/services/abilitymgr/include", + "//utils/system/safwk/native/include", + "//foundation/appexecfwk/standard/kits/appkit/native/app/include", + "//foundation/appexecfwk/standard/interfaces/innerkits/fmskit/native/include", + "//foundation/aafwk/standard/interfaces/innerkits/want/include/ohos/aafwk/content", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base/include", + "//foundation/distributedschedule/dmsfwk/services/dtbschedmgr/include", + "//foundation/distributeddatamgr/distributeddatamgr/interfaces/innerkits/app_distributeddata/include", + "//foundation/aafwk/standard/frameworks/kits/ability/native/include", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler/include", + "//foundation/aafwk/standard/services/common/include", + + "//foundation/appexecfwk/standard/interfaces/innerkits/task_dispatcher/include/dispatcher", + "//foundation/appexecfwk/standard/interfaces/innerkits/task_dispatcher/include/task", + "//foundation/appexecfwk/standard/interfaces/innerkits/task_dispatcher/include/threading", + "//foundation/appexecfwk/standard/kits/appkit/native/app/include/task", + ] + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + defines = [ + "APP_LOG_TAG = \"AbilityUnitTest\"", + "LOG_DOMAIN = 0xD002201", + ] +} + +config("module_ability_context_config") { + visibility = [ ":*" ] + include_dirs = [ + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_core/include/appmgr", + "//EOSP/communication/libsoftbus/../../../foundation/distributedschedule/dmsfwk/services/dtbschedmgr/include", + "//foundation/aafwk/standard/interfaces/innerkits/want/include/ohos/aafwk/content", + "//foundation/aafwk/standard/frameworks/kits/ability/native/test/mock/include", + "//foundation/appexecfwk/standard/kits/appkit/native/test/mock/include", + "//foundation/aafwk/standard/interfaces/innerkits/ability_manager/include", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy/include", + "//third_party/googletest/googlemock/include", + "//foundation/aafwk/standard/frameworks/kits/ability/native/include", + "//foundation/appexecfwk/standard/kits/appkit/native/app/include", + "//foundation/communication/ipc/interfaces/innerkits/ipc_core/include", + "//foundation/multimodalinput/input/interfaces/native/innerkits/event/include", + "//foundation/aafwk/standard/interfaces/innerkits/base/include", + "//third_party/libuv/include", + "//foundation/aafwk/standard/interfaces/innerkits/base/include/ohos/aafwk/base", + "//base/global/resmgr_standard/interfaces/innerkits/include", + ] + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + defines = [ + "APP_LOG_TAG = \"AbilityUnitTest\"", + "LOG_DOMAIN = 0xD002201", + ] +} + +ohos_unittest("ability_test") { + module_out_path = module_output_path + sources = [ + "//foundation/appexecfwk/standard/kits/appkit/native/app/src/app_loader.cpp", + "//foundation/appexecfwk/standard/kits/appkit/native/app/src/application_context.cpp", + "//foundation/appexecfwk/standard/kits/appkit/native/app/src/ohos_application.cpp", + "unittest/ability_test.cpp", + ] + + configs = [ ":module_private_config" ] + + deps = [ + "${INNERKITS_PATH}/want:want", + "//base/global/resmgr_standard/frameworks/resmgr:global_resmgr", + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/interfaces/innerkits/ability_manager:ability_manager", + "//foundation/aafwk/standard/interfaces/innerkits/base:base", + "//foundation/aafwk/standard/interfaces/innerkits/base:base", + "//foundation/appexecfwk/standard/common:libappexecfwk_common", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/appexecfwk/standard/interfaces/innerkits/task_dispatcher:appkit_dispatcher_td", + "//foundation/appexecfwk/standard/interfaces/innerkits/task_dispatcher:appkit_dispatcher_td", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy:samgr_proxy", + "//foundation/graphic/standard:libwmclient", + "//foundation/multimodalinput/input/interfaces/native/innerkits/event:mmi_event", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] +} + +ohos_unittest("ability_lifecycle_test") { + module_out_path = module_output_path + sources = [ + "../src/ability_lifecycle.cpp", + "unittest/ability_lifecycle_test.cpp", + ] + + configs = [ ":module_private_config" ] + + deps = [ + "${INNERKITS_PATH}/want:want", + "//base/global/resmgr_standard/frameworks/resmgr:global_resmgr", + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/interfaces/innerkits/ability_manager:ability_manager", + "//foundation/aafwk/standard/interfaces/innerkits/base:base", + "//foundation/aafwk/standard/interfaces/innerkits/base:base", + "//foundation/appexecfwk/standard/common:libappexecfwk_common", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy:samgr_proxy", + "//foundation/multimodalinput/input/interfaces/native/innerkits/event:mmi_event", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] +} + +ohos_unittest("ability_lifecycle_executor_test") { + module_out_path = module_output_path + sources = [ + "../src/ability_lifecycle_executor.cpp", + "unittest/ability_lifecycle_executor_test.cpp", + ] + + configs = [ ":module_private_config" ] + + deps = [ + "${INNERKITS_PATH}/want:want", + "//base/global/resmgr_standard/frameworks/resmgr:global_resmgr", + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/interfaces/innerkits/ability_manager:ability_manager", + "//foundation/aafwk/standard/interfaces/innerkits/base:base", + "//foundation/aafwk/standard/interfaces/innerkits/base:base", + "//foundation/appexecfwk/standard/common:libappexecfwk_common", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy:samgr_proxy", + "//foundation/multimodalinput/input/interfaces/native/innerkits/event:mmi_event", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] +} + +ohos_unittest("ability_context_for_task_dispacher_test") { + module_out_path = module_output_path + sources = [ "unittest/ability_context_for_task_dispacher_test.cpp" ] + + include_dirs = [ "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler/include" ] + + configs = [ ":module_ability_context_config" ] + + deps = [ + "${INNERKITS_PATH}/want:want", + "//base/global/resmgr_standard/frameworks/resmgr:global_resmgr", + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/frameworks/kits/ability/native:dummy_classes", + "//foundation/aafwk/standard/interfaces/innerkits/ability_manager:ability_manager", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/appexecfwk/standard/interfaces/innerkits/task_dispatcher:appkit_dispatcher_td", + "//foundation/appexecfwk/standard/kits:appkit_native", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy:samgr_proxy", + "//foundation/multimodalinput/input/interfaces/native/innerkits/event:mmi_event", + "//third_party/googletest:gmock_main", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] +} + +ohos_unittest("ability_context_interface_test") { + module_out_path = module_output_path + sources = [ + "mock/include/mock_ability_manager_client_interface1.cpp", + "mock/include/mock_resourceManager_interface1.cpp", + "unittest/ability_context_interface1_test.cpp", + ] + + configs = [ ":module_ability_context_config" ] + + deps = [ + "${INNERKITS_PATH}/want:want", + "//base/global/resmgr_standard/frameworks/resmgr:global_resmgr", + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/frameworks/kits/ability/native:dummy_classes", + "//foundation/aafwk/standard/interfaces/innerkits/ability_manager:ability_manager", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/appexecfwk/standard/kits:appkit_native", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy:samgr_proxy", + "//foundation/multimodalinput/input/interfaces/native/innerkits/event:mmi_event", + "//third_party/googletest:gmock_main", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] +} + +ohos_unittest("ability_context_test") { + module_out_path = module_output_path + sources = [ + "mock/include/mock_ability_manager_clientex.cpp", + "mock/include/mock_ability_manager_service.cpp", + "mock/include/mock_bundle_manager.cpp", + "mock/include/sys_mgr_client_mock.cpp", + "unittest/ability_context_test.cpp", + ] + + configs = [ ":module_ability_context_config" ] + + deps = [ + "${INNERKITS_PATH}/want:want", + "//base/global/resmgr_standard/frameworks/resmgr:global_resmgr", + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/frameworks/kits/ability/native:dummy_classes", + "//foundation/aafwk/standard/interfaces/innerkits/ability_manager:ability_manager", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/appexecfwk/standard/kits:appkit_native", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy:samgr_proxy", + "//foundation/multimodalinput/input/interfaces/native/innerkits/event:mmi_event", + "//third_party/googletest:gmock_main", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] +} + +ohos_unittest("page_ability_impl_test") { + module_out_path = module_output_path + sources = [ + "../src/page_ability_impl.cpp", + "//foundation/aafwk/standard/frameworks/kits/ability/native/test/mock/include/mock_replace_ability_impl.cpp", + "unittest/page_ability_impl_test.cpp", + ] + + configs = [ ":module_private_config" ] + + deps = [ + "${INNERKITS_PATH}/want:want", + "//base/global/resmgr_standard/frameworks/resmgr:global_resmgr", + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/interfaces/innerkits/ability_manager:ability_manager", + "//foundation/aafwk/standard/interfaces/innerkits/base:base", + "//foundation/appexecfwk/standard/common:libappexecfwk_common", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/appexecfwk/standard/kits:appkit_native", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy:samgr_proxy", + "//foundation/multimodalinput/input/interfaces/native/innerkits/event:mmi_event", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] +} + +ohos_unittest("service_ability_impl_test") { + module_out_path = module_output_path + sources = [ + "../src/page_ability_impl.cpp", + "unittest/service_ability_impl_test.cpp", + ] + + configs = [ ":module_private_config" ] + + deps = [ + "${INNERKITS_PATH}/want:want", + "//base/global/resmgr_standard/frameworks/resmgr:global_resmgr", + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/interfaces/innerkits/ability_manager:ability_manager", + "//foundation/aafwk/standard/interfaces/innerkits/base:base", + "//foundation/appexecfwk/standard/common:libappexecfwk_common", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/appexecfwk/standard/kits:appkit_native", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy:samgr_proxy", + "//foundation/multimodalinput/input/interfaces/native/innerkits/event:mmi_event", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] +} + +ohos_unittest("data_ability_helper_test") { + module_out_path = module_output_path + include_dirs = [ "//foundation/aafwk/standard/services/abilitymgr/include" ] + + sources = [ "unittest/data_ability_helper_test.cpp" ] + + configs = [ ":module_ability_context_config" ] + + deps = [ + "${INNERKITS_PATH}/want:want", + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/frameworks/kits/ability/native:dummy_classes", + "//foundation/aafwk/standard/interfaces/innerkits/ability_manager:ability_manager", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//third_party/googletest:gmock_main", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + "native_appdatamgr:native_appdatafwk", + "native_appdatamgr:native_dataability", + "native_appdatamgr:native_rdb", + ] +} + +ohos_unittest("data_ability_operation_test") { + module_out_path = module_output_path + sources = [ "unittest/data_ability_operation_test.cpp" ] + + configs = [ ":module_private_config" ] + + deps = [ + "${INNERKITS_PATH}/want:want", + "//base/global/resmgr_standard/frameworks/resmgr:global_resmgr", + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/frameworks/kits/ability/native:dummy_classes", + "//foundation/aafwk/standard/interfaces/innerkits/base:base", + "//foundation/appexecfwk/standard/common:libappexecfwk_common", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/appexecfwk/standard/kits:appkit_native", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy:samgr_proxy", + "//foundation/multimodalinput/input/interfaces/native/innerkits/event:mmi_event", + "//third_party/googletest:gmock_main", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + "native_appdatamgr:native_appdatafwk", + "native_appdatamgr:native_dataability", + "native_appdatamgr:native_rdb", + ] +} + +ohos_unittest("ability_impl_active_test") { + module_out_path = module_output_path + sources = [ + "//foundation/appexecfwk/standard/kits/appkit/native/app/src/app_loader.cpp", + "//foundation/appexecfwk/standard/kits/appkit/native/app/src/application_context.cpp", + "//foundation/appexecfwk/standard/kits/appkit/native/app/src/ohos_application.cpp", + "unittest/ability_impl_active_test.cpp", + ] + + configs = [ ":module_private_config" ] + + deps = [ + "${INNERKITS_PATH}/want:want", + "//base/global/resmgr_standard/frameworks/resmgr:global_resmgr", + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/interfaces/innerkits/ability_manager:ability_manager", + "//foundation/aafwk/standard/interfaces/innerkits/base:base", + "//foundation/appexecfwk/standard/common:libappexecfwk_common", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/appexecfwk/standard/interfaces/innerkits/task_dispatcher:appkit_dispatcher_td", + "//foundation/appexecfwk/standard/kits:appkit_native", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy:samgr_proxy", + "//foundation/multimodalinput/input/interfaces/native/innerkits/event:mmi_event", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] +} + +ohos_unittest("ability_impl_test") { + module_out_path = module_output_path + sources = [ + "//foundation/appexecfwk/standard/kits/appkit/native/app/src/app_loader.cpp", + "//foundation/appexecfwk/standard/kits/appkit/native/app/src/application_context.cpp", + "//foundation/appexecfwk/standard/kits/appkit/native/app/src/ohos_application.cpp", + "unittest/ability_impl_test.cpp", + ] + + configs = [ ":module_private_config" ] + + deps = [ + "${INNERKITS_PATH}/want:want", + "//base/global/resmgr_standard/frameworks/resmgr:global_resmgr", + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/interfaces/innerkits/ability_manager:ability_manager", + "//foundation/aafwk/standard/interfaces/innerkits/base:base", + "//foundation/appexecfwk/standard/common:libappexecfwk_common", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/appexecfwk/standard/interfaces/innerkits/task_dispatcher:appkit_dispatcher_td", + "//foundation/appexecfwk/standard/interfaces/innerkits/task_dispatcher:appkit_dispatcher_td", + "//foundation/appexecfwk/standard/kits:appkit_native", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy:samgr_proxy", + "//foundation/multimodalinput/input/interfaces/native/innerkits/event:mmi_event", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + "native_appdatamgr:native_appdatafwk", + "native_appdatamgr:native_dataability", + "native_appdatamgr:native_rdb", + ] +} + +ohos_unittest("ability_thread_test") { + module_out_path = module_output_path + sources = [ + "//foundation/aafwk/standard/frameworks/kits/ability/native/test/mock/include/mock_data_ability_impl.cpp", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_core/src/appmgr/process_info.cpp", + "//foundation/appexecfwk/standard/kits/appkit/native/app/src/app_loader.cpp", + "//foundation/appexecfwk/standard/kits/appkit/native/app/src/application_context.cpp", + "//foundation/appexecfwk/standard/kits/appkit/native/app/src/context_container.cpp", + "//foundation/appexecfwk/standard/kits/appkit/native/app/src/context_deal.cpp", + "//foundation/appexecfwk/standard/kits/appkit/native/app/src/ohos_application.cpp", + "//foundation/distributedschedule/dmsfwk/services/dtbschedmgr/include/uri.h", + "mock/include/mock_ability_manager_client.cpp", + "mock/include/sys_mgr_client_mock.cpp", + "unittest/ability_thread_test.cpp", + ] + + configs = [ ":module_private_config" ] + + deps = [ + "${INNERKITS_PATH}/want:want", + "//base/global/resmgr_standard/frameworks/resmgr:global_resmgr", + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/frameworks/kits/ability/native:dummy_classes", + "//foundation/aafwk/standard/interfaces/innerkits/ability_manager:ability_manager", + "//foundation/aafwk/standard/interfaces/innerkits/base:base", + "//foundation/appexecfwk/standard/common:libappexecfwk_common", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/appexecfwk/standard/interfaces/innerkits/task_dispatcher:appkit_dispatcher_td", + "//foundation/appexecfwk/standard/interfaces/innerkits/task_dispatcher:appkit_dispatcher_td", + "//foundation/appexecfwk/standard/kits:appkit_native", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy:samgr_proxy", + "//foundation/graphic/standard:libwmclient", + "//foundation/multimodalinput/input/interfaces/native/innerkits/event:mmi_event", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + "native_appdatamgr:native_appdatafwk", + "native_appdatamgr:native_dataability", + "native_appdatamgr:native_rdb", + ] +} + +ohos_unittest("form_provider_client_test") { + module_out_path = module_output_path + include_dirs = [ + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base/include", + "//foundation/appexecfwk/appexecfwk_lite/interfaces/kits/bundle_lite", + ] + + sources = [ + "mock/include/mock_form_supply_callback.cpp", + "unittest/form_provider_client_test.cpp", + ] + + configs = [ ":module_private_config" ] + + deps = [ + "${INNERKITS_PATH}/want:want", + "//base/global/resmgr_standard/frameworks/resmgr:global_resmgr", + "//base/security/permission/interfaces/innerkits/permission_standard/permissionsdk:libpermissionsdk_standard", + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/interfaces/innerkits/ability_manager:ability_manager", + "//foundation/aafwk/standard/interfaces/innerkits/base:base", + "//foundation/aafwk/standard/interfaces/innerkits/base:base", + "//foundation/appexecfwk/standard/common:libappexecfwk_common", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_core:appexecfwk_core", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy:samgr_proxy", + "//foundation/graphic/standard:libwmclient", + "//foundation/multimodalinput/input/interfaces/native/innerkits/event:mmi_event", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] +} + +ohos_unittest("data_ability_impl_test") { + module_out_path = module_output_path + sources = [ + "//foundation/aafwk/standard/frameworks/kits/ability/native/test/mock/include/mock_replace_ability_impl.cpp", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_core/src/appmgr/process_info.cpp", + "//foundation/appexecfwk/standard/kits/appkit/native/app/src/app_loader.cpp", + "//foundation/appexecfwk/standard/kits/appkit/native/app/src/application_context.cpp", + "//foundation/appexecfwk/standard/kits/appkit/native/app/src/context_container.cpp", + "//foundation/appexecfwk/standard/kits/appkit/native/app/src/context_deal.cpp", + "//foundation/appexecfwk/standard/kits/appkit/native/app/src/ohos_application.cpp", + "//foundation/distributedschedule/dmsfwk/services/dtbschedmgr/include/uri.h", + "unittest/data_ability_impl_test.cpp", + ] + + configs = [ ":module_private_config" ] + + deps = [ + "${INNERKITS_PATH}/want:want", + "//base/global/resmgr_standard/frameworks/resmgr:global_resmgr", + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/frameworks/kits/ability/native:dummy_classes", + "//foundation/aafwk/standard/interfaces/innerkits/ability_manager:ability_manager", + "//foundation/appexecfwk/standard/common:libappexecfwk_common", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/appexecfwk/standard/interfaces/innerkits/task_dispatcher:appkit_dispatcher_td", + "//foundation/appexecfwk/standard/interfaces/innerkits/task_dispatcher:appkit_dispatcher_td", + "//foundation/appexecfwk/standard/kits:appkit_native", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy:samgr_proxy", + "//foundation/graphic/standard:libwmclient", + "//foundation/multimodalinput/input/interfaces/native/innerkits/event:mmi_event", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + "native_appdatamgr:native_appdatafwk", + "native_appdatamgr:native_dataability", + "native_appdatamgr:native_rdb", + ] +} + +ohos_unittest("data_ability_impl_file_secondpart_test") { + module_out_path = module_output_path + sources = [ + "//foundation/aafwk/standard/frameworks/kits/ability/native/test/mock/include/mock_replace_ability_impl.cpp", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_core/src/appmgr/process_info.cpp", + "//foundation/appexecfwk/standard/kits/appkit/native/app/src/app_loader.cpp", + "//foundation/appexecfwk/standard/kits/appkit/native/app/src/application_context.cpp", + "//foundation/appexecfwk/standard/kits/appkit/native/app/src/context_container.cpp", + "//foundation/appexecfwk/standard/kits/appkit/native/app/src/context_deal.cpp", + "//foundation/appexecfwk/standard/kits/appkit/native/app/src/ohos_application.cpp", + "//foundation/distributedschedule/dmsfwk/services/dtbschedmgr/include/uri.h", + "unittest/data_ability_impl_file_secondpart_test.cpp", + ] + + configs = [ ":module_private_config" ] + + deps = [ + "${INNERKITS_PATH}/want:want", + "//base/global/resmgr_standard/frameworks/resmgr:global_resmgr", + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/frameworks/kits/ability/native:dummy_classes", + "//foundation/aafwk/standard/interfaces/innerkits/ability_manager:ability_manager", + "//foundation/appexecfwk/standard/common:libappexecfwk_common", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/appexecfwk/standard/interfaces/innerkits/task_dispatcher:appkit_dispatcher_td", + "//foundation/appexecfwk/standard/interfaces/innerkits/task_dispatcher:appkit_dispatcher_td", + "//foundation/appexecfwk/standard/kits:appkit_native", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy:samgr_proxy", + "//foundation/graphic/standard:libwmclient", + "//foundation/multimodalinput/input/interfaces/native/innerkits/event:mmi_event", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + "native_appdatamgr:native_appdatafwk", + "native_appdatamgr:native_dataability", + "native_appdatamgr:native_rdb", + ] +} + +ohos_unittest("data_ability_impl_file_test") { + module_out_path = module_output_path + sources = [ + "//foundation/aafwk/standard/frameworks/kits/ability/native/test/mock/include/mock_replace_ability_impl.cpp", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_core/src/appmgr/process_info.cpp", + "//foundation/appexecfwk/standard/kits/appkit/native/app/src/app_loader.cpp", + "//foundation/appexecfwk/standard/kits/appkit/native/app/src/application_context.cpp", + "//foundation/appexecfwk/standard/kits/appkit/native/app/src/context_container.cpp", + "//foundation/appexecfwk/standard/kits/appkit/native/app/src/context_deal.cpp", + "//foundation/appexecfwk/standard/kits/appkit/native/app/src/ohos_application.cpp", + "//foundation/distributedschedule/dmsfwk/services/dtbschedmgr/include/uri.h", + "unittest/data_ability_impl_file_test.cpp", + ] + + configs = [ ":module_private_config" ] + + deps = [ + "${INNERKITS_PATH}/want:want", + "//base/global/resmgr_standard/frameworks/resmgr:global_resmgr", + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/frameworks/kits/ability/native:dummy_classes", + "//foundation/aafwk/standard/interfaces/innerkits/ability_manager:ability_manager", + "//foundation/appexecfwk/standard/common:libappexecfwk_common", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/appexecfwk/standard/interfaces/innerkits/task_dispatcher:appkit_dispatcher_td", + "//foundation/appexecfwk/standard/interfaces/innerkits/task_dispatcher:appkit_dispatcher_td", + "//foundation/appexecfwk/standard/kits:appkit_native", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy:samgr_proxy", + "//foundation/graphic/standard:libwmclient", + "//foundation/multimodalinput/input/interfaces/native/innerkits/event:mmi_event", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + "native_appdatamgr:native_appdatafwk", + "native_appdatamgr:native_dataability", + "native_appdatamgr:native_rdb", + ] +} + +ohos_unittest("ability_thread_dataability_test") { + module_out_path = module_output_path + sources = [ + "//foundation/aafwk/standard/frameworks/kits/ability/native/test/mock/include/mock_data_ability_impl.cpp", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_core/src/appmgr/process_info.cpp", + "//foundation/appexecfwk/standard/kits/appkit/native/app/src/app_loader.cpp", + "//foundation/appexecfwk/standard/kits/appkit/native/app/src/application_context.cpp", + "//foundation/appexecfwk/standard/kits/appkit/native/app/src/context_container.cpp", + "//foundation/appexecfwk/standard/kits/appkit/native/app/src/context_deal.cpp", + "//foundation/appexecfwk/standard/kits/appkit/native/app/src/ohos_application.cpp", + "//foundation/distributedschedule/dmsfwk/services/dtbschedmgr/include/uri.h", + "mock/include/mock_ability_manager_client.cpp", + "mock/include/sys_mgr_client_mock.cpp", + "unittest/ability_thread_dataability_test.cpp", + ] + + configs = [ ":module_private_config" ] + + deps = [ + "${INNERKITS_PATH}/want:want", + "//base/global/resmgr_standard/frameworks/resmgr:global_resmgr", + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/frameworks/kits/ability/native:dummy_classes", + "//foundation/aafwk/standard/interfaces/innerkits/ability_manager:ability_manager", + "//foundation/aafwk/standard/interfaces/innerkits/base:base", + "//foundation/appexecfwk/standard/common:libappexecfwk_common", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/appexecfwk/standard/interfaces/innerkits/task_dispatcher:appkit_dispatcher_td", + "//foundation/appexecfwk/standard/interfaces/innerkits/task_dispatcher:appkit_dispatcher_td", + "//foundation/appexecfwk/standard/kits:appkit_native", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy:samgr_proxy", + "//foundation/graphic/standard:libwmclient", + "//foundation/multimodalinput/input/interfaces/native/innerkits/event:mmi_event", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + "native_appdatamgr:native_appdatafwk", + "native_appdatamgr:native_dataability", + "native_appdatamgr:native_rdb", + ] +} + +config("data_uri_utils_test_config") { + visibility = [ ":*" ] + include_dirs = + [ "//foundation/aafwk/standard/frameworks/kits/ability/native/include/" ] + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + defines = [ + "APP_LOG_TAG = \"AbilityUnitTest\"", + "LOG_DOMAIN = 0xD002201", + ] +} +ohos_unittest("data_uri_utils_test") { + module_out_path = module_output_path + + configs = [ + ":module_private_config", + ":data_uri_utils_test_config", + ] + + sources = [ + "//foundation/aafwk/standard/frameworks/kits/ability/native/src/data_uri_utils.cpp", + "//foundation/aafwk/standard/frameworks/kits/ability/native/test/unittest/data_uri_utils_test.cpp", + "//foundation/distributedschedule/dmsfwk/utils/native/source/uri.cpp", + ] + + deps = [ + "//foundation/appexecfwk/standard/common:libappexecfwk_common", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/appexecfwk/standard/kits:appkit_native", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] +} + +ohos_unittest("pac_map_test") { + module_out_path = module_output_path + sources = [ "//foundation/aafwk/standard/frameworks/kits/ability/native/test/unittest/pac_map_test.cpp" ] + + configs = [ ":module_private_config" ] + + deps = [ + "${INNERKITS_PATH}/want:want", + "//foundation/aafwk/standard/interfaces/innerkits/base:base", + "//foundation/appexecfwk/standard/common:libappexecfwk_common", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] +} + +ohos_unittest("ability_permission_test") { + module_out_path = module_output_path + sources = [ + "//foundation/aafwk/standard/frameworks/kits/ability/native/test/unittest/ability_permission_test.cpp", + "mock/include/mock_ability_manager_service.cpp", + "mock/include/mock_bundle_manager.cpp", + "mock/include/sys_mgr_client_mock.cpp", + ] + + configs = [ ":module_ability_context_config" ] + + deps = [ + "${INNERKITS_PATH}/want:want", + "//base/global/resmgr_standard/frameworks/resmgr:global_resmgr", + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/interfaces/innerkits/ability_manager:ability_manager", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/appexecfwk/standard/kits:appkit_native", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy:samgr_proxy", + "//third_party/googletest:gmock_main", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] +} + +ohos_unittest("task_handler_client_test") { + module_out_path = module_output_path + sources = [ "//foundation/aafwk/standard/frameworks/kits/ability/native/test/unittest/task_handler_client_test.cpp" ] + + configs = [ ":module_private_config" ] + + deps = [ + "${INNERKITS_PATH}/want:want", + "//foundation/aafwk/standard/interfaces/innerkits/ability_manager:ability_manager", + "//foundation/aafwk/standard/interfaces/innerkits/base:base", + "//foundation/appexecfwk/standard/common:libappexecfwk_common", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ "hiviewdfx_hilog_native:libhilog" ] +} + +ohos_unittest("ability_thread_for_ability_on_configuration_update") { + module_out_path = module_output_path + + sources = [ "//foundation/aafwk/standard/frameworks/kits/ability/native/test/unittest/ability_thread_for_ability_on_configuration_update.cpp" ] + + configs = [ ":module_private_config" ] + + deps = [ + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/interfaces/innerkits/ability_manager:ability_manager", + "//foundation/aafwk/standard/interfaces/innerkits/want:want", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/appexecfwk/standard/kits:appkit_native", + "//third_party/googletest:gmock_main", + "//third_party/googletest:gtest_main", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] +} + +ohos_unittest("data_ability_result_test") { + module_out_path = module_output_path + sources = [ "//foundation/aafwk/standard/frameworks/kits/ability/native/test/unittest/data_ability_result_test.cpp" ] + + configs = [ ":module_private_config" ] + + deps = [ + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/appexecfwk/standard/common:libappexecfwk_common", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//third_party/googletest:gtest_main", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] +} + +ohos_unittest("form_host_client_test") { + module_out_path = module_output_path + sources = [ + "//foundation/aafwk/standard/services/abilitymgr/src/ability_start_setting.cpp", + "//foundation/appexecfwk/standard/kits/appkit/native/app/src/app_loader.cpp", + "//foundation/appexecfwk/standard/kits/appkit/native/app/src/application_context.cpp", + "//foundation/appexecfwk/standard/kits/appkit/native/app/src/ohos_application.cpp", + "mock/include/mock_bundle_manager_form.cpp", + "unittest/form_host_client_test.cpp", + ] + + configs = [ ":module_private_config" ] + + deps = [ + "${INNERKITS_PATH}/want:want", + "//base/global/resmgr_standard/frameworks/resmgr:global_resmgr", + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/interfaces/innerkits/ability_manager:ability_manager", + "//foundation/aafwk/standard/interfaces/innerkits/base:base", + "//foundation/appexecfwk/standard/common:libappexecfwk_common", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_core:appexecfwk_core", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/appexecfwk/standard/interfaces/innerkits/task_dispatcher:appkit_dispatcher_td", + "//foundation/appexecfwk/standard/interfaces/innerkits/task_dispatcher:appkit_dispatcher_td", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy:samgr_proxy", + "//foundation/graphic/standard:libwmclient", + "//foundation/multimodalinput/input/interfaces/native/innerkits/event:mmi_event", + "//third_party/googletest:gmock_main", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "appexecfwk_standard:fmskit_native", + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] +} + +############################################################################### + +group("unittest") { + testonly = true + deps = [] + + deps += [ + ":ability_context_test", + ":ability_impl_test", + ":ability_lifecycle_executor_test", + ":ability_lifecycle_test", + ":ability_permission_test", + ":ability_test", + ":ability_thread_dataability_test", + ":ability_thread_test", + ":data_ability_helper_test", + ":data_ability_impl_file_secondpart_test", + ":data_ability_impl_file_test", + ":data_ability_impl_test", + ":data_ability_operation_test", + ":data_ability_result_test", + ":data_uri_utils_test", + ":form_host_client_test", + ":form_provider_client_test", + ":pac_map_test", + ":page_ability_impl_test", + ":service_ability_impl_test", + ":task_handler_client_test", + ] +} +############################################################################### diff --git a/tools/frameworks/kits/ability/native/test/mock/include/bundle_mgr_interface.h b/tools/frameworks/kits/ability/native/test/mock/include/bundle_mgr_interface.h new file mode 100644 index 00000000000..7d5c9febf86 --- /dev/null +++ b/tools/frameworks/kits/ability/native/test/mock/include/bundle_mgr_interface.h @@ -0,0 +1,263 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_APPEXECFWK_INTERFACES_INNERKITS_BUNDLEMGR_INCLUDE_MOCK_BUNDLE_MGR_INTERFACE_H +#define FOUNDATION_APPEXECFWK_INTERFACES_INNERKITS_BUNDLEMGR_INCLUDE_MOCK_BUNDLE_MGR_INTERFACE_H + +#include "ability_info.h" +#include "application_info.h" +#include "iremote_broker.h" +#include "iremote_object.h" + +#include "bundle_info.h" +#include "hap_module_info.h" +#include "ohos/aafwk/content/want.h" +#include "permission_def.h" +#include "module_usage_record.h" + +using OHOS::AAFwk::Want; + +namespace OHOS { +namespace AppExecFwk { +enum class DumpFlag { + DUMP_BUNDLE_LIST = 1, + DUMP_ALL_BUNDLE_INFO, + DUMP_BUNDLE_INFO, +}; + +enum class InstallFlag { + NORMAL = 0, + // Allow to replace the existing bundle when the new version isn't lower than the old one. + // If the bundle does not exist, just like normal flag. + REPLACE_EXISTING = 1, +}; + +enum class InstallLocation { + INTERNAL_ONLY = 1, + PREFER_EXTERNAL = 2, +}; + +struct InstallParam : public Parcelable { + InstallFlag installFlag = InstallFlag::NORMAL; + InstallLocation installLocation = InstallLocation::INTERNAL_ONLY; + int userId = -1; + // Is keep user data while uninstall. + bool isKeepData = false; + bool noCheckSignature = false; + + // the parcel object function is not const. + bool ReadFromParcel(Parcel &parcel); + virtual bool Marshalling(Parcel &parcel) const override; + static InstallParam *Unmarshalling(Parcel &parcel); +}; +class IBundleStatusCallback : public IRemoteBroker { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"ohos.appexecfwk.BundleStatusCallback"); + + virtual void OnBundleStateChanged(const uint8_t installType, const int32_t resultCode, const std::string &resultMsg, + const std::string &bundleName) = 0; + + enum class Message { + ON_BUNDLE_STATE_CHANGED, + }; +}; + +class ICleanCacheCallback : public IRemoteBroker { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"ohos.appexecfwk.CleanCacheCallback"); + + virtual void OnCleanCacheFinished(bool succeeded) = 0; + + enum class Message { + ON_CLEAN_CACHE_CALLBACK, + }; +}; + +class OnPermissionChangedCallback : public IRemoteBroker { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"ohos.appexecfwk.OnPermissionChangedCallback"); + /** + * @brief Called when an application's permission changed. + * @param uid Indicates the uid of the application which permission changed. + */ + virtual void OnChanged(const int32_t uid) = 0; + + enum class Message { + ON_CHANGED, + }; +}; + +class IStatusReceiver : public IRemoteBroker { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"ohos.appexecfwk.StatusReceiver"); + + virtual void OnStatusNotify(const int progress) = 0; + virtual void OnFinished(const int32_t resultCode, const std::string &resultMsg) = 0; + + enum class Message { + ON_STATUS_NOTIFY, + ON_FINISHED, + }; + + enum { + SUCCESS = 0, + ERR_INSTALL_INTERNAL_ERROR, + ERR_INSTALL_PARSE_FAILED, + ERR_INSTALL_VERSION_DOWNGRADE, + ERR_INSTALL_VERIFICATION_FAILED, + ERR_INSTALL_NO_SIGNATURE_INFO, + ERR_INSTALL_UPDATE_INCOMPATIBLE, + ERR_INSTALL_INVALID_BUNDLE_FILE, + ERR_INSTALL_MISSING_INSTALLED_BUNDLE, + ERR_INSTALL_ALREADY_EXIST, + ERR_INSTALL_PARSE_UNEXPECTED, + ERR_INSTALL_PARSE_MISSING_BUNDLE, + ERR_INSTALL_PARSE_MISSING_ABILITY, + ERR_INSTALL_PARSE_NO_PROFILE, + ERR_INSTALL_PARSE_BAD_PROFILE, + ERR_INSTALL_PARSE_PROFILE_PROP_TYPE_ERROR, + ERR_INSTALL_PARSE_PROFILE_MISSING_PROP, + ERR_UNINSTALL_INVALID_NAME, + ERR_UNKNOW, + }; +}; + +class IBundleInstaller : public IRemoteBroker { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"ohos.appexecfwk.BundleInstaller"); + + virtual bool Install(const std::string &bundleFilePath, const InstallParam &installParam, + const sptr &statusReceiver) = 0; + virtual bool Uninstall(const std::string &bundleName, const InstallParam &installParam, + const sptr &statusReceiver) = 0; + + enum class Message { + INSTALL, + UNINSTALL, + }; +}; + +class IBundleMgr : public IRemoteBroker { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"ohos.aafwk.BundleMgr"); + virtual bool GetApplicationInfo( + const std::string &appName, const ApplicationFlag flag, const int userId, ApplicationInfo &appInfo) = 0; + virtual bool GetApplicationInfos( + const ApplicationFlag flag, const int userId, std::vector &appInfos) = 0; + virtual bool GetBundleInfo(const std::string &bundleName, const BundleFlag flag, BundleInfo &bundleInfo) = 0; + virtual bool GetBundleInfos(const BundleFlag flag, std::vector &bundleInfos) = 0; + virtual int GetUidByBundleName(const std::string &bundleName, const int userId) = 0; + virtual std::string GetAppIdByBundleName(const std::string &bundleName, const int userId) = 0; + virtual bool GetBundleNameForUid(const int uid, std::string &bundleName) = 0; + virtual bool GetBundlesForUid(const int uid, std::vector &bundleNames) = 0; + virtual bool GetNameForUid(const int uid, std::string &name) = 0; + virtual bool GetBundleGids(const std::string &bundleName, std::vector &gids) = 0; + virtual std::string GetAppType(const std::string &bundleName) = 0; + virtual bool CheckIsSystemAppByUid(const int uid) = 0; + virtual bool GetBundleInfosByMetaData(const std::string &metaData, std::vector &bundleInfos) = 0; + virtual bool QueryAbilityInfo(const Want &want, AbilityInfo &abilityInfo) = 0; + virtual bool QueryAbilityInfos(const Want &want, std::vector &abilityInfos) = 0; + virtual bool QueryAbilityInfoByUri(const std::string &abilityUri, AbilityInfo &abilityInfo) = 0; + virtual bool QueryKeepAliveBundleInfos(std::vector &bundleInfos) = 0; + virtual std::string GetAbilityLabel(const std::string &bundleName, const std::string &className) = 0; + virtual bool GetBundleArchiveInfo( + const std::string &hapFilePath, const BundleFlag flag, BundleInfo &bundleInfo) = 0; + virtual bool GetHapModuleInfo(const AbilityInfo &abilityInfo, HapModuleInfo &hapModuleInfo) = 0; + virtual bool GetLaunchWantForBundle(const std::string &bundleName, Want &want) = 0; + virtual int CheckPublicKeys(const std::string &firstBundleName, const std::string &secondBundleName) = 0; + virtual int CheckPermission(const std::string &bundleName, const std::string &permission) = 0; + virtual bool GetPermissionDef(const std::string &permissionName, PermissionDef &permissionDef) = 0; + virtual bool GetAllPermissionGroupDefs(std::vector &permissionDefs) = 0; + virtual bool GetAppsGrantedPermissions( + const std::vector &permissions, std::vector &appNames) = 0; + virtual bool HasSystemCapability(const std::string &capName) = 0; + virtual bool GetSystemAvailableCapabilities(std::vector &systemCaps) = 0; + virtual bool IsSafeMode() = 0; + virtual bool CleanBundleCacheFiles( + const std::string &bundleName, const sptr &cleanCacheCallback) = 0; + virtual bool CleanBundleDataFiles(const std::string &bundleName) = 0; + virtual bool RegisterBundleStatusCallback(const sptr &bundleStatusCallback) = 0; + virtual bool ClearBundleStatusCallback(const sptr &bundleStatusCallback) = 0; + virtual bool UnregisterBundleStatusCallback() = 0; + virtual bool DumpInfos(const DumpFlag flag, const std::string &bundleName, std::string &result) = 0; + virtual bool IsApplicationEnabled(const std::string &bundleName) = 0; + virtual bool SetApplicationEnabled(const std::string &bundleName, bool isEnable) = 0; + virtual bool IsAbilityEnabled(const AbilityInfo &abilityInfo) = 0; + virtual bool SetAbilityEnabled(const AbilityInfo &abilityInfo, bool isEnabled) = 0; + virtual std::string GetAbilityIcon(const std::string &bundleName, const std::string &className) = 0; + virtual bool CanRequestPermission( + const std::string &bundleName, const std::string &permissionName, const int userId) = 0; + virtual bool RequestPermissionFromUser( + const std::string &bundleName, const std::string &permission, const int userId) = 0; + virtual bool RegisterAllPermissionsChanged(const sptr &callback) = 0; + virtual bool RegisterPermissionsChanged( + const std::vector &uids, const sptr &callback) = 0; + virtual bool UnregisterPermissionsChanged(const sptr &callback) = 0; + virtual sptr GetBundleInstaller() = 0; + virtual bool GetModuleUsageRecords( + const int32_t number, std::vector &moduleUsageRecords) = 0; + virtual bool NotifyActivityLifeStatus( + const std::string &bundleName, const std::string &abilityName, const int64_t launchTime) = 0; + enum class Message { + GET_APPLICATION_INFO, + GET_APPLICATION_INFOS, + GET_BUNDLE_INFO, + GET_BUNDLE_INFOS, + GET_UID_BY_BUNDLE_NAME, + GET_APPID_BY_BUNDLE_NAME, + GET_BUNDLE_NAME_FOR_UID, + GET_BUNDLES_FOR_UID, + GET_NAME_FOR_UID, + GET_BUNDLE_GIDS, + GET_APP_TYPE, + CHECK_IS_SYSTEM_APP_BY_UID, + GET_BUNDLE_INFOS_BY_METADATA, + QUERY_ABILITY_INFO, + QUERY_ABILITY_INFO_BY_URI, + QUERY_KEEPALIVE_BUNDLE_INFOS, + GET_ABILITY_LABEL, + GET_BUNDLE_ARCHIVE_INFO, + GET_HAP_MODULE_INFO, + GET_LAUNCH_WANT_FOR_BUNDLE, + CHECK_PUBLICKEYS, + CHECK_PERMISSION, + GET_PERMISSION_DEF, + GET_ALL_PERMISSION_GROUP_DEFS, + GET_APPS_GRANTED_PERMISSIONS, + HAS_SYSTEM_CAPABILITY, + GET_SYSTEM_AVAILABLE_CAPABILITIES, + IS_SAFE_MODE, + CLEAN_BUNDLE_CACHE_FILES, + CLEAN_BUNDLE_DATA_FILES, + REGISTER_BUNDLE_STATUS_CALLBACK, + CLEAR_BUNDLE_STATUS_CALLBACK, + UNREGISTER_BUNDLE_STATUS_CALLBACK, + DUMP_INFOS, + IS_APPLICATION_ENABLED, + SET_APPLICATION_ENABLED, + IS_ABILITY_ENABLED, + SET_ABILITY_ENABLED, + GET_ABILITY_ICON, + CAN_REQUEST_PERMISSION, + REQUEST_PERMISSION_FROM_USER, + REGISTER_ALL_PERMISSIONS_CHANGED, + REGISTER_PERMISSIONS_CHANGED, + UNREGISTER_PERMISSIONS_CHANGED, + GET_BUNDLE_INSTALLER, + }; +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_APPEXECFWK_INTERFACES_INNERKITS_BUNDLEMGR_INCLUDE_MOCK_BUNDLE_MGR_INTERFACE_H \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/test/mock/include/mock_ability.cpp b/tools/frameworks/kits/ability/native/test/mock/include/mock_ability.cpp new file mode 100644 index 00000000000..61b0a03e70b --- /dev/null +++ b/tools/frameworks/kits/ability/native/test/mock/include/mock_ability.cpp @@ -0,0 +1,438 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ability.h" +#include +#include "ability_loader.h" +#include "app_log_wrapper.h" +#include "iservice_registry.h" +#include "system_ability_definition.h" + +namespace OHOS { +namespace AppExecFwk { +REGISTER_AA(Ability) + +void Ability::Init(std::shared_ptr &abilityInfo, const std::shared_ptr &application, + std::shared_ptr &handler, const sptr &token) +{ + APP_LOGI("Ability::Init called."); + + abilityInfo_ = abilityInfo; + handler_ = handler; + AbilityContext::token_ = token; + + // page ability only. + if (abilityInfo_->type == AbilityType::PAGE) { + abilityWindow_ = std::make_shared(); + } + lifecycle_ = std::make_shared(); + abilityLifecycleExecutor_ = std::make_shared(); + application_ = application; +} + +std::shared_ptr Ability::GetResourceManager() const +{ + std::shared_ptr remoteObject(Global::CreateResourceManager()); + return remoteObject; +} + +void Ability::OnStart(const Want &want) +{ + return; +} + +void Ability::OnStop() +{ + return; +} + +void Ability::OnActive() +{ + return; +} + +void Ability::OnInactive() +{} + +void Ability::OnForeground(const Want &want) +{ + return; +} + +void Ability::OnBackground() +{ + return; +} + +sptr Ability::OnConnect(const Want &want) +{ + return nullptr; +} + +void Ability::OnDisconnect(const Want &want) +{} + +void Ability::StartAbilityForResult(const Want &want, int requestCode) +{ + return; +} + +void Ability::StartAbilityForResult(const Want &want, int requestCode, AbilityStartSetting abilityStartSetting) +{ + return; +} + +void Ability::StartAbility(const Want &want, AbilityStartSetting abilityStartSetting) +{ + return; +} + +bool Ability::OnKeyDown(int keyCode, const KeyEvent &keyEvent) +{ + return false; +} + +bool Ability::OnKeyUp(int keyCode, const KeyEvent &keyEvent) +{ + return false; +} + +bool Ability::OnTouchEvent(const TouchEvent &touchEvent) +{ + return false; +} + +void Ability::SetUIContent(const ComponentContainer &componentContainer) +{ + return; +} + +void Ability::SetUIContent(int layoutRes) +{ + return; +} // namespace AppExecFwk + +void Ability::SetUIContent( + const ComponentContainer &componentContainer, std::shared_ptr &context, int typeFlag) +{ + return; +} + +void Ability::SetUIContent(int layoutRes, std::shared_ptr &context, int typeFlag) +{ + return; +} + +/** + * @brief Inflates UI controls by using WindowConfig. + * + * @param config Indicates the window config defined by the user. + */ +void Ability::SetUIContent(const WindowConfig &config) +{ + if (abilityWindow_ == nullptr) { + APP_LOGE("Ability::SetUIContent abilityWindow_ is nullptr"); + return; + } + + APP_LOGI("Ability::SetUIContent called"); + abilityWindow_->SetWindowConfig(config); +} + +/** + * @brief Get the window belong to the ability. + * + * @return Returns a IWindowsManager object pointer. + */ +std::unique_ptr &Ability::GetWindow(int windowID) +{ + APP_LOGI("Ability::GetWindow called windowID = %d.", windowID); + + return abilityWindow_->GetWindow(windowID); +} + +int Ability::GetVolumeTypeAdjustedByKey() +{ + return 0; +} + +bool Ability::HasWindowFocus() +{ + return false; +} + +bool Ability::OnKeyPressAndHold(int keyCode, const std::shared_ptr &keyEvent) +{ + return false; +} + +void Ability::OnRequestPermissionsFromUserResult( + int requestCode, const std::vector &permissions, const std::vector &grantResults) +{ + return; +} + +void Ability::OnLeaveForeground() +{ + return; +} + +std::string Ability::GetType(const Uri &uri) +{ + std::string value("\nullptr"); + return value; +} + +int Ability::Insert(const Uri &uri, const NativeRdb::ValuesBucket &value) +{ + GTEST_LOG_(INFO) << "Mock Ability::Insert called"; + return 1; +} + +void Ability::OnConfigurationUpdated(const Configuration &configuration) +{ + return; +} + +void Ability::OnMemoryLevel(int level) +{ + return; +} + +std::shared_ptr Ability::OpenRawFile(const Uri &uri, const std::string &mode) +{ + return nullptr; +} + +int Ability::Update(const Uri &uri, const NativeRdb::ValuesBucket &value, const NativeRdb::DataAbilityPredicates &predicates) +{ + GTEST_LOG_(INFO) << "Mock Ability::Update called"; + return 1; +} + +std::shared_ptr Ability::GetApplication() +{ + return application_; +} + +std::string Ability::GetAbilityName() +{ + return abilityInfo_->name; +} + +bool Ability::IsTerminating() +{ + return false; +} + +void Ability::OnAbilityResult(int requestCode, int resultCode, const Want &want) +{} + +void Ability::OnBackPressed() +{ + return; +} + +void Ability::OnNewWant(const Want &want) +{ + APP_LOGI("Ability::OnNewWant called"); +} + +void Ability::OnRestoreAbilityState(const PacMap &inState) +{ + APP_LOGI("Ability::OnRestoreAbilityState called"); +} + +void Ability::OnSaveAbilityState(const PacMap &outState) +{ + APP_LOGI("Ability::OnSaveAbilityState called"); +} + +void Ability::OnEventDispatch() +{ + return; +} + +void Ability::OnWindowFocusChanged(bool hasFocus) +{ + return; +} + +void Ability::SetWant(const AAFwk::Want &want) +{ + setWant_ = std::make_shared(want); +} + +std::shared_ptr Ability::GetWant() +{ + return setWant_; +} + +void Ability::SetResult(int resultCode, const Want &resultData) +{ + if (abilityInfo_ == nullptr) { + APP_LOGI("Ability::SetResult nullptr == abilityInfo_"); + return; + } + APP_LOGI("Ability::SetResult called type = %{public}d", abilityInfo_->type); + if (abilityInfo_->type == AppExecFwk::AbilityType::PAGE) { + AbilityContext::resultWant_ = resultData; + AbilityContext::resultCode_ = resultCode; + } +} + +void Ability::SetVolumeTypeAdjustedByKey(int volumeType) +{ + return; +} + +void Ability::OnCommand(const AAFwk::Want &want, bool restart, int startId) +{ + return; +} + +void Ability::Dump(const std::string &extra) +{ + return; +} + +void Ability::KeepBackgroundRunning(int id, const NotificationRequest ¬ificationRequest) +{ + return; +} + +void Ability::CancelBackgroundRunning() +{ + return; +} + +const std::shared_ptr Ability::NormalizeUri(const Uri &uri) +{ + return nullptr; +} + +int Ability::Delete(const Uri &uri, const NativeRdb::DataAbilityPredicates &predicates) +{ + GTEST_LOG_(INFO) << "Mock Ability::Delete called"; + return 1; +} + +std::vector Ability::GetFileTypes(const Uri &uri, const std::string &mimeTypeFilter) +{ + std::vector value; + value.push_back(mimeTypeFilter); + GTEST_LOG_(INFO) << "Mock Ability::GetFileTypes called"; + return value; +} + +int Ability::OpenFile(const Uri &uri, const std::string &mode) +{ + GTEST_LOG_(INFO) << "Mock Ability::OpenFile called"; + return 1; +} + +std::shared_ptr Ability::Query( + const Uri &uri, const std::vector &columns, const NativeRdb::DataAbilityPredicates &predicates) +{ + GTEST_LOG_(INFO) << "Mock Ability::Query called"; + return nullptr; +} + +bool Ability::Reload(const Uri &uri, const PacMap &extras) +{ + return true; +} + +void Ability::ContinueAbilityReversibly(const std::string &deviceId) +{ + return; +} + +void Ability::ContinueAbilityReversibly() +{ + return; +} + +std::string Ability::GetOriginalDeviceId() +{ + return ""; +} + +std::shared_ptr Ability::GetContinuationState() +{ + return nullptr; +} + +std::shared_ptr Ability::GetAbilityPackage() +{ + return nullptr; +} + +std::shared_ptr Ability::DenormalizeUri(const Uri &uri) +{ + return nullptr; +} + +std::shared_ptr Ability::GetLifecycle() +{ + APP_LOGI("Ability::GetLifecycle called"); + return lifecycle_; +} + +AbilityLifecycleExecutor::LifecycleState Ability::GetState() +{ + APP_LOGI("Ability::GetState called"); + + if (abilityLifecycleExecutor_ == nullptr) { + APP_LOGI("Ability::GetState error. abilityLifecycleExecutor_ == nullptr."); + return AbilityLifecycleExecutor::LifecycleState::UNINITIALIZED; + } + + return (AbilityLifecycleExecutor::LifecycleState)abilityLifecycleExecutor_->GetState(); +} + +void Ability::StartAbility(const Want &want) +{ + APP_LOGI("Ability::StartAbility called"); + AbilityContext::StartAbility(want, -1); +} + +void Ability::TerminateAbility() +{ + APP_LOGI("Ability::TerminateAbility called"); + AbilityContext::TerminateAbility(); +} + +int Ability::TerminateAbility(Want &want) +{ + return -1; +} + +void Ability::SetMainRoute(const std::string &entry) +{ + return; +} + +void Ability::AddActionRoute(const std::string &action, const std::string &entry) +{ + return; +} + +int Ability::SetWindowBackgroundColor(int red, int green, int blue) +{ + return -1; +} +} // namespace AppExecFwk +} // namespace OHOS diff --git a/tools/frameworks/kits/ability/native/test/mock/include/mock_ability_impl.h b/tools/frameworks/kits/ability/native/test/mock/include/mock_ability_impl.h new file mode 100644 index 00000000000..bb7fbe6f95c --- /dev/null +++ b/tools/frameworks/kits/ability/native/test/mock/include/mock_ability_impl.h @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_APPEXECFWK_OHOS_MOCK_INHERITANCE_IMPL_H +#define FOUNDATION_APPEXECFWK_OHOS_MOCK_INHERITANCE_IMPL_H + +#include "ability.h" +#include "ability_impl.h" +#include + +namespace OHOS { +namespace AppExecFwk { +using Want = OHOS::AAFwk::Want; + +class MockAbilityimpl : public AbilityImpl { +public: + MockAbilityimpl() = default; + virtual ~MockAbilityimpl() = default; + + void ImplStart(const Want &want) + { + this->Start(want); + } + + void ImplStop() + { + this->Stop(); + } + + void ImplActive() + { + this->Active(); + } + + void ImplInactive() + { + this->Inactive(); + } + + void ImplForeground(const Want &want) + { + this->Foreground(want); + } + + void ImplBackground() + { + this->Background(); + } + + void SetlifecycleState(int state) + { + this->lifecycleState_ = state; + } + + int MockGetCurrentState() + { + int value; + value = GetCurrentState(); + return value; + } + + sptr GetToken() + { + return token_; + } + + std::shared_ptr GetAbility() + { + return ability_; + } + +private: + AbilityImpl AbilityImpl_; +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_APPEXECFWK_OHOS_MOCK_PAGE_ABILITY_H \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/test/mock/include/mock_ability_manager_client.cpp b/tools/frameworks/kits/ability/native/test/mock/include/mock_ability_manager_client.cpp new file mode 100755 index 00000000000..41f78779594 --- /dev/null +++ b/tools/frameworks/kits/ability/native/test/mock/include/mock_ability_manager_client.cpp @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "mock_ability_manager_client.h" +#include +#include "ability_manager_client.h" + +namespace OHOS { +namespace AAFwk { +std::shared_ptr mockInstance_ = nullptr; +std::mutex mockMutex_; + +std::shared_ptr AbilityManagerClient::GetInstance() +{ + if (mockInstance_ == nullptr) { + std::lock_guard lock_l(mockMutex_); + if (mockInstance_ == nullptr) { + mockInstance_ = std::make_shared(); + } + } + return mockInstance_; +} + +AbilityManagerClient::AbilityManagerClient() +{ + // log +} + +AbilityManagerClient::~AbilityManagerClient() +{} + +ErrCode AbilityManagerClient::AttachAbilityThread( + const sptr &scheduler, const sptr &token) +{ + GTEST_LOG_(INFO) << "Mock AbilityManagerClient::AttachAbilityThread called"; + return -1; +} + +ErrCode AbilityManagerClient::AbilityTransitionDone(const sptr &token, int state) +{ + return -1; +} + +ErrCode AbilityManagerClient::ScheduleConnectAbilityDone( + const sptr &token, const sptr &remoteObject) +{ + return -1; +} + +ErrCode AbilityManagerClient::ScheduleDisconnectAbilityDone(const sptr &token) +{ + return -1; +} + +ErrCode AbilityManagerClient::ScheduleCommandAbilityDone(const sptr &token) +{ + return -1; +} + +void AbilityManagerClient::AddWindowInfo(const sptr &token, int32_t windowToken) +{ + return; +} + +ErrCode AbilityManagerClient::StartAbility(const Want &want, int requestCode) +{ + return -1; +} + +ErrCode AbilityManagerClient::TerminateAbility(const sptr &token, int resultCode, const Want *resultWant) +{ + return -1; +} + +ErrCode AbilityManagerClient::TerminateAbility(const sptr &callerToken, int requestCode) +{ + GTEST_LOG_(INFO) << "Mock AbilityManagerClient::TerminateAbility called"; + return -1; +} + +ErrCode AbilityManagerClient::TerminateAbilityResult(const sptr &token, int startId) +{ + return -1; +} + +ErrCode AbilityManagerClient::ConnectAbility( + const Want &want, const sptr &connect, const sptr &callerToken) +{ + return -1; +} + +ErrCode AbilityManagerClient::DisconnectAbility(const sptr &connect) +{ + return -1; +} + +sptr AbilityManagerClient::AcquireDataAbility( + const Uri &uri, bool tryBind, const sptr &callerToken) +{ + GTEST_LOG_(INFO) << "Mock AcquireDataAbility called"; + sptr dataScheduler = new (std::nothrow) OHOS::AppExecFwk::MockAbilityThread(); + return dataScheduler; +} + +ErrCode AbilityManagerClient::ReleaseDataAbility( + sptr dataAbilityScheduler, const sptr &callerToken) +{ + GTEST_LOG_(INFO) << "Mock ReleaseDataAbility called"; + return ERR_OK; +} + +ErrCode AbilityManagerClient::DumpState(const std::string &args, std::vector &state) +{ + return -1; +} + +ErrCode AbilityManagerClient::Connect() +{ + return -1; +} + +ErrCode AbilityManagerClient::GetAllStackInfo(StackInfo &stackInfo) +{ + return -1; +} + +ErrCode AbilityManagerClient::StopServiceAbility(const Want &want) +{ + return -1; +} +} // namespace AAFwk +} // namespace OHOS diff --git a/tools/frameworks/kits/ability/native/test/mock/include/mock_ability_manager_client.h b/tools/frameworks/kits/ability/native/test/mock/include/mock_ability_manager_client.h new file mode 100644 index 00000000000..8344403e603 --- /dev/null +++ b/tools/frameworks/kits/ability/native/test/mock/include/mock_ability_manager_client.h @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_APPEXECFWK_OHOS_ABILITY_NATIVE_MOCK_ABILITY_MANAGER_CLIENT_H +#define FOUNDATION_APPEXECFWK_OHOS_ABILITY_NATIVE_MOCK_ABILITY_MANAGER_CLIENT_H + +#include +#include +#include "abs_shared_result_set.h" +#include "data_ability_predicates.h" +#include "values_bucket.h" +#include "ability_connect_callback_interface.h" +#include "ability_manager_errors.h" +#include "ability_context.h" +#include "ability_manager_interface.h" +#include "ability_scheduler_interface.h" +#include "app_log_wrapper.h" +#include "iremote_object.h" +#include "iremote_stub.h" +#include "want.h" + +#define OPENFILENUM (1246) +#define INSERTNUM (2345) +#define UPDATENUM (3456) +#define OPENRAWFILENUM (5678) +#define DELETENUM (6789) +#define BATCHINSERTNUM (789) + +namespace OHOS { +namespace AppExecFwk { +using DummyConfiguration = AAFwk::DummyConfiguration; +class MockAbility : public AbilityContext { +public: + MockAbility() = default; + virtual ~MockAbility() = default; +}; + +class MockAbilityThread : public IRemoteStub { +public: + virtual void ScheduleAbilityTransaction(const Want &want, const LifeCycleStateInfo &targetState){}; + virtual void SendResult(int requestCode, int resultCode, const Want &resultWant){}; + virtual void ScheduleConnectAbility(const Want &want){}; + virtual void ScheduleDisconnectAbility(const Want &want){}; + virtual void ScheduleCommandAbility(const Want &want, bool restart, int startId){}; + virtual void ScheduleSaveAbilityState(PacMap &outState){}; + virtual void ScheduleRestoreAbilityState(const PacMap &inState){}; + virtual void ScheduleUpdateConfiguration(const DummyConfiguration &config){}; + virtual std::vector GetFileTypes(const Uri &uri, const std::string &mimeTypeFilter) + { + return std::vector(); + }; + virtual int OpenFile(const Uri &uri, const std::string &mode) + { + return OPENFILENUM; + }; + virtual int OpenRawFile(const Uri &uri, const std::string &mode) + { + return OPENRAWFILENUM; + }; + virtual int Insert(const Uri &uri, const NativeRdb::ValuesBucket &value) + { + return INSERTNUM; + }; + virtual int Update(const Uri &uri, const NativeRdb::ValuesBucket &value, const NativeRdb::DataAbilityPredicates &predicates) + { + return UPDATENUM; + }; + virtual int Delete(const Uri &uri, const NativeRdb::DataAbilityPredicates &predicates) + { + return DELETENUM; + }; + virtual std::shared_ptr Query( + const Uri &uri, std::vector &columns, const NativeRdb::DataAbilityPredicates &predicates) + { + return std::make_shared("resultset"); + }; + virtual std::string GetType(const Uri &uri) + { + return std::string("Type1"); + }; + virtual bool Reload(const Uri &uri, const PacMap &extras) + { + return true; + }; + virtual int BatchInsert(const Uri &uri, const std::vector &values) + { + return BATCHINSERTNUM; + }; + virtual bool ScheduleRegisterObserver(const Uri &uri, const sptr &dataObserver) + { + return true; + }; + virtual bool ScheduleUnregisterObserver(const Uri &uri, const sptr &dataObserver) + { + return true; + }; + virtual void NotifyMultiWinModeChanged(int32_t winModeKey, bool flag){}; + virtual void NotifyTopActiveAbilityChanged(bool flag){}; + virtual bool ScheduleNotifyChange(const Uri &uri) + { + return true; + }; + virtual Uri NormalizeUri(const Uri &uri) + { + return Uri("dataability:///test.aaa"); + }; + virtual Uri DenormalizeUri(const Uri &uri) + { + return Uri("dataability:///test.aaa"); + }; + virtual std::vector> ExecuteBatch( + const std::vector> &operations) + { + return std::vector>(); + }; + +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_APPEXECFWK_OHOS_ABILITY_NATIVE_MOCK_ABILITY_MANAGER_CLIENT_H \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/test/mock/include/mock_ability_manager_client_for_data_ability_observer.h b/tools/frameworks/kits/ability/native/test/mock/include/mock_ability_manager_client_for_data_ability_observer.h new file mode 100644 index 00000000000..db35b0af000 --- /dev/null +++ b/tools/frameworks/kits/ability/native/test/mock/include/mock_ability_manager_client_for_data_ability_observer.h @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef OHOS_APPEXECFWK_MOCK_ABILITY_MANAGER_CLIENT_FOR_DATA_ABILITY_OBSERVER_STUB_H +#define OHOS_APPEXECFWK_MOCK_ABILITY_MANAGER_CLIENT_FOR_DATA_ABILITY_OBSERVER_STUB_H + +#include "gmock/gmock.h" + +#include "ability_manager_client.h" +#include "ability_scheduler_proxy.h" +#include "ability_thread.h" + +#include +#include + +#include "mock_ability_scheduler_for_observer.h" + +namespace OHOS { +namespace AppExecFwk { + +class MockAbilitySchedulerTools { +public: + MockAbilitySchedulerTools():mockStatus(false){}; + ~MockAbilitySchedulerTools() = default; + + // return Copy AbilityThread class Smart pointer + std::shared_ptr GetMockAbilityScheduler() + { + if (mockAbilitySchedulerStubInstance == nullptr) { + mockAbilitySchedulerStubInstance = std::make_shared(); + } + return mockAbilitySchedulerStubInstance; + }; + + // return access proxy class sptr pointer + sptr GetAbilitySchedulerProxy() + { + if (mockStatus) { + if (abilitySchedulerProxyInstance1 == nullptr) { + if (mockAbilitySchedulerStubInstance == nullptr) { + mockAbilitySchedulerStubInstance = std::make_shared(); + } + abilitySchedulerProxyInstance1 = sptr( + new (std::nothrow) AAFwk::AbilitySchedulerProxy(mockAbilitySchedulerStubInstance->AsObject())); + } + return abilitySchedulerProxyInstance1; + } else { + if (abilitySchedulerProxyInstance2 == nullptr) { + if (abilityThreadInstance == nullptr) { + abilityThreadInstance = std::make_shared(); + } + abilitySchedulerProxyInstance2 = sptr( + new (std::nothrow) AAFwk::AbilitySchedulerProxy(abilityThreadInstance->AsObject())); + } + return abilitySchedulerProxyInstance2; + } + }; + + void SetMockStatus(bool nflag) + { + mockStatus = nflag; + } + + static std::shared_ptr GetInstance() + { + if (instance_ == nullptr) { + instance_ = std::make_shared(); + } + return instance_; + }; + + static void DestoryInstance() + { + instance_ = nullptr; + } + +private: + static std::shared_ptr instance_; + sptr abilitySchedulerProxyInstance1; + std::shared_ptr mockAbilitySchedulerStubInstance; + sptr abilitySchedulerProxyInstance2; + std::shared_ptr abilityThreadInstance; + bool mockStatus; +}; + +std::shared_ptr MockAbilitySchedulerTools::instance_ = nullptr; + +} // namespace AppExecFwk +} // namespace OHOS + +namespace OHOS { +namespace AAFwk { + +sptr AAFwk::AbilityManagerClient::AcquireDataAbility( + const Uri &uri, bool tryBind, const sptr &callerToken) +{ + return AppExecFwk::MockAbilitySchedulerTools::GetInstance()->GetAbilitySchedulerProxy(); +} + +ErrCode AbilityManagerClient::ReleaseDataAbility( + sptr dataAbilityScheduler, const sptr &callerToken) +{ + return ERR_OK; +} + +} // namespace AAFwk +} // namespace OHOS +#endif /* OHOS_APPEXECFWK_MOCK_ABILITY_MANAGER_CLIENT_FOR_DATA_ABILITY_OBSERVER_STUB_H */ \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/test/mock/include/mock_ability_manager_client_interface1.cpp b/tools/frameworks/kits/ability/native/test/mock/include/mock_ability_manager_client_interface1.cpp new file mode 100644 index 00000000000..7dc0b223c3b --- /dev/null +++ b/tools/frameworks/kits/ability/native/test/mock/include/mock_ability_manager_client_interface1.cpp @@ -0,0 +1,369 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include "gmock/gmock.h" + +#include "string_ex.h" + +#include "ability_manager_interface.h" +#include "ability_context.h" + +#include "mock_ability_manager_client_interface1.h" + +namespace OHOS { +namespace AAFwk { +MockAbilityManagerClient::MockAbilityManagerClient() +{ + startAbility_ = ERR_INVALID_OPERATION; + terminateAbility_ = ERR_INVALID_OPERATION; + terminateAbilityResult_ = ERR_INVALID_OPERATION; + isFirstInMission_ = ERR_INVALID_OPERATION; + removeMissionsE_ = ERR_INVALID_OPERATION; + terminateAbilityValue_ = 0; + removeMissions_ = 0; + missionId_ = -1; + moveMissionToEnd_ = false; +} +MockAbilityManagerClient::~MockAbilityManagerClient() +{} + +std::shared_ptr MockAbilityManagerClient::mock_instance_ = nullptr; +bool MockAbilityManagerClient::mock_intanceIsNull_ = true; + +std::shared_ptr MockAbilityManagerClient::GetInstance() +{ + if (mock_instance_ == nullptr) { + mock_instance_ = std::make_shared(); + } + + return mock_instance_; +} + +void MockAbilityManagerClient::SetInstanceNull(bool flag) +{ + mock_intanceIsNull_ = flag; +} + +std::shared_ptr AbilityManagerClient::GetInstance() +{ + if (instance_ == nullptr) { + std::lock_guard lock_l(mutex_); + if (instance_ == nullptr) { + instance_ = MockAbilityManagerClient::GetInstance(); + } + } + if (MockAbilityManagerClient::mock_intanceIsNull_) + return instance_; + else + return nullptr; +} + +AbilityManagerClient::~AbilityManagerClient() +{} + +ErrCode AbilityManagerClient::AttachAbilityThread( + const sptr &scheduler, const sptr &token) +{ + return ERR_OK; +} + +ErrCode AbilityManagerClient::AbilityTransitionDone(const sptr &token, int state) +{ + return ERR_OK; +} + +ErrCode AbilityManagerClient::ScheduleConnectAbilityDone( + const sptr &token, const sptr &remoteObject) +{ + return ERR_OK; +} + +ErrCode AbilityManagerClient::ScheduleDisconnectAbilityDone(const sptr &token) +{ + return ERR_OK; +} + +ErrCode AbilityManagerClient::ScheduleCommandAbilityDone(const sptr &token) +{ + return ERR_OK; +} + +void AbilityManagerClient::AddWindowInfo(const sptr &token, int32_t windowToken) +{ + return; +} + +ErrCode AbilityManagerClient::TerminateAbility(const sptr &token, int resultCode, const Want *resultWant) +{ + return ERR_OK; +} + +ErrCode AbilityManagerClient::ConnectAbility( + const Want &want, const sptr &connect, const sptr &callerToken) +{ + return ERR_OK; +} + +ErrCode AbilityManagerClient::DisconnectAbility(const sptr &connect) +{ + return ERR_OK; +} + +sptr AbilityManagerClient::AcquireDataAbility( + const Uri &uri, bool tryBind, const sptr &callerToken) +{ + return nullptr; +} + +ErrCode AbilityManagerClient::ReleaseDataAbility( + sptr dataAbilityScheduler, const sptr &callerToken) +{ + return ERR_OK; +} + +ErrCode AbilityManagerClient::DumpState(const std::string &args, std::vector &state) +{ + return ERR_OK; +} + +ErrCode AbilityManagerClient::Connect() +{ + return ERR_OK; +} + +ErrCode AbilityManagerClient::GetAllStackInfo(StackInfo &stackInfo) +{ + return ERR_OK; +} + +ErrCode AbilityManagerClient::StopServiceAbility(const Want &want) +{ + return ERR_OK; +} + +ErrCode AbilityManagerClient::GetRecentMissions( + const int32_t numMax, const int32_t flags, std::vector &recentList) +{ + return ERR_OK; +} + +ErrCode AbilityManagerClient::GetMissionSnapshot(const int32_t missionId, MissionSnapshotInfo &snapshot) +{ + return ERR_OK; +} + +ErrCode AbilityManagerClient::MoveMissionToTop(int32_t missionId) +{ + return ERR_OK; +} + +ErrCode AbilityManagerClient::RemoveMissions(std::vector missionId) +{ + ErrCode ret = MockAbilityManagerClient::GetInstance()->GetRemoveMissions(); + if (ret == ERR_OK) { + MockAbilityManagerClient::GetInstance()->ChangeRemoveMissionsValue(); + } + return ret; +} + +ErrCode AbilityManagerClient::RemoveStack(int id) +{ + return ERR_OK; +} + +ErrCode AbilityManagerClient::KillProcess(const std::string &bundleName) +{ + return ERR_OK; +} + +ErrCode AbilityManagerClient::StartAbility(const Want &want, int requestCode) +{ + return MockAbilityManagerClient::GetInstance()->GetStartAbility(); +} + +ErrCode AbilityManagerClient::StartAbility(const Want &want, const sptr &callerToken, int requestCode) +{ + return MockAbilityManagerClient::GetInstance()->GetStartAbility(); +} + +ErrCode AbilityManagerClient::TerminateAbility(const sptr &callerToken, int requestCode) +{ + MockAbilityManagerClient::GetInstance()->SetTerminateAbilityValue(requestCode); + return MockAbilityManagerClient::GetInstance()->GetTerminateAbility(); +} + +ErrCode AbilityManagerClient::TerminateAbilityResult(const sptr &token, int startId) +{ + return MockAbilityManagerClient::GetInstance()->GetTerminateAbilityResult(); +} + +ErrCode AbilityManagerClient::IsFirstInMission(const sptr &token) +{ + return MockAbilityManagerClient::GetInstance()->GetIsFirstInMission(); +} + +ErrCode AbilityManagerClient::MoveMissionToEnd(const sptr &token, const bool nonFirst) +{ + MockAbilityManagerClient::GetInstance()->SetMockMoveMissionToEnd( + !MockAbilityManagerClient::GetInstance()->GetMockMoveMissionToEnd()); + return ERR_OK; +} + +ErrCode AbilityManagerClient::LockMission(int missionId) +{ + MockAbilityManagerClient::GetInstance()->SetMockMissionId(missionId); + return ERR_OK; +} + +ErrCode AbilityManagerClient::UnlockMission(int missionId) +{ + MockAbilityManagerClient::GetInstance()->SetMockMissionId(missionId); + return ERR_OK; +} + +ErrCode AbilityManagerClient::SetMissionDescriptionInfo( + const sptr &token, const MissionDescriptionInfo &missionDescriptionInfo) +{ + return ERR_OK; +} + +ErrCode MockAbilityManagerClient::GetStartAbility() +{ + return startAbility_; +} +ErrCode MockAbilityManagerClient::GetTerminateAbility() +{ + return terminateAbility_; +} +ErrCode MockAbilityManagerClient::GetTerminateAbilityResult() +{ + return terminateAbilityResult_; +} +ErrCode MockAbilityManagerClient::GetIsFirstInMission() +{ + return isFirstInMission_; +} +ErrCode MockAbilityManagerClient::GetRemoveMissions() +{ + return removeMissionsE_; +} + +void MockAbilityManagerClient::SetStartAbility(ErrCode tValue) +{ + startAbility_ = tValue; +} +void MockAbilityManagerClient::SetTerminateAbility(ErrCode tValue) +{ + terminateAbility_ = tValue; +} +void MockAbilityManagerClient::SetTerminateAbilityResult(ErrCode tValue) +{ + terminateAbilityResult_ = tValue; +} +void MockAbilityManagerClient::SetIsFirstInMission(ErrCode tValue) +{ + isFirstInMission_ = tValue; +} +void MockAbilityManagerClient::SetRemoveMissions(ErrCode tValue) +{ + removeMissionsE_ = tValue; +} + +int MockAbilityManagerClient::GetTerminateAbilityValue() +{ + return terminateAbilityValue_; +} +void MockAbilityManagerClient::SetTerminateAbilityValue(int nValue) +{ + terminateAbilityValue_ = nValue; +} +int MockAbilityManagerClient::GetRemoveMissionsValue() +{ + return removeMissions_; +} +void MockAbilityManagerClient::ChangeRemoveMissionsValue() +{ + ++removeMissions_; +} + +int MockAbilityManagerClient::GetMockMissionId() +{ + return missionId_; +} +void MockAbilityManagerClient::SetMockMissionId(int missionId) +{ + missionId_ = missionId; +} + +bool MockAbilityManagerClient::GetMockMoveMissionToEnd() +{ + return moveMissionToEnd_; +} +void MockAbilityManagerClient::SetMockMoveMissionToEnd(bool flag) +{ + moveMissionToEnd_ = flag; +} + +} // namespace AAFwk +} // namespace OHOS + +namespace OHOS { +namespace AppExecFwk { + +MockAbilityContextDeal::MockAbilityContextDeal() +{ + hapModInfo_ = nullptr; +} +MockAbilityContextDeal::~MockAbilityContextDeal() +{} + +std::shared_ptr MockAbilityContextDeal::GetHapModuleInfo() +{ + if (hapModInfo_ == nullptr) { + hapModInfo_ = std::make_shared(); + } + return hapModInfo_; +} + +MockAbilityContextTest::MockAbilityContextTest() +{ + startAbilityRunCount_ = 0; +} +MockAbilityContextTest::~MockAbilityContextTest() +{} + +void MockAbilityContextTest::StartAbility(const AAFwk::Want &want, int requestCode) +{ + ++startAbilityRunCount_; +} + +size_t MockAbilityContextTest::GetStartAbilityRunCount() +{ + return startAbilityRunCount_; +} +void MockAbilityContextTest::SetStartAbilityRunCount(size_t nCount) +{ + startAbilityRunCount_ = nCount; +} + +void MockAbilityContextTest::SetToken(const sptr token) +{ + token_ = token; +} + +} // namespace AppExecFwk +} // namespace OHOS diff --git a/tools/frameworks/kits/ability/native/test/mock/include/mock_ability_manager_client_interface1.h b/tools/frameworks/kits/ability/native/test/mock/include/mock_ability_manager_client_interface1.h new file mode 100644 index 00000000000..24be4d90614 --- /dev/null +++ b/tools/frameworks/kits/ability/native/test/mock/include/mock_ability_manager_client_interface1.h @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_MOCK_ABILITY_MANAGER_CLIENT2_H +#define OHOS_AAFWK_MOCK_ABILITY_MANAGER_CLIENT2_H + +#include + +#include "ability_connect_callback_interface.h" +#include "ability_manager_errors.h" +#include "ability_scheduler_interface.h" +#include "ability_manager_interface.h" +#include "want.h" + +#include "iremote_object.h" +#include "iremote_stub.h" + +#include "ability_manager_client.h" + +namespace OHOS { +namespace AppExecFwk { + +class IAbilityMock : public OHOS::IRemoteBroker { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"ohos.aafwk.AbilityMock"); +}; + +class MockAbilityStub : public IRemoteStub { +public: + MockAbilityStub() = default; + virtual ~MockAbilityStub() = default; + virtual int OnRemoteRequest( + uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override + { + return IPCObjectStub::OnRemoteRequest(code, data, reply, option); + }; +}; + +class MockAbilityContextDeal : public ContextDeal { +public: + MockAbilityContextDeal(); + virtual ~MockAbilityContextDeal(); + + std::shared_ptr GetHapModuleInfo(); + + std::shared_ptr hapModInfo_; +}; + +class MockAbilityContextTest : public AbilityContext { +public: + MockAbilityContextTest(); + ~MockAbilityContextTest(); + + void StartAbility(const AAFwk::Want &want, int requestCode); + + void SetToken(const sptr token); + + size_t GetStartAbilityRunCount(); + void SetStartAbilityRunCount(size_t nCount); + + size_t startAbilityRunCount_; +}; + +} // namespace AppExecFwk +} // namespace OHOS + +namespace OHOS { +namespace AAFwk { + +class MockAbilityManagerClient : public AbilityManagerClient { +public: + MockAbilityManagerClient(); + virtual ~MockAbilityManagerClient(); + + ErrCode GetStartAbility(); + ErrCode GetTerminateAbility(); + ErrCode GetTerminateAbilityResult(); + ErrCode GetIsFirstInMission(); + ErrCode GetRemoveMissions(); + + void SetStartAbility(ErrCode tValue); + void SetTerminateAbility(ErrCode tValue); + void SetTerminateAbilityResult(ErrCode tValue); + void SetIsFirstInMission(ErrCode tValue); + void SetRemoveMissions(ErrCode tValue); + + int GetTerminateAbilityValue(); + void SetTerminateAbilityValue(int nValue); + + int GetRemoveMissionsValue(); + void ChangeRemoveMissionsValue(); + + int GetMockMissionId(); + void SetMockMissionId(int missionId); + + bool GetMockMoveMissionToEnd(); + void SetMockMoveMissionToEnd(bool flag); + + static std::shared_ptr mock_instance_; + static bool mock_intanceIsNull_; + + static std::shared_ptr GetInstance(); + static void SetInstanceNull(bool flag); + +private: + ErrCode startAbility_; + ErrCode terminateAbility_; + ErrCode terminateAbilityResult_; + ErrCode isFirstInMission_; + ErrCode removeMissionsE_; + + int terminateAbilityValue_; + int removeMissions_; + int missionId_; + bool moveMissionToEnd_; +}; + +}; // namespace AAFwk + +} // namespace OHOS + +#endif // OHOS_AAFWK_ABILITY_MANAGER_H diff --git a/tools/frameworks/kits/ability/native/test/mock/include/mock_ability_manager_clientex.cpp b/tools/frameworks/kits/ability/native/test/mock/include/mock_ability_manager_clientex.cpp new file mode 100755 index 00000000000..52e5c385de3 --- /dev/null +++ b/tools/frameworks/kits/ability/native/test/mock/include/mock_ability_manager_clientex.cpp @@ -0,0 +1,229 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include "ability_manager_client.h" +#include "ability_manager_interface.h" +#include "string_ex.h" +#include "hilog_wrapper.h" +#include "ipc_skeleton.h" +#include "if_system_ability_manager.h" +#include "iservice_registry.h" +#include "system_ability_definition.h" +#include "sys_mgr_client.h" + +namespace OHOS { +namespace AAFwk { +std::shared_ptr mockInstanceEx_ = nullptr; +std::mutex mockMutexEx_; + +std::shared_ptr AbilityManagerClient::GetInstance() +{ + if (mockInstanceEx_ == nullptr) { + std::lock_guard lock_l(mockMutexEx_); + if (mockInstanceEx_ == nullptr) { + mockInstanceEx_ = std::make_shared(); + } + } + return mockInstanceEx_; +} + +AbilityManagerClient::AbilityManagerClient() +{} + +AbilityManagerClient::~AbilityManagerClient() +{} + +ErrCode AbilityManagerClient::AttachAbilityThread( + const sptr &scheduler, const sptr &token) +{ + HILOG_INFO("AbilityManagerClient::AttachAbilityThread start"); + ErrCode err = Connect(); + if (err != ERR_OK) { + return ABILITY_SERVICE_NOT_CONNECTED; + } + + sptr abms = iface_cast(remoteObject_); + return abms->AttachAbilityThread(scheduler, token); +} + +ErrCode AbilityManagerClient::AbilityTransitionDone(const sptr &token, int state) +{ + if (remoteObject_ == nullptr) { + return ABILITY_SERVICE_NOT_CONNECTED; + } + sptr abms = iface_cast(remoteObject_); + return abms->AbilityTransitionDone(token, state); +} + +ErrCode AbilityManagerClient::ScheduleConnectAbilityDone( + const sptr &token, const sptr &remoteObject) +{ + if (remoteObject_ == nullptr) { + return ABILITY_SERVICE_NOT_CONNECTED; + } + sptr abms = iface_cast(remoteObject_); + return abms->ScheduleConnectAbilityDone(token, remoteObject); +} + +ErrCode AbilityManagerClient::ScheduleDisconnectAbilityDone(const sptr &token) +{ + if (remoteObject_ == nullptr) { + return ABILITY_SERVICE_NOT_CONNECTED; + } + sptr abms = iface_cast(remoteObject_); + return abms->ScheduleDisconnectAbilityDone(token); +} + +ErrCode AbilityManagerClient::ScheduleCommandAbilityDone(const sptr &token) +{ + if (remoteObject_ == nullptr) { + HILOG_ERROR("%{private}s:ability service not command", __func__); + return ABILITY_SERVICE_NOT_CONNECTED; + } + sptr abms = iface_cast(remoteObject_); + return abms->ScheduleCommandAbilityDone(token); +} + +void AbilityManagerClient::AddWindowInfo(const sptr &token, int32_t windowToken) +{ + if (remoteObject_ == nullptr) { + return; + } + sptr abms = iface_cast(remoteObject_); + abms->AddWindowInfo(token, windowToken); +} + +ErrCode AbilityManagerClient::StartAbility(const Want &want, int requestCode) +{ + if (remoteObject_ == nullptr) { + return ABILITY_SERVICE_NOT_CONNECTED; + } + sptr abms = iface_cast(remoteObject_); + return abms->StartAbility(want, requestCode); +} + +ErrCode AbilityManagerClient::TerminateAbility(const sptr &token, int resultCode, const Want *resultWant) +{ + HILOG_INFO("AbilityManagerClient::TerminateAbility start"); + if (remoteObject_ == nullptr) { + remoteObject_ = + OHOS::DelayedSingleton::GetInstance()->GetSystemAbility(ABILITY_MGR_SERVICE_ID); + } + sptr abms = iface_cast(remoteObject_); + HILOG_INFO("AbilityManagerClient::TerminateAbility end"); + return abms->TerminateAbility(token, resultCode, resultWant); +} + +ErrCode AbilityManagerClient::TerminateAbility(const sptr &callerToken, int requestCode) +{ + if (remoteObject_ == nullptr) { + HILOG_ERROR("%{private}s:ability service not connect", __func__); + return ABILITY_SERVICE_NOT_CONNECTED; + } + sptr abms = iface_cast(remoteObject_); + return abms->TerminateAbility(callerToken, requestCode); +} + +ErrCode AbilityManagerClient::ConnectAbility( + const Want &want, const sptr &connect, const sptr &callerToken) +{ + if (remoteObject_ == nullptr) { + remoteObject_ = + OHOS::DelayedSingleton::GetInstance()->GetSystemAbility(ABILITY_MGR_SERVICE_ID); + } + sptr abms = iface_cast(remoteObject_); + return abms->ConnectAbility(want, connect, callerToken); +} + +ErrCode AbilityManagerClient::DisconnectAbility(const sptr &connect) +{ + if (remoteObject_ == nullptr) { + remoteObject_ = + OHOS::DelayedSingleton::GetInstance()->GetSystemAbility(ABILITY_MGR_SERVICE_ID); + } + sptr abms = iface_cast(remoteObject_); + return abms->DisconnectAbility(connect); +} + +ErrCode AbilityManagerClient::DumpState(const std::string &args, std::vector &state) +{ + if (remoteObject_ == nullptr) { + return ABILITY_SERVICE_NOT_CONNECTED; + } + sptr abms = iface_cast(remoteObject_); + abms->DumpState(args, state); + return ERR_OK; +} + +ErrCode AbilityManagerClient::Connect() +{ + std::lock_guard lock(mockMutexEx_); + remoteObject_ = + OHOS::DelayedSingleton::GetInstance()->GetSystemAbility(ABILITY_MGR_SERVICE_ID); + if (remoteObject_ == nullptr) { + HILOG_ERROR("AbilityManagerClient::Connect remoteObject_ == nullptr"); + return ERR_NO_MEMORY; + } + + return ERR_OK; +} + +ErrCode AbilityManagerClient::GetAllStackInfo(StackInfo &stackInfo) +{ + if (remoteObject_ == nullptr) { + return ABILITY_SERVICE_NOT_CONNECTED; + } + + sptr abms = iface_cast(remoteObject_); + return abms->GetAllStackInfo(stackInfo); +} + +ErrCode AbilityManagerClient::StopServiceAbility(const Want &want) +{ + if (remoteObject_ == nullptr) { + remoteObject_ = + OHOS::DelayedSingleton::GetInstance()->GetSystemAbility(ABILITY_MGR_SERVICE_ID); + } + sptr abms = iface_cast(remoteObject_); + return abms->StopServiceAbility(want); +} + +sptr AbilityManagerClient::AcquireDataAbility( + const Uri &uri, bool tryBind, const sptr &callerToken) +{ + remoteObject_ = + OHOS::DelayedSingleton::GetInstance()->GetSystemAbility(ABILITY_MGR_SERVICE_ID); + if (remoteObject_ == nullptr) { + return nullptr; + } + + sptr abms = iface_cast(remoteObject_); + return abms->AcquireDataAbility(uri, tryBind, callerToken); +} + +ErrCode AbilityManagerClient::ReleaseDataAbility( + sptr dataAbilityScheduler, const sptr &callerToken) +{ + remoteObject_ = + OHOS::DelayedSingleton::GetInstance()->GetSystemAbility(ABILITY_MGR_SERVICE_ID); + if (remoteObject_ == nullptr) { + return -1; + } + + sptr abms = iface_cast(remoteObject_); + return abms->ReleaseDataAbility(dataAbilityScheduler, callerToken); +} +} // namespace AAFwk +} // namespace OHOS diff --git a/tools/frameworks/kits/ability/native/test/mock/include/mock_ability_manager_service.cpp b/tools/frameworks/kits/ability/native/test/mock/include/mock_ability_manager_service.cpp new file mode 100644 index 00000000000..5d71e081bbd --- /dev/null +++ b/tools/frameworks/kits/ability/native/test/mock/include/mock_ability_manager_service.cpp @@ -0,0 +1,201 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "mock_ability_manager_service.h" +#include + +#include +#include +#include +#include + +using OHOS::AppExecFwk::ElementName; + +namespace OHOS { +namespace AAFwk { +MockAbilityManagerService::MockAbilityManagerService() : abilityScheduler_(nullptr) +{ + abilityScheduler_ = nullptr; +} + +MockAbilityManagerService::~MockAbilityManagerService() +{} + +int MockAbilityManagerService::StartAbility(const Want &want, int requestCode) +{ + AbilityLifeCycleState state = AbilityLifeCycleState::ABILITY_STATE_INITIAL; + switch (requestCode) { + // Test code, representing the life cycle: Ability_ STATE_ INITIAL + case RequestCode::E_STATE_INITIAL: + state = AbilityLifeCycleState::ABILITY_STATE_INITIAL; + break; + // Test code, representing the life cycle: ABILITY_STATE_INACTIVE + case RequestCode::E_STATE_INACTIVE: + state = AbilityLifeCycleState::ABILITY_STATE_INACTIVE; + break; + // Test code, representing the life cycle: ABILITY_STATE_ACTIVE + case RequestCode::E_STATE_ACTIVE: + state = AbilityLifeCycleState::ABILITY_STATE_ACTIVE; + break; + // Test code, representing the life cycle: ABILITY_STATE_BACKGROUND + case RequestCode::E_STATE_BACKGROUND: + state = AbilityLifeCycleState::ABILITY_STATE_BACKGROUND; + break; + // Test code, representing the life cycle: ABILITY_STATE_SUSPENDED + case RequestCode::E_STATE_SUSPENDED: + state = AbilityLifeCycleState::ABILITY_STATE_SUSPENDED; + break; + default: + break; + } + + if (abilityScheduler_ != nullptr) { + want_ = want; + want_.SetElementName("BundleName", "abilityName"); + LifeCycleStateInfo stateInfo; + stateInfo.state = state; + abilityScheduler_->ScheduleAbilityTransaction(want_, stateInfo); + } + + return 0; +} + +int MockAbilityManagerService::TerminateAbility( + const sptr &token, int resultCode, const Want *resultWant) +{ + GTEST_LOG_(INFO) << "MockAbilityManagerService::TerminateAbility"; + + if (abilityScheduler_ != nullptr) { + LifeCycleStateInfo stateInfo; + stateInfo.state = AbilityLifeCycleState::ABILITY_STATE_INITIAL; + abilityScheduler_->ScheduleAbilityTransaction(want_, stateInfo); + + int ceode = 250; + abilityScheduler_->SendResult(ceode, resultCode, *resultWant); + } + return 0; +} + +int MockAbilityManagerService::ConnectAbility( + const Want &want, const sptr &connect, const sptr &callerToken) +{ + GTEST_LOG_(INFO) << "MockAbilityManagerService::ConnectAbility"; + return ERR_OK; +} + +int MockAbilityManagerService::DisconnectAbility(const sptr &connect) +{ + GTEST_LOG_(INFO) << "MockAbilityManagerService::DisconnectAbility"; + return ERR_OK; +} + +int MockAbilityManagerService::AttachAbilityThread( + const sptr &scheduler, const sptr &token) +{ + abilityScheduler_ = scheduler; + EXPECT_NE(nullptr, token); + return 0; +} + +void MockAbilityManagerService::DumpState(const std::string &args, std::vector &info) +{} + +int MockAbilityManagerService::AbilityTransitionDone(const sptr &token, int state) +{ + return 0; +} + +int MockAbilityManagerService::ScheduleConnectAbilityDone( + const sptr &token, const sptr &remoteObject) +{ + return 0; +} + +int MockAbilityManagerService::ScheduleDisconnectAbilityDone(const sptr &token) +{ + return 0; +} + +int MockAbilityManagerService::ScheduleCommandAbilityDone(const sptr &token) +{ + return 0; +} + +void MockAbilityManagerService::AddWindowInfo(const sptr &token, int32_t windowToken) +{} + +int MockAbilityManagerService::TerminateAbilityResult(const sptr &token, int startId) +{ + GTEST_LOG_(INFO) << "MockAbilityManagerService::TerminateAbilityResult"; + return ERR_OK; +} + +int MockAbilityManagerService::StopServiceAbility(const Want &want) +{ + GTEST_LOG_(INFO) << "MockAbilityManagerService::StopServiceAbility"; + return ERR_OK; +} + +int MockAbilityManagerService::RemoveMission(int id) +{ + return 0; +} + +int MockAbilityManagerService::RemoveStack(int id) +{ + return 0; +} + +int MockAbilityManagerService::MoveMissionToTop(int32_t missionId) +{ + return 0; +} + +int MockAbilityManagerService::KillProcess(const std::string &bundleName) +{ + return 0; +} + +int MockAbilityManagerService::UninstallApp(const std::string &bundleName) +{ + return 0; +} + +int MockAbilityManagerService::MoveMissionToEnd(const sptr &token, const bool nonFirst) +{ + return 0; +} + +bool MockAbilityManagerService::IsFirstInMission(const sptr &token) +{ + return true; +} + +int MockAbilityManagerService::CompelVerifyPermission(const std::string &permission, int pid, int uid, std::string &message) +{ + return 0; +} + +int MockAbilityManagerService::PowerOff() +{ + return 0; +} +int MockAbilityManagerService::PowerOn() +{ + return 0; +} + +} // namespace AAFwk +} // namespace OHOS diff --git a/tools/frameworks/kits/ability/native/test/mock/include/mock_ability_manager_service.h b/tools/frameworks/kits/ability/native/test/mock/include/mock_ability_manager_service.h new file mode 100755 index 00000000000..b688370c379 --- /dev/null +++ b/tools/frameworks/kits/ability/native/test/mock/include/mock_ability_manager_service.h @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_ABILITY_MOCK_MANAGER_SERVICE_H +#define OHOS_AAFWK_ABILITY_MOCK_MANAGER_SERVICE_H + +#include +#include +#include +#include + +#include "ability_manager_stub.h" +#include "iremote_object.h" + +#include "gmock/gmock.h" + +namespace OHOS { +namespace AAFwk { +enum class ServiceRunningState { STATE_NOT_START, STATE_RUNNING }; + +class MockAbilityManagerService : public AbilityManagerStub { +public: + MockAbilityManagerService(); + ~MockAbilityManagerService(); + int StartAbility(const Want &want, int requestCode = -1) override; + int StartAbility(const Want &want, const sptr &callerToken, int requestCode = -1) override + { + return 0; + } + int TerminateAbility( + const sptr &token, int resultCode = -1, const Want *resultWant = nullptr) override; + int ConnectAbility( + const Want &want, const sptr &connect, const sptr &callerToken) override; + int DisconnectAbility(const sptr &connect) override; + + void AddWindowInfo(const sptr &token, int32_t windowToken) override; + + int AttachAbilityThread(const sptr &scheduler, const sptr &token) override; + + int AbilityTransitionDone(const sptr &token, int state) override; + int ScheduleConnectAbilityDone(const sptr &token, const sptr &remoteObject) override; + int ScheduleDisconnectAbilityDone(const sptr &token) override; + int ScheduleCommandAbilityDone(const sptr &token) override; + + void DumpState(const std::string &args, std::vector &info) override; + + int TerminateAbilityResult(const sptr &token, int startId) override; + int StopServiceAbility(const Want &want) override; + int PowerOff() override; + int PowerOn() override; + + int LockMission(int missionId) override + { + return 0; + }; + int UnlockMission(int missionId) override + { + return 0; + }; + + int SetMissionDescriptionInfo( + const sptr &token, const MissionDescriptionInfo &missionDescriptionInfo) override + { + return 0; + }; + + int GetMissionLockModeState() + { + return 0; + } + + int UpdateConfiguration(const DummyConfiguration &config) + { + return 0; + } + + MOCK_METHOD1(GetAllStackInfo, int(StackInfo &stackInfo)); + MOCK_METHOD2( + GetWantSender, sptr(const WantSenderInfo &wantSenderInfo, const sptr &callerToken)); + MOCK_METHOD2(SendWantSender, int(const sptr &target, const SenderInfo &senderInfo)); + MOCK_METHOD1(CancelWantSender, void(const sptr &sender)); + MOCK_METHOD1(GetPendingWantUid, int(const sptr &target)); + MOCK_METHOD1(GetPendingWantUserId, int(const sptr &target)); + MOCK_METHOD1(GetPendingWantBundleName, std::string(const sptr &target)); + MOCK_METHOD1(GetPendingWantCode, int(const sptr &target)); + MOCK_METHOD1(GetPendingWantType, int(const sptr &target)); + MOCK_METHOD2(RegisterCancelListener, void(const sptr &sender, const sptr &receiver)); + MOCK_METHOD2(UnregisterCancelListener, void(const sptr &sender, const sptr &receiver)); + MOCK_METHOD2(GetPendingRequestWant, int(const sptr &target, std::shared_ptr &want)); + + MOCK_METHOD4(StartAbility, int(const Want &want, const AbilityStartSetting &abilityStartSetting, + const sptr &callerToken, int requestCode)); + MOCK_METHOD1(MoveMissionToFloatingStack, int(const MissionOption &missionOption)); + MOCK_METHOD1(MoveMissionToSplitScreenStack, int(const MissionOption &missionOption)); + MOCK_METHOD2( + ChangeFocusAbility, int(const sptr &lostFocusToken, const sptr &getFocusToken)); + MOCK_METHOD1(MinimizeMultiWindow, int(int missionId)); + MOCK_METHOD1(MaximizeMultiWindow, int(int missionId)); + MOCK_METHOD1(GetFloatingMissions, int(std::vector &list)); + MOCK_METHOD1(CloseMultiWindow, int(int missionId)); + MOCK_METHOD1(SetMissionStackSetting, int(const StackSetting &stackSetting)); + MOCK_METHOD1(GetPendinTerminateAbilityTestgRequestWant, void(int id)); + + int RemoveMission(int id) override; + + int RemoveStack(int id) override; + sptr AcquireDataAbility( + const Uri &uri, bool tryBind, const sptr &callerToken) override + { + return nullptr; + } + + int ReleaseDataAbility( + sptr dataAbilityScheduler, const sptr &callerToken) override + { + return 0; + } + + int GetRecentMissions( + const int32_t numMax, const int32_t flags, std::vector &recentList) override + { + return 0; + } + + int GetMissionSnapshot(const int32_t missionId, MissionSnapshotInfo &snapshot) + { + return 0; + } + + int MoveMissionToTop(int32_t missionId) override; + + int KillProcess(const std::string &bundleName) override; + + int UninstallApp(const std::string &bundleName) override; + + int TerminateAbilityByCaller(const sptr &callerToken, int requestCode) override + { + return 0; + } + + virtual int MoveMissionToEnd(const sptr &token, const bool nonFirst); + + virtual bool IsFirstInMission(const sptr &token); + + virtual int CompelVerifyPermission(const std::string &permission, int pid, int uid, std::string &message); + + enum RequestCode { + E_STATE_INITIAL = 0, + E_STATE_INACTIVE, + E_STATE_ACTIVE, + E_STATE_BACKGROUND, + E_STATE_SUSPENDED, + }; + + sptr abilityScheduler_; // kit interface used to schedule ability life + Want want_; +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_ABILITY_MOCK_MANAGER_SERVICE_H diff --git a/tools/frameworks/kits/ability/native/test/mock/include/mock_ability_scheduler_for_observer.h b/tools/frameworks/kits/ability/native/test/mock/include/mock_ability_scheduler_for_observer.h new file mode 100644 index 00000000000..23d403dd7fb --- /dev/null +++ b/tools/frameworks/kits/ability/native/test/mock/include/mock_ability_scheduler_for_observer.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef OHOS_APPEXECFWK_MOCK_ABILITY_SCHEDULER_FOR_OBESERVER_H +#define OHOS_APPEXECFWK_MOCK_ABILITY_SCHEDULER_FOR_OBESERVER_H + +#include "gmock/gmock.h" + +#include "ability_scheduler_stub.h" + +#include +#include + +namespace OHOS { +namespace AppExecFwk { + +// copy AbilityThread class +class MockAbilitySchedulerStub : public AAFwk::AbilitySchedulerStub { +public: + MockAbilitySchedulerStub() = default; + virtual ~MockAbilitySchedulerStub() = default; + + MOCK_METHOD2(ScheduleAbilityTransaction, void(const AAFwk::Want &, const AAFwk::LifeCycleStateInfo &)); + MOCK_METHOD3(SendResult, void(int, int, const AAFwk::Want &)); + MOCK_METHOD1(ScheduleConnectAbility, void(const AAFwk::Want &)); + MOCK_METHOD1(ScheduleDisconnectAbility, void(const AAFwk::Want &)); + MOCK_METHOD3(ScheduleCommandAbility, void(const AAFwk::Want &, bool, int)); + MOCK_METHOD1(ScheduleSaveAbilityState, void(PacMap &)); + MOCK_METHOD1(ScheduleRestoreAbilityState, void(const PacMap &)); + MOCK_METHOD1(ScheduleUpdateConfiguration, void(const AAFwk::DummyConfiguration &)); + MOCK_METHOD2(GetFileTypes, std::vector(const Uri &, const std::string &)); + MOCK_METHOD2(OpenFile, int(const Uri &, const std::string &)); + MOCK_METHOD2(OpenRawFile, int(const Uri &, const std::string &)); + MOCK_METHOD2(Insert, int(const Uri &, const NativeRdb::ValuesBucket &)); + MOCK_METHOD3(Update, int(const Uri &, const NativeRdb::ValuesBucket &, const NativeRdb::DataAbilityPredicates &)); + MOCK_METHOD2(Delete, int(const Uri &, const NativeRdb::DataAbilityPredicates &)); + MOCK_METHOD3( + Query, std::shared_ptr(const Uri &, std::vector &, const NativeRdb::DataAbilityPredicates &)); + MOCK_METHOD1(GetType, std::string(const Uri &)); + MOCK_METHOD2(Reload, bool(const Uri &, const PacMap &)); + MOCK_METHOD2(BatchInsert, int(const Uri &, const std::vector &)); + MOCK_METHOD1(DenormalizeUri, Uri(const Uri &)); + MOCK_METHOD1(NormalizeUri, Uri(const Uri &)); + MOCK_METHOD1(NotifyTopActiveAbilityChanged, void(bool flag)); + MOCK_METHOD2(NotifyMultiWinModeChanged, void(int32_t winModeKey, bool flag)); + MOCK_METHOD2(ScheduleRegisterObserver, bool(const Uri &uri, const sptr &dataObserver)); + MOCK_METHOD2(ScheduleUnregisterObserver, bool(const Uri &uri, const sptr &dataObserver)); + MOCK_METHOD1(ScheduleNotifyChange, bool(const Uri &uri)); + MOCK_METHOD1(ExecuteBatch, std::vector>(const std::vector> &operation)); +}; + +} // namespace AppExecFwk +} // namespace OHOS + +#endif /* OHOS_APPEXECFWK_MOCK_ABILITY_SCHEDULER_FOR_OBESERVER_H */ \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/test/mock/include/mock_ability_thread.h b/tools/frameworks/kits/ability/native/test/mock/include/mock_ability_thread.h new file mode 100644 index 00000000000..1473506b2d4 --- /dev/null +++ b/tools/frameworks/kits/ability/native/test/mock/include/mock_ability_thread.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_APPEXECFWK_OHOS_MOCK_ABILITY_THREAD_H +#define FOUNDATION_APPEXECFWK_OHOS_MOCK_ABILITY_THREAD_H + +#include "ability.h" +#include "ability_impl.h" +#include "ability_thread.h" +#include + +namespace OHOS { +namespace AppExecFwk { +using Want = OHOS::AAFwk::Want; + +class MockAbilityThread : public AbilityThread { +public: + MockAbilityThread() = default; + virtual ~MockAbilityThread() = default; + +private: + AbilityThread AbilityThread_; +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_APPEXECFWK_OHOS_MOCK_PAGE_ABILITY_H \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/test/mock/include/mock_ability_thread_for_ability_on_configuration_update.h b/tools/frameworks/kits/ability/native/test/mock/include/mock_ability_thread_for_ability_on_configuration_update.h new file mode 100644 index 00000000000..ef3d6d49cf8 --- /dev/null +++ b/tools/frameworks/kits/ability/native/test/mock/include/mock_ability_thread_for_ability_on_configuration_update.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_APPEXECFWK_MOCK_ABILITY_THREAD_FOR_ABILITY_ON_CONFIGURATION_UPDATE_H +#define OHOS_APPEXECFWK_MOCK_ABILITY_THREAD_FOR_ABILITY_ON_CONFIGURATION_UPDATE_H + +#include "gtest/gtest.h" +#include "gmock/gmock.h" + +#include "ability.h" + +namespace OHOS { +namespace AppExecFwk { + +class AbilityTest : public Ability { +public: + AbilityTest() = default; + virtual ~AbilityTest() = default; + + MOCK_METHOD1(OnConfigurationUpdated, void(const Configuration &)); + + static std::shared_ptr GetInstance() + { + return abilitTest_; + }; + + static void InitInstance() + { + AbilityTest::abilitTest_ = std::make_shared(); + }; + + static void UnInitInstance() + { + AbilityTest::abilitTest_ = nullptr; + }; + + static std::shared_ptr abilitTest_; +}; + +std::shared_ptr AbilityTest::abilitTest_ = nullptr; + +} // namespace AppExecFwk +} // namespace OHOS + +#endif // OHOS_APPEXECFWK_MOCK_ABILITY_THREAD_FOR_ABILITY_ON_CONFIGURATION_UPDATE_H diff --git a/tools/frameworks/kits/ability/native/test/mock/include/mock_ability_token.h b/tools/frameworks/kits/ability/native/test/mock/include/mock_ability_token.h new file mode 100644 index 00000000000..e2957c57948 --- /dev/null +++ b/tools/frameworks/kits/ability/native/test/mock/include/mock_ability_token.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_APPEXECFWK_KITS_APPKIT_TEST_MOCK_INCLUDE_MOCK_ABILITY_TOKEN_H +#define FOUNDATION_APPEXECFWK_KITS_APPKIT_TEST_MOCK_INCLUDE_MOCK_ABILITY_TOKEN_H + +#include "nocopyable.h" +#include "iremote_broker.h" +#include "iremote_object.h" +#include "iremote_proxy.h" +#include "iremote_stub.h" + +namespace OHOS { +namespace AppExecFwk { +class IAbilityToken : public IRemoteBroker { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"ohos.appexecfwk.AbilityToken"); +}; + +class MockAbilityToken : public IRemoteStub { +public: + MockAbilityToken() = default; + virtual ~MockAbilityToken() = default; + + virtual int OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) + { + return 0; + } + +private: + DISALLOW_COPY_AND_MOVE(MockAbilityToken); +}; + +class AbilityTokenProxy : public IRemoteProxy { +public: + explicit AbilityTokenProxy(const sptr &impl) : IRemoteProxy(impl) + {} + + virtual ~AbilityTokenProxy() = default; + +private: + DISALLOW_COPY_AND_MOVE(AbilityTokenProxy); +}; + +DECLARE_INTERFACE_DESCRIPTOR(u"IAbilityToken"); +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_APPEXECFWK_KITS_APPKIT_TEST_MOCK_INCLUDE_MOCK_ABILITY_TOKEN_H diff --git a/tools/frameworks/kits/ability/native/test/mock/include/mock_bundle_manager.cpp b/tools/frameworks/kits/ability/native/test/mock/include/mock_bundle_manager.cpp new file mode 100644 index 00000000000..ad5672e844c --- /dev/null +++ b/tools/frameworks/kits/ability/native/test/mock/include/mock_bundle_manager.cpp @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "mock_bundle_manager.h" +#include +#include "ability_info.h" +#include "application_info.h" + +namespace OHOS { +namespace AppExecFwk { + +bool BundleMgrProxy::QueryAbilityInfo(const AAFwk::Want &want, AbilityInfo &abilityInfo) +{ + ElementName eleName = want.GetElement(); + if (eleName.GetBundleName().empty()) { + return false; + } + abilityInfo.visible = true; + abilityInfo.name = eleName.GetAbilityName(); + abilityInfo.bundleName = eleName.GetBundleName(); + abilityInfo.applicationName = "Helloworld"; + return true; +} + +bool BundleMgrProxy::QueryAbilityInfoByUri(const std::string &uri, AbilityInfo &abilityInfo) +{ + return false; +} + +bool BundleMgrProxy::GetApplicationInfo( + const std::string &appName, const ApplicationFlag flag, const int userId, ApplicationInfo &appInfo) +{ + if (appName.empty()) { + return false; + } + appInfo.name = "Helloworld"; + appInfo.bundleName = "com.ohos.hiworld"; + return true; +} + +std::string BundleMgrProxy::GetAppType(const std::string &bundleName) +{ + GTEST_LOG_(INFO) << " BundleMgrProxy::GetAppTyp"; + return "system"; +} + +int BundleMgrStub::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) +{ + return 0; +} + +bool BundleMgrService::QueryAbilityInfo(const AAFwk::Want &want, AbilityInfo &abilityInfo) +{ + ElementName elementName = want.GetElement(); + if (elementName.GetBundleName().empty()) { + return false; + } + if (std::string::npos != elementName.GetBundleName().find("service")) { + abilityInfo.type = AppExecFwk::AbilityType::SERVICE; + } + abilityInfo.visible = true; + abilityInfo.name = elementName.GetAbilityName(); + abilityInfo.bundleName = elementName.GetBundleName(); + abilityInfo.applicationName = elementName.GetBundleName(); + if (want.HasEntity(Want::ENTITY_HOME) && want.GetAction() == Want::ACTION_HOME) { + abilityInfo.applicationInfo.isLauncherApp = true; + } else { + abilityInfo.applicationInfo.isLauncherApp = false; + } + return true; +} + +bool BundleMgrService::QueryAbilityInfoByUri(const std::string &uri, AbilityInfo &abilityInfo) +{ + return false; +} + +bool BundleMgrService::GetApplicationInfo( + const std::string &appName, const ApplicationFlag flag, const int userId, ApplicationInfo &appInfo) +{ + if (appName.empty()) { + return false; + } + appInfo.name = "Helloworld"; + appInfo.bundleName = "com.foobar.hiworld"; + return true; +} + +std::string BundleMgrService::GetAppType(const std::string &bundleName) +{ + GTEST_LOG_(INFO) << " BundleMgrService::GetAppType"; + return "system"; +} + +bool BundleMgrService::GetHapModuleInfo(const AbilityInfo &abilityInfo, HapModuleInfo &hapModuleInfo) +{ + GTEST_LOG_(INFO) << " BundleMgrService::GetHapModuleInfo"; + hapModuleInfo.name = "Captain"; + return true; +} +} // namespace AppExecFwk +} // namespace OHOS diff --git a/tools/frameworks/kits/ability/native/test/mock/include/mock_bundle_manager.h b/tools/frameworks/kits/ability/native/test/mock/include/mock_bundle_manager.h new file mode 100644 index 00000000000..945dcf3ba6e --- /dev/null +++ b/tools/frameworks/kits/ability/native/test/mock/include/mock_bundle_manager.h @@ -0,0 +1,442 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_ABILITY_MOCK_BUNDLE_MANAGER_H +#define OHOS_AAFWK_ABILITY_MOCK_BUNDLE_MANAGER_H + +#include + +#include "ability_info.h" +#include "application_info.h" +#include "bundle_mgr_interface.h" +#include "ohos/aafwk/content/want.h" +#include "iremote_proxy.h" +#include "iremote_stub.h" + +namespace OHOS { +namespace AppExecFwk { +class BundleMgrProxy : public IRemoteProxy { +public: + explicit BundleMgrProxy(const sptr &impl) : IRemoteProxy(impl) + {} + ~BundleMgrProxy() = default; + + virtual bool QueryAbilityInfo(const Want &want, AbilityInfo &abilityInfo) override; + virtual bool QueryAbilityInfoByUri(const std::string &uri, AbilityInfo &abilityInfo) override; + + virtual std::string GetAppType(const std::string &bundleName) override; + + virtual bool GetApplicationInfo( + const std::string &appName, const ApplicationFlag flag, const int userId, ApplicationInfo &appInfo) override; + virtual bool GetApplicationInfos( + const ApplicationFlag flag, const int userId, std::vector &appInfos) override + { + return true; + }; + bool QueryAbilityInfos(const Want &want, std::vector &abilityInfos) override + { + return true; + }; + bool CheckIsSystemAppByUid(const int uid) override + { + return true; + }; + virtual bool GetBundleInfo(const std::string &bundleName, const BundleFlag flag, BundleInfo &bundleInfo) override + { + return true; + }; + virtual bool GetBundleInfos(const BundleFlag flag, std::vector &bundleInfos) override + { + return true; + }; + virtual int GetUidByBundleName(const std::string &bundleName, const int userId) override + { + return 0; + }; + virtual bool GetBundleNameForUid(const int uid, std::string &bundleName) override + { + return true; + }; + virtual bool GetBundleGids(const std::string &bundleName, std::vector &gids) override + { + return true; + }; + virtual bool GetBundleInfosByMetaData(const std::string &metaData, std::vector &bundleInfos) override + { + return true; + }; + virtual bool QueryKeepAliveBundleInfos(std::vector &bundleInfos) override + { + return true; + }; + virtual std::string GetAbilityLabel(const std::string &bundleName, const std::string &className) override + { + return ""; + }; + // obtains information about an application bundle contained in a OHOS Ability Package (HAP). + virtual bool GetBundleArchiveInfo( + const std::string &hapFilePath, const BundleFlag flag, BundleInfo &bundleInfo) override + { + return true; + }; + virtual bool GetHapModuleInfo(const AbilityInfo &abilityInfo, HapModuleInfo &hapModuleInfo) override; + // obtains the Want for starting the main ability of an application based on the given bundle name. + virtual bool GetLaunchWantForBundle(const std::string &bundleName, Want &want) override + { + return true; + }; + // checks whether the publickeys of two bundles are the same. + virtual int CheckPublicKeys(const std::string &firstBundleName, const std::string &secondBundleName) override + { + return 0; + }; + // checks whether a specified bundle has been granted a specific permission. + virtual int CheckPermission(const std::string &bundleName, const std::string &permission) override + { + return 0; + }; + virtual bool GetPermissionDef(const std::string &permissionName, PermissionDef &permissionDef) override + { + return true; + }; + virtual bool GetAllPermissionGroupDefs(std::vector &permissionDefs) override + { + return true; + }; + virtual bool GetAppsGrantedPermissions( + const std::vector &permissions, std::vector &appNames) override + { + return true; + }; + virtual bool HasSystemCapability(const std::string &capName) override + { + return true; + }; + virtual bool GetSystemAvailableCapabilities(std::vector &systemCaps) override + { + return true; + }; + virtual bool IsSafeMode() override + { + return true; + }; + // clears cache data of a specified application. + virtual bool CleanBundleCacheFiles( + const std::string &bundleName, const sptr &cleanCacheCallback) override + { + return true; + }; + virtual bool CleanBundleDataFiles(const std::string &bundleName) override + { + return true; + }; + virtual bool RegisterBundleStatusCallback(const sptr &bundleStatusCallback) override + { + return true; + }; + virtual bool ClearBundleStatusCallback(const sptr &bundleStatusCallback) override + { + return true; + }; + // unregister callback of all application + virtual bool UnregisterBundleStatusCallback() override + { + return true; + }; + virtual bool DumpInfos(const DumpFlag flag, const std::string &bundleName, std::string &result) override + { + return true; + }; + virtual sptr GetBundleInstaller() override + { + return nullptr; + }; + virtual bool CanRequestPermission( + const std::string &bundleName, const std::string &permissionName, const int userId) override + { + printf("===================22222222===========\n"); + return false; + } + virtual bool RequestPermissionFromUser( + const std::string &bundleName, const std::string &permission, const int userId) override + { + return true; + } + virtual std::string GetAppIdByBundleName(const std::string &bundleName, const int userId) override + { + return ""; + } + virtual bool GetBundlesForUid(const int uid, std::vector &bundleNames) override + { + return true; + } + virtual bool GetNameForUid(const int uid, std::string &name) override + { + return true; + } + virtual bool IsAbilityEnabled(const AbilityInfo &abilityInfo) override + { + return true; + } + virtual bool SetAbilityEnabled(const AbilityInfo &abilityInfo, bool isEnabled) override + { + return true; + } + virtual std::string GetAbilityIcon(const std::string &bundleName, const std::string &className) override + { + return ""; + } + virtual bool RegisterAllPermissionsChanged(const sptr &callback) override + { + return true; + } + virtual bool RegisterPermissionsChanged( + const std::vector &uids, const sptr &callback) override + { + return true; + } + virtual bool UnregisterPermissionsChanged(const sptr &callback) override + { + return true; + } + virtual bool IsApplicationEnabled(const std::string &bundleName) override + { + return true; + } + virtual bool SetApplicationEnabled(const std::string &bundleName, bool isEnable) override + { + return true; + } + virtual bool GetModuleUsageRecords( + const int32_t number, std::vector &moduleUsageRecords) override + { + return true; + } + virtual bool NotifyActivityLifeStatus( + const std::string &bundleName, const std::string &abilityName, const int64_t launchTime) override + { + return true; + } +}; + +class BundleMgrStub : public IRemoteStub { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"IBundleMgr"); + virtual int OnRemoteRequest( + uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override; +}; + +class BundleMgrService : public BundleMgrStub { +public: + virtual bool QueryAbilityInfo(const AAFwk::Want &want, AbilityInfo &abilityInfo) override; + virtual bool QueryAbilityInfoByUri(const std::string &uri, AbilityInfo &abilityInfo) override; + + virtual std::string GetAppType(const std::string &bundleName) override; + + virtual bool GetApplicationInfo( + const std::string &appName, const ApplicationFlag flag, const int userId, ApplicationInfo &appInfo) override; + virtual bool GetApplicationInfos( + const ApplicationFlag flag, const int userId, std::vector &appInfos) override + { + return true; + }; + virtual bool QueryAbilityInfos(const Want &want, std::vector &abilityInfos) override + { + return true; + }; + virtual bool CheckIsSystemAppByUid(const int uid) override + { + return true; + }; + virtual bool GetBundleInfo(const std::string &bundleName, const BundleFlag flag, BundleInfo &bundleInfo) override + { + return true; + }; + virtual bool GetBundleInfos(const BundleFlag flag, std::vector &bundleInfos) override + { + return true; + }; + virtual int GetUidByBundleName(const std::string &bundleName, const int userId) override + { + return 0; + }; + virtual bool GetBundleNameForUid(const int uid, std::string &bundleName) override + { + return true; + }; + virtual bool GetBundleGids(const std::string &bundleName, std::vector &gids) override + { + return true; + }; + virtual bool GetBundleInfosByMetaData(const std::string &metaData, std::vector &bundleInfos) override + { + return true; + }; + virtual bool QueryKeepAliveBundleInfos(std::vector &bundleInfos) override + { + return true; + }; + virtual std::string GetAbilityLabel(const std::string &bundleName, const std::string &className) override + { + return ""; + }; + // obtains information about an application bundle contained in a OHOS Ability Package (HAP). + virtual bool GetBundleArchiveInfo( + const std::string &hapFilePath, const BundleFlag flag, BundleInfo &bundleInfo) override + { + return true; + }; + virtual bool GetHapModuleInfo(const AbilityInfo &abilityInfo, HapModuleInfo &hapModuleInfo) override; + // obtains the Want for starting the main ability of an application based on the given bundle name. + virtual bool GetLaunchWantForBundle(const std::string &bundleName, Want &want) override + { + return true; + }; + // checks whether the publickeys of two bundles are the same. + virtual int CheckPublicKeys(const std::string &firstBundleName, const std::string &secondBundleName) override + { + return 0; + }; + // checks whether a specified bundle has been granted a specific permission. + virtual int CheckPermission(const std::string &bundleName, const std::string &permission) override + { + return 0; + }; + virtual bool GetPermissionDef(const std::string &permissionName, PermissionDef &permissionDef) override + { + return true; + }; + virtual bool GetAllPermissionGroupDefs(std::vector &permissionDefs) override + { + return true; + }; + virtual bool GetAppsGrantedPermissions( + const std::vector &permissions, std::vector &appNames) override + { + return true; + }; + virtual bool HasSystemCapability(const std::string &capName) override + { + return true; + }; + virtual bool GetSystemAvailableCapabilities(std::vector &systemCaps) override + { + return true; + }; + virtual bool IsSafeMode() override + { + return true; + }; + // clears cache data of a specified application. + virtual bool CleanBundleCacheFiles( + const std::string &bundleName, const sptr &cleanCacheCallback) override + { + return true; + }; + virtual bool CleanBundleDataFiles(const std::string &bundleName) override + { + return true; + }; + virtual bool RegisterBundleStatusCallback(const sptr &bundleStatusCallback) override + { + return true; + }; + virtual bool ClearBundleStatusCallback(const sptr &bundleStatusCallback) override + { + return true; + }; + // unregister callback of all application + virtual bool UnregisterBundleStatusCallback() override + { + return true; + }; + virtual bool DumpInfos(const DumpFlag flag, const std::string &bundleName, std::string &result) override + { + return true; + }; + virtual sptr GetBundleInstaller() override + { + return nullptr; + }; + virtual bool CanRequestPermission( + const std::string &bundleName, const std::string &permissionName, const int userId) override + { + printf("===================333333333333333333===========\n"); + return false; + } + virtual bool RequestPermissionFromUser( + const std::string &bundleName, const std::string &permission, const int userId) override + { + return true; + } + virtual std::string GetAppIdByBundleName(const std::string &bundleName, const int userId) override + { + return ""; + } + virtual bool GetBundlesForUid(const int uid, std::vector &bundleNames) override + { + return true; + } + virtual bool GetNameForUid(const int uid, std::string &name) override + { + return true; + } + virtual bool IsAbilityEnabled(const AbilityInfo &abilityInfo) override + { + return true; + } + virtual bool SetAbilityEnabled(const AbilityInfo &abilityInfo, bool isEnabled) override + { + return true; + } + virtual std::string GetAbilityIcon(const std::string &bundleName, const std::string &className) override + { + return ""; + } + virtual bool RegisterAllPermissionsChanged(const sptr &callback) override + { + return true; + } + virtual bool RegisterPermissionsChanged( + const std::vector &uids, const sptr &callback) override + { + return true; + } + virtual bool UnregisterPermissionsChanged(const sptr &callback) override + { + return true; + } + virtual bool IsApplicationEnabled(const std::string &bundleName) override + { + return true; + } + virtual bool SetApplicationEnabled(const std::string &bundleName, bool isEnable) override + { + return true; + } + virtual bool GetModuleUsageRecords( + const int32_t number, std::vector &moduleUsageRecords) override + { + return true; + } + virtual bool NotifyActivityLifeStatus( + const std::string &bundleName, const std::string &abilityName, const int64_t launchTime) override + { + return true; + } +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif // OHOS_AAFWK_ABILITY_MOCK_BUNDLE_MANAGER_H diff --git a/tools/frameworks/kits/ability/native/test/mock/include/mock_bundle_manager_form.cpp b/tools/frameworks/kits/ability/native/test/mock/include/mock_bundle_manager_form.cpp new file mode 100644 index 00000000000..5a86fcb283b --- /dev/null +++ b/tools/frameworks/kits/ability/native/test/mock/include/mock_bundle_manager_form.cpp @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "mock_bundle_manager_form.h" +#include +#include "ability_info.h" +#include "application_info.h" +#include "form_info.h" + +namespace OHOS { +namespace AppExecFwk { +const std::string FORM_PROVIDER_BUNDLE_NAME = "com.form.provider.service"; +const std::string PARAM_PROVIDER_PACKAGE_NAME = "com.form.provider.app.test.abiliy"; +const std::string PARAM_PROVIDER_MODULE_NAME = "com.form.provider.app.test.abiliy"; +const std::string FORM_PROVIDER_ABILITY_NAME = "com.form.provider.app.test.abiliy"; +const std::string FORM_PROVIDER_MODULE_SOURCE_DIR = ""; +const std::string FORM_JS_COMPOMENT_NAME = "jsComponentName"; +const std::string PARAM_FORM_NAME = "com.form.name.test"; +const std::string DEVICE_ID = "ohos-phone1"; + +bool BundleMgrProxy::GetBundleInfo(const std::string &bundleName, const BundleFlag flag, BundleInfo &bundleInfo) +{ + return true; +} + +int BundleMgrService::GetUidByBundleName(const std::string &bundleName, const int userId) +{ + if (bundleName.compare("com.form.host.app600") == 0) { + return 600; + } + return 0; +} + +bool BundleMgrProxy::GetAllFormsInfo(std::vector &formInfo) +{ + return true; +} +bool BundleMgrProxy::GetFormsInfoByApp(const std::string &bundleName, std::vector &formInfo) +{ + return true; +} +bool BundleMgrProxy::GetFormsInfoByModule( + const std::string &bundleName, + const std::string &moduleName, + std::vector &formInfo) +{ + return true; +} + +int BundleMgrStub::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) +{ + return 0; +} + +bool BundleMgrService::QueryAbilityInfo(const AAFwk::Want &want, AbilityInfo &abilityInfo) +{ + return true; +} + +bool BundleMgrService::QueryAbilityInfoByUri(const std::string &uri, AbilityInfo &abilityInfo) +{ + return false; +} + +bool BundleMgrService::GetApplicationInfo( + const std::string &appName, const ApplicationFlag flag, const int userId, ApplicationInfo &appInfo) +{ + return true; +} + +std::string BundleMgrService::GetAppType(const std::string &bundleName) +{ + return "system"; +} + +bool BundleMgrService::GetBundleInfo(const std::string &bundleName, const BundleFlag flag, BundleInfo &bundleInfo) +{ + std::vector abilityInfos; + ApplicationInfo applicationInfo; + ModuleInfo moduleInfo; + + moduleInfo.moduleSourceDir = FORM_PROVIDER_MODULE_SOURCE_DIR; + moduleInfo.moduleName = PARAM_PROVIDER_MODULE_NAME; + bundleInfo.name = bundleName; + applicationInfo.bundleName = bundleName; + applicationInfo.moduleInfos.emplace_back(moduleInfo); + bundleInfo.applicationInfo = applicationInfo; + + bundleInfo.moduleNames.emplace_back(PARAM_PROVIDER_MODULE_NAME); + + AbilityInfo abilityInfo; + abilityInfo.name = FORM_PROVIDER_ABILITY_NAME; + abilityInfo.package = PARAM_PROVIDER_PACKAGE_NAME; + abilityInfo.moduleName = PARAM_PROVIDER_MODULE_NAME; + abilityInfo.deviceId = DEVICE_ID; + bundleInfo.abilityInfos.emplace_back(abilityInfo); + + return true; +} +bool BundleMgrService::GetBundleGids(const std::string &bundleName, std::vector &gids) +{ + return true; +} + +bool BundleMgrService::GetAllFormsInfo(std::vector &formInfo) +{ + FormInfo form; + form.abilityName = FORM_PROVIDER_ABILITY_NAME; + form.moduleName = PARAM_PROVIDER_MODULE_NAME; + form.name = PARAM_FORM_NAME; + form.updateEnabled = true; + form.updateDuration = 1; + form.scheduledUpateTime = "06:06"; + form.jsComponentName = FORM_JS_COMPOMENT_NAME; + form.formVisibleNotify = true; + form.supportDimensions = {1, 2}; + form.defaultDimension = 1; + formInfo.emplace_back(form); + return true; +} +bool BundleMgrService::GetFormsInfoByApp(const std::string &bundleName, std::vector &formInfo) +{ + FormInfo form; + form.bundleName = bundleName; + form.abilityName = FORM_PROVIDER_ABILITY_NAME; + form.moduleName = PARAM_PROVIDER_MODULE_NAME; + form.name = PARAM_FORM_NAME; + form.updateEnabled = true; + form.updateDuration = 1; + form.scheduledUpateTime = "06:06"; + form.jsComponentName = FORM_JS_COMPOMENT_NAME; + form.formVisibleNotify = true; + form.supportDimensions = {1, 2}; + form.defaultDimension = 1; + formInfo.emplace_back(form); + return true; +} +bool BundleMgrService::GetFormsInfoByModule( + const std::string &bundleName, + const std::string &moduleName, + std::vector &formInfo) +{ + FormInfo form; + form.bundleName = bundleName; + form.abilityName = FORM_PROVIDER_ABILITY_NAME; + form.moduleName = PARAM_PROVIDER_MODULE_NAME; + form.name = PARAM_FORM_NAME; + form.updateEnabled = true; + form.updateDuration = 1; + form.scheduledUpateTime = "06:06"; + form.jsComponentName = FORM_JS_COMPOMENT_NAME; + form.formVisibleNotify = true; + form.supportDimensions = {1, 2}; + form.defaultDimension = 1; + formInfo.emplace_back(form); + return true; +} +} // namespace AppExecFwk +} // namespace OHOS diff --git a/tools/frameworks/kits/ability/native/test/mock/include/mock_bundle_manager_form.h b/tools/frameworks/kits/ability/native/test/mock/include/mock_bundle_manager_form.h new file mode 100644 index 00000000000..9e6f68b68ee --- /dev/null +++ b/tools/frameworks/kits/ability/native/test/mock/include/mock_bundle_manager_form.h @@ -0,0 +1,471 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_ABILITY_MOCK_BUNDLE_MANAGER_H +#define OHOS_AAFWK_ABILITY_MOCK_BUNDLE_MANAGER_H + +#include + +#include "ability_info.h" +#include "application_info.h" +#include "foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_core/include/bundlemgr/bundle_mgr_interface.h" +#include "gmock/gmock.h" +#include "iremote_proxy.h" +#include "iremote_stub.h" +#include "ohos/aafwk/content/want.h" + +namespace OHOS { +namespace AppExecFwk { +class BundleMgrProxy : public IRemoteProxy { +public: + explicit BundleMgrProxy(const sptr &impl) : IRemoteProxy(impl) + {} + virtual ~BundleMgrProxy() + {} + + bool QueryAbilityInfo(const AAFwk::Want &want, AbilityInfo &abilityInfo) override + { + return true; + } + bool QueryAbilityInfoByUri(const std::string &uri, AbilityInfo &abilityInfo) override + { + return true; + } + + std::string GetAppType(const std::string &bundleName) override + { + return "system"; + } + + virtual bool GetApplicationInfo( + const std::string &appName, + const ApplicationFlag flag, + const int userId, + ApplicationInfo &appInfo) override + { + return true; + } + virtual bool GetApplicationInfos( + const ApplicationFlag flag, const int userId, std::vector &appInfos) override + { + return true; + } + + virtual bool GetBundleInfos(const BundleFlag flag, std::vector &bundleInfos) override + { + return true; + } + virtual int GetUidByBundleName(const std::string &bundleName, const int userId) override + { + if (bundleName.compare("com.form.host.app600") == 0) { + return 600; + } + return 0; + } + virtual std::string GetAppIdByBundleName(const std::string &bundleName, const int userId) override + { + return ""; + } + virtual bool GetBundleNameForUid(const int uid, std::string &bundleName) override + { + bundleName = "com.form.provider.service"; + return true; + } + virtual bool GetBundleGids(const std::string &bundleName, std::vector &gids) override + { + return true; + } + virtual bool GetBundleInfosByMetaData(const std::string &metaData, std::vector &bundleInfos) override + { + return true; + } + virtual bool QueryKeepAliveBundleInfos(std::vector &bundleInfos) override + { + return true; + } + virtual std::string GetAbilityLabel(const std::string &bundleName, const std::string &className) override + { + return ""; + } + + virtual bool GetBundleArchiveInfo( + const std::string &hapFilePath, const BundleFlag flag, BundleInfo &bundleInfo) override + { + return true; + } + + virtual bool GetLaunchWantForBundle(const std::string &bundleName, Want &want) override + { + return true; + } + + virtual int CheckPublicKeys(const std::string &firstBundleName, const std::string &secondBundleName) override + { + return 0; + } + + virtual int CheckPermission(const std::string &bundleName, const std::string &permission) override + { + return 0; + } + virtual bool GetPermissionDef(const std::string &permissionName, PermissionDef &permissionDef) override + { + return true; + } + virtual bool GetAllPermissionGroupDefs(std::vector &permissionDefs) override + { + return true; + } + virtual bool GetAppsGrantedPermissions( + const std::vector &permissions, std::vector &appNames) override + { + return true; + } + virtual bool HasSystemCapability(const std::string &capName) override + { + return true; + } + virtual bool GetSystemAvailableCapabilities(std::vector &systemCaps) override + { + return true; + } + virtual bool IsSafeMode() override + { + return true; + } + // clears cache data of a specified application. + virtual bool CleanBundleCacheFiles( + const std::string &bundleName, const sptr &cleanCacheCallback) override + { + return true; + } + virtual bool CleanBundleDataFiles(const std::string &bundleName) override + { + return true; + } + virtual bool RegisterBundleStatusCallback(const sptr &bundleStatusCallback) override + { + return true; + } + virtual bool ClearBundleStatusCallback(const sptr &bundleStatusCallback) override + { + return true; + } + // unregister callback of all application + virtual bool UnregisterBundleStatusCallback() override + { + return true; + } + virtual bool DumpInfos(const DumpFlag flag, const std::string &bundleName, std::string &result) override + { + return true; + } + virtual sptr GetBundleInstaller() override + { + return nullptr; + } + + /** + * @brief Obtains information about the shortcuts of the application. + * @param bundleName Indicates the name of the bundle to shortcut. + * @param form Indicates the callback a list to shortcutinfo. + * @return Returns true if shortcutinfo get success + */ + virtual bool GetShortcutInfos(const std::string &bundleName,std::vector &shortcut) override{ + return true; + } + // /** + // * @brief Starts a shortcut based on the given shortcut ID and bundle name. + // * @param bundleName BundleName Indicates the bundle name of the application to which the shortcut belongs. + // * @param shortcutId Starts a shortcut based on the given shortcut ID and bundle name. + // * @return Returns true if StartShortcut get success + // */ + // virtual bool StartShortcut(const std::string &shortcutId, const std::string &bundleName) override{ + // return true; + // } + /** + * @brief Disables specified home-screen shortcuts that are no longer used. + * @param shortcutIds Indicates the list of shortcut IDs to be disabled. + * @return Returns true if disableHomeShortcuts get success + */ + // virtual bool DisableHomeShortcuts(std::vector &shortcutIds) override{ + // return true; + // } + // /** + // * @brief Enables specified home-screen shortcuts. + // * @param shortcutIds Indicates the list of shortcut IDs to be enabled. + // * @return Returns true if enableHomeShortcuts? get success + // */ + // virtual bool EnableHomeShortcuts(std::vector &shortcutIds) override{ + // return true; + // } + // /** + // * @brief Checks whether a shortcut can be added to the home screen where the application is located. + // * @return Returns true if a shortcut can be added to the home screen; returns false otherwise. + // */ + // virtual bool IsHomeShortcutSupportes() override{ + // return true; + // } + // /** + // * @brief Adds a home-screen shortcut that will be fixed on the home screen. + // * @param shortcutInfo Indicates the ShortcutInfo object containing information about the home-screen shortcut to add. The id, label, and intent attributes of this parameter must be specified. + // * @return Returns true if the shortcut is successfully added; returns false otherwise. + // */ + // virtual bool AddHomeShortcut(ShortcutInfo &shortcutInfo) override{ + // return true; + // } + // /** + // * @brief Updates information about specified home-screen shortcuts that have been added. + // * @param shortcutInfos Updates information about specified home-screen shortcuts that have been added. + // * @return Returns true if the operation is successful; returns false otherwise. + // */ + // virtual bool UpdateShortcuts(std::vector &shortcutInfos) override{ + // return true; + // } + // /** + // * @brief Checks whether a specified shortcut is available. + // * @param shortcutId Indicates the ID of the shortcut to check. + // * @param flag Indicates the type of the shortcut to check. Currently, only the home-screen shortcut IBundleManager#QUERY_SHORTCUT_HOME is available. + // * @return Returns IBundleManager#SHORTCUT_EXISTENCE_EXISTS if the specified shortcut is available; returns IBundleManager#SHORTCUT_EXISTENCE_NOT_EXISTS if it is not available; returns IBundleManager.SHORTCUT_EXISTENCE_UNKNOW if an error occurs. + // */ + // virtual int IsShortcutExist(const std::string &shortcutId, const int &flag) override{ + // return 0; + // } + /** + * @brief Obtain the HAP module info of a specific ability. + * @param abilityInfo Indicates the ability. + * @param hapModuleInfo Indicates the obtained HapModuleInfo object. + * @return Returns true if the HapModuleInfo is successfully obtained; returns false otherwise. + */ + virtual bool GetHapModuleInfo(const AbilityInfo &abilityInfo, HapModuleInfo &hapModuleInfo) override + { + return true; + } + + virtual bool CheckIsSystemAppByUid(const int uid) override + { + if (uid == 600) { + return true; + } + return false; + } + virtual bool IsApplicationEnabled(const std::string &bundleName)override + { + return true; + } + virtual bool SetApplicationEnabled(const std::string &bundleName, bool isEnable) override + { + return true; + } + + virtual bool GetBundleInfo(const std::string &bundleName, const BundleFlag flag, BundleInfo &bundleInfo) override; + virtual bool GetAllFormsInfo(std::vector &formInfo) override; + virtual bool GetFormsInfoByApp(const std::string &bundleName, std::vector &formInfo) override; + virtual bool GetFormsInfoByModule( + const std::string &bundleName, + const std::string &moduleName, + std::vector &formInfo) override; +}; + +class BundleMgrStub : public IRemoteStub { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"IBundleMgr"); + ~BundleMgrStub() = default; + virtual int OnRemoteRequest( + uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override; +}; + +class BundleMgrService : public BundleMgrStub { +public: + MOCK_METHOD2(GetAppIdByBundleName, std::string(const std::string &bundleName, const int userId)); + MOCK_METHOD2(CheckPermission, int(const std::string &bundleName, const std::string &permission)); + MOCK_METHOD1(CleanBundleDataFiles, bool(const std::string &bundleName)); + MOCK_METHOD3( + CanRequestPermission, bool(const std::string &bundleName, const std::string &permissionName, const int userId)); + MOCK_METHOD3(RequestPermissionFromUser, + bool(const std::string &bundleName, const std::string &permission, const int userId)); + MOCK_METHOD2(GetNameForUid, bool(const int uid, std::string &name)); + MOCK_METHOD2(GetBundlesForUid, bool(const int uid, std::vector &)); + MOCK_METHOD2(SetAbilityEnabled, bool(const AbilityInfo &, bool)); + MOCK_METHOD1(IsAbilityEnabled, bool(const AbilityInfo &)); + MOCK_METHOD2(GetAbilityIcon, std::string(const std::string &bundleName, const std::string &className)); + MOCK_METHOD1(RegisterAllPermissionsChanged, bool(const sptr &callback)); + MOCK_METHOD2(RegisterPermissionsChanged, + bool(const std::vector &uids, const sptr &callback)); + MOCK_METHOD1(UnregisterPermissionsChanged, bool(const sptr &callback)); + bool QueryAbilityInfo(const AAFwk::Want &want, AbilityInfo &abilityInfo) override; + bool QueryAbilityInfoByUri(const std::string &uri, AbilityInfo &abilityInfo) override; + + std::string GetAppType(const std::string &bundleName) override; + virtual int GetUidByBundleName(const std::string &bundleName, const int userId) override; + + virtual bool GetApplicationInfo( + const std::string &appName, const ApplicationFlag flag, const int userId, ApplicationInfo &appInfo) override; + virtual bool GetApplicationInfos( + const ApplicationFlag flag, const int userId, std::vector &appInfos) override + { + return true; + }; + virtual bool GetBundleInfo(const std::string &bundleName, const BundleFlag flag, BundleInfo &bundleInfo) override; + virtual bool GetBundleInfos(const BundleFlag flag, std::vector &bundleInfos) override + { + return true; + }; + virtual bool GetBundleNameForUid(const int uid, std::string &bundleName) override + { + bundleName = "com.form.provider.service"; + return true; + }; + virtual bool GetBundleGids(const std::string &bundleName, std::vector &gids) override; + virtual bool GetBundleInfosByMetaData(const std::string &metaData, std::vector &bundleInfos) override + { + return true; + }; + virtual bool QueryKeepAliveBundleInfos(std::vector &bundleInfos) override + { + return true; + }; + virtual std::string GetAbilityLabel(const std::string &bundleName, const std::string &className) override + { + return ""; + }; + // obtains information about an application bundle contained in a ohos Ability Package (HAP). + virtual bool GetBundleArchiveInfo( + const std::string &hapFilePath, const BundleFlag flag, BundleInfo &bundleInfo) override + { + return true; + }; + virtual bool GetHapModuleInfo(const AbilityInfo &abilityInfo, HapModuleInfo &hapModuleInfo) override + { + return true; + } + // obtains the Want for starting the main ability of an application based on the given bundle name. + virtual bool GetLaunchWantForBundle(const std::string &bundleName, Want &want) override + { + return true; + }; + // checks whether the publickeys of two bundles are the same. + virtual int CheckPublicKeys(const std::string &firstBundleName, const std::string &secondBundleName) override + { + return 0; + }; + // checks whether a specified bundle has been granted a specific permission. + virtual bool GetPermissionDef(const std::string &permissionName, PermissionDef &permissionDef) override + { + return true; + }; + virtual bool GetAllPermissionGroupDefs(std::vector &permissionDefs) override + { + return true; + }; + virtual bool GetAppsGrantedPermissions( + const std::vector &permissions, std::vector &appNames) override + { + return true; + }; + virtual bool HasSystemCapability(const std::string &capName) override + { + return true; + }; + virtual bool GetSystemAvailableCapabilities(std::vector &systemCaps) override + { + return true; + }; + virtual bool IsSafeMode() override + { + return true; + }; + // clears cache data of a specified application. + virtual bool CleanBundleCacheFiles( + const std::string &bundleName, const sptr &cleanCacheCallback) override + { + return true; + }; + + virtual bool RegisterBundleStatusCallback(const sptr &bundleStatusCallback) override + { + return true; + }; + virtual bool ClearBundleStatusCallback(const sptr &bundleStatusCallback) override + { + return true; + }; + // unregister callback of all application + virtual bool UnregisterBundleStatusCallback() override + { + return true; + }; + virtual bool DumpInfos(const DumpFlag flag, const std::string &bundleName, std::string &result) override + { + return true; + }; + virtual sptr GetBundleInstaller() override + { + return nullptr; + }; + virtual bool IsApplicationEnabled(const std::string &bundleName) override + { + return true; + }; + virtual bool CheckIsSystemAppByUid(const int uid) override + { + if (uid == 600) { + return false; + } + + return true; + }; + virtual bool SetApplicationEnabled(const std::string &bundleName, bool isEnable) override + { + return true; + }; + + /** + * @brief Obtains information about the shortcuts of the application. + * @param bundleName Indicates the name of the bundle to shortcut. + * @param form Indicates the callback a list to shortcutinfo. + * @return Returns true if shortcutinfo get success + */ + virtual bool GetShortcutInfos(const std::string &bundleName,std::vector &shortcut) override{ + return true; + } + + virtual bool GetAllFormsInfo(std::vector &formInfo) override; + virtual bool GetFormsInfoByApp(const std::string &bundleName, std::vector &formInfo) override; + virtual bool GetFormsInfoByModule( + const std::string &bundleName, + const std::string &moduleName, + std::vector &formInfo) override; + virtual bool QueryAbilityInfos(const Want &want, std::vector &abilityInfos) override + { + return true; + }; + virtual bool GetModuleUsageRecords( + const int32_t number, std::vector &moduleUsageRecords) override + { + return true; + } + virtual bool NotifyActivityLifeStatus( + const std::string &bundleName, const std::string &abilityName, const int64_t launchTime) override + { + return true; + } + +}; + +} // namespace AppExecFwk +} // namespace OHOS + +#endif // OHOS_AAFWK_ABILITY_MOCK_BUNDLE_MANAGER_H diff --git a/tools/frameworks/kits/ability/native/test/mock/include/mock_data_ability.h b/tools/frameworks/kits/ability/native/test/mock/include/mock_data_ability.h new file mode 100644 index 00000000000..3d6db6457af --- /dev/null +++ b/tools/frameworks/kits/ability/native/test/mock/include/mock_data_ability.h @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_APPEXECFWK_OHOS_MOCK_DATA_ABILITY_H +#define FOUNDATION_APPEXECFWK_OHOS_MOCK_DATA_ABILITY_H + +#include "ability.h" +#include + +#include "abs_shared_result_set.h" +#include "data_ability_predicates.h" +#include "values_bucket.h" + +namespace OHOS { +namespace AppExecFwk { +using Want = OHOS::AAFwk::Want; + +class MockDataAbility : public Ability { +public: + MockDataAbility() = default; + virtual ~MockDataAbility() = default; + + enum Event { ON_ACTIVE = 0, ON_BACKGROUND, ON_FOREGROUND, ON_INACTIVE, ON_START, ON_STOP, UNDEFINED }; + + virtual int OpenFile(const Uri &uri, const std::string &mode) + { + GTEST_LOG_(INFO) << "MockDataAbility::OpenFile called"; + + return 1; + } + + virtual int Insert(const Uri &uri, const NativeRdb::ValuesBucket &value) + { + GTEST_LOG_(INFO) << "MockDataAbility::Insert called"; + + return 1; + } + + virtual int Update(const Uri &uri, const NativeRdb::ValuesBucket &value, const NativeRdb::DataAbilityPredicates &predicates) + { + GTEST_LOG_(INFO) << "MockDataAbility::Update called"; + + return 1; + } + + virtual int Delete(const Uri &uri, const NativeRdb::DataAbilityPredicates &predicates) + { + GTEST_LOG_(INFO) << "MockDataAbility::Delete called"; + + return 1; + } + + virtual int OpenRawFile(const Uri &uri, const std::string &mode) + { + GTEST_LOG_(INFO) << "MockDataAbility::OpenRawFile called"; + + return 1; + } + + virtual bool Reload(const Uri &uri, const PacMap &extras) + { + GTEST_LOG_(INFO) << "MockDataAbility::Reload called"; + + return 1; + } + + virtual int BatchInsert(const Uri &uri, const std::vector &values) + { + GTEST_LOG_(INFO) << "MockDataAbility::BatchInsert called"; + + return 1; + } + + virtual std::shared_ptr Query( + const Uri &uri, const std::vector &columns, const NativeRdb::DataAbilityPredicates &predicates) + { + GTEST_LOG_(INFO) << "MockDataAbility::Query called"; + std::shared_ptr set = std::make_shared("QueryTest"); + return set; + } + + virtual std::vector GetFileTypes(const Uri &uri, const std::string &mimeTypeFilter) + { + GTEST_LOG_(INFO) << "MockDataAbility::GetFileTypes called"; + value.push_back(mimeTypeFilter); + return value; + } + + virtual std::string GetType(const Uri &uri) + { + GTEST_LOG_(INFO) << "MockDataAbility::GetType called"; + std::string value("Type1"); + return value; + } + + int datatest = 0; + MockDataAbility::Event state_ = UNDEFINED; + std::vector value; +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_APPEXECFWK_OHOS_MOCK_PAGE_ABILITY_H \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/test/mock/include/mock_data_ability_impl.cpp b/tools/frameworks/kits/ability/native/test/mock/include/mock_data_ability_impl.cpp new file mode 100644 index 00000000000..3c71f4f14a0 --- /dev/null +++ b/tools/frameworks/kits/ability/native/test/mock/include/mock_data_ability_impl.cpp @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "abs_shared_result_set.h" +#include "data_ability_predicates.h" +#include "values_bucket.h" +#include "data_ability_impl.h" +#include +#include "app_log_wrapper.h" + +const int returnValueOpenfile = 11; +const int returnValueInsert = 22; +const int returnValueUpdate = 33; +const int returnValueDelete = 44; + +namespace OHOS { +namespace AppExecFwk { +void DataAbilityImpl::HandleAbilityTransaction(const Want &want, const AAFwk::LifeCycleStateInfo &targetState) +{ + GTEST_LOG_(INFO) << "Mock DataAbilityImpl::HandleAbilityTransaction called"; +} + +std::vector DataAbilityImpl::GetFileTypes(const Uri &uri, const std::string &mimeTypeFilter) +{ + GTEST_LOG_(INFO) << "Mock DataAbilityImpl::GetFileTypes called"; + std::vector types; + types.push_back("Type1"); + types.push_back("Type2"); + types.push_back("Type3"); + return types; +} + +int DataAbilityImpl::OpenFile(const Uri &uri, const std::string &mode) +{ + GTEST_LOG_(INFO) << "Mock DataAbilityImpl::OpenFile called"; + return returnValueOpenfile; +} + +int DataAbilityImpl::Insert(const Uri &uri, const NativeRdb::ValuesBucket &value) +{ + GTEST_LOG_(INFO) << "Mock DataAbilityImpl::Insert called"; + return returnValueInsert; +} + +int DataAbilityImpl::Update(const Uri &uri, const NativeRdb::ValuesBucket &value, const NativeRdb::DataAbilityPredicates &predicates) +{ + GTEST_LOG_(INFO) << "Mock DataAbilityImpl::Update called"; + return returnValueUpdate; +} + +int DataAbilityImpl::Delete(const Uri &uri, const NativeRdb::DataAbilityPredicates &predicates) +{ + GTEST_LOG_(INFO) << "Mock DataAbilityImpl::Delete called"; + return returnValueDelete; +} + +std::shared_ptr DataAbilityImpl::Query( + const Uri &uri, std::vector &columns, const NativeRdb::DataAbilityPredicates &predicates) +{ + GTEST_LOG_(INFO) << "Mock DataAbilityImpl::Query called"; + std::shared_ptr resultSet = std::make_shared(std::string("Test")); + return resultSet; +} + +std::string DataAbilityImpl::GetType(const Uri &uri) +{ + GTEST_LOG_(INFO) << "Mock DataAbilityImpl::GetType called"; + std::string type("type"); + return type; +} +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/test/mock/include/mock_form_mgr_service.h b/tools/frameworks/kits/ability/native/test/mock/include/mock_form_mgr_service.h new file mode 100755 index 00000000000..ba866ffae5a --- /dev/null +++ b/tools/frameworks/kits/ability/native/test/mock/include/mock_form_mgr_service.h @@ -0,0 +1,236 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_APPEXECFWK_SERVICES_MOCK_FORM_MGR_SERVICE_H +#define FOUNDATION_APPEXECFWK_SERVICES_MOCK_FORM_MGR_SERVICE_H + +#include +#include +#include +#include +#include +#include + +#include "event_handler.h" +#include "form_constants.h" +#include "form_mgr_stub.h" +#include "form_js_info.h" +#include "form_provider_data.h" +#include "ipc_types.h" +#include "iremote_object.h" + +namespace OHOS { +namespace AppExecFwk { +/** + * @class MockFormMgrService. + * The mockFormMgrService for ability test. + */ +class MockFormMgrService : public IFormMgr { +public: + MockFormMgrService(){}; + virtual ~MockFormMgrService(){}; + + sptr AsObject() + { + return nullptr; + } + + /** + * @brief Start envent for the form manager service. + */ + void OnStart(){} + + /** + * @brief Stop envent for the form manager service. + */ + void OnStop(){} + + /** + * @brief Add form with want, send want to form manager service. + * @param formId The Id of the forms to add. + * @param want The want of the form to add. + * @param callerToken Caller ability token. + * @param formInfo Form info. + * @return Returns ERR_OK on success, others on failure. + */ + int AddForm(const int64_t formId, const Want &want, const sptr &callerToken, FormJsInfo &formInfo) + { + // int64_t formId = want.GetLongParam(Constants::PARAM_FORM_IDENTITY_KEY, 0L); + if (formId == 300L) { + formInfo.formId = formId; + } + return 0; + } + + /** + * @brief Delete forms with formIds, send formIds to form manager service. + * @param formId The Id of the forms to delete. + * @param callerToken Caller ability token. + * @return Returns ERR_OK on success, others on failure. + */ + int DeleteForm(const int64_t formId, const sptr &callerToken) + { + return 0; + } + + /** + * @brief Release forms with formIds, send formIds to form manager service. + * @param formId The Id of the forms to release. + * @param callerToken Caller ability token. + * @param delCache Delete Cache or not. + * @return Returns ERR_OK on success, others on failure. + */ + int ReleaseForm(const int64_t formId, const sptr &callerToken, const bool delCache) + { + return 0; + } + + /** + * @brief Update form with formId, send formId to form manager service. + * @param formId The Id of the form to update. + * @param bundleName Provider ability bundleName. + * @param formBindingData Form binding data. + * @return Returns ERR_OK on success, others on failure. + */ + int UpdateForm(const int64_t formId, const std::string& bundleName, const FormProviderData& formBindingData) + { + if (formId == 300L){ + return -1; + } + return 0; + } + + /** + * @brief Request form with formId and want, send formId and want to form manager service. + * @param formId The Id of the form to update. + * @param callerToken Caller ability token. + * @param want The want of the form to add. + * @return Returns ERR_OK on success, others on failure. + */ + int RequestForm(const int64_t formId, const sptr &callerToken, const Want &want) + { + return 0; + } + + /** + * @brief Form visible/invisible notify, send formIds to form manager service. + * @param formIds The Id list of the forms to notify. + * @param callerToken Caller ability token. + * @return Returns ERR_OK on success, others on failure. + */ + int NotifyWhetherVisibleForms( + const std::vector &formIds, + const sptr &callerToken, + const int32_t formVisibleType) + { + if (formIds.size() == 1) { + return 0; + } + return 1; + } + + /** + * @brief temp form to normal form. + * @param formId The Id of the form. + * @param callerToken Caller ability token. + * @return Returns ERR_OK on success, others on failure. + */ + int CastTempForm(const int64_t formId, const sptr &callerToken) + { + if (formId == 175L)return 0; + return 1; + } + + /** + * @brief Dump all of form storage infos. + * @param formInfos All of form storage infos. + * @return Returns ERR_OK on success, others on failure. + */ + int DumpStorageFormInfos(std::string& formInfos) + { + return 0; + } + + /** + * @brief Dump form info by a bundle name. + * @param bundleName The bundle name of form provider. + * @param formInfos Form infos. + * @return Returns ERR_OK on success, others on failure. + */ + int DumpFormInfoByBundleName(const std::string &bundleName, std::string &formInfos) + { + return 0; + } + + /** + * @brief Dump form info by a bundle name. + * @param formId The id of the form. + * @param formInfo Form info. + * @return Returns ERR_OK on success, others on failure. + */ + int DumpFormInfoByFormId(const std::int64_t formId, std::string &formInfo) + { + return 0; + } + + /** + * @brief Set next refresh time. + * @param formId The Id of the form. + * @param nextTime The next refresh time. + * @return Returns ERR_OK on success, others on failure. + */ + int SetNextRefreshTime(const int64_t formId, const int64_t nextTime) + { + if (formId >= 1) { + return ERR_OK; + } else { + return ERR_INVALID_VALUE; + } + } + + /** + * @brief Lifecycle Update. + * @param formIds The Id list of the forms to notify. + * @param callerToken Caller ability token. + * @param updateType The update type. + * @return Returns ERR_OK on success, others on failure. + */ + int LifecycleUpdate( + const std::vector &formIds, + const sptr &callerToken, + const int32_t updateType) + { + if (formIds.size() == 0) { + return ERR_INVALID_VALUE; + } + return ERR_OK; + } + + /** + * @brief Process js message event. + * @param formId Indicates the unique id of form. + * @param want information passed to supplier. + * @param callerToken Caller ability token. + * @return Returns true if execute success, false otherwise. + */ + int MessageEvent(const int64_t formId, const Want &want, const sptr &callerToken) + { + return 0; + } +}; + +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_APPEXECFWK_SERVICES_MOCK_FORM_MGR_SERVICE_H diff --git a/tools/frameworks/kits/ability/native/test/mock/include/mock_form_supply_callback.cpp b/tools/frameworks/kits/ability/native/test/mock/include/mock_form_supply_callback.cpp new file mode 100644 index 00000000000..f0a04834422 --- /dev/null +++ b/tools/frameworks/kits/ability/native/test/mock/include/mock_form_supply_callback.cpp @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "app_log_wrapper.h" +#include "mock_form_supply_callback.h" + +namespace OHOS { +namespace AppExecFwk { +sptr MockFormSupplyCallback::instance = nullptr; +std::mutex MockFormSupplyCallback::mutex; + +sptr MockFormSupplyCallback::GetInstance() +{ + if (instance == nullptr) { + std::lock_guard lockl(mutex); + if (instance == nullptr) { + instance = new MockFormSupplyCallback(); + } + } + return instance; +} + +/** + * onAcquire + * + * @param formInfo Form Provider Info. + * @param want data + */ +int MockFormSupplyCallback::OnAcquire(const FormProviderInfo &formProviderInfo, const Want& want) +{ + APP_LOGI("MockFormSupplyCallback::OnAcquire called."); + return 1; +} + + +/** + * onEventHandle + * + * @param want data + */ +int MockFormSupplyCallback::OnEventHandle(const Want& want) +{ + APP_LOGI("MockFormSupplyCallback::OnEventHandle called."); + return 1; +} +} // namespace AppExecFwk +} // namespace OHOS diff --git a/tools/frameworks/kits/ability/native/test/mock/include/mock_form_supply_callback.h b/tools/frameworks/kits/ability/native/test/mock/include/mock_form_supply_callback.h new file mode 100644 index 00000000000..4c1b5198dfe --- /dev/null +++ b/tools/frameworks/kits/ability/native/test/mock/include/mock_form_supply_callback.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_APPEXECFWK_SERVICES_FORMMGR_INCLUDE_FORMMGR_FORM_SUPPLY_CALLBACK_H +#define FOUNDATION_APPEXECFWK_SERVICES_FORMMGR_INCLUDE_FORMMGR_FORM_SUPPLY_CALLBACK_H + +#include "form_supply_stub.h" + +namespace OHOS { +namespace AppExecFwk { +/** + * @class FormSupplyStub + * FormSupplyStub. + */ +class MockFormSupplyCallback : public FormSupplyStub { +public: + MockFormSupplyCallback() = default; + virtual ~MockFormSupplyCallback() = default; + static sptr GetInstance(); + + /** + * onAcquire + * + * @param providerFormInfo providerFormInfo + * @param want data + */ + virtual int OnAcquire(const FormProviderInfo &formInfo, const Want& want) override; + + /** + * onEventHandle + * + * @param want data + */ + virtual int OnEventHandle(const Want& want) override; + +private: + static std::mutex mutex; + static sptr instance; + + DISALLOW_COPY_AND_MOVE(MockFormSupplyCallback); +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_APPEXECFWK_SERVICES_FORMMGR_INCLUDE_FORMMGR_FORM_SUPPLY_CALLBACK_H diff --git a/tools/frameworks/kits/ability/native/test/mock/include/mock_lifecycle_observer.h b/tools/frameworks/kits/ability/native/test/mock/include/mock_lifecycle_observer.h new file mode 100644 index 00000000000..589718ba388 --- /dev/null +++ b/tools/frameworks/kits/ability/native/test/mock/include/mock_lifecycle_observer.h @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_APPEXECFWK_OHOS_MOCK_LIFECYCLE_OBSERVER_INTERFACE_H +#define FOUNDATION_APPEXECFWK_OHOS_MOCK_LIFECYCLE_OBSERVER_INTERFACE_H + +#include "want.h" +#include "ability_lifecycle_observer_interface.h" +#include + +namespace OHOS { +namespace AppExecFwk { +using Want = OHOS::AAFwk::Want; + +class MockLifecycleObserver : public ILifecycleObserver { +public: + MockLifecycleObserver() = default; + virtual ~MockLifecycleObserver() = default; + + /** + * Called back in response to an ON_ACTIVE event. + * When an ON_ACTIVE event is received, the ability or ability slice is in the foreground and is interactive. + */ + virtual void OnActive() + { + GTEST_LOG_(INFO) << "MockLifecycleObserver::OnActive called"; + } + + /** + * Called back in response to an ON_BACKGROUND event. + * When an ON_BACKGROUND event is received, the ability or ability slice is invisible. You are advised to + * suspend the threads related to this ability or ability slice and clear resources for more system memory. + * + */ + + virtual void OnBackground() + { + GTEST_LOG_(INFO) << "MockLifecycleObserver::OnBackground called"; + } + + /** + * Called back in response to an ON_FOREGROUND event, where information for the + * ability or ability slice to go back to the ACTIVE state is carried in the want parameter. + * When an ON_FOREGROUND event is received, the ability or ability slice returns to the foreground. You can use + * this method to implement re-initialization or adjust the UI display by using the want parameter. + * + * @param want Indicates the information for the ability or ability slice to go back to the ACTIVE state. + */ + virtual void OnForeground(const Want &want) + { + (void)want; + GTEST_LOG_(INFO) << "MockLifecycleObserver::OnForeground called"; + } + + /** + * Called back in response to an ON_INACTIVE event. + * When an ON_INACTIVE event is received, the ability or ability slice is in the INACTIVE state. INACTIVE is an + * intermediate state before the state changes to ACTIVE or BACKGROUND. In this state, the UI may be visible but is + * not interactive. You are advised not to use this method to invoke complex service logic. + * + */ + virtual void OnInactive() + { + GTEST_LOG_(INFO) << "MockLifecycleObserver::OnInactive called"; + } + + /** + * Called back in response to an ON_START event, where the startup information + * is carried in the want parameter. + * This method initializes an Ability or AbilitySlice and is called back only once during the entire lifecycle. + * You are advised to implement some initialization logic using this method, for example, you can initialize a + * timer or define some global objects. + * + * @param want Indicates the startup information. + */ + virtual void OnStart(const Want &want) + { + (void)want; + GTEST_LOG_(INFO) << "MockLifecycleObserver::OnStart called"; + } + + /** + * Called back in response to an ON_STOP event. + * This method is called back when the lifecycle of the ability or ability slice is destroyed. You can reclaim + * resources using this method. + * + */ + virtual void OnStop() + { + GTEST_LOG_(INFO) << "MockLifecycleObserver::OnStop called"; + } + + /** + * @brief Called back in response to a lifecycle change. This method is triggered by a registered LifecycleObserver + * each time the lifecycle state changes. + * + * @param event Indicates the lifecycle event. + * @param want Indicates the state change information. + */ + virtual void OnStateChanged(LifeCycle::Event event, const Want &want) + { + (void)event; + (void)want; + GTEST_LOG_(INFO) << "MockLifecycleObserver::OnStateChanged called"; + } + + /** + * @brief Called back in response to a lifecycle change. This method is triggered by a registered LifecycleObserver + * each time the lifecycle state changes. + * + * @param event Indicates the lifecycle event. + */ + virtual void OnStateChanged(LifeCycle::Event event) + { + (void)event; + GTEST_LOG_(INFO) << "MockLifecycleObserver::OnStateChanged called"; + } +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_APPEXECFWK_OHOS_MOCK_LIFECYCLE_OBSERVER_INTERFACE_H \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/test/mock/include/mock_page_ability.h b/tools/frameworks/kits/ability/native/test/mock/include/mock_page_ability.h new file mode 100644 index 00000000000..affe8c6a301 --- /dev/null +++ b/tools/frameworks/kits/ability/native/test/mock/include/mock_page_ability.h @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_APPEXECFWK_OHOS_MOCK_PAGE_ABILITY_H +#define FOUNDATION_APPEXECFWK_OHOS_MOCK_PAGE_ABILITY_H + +#include "ability.h" +#include + +namespace OHOS { +namespace AppExecFwk { +using Want = OHOS::AAFwk::Want; + +class MockPageAbility : public Ability { +public: + MockPageAbility() = default; + virtual ~MockPageAbility() = default; + + enum Event { ON_ACTIVE = 0, ON_BACKGROUND, ON_FOREGROUND, ON_INACTIVE, ON_START, ON_STOP, UNDEFINED }; + + bool OnKeyDown(int keyCode, const KeyEvent &keyEvent) + { + GTEST_LOG_(INFO) << "MockPageAbility::OnKeyDown called"; + return true; + } + + bool OnKeyUp(int keyCode, const KeyEvent &keyEvent) + { + GTEST_LOG_(INFO) << "MockPageAbility::OnKeyUp called"; + return true; + } + + bool OnTouchEvent(const TouchEvent &touchEvent) + { + GTEST_LOG_(INFO) << "MockPageAbility::OnTouchEvent called"; + return true; + } + + void OnAbilityResult(int requestCode, int resultCode, const AAFwk::Want &resultData) + { + GTEST_LOG_(INFO) << "MockPageAbility::OnAbilityResult called"; + state_ = ON_ACTIVE; + } + + void OnNewWant(const Want &want) + { + onNewWantCalled_ = true; + GTEST_LOG_(INFO) << "MockPageAbility::OnNewWant called"; + } + + void OnStart(const Want &want) + { + GTEST_LOG_(INFO) << "MockPageAbility::OnStart called"; + state_ = ON_START; + } + + void OnStop() + { + GTEST_LOG_(INFO) << "MockPageAbility::OnStop called"; + state_ = ON_STOP; + } + + void OnActive() + { + GTEST_LOG_(INFO) << "MockPageAbility::OnActive called"; + state_ = ON_ACTIVE; + } + + void OnInactive() + { + GTEST_LOG_(INFO) << "MockPageAbility::OnInactive called"; + state_ = ON_INACTIVE; + } + + void OnForeground(const Want &want) + { + GTEST_LOG_(INFO) << "MockPageAbility::OnForeground called"; + state_ = ON_FOREGROUND; + } + + void OnBackground() + { + GTEST_LOG_(INFO) << "MockPageAbility::OnBackground called"; + state_ = ON_BACKGROUND; + } + + sptr OnConnect(const Want &want) + { + GTEST_LOG_(INFO) << "MockPageAbility::OnConnect called"; + state_ = ON_ACTIVE; + return nullptr; + } + + void OnCommand(const AAFwk::Want &want, bool restart, int startId) + { + GTEST_LOG_(INFO) << "MockPageAbility::OnBackground called"; + state_ = ON_ACTIVE; + } + + int OpenFile(const Uri &uri, const std::string &mode) + { + GTEST_LOG_(INFO) << "MockPageAbility::OpenFile called"; + state_ = ON_ACTIVE; + return 1; + } + + int Insert(const Uri &uri, const NativeRdb::ValuesBucket &value) + { + GTEST_LOG_(INFO) << "MockPageAbility::Insert called"; + state_ = ON_ACTIVE; + return -1; + } + + int Update(const Uri &uri, const NativeRdb::ValuesBucket &value, const NativeRdb::DataAbilityPredicates &predicates) + { + GTEST_LOG_(INFO) << "MockPageAbility::Update called"; + state_ = ON_ACTIVE; + return -1; + } + + int Delete(const Uri &uri, const NativeRdb::DataAbilityPredicates &predicates) + { + GTEST_LOG_(INFO) << "MockPageAbility::Delete called"; + state_ = ON_ACTIVE; + return -1; + } + + std::shared_ptr Query( + const Uri &uri, const std::vector &columns, const NativeRdb::DataAbilityPredicates &predicates) + { + GTEST_LOG_(INFO) << "MockPageAbility::Query called"; + state_ = ON_ACTIVE; + return nullptr; + } + + std::vector GetFileTypes(const Uri &uri, const std::string &mimeTypeFilter) + { + GTEST_LOG_(INFO) << "MockPageAbility::GetFileTypes called"; + + value.push_back(mimeTypeFilter); + return value; + } + + void OnRestoreAbilityState(const PacMap &inState) + { + GTEST_LOG_(INFO) << "Mock Ability::OnRestoreAbilityState called"; + } + + void OnSaveAbilityState(PacMap &outState) + { + GTEST_LOG_(INFO) << "Mock Ability::OnSaveAbilityState called"; + } + + MockPageAbility::Event state_ = UNDEFINED; + bool onNewWantCalled_ = false; + std::vector value; +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_APPEXECFWK_OHOS_MOCK_PAGE_ABILITY_H \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/test/mock/include/mock_replace_ability_impl.cpp b/tools/frameworks/kits/ability/native/test/mock/include/mock_replace_ability_impl.cpp new file mode 100644 index 00000000000..8867ae3e551 --- /dev/null +++ b/tools/frameworks/kits/ability/native/test/mock/include/mock_replace_ability_impl.cpp @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ability_impl.h" +#include +#include "ability_local_record.h" +#include "app_log_wrapper.h" + +namespace OHOS { +namespace AppExecFwk { +void AbilityImpl::Init(std::shared_ptr &application, const std::shared_ptr &record, + std::shared_ptr &ability, std::shared_ptr &handler, const sptr &token, + std::shared_ptr &contextDeal) +{ + APP_LOGI("AbilityImpl::init begin"); + + if (token == nullptr) { + APP_LOGE("AbilityImpl::init failed, token is nullptr"); + return; + } + + if (application == nullptr) { + APP_LOGE("AbilityImpl::init failed, application is nullptr"); + return; + } + + if (record == nullptr) { + APP_LOGE("AbilityImpl::init failed, record is nullptr"); + return; + } + + if (ability == nullptr) { + APP_LOGE("AbilityImpl::init failed, ability is nullptr"); + return; + } + + if (token == nullptr) { + APP_LOGE("AbilityImpl::init failed, token is nullptr"); + return; + } + + if (contextDeal == nullptr) { + APP_LOGE("AbilityImpl::init failed, contextDeal is nullptr"); + return; + } + + token_ = record->GetToken(); + record->SetAbilityImpl(shared_from_this()); + ability_ = ability; + ability_->Init(record->GetAbilityInfo(), application, handler, token); + lifecycleState_ = AAFwk::ABILITY_STATE_INITIAL; + abilityLifecycleCallbacks_ = application; + contextDeal_ = contextDeal; + APP_LOGI("AbilityImpl::init end"); +} + +void AbilityImpl::Start(const Want &want) +{ + GTEST_LOG_(INFO) << "Mock AbilityImpl::Start called"; +} + +void AbilityImpl::Stop() +{ + GTEST_LOG_(INFO) << "Mock AbilityImpl::Stop called"; +} + +void AbilityImpl::Active() +{ + GTEST_LOG_(INFO) << "Mock AbilityImpl::Active called"; +} + +void AbilityImpl::Inactive() +{ + GTEST_LOG_(INFO) << "Mock AbilityImpl::Inactive called"; +} + +void AbilityImpl::Foreground(const Want &want) +{ + GTEST_LOG_(INFO) << "Mock AbilityImpl::Foreground called"; +} + +void AbilityImpl::Background() +{ + GTEST_LOG_(INFO) << "Mock AbilityImpl::Background called"; +} + +void AbilityImpl::DispatchSaveAbilityState(PacMap &outState) +{ + GTEST_LOG_(INFO) << "Mock AbilityImpl::DispatchSaveAbilityState called"; +} + +void AbilityImpl::DispatchRestoreAbilityState(const PacMap &inState) +{ + GTEST_LOG_(INFO) << "Mock AbilityImpl::DispatchRestoreAbilityState called"; +} + +void AbilityImpl::HandleAbilityTransaction(const Want &want, const AAFwk::LifeCycleStateInfo &targetState) +{ + GTEST_LOG_(INFO) << "Mock AbilityImpl::HandleAbilityTransaction called"; +} + +sptr AbilityImpl::ConnectAbility(const Want &want) +{ + GTEST_LOG_(INFO) << "Mock AbilityImpl::ConnectAbility called"; + return nullptr; +} + +void AbilityImpl::DisconnectAbility(const Want &want) +{ + GTEST_LOG_(INFO) << "Mock AbilityImpl::DisconnectAbility called"; +} + +void AbilityImpl::CommandAbility(const Want &want, bool restart, int startId) +{ + GTEST_LOG_(INFO) << "Mock AbilityImpl::CommandAbility called"; +} + +int AbilityImpl::GetCurrentState() +{ + return lifecycleState_; +} + +bool AbilityImpl::DoKeyDown(int keyCode, const KeyEvent &keyEvent) +{ + return false; +} + +bool AbilityImpl::DoKeyUp(int keyCode, const KeyEvent &keyEvent) +{ + return false; +} + +bool AbilityImpl::DoTouchEvent(const TouchEvent &touchEvent) +{ + return false; +} + +void AbilityImpl::SendResult(int requestCode, int resultCode, const Want &resultData) +{ + GTEST_LOG_(INFO) << "Mock AbilityImpl::SendResult called"; +} + +void AbilityImpl::NewWant(const Want &want) +{} + +std::vector AbilityImpl::GetFileTypes(const Uri &uri, const std::string &mimeTypeFilter) +{ + std::vector value; + value.push_back(mimeTypeFilter); + GTEST_LOG_(INFO) << "Mock AbilityImpl::GetFileTypes called"; + return value; +} + +int AbilityImpl::OpenFile(const Uri &uri, const std::string &mode) +{ + GTEST_LOG_(INFO) << "Mock AbilityImpl::OpenFile called"; + return 1; +} + +int AbilityImpl::Insert(const Uri &uri, const NativeRdb::ValuesBucket &value) +{ + GTEST_LOG_(INFO) << "Mock AbilityImpl::Insert called"; + return 1; +} + +int AbilityImpl::Update(const Uri &uri, const NativeRdb::ValuesBucket &value, const NativeRdb::DataAbilityPredicates &predicates) +{ + GTEST_LOG_(INFO) << "Mock AbilityImpl::Update called"; + return 1; +} + +int AbilityImpl::Delete(const Uri &uri, const NativeRdb::DataAbilityPredicates &predicates) +{ + GTEST_LOG_(INFO) << "Mock AbilityImpl::Delete called"; + return 1; +} + +std::shared_ptr AbilityImpl::Query( + const Uri &uri, std::vector &columns, const NativeRdb::DataAbilityPredicates &predicates) +{ + GTEST_LOG_(INFO) << "Mock AbilityImpl::Query called"; + return nullptr; +} + +std::string AbilityImpl::GetType(const Uri &uri) +{ + GTEST_LOG_(INFO) << "Mock AbilityImpl::GetType called"; + return ""; +} +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/test/mock/include/mock_resourceManager_interface1.cpp b/tools/frameworks/kits/ability/native/test/mock/include/mock_resourceManager_interface1.cpp new file mode 100644 index 00000000000..71f3204868f --- /dev/null +++ b/tools/frameworks/kits/ability/native/test/mock/include/mock_resourceManager_interface1.cpp @@ -0,0 +1,285 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include +#include "gmock/gmock.h" + +#include "mock_resourceManager_interface1.h" + +#include "res_config.h" +#include +#include +#include + +namespace OHOS { +namespace Global { +namespace Resource { +class ResourceManagerTestInstance : public ResourceManager2 { +public: + ResourceManagerTestInstance(){}; + virtual ~ResourceManagerTestInstance(){}; + + bool AddResource(const char *path) override + { + return false; + }; + + virtual RState UpdateResConfig(ResConfig &resConfig) + { + return ERROR; + }; + + virtual void GetResConfig(ResConfig &resConfig){}; + + virtual RState GetStringById(uint32_t id, std::string &outValue) + { + auto iter = StringById_.find(id); + if (iter == StringById_.end()) { + return ERROR; + } + outValue = iter->second; + return SUCCESS; + }; + void SetStringById(uint32_t id, std::string &inValue) override + { + if (!StringById_.empty()) { + StringById_.clear(); + } + StringById_[id] = inValue; + }; + + virtual RState GetStringByName(const char *name, std::string &outValue) + { + return ERROR; + }; + + virtual RState GetStringFormatById(std::string &outValue, uint32_t id, ...) + { + return ERROR; + }; + void SetStringFormatById(std::string &inValue, uint32_t id, ...) override{}; + + virtual RState GetStringFormatByName(std::string &outValue, const char *name, ...) + { + return ERROR; + }; + + virtual RState GetStringArrayById(uint32_t id, std::vector &outValue) + { + auto iter = StringArrayById_.find(id); + if (iter == StringArrayById_.end()) { + return ERROR; + } + outValue = iter->second; + return SUCCESS; + }; + virtual void SetStringArrayById(uint32_t id, std::vector &inValue) + { + if (!StringArrayById_.empty()) { + StringArrayById_.clear(); + } + StringArrayById_[id] = inValue; + }; + + virtual RState GetStringArrayByName(const char *name, std::vector &outValue) + { + return ERROR; + }; + + virtual RState GetPatternById(uint32_t id, std::map &outValue) + { + auto iter = PatternById_.find(id); + if (iter == PatternById_.end()) { + return ERROR; + } + outValue = iter->second; + return SUCCESS; + }; + virtual void SetPatternById(uint32_t id, std::map &inValue) + { + if (!PatternById_.empty()) { + PatternById_.clear(); + } + PatternById_[id] = inValue; + }; + + virtual RState GetPatternByName(const char *name, std::map &outValue) + { + return ERROR; + }; + + virtual RState GetPluralStringById(uint32_t id, int quantity, std::string &outValue) + { + return ERROR; + }; + + virtual RState GetPluralStringByName(const char *name, int quantity, std::string &outValue) + { + return ERROR; + }; + + virtual RState GetPluralStringByIdFormat(std::string &outValue, uint32_t id, int quantity, ...) + { + return ERROR; + }; + + virtual RState GetPluralStringByNameFormat(std::string &outValue, const char *name, int quantity, ...) + { + return ERROR; + }; + + virtual RState GetThemeById(uint32_t id, std::map &outValue) + { + + auto iter = ThemeById_.find(id); + if (iter == ThemeById_.end()) { + return ERROR; + } + outValue = iter->second; + return SUCCESS; + }; + virtual void SetThemeById(uint32_t id, std::map &inValue) + { + if (!ThemeById_.empty()) { + ThemeById_.clear(); + } + ThemeById_[id] = inValue; + }; + + virtual RState GetThemeByName(const char *name, std::map &outValue) + { + return ERROR; + }; + + virtual RState GetBooleanById(uint32_t id, bool &outValue) + { + return ERROR; + }; + + virtual RState GetBooleanByName(const char *name, bool &outValue) + { + return ERROR; + }; + + virtual RState GetIntegerById(uint32_t id, int &outValue) + { + return ERROR; + }; + + virtual RState GetIntegerByName(const char *name, int &outValue) + { + return ERROR; + }; + + virtual RState GetFloatById(uint32_t id, float &outValue) + { + return ERROR; + }; + + virtual RState GetFloatByName(const char *name, float &outValue) + { + return ERROR; + }; + + virtual RState GetIntArrayById(uint32_t id, std::vector &outValue) + { + auto iter = IntArrayById_.find(id); + if (iter == IntArrayById_.end()) { + return ERROR; + } + outValue = iter->second; + return SUCCESS; + }; + virtual void SetIntArrayById(uint32_t id, std::vector &inValue) + { + if (!IntArrayById_.empty()) { + IntArrayById_.clear(); + } + IntArrayById_[id] = inValue; + }; + + virtual RState GetIntArrayByName(const char *name, std::vector &outValue) + { + return ERROR; + }; + + virtual RState GetColorById(uint32_t id, uint32_t &outValue) + { + auto iter = ColorById_.find(id); + if (iter == ColorById_.end()) { + return ERROR; + } + outValue = iter->second; + return SUCCESS; + }; + void SetColorById(uint32_t id, uint32_t &inValue) override + { + if (!ColorById_.empty()) { + ColorById_.clear(); + } + ColorById_[id] = inValue; + }; + + virtual RState GetColorByName(const char *name, uint32_t &outValue) + { + return ERROR; + }; + + virtual RState GetProfileById(uint32_t id, std::string &outValue) + { + return ERROR; + }; + + virtual RState GetProfileByName(const char *name, std::string &outValue) + { + return ERROR; + }; + + virtual RState GetMediaById(uint32_t id, std::string &outValue) + { + return ERROR; + }; + + virtual RState GetMediaByName(const char *name, std::string &outValue) + { + return ERROR; + }; + +public: + std::map StringById_; + std::map StringFormatById_; + std::map> StringArrayById_; + std::map> PatternById_; + std::map> ThemeById_; + std::map> IntArrayById_; + std::map ColorById_; + + // static ResourceManagerTestInstance* instance; + static std::shared_ptr instance; +}; + +std::shared_ptr ResourceManagerTestInstance::instance = nullptr; + +std::shared_ptr CreateResourceManager2() +{ + if (ResourceManagerTestInstance::instance == nullptr) { /* */ + ResourceManagerTestInstance::instance = std::make_shared(); + } + return ResourceManagerTestInstance::instance; +} + +} // namespace Resource +} // namespace Global +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/test/mock/include/mock_resourceManager_interface1.h b/tools/frameworks/kits/ability/native/test/mock/include/mock_resourceManager_interface1.h new file mode 100644 index 00000000000..d6104e68cd7 --- /dev/null +++ b/tools/frameworks/kits/ability/native/test/mock/include/mock_resourceManager_interface1.h @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef OHOS_MOCK_RESOURCE_MANAGER_RESOURCEMANAGER1_H +#define OHOS_MOCK_RESOURCE_MANAGER_RESOURCEMANAGER1_H + +#include "res_config.h" +#include +#include +#include + +#include "resource_manager.h" + +namespace OHOS { +namespace Global { +namespace Resource { +class ResourceManager2 : public ResourceManager { +public: + ResourceManager2(){}; + virtual ~ResourceManager2(){}; + + virtual bool AddResource(const char *path) = 0; + + virtual RState UpdateResConfig(ResConfig &resConfig) = 0; + + virtual void GetResConfig(ResConfig &resConfig) = 0; + + virtual RState GetStringById(uint32_t id, std::string &outValue) = 0; + virtual void SetStringById(uint32_t id, std::string &outValue) = 0; + + virtual RState GetStringByName(const char *name, std::string &outValue) = 0; + + virtual RState GetStringFormatById(std::string &outValue, uint32_t id, ...) = 0; + virtual void SetStringFormatById(std::string &outValue, uint32_t id, ...) = 0; + + virtual RState GetStringFormatByName(std::string &outValue, const char *name, ...) = 0; + + virtual RState GetStringArrayById(uint32_t id, std::vector &outValue) = 0; + virtual void SetStringArrayById(uint32_t id, std::vector &outValue) = 0; + + virtual RState GetStringArrayByName(const char *name, std::vector &outValue) = 0; + + virtual RState GetPatternById(uint32_t id, std::map &outValue) = 0; + virtual void SetPatternById(uint32_t id, std::map &outValue) = 0; + + virtual RState GetPatternByName(const char *name, std::map &outValue) = 0; + + virtual RState GetPluralStringById(uint32_t id, int quantity, std::string &outValue) = 0; + + virtual RState GetPluralStringByName(const char *name, int quantity, std::string &outValue) = 0; + + virtual RState GetPluralStringByIdFormat(std::string &outValue, uint32_t id, int quantity, ...) = 0; + + virtual RState GetPluralStringByNameFormat(std::string &outValue, const char *name, int quantity, ...) = 0; + + virtual RState GetThemeById(uint32_t id, std::map &outValue) = 0; + virtual void SetThemeById(uint32_t id, std::map &outValue) = 0; + + virtual RState GetThemeByName(const char *name, std::map &outValue) = 0; + + virtual RState GetBooleanById(uint32_t id, bool &outValue) = 0; + + virtual RState GetBooleanByName(const char *name, bool &outValue) = 0; + + virtual RState GetIntegerById(uint32_t id, int &outValue) = 0; + + virtual RState GetIntegerByName(const char *name, int &outValue) = 0; + + virtual RState GetFloatById(uint32_t id, float &outValue) = 0; + + virtual RState GetFloatByName(const char *name, float &outValue) = 0; + + virtual RState GetIntArrayById(uint32_t id, std::vector &outValue) = 0; + virtual void SetIntArrayById(uint32_t id, std::vector &outValue) = 0; + + virtual RState GetIntArrayByName(const char *name, std::vector &outValue) = 0; + + virtual RState GetColorById(uint32_t id, uint32_t &outValue) = 0; + virtual void SetColorById(uint32_t id, uint32_t &outValue) = 0; + + virtual RState GetColorByName(const char *name, uint32_t &outValue) = 0; + + virtual RState GetProfileById(uint32_t id, std::string &outValue) = 0; + + virtual RState GetProfileByName(const char *name, std::string &outValue) = 0; + + virtual RState GetMediaById(uint32_t id, std::string &outValue) = 0; + + virtual RState GetMediaByName(const char *name, std::string &outValue) = 0; +}; + +std::shared_ptr CreateResourceManager2(); +} // namespace Resource +} // namespace Global +} // namespace OHOS +#endif \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/test/mock/include/mock_service_ability.h b/tools/frameworks/kits/ability/native/test/mock/include/mock_service_ability.h new file mode 100644 index 00000000000..e99e2878fed --- /dev/null +++ b/tools/frameworks/kits/ability/native/test/mock/include/mock_service_ability.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_APPEXECFWK_OHOS_MOCK_SERVICE_ABILITY_H +#define FOUNDATION_APPEXECFWK_OHOS_MOCK_SERVICE_ABILITY_H + +#include "ability.h" +#include + +namespace OHOS { +namespace AppExecFwk { +using Want = OHOS::AAFwk::Want; + +class MockServiceAbility : public Ability { +public: + MockServiceAbility() = default; + virtual ~MockServiceAbility() = default; + + bool OnKeyDown(int keyCode, const KeyEvent &keyEvent) + { + GTEST_LOG_(INFO) << "MockServiceAbility::OnKeyDown called"; + return true; + } + + bool OnKeyUp(int keyCode, const KeyEvent &keyEvent) + { + GTEST_LOG_(INFO) << "MockServiceAbility::OnKeyUp called"; + return true; + } + + bool OnTouchEvent(const TouchEvent &touchEvent) + { + GTEST_LOG_(INFO) << "MockServiceAbility::OnTouchEvent called"; + return true; + } + + void OnAbilityResult(int requestCode, int resultCode, const AAFwk::Want &resultData) + { + GTEST_LOG_(INFO) << "MockServiceAbility::OnAbilityResult called"; + } + + void OnNewWant(const Want &want) + { + GTEST_LOG_(INFO) << "MockServiceAbility::OnNewWant called"; + } + + void OnBackground() + { + GTEST_LOG_(INFO) << "MockServiceAbility::OnBackground called"; + } + + void OnStop() + { + GTEST_LOG_(INFO) << "MockServiceAbility::OnStop called"; + } + + void OnStart(const Want &want) + { + GTEST_LOG_(INFO) << "MockServiceAbility::OnStart called"; + } +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_APPEXECFWK_OHOS_MOCK_SERVICE_ABILITY_H \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/test/mock/include/sys_mgr_client_mock.cpp b/tools/frameworks/kits/ability/native/test/mock/include/sys_mgr_client_mock.cpp new file mode 100644 index 00000000000..84e9d468167 --- /dev/null +++ b/tools/frameworks/kits/ability/native/test/mock/include/sys_mgr_client_mock.cpp @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "sys_mgr_client.h" +#include "hilog_wrapper.h" +#include "if_system_ability_manager.h" +#include "ipc_skeleton.h" +#include "iservice_registry.h" +#include "string_ex.h" + +namespace OHOS { +namespace AppExecFwk { +SysMrgClient::SysMrgClient() : abilityManager_(nullptr) +{} + +SysMrgClient::~SysMrgClient() +{} + +sptr SysMrgClient::GetSystemAbility(const int32_t systemAbilityId) +{ + if (servicesMap_[systemAbilityId] == nullptr) { + OHOS::sptr abilityManager = + SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + if (abilityManager == nullptr) { + HILOG_ERROR("%s:fail to get Registry", __func__); + return nullptr; + } + OHOS::sptr object = abilityManager->GetSystemAbility(systemAbilityId); + servicesMap_[systemAbilityId] = object; + } + return servicesMap_[systemAbilityId]; +} + +void SysMrgClient::RegisterSystemAbility(const int32_t systemAbilityId, sptr broker) +{ + servicesMap_[systemAbilityId] = broker; +} +} // namespace AppExecFwk +} // namespace OHOS diff --git a/tools/frameworks/kits/ability/native/test/unittest/ability_context_for_task_dispacher_test.cpp b/tools/frameworks/kits/ability/native/test/unittest/ability_context_for_task_dispacher_test.cpp new file mode 100644 index 00000000000..526d6f12fbf --- /dev/null +++ b/tools/frameworks/kits/ability/native/test/unittest/ability_context_for_task_dispacher_test.cpp @@ -0,0 +1,221 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include "ability_context.h" +#include "application_context.h" +#include "event_runner.h" +#include "context_deal.h" + +namespace OHOS { +namespace AppExecFwk { +using namespace testing::ext; +using namespace OHOS; +using namespace OHOS::AppExecFwk; + +class AbilityContextForTaskDispatcherTest : public testing::Test { +public: + AbilityContextForTaskDispatcherTest() + {} + ~AbilityContextForTaskDispatcherTest() + {} + + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void AbilityContextForTaskDispatcherTest::SetUpTestCase(void) +{} + +void AbilityContextForTaskDispatcherTest::TearDownTestCase(void) +{} + +void AbilityContextForTaskDispatcherTest::SetUp(void) +{} + +void AbilityContextForTaskDispatcherTest::TearDown(void) +{} + +/** + * @tc.number: AaFwk_AbilityContext_GetUITaskDispatcher_0100 + * @tc.name: GetUITaskDispatcher + * @tc.desc: Test the attachbasecontext call to verify that the return value of gethapmoduleinfo is correct. + */ +HWTEST_F( + AbilityContextForTaskDispatcherTest, AaFwk_AbilityContext_GetUITaskDispatcher_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_GetUITaskDispatcher_0100 start"; + std::shared_ptr runner = EventRunner::Create(false); + std::shared_ptr contextdeal = std::make_shared(); + contextdeal->SetRunner(runner); + std::shared_ptr abilitycontext = std::make_shared(); + abilitycontext->AttachBaseContext(contextdeal); + EXPECT_TRUE((nullptr != abilitycontext->GetUITaskDispatcher())); + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_GetUITaskDispatcher_0100 end"; +} +/** + * @tc.number: AaFwk_AbilityContext_GetUITaskDispatcher_0200 + * @tc.name: GetUITaskDispatcher + * @tc.desc: Test the attachbasecontext call to verify that the return value of gethapmoduleinfo is correct. + */ +HWTEST_F( + AbilityContextForTaskDispatcherTest, AaFwk_AbilityContext_GetUITaskDispatcher_0200, Function | MediumTest | Level3) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_GetUITaskDispatcher_0200 start"; + std::shared_ptr abilitycontext = std::make_shared(); + EXPECT_TRUE((nullptr == abilitycontext->GetUITaskDispatcher())); + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_GetUITaskDispatcher_0200 end"; +} + +/** + * @tc.number: AaFwk_AbilityContext_GetMainTaskDispatcher_0100 + * @tc.name: GetMainTaskDispatcher + * @tc.desc: Test the attachbasecontext call to verify that the return value of gethapmoduleinfo is correct. + */ +HWTEST_F(AbilityContextForTaskDispatcherTest, AaFwk_AbilityContext_GetMainTaskDispatcher_0100, + Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_GetMainTaskDispatcher_0100 start"; + std::shared_ptr runner = EventRunner::Create(false); + std::shared_ptr contextdeal = std::make_shared(); + contextdeal->SetRunner(runner); + std::shared_ptr abilitycontext = std::make_shared(); + abilitycontext->AttachBaseContext(contextdeal); + EXPECT_TRUE((nullptr != abilitycontext->GetMainTaskDispatcher())); + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_GetMainTaskDispatcher_0100 end"; +} +/** + * @tc.number: AaFwk_AbilityContext_GetMainTaskDispatcher_0200 + * @tc.name: GetMainTaskDispatcher + * @tc.desc: Test the attachbasecontext call to verify that the return value of gethapmoduleinfo is correct. + */ +HWTEST_F(AbilityContextForTaskDispatcherTest, AaFwk_AbilityContext_GetMainTaskDispatcher_0200, + Function | MediumTest | Level3) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_GetMainTaskDispatcher_0200 start"; + std::shared_ptr abilitycontext = std::make_shared(); + EXPECT_TRUE((nullptr == abilitycontext->GetMainTaskDispatcher())); + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_GetMainTaskDispatcher_0200 end"; +} + +/** + * @tc.number: AaFwk_AbilityContext_CreateParallelTaskDispatcher_0100 + * @tc.name: CreateParallelTaskDispatcher + * @tc.desc: Test the attachbasecontext call to verify that the return value of gethapmoduleinfo is correct. + */ +HWTEST_F(AbilityContextForTaskDispatcherTest, AaFwk_AbilityContext_CreateParallelTaskDispatcher_0100, + Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_CreateParallelTaskDispatcher_0100 start"; + std::shared_ptr contextdeal = std::make_shared(); + std::shared_ptr appcontext = std::make_shared(); + contextdeal->SetApplicationContext(appcontext); + std::shared_ptr abilitycontext = std::make_shared(); + abilitycontext->AttachBaseContext(contextdeal); + std::string name("ParalleTest"); + TaskPriority high = TaskPriority::HIGH; + EXPECT_TRUE((nullptr != abilitycontext->CreateParallelTaskDispatcher(name, high))); + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_CreateParallelTaskDispatcher_0100 end"; +} +/** + * @tc.number: AaFwk_AbilityContext_CreateParallelTaskDispatcher_0200 + * @tc.name: CreateParallelTaskDispatcher + * @tc.desc: Test the attachbasecontext call to verify that the return value of gethapmoduleinfo is correct. + */ +HWTEST_F(AbilityContextForTaskDispatcherTest, AaFwk_AbilityContext_CreateParallelTaskDispatcher_0200, + Function | MediumTest | Level3) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_CreateParallelTaskDispatcher_0200 start"; + std::shared_ptr abilitycontext = std::make_shared(); + std::string name("ParalleTest"); + TaskPriority high = TaskPriority::HIGH; + EXPECT_TRUE((nullptr == abilitycontext->CreateParallelTaskDispatcher(name, high))); + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_CreateParallelTaskDispatcher_0200 end"; +} + +/** + * @tc.number: AaFwk_AbilityContext_CreateSerialTaskDispatcher_0100 + * @tc.name: CreateSerialTaskDispatcher + * @tc.desc: Test the attachbasecontext call to verify that the return value of gethapmoduleinfo is correct. + */ +HWTEST_F(AbilityContextForTaskDispatcherTest, AaFwk_AbilityContext_CreateSerialTaskDispatcher_0100, + Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_CreateSerialTaskDispatcher_0100 start"; + std::shared_ptr contextdeal = std::make_shared(); + std::shared_ptr appcontext = std::make_shared(); + contextdeal->SetApplicationContext(appcontext); + std::shared_ptr abilitycontext = std::make_shared(); + abilitycontext->AttachBaseContext(contextdeal); + std::string name("Serial"); + TaskPriority high = TaskPriority::HIGH; + EXPECT_TRUE((nullptr != abilitycontext->CreateSerialTaskDispatcher(name, high))); + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_CreateSerialTaskDispatcher_0100 end"; +} +/** + * @tc.number: AaFwk_AbilityContext_CreateSerialTaskDispatcher_0200 + * @tc.name: CreateSerialTaskDispatcher + * @tc.desc: Test the attachbasecontext call to verify that the return value of gethapmoduleinfo is correct. + */ +HWTEST_F(AbilityContextForTaskDispatcherTest, AaFwk_AbilityContext_CreateSerialTaskDispatcher_0200, + Function | MediumTest | Level3) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_CreateSerialTaskDispatcher_0200 start"; + std::shared_ptr abilitycontext = std::make_shared(); + std::string name("Serial"); + TaskPriority high = TaskPriority::HIGH; + EXPECT_TRUE((nullptr == abilitycontext->CreateSerialTaskDispatcher(name, high))); + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_CreateSerialTaskDispatcher_0200 end"; +} + +/** + * @tc.number: AaFwk_AbilityContext_GetGlobalTaskDispatcher_0100 + * @tc.name: GetGlobalTaskDispatcher + * @tc.desc: Test the attachbasecontext call to verify that the return value of gethapmoduleinfo is correct. + */ +HWTEST_F(AbilityContextForTaskDispatcherTest, AaFwk_AbilityContext_GetGlobalTaskDispatcher_0100, + Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_GetGlobalTaskDispatcher_0100 start"; + std::shared_ptr contextdeal = std::make_shared(); + std::shared_ptr appcontext = std::make_shared(); + contextdeal->SetApplicationContext(appcontext); + std::shared_ptr abilitycontext = std::make_shared(); + abilitycontext->AttachBaseContext(contextdeal); + TaskPriority high = TaskPriority::HIGH; + EXPECT_TRUE((nullptr != abilitycontext->GetGlobalTaskDispatcher(high))); + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_GetGlobalTaskDispatcher_0100 end"; +} +/** + * @tc.number: AaFwk_AbilityContext_GetGlobalTaskDispatcher_0200 + * @tc.name: GetGlobalTaskDispatcher + * @tc.desc: Test the attachbasecontext call to verify that the return value of gethapmoduleinfo is correct. + */ +HWTEST_F(AbilityContextForTaskDispatcherTest, AaFwk_AbilityContext_GetGlobalTaskDispatcher_0200, + Function | MediumTest | Level3) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_GetGlobalTaskDispatcher_0200 start"; + std::shared_ptr abilitycontext = std::make_shared(); + TaskPriority high = TaskPriority::HIGH; + EXPECT_TRUE((nullptr == abilitycontext->GetGlobalTaskDispatcher(high))); + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_GetGlobalTaskDispatcher_0200 end"; +} + +} // namespace AppExecFwk +} // namespace OHOS diff --git a/tools/frameworks/kits/ability/native/test/unittest/ability_context_interface1_test.cpp b/tools/frameworks/kits/ability/native/test/unittest/ability_context_interface1_test.cpp new file mode 100644 index 00000000000..249d2584fa6 --- /dev/null +++ b/tools/frameworks/kits/ability/native/test/unittest/ability_context_interface1_test.cpp @@ -0,0 +1,722 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include "gmock/gmock.h" + +#include "ability_context.h" +#include "ohos_application.h" +#include "ability_handler.h" +#include "ability_info.h" +#include "ability.h" + +#include "mock_ability_manager_client_interface1.h" +#include "mock_resourceManager_interface1.h" + +namespace OHOS { +namespace AppExecFwk { +using namespace testing::ext; + +class AbilityContextInterfaceTest : public testing::Test { +public: + AbilityContextInterfaceTest() : context_(nullptr) + {} + ~AbilityContextInterfaceTest() + {} + std::unique_ptr context_ = nullptr; + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void AbilityContextInterfaceTest::SetUpTestCase(void) +{} +void AbilityContextInterfaceTest::TearDownTestCase(void) +{} +void AbilityContextInterfaceTest::SetUp() +{} +void AbilityContextInterfaceTest::TearDown() +{} + +/** + * @tc.number: AaFwk_AbilityContext_TerminateAbilityResult_0100 + * @tc.name: TerminateAbilityResult + * @tc.desc: Test the attachbasecontext call to verify that the return value of TerminateAbilityResult is correct. + */ +HWTEST_F(AbilityContextInterfaceTest, AaFwk_AbilityContext_TerminateAbilityResult_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_TerminateAbilityResult_0100 start"; + const ErrCode testValue = ERR_OK; + OHOS::AAFwk::MockAbilityManagerClient::GetInstance()->SetTerminateAbilityResult(testValue); + std::shared_ptr abilityContext = std::make_shared(); + EXPECT_TRUE(abilityContext->TerminateAbilityResult(0)); + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_TerminateAbilityResult_0100 end"; +} + +/** + * @tc.number: AaFwk_AbilityContext_TerminateAbilityResult_0200 + * @tc.name: TerminateAbilityResult + * @tc.desc: Test the attachbasecontext call to verify that the return value of TerminateAbilityResult is correct. + */ +HWTEST_F(AbilityContextInterfaceTest, AaFwk_AbilityContext_TerminateAbilityResult_0200, Function | MediumTest | Level3) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_TerminateAbilityResult_0200 start"; + const ErrCode testValue = ERR_NO_INIT; + OHOS::AAFwk::MockAbilityManagerClient::GetInstance()->SetTerminateAbilityResult(testValue); + std::shared_ptr abilityContext = std::make_shared(); + EXPECT_FALSE(abilityContext->TerminateAbilityResult(0)); + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_TerminateAbilityResult_0200 end"; +} + +/** + * @tc.number: AaFwk_AbilityContext_TerminateAbilityResult_0300 + * @tc.name: TerminateAbilityResult + * @tc.desc: Test the attachbasecontext call to verify that the return value of TerminateAbilityResult is correct. + */ +HWTEST_F(AbilityContextInterfaceTest, AaFwk_AbilityContext_TerminateAbilityResult_0300, Function | MediumTest | Level3) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_TerminateAbilityResult_0300 start"; + OHOS::AAFwk::MockAbilityManagerClient::SetInstanceNull(false); + std::shared_ptr abilityContext = std::make_shared(); + EXPECT_FALSE(abilityContext->TerminateAbilityResult(0)); + OHOS::AAFwk::MockAbilityManagerClient::SetInstanceNull(true); + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_TerminateAbilityResult_0300 end"; +} + +/** + * @tc.number: AaFwk_AbilityContext_IsFirstInMission_0100 + * @tc.name: IsFirstInMission + * @tc.desc: Test the attachbasecontext call to verify that the return value of IsFirstInMission is correct. + */ +HWTEST_F(AbilityContextInterfaceTest, AaFwk_AbilityContext_IsFirstInMission_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_IsFirstInMission_0100 start"; + const ErrCode testValue = ERR_OK; + OHOS::AAFwk::MockAbilityManagerClient::GetInstance()->SetIsFirstInMission(testValue); + std::shared_ptr abilityContext = std::make_shared(); + EXPECT_TRUE(abilityContext->IsFirstInMission()); + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_IsFirstInMission_0100 end"; +} + +/** + * @tc.number: AaFwk_AbilityContext_IsFirstInMission_0200 + * @tc.name: IsFirstInMission + * @tc.desc: Test the attachbasecontext call to verify that the return value of IsFirstInMission is correct. + */ +HWTEST_F(AbilityContextInterfaceTest, AaFwk_AbilityContext_IsFirstInMission_0200, Function | MediumTest | Level3) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_IsFirstInMission_0200 start"; + const ErrCode testValue = ERR_NO_INIT; + OHOS::AAFwk::MockAbilityManagerClient::GetInstance()->SetIsFirstInMission(testValue); + std::shared_ptr abilityContext = std::make_shared(); + EXPECT_FALSE(abilityContext->IsFirstInMission()); + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_IsFirstInMission_0200 end"; +} + +/** + * @tc.number: AaFwk_AbilityContext_IsFirstInMission_0300 + * @tc.name: IsFirstInMission + * @tc.desc: Test the attachbasecontext call to verify that the return value of IsFirstInMission is correct. + */ +HWTEST_F(AbilityContextInterfaceTest, AaFwk_AbilityContext_IsFirstInMission_0300, Function | MediumTest | Level3) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_IsFirstInMission_0300 start"; + OHOS::AAFwk::MockAbilityManagerClient::SetInstanceNull(false); + std::shared_ptr abilityContext = std::make_shared(); + EXPECT_FALSE(abilityContext->IsFirstInMission()); + OHOS::AAFwk::MockAbilityManagerClient::SetInstanceNull(true); + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_IsFirstInMission_0300 end"; +} + +/** + * @tc.number: AaFwk_AbilityContext_SetColorMode_0100 + * @tc.name: SetColorMode + * @tc.desc: Test the attachbasecontext call to verify that the return value of SetColorMode is correct. + */ +HWTEST_F(AbilityContextInterfaceTest, AaFwk_AbilityContext_SetColorMode_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_SetColorMode_0100 start"; + std::shared_ptr abilityContext = std::make_shared(); + std::shared_ptr contextDeal = std::make_shared(); + abilityContext->AttachBaseContext(contextDeal); + int testValue = 1; + abilityContext->SetColorMode(testValue); + EXPECT_EQ(testValue, abilityContext->GetColorMode()); + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_SetColorMode_0100 end"; +} + +/** + * @tc.number: AaFwk_AbilityContext_SetColorMode_0200 + * @tc.name: SetColorMode + * @tc.desc: Test the attachbasecontext call to verify that the return value of SetColorMode is correct. + */ +HWTEST_F(AbilityContextInterfaceTest, AaFwk_AbilityContext_SetColorMode_0200, Function | MediumTest | Level3) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_SetColorMode_0200 start"; + std::shared_ptr abilityContext = std::make_shared(); + int testValue = 0; + abilityContext->SetColorMode(testValue); + EXPECT_GT(testValue, abilityContext->GetColorMode()); + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_SetColorMode_0200 end"; +} + +/** + * @tc.number: AaFwk_AbilityContext_GetColorMode_0100 + * @tc.name: GetColorMode + * @tc.desc: Test the attachbasecontext call to verify that the return value of GetColorMode is correct. + */ +HWTEST_F(AbilityContextInterfaceTest, AaFwk_AbilityContext_GetColorMode_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_GetColorMode_0100 start"; + std::shared_ptr abilityContext = std::make_shared(); + std::shared_ptr contextDeal = std::make_shared(); + abilityContext->AttachBaseContext(contextDeal); + int testValue = 1; + abilityContext->SetColorMode(testValue); + EXPECT_EQ(testValue, abilityContext->GetColorMode()); + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_GetColorMode_0100 end"; +} + +/** + * @tc.number: AaFwk_AbilityContext_GetColorMode_0200 + * @tc.name: GetColorMode + * @tc.desc: Test the attachbasecontext call to verify that the return value of GetColorMode is correct. + */ +HWTEST_F(AbilityContextInterfaceTest, AaFwk_AbilityContext_GetColorMode_0200, Function | MediumTest | Level3) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_GetColorMode_0200 start"; + std::shared_ptr abilityContext = std::make_shared(); + int testValue = 0; + abilityContext->SetColorMode(testValue); + EXPECT_GT(testValue, abilityContext->GetColorMode()); + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_GetColorMode_0200 end"; +} + +/** + * @tc.number: AaFwk_AbilityContext_SetTheme_0100 + * @tc.name: SetTheme + * @tc.desc: Test the attachbasecontext call to verify that the return value of SetTheme is correct. + */ +HWTEST_F(AbilityContextInterfaceTest, AaFwk_AbilityContext_SetTheme_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_SetTheme_0100 start"; + int testValue = 1; + std::map testList = { + {"Pattern1", "PatternA"}, {"Pattern2", "PatternB"}, {"Pattern3", "PatternC"}}; + std::shared_ptr resourceManager(Global::Resource::CreateResourceManager2()); + std::shared_ptr contextDeal = std::make_shared(); + std::shared_ptr abilityContext = std::make_shared(); + resourceManager->SetThemeById(testValue, testList); + contextDeal->initResourceManager(resourceManager); + abilityContext->AttachBaseContext(contextDeal); + abilityContext->SetTheme(testValue); + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_SetTheme_0100 end"; +} + +/** + * @tc.number: AaFwk_AbilityContext_SetTheme_0200 + * @tc.name: SetTheme + * @tc.desc: Test the attachbasecontext call to verify that the return value of SetTheme is correct. + */ +HWTEST_F(AbilityContextInterfaceTest, AaFwk_AbilityContext_SetTheme_0200, Function | MediumTest | Level3) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_SetTheme_0200 start"; + int testValue = 2; + std::shared_ptr resourceManager(Global::Resource::CreateResourceManager2()); + std::shared_ptr contextDeal = std::make_shared(); + std::shared_ptr abilityContext = std::make_shared(); + abilityContext->SetTheme(testValue); + abilityContext->AttachBaseContext(contextDeal); + abilityContext->SetTheme(testValue); + contextDeal->initResourceManager(resourceManager); + abilityContext->SetTheme(testValue); + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_SetTheme_0200 end"; +} + +/** + * @tc.number: AaFwk_AbilityContext_StartAbilities_0100 + * @tc.name: StartAbilities + * @tc.desc: Test the attachbasecontext call to verify that the return value of StartAbilities is correct. + */ +HWTEST_F(AbilityContextInterfaceTest, AaFwk_AbilityContext_StartAbilities_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_StartAbilities_0100 start"; + std::shared_ptr contextDeal = std::make_shared(); + std::shared_ptr abilityContext = std::make_shared(); + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->type = OHOS::AppExecFwk::AbilityType::DATA; + contextDeal->SetAbilityInfo(abilityInfo); + abilityContext->AttachBaseContext(contextDeal); + std::vector testlist = {AAFwk::Want(), AAFwk::Want()}; + abilityContext->StartAbilities(testlist); + EXPECT_TRUE((testlist.size() == abilityContext->GetStartAbilityRunCount())); + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_StartAbilities_0100 end"; +} + +/** + * @tc.number: AaFwk_AbilityContext_GetPreferencesDir_0100 + * @tc.name: GetPreferencesDir + * @tc.desc: Test the attachbasecontext call to verify that the return value of GetPreferencesDir is correct. + */ +HWTEST_F(AbilityContextInterfaceTest, AaFwk_AbilityContext_GetPreferencesDir_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_GetPreferencesDir_0100 start"; + std::shared_ptr abilityInfo = std::make_shared(); + std::shared_ptr applicationInfo = std::make_shared(); + std::shared_ptr contextDeal = std::make_shared(); + std::shared_ptr abilityContext = std::make_shared(); + const std::string testValue = "./1234test/preferences"; + abilityInfo->name = "test1234.1234test"; + applicationInfo->dataDir = "."; + contextDeal->SetAbilityInfo(abilityInfo); + contextDeal->SetApplicationInfo(applicationInfo); + abilityContext->AttachBaseContext(contextDeal); + EXPECT_STREQ(testValue.c_str(), abilityContext->GetPreferencesDir().c_str()); + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_GetPreferencesDir_0100 end"; +} + +/** + * @tc.number: AaFwk_AbilityContext_GetPattern_0100 + * @tc.name: GetPattern + * @tc.desc: Test the attachbasecontext call to verify that the return value of GetPattern is correct. + */ +HWTEST_F(AbilityContextInterfaceTest, AaFwk_AbilityContext_GetPattern_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_GetPattern_0100 start"; + int testValue = 0; + std::map testList = { + {"Pattern1", "PatternA"}, {"Pattern2", "PatternB"}, {"Pattern3", "PatternC"}}; + std::shared_ptr resourceManager(Global::Resource::CreateResourceManager2()); + std::shared_ptr contextDeal = std::make_shared(); + std::shared_ptr abilityContext = std::make_shared(); + resourceManager->SetPatternById(testValue, testList); + contextDeal->initResourceManager(resourceManager); + abilityContext->AttachBaseContext(contextDeal); + abilityContext->SetPattern(testValue); + std::map retVal = abilityContext->GetPattern(); + EXPECT_TRUE((retVal == testList)); + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_GetPattern_0100 end"; +} + +/** + * @tc.number: AaFwk_AbilityContext_GetTheme_0100 + * @tc.name: GetTheme + * @tc.desc: Test the attachbasecontext call to verify that the return value of GetTheme is correct. + */ +HWTEST_F(AbilityContextInterfaceTest, AaFwk_AbilityContext_GetTheme_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_GetTheme_0100 start"; + int testValue = 0; + std::map testList = {{"Theme1", "ThemeA"}, {"Theme2", "ThemeB"}, {"Theme3", "ThemeC"}}; + std::shared_ptr resourceManager(Global::Resource::CreateResourceManager2()); + std::shared_ptr contextDeal = std::make_shared(); + std::shared_ptr abilityContext = std::make_shared(); + resourceManager->SetThemeById(testValue, testList); + contextDeal->initResourceManager(resourceManager); + abilityContext->AttachBaseContext(contextDeal); + std::map retVal = abilityContext->GetTheme(); + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_GetTheme_0100 end"; +} + +/** + * @tc.number: AaFwk_AbilityContext_GetString_ById_0100 + * @tc.name: GetString + * @tc.desc: Test the attachbasecontext call to verify that the return value of GetString is correct. + */ +HWTEST_F(AbilityContextInterfaceTest, AaFwk_AbilityContext_GetString_ById_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_GetString_ById_0100 start"; + std::shared_ptr resourceManager(Global::Resource::CreateResourceManager2()); + std::shared_ptr contextDeal = std::make_shared(); + std::shared_ptr abilityContext = std::make_shared(); + int testCount = 0; + std::string testValue = "GetString test"; + resourceManager->SetStringById(testCount, testValue); + contextDeal->initResourceManager(resourceManager); + abilityContext->AttachBaseContext(contextDeal); + EXPECT_STREQ(testValue.c_str(), abilityContext->GetString(testCount).c_str()); + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_GetString_ById_0100 end"; +} + +/** + * @tc.number: AaFwk_AbilityContext_GetString_ByIdAndFormat_0100 + * @tc.name: GetString + * @tc.desc: Test the attachbasecontext call to verify that the return value of GetString is correct. + */ +HWTEST_F(AbilityContextInterfaceTest, AaFwk_AbilityContext_GetString_ByIdAndFormat_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_GetString_ByIdAndFormat_0100 start"; + std::shared_ptr resourceManager(Global::Resource::CreateResourceManager2()); + std::shared_ptr contextDeal = std::make_shared(); + std::shared_ptr abilityContext = std::make_shared(); + std::string testByName = ""; + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_GetString_ByIdAndFormat_0100 end"; +} + +/** + * @tc.number: AaFwk_AbilityContext_GetStringArray_0100 + * @tc.name: GetStringArray + * @tc.desc: Test the attachbasecontext call to verify that the return value of GetStringArray is correct. + */ +HWTEST_F(AbilityContextInterfaceTest, AaFwk_AbilityContext_GetStringArray_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_GetStringArray_0100 start"; + std::shared_ptr resourceManager(Global::Resource::CreateResourceManager2()); + std::shared_ptr contextDeal = std::make_shared(); + std::shared_ptr abilityContext = std::make_shared(); + int testCount = 0; + std::vector testValue = {"123", "456", "789"}; + resourceManager->SetStringArrayById(testCount, testValue); + contextDeal->initResourceManager(resourceManager); + abilityContext->AttachBaseContext(contextDeal); + std::vector retVal = abilityContext->GetStringArray(testCount); + EXPECT_TRUE((retVal == testValue)); + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_GetStringArray_0100 end"; +} + +/** + * @tc.number: AaFwk_AbilityContext_GetStringArray_0200 + * @tc.name: GetStringArray + * @tc.desc: Test the attachbasecontext call to verify that the return value of GetStringArray is correct. + */ +HWTEST_F(AbilityContextInterfaceTest, AaFwk_AbilityContext_GetStringArray_0200, Function | MediumTest | Level3) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_GetStringArray_0200 start"; + std::shared_ptr resourceManager(Global::Resource::CreateResourceManager2()); + std::shared_ptr contextDeal = std::make_shared(); + std::shared_ptr abilityContext = std::make_shared(); + int testCount = 0; + std::vector testValue = {"123", "456", "789"}; + resourceManager->SetStringArrayById(testCount + 1, testValue); + contextDeal->initResourceManager(resourceManager); + abilityContext->AttachBaseContext(contextDeal); + std::vector retVal = abilityContext->GetStringArray(testCount); + EXPECT_FALSE((retVal == testValue)); + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_GetStringArray_0200 end"; +} + +/** + * @tc.number: AaFwk_AbilityContext_GetIntArray_0100 + * @tc.name: GetIntArray + * @tc.desc: Test the attachbasecontext call to verify that the return value of GetIntArray is correct. + */ +HWTEST_F(AbilityContextInterfaceTest, AaFwk_AbilityContext_GetIntArray_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_GetIntArray_0100 start"; + std::shared_ptr resourceManager(Global::Resource::CreateResourceManager2()); + std::shared_ptr contextDeal = std::make_shared(); + std::shared_ptr abilityContext = std::make_shared(); + int testCount = 0; + std::vector testValue = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0}; + resourceManager->SetIntArrayById(testCount, testValue); + contextDeal->initResourceManager(resourceManager); + abilityContext->AttachBaseContext(contextDeal); + std::vector retVal = abilityContext->GetIntArray(testCount); + EXPECT_TRUE((retVal == testValue)); + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_GetIntArray_0100 end"; +} + +/** + * @tc.number: AaFwk_AbilityContext_GetIntArray_0200 + * @tc.name: GetIntArray + * @tc.desc: Test the attachbasecontext call to verify that the return value of GetIntArray is correct. + */ +HWTEST_F(AbilityContextInterfaceTest, AaFwk_AbilityContext_GetIntArray_0200, Function | MediumTest | Level3) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_GetIntArray_0200 start"; + std::shared_ptr resourceManager(Global::Resource::CreateResourceManager2()); + std::shared_ptr contextDeal = std::make_shared(); + std::shared_ptr abilityContext = std::make_shared(); + int testCount = 0; + std::vector testValue = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0}; + resourceManager->SetIntArrayById(testCount + 1, testValue); + contextDeal->initResourceManager(resourceManager); + abilityContext->AttachBaseContext(contextDeal); + std::vector retVal = abilityContext->GetIntArray(testCount); + EXPECT_FALSE((retVal == testValue)); + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_GetIntArray_0200 end"; +} + +/** + * @tc.number: AaFwk_AbilityContext_GetColor_0100 + * @tc.name: GetColor + * @tc.desc: Test the attachbasecontext call to verify that the return value of GetColor is correct. + */ +HWTEST_F(AbilityContextInterfaceTest, AaFwk_AbilityContext_GetColor_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_GetColor_0100 start"; + std::shared_ptr resourceManager(Global::Resource::CreateResourceManager2()); + std::shared_ptr contextDeal = std::make_shared(); + std::shared_ptr abilityContext = std::make_shared(); + int testCount = 0; + uint32_t testValue = 1; + const int testVal = static_cast(testValue); + resourceManager->SetColorById(testCount, testValue); + contextDeal->initResourceManager(resourceManager); + abilityContext->AttachBaseContext(contextDeal); + EXPECT_EQ(testVal, abilityContext->GetColor(testCount)); + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_GetColor_0100 end"; +} + +/** + * @tc.number: AaFwk_AbilityContext_GetColor_0200 + * @tc.name: GetColor + * @tc.desc: Test the attachbasecontext call to verify that the return value of GetColor is correct. + */ +HWTEST_F(AbilityContextInterfaceTest, AaFwk_AbilityContext_GetColor_0200, Function | MediumTest | Level3) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_GetColor_0200 start"; + std::shared_ptr resourceManager(Global::Resource::CreateResourceManager2()); + std::shared_ptr contextDeal = std::make_shared(); + std::shared_ptr abilityContext = std::make_shared(); + int testCount = 0; + uint32_t testValue = 1; + const int testVal = static_cast(testValue); + resourceManager->SetColorById(testCount + 1, testValue); + contextDeal->initResourceManager(resourceManager); + abilityContext->AttachBaseContext(contextDeal); + EXPECT_NE(testVal, abilityContext->GetColor(testCount)); + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_GetColor_0200 end"; +} + +/** + * @tc.number: AaFwk_AbilityContext_GetThemeId_0100 + * @tc.name: GetThemeId + * @tc.desc: Test the attachbasecontext call to verify that the return value of GetThemeId is correct. + */ +HWTEST_F(AbilityContextInterfaceTest, AaFwk_AbilityContext_GetThemeId_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_GetThemeId_0100 start"; + std::shared_ptr contextDeal = std::make_shared(); + std::shared_ptr abilityContext = std::make_shared(); + abilityContext->AttachBaseContext(contextDeal); + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_GetThemeId_0100 end"; +} + +/** + * @tc.number: AaFwk_AbilityContext_GetDisplayOrientation_0100 + * @tc.name: GetDisplayOrientation + * @tc.desc: Test the attachbasecontext call to verify that the return value of GetDisplayOrientation is correct. + */ +HWTEST_F(AbilityContextInterfaceTest, AaFwk_AbilityContext_GetDisplayOrientation_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_GetDisplayOrientation_0100 start"; + std::shared_ptr contextDeal = std::make_shared(); + std::shared_ptr abilityContext = std::make_shared(); + std::shared_ptr abilityInfo = std::make_shared(); + int testValue = 1; + abilityInfo->orientation = static_cast(testValue); + contextDeal->SetAbilityInfo(abilityInfo); + abilityContext->AttachBaseContext(contextDeal); + EXPECT_EQ(testValue, abilityContext->GetDisplayOrientation()); + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_GetDisplayOrientation_0100 end"; +} + +/** + * @tc.number: AaFwk_AbilityContext_SetPattern_0100 + * @tc.name: SetPattern + * @tc.desc: Test the attachbasecontext call to verify that the return value of SetPattern is correct. + */ +HWTEST_F(AbilityContextInterfaceTest, AaFwk_AbilityContext_SetPattern_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_SetPattern_0100 start"; + std::shared_ptr resourceManager(Global::Resource::CreateResourceManager2()); + std::shared_ptr contextDeal = std::make_shared(); + std::shared_ptr abilityContext = std::make_shared(); + int testCount = 0; + std::map testList = {{"123", "abc"}, {"456", "def"}}; + resourceManager->SetPatternById(testCount, testList); + contextDeal->initResourceManager(resourceManager); + abilityContext->AttachBaseContext(contextDeal); + abilityContext->SetPattern(testCount); + std::map retVal; + EXPECT_FALSE((retVal == testList)); + retVal = abilityContext->GetPattern(); + EXPECT_TRUE((retVal == testList)); + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_SetPattern_0100 end"; +} + +/** + * @tc.number: AaFwk_AbilityContext_TerminateAbility_0100 + * @tc.name: TerminateAbility + * @tc.desc: Test the attachbasecontext call to verify that the return value of TerminateAbility is correct. + */ +HWTEST_F(AbilityContextInterfaceTest, AaFwk_AbilityContext_TerminateAbility_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_TerminateAbility_0100 start"; + const ErrCode mockValue = ERR_OK; + int testValue = 0; + OHOS::AAFwk::MockAbilityManagerClient::GetInstance()->SetTerminateAbility(mockValue); + std::shared_ptr abilityContext = std::make_shared(); + abilityContext->TerminateAbility(testValue); + EXPECT_EQ(testValue, AAFwk::MockAbilityManagerClient::GetInstance()->GetTerminateAbilityValue()); + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_TerminateAbility_0100 end"; +} + +/** + * @tc.number: AaFwk_Ability_TerminateAndRemoveMission_0100 + * @tc.name: TerminateAndRemoveMission + * @tc.desc: Test the attachbasecontext call to verify that the return value of TerminateAbility is correct. + */ +HWTEST_F(AbilityContextInterfaceTest, AaFwk_Ability_TerminateAndRemoveMission_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_Ability_TerminateAndRemoveMission_0100 start"; + const ErrCode mockValue = ERR_OK; + OHOS::AAFwk::MockAbilityManagerClient::GetInstance()->SetRemoveMissions(mockValue); + std::shared_ptr contextDeal = std::make_shared(); + std::shared_ptr lifeCycleStateInfo = std::make_shared(); + std::shared_ptr ability = std::make_shared(); + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "TerminateAndRemoveMission"; + std::shared_ptr ohosApplication = std::make_shared(); + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + std::shared_ptr abilityHandler = std::make_shared(eventRunner, abilityThread); + sptr token = nullptr; + int testValue = OHOS::AAFwk::MockAbilityManagerClient::GetInstance()->GetRemoveMissionsValue(); + lifeCycleStateInfo->missionId = 0; + contextDeal->SetLifeCycleStateInfo(*lifeCycleStateInfo); + ability->Init(abilityInfo, ohosApplication, abilityHandler, token); + ability->AttachBaseContext(contextDeal); + ability->OnActive(); + ability->TerminateAndRemoveMission(); + EXPECT_NE(testValue, AAFwk::MockAbilityManagerClient::GetInstance()->GetRemoveMissionsValue()); + GTEST_LOG_(INFO) << "AaFwk_Ability_TerminateAndRemoveMission_0100 end"; +} + +/** + * @tc.number: AaFwk_Ability_TerminateAndRemoveMission_0200 + * @tc.name: TerminateAndRemoveMission + * @tc.desc: Test the attachbasecontext call to verify that the return value of TerminateAbility is correct. + */ +HWTEST_F(AbilityContextInterfaceTest, AaFwk_Ability_TerminateAndRemoveMission_0200, Function | MediumTest | Level3) +{ + GTEST_LOG_(INFO) << "AaFwk_Ability_TerminateAndRemoveMission_0200 start"; + const ErrCode mockValue = ERR_OK; + OHOS::AAFwk::MockAbilityManagerClient::GetInstance()->SetRemoveMissions(mockValue); + std::shared_ptr contextDeal = std::make_shared(); + std::shared_ptr lifeCycleStateInfo = std::make_shared(); + std::shared_ptr ability = std::make_shared(); + int testValue = OHOS::AAFwk::MockAbilityManagerClient::GetInstance()->GetRemoveMissionsValue(); + lifeCycleStateInfo->missionId = 0; + contextDeal->SetLifeCycleStateInfo(*lifeCycleStateInfo); + ability->AttachBaseContext(contextDeal); + ability->OnActive(); + ability->TerminateAndRemoveMission(); + EXPECT_EQ(testValue, AAFwk::MockAbilityManagerClient::GetInstance()->GetRemoveMissionsValue()); + GTEST_LOG_(INFO) << "AaFwk_Ability_TerminateAndRemoveMission_0200 end"; +} + +HWTEST_F(AbilityContextInterfaceTest, AaFwk_AbilityContext_MoveMissionToEnd_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_MoveMissionToEnd_0100 start"; + std::shared_ptr abilityContext = std::make_shared(); + const sptr token(new (std::nothrow) MockAbilityStub()); + bool testValue = OHOS::AAFwk::MockAbilityManagerClient::GetInstance()->GetMockMoveMissionToEnd(); + + abilityContext->SetToken(token); + EXPECT_TRUE(abilityContext->MoveMissionToEnd(!testValue)); + + if (testValue) { + EXPECT_FALSE(OHOS::AAFwk::MockAbilityManagerClient::GetInstance()->GetMockMoveMissionToEnd()); + } else { + EXPECT_TRUE(OHOS::AAFwk::MockAbilityManagerClient::GetInstance()->GetMockMoveMissionToEnd()); + } + + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_MoveMissionToEnd_0100 end"; +} + +HWTEST_F(AbilityContextInterfaceTest, AaFwk_AbilityContext_LockMission_0100, Function | MediumTest | Level3) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_LockMission_0100 start"; + std::shared_ptr abilityContext = std::make_shared(); + std::shared_ptr contextDeal = std::make_shared(); + + int testValue = OHOS::AAFwk::MockAbilityManagerClient::GetInstance()->GetMockMissionId(); + testValue++; + AAFwk::LifeCycleStateInfo lifeInfo; + lifeInfo.missionId = testValue; + contextDeal->SetLifeCycleStateInfo(lifeInfo); + abilityContext->AttachBaseContext(contextDeal); + + abilityContext->LockMission(); + + EXPECT_EQ(testValue, OHOS::AAFwk::MockAbilityManagerClient::GetInstance()->GetMockMissionId()); + + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_LockMission_0100 end"; +} + +HWTEST_F(AbilityContextInterfaceTest, AaFwk_AbilityContext_UnlockMission_0100, Function | MediumTest | Level3) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_UnlockMission_0100 start"; + std::shared_ptr abilityContext = std::make_shared(); + std::shared_ptr contextDeal = std::make_shared(); + + int testValue = OHOS::AAFwk::MockAbilityManagerClient::GetInstance()->GetMockMissionId(); + testValue++; + AAFwk::LifeCycleStateInfo lifeInfo; + lifeInfo.missionId = testValue; + contextDeal->SetLifeCycleStateInfo(lifeInfo); + abilityContext->AttachBaseContext(contextDeal); + + abilityContext->UnlockMission(); + + EXPECT_EQ(testValue, OHOS::AAFwk::MockAbilityManagerClient::GetInstance()->GetMockMissionId()); + + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_UnlockMission_0100 end"; +} + +HWTEST_F(AbilityContextInterfaceTest, AaFwk_AbilityContext_GetMissionId_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_GetMissionId_0100 start"; + std::shared_ptr abilityContext = std::make_shared(); + std::shared_ptr contextDeal = std::make_shared(); + const int testValue = 1; + + EXPECT_NE(testValue, abilityContext->GetMissionId()); + + abilityContext->AttachBaseContext(contextDeal); + + EXPECT_NE(testValue, abilityContext->GetMissionId()); + + AAFwk::LifeCycleStateInfo lifeInfo; + lifeInfo.missionId = testValue; + contextDeal->SetLifeCycleStateInfo(lifeInfo); + + EXPECT_EQ(testValue, abilityContext->GetMissionId()); + + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_GetMissionId_0100 end"; +} + +HWTEST_F(AbilityContextInterfaceTest, AaFwk_AbilityContext_SetMissionInformation_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_SetMissionInformation_0100 start"; + std::shared_ptr abilityContext = std::make_shared(); + const sptr token(new (std::nothrow) MockAbilityStub()); + AppExecFwk::MissionInformation missionInformation; + + EXPECT_FALSE(abilityContext->SetMissionInformation(missionInformation)); + + abilityContext->SetToken(token); + + EXPECT_TRUE(abilityContext->SetMissionInformation(missionInformation)); + + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_SetMissionInformation_0100 end"; +} + +} // namespace AppExecFwk +} // namespace OHOS diff --git a/tools/frameworks/kits/ability/native/test/unittest/ability_context_test.cpp b/tools/frameworks/kits/ability/native/test/unittest/ability_context_test.cpp new file mode 100644 index 00000000000..52231897ad4 --- /dev/null +++ b/tools/frameworks/kits/ability/native/test/unittest/ability_context_test.cpp @@ -0,0 +1,578 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include "ability_context.h" +#include "ohos_application.h" +#include "ability_info.h" +#include "ability.h" +#include "context_deal.h" +#include "iservice_registry.h" +#include "mock_bundle_manager.h" +#include "mock_ability_manager_service.h" +#include "system_ability_definition.h" +#include "sys_mgr_client.h" +#include "sa_mgr_client.h" + +namespace OHOS { +namespace AppExecFwk { +using namespace testing::ext; +using namespace OHOS; +using namespace OHOS::AppExecFwk; + +class AbilityContextTest : public testing::Test { +public: + AbilityContextTest() : context_(nullptr) + {} + ~AbilityContextTest() + {} + std::unique_ptr context_ = nullptr; + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void AbilityContextTest::SetUpTestCase(void) +{ + GTEST_LOG_(INFO) << "AppExecFwk_AbilityContext_SetUpTestCase start"; + OHOS::sptr bundleObject = new (std::nothrow) BundleMgrService(); + OHOS::sptr abilityObject = new (std::nothrow) OHOS::AAFwk::MockAbilityManagerService(); + + auto sysMgr = OHOS::DelayedSingleton::GetInstance(); + if (sysMgr == NULL) { + GTEST_LOG_(ERROR) << "fail to get ISystemAbilityManager"; + return; + } + + sysMgr->RegisterSystemAbility(OHOS::BUNDLE_MGR_SERVICE_SYS_ABILITY_ID, bundleObject); + sysMgr->RegisterSystemAbility(OHOS::ABILITY_MGR_SERVICE_ID, abilityObject); + + GTEST_LOG_(INFO) << "AppExecFwk_AbilityContext_SetUpTestCase end"; +} + +void AbilityContextTest::TearDownTestCase(void) +{} + +void AbilityContextTest::SetUp(void) +{ + context_ = std::make_unique(); + GTEST_LOG_(INFO) << "AppExecFwk_AbilityContext_SetUp end"; +} + +void AbilityContextTest::TearDown(void) +{} + + +/** + * @tc.number: AaFwk_AbilityContext_StartAbility_0100 + * @tc.name: StartAbility + * @tc.desc: Test whether startability is called normally. + */ +HWTEST_F(AbilityContextTest, AaFwk_AbilityContext_StartAbility_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_StartAbility_0100 start"; + AAFwk::Want want; + int requestCode = 0; + context_->StartAbility(want, requestCode); + GTEST_LOG_(INFO) << "AaFwk_AbilityContext_StartAbility_0100 end"; +} + +/** + * @tc.number: AaFwk_AbilityContext_TerminateAbility_0100 + * @tc.name: TerminateAbility + * @tc.desc: Test whether TerminateAbility is called normally. + */ +HWTEST_F(AbilityContextTest, AaFwk_AbilityContext_TerminateAbility_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AppExecFwk_AbilityContext_TerminateAbility_0100 start"; + context_->TerminateAbility(); + GTEST_LOG_(INFO) << "AppExecFwk_AbilityContext_TerminateAbility_0100 end"; +} + +/** + * @tc.number: AaFwk_AbilityContext_GetCallingAbility_0100 + * @tc.name: GetCallingAbility + * @tc.desc: Test whether the return value of getcallingability is correct. + */ +HWTEST_F(AbilityContextTest, AaFwk_AbilityContext_GetCallingAbility_0100, Function | MediumTest | Level1) +{ + // init + AAFwk::Want want; + OHOS::AppExecFwk::ElementName elementName; + elementName.SetBundleName(std::string("App.System.Test.bundleName_0127")); + elementName.SetAbilityName(std::string("App.System.Test.AbilityName_0127")); + want.SetElement(elementName); + + std::shared_ptr ability = std::make_shared(); + // start + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->type = AppExecFwk::AbilityType::PAGE; + std::shared_ptr handler = nullptr; + ability->Init(abilityInfo, nullptr, handler, nullptr); + ability->StartAbilityForResult(want, -1); + + ability->SetCallingContext("", "", std::string("App.System.Test.AbilityName_0127")); + std::shared_ptr elementNameTest = ability->GetCallingAbility(); + std::string abilityName; + if (elementNameTest != nullptr) { + abilityName = elementNameTest->GetAbilityName(); + } + + // Test + EXPECT_EQ(abilityName, std::string("App.System.Test.AbilityName_0127")); +} + +/** + * @tc.number: AaFwk_AbilityContext_GetApplicationInfo_0100 + * @tc.name: GetApplicationInfo + * @tc.desc: Test whether the getapplicationinfo return value is correct. + */ +HWTEST_F(AbilityContextTest, AaFwk_AbilityContext_GetApplicationInfo_0100, Function | MediumTest | Level1) +{ + std::shared_ptr deal = std::make_shared(); + std::shared_ptr info = std::make_shared(); + std::string name = "WeChat"; + info->name = name; + deal->SetApplicationInfo(info); + + context_->AttachBaseContext(deal); + EXPECT_STREQ(name.c_str(), context_->GetApplicationInfo()->name.c_str()); +} + +/** + * @tc.number: AaFwk_AbilityContext_GetCacheDir_0100 + * @tc.name: GetCacheDir + * @tc.desc: Test the attachbasecontext call to verify whether the return value of getcachedir is correct. + */ +HWTEST_F(AbilityContextTest, AaFwk_AbilityContext_GetCacheDir_0100, Function | MediumTest | Level1) +{ + std::shared_ptr deal = std::make_shared(); + std::shared_ptr info = std::make_shared(); + std::string dir = "CacheDir"; + info->cacheDir = dir; + deal->SetApplicationInfo(info); + context_->AttachBaseContext(deal); + + EXPECT_STREQ(dir.c_str(), context_->GetCacheDir().c_str()); +} + +/** + * @tc.number: AaFwk_AbilityContext_GetCodeCacheDir_0100 + * @tc.name: GetCodeCacheDir + * @tc.desc: Test the attachbasecontext call to verify whether the return value of getcodechedir is correct. + */ +HWTEST_F(AbilityContextTest, AaFwk_AbilityContext_GetCodeCacheDir_0100, Function | MediumTest | Level1) +{ + std::shared_ptr deal = std::make_shared(); + std::shared_ptr info = std::make_shared(); + std::string dir = "CacheDir"; + info->dataDir = dir; + deal->SetApplicationInfo(info); + context_->AttachBaseContext(deal); + std::string dirCompare = "CacheDir/code_cache"; + EXPECT_STREQ(dirCompare.c_str(), context_->GetCodeCacheDir().c_str()); +} + +/** + * @tc.number: AaFwk_AbilityContext_GetDatabaseDir_0100 + * @tc.name: GetDatabaseDir + * @tc.desc: Test the attachbasecontext call to verify whether the return value of getdatabasedir is correct. + */ +HWTEST_F(AbilityContextTest, AaFwk_AbilityContext_GetDatabaseDir_0100, Function | MediumTest | Level1) +{ + std::shared_ptr deal = std::make_shared(); + std::shared_ptr info = std::make_shared(); + std::string dir = "dataBaseDir"; + info->dataBaseDir = dir; + deal->SetApplicationInfo(info); + context_->AttachBaseContext(deal); + + EXPECT_STREQ(dir.c_str(), context_->GetDatabaseDir().c_str()); +} + +/** + * @tc.number: AaFwk_AbilityContext_GetDataDir_0100 + * @tc.name: GetDataDir + * @tc.desc: Test the attachbasecontext call to verify whether the return value of getdatadir is correct. + */ +HWTEST_F(AbilityContextTest, AaFwk_AbilityContext_GetDataDir_0100, Function | MediumTest | Level1) +{ + std::shared_ptr deal = std::make_shared(); + std::shared_ptr info = std::make_shared(); + std::string dir = "dataDir"; + info->dataDir = dir; + deal->SetApplicationInfo(info); + context_->AttachBaseContext(deal); + + EXPECT_STREQ(dir.c_str(), context_->GetDataDir().c_str()); +} + +/** + * @tc.number: AaFwk_AbilityContext_GetBundleManager_0100 + * @tc.name: GetBundleManager + * @tc.desc: Test the attachbasecontext call to verify whether the return value of getbundlemanager is correct. + */ +HWTEST_F(AbilityContextTest, AaFwk_AbilityContext_GetBundleManager_0100, Function | MediumTest | Level3) +{ + std::shared_ptr deal = std::make_shared(); + context_->AttachBaseContext(deal); + sptr ptr = context_->GetBundleManager(); + + EXPECT_NE(nullptr, ptr); +} + +/** + * @tc.number: AaFwk_AbilityContext_GetBundleCodePath_0100 + * @tc.name: GetBundleCodePath + * @tc.desc: Test the attachbasecontext call to verify whether the return value of getbundlecodepath is correct. + */ +HWTEST_F(AbilityContextTest, AaFwk_AbilityContext_GetBundleCodePath_0100, Function | MediumTest | Level1) +{ + std::shared_ptr appInfo = std::make_shared(); + std::string codePath = "hello"; + appInfo->codePath = codePath; + + std::shared_ptr deal = std::make_shared(); + deal->SetApplicationInfo(appInfo); + + context_->AttachBaseContext(deal); + EXPECT_STREQ(codePath.c_str(), context_->GetBundleCodePath().c_str()); +} + +/** + * @tc.number: AaFwk_AbilityContext_GetBundleName_0100 + * @tc.name: GetBundleName + * @tc.desc: Test the attachbasecontext call to verify whether the return value of getbundlename is correct. + */ +HWTEST_F(AbilityContextTest, AaFwk_AbilityContext_GetBundleName_0100, Function | MediumTest | Level1) +{ + std::shared_ptr appInfo = std::make_shared(); + std::string name = "hello"; + appInfo->bundleName = name; + + std::shared_ptr deal = std::make_shared(); + deal->SetApplicationInfo(appInfo); + + context_->AttachBaseContext(deal); + EXPECT_STREQ(name.c_str(), context_->GetBundleName().c_str()); +} + +/** + * @tc.number: AaFwk_AbilityContext_GetBundleResourcePath_0100 + * @tc.name: GetBundleResourcePath + * @tc.desc: Test the attachbasecontext call to verify whether the return value of getbundleresourcepath is correct. + */ +HWTEST_F(AbilityContextTest, AaFwk_AbilityContext_GetBundleResourcePath_0100, Function | MediumTest | Level1) +{ + std::shared_ptr abilityInfo = std::make_shared(); + std::string resourcePath = "hello"; + abilityInfo->resourcePath = resourcePath; + + std::shared_ptr deal = std::make_shared(); + deal->SetAbilityInfo(abilityInfo); + + context_->AttachBaseContext(deal); + EXPECT_STREQ(resourcePath.c_str(), context_->GetBundleResourcePath().c_str()); +} + +/** + * @tc.number: AaFwk_AbilityContext_GetApplicationContext_0100 + * @tc.name: GetApplicationContext + * @tc.desc: Test the attachbasecontext call to verify whether the return value of getapplicationcontext is correct. + */ +HWTEST_F(AbilityContextTest, AaFwk_AbilityContext_GetApplicationContext_0100, Function | MediumTest | Level3) +{ + std::shared_ptr application = std::make_shared(); + std::shared_ptr deal = std::make_shared(); + deal->SetApplicationContext(application); + context_->AttachBaseContext(deal); + EXPECT_NE(nullptr, context_->GetApplicationContext()); +} + +/** + * @tc.number: AaFwk_AbilityContext_GetContext_0100 + * @tc.name: GetContext + * @tc.desc: Test the attachbasecontext call to verify whether the getcontext return value is correct. + */ +HWTEST_F(AbilityContextTest, AaFwk_AbilityContext_GetContext_0100, Function | MediumTest | Level1) +{ + std::shared_ptr ability = std::make_shared(); + std::shared_ptr deal = std::make_shared(); + std::shared_ptr abilityInfo = std::make_shared(); + + std::string name = "hello"; + abilityInfo->name = name; + + deal->SetAbilityInfo(abilityInfo); + std::shared_ptr context(ability); + deal->SetContext(context); + ability->AttachBaseContext(deal); + + EXPECT_STREQ(name.c_str(), ability->GetContext()->GetAbilityInfo()->name.c_str()); +} + +/** + * @tc.number: AaFwk_AbilityContext_GetAbilityManager_0100 + * @tc.name: GetAbilityManager + * @tc.desc: Test the attachbasecontext call to verify whether the return value of getabilitymanager is correct. + */ +HWTEST_F(AbilityContextTest, AaFwk_AbilityContext_GetAbilityManager_0100, Function | MediumTest | Level3) +{ + std::shared_ptr deal = std::make_shared(); + context_->AttachBaseContext(deal); + sptr ptr = context_->GetAbilityManager(); + + EXPECT_NE(nullptr, ptr); +} + +/** + * @tc.number: AaFwk_AbilityContext_GetProcessInfo_0100 + * @tc.name: GetProcessInfo + * @tc.desc: Test the attachbasecontext call to verify that the getprocessinfo return value is correct. + */ +HWTEST_F(AbilityContextTest, AaFwk_AbilityContext_GetProcessInfo_0100, Function | MediumTest | Level1) +{ + std::string name = "OHOS"; + pid_t id = 0; + ProcessInfo info(name, id); + + std::shared_ptr processInfo = std::make_shared(info); + std::shared_ptr deal = std::make_shared(); + deal->SetProcessInfo(processInfo); + context_->AttachBaseContext(deal); + + EXPECT_STREQ(name.c_str(), context_->GetProcessInfo()->GetProcessName().c_str()); +} + +/** + * @tc.number: AaFwk_AbilityContext_GetAppType_0100 + * @tc.name: GetAppType + * @tc.desc: Test the attachbasecontext call to verify that the getapptype return value is correct. + */ +HWTEST_F(AbilityContextTest, AaFwk_AbilityContext_GetAppType_0100, Function | MediumTest | Level1) +{ + std::string empty = "system"; + std::shared_ptr deal = std::make_shared(); + std::shared_ptr info = std::make_shared(); + info->bundleName = "hello"; + deal->SetApplicationInfo(info); + context_->AttachBaseContext(deal); + + EXPECT_STREQ(empty.c_str(), context_->GetAppType().c_str()); +} + +/** + * @tc.number: AaFwk_AbilityContext_GetAbilityInfo_0100 + * @tc.name: GetAbilityInfo + * @tc.desc: Test the attachbasecontext call to verify that the getabilityinfo return value is correct. + */ +HWTEST_F(AbilityContextTest, AaFwk_AbilityContext_GetAbilityInfo_0100, Function | MediumTest | Level1) +{ + std::shared_ptr deal = std::make_shared(); + std::shared_ptr abilityInfo = std::make_shared(); + + std::string name = "hello"; + abilityInfo->name = name; + deal->SetAbilityInfo(abilityInfo); + context_->AttachBaseContext(deal); + + EXPECT_STREQ(name.c_str(), context_->GetAbilityInfo()->name.c_str()); +} + +/** + * @tc.number: AaFwk_AbilityContext_GetElementName_0100 + * @tc.name: GetElementName + * @tc.desc: Verify that the getelementname return value is correct. + */ +HWTEST_F(AbilityContextTest, AaFwk_AbilityContext_GetElementName_0100, Function | MediumTest | Level3) +{ + EXPECT_EQ(nullptr, context_->GetElementName()); +} + +/** + * @tc.number: AaFwk_AbilityContext_GetElementName_0200 + * @tc.name: GetElementName + * @tc.desc: Test getelementname exception status. + */ +HWTEST_F(AbilityContextTest, AaFwk_AbilityContext_GetElementName_0200, Function | MediumTest | Level3) +{ + std::shared_ptr deal = std::make_shared(); + std::shared_ptr abilityInfo = std::make_shared(); + + std::string name = "abilityName"; + abilityInfo->name = name; + deal->SetAbilityInfo(abilityInfo); + context_->AttachBaseContext(deal); + + EXPECT_STREQ(name.c_str(), context_->GetElementName()->GetAbilityName().c_str()); +} + +/** + * @tc.number: AaFwk_AbilityContext_GetCallingBundle_0100 + * @tc.name: GetCallingBundle + * @tc.desc: Test getcallingbundle exception state. + */ +HWTEST_F(AbilityContextTest, AaFwk_AbilityContext_GetCallingBundle_0100, Function | MediumTest | Level3) +{ + std::string empty = ""; + EXPECT_STREQ(empty.c_str(), context_->GetCallingBundle().c_str()); +} + +/** + * @tc.number: AaFwk_AbilityContext_GetCallingBundle_0200 + * @tc.name: GetCallingBundle + * @tc.desc: Test whether the return value of getcallingbundle is correct. + */ +HWTEST_F(AbilityContextTest, AaFwk_AbilityContext_GetCallingBundle_0200, Function | MediumTest | Level1) +{ + Want want; + std::string bundleName = "BundleName"; + std::string abilityName = "abilityName"; + want.SetElementName(bundleName, abilityName); + + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->type = AppExecFwk::AbilityType::PAGE; + std::shared_ptr handler = nullptr; + std::shared_ptr ability = std::make_shared(); + ability->Init(abilityInfo, nullptr, handler, nullptr); + ability->StartAbilityForResult(want, -1); + ability->SetCallingContext("", "BundleName", ""); + + EXPECT_STREQ(bundleName.c_str(), ability->GetCallingBundle().c_str()); +} + +/** + * @tc.number: AaFwk_AbilityContext_GetCallingAbility_0200 + * @tc.name: GetCallingAbility + * @tc.desc: Test getcallingability exception status. + */ +HWTEST_F(AbilityContextTest, AaFwk_AbilityContext_GetCallingAbility_0200, Function | MediumTest | Level3) +{ + EXPECT_NE(nullptr, context_->GetCallingAbility()); +} + +/** + * @tc.number: AaFwk_AbilityContext_ConnectAbility_0100 + * @tc.name: ConnectAbility + * @tc.desc: Test the attachbasecontext call to verify that the return value of connectability is true. + */ +HWTEST_F(AbilityContextTest, AaFwk_AbilityContext_ConnectAbility_0100, Function | MediumTest | Level1) +{ + std::shared_ptr deal = std::make_shared(); + std::shared_ptr abilityInfo = std::make_shared(); + + abilityInfo->type = AppExecFwk::AbilityType::SERVICE; + deal->SetAbilityInfo(abilityInfo); + context_->AttachBaseContext(deal); + + Want want; + bool ret = context_->ConnectAbility(want, nullptr); + EXPECT_TRUE(ret); +} + +/** + * @tc.number: AaFwk_AbilityContext_ConnectAbility_0200 + * @tc.name: ConnectAbility + * @tc.desc: Test the attachbasecontext call to verify that the return value of connectability is false. + */ +HWTEST_F(AbilityContextTest, AaFwk_AbilityContext_ConnectAbility_0200, Function | MediumTest | Level3) +{ + Want want; + bool ret = context_->ConnectAbility(want, nullptr); + EXPECT_FALSE(ret); +} + +/** + * @tc.number: AaFwk_AbilityContext_DisconnectAbility_0100 + * @tc.name: DisconnectAbility + * @tc.desc: Test whether the disconnectability is called normally. + */ +HWTEST_F(AbilityContextTest, AaFwk_AbilityContext_DisconnectAbility_0100, Function | MediumTest | Level1) +{ + std::shared_ptr deal = std::make_shared(); + std::shared_ptr abilityInfo = std::make_shared(); + + abilityInfo->type = AppExecFwk::AbilityType::SERVICE; + deal->SetAbilityInfo(abilityInfo); + context_->AttachBaseContext(deal); + context_->DisconnectAbility(nullptr); +} + +/** + * @tc.number: AaFwk_AbilityContext_StopAbility_0100 + * @tc.name: StopAbility + * @tc.desc: Test the attachbasecontext call to verify that the return value of stopability is true. + */ +HWTEST_F(AbilityContextTest, AaFwk_AbilityContext_StopAbility_0100, Function | MediumTest | Level1) +{ + Want want; + std::shared_ptr deal = std::make_shared(); + std::shared_ptr abilityInfo = std::make_shared(); + + abilityInfo->type = AppExecFwk::AbilityType::SERVICE; + deal->SetAbilityInfo(abilityInfo); + context_->AttachBaseContext(deal); + bool ret = context_->StopAbility(want); + EXPECT_TRUE(ret); +} + +/** + * @tc.number: AaFwk_AbilityContext_StopAbility_0200 + * @tc.name: StopAbility + * @tc.desc: Test the attachbasecontext call to verify that the return value of stopability is false. + */ +HWTEST_F(AbilityContextTest, AaFwk_AbilityContext_StopAbility_0200, Function | MediumTest | Level3) +{ + Want want; + bool ret = context_->StopAbility(want); + EXPECT_FALSE(ret); +} + +/** + * @tc.number: AaFwk_AbilityContext_TerminateAbility_0200 + * @tc.name: TerminateAbility + * @tc.desc: Test whether terminateability is called normally. + */ +HWTEST_F(AbilityContextTest, AaFwk_AbilityContext_TerminateAbility_0200, Function | MediumTest | Level1) +{ + int code = 1992; + context_->TerminateAbility(code); +} + +/** + * @tc.number: AaFwk_Ability_GetHapModuleInfo_0100 + * @tc.name: GetHapModuleInfo + * @tc.desc: Test the attachbasecontext call to verify that the return value of gethapmoduleinfo is correct. + */ +HWTEST_F(AbilityContextTest, AaFwk_Ability_GetHapModuleInfo_0100, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_Ability_GetHapModuleInfo_0100 start"; + + std::shared_ptr contextDeal = std::make_shared(); + std::shared_ptr abilityInfo = std::make_shared(); + std::string name = "Captain"; + abilityInfo->name = name; + contextDeal->SetAbilityInfo(abilityInfo); + context_->AttachBaseContext(contextDeal); + Want want; + std::shared_ptr info = context_->GetHapModuleInfo(); + EXPECT_STREQ(info->name.c_str(), name.c_str()); + GTEST_LOG_(INFO) << "AaFwk_Ability_GetHapModuleInfo_0100 end"; +} +} // namespace AppExecFwk +} // namespace OHOS diff --git a/tools/frameworks/kits/ability/native/test/unittest/ability_impl_active_test.cpp b/tools/frameworks/kits/ability/native/test/unittest/ability_impl_active_test.cpp new file mode 100644 index 00000000000..3c5ccf1917a --- /dev/null +++ b/tools/frameworks/kits/ability/native/test/unittest/ability_impl_active_test.cpp @@ -0,0 +1,354 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include "ability.h" +#include "ability_impl.h" +#include "ability_state.h" +#include "app_log_wrapper.h" +#include "context_deal.h" +#include "foundation/distributedschedule/dmsfwk/services/dtbschedmgr/include/uri.h" +#include "mock_ability_token.h" +#include "ohos_application.h" +#include "page_ability_impl.h" + +namespace OHOS { +namespace AppExecFwk { +using namespace testing::ext; +using namespace OHOS; +using namespace OHOS::AppExecFwk; + +class AbilityImplActiveTest : public testing::Test { +public: + AbilityImplActiveTest() + {} + ~AbilityImplActiveTest() + {} + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +class MockAbilityimpl : public AbilityImpl { +public: + MockAbilityimpl(){}; + virtual ~MockAbilityimpl(){}; + + void Inactive() + { + AbilityImpl::Inactive(); + } + void Active() + { + AbilityImpl::Active(); + } +}; + +class MockAbilityClass : public Ability { +public: + MockAbilityClass() : topFocus_(false), topFocusChange_(false), windowFocus_(false), windowFocusChange_(false){}; + virtual ~MockAbilityClass(){}; + + virtual void OnWindowFocusChanged(bool hasFocus) + { + windowFocus_ = hasFocus; + windowFocusChange_ = true; + }; + virtual void OnTopActiveAbilityChanged(bool topActive) + { + topFocus_ = topActive; + topFocusChange_ = true; + }; + bool GetWindowFocusStatus() + { + return windowFocus_; + }; + bool GetTopFocusStatus() + { + return topFocus_; + }; + bool GetWindowFocusChangeStatus() + { + return windowFocusChange_; + }; + bool GetTopFocusChangeStatus() + { + return topFocusChange_; + }; + virtual void OnActive(){}; + virtual void OnInactive(){}; + +private: + bool topFocus_; + bool topFocusChange_; + bool windowFocus_; + bool windowFocusChange_; +}; + +void AbilityImplActiveTest::SetUpTestCase(void) +{} + +void AbilityImplActiveTest::TearDownTestCase(void) +{} + +void AbilityImplActiveTest::SetUp(void) +{} + +void AbilityImplActiveTest::TearDown(void) +{} + +/* + * Feature: AbilityImpl + * Function: Active + * SubFunction: NA + * FunctionPoints: Active + * EnvConditions: NA + * CaseDescription: Validate when normally entering a string + */ +HWTEST_F(AbilityImplActiveTest, AaFwk_AbilityImpl_Active_001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_Active_001 start"; + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_Active_001 pretest"; + std::shared_ptr abilityImpl = std::make_shared(); + std::shared_ptr abilityInfo = std::make_shared(); + sptr token(new (std::nothrow) MockAbilityToken()); + std::shared_ptr application = std::make_shared(); + std::shared_ptr record = std::make_shared(abilityInfo, token); + std::shared_ptr mockAbility = std::make_shared(); + std::shared_ptr ability = std::static_pointer_cast(mockAbility); + std::shared_ptr handler = std::make_shared(nullptr, nullptr); + std::shared_ptr contextDeal = std::make_shared(); + + abilityInfo->type = AbilityType::PAGE; + contextDeal->SetAbilityInfo(abilityInfo); + mockAbility->AttachBaseContext(contextDeal); + abilityImpl->Init(application, record, ability, handler, token, contextDeal); + abilityImpl->Inactive(); + + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_Active_001 test proc"; + abilityImpl->Active(); + + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_Active_001 test result check"; + EXPECT_TRUE(mockAbility->GetWindowFocusChangeStatus()); + EXPECT_TRUE(mockAbility->GetWindowFocusStatus()); + EXPECT_TRUE(mockAbility->GetTopFocusChangeStatus()); + EXPECT_TRUE(mockAbility->GetTopFocusStatus()); + + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_Active_001 end"; +} + +/* + * Feature: AbilityImpl + * Function: Active + * SubFunction: NA + * FunctionPoints: Active + * EnvConditions: NA + * CaseDescription: Validate when normally entering a string + */ +HWTEST_F(AbilityImplActiveTest, AaFwk_AbilityImpl_Active_002, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_Active_002 start"; + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_Active_002 pretest"; + std::shared_ptr abilityImpl = std::make_shared(); + std::shared_ptr abilityInfo = std::make_shared(); + sptr token(new (std::nothrow) MockAbilityToken()); + std::shared_ptr application = std::make_shared(); + std::shared_ptr record = std::make_shared(abilityInfo, token); + std::shared_ptr mockAbility = std::make_shared(); + std::shared_ptr ability = std::static_pointer_cast(mockAbility); + std::shared_ptr handler = std::make_shared(nullptr, nullptr); + std::shared_ptr contextDeal = std::make_shared(); + + abilityInfo->type = AbilityType::SERVICE; + contextDeal->SetAbilityInfo(abilityInfo); + mockAbility->AttachBaseContext(contextDeal); + abilityImpl->Init(application, record, ability, handler, token, contextDeal); + abilityImpl->Inactive(); + + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_Active_002 test proc"; + abilityImpl->Active(); + + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_Active_002 test result check"; + EXPECT_FALSE(mockAbility->GetWindowFocusChangeStatus()); + EXPECT_FALSE(mockAbility->GetWindowFocusStatus()); + EXPECT_FALSE(mockAbility->GetTopFocusChangeStatus()); + EXPECT_FALSE(mockAbility->GetTopFocusStatus()); + + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_Active_002 end"; +} + +/* + * Feature: AbilityImpl + * Function: Active + * SubFunction: NA + * FunctionPoints: Active + * EnvConditions: NA + * CaseDescription: Validate when normally entering a string + */ +HWTEST_F(AbilityImplActiveTest, AaFwk_AbilityImpl_Active_003, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_Active_003 start"; + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_Active_003 pretest"; + std::shared_ptr abilityImpl = std::make_shared(); + std::shared_ptr abilityInfo = std::make_shared(); + sptr token(new (std::nothrow) MockAbilityToken()); + std::shared_ptr application = std::make_shared(); + std::shared_ptr record = std::make_shared(abilityInfo, token); + std::shared_ptr mockAbility = std::make_shared(); + std::shared_ptr ability = std::static_pointer_cast(mockAbility); + std::shared_ptr handler = std::make_shared(nullptr, nullptr); + std::shared_ptr contextDeal = std::make_shared(); + + abilityInfo->type = AbilityType::PAGE; + contextDeal->SetAbilityInfo(abilityInfo); + mockAbility->AttachBaseContext(contextDeal); + abilityImpl->Init(application, record, ability, handler, token, contextDeal); + + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_Active_003 test proc"; + abilityImpl->Active(); + + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_Active_003 test result check"; + EXPECT_FALSE(mockAbility->GetWindowFocusChangeStatus()); + EXPECT_FALSE(mockAbility->GetWindowFocusStatus()); + EXPECT_FALSE(mockAbility->GetTopFocusChangeStatus()); + EXPECT_FALSE(mockAbility->GetTopFocusStatus()); + + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_Active_003 end"; +} + +/* + * Feature: AbilityImpl + * Function: Active + * SubFunction: NA + * FunctionPoints: Active + * EnvConditions: NA + * CaseDescription: Validate when normally entering a string + */ +HWTEST_F(AbilityImplActiveTest, AaFwk_AbilityImpl_InActive_001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_InActive_001 start"; + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_InActive_001 pretest"; + std::shared_ptr abilityImpl = std::make_shared(); + std::shared_ptr abilityInfo = std::make_shared(); + sptr token(new (std::nothrow) MockAbilityToken()); + std::shared_ptr application = std::make_shared(); + std::shared_ptr record = std::make_shared(abilityInfo, token); + std::shared_ptr mockAbility = std::make_shared(); + std::shared_ptr ability = std::static_pointer_cast(mockAbility); + std::shared_ptr handler = std::make_shared(nullptr, nullptr); + std::shared_ptr contextDeal = std::make_shared(); + + abilityInfo->type = AbilityType::PAGE; + contextDeal->SetAbilityInfo(abilityInfo); + mockAbility->AttachBaseContext(contextDeal); + abilityImpl->Init(application, record, ability, handler, token, contextDeal); + abilityImpl->Active(); + + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_InActive_001 test proc"; + abilityImpl->Inactive(); + + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_InActive_001 test result check"; + EXPECT_TRUE(mockAbility->GetWindowFocusChangeStatus()); + EXPECT_FALSE(mockAbility->GetWindowFocusStatus()); + EXPECT_TRUE(mockAbility->GetTopFocusChangeStatus()); + EXPECT_FALSE(mockAbility->GetTopFocusStatus()); + + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_InActive_001 end"; +} + +/* + * Feature: AbilityImpl + * Function: Active + * SubFunction: NA + * FunctionPoints: Active + * EnvConditions: NA + * CaseDescription: Validate when normally entering a string + */ +HWTEST_F(AbilityImplActiveTest, AaFwk_AbilityImpl_InActive_002, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_InActive_002 start"; + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_InActive_002 pretest"; + std::shared_ptr abilityImpl = std::make_shared(); + std::shared_ptr abilityInfo = std::make_shared(); + sptr token(new (std::nothrow) MockAbilityToken()); + std::shared_ptr application = std::make_shared(); + std::shared_ptr record = std::make_shared(abilityInfo, token); + std::shared_ptr mockAbility = std::make_shared(); + std::shared_ptr ability = std::static_pointer_cast(mockAbility); + std::shared_ptr handler = std::make_shared(nullptr, nullptr); + std::shared_ptr contextDeal = std::make_shared(); + + abilityInfo->type = AbilityType::DATA; + contextDeal->SetAbilityInfo(abilityInfo); + mockAbility->AttachBaseContext(contextDeal); + abilityImpl->Init(application, record, ability, handler, token, contextDeal); + abilityImpl->Active(); + + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_InActive_002 test proc"; + abilityImpl->Inactive(); + + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_InActive_002 test result check"; + EXPECT_FALSE(mockAbility->GetWindowFocusChangeStatus()); + EXPECT_FALSE(mockAbility->GetWindowFocusStatus()); + EXPECT_FALSE(mockAbility->GetTopFocusChangeStatus()); + EXPECT_FALSE(mockAbility->GetTopFocusStatus()); + + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_InActive_002 end"; +} + +/* + * Feature: AbilityImpl + * Function: Active + * SubFunction: NA + * FunctionPoints: Active + * EnvConditions: NA + * CaseDescription: Validate when normally entering a string + */ +HWTEST_F(AbilityImplActiveTest, AaFwk_AbilityImpl_InActive_003, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_InActive_003 start"; + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_InActive_003 pretest"; + std::shared_ptr abilityImpl = std::make_shared(); + std::shared_ptr abilityInfo = std::make_shared(); + sptr token(new (std::nothrow) MockAbilityToken()); + std::shared_ptr application = std::make_shared(); + std::shared_ptr record = std::make_shared(abilityInfo, token); + std::shared_ptr mockAbility = std::make_shared(); + std::shared_ptr ability = std::static_pointer_cast(mockAbility); + std::shared_ptr handler = std::make_shared(nullptr, nullptr); + std::shared_ptr contextDeal = std::make_shared(); + + abilityInfo->type = AbilityType::PAGE; + contextDeal->SetAbilityInfo(abilityInfo); + mockAbility->AttachBaseContext(contextDeal); + abilityImpl->Init(application, record, ability, handler, token, contextDeal); + + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_InActive_003 test proc"; + abilityImpl->Inactive(); + + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_InActive_003 test result check"; + EXPECT_FALSE(mockAbility->GetWindowFocusChangeStatus()); + EXPECT_FALSE(mockAbility->GetWindowFocusStatus()); + EXPECT_FALSE(mockAbility->GetTopFocusChangeStatus()); + EXPECT_FALSE(mockAbility->GetTopFocusStatus()); + + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_InActive_003 end"; +} + +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/test/unittest/ability_impl_test.cpp b/tools/frameworks/kits/ability/native/test/unittest/ability_impl_test.cpp new file mode 100644 index 00000000000..201c1137c36 --- /dev/null +++ b/tools/frameworks/kits/ability/native/test/unittest/ability_impl_test.cpp @@ -0,0 +1,1344 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "ability_impl.h" +#include "ability.h" +#include "ability_state.h" +#include "app_log_wrapper.h" +#include "context_deal.h" +#include "foundation/distributedschedule/dmsfwk/services/dtbschedmgr/include/uri.h" +#include "mock_ability_token.h" +#include "mock_page_ability.h" +#include "mock_ability_impl.h" +#include "mock_ability_lifecycle_callbacks.h" +#include "ohos_application.h" +#include "page_ability_impl.h" + +#include "abs_shared_result_set.h" +#include "data_ability_predicates.h" +#include "values_bucket.h" + +namespace OHOS { +namespace AppExecFwk { +using namespace testing::ext; +using namespace OHOS; +using namespace OHOS::AppExecFwk; + +class AbilityImplTest : public testing::Test { +public: + AbilityImplTest() : AbilityImpl_(nullptr), MocKPageAbility_(nullptr) + {} + ~AbilityImplTest() + {} + std::shared_ptr AbilityImpl_; + std::shared_ptr MocKPageAbility_; + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void AbilityImplTest::SetUpTestCase(void) +{} + +void AbilityImplTest::TearDownTestCase(void) +{} + +void AbilityImplTest::SetUp(void) +{ + AbilityImpl_ = std::make_shared(); + MocKPageAbility_ = std::make_shared(); +} + +void AbilityImplTest::TearDown(void) +{} + +/* + * Feature: AbilityImpl + * Function: Init + * SubFunction: NA + * FunctionPoints: Init + * EnvConditions: NA + * CaseDescription: Validate when normally entering a string + */ +HWTEST_F(AbilityImplTest, AaFwk_AbilityImpl_Init_001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_Init_001 start"; + + std::shared_ptr mockAbilityimpl = std::make_shared(); + std::shared_ptr application = std::make_shared(); + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "pageAbility"; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + EXPECT_NE(token, nullptr); + if (token != nullptr) { + std::shared_ptr record = std::make_shared(abilityInfo, token); + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + EXPECT_NE(abilityThread, nullptr); + if (abilityThread != nullptr) { + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + std::shared_ptr ability = std::make_shared(); + std::shared_ptr contextDeal = std::make_shared(); + mockAbilityimpl->Init(application, record, ability, handler, token, contextDeal); + EXPECT_EQ(mockAbilityimpl->GetToken(), record->GetToken()); + EXPECT_EQ(mockAbilityimpl->GetAbility(), ability); + EXPECT_EQ(mockAbilityimpl->GetCurrentState(), AAFwk::ABILITY_STATE_INITIAL); + } + } + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_Init_001 end"; +} + +/* + * Feature: AbilityImpl + * Function: Start + * SubFunction: NA + * FunctionPoints: Start + * EnvConditions: NA + * CaseDescription: Test the normal behavior of the AbilityImpl::Start + */ +HWTEST_F(AbilityImplTest, AaFwk_AbilityImpl_Start_001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_Start_001 start"; + + std::shared_ptr mockAbilityimpl = std::make_shared(); + std::shared_ptr application = std::make_shared(); + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "pageAbility"; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + EXPECT_NE(token, nullptr); + if (token != nullptr) { + std::shared_ptr record = std::make_shared(abilityInfo, token); + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + EXPECT_NE(abilityThread, nullptr); + if (abilityThread != nullptr) { + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + std::shared_ptr ability; + MockPageAbility *pMocKPageAbility = new (std::nothrow) MockPageAbility(); + EXPECT_NE(pMocKPageAbility, nullptr); + if (pMocKPageAbility != nullptr) { + ability.reset(pMocKPageAbility); + std::shared_ptr contextDeal = std::make_shared(); + contextDeal->SetAbilityInfo(abilityInfo); + ability->AttachBaseContext(contextDeal); + mockAbilityimpl->Init(application, record, ability, handler, token, contextDeal); + Want want; + mockAbilityimpl->ImplStart(want); + EXPECT_EQ(MockPageAbility::Event::ON_START, pMocKPageAbility->state_); + EXPECT_EQ(AAFwk::ABILITY_STATE_INACTIVE, mockAbilityimpl->GetCurrentState()); + } + } + } + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_Start_001 end"; +} + +/* + * Feature: AbilityImpl + * Function: Start + * SubFunction: NA + * FunctionPoints: Start + * EnvConditions: NA + * CaseDescription: Test the abnormal behavior of the AbilityImpl::Start + */ +HWTEST_F(AbilityImplTest, AaFwk_AbilityImpl_Start_002, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_Start_002 start"; + + std::shared_ptr mockAbilityimpl = std::make_shared(); + std::shared_ptr application = std::make_shared(); + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "pageAbility"; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + EXPECT_NE(token, nullptr); + if (token != nullptr) { + std::shared_ptr record = std::make_shared(abilityInfo, token); + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + EXPECT_NE(abilityThread, nullptr); + if (abilityThread != nullptr) { + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + std::shared_ptr ability = nullptr; + std::shared_ptr contextDeal = std::make_shared(); + mockAbilityimpl->Init(application, record, ability, handler, token, contextDeal); + + Want want; + mockAbilityimpl->ImplStart(want); + + mockAbilityimpl->SetlifecycleState(AAFwk::ABILITY_STATE_SUSPENDED); + EXPECT_EQ(AAFwk::ABILITY_STATE_SUSPENDED, mockAbilityimpl->GetCurrentState()); + } + } + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_Start_002 end"; +} + +/* + * Feature: AbilityImpl + * Function: Stop + * SubFunction: NA + * FunctionPoints: Stop + * EnvConditions: NA + * CaseDescription: Test the normal behavior of the AbilityImpl::Stop + */ +HWTEST_F(AbilityImplTest, AaFwk_AbilityImpl_Stop_001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_Stop_001 start"; + std::shared_ptr mockAbilityimpl = std::make_shared(); + std::shared_ptr application = std::make_shared(); + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "pageAbility"; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + EXPECT_NE(token, nullptr); + if (token != nullptr) { + std::shared_ptr record = std::make_shared(abilityInfo, token); + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + EXPECT_NE(abilityThread, nullptr); + if (abilityThread != nullptr) { + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + std::shared_ptr ability; + MockPageAbility *pMocKPageAbility = new (std::nothrow) MockPageAbility(); + EXPECT_NE(pMocKPageAbility, nullptr); + if (pMocKPageAbility != nullptr) { + ability.reset(pMocKPageAbility); + std::shared_ptr contextDeal = std::make_shared(); + mockAbilityimpl->Init(application, record, ability, handler, token, contextDeal); + + mockAbilityimpl->ImplStop(); + + EXPECT_EQ(MockPageAbility::Event::ON_STOP, pMocKPageAbility->state_); + EXPECT_EQ(AAFwk::ABILITY_STATE_INITIAL, mockAbilityimpl->GetCurrentState()); + } + } + } + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_Stop_001 end"; +} + +/* + * Feature: AbilityImpl + * Function: Stop + * SubFunction: NA + * FunctionPoints: Stop + * EnvConditions: NA + * CaseDescription: Test the abnormal behavior of the AbilityImpl::Stop + */ +HWTEST_F(AbilityImplTest, AaFwk_AbilityImpl_Stop_002, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_Stop_002 start"; + std::shared_ptr mockAbilityimpl = std::make_shared(); + std::shared_ptr application = std::make_shared(); + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "pageAbility"; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + EXPECT_NE(token, nullptr); + if (token != nullptr) { + std::shared_ptr record = std::make_shared(abilityInfo, token); + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + EXPECT_NE(abilityThread, nullptr); + if (abilityThread != nullptr) { + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + std::shared_ptr ability = nullptr; + std::shared_ptr contextDeal = std::make_shared(); + mockAbilityimpl->Init(application, record, ability, handler, token, contextDeal); + + mockAbilityimpl->ImplStop(); + mockAbilityimpl->SetlifecycleState(AAFwk::ABILITY_STATE_SUSPENDED); + + EXPECT_EQ(AAFwk::ABILITY_STATE_SUSPENDED, mockAbilityimpl->GetCurrentState()); + } + } + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_Stop_002 end"; +} + +/* + * Feature: AbilityImpl + * Function: Active + * SubFunction: NA + * FunctionPoints: Active + * EnvConditions: NA + * CaseDescription: Test the normal behavior of the AbilityImpl::Active + */ +HWTEST_F(AbilityImplTest, AaFwk_AbilityImpl_Active_001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_Active_001 start"; + std::shared_ptr mockAbilityimpl = std::make_shared(); + std::shared_ptr application = std::make_shared(); + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "pageAbility"; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + EXPECT_NE(token, nullptr); + if (token != nullptr) { + std::shared_ptr record = std::make_shared(abilityInfo, token); + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + EXPECT_NE(abilityThread, nullptr); + if (abilityThread != nullptr) { + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + std::shared_ptr ability; + MockPageAbility *pMocKPageAbility = new (std::nothrow) MockPageAbility(); + EXPECT_NE(pMocKPageAbility, nullptr); + if (pMocKPageAbility != nullptr) { + ability.reset(pMocKPageAbility); + std::shared_ptr contextDeal = std::make_shared(); + mockAbilityimpl->Init(application, record, ability, handler, token, contextDeal); + + AbilityLifecycleExecutor AbilityLifecycleExecutor_; + mockAbilityimpl->ImplActive(); + + EXPECT_EQ(MockPageAbility::Event::ON_ACTIVE, pMocKPageAbility->state_); + EXPECT_EQ(AAFwk::ABILITY_STATE_ACTIVE, mockAbilityimpl->GetCurrentState()); + } + } + } + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_Active_001 end"; +} + +/* + * Feature: AbilityImpl + * Function: Active + * SubFunction: NA + * FunctionPoints: Active + * EnvConditions: NA + * CaseDescription: Test the abnormal behavior of the AbilityImpl::Active + */ +HWTEST_F(AbilityImplTest, AaFwk_AbilityImpl_Active_002, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_Active_002 start"; + std::shared_ptr mockAbilityimpl = std::make_shared(); + std::shared_ptr application = std::make_shared(); + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "pageAbility"; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + EXPECT_NE(token, nullptr); + if (token != nullptr) { + std::shared_ptr record = std::make_shared(abilityInfo, token); + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + EXPECT_NE(abilityThread, nullptr); + if (abilityThread != nullptr) { + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + std::shared_ptr ability = nullptr; + std::shared_ptr contextDeal = std::make_shared(); + mockAbilityimpl->Init(application, record, ability, handler, token, contextDeal); + + AbilityLifecycleExecutor AbilityLifecycleExecutor_; + mockAbilityimpl->ImplActive(); + mockAbilityimpl->SetlifecycleState(AAFwk::ABILITY_STATE_SUSPENDED); + + EXPECT_EQ(AAFwk::ABILITY_STATE_SUSPENDED, mockAbilityimpl->GetCurrentState()); + } + } + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_Active_002 end"; +} + +/* + * Feature: AbilityImpl + * Function: Inactive + * SubFunction: NA + * FunctionPoints: Inactive + * EnvConditions: NA + * CaseDescription: Test the normal behavior of the AbilityImpl::Inactive + */ +HWTEST_F(AbilityImplTest, AaFwk_AbilityImpl_Inactive_001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_Inactive_001 start"; + std::shared_ptr mockAbilityimpl = std::make_shared(); + std::shared_ptr application = std::make_shared(); + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "pageAbility"; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + EXPECT_NE(token, nullptr); + if (token != nullptr) { + std::shared_ptr record = std::make_shared(abilityInfo, token); + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + EXPECT_NE(abilityThread, nullptr); + if (abilityThread != nullptr) { + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + std::shared_ptr ability; + MockPageAbility *pMocKPageAbility = new (std::nothrow) MockPageAbility(); + EXPECT_NE(pMocKPageAbility, nullptr); + if (pMocKPageAbility != nullptr) { + ability.reset(pMocKPageAbility); + std::shared_ptr contextDeal = std::make_shared(); + mockAbilityimpl->Init(application, record, ability, handler, token, contextDeal); + + AbilityLifecycleExecutor AbilityLifecycleExecutor_; + mockAbilityimpl->ImplInactive(); + + EXPECT_EQ(MockPageAbility::Event::ON_INACTIVE, pMocKPageAbility->state_); + EXPECT_EQ(AAFwk::ABILITY_STATE_INACTIVE, mockAbilityimpl->GetCurrentState()); + } + } + } + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_Inactive_001 end"; +} + +/* + * Feature: AbilityImpl + * Function: Inactive + * SubFunction: NA + * FunctionPoints: Inactive + * EnvConditions: NA + * CaseDescription: Test the abnormal behavior of the AbilityImpl::Inactive + */ +HWTEST_F(AbilityImplTest, AaFwk_AbilityImpl_Inactive_002, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_Inactive_002 start"; + std::shared_ptr mockAbilityimpl = std::make_shared(); + std::shared_ptr application = std::make_shared(); + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "pageAbility"; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + EXPECT_NE(token, nullptr); + if (token != nullptr) { + std::shared_ptr record = std::make_shared(abilityInfo, token); + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + EXPECT_NE(abilityThread, nullptr); + if (abilityThread != nullptr) { + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + std::shared_ptr ability = nullptr; + std::shared_ptr contextDeal = std::make_shared(); + mockAbilityimpl->Init(application, record, ability, handler, token, contextDeal); + + AbilityLifecycleExecutor AbilityLifecycleExecutor_; + mockAbilityimpl->ImplInactive(); + mockAbilityimpl->SetlifecycleState(AAFwk::ABILITY_STATE_SUSPENDED); + + EXPECT_EQ(AAFwk::ABILITY_STATE_SUSPENDED, mockAbilityimpl->GetCurrentState()); + } + } + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_Inactive_002 end"; +} + +/* + * Feature: AbilityImpl + * Function: Foreground + * SubFunction: NA + * FunctionPoints: Foreground + * EnvConditions: NA + * CaseDescription: Test the normal behavior of the AbilityImpl::Foreground + */ +HWTEST_F(AbilityImplTest, AaFwk_AbilityImpl_Foreground_001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_Foreground_001 start"; + std::shared_ptr mockAbilityimpl = std::make_shared(); + std::shared_ptr application = std::make_shared(); + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "pageAbility"; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + EXPECT_NE(token, nullptr); + if (token != nullptr) { + std::shared_ptr record = std::make_shared(abilityInfo, token); + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + EXPECT_NE(abilityThread, nullptr); + if (abilityThread != nullptr) { + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + std::shared_ptr ability = nullptr; + MockPageAbility *pMocKPageAbility = new (std::nothrow) MockPageAbility(); + EXPECT_NE(pMocKPageAbility, nullptr); + if (pMocKPageAbility != nullptr) { + ability.reset(pMocKPageAbility); + std::shared_ptr contextDeal = std::make_shared(); + mockAbilityimpl->Init(application, record, ability, handler, token, contextDeal); + + Want want; + AbilityLifecycleExecutor AbilityLifecycleExecutor_; + mockAbilityimpl->ImplForeground(want); + + EXPECT_EQ(MockPageAbility::Event::ON_FOREGROUND, pMocKPageAbility->state_); + EXPECT_EQ(AAFwk::ABILITY_STATE_INACTIVE, mockAbilityimpl->GetCurrentState()); + } + } + } + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_Foreground_001 end"; +} + +/* + * Feature: AbilityImpl + * Function: Foreground + * SubFunction: NA + * FunctionPoints: Foreground + * EnvConditions: NA + * CaseDescription: Test the abnormal behavior of the AbilityImpl::Foreground + */ +HWTEST_F(AbilityImplTest, AaFwk_AbilityImpl_Foreground_002, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_Foreground_002 start"; + std::shared_ptr mockAbilityimpl = std::make_shared(); + std::shared_ptr application = std::make_shared(); + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "pageAbility"; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + EXPECT_NE(token, nullptr); + if (token != nullptr) { + std::shared_ptr record = std::make_shared(abilityInfo, token); + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + EXPECT_NE(abilityThread, nullptr); + if (abilityThread != nullptr) { + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + std::shared_ptr ability = nullptr; + std::shared_ptr contextDeal = std::make_shared(); + mockAbilityimpl->Init(application, record, ability, handler, token, contextDeal); + + Want want; + AbilityLifecycleExecutor AbilityLifecycleExecutor_; + mockAbilityimpl->ImplForeground(want); + mockAbilityimpl->SetlifecycleState(AAFwk::ABILITY_STATE_SUSPENDED); + + EXPECT_EQ(AAFwk::ABILITY_STATE_SUSPENDED, mockAbilityimpl->GetCurrentState()); + } + } + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_Foreground_002 end"; +} + +/* + * Feature: AbilityImpl + * Function: Background + * SubFunction: NA + * FunctionPoints: Background + * EnvConditions: NA + * CaseDescription: Test the normal behavior of the AbilityImpl::Background + */ +HWTEST_F(AbilityImplTest, AaFwk_AbilityImpl_Background_001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_Background_001 start"; + std::shared_ptr mockAbilityimpl = std::make_shared(); + std::shared_ptr application = std::make_shared(); + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "pageAbility"; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + EXPECT_NE(token, nullptr); + if (token != nullptr) { + std::shared_ptr record = std::make_shared(abilityInfo, token); + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + EXPECT_NE(abilityThread, nullptr); + if (abilityThread != nullptr) { + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + std::shared_ptr ability; + MockPageAbility *pMocKPageAbility = new (std::nothrow) MockPageAbility(); + EXPECT_NE(pMocKPageAbility, nullptr); + if (pMocKPageAbility != nullptr) { + ability.reset(pMocKPageAbility); + std::shared_ptr contextDeal = std::make_shared(); + mockAbilityimpl->Init(application, record, ability, handler, token, contextDeal); + + AbilityLifecycleExecutor AbilityLifecycleExecutor_; + mockAbilityimpl->ImplBackground(); + + EXPECT_EQ(MockPageAbility::Event::ON_BACKGROUND, pMocKPageAbility->state_); + EXPECT_EQ(AAFwk::ABILITY_STATE_BACKGROUND, mockAbilityimpl->GetCurrentState()); + } + } + } + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_Background_001 end"; +} + +/* + * Feature: AbilityImpl + * Function: Background + * SubFunction: NA + * FunctionPoints: Background + * EnvConditions: NA + * CaseDescription: Test the abnormal behavior of the AbilityImpl::Background + */ +HWTEST_F(AbilityImplTest, AaFwk_AbilityImpl_Background_002, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_Background_002 start"; + std::shared_ptr mockAbilityimpl = std::make_shared(); + std::shared_ptr application = std::make_shared(); + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "pageAbility"; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + EXPECT_NE(token, nullptr); + if (token != nullptr) { + std::shared_ptr record = std::make_shared(abilityInfo, token); + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + EXPECT_NE(abilityThread, nullptr); + if (abilityThread != nullptr) { + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + std::shared_ptr ability = nullptr; + std::shared_ptr contextDeal = std::make_shared(); + mockAbilityimpl->Init(application, record, ability, handler, token, contextDeal); + + mockAbilityimpl->ImplBackground(); + mockAbilityimpl->SetlifecycleState(AAFwk::ABILITY_STATE_SUSPENDED); + + EXPECT_EQ(AAFwk::ABILITY_STATE_SUSPENDED, mockAbilityimpl->GetCurrentState()); + } + } + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_Background_002 end"; +} + +/* + * Feature: AbilityImpl + * Function: DisoatcgSaveAbilityState + * SubFunction: NA + * FunctionPoints: DisoatcgSaveAbilityState + * EnvConditions: NA + * CaseDescription: Test the normal behavior of the AbilityImpl::DisoatcgSaveAbilityState + */ +HWTEST_F(AbilityImplTest, AaFwk_AbilityImpl_DispatchSaveAbilityState_001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_DispatchSaveAbilityState_001 start"; + std::shared_ptr mockAbilityimpl = std::make_shared(); + std::shared_ptr application = std::make_shared(); + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "pageAbility"; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + EXPECT_NE(token, nullptr); + if (token != nullptr) { + std::shared_ptr record = std::make_shared(abilityInfo, token); + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + EXPECT_NE(abilityThread, nullptr); + if (abilityThread != nullptr) { + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + std::shared_ptr ability = std::make_shared(); + std::shared_ptr contextDeal = std::make_shared(); + mockAbilityimpl->Init(application, record, ability, handler, token, contextDeal); + + PacMap outState; + AbilityLifecycleExecutor AbilityLifecycleExecutor_; + mockAbilityimpl->DispatchSaveAbilityState(outState); + } + } + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_DispatchSaveAbilityState_001 end"; +} + +/* + * Feature: AbilityImpl + * Function: DisoatcgSaveAbilityState + * SubFunction: NA + * FunctionPoints: DisoatcgSaveAbilityState + * EnvConditions: NA + * CaseDescription: Test the normal behavior of the AbilityImpl::DisoatcgSaveAbilityState + */ +HWTEST_F(AbilityImplTest, AaFwk_AbilityImpl_DispatchSaveAbilityState_002, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_DispatchSaveAbilityState_002 start"; + std::shared_ptr mockAbilityimpl = std::make_shared(); + std::shared_ptr application = std::make_shared(); + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "pageAbility"; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + EXPECT_NE(token, nullptr); + if (token != nullptr) { + std::shared_ptr record = std::make_shared(abilityInfo, token); + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + EXPECT_NE(abilityThread, nullptr); + if (abilityThread != nullptr) { + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + std::shared_ptr ability = nullptr; + std::shared_ptr contextDeal = std::make_shared(); + mockAbilityimpl->Init(application, record, ability, handler, token, contextDeal); + + PacMap outState; + mockAbilityimpl->DispatchSaveAbilityState(outState); + } + } + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_DispatchSaveAbilityState_002 end"; +} + +/* + * Feature: AbilityImpl + * Function: DispatchRestoreAbilityState + * SubFunction: NA + * FunctionPoints: DispatchRestoreAbilityState + * EnvConditions: NA + * CaseDescription: Test the abnormal behavior of the AbilityImpl::DispatchRestoreAbilityState + */ +HWTEST_F(AbilityImplTest, AaFwk_AbilityImpl_DispatchRestoreAbilityState_001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_DispatchRestoreAbilityState_001 start"; + std::shared_ptr mockAbilityimpl = std::make_shared(); + std::shared_ptr application = std::make_shared(); + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "pageAbility"; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + EXPECT_NE(token, nullptr); + if (token != nullptr) { + std::shared_ptr record = std::make_shared(abilityInfo, token); + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + EXPECT_NE(abilityThread, nullptr); + if (abilityThread != nullptr) { + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + std::shared_ptr ability = std::make_shared(); + std::shared_ptr contextDeal = std::make_shared(); + mockAbilityimpl->Init(application, record, ability, handler, token, contextDeal); + + PacMap inState; + + mockAbilityimpl->DispatchRestoreAbilityState(inState); + } + } + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_DispatchRestoreAbilityState_001 end"; +} + +/* + * Feature: AbilityImpl + * Function: DispatchRestoreAbilityState + * SubFunction: NA + * FunctionPoints: DispatchRestoreAbilityState + * EnvConditions: NA + * CaseDescription: Test the abnormal behavior of the AbilityImpl::DispatchRestoreAbilityState + */ +HWTEST_F(AbilityImplTest, AaFwk_AbilityImpl_DispatchRestoreAbilityState_002, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_DispatchRestoreAbilityState_002 start"; + std::shared_ptr mockAbilityimpl = std::make_shared(); + std::shared_ptr application = std::make_shared(); + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "pageAbility"; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + EXPECT_NE(token, nullptr); + if (token != nullptr) { + std::shared_ptr record = std::make_shared(abilityInfo, token); + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + EXPECT_NE(abilityThread, nullptr); + if (abilityThread != nullptr) { + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + std::shared_ptr ability = nullptr; + std::shared_ptr contextDeal = std::make_shared(); + mockAbilityimpl->Init(application, record, ability, handler, token, contextDeal); + + PacMap inState; + mockAbilityimpl->DispatchRestoreAbilityState(inState); + } + } + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_DispatchRestoreAbilityState_002 end"; +} + +/* + * Feature: AbilityImpl + * Function: ConnectAbility + * SubFunction: NA + * FunctionPoints: ConnectAbility + * EnvConditions: NA + * CaseDescription: Test the normal behavior of the AbilityImpl::ConnectAbility + */ +HWTEST_F(AbilityImplTest, AaFwk_AbilityImpl_ConnectAbility_001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_ConnectAbility_001 start"; + std::shared_ptr mockAbilityimpl = std::make_shared(); + std::shared_ptr application = std::make_shared(); + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "pageAbility"; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + EXPECT_NE(token, nullptr); + if (token != nullptr) { + std::shared_ptr record = std::make_shared(abilityInfo, token); + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + EXPECT_NE(abilityThread, nullptr); + if (abilityThread != nullptr) { + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + std::shared_ptr ability; + MockPageAbility *pMocKPageAbility = new (std::nothrow) MockPageAbility(); + EXPECT_NE(pMocKPageAbility, nullptr); + if (pMocKPageAbility != nullptr) { + ability.reset(pMocKPageAbility); + std::shared_ptr contextDeal = std::make_shared(); + mockAbilityimpl->Init(application, record, ability, handler, token, contextDeal); + + Want want; + + AbilityLifecycleExecutor AbilityLifecycleExecutor_; + mockAbilityimpl->ConnectAbility(want); + + EXPECT_EQ(MockPageAbility::Event::ON_ACTIVE, pMocKPageAbility->state_); + EXPECT_EQ(AAFwk::ABILITY_STATE_ACTIVE, mockAbilityimpl->GetCurrentState()); + EXPECT_EQ(nullptr, mockAbilityimpl->ConnectAbility(want)); + } + } + } + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_ConnectAbility_001 end"; +} + +/* + * Feature: AbilityImpl + * Function: ConnectAbility + * SubFunction: NA + * FunctionPoints: ConnectAbility + * EnvConditions: NA + * CaseDescription: Test the abnormal behavior of the AbilityImpl::ConnectAbility + */ +HWTEST_F(AbilityImplTest, AaFwk_AbilityImpl_ConnectAbility_002, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_ConnectAbility_002 start"; + std::shared_ptr mockAbilityimpl = std::make_shared(); + std::shared_ptr application = std::make_shared(); + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "pageAbility"; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + EXPECT_NE(token, nullptr); + if (token != nullptr) { + std::shared_ptr record = std::make_shared(abilityInfo, token); + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + EXPECT_NE(abilityThread, nullptr); + if (abilityThread != nullptr) { + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + std::shared_ptr ability = nullptr; + std::shared_ptr contextDeal = std::make_shared(); + mockAbilityimpl->Init(application, record, ability, handler, token, contextDeal); + + Want want; + + AbilityLifecycleExecutor AbilityLifecycleExecutor_; + mockAbilityimpl->ConnectAbility(want); + mockAbilityimpl->SetlifecycleState(AAFwk::ABILITY_STATE_SUSPENDED); + + EXPECT_EQ(AAFwk::ABILITY_STATE_SUSPENDED, mockAbilityimpl->GetCurrentState()); + } + } + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_ConnectAbility_002 end"; +} + +/* + * Feature: AbilityImpl + * Function: CommandAbility + * SubFunction: NA + * FunctionPoints: CommandAbility + * EnvConditions: NA + * CaseDescription: Test the normal behavior of the AbilityImpl::CommandAbility + */ +HWTEST_F(AbilityImplTest, AaFwk_AbilityImpl_CommandAbility_001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_CommandAbility_001 start"; + std::shared_ptr mockAbilityimpl = std::make_shared(); + std::shared_ptr application = std::make_shared(); + + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "pageAbility"; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + EXPECT_NE(token, nullptr); + if (token != nullptr) { + std::shared_ptr record = std::make_shared(abilityInfo, token); + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + EXPECT_NE(abilityThread, nullptr); + if (abilityThread != nullptr) { + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + std::shared_ptr ability; + MockPageAbility *pMocKPageAbility = new (std::nothrow) MockPageAbility(); + EXPECT_NE(pMocKPageAbility, nullptr); + if (pMocKPageAbility != nullptr) { + ability.reset(pMocKPageAbility); + std::shared_ptr contextDeal = std::make_shared(); + mockAbilityimpl->Init(application, record, ability, handler, token, contextDeal); + + Want want; + bool restart = true; + int startId = 1; + AbilityLifecycleExecutor AbilityLifecycleExecutor_; + mockAbilityimpl->CommandAbility(want, restart, startId); + + EXPECT_EQ(MockPageAbility::Event::ON_ACTIVE, pMocKPageAbility->state_); + EXPECT_EQ(AAFwk::ABILITY_STATE_ACTIVE, mockAbilityimpl->GetCurrentState()); + } + } + } + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_CommandAbility_001 end"; +} + +/* + * Feature: AbilityImpl + * Function: CommandAbility + * SubFunction: NA + * FunctionPoints: CommandAbility + * EnvConditions: NA + * CaseDescription: Test the abnormal behavior of the AbilityImpl::CommandAbility + */ +HWTEST_F(AbilityImplTest, AaFwk_AbilityImpl_CommandAbility_002, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_CommandAbility_002 start"; + std::shared_ptr mockAbilityimpl = std::make_shared(); + std::shared_ptr application = std::make_shared(); + + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "pageAbility"; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + EXPECT_NE(token, nullptr); + if (token != nullptr) { + std::shared_ptr record = std::make_shared(abilityInfo, token); + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + EXPECT_NE(abilityThread, nullptr); + if (abilityThread != nullptr) { + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + std::shared_ptr ability = nullptr; + std::shared_ptr contextDeal = std::make_shared(); + AbilityImpl_->Init(application, record, ability, handler, token, contextDeal); + + Want want; + + bool restart = true; + int startId = 1; + + AbilityLifecycleExecutor AbilityLifecycleExecutor_; + AbilityImpl_->CommandAbility(want, restart, startId); + mockAbilityimpl->SetlifecycleState(AAFwk::ABILITY_STATE_SUSPENDED); + + EXPECT_EQ(AAFwk::ABILITY_STATE_SUSPENDED, mockAbilityimpl->MockGetCurrentState()); + } + } + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_CommandAbility_002 end"; +} + +/* + * Feature: AbilityImpl + * Function: GetCUrrentState + * SubFunction: NA + * FunctionPoints: GetCUrrentState + * EnvConditions: NA + * CaseDescription: Test the normal behavior of the AbilityImpl::GetCUrrentState + */ +HWTEST_F(AbilityImplTest, AaFwk_AbilityImpl_GetCurrentState_001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_GetCurrentState_001 start"; + + AbilityImpl abilityimpl; + + EXPECT_EQ(AAFwk::ABILITY_STATE_INITIAL, abilityimpl.GetCurrentState()); + + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_GetCurrentState_001 end"; +} + +/* + * Feature: AbilityImpl + * Function: DoKeyDown + * SubFunction: NA + * FunctionPoints: DoKeyDown + * EnvConditions: NA + * CaseDescription: Test the normal behavior of the AbilityImpl::DoKeyDown + */ +HWTEST_F(AbilityImplTest, AaFwk_AbilityImpl_DoKeyDown_001, TestSize.Level1) +{ + + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_DoKeyDown_001 start"; + + int keyCode = 0; + KeyEvent keyEvent; + + EXPECT_EQ(false, AbilityImpl_->DoKeyDown(keyCode, keyEvent)); + + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_DoKeyDown_001 end"; +} + +/* + * Feature: AbilityImpl + * Function: DoKeyUp + * SubFunction: NA + * FunctionPoints: DoKeyUp + * EnvConditions: NA + * CaseDescription: Test the normal behavior of the AbilityImpl::DoKeyUp + */ +HWTEST_F(AbilityImplTest, AaFwk_AbilityImpl_DoKeyUp_001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_DoKeyUp_001 start"; + int keyCode = 0; + KeyEvent keyEvent; + + EXPECT_EQ(false, AbilityImpl_->DoKeyUp(keyCode, keyEvent)); + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_DoKeyUp_001 end"; +} + +/* + * Feature: AbilityImpl + * Function: DoTouchEvvent + * SubFunction: NA + * FunctionPoints: DoTouchEvvent + * EnvConditions: NA + * CaseDescription: Test the normal behavior of the AbilityImpl::DoTouchEvvent + */ +HWTEST_F(AbilityImplTest, AaFwk_AbilityImpl_DoTouchEvent_001, TestSize.Level1) +{ + + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_DoTouchEvent_001 start"; + TouchEvent touchEvent; + + EXPECT_EQ(false, AbilityImpl_->DoTouchEvent(touchEvent)); + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_DoTouchEvent_001 end"; +} + +/* + * Feature: AbilityImpl + * Function: SendResult + * SubFunction: NA + * FunctionPoints: SendResult + * EnvConditions: NA + * CaseDescription: Test the normal behavior of the AbilityImpl::SendResult + */ +HWTEST_F(AbilityImplTest, AaFwk_AbilityImpl_SendResult_001, TestSize.Level1) +{ + + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_SendResult_001 start"; + std::shared_ptr mockAbilityimpl = std::make_shared(); + std::shared_ptr application = std::make_shared(); + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "pageAbility"; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + EXPECT_NE(token, nullptr); + if (token != nullptr) { + std::shared_ptr record = std::make_shared(abilityInfo, token); + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + EXPECT_NE(abilityThread, nullptr); + if (abilityThread != nullptr) { + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + std::shared_ptr ability; + MockPageAbility *pMocKPageAbility = new (std::nothrow) MockPageAbility(); + EXPECT_NE(pMocKPageAbility, nullptr); + if (pMocKPageAbility != nullptr) { + ability.reset(pMocKPageAbility); + + std::shared_ptr contextDeal = std::make_shared(); + mockAbilityimpl->Init(application, record, ability, handler, token, contextDeal); + + int requestCode = 0; + int resultCode = 0; + Want resultData; + + mockAbilityimpl->SendResult(requestCode, resultCode, resultData); + EXPECT_EQ(MockPageAbility::Event::ON_ACTIVE, pMocKPageAbility->state_); + } + } + } + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_SendResult_001 end"; +} + +/* + * Feature: AbilityImpl + * Function: NewWant + * SubFunction: NA + * FunctionPoints: NewWant + * EnvConditions: NA + * CaseDescription: Test the normal behavior of the AbilityImpl::NewWant + */ +HWTEST_F(AbilityImplTest, AaFwk_AbilityImpl_NewWant_001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_NewWant_001 start"; + + std::shared_ptr mockAbilityimpl = std::make_shared(); + std::shared_ptr application = std::make_shared(); + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "pageAbility"; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + EXPECT_NE(token, nullptr); + if (token != nullptr) { + std::shared_ptr record = std::make_shared(abilityInfo, token); + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + EXPECT_NE(abilityThread, nullptr); + if (abilityThread != nullptr) { + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + std::shared_ptr ability; + MockPageAbility *pMocKPageAbility = new (std::nothrow) MockPageAbility(); + EXPECT_NE(pMocKPageAbility, nullptr); + if (pMocKPageAbility != nullptr) { + ability.reset(pMocKPageAbility); + + std::shared_ptr contextDeal = std::make_shared(); + mockAbilityimpl->Init(application, record, ability, handler, token, contextDeal); + + Want want; + mockAbilityimpl->NewWant(want); + EXPECT_EQ(1, pMocKPageAbility->onNewWantCalled_); + } + } + } + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_NewWant_001 end"; +} + +/* + * Feature: AbilityImpl + * Function: GetFileTypes + * SubFunction: NA + * FunctionPoints: GetFileTypes + * EnvConditions: NA + * CaseDescription: Test the normal behavior of the AbilityImpl::GetFileTypes + */ +HWTEST_F(AbilityImplTest, AaFwk_AbilityImpl_GetFileTypes_001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_GetFileTypes_001 start"; + std::shared_ptr mockAbilityimpl = std::make_shared(); + std::shared_ptr application = std::make_shared(); + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "pageAbility"; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + EXPECT_NE(token, nullptr); + if (token != nullptr) { + std::shared_ptr record = std::make_shared(abilityInfo, token); + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + EXPECT_NE(abilityThread, nullptr); + if (abilityThread != nullptr) { + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + std::shared_ptr ability; + MockPageAbility *pMocKPageAbility = new (std::nothrow) MockPageAbility(); + EXPECT_NE(pMocKPageAbility, nullptr); + if (pMocKPageAbility != nullptr) { + ability.reset(pMocKPageAbility); + std::shared_ptr contextDeal = std::make_shared(); + mockAbilityimpl->Init(application, record, ability, handler, token, contextDeal); + + Uri uri("nullptr"); + + std::string mimeTypeFilter("string1"); + + std::vector result = mockAbilityimpl->GetFileTypes(uri, mimeTypeFilter); + int count = result.size(); + EXPECT_EQ(count, 0); + } + } + } + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_GetFileTypes_001 end"; +} + +/* + * Feature: AbilityImpl + * Function: OpenFile + * SubFunction: NA + * FunctionPoints: OpenFile + * EnvConditions: NA + * CaseDescription: Test the normal behavior of the AbilityImpl::OpenFile + */ +HWTEST_F(AbilityImplTest, AaFwk_AbilityImpl_OpenFile_001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_OpenFile_001 start"; + std::shared_ptr mockAbilityimpl = std::make_shared(); + std::shared_ptr application = std::make_shared(); + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "pageAbility"; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + EXPECT_NE(token, nullptr); + if (token != nullptr) { + std::shared_ptr record = std::make_shared(abilityInfo, token); + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + EXPECT_NE(abilityThread, nullptr); + if (abilityThread != nullptr) { + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + std::shared_ptr ability; + MockPageAbility *pMocKPageAbility = new (std::nothrow) MockPageAbility(); + EXPECT_NE(pMocKPageAbility, nullptr); + if (pMocKPageAbility != nullptr) { + ability.reset(pMocKPageAbility); + std::shared_ptr contextDeal = std::make_shared(); + mockAbilityimpl->Init(application, record, ability, handler, token, contextDeal); + + Uri uri("\nullptr"); + std::string mode; + int index = mockAbilityimpl->OpenFile(uri, mode); + + EXPECT_EQ(-1, index); + } + } + } + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_OpenFile_001 end"; +} + +/* + * Feature: AbilityImpl + * Function: Insert + * SubFunction: NA + * FunctionPoints: Insert + * EnvConditions: NA + * CaseDescription: Test the normal behavior of the AbilityImpl::Insert + */ +HWTEST_F(AbilityImplTest, AaFwk_AbilityImpl_Insert_001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_Insert_001 start"; + std::shared_ptr mockAbilityimpl = std::make_shared(); + std::shared_ptr application = std::make_shared(); + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "pageAbility"; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + EXPECT_NE(token, nullptr); + if (token != nullptr) { + std::shared_ptr record = std::make_shared(abilityInfo, token); + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + EXPECT_NE(abilityThread, nullptr); + if (abilityThread != nullptr) { + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + std::shared_ptr ability; + MockPageAbility *pMocKPageAbility = new (std::nothrow) MockPageAbility(); + EXPECT_NE(pMocKPageAbility, nullptr); + if (pMocKPageAbility != nullptr) { + ability.reset(pMocKPageAbility); + std::shared_ptr contextDeal = std::make_shared(); + mockAbilityimpl->Init(application, record, ability, handler, token, contextDeal); + + Uri uri("\nullptr"); + + NativeRdb::ValuesBucket numerical; + int index = mockAbilityimpl->Insert(uri, numerical); + + EXPECT_EQ(-1, index); + } + } + } + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_Insert_001 end"; +} + +/* + * Feature: AbilityImpl + * Function: Update + * SubFunction: NA + * FunctionPoints: Update + * EnvConditions: NA + * CaseDescription: Test the normal behavior of the AbilityImpl::Update + */ +HWTEST_F(AbilityImplTest, AaFwk_AbilityImpl_Update_001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_Update_001 start"; + std::shared_ptr mockAbilityimpl = std::make_shared(); + std::shared_ptr application = std::make_shared(); + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "pageAbility"; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + EXPECT_NE(token, nullptr); + if (token != nullptr) { + std::shared_ptr record = std::make_shared(abilityInfo, token); + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + EXPECT_NE(abilityThread, nullptr); + if (abilityThread != nullptr) { + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + std::shared_ptr ability; + MockPageAbility *pMocKPageAbility = new (std::nothrow) MockPageAbility(); + EXPECT_NE(pMocKPageAbility, nullptr); + if (pMocKPageAbility != nullptr) { + ability.reset(pMocKPageAbility); + std::shared_ptr contextDeal = std::make_shared(); + mockAbilityimpl->Init(application, record, ability, handler, token, contextDeal); + + Uri uri("\nullptr"); + + NativeRdb::ValuesBucket numerical; + NativeRdb::DataAbilityPredicates predicates; + int index = mockAbilityimpl->Update(uri, numerical, predicates); + + EXPECT_EQ(-1, index); + } + } + } + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_Update_001 end"; +} + +/* + * Feature: AbilityImpl + * Function: Delate + * SubFunction: NA + * FunctionPoints: Delate + * EnvConditions: NA + * CaseDescription: Test the normal behavior of the AbilityImpl::Delate + */ +HWTEST_F(AbilityImplTest, AaFwk_AbilityImpl_Delete_001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_Delete_001 start"; + std::shared_ptr mockAbilityimpl = std::make_shared(); + std::shared_ptr application = std::make_shared(); + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "pageAbility"; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + EXPECT_NE(token, nullptr); + if (token != nullptr) { + std::shared_ptr record = std::make_shared(abilityInfo, token); + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + EXPECT_NE(abilityThread, nullptr); + if (abilityThread != nullptr) { + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + std::shared_ptr ability; + MockPageAbility *pMocKPageAbility = new (std::nothrow) MockPageAbility(); + EXPECT_NE(pMocKPageAbility, nullptr); + if (pMocKPageAbility != nullptr) { + ability.reset(pMocKPageAbility); + std::shared_ptr contextDeal = std::make_shared(); + mockAbilityimpl->Init(application, record, ability, handler, token, contextDeal); + + Uri uri("\nullptr"); + + NativeRdb::DataAbilityPredicates predicates; + int index = mockAbilityimpl->Delete(uri, predicates); + + EXPECT_EQ(-1, index); + } + } + } + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_Delete_001 end"; +} + +/* + * Feature: AbilityImpl + * Function: Query + * SubFunction: NA + * FunctionPoints: Query + * EnvConditions: NA + * CaseDescription: Test the normal behavior of the AbilityImpl::Query + */ +HWTEST_F(AbilityImplTest, AaFwk_AbilityImpl_Query_001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_Query_001 start"; + std::shared_ptr mockAbilityimpl = std::make_shared(); + std::shared_ptr application = std::make_shared(); + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "pageAbility"; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + EXPECT_NE(token, nullptr); + if (token != nullptr) { + std::shared_ptr record = std::make_shared(abilityInfo, token); + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + EXPECT_NE(abilityThread, nullptr); + if (abilityThread != nullptr) { + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + std::shared_ptr ability; + MockPageAbility *pMocKPageAbility = new (std::nothrow) MockPageAbility(); + EXPECT_NE(pMocKPageAbility, nullptr); + if (pMocKPageAbility != nullptr) { + ability.reset(pMocKPageAbility); + std::shared_ptr contextDeal = std::make_shared(); + mockAbilityimpl->Init(application, record, ability, handler, token, contextDeal); + + Uri uri("\nullptr"); + std::vector columns; + columns.push_back("string1"); + columns.push_back("string2"); + columns.push_back("string3"); + NativeRdb::DataAbilityPredicates predicates; + + EXPECT_EQ(nullptr, mockAbilityimpl->Query(uri, columns, predicates)); + } + } + } + GTEST_LOG_(INFO) << "AaFwk_AbilityImpl_Query_001 end"; +} +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/test/unittest/ability_lifecycle_executor_test.cpp b/tools/frameworks/kits/ability/native/test/unittest/ability_lifecycle_executor_test.cpp new file mode 100644 index 00000000000..029a332446c --- /dev/null +++ b/tools/frameworks/kits/ability/native/test/unittest/ability_lifecycle_executor_test.cpp @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "ability_lifecycle_executor.h" + +namespace OHOS { +namespace AppExecFwk { +using namespace testing::ext; +using namespace OHOS; +using namespace OHOS::AppExecFwk; + +class AbilityLifecycleExecutorTest : public testing::Test { +public: + AbilityLifecycleExecutorTest() : abilityLifecycleExecutor_(nullptr) + {} + ~AbilityLifecycleExecutorTest() + {} + std::shared_ptr abilityLifecycleExecutor_; + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void AbilityLifecycleExecutorTest::SetUpTestCase(void) +{} + +void AbilityLifecycleExecutorTest::TearDownTestCase(void) +{} + +void AbilityLifecycleExecutorTest::SetUp(void) +{ + abilityLifecycleExecutor_ = std::make_shared(); +} + +void AbilityLifecycleExecutorTest::TearDown(void) +{} + +// AaFwk_AbilityLifecycleExecutor_GetState + +/** + * @tc.number: AaFwk_AbilityLifecycleExecutor_GetState_0100 + * @tc.name: GetState + * @tc.desc: Verify that the return value of getstate is UNINITIALIZED. + */ +HWTEST_F(AbilityLifecycleExecutorTest, AaFwk_AbilityLifecycleExecutor_GetState_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityLifecycleExecutor_GetState_0100 start"; + + AbilityLifecycleExecutor::LifecycleState state = + (AbilityLifecycleExecutor::LifecycleState)abilityLifecycleExecutor_->GetState(); + EXPECT_EQ(AbilityLifecycleExecutor::LifecycleState::UNINITIALIZED, state); + + GTEST_LOG_(INFO) << "AaFwk_AbilityLifecycleExecutor_GetState_0100 end"; +} + +/** + * @tc.number: AaFwk_AbilityLifecycleExecutor_DispatchLifecycleState_0100 + * @tc.name: DispatchLifecycleState + * @tc.desc: Test whether attachbasecontext is called normally, + * and verify whether the return value of getdatabasedir is ACTIVE. + */ +HWTEST_F(AbilityLifecycleExecutorTest, AaFwk_AbilityLifecycleExecutor_DispatchLifecycleState_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityLifecycleExecutor_DispatchLifecycleState_0100 start"; + + AbilityLifecycleExecutor::LifecycleState targetState = AbilityLifecycleExecutor::LifecycleState::ACTIVE; + abilityLifecycleExecutor_->DispatchLifecycleState(targetState); + AbilityLifecycleExecutor::LifecycleState state = + (AbilityLifecycleExecutor::LifecycleState)abilityLifecycleExecutor_->GetState(); + EXPECT_EQ(targetState, state); + + GTEST_LOG_(INFO) << "AaFwk_AbilityLifecycleExecutor_DispatchLifecycleState_0100 end"; +} + +/** + * @tc.number: AaFwk_AbilityLifecycleExecutor_DispatchLifecycleState_0200 + * @tc.name: DispatchLifecycleState + * @tc.desc: Test whether attachbasecontext is called normally, + * and verify whether the return value of getdatabasedir is BACKGROUND. + */ +HWTEST_F(AbilityLifecycleExecutorTest, AaFwk_AbilityLifecycleExecutor_DispatchLifecycleState_0200, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityLifecycleExecutor_DispatchLifecycleState_0200 start"; + + AbilityLifecycleExecutor::LifecycleState targetState = AbilityLifecycleExecutor::LifecycleState::BACKGROUND; + abilityLifecycleExecutor_->DispatchLifecycleState(targetState); + AbilityLifecycleExecutor::LifecycleState state = + (AbilityLifecycleExecutor::LifecycleState)abilityLifecycleExecutor_->GetState(); + EXPECT_EQ(targetState, state); + + GTEST_LOG_(INFO) << "AaFwk_AbilityLifecycleExecutor_DispatchLifecycleState_0200 end"; +} + +/** + * @tc.number: AaFwk_AbilityLifecycleExecutor_DispatchLifecycleState_0300 + * @tc.name: DispatchLifecycleState + * @tc.desc: Test whether attachbasecontext is called normally, + * and verify whether the return value of getdatabasedir is INACTIVE. + */ +HWTEST_F(AbilityLifecycleExecutorTest, AaFwk_AbilityLifecycleExecutor_DispatchLifecycleState_0300, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityLifecycleExecutor_DispatchLifecycleState_0300 start"; + + AbilityLifecycleExecutor::LifecycleState targetState = AbilityLifecycleExecutor::LifecycleState::INACTIVE; + abilityLifecycleExecutor_->DispatchLifecycleState(targetState); + AbilityLifecycleExecutor::LifecycleState state = + (AbilityLifecycleExecutor::LifecycleState)abilityLifecycleExecutor_->GetState(); + EXPECT_EQ(targetState, state); + + GTEST_LOG_(INFO) << "AaFwk_AbilityLifecycleExecutor_DispatchLifecycleState_0300 end"; +} + +/** + * @tc.number: AaFwk_AbilityLifecycleExecutor_DispatchLifecycleState_0400 + * @tc.name: DispatchLifecycleState + * @tc.desc: Test whether attachbasecontext is called normally, + * and verify whether the return value of getdatabasedir is INITIAL. + */ +HWTEST_F(AbilityLifecycleExecutorTest, AaFwk_AbilityLifecycleExecutor_DispatchLifecycleState_0400, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityLifecycleExecutor_DispatchLifecycleState_0400 start"; + + AbilityLifecycleExecutor::LifecycleState targetState = AbilityLifecycleExecutor::LifecycleState::INITIAL; + abilityLifecycleExecutor_->DispatchLifecycleState(targetState); + AbilityLifecycleExecutor::LifecycleState state = + (AbilityLifecycleExecutor::LifecycleState)abilityLifecycleExecutor_->GetState(); + EXPECT_EQ(targetState, state); + + GTEST_LOG_(INFO) << "AaFwk_AbilityLifecycleExecutor_DispatchLifecycleState_0400 end"; +} + +/** + * @tc.number: AaFwk_AbilityLifecycleExecutor_DispatchLifecycleState_0500 + * @tc.name: DispatchLifecycleState + * @tc.desc: Test whether attachbasecontext is called normally, + * and verify whether the return value of getdatabasedir is UNINITIALIZED. + */ +HWTEST_F(AbilityLifecycleExecutorTest, AaFwk_AbilityLifecycleExecutor_DispatchLifecycleState_0500, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityLifecycleExecutor_DispatchLifecycleState_0500 start"; + + AbilityLifecycleExecutor::LifecycleState targetState = AbilityLifecycleExecutor::LifecycleState::UNINITIALIZED; + abilityLifecycleExecutor_->DispatchLifecycleState(targetState); + AbilityLifecycleExecutor::LifecycleState state = + (AbilityLifecycleExecutor::LifecycleState)abilityLifecycleExecutor_->GetState(); + EXPECT_EQ(targetState, state); + + GTEST_LOG_(INFO) << "AaFwk_AbilityLifecycleExecutor_DispatchLifecycleState_0500 end"; +} +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/test/unittest/ability_lifecycle_test.cpp b/tools/frameworks/kits/ability/native/test/unittest/ability_lifecycle_test.cpp new file mode 100644 index 00000000000..f4aef35c6ce --- /dev/null +++ b/tools/frameworks/kits/ability/native/test/unittest/ability_lifecycle_test.cpp @@ -0,0 +1,368 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "ability_lifecycle.h" +#include "mock_lifecycle_observer.h" +#include "want.h" + +namespace OHOS { +namespace AppExecFwk { +using namespace testing::ext; +using namespace OHOS; +using namespace OHOS::AppExecFwk; +using Want = OHOS::AAFwk::Want; + +class LifeCycleTest : public testing::Test { +public: + LifeCycleTest() : lifeCycle_(nullptr) + {} + ~LifeCycleTest() + {} + std::shared_ptr lifeCycle_; + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void LifeCycleTest::SetUpTestCase(void) +{} + +void LifeCycleTest::TearDownTestCase(void) +{} + +void LifeCycleTest::SetUp(void) +{ + lifeCycle_ = std::make_shared(); +} + +void LifeCycleTest::TearDown(void) +{} + + +/** + * @tc.number: AaFwk_LifeCycle_GetLifecycleState_0100 + * @tc.name: GetLifecycleState + * @tc.desc: Determine whether the return value of getlifecycle state is equal to undefined. + */ +HWTEST_F(LifeCycleTest, AaFwk_LifeCycle_GetLifecycleState_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_LifeCycle_GetLifecycleState_0100 start"; + + LifeCycle::Event state = lifeCycle_->GetLifecycleState(); + EXPECT_EQ(LifeCycle::Event::UNDEFINED, state); + + GTEST_LOG_(INFO) << "AaFwk_LifeCycle_GetLifecycleState_0100 end"; +} + +/** + * @tc.number: AaFwk_LifeCycle_AddObserver_0100 + * @tc.name: AddObserver + * @tc.desc: Determine whether the return value of getlifecycle state is equal to undefined. + */ +HWTEST_F(LifeCycleTest, AaFwk_LifeCycle_AddObserver_0100, Function | MediumTest | Level3) +{ + GTEST_LOG_(INFO) << "AaFwk_LifeCycle_AddObserver_0100 start"; + + lifeCycle_->AddObserver(nullptr); + + GTEST_LOG_(INFO) << "AaFwk_LifeCycle_AddObserver_0100 end"; +} + +/** + * @tc.number: AaFwk_LifeCycle_AddObserver_0200 + * @tc.name: AddObserver + * @tc.desc: Determine whether the return value of getlifecycle state is equal to undefined. + */ +HWTEST_F(LifeCycleTest, AaFwk_LifeCycle_AddObserver_0200, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_LifeCycle_AddObserver_0200 start"; + + std::shared_ptr observer = std::make_shared(); + lifeCycle_->AddObserver(observer); + lifeCycle_->DispatchLifecycle(LifeCycle::Event::ON_ACTIVE); + + GTEST_LOG_(INFO) << "AaFwk_LifeCycle_AddObserver_0200 end"; +} + +/** + * @tc.number: AaFwk_LifeCycle_RemoveObserver_0100 + * @tc.name: RemoveObserver + * @tc.desc: Test the removeobserver exception state. + */ +HWTEST_F(LifeCycleTest, AaFwk_LifeCycle_RemoveObserver_0100, Function | MediumTest | Level3) +{ + GTEST_LOG_(INFO) << "AaFwk_LifeCycle_RemoveObserver_0100 start"; + + std::shared_ptr observer = std::make_shared(); + lifeCycle_->AddObserver(observer); + lifeCycle_->DispatchLifecycle(LifeCycle::Event::ON_ACTIVE); + lifeCycle_->RemoveObserver(nullptr); + lifeCycle_->DispatchLifecycle(LifeCycle::Event::ON_ACTIVE); + + GTEST_LOG_(INFO) << "AaFwk_LifeCycle_RemoveObserver_0100 end"; +} +/** + * @tc.number: AaFwk_LifeCycle_RemoveObserver_0200 + * @tc.name: RemoveObserver + * @tc.desc: Test whether addobserver is added and confirm whether removeobserver is deleted. + */ +HWTEST_F(LifeCycleTest, AaFwk_LifeCycle_RemoveObserver_0200, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_LifeCycle_RemoveObserver_0200 start"; + + std::shared_ptr observer = std::make_shared(); + lifeCycle_->AddObserver(observer); + lifeCycle_->DispatchLifecycle(LifeCycle::Event::ON_ACTIVE); + lifeCycle_->RemoveObserver(observer); + lifeCycle_->DispatchLifecycle(LifeCycle::Event::ON_ACTIVE); + + GTEST_LOG_(INFO) << "AaFwk_LifeCycle_RemoveObserver_0200 end"; +} + +/** + * @tc.number: AaFwk_LifeCycle_DispatchLifecycle_event_want_0100 + * @tc.name: DispatchLifecycle + * @tc.desc: Determine whether the current action is correct through dispatchlifecycle. + */ +HWTEST_F(LifeCycleTest, AaFwk_LifeCycle_DispatchLifecycle_event_want_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_LifeCycle_DispatchLifecycle_event_want_0100 start"; + + std::shared_ptr observer = std::make_shared(); + Want want; + lifeCycle_->AddObserver(observer); + lifeCycle_->DispatchLifecycle(LifeCycle::Event::UNDEFINED, want); + + GTEST_LOG_(INFO) << "AaFwk_LifeCycle_DispatchLifecycle_event_want_0100 end"; +} + +/** + * @tc.number: AaFwk_LifeCycle_DispatchLifecycle_event_want_0200 + * @tc.name: DispatchLifecycle + * @tc.desc: Determine whether the current action is correct through dispatchlifecycle. + */ +HWTEST_F(LifeCycleTest, AaFwk_LifeCycle_DispatchLifecycle_event_want_0200, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_LifeCycle_DispatchLifecycle_event_want_0200 start"; + + std::shared_ptr observer = std::make_shared(); + Want want; + lifeCycle_->AddObserver(observer); + lifeCycle_->DispatchLifecycle(LifeCycle::Event::ON_ACTIVE, want); + + GTEST_LOG_(INFO) << "AaFwk_LifeCycle_DispatchLifecycle_event_want_0200 end"; +} + +/** + * @tc.number: AaFwk_LifeCycle_DispatchLifecycle_event_want_0300 + * @tc.name: DispatchLifecycle + * @tc.desc: Determine whether the current action is correct through dispatchlifecycle. + */ +HWTEST_F(LifeCycleTest, AaFwk_LifeCycle_DispatchLifecycle_event_want_0300, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_LifeCycle_DispatchLifecycle_event_want_0300 start"; + + std::shared_ptr observer = std::make_shared(); + Want want; + lifeCycle_->AddObserver(observer); + lifeCycle_->DispatchLifecycle(LifeCycle::Event::ON_BACKGROUND, want); + + GTEST_LOG_(INFO) << "AaFwk_LifeCycle_DispatchLifecycle_event_want_0300 end"; +} + +/** + * @tc.number: AaFwk_LifeCycle_DispatchLifecycle_event_want_0400 + * @tc.name: DispatchLifecycle + * @tc.desc: Determine whether the current action is correct through dispatchlifecycle. + */ +HWTEST_F(LifeCycleTest, AaFwk_LifeCycle_DispatchLifecycle_event_want_0400, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_LifeCycle_DispatchLifecycle_event_want_0400 start"; + + std::shared_ptr observer = std::make_shared(); + Want want; + lifeCycle_->AddObserver(observer); + lifeCycle_->DispatchLifecycle(LifeCycle::Event::ON_FOREGROUND, want); + + GTEST_LOG_(INFO) << "AaFwk_LifeCycle_DispatchLifecycle_event_want_0400 end"; +} + +/** + * @tc.number: AaFwk_LifeCycle_DispatchLifecycle_event_want_0500 + * @tc.name: DispatchLifecycle + * @tc.desc: Determine whether the current action is correct through dispatchlifecycle. + */ +HWTEST_F(LifeCycleTest, AaFwk_LifeCycle_DispatchLifecycle_event_want_0500, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_LifeCycle_DispatchLifecycle_event_want_0500 start"; + + std::shared_ptr observer = std::make_shared(); + Want want; + lifeCycle_->AddObserver(observer); + lifeCycle_->DispatchLifecycle(LifeCycle::Event::ON_INACTIVE, want); + + GTEST_LOG_(INFO) << "AaFwk_LifeCycle_DispatchLifecycle_event_want_0500 end"; +} + +/** + * @tc.number: AaFwk_LifeCycle_DispatchLifecycle_event_want_0600 + * @tc.name: DispatchLifecycle + * @tc.desc: Determine whether the current action is correct through dispatchlifecycle. + */ +HWTEST_F(LifeCycleTest, AaFwk_LifeCycle_DispatchLifecycle_event_want_0600, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_LifeCycle_DispatchLifecycle_event_want_0600 start"; + + std::shared_ptr observer = std::make_shared(); + Want want; + lifeCycle_->AddObserver(observer); + lifeCycle_->DispatchLifecycle(LifeCycle::Event::ON_START, want); + + GTEST_LOG_(INFO) << "AaFwk_LifeCycle_DispatchLifecycle_event_want_006 end"; +} + +/** + * @tc.number: AaFwk_LifeCycle_DispatchLifecycle_event_want_0700 + * @tc.name: DispatchLifecycle + * @tc.desc: Determine whether the current action is correct through dispatchlifecycle. + */ +HWTEST_F(LifeCycleTest, AaFwk_LifeCycle_DispatchLifecycle_event_want_0700, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_LifeCycle_DispatchLifecycle_event_want_0700 start"; + + std::shared_ptr observer = std::make_shared(); + Want want; + lifeCycle_->AddObserver(observer); + lifeCycle_->DispatchLifecycle(LifeCycle::Event::ON_STOP, want); + + GTEST_LOG_(INFO) << "AaFwk_LifeCycle_DispatchLifecycle_event_want_0700 end"; +} + +/** + * @tc.number: AaFwk_LifeCycle_DispatchLifecycle_event_0100 + * @tc.name: DispatchLifecycle + * @tc.desc: Determine whether the current action is correct through dispatchlifecycle. + */ +HWTEST_F(LifeCycleTest, AaFwk_LifeCycle_DispatchLifecycle_event_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_LifeCycle_DispatchLifecycle_event_0100 start"; + + std::shared_ptr observer = std::make_shared(); + lifeCycle_->AddObserver(observer); + lifeCycle_->DispatchLifecycle(LifeCycle::Event::UNDEFINED); + + GTEST_LOG_(INFO) << "AaFwk_LifeCycle_DispatchLifecycle_event_0100 end"; +} + +/** + * @tc.number: AaFwk_LifeCycle_DispatchLifecycle_event_0200 + * @tc.name: DispatchLifecycle + * @tc.desc: Determine whether the current action is correct through dispatchlifecycle. + */ +HWTEST_F(LifeCycleTest, AaFwk_LifeCycle_DispatchLifecycle_event_0200, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_LifeCycle_DispatchLifecycle_event_0200 start"; + + std::shared_ptr observer = std::make_shared(); + lifeCycle_->AddObserver(observer); + lifeCycle_->DispatchLifecycle(LifeCycle::Event::ON_ACTIVE); + + GTEST_LOG_(INFO) << "AaFwk_LifeCycle_DispatchLifecycle_event_0200 end"; +} + +/** + * @tc.number: AaFwk_LifeCycle_DispatchLifecycle_event_0300 + * @tc.name: DispatchLifecycle + * @tc.desc: Determine whether the current action is correct through dispatchlifecycle. + */ +HWTEST_F(LifeCycleTest, AaFwk_LifeCycle_DispatchLifecycle_event_0300, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_LifeCycle_DispatchLifecycle_event_0300 start"; + + std::shared_ptr observer = std::make_shared(); + lifeCycle_->AddObserver(observer); + lifeCycle_->DispatchLifecycle(LifeCycle::Event::ON_BACKGROUND); + + GTEST_LOG_(INFO) << "AaFwk_LifeCycle_DispatchLifecycle_event_0300 end"; +} + +/** + * @tc.number: AaFwk_LifeCycle_DispatchLifecycle_event_0400 + * @tc.name: DispatchLifecycle + * @tc.desc: Determine whether the current action is correct through dispatchlifecycle. + */ +HWTEST_F(LifeCycleTest, AaFwk_LifeCycle_DispatchLifecycle_event_0400, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_LifeCycle_DispatchLifecycle_event_0400 start"; + + std::shared_ptr observer = std::make_shared(); + lifeCycle_->AddObserver(observer); + lifeCycle_->DispatchLifecycle(LifeCycle::Event::ON_FOREGROUND); + + GTEST_LOG_(INFO) << "AaFwk_LifeCycle_DispatchLifecycle_event_0400 end"; +} + +/** + * @tc.number: AaFwk_LifeCycle_DispatchLifecycle_event_0500 + * @tc.name: DispatchLifecycle + * @tc.desc: Determine whether the current action is correct through dispatchlifecycle. + */ +HWTEST_F(LifeCycleTest, AaFwk_LifeCycle_DispatchLifecycle_event_0500, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_LifeCycle_DispatchLifecycle_event_0500 start"; + + std::shared_ptr observer = std::make_shared(); + lifeCycle_->AddObserver(observer); + lifeCycle_->DispatchLifecycle(LifeCycle::Event::ON_INACTIVE); + + GTEST_LOG_(INFO) << "AaFwk_LifeCycle_DispatchLifecycle_event_0500 end"; +} + +/** + * @tc.number: AaFwk_LifeCycle_DispatchLifecycle_event_0600 + * @tc.name: DispatchLifecycle + * @tc.desc: Determine whether the current action is correct through dispatchlifecycle. + */ +HWTEST_F(LifeCycleTest, AaFwk_LifeCycle_DispatchLifecycle_event_0600, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_LifeCycle_DispatchLifecycle_event_0600 start"; + + std::shared_ptr observer = std::make_shared(); + lifeCycle_->AddObserver(observer); + lifeCycle_->DispatchLifecycle(LifeCycle::Event::ON_START); + + GTEST_LOG_(INFO) << "AaFwk_LifeCycle_DispatchLifecycle_event_0600 end"; +} + +/** + * @tc.number: AaFwk_LifeCycle_DispatchLifecycle_event_0700 + * @tc.name: DispatchLifecycle + * @tc.desc: Determine whether the current action is correct through dispatchlifecycle. + */ +HWTEST_F(LifeCycleTest, AaFwk_LifeCycle_DispatchLifecycle_event_0700, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_LifeCycle_DispatchLifecycle_event_0700 start"; + + std::shared_ptr observer = std::make_shared(); + lifeCycle_->AddObserver(observer); + lifeCycle_->DispatchLifecycle(LifeCycle::Event::ON_STOP); + + GTEST_LOG_(INFO) << "AaFwk_LifeCycle_DispatchLifecycle_event_0700 end"; +} +} // namespace AppExecFwk +} // namespace OHOS diff --git a/tools/frameworks/kits/ability/native/test/unittest/ability_permission_test.cpp b/tools/frameworks/kits/ability/native/test/unittest/ability_permission_test.cpp new file mode 100755 index 00000000000..06f9bd1c321 --- /dev/null +++ b/tools/frameworks/kits/ability/native/test/unittest/ability_permission_test.cpp @@ -0,0 +1,200 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "ability_context.h" +#include "context_deal.h" +#include "ability_info.h" +#include "ability.h" +#include "mock_bundle_manager.h" +#include "sys_mgr_client.h" +#include "sa_mgr_client.h" +#include "mock_ability_manager_service.h" +#include "iservice_registry.h" +#include "system_ability_definition.h" + +namespace OHOS { +namespace AppExecFwk { +using namespace testing::ext; +using namespace OHOS; +using namespace OHOS::AppExecFwk; + +class AbilityPermissionTest : public testing::Test { +public: + AbilityPermissionTest() : context_(nullptr) + {} + ~AbilityPermissionTest() + {} + std::shared_ptr context_ = nullptr; + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void AbilityPermissionTest::SetUpTestCase(void) +{ + OHOS::sptr bundleObject = new (std::nothrow) BundleMgrService(); + OHOS::sptr abilityObject = new (std::nothrow) AAFwk::MockAbilityManagerService(); + + auto sysMgr = OHOS::DelayedSingleton::GetInstance(); + + if (sysMgr == NULL) { + GTEST_LOG_(ERROR) << "fail to get ISystemAbilityManager"; + return; + } + + sysMgr->RegisterSystemAbility(OHOS::BUNDLE_MGR_SERVICE_SYS_ABILITY_ID, bundleObject); + sysMgr->RegisterSystemAbility(OHOS::ABILITY_MGR_SERVICE_ID, abilityObject); +} + +void AbilityPermissionTest::TearDownTestCase(void) +{} + +void AbilityPermissionTest::SetUp(void) +{ + context_ = std::make_shared(); +} + +void AbilityPermissionTest::TearDown(void) +{} + +/** + * @tc.number: AaFwk_AbilityPermissionTest_VerifySelfPermission_0100 + * @tc.name: VerifySelfPermission + * @tc.desc: Verify that the verifyselfpermission return value is correct. + */ +HWTEST_F(AbilityPermissionTest, AaFwk_AbilityPermissionTest_VerifySelfPermission_0100, Function | MediumTest | Level1) +{ + if (context_ == nullptr) { + EXPECT_EQ(true, context_ != nullptr); + return; + } + + std::string permission_name("permission_VerifySelfPermission"); + std::shared_ptr appInfo = std::make_shared(); + std::string name = "hello"; + appInfo->bundleName = name; + + std::shared_ptr deal = std::make_shared(); + deal->SetApplicationInfo(appInfo); + context_->AttachBaseContext(deal); + + context_->VerifySelfPermission(permission_name); +} + +/** + * @tc.number: AaFwk_AbilityPermissionTest_VerifyCallingOrSelfPermission_0100 + * @tc.name: VerifyCallingOrSelfPermission + * @tc.desc: Verify that the VerifyCallingOrSelfPermission return value is correct. + */ +HWTEST_F(AbilityPermissionTest, AaFwk_AbilityPermissionTest_VerifyCallingOrSelfPermission_0100, + Function | MediumTest | Level1) +{ + if (context_ == nullptr) { + EXPECT_EQ(true, context_ != nullptr); + return; + } + + std::string permission_name("permission_VerifyCallingOrSelfPermission"); + std::shared_ptr appInfo = std::make_shared(); + std::string name = "hello"; + appInfo->bundleName = name; + + std::shared_ptr deal = std::make_shared(); + deal->SetApplicationInfo(appInfo); + + context_->AttachBaseContext(deal); + + context_->VerifyCallingOrSelfPermission(permission_name); +} + +/** + * @tc.number: AaFwk_AbilityPermissionTest_VerifyPermission_0100 + * @tc.name: VerifyPermission + * @tc.desc: Verify that the VerifyPermission return value is correct. + */ +HWTEST_F(AbilityPermissionTest, AaFwk_AbilityPermissionTest_VerifyPermission_0100, Function | MediumTest | Level1) +{ + if (context_ == nullptr) { + EXPECT_EQ(true, context_ != nullptr); + return; + } + + std::string permission_name("permission_VerifyPermission"); + std::shared_ptr appInfo = std::make_shared(); + std::string name = "hello"; + appInfo->bundleName = name; + + std::shared_ptr deal = std::make_shared(); + deal->SetApplicationInfo(appInfo); + + context_->AttachBaseContext(deal); + + context_->VerifyPermission(permission_name, 0, 10); +} + +/** + * @tc.number: AaFwk_AbilityPermissionTest_CanRequestPermission_0100 + * @tc.name: CanRequestPermission + * @tc.desc: Verify that the CanRequestPermission return value is correct. + */ +HWTEST_F(AbilityPermissionTest, AaFwk_AbilityPermissionTest_CanRequestPermission_0100, Function | MediumTest | Level1) +{ + if (context_ == nullptr) { + EXPECT_EQ(true, context_ != nullptr); + return; + } + + std::string permission_name("permission_CanRequestPermission"); + std::shared_ptr appInfo = std::make_shared(); + std::string name = "hello"; + appInfo->bundleName = name; + + std::shared_ptr deal = std::make_shared(); + deal->SetApplicationInfo(appInfo); + + context_->AttachBaseContext(deal); + context_->CanRequestPermission(permission_name); +} + +/** + * @tc.number: AaFwk_AbilityPermissionTest_RequestPermissionsFromUser_0100 + * @tc.name: RequestPermissionsFromUser + * @tc.desc: Verify that requestpermissionsfromuser is called. + */ +HWTEST_F( + AbilityPermissionTest, AaFwk_AbilityPermissionTest_RequestPermissionsFromUser_0100, Function | MediumTest | Level1) +{ + if (context_ == nullptr) { + EXPECT_EQ(true, context_ != nullptr); + return; + } + + std::shared_ptr appInfo = std::make_shared(); + std::string name = "hello"; + appInfo->bundleName = name; + std::vector permissions; + permissions.emplace_back("permission_1"); + permissions.emplace_back("permission_2"); + permissions.emplace_back("permission_3"); + + std::shared_ptr deal = std::make_shared(); + deal->SetApplicationInfo(appInfo); + context_->AttachBaseContext(deal); + context_->RequestPermissionsFromUser(permissions, 1004); +} +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/test/unittest/ability_test.cpp b/tools/frameworks/kits/ability/native/test/unittest/ability_test.cpp new file mode 100755 index 00000000000..714e9f6c3c2 --- /dev/null +++ b/tools/frameworks/kits/ability/native/test/unittest/ability_test.cpp @@ -0,0 +1,851 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "ability.h" +#include "ability_local_record.h" +#include "ability_handler.h" +#include "ability_info.h" +#include "ability_start_setting.h" +#include "context_deal.h" +#include "mock_page_ability.h" + +namespace OHOS { +namespace AppExecFwk { +using namespace testing::ext; +using namespace OHOS; +using namespace OHOS::AppExecFwk; +using OHOS::Parcel; + +class AbilityBaseTest : public testing::Test { +public: + AbilityBaseTest() : ability_(nullptr) + {} + ~AbilityBaseTest() + {} + std::shared_ptr ability_; + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void AbilityBaseTest::SetUpTestCase(void) +{} + +void AbilityBaseTest::TearDownTestCase(void) +{} + +void AbilityBaseTest::SetUp(void) +{ + ability_ = std::make_shared(); +} + +void AbilityBaseTest::TearDown(void) +{} + +/** + * @tc.number: AaFwk_Ability_Name_0100 + * @tc.name: GetAbilityName + * @tc.desc: Verify that the return value of getabilityname is correct. + */ +HWTEST_F(AbilityBaseTest, AaFwk_Ability_Name_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_Ability_Name_0100 start"; + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "ability"; + std::shared_ptr application = std::make_shared(); + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + sptr token = nullptr; + + ability_->Init(abilityInfo, application, handler, token); + EXPECT_STREQ(abilityInfo->name.c_str(), ability_->GetAbilityName().c_str()); + + GTEST_LOG_(INFO) << "AaFwk_Ability_Name_0100 end"; +} + +/** + * @tc.number: AaFwk_Ability_GetLifecycle_0100 + * @tc.name: GetLifecycle + * @tc.desc: Verify that the return value of getlifecycle is not empty. + */ +HWTEST_F(AbilityBaseTest, AaFwk_Ability_GetLifecycle_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_Ability_GetLifecycle_0100 start"; + + std::shared_ptr abilityInfo = std::make_shared(); + std::shared_ptr application = std::make_shared(); + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + sptr token = nullptr; + + ability_->Init(abilityInfo, application, handler, token); + std::shared_ptr lifeCycle = ability_->GetLifecycle(); + + EXPECT_NE(lifeCycle, nullptr); + + GTEST_LOG_(INFO) << "AaFwk_Ability_GetLifecycle_0100 end"; +} + +/** + * @tc.number: AaFwk_Ability_GetState_0100 + * @tc.name: GetState + * @tc.desc: Verify that the return value of getstate is equal to active. + */ +HWTEST_F(AbilityBaseTest, AaFwk_Ability_GetState_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_Ability_GetState_0100 start"; + + std::shared_ptr abilityInfo = std::make_shared(); + std::shared_ptr application = std::make_shared(); + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + sptr token = nullptr; + + ability_->Init(abilityInfo, application, handler, token); + + ability_->OnActive(); + AbilityLifecycleExecutor::LifecycleState state = ability_->GetState(); + EXPECT_EQ(AbilityLifecycleExecutor::LifecycleState::ACTIVE, state); + + GTEST_LOG_(INFO) << "AaFwk_Ability_GetState_0100 end"; +} + +/** + * @tc.number: AaFwk_Ability_GetState_0200 + * @tc.name: GetState + * @tc.desc: Getstate exception test. + */ +HWTEST_F(AbilityBaseTest, AaFwk_Ability_GetState_0200, Function | MediumTest | Level3) +{ + GTEST_LOG_(INFO) << "AaFwk_Ability_GetState_0200 start"; + + ability_->OnActive(); + AbilityLifecycleExecutor::LifecycleState state = ability_->GetState(); + EXPECT_EQ(AbilityLifecycleExecutor::LifecycleState::UNINITIALIZED, state); + + GTEST_LOG_(INFO) << "AaFwk_Ability_GetState_0200 end"; +} + +/** + * @tc.number: AaFwk_Ability_Dump_0100 + * @tc.name: Dump + * @tc.desc: Test dump normal flow. + */ +HWTEST_F(AbilityBaseTest, AaFwk_Ability_Dump_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_Ability_Dump_0100 start"; + + std::shared_ptr abilityInfo = std::make_shared(); + std::shared_ptr application = std::make_shared(); + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + sptr token = nullptr; + + ability_->Init(abilityInfo, application, handler, token); + + std::string extra = ""; + ability_->Dump(extra); + + GTEST_LOG_(INFO) << "AaFwk_Ability_Dump_0100 end"; +} + +/** + * @tc.number: AaFwk_Ability_OnNewWant_0100 + * @tc.name: OnNewWant + * @tc.desc: Test whether onnewwant can be called normally. + */ +HWTEST_F(AbilityBaseTest, AaFwk_Ability_OnNewWant_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_Ability_OnNewWant_0100 start"; + + std::shared_ptr abilityInfo = std::make_shared(); + std::shared_ptr application = std::make_shared(); + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + sptr token = nullptr; + + ability_->Init(abilityInfo, application, handler, token); + + Want want; + ability_->OnNewWant(want); + + GTEST_LOG_(INFO) << "AaFwk_Ability_OnNewWant_0100 end"; +} + +/** + * @tc.number: AaFwk_Ability_OnRestoreAbilityState_0100 + * @tc.name: OnRestoreAbilityState + * @tc.desc: Test whether onnewwant can be called normally. + */ +HWTEST_F(AbilityBaseTest, AaFwk_Ability_OnRestoreAbilityState_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_Ability_OnRestoreAbilityState_0100 start"; + + std::shared_ptr abilityInfo = std::make_shared(); + std::shared_ptr application = std::make_shared(); + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + sptr token = nullptr; + + ability_->Init(abilityInfo, application, handler, token); + + PacMap inState; + ability_->OnRestoreAbilityState(inState); + + GTEST_LOG_(INFO) << "AaFwk_Ability_OnRestoreAbilityState_0100 end"; +} + +/** + * @tc.number: AaFwk_Ability_GetAbilityName_0100 + * @tc.name: GetAbilityName + * @tc.desc: Verify that the getabilityname return value is correct. + */ +HWTEST_F(AbilityBaseTest, AaFwk_Ability_GetAbilityName_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_Ability_GetAbilityName_0100 start"; + + std::shared_ptr abilityInfo = std::make_shared(); + std::shared_ptr application = std::make_shared(); + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + sptr token = nullptr; + + std::string name = "LOL"; + abilityInfo->name = name; + ability_->Init(abilityInfo, application, handler, token); + + EXPECT_STREQ(ability_->GetAbilityName().c_str(), name.c_str()); + + GTEST_LOG_(INFO) << "AaFwk_Ability_GetAbilityName_0100 end"; +} + +/** + * @tc.number: AaFwk_Ability_GetApplication_0100 + * @tc.name: GetApplication + * @tc.desc: Verify that the getapplication return value is correct. + */ +HWTEST_F(AbilityBaseTest, AaFwk_Ability_GetApplication_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_Ability_GetApplication_0100 start"; + + std::shared_ptr abilityInfo = std::make_shared(); + std::shared_ptr application = std::make_shared(); + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + sptr token = nullptr; + + ability_->Init(abilityInfo, application, handler, token); + std::shared_ptr applicationRet = ability_->GetApplication(); + EXPECT_EQ(application, applicationRet); + + GTEST_LOG_(INFO) << "AaFwk_Ability_GetApplication_0100 end"; +} + +/** + * @tc.number: AaFwk_Ability_GetApplication_0200 + * @tc.name: GetApplication + * @tc.desc: Test getapplication exception status. + */ +HWTEST_F(AbilityBaseTest, AaFwk_Ability_GetApplication_0200, Function | MediumTest | Level3) +{ + GTEST_LOG_(INFO) << "AaFwk_Ability_GetApplication_0200 start"; + + std::shared_ptr abilityInfo = std::make_shared(); + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + sptr token = nullptr; + + ability_->Init(abilityInfo, nullptr, handler, token); + std::shared_ptr application = ability_->GetApplication(); + EXPECT_EQ(application, nullptr); + + GTEST_LOG_(INFO) << "AaFwk_Ability_GetApplication_0200 end"; +} + +/** + * @tc.number: AaFwk_Ability_OnSaveAbilityState_0100 + * @tc.name: OnSaveAbilityState + * @tc.desc: Test whether onsaveabilitystate is called normally. + */ +HWTEST_F(AbilityBaseTest, AaFwk_Ability_OnSaveAbilityState_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_Ability_OnSaveAbilityState_0100 start"; + + std::shared_ptr abilityInfo = std::make_shared(); + std::shared_ptr application = std::make_shared(); + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + sptr token = nullptr; + + ability_->Init(abilityInfo, application, handler, token); + + PacMap outState; + ability_->OnSaveAbilityState(outState); + + GTEST_LOG_(INFO) << "AaFwk_Ability_OnSaveAbilityState_0100 end"; +} + +/** + * @tc.number: AaFwk_Ability_SetWant_GetWant_0100 + * @tc.name: OnSaveAbilityState + * @tc.desc: Verify that setwant creates the object normally, + * and judge whether the return value of getwant is correct. + */ +HWTEST_F(AbilityBaseTest, AaFwk_Ability_SetWant_GetWant_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_Ability_SetWant_GetWant_0100 start"; + + std::string abilityName = "Ability"; + std::string bundleName = "Bundle"; + AAFwk::Want want; + want.SetElementName(bundleName, abilityName); + ability_->SetWant(want); + + EXPECT_STREQ(ability_->GetWant()->GetElement().GetBundleName().c_str(), bundleName.c_str()); + EXPECT_STREQ(ability_->GetWant()->GetElement().GetAbilityName().c_str(), abilityName.c_str()); + GTEST_LOG_(INFO) << "AaFwk_Ability_SetWant_GetWant_0100 end"; +} + +/** + * @tc.number: AaFwk_Ability_SetResult_0100 + * @tc.name: SetResult + * @tc.desc: Test whether setresult is called normally. + */ +HWTEST_F(AbilityBaseTest, AaFwk_Ability_SetResult_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_Ability_SetResult_0100 start"; + + int resultCode = 0; + Want want; + std::string action = "Action"; + want.SetAction(action); + + std::shared_ptr abilityInfo = std::make_shared(); + AbilityType type = AbilityType::PAGE; + abilityInfo->type = type; + std::shared_ptr application = nullptr; + std::shared_ptr handler = nullptr; + sptr token = nullptr; + ability_->Init(abilityInfo, application, handler, token); + ability_->SetResult(resultCode, want); + + GTEST_LOG_(INFO) << "AaFwk_Ability_SetResult_0100 end"; +} + +/** + * @tc.number: AaFwk_Ability_StartAbilityForResult_0100 + * @tc.name: StartAbilityForResult + * @tc.desc: Test whether startabilityforesult is called normally. + */ +HWTEST_F(AbilityBaseTest, AaFwk_Ability_StartAbilityForResult_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_Ability_StartAbilityForResult_0100 start"; + + int resultCode = 0; + Want want; + std::shared_ptr abilityInfo = std::make_shared(); + AbilityType type = AbilityType::PAGE; + abilityInfo->type = type; + std::shared_ptr application = nullptr; + std::shared_ptr handler = nullptr; + sptr token = nullptr; + ability_->Init(abilityInfo, application, handler, token); + ability_->StartAbilityForResult(want, resultCode); + + GTEST_LOG_(INFO) << "AaFwk_Ability_StartAbilityForResult_0100 end"; +} + +/** + * @tc.number: AaFwk_Ability_StartAbility_0100 + * @tc.name: StartAbility + * @tc.desc: Test whether startability is called normally. + */ +HWTEST_F(AbilityBaseTest, AaFwk_Ability_StartAbility_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_Ability_StartAbility_0100 start"; + + Want want; + ability_->StartAbility(want); + + GTEST_LOG_(INFO) << "AaFwk_Ability_StartAbility_0100 end"; +} + +/** + * @tc.number: AaFwk_Ability_TerminateAbility_0100 + * @tc.name: TerminateAbility + * @tc.desc: Test whether terminateability is called normally. + */ +HWTEST_F(AbilityBaseTest, AaFwk_Ability_TerminateAbility_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_Ability_TerminateAbility_0100 start"; + + ability_->TerminateAbility(); + + GTEST_LOG_(INFO) << "AaFwk_Ability_TerminateAbility_0100 end"; +} + +HWTEST_F(AbilityBaseTest, AaFwk_Ability_GetWindow_001, Function | MediumTest | Level1) +{ + std::shared_ptr abilityInfo = std::make_shared(); + AbilityType type = AbilityType::PAGE; + abilityInfo->type = type; + std::shared_ptr application = nullptr; + std::shared_ptr handler = nullptr; + sptr token = nullptr; + ability_->Init(abilityInfo, application, handler, token); +} + +/** + * @tc.number: AaFwk_Ability_OnStart_0100 + * @tc.name: OnStart + * @tc.desc: Test whether OnStart is called normally and verify whether the members are correct. + */ +HWTEST_F(AbilityBaseTest, AaFwk_Ability_OnStart_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_Ability_OnStart_0100 start"; + + std::shared_ptr abilityInfo = std::make_shared(); + AbilityType type = AbilityType::PAGE; + abilityInfo->type = type; + std::shared_ptr application = nullptr; + std::shared_ptr handler = nullptr; + sptr token = nullptr; + ability_->Init(abilityInfo, application, handler, token); + + Want want; + ability_->OnStart(want); + + AbilityLifecycleExecutor::LifecycleState state = ability_->GetState(); + std::shared_ptr lifeCycle = ability_->GetLifecycle(); + LifeCycle::Event lifeCycleState = lifeCycle->GetLifecycleState(); + + EXPECT_EQ(AbilityLifecycleExecutor::LifecycleState::INACTIVE, state); + EXPECT_EQ(LifeCycle::Event::ON_START, lifeCycleState); + + GTEST_LOG_(INFO) << "AaFwk_Ability_OnStart_0100 end"; +} + +/** + * @tc.number: AaFwk_Ability_OnStart_0200 + * @tc.name: OnStart + * @tc.desc: Test the OnStart exception. + */ +HWTEST_F(AbilityBaseTest, AaFwk_Ability_OnStart_0200, Function | MediumTest | Level3) +{ + GTEST_LOG_(INFO) << "AaFwk_Ability_OnStart_0200 start"; + + Want want; + ability_->OnStart(want); + AbilityLifecycleExecutor::LifecycleState state = ability_->GetState(); + std::shared_ptr lifeCycle = ability_->GetLifecycle(); + + EXPECT_EQ(AbilityLifecycleExecutor::LifecycleState::UNINITIALIZED, state); + EXPECT_EQ(nullptr, lifeCycle); + + GTEST_LOG_(INFO) << "AaFwk_Ability_OnStart_0200 end"; +} + +/** + * @tc.number: AaFwk_Ability_OnStop_0100 + * @tc.name: OnStop + * @tc.desc: Test whether onstop is called normally and verify whether the members are correct. + */ +HWTEST_F(AbilityBaseTest, AaFwk_Ability_OnStop_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_Ability_OnStop_0100 start"; + + std::shared_ptr abilityInfo = std::make_shared(); + AbilityType type = AbilityType::PAGE; + abilityInfo->type = type; + std::shared_ptr application = nullptr; + std::shared_ptr handler = nullptr; + sptr token = nullptr; + ability_->Init(abilityInfo, application, handler, token); + + ability_->OnStop(); + + AbilityLifecycleExecutor::LifecycleState state = ability_->GetState(); + std::shared_ptr lifeCycle = ability_->GetLifecycle(); + LifeCycle::Event lifeCycleState = lifeCycle->GetLifecycleState(); + + EXPECT_EQ(AbilityLifecycleExecutor::LifecycleState::INITIAL, state); + EXPECT_EQ(LifeCycle::Event::ON_STOP, lifeCycleState); + + GTEST_LOG_(INFO) << "AaFwk_Ability_OnStop_0100 end"; +} + +/** + * @tc.number: AaFwk_Ability_OnStop_0200 + * @tc.name: OnStop + * @tc.desc: Test the OnStop exception. + */ +HWTEST_F(AbilityBaseTest, AaFwk_Ability_OnStop_0200, Function | MediumTest | Level3) +{ + GTEST_LOG_(INFO) << "AaFwk_Ability_OnStop_0200 start"; + + ability_->OnStop(); + + AbilityLifecycleExecutor::LifecycleState state = ability_->GetState(); + std::shared_ptr lifeCycle = ability_->GetLifecycle(); + + EXPECT_EQ(AbilityLifecycleExecutor::LifecycleState::UNINITIALIZED, state); + EXPECT_EQ(nullptr, lifeCycle); + + GTEST_LOG_(INFO) << "AaFwk_Ability_OnStop_0200 end"; +} + +/** + * @tc.number: AaFwk_Ability_OnActive_0100 + * @tc.name: OnActive + * @tc.desc: Test whether onactive is called normally and verify whether the member is correct. + */ +HWTEST_F(AbilityBaseTest, AaFwk_Ability_OnActive_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_Ability_OnActive_0100 start"; + + std::shared_ptr abilityInfo = std::make_shared(); + AbilityType type = AbilityType::PAGE; + abilityInfo->type = type; + std::shared_ptr application = nullptr; + std::shared_ptr handler = nullptr; + sptr token = nullptr; + ability_->Init(abilityInfo, application, handler, token); + + ability_->OnActive(); + + AbilityLifecycleExecutor::LifecycleState state = ability_->GetState(); + std::shared_ptr lifeCycle = ability_->GetLifecycle(); + LifeCycle::Event lifeCycleState = lifeCycle->GetLifecycleState(); + + EXPECT_EQ(AbilityLifecycleExecutor::LifecycleState::ACTIVE, state); + EXPECT_EQ(LifeCycle::Event::ON_ACTIVE, lifeCycleState); + + GTEST_LOG_(INFO) << "AaFwk_Ability_OnActive_0100 end"; +} + +/** + * @tc.number: AaFwk_Ability_OnActive_0200 + * @tc.name: OnActive + * @tc.desc: Test the OnActive exception. + */ +HWTEST_F(AbilityBaseTest, AaFwk_Ability_OnActive_0200, Function | MediumTest | Level3) +{ + GTEST_LOG_(INFO) << "AaFwk_Ability_OnActive_0200 start"; + + ability_->OnActive(); + + AbilityLifecycleExecutor::LifecycleState state = ability_->GetState(); + std::shared_ptr lifeCycle = ability_->GetLifecycle(); + + EXPECT_EQ(AbilityLifecycleExecutor::LifecycleState::UNINITIALIZED, state); + EXPECT_EQ(nullptr, lifeCycle); + + GTEST_LOG_(INFO) << "AaFwk_Ability_OnActive_0200 end"; +} + +/** + * @tc.number: AaFwk_Ability_OnInactive_0100 + * @tc.name: OnInactive + * @tc.desc: Test whether oninactive is called normally and verify whether the member is correct. + */ +HWTEST_F(AbilityBaseTest, AaFwk_Ability_OnInactive_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_Ability_OnInactive_0100 start"; + + std::shared_ptr abilityInfo = std::make_shared(); + AbilityType type = AbilityType::PAGE; + abilityInfo->type = type; + std::shared_ptr application = nullptr; + std::shared_ptr handler = nullptr; + sptr token = nullptr; + ability_->Init(abilityInfo, application, handler, token); + + ability_->OnInactive(); + + AbilityLifecycleExecutor::LifecycleState state = ability_->GetState(); + std::shared_ptr lifeCycle = ability_->GetLifecycle(); + LifeCycle::Event lifeCycleState = lifeCycle->GetLifecycleState(); + + EXPECT_EQ(AbilityLifecycleExecutor::LifecycleState::INACTIVE, state); + EXPECT_EQ(LifeCycle::Event::ON_INACTIVE, lifeCycleState); + + GTEST_LOG_(INFO) << "AaFwk_Ability_OnInactive_0100 end"; +} + +/** + * @tc.number: AaFwk_Ability_OnInactive_0200 + * @tc.name: OnInactive + * @tc.desc: Test the OnInactive exception. + */ +HWTEST_F(AbilityBaseTest, AaFwk_Ability_OnInactive_0200, Function | MediumTest | Level3) +{ + GTEST_LOG_(INFO) << "AaFwk_Ability_OnInactive_0200 start"; + + ability_->OnInactive(); + + AbilityLifecycleExecutor::LifecycleState state = ability_->GetState(); + std::shared_ptr lifeCycle = ability_->GetLifecycle(); + + EXPECT_EQ(AbilityLifecycleExecutor::LifecycleState::UNINITIALIZED, state); + EXPECT_EQ(nullptr, lifeCycle); + + GTEST_LOG_(INFO) << "AaFwk_Ability_OnInactive_0200 end"; +} + +/** + * @tc.number: AaFwk_Ability_OnForeground_0100 + * @tc.name: OnForeground + * @tc.desc: Test whether onforegroup is called normally, and verify whether the member is correct. + */ +HWTEST_F(AbilityBaseTest, AaFwk_Ability_OnForeground_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_Ability_OnForeground_0100 start"; + + std::shared_ptr abilityInfo = std::make_shared(); + AbilityType type = AbilityType::PAGE; + abilityInfo->type = type; + std::shared_ptr application = nullptr; + std::shared_ptr handler = nullptr; + sptr token = nullptr; + ability_->Init(abilityInfo, application, handler, token); + + Want want; + ability_->OnForeground(want); + + AbilityLifecycleExecutor::LifecycleState state = ability_->GetState(); + std::shared_ptr lifeCycle = ability_->GetLifecycle(); + LifeCycle::Event lifeCycleState = lifeCycle->GetLifecycleState(); + + EXPECT_EQ(AbilityLifecycleExecutor::LifecycleState::INACTIVE, state); + EXPECT_EQ(LifeCycle::Event::ON_FOREGROUND, lifeCycleState); + + GTEST_LOG_(INFO) << "AaFwk_Ability_OnForeground_0100 end"; +} + +/** + * @tc.number: AaFwk_Ability_OnForeground_0200 + * @tc.name: OnForeground + * @tc.desc: Test the OnInactive exception. + */ +HWTEST_F(AbilityBaseTest, AaFwk_Ability_OnForeground_0200, Function | MediumTest | Level3) +{ + GTEST_LOG_(INFO) << "AaFwk_Ability_OnForeground_0200 start"; + + Want want; + ability_->OnForeground(want); + + AbilityLifecycleExecutor::LifecycleState state = ability_->GetState(); + std::shared_ptr lifeCycle = ability_->GetLifecycle(); + + EXPECT_EQ(AbilityLifecycleExecutor::LifecycleState::UNINITIALIZED, state); + EXPECT_EQ(nullptr, lifeCycle); + + GTEST_LOG_(INFO) << "AaFwk_Ability_OnForeground_0200 end"; +} + +/** + * @tc.number: AaFwk_Ability_OnBackground_0100 + * @tc.name: OnBackground + * @tc.desc: Test whether onbackground is called normally and verify whether the members are correct. + */ +HWTEST_F(AbilityBaseTest, AaFwk_Ability_OnBackground_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_Ability_OnBackground_0100 start"; + + std::shared_ptr abilityInfo = std::make_shared(); + AbilityType type = AbilityType::PAGE; + abilityInfo->type = type; + std::shared_ptr application = nullptr; + std::shared_ptr handler = nullptr; + sptr token = nullptr; + ability_->Init(abilityInfo, application, handler, token); + + ability_->OnBackground(); + + AbilityLifecycleExecutor::LifecycleState state = ability_->GetState(); + std::shared_ptr lifeCycle = ability_->GetLifecycle(); + LifeCycle::Event lifeCycleState = lifeCycle->GetLifecycleState(); + + EXPECT_EQ(AbilityLifecycleExecutor::LifecycleState::BACKGROUND, state); + EXPECT_EQ(LifeCycle::Event::ON_BACKGROUND, lifeCycleState); + + GTEST_LOG_(INFO) << "AaFwk_Ability_OnBackground_0100 end"; +} + +/** + * @tc.number: AaFwk_Ability_OnBackground_0200 + * @tc.name: OnBackground + * @tc.desc: Test the OnBackground exception. + */ +HWTEST_F(AbilityBaseTest, AaFwk_Ability_OnBackground_0200, Function | MediumTest | Level3) +{ + GTEST_LOG_(INFO) << "AaFwk_Ability_OnBackground_0200 start"; + + ability_->OnBackground(); + + AbilityLifecycleExecutor::LifecycleState state = ability_->GetState(); + std::shared_ptr lifeCycle = ability_->GetLifecycle(); + + EXPECT_EQ(AbilityLifecycleExecutor::LifecycleState::UNINITIALIZED, state); + EXPECT_EQ(nullptr, lifeCycle); + + GTEST_LOG_(INFO) << "AaFwk_Ability_OnBackground_0200 end"; +} + +/** + * @tc.number: AaFwk_Ability_OnConnect_0100 + * @tc.name: OnConnect + * @tc.desc: Test whether onconnect is called normally and verify whether the members are correct. + */ +HWTEST_F(AbilityBaseTest, AaFwk_Ability_OnConnect_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_Ability_OnConnect_0100 start"; + + std::shared_ptr abilityInfo = std::make_shared(); + AbilityType type = AbilityType::PAGE; + abilityInfo->type = type; + std::shared_ptr application = nullptr; + std::shared_ptr handler = nullptr; + sptr token = nullptr; + ability_->Init(abilityInfo, application, handler, token); + + Want want; + ability_->OnConnect(want); + + AbilityLifecycleExecutor::LifecycleState state = ability_->GetState(); + + EXPECT_EQ(AbilityLifecycleExecutor::LifecycleState::ACTIVE, state); + + GTEST_LOG_(INFO) << "AaFwk_Ability_OnConnect_0100 end"; +} + +/** + * @tc.number: AaFwk_Ability_OnCommond_0100 + * @tc.name: OnCommand + * @tc.desc: Test whether oncommand is called normally and verify whether the members are correct. + */ +HWTEST_F(AbilityBaseTest, AaFwk_Ability_OnCommond_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_Ability_OnCommond_0100 start"; + + std::shared_ptr abilityInfo = std::make_shared(); + AbilityType type = AbilityType::PAGE; + abilityInfo->type = type; + std::shared_ptr application = nullptr; + std::shared_ptr handler = nullptr; + sptr token = nullptr; + ability_->Init(abilityInfo, application, handler, token); + + Want want; + ability_->OnCommand(want, false, 0); + + AbilityLifecycleExecutor::LifecycleState state = ability_->GetState(); + + EXPECT_EQ(AbilityLifecycleExecutor::LifecycleState::ACTIVE, state); + + GTEST_LOG_(INFO) << "AaFwk_Ability_OnCommond_0100 end"; +} + +/** + * @tc.number: AaFwk_Ability_OnDisconnect_0100 + * @tc.name: OnDisconnect + * @tc.desc: Test whether ondisconnect is called normally. + */ +HWTEST_F(AbilityBaseTest, AaFwk_Ability_OnDisconnect_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_Ability_OnDisconnect_0100 start"; + + Want want; + ability_->OnDisconnect(want); + + GTEST_LOG_(INFO) << "AaFwk_Ability_OnDisconnect_0100 end"; +} + +/** + * @tc.number: AaFwk_Ability_StartAbilitySetting_0100 + * @tc.name: StartAbility + * @tc.desc: Test whether startability is called normally. + */ +HWTEST_F(AbilityBaseTest, AaFwk_Ability_StartAbilitySetting_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_Ability_StartAbilitySetting_0100 start"; + + Want want; + std::shared_ptr setting = AbilityStartSetting::GetEmptySetting(); + + ability_->StartAbility(want, *setting.get()); + + GTEST_LOG_(INFO) << "AaFwk_Ability_StartAbilitySetting_0100 end"; +} + +/** + * @tc.number: AaFwk_Ability_StartAbilitySetting_0200 + * @tc.name: StartAbility + * @tc.desc: Test startability exception status. + */ +HWTEST_F(AbilityBaseTest, AaFwk_Ability_StartAbilitySetting_0200, Function | MediumTest | Level3) +{ + GTEST_LOG_(INFO) << "AaFwk_Ability_StartAbilitySetting_0200 start"; + + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->type = AbilityType::PAGE; + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + + ability_->Init(abilityInfo, nullptr, handler, nullptr); + Want want; + std::shared_ptr setting = AbilityStartSetting::GetEmptySetting(); + ability_->StartAbility(want, *setting.get()); + + GTEST_LOG_(INFO) << "AaFwk_Ability_StartAbilitySetting_0200 end"; +} + +/** + * @tc.number: AaFwk_Ability_PostTask_0100 + * @tc.name: PostTask + * @tc.desc: Test whether posttask is called normally. + */ +HWTEST_F(AbilityBaseTest, AaFwk_Ability_PostTask_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_Ability_PostTask_0100 start"; + + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->type = AbilityType::PAGE; + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + + ability_->Init(abilityInfo, nullptr, handler, nullptr); + auto task = []() { GTEST_LOG_(INFO) << "AaFwk_Ability_PostTask_001 task called"; }; + ability_->PostTask(task, 1000); + + GTEST_LOG_(INFO) << "AaFwk_Ability_PostTask_0100 end"; +} +} // namespace AppExecFwk +} // namespace OHOS diff --git a/tools/frameworks/kits/ability/native/test/unittest/ability_thread_dataability_test.cpp b/tools/frameworks/kits/ability/native/test/unittest/ability_thread_dataability_test.cpp new file mode 100644 index 00000000000..14e5e059ef0 --- /dev/null +++ b/tools/frameworks/kits/ability/native/test/unittest/ability_thread_dataability_test.cpp @@ -0,0 +1,410 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include "ability_thread.h" +#include "ability_state.h" +#include "ability_loader.h" +#include "app_log_wrapper.h" +#include "ability_impl_factory.h" +#include "ability_impl.h" +#include "ability.h" +#include "context_deal.h" +#include "mock_page_ability.h" +#include "mock_ability_token.h" +#include "mock_ability_lifecycle_callbacks.h" +#include "mock_ability_impl.h" +#include "mock_ability_thread.h" +#include "mock_data_ability.h" +#include "ohos_application.h" +#include "page_ability_impl.h" +#include "uri.h" + +#include "abs_shared_result_set.h" +#include "data_ability_predicates.h" +#include "values_bucket.h" + +namespace OHOS { +namespace AppExecFwk { +using namespace testing::ext; +using namespace OHOS; +using namespace OHOS::AppExecFwk; + +REGISTER_AA(MockDataAbility) +REGISTER_AA(MockPageAbility) + +class AbilityThreadTest : public testing::Test { +public: + AbilityThreadTest() : abilitythread_(nullptr) + {} + ~AbilityThreadTest() + { + abilitythread_ = nullptr; + } + AbilityThread *abilitythread_; + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void AbilityThreadTest::SetUpTestCase(void) +{} + +void AbilityThreadTest::TearDownTestCase(void) +{} + +void AbilityThreadTest::SetUp(void) +{ + GTEST_LOG_(INFO) << "AbilityThreadTest SetUp"; +} + +void AbilityThreadTest::TearDown(void) +{ + GTEST_LOG_(INFO) << "AbilityThreadTest TearDown"; +} + +/** + * @tc.number: AaFwk_AbilityThread_Query_0100 + * @tc.name: Query + * @tc.desc: Simulate successful test cases. + */ +HWTEST_F(AbilityThreadTest, AaFwk_AbilityThread_Query_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityThread_Query_0100 start"; + + AbilityThread *abilitythread = new (std::nothrow) AbilityThread(); + EXPECT_NE(abilitythread, nullptr); + if (abilitythread != nullptr) { + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "MockDataAbility"; + abilityInfo->type = AbilityType::DATA; + abilityInfo->isNativeAbility = true; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + EXPECT_NE(token, nullptr); + if (token != nullptr) { + std::shared_ptr application = std::make_shared(); + std::shared_ptr abilityRecord = + std::make_shared(abilityInfo, token); + std::shared_ptr mainRunner = EventRunner::Create(abilityInfo->name); + abilitythread->Attach(application, abilityRecord, mainRunner); + std::shared_ptr mockdataability = std::make_shared(); + + Uri uri("dataabilitytest:///com.example.myapplication5.DataAbilityTest"); + std::vector columns; + columns.push_back("string1"); + + NativeRdb::DataAbilityPredicates predicates("test"); + std::shared_ptr resultSet = abilitythread->Query(uri, columns, predicates); + EXPECT_TRUE(resultSet != nullptr); + } + } + GTEST_LOG_(INFO) << "AaFwk_AbilityThread_Query_0100 end"; +} + +/** + * @tc.number: AaFwk_AbilityThread_Query_0200 + * @tc.name: Query + * @tc.desc: Validate when normally entering a string. + */ +HWTEST_F(AbilityThreadTest, AaFwk_AbilityThread_Query_0200, Function | MediumTest | Level1) +{ + + GTEST_LOG_(INFO) << "AaFwk_AbilityThread_Query_0200 start"; + AbilityThread *abilitythread = new AbilityThread(); + + std::shared_ptr abilityimpl = std::make_shared(); + + int valuetest = -1; + int value = 0; + Uri uri("\nullptr"); + std::vector columns; + columns.push_back("string1"); + NativeRdb::DataAbilityPredicates predicates("test"); + + abilitythread->Query(uri, columns, predicates); + valuetest = abilityimpl->GetCurrentState(); + + EXPECT_EQ(value, valuetest); + + GTEST_LOG_(INFO) << "AaFwk_AbilityThread_Query_0200 end"; +} + +/** + * @tc.number: AaFwk_AbilityThread_GetFileTypes_0100 + * @tc.name: GetFileTypes + * @tc.desc: Simulate successful test cases. + */ +HWTEST_F(AbilityThreadTest, AaFwk_AbilityThread_GetFileTypes_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityThread_GetFileTypes_0100 start"; + + AbilityThread *abilitythread = new (std::nothrow) AbilityThread(); + EXPECT_NE(abilitythread, nullptr); + if (abilitythread != nullptr) { + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "MockDataAbility"; + abilityInfo->type = AbilityType::DATA; + abilityInfo->isNativeAbility = true; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + EXPECT_NE(token, nullptr); + if (token != nullptr) { + std::shared_ptr application = std::make_shared(); + std::shared_ptr abilityRecord = + std::make_shared(abilityInfo, token); + std::shared_ptr mainRunner = EventRunner::Create(abilityInfo->name); + abilitythread->Attach(application, abilityRecord, mainRunner); + std::shared_ptr mockdataability = std::make_shared(); + + Uri uri("dataabilitytest://com.example.myapplication5.DataAbilityTest"); + std::string mimeTypeFilter("nullptr"); + std::vector types; + + types = abilitythread->GetFileTypes(uri, mimeTypeFilter); + + EXPECT_EQ((int)types.size(), 3); + if (types.size() == 3) { + EXPECT_STREQ("Type1", types.at(0).c_str()); + EXPECT_STREQ("Type2", types.at(1).c_str()); + EXPECT_STREQ("Type3", types.at(2).c_str()); + } + } + } + GTEST_LOG_(INFO) << "AaFwk_AbilityThread_GetFileTypes_0100 end"; +} + +/** + * @tc.number: AaFwk_AbilityThread_GetFileTypes_0200 + * @tc.name: GetFileTypes + * @tc.desc: Simulate successful test cases. + */ +HWTEST_F(AbilityThreadTest, AaFwk_AbilityThread_GetFileTypes_0200, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityThread_GetFileTypes_0200 start"; + + AbilityThread *abilitythread = new (std::nothrow) AbilityThread(); + EXPECT_NE(abilitythread, nullptr); + if (abilitythread != nullptr) { + Uri uri("\nullptr"); + std::string mimeTypeFilter("nullptr"); + std::vector types; + int number = 0; + int types_size; + + types = abilitythread->GetFileTypes(uri, mimeTypeFilter); + + types_size = types.size(); + EXPECT_EQ(number, types_size); + } + GTEST_LOG_(INFO) << "AaFwk_AbilityThread_GetFileTypes_0200 end"; +} + +/** + * @tc.number: AaFwk_AbilityThread_OpenFile_0100 + * @tc.name: OpenFile + * @tc.desc: Simulate successful test cases. + */ +HWTEST_F(AbilityThreadTest, AaFwk_AbilityThread_OpenFile_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityThread_OpenFile_0100 start"; + + AbilityThread *abilitythread = new (std::nothrow) AbilityThread(); + EXPECT_NE(abilitythread, nullptr); + if (abilitythread != nullptr) { + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "MockDataAbility"; + abilityInfo->type = AbilityType::DATA; + abilityInfo->isNativeAbility = true; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + EXPECT_NE(token, nullptr); + if (token != nullptr) { + std::shared_ptr application = std::make_shared(); + std::shared_ptr abilityRecord = + std::make_shared(abilityInfo, token); + std::shared_ptr mainRunner = EventRunner::Create(abilityInfo->name); + abilitythread->Attach(application, abilityRecord, mainRunner); + std::shared_ptr mockdataability = std::make_shared(); + + Uri uri("dataabilitytest://com.example.myapplication5.DataAbilityTest"); + std::string mode; + int fd = abilitythread->OpenFile(uri, mode); + + EXPECT_EQ(fd, 11); + sleep(1); + } + } + GTEST_LOG_(INFO) << "AaFwk_AbilityThread_OpenFile_0100 end"; +} + +/** + * @tc.number: AaFwk_AbilityThread_OpenFile_0200 + * @tc.name: OpenFile + * @tc.desc: Validate when normally entering a string. + */ +HWTEST_F(AbilityThreadTest, AaFwk_AbilityThread_OpenFile_0200, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityThread_OpenFile_0200 start"; + + AbilityThread *abilitythread = new (std::nothrow) AbilityThread(); + EXPECT_NE(abilitythread, nullptr); + if (abilitythread != nullptr) { + int fd = -1; + int value; + Uri uri("nullptr"); + std::string mode; + value = abilitythread->OpenFile(uri, mode); + + EXPECT_EQ(fd, value); + } + GTEST_LOG_(INFO) << "AaFwk_AbilityThread_OpenFile_0200 end"; +} + +/** + * @tc.number: AaFwk_AbilityThread_Insert_0100 + * @tc.name: Insert + * @tc.desc: Simulate successful test cases. + */ +HWTEST_F(AbilityThreadTest, AaFwk_AbilityThread_Insert_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityThread_Insert_0100 start"; + + AbilityThread *abilitythread = new (std::nothrow) AbilityThread(); + EXPECT_NE(abilitythread, nullptr); + if (abilitythread != nullptr) { + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "MockDataAbility"; + abilityInfo->type = AbilityType::DATA; + abilityInfo->isNativeAbility = true; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + EXPECT_NE(token, nullptr); + if (token != nullptr) { + std::shared_ptr application = std::make_shared(); + std::shared_ptr abilityRecord = + std::make_shared(abilityInfo, token); + std::shared_ptr mainRunner = EventRunner::Create(abilityInfo->name); + abilitythread->Attach(application, abilityRecord, mainRunner); + std::shared_ptr mockdataability = std::make_shared(); + + Uri uri("dataabilitytest://com.example.myapplication5.DataAbilityTest"); + NativeRdb::ValuesBucket value; + + EXPECT_EQ(22, abilitythread->Insert(uri, value)); + } + } + GTEST_LOG_(INFO) << "AaFwk_AbilityThread_Insert_0100 end"; +} + +/** + * @tc.number: AaFwk_AbilityThread_Insert_0200 + * @tc.name: Insert + * @tc.desc: Validate when normally entering a string. + */ +HWTEST_F(AbilityThreadTest, AaFwk_AbilityThread_Insert_0200, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityThread_Insert_0200 start"; + + AbilityThread *abilitythread = new (std::nothrow) AbilityThread(); + EXPECT_NE(abilitythread, nullptr); + if (abilitythread != nullptr) { + Uri uri("\nullptr"); + int number = -1; + NativeRdb::ValuesBucket value; + + EXPECT_EQ(number, abilitythread->Insert(uri, value)); + } + GTEST_LOG_(INFO) << "AaFwk_AbilityThread_Insert_0200 end"; +} + +/** + * @tc.number: AaFwk_AbilityThread_Update_0100 + * @tc.name: Update + * @tc.desc: Simulate successful test cases. + */ +HWTEST_F(AbilityThreadTest, AaFwk_AbilityThread_Update_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityThread_Update_0100 start"; + + AbilityThread *abilitythread = new (std::nothrow) AbilityThread(); + EXPECT_NE(abilitythread, nullptr); + if (abilitythread != nullptr) { + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "MockDataAbility"; + abilityInfo->type = AbilityType::DATA; + abilityInfo->isNativeAbility = true; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + EXPECT_NE(token, nullptr); + if (token != nullptr) { + std::shared_ptr application = std::make_shared(); + std::shared_ptr abilityRecord = + std::make_shared(abilityInfo, token); + std::shared_ptr mainRunner = EventRunner::Create(abilityInfo->name); + abilitythread->Attach(application, abilityRecord, mainRunner); + std::shared_ptr mockdataability = std::make_shared(); + + Uri uri("dataabilitytest://com.example.myapplication5.DataAbilityTest"); + NativeRdb::ValuesBucket value; + NativeRdb::DataAbilityPredicates predicates("test"); + + EXPECT_EQ(33, abilitythread->Update(uri, value, predicates)); + } + } + GTEST_LOG_(INFO) << "AaFwk_AbilityThread_Update_0100 end"; +} + +/** + * @tc.number: AaFwk_AbilityThread_Update_0200 + * @tc.name: Update + * @tc.desc: Validate when normally entering a string. + */ +HWTEST_F(AbilityThreadTest, AaFwk_AbilityThread_Update_0200, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityThread_Update_0200 start"; + + AbilityThread *abilitythread = new (std::nothrow) AbilityThread(); + EXPECT_NE(abilitythread, nullptr); + if (abilitythread != nullptr) { + Uri uri("\nullptr"); + int number = -1; + NativeRdb::ValuesBucket value; + NativeRdb::DataAbilityPredicates predicates("test"); + + EXPECT_EQ(number, abilitythread->Update(uri, value, predicates)); + } + GTEST_LOG_(INFO) << "AaFwk_AbilityThread_Update_0200 end"; +} + +/** + * @tc.number: AaFwk_AbilityThread_Delete_0100 + * @tc.name: Delete + * @tc.desc: Validate when normally entering a string. + */ +HWTEST_F(AbilityThreadTest, AaFwk_AbilityThread_Delete_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityThread_Delete_0100 start"; + + AbilityThread *abilitythread = new (std::nothrow) AbilityThread(); + EXPECT_NE(abilitythread, nullptr); + if (abilitythread != nullptr) { + Uri uri("\nullptr"); + int number = -1; + NativeRdb::DataAbilityPredicates predicates("test"); + + EXPECT_EQ(number, abilitythread->Delete(uri, predicates)); + } + GTEST_LOG_(INFO) << "AaFwk_AbilityThread_Delete_0100 end"; +} +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/test/unittest/ability_thread_for_ability_on_configuration_update.cpp b/tools/frameworks/kits/ability/native/test/unittest/ability_thread_for_ability_on_configuration_update.cpp new file mode 100644 index 00000000000..ad43df2970b --- /dev/null +++ b/tools/frameworks/kits/ability/native/test/unittest/ability_thread_for_ability_on_configuration_update.cpp @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#include "gtest/gtest.h" +#include "gmock/gmock.h" + +#include "ability_thread.h" +#include "ability.h" +#include "ability_impl.h" + +#include "mock_ability_thread_for_ability_on_configuration_update.h" + +namespace OHOS { +namespace AppExecFwk { +using namespace testing::ext; + +class AbilityThreadTest : public testing::Test { +public: + AbilityThreadTest() : abilitythread_(nullptr) + {} + ~AbilityThreadTest() + { + abilitythread_ = nullptr; + } + AbilityThread *abilitythread_; + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void AbilityThreadTest::SetUpTestCase(void) +{ + AbilityTest::InitInstance(); +} + +void AbilityThreadTest::TearDownTestCase(void) +{ + AbilityTest::UnInitInstance(); +} + +void AbilityThreadTest::SetUp(void) +{} + +void AbilityThreadTest::TearDown(void) +{} + +AbilityThread::AbilityThread() + : abilityImpl_(nullptr), token_(nullptr), currentAbility_(nullptr), abilityHandler_(nullptr), runner_(nullptr) +{ + abilityImpl_ = std::make_shared(); + abilityHandler_ = std::make_shared(EventRunner::Create("AbilityTest"), this); + + std::shared_ptr application = nullptr; + std::shared_ptr ability = AbilityTest::GetInstance(); + std::shared_ptr contextDeal = nullptr; + abilityImpl_->Init(application, nullptr, ability, abilityHandler_, nullptr, contextDeal); +} + +void AbilityImpl::Init(std::shared_ptr &application, const std::shared_ptr &record, + std::shared_ptr &ability, std::shared_ptr &handler, const sptr &token, + std::shared_ptr &contextDeal) +{ + ability_ = ability; +} + +/** + * @tc.number: AaFwk_AbilityThread_ScheduleUpdateConfiguration_0100 + * @tc.name: ScheduleUpdateConfiguration + * @tc.desc: Simulate successful test cases + */ +HWTEST_F(AbilityThreadTest, AaFwk_AbilityThread_ScheduleUpdateConfiguration_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityThread_ScheduleUpdateConfiguration_0100 start"; + std::shared_ptr abilityThread = std::make_shared(); + + DummyConfiguration config; + uint32_t code = OHOS::AAFwk::IAbilityScheduler::SCHEDULE_UPDATE_CONFIGURATION; + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(AbilityThread::GetDescriptor())) { + EXPECT_TRUE(false); + GTEST_LOG_(ERROR) << "---------- data.WriteInterfaceToken retval is false"; + return; + } + + if (!data.WriteParcelable(&config)) { + EXPECT_TRUE(false); + GTEST_LOG_(ERROR) << "---------- data.WriteParcelable retval is false"; + return; + } + + if (AbilityTest::GetInstance() == nullptr) { + EXPECT_TRUE(false); + GTEST_LOG_(ERROR) << "---------- AbilityTest::GetInstance() is nullptr"; + return; + } + + auto call = [](const Configuration &) { GTEST_LOG_(INFO) << "---------- OnConfigurationUpdated Call Success"; }; + + EXPECT_CALL(*AbilityTest::GetInstance(), OnConfigurationUpdated(testing::_)) + .Times(1) + .WillOnce(testing::Invoke(call)); + + abilityThread->OnRemoteRequest(code, data, reply, option); + + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + + GTEST_LOG_(INFO) << "AaFwk_AbilityThread_ScheduleUpdateConfiguration_0100 end"; +} + +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/test/unittest/ability_thread_test.cpp b/tools/frameworks/kits/ability/native/test/unittest/ability_thread_test.cpp new file mode 100644 index 00000000000..3833720e4d2 --- /dev/null +++ b/tools/frameworks/kits/ability/native/test/unittest/ability_thread_test.cpp @@ -0,0 +1,691 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include "ability_thread.h" +#include "ability_state.h" +#include "ability_loader.h" +#include "app_log_wrapper.h" +#include "ability_impl_factory.h" +#include "ability.h" +#include "ability_impl.h" +#include "context_deal.h" +#include "mock_page_ability.h" +#include "mock_service_ability.h" +#include "mock_ability_token.h" +#include "mock_ability_lifecycle_callbacks.h" +#include "mock_ability_impl.h" +#include "mock_ability_thread.h" +#include "mock_data_ability.h" +#include "ohos_application.h" +#include "page_ability_impl.h" +#include "uri.h" + +namespace OHOS { +namespace AppExecFwk { +using namespace testing::ext; +using namespace OHOS; +using namespace OHOS::AppExecFwk; + +REGISTER_AA(MockDataAbility) +REGISTER_AA(MockPageAbility) +REGISTER_AA(MockServiceAbility) + +class AbilityThreadTest : public testing::Test { +public: + AbilityThreadTest() : abilitythread_(nullptr) + {} + ~AbilityThreadTest() + { + abilitythread_ = nullptr; + } + AbilityThread *abilitythread_; + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void AbilityThreadTest::SetUpTestCase(void) +{} + +void AbilityThreadTest::TearDownTestCase(void) +{} + +void AbilityThreadTest::SetUp(void) +{ + GTEST_LOG_(INFO) << "AbilityThreadTest SetUp"; +} + +void AbilityThreadTest::TearDown(void) +{ + GTEST_LOG_(INFO) << "AbilityThreadTest TearDown"; +} + +/** + * @tc.number: AaFwk_AbilityThread_ScheduleSaveAbilityState_0100 + * @tc.name: ScheduleSaveAbilityState + * @tc.desc: Simulate successful test cases + */ +HWTEST_F(AbilityThreadTest, AaFwk_AbilityThread_ScheduleSaveAbilityState_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityThread_ScheduleSaveAbilityState_0100 start"; + + AbilityThread *abilitythread = new (std::nothrow) AbilityThread(); + EXPECT_NE(abilitythread, nullptr); + if (abilitythread != nullptr) { + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "MockPageAbility"; + abilityInfo->type = AbilityType::PAGE; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + EXPECT_NE(token, nullptr); + if (token != nullptr) { + std::shared_ptr application = std::make_shared(); + std::shared_ptr abilityRecord = + std::make_shared(abilityInfo, token); + std::shared_ptr mainRunner = EventRunner::Create(abilityInfo->name); + abilitythread->Attach(application, abilityRecord, mainRunner); + + PacMap state; + abilitythread->ScheduleSaveAbilityState(state); + + sleep(1); + } + } + GTEST_LOG_(INFO) << "AaFwk_AbilityThread_ScheduleSaveAbilityState_0100 end"; +} + +/** + * @tc.number: AaFwk_AbilityThread_ScheduleSaveAbilityState_0200 + * @tc.name: ScheduleSaveAbilityState + * @tc.desc: Validate when normally entering a string + */ +HWTEST_F(AbilityThreadTest, AaFwk_AbilityThread_ScheduleSaveAbilityState_0200, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityThread_ScheduleSaveAbilityState_0200 start"; + + AbilityThread *abilitythread = new (std::nothrow) AbilityThread(); + EXPECT_NE(abilitythread, nullptr); + if (abilitythread != nullptr) { + PacMap state; + abilitythread->ScheduleSaveAbilityState(state); + } + GTEST_LOG_(INFO) << "AaFwk_AbilityThread_ScheduleSaveAbilityState_0200 end"; +} + +/** + * @tc.number: AaFwk_AbilityThread_ScheduleRestoreAbilityState_0100 + * @tc.name: ScheduleRestoreAbilityState + * @tc.desc: Simulate successful test cases + */ +HWTEST_F(AbilityThreadTest, AaFwk_AbilityThread_ScheduleRestoreAbilityState_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityThread_ScheduleRestoreAbilityState_0100 start"; + + AbilityThread *abilitythread = new (std::nothrow) AbilityThread(); + EXPECT_NE(abilitythread, nullptr); + if (abilitythread != nullptr) { + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "MockPageAbility"; + abilityInfo->type = AbilityType::PAGE; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + EXPECT_NE(token, nullptr); + if (token != nullptr) { + std::shared_ptr application = std::make_shared(); + std::shared_ptr abilityRecord = + std::make_shared(abilityInfo, token); + std::shared_ptr mainRunner = EventRunner::Create(abilityInfo->name); + abilitythread->Attach(application, abilityRecord, mainRunner); + PacMap state; + + abilitythread->ScheduleRestoreAbilityState(state); + + sleep(1); + } + } + GTEST_LOG_(INFO) << "AaFwk_AbilityThread_ScheduleRestoreAbilityState_0100 end"; +} + +/** + * @tc.number: AaFwk_AbilityThread_ScheduleRestoreAbilityState_0200 + * @tc.name: ScheduleRestoreAbilityState + * @tc.desc: Validate when normally entering a string + */ +HWTEST_F(AbilityThreadTest, AaFwk_AbilityThread_ScheduleRestoreAbilityState_0200, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityThread_ScheduleRestoreAbilityState_0200 start"; + + AbilityThread *abilitythread = new (std::nothrow) AbilityThread(); + EXPECT_NE(abilitythread, nullptr); + if (abilitythread != nullptr) { + PacMap state; + abilitythread->ScheduleSaveAbilityState(state); + } + GTEST_LOG_(INFO) << "AaFwk_AbilityThread_ScheduleRestoreAbilityState_0200 end"; +} + +/** + * @tc.number: AaFwk_AbilityThread_Attach_3_Param_0100 + * @tc.name: Attach + * @tc.desc: Simulate successful test cases + */ +HWTEST_F(AbilityThreadTest, AaFwk_AbilityThread_Attach_3_Param_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityThread_Attach_3_Param_0100 start"; + AbilityThread *abilitythread = new (std::nothrow) AbilityThread(); + EXPECT_NE(abilitythread, nullptr); + if (abilitythread != nullptr) { + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "MockPageAbility"; + abilityInfo->type = AbilityType::PAGE; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + EXPECT_NE(token, nullptr); + if (token != nullptr) { + std::shared_ptr application = std::make_shared(); + std::shared_ptr abilityRecord = + std::make_shared(abilityInfo, token); + std::shared_ptr mainRunner = EventRunner::Create(abilityInfo->name); + abilitythread->Attach(application, abilityRecord, mainRunner); + sleep(1); + } + } + GTEST_LOG_(INFO) << "AaFwk_AbilityThread_Attach_3_Param_0100 end"; +} + +/** + * @tc.number: AaFwk_AbilityThread_Attach_3_Param_0200 + * @tc.name: Attach + * @tc.desc: Simulate successful test cases + */ +HWTEST_F(AbilityThreadTest, AaFwk_AbilityThread_Attach_3_Param_0200, Function | MediumTest | Level3) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityThread_Attach_3_Param_0200 start"; + AbilityThread *abilitythread = new (std::nothrow) AbilityThread(); + EXPECT_NE(abilitythread, nullptr); + if (abilitythread != nullptr) { + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "MockPageAbility"; + abilityInfo->type = AbilityType::PAGE; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + EXPECT_NE(token, nullptr); + if (token != nullptr) { + std::shared_ptr application = nullptr; + std::shared_ptr abilityRecord = + std::make_shared(abilityInfo, token); + std::shared_ptr mainRunner = EventRunner::Create(abilityInfo->name); + abilitythread->Attach(application, abilityRecord, mainRunner); + + sleep(1); + } + } + GTEST_LOG_(INFO) << "AaFwk_AbilityThread_Attach_3_Param_0200 end"; +} + +/** + * @tc.number: AaFwk_AbilityThread_Attach_2_Param_0100 + * @tc.name: Attach + * @tc.desc: Simulate successful test cases + */ +HWTEST_F(AbilityThreadTest, AaFwk_AbilityThread_Attach_2_Param_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityThread_Attach_2_Param_0100 start"; + AbilityThread *abilitythread = new (std::nothrow) AbilityThread(); + EXPECT_NE(abilitythread, nullptr); + if (abilitythread != nullptr) { + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "MockPageAbility"; + abilityInfo->type = AbilityType::PAGE; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + EXPECT_NE(token, nullptr); + if (token != nullptr) { + std::shared_ptr application = std::make_shared(); + std::shared_ptr abilityRecord = + std::make_shared(abilityInfo, token); + abilitythread->Attach(application, abilityRecord); + + sleep(1); + } + } + GTEST_LOG_(INFO) << "AaFwk_AbilityThread_Attach_2_Param_0100 end"; +} + +/** + * @tc.number: AaFwk_AbilityThread_Attach_2_Param_0200 + * @tc.name: Attach + * @tc.desc: Simulate successful test cases + */ +HWTEST_F(AbilityThreadTest, AaFwk_AbilityThread_Attach_2_Param_0200, Function | MediumTest | Level3) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityThread_Attach_2_Param_0200 start"; + AbilityThread *abilitythread = new (std::nothrow) AbilityThread(); + EXPECT_NE(abilitythread, nullptr); + if (abilitythread != nullptr) { + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "MockPageAbility"; + abilityInfo->type = AbilityType::PAGE; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + EXPECT_NE(token, nullptr); + if (token != nullptr) { + std::shared_ptr application = nullptr; + std::shared_ptr abilityRecord = + std::make_shared(abilityInfo, token); + std::shared_ptr mainRunner = EventRunner::Create(abilityInfo->name); + + abilitythread->Attach(application, abilityRecord); + + sleep(1); + } + } + GTEST_LOG_(INFO) << "AaFwk_AbilityThread_Attach_2_Param_0200 end"; +} + +/** + * @tc.number: AaFwk_AbilityThread_ScheduleAbilityTransaction_0100 + * @tc.name: ScheduleAbilityTransaction + * @tc.desc: Simulate successful test cases + */ +HWTEST_F(AbilityThreadTest, AaFwk_AbilityThread_ScheduleAbilityTransaction_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityThread_ScheduleAbilityTransaction_0100 start"; + + AbilityThread *abilitythread = new (std::nothrow) AbilityThread(); + EXPECT_NE(abilitythread, nullptr); + if (abilitythread != nullptr) { + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "MockPageAbility"; + abilityInfo->type = AbilityType::PAGE; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + EXPECT_NE(token, nullptr); + if (token != nullptr) { + std::shared_ptr application = std::make_shared(); + std::shared_ptr abilityRecord = + std::make_shared(abilityInfo, token); + std::shared_ptr mainRunner = EventRunner::Create(abilityInfo->name); + abilitythread->Attach(application, abilityRecord, mainRunner); + + Want want; + LifeCycleStateInfo lifeCycleStateInfo; + abilitythread->ScheduleAbilityTransaction(want, lifeCycleStateInfo); + + sleep(1); + } + } + GTEST_LOG_(INFO) << "AaFwk_AbilityThread_ScheduleAbilityTransaction_0100 end"; +} + +/** + * @tc.number: AaFwk_AbilityThread_ScheduleAbilityTransaction_0200 + * @tc.name: ScheduleAbilityTransaction + * @tc.desc: Validate when normally entering a string + */ +HWTEST_F(AbilityThreadTest, AaFwk_AbilityThread_ScheduleAbilityTransaction_0200, Function | MediumTest | Level3) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityThread_ScheduleAbilityTransaction_0200 start"; + AbilityThread *abilitythread = new (std::nothrow) AbilityThread(); + EXPECT_NE(abilitythread, nullptr); + if (abilitythread != nullptr) { + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "MockPageAbility"; + abilityInfo->type = AbilityType::PAGE; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + EXPECT_NE(token, nullptr); + if (token != nullptr) { + std::shared_ptr application = std::make_shared(); + std::shared_ptr abilityRecord = + std::make_shared(abilityInfo, token); + abilitythread->Attach(application, abilityRecord, nullptr); + + Want want; + LifeCycleStateInfo lifeCycleStateInfo; + abilitythread->ScheduleAbilityTransaction(want, lifeCycleStateInfo); + } + } + GTEST_LOG_(INFO) << "AaFwk_AbilityThread_ScheduleAbilityTransaction_0200 end"; +} + +/** + * @tc.number: AaFwk_AbilityThread_ScheduleConnectAbility_0100 + * @tc.name: ScheduleConnectAbility + * @tc.desc: Simulate successful test cases + */ +HWTEST_F(AbilityThreadTest, AaFwk_AbilityThread_ScheduleConnectAbility_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityThread_ScheduleConnectAbility_0100 start"; + + AbilityThread *abilitythread = new (std::nothrow) AbilityThread(); + EXPECT_NE(abilitythread, nullptr); + if (abilitythread != nullptr) { + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "MockPageAbility"; + abilityInfo->type = AbilityType::PAGE; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + EXPECT_NE(token, nullptr); + if (token != nullptr) { + std::shared_ptr application = std::make_shared(); + std::shared_ptr abilityRecord = + std::make_shared(abilityInfo, token); + std::shared_ptr mainRunner = EventRunner::Create(abilityInfo->name); + abilitythread->Attach(application, abilityRecord, mainRunner); + + Want want; + abilitythread->ScheduleConnectAbility(want); + + sleep(1); + } + } + GTEST_LOG_(INFO) << "AaFwk_AbilityThread_ScheduleConnectAbility_0100 end"; +} + +/** + * @tc.number: AaFwk_AbilityThread_ScheduleConnectAbility_0200 + * @tc.name: ScheduleConnectAbility + * @tc.desc: Validate when normally entering a string + */ +HWTEST_F(AbilityThreadTest, AaFwk_AbilityThread_ScheduleConnectAbility_0200, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityThread_ScheduleConnectAbility_0200 start"; + + AbilityThread *abilitythread = new (std::nothrow) AbilityThread(); + EXPECT_NE(abilitythread, nullptr); + if (abilitythread != nullptr) { + Want want; + abilitythread->ScheduleConnectAbility(want); + } + GTEST_LOG_(INFO) << "AaFwk_AbilityThread_ScheduleConnectAbility_0200 end"; +} + +/** + * @tc.number: AaFwk_AbilityThread_ScheduleDisconnectAbility_0100 + * @tc.name: ScheduleDisconnectAbility + * @tc.desc: Simulate successful test cases + */ +HWTEST_F(AbilityThreadTest, AaFwk_AbilityThread_ScheduleDisconnectAbility_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityThread_ScheduleDisconnectAbility_0100 start"; + + AbilityThread *abilitythread = new (std::nothrow) AbilityThread(); + EXPECT_NE(abilitythread, nullptr); + if (abilitythread != nullptr) { + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "MockPageAbility"; + abilityInfo->type = AbilityType::PAGE; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + EXPECT_NE(token, nullptr); + if (token != nullptr) { + std::shared_ptr application = std::make_shared(); + std::shared_ptr abilityRecord = + std::make_shared(abilityInfo, token); + std::shared_ptr mainRunner = EventRunner::Create(abilityInfo->name); + abilitythread->Attach(application, abilityRecord, mainRunner); + + Want want; + abilitythread->ScheduleDisconnectAbility(want); + + sleep(1); + } + } + GTEST_LOG_(INFO) << "AaFwk_AbilityThread_ScheduleDisconnectAbility_0100 end"; +} + +/** + * @tc.number: AaFwk_AbilityThread_ScheduleDisconnectAbility_0200 + * @tc.name: ScheduleDisconnectAbility + * @tc.desc: Validate when normally entering a string + */ +HWTEST_F(AbilityThreadTest, AaFwk_AbilityThread_ScheduleDisconnectAbility_0200, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityThread_ScheduleDisconnectAbility_0200 start"; + + AbilityThread *abilitythread = new (std::nothrow) AbilityThread(); + EXPECT_NE(abilitythread, nullptr); + if (abilitythread != nullptr) { + std::shared_ptr abilityimpl = std::make_shared(); + + Want want; + abilitythread->ScheduleDisconnectAbility(want); + } + GTEST_LOG_(INFO) << "AaFwk_AbilityThread_ScheduleDisconnectAbility_0200 end"; +} + +/** + * @tc.number: AaFwk_AbilityThread_ScheduleCommandAbility_0100 + * @tc.name: ScheduleCommandAbility + * @tc.desc: Simulate successful test cases + */ +HWTEST_F(AbilityThreadTest, AaFwk_AbilityThread_ScheduleCommandAbility_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityThread_ScheduleCommandAbility_0100 start"; + + AbilityThread *abilitythread = new (std::nothrow) AbilityThread(); + EXPECT_NE(abilitythread, nullptr); + if (abilitythread != nullptr) { + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "MockServiceAbility"; + abilityInfo->type = AbilityType::SERVICE; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + EXPECT_NE(token, nullptr); + if (token != nullptr) { + std::shared_ptr application = std::make_shared(); + std::shared_ptr abilityRecord = + std::make_shared(abilityInfo, token); + std::shared_ptr mainRunner = EventRunner::Create(abilityInfo->name); + std::shared_ptr abilityimpl = std::make_shared(); + abilitythread->Attach(application, abilityRecord, mainRunner); + + Want want; + bool restart = true; + int startId = 0; + + abilitythread->ScheduleCommandAbility(want, restart, startId); + + sleep(1); + } + } + GTEST_LOG_(INFO) << "AaFwk_AbilityThread_ScheduleCommandAbility_0100 end"; +} + +/** + * @tc.number: AaFwk_AbilityThread_ScheduleCommandAbility_0200 + * @tc.name: ScheduleCommandAbility + * @tc.desc: Validate when normally entering a string + */ +HWTEST_F(AbilityThreadTest, AaFwk_AbilityThread_ScheduleCommandAbility_0200, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityThread_ScheduleCommandAbility_0200 start"; + + AbilityThread *abilitythread = new (std::nothrow) AbilityThread(); + EXPECT_NE(abilitythread, nullptr); + if (abilitythread != nullptr) { + Want want; + bool restart = true; + int startId = 0; + + abilitythread->ScheduleCommandAbility(want, restart, startId); + } + GTEST_LOG_(INFO) << "AaFwk_AbilityThread_ScheduleCommandAbility_0200 end"; +} + +/** + * @tc.number: AaFwk_AbilityThread_SendResult_0100 + * @tc.name: SendResult + * @tc.desc: Simulate successful test cases + */ +HWTEST_F(AbilityThreadTest, AaFwk_AbilityThread_SendResult_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityThread_SendResult_0100 start"; + + AbilityThread *abilitythread = new (std::nothrow) AbilityThread(); + EXPECT_NE(abilitythread, nullptr); + if (abilitythread != nullptr) { + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "MockPageAbility"; + abilityInfo->type = AbilityType::PAGE; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + EXPECT_NE(token, nullptr); + if (token != nullptr) { + std::shared_ptr application = std::make_shared(); + std::shared_ptr abilityRecord = + std::make_shared(abilityInfo, token); + std::shared_ptr mainRunner = EventRunner::Create(abilityInfo->name); + std::shared_ptr abilityimpl = std::make_shared(); + abilitythread->Attach(application, abilityRecord, mainRunner); + + int requestCode = 0; + int resultCode = 0; + Want want; + abilitythread->SendResult(requestCode, resultCode, want); + + sleep(1); + } + } + GTEST_LOG_(INFO) << "AaFwk_AbilityThread_SendResult_0100 end"; +} + +/** + * @tc.number: AaFwk_AbilityThread_SendResult_0200 + * @tc.name: SendResult + * @tc.desc: Validate when normally entering a string + */ +HWTEST_F(AbilityThreadTest, AaFwk_AbilityThread_SendResult_0200, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityThread_SendResult_0200 start"; + + AbilityThread *abilitythread = new (std::nothrow) AbilityThread(); + EXPECT_NE(abilitythread, nullptr); + if (abilitythread != nullptr) { + std::shared_ptr abilityimpl = std::make_shared(); + + int requestCode = 0; + int resultCode = 0; + Want want; + abilitythread->SendResult(requestCode, resultCode, want); + } + GTEST_LOG_(INFO) << "AaFwk_AbilityThread_SendResult_0200 end"; +} + +/** + * @tc.number: AaFwk_AbilityThread_AbilityThreadMain_0100 + * @tc.name: AbilityThreadMain + * @tc.desc: Validate when normally entering a string + */ +HWTEST_F(AbilityThreadTest, AaFwk_AbilityThread_AbilityThreadMain_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityThread_AbilityThreadMain_0100 start"; + AbilityThread *abilitythread = new (std::nothrow) AbilityThread(); + EXPECT_NE(abilitythread, nullptr); + if (abilitythread != nullptr) { + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "MockPageAbility"; + abilityInfo->type = AbilityType::PAGE; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + EXPECT_NE(token, nullptr); + if (token != nullptr) { + std::shared_ptr application = std::make_shared(); + std::shared_ptr abilityRecord = + std::make_shared(abilityInfo, token); + std::shared_ptr mainRunner = EventRunner::Create(abilityInfo->name); + + abilitythread->AbilityThreadMain(application, abilityRecord, mainRunner); + } + } + GTEST_LOG_(INFO) << "AaFwk_AbilityThread_AbilityThreadMain_0100 end"; +} + +/** + * @tc.number: AaFwk_AbilityThread_AbilityThreadMain_0200 + * @tc.name: AbilityThreadMain + * @tc.desc: Validate when normally entering a string + */ +HWTEST_F(AbilityThreadTest, AaFwk_AbilityThread_AbilityThreadMain_0200, Function | MediumTest | Level3) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityThread_AbilityThreadMain_0200 start"; + AbilityThread *abilitythread = new (std::nothrow) AbilityThread(); + EXPECT_NE(abilitythread, nullptr); + if (abilitythread != nullptr) { + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "MockPageAbility"; + abilityInfo->type = AbilityType::PAGE; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + EXPECT_NE(token, nullptr); + if (token != nullptr) { + std::shared_ptr application = nullptr; + std::shared_ptr abilityRecord = + std::make_shared(abilityInfo, token); + std::shared_ptr mainRunner = EventRunner::Create(abilityInfo->name); + + abilitythread->AbilityThreadMain(application, abilityRecord, mainRunner); + } + } + GTEST_LOG_(INFO) << "AaFwk_AbilityThread_AbilityThreadMain_0200 end"; +} + +/** + * @tc.number: AaFwk_AbilityThread_AbilityThreadMain_0300 + * @tc.name: AbilityThreadMain + * @tc.desc: Validate when normally entering a string + */ +HWTEST_F(AbilityThreadTest, AaFwk_AbilityThread_AbilityThreadMain_0300, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityThread_AbilityThreadMain_0300 start"; + AbilityThread *abilitythread = new (std::nothrow) AbilityThread(); + EXPECT_NE(abilitythread, nullptr); + if (abilitythread != nullptr) { + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "MockPageAbility"; + abilityInfo->type = AbilityType::PAGE; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + EXPECT_NE(token, nullptr); + if (token != nullptr) { + std::shared_ptr application = std::make_shared(); + std::shared_ptr abilityRecord = + std::make_shared(abilityInfo, token); + std::shared_ptr mainRunner = EventRunner::Create(abilityInfo->name); + + abilitythread->AbilityThreadMain(application, abilityRecord); + } + } + GTEST_LOG_(INFO) << "AaFwk_AbilityThread_AbilityThreadMain_0300 end"; +} + +/** + * @tc.number: AaFwk_AbilityThread_AbilityThreadMain_0400 + * @tc.name: AbilityThreadMain + * @tc.desc: Validate when normally entering a string + */ +HWTEST_F(AbilityThreadTest, AaFwk_AbilityThread_AbilityThreadMain_0400, Function | MediumTest | Level3) +{ + GTEST_LOG_(INFO) << "AaFwk_AbilityThread_AbilityThreadMain_0400 start"; + AbilityThread *abilitythread = new (std::nothrow) AbilityThread(); + EXPECT_NE(abilitythread, nullptr); + if (abilitythread != nullptr) { + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "MockPageAbility"; + abilityInfo->type = AbilityType::PAGE; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + EXPECT_NE(token, nullptr); + if (token != nullptr) { + std::shared_ptr application = nullptr; + std::shared_ptr abilityRecord = + std::make_shared(abilityInfo, token); + std::shared_ptr mainRunner = EventRunner::Create(abilityInfo->name); + + abilitythread->AbilityThreadMain(application, abilityRecord); + } + } + GTEST_LOG_(INFO) << "AaFwk_AbilityThread_AbilityThreadMain_0400 end"; +} +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/test/unittest/data_ability_helper_test.cpp b/tools/frameworks/kits/ability/native/test/unittest/data_ability_helper_test.cpp new file mode 100644 index 00000000000..dd227924b8e --- /dev/null +++ b/tools/frameworks/kits/ability/native/test/unittest/data_ability_helper_test.cpp @@ -0,0 +1,781 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "gtest/gtest.h" + +#include "mock_ability_manager_client_for_data_ability_observer.h" +#include "mock_ability_scheduler_for_observer.h" +#include "mock_ability_manager_client.h" +#include "context.h" +#include "ability_context.h" +#include "data_ability_helper.h" + +#include "abs_shared_result_set.h" +#include "data_ability_predicates.h" +#include "values_bucket.h" + +namespace OHOS { +namespace AppExecFwk { +using namespace testing::ext; + +class DataAbilityHelperForObserverTest : public testing::Test { +public: + DataAbilityHelperForObserverTest() + {} + virtual ~DataAbilityHelperForObserverTest() + {} + + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void DataAbilityHelperForObserverTest::SetUpTestCase(void) +{} + +void DataAbilityHelperForObserverTest::TearDownTestCase(void) +{ + MockAbilitySchedulerTools::GetInstance()->SetMockStatus(false); +} + +void DataAbilityHelperForObserverTest::SetUp(void) +{} + +void DataAbilityHelperForObserverTest::TearDown(void) +{ + MockAbilitySchedulerTools::DestoryInstance(); +} + +/** + * @tc.number: AaFwk_DataAbilityHelper_GetFileTypes_0100 + * @tc.name: GetFileTypes + * @tc.desc: Simulate successful test cases + */ +HWTEST_F(DataAbilityHelperForObserverTest, AaFwk_DataAbilityHelper_GetFileTypes_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_GetFileTypes_0100 start"; + + std::shared_ptr mockTools = MockAbilitySchedulerTools::GetInstance(); + mockTools->SetMockStatus(true); + std::shared_ptr context = std::make_shared(); + std::shared_ptr uri = + std::make_shared("dataability://device_id/com.domainname.dataability.persondata/person/10"); + std::shared_ptr dataAbilityHelper = DataAbilityHelper::Creator(context, uri); + std::string mimeTypeFilter("mimeTypeFiltertest"); + // Test to AbilityThread interface + auto returnGetFileTypes = [&](const Uri &uri, const std::string &mimeTypeFilter) { + std::vector matchedMIMEs; + matchedMIMEs.push_back("test1"); + matchedMIMEs.push_back("test2"); + matchedMIMEs.push_back("test3"); + return matchedMIMEs; + }; + EXPECT_CALL(*mockTools->GetMockAbilityScheduler(), GetFileTypes(testing::_, testing::_)) + .Times(1) + .WillOnce(testing::Invoke(returnGetFileTypes)); + + dataAbilityHelper->GetFileTypes(*uri, mimeTypeFilter); + + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_GetFileTypes_0100 end"; +} + +/** + * @tc.number: AaFwk_DataAbilityHelper_GetFileTypes_0200 + * @tc.name: GetFileTypes + * @tc.desc: Simulate successful test cases + */ +HWTEST_F(DataAbilityHelperForObserverTest, AaFwk_DataAbilityHelper_GetFileTypes_0200, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_GetFileTypes_0200 start"; + + std::shared_ptr mockTools = MockAbilitySchedulerTools::GetInstance(); + mockTools->SetMockStatus(true); + std::shared_ptr context = std::make_shared(); + std::shared_ptr uri = + std::make_shared("dataability://device_id/com.domainname.dataability.persondata/person/10"); + std::shared_ptr dataAbilityHelper = DataAbilityHelper::Creator(context); + std::string mimeTypeFilter("mimeTypeFiltertest"); + // Test to AbilityThread interface + auto returnGetFileTypes = [&](const Uri &uri, const std::string &mimeTypeFilter) { + std::vector matchedMIMEs; + matchedMIMEs.push_back("test1"); + matchedMIMEs.push_back("test2"); + matchedMIMEs.push_back("test3"); + return matchedMIMEs; + }; + EXPECT_CALL(*mockTools->GetMockAbilityScheduler(), GetFileTypes(testing::_, testing::_)) + .Times(1) + .WillOnce(testing::Invoke(returnGetFileTypes)); + + dataAbilityHelper->GetFileTypes(*uri, mimeTypeFilter); + + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_GetFileTypes_0200 end"; +} + +/** + * @tc.number: AaFwk_DataAbilityHelper_OpenFile_0100 + * @tc.name: OpenFile + * @tc.desc: Simulate successful test cases + */ +HWTEST_F(DataAbilityHelperForObserverTest, AaFwk_DataAbilityHelper_OpenFile_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_OpenFile_0100 start"; + + std::shared_ptr mockTools = MockAbilitySchedulerTools::GetInstance(); + mockTools->SetMockStatus(true); + std::shared_ptr context = std::make_shared(); + std::shared_ptr uri = + std::make_shared("dataability://device_id/com.domainname.dataability.persondata/person/10"); + std::shared_ptr dataAbilityHelper = DataAbilityHelper::Creator(context, uri); + std::string mode("modetest"); + // Test to AbilityThread interface + auto returnOpenFile = [&](const Uri &uri, const std::string &mode) { + int fd = 1234; + return fd; + }; + EXPECT_CALL(*mockTools->GetMockAbilityScheduler(), OpenFile(testing::_, testing::_)) + .Times(1) + .WillOnce(testing::Invoke(returnOpenFile)); + + dataAbilityHelper->OpenFile(*uri, mode); + + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_OpenFile_0100 end"; +} + +/** + * @tc.number: AaFwk_DataAbilityHelper_OpenFile_0200 + * @tc.name: OpenFile + * @tc.desc: Simulate successful test cases + */ +HWTEST_F(DataAbilityHelperForObserverTest, AaFwk_DataAbilityHelper_OpenFile_0200, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_OpenFile_0200 start"; + + std::shared_ptr mockTools = MockAbilitySchedulerTools::GetInstance(); + mockTools->SetMockStatus(true); + std::shared_ptr context = std::make_shared(); + std::shared_ptr uri = + std::make_shared("dataability://device_id/com.domainname.dataability.persondata/person/10"); + std::shared_ptr dataAbilityHelper = DataAbilityHelper::Creator(context); + std::string mode("modetest"); + // Test to AbilityThread interface + auto returnOpenFile = [&](const Uri &uri, const std::string &mode) { + int fd = 1234; + return fd; + }; + EXPECT_CALL(*mockTools->GetMockAbilityScheduler(), OpenFile(testing::_, testing::_)) + .Times(1) + .WillOnce(testing::Invoke(returnOpenFile)); + + dataAbilityHelper->OpenFile(*uri, mode); + + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_OpenFile_0200 end"; +} + +/** + * @tc.number: AaFwk_DataAbilityHelper_Insert_0100 + * @tc.name: Insert + * @tc.desc: Simulate successful test cases + */ +HWTEST_F(DataAbilityHelperForObserverTest, AaFwk_DataAbilityHelper_Insert_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_Insert_0100 start"; + + std::shared_ptr mockTools = MockAbilitySchedulerTools::GetInstance(); + mockTools->SetMockStatus(true); + std::shared_ptr context = std::make_shared(); + std::shared_ptr uri = + std::make_shared("dataability://device_id/com.domainname.dataability.persondata/person/10"); + std::shared_ptr dataAbilityHelper = DataAbilityHelper::Creator(context, uri); + NativeRdb::ValuesBucket val; + val.PutInt("valtest", 20); + // Test to AbilityThread interface + auto returnInsert = [&](const Uri &uri, const NativeRdb::ValuesBucket &val) { + int index = 1234; + return index; + }; + EXPECT_CALL(*mockTools->GetMockAbilityScheduler(), Insert(testing::_, testing::_)) + .Times(1) + .WillOnce(testing::Invoke(returnInsert)); + + dataAbilityHelper->Insert(*uri, val); + + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_Insert_0100 end"; +} + +/** + * @tc.number: AaFwk_DataAbilityHelper_Insert_0200 + * @tc.name: Insert + * @tc.desc: Simulate successful test cases + */ +HWTEST_F(DataAbilityHelperForObserverTest, AaFwk_DataAbilityHelper_Insert_0200, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_Insert_0200 start"; + + std::shared_ptr mockTools = MockAbilitySchedulerTools::GetInstance(); + mockTools->SetMockStatus(true); + std::shared_ptr context = std::make_shared(); + std::shared_ptr uri = + std::make_shared("dataability://device_id/com.domainname.dataability.persondata/person/10"); + std::shared_ptr dataAbilityHelper = DataAbilityHelper::Creator(context); + NativeRdb::ValuesBucket val; + val.PutInt("valtest", 20); + // Test to AbilityThread interface + auto returnInsert = [&](const Uri &uri, const NativeRdb::ValuesBucket &val) { + int index = 1234; + return index; + }; + EXPECT_CALL(*mockTools->GetMockAbilityScheduler(), Insert(testing::_, testing::_)) + .Times(1) + .WillOnce(testing::Invoke(returnInsert)); + + dataAbilityHelper->Insert(*uri, val); + + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_Insert_0200 end"; +} + +/** + * @tc.number: AaFwk_DataAbilityHelper_Update_0100 + * @tc.name: Update + * @tc.desc: Simulate successful test cases + */ +HWTEST_F(DataAbilityHelperForObserverTest, AaFwk_DataAbilityHelper_Update_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_Update_0100 start"; + + std::shared_ptr mockTools = MockAbilitySchedulerTools::GetInstance(); + mockTools->SetMockStatus(true); + std::shared_ptr context = std::make_shared(); + std::shared_ptr uri = + std::make_shared("dataability://device_id/com.domainname.dataability.persondata/person/10"); + std::shared_ptr dataAbilityHelper = DataAbilityHelper::Creator(context, uri); + NativeRdb::ValuesBucket val; + val.PutInt("valtest", 20); + NativeRdb::DataAbilityPredicates predicates("predicatestest"); + // Test to AbilityThread interface + auto returnUpdate = [&](const Uri &uri, const NativeRdb::ValuesBucket &val, const NativeRdb::DataAbilityPredicates &predicates) { + int index = 1234; + return index; + }; + EXPECT_CALL(*mockTools->GetMockAbilityScheduler(), Update(testing::_, testing::_, testing::_)) + .Times(1) + .WillOnce(testing::Invoke(returnUpdate)); + + dataAbilityHelper->Update(*uri, val, predicates); + + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_Update_0100 end"; +} + +/** + * @tc.number: AaFwk_DataAbilityHelper_Update_0200 + * @tc.name: Update + * @tc.desc: Simulate successful test cases + */ +HWTEST_F(DataAbilityHelperForObserverTest, AaFwk_DataAbilityHelper_Update_0200, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_Update_0200 start"; + + std::shared_ptr mockTools = MockAbilitySchedulerTools::GetInstance(); + mockTools->SetMockStatus(true); + std::shared_ptr context = std::make_shared(); + std::shared_ptr uri = + std::make_shared("dataability://device_id/com.domainname.dataability.persondata/person/10"); + std::shared_ptr dataAbilityHelper = DataAbilityHelper::Creator(context); + NativeRdb::ValuesBucket val; + val.PutInt("valtest", 20); + NativeRdb::DataAbilityPredicates predicates("predicatestest"); + // Test to AbilityThread interface + auto returnUpdate = [&](const Uri &uri, const NativeRdb::ValuesBucket &val, const NativeRdb::DataAbilityPredicates &predicates) { + int index = 1234; + return index; + }; + EXPECT_CALL(*mockTools->GetMockAbilityScheduler(), Update(testing::_, testing::_, testing::_)) + .Times(1) + .WillOnce(testing::Invoke(returnUpdate)); + + dataAbilityHelper->Update(*uri, val, predicates); + + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_Update_0200 end"; +} + +/** + * @tc.number: AaFwk_DataAbilityHelper_Delete_0100 + * @tc.name: Delete + * @tc.desc: Simulate successful test cases + */ +HWTEST_F(DataAbilityHelperForObserverTest, AaFwk_DataAbilityHelper_Delete_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_Delete_0100 start"; + + std::shared_ptr mockTools = MockAbilitySchedulerTools::GetInstance(); + mockTools->SetMockStatus(true); + std::shared_ptr context = std::make_shared(); + std::shared_ptr uri = + std::make_shared("dataability://device_id/com.domainname.dataability.persondata/person/10"); + std::shared_ptr dataAbilityHelper = DataAbilityHelper::Creator(context, uri); + NativeRdb::DataAbilityPredicates predicates("predicatestest"); + // Test to AbilityThread interface + auto returnDelete = [&](const Uri &uri, const NativeRdb::DataAbilityPredicates &predicates) { + int index = 1234; + return index; + }; + EXPECT_CALL(*mockTools->GetMockAbilityScheduler(), Delete(testing::_, testing::_)) + .Times(1) + .WillOnce(testing::Invoke(returnDelete)); + + dataAbilityHelper->Delete(*uri, predicates); + + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_Delete_0100 end"; +} + +/** + * @tc.number: AaFwk_DataAbilityHelper_Delete_0200 + * @tc.name: Delete + * @tc.desc: Simulate successful test cases + */ +HWTEST_F(DataAbilityHelperForObserverTest, AaFwk_DataAbilityHelper_Delete_0200, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_Delete_0200 start"; + + std::shared_ptr mockTools = MockAbilitySchedulerTools::GetInstance(); + mockTools->SetMockStatus(true); + std::shared_ptr context = std::make_shared(); + std::shared_ptr uri = + std::make_shared("dataability://device_id/com.domainname.dataability.persondata/person/10"); + std::shared_ptr dataAbilityHelper = DataAbilityHelper::Creator(context); + NativeRdb::DataAbilityPredicates predicates("predicatestest"); + // Test to AbilityThread interface + auto returnDelete = [&](const Uri &uri, const NativeRdb::DataAbilityPredicates &predicates) { + int index = 1234; + return index; + }; + EXPECT_CALL(*mockTools->GetMockAbilityScheduler(), Delete(testing::_, testing::_)) + .Times(1) + .WillOnce(testing::Invoke(returnDelete)); + + dataAbilityHelper->Delete(*uri, predicates); + + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_Delete_0200 end"; +} + +/** + * @tc.number: AaFwk_DataAbilityHelper_Query_0100 + * @tc.name: Query + * @tc.desc: Simulate successful test cases + */ +HWTEST_F(DataAbilityHelperForObserverTest, AaFwk_DataAbilityHelper_Query_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_Query_0100 start"; + + std::shared_ptr mockTools = MockAbilitySchedulerTools::GetInstance(); + mockTools->SetMockStatus(true); + std::shared_ptr context = std::make_shared(); + std::shared_ptr uri = + std::make_shared("dataability://device_id/com.domainname.dataability.persondata/person/10"); + std::shared_ptr dataAbilityHelper = DataAbilityHelper::Creator(context, uri); + std::vector columns; + NativeRdb::DataAbilityPredicates predicates("predicatestest"); + // Test to AbilityThread interface + auto returnQuery = + [&](const Uri &uri, const std::vector &columns, const NativeRdb::DataAbilityPredicates &predicates) { + std::shared_ptr set = std::make_shared("resultset"); + return set; + }; + EXPECT_CALL(*mockTools->GetMockAbilityScheduler(), Query(testing::_, testing::_, testing::_)) + .Times(1) + .WillOnce(testing::Invoke(returnQuery)); + + dataAbilityHelper->Query(*uri, columns, predicates); + + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_Query_0100 end"; +} + +/** + * @tc.number: AaFwk_DataAbilityHelper_Query_0200 + * @tc.name: Query + * @tc.desc: Simulate successful test cases + */ +HWTEST_F(DataAbilityHelperForObserverTest, AaFwk_DataAbilityHelper_Query_0200, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_Query_0200 start"; + + std::shared_ptr mockTools = MockAbilitySchedulerTools::GetInstance(); + mockTools->SetMockStatus(true); + std::shared_ptr context = std::make_shared(); + std::shared_ptr uri = + std::make_shared("dataability://device_id/com.domainname.dataability.persondata/person/10"); + std::shared_ptr dataAbilityHelper = DataAbilityHelper::Creator(context); + std::vector columns; + NativeRdb::DataAbilityPredicates predicates("predicatestest"); + // Test to AbilityThread interface + auto returnQuery = + [&](const Uri &uri, const std::vector &columns, const NativeRdb::DataAbilityPredicates &predicates) { + std::shared_ptr set = std::make_shared("resultset"); + return set; + }; + EXPECT_CALL(*mockTools->GetMockAbilityScheduler(), Query(testing::_, testing::_, testing::_)) + .Times(1) + .WillOnce(testing::Invoke(returnQuery)); + + dataAbilityHelper->Query(*uri, columns, predicates); + + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_Query_0200 end"; +} + +/** + * @tc.number: AaFwk_DataAbilityHelper_GetType_0100 + * @tc.name: GetType + * @tc.desc: Simulate successful test cases + */ +HWTEST_F(DataAbilityHelperForObserverTest, AaFwk_DataAbilityHelper_GetType_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_GetType_0100 start"; + + std::shared_ptr mockTools = MockAbilitySchedulerTools::GetInstance(); + mockTools->SetMockStatus(true); + std::shared_ptr context = std::make_shared(); + std::shared_ptr uri = + std::make_shared("dataability://device_id/com.domainname.dataability.persondata/person/10"); + std::shared_ptr dataAbilityHelper = DataAbilityHelper::Creator(context, uri); + // Test to AbilityThread interface + auto returnGetType = [&](const Uri &uri) { + std::string type("Type1"); + return type; + }; + EXPECT_CALL(*mockTools->GetMockAbilityScheduler(), GetType(testing::_)) + .Times(1) + .WillOnce(testing::Invoke(returnGetType)); + + dataAbilityHelper->GetType(*uri); + + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_GetType_0100 end"; +} + +/** + * @tc.number: AaFwk_DataAbilityHelper_GetType_0200 + * @tc.name: GetType + * @tc.desc: Simulate successful test cases + */ +HWTEST_F(DataAbilityHelperForObserverTest, AaFwk_DataAbilityHelper_GetType_0200, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_GetType_0200 start"; + + std::shared_ptr mockTools = MockAbilitySchedulerTools::GetInstance(); + mockTools->SetMockStatus(true); + std::shared_ptr context = std::make_shared(); + std::shared_ptr uri = + std::make_shared("dataability://device_id/com.domainname.dataability.persondata/person/10"); + std::shared_ptr dataAbilityHelper = DataAbilityHelper::Creator(context); + // Test to AbilityThread interface + auto returnGetType = [&](const Uri &uri) { + std::string type("Type1"); + return type; + }; + EXPECT_CALL(*mockTools->GetMockAbilityScheduler(), GetType(testing::_)) + .Times(1) + .WillOnce(testing::Invoke(returnGetType)); + + dataAbilityHelper->GetType(*uri); + + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_GetType_0200 end"; +} + +/** + * @tc.number: AaFwk_DataAbilityHelper_OpenRawFile_0100 + * @tc.name: OpenRawFile + * @tc.desc: Simulate successful test cases + */ +HWTEST_F(DataAbilityHelperForObserverTest, AaFwk_DataAbilityHelper_OpenRawFile_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_OpenRawFile_0100 start"; + + std::shared_ptr mockTools = MockAbilitySchedulerTools::GetInstance(); + mockTools->SetMockStatus(true); + std::shared_ptr context = std::make_shared(); + std::shared_ptr uri = + std::make_shared("dataability://device_id/com.domainname.dataability.persondata/person/10"); + std::shared_ptr dataAbilityHelper = DataAbilityHelper::Creator(context, uri); + // Test to AbilityThread interface + std::string mode("modetest"); + auto returnOpenRawFile = [&](const Uri &uri, const std::string &mode) { + int fd = 1234; + return fd; + }; + EXPECT_CALL(*mockTools->GetMockAbilityScheduler(), OpenRawFile(testing::_, testing::_)) + .Times(1) + .WillOnce(testing::Invoke(returnOpenRawFile)); + + dataAbilityHelper->OpenRawFile(*uri, mode); + + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_OpenRawFile_0100 end"; +} + +/** + * @tc.number: AaFwk_DataAbilityHelper_OpenRawFile_0200 + * @tc.name: OpenRawFile + * @tc.desc: Simulate successful test cases + */ +HWTEST_F(DataAbilityHelperForObserverTest, AaFwk_DataAbilityHelper_OpenRawFile_0200, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_OpenRawFile_0200 start"; + + std::shared_ptr mockTools = MockAbilitySchedulerTools::GetInstance(); + mockTools->SetMockStatus(true); + std::shared_ptr context = std::make_shared(); + std::shared_ptr uri = + std::make_shared("dataability://device_id/com.domainname.dataability.persondata/person/10"); + std::shared_ptr dataAbilityHelper = DataAbilityHelper::Creator(context); + // Test to AbilityThread interface + std::string mode("modetest"); + auto returnOpenRawFile = [&](const Uri &uri, const std::string &mode) { + int fd = 1234; + return fd; + }; + EXPECT_CALL(*mockTools->GetMockAbilityScheduler(), OpenRawFile(testing::_, testing::_)) + .Times(1) + .WillOnce(testing::Invoke(returnOpenRawFile)); + + dataAbilityHelper->OpenRawFile(*uri, mode); + + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_OpenRawFile_0200 end"; +} + +/** + * @tc.number: AaFwk_DataAbilityHelper_Reload_0100 + * @tc.name: Reload + * @tc.desc: Simulate successful test cases + */ +HWTEST_F(DataAbilityHelperForObserverTest, AaFwk_DataAbilityHelper_Reload_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_Reload_0100 start"; + + std::shared_ptr mockTools = MockAbilitySchedulerTools::GetInstance(); + mockTools->SetMockStatus(true); + std::shared_ptr context = std::make_shared(); + std::shared_ptr uri = + std::make_shared("dataability://device_id/com.domainname.dataability.persondata/person/10"); + std::shared_ptr dataAbilityHelper = DataAbilityHelper::Creator(context, uri); + // Test to AbilityThread interface + PacMap extras; + auto returnReload = [&](const Uri &uri, const PacMap &extras) { return true; }; + EXPECT_CALL(*mockTools->GetMockAbilityScheduler(), Reload(testing::_, testing::_)) + .Times(1) + .WillOnce(testing::Invoke(returnReload)); + + dataAbilityHelper->Reload(*uri, extras); + + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_Reload_0100 end"; +} + +/** + * @tc.number: AaFwk_DataAbilityHelper_Reload_0200 + * @tc.name: Reload + * @tc.desc: Simulate successful test cases + */ +HWTEST_F(DataAbilityHelperForObserverTest, AaFwk_DataAbilityHelper_Reload_0200, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_Reload_0200 start"; + + std::shared_ptr mockTools = MockAbilitySchedulerTools::GetInstance(); + mockTools->SetMockStatus(true); + std::shared_ptr context = std::make_shared(); + std::shared_ptr uri = + std::make_shared("dataability://device_id/com.domainname.dataability.persondata/person/10"); + std::shared_ptr dataAbilityHelper = DataAbilityHelper::Creator(context); + // Test to AbilityThread interface + PacMap extras; + auto returnReload = [&](const Uri &uri, const PacMap &extras) { return true; }; + EXPECT_CALL(*mockTools->GetMockAbilityScheduler(), Reload(testing::_, testing::_)) + .Times(1) + .WillOnce(testing::Invoke(returnReload)); + + dataAbilityHelper->Reload(*uri, extras); + + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_Reload_0200 end"; +} + +/** + * @tc.number: AaFwk_DataAbilityHelper_BatchInsert_0100 + * @tc.name: BatchInsert + * @tc.desc: Simulate successful test cases + */ +HWTEST_F(DataAbilityHelperForObserverTest, AaFwk_DataAbilityHelper_BatchInsert_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_BatchInsert_0100 start"; + + std::shared_ptr mockTools = MockAbilitySchedulerTools::GetInstance(); + mockTools->SetMockStatus(true); + std::shared_ptr context = std::make_shared(); + std::shared_ptr uri = + std::make_shared("dataability://device_id/com.domainname.dataability.persondata/person/10"); + std::shared_ptr dataAbilityHelper = DataAbilityHelper::Creator(context, uri); + // Test to AbilityThread interface + std::vector values; + auto returnBatchInsert = [&](const Uri &uri, const std::vector &values) { return true; }; + EXPECT_CALL(*mockTools->GetMockAbilityScheduler(), BatchInsert(testing::_, testing::_)) + .Times(1) + .WillOnce(testing::Invoke(returnBatchInsert)); + + dataAbilityHelper->BatchInsert(*uri, values); + + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_BatchInsert_0100 end"; +} + +/** + * @tc.number: AaFwk_DataAbilityHelper_BatchInsert_0200 + * @tc.name: BatchInsert + * @tc.desc: Simulate successful test cases + */ +HWTEST_F(DataAbilityHelperForObserverTest, AaFwk_DataAbilityHelper_BatchInsert_0200, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_BatchInsert_0200 start"; + + std::shared_ptr mockTools = MockAbilitySchedulerTools::GetInstance(); + mockTools->SetMockStatus(true); + std::shared_ptr context = std::make_shared(); + std::shared_ptr uri = + std::make_shared("dataability://device_id/com.domainname.dataability.persondata/person/10"); + std::shared_ptr dataAbilityHelper = DataAbilityHelper::Creator(context); + // Test to AbilityThread interface + std::vector values; + auto returnBatchInsert = [&](const Uri &uri, const std::vector &values) { return true; }; + EXPECT_CALL(*mockTools->GetMockAbilityScheduler(), BatchInsert(testing::_, testing::_)) + .Times(1) + .WillOnce(testing::Invoke(returnBatchInsert)); + + dataAbilityHelper->BatchInsert(*uri, values); + + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_BatchInsert_0200 end"; +} + +/** + * @tc.number: AaFwk_DataAbilityHelper_NormalizeUri_0100 + * @tc.name: NormalizeUri + * @tc.desc: Simulate successful test cases + */ +HWTEST_F(DataAbilityHelperForObserverTest, AaFwk_DataAbilityHelper_NormalizeUri_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_NormalizeUri_0100 start"; + + std::shared_ptr mockTools = MockAbilitySchedulerTools::GetInstance(); + mockTools->SetMockStatus(true); + std::shared_ptr context = std::make_shared(); + std::shared_ptr uri = + std::make_shared("dataability://device_id/com.domainname.dataability.persondata/person/10"); + std::shared_ptr dataAbilityHelper = DataAbilityHelper::Creator(context, uri); + // Test to AbilityThread interface + auto returnNormalizeUri = [&](const Uri &uri) { + Uri uriValue("dataability://device_id/com.domainname.dataability."); + return uriValue; + }; + EXPECT_CALL(*mockTools->GetMockAbilityScheduler(), NormalizeUri(testing::_)) + .Times(1) + .WillOnce(testing::Invoke(returnNormalizeUri)); + + dataAbilityHelper->NormalizeUri(*uri); + + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_NormalizeUri_0100 end"; +} + +/** + * @tc.number: AaFwk_DataAbilityHelper_NormalizeUri_0200 + * @tc.name: NormalizeUri + * @tc.desc: Simulate successful test cases + */ +HWTEST_F(DataAbilityHelperForObserverTest, AaFwk_DataAbilityHelper_NormalizeUri_0200, Function | MediumTest | Level3) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_NormalizeUri_0200 start"; + + std::shared_ptr mockTools = MockAbilitySchedulerTools::GetInstance(); + mockTools->SetMockStatus(true); + std::shared_ptr context = std::make_shared(); + std::shared_ptr uri = + std::make_shared("dataability://device_id/com.domainname.dataability.persondata/person/10"); + std::shared_ptr dataAbilityHelper = DataAbilityHelper::Creator(context); + // Test to AbilityThread interface + auto returnNormalizeUri = [&](const Uri &uri) { + Uri uriValue("dataability://device_id/com.domainname.dataability."); + return uriValue; + }; + EXPECT_CALL(*mockTools->GetMockAbilityScheduler(), NormalizeUri(testing::_)) + .Times(1) + .WillOnce(testing::Invoke(returnNormalizeUri)); + + dataAbilityHelper->NormalizeUri(*uri); + + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_NormalizeUri_0200 end"; +} + +/** + * @tc.number: AaFwk_DataAbilityHelper_DenormalizeUri_0100 + * @tc.name: DenormalizeUri + * @tc.desc: Simulate successful test cases + */ +HWTEST_F(DataAbilityHelperForObserverTest, AaFwk_DataAbilityHelper_DenormalizeUri_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_DenormalizeUri_0100 start"; + + std::shared_ptr mockTools = MockAbilitySchedulerTools::GetInstance(); + mockTools->SetMockStatus(true); + std::shared_ptr context = std::make_shared(); + std::shared_ptr uri = + std::make_shared("dataability://device_id/com.domainname.dataability.persondata/person/10"); + std::shared_ptr dataAbilityHelper = DataAbilityHelper::Creator(context, uri); + // Test to AbilityThread interface + auto returnDenormalizeUri = [&](const Uri &uri) { + Uri uriValue("dataability://device_id/com.domainname.dataability."); + return uriValue; + }; + EXPECT_CALL(*mockTools->GetMockAbilityScheduler(), DenormalizeUri(testing::_)) + .Times(1) + .WillOnce(testing::Invoke(returnDenormalizeUri)); + + dataAbilityHelper->DenormalizeUri(*uri); + + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_DenormalizeUri_0100 end"; +} + +/** + * @tc.number: AaFwk_DataAbilityHelper_DenormalizeUri_0200 + * @tc.name: DenormalizeUri + * @tc.desc: Simulate successful test cases + */ +HWTEST_F(DataAbilityHelperForObserverTest, AaFwk_DataAbilityHelper_DenormalizeUri_0200, Function | MediumTest | Level3) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_DenormalizeUri_0200 start"; + + std::shared_ptr mockTools = MockAbilitySchedulerTools::GetInstance(); + mockTools->SetMockStatus(true); + std::shared_ptr context = std::make_shared(); + std::shared_ptr uri = + std::make_shared("dataability://device_id/com.domainname.dataability.persondata/person/10"); + std::shared_ptr dataAbilityHelper = DataAbilityHelper::Creator(context); + // Test to AbilityThread interface + auto returnDenormalizeUri = [&](const Uri &uri) { + Uri uriValue("dataability://device_id/com.domainname.dataability."); + return uriValue; + }; + EXPECT_CALL(*mockTools->GetMockAbilityScheduler(), DenormalizeUri(testing::_)) + .Times(1) + .WillOnce(testing::Invoke(returnDenormalizeUri)); + + dataAbilityHelper->DenormalizeUri(*uri); + + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_DenormalizeUri_0200 end"; +} + +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/test/unittest/data_ability_impl_file_secondpart_test.cpp b/tools/frameworks/kits/ability/native/test/unittest/data_ability_impl_file_secondpart_test.cpp new file mode 100644 index 00000000000..667b0516800 --- /dev/null +++ b/tools/frameworks/kits/ability/native/test/unittest/data_ability_impl_file_secondpart_test.cpp @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "ability_loader.h" +#include "app_log_wrapper.h" +#include "data_ability_impl.h" +#include "mock_ability_token.h" +#include "mock_data_ability.h" + +namespace OHOS { +namespace AppExecFwk { +using namespace testing::ext; +using namespace OHOS; +using namespace OHOS::AppExecFwk; + +REGISTER_AA(MockDataAbility) + +class DataAbilityImplTest : public testing::Test { +public: + DataAbilityImplTest() : dataabilityimpl(nullptr) + {} + ~DataAbilityImplTest() + { + dataabilityimpl = nullptr; + } + DataAbilityImpl *dataabilityimpl; + + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void DataAbilityImplTest::SetUpTestCase(void) +{} + +void DataAbilityImplTest::TearDownTestCase(void) +{} + +void DataAbilityImplTest::SetUp(void) +{} + +void DataAbilityImplTest::TearDown(void) +{} + +/** + * @tc.number: AaFwk_DataAbilityImplTest_BatchInsert_0100 + * @tc.name: BatchInsert + * @tc.desc: Simulate successful test cases. + */ +HWTEST_F(DataAbilityImplTest, AaFwk_DataAbilityImplTest_BatchInsert_001, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityImplTest_BatchInsert_001 start"; + std::shared_ptr dataabilityimpl = std::make_shared(); + std::shared_ptr application = std::make_shared(); + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "MockDataAbility"; + abilityInfo->type = AbilityType::DATA; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + std::shared_ptr record = std::make_shared(abilityInfo, token); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + std::shared_ptr handler = std::make_shared(nullptr, abilityThread); + std::shared_ptr ability = std::make_shared(); + std::shared_ptr contextDeal = std::make_shared(); + dataabilityimpl->Init(application, record, ability, handler, token, contextDeal); + + int ret; + Uri uri("nullptr"); + std::vector values; + ret = dataabilityimpl->BatchInsert(uri, values); + + EXPECT_EQ(1, ret); + sleep(1); + GTEST_LOG_(INFO) << "AaFwk_DataAbilityImplTest_BatchInsert_001 end"; +} + +/** + * @tc.number: AaFwk_DataAbilityImplTest_BatchInsert_0200 + * @tc.name: BatchInsert + * @tc.desc: Validate when normally entering a string. + */ +HWTEST_F(DataAbilityImplTest, AaFwk_DataAbilityImplTest_BatchInsert_002, Function | MediumTest | Level3) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityImplTest_BatchInsert_002 start"; + std::shared_ptr dataabilityimpl = std::make_shared(); + int ret; + Uri uri("nullptr"); + std::vector values; + ret = dataabilityimpl->BatchInsert(uri, values); + + EXPECT_EQ(-1, ret); + sleep(1); + GTEST_LOG_(INFO) << "AaFwk_DataAbilityImplTest_BatchInsert_002 end"; +} + +/** + * @tc.number: AaFwk_DataAbilityImplTest_HandleAbilityTransaction_0100 + * @tc.name: GetFileTypes + * @tc.desc: Simulate successful test cases. + */ +HWTEST_F(DataAbilityImplTest, AaFwk_DataAbilityImplTest_HandleAbilityTransaction_001, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityImplTest_HandleAbilityTransaction_001 start"; + std::shared_ptr dataabilityimpl = std::make_shared(); + std::shared_ptr application = std::make_shared(); + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "MockDataAbility"; + abilityInfo->type = AbilityType::DATA; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + std::shared_ptr record = std::make_shared(abilityInfo, token); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + std::shared_ptr handler = std::make_shared(nullptr, abilityThread); + std::shared_ptr ability = std::make_shared(); + std::shared_ptr contextDeal = std::make_shared(); + dataabilityimpl->Init(application, record, ability, handler, token, contextDeal); + + Want want; + LifeCycleStateInfo targetState; + + dataabilityimpl->HandleAbilityTransaction(want, targetState); + sleep(1); + GTEST_LOG_(INFO) << "AaFwk_DataAbilityImplTest_HandleAbilityTransaction_001 end"; +} + +/** + * @tc.number: AaFwk_DataAbilityImplTest_HandleAbilityTransaction_0200 + * @tc.name: GetFileTypes + * @tc.desc: Simulate successful test cases. + */ +HWTEST_F(DataAbilityImplTest, AaFwk_DataAbilityImplTest_HandleAbilityTransaction_002, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityImplTest_HandleAbilityTransaction_002 start"; + std::shared_ptr dataabilityimpl = std::make_shared(); + std::shared_ptr application = std::make_shared(); + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "MockDataAbility"; + abilityInfo->type = AbilityType::DATA; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + std::shared_ptr record = std::make_shared(abilityInfo, token); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + std::shared_ptr handler = std::make_shared(nullptr, abilityThread); + std::shared_ptr ability = std::make_shared(); + std::shared_ptr contextDeal = std::make_shared(); + dataabilityimpl->Init(application, record, ability, handler, token, contextDeal); + + Want want; + LifeCycleStateInfo targetState; + + dataabilityimpl->HandleAbilityTransaction(want, targetState); + sleep(1); + GTEST_LOG_(INFO) << "AaFwk_DataAbilityImplTest_HandleAbilityTransaction_002 end"; +} +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/test/unittest/data_ability_impl_file_test.cpp b/tools/frameworks/kits/ability/native/test/unittest/data_ability_impl_file_test.cpp new file mode 100644 index 00000000000..acb146d4bbb --- /dev/null +++ b/tools/frameworks/kits/ability/native/test/unittest/data_ability_impl_file_test.cpp @@ -0,0 +1,339 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "ability_loader.h" +#include "app_log_wrapper.h" +#include "data_ability_impl.h" +#include "mock_ability_token.h" +#include "mock_data_ability.h" + +namespace OHOS { +namespace AppExecFwk { +using namespace testing::ext; +using namespace OHOS; +using namespace OHOS::AppExecFwk; + +REGISTER_AA(MockDataAbility) + +class DataAbilityImplTest : public testing::Test { +public: + DataAbilityImplTest() : dataabilityimpl(nullptr) + {} + ~DataAbilityImplTest() + { + dataabilityimpl = nullptr; + } + DataAbilityImpl *dataabilityimpl; + + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void DataAbilityImplTest::SetUpTestCase(void) +{} + +void DataAbilityImplTest::TearDownTestCase(void) +{} + +void DataAbilityImplTest::SetUp(void) +{} + +void DataAbilityImplTest::TearDown(void) +{} + +/** + * @tc.number: AaFwk_DataAbilityImplTest_GetType_0100 + * @tc.name: Query + * @tc.desc: Simulate successful test cases. + */ +HWTEST_F(DataAbilityImplTest, AaFwk_DataAbilityImplTest_GetType_001, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityImplTest_GetType_001 start"; + std::shared_ptr dataabilityimpl = std::make_shared(); + std::shared_ptr application = std::make_shared(); + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "MockDataAbility"; + abilityInfo->type = AbilityType::DATA; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + std::shared_ptr record = std::make_shared(abilityInfo, token); + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + std::shared_ptr dataAbility = std::make_shared(); + std::shared_ptr ability; + ability.reset(dataAbility.get()); + std::shared_ptr contextDeal = std::make_shared(); + dataabilityimpl->Init(application, record, ability, handler, token, contextDeal); + + Uri uri("\nullptr"); + + EXPECT_STREQ("Type1", dataabilityimpl->GetType(uri).c_str()); + sleep(1); + GTEST_LOG_(INFO) << "AaFwk_DataAbilityImplTest_GetType_001 end"; +} + +/** + * @tc.number: AaFwk_DataAbilityImplTest_GetType_0200 + * @tc.name: Query + * @tc.desc: Simulate successful test cases. + */ +HWTEST_F(DataAbilityImplTest, AaFwk_DataAbilityImplTest_GetType_002, Function | MediumTest | Level3) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityImplTest_GetType_002 start"; + std::shared_ptr dataabilityimpl = std::make_shared(); + std::shared_ptr application = std::make_shared(); + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "MockDataAbility"; + abilityInfo->type = AbilityType::DATA; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + std::shared_ptr record = std::make_shared(abilityInfo, token); + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + std::shared_ptr ability = nullptr; + std::shared_ptr contextDeal = std::make_shared(); + dataabilityimpl->Init(application, record, ability, handler, token, contextDeal); + + Uri uri("\nullptr"); + EXPECT_STREQ("", dataabilityimpl->GetType(uri).c_str()); + sleep(1); + GTEST_LOG_(INFO) << "AaFwk_DataAbilityImplTest_GetType_002 end"; +} + +/** + * @tc.number: AaFwk_DataAbilityImplTest_GetFileTypes_0100 + * @tc.name: GetFileTypes + * @tc.desc: Simulate successful test cases. + */ +HWTEST_F(DataAbilityImplTest, AaFwk_DataAbilityImplTest_GetFileTypes_001, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityImplTest_GetFileTypes_001 start"; + std::shared_ptr dataabilityimpl = std::make_shared(); + std::shared_ptr application = std::make_shared(); + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "MockDataAbility"; + abilityInfo->type = AbilityType::DATA; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + std::shared_ptr record = std::make_shared(abilityInfo, token); + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + std::shared_ptr dataAbility = std::make_shared(); + std::shared_ptr ability; + ability.reset(dataAbility.get()); + std::shared_ptr contextDeal = std::make_shared(); + dataabilityimpl->Init(application, record, ability, handler, token, contextDeal); + + Uri uri("\nullptr"); + std::string mimeTypeFilter("nullptr"); + std::vector types; + + types = dataabilityimpl->GetFileTypes(uri, mimeTypeFilter); + + if (types.size() != 0) { + EXPECT_STREQ(mimeTypeFilter.c_str(), types.at(0).c_str()); + } + sleep(1); + GTEST_LOG_(INFO) << "AaFwk_DataAbilityImplTest_GetFileTypes_001 end"; +} + +/** + * @tc.number: AaFwk_DataAbilityImplTest_GetFileTypes_0200 + * @tc.name: GetFileTypes + * @tc.desc: Simulate successful test cases. + */ +HWTEST_F(DataAbilityImplTest, AaFwk_DataAbilityImplTest_GetFileTypes_002, Function | MediumTest | Level3) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityImplTest_GetFileTypes_002 start"; + std::shared_ptr dataabilityimpl = std::make_shared(); + Uri uri("\nullptr"); + std::string mimeTypeFilter("nullptr"); + std::vector types; + int number = 0; + int typesSize; + + types = dataabilityimpl->GetFileTypes(uri, mimeTypeFilter); + typesSize = types.size(); + EXPECT_EQ(number, typesSize); + sleep(1); + GTEST_LOG_(INFO) << "AaFwk_DataAbilityImplTest_GetFileTypes_002 end"; +} + +/** + * @tc.number: AaFwk_DataAbilityImplTest_OpenFile_0100 + * @tc.name: OpenFile + * @tc.desc: Simulate successful test cases. + */ +HWTEST_F(DataAbilityImplTest, AaFwk_DataAbilityImplTest_OpenFile_001, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityImplTest_OpenFile_001 start"; + std::shared_ptr dataabilityimpl = std::make_shared(); + std::shared_ptr application = std::make_shared(); + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "MockDataAbility"; + abilityInfo->type = AbilityType::DATA; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + std::shared_ptr record = std::make_shared(abilityInfo, token); + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + std::shared_ptr dataAbility = std::make_shared(); + std::shared_ptr ability; + ability.reset(dataAbility.get()); + std::shared_ptr contextDeal = std::make_shared(); + dataabilityimpl->Init(application, record, ability, handler, token, contextDeal); + + int fd = 1; + int value; + Uri uri("nullptr"); + std::string mode; + value = dataabilityimpl->OpenFile(uri, mode); + + EXPECT_EQ(fd, value); + sleep(1); + GTEST_LOG_(INFO) << "AaFwk_DataAbilityImplTest_OpenFile_001 end"; +} + +/** + * @tc.number: AaFwk_DataAbilityImplTest_OpenFile_0200 + * @tc.name: OpenFile + * @tc.desc: Validate when normally entering a string. + */ +HWTEST_F(DataAbilityImplTest, AaFwk_DataAbilityImplTest_OpenFile_002, Function | MediumTest | Level3) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityImplTest_OpenFile_002 start"; + std::shared_ptr dataabilityimpl = std::make_shared(); + int fd = -1; + int value; + Uri uri("nullptr"); + std::string mode; + value = dataabilityimpl->OpenFile(uri, mode); + + EXPECT_EQ(fd, value); + sleep(1); + GTEST_LOG_(INFO) << "AaFwk_DataAbilityImplTest_OpenFile_002 end"; +} + +/** + * @tc.number: AaFwk_DataAbilityImplTest_OpenRawFile_0100 + * @tc.name: OpenRawFile + * @tc.desc: Simulate successful test cases. + */ +HWTEST_F(DataAbilityImplTest, AaFwk_DataAbilityImplTest_OpenRawFile_001, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityImplTest_OpenRawFile_001 start"; + std::shared_ptr dataabilityimpl = std::make_shared(); + std::shared_ptr application = std::make_shared(); + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "MockDataAbility"; + abilityInfo->type = AbilityType::DATA; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + std::shared_ptr record = std::make_shared(abilityInfo, token); + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + std::shared_ptr dataAbility = std::make_shared(); + std::shared_ptr ability; + ability.reset(dataAbility.get()); + std::shared_ptr contextDeal = std::make_shared(); + dataabilityimpl->Init(application, record, ability, handler, token, contextDeal); + + int fd = 1; + int value; + Uri uri("nullptr"); + std::string mode; + value = dataabilityimpl->OpenRawFile(uri, mode); + + EXPECT_EQ(fd, value); + sleep(1); + GTEST_LOG_(INFO) << "AaFwk_DataAbilityImplTest_OpenRawFile_001 end"; +} + +/** + * @tc.number: AaFwk_DataAbilityImplTest_OpenRawFile_0200 + * @tc.name: OpenRawFile + * @tc.desc: Validate when normally entering a string. + */ +HWTEST_F(DataAbilityImplTest, AaFwk_DataAbilityImplTest_OpenRawFile_002, Function | MediumTest | Level3) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityImplTest_OpenRawFile_002 start"; + std::shared_ptr dataabilityimpl = std::make_shared(); + int fd = -1; + int value; + Uri uri("nullptr"); + std::string mode; + value = dataabilityimpl->OpenRawFile(uri, mode); + + EXPECT_EQ(fd, value); + sleep(1); + GTEST_LOG_(INFO) << "AaFwk_DataAbilityImplTest_OpenRawFile_002 end"; +} + +/** + * @tc.number: AaFwk_DataAbilityImplTest_Reload_0100 + * @tc.name: Reload + * @tc.desc: Simulate successful test cases. + */ +HWTEST_F(DataAbilityImplTest, AaFwk_DataAbilityImplTest_Reload_001, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityImplTest_Reload_001 start"; + std::shared_ptr dataabilityimpl = std::make_shared(); + std::shared_ptr application = std::make_shared(); + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "MockDataAbility"; + abilityInfo->type = AbilityType::DATA; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + std::shared_ptr record = std::make_shared(abilityInfo, token); + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + std::shared_ptr dataAbility = std::make_shared(); + std::shared_ptr ability; + ability.reset(dataAbility.get()); + std::shared_ptr contextDeal = std::make_shared(); + dataabilityimpl->Init(application, record, ability, handler, token, contextDeal); + + Uri uri("nullptr"); + PacMap extras; + bool ret = dataabilityimpl->Reload(uri, extras); + + EXPECT_EQ(true, ret); + sleep(1); + GTEST_LOG_(INFO) << "AaFwk_DataAbilityImplTest_Reload_001 end"; +} + +/** + * @tc.number: AaFwk_DataAbilityImplTest_Reload_0200 + * @tc.name: Reload + * @tc.desc: Validate when normally entering a string. + */ +HWTEST_F(DataAbilityImplTest, AaFwk_DataAbilityImplTest_Reload_002, Function | MediumTest | Level3) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityImplTest_Reload_002 start"; + std::shared_ptr dataabilityimpl = std::make_shared(); + + Uri uri("nullptr"); + PacMap extras; + bool ret = dataabilityimpl->Reload(uri, extras); + + EXPECT_EQ(false, ret); + sleep(1); + GTEST_LOG_(INFO) << "AaFwk_DataAbilityImplTest_Reload_002 end"; +} +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/test/unittest/data_ability_impl_test.cpp b/tools/frameworks/kits/ability/native/test/unittest/data_ability_impl_test.cpp new file mode 100644 index 00000000000..e57406e4703 --- /dev/null +++ b/tools/frameworks/kits/ability/native/test/unittest/data_ability_impl_test.cpp @@ -0,0 +1,270 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "ability_loader.h" +#include "app_log_wrapper.h" +#include "data_ability_impl.h" +#include "mock_ability_token.h" +#include "mock_data_ability.h" + +namespace OHOS { +namespace AppExecFwk { +using namespace testing::ext; +using namespace OHOS; +using namespace OHOS::AppExecFwk; + +REGISTER_AA(MockDataAbility) + +class DataAbilityImplTest : public testing::Test { +public: + DataAbilityImplTest() : dataabilityimpl(nullptr) + {} + ~DataAbilityImplTest() + { + dataabilityimpl = nullptr; + } + DataAbilityImpl *dataabilityimpl; + + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void DataAbilityImplTest::SetUpTestCase(void) +{} + +void DataAbilityImplTest::TearDownTestCase(void) +{} + +void DataAbilityImplTest::SetUp(void) +{} + +void DataAbilityImplTest::TearDown(void) +{} + + +/** + * @tc.number: AaFwk_DataAbilityImplTest_Insert_0100 + * @tc.name: Insert + * @tc.desc: Simulate successful test cases. + */ +HWTEST_F(DataAbilityImplTest, AaFwk_DataAbilityImplTest_Insert_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityImplTest_Insert_0100 start"; + std::shared_ptr dataabilityimpl = std::make_shared(); + + std::shared_ptr application = std::make_shared(); + + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "MockDataAbility"; + abilityInfo->type = AbilityType::DATA; + abilityInfo->isNativeAbility = true; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + std::shared_ptr record = std::make_shared(abilityInfo, token); + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + std::shared_ptr ability = std::make_shared(); + std::shared_ptr contextDeal = std::make_shared(); + + dataabilityimpl->Init(application, record, ability, handler, token, contextDeal); + EXPECT_NE(dataabilityimpl, nullptr); + Uri uri("\nullptr"); + int number = 1; + int result = 0; + NativeRdb::ValuesBucket value; + result = dataabilityimpl->Insert(uri, value); + + EXPECT_EQ(number, result); + sleep(1); + GTEST_LOG_(INFO) << "AaFwk_DataAbilityImplTest_Insert_0100 end"; +} + +/** + * @tc.number: AaFwk_DataAbilityImplTest_Insert_0200 + * @tc.name: Insert + * @tc.desc: Validate when normally entering a string. + */ +HWTEST_F(DataAbilityImplTest, AaFwk_DataAbilityImplTest_Insert_0200, Function | MediumTest | Level3) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityImplTest_Insert_0200 start"; + std::shared_ptr dataabilityimpl = std::make_shared(); + Uri uri("\nullptr"); + int number = -1; + NativeRdb::ValuesBucket value; + + EXPECT_EQ(number, dataabilityimpl->Insert(uri, value)); + sleep(1); + GTEST_LOG_(INFO) << "AaFwk_DataAbilityImplTest_Insert_0200 end"; +} + + +/** + * @tc.number: AaFwk_DataAbilityImplTest_Update_0100 + * @tc.name: Update + * @tc.desc: Simulate successful test cases. + */ +HWTEST_F(DataAbilityImplTest, AaFwk_DataAbilityImplTest_Update_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityImplTest_Update_0100 start"; + std::shared_ptr dataabilityimpl = std::make_shared(); + std::shared_ptr application = std::make_shared(); + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "MockDataAbility"; + abilityInfo->type = AbilityType::DATA; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + std::shared_ptr record = std::make_shared(abilityInfo, token); + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + std::shared_ptr ability = std::make_shared(); + std::shared_ptr contextDeal = std::make_shared(); + dataabilityimpl->Init(application, record, ability, handler, token, contextDeal); + + Uri uri("\nullptr"); + int number = 1; + NativeRdb::ValuesBucket value; + NativeRdb::DataAbilityPredicates predicates; + + EXPECT_EQ(number, dataabilityimpl->Update(uri, value, predicates)); + sleep(1); + GTEST_LOG_(INFO) << "AaFwk_DataAbilityImplTest_Update_0100 end"; +} + +/** + * @tc.number: AaFwk_DataAbilityImplTest_Update_0200 + * @tc.name: Update + * @tc.desc: Validate when normally entering a string. + */ +HWTEST_F(DataAbilityImplTest, AaFwk_DataAbilityImplTest_Update_0200, Function | MediumTest | Level3) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityImplTest_Update_0200 start"; + std::shared_ptr dataabilityimpl = std::make_shared(); + Uri uri("\nullptr"); + int number = -1; + NativeRdb::ValuesBucket value; + NativeRdb::DataAbilityPredicates predicates; + + EXPECT_EQ(number, dataabilityimpl->Update(uri, value, predicates)); + sleep(1); + GTEST_LOG_(INFO) << "AaFwk_DataAbilityImplTest_Update_0200 end"; +} + +/** + * @tc.number: AaFwk_DataAbilityImplTest_Delete_0100 + * @tc.name: Delete + * @tc.desc: Simulate successful test cases. + */ +HWTEST_F(DataAbilityImplTest, AaFwk_DataAbilityImplTest_Delete_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityImplTest_Delete_0100 start"; + std::shared_ptr dataabilityimpl = std::make_shared(); + std::shared_ptr application = std::make_shared(); + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "MockDataAbility"; + abilityInfo->type = AbilityType::DATA; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + std::shared_ptr record = std::make_shared(abilityInfo, token); + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + std::shared_ptr ability = std::make_shared(); + std::shared_ptr contextDeal = std::make_shared(); + dataabilityimpl->Init(application, record, ability, handler, token, contextDeal); + + Uri uri("\nullptr"); + int number = 1; + + NativeRdb::DataAbilityPredicates predicates; + + EXPECT_EQ(number, dataabilityimpl->Delete(uri, predicates)); + sleep(1); + GTEST_LOG_(INFO) << "AaFwk_DataAbilityImplTest_Delete_0100 end"; +} + +/** + * @tc.number: AaFwk_DataAbilityImplTest_Delete_0200 + * @tc.name: Delete + * @tc.desc: Validate when normally entering a string. + */ +HWTEST_F(DataAbilityImplTest, AaFwk_DataAbilityImplTest_Delete_0200, Function | MediumTest | Level3) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityImplTest_Delete_0200 start"; + std::shared_ptr dataabilityimpl = std::make_shared(); + Uri uri("\nullptr"); + int number = -1; + NativeRdb::DataAbilityPredicates predicates; + + EXPECT_EQ(number, dataabilityimpl->Delete(uri, predicates)); + sleep(1); + GTEST_LOG_(INFO) << "AaFwk_DataAbilityImplTest_Delete_0200 end"; +} + +/** + * @tc.number: AaFwk_DataAbilityImplTest_Query_0100 + * @tc.name: Query + * @tc.desc: Simulate successful test cases. + */ +HWTEST_F(DataAbilityImplTest, AaFwk_DataAbilityImplTest_Query_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityImplTest_Query_0100 start"; + std::shared_ptr dataabilityimpl = std::make_shared(); + std::shared_ptr application = std::make_shared(); + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "MockDataAbility"; + abilityInfo->type = AbilityType::DATA; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + std::shared_ptr record = std::make_shared(abilityInfo, token); + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + std::shared_ptr ability = std::make_shared(); + std::shared_ptr contextDeal = std::make_shared(); + dataabilityimpl->Init(application, record, ability, handler, token, contextDeal); + Uri uri("\nullptr"); + std::vector columns; + columns.push_back("string1"); + NativeRdb::DataAbilityPredicates predicates; + std::shared_ptr set = dataabilityimpl->Query(uri, columns, predicates); + + EXPECT_TRUE(set != nullptr); + dataabilityimpl.reset(); + sleep(1); + GTEST_LOG_(INFO) << "AaFwk_DataAbilityImplTest_Query_0100 end"; +} + +/** + * @tc.number: AaFwk_DataAbilityImplTest_Query_0200 + * @tc.name: Query + * @tc.desc: Validate when normally entering a string. + */ +HWTEST_F(DataAbilityImplTest, AaFwk_DataAbilityImplTest_Query_0200, Function | MediumTest | Level3) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityImplTest_Query_0200 start"; + std::shared_ptr dataabilityimpl = std::make_shared(); + Uri uri("\nullptr"); + std::vector columns; + columns.push_back("string1"); + NativeRdb::DataAbilityPredicates predicates; + + std::shared_ptr set = dataabilityimpl->Query(uri, columns, predicates); + EXPECT_EQ(nullptr, set); + sleep(1); + GTEST_LOG_(INFO) << "AaFwk_DataAbilityImplTest_Query_0200 end"; +} +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/test/unittest/data_ability_operation_test.cpp b/tools/frameworks/kits/ability/native/test/unittest/data_ability_operation_test.cpp new file mode 100644 index 00000000000..0d679d121ea --- /dev/null +++ b/tools/frameworks/kits/ability/native/test/unittest/data_ability_operation_test.cpp @@ -0,0 +1,728 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "abs_shared_result_set.h" +#include "data_ability_predicates.h" +#include "values_bucket.h" +#include "data_ability_operation.h" +#include "data_ability_operation_builder.h" +#include +#include "parcel.h" + +namespace OHOS { +namespace AppExecFwk { +using namespace testing::ext; +using namespace OHOS; +using namespace OHOS::AppExecFwk; +static const std::string URI = "dataability://ohos.demo.TestDataAbilityOperation"; +class DataAbilityOperationTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + void CreateBuilder(int type, std::shared_ptr &uri); + std::shared_ptr builder = nullptr; +}; + +void DataAbilityOperationTest::SetUpTestCase(void) +{} + +void DataAbilityOperationTest::TearDownTestCase(void) +{} + +void DataAbilityOperationTest::SetUp(void) +{} + +void DataAbilityOperationTest::TearDown(void) +{ + builder = nullptr; +} + +void DataAbilityOperationTest::CreateBuilder(int type, std::shared_ptr &uri) +{ + builder = std::make_shared(type, uri); +} + +/** + * @tc.number: AaFwk_DataAbilityOperation_Create_0100 + * @tc.name: Constructor + * @tc.desc: Test the dataabilityoperation object. + */ +HWTEST_F(DataAbilityOperationTest, AaFwk_DataAbilityOperation_Create_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_Create_0100 start"; + std::shared_ptr dataAbilityOperation = std::make_shared(); + EXPECT_EQ(dataAbilityOperation->GetUri(), nullptr); + EXPECT_EQ(dataAbilityOperation->GetType(), 0); + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_Create_0100 end"; +} + +/** + * @tc.number: AaFwk_DataAbilityOperation_Create_0200 + * @tc.name: Constructor + * @tc.desc: Test the dataabilityoperation object. + */ +HWTEST_F(DataAbilityOperationTest, AaFwk_DataAbilityOperation_Create_0200, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_Create_0200 start"; + Parcel in; + std::shared_ptr dataAbilityOperation = std::make_shared(in); + EXPECT_EQ(dataAbilityOperation->GetUri(), nullptr); + EXPECT_EQ(dataAbilityOperation->GetType(), -1); + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_Create_0200 end"; +} + +/** + * @tc.number: AaFwk_DataAbilityOperation_Create_0300 + * @tc.name: Constructor + * @tc.desc: Test the dataabilityoperation object. + */ +HWTEST_F(DataAbilityOperationTest, AaFwk_DataAbilityOperation_Create_0300, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_Create_0300 start"; + std::shared_ptr uri = std::make_shared(URI); + std::unique_ptr dataAbilityOperation = std::make_unique(nullptr, uri); + EXPECT_EQ(dataAbilityOperation->GetUri()->ToString(), URI); + EXPECT_EQ(dataAbilityOperation->GetType(), 0); + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_Create_0300 end"; +} + +/** + * @tc.number: AaFwk_DataAbilityOperation_Create_0400 + * @tc.name: Constructor + * @tc.desc: Test the dataabilityoperation object. + */ +HWTEST_F(DataAbilityOperationTest, AaFwk_DataAbilityOperation_Create_0400, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_Create_0400 start"; + Parcel in; + std::shared_ptr dataAbilityOperation = std::make_shared(in); + std::shared_ptr uri = std::make_shared(URI); + std::unique_ptr operation = std::make_unique(dataAbilityOperation, uri); + EXPECT_EQ(operation->GetUri()->ToString(), URI); + EXPECT_EQ(operation->GetType(), -1); + dataAbilityOperation.reset(); + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_Create_0400 end"; +} + +/** + * @tc.number: AaFwk_DataAbilityOperation_Create_0500 + * @tc.name: Constructor/GetUri + * @tc.desc: Test the dataabilityoperation object. + */ +HWTEST_F(DataAbilityOperationTest, AaFwk_DataAbilityOperation_Create_0500, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_Create_0500 start"; + std::shared_ptr uri = std::make_shared(URI); + std::shared_ptr builder = + std::make_shared(DataAbilityOperation::TYPE_INSERT, uri); + + std::unique_ptr dataAbilityOperation = std::make_unique(builder); + EXPECT_EQ(dataAbilityOperation->GetUri()->ToString(), URI); + EXPECT_EQ(dataAbilityOperation->GetType(), 1); + dataAbilityOperation.reset(); + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_Create_0500 end"; +} + +/** + * @tc.number: AaFwk_DataAbilityOperation_NewInsertBuilder_0100 + * @tc.name: NewInsertBuilder + * @tc.desc: Test whether the return value of NewInsertBuilder is DataAbilityOperationBuilder + */ +HWTEST_F(DataAbilityOperationTest, AaFwk_DataAbilityOperation_NewInsertBuilder_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_NewInsertBuilder_0100 start"; + std::shared_ptr uri = std::make_shared(URI); + + std::shared_ptr builder = DataAbilityOperation::NewInsertBuilder(uri); + EXPECT_NE(builder, nullptr); + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_NewInsertBuilder_0100 end"; +} +/** + * @tc.number: AaFwk_DataAbilityOperation_NewInsertBuilder_0200 + * @tc.name: NewInsertBuilder + * @tc.desc: Test whether the return value of NewInsertBuilder is DataAbilityOperationBuilder + */ +HWTEST_F(DataAbilityOperationTest, AaFwk_DataAbilityOperation_NewInsertBuilder_0200, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_NewInsertBuilder_0200 start"; + std::shared_ptr builder = DataAbilityOperation::NewInsertBuilder(nullptr); + EXPECT_EQ(builder, nullptr); + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_NewInsertBuilder_0200 end"; +} + +/** + * @tc.number: AaFwk_DataAbilityOperation_NewUpdateBuilder_0100 + * @tc.name: NewUpdateBuilder + * @tc.desc: Test whether the return value of NewUpdateBuilder is DataAbilityOperationBuilder + */ +HWTEST_F(DataAbilityOperationTest, AaFwk_DataAbilityOperation_NewUpdateBuilder_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_NewUpdateBuilder_0100 start"; + std::shared_ptr uri = std::make_shared(URI); + + std::shared_ptr builder = DataAbilityOperation::NewUpdateBuilder(uri); + EXPECT_NE(builder, nullptr); + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_NewUpdateBuilder_0100 end"; +} +/** + * @tc.number: AaFwk_DataAbilityOperation_NewUpdateBuilder_0200 + * @tc.name: NewUpdateBuilder + * @tc.desc: Test whether the return value of NewUpdateBuilder is DataAbilityOperationBuilder + */ +HWTEST_F(DataAbilityOperationTest, AaFwk_DataAbilityOperation_NewUpdateBuilder_0200, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_NewUpdateBuilder_0200 start"; + std::shared_ptr builder = DataAbilityOperation::NewUpdateBuilder(nullptr); + EXPECT_EQ(builder, nullptr); + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_NewUpdateBuilder_0200 end"; +} + +/** + * @tc.number: AaFwk_DataAbilityOperation_NewDeleteBuilder_0100 + * @tc.name: NewDeleteBuilder + * @tc.desc: Test whether the return value of NewDeleteBuilder is DataAbilityOperationBuilder + */ +HWTEST_F(DataAbilityOperationTest, AaFwk_DataAbilityOperation_NewDeleteBuilder_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_NewDeleteBuilder_0100 start"; + std::shared_ptr uri = std::make_shared(URI); + + std::shared_ptr builder = DataAbilityOperation::NewDeleteBuilder(uri); + EXPECT_NE(builder, nullptr); + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_NewDeleteBuilder_0100 end"; +} +/** + * @tc.number: AaFwk_DataAbilityOperation_NewDeleteBuilder_0200 + * @tc.name: NewDeleteBuilder + * @tc.desc: Test whether the return value of NewDeleteBuilder is DataAbilityOperationBuilder + */ +HWTEST_F(DataAbilityOperationTest, AaFwk_DataAbilityOperation_NewDeleteBuilder_0200, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_NewDeleteBuilder_0200 start"; + std::shared_ptr builder = DataAbilityOperation::NewDeleteBuilder(nullptr); + EXPECT_EQ(builder, nullptr); + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_NewDeleteBuilder_0200 end"; +} + +/** + * @tc.number: AaFwk_DataAbilityOperation_NewAssertBuilder_0100 + * @tc.name: NewAssertBuilder + * @tc.desc: Test whether the return value of NewAssertBuilder is DataAbilityOperationBuilder + */ +HWTEST_F(DataAbilityOperationTest, AaFwk_DataAbilityOperation_NewAssertBuilder_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_NewAssertBuilder_0100 start"; + std::shared_ptr uri = std::make_shared(URI); + + std::shared_ptr builder = DataAbilityOperation::NewAssertBuilder(uri); + EXPECT_NE(builder, nullptr); + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_NewAssertBuilder_0100 end"; +} +/** + * @tc.number: AaFwk_DataAbilityOperation_NewAssertBuilder_0200 + * @tc.name: NewAssertBuilder + * @tc.desc: Test whether the return value of NewAssertBuilder is DataAbilityOperationBuilder + */ +HWTEST_F(DataAbilityOperationTest, AaFwk_DataAbilityOperation_NewAssertBuilder_0200, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_NewAssertBuilder_0200 start"; + std::shared_ptr builder = DataAbilityOperation::NewAssertBuilder(nullptr); + EXPECT_EQ(builder, nullptr); + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_NewAssertBuilder_0200 end"; +} + +/** + * @tc.number: AaFwk_DataAbilityOperation_GetType_0100 + * @tc.name: GetType + * @tc.desc: Test whether the return value of GetType is 3 + */ +HWTEST_F(DataAbilityOperationTest, AaFwk_DataAbilityOperation_GetType_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_GetType_0100 start"; + std::shared_ptr uri = std::make_shared(URI); + CreateBuilder(DataAbilityOperation::TYPE_DELETE, uri); + std::unique_ptr dataAbilityOperation = std::make_unique(builder); + EXPECT_EQ(dataAbilityOperation->GetType(), 3); + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_GetType_0100 end"; +} +/** + * @tc.number: AaFwk_DataAbilityOperation_GetValuesBucket_0100 + * @tc.name: GetValuesBucket + * @tc.desc: Test whether the return value of GetValuesBucket is nullptr + */ +HWTEST_F(DataAbilityOperationTest, AaFwk_DataAbilityOperation_GetValuesBucket_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_GetValuesBucket_0100 start"; + std::shared_ptr uri = std::make_shared(URI); + CreateBuilder(DataAbilityOperation::TYPE_DELETE, uri); + std::unique_ptr dataAbilityOperation = std::make_unique(builder); + EXPECT_EQ(dataAbilityOperation->GetValuesBucket(), nullptr); + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_GetValuesBucket_0100 end"; +} +/** + * @tc.number: AaFwk_DataAbilityOperation_GetValuesBucket_0200 + * @tc.name: GetValuesBucket + * @tc.desc: Test whether the return value of GetValuesBucket is not nullptr + */ +HWTEST_F(DataAbilityOperationTest, AaFwk_DataAbilityOperation_GetValuesBucket_0200, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_GetValuesBucket_0200 start"; + std::shared_ptr uri = std::make_shared(URI); + std::shared_ptr values = std::make_shared(); + std::shared_ptr dataAbilityOperation = + DataAbilityOperation::NewAssertBuilder(uri)->WithValuesBucket(values)->Build(); + EXPECT_NE(dataAbilityOperation->GetValuesBucket(), nullptr); + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_GetValuesBucket_0200 end"; +} +/** + * @tc.number: AaFwk_DataAbilityOperation_GetExpectedCount_0100 + * @tc.name: GetExpectedCount + * @tc.desc: Test whether the return value of GetExpectedCount is 0 + */ +HWTEST_F(DataAbilityOperationTest, AaFwk_DataAbilityOperation_GetExpectedCount_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_GetExpectedCount_0100 start"; + std::shared_ptr uri = std::make_shared(URI); + CreateBuilder(DataAbilityOperation::TYPE_DELETE, uri); + std::unique_ptr dataAbilityOperation = std::make_unique(builder); + EXPECT_EQ(dataAbilityOperation->GetExpectedCount(), 0); + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_GetExpectedCount_0100 end"; +} +/** + * @tc.number: AaFwk_DataAbilityOperation_GetExpectedCount_0200 + * @tc.name: GetExpectedCount + * @tc.desc: Test whether the return value of GetExpectedCount is 10 + */ +HWTEST_F(DataAbilityOperationTest, AaFwk_DataAbilityOperation_GetExpectedCount_0200, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_GetExpectedCount_0200 start"; + std::shared_ptr uri = std::make_shared(URI); + std::shared_ptr dataAbilityOperation = + DataAbilityOperation::NewAssertBuilder(uri)->WithExpectedCount(10)->Build(); + EXPECT_EQ(dataAbilityOperation->GetExpectedCount(), 10); + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_GetExpectedCount_0200 end"; +} +/** + * @tc.number: AaFwk_DataAbilityOperation_GetDataAbilityPredicates_0100 + * @tc.name: GetDataAbilityPredicates + * @tc.desc: Test whether the return value of GetDataAbilityPredicates is nullptr + */ +HWTEST_F( + DataAbilityOperationTest, AaFwk_DataAbilityOperation_GetDataAbilityPredicates_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_GetDataAbilityPredicates_0100 start"; + std::shared_ptr uri = std::make_shared(URI); + CreateBuilder(DataAbilityOperation::TYPE_DELETE, uri); + std::unique_ptr dataAbilityOperation = std::make_unique(builder); + EXPECT_EQ(dataAbilityOperation->GetDataAbilityPredicates(), nullptr); + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_GetDataAbilityPredicates_0100 end"; +} +/** + * @tc.number: AaFwk_DataAbilityOperation_GetDataAbilityPredicates_0200 + * @tc.name: GetDataAbilityPredicates + * @tc.desc: Test whether the return value of GetDataAbilityPredicates is not nullptr + */ +HWTEST_F( + DataAbilityOperationTest, AaFwk_DataAbilityOperation_GetDataAbilityPredicates_0200, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_GetDataAbilityPredicates_0200 start"; + std::shared_ptr uri = std::make_shared(URI); + std::shared_ptr predicates = std::make_shared(); + std::shared_ptr dataAbilityOperation = + DataAbilityOperation::NewAssertBuilder(uri)->WithPredicates(predicates)->Build(); + EXPECT_NE(dataAbilityOperation->GetDataAbilityPredicates(), nullptr); + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_GetDataAbilityPredicates_0200 end"; +} +/** + * @tc.number: AaFwk_DataAbilityOperation_GetValuesBucketReferences_0100 + * @tc.name: GetValuesBucketReferences + * @tc.desc: Test whether the return value of GetValuesBucketReferences is nullptr + */ +HWTEST_F( + DataAbilityOperationTest, AaFwk_DataAbilityOperation_GetValuesBucketReferences_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_GetValuesBucketReferences_0100 start"; + std::shared_ptr uri = std::make_shared(URI); + CreateBuilder(DataAbilityOperation::TYPE_DELETE, uri); + + std::unique_ptr dataAbilityOperation = std::make_unique(builder); + EXPECT_EQ(dataAbilityOperation->GetValuesBucketReferences(), nullptr); + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_GetValuesBucketReferences_0100 end"; +} +/** + * @tc.number: AaFwk_DataAbilityOperation_GetValuesBucketReferences_0200 + * @tc.name: GetValuesBucketReferences + * @tc.desc: Test whether the return value of GetValuesBucketReferences is not nullptr + */ +HWTEST_F( + DataAbilityOperationTest, AaFwk_DataAbilityOperation_GetValuesBucketReferences_0200, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_GetValuesBucketReferences_0200 start"; + std::shared_ptr uri = std::make_shared(URI); + std::shared_ptr backReferences = std::make_shared(); + std::shared_ptr dataAbilityOperation = + DataAbilityOperation::NewAssertBuilder(uri)->WithValueBackReferences(backReferences)->Build(); + EXPECT_NE(dataAbilityOperation->GetValuesBucketReferences(), nullptr); + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_GetValuesBucketReferences_0200 end"; +} +/** + * @tc.number: AaFwk_DataAbilityOperation_GetDataAbilityPredicatesBackReferences_0100 + * @tc.name: GetDataAbilityPredicatesBackReferences + * @tc.desc: Test whether the return value of GetDataAbilityPredicatesBackReferences is empty + */ +HWTEST_F(DataAbilityOperationTest, AaFwk_DataAbilityOperation_GetDataAbilityPredicatesBackReferences_0100, + Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_GetDataAbilityPredicatesBackReferences_0100 start"; + std::shared_ptr uri = std::make_shared(URI); + CreateBuilder(DataAbilityOperation::TYPE_DELETE, uri); + + std::unique_ptr dataAbilityOperation = std::make_unique(builder); + std::map map = dataAbilityOperation->GetDataAbilityPredicatesBackReferences(); + EXPECT_TRUE(map.empty()); + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_GetDataAbilityPredicatesBackReferences_0100 end"; +} +/** + * @tc.number: AaFwk_DataAbilityOperation_GetDataAbilityPredicatesBackReferences_0200 + * @tc.name: GetDataAbilityPredicatesBackReferences + * @tc.desc: Test whether the value of the return value is 5 + */ +HWTEST_F(DataAbilityOperationTest, AaFwk_DataAbilityOperation_GetDataAbilityPredicatesBackReferences_0200, + Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_GetDataAbilityPredicatesBackReferences_0200 start"; + std::shared_ptr uri = std::make_shared(URI); + std::shared_ptr dataAbilityOperation = + DataAbilityOperation::NewAssertBuilder(uri)->WithPredicatesBackReference(2, 5)->Build(); + std::map map = dataAbilityOperation->GetDataAbilityPredicatesBackReferences(); + std::map::iterator iter; + iter = map.find(2); + EXPECT_EQ(iter->second, 5); + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_GetDataAbilityPredicatesBackReferences_0200 end"; +} +/** + * @tc.number: AaFwk_DataAbilityOperation_IsInsertOperation_0100 + * @tc.name: IsInsertOperation + * @tc.desc: Test whether the return value of IsInsertOperation is true + */ +HWTEST_F(DataAbilityOperationTest, AaFwk_DataAbilityOperation_IsInsertOperation_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_IsInsertOperation_0100 start"; + std::shared_ptr uri = std::make_shared(URI); + CreateBuilder(DataAbilityOperation::TYPE_INSERT, uri); + + std::unique_ptr dataAbilityOperation = std::make_unique(builder); + EXPECT_TRUE(dataAbilityOperation->IsInsertOperation()); + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_IsInsertOperation_0100 end"; +} +/** + * @tc.number: AaFwk_DataAbilityOperation_IsInsertOperation_0200 + * @tc.name: IsInsertOperation + * @tc.desc: Test whether the return value of IsInsertOperation is false + */ +HWTEST_F(DataAbilityOperationTest, AaFwk_DataAbilityOperation_IsInsertOperation_0200, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_IsInsertOperation_0200 start"; + std::shared_ptr uri = std::make_shared(URI); + CreateBuilder(DataAbilityOperation::TYPE_UPDATE, uri); + + std::unique_ptr dataAbilityOperation = std::make_unique(builder); + EXPECT_FALSE(dataAbilityOperation->IsInsertOperation()); + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_IsInsertOperation_0200 end"; +} +/** + * @tc.number: AaFwk_DataAbilityOperation_IsUpdateOperation_0100 + * @tc.name: IsUpdateOperation + * @tc.desc: Test whether the return value of IsUpdateOperation is true + */ +HWTEST_F(DataAbilityOperationTest, AaFwk_DataAbilityOperation_IsUpdateOperation_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_IsUpdateOperation_0100 start"; + std::shared_ptr uri = std::make_shared(URI); + CreateBuilder(DataAbilityOperation::TYPE_UPDATE, uri); + + std::unique_ptr dataAbilityOperation = std::make_unique(builder); + EXPECT_TRUE(dataAbilityOperation->IsUpdateOperation()); + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_IsUpdateOperation_0100 end"; +} +/** + * @tc.number: AaFwk_DataAbilityOperation_IsUpdateOperation_0200 + * @tc.name: IsUpdateOperation + * @tc.desc: Test whether the return value of IsUpdateOperation is false + */ +HWTEST_F(DataAbilityOperationTest, AaFwk_DataAbilityOperation_IsUpdateOperation_0200, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_IsUpdateOperation_0200 start"; + std::shared_ptr uri = std::make_shared(URI); + CreateBuilder(DataAbilityOperation::TYPE_DELETE, uri); + + std::unique_ptr dataAbilityOperation = std::make_unique(builder); + EXPECT_FALSE(dataAbilityOperation->IsUpdateOperation()); + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_IsUpdateOperation_0200 end"; +} +/** + * @tc.number: AaFwk_DataAbilityOperation_IsDeleteOperation_0100 + * @tc.name: IsDeleteOperation + * @tc.desc: Test whether the return value of IsDeleteOperation is true + */ +HWTEST_F(DataAbilityOperationTest, AaFwk_DataAbilityOperation_IsDeleteOperation_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_IsDeleteOperation_0100 start"; + std::shared_ptr uri = std::make_shared(URI); + CreateBuilder(DataAbilityOperation::TYPE_DELETE, uri); + + std::unique_ptr dataAbilityOperation = std::make_unique(builder); + EXPECT_TRUE(dataAbilityOperation->IsDeleteOperation()); + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_IsDeleteOperation_0100 end"; +} +/** + * @tc.number: AaFwk_DataAbilityOperation_IsDeleteOperation_0200 + * @tc.name: IsDeleteOperation + * @tc.desc: Test whether the return value of IsDeleteOperation is false + */ +HWTEST_F(DataAbilityOperationTest, AaFwk_DataAbilityOperation_IsDeleteOperation_0200, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_IsDeleteOperation_0200 start"; + std::shared_ptr uri = std::make_shared(URI); + CreateBuilder(DataAbilityOperation::TYPE_ASSERT, uri); + + std::unique_ptr dataAbilityOperation = std::make_unique(builder); + EXPECT_FALSE(dataAbilityOperation->IsDeleteOperation()); + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_IsDeleteOperation_0200 end"; +} + +/** + * @tc.number: AaFwk_DataAbilityOperation_IsAssertOperation_0100 + * @tc.name: IsAssertOperation + * @tc.desc: Test whether the return value of IsAssertOperation is true + */ +HWTEST_F(DataAbilityOperationTest, AaFwk_DataAbilityOperation_IsAssertOperation_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_IsAssertOperation_0100 start"; + std::shared_ptr uri = std::make_shared(URI); + CreateBuilder(DataAbilityOperation::TYPE_ASSERT, uri); + + std::unique_ptr dataAbilityOperation = std::make_unique(builder); + EXPECT_TRUE(dataAbilityOperation->IsAssertOperation()); + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_IsAssertOperation_0100 end"; +} +/** + * @tc.number: AaFwk_DataAbilityOperation_IsAssertOperation_0200 + * @tc.name: IsAssertOperation + * @tc.desc: Test whether the return value of IsAssertOperation is false + */ +HWTEST_F(DataAbilityOperationTest, AaFwk_DataAbilityOperation_IsAssertOperation_0200, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_IsAssertOperation_0200 start"; + std::shared_ptr uri = std::make_shared(URI); + CreateBuilder(DataAbilityOperation::TYPE_DELETE, uri); + + std::unique_ptr dataAbilityOperation = std::make_unique(builder); + EXPECT_FALSE(dataAbilityOperation->IsAssertOperation()); + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_IsAssertOperation_0200 end"; +} +/** + * @tc.number: AaFwk_DataAbilityOperation_IsInterruptionAllowed_0100 + * @tc.name: IsInterruptionAllowed + * @tc.desc: Test whether the return value of IsInterruptionAllowed is false + */ +HWTEST_F( + DataAbilityOperationTest, AaFwk_DataAbilityOperation_IsInterruptionAllowed_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_IsInterruptionAllowed_0100 start"; + std::shared_ptr uri = std::make_shared(URI); + CreateBuilder(DataAbilityOperation::TYPE_DELETE, uri); + + std::unique_ptr dataAbilityOperation = std::make_unique(builder); + EXPECT_FALSE(dataAbilityOperation->IsInterruptionAllowed()); + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_IsInterruptionAllowed_0100 end"; +} +/** + * @tc.number: AaFwk_DataAbilityOperation_IsInterruptionAllowed_0200 + * @tc.name: IsInterruptionAllowed + * @tc.desc: Test whether the return value of IsInterruptionAllowed is true + */ +HWTEST_F( + DataAbilityOperationTest, AaFwk_DataAbilityOperation_IsInterruptionAllowed_0200, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_IsInterruptionAllowed_0200 start"; + std::shared_ptr uri = std::make_shared(URI); + CreateBuilder(DataAbilityOperation::TYPE_DELETE, uri); + builder = builder->WithInterruptionAllowed(true); + EXPECT_NE(builder, nullptr); + std::unique_ptr dataAbilityOperation = std::make_unique(builder); + EXPECT_TRUE(dataAbilityOperation->IsInterruptionAllowed()); + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_IsInterruptionAllowed_0200 end"; +} + +/** + * @tc.number: AaFwk_DataAbilityOperation_CreateFromParcel_0100 + * @tc.name: CreateFromParcel + * @tc.desc: Test whether the return value of CreateFromParcel is not nullptr + */ +HWTEST_F(DataAbilityOperationTest, AaFwk_DataAbilityOperation_CreateFromParcel_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_CreateFromParcel_0100 start"; + Parcel in; + std::shared_ptr dataAbilityOperation = DataAbilityOperation::CreateFromParcel(in); + EXPECT_NE(dataAbilityOperation, nullptr); + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_CreateFromParcel_0100 end"; +} + +/** + * @tc.number: AaFwk_DataAbilityOperation_Marshalling_0100 + * @tc.name: Marshalling + * @tc.desc: Validation serialization. + */ +HWTEST_F(DataAbilityOperationTest, AaFwk_DataAbilityOperation_Marshalling_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_Marshalling_0100 start"; + + std::shared_ptr uri = std::make_shared(URI); + std::shared_ptr dataAbilityOperation = DataAbilityOperation::NewAssertBuilder(uri) + ->WithInterruptionAllowed(true) + ->WithPredicatesBackReference(0, 0) + ->Build(); + std::map references = dataAbilityOperation->GetDataAbilityPredicatesBackReferences(); + for (int i = 0; i < 3 * 1024 * 1024 + 1; i++) { + references.insert(std::make_pair(i, i)); + } + + Parcel out; + dataAbilityOperation->Marshalling(out); + + EXPECT_TRUE(out.GetReadableBytes() < 3 * 1024 * 1024); + + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_Marshalling_0100 end"; +} +/** + * @tc.number: AaFwk_DataAbilityOperation_Unmarshalling_0100 + * @tc.name: Unmarshalling + * @tc.desc: Validation serialization. + */ +HWTEST_F(DataAbilityOperationTest, AaFwk_DataAbilityOperation_Unmarshalling_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_Unmarshalling_0100 start"; + + std::shared_ptr uri = std::make_shared(URI); + std::shared_ptr dataAbilityOperation = DataAbilityOperation::NewAssertBuilder(uri) + ->WithInterruptionAllowed(true) + ->WithPredicatesBackReference(0, 0) + ->Build(); + Parcel in; + dataAbilityOperation->Marshalling(in); + DataAbilityOperation *pDataAbilityOperation = DataAbilityOperation::Unmarshalling(in); + std::map references = dataAbilityOperation->GetDataAbilityPredicatesBackReferences(); + EXPECT_TRUE(references.size() == 1); + delete pDataAbilityOperation; + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_Unmarshalling_0100 end"; +} +/** + * @tc.number: AaFwk_DataAbilityOperationBuilder_WithValuesBucket_0100 + * @tc.name: WithValuesBucket + * @tc.desc: Test whether the return value of WithValuesBucket is nullptr + */ +HWTEST_F( + DataAbilityOperationTest, AaFwk_DataAbilityOperationBuilder_WithValuesBucket_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperationBuilder_WithValuesBucket_0100 start"; + std::shared_ptr uri = std::make_shared(URI); + CreateBuilder(DataAbilityOperation::TYPE_DELETE, uri); + std::shared_ptr values = std::make_shared(); + builder = builder->WithValuesBucket(values); + EXPECT_EQ(builder, nullptr); + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperationBuilder_WithValuesBucket_0100 end"; +} +/** + * @tc.number: AaFwk_DataAbilityOperationBuilder_WithPredicates_0100 + * @tc.name: WithPredicates + * @tc.desc: Test whether the return value of WithPredicates is nullptr + */ +HWTEST_F( + DataAbilityOperationTest, AaFwk_DataAbilityOperationBuilder_WithPredicates_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperationBuilder_WithPredicates_0100 start"; + std::shared_ptr uri = std::make_shared(URI); + CreateBuilder(DataAbilityOperation::TYPE_INSERT, uri); + std::shared_ptr predicates = std::make_shared(); + builder = builder->WithPredicates(predicates); + EXPECT_EQ(builder, nullptr); + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperationBuilder_WithPredicates_0100 end"; +} +/** + * @tc.number: AaFwk_DataAbilityOperationBuilder_WithExpectedCount_0100 + * @tc.name: WithExpectedCount + * @tc.desc: Test whether the return value of WithExpectedCount is nullptr + */ +HWTEST_F( + DataAbilityOperationTest, AaFwk_DataAbilityOperationBuilder_WithExpectedCount_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperationBuilder_WithExpectedCount_0100 start"; + std::shared_ptr uri = std::make_shared(URI); + CreateBuilder(DataAbilityOperation::TYPE_INSERT, uri); + builder = builder->WithExpectedCount(1); + EXPECT_EQ(builder, nullptr); + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperationBuilder_WithExpectedCount_0100 end"; +} +/** + * @tc.number: AaFwk_DataAbilityOperationBuilder_WithPredicatesBackReference_0100 + * @tc.name: WithPredicatesBackReference + * @tc.desc: Test whether the return value of WithPredicatesBackReference is nullptr + */ +HWTEST_F(DataAbilityOperationTest, AaFwk_DataAbilityOperationBuilder_WithPredicatesBackReference_0100, + Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperationBuilder_WithPredicatesBackReference_0100 start"; + std::shared_ptr uri = std::make_shared(URI); + CreateBuilder(DataAbilityOperation::TYPE_INSERT, uri); + builder = builder->WithPredicatesBackReference(1, 1); + EXPECT_EQ(builder, nullptr); + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperationBuilder_WithPredicatesBackReference_0100 end"; +} +/** + * @tc.number: AaFwk_DataAbilityOperationBuilder_WithValueBackReferences_0100 + * @tc.name: WithValueBackReferences + * @tc.desc: Test whether the return value of WithValueBackReferences is nullptr + */ +HWTEST_F(DataAbilityOperationTest, AaFwk_DataAbilityOperationBuilder_WithValueBackReferences_0100, + Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperationBuilder_WithValueBackReferences_0100 start"; + std::shared_ptr uri = std::make_shared(URI); + CreateBuilder(DataAbilityOperation::TYPE_DELETE, uri); + std::shared_ptr backReferences = std::make_shared(); + builder = builder->WithValueBackReferences(backReferences); + EXPECT_EQ(builder, nullptr); + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperationBuilder_WithValueBackReferences_0100 end"; +} +/** + * @tc.number: AaFwk_DataAbilityOperationBuilder_WithInterruptionAllowed_0100 + * @tc.name: WithInterruptionAllowed + * @tc.desc: Test whether the return value of WithInterruptionAllowed is nullptr + */ +HWTEST_F(DataAbilityOperationTest, AaFwk_DataAbilityOperationBuilder_WithInterruptionAllowed_0100, + Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperationBuilder_WithInterruptionAllowed_0100 start"; + std::shared_ptr uri = std::make_shared(URI); + CreateBuilder(0, uri); + builder = builder->WithInterruptionAllowed(false); + EXPECT_EQ(builder, nullptr); + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperationBuilder_WithInterruptionAllowed_0100 end"; +} +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/test/unittest/data_ability_result_test.cpp b/tools/frameworks/kits/ability/native/test/unittest/data_ability_result_test.cpp new file mode 100644 index 00000000000..37afa74f910 --- /dev/null +++ b/tools/frameworks/kits/ability/native/test/unittest/data_ability_result_test.cpp @@ -0,0 +1,279 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include "data_ability_result.h" + +using namespace testing::ext; +using namespace OHOS::AppExecFwk; + +namespace OHOS { +namespace AppExecFwk { + +static const int COUNT_NULL = 0; +static const int SET_COUNT = 1; +static const Uri uri("scheme://authority/path1/path2/path3?id = 1&name = mingming&old#fragment"); +class DataAbilityResultTest : public testing::Test { +public: + DataAbilityResultTest() + {} + ~DataAbilityResultTest() + {} + + std::shared_ptr Base_ = nullptr; + + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void DataAbilityResultTest::SetUpTestCase(void) +{} + +void DataAbilityResultTest::TearDownTestCase(void) +{} + +void DataAbilityResultTest::SetUp(void) +{ + Base_ = std::make_shared(COUNT_NULL); +} + +void DataAbilityResultTest::TearDown(void) +{} + +/** + * @tc.number: + * @tc.name: + * @tc.desc: + */ +HWTEST_F(DataAbilityResultTest, AppExecFwk_DataAbilityResult_DataAbilityResult0100, Function | MediumTest | Level1) +{ + DataAbilityResult test1(SET_COUNT); + EXPECT_EQ(SET_COUNT, test1.GetCount()); + EXPECT_EQ(std::string(""), test1.GetUri().ToString()); + + DataAbilityResult test2(uri); + EXPECT_EQ(COUNT_NULL, test2.GetCount()); + EXPECT_EQ(uri.ToString(), test2.GetUri().ToString()); + + DataAbilityResult test3(uri, SET_COUNT); + EXPECT_EQ(SET_COUNT, test3.GetCount()); + EXPECT_EQ(uri.ToString(), test3.GetUri().ToString()); + + *Base_ = test3; + if (Base_) { + Parcel in; + Base_->Marshalling(in); + DataAbilityResult test4(in); + EXPECT_EQ(SET_COUNT, test4.GetCount()); + EXPECT_EQ(uri.ToString(), test4.GetUri().ToString()); + } +} + +/** + * @tc.number: + * @tc.name: + * @tc.desc: + */ +HWTEST_F(DataAbilityResultTest, AppExecFwk_DataAbilityResult_DataAbilityResult0200, Function | MediumTest | Level1) +{ + DataAbilityResult test1(COUNT_NULL); + EXPECT_EQ(COUNT_NULL, test1.GetCount()); + EXPECT_EQ(std::string(""), test1.GetUri().ToString()); + + Uri zero(""); + DataAbilityResult test2(zero); + EXPECT_EQ(COUNT_NULL, test2.GetCount()); + EXPECT_EQ(zero.ToString(), test2.GetUri().ToString()); + + DataAbilityResult test3(uri, SET_COUNT); + EXPECT_EQ(SET_COUNT, test3.GetCount()); + EXPECT_EQ(uri.ToString(), test3.GetUri().ToString()); + + Parcel in; + test3.Marshalling(in); + DataAbilityResult test4(in); + EXPECT_EQ(SET_COUNT, test4.GetCount()); + EXPECT_EQ(uri.ToString(), test4.GetUri().ToString()); +} + +/** + * @tc.number: + * @tc.name: + * @tc.desc: + */ +HWTEST_F(DataAbilityResultTest, AppExecFwk_DataAbilityResult_Get0100, Function | MediumTest | Level1) +{ + // Uri uri("abc"); + DataAbilityResult test(uri, SET_COUNT); + EXPECT_EQ(SET_COUNT, test.GetCount()); + EXPECT_EQ(uri.ToString(), test.GetUri().ToString()); +} + +/** + * @tc.number: + * @tc.name: + * @tc.desc: + */ +HWTEST_F(DataAbilityResultTest, AppExecFwk_DataAbilityResult_Get0200, Function | MediumTest | Level1) +{ + EXPECT_EQ(true, Base_->GetUri().ToString().empty()); + EXPECT_EQ(COUNT_NULL, Base_->GetCount()); +} + +/** + * @tc.number: + * @tc.name: + * @tc.desc: + */ +HWTEST_F(DataAbilityResultTest, AppExecFwk_DataAbilityResult_CreateFromParcel0100, Function | MediumTest | Level1) +{ + Parcel in; + Base_->Marshalling(in); + DataAbilityResult *ptr = Base_->CreateFromParcel(in); + + if (ptr != nullptr) { + EXPECT_EQ(true, ptr->GetUri().ToString().empty()); + EXPECT_EQ(COUNT_NULL, ptr->GetCount()); + } +} + +/** + * @tc.number: + * @tc.name: + * @tc.desc: + */ +HWTEST_F(DataAbilityResultTest, AppExecFwk_DataAbilityResult_ToString0100, Function | MediumTest | Level1) +{ + std::string search = "DataAbilityResult("; + std::size_t pos = 0; + std::size_t result = 0; + + DataAbilityResult dataAbilityResult(uri, SET_COUNT); + std::string str = dataAbilityResult.ToString(); + + result = str.find(search, pos); + EXPECT_EQ(result, pos); + if (result != std::string::npos) { + pos += search.length() - 1; + } + + search = std::string("uri=") + uri.ToString() + std::string(" "); + result = str.find(search, pos); + + EXPECT_NE(result, std::string::npos); + EXPECT_GE(result, pos); + if (result != std::string::npos) { + pos += search.length(); + } + + search = std::string("count=") + std::to_string(dataAbilityResult.GetCount()) + std::string(")"); + result = str.find(search, pos); + EXPECT_NE(result, std::string::npos); + EXPECT_GE(result, pos); + if (result != std::string::npos) { + pos += search.length() + 1; + } + + EXPECT_EQ(str.length(), pos); +} + +/** + * @tc.number: + * @tc.name: + * @tc.desc: + */ +HWTEST_F(DataAbilityResultTest, AppExecFwk_DataAbilityResult_ToString0200, Function | MediumTest | Level1) +{ + + std::string search = "DataAbilityResult("; + std::size_t pos = 0; + std::size_t result = 0; + + DataAbilityResult dataAbilityResult(COUNT_NULL); + std::string str = dataAbilityResult.ToString(); + + result = str.find(search, pos); + EXPECT_EQ(result, pos); + if (result != std::string::npos) { + pos += search.length() - 1; + } + + search = std::string("uri=") + dataAbilityResult.GetUri().ToString() + std::string(" "); + result = str.find(search, pos); + + EXPECT_NE(result, std::string::npos); + EXPECT_GE(result, pos); + if (result != std::string::npos) { + pos += search.length(); + } + + search = std::string("count=") + std::to_string(dataAbilityResult.GetCount()) + std::string(")"); + result = str.find(search, pos); + EXPECT_NE(result, std::string::npos); + EXPECT_GE(result, pos); + if (result != std::string::npos) { + pos += search.length() + 1; + } + + EXPECT_EQ(str.length(), pos); +} + +/** + * @tc.number: + * @tc.name: Marshalling/Unmarshalling + * @tc.desc: marshalling + */ +HWTEST_F(DataAbilityResultTest, AppExecFwk_DataAbilityResult_Parcelable_0100, Function | MediumTest | Level1) +{ + std::shared_ptr ResultIn_ = std::make_shared(COUNT_NULL); + if (ResultIn_ == nullptr) { + return; + } + + Parcel in; + ResultIn_->Marshalling(in); + std::shared_ptr ResultOut_(DataAbilityResult::Unmarshalling(in)); + + if (ResultOut_ != nullptr) { + EXPECT_EQ(ResultIn_->GetUri().ToString(), ResultOut_->GetUri().ToString()); + EXPECT_EQ(ResultIn_->GetCount(), ResultOut_->GetCount()); + } +} + +/** + * @tc.number: + * @tc.name: Marshalling/Unmarshalling + * @tc.desc: + */ +HWTEST_F(DataAbilityResultTest, AppExecFwk_DataAbilityResult_Parcelable_0200, Function | MediumTest | Level1) +{ + std::shared_ptr ResultIn_ = std::make_shared(uri); + if (ResultIn_ == nullptr) { + return; + } + + Parcel in; + ResultIn_->Marshalling(in); + std::shared_ptr ResultOut_(DataAbilityResult::Unmarshalling(in)); + + if (ResultOut_ != nullptr) { + EXPECT_EQ(ResultIn_->GetUri().ToString(), ResultOut_->GetUri().ToString()); + EXPECT_EQ(ResultIn_->GetCount(), ResultOut_->GetCount()); + } +} + +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/test/unittest/data_uri_utils_test.cpp b/tools/frameworks/kits/ability/native/test/unittest/data_uri_utils_test.cpp new file mode 100644 index 00000000000..42ef7219443 --- /dev/null +++ b/tools/frameworks/kits/ability/native/test/unittest/data_uri_utils_test.cpp @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "data_uri_utils.h" +#include +#include "uri.h" + +namespace OHOS { +namespace AppExecFwk { +using namespace testing::ext; +using namespace OHOS::AppExecFwk; + +class DataUriUtilsTest : public testing::Test { +public: + DataUriUtilsTest() + {} + ~DataUriUtilsTest() + {} + + std::unique_ptr data_uri_util_ = nullptr; + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void DataUriUtilsTest::SetUpTestCase(void) +{} +void DataUriUtilsTest::TearDownTestCase(void) +{} +void DataUriUtilsTest::SetUp() +{ + data_uri_util_ = std::make_unique(); +} + +void DataUriUtilsTest::TearDown() +{} + +// URI: scheme://authority/path1/path2/path3?id = 1&name = mingming&old#fragment +/** + * @tc.number: AaFwk_DataUriUtils_AttachId_GetId_0100 + * @tc.name: AttachId/GetId + * @tc.desc: Test if attachd and getid return values are correct. + */ +HWTEST_F(DataUriUtilsTest, AaFwk_DataUriUtils_AttachId_Get001, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataUriUtils_001 start"; + + Uri uri("scheme://authority/path1/path2/path3?id = 1&name = mingming&old#fragment"); + Uri uriRet1 = DataUriUtils::AttachId(uri, 1000); + + long long ret1 = DataUriUtils::GetId(uriRet1); + EXPECT_EQ(ret1, 1000); + + GTEST_LOG_(INFO) << "AaFwk_DataUriUtils_001 end"; +} + +/** + * @tc.number: AaFwk_DataUriUtils_AttachId_GetId_0100 + * @tc.name: AttachId/DeleteId/IsAttachedId + * @tc.desc: Test whether the return values of attachid, deleteid and isattachedidare correct. + */ +HWTEST_F(DataUriUtilsTest, AaFwk_DataUriUtils_DeleteId_IsAttachedId001, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataUriUtils_DeleteId_IsAttachedId001 start"; + + Uri uri("scheme://authority/path1/path2/path3?id = 1&name = mingming&old#fragment"); + Uri uriRet1 = DataUriUtils::AttachId(uri, 1000); + + Uri uriRet2 = DataUriUtils::DeleteId(uriRet1); + + bool ret2 = DataUriUtils::IsAttachedId(uriRet2); + EXPECT_EQ(ret2, false); + + GTEST_LOG_(INFO) << "AaFwk_DataUriUtils_DeleteId_IsAttachedId001 end"; +} + +/** + * @tc.number: AaFwk_DataUriUtils_DeleteId_IsAttachedId002 + * @tc.name: AttachId/DeleteId/IsAttachedId + * @tc.desc: Test whether the return values of attachid, deleteid and isattachedidare correct. + */ +HWTEST_F(DataUriUtilsTest, AaFwk_DataUriUtils_DeleteId_IsAttachedId002, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataUriUtils_DeleteId_IsAttachedId002 start"; + + Uri uri("scheme://authority/path1/path2/path3?id = 1&name = mingming&old#fragment"); + Uri uriRet1 = DataUriUtils::AttachId(uri, -1000); + Uri uriRet2 = DataUriUtils::DeleteId(uriRet1); + bool ret2 = DataUriUtils::IsAttachedId(uriRet2); + EXPECT_EQ(ret2, false); + + GTEST_LOG_(INFO) << "AaFwk_DataUriUtils_DeleteId_IsAttachedId002 end"; +} +/** + * @tc.number: AaFwk_DataUriUtils_DeleteId_IsAttachedId003 + * @tc.name: AttachId/DeleteId/IsAttachedId + * @tc.desc: Test whether the return values of attachid, deleteid and isattachedidare correct. + */ +HWTEST_F(DataUriUtilsTest, AaFwk_DataUriUtils_DeleteId_IsAttachedId003, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataUriUtils_DeleteId_IsAttachedId003 start"; + + Uri uri("scheme://authority/path1/path2/path3?id = 1&name = mingming&old#fragment"); + Uri uriRet1 = DataUriUtils::AttachId(uri, 123456789011); + + long long id = DataUriUtils::GetId(uriRet1); + EXPECT_EQ(id, 123456789011); + Uri uriRet2 = DataUriUtils::DeleteId(uriRet1); + + bool ret2 = DataUriUtils::IsAttachedId(uriRet2); + EXPECT_EQ(ret2, false); + + GTEST_LOG_(INFO) << "AaFwk_DataUriUtils_DeleteId_IsAttachedId003 end"; +} +/** + * @tc.number: AaFwk_DataUriUtils_AttachIdUpdateId_0100 + * @tc.name: AttachId/UpdateId/GetId + * @tc.desc: Test whether the return values of attachid, updateid and getid are correct. + */ +HWTEST_F(DataUriUtilsTest, AaFwk_DataUriUtils_AttachIdUpdateId001, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataUriUtils_AttachIdUpdateId001 start"; + + Uri uri("scheme://authority/path1/path2/path3?id = 1&name = mingming&old#fragment"); + // case 3 + Uri uriRet3 = DataUriUtils::AttachId(uri, 100); + Uri uriRet4 = DataUriUtils::UpdateId(uriRet3, 800); + long ret4Id = DataUriUtils::GetId(uriRet4); + + EXPECT_EQ(ret4Id, 800); + + GTEST_LOG_(INFO) << "AaFwk_DataUriUtils_AttachIdUpdateId001 end"; +} +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/test/unittest/form_ability_test.cpp b/tools/frameworks/kits/ability/native/test/unittest/form_ability_test.cpp new file mode 100755 index 00000000000..cdda5e9c2ce --- /dev/null +++ b/tools/frameworks/kits/ability/native/test/unittest/form_ability_test.cpp @@ -0,0 +1,1259 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#define private public +#include "ability.h" +#undef private +#include "ability_info.h" +#include "ability_handler.h" +#include "ability_local_record.h" +#include "ability_start_setting.h" +#include "context_deal.h" +#include "form_mgr.h" +#include "mock_form_mgr_service.h" +#include "mock_page_ability.h" +// #include "form_info.h" +#include "mock_bundle_manager_form.h" + +namespace OHOS { +namespace AppExecFwk { +using namespace testing::ext; +using namespace OHOS; +using namespace OHOS::AppExecFwk; +using OHOS::Parcel; + +class FormAbilityTest : public testing::Test { +public: + FormAbilityTest() : ability_(nullptr) + {} + ~FormAbilityTest() + {} + std::shared_ptr ability_; + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + +protected: + sptr mockBundleMgr_; +}; + +void FormAbilityTest::SetUpTestCase(void) +{} + +void FormAbilityTest::TearDownTestCase(void) +{} + +void FormAbilityTest::SetUp(void) +{ + ability_ = std::make_shared(); + FormMgr::GetInstance().SetFormMgrService(sptr(new (std::nothrow) MockFormMgrService())); + FormMgr::SetRecoverStatus(Constants::NOT_IN_RECOVERY); + + mockBundleMgr_ = new (std::nothrow) BundleMgrService(); + EXPECT_TRUE(mockBundleMgr_ != nullptr); + ability_->SetBundleManager(mockBundleMgr_); +} + +void FormAbilityTest::TearDown(void) +{} + +/** + * @tc.number: AaFwk_Ability_AcquireForm_0100 + * @tc.name: AcquireForm + * @tc.desc: Test whether acquireForm is called normally when want is nothing. + */ +HWTEST_F(FormAbilityTest, AaFwk_Ability_AcquireForm_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_Ability_AcquireForm_0100 start"; + + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->type = AbilityType::PAGE; + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + + ability_->Init(abilityInfo, nullptr, handler, nullptr); + + Want want; + std::shared_ptr callback; + + EXPECT_EQ(false, ability_->AcquireForm(0, want, callback)); + + GTEST_LOG_(INFO) << "AaFwk_Ability_AcquireForm_0100 end"; +} + +/** + * @tc.number: AaFwk_Ability_AcquireForm_0200 + * @tc.name: AcquireForm + * @tc.desc: Test whether acquireForm is called normally. + */ +HWTEST_F(FormAbilityTest, AaFwk_Ability_AcquireForm_0200, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_Ability_AcquireForm_0200 start"; + + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->type = AbilityType::PAGE; + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + + ability_->Init(abilityInfo, nullptr, handler, nullptr); + + std::string formName = "Form0200"; + std::string moduleName = "ModuleName0200"; + std::string deviceId = "DeviceId0200"; + std::string bundleName = "Bundle0200"; + std::string abilityName = "Ability0200"; + bool tempFormFlg = false; + Want want; + want.SetParam(Constants::PARAM_FORM_NAME_KEY, formName) + .SetParam(Constants::PARAM_MODULE_NAME_KEY, moduleName) + .SetElementName(deviceId, bundleName, abilityName) + .SetParam(Constants::PARAM_FORM_TEMPORARY_KEY, tempFormFlg); + std::shared_ptr callback; + + EXPECT_EQ(true, ability_->AcquireForm(0, want, callback)); + + GTEST_LOG_(INFO) << "AaFwk_Ability_AcquireForm_0200 end"; +} + +/** + * @tc.number: AaFwk_Ability_AcquireForm_0300 + * @tc.name: AcquireForm + * @tc.desc: Test whether acquireForm is called normally when the same id is requested twice in succession. + */ +HWTEST_F(FormAbilityTest, AaFwk_Ability_AcquireForm_0300, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_Ability_AcquireForm_0300 start"; + + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->type = AbilityType::PAGE; + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + + ability_->Init(abilityInfo, nullptr, handler, nullptr); + + std::string formName = "Form0300"; + std::string moduleName = "ModuleName0300"; + std::string deviceId = "DeviceId0300"; + std::string bundleName = "Bundle0300"; + std::string abilityName = "Ability0300"; + bool tempFormFlg = false; + Want want; + want.SetParam(Constants::PARAM_FORM_NAME_KEY, formName) + .SetParam(Constants::PARAM_MODULE_NAME_KEY, moduleName) + .SetElementName(deviceId, bundleName, abilityName) + .SetParam(Constants::PARAM_FORM_TEMPORARY_KEY, tempFormFlg); + std::shared_ptr callback; + + // first request + ability_->AcquireForm(300, want, callback); + // second request by same want + EXPECT_EQ(false, ability_->AcquireForm(300, want, callback)); + + GTEST_LOG_(INFO) << "AaFwk_Ability_AcquireForm_0300 end"; +} + +/** + * @tc.number: AaFwk_Ability_AcquireForm_0400 + * @tc.name: AcquireForm + * @tc.desc: Test whether acquireForm is called normally when form id is negative in want + */ +HWTEST_F(FormAbilityTest, AaFwk_Ability_AcquireForm_0400, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_Ability_AcquireForm_0400 start"; + + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->type = AbilityType::PAGE; + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + + ability_->Init(abilityInfo, nullptr, handler, nullptr); + + std::string formName = "Form0400"; + std::string moduleName = "ModuleName0400"; + std::string deviceId = "DeviceId0400"; + std::string bundleName = "Bundle0400"; + std::string abilityName = "Ability0400"; + bool tempFormFlg = false; + Want want; + want.SetParam(Constants::PARAM_FORM_NAME_KEY, formName) + .SetParam(Constants::PARAM_MODULE_NAME_KEY, moduleName) + .SetElementName(deviceId, bundleName, abilityName) + .SetParam(Constants::PARAM_FORM_TEMPORARY_KEY, tempFormFlg); + std::shared_ptr callback; + + EXPECT_EQ(false, ability_->AcquireForm(-150, want, callback)); + + GTEST_LOG_(INFO) << "AaFwk_Ability_AcquireForm_0400 end"; +} + +/** + * @tc.number: AaFwk_Ability_AcquireForm_0500 + * @tc.name: AcquireForm + * @tc.desc: Test whether acquireForm is called normally when select form id when acquire temporary form + */ +HWTEST_F(FormAbilityTest, AaFwk_Ability_AcquireForm_0500, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_Ability_AcquireForm_0500 start"; + + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->type = AbilityType::PAGE; + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + + ability_->Init(abilityInfo, nullptr, handler, nullptr); + + std::string formName = "Form0500"; + std::string moduleName = "ModuleName0500"; + std::string deviceId = "DeviceId0500"; + std::string bundleName = "Bundle0500"; + std::string abilityName = "Ability0500"; + bool tempFormFlg = true; + Want want; + want.SetParam(Constants::PARAM_FORM_NAME_KEY, formName) + .SetParam(Constants::PARAM_MODULE_NAME_KEY, moduleName) + .SetElementName(deviceId, bundleName, abilityName) + .SetParam(Constants::PARAM_FORM_TEMPORARY_KEY, tempFormFlg); + std::shared_ptr callback; + + EXPECT_EQ(false, ability_->AcquireForm(60, want, callback)); + + GTEST_LOG_(INFO) << "AaFwk_Ability_AcquireForm_0500 end"; +} + +/** + * @tc.number: AaFwk_Ability_AcquireForm_0600 + * @tc.name: AcquireForm + * @tc.desc: Test whether acquireForm is called normally when dimension is zero or negative in want + */ +HWTEST_F(FormAbilityTest, AaFwk_Ability_AcquireForm_0600, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_Ability_AcquireForm_0600 start"; + + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->type = AbilityType::PAGE; + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + + ability_->Init(abilityInfo, nullptr, handler, nullptr); + + std::string formName = "Form0600"; + std::string moduleName = "ModuleName0600"; + std::string deviceId = "DeviceId0600"; + std::string bundleName = "Bundle0600"; + std::string abilityName = "Ability0600"; + bool tempFormFlg = false; + Want want; + want.SetParam(Constants::PARAM_FORM_NAME_KEY, formName) + .SetParam(Constants::PARAM_MODULE_NAME_KEY, moduleName) + .SetElementName(deviceId, bundleName, abilityName) + .SetParam(Constants::PARAM_FORM_TEMPORARY_KEY, tempFormFlg) + .SetParam(Constants::PARAM_FORM_DIMENSION_KEY, -1); + std::shared_ptr callback; + + EXPECT_EQ(false, ability_->AcquireForm(0, want, callback)); + + GTEST_LOG_(INFO) << "AaFwk_Ability_AcquireForm_0600 end"; +} + +/** + * @tc.number: AaFwk_Ability_UpdateForm_0100 + * @tc.name: UpdateForm + * @tc.desc: Test whether updateForm is called normally when jsonFormProviderData is empty. + */ +HWTEST_F(FormAbilityTest, AaFwk_Ability_UpdateForm_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_Ability_UpdateForm_0100 start"; + + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->type = AbilityType::PAGE; + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + + ability_->Init(abilityInfo, nullptr, handler, nullptr); + + int64_t formId = 100; + FormProviderData formProviderData; + + EXPECT_EQ(false, ability_->UpdateForm(formId, formProviderData)); + + GTEST_LOG_(INFO) << "AaFwk_Ability_UpdateForm_0100 end"; +} + +/** + * @tc.number: AaFwk_Ability_UpdateForm_0200 + * @tc.name: UpdateForm + * @tc.desc: Test whether updateForm is called normally when recoverStatus is recovering. + */ +HWTEST_F(FormAbilityTest, AaFwk_Ability_UpdateForm_0200, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_Ability_UpdateForm_0200 start"; + + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->type = AbilityType::PAGE; + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + + ability_->Init(abilityInfo, nullptr, handler, nullptr); + + int64_t formId = 200L; + FormProviderData formProviderData = FormProviderData(std::string("{\"city\": \"beijing200\"}")); + FormMgr::SetRecoverStatus(Constants::IN_RECOVERING); + + EXPECT_EQ(false, ability_->UpdateForm(formId, formProviderData)); + + GTEST_LOG_(INFO) << "AaFwk_Ability_UpdateForm_0200 end"; +} + +/** + * @tc.number: AaFwk_Ability_UpdateForm_0300 + * @tc.name: UpdateForm + * @tc.desc: Test whether updateForm is called normally when fms is error. + */ +HWTEST_F(FormAbilityTest, AaFwk_Ability_UpdateForm_0300, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_Ability_UpdateForm_0300 start"; + + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->type = AbilityType::PAGE; + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + + ability_->Init(abilityInfo, nullptr, handler, nullptr); + + int64_t formId = 300L; + FormProviderData formProviderData = FormProviderData(std::string("{\"city\": \"beijing300\"}")); + FormMgr::SetRecoverStatus(Constants::NOT_IN_RECOVERY); + + EXPECT_EQ(false, ability_->UpdateForm(formId, formProviderData)); + + GTEST_LOG_(INFO) << "AaFwk_Ability_UpdateForm_0300 end"; +} + +/** + * @tc.number: AaFwk_Ability_UpdateForm_0400 + * @tc.name: UpdateForm + * @tc.desc: Test whether updateForm is called normally when fms is ok. + */ +HWTEST_F(FormAbilityTest, AaFwk_Ability_UpdateForm_0400, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_Ability_UpdateForm_0400 start"; + + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->type = AbilityType::PAGE; + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + + ability_->Init(abilityInfo, nullptr, handler, nullptr); + + int64_t formId = 400L; + FormProviderData formProviderData = FormProviderData(std::string("{\"city\": \"beijing400\"}")); + + EXPECT_EQ(true, ability_->UpdateForm(formId, formProviderData)); + + GTEST_LOG_(INFO) << "AaFwk_Ability_UpdateForm_0400 end"; +} +/** + * @tc.number: AaFwk_Ability_DeleteForm_0100 + * @tc.name: DeleteForm + * @tc.desc: Test whether DeleteForm is called normally + */ +HWTEST_F(FormAbilityTest, AaFwk_Ability_DeleteForm_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_Ability_DeleteForm_0100 start"; + + std::string formName1 = "Form0101"; + std::string moduleName1 = "ModuleName0101"; + std::string deviceId1 = "DeviceId0101"; + std::string bundleName1 = "Bundle0101"; + std::string abilityName1 = "Ability0101"; + bool tempFormFlg1 = false; + Want want1; + want1.SetParam(Constants::PARAM_FORM_IDENTITY_KEY, 120L) + .SetParam(Constants::PARAM_FORM_NAME_KEY, formName1) + .SetParam(Constants::PARAM_MODULE_NAME_KEY, moduleName1) + .SetElementName(deviceId1, bundleName1, abilityName1) + .SetParam(Constants::PARAM_FORM_TEMPORARY_KEY, tempFormFlg1); + std::shared_ptr callback1; + + std::string formName2 = "Form0102"; + std::string moduleName2 = "ModuleName0102"; + std::string deviceId2 = "DeviceId0102"; + std::string bundleName2 = "Bundle0102"; + std::string abilityName2 = "Ability0102"; + bool tempFormFlg2 = false; + Want want2; + want2.SetParam(Constants::PARAM_FORM_IDENTITY_KEY, 121L) + .SetParam(Constants::PARAM_FORM_NAME_KEY, formName2) + .SetParam(Constants::PARAM_MODULE_NAME_KEY, moduleName2) + .SetElementName(deviceId2, bundleName2, abilityName2) + .SetParam(Constants::PARAM_FORM_TEMPORARY_KEY, tempFormFlg2); + std::shared_ptr callback_2; + + ability_->appCallbacks_.insert(std::make_pair(120L, callback1)); + ability_->userReqParams_.insert(std::make_pair(120L, want1)); + ability_->appCallbacks_.insert(std::make_pair(121L, callback_2)); + ability_->userReqParams_.insert(std::make_pair(121L, want2)); + + int64_t formId = 120L; + ability_->DeleteForm(formId); + + + size_t cnt {1}; + EXPECT_EQ(cnt, ability_->appCallbacks_.size()); + + GTEST_LOG_(INFO) << "AaFwk_Ability_DeleteForm_0100 end"; +} + +/** + * @tc.number: AaFwk_Ability_DeleteForm_0200 + * @tc.name: DeleteForm + * @tc.desc: Test whether DeleteForm is called normally when form id is negative + */ +HWTEST_F(FormAbilityTest, AaFwk_Ability_DeleteForm_0200, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_Ability_DeleteForm_0200 start"; + + int64_t formId = -26; + EXPECT_EQ(false, ability_->DeleteForm(formId)); + + GTEST_LOG_(INFO) << "AaFwk_Ability_DeleteForm_0200 end"; +} + +/** + * @tc.number: AaFwk_Ability_DeleteForm_0300 + * @tc.name: DeleteForm + * @tc.desc: Test whether DeleteForm is called normally when form is in recover status + */ +HWTEST_F(FormAbilityTest, AaFwk_Ability_DeleteForm_0300, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_Ability_DeleteForm_0300 start"; + + int64_t formId = 26; + FormMgr::SetRecoverStatus(Constants::IN_RECOVERING); + + EXPECT_EQ(false, ability_->DeleteForm(formId)); + FormMgr::SetRecoverStatus(Constants::NOT_IN_RECOVERY); + + GTEST_LOG_(INFO) << "AaFwk_Ability_DeleteForm_0300 end"; +} + +/** + * @tc.number: AaFwk_Ability_DeleteForm_0400 + * @tc.name: DeleteForm + * @tc.desc: Test whether DeleteForm is called normally when form is temp form + */ +HWTEST_F(FormAbilityTest, AaFwk_Ability_DeleteForm_0400, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_Ability_DeleteForm_0400 start"; + + std::string formName1 = "Form0401"; + std::string moduleName1 = "ModuleName0401"; + std::string deviceId1 = "DeviceId0401"; + std::string bundleName1 = "Bundle0401"; + std::string abilityName1 = "Ability0401"; + bool tempFormFlg1 = true; + Want want1; + want1.SetParam(Constants::PARAM_FORM_IDENTITY_KEY, 120L) + .SetParam(Constants::PARAM_FORM_NAME_KEY, formName1) + .SetParam(Constants::PARAM_MODULE_NAME_KEY, moduleName1) + .SetElementName(deviceId1, bundleName1, abilityName1) + .SetParam(Constants::PARAM_FORM_TEMPORARY_KEY, tempFormFlg1); + std::shared_ptr callback1; + + std::string formName2 = "Form0402"; + std::string moduleName2 = "ModuleName0402"; + std::string deviceId2 = "DeviceId0402"; + std::string bundleName2 = "Bundle0402"; + std::string abilityName2 = "Ability0402"; + bool tempFormFlg2 = true; + Want want2; + want2.SetParam(Constants::PARAM_FORM_IDENTITY_KEY, 121L) + .SetParam(Constants::PARAM_FORM_NAME_KEY, formName2) + .SetParam(Constants::PARAM_MODULE_NAME_KEY, moduleName2) + .SetElementName(deviceId2, bundleName2, abilityName2) + .SetParam(Constants::PARAM_FORM_TEMPORARY_KEY, tempFormFlg2); + std::shared_ptr callback2; + + ability_->appCallbacks_.insert(std::make_pair(120L, callback1)); + ability_->userReqParams_.insert(std::make_pair(120L, want1)); + ability_->appCallbacks_.insert(std::make_pair(121L, callback2)); + ability_->userReqParams_.insert(std::make_pair(121L, want2)); + ability_->lostedByReconnectTempForms_.push_back(120L); + ability_->lostedByReconnectTempForms_.push_back(121L); + + int64_t formId = 121L; + ability_->DeleteForm(formId); + + size_t cnt {1}; + EXPECT_EQ(cnt, ability_->lostedByReconnectTempForms_.size()); + + ability_->userReqParams_.clear(); + + GTEST_LOG_(INFO) << "AaFwk_Ability_DeleteForm_0400 end"; +} + +/** + * @tc.number: AaFwk_Ability_CastTempForm_0100 + * @tc.name: CastTempForm + * @tc.desc: Test whether CastTempForm is called normally. + */ +HWTEST_F(FormAbilityTest, AaFwk_Ability_CastTempForm_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_Ability_CastTempForm_0100 start"; + + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->type = AbilityType::PAGE; + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + + ability_->Init(abilityInfo, nullptr, handler, nullptr); + + int64_t formId = 170L; + + EXPECT_EQ(true, ability_->CastTempForm(formId)); + EXPECT_EQ(false, ability_->userReqParams_[formId].GetBoolParam(Constants::PARAM_FORM_TEMPORARY_KEY, true)); + + GTEST_LOG_(INFO) << "AaFwk_Ability_CastTempForm_0100 end"; +} + +/** + * @tc.number: AaFwk_Ability_CastTempForm_0200 + * @tc.name: CastTempForm + * @tc.desc: Test whether CastTempForm is called normally. + */ +HWTEST_F(FormAbilityTest, AaFwk_Ability_CastTempForm_0200, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_Ability_CastTempForm_0200 start"; + + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->type = AbilityType::PAGE; + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + + ability_->Init(abilityInfo, nullptr, handler, nullptr); + + int64_t formId = 175L; + + EXPECT_EQ(false, ability_->CastTempForm(formId)); + + GTEST_LOG_(INFO) << "AaFwk_Ability_CastTempForm_0200 end"; +} + +/** + * @tc.number: AaFwk_Ability_CastTempForm_0300 + * @tc.name: CastTempForm + * @tc.desc: Test whether CastTempForm is called normally. + */ +HWTEST_F(FormAbilityTest, AaFwk_Ability_CastTempForm_0300, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_Ability_CastTempForm_0300 start"; + + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->type = AbilityType::PAGE; + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + + ability_->Init(abilityInfo, nullptr, handler, nullptr); + + int64_t formId = -175L; + + EXPECT_EQ(false, ability_->CastTempForm(formId)); + + GTEST_LOG_(INFO) << "AaFwk_Ability_CastTempForm_0300 end"; +} + +/** + * @tc.number: AaFwk_Ability_EnableUpdateForm_0100 + * @tc.name: EnableUpdateForm + * @tc.desc: Test whether enableUpdateForm is called normally. + */ +HWTEST_F(FormAbilityTest, AaFwk_Ability_EnableUpdateForm_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_Ability_EnableUpdateForm_0100 start"; + + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->type = AbilityType::PAGE; + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + + ability_->Init(abilityInfo, nullptr, handler, nullptr); + std::vector formIds; + EXPECT_EQ(false, ability_->EnableUpdateForm(formIds)); + + GTEST_LOG_(INFO) << "AaFwk_Ability_EnableUpdateForm_0100 end"; +} + +/** + * @tc.number: AaFwk_Ability_EnableUpdateForm_0200 + * @tc.name: EnableUpdateForm + * @tc.desc: Test whether enableUpdateForm is called normally. + */ +HWTEST_F(FormAbilityTest, AaFwk_Ability_EnableUpdateForm_0200, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_Ability_EnableUpdateForm_0200 start"; + + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->type = AbilityType::PAGE; + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + + ability_->Init(abilityInfo, nullptr, handler, nullptr); + + std::vector formIds; + formIds.push_back(200); + EXPECT_EQ(true, ability_->EnableUpdateForm(formIds)); + + GTEST_LOG_(INFO) << "AaFwk_Ability_EnableUpdateForm_0200 end"; +} + +/** + * @tc.number: AaFwk_Ability_DisableUpdateForm_0100 + * @tc.name: DisableUpdateForm + * @tc.desc: Test whether disableUpdateForm is called normally. + */ +HWTEST_F(FormAbilityTest, AaFwk_Ability_DisableUpdateForm_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_Ability_DisableUpdateForm_0100 start"; + + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->type = AbilityType::PAGE; + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + + ability_->Init(abilityInfo, nullptr, handler, nullptr); + std::vector formIds; + EXPECT_EQ(false, ability_->DisableUpdateForm(formIds)); + + GTEST_LOG_(INFO) << "AaFwk_Ability_DisableUpdateForm_0100 end"; +} + +/** + * @tc.number: AaFwk_Ability_DisableUpdateForm_0200 + * @tc.name: DisableUpdateForm + * @tc.desc: Test whether disableUpdateForm is called normally. + */ +HWTEST_F(FormAbilityTest, AaFwk_Ability_DisableUpdateForm_0200, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_Ability_DisableUpdateForm_0200 start"; + + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->type = AbilityType::PAGE; + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + + ability_->Init(abilityInfo, nullptr, handler, nullptr); + std::vector formIds; + formIds.push_back(200); + EXPECT_EQ(true, ability_->DisableUpdateForm(formIds)); + + GTEST_LOG_(INFO) << "AaFwk_Ability_DisableUpdateForm_0200 end"; +} + +/** + * @tc.number: AaFwk_Ability_DisableUpdateForm_0300 + * @tc.name: EnableUpdateForm + * @tc.desc: Test whether enableUpdateForm is called normally.(RecoverStatus is IN_RECOVERING) + */ +HWTEST_F(FormAbilityTest, AaFwk_Ability_DisableUpdateForm_0300, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_Ability_DisableUpdateForm_0300 start"; + + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->type = AbilityType::PAGE; + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + + ability_->Init(abilityInfo, nullptr, handler, nullptr); + + std::vector formIds; + formIds.push_back(300); + + // SetRecoverStatus IN_RECOVERING + volatile int recoverStatus = Constants::IN_RECOVERING; + FormMgr::GetInstance().SetRecoverStatus(recoverStatus); + + EXPECT_EQ(false, ability_->DisableUpdateForm(formIds)); + + // SetRecoverStatus NOT_IN_RECOVERY + recoverStatus = Constants::NOT_IN_RECOVERY; + FormMgr::GetInstance().SetRecoverStatus(recoverStatus); + + GTEST_LOG_(INFO) << "AaFwk_Ability_DisableUpdateForm_0300 end"; +} + +/** + * @tc.number: AaFwk_Ability_SetFormNextRefreshTime_0100 + * @tc.name: SetFormNextRefreshTime + * @tc.desc: Test whether SetFormNextRefreshTime is called normally.(next time litte than 5 mins) + */ +HWTEST_F(FormAbilityTest, AaFwk_Ability_SetFormNextRefreshTime_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_Ability_SetFormNextRefreshTime_0100 start"; + int64_t formId = 100; + int64_t nextTime = Constants::MIN_NEXT_TIME - 1; + EXPECT_EQ(false, ability_->SetFormNextRefreshTime(formId, nextTime)); + GTEST_LOG_(INFO) << "AaFwk_Ability_SetFormNextRefreshTime_0100 end"; +} + +/** + * @tc.number: AaFwk_Ability_SetFormNextRefreshTime_0200 + * @tc.name: SetFormNextRefreshTime + * @tc.desc: Test whether SetFormNextRefreshTime is called normally.(RecoverStatus is IN_RECOVERING) + */ +HWTEST_F(FormAbilityTest, AaFwk_Ability_SetFormNextRefreshTime_0200, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_Ability_SetFormNextRefreshTime_0200 start"; + int64_t formId = 200; + int64_t nextTime = Constants::MIN_NEXT_TIME; + + // SetRecoverStatus IN_RECOVERING + volatile int recoverStatus = Constants::IN_RECOVERING; + FormMgr::GetInstance().SetRecoverStatus(recoverStatus); + + EXPECT_EQ(false, ability_->SetFormNextRefreshTime(formId, nextTime)); + GTEST_LOG_(INFO) << "AaFwk_Ability_SetFormNextRefreshTime_0200 end"; +} + +/** + * @tc.number: AaFwk_Ability_SetFormNextRefreshTime_0300 + * @tc.name: SetFormNextRefreshTime + * @tc.desc: Test whether SetFormNextRefreshTime is called normally.(SetNextRefreshTime reply false) + */ +HWTEST_F(FormAbilityTest, AaFwk_Ability_SetFormNextRefreshTime_0300, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_Ability_SetFormNextRefreshTime_0300 start"; + int64_t invalidFormId = 0; + int64_t nextTime = Constants::MIN_NEXT_TIME; + + // SetRecoverStatus NOT_IN_RECOVERY + int recoverStatus = Constants::NOT_IN_RECOVERY; + FormMgr::GetInstance().SetRecoverStatus(recoverStatus); + + EXPECT_EQ(false, ability_->SetFormNextRefreshTime(invalidFormId, nextTime)); + GTEST_LOG_(INFO) << "AaFwk_Ability_SetFormNextRefreshTime_0300 end"; +} + +/** + * @tc.number: AaFwk_Ability_SetFormNextRefreshTime_0400 + * @tc.name: SetFormNextRefreshTime + * @tc.desc: Test whether SetFormNextRefreshTime is called normally.(SetNextRefreshTime reply true) + */ +HWTEST_F(FormAbilityTest, AaFwk_Ability_SetFormNextRefreshTime_0400, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_Ability_SetFormNextRefreshTime_0400 start"; + int64_t formId = 400; + int64_t nextTime = Constants::MIN_NEXT_TIME; + + // SetRecoverStatus NOT_IN_RECOVERY + int recoverStatus = Constants::NOT_IN_RECOVERY; + FormMgr::GetInstance().SetRecoverStatus(recoverStatus); + + EXPECT_EQ(true, ability_->SetFormNextRefreshTime(formId, nextTime)); + GTEST_LOG_(INFO) << "AaFwk_Ability_SetFormNextRefreshTime_0400 end"; +} + +/** + * @tc.number: AaFwk_Ability_RequestForm_0100 + * @tc.name: RequestForm + * @tc.desc: Normal case: test whether RequestForm is called normally. + */ +HWTEST_F(FormAbilityTest, AaFwk_Ability_RequestForm_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_Ability_RequestForm_0100 start"; + + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->type = AbilityType::PAGE; + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + + ability_->Init(abilityInfo, nullptr, handler, nullptr); + + int64_t formId = 100L; + + EXPECT_EQ(true, ability_->RequestForm(formId)); + + GTEST_LOG_(INFO) << "AaFwk_Ability_RequestForm_0100 end"; +} + +/** + * @tc.number: AaFwk_Ability_RequestForm_0200 + * @tc.name: RequestForm + * @tc.desc: Abnormal case: test whether return fasle when formId is 0. + */ +HWTEST_F(FormAbilityTest, AaFwk_Ability_RequestForm_0200, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_Ability_RequestForm_0200 start"; + + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->type = AbilityType::PAGE; + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + + ability_->Init(abilityInfo, nullptr, handler, nullptr); + + int64_t formId = 0; + + EXPECT_EQ(false, ability_->RequestForm(formId)); + + GTEST_LOG_(INFO) << "AaFwk_Ability_RequestForm_0200 end"; +} + +/** + * @tc.number: AaFwk_Ability_RequestForm_0300 + * @tc.name: RequestForm + * @tc.desc: Abnormal case: test whether return fasle when RecoverStatus is IN_RECOVERING. + */ +HWTEST_F(FormAbilityTest, AaFwk_Ability_RequestForm_0300, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_Ability_RequestForm_0300 start"; + + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->type = AbilityType::PAGE; + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + + ability_->Init(abilityInfo, nullptr, handler, nullptr); + FormMgr::SetRecoverStatus(Constants::IN_RECOVERING); + int64_t formId = 300L; + + EXPECT_EQ(false, ability_->RequestForm(formId)); + + GTEST_LOG_(INFO) << "AaFwk_Ability_RequestForm_0300 end"; +} + +/** + * @tc.number: AaFwk_Ability_NotifyInvisibleForms_0100 + * @tc.name: NotifyInvisibleForms + * @tc.desc: Normal case: test whether NotifyInvisibleForms is called normally.(formId is illegal) + */ +HWTEST_F(FormAbilityTest, AaFwk_Ability_NotifyInvisibleForms_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_Ability_NotifyInvisibleForms_0100 start"; + std::vector formIds; + ability_->NotifyInvisibleForms(formIds); + GTEST_LOG_(INFO) << "AaFwk_Ability_NotifyInvisibleForms_0100 end"; +} + +/** + * @tc.number: AaFwk_Ability_NotifyInvisibleForms_0200 + * @tc.name: NotifyInvisibleForms + * @tc.desc: Normal case: test whether NotifyInvisibleForms is called normally.(RecoverStatus is IN_RECOVERING) + */ +HWTEST_F(FormAbilityTest, AaFwk_Ability_NotifyInvisibleForms_0200, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_Ability_NotifyInvisibleForms_0200 start"; + std::vector formIds; + formIds.push_back(1); + FormMgr::SetRecoverStatus(Constants::IN_RECOVERING); + ability_->NotifyInvisibleForms(formIds); + GTEST_LOG_(INFO) << "AaFwk_Ability_NotifyInvisibleForms_0200 end"; +} + +/** + * @tc.number: AaFwk_Ability_NotifyInvisibleForms_0300 + * @tc.name: NotifyInvisibleForms + * @tc.desc: Normal case: test whether NotifyInvisibleForms is called normally.(FormMgr reply 0) + */ +HWTEST_F(FormAbilityTest, AaFwk_Ability_NotifyInvisibleForms_0300, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_Ability_NotifyInvisibleForms_0300 start"; + std::vector formIds; + formIds.push_back(1); + FormMgr::SetRecoverStatus(Constants::NOT_IN_RECOVERY); + ability_->NotifyInvisibleForms(formIds); + GTEST_LOG_(INFO) << "AaFwk_Ability_NotifyInvisibleForms_0300 end"; +} + +/** + * @tc.number: AaFwk_Ability_NotifyInvisibleForms_0400 + * @tc.name: NotifyInvisibleForms + * @tc.desc: Normal case: test whether NotifyInvisibleForms is called normally.(FormMgr reply 1) + */ +HWTEST_F(FormAbilityTest, AaFwk_Ability_NotifyInvisibleForms_0400, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_Ability_NotifyInvisibleForms_0400 start"; + std::vector formIds; + formIds.push_back(1); + formIds.push_back(2); + FormMgr::SetRecoverStatus(Constants::NOT_IN_RECOVERY); + ability_->NotifyInvisibleForms(formIds); + GTEST_LOG_(INFO) << "AaFwk_Ability_NotifyInvisibleForms_0400 end"; +} + +/** + * @tc.number: AaFwk_Ability_NotifyVisibleForms_0100 + * @tc.name: NotifyVisibleForms + * @tc.desc: Normal case: test whether NotifyVisibleForms is called normally. + */ +HWTEST_F(FormAbilityTest, AaFwk_Ability_NotifyVisibleForms_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_Ability_NotifyVisibleForms_0100 start"; + + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->type = AbilityType::PAGE; + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + + ability_->Init(abilityInfo, nullptr, handler, nullptr); + + std::vector formIds; + formIds.push_back(100); + formIds.push_back(101); + ability_->NotifyVisibleForms(formIds); + + GTEST_LOG_(INFO) << "AaFwk_Ability_NotifyVisibleForms_0100 end"; +} + +/** + * @tc.number: AaFwk_Ability_NotifyVisibleForms_0200 + * @tc.name: NotifyVisibleForms + * @tc.desc: Abnormal case: test whether NotifyVisibleForms is called with + * specified error log when the size of formIds is empty. + */ +HWTEST_F(FormAbilityTest, AaFwk_Ability_NotifyVisibleForms_0200, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_Ability_NotifyVisibleForms_0200 start"; + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->type = AbilityType::PAGE; + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + + ability_->Init(abilityInfo, nullptr, handler, nullptr); + + std::vector formIds; + ability_->NotifyVisibleForms(formIds); + GTEST_LOG_(INFO) << "AaFwk_Ability_NotifyVisibleForms_0200 end"; +} + +/** + * @tc.number: AaFwk_Ability_NotifyVisibleForms_0300 + * @tc.name: NotifyVisibleForms + * @tc.desc: Normal case: test whether NotifyVisibleForms is called with + * specified error log when the size of formIds is larger than 32. + */ +HWTEST_F(FormAbilityTest, AaFwk_Ability_NotifyVisibleForms_0300, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_Ability_NotifyVisibleForms_0300 start"; + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->type = AbilityType::PAGE; + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + + ability_->Init(abilityInfo, nullptr, handler, nullptr); + + std::vector formIds; + for (int64_t formId = 300L; formId < 333L; formId++) { + formIds.push_back(formId); + } + ability_->NotifyVisibleForms(formIds); + GTEST_LOG_(INFO) << "AaFwk_Ability_NotifyVisibleForms_0300 end"; +} + +/** + * @tc.number: AaFwk_Ability_NotifyVisibleForms_0400 + * @tc.name: NotifyVisibleForms + * @tc.desc: Normal case: test whether NotifyVisibleForms is called with + * specified error log when the recover status is in recovering. + */ +HWTEST_F(FormAbilityTest, AaFwk_Ability_NotifyVisibleForms_0400, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_Ability_NotifyVisibleForms_0400 start"; + + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->type = AbilityType::PAGE; + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + + ability_->Init(abilityInfo, nullptr, handler, nullptr); + + std::vector formIds; + formIds.push_back(100); + formIds.push_back(101); + FormMgr::SetRecoverStatus(Constants::IN_RECOVERING); + ability_->NotifyVisibleForms(formIds); + + GTEST_LOG_(INFO) << "AaFwk_Ability_NotifyVisibleForms_0400 end"; +} + +/** + * @tc.number: AaFwk_Ability_FmsDeathCallback_OnDeathReceived_0100 + * @tc.name: OnDeathReceived + * @tc.desc: Normal case: test whether OnDeathReceived is called normally with a form. + */ +HWTEST_F(FormAbilityTest, AaFwk_Ability_FmsDeathCallback_OnDeathReceived_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_Ability_FmsDeathCallback_OnDeathReceived_0100 start"; + + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->type = AbilityType::PAGE; + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + + ability_->Init(abilityInfo, nullptr, handler, nullptr); + + std::string formName = "formName0100"; + std::string moduleName = "moduleName0100"; + std::string deviceId = "deviceId0100"; + std::string bundleName = "bundleName0100"; + std::string abilityName = "abilityName0100"; + bool tempFormFlg = false; + Want want; + want.SetParam(Constants::PARAM_FORM_NAME_KEY, formName) + .SetParam(Constants::PARAM_MODULE_NAME_KEY, moduleName) + .SetElementName(deviceId, bundleName, abilityName) + .SetParam(Constants::PARAM_FORM_TEMPORARY_KEY, tempFormFlg); + std::shared_ptr callback; + + FormMgr::GetInstance().RegisterDeathCallback(ability_); + + int64_t formId = 100L; + ability_->userReqParams_.emplace(formId, want); + ability_->appCallbacks_.emplace(formId, callback); + + EXPECT_EQ(true, ability_->lostedByReconnectTempForms_.empty()); + ability_->OnDeathReceived(); + EXPECT_EQ(true, ability_->lostedByReconnectTempForms_.empty()); + GTEST_LOG_(INFO) << "AaFwk_Ability_FmsDeathCallback_OnDeathReceived_0100 end"; +} + +/** + * @tc.number: AaFwk_Ability_FmsDeathCallback_OnDeathReceived_0200 + * @tc.name: OnDeathReceived + * @tc.desc: Normal case: test whether OnDeathReceived is called normally with a form and a temp form. + */ +HWTEST_F(FormAbilityTest, AaFwk_Ability_FmsDeathCallback_OnDeathReceived_0200, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_Ability_FmsDeathCallback_OnDeathReceived_0200 start"; + + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->type = AbilityType::PAGE; + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + + ability_->Init(abilityInfo, nullptr, handler, nullptr); + + std::string formName1 = "formName0200"; + std::string moduleName1 = "moduleName0200"; + std::string deviceId1 = "deviceId0200"; + std::string bundleName1 = "bundleName0200"; + std::string abilityName1 = "abilityName0200"; + bool tempFormFlg1 = false; + Want want1; + want1.SetParam(Constants::PARAM_FORM_NAME_KEY, formName1) + .SetParam(Constants::PARAM_MODULE_NAME_KEY, moduleName1) + .SetElementName(deviceId1, bundleName1, abilityName1) + .SetParam(Constants::PARAM_FORM_TEMPORARY_KEY, tempFormFlg1); + std::shared_ptr callback1; + + std::string formName2 = "formName0201"; + std::string moduleName2 = "moduleName0201"; + std::string deviceId2 = "deviceId0201"; + std::string bundleName2 = "bundleName0201"; + std::string abilityName2 = "abilityName0201"; + bool tempFormFlg2 = true; + Want want2; + want2.SetParam(Constants::PARAM_FORM_NAME_KEY, formName2) + .SetParam(Constants::PARAM_MODULE_NAME_KEY, moduleName2) + .SetElementName(deviceId2, bundleName2, abilityName2) + .SetParam(Constants::PARAM_FORM_TEMPORARY_KEY, tempFormFlg2); + std::shared_ptr callback2; + + FormMgr::GetInstance().RegisterDeathCallback(ability_); + + int64_t formId1 = 200L; + int64_t formId2 = 201L; + ability_->userReqParams_.emplace(formId1, want1); + ability_->userReqParams_.emplace(formId2, want2); + ability_->appCallbacks_.emplace(formId1, callback1); + ability_->appCallbacks_.emplace(formId2, callback2); + + EXPECT_EQ(true, ability_->lostedByReconnectTempForms_.empty()); + ability_->OnDeathReceived(); + EXPECT_EQ(true, ability_->lostedByReconnectTempForms_.size() == 1); + EXPECT_EQ(formId2, ability_->lostedByReconnectTempForms_[0]); + GTEST_LOG_(INFO) << "AaFwk_Ability_FmsDeathCallback_OnDeathReceived_0200 end"; +} + +/** + * @tc.number: AaFwk_Ability_FmsDeathCallback_OnDeathReceived_0300 + * @tc.name: OnDeathReceived + * @tc.desc: Normal case: test whether OnDeathReceived is called normally with two temp form. + */ +HWTEST_F(FormAbilityTest, AaFwk_Ability_FmsDeathCallback_OnDeathReceived_0300, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_Ability_FmsDeathCallback_OnDeathReceived_0300 start"; + + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->type = AbilityType::PAGE; + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + + ability_->Init(abilityInfo, nullptr, handler, nullptr); + + std::string formName1 = "formName0300"; + std::string moduleName1 = "moduleName0300"; + std::string deviceId1 = "deviceId0300"; + std::string bundleName1 = "bundleName0300"; + std::string abilityName1 = "abilityName0300"; + bool tempFormFlg1 = true; + Want want1; + want1.SetParam(Constants::PARAM_FORM_NAME_KEY, formName1) + .SetParam(Constants::PARAM_MODULE_NAME_KEY, moduleName1) + .SetElementName(deviceId1, bundleName1, abilityName1) + .SetParam(Constants::PARAM_FORM_TEMPORARY_KEY, tempFormFlg1); + std::shared_ptr callback1; + + std::string formName2 = "formName0301"; + std::string moduleName2 = "moduleName0301"; + std::string deviceId2 = "deviceId0301"; + std::string bundleName2 = "bundleName0301"; + std::string abilityName2 = "abilityName0301"; + bool tempFormFlg2 = true; + Want want2; + want2.SetParam(Constants::PARAM_FORM_NAME_KEY, formName2) + .SetParam(Constants::PARAM_MODULE_NAME_KEY, moduleName2) + .SetElementName(deviceId2, bundleName2, abilityName2) + .SetParam(Constants::PARAM_FORM_TEMPORARY_KEY, tempFormFlg2); + std::shared_ptr callback2; + + FormMgr::GetInstance().RegisterDeathCallback(ability_); + + int64_t formId1 = 200L; + int64_t formId2 = 201L; + ability_->userReqParams_.emplace(formId1, want1); + ability_->userReqParams_.emplace(formId2, want2); + ability_->appCallbacks_.emplace(formId1, callback1); + ability_->appCallbacks_.emplace(formId2, callback2); + + EXPECT_EQ(true, ability_->lostedByReconnectTempForms_.empty()); + ability_->OnDeathReceived(); + EXPECT_EQ(true, ability_->lostedByReconnectTempForms_.size() == 2); + EXPECT_EQ(formId1, ability_->lostedByReconnectTempForms_[0]); + EXPECT_EQ(formId2, ability_->lostedByReconnectTempForms_[1]); + + GTEST_LOG_(INFO) << "AaFwk_Ability_FmsDeathCallback_OnDeathReceived_0300 end"; +} + +/** + * @tc.number: AaFwk_Ability_CheckFMSReady_0100 + * @tc.name: CheckFMSReady + * @tc.desc: Test whether CheckFMSReady is called normally. + */ +HWTEST_F(FormAbilityTest, AaFwk_Ability_CheckFMSReady_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_Ability_CheckFMSReady_0100 start"; + + std::string bundleName = "Bundle"; + std::vector formInfos; + formInfos.clear(); + EXPECT_EQ(true, ability_->CheckFMSReady()); + + GTEST_LOG_(INFO) << "AaFwk_Ability_CheckFMSReady_0100 end"; +} + +/** + * @tc.number: AaFwk_Ability_GetAllFormsInfo_0100 + * @tc.name: GetAllFormsInfo + * @tc.desc: Test whether GetAllFormsInfo is called normally. + */ +HWTEST_F(FormAbilityTest, AaFwk_Ability_GetAllFormsInfo_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_Ability_GetAllFormsInfo_0100 start"; + + std::string bundleName = "Bundle"; + std::vector formInfos; + formInfos.clear(); + EXPECT_EQ(true, ability_->GetAllFormsInfo(formInfos)); + size_t dataSize {1}; + EXPECT_EQ(dataSize, formInfos.size()); + + GTEST_LOG_(INFO) << "AaFwk_Ability_GetAllFormsInfo_0100 end"; +} + +/** + * @tc.number: AaFwk_Ability_GetFormsInfoByApp_0100 + * @tc.name: GetFormsInfoByApp + * @tc.desc: Test whether GetFormsInfoByApp is called normally. + */ +HWTEST_F(FormAbilityTest, AaFwk_Ability_GetFormsInfoByApp_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_Ability_GetFormsInfoByApp_0100 start"; + + std::string bundleName = "Bundle"; + std::vector formInfos; + formInfos.clear(); + EXPECT_EQ(true, ability_->GetFormsInfoByApp(bundleName, formInfos)); + size_t dataSize {1}; + EXPECT_EQ(dataSize, formInfos.size()); + bundleName = ""; + EXPECT_EQ(false, ability_->GetFormsInfoByApp(bundleName, formInfos)); + + GTEST_LOG_(INFO) << "AaFwk_Ability_GetFormsInfoByApp_0100 end"; +} + +/** + * @tc.number: AaFwk_Ability_GetFormsInfoByModule_0100 + * @tc.name: GetFormsInfoByModule + * @tc.desc: Test whether GetFormsInfoByModule is called normally. + */ +HWTEST_F(FormAbilityTest, AaFwk_Ability_GetFormsInfoByModule_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_Ability_GetFormsInfoByModule_0100 start"; + + std::string bundleName = "Bundle"; + std::string moduleName = "Module"; + std::vector formInfos; + formInfos.clear(); + EXPECT_EQ(true, ability_->GetFormsInfoByModule(bundleName, moduleName, formInfos)); + size_t dataSize {1}; + EXPECT_EQ(dataSize, formInfos.size()); + bundleName = ""; + EXPECT_EQ(false, ability_->GetFormsInfoByModule(bundleName, moduleName, formInfos)); + + GTEST_LOG_(INFO) << "AaFwk_Ability_GetFormsInfoByModule_0100 end"; +} +} // namespace AppExecFwk +} // namespace OHOS diff --git a/tools/frameworks/kits/ability/native/test/unittest/form_host_client_test.cpp b/tools/frameworks/kits/ability/native/test/unittest/form_host_client_test.cpp new file mode 100644 index 00000000000..3900a34b744 --- /dev/null +++ b/tools/frameworks/kits/ability/native/test/unittest/form_host_client_test.cpp @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "ability.h" +#include "ability_handler.h" +#include "ability_info.h" +#include "ability_local_record.h" +#include "ability_start_setting.h" +#include "context_deal.h" +#include "form_host_client.h" +#include "mock_page_ability.h" + +namespace OHOS { +namespace AppExecFwk { +using namespace testing::ext; +using namespace OHOS; +using namespace OHOS::AppExecFwk; +using OHOS::Parcel; + +class FormHostClientTest : public testing::Test { +public: + FormHostClientTest() + {} + ~FormHostClientTest() + {} + sptr instance_; + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void FormHostClientTest::SetUpTestCase(void) +{} + +void FormHostClientTest::TearDownTestCase(void) +{} + +void FormHostClientTest::SetUp(void) +{ + instance_ = FormHostClient::GetInstance(); +} + +void FormHostClientTest::TearDown(void) +{ + instance_ = nullptr; +} + +/** + * @tc.number: AaFwk_FormHostClient_AddForm_0100 + * @tc.name: AddForm + * @tc.desc: Verify that the return value of AddForm is correct. + */ +HWTEST_F(FormHostClientTest, AaFwk_formHostClientAddForm_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_FormHostClient_AddForm_0100 start"; + std::shared_ptr ability = std::make_shared(); + int64_t formId = 0; + instance_->AddForm(ability, formId); + formId = 1; + instance_->AddForm(ability, formId); + formId = 2; + instance_->AddForm(ability, formId); + + GTEST_LOG_(INFO) << "AaFwk_FormHostClient_AddForm_0100 end"; +} + +/** + * @tc.number: AaFwk_FormHostClient_RemoveForm_0100 + * @tc.name: RemoveForm + * @tc.desc: Verify that the return value of RemoveForm is correct. + */ +HWTEST_F(FormHostClientTest, AaFwk_FormHostClient_RemoveForm_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_FormHostClient_RemoveForm_0100 start"; + std::shared_ptr ability = std::make_shared(); + int64_t formId = 0; + instance_->RemoveForm(ability, formId); + instance_->AddForm(ability, formId); + instance_->RemoveForm(ability, formId); + + GTEST_LOG_(INFO) << "AaFwk_FormHostClient_RemoveForm_0100 end"; +} + +/** + * @tc.number: AaFwk_FormHostClient_ContainsForm_0100 + * @tc.name: ContainsForm + * @tc.desc: Verify that the return value of ContainsForm is correct. + */ +HWTEST_F(FormHostClientTest, AaFwk_FormHostClient_ContainsForm_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_FormHostClient_ContainsForm_0100 start"; + int64_t formId = 0; + EXPECT_EQ(false, instance_->ContainsForm(formId)); + std::shared_ptr ability = std::make_shared(); + formId = 1; + instance_->AddForm(ability, formId); + EXPECT_EQ(true, instance_->ContainsForm(formId)); + + GTEST_LOG_(INFO) << "AaFwk_FormHostClient_ContainsForm_0100 end"; +} + +/** + * @tc.number: AaFwk_FormHostClient_OnAcquired_0100 + * @tc.name: OnAcquired + * @tc.desc: Verify that the return value of OnAcquired is correct. + */ +HWTEST_F(FormHostClientTest, AaFwk_FormHostClient_OnAcquired_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_FormHostClient_OnAcquired_0100 start"; + FormJsInfo formInfo; + formInfo.formId = -1; + instance_->OnAcquired(formInfo); + int64_t formId = 1; + std::shared_ptr ability = std::make_shared(); + instance_->AddForm(ability, formId); + formInfo.formId = 1; + instance_->OnAcquired(formInfo); + + GTEST_LOG_(INFO) << "AaFwk_FormHostClient_OnAcquired_0100 end"; +} + +/** + * @tc.number: AaFwk_FormHostClient_OnUpdate_0100 + * @tc.name: OnUpdate + * @tc.desc: Verify that the return value of OnUpdate is correct. + */ +HWTEST_F(FormHostClientTest, AaFwk_FormHostClient_OnUpdate_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_FormHostClient_OnUpdate_0100 start"; + FormJsInfo formInfo; + formInfo.formId = -1; + instance_->OnUpdate(formInfo); + int64_t formId = 1; + std::shared_ptr ability = std::make_shared(); + instance_->AddForm(ability, formId); + formInfo.formId = 1; + instance_->OnUpdate(formInfo); + + GTEST_LOG_(INFO) << "AaFwk_FormHostClient_OnUpdate_0100 end"; +} +} // namespace AppExecFwk +} // namespace OHOS diff --git a/tools/frameworks/kits/ability/native/test/unittest/form_provider_client_test.cpp b/tools/frameworks/kits/ability/native/test/unittest/form_provider_client_test.cpp new file mode 100644 index 00000000000..b75ce4a11dd --- /dev/null +++ b/tools/frameworks/kits/ability/native/test/unittest/form_provider_client_test.cpp @@ -0,0 +1,509 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "appexecfwk_errors.h" +#include +#include "form_constants.h" +#include "form_provider_client.h" +#include "mock_form_supply_callback.h" +#include "permission/permission.h" +#include "permission/permission_kit.h" + +namespace OHOS { +namespace AppExecFwk { +using namespace testing::ext; +using namespace OHOS; +using namespace OHOS::AppExecFwk; +using namespace OHOS::Security; + +const std::string PERMISSION_NAME_REQUIRE_FORM = "ohos.permission.REQUIRE_FORM"; +const std::string FORM_MANAGER_SERVICE_BUNDLE_NAME = "com.form.fms.app"; +const std::string DEF_LABEL1 = "PermissionFormRequireGrant"; +const std::string FORM_SUPPLY_INFO = "com.form.supply.info.test"; + +class FormProviderClientTest : public testing::Test { +public: + FormProviderClientTest() + {} + ~FormProviderClientTest() + {} + sptr instance_; + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void FormProviderClientTest::SetUpTestCase(void) +{} + +void FormProviderClientTest::TearDownTestCase(void) +{} + +void FormProviderClientTest::SetUp(void) +{ + instance_ = new FormProviderClient(); + + // Permission install + std::vector permList; + Permission::PermissionDef permDef; + permDef.permissionName = PERMISSION_NAME_REQUIRE_FORM; + permDef.bundleName = FORM_MANAGER_SERVICE_BUNDLE_NAME; + permDef.grantMode = Permission::GrantMode::USER_GRANT; + permDef.availableScope = Permission::AvailableScope::AVAILABLE_SCOPE_ALL; + permDef.label = DEF_LABEL1; + permDef.labelId = 1; + permDef.description = DEF_LABEL1; + permDef.descriptionId = 1; + permList.emplace_back(permDef); + Permission::PermissionKit::AddDefPermissions(permList); + std::vector permnameList; + permnameList.emplace_back(PERMISSION_NAME_REQUIRE_FORM); + Permission::PermissionKit::AddUserGrantedReqPermissions(FORM_MANAGER_SERVICE_BUNDLE_NAME, + permnameList, 0); + Permission::PermissionKit::GrantUserGrantedPermission(FORM_MANAGER_SERVICE_BUNDLE_NAME, + PERMISSION_NAME_REQUIRE_FORM, 0); +} + +void FormProviderClientTest::TearDown(void) +{ + instance_ = nullptr; +} + +/** + * @tc.number: AaFwk_FormProviderClient_AcquireProviderFormInfo_0100 + * @tc.name: AcquireProviderFormInfo + * @tc.desc: Verify that the return value of AddForm is correct. + */ +HWTEST_F(FormProviderClientTest, AaFwk_FormProviderClient_AcquireProviderFormInfo_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_FormProviderClient_AcquireProviderFormInfo_0100 start"; + + const std::shared_ptr ability = std::make_shared(); + instance_->SetOwner(ability); + + const sptr callerToken = MockFormSupplyCallback::GetInstance(); + Want want; + want.SetParam(Constants::PARAM_FORM_MANAGER_SERVICE_BUNDLENAME_KEY, FORM_MANAGER_SERVICE_BUNDLE_NAME) + .SetParam(Constants::ACQUIRE_TYPE, 100) + .SetParam(Constants::FORM_CONNECT_ID, 100L) + .SetParam(Constants::PARAM_FORM_IDENTITY_KEY, 100L) + .SetParam(Constants::FORM_SUPPLY_INFO, FORM_SUPPLY_INFO); + int64_t formId = 1001L; + instance_->AcquireProviderFormInfo(formId, want, callerToken); + + GTEST_LOG_(INFO) << "AaFwk_FormProviderClient_AcquireProviderFormInfo_0100 end"; +} + +/** + * @tc.number: AaFwk_FormProviderClient_AcquireProviderFormInfo_0200 + * @tc.name: AcquireProviderFormInfo + * @tc.desc: Verify that the return value of AddForm is correct. + */ +HWTEST_F(FormProviderClientTest, AaFwk_FormProviderClient_AcquireProviderFormInfo_0200, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_FormProviderClient_AcquireProviderFormInfo_0200 start"; + + instance_->SetOwner(nullptr); + + const sptr callerToken = MockFormSupplyCallback::GetInstance(); + Want want; + want.SetParam(Constants::PARAM_FORM_MANAGER_SERVICE_BUNDLENAME_KEY, FORM_MANAGER_SERVICE_BUNDLE_NAME) + .SetParam(Constants::ACQUIRE_TYPE, 200) + .SetParam(Constants::FORM_CONNECT_ID, 200L) + .SetParam(Constants::PARAM_FORM_IDENTITY_KEY, 200L) + .SetParam(Constants::FORM_SUPPLY_INFO, FORM_SUPPLY_INFO); + + int64_t formId = 1002L; + instance_->AcquireProviderFormInfo(formId, want, callerToken); + + GTEST_LOG_(INFO) << "AaFwk_FormProviderClient_AcquireProviderFormInfo_0200 end"; +} + +/** + * @tc.number: AaFwk_FormProviderClient_AcquireProviderFormInfo_0300 + * @tc.name: AcquireProviderFormInfo + * @tc.desc: Verify that the return value of AddForm is correct. + */ +HWTEST_F(FormProviderClientTest, AaFwk_FormProviderClient_AcquireProviderFormInfo_0300, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_FormProviderClient_AcquireProviderFormInfo_0300 start"; + + const std::shared_ptr ability = std::make_shared(); + instance_->SetOwner(ability); + + const sptr callerToken = MockFormSupplyCallback::GetInstance(); + Want want; + want.SetParam(Constants::ACQUIRE_TYPE, 300) + .SetParam(Constants::FORM_CONNECT_ID, 300L) + .SetParam(Constants::PARAM_FORM_IDENTITY_KEY, 300L) + .SetParam(Constants::FORM_SUPPLY_INFO, FORM_SUPPLY_INFO); + + int64_t formId = 1003L; + instance_->AcquireProviderFormInfo(formId, want, callerToken); + + GTEST_LOG_(INFO) << "AaFwk_FormProviderClient_AcquireProviderFormInfo_0300 end"; +} + +/** + * @tc.number: AaFwk_FormProviderClient_AcquireProviderFormInfo_0400 + * @tc.name: AcquireProviderFormInfo + * @tc.desc: Verify that the return value of AddForm is correct. + */ +HWTEST_F(FormProviderClientTest, AaFwk_FormProviderClient_AcquireProviderFormInfo_0400, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_FormProviderClient_AcquireProviderFormInfo_0400 start"; + + const std::shared_ptr ability = std::make_shared(); + instance_->SetOwner(ability); + instance_->ClearOwner(ability); + + const sptr callerToken = MockFormSupplyCallback::GetInstance(); + Want want; + want.SetParam(Constants::PARAM_FORM_MANAGER_SERVICE_BUNDLENAME_KEY, FORM_MANAGER_SERVICE_BUNDLE_NAME) + .SetParam(Constants::ACQUIRE_TYPE, 400) + .SetParam(Constants::FORM_CONNECT_ID, 400L) + .SetParam(Constants::PARAM_FORM_IDENTITY_KEY, 400L) + .SetParam(Constants::FORM_SUPPLY_INFO, FORM_SUPPLY_INFO); + + int64_t formId = 1004L; + instance_->AcquireProviderFormInfo(formId, want, callerToken); + + GTEST_LOG_(INFO) << "AaFwk_FormProviderClient_AcquireProviderFormInfo_0400 end"; +} + +/** + * @tc.number: AaFwk_FormProviderClient_AcquireProviderFormInfo_0500 + * @tc.name: AcquireProviderFormInfo + * @tc.desc: Verify that the return value of AddForm is correct. + */ +HWTEST_F(FormProviderClientTest, AaFwk_FormProviderClient_AcquireProviderFormInfo_0500, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_FormProviderClient_AcquireProviderFormInfo_0500 start"; + + const std::shared_ptr ability = std::make_shared(); + instance_->SetOwner(ability); + + Want want; + want.SetParam(Constants::PARAM_FORM_MANAGER_SERVICE_BUNDLENAME_KEY, FORM_MANAGER_SERVICE_BUNDLE_NAME) + .SetParam(Constants::ACQUIRE_TYPE, 500) + .SetParam(Constants::FORM_CONNECT_ID, 500L) + .SetParam(Constants::PARAM_FORM_IDENTITY_KEY, 500L) + .SetParam(Constants::FORM_SUPPLY_INFO, FORM_SUPPLY_INFO); + + const sptr callerToken = nullptr; + int64_t formId = 1005L; + EXPECT_EQ(ERR_APPEXECFWK_FORM_BIND_PROVIDER_FAILED, instance_->AcquireProviderFormInfo(formId, want, callerToken)); + GTEST_LOG_(INFO) << "AaFwk_FormProviderClient_AcquireProviderFormInfo_0500 end"; +} + +/** + * @tc.number: AaFwk_FormProviderClient_EventNotify_0100 + * @tc.name: EventNotify + * @tc.desc: Verify that the return value of EventNotify is correct. + */ +HWTEST_F(FormProviderClientTest, AaFwk_FormProviderClient_EventNotify_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_FormProviderClient_EventNotify_0100 start"; + + // Ability + const std::shared_ptr ability = std::make_shared(); + instance_->SetOwner(ability); + + // callerToken + const sptr callerToken = MockFormSupplyCallback::GetInstance(); + + // want + Want want; + want.SetParam(Constants::PARAM_FORM_MANAGER_SERVICE_BUNDLENAME_KEY, FORM_MANAGER_SERVICE_BUNDLE_NAME) + .SetParam(Constants::ACQUIRE_TYPE, 100) + .SetParam(Constants::FORM_CONNECT_ID, 100L) + .SetParam(Constants::PARAM_FORM_IDENTITY_KEY, 100L) + .SetParam(Constants::FORM_SUPPLY_INFO, FORM_SUPPLY_INFO); + + // formEvents + int64_t formId = 100; + std::vector formEvents; + formEvents.push_back(formId); + + int32_t formVisibleType = Constants::FORM_INVISIBLE; + + EXPECT_EQ(ERR_OK, instance_->EventNotify(formEvents, formVisibleType, want, callerToken)); + + GTEST_LOG_(INFO) << "AaFwk_FormProviderClient_EventNotify_0100 end"; +} + +/** + * @tc.number: AaFwk_FormProviderClient_EventNotify_0200 + * @tc.name: EventNotify + * @tc.desc: Verify that the return value of EventNotify is correct. + */ +HWTEST_F(FormProviderClientTest, AaFwk_FormProviderClient_EventNotify_0200, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_FormProviderClient_EventNotify_0200 start"; + + // Ability is nullptr + instance_->SetOwner(nullptr); + + // callerToken + const sptr callerToken = MockFormSupplyCallback::GetInstance(); + + // want + Want want; + want.SetParam(Constants::PARAM_FORM_MANAGER_SERVICE_BUNDLENAME_KEY, FORM_MANAGER_SERVICE_BUNDLE_NAME) + .SetParam(Constants::ACQUIRE_TYPE, 100) + .SetParam(Constants::FORM_CONNECT_ID, 100L) + .SetParam(Constants::PARAM_FORM_IDENTITY_KEY, 100L) + .SetParam(Constants::FORM_SUPPLY_INFO, FORM_SUPPLY_INFO); + + // formEvents + int64_t formId = 100; + std::vector formEvents; + formEvents.push_back(formId); + + int32_t formVisibleType = Constants::FORM_INVISIBLE; + + EXPECT_EQ(ERR_APPEXECFWK_FORM_NO_SUCH_ABILITY, + instance_->EventNotify(formEvents, formVisibleType, want, callerToken )); + + GTEST_LOG_(INFO) << "AaFwk_FormProviderClient_EventNotify_0200 end"; +} + + +/** + * @tc.number: AaFwk_FormProviderClient_NotifyFormCastTempForm_0100 + * @tc.name: NotifyFormCastTempForm + * @tc.desc: Verify that the return value of AddForm is correct. + */ +HWTEST_F(FormProviderClientTest, AaFwk_FormProviderClient_NotifyFormCastTempForm_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_FormProviderClient_NotifyFormCastTempForm_0100 start"; + + const std::shared_ptr ability = std::make_shared(); + instance_->SetOwner(ability); + + Want want; + want.SetParam(Constants::PARAM_FORM_MANAGER_SERVICE_BUNDLENAME_KEY, FORM_MANAGER_SERVICE_BUNDLE_NAME) + .SetParam(Constants::ACQUIRE_TYPE, 101) + .SetParam(Constants::FORM_CONNECT_ID, 101L) + .SetParam(Constants::PARAM_FORM_IDENTITY_KEY, 101L) + .SetParam(Constants::FORM_SUPPLY_INFO, FORM_SUPPLY_INFO); + + int64_t formId = 720L; + const sptr callerToken = MockFormSupplyCallback::GetInstance(); + + EXPECT_EQ(ERR_OK, instance_->NotifyFormCastTempForm(formId, want, callerToken)); + + GTEST_LOG_(INFO) << "AaFwk_FormProviderClient_NotifyFormCastTempForm_0100 end"; +} + +/** + * @tc.number: AaFwk_FormProviderClient_NotifyFormCastTempForm_0100 + * @tc.name: NotifyFormCastTempForm + * @tc.desc: Verify that the return value of AddForm is correct. + */ +HWTEST_F(FormProviderClientTest, AaFwk_FormProviderClient_NotifyFormCastTempForm_0200, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_FormProviderClient_NotifyFormCastTempForm_0200 start"; + + const std::shared_ptr ability = std::make_shared(); + instance_->SetOwner(nullptr); + + Want want; + want.SetParam(Constants::PARAM_FORM_MANAGER_SERVICE_BUNDLENAME_KEY, FORM_MANAGER_SERVICE_BUNDLE_NAME) + .SetParam(Constants::ACQUIRE_TYPE, 102) + .SetParam(Constants::FORM_CONNECT_ID, 102L) + .SetParam(Constants::PARAM_FORM_IDENTITY_KEY, 102L) + .SetParam(Constants::FORM_SUPPLY_INFO, FORM_SUPPLY_INFO); + + int64_t formId = 722L; + const sptr callerToken = MockFormSupplyCallback::GetInstance(); + + EXPECT_EQ(ERR_APPEXECFWK_FORM_NO_SUCH_ABILITY, instance_->NotifyFormCastTempForm(formId, want, callerToken)); + + GTEST_LOG_(INFO) << "AaFwk_FormProviderClient_NotifyFormCastTempForm_0200 end"; +} + + +/** + * @tc.number: AaFwk_FormProviderClient_NotifyFormCastTempForm_0100 + * @tc.name: NotifyFormCastTempForm + * @tc.desc: Verify that the return value of AddForm is correct. + */ +HWTEST_F(FormProviderClientTest, AaFwk_FormProviderClient_NotifyFormCastTempForm_0300, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_FormProviderClient_NotifyFormCastTempForm_0300 start"; + + const std::shared_ptr ability = std::make_shared(); + instance_->SetOwner(ability); + + Want want; + want.SetParam(Constants::PARAM_FORM_MANAGER_SERVICE_BUNDLENAME_KEY, FORM_MANAGER_SERVICE_BUNDLE_NAME) + .SetParam(Constants::ACQUIRE_TYPE, 103) + .SetParam(Constants::FORM_CONNECT_ID, 103L) + .SetParam(Constants::PARAM_FORM_IDENTITY_KEY, 103L) + .SetParam(Constants::FORM_SUPPLY_INFO, FORM_SUPPLY_INFO); + + int64_t formId = 723L; + const sptr callerToken = nullptr; + + EXPECT_EQ(ERR_APPEXECFWK_FORM_BIND_PROVIDER_FAILED, instance_->NotifyFormCastTempForm(formId, want, callerToken)); + + GTEST_LOG_(INFO) << "AaFwk_FormProviderClient_NotifyFormCastTempForm_0300 end"; +} + +/** + * @tc.number: AaFwk_FormProviderClient_FireFormEvent_0100 + * @tc.name: FireFormEvent + * @tc.desc: Verify that the return value of FireFormEvent is correct. + */ +HWTEST_F(FormProviderClientTest, AaFwk_FormProviderClient_FireFormEvent_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_FormProviderClient_FireFormEvent_0100 start"; + + const std::shared_ptr ability = std::make_shared(); + instance_->SetOwner(ability); + + Want want; + want.SetParam(Constants::PARAM_FORM_MANAGER_SERVICE_BUNDLENAME_KEY, FORM_MANAGER_SERVICE_BUNDLE_NAME) + .SetParam(Constants::FORM_CONNECT_ID, 104L); + + int64_t formId = 724L; + std::string message = "event message"; + const sptr callerToken = MockFormSupplyCallback::GetInstance(); + + EXPECT_EQ(ERR_OK, instance_->FireFormEvent(formId, message, want, callerToken)); + + GTEST_LOG_(INFO) << "AaFwk_FormProviderClient_FireFormEvent_0100 end"; +} + +/** + * @tc.number: AaFwk_FormProviderClient_FireFormEvent_0200 + * @tc.name: FireFormEvent + * @tc.desc: Verify that the return value of FireFormEvent is correct. + */ +HWTEST_F(FormProviderClientTest, AaFwk_FormProviderClient_FireFormEvent_0200, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_FormProviderClient_FireFormEvent_0200 start"; + + const std::shared_ptr ability = std::make_shared(); + instance_->SetOwner(nullptr); + + Want want; + want.SetParam(Constants::PARAM_FORM_MANAGER_SERVICE_BUNDLENAME_KEY, FORM_MANAGER_SERVICE_BUNDLE_NAME) + .SetParam(Constants::FORM_CONNECT_ID, 105L); + int64_t formId = 725L; + std::string message = "event message"; + const sptr callerToken = MockFormSupplyCallback::GetInstance(); + + EXPECT_EQ(ERR_APPEXECFWK_FORM_NO_SUCH_ABILITY, instance_->FireFormEvent(formId, message, want, callerToken)); + + GTEST_LOG_(INFO) << "AaFwk_FormProviderClient_FireFormEvent_0200 end"; +} +/** + * @tc.number: AaFwk_FormProviderClient_FireFormEvent_0300 + * @tc.name: NotifyFormCastTempForm + * @tc.desc: Verify that the return value of AddForm is correct. + */ +HWTEST_F(FormProviderClientTest, AaFwk_FormProviderClient_FireFormEvent_0300, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_FormProviderClient_FireFormEvent_0300 start"; + + const std::shared_ptr ability = std::make_shared(); + instance_->SetOwner(ability); + + Want want; + want.SetParam(Constants::PARAM_FORM_MANAGER_SERVICE_BUNDLENAME_KEY, FORM_MANAGER_SERVICE_BUNDLE_NAME) + .SetParam(Constants::FORM_CONNECT_ID, 106L); + + int64_t formId = 726L; + std::string message = "event message"; + const sptr callerToken = nullptr; + + EXPECT_EQ(ERR_APPEXECFWK_FORM_BIND_PROVIDER_FAILED, instance_->FireFormEvent(formId, message, want, callerToken)); + + GTEST_LOG_(INFO) << "AaFwk_FormProviderClient_FireFormEvent_0300 end"; +} + +/** + * @tc.number: AaFwk_FormProviderClient_NotifyFormsDelete_0100 + * @tc.name: FireFormEvent + * @tc.desc: Verify that the return value of FireFormEvent is correct. + */ +HWTEST_F(FormProviderClientTest, AaFwk_FormProviderClient_NotifyFormsDelete_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_FormProviderClient_NotifyFormsDelete_0100 start"; + + const std::shared_ptr ability = std::make_shared(); + instance_->SetOwner(ability); + + Want want; + want.SetParam(Constants::PARAM_FORM_MANAGER_SERVICE_BUNDLENAME_KEY, FORM_MANAGER_SERVICE_BUNDLE_NAME) + .SetParam(Constants::FORM_CONNECT_ID, 107L); + + std::vector formIds = {727L, 728L, 729L}; + const sptr callerToken = MockFormSupplyCallback::GetInstance(); + + EXPECT_EQ(ERR_OK, instance_->NotifyFormsDelete(formIds, want, callerToken)); + + GTEST_LOG_(INFO) << "AaFwk_FormProviderClient_NotifyFormsDelete_0100 end"; +} +/** + * @tc.number: AaFwk_FormProviderClient_NotifyFormsDelete_0200 + * @tc.name: FireFormEvent + * @tc.desc: Verify that the return value of FireFormEvent is correct. + */ +HWTEST_F(FormProviderClientTest, AaFwk_FormProviderClient_NotifyFormsDelete_0200, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_FormProviderClient_NotifyFormsDelete_0200 start"; + + const std::shared_ptr ability = std::make_shared(); + instance_->SetOwner(nullptr); + + Want want; + want.SetParam(Constants::PARAM_FORM_MANAGER_SERVICE_BUNDLENAME_KEY, FORM_MANAGER_SERVICE_BUNDLE_NAME) + .SetParam(Constants::FORM_CONNECT_ID, 108L); + std::vector formIds = {730L, 731L, 732L}; + const sptr callerToken = MockFormSupplyCallback::GetInstance(); + + EXPECT_EQ(ERR_APPEXECFWK_FORM_NO_SUCH_ABILITY, instance_->NotifyFormsDelete(formIds, want, callerToken)); + + GTEST_LOG_(INFO) << "AaFwk_FormProviderClient_NotifyFormsDelete_0200 end"; +} +/** + * @tc.number: AaFwk_FormProviderClient_NotifyFormsDelete_0300 + * @tc.name: NotifyFormCastTempForm + * @tc.desc: Verify that the return value of AddForm is correct. + */ +HWTEST_F(FormProviderClientTest, AaFwk_FormProviderClient_NotifyFormsDelete_0300, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_FormProviderClient_NotifyFormsDelete_0300 start"; + + const std::shared_ptr ability = std::make_shared(); + instance_->SetOwner(ability); + + Want want; + want.SetParam(Constants::PARAM_FORM_MANAGER_SERVICE_BUNDLENAME_KEY, FORM_MANAGER_SERVICE_BUNDLE_NAME) + .SetParam(Constants::FORM_CONNECT_ID, 109L); + + std::vector formIds = {730L, 731L, 732L}; + const sptr callerToken = nullptr; + + EXPECT_EQ(ERR_APPEXECFWK_FORM_BIND_PROVIDER_FAILED, instance_->NotifyFormsDelete(formIds, want, callerToken)); + + GTEST_LOG_(INFO) << "AaFwk_FormProviderClient_NotifyFormsDelete_0300 end"; +} +} // namespace AppExecFwk +} // namespace OHOS diff --git a/tools/frameworks/kits/ability/native/test/unittest/pac_map_test.cpp b/tools/frameworks/kits/ability/native/test/unittest/pac_map_test.cpp new file mode 100755 index 00000000000..08b15de9a21 --- /dev/null +++ b/tools/frameworks/kits/ability/native/test/unittest/pac_map_test.cpp @@ -0,0 +1,747 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include "pac_map.h" +#include "ohos/aafwk/base/user_object_base.h" +namespace OHOS { +namespace AppExecFwk { +using namespace testing::ext; +using namespace OHOS; +using namespace OHOS::AppExecFwk; + +#define PAC_MPA_TEST_INT 1000 +#define PAC_MAP_TEST_LONG -1000 +#define PAC_MAP_TEST_FLOAT 1.0f +#define PAC_MAP_TEST_DOUBLE 3.1415926 +namespace { +const std::regex INTEGER_REGEX("^[-+]?([0-9]+)([.]([0-9]+))?$"); +}; +class TUserObjectTest : public UserObjectBase { +public: + TUserObjectTest() : UserObjectBase("TUserObjectTest"), str_data_("用户自定义对象"), int_data_(0) + {} + virtual ~TUserObjectTest() + {} + + virtual std::string ToString() const override + { + std::string tostring = str_data_; + tostring += "#" + std::to_string(int_data_); + return tostring; + } + + virtual void Parse(const std::string &str) override + { + std::vector elems; + + std::size_t splitPos = str.find("#"); + if (splitPos == std::string::npos) { + return; + } + std::string str_data = str.substr(0, splitPos); + std::string intdata = str.substr(str_data.length() + 1, str.length() - 1); + if (str_data.length() + 1 + intdata.length() != str.length()) { + return; + } + bool isNumber = std::regex_match(intdata, INTEGER_REGEX); + if (isNumber) { + str_data_ = str_data; + int_data_ = std::stoi(intdata); + } + } + + virtual bool Equals(std::shared_ptr &other) override + { + if (other->GetClassName() != GetClassName()) { + return false; + } + + TUserObjectTest *pobject = static_cast(other.get()); + if (pobject == nullptr) { + return false; + } + return ((str_data_ == pobject->str_data_) && (int_data_ == pobject->int_data_)); + } + + virtual void DeepCopy(std::shared_ptr &other) override + { + if (other->GetClassName() != GetClassName()) { + return; + } + + TUserObjectTest *pobject = static_cast(other.get()); + if (pobject != nullptr) { + str_data_ = pobject->str_data_; + int_data_ = pobject->int_data_; + } + } + + virtual bool Marshalling(Parcel &parcel) const override + { + return true; + } + + virtual bool Unmarshalling(Parcel &parcel) override + { + return true; + } + +private: + std::string str_data_ = ""; + int int_data_ = 0; +}; +REGISTER_USER_OBJECT_BASE(TUserObjectTest); + +/* + * Description:Test for data type of base: like int, short, long std::string etc. + */ +class PacMapTest : public testing::Test { +public: + PacMapTest() : pacmap_(nullptr) + {} + ~PacMapTest() + {} + + std::shared_ptr pacmap_ = nullptr; + std::shared_ptr pacmap2_ = nullptr; + static void FillData(PacMap &pacmap); + static void FillData2(PacMap &pacmap, const PacMap ¶m_map); + + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void PacMapTest::SetUpTestCase(void) +{} + +void PacMapTest::TearDownTestCase(void) +{} + +void PacMapTest::SetUp() +{ + pacmap_ = std::make_shared(); + pacmap2_ = std::make_shared(); +} + +void PacMapTest::TearDown() +{} + +void PacMapTest::FillData(PacMap &pacmap) +{ + std::vector arrayShort; + std::vector arrayInt; + std::vector arrayLong; + std::vector arrayByte; + std::vector arrayBool; + std::vector arrayFloat; + std::vector arrayDouble; + std::vector arrayString; + + arrayShort.push_back(PAC_MPA_TEST_INT); + arrayInt.push_back(PAC_MPA_TEST_INT); + arrayLong.push_back(PAC_MAP_TEST_LONG); + arrayByte.push_back('a'); + arrayBool.push_back(true); + arrayFloat.push_back(PAC_MAP_TEST_FLOAT); + arrayDouble.push_back(PAC_MAP_TEST_DOUBLE); + arrayString.push_back("<~!@#$%^&*()_+>特殊字符"); + + pacmap.PutShortValue("key_short", PAC_MPA_TEST_INT); + pacmap.PutIntValue("key_int", PAC_MPA_TEST_INT); + pacmap.PutLongValue("key_long", PAC_MAP_TEST_LONG); + pacmap.PutByteValue("key_byte", 'A'); + pacmap.PutBooleanValue("key_boolean", true); + pacmap.PutFloatValue("key_float", PAC_MAP_TEST_FLOAT); + pacmap.PutDoubleValue("key_double", PAC_MAP_TEST_DOUBLE); + pacmap.PutStringValue("key_string", "test clone"); + + std::shared_ptr pubObject = std::make_shared(); + pacmap.PutObject("key_object", pubObject); + + pacmap.PutShortValueArray("key_short_array", arrayShort); + pacmap.PutIntValueArray("key_int_array", arrayInt); + pacmap.PutLongValueArray("key_long_array", arrayLong); + pacmap.PutByteValueArray("key_byte_array", arrayByte); + pacmap.PutFloatValueArray("key_float_array", arrayFloat); + pacmap.PutBooleanValueArray("key_boolean_array", arrayBool); + pacmap.PutDoubleValueArray("key_double_array", arrayDouble); + pacmap.PutStringValueArray("key_string_array", arrayString); +} + +void PacMapTest::FillData2(PacMap &pacmap, const PacMap ¶m_map) +{ + std::vector arrayShort; + std::vector arrayInt; + std::vector arrayLong; + std::vector arrayByte; + std::vector arrayBool; + std::vector arrayFloat; + std::vector arrayDouble; + std::vector arrayString; + + arrayShort.push_back(PAC_MPA_TEST_INT); + arrayInt.push_back(PAC_MPA_TEST_INT); + arrayLong.push_back(PAC_MAP_TEST_LONG); + arrayByte.push_back('a'); + arrayBool.push_back(true); + arrayFloat.push_back(PAC_MAP_TEST_FLOAT); + arrayDouble.push_back(PAC_MAP_TEST_DOUBLE); + arrayString.push_back("<~!@#$%^&*()_+>特殊字符"); + + pacmap.PutShortValue("key_short", PAC_MPA_TEST_INT); + pacmap.PutIntValue("key_int", PAC_MPA_TEST_INT); + pacmap.PutLongValue("key_long", PAC_MAP_TEST_LONG); + pacmap.PutByteValue("key_byte", 'A'); + pacmap.PutBooleanValue("key_boolean", true); + pacmap.PutFloatValue("key_float", PAC_MAP_TEST_FLOAT); + pacmap.PutDoubleValue("key_double", PAC_MAP_TEST_DOUBLE); + pacmap.PutStringValue("key_string", "test clone"); + + pacmap.PutPacMap("key_map", param_map); + + pacmap.PutShortValueArray("key_short_array", arrayShort); + pacmap.PutIntValueArray("key_int_array", arrayInt); + pacmap.PutLongValueArray("key_long_array", arrayLong); + pacmap.PutByteValueArray("key_byte_array", arrayByte); + pacmap.PutFloatValueArray("key_float_array", arrayFloat); + pacmap.PutBooleanValueArray("key_boolean_array", arrayBool); + pacmap.PutDoubleValueArray("key_double_array", arrayDouble); + pacmap.PutStringValueArray("key_string_array", arrayString); +} +/** + * @tc.number: AppExecFwk_PacMap_PutShortValue_0100 + * @tc.name: PutShortValue + * @tc.desc: Verify PutShortValue() and GetShortValue(). + */ +HWTEST_F(PacMapTest, AppExecFwk_PacMap_PutShortValue_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AppExecFwk_PacMap_PutShortValue_0100 start"; + short value = 1000; + pacmap_->PutShortValue("key_short", value); + EXPECT_EQ(value, pacmap_->GetShortValue("key_short")); + GTEST_LOG_(INFO) << "AppExecFwk_PacMap_PutShortValue_0100 end"; +} + +/** + * @tc.number: AppExecFwk_PacMap_PutIntValue_0100 + * @tc.name: PutIntValue and GetIntValue + * @tc.desc: Verify PutIntValue() and GetIntValue(). + */ +HWTEST_F(PacMapTest, AppExecFwk_PacMap_PutIntValue_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AppExecFwk_PacMap_PutIntValue_0100 start"; + int value = 1000; + pacmap_->PutIntValue("key_int", value); + EXPECT_EQ(value, pacmap_->GetIntValue("key_int")); + GTEST_LOG_(INFO) << "AppExecFwk_PacMap_PutIntValue_0100 end"; +} + +/** + * @tc.number: AppExecFwk_PacMap_PutLongValue_0100 + * @tc.name: PutLongValue and GetLongValue + * @tc.desc: Verify PutLongValue() and GetLongValue(). + */ +HWTEST_F(PacMapTest, AppExecFwk_PacMap_PutLongValue_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AppExecFwk_PacMap_PutLongValue_0100 start"; + long value = -1000; + pacmap_->PutLongValue("key_long", value); + EXPECT_EQ(value, pacmap_->GetLongValue("key_long")); + GTEST_LOG_(INFO) << "AppExecFwk_PacMap_PutLongValue_0100 end"; +} + +/** + * @tc.number: AppExecFwk_PacMap_PutByteValue_0100 + * @tc.name: PutByteValue and GetByteValue + * @tc.desc: Verify PutByteValue() and GetByteValue(). + */ +HWTEST_F(PacMapTest, AppExecFwk_PacMap_PutByteValue_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AppExecFwk_PacMap_PutByteValue_0100 start"; + AAFwk::byte value = 'A'; + pacmap_->PutByteValue("key_byte", value); + EXPECT_EQ(value, pacmap_->GetByteValue("key_byte")); + GTEST_LOG_(INFO) << "AppExecFwk_PacMap_PutByteValue_0100 end"; +} + +/** + * @tc.number: AppExecFwk_PacMap_PutBooleanValue_0100 + * @tc.name: PutBooleanValue and GetBooleanValue + * @tc.desc: Verify PutBooleanValue() and GetBooleanValue(). + */ +HWTEST_F(PacMapTest, AppExecFwk_PacMap_PutBooleanValue_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AppExecFwk_PacMap_PutBooleanValue_0100 start"; + bool value = true; + pacmap_->PutBooleanValue("key_boolean_true", value); + EXPECT_EQ(value, pacmap_->GetBooleanValue("key_boolean_true")); + + value = false; + pacmap_->PutBooleanValue("key_boolean_false", value); + EXPECT_EQ(value, pacmap_->GetBooleanValue("key_boolean_false")); + + GTEST_LOG_(INFO) << "AppExecFwk_PacMap_PutBooleanValue_0100 end"; +} + +/** + * @tc.number: AppExecFwk_PacMap_PutFloatValue_0100 + * @tc.name: PutFloatValue and GetFloatValue + * @tc.desc: Verify PutFloatValue() and GetFloatValue(). + */ +HWTEST_F(PacMapTest, AppExecFwk_PacMap_PutFloatValue_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AppExecFwk_PacMap_PutFloatValue_0100 start"; + float value = 3.14f; + pacmap_->PutFloatValue("key_float", value); + EXPECT_EQ(value, pacmap_->GetFloatValue("key_float")); + GTEST_LOG_(INFO) << "AppExecFwk_PacMap_PutFloatValue_0100 end"; +} + +/** + * @tc.number: AppExecFwk_PacMap_PutDoubleValue_0100 + * @tc.name: PutDoubleValue and GetDoubleValue + * @tc.desc: Verify PutDoubleValue() and GetDoubleValue(). + */ +HWTEST_F(PacMapTest, AppExecFwk_PacMap_PutDoubleValue_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AppExecFwk_PacMap_PutDoubleValue_0100 start"; + double value = 3.1415926; + pacmap_->PutDoubleValue("key_double", value); + EXPECT_EQ(value, pacmap_->GetDoubleValue("key_double")); + GTEST_LOG_(INFO) << "AppExecFwk_PacMap_PutDoubleValue_0100 end"; +} + +/** + * @tc.number: AppExecFwk_PacMap_PutStringValue_0100 + * @tc.name: PutStringValue and GetStringValue + * @tc.desc: Verify PutStringValue() and GetStringValue(). + */ +HWTEST_F(PacMapTest, AppExecFwk_PacMap_PutStringValue_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AppExecFwk_PacMap_PutStringValue_0100 start"; + std::string value("AppExecFwk_PacMap_PutStringValue_0100 PACMAP测试"); + pacmap_->PutStringValue("key_string", value); + std::string getStr = pacmap_->GetStringValue("key_string"); + EXPECT_STREQ(value.c_str(), getStr.c_str()); + GTEST_LOG_(INFO) << "AppExecFwk_PacMap_PutStringValue_0100 end"; +} + +/** + * @tc.number: AppExecFwk_PacMap_PutShortValueArray_0100 + * @tc.name: PutShortValueArray and GetShortValueArray + * @tc.desc: Verify PutShortValueArray() and GetShortValueArray(). + */ +HWTEST_F(PacMapTest, AppExecFwk_PacMap_PutShortValueArray_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AppExecFwk_PacMap_PutShortValueArray_0100 start"; + + std::vector putValue; + std::vector getValue; + for (int i = 0; i < 100; i++) { + putValue.emplace_back(i + 1); + } + pacmap_->PutShortValueArray("key_short_array", putValue); + pacmap_->GetShortValueArray("key_short_array", getValue); + + bool isEqual = (putValue == getValue); + EXPECT_EQ(true, isEqual); + + GTEST_LOG_(INFO) << "AppExecFwk_PacMap_PutShortValueArray_0100 end"; +} + +/** + * @tc.number: AppExecFwk_PacMap_PutIntValueArray_0100 + * @tc.name: PutIntValueArray and GetIntValueArray + * @tc.desc: Verify PutIntValueArray() and GetIntValueArray(). + */ +HWTEST_F(PacMapTest, AppExecFwk_PacMap_PutIntValueArray_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AppExecFwk_PacMap_PutIntValueArray_0100 start"; + + std::vector putValue; + std::vector getValue; + for (int i = 0; i < 100; i++) { + putValue.emplace_back(i + 1); + } + pacmap_->PutIntValueArray("key_int_array", putValue); + pacmap_->GetIntValueArray("key_int_array", getValue); + + bool isEqual = (putValue == getValue); + EXPECT_EQ(true, isEqual); + + GTEST_LOG_(INFO) << "AppExecFwk_PacMap_PutIntValueArray_0100 end"; +} + +/** + * @tc.number: AppExecFwk_PacMap_PutLongArray_0100 + * @tc.name: PutLongValueArray and GetLongValueArray + * @tc.desc: Verify PutLongValueArray() and GetLongValueArray(). + */ +HWTEST_F(PacMapTest, AppExecFwk_PacMap_PutLongArray_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AppExecFwk_PacMap_PutLongArray_0100 start"; + + std::vector putValue; + std::vector getValue; + for (int i = 0; i < 100; i++) { + putValue.emplace_back(i + 1); + } + pacmap_->PutLongValueArray("key_long_array", putValue); + pacmap_->GetLongValueArray("key_long_array", getValue); + + bool isEqual = (putValue == getValue); + EXPECT_EQ(true, isEqual); + + GTEST_LOG_(INFO) << "AppExecFwk_PacMap_PutLongArray_0100 end"; +} + +/** + * @tc.number: AppExecFwk_PacMap_PutByteArray_0100 + * @tc.name: PutByteValueArray and GetByteValueArray + * @tc.desc: Verify PutByteValueArray() and GetByteValueArray(). + */ +HWTEST_F(PacMapTest, AppExecFwk_PacMap_PutByteArray_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AppExecFwk_PacMap_PutByteArray_0100 start"; + + std::vector putValue; + std::vector getValue; + for (int i = 0; i < 26; i++) { + putValue.emplace_back('A' + i); + } + pacmap_->PutByteValueArray("key_byte_array", putValue); + pacmap_->GetByteValueArray("key_byte_array", getValue); + + bool isEqual = (putValue == getValue); + EXPECT_EQ(true, isEqual); + + GTEST_LOG_(INFO) << "AppExecFwk_PacMap_PutByteArray_0100 end"; +} + +/** + * @tc.number: AppExecFwk_PacMap_PutFloatArray_0100 + * @tc.name: PutLongValueArray and GetLongValueArray + * @tc.desc: Verify PutLongValueArray() and GetLongValueArray(). + */ +HWTEST_F(PacMapTest, AppExecFwk_PacMap_PutFloatArray_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AppExecFwk_PacMap_PutFloatArray_0100 start"; + + std::vector putValue; + std::vector getValue; + for (int i = 0; i < 100; i++) { + putValue.emplace_back((i + 1) * 1.0f); + } + pacmap_->PutFloatValueArray("key_long_array", putValue); + pacmap_->GetFloatValueArray("key_long_array", getValue); + + bool isEqual = (putValue == getValue); + EXPECT_EQ(true, isEqual); + + GTEST_LOG_(INFO) << "AppExecFwk_PacMap_PutFloatArray_0100 end"; +} + +/** + * @tc.number: AppExecFwk_PacMap_PutDoubleArray_0100 + * @tc.name: PutDoubleValueArray and GetDoubleValueArray + * @tc.desc: Verify PutDoubleValueArray() and GetDoubleValueArray(). + */ +HWTEST_F(PacMapTest, AppExecFwk_PacMap_PutDoubleArray_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AppExecFwk_PacMap_PutDoubleArray_0100 start"; + + std::vector putValue; + std::vector getValue; + for (int i = 0; i < 100; i++) { + putValue.emplace_back((i + 1) * 1.0); + } + pacmap_->PutDoubleValueArray("key_double_array", putValue); + pacmap_->GetDoubleValueArray("key_double_array", getValue); + + bool isEqual = (putValue == getValue); + EXPECT_EQ(true, isEqual); + + GTEST_LOG_(INFO) << "AppExecFwk_PacMap_PutDoubleArray_0100 end"; +} + +/** + * @tc.number: AppExecFwk_PacMap_PutStringArray_0100 + * @tc.name: PutStringValueArray and GetStringValueArray + * @tc.desc: Verify PutStringValueArray() and GetStringValueArray(). + */ +HWTEST_F(PacMapTest, AppExecFwk_PacMap_PutStringArray_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AppExecFwk_PacMap_PutStringArray_0100 start"; + + std::vector tempValue; + std::vector putValue; + std::vector getValue; + + tempValue.emplace_back("Adds a String value matching a specified key."); + tempValue.emplace_back("添加字符串"); + tempValue.emplace_back("<~!@#$%^&*()_+>特殊字符"); + + for (int i = 0; i < 100; i++) { + putValue.emplace_back(tempValue[i % 3]); + } + pacmap_->PutStringValueArray("key_string_array", putValue); + pacmap_->GetStringValueArray("key_string_array", getValue); + + bool isEqual = (putValue == getValue); + EXPECT_EQ(true, isEqual); + + GTEST_LOG_(INFO) << "AppExecFwk_PacMap_PutStringArray_0100 end"; +} + +/** + * @tc.number: AppExecFwk_PacMap_PutObject_0100 + * @tc.name: PutObject and GetObject + * @tc.desc: Verify PutObject() and GetObject(). + */ +HWTEST_F(PacMapTest, AppExecFwk_PacMap_PutObject_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AppExecFwk_PacMap_PutObject_0100 start"; + + std::shared_ptr putObject = std::make_shared(); + pacmap_->PutObject("key_object", putObject); + + std::shared_ptr getObject = pacmap_->GetObject("key_object"); + bool isEqual = false; + if (getObject.get() != nullptr) { + isEqual = getObject->Equals(getObject); + } + EXPECT_EQ(true, isEqual); + + GTEST_LOG_(INFO) << "AppExecFwk_PacMap_PutObject_0100 end"; +} + +/** + * @tc.number: AppExecFwk_PacMap_Clone_0100 + * @tc.name: Clone and Equals + * @tc.desc: Verify Clone() and Equals(). + */ +HWTEST_F(PacMapTest, AppExecFwk_PacMap_Clone_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AppExecFwk_PacMap_Clone_0100 start"; + + PacMap otherMap; + FillData(*pacmap_.get()); + otherMap = pacmap_->Clone(); + EXPECT_EQ(true, pacmap_->Equals(otherMap)); + + GTEST_LOG_(INFO) << "AppExecFwk_PacMap_Clone_0100 end"; +} + +/** + * @tc.number: AppExecFwk_PacMap_DeepCopy_0100 + * @tc.name: DeepCopy + * @tc.desc: Verify DeepCopy(). + */ +HWTEST_F(PacMapTest, AppExecFwk_PacMap_DeepCopy_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AppExecFwk_PacMap_DeepCopy_0100 start"; + + PacMap otherMap; + FillData(*pacmap_.get()); + otherMap = pacmap_->DeepCopy(); + EXPECT_EQ(true, pacmap_->Equals(otherMap)); + + GTEST_LOG_(INFO) << "AppExecFwk_PacMap_DeepCopy_0100 end"; +} + +/** + * @tc.number: AppExecFwk_PacMap_Clear_0100 + * @tc.name: Clear and GetSize + * @tc.desc: Verify Clear() and GetSize(). + */ +HWTEST_F(PacMapTest, AppExecFwk_PacMap_Clear_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AppExecFwk_PacMap_Clear_0100 start"; + + FillData(*pacmap_.get()); + pacmap_->Clear(); + EXPECT_EQ(0, pacmap_->GetSize()); + + GTEST_LOG_(INFO) << "AppExecFwk_PacMap_Clear_0100 end"; +} + +/** + * @tc.number: AppExecFwk_PacMap_PutAll_0100 + * @tc.name: PutAll + * @tc.desc: Verify PutAll(). + */ +HWTEST_F(PacMapTest, AppExecFwk_PacMap_PutAll_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AppExecFwk_PacMap_PutAll_0100 start"; + + PacMap otherMap; + FillData(otherMap); + pacmap_->PutAll(otherMap); + EXPECT_EQ(true, pacmap_->Equals(otherMap)); + + GTEST_LOG_(INFO) << "AppExecFwk_PacMap_PutAll_0100 end"; +} + +/** + * @tc.number: AppExecFwk_PacMap_GetAll_0100 + * @tc.name: GetAll + * @tc.desc: Verify GetAll(). + */ +HWTEST_F(PacMapTest, AppExecFwk_PacMap_GetAll_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AppExecFwk_PacMap_GetAll_0100 start"; + + FillData(*pacmap_.get()); + std::map data = pacmap_->GetAll(); + + EXPECT_EQ(data.size(), (std::size_t)pacmap_->GetSize()); + + GTEST_LOG_(INFO) << "AppExecFwk_PacMap_GetAll_0100 end"; +} + +/** + * @tc.number: AppExecFwk_PacMap_HasKey_0100 + * @tc.name: HasKey + * @tc.desc: Verify HasKey(). + */ +HWTEST_F(PacMapTest, AppExecFwk_PacMap_HasKey_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AppExecFwk_PacMap_HasKey_0100 start"; + + FillData(*pacmap_.get()); + EXPECT_EQ(true, pacmap_->HasKey("key_short_array")); + + GTEST_LOG_(INFO) << "AppExecFwk_PacMap_HasKey_0100 end"; +} + +/** + * @tc.number: AppExecFwk_PacMap_GetKeys_0100 + * @tc.name: GetKeys + * @tc.desc: Verify GetKeys(). + */ +HWTEST_F(PacMapTest, AppExecFwk_PacMap_GetKeys_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AppExecFwk_PacMap_GetKeys_0100 start"; + + FillData(*pacmap_.get()); + const std::set keys = pacmap_->GetKeys(); + EXPECT_EQ((int)keys.size(), pacmap_->GetSize()); + + GTEST_LOG_(INFO) << "AppExecFwk_PacMap_GetKeys_0100 end"; +} + +/** + * @tc.number: AppExecFwk_PacMap_Remove_0100 + * @tc.name: Remove + * @tc.desc: Verify Remove(). + */ +HWTEST_F(PacMapTest, AppExecFwk_PacMap_Remove_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AppExecFwk_PacMap_Remove_0100 start"; + + FillData(*pacmap_.get()); + EXPECT_EQ(true, pacmap_->HasKey("key_short_array")); + pacmap_->Remove("key_short_array"); + EXPECT_EQ(false, pacmap_->HasKey("key_short_array")); + + GTEST_LOG_(INFO) << "AppExecFwk_PacMap_Remove_0100 end"; +} + +/** + * @tc.number: AppExecFwk_PacMap_IsEmpty_0100 + * @tc.name: IsEmpty + * @tc.desc: Verify IsEmpty(). + */ +HWTEST_F(PacMapTest, AppExecFwk_PacMap_IsEmpty_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AppExecFwk_PacMap_IsEmpty_0100 start"; + + FillData(*pacmap_.get()); + EXPECT_EQ(false, pacmap_->IsEmpty()); + pacmap_->Clear(); + EXPECT_EQ(true, pacmap_->IsEmpty()); + + GTEST_LOG_(INFO) << "AppExecFwk_PacMap_IsEmpty_0100 end"; +} + +/** + * @tc.number: AppExecFwk_PacMap_Marshalling_0100 + * @tc.name: Marshalling and Unmarshalling + * @tc.desc: Verify Marshalling() and Unmarshalling(). + */ +HWTEST_F(PacMapTest, AppExecFwk_PacMap_Marshalling_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AppExecFwk_PacMap_Marshalling_0100 start"; + + Parcel parcel; + FillData(*pacmap_.get()); + EXPECT_EQ(true, pacmap_->Marshalling(parcel)); + + PacMap *unmarshingMap = PacMap::Unmarshalling(parcel); + EXPECT_EQ(true, unmarshingMap != nullptr); + if (unmarshingMap != nullptr) { + EXPECT_EQ(true, pacmap_->Equals(unmarshingMap)); + delete unmarshingMap; + unmarshingMap = nullptr; + } + GTEST_LOG_(INFO) << "AppExecFwk_PacMap_Marshalling_0100 end"; +} +/** + * @tc.number: AppExecFwk_PacMap_Marshalling_0200 + * @tc.name: Marshalling and Unmarshalling + * @tc.desc: Verify Marshalling() and Unmarshalling(). + */ +HWTEST_F(PacMapTest, AppExecFwk_PacMap_Marshalling_0200, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AppExecFwk_PacMap_Marshalling_0200 start"; + + Parcel parcel; + FillData(*pacmap_.get()); + FillData2(*pacmap2_.get(), *pacmap_.get()); + + EXPECT_EQ(true, pacmap2_->Marshalling(parcel)); + PacMap *unmarshingMap = PacMap::Unmarshalling(parcel); + + EXPECT_EQ(true, unmarshingMap != nullptr); + if (unmarshingMap != nullptr) { + EXPECT_EQ(true, pacmap2_->Equals(unmarshingMap)); + delete unmarshingMap; + unmarshingMap = nullptr; + } + GTEST_LOG_(INFO) << "AppExecFwk_PacMap_Marshalling_0200 end"; +} +/** + * @tc.number: AppExecFwk_PacMap_Marshalling_0300 + * @tc.name: Marshalling and Unmarshalling + * @tc.desc: Verify Marshalling() and Unmarshalling(). + */ +HWTEST_F(PacMapTest, AppExecFwk_PacMap_Marshalling_0300, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AppExecFwk_PacMap_Marshalling_0300 start"; + + Parcel parcel; + EXPECT_EQ(true, pacmap2_->Marshalling(parcel)); + PacMap *unmarshingMap = PacMap::Unmarshalling(parcel); + + EXPECT_EQ(true, unmarshingMap != nullptr); + GTEST_LOG_(INFO) << "AppExecFwk_PacMap_Marshalling_0300 end"; +} +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/test/unittest/page_ability_impl_test.cpp b/tools/frameworks/kits/ability/native/test/unittest/page_ability_impl_test.cpp new file mode 100644 index 00000000000..98d13e7b807 --- /dev/null +++ b/tools/frameworks/kits/ability/native/test/unittest/page_ability_impl_test.cpp @@ -0,0 +1,683 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "ability_state.h" +#include "mock_page_ability.h" +#include "mock_ability_lifecycle_callbacks.h" +#include "mock_ability_token.h" +#include "page_ability_impl.h" + +namespace OHOS { +namespace AppExecFwk { +using namespace testing::ext; +using namespace OHOS; +using namespace OHOS::AppExecFwk; +using namespace OHOS::AAFwk; + +class PageAbilityImplTest : public testing::Test { +public: + PageAbilityImplTest() : pageAbilityImpl_(nullptr) + {} + ~PageAbilityImplTest() + { + pageAbilityImpl_ = nullptr; + } + std::shared_ptr pageAbilityImpl_; + + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void PageAbilityImplTest::SetUpTestCase(void) +{} + +void PageAbilityImplTest::TearDownTestCase(void) +{} + +void PageAbilityImplTest::SetUp(void) +{ + pageAbilityImpl_ = std::make_shared(); +} + +void PageAbilityImplTest::TearDown(void) +{} + + +/** + * @tc.number: AaFwk_PageAbilityImpl_DoKeyDown_0100 + * @tc.name: DoKeyDown + * @tc.desc: Verify that the event is handled by an exception + */ +HWTEST_F(PageAbilityImplTest, AaFwk_PageAbilityImpl_DoKeyDown_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_PageAbilityImpl_DoKeyDown_0100 start"; + + std::shared_ptr application = std::make_shared(); + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "pageAbility"; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + std::shared_ptr record = std::make_shared(abilityInfo, token); + + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + + std::shared_ptr ability = std::make_shared(); + std::shared_ptr contextDeal = std::make_shared(); + pageAbilityImpl_->Init(application, record, ability, handler, token, contextDeal); + + int keyCode = 1; + KeyEvent keyEvent; + bool ret = pageAbilityImpl_->DoKeyDown(keyCode, keyEvent); + EXPECT_EQ(ret, false); + sleep(1); + GTEST_LOG_(INFO) << "AaFwk_PageAbilityImpl_DoKeyDown_0100 end"; +} + +/** + * @tc.number: AaFwk_PageAbilityImpl_DoKeyDown_0200 + * @tc.name: DoKeyDown + * @tc.desc: Verify that the event is handled properly + */ +HWTEST_F(PageAbilityImplTest, AaFwk_PageAbilityImpl_DoKeyDown_0200, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_PageAbilityImpl_DoKeyDown_0200 start"; + + std::shared_ptr application = std::make_shared(); + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "pageAbility"; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + std::shared_ptr record = std::make_shared(abilityInfo, token); + + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + + std::shared_ptr ability = std::make_shared(); + std::shared_ptr contextDeal = std::make_shared(); + pageAbilityImpl_->Init(application, record, ability, handler, token, contextDeal); + + int keyCode = 1; + KeyEvent keyEvent; + bool ret = pageAbilityImpl_->DoKeyDown(keyCode, keyEvent); + EXPECT_EQ(ret, true); + GTEST_LOG_(INFO) << "AaFwk_PageAbilityImpl_DoKeyDown_0200 end"; +} + +/** + * @tc.number: AaFwk_PageAbilityImpl_DoKeyUp_0100 + * @tc.name: DoKeyUp + * @tc.desc: Verify that the event is handled by an exception + */ +HWTEST_F(PageAbilityImplTest, AaFwk_PageAbilityImpl_DoKeyUp_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_PageAbilityImpl_DoKeyUp_0100 start"; + + std::shared_ptr application = std::make_shared(); + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "pageAbility"; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + std::shared_ptr record = std::make_shared(abilityInfo, token); + + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + + std::shared_ptr ability = std::make_shared(); + std::shared_ptr contextDeal = std::make_shared(); + pageAbilityImpl_->Init(application, record, ability, handler, token, contextDeal); + + int keyCode = 1; + KeyEvent keyEvent; + bool ret = pageAbilityImpl_->DoKeyUp(keyCode, keyEvent); + EXPECT_EQ(ret, false); + + GTEST_LOG_(INFO) << "AaFwk_PageAbilityImpl_DoKeyUp_0100 end"; +} + +/** + * @tc.number: AaFwk_PageAbilityImpl_DoKeyUp_0200 + * @tc.name: DoKeyUp + * @tc.desc: Verify that the event is handled properly + */ +HWTEST_F(PageAbilityImplTest, AaFwk_PageAbilityImpl_DoKeyUp_0200, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_PageAbilityImpl_DoKeyUp_0200 start"; + + std::shared_ptr application = std::make_shared(); + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "pageAbility"; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + std::shared_ptr record = std::make_shared(abilityInfo, token); + + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + + std::shared_ptr ability = std::make_shared(); + + std::shared_ptr contextDeal = std::make_shared(); + pageAbilityImpl_->Init(application, record, ability, handler, token, contextDeal); + + int keyCode = 1; + KeyEvent keyEvent; + bool ret = pageAbilityImpl_->DoKeyUp(keyCode, keyEvent); + EXPECT_EQ(ret, true); + + GTEST_LOG_(INFO) << "AaFwk_PageAbilityImpl_DoKeyUp_0200 end"; +} + +/** + * @tc.number: AaFwk_PageAbilityImpl_DoTouchEvent_0100 + * @tc.name: DoTouchEvent + * @tc.desc: Verify that the event is handled by an exception + */ +HWTEST_F(PageAbilityImplTest, AaFwk_PageAbilityImpl_DoTouchEvent_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_PageAbilityImpl_DoTouchEvent_0100 start"; + + std::shared_ptr application = std::make_shared(); + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "pageAbility"; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + std::shared_ptr record = std::make_shared(abilityInfo, token); + + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + + std::shared_ptr ability = std::make_shared(); + + std::shared_ptr contextDeal = std::make_shared(); + pageAbilityImpl_->Init(application, record, ability, handler, token, contextDeal); + + TouchEvent touchEvent; + bool ret = pageAbilityImpl_->DoTouchEvent(touchEvent); + EXPECT_EQ(ret, false); + + GTEST_LOG_(INFO) << "AaFwk_PageAbilityImpl_DoTouchEvent_0100 end"; +} + +/** + * @tc.number: AaFwk_PageAbilityImpl_DoTouchEvent_0200 + * @tc.name: DoTouchEvent + * @tc.desc: Verify that the event is handled properly + */ +HWTEST_F(PageAbilityImplTest, AaFwk_PageAbilityImpl_DoTouchEvent_0200, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_PageAbilityImpl_DoTouchEvent_0200 start"; + + std::shared_ptr application = std::make_shared(); + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "pageAbility"; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + std::shared_ptr record = std::make_shared(abilityInfo, token); + + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + + std::shared_ptr ability = std::make_shared(); + + std::shared_ptr contextDeal = std::make_shared(); + pageAbilityImpl_->Init(application, record, ability, handler, token, contextDeal); + + TouchEvent touchEvent; + bool ret = pageAbilityImpl_->DoTouchEvent(touchEvent); + EXPECT_EQ(ret, true); + + GTEST_LOG_(INFO) << "AaFwk_PageAbilityImpl_DoTouchEvent_0200 end"; +} + +/** + * @tc.number: AaFwk_PageAbilityImpl_HandleAbilityTransaction_0100 + * @tc.name: HandleAbilityTransaction + * @tc.desc: Handle transactions in the Initial state + */ +HWTEST_F(PageAbilityImplTest, AaFwk_PageAbilityImpl_HandleAbilityTransaction_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_PageAbilityImpl_HandleAbilityTransaction_0100 start"; + + std::shared_ptr application = std::make_shared(); + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "pageAbility"; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + std::shared_ptr record = std::make_shared(abilityInfo, token); + + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + + std::shared_ptr ability = std::make_shared(); + + std::shared_ptr contextDeal = std::make_shared(); + pageAbilityImpl_->Init(application, record, ability, handler, token, contextDeal); + + Want want; + AAFwk::LifeCycleStateInfo state; + state.state = ABILITY_STATE_INITIAL; + GTEST_LOG_(INFO) << "AaFwk_PageAbilityImpl_HandleAbilityTransaction_0100 midle"; + pageAbilityImpl_->HandleAbilityTransaction(want, state); + GTEST_LOG_(INFO) << "AaFwk_PageAbilityImpl_HandleAbilityTransaction_0100 midle2"; + EXPECT_EQ(ABILITY_STATE_INITIAL, pageAbilityImpl_->GetCurrentState()); + + GTEST_LOG_(INFO) << "AaFwk_PageAbilityImpl_HandleAbilityTransaction_0100 end"; +} + +/** + * @tc.number: AaFwk_PageAbilityImpl_HandleAbilityTransaction_0200 + * @tc.name: HandleAbilityTransaction + * @tc.desc: Handle transactions in the Inactive state + */ +HWTEST_F(PageAbilityImplTest, AaFwk_PageAbilityImpl_HandleAbilityTransaction_0200, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_PageAbilityImpl_HandleAbilityTransaction_0200 start"; + + std::shared_ptr application = std::make_shared(); + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "pageAbility"; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + std::shared_ptr record = std::make_shared(abilityInfo, token); + + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + + std::shared_ptr ability = std::make_shared(); + + std::shared_ptr contextDeal = std::make_shared(); + pageAbilityImpl_->Init(application, record, ability, handler, token, contextDeal); + + Want want; + AAFwk::LifeCycleStateInfo state; + state.state = ABILITY_STATE_INACTIVE; + pageAbilityImpl_->HandleAbilityTransaction(want, state); + + GTEST_LOG_(INFO) << "AaFwk_PageAbilityImpl_HandleAbilityTransaction_0200 end"; +} + +/** + * @tc.number: AaFwk_PageAbilityImpl_HandleAbilityTransaction_0300 + * @tc.name: HandleAbilityTransaction + * @tc.desc: Handle transactions in the Active state + */ +HWTEST_F(PageAbilityImplTest, AaFwk_PageAbilityImpl_HandleAbilityTransaction_0300, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_PageAbilityImpl_HandleAbilityTransaction_0300 start"; + + std::shared_ptr application = std::make_shared(); + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "pageAbility"; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + std::shared_ptr record = std::make_shared(abilityInfo, token); + + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + + std::shared_ptr ability = std::make_shared(); + + std::shared_ptr contextDeal = std::make_shared(); + pageAbilityImpl_->Init(application, record, ability, handler, token, contextDeal); + + Want want; + AAFwk::LifeCycleStateInfo state; + state.state = ABILITY_STATE_ACTIVE; + pageAbilityImpl_->HandleAbilityTransaction(want, state); + + GTEST_LOG_(INFO) << "AaFwk_PageAbilityImpl_HandleAbilityTransaction_0300 end"; +} + +/** + * @tc.number: AaFwk_PageAbilityImpl_HandleAbilityTransaction_0400 + * @tc.name: HandleAbilityTransaction + * @tc.desc: Handle transactions in the Background state + */ +HWTEST_F(PageAbilityImplTest, AaFwk_PageAbilityImpl_HandleAbilityTransaction_0400, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_PageAbilityImpl_HandleAbilityTransaction_0400 start"; + + std::shared_ptr application = std::make_shared(); + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "pageAbility"; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + std::shared_ptr record = std::make_shared(abilityInfo, token); + + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + + std::shared_ptr ability = std::make_shared(); + + std::shared_ptr contextDeal = std::make_shared(); + pageAbilityImpl_->Init(application, record, ability, handler, token, contextDeal); + + Want want; + AAFwk::LifeCycleStateInfo state; + state.state = ABILITY_STATE_BACKGROUND; + pageAbilityImpl_->HandleAbilityTransaction(want, state); + + GTEST_LOG_(INFO) << "AaFwk_PageAbilityImpl_HandleAbilityTransaction_0400 end"; +} + +/** + * @tc.number: AaFwk_PageAbilityImpl_HandleAbilityTransaction_0500 + * @tc.name: HandleAbilityTransaction + * @tc.desc: Handle transactions in the Active and Inactive states + */ +HWTEST_F(PageAbilityImplTest, AaFwk_PageAbilityImpl_HandleAbilityTransaction_0500, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_PageAbilityImpl_HandleAbilityTransaction_0500 start"; + + std::shared_ptr application = std::make_shared(); + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "pageAbility"; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + std::shared_ptr record = std::make_shared(abilityInfo, token); + + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + + std::shared_ptr ability = std::make_shared(); + + std::shared_ptr contextDeal = std::make_shared(); + pageAbilityImpl_->Init(application, record, ability, handler, token, contextDeal); + + Want want; + AAFwk::LifeCycleStateInfo state; + state.state = ABILITY_STATE_ACTIVE; + pageAbilityImpl_->HandleAbilityTransaction(want, state); + state.state = ABILITY_STATE_INACTIVE; + pageAbilityImpl_->HandleAbilityTransaction(want, state); + + GTEST_LOG_(INFO) << "AaFwk_PageAbilityImpl_HandleAbilityTransaction_0500 end"; +} + +/** + * @tc.number: AaFwk_PageAbilityImpl_HandleAbilityTransaction_0600 + * @tc.name: HandleAbilityTransaction + * @tc.desc: Handle transactions in the Active and Background states + */ +HWTEST_F(PageAbilityImplTest, AaFwk_PageAbilityImpl_HandleAbilityTransaction_0600, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_PageAbilityImpl_HandleAbilityTransaction_0600 start"; + + std::shared_ptr application = std::make_shared(); + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "pageAbility"; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + std::shared_ptr record = std::make_shared(abilityInfo, token); + + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + + std::shared_ptr ability = std::make_shared(); + + std::shared_ptr contextDeal = std::make_shared(); + pageAbilityImpl_->Init(application, record, ability, handler, token, contextDeal); + + Want want; + + AAFwk::LifeCycleStateInfo state; + state.state = ABILITY_STATE_ACTIVE; + pageAbilityImpl_->HandleAbilityTransaction(want, state); + state.state = ABILITY_STATE_BACKGROUND; + pageAbilityImpl_->HandleAbilityTransaction(want, state); + + GTEST_LOG_(INFO) << "AaFwk_PageAbilityImpl_HandleAbilityTransaction_0600 end"; +} + +/** + * @tc.number: AaFwk_PageAbilityImpl_HandleAbilityTransaction_0700 + * @tc.name: HandleAbilityTransaction + * @tc.desc: Handle transactions in the Active and Background states + */ +HWTEST_F(PageAbilityImplTest, AaFwk_PageAbilityImpl_HandleAbilityTransaction_0700, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_PageAbilityImpl_HandleAbilityTransaction_0700 start"; + + std::shared_ptr application = std::make_shared(); + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "pageAbility"; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + std::shared_ptr record = std::make_shared(abilityInfo, token); + + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + + std::shared_ptr ability = std::make_shared(); + + std::shared_ptr contextDeal = std::make_shared(); + pageAbilityImpl_->Init(application, record, ability, handler, token, contextDeal); + + Want want; + AAFwk::LifeCycleStateInfo state; + state.state = ABILITY_STATE_ACTIVE; + + pageAbilityImpl_->HandleAbilityTransaction(want, state); + state.state = ABILITY_STATE_BACKGROUND; + pageAbilityImpl_->HandleAbilityTransaction(want, state); + state.state = ABILITY_STATE_ACTIVE; + pageAbilityImpl_->HandleAbilityTransaction(want, state); + + GTEST_LOG_(INFO) << "AaFwk_PageAbilityImpl_HandleAbilityTransaction_0700 end"; +} + +/** + * @tc.number: AaFwk_PageAbilityImpl_HandleAbilityTransaction_0800 + * @tc.name: HandleAbilityTransaction + * @tc.desc: Handle transactions in the Active and Background states + */ +HWTEST_F(PageAbilityImplTest, AaFwk_PageAbilityImpl_HandleAbilityTransaction_0800, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_PageAbilityImpl_HandleAbilityTransaction_0800 start"; + + std::shared_ptr application = std::make_shared(); + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "pageAbility"; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + std::shared_ptr record = std::make_shared(abilityInfo, token); + + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + + std::shared_ptr ability = std::make_shared(); + + std::shared_ptr contextDeal = std::make_shared(); + pageAbilityImpl_->Init(application, record, ability, handler, token, contextDeal); + + Want want; + AAFwk::LifeCycleStateInfo state; + state.state = ABILITY_STATE_ACTIVE; + pageAbilityImpl_->HandleAbilityTransaction(want, state); + state.state = ABILITY_STATE_BACKGROUND; + pageAbilityImpl_->HandleAbilityTransaction(want, state); + state.state = ABILITY_STATE_INACTIVE; + pageAbilityImpl_->HandleAbilityTransaction(want, state); + + GTEST_LOG_(INFO) << "AaFwk_PageAbilityImpl_HandleAbilityTransaction_0800 end"; +} + +/** + * @tc.number: AaFwk_PageAbilityImpl_HandleAbilityTransaction_0900 + * @tc.name: HandleAbilityTransaction + * @tc.desc: Handle transactions in the Active/Background/Inactive/Inital states + */ +HWTEST_F(PageAbilityImplTest, AaFwk_PageAbilityImpl_HandleAbilityTransaction_0900, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_PageAbilityImpl_HandleAbilityTransaction_0900 start"; + + std::shared_ptr application = std::make_shared(); + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "pageAbility"; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + std::shared_ptr record = std::make_shared(abilityInfo, token); + + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + + std::shared_ptr ability = std::make_shared(); + + std::shared_ptr contextDeal = std::make_shared(); + pageAbilityImpl_->Init(application, record, ability, handler, token, contextDeal); + + Want want; + AAFwk::LifeCycleStateInfo state; + state.state = ABILITY_STATE_ACTIVE; + pageAbilityImpl_->HandleAbilityTransaction(want, state); + state.state = ABILITY_STATE_BACKGROUND; + pageAbilityImpl_->HandleAbilityTransaction(want, state); + state.state = ABILITY_STATE_INACTIVE; + pageAbilityImpl_->HandleAbilityTransaction(want, state); + state.state = ABILITY_STATE_INITIAL; + pageAbilityImpl_->HandleAbilityTransaction(want, state); + + GTEST_LOG_(INFO) << "AaFwk_PageAbilityImpl_HandleAbilityTransaction_0900 end"; +} + +/** + * @tc.number: AaFwk_PageAbilityImpl_DispatchSaveAbilityState_0100 + * @tc.name: DispatchSaveAbilityState + * @tc.desc: Test the normal behavior of the AbilityImpl::DisoatcgSaveAbilityState + */ +HWTEST_F(PageAbilityImplTest, AaFwk_PageAbilityImpl_DispatchSaveAbilityState_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_PageAbilityImpl_DispatchSaveAbilityState_0100 start"; + + std::shared_ptr application = std::make_shared(); + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "pageAbility"; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + std::shared_ptr record = std::make_shared(abilityInfo, token); + + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + + std::shared_ptr ability = std::make_shared(); + + std::shared_ptr callback = std::make_shared(); + application->RegisterAbilityLifecycleCallbacks(callback); + + std::shared_ptr contextDeal = std::make_shared(); + pageAbilityImpl_->Init(application, record, ability, handler, token, contextDeal); + + PacMap outState; + pageAbilityImpl_->DispatchSaveAbilityState(outState); + + GTEST_LOG_(INFO) << "AaFwk_PageAbilityImpl_DispatchSaveAbilityState_0100 end"; +} + +/** + * @tc.number: AaFwk_PageAbilityImpl_DispatchRestoreAbilityState_0100 + * @tc.name: DispatchRestoreAbilityState + * @tc.desc: Test the abnormal behavior of the AbilityImpl::DispatchRestoreAbilityState + */ +HWTEST_F(PageAbilityImplTest, AaFwk_PageAbilityImpl_DispatchRestoreAbilityState_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_PageAbilityImpl_DispatchRestoreAbilityState_0100 start"; + + std::shared_ptr application = std::make_shared(); + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "pageAbility"; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + std::shared_ptr record = std::make_shared(abilityInfo, token); + + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + + std::shared_ptr ability = std::make_shared(); + + std::shared_ptr contextDeal = std::make_shared(); + pageAbilityImpl_->Init(application, record, ability, handler, token, contextDeal); + + PacMap inState; + pageAbilityImpl_->DispatchRestoreAbilityState(inState); + + GTEST_LOG_(INFO) << "AaFwk_PageAbilityImpl_DispatchRestoreAbilityState_0100 end"; +} + +/** + * @tc.number: AaFwk_PageAbilityImpl_SendResult_0100 + * @tc.name: SendResult + * @tc.desc: Test the normal behavior of the AbilityImpl::SendResult + */ +HWTEST_F(PageAbilityImplTest, AaFwk_PageAbilityImpl_SendResult_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_PageAbilityImpl_SendResult_0100 start"; + + std::shared_ptr application = std::make_shared(); + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "pageAbility"; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + std::shared_ptr record = std::make_shared(abilityInfo, token); + + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + + std::shared_ptr ability = std::make_shared(); + + std::shared_ptr contextDeal = std::make_shared(); + pageAbilityImpl_->Init(application, record, ability, handler, token, contextDeal); + + int requestCode = 1; + int resultCode = 2; + Want want; + pageAbilityImpl_->SendResult(requestCode, resultCode, want); + + GTEST_LOG_(INFO) << "AaFwk_PageAbilityImpl_SendResult_0100 end"; +} + +/** + * @tc.number: AaFwk_PageAbilityImpl_NewWant_0100 + * @tc.name: NewWant + * @tc.desc: Test the normal behavior of the AbilityImpl::NewWant + */ +HWTEST_F(PageAbilityImplTest, AaFwk_PageAbilityImpl_NewWant_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_PageAbilityImpl_NewWant_0100 start"; + + std::shared_ptr application = std::make_shared(); + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "pageAbility"; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + std::shared_ptr record = std::make_shared(abilityInfo, token); + + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + + std::shared_ptr ability = std::make_shared(); + + std::shared_ptr contextDeal = std::make_shared(); + pageAbilityImpl_->Init(application, record, ability, handler, token, contextDeal); + + Want want; + pageAbilityImpl_->NewWant(want); + + GTEST_LOG_(INFO) << "AaFwk_PageAbilityImpl_NewWant_0100 end"; +} +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/test/unittest/service_ability_impl_test.cpp b/tools/frameworks/kits/ability/native/test/unittest/service_ability_impl_test.cpp new file mode 100644 index 00000000000..bfcf7ba53f2 --- /dev/null +++ b/tools/frameworks/kits/ability/native/test/unittest/service_ability_impl_test.cpp @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "app_log_wrapper.h" +#include "context_deal.h" +#include "mock_service_ability.h" +#include "mock_ability_token.h" +#include "service_ability_impl.h" + +namespace OHOS { +namespace AppExecFwk { +using namespace testing::ext; +using namespace OHOS; +using namespace OHOS::AppExecFwk; +using namespace OHOS::AAFwk; + +class ServiceAbilityImplTest : public testing::Test { +public: + ServiceAbilityImplTest() : serviceAbilityImpl_(nullptr) + {} + ~ServiceAbilityImplTest() + { + serviceAbilityImpl_ = nullptr; + } + std::shared_ptr serviceAbilityImpl_ = nullptr; + + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void ServiceAbilityImplTest::SetUpTestCase(void) +{} + +void ServiceAbilityImplTest::TearDownTestCase(void) +{} + +void ServiceAbilityImplTest::SetUp(void) +{ + serviceAbilityImpl_ = std::make_shared(); +} + +void ServiceAbilityImplTest::TearDown(void) +{} + +/** + * @tc.number: AaFwk_ServiceAbilityImpl_HandleAbilityTransaction_0100 + * @tc.name: HandleAbilityTransaction + * @tc.desc: Test whether handleabilitytransaction is called normally, + * and verify that getcurrentstate returns ABILITY_STATE_INITIAL. + */ +HWTEST_F(ServiceAbilityImplTest, AaFwk_ServiceAbilityImpl_HandleAbilityTransaction_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_ServiceAbilityImpl_HandleAbilityTransaction_0100 start"; + + std::shared_ptr application = std::make_shared(); + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "MockServiceAbility"; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + std::shared_ptr record = std::make_shared(abilityInfo, token); + + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + + std::shared_ptr ability = std::make_shared(); + std::shared_ptr deal = std::make_shared(); + deal->SetAbilityInfo(abilityInfo); + ability->AttachBaseContext(deal); + + serviceAbilityImpl_->Init(application, record, ability, handler, token, deal); + Want want; + serviceAbilityImpl_->ConnectAbility(want); + + AAFwk::LifeCycleStateInfo state; + state.state = ABILITY_STATE_INITIAL; + GTEST_LOG_(INFO) << "AaFwk_ServiceAbilityImpl_HandleAbilityTransaction_001 midle"; + serviceAbilityImpl_->HandleAbilityTransaction(want, state); + GTEST_LOG_(INFO) << "AaFwk_ServiceAbilityImpl_HandleAbilityTransaction_001 midle2"; + EXPECT_EQ(ABILITY_STATE_INITIAL, serviceAbilityImpl_->GetCurrentState()); + + GTEST_LOG_(INFO) << "AaFwk_ServiceAbilityImpl_HandleAbilityTransaction_0100 end"; +} + +/** + * @tc.number: AaFwk_ServiceAbilityImpl_HandleAbilityTransaction_0200 + * @tc.name: HandleAbilityTransaction + * @tc.desc: Test whether handleabilitytransaction is called normally, + * and verify that getcurrentstate returns ABILITY_STATE_INACTIVE. + */ +HWTEST_F(ServiceAbilityImplTest, AaFwk_ServiceAbilityImpl_HandleAbilityTransaction_0200, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_ServiceAbilityImpl_HandleAbilityTransaction_0200 start"; + + std::shared_ptr application = std::make_shared(); + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "MockServiceAbility"; + abilityInfo->type = AppExecFwk::AbilityType::SERVICE; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + std::shared_ptr record = std::make_shared(abilityInfo, token); + + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + + std::shared_ptr ability = std::make_shared(); + std::shared_ptr deal = std::make_shared(); + deal->SetAbilityInfo(abilityInfo); + ability->AttachBaseContext(deal); + + serviceAbilityImpl_->Init(application, record, ability, handler, token, deal); + + Want want; + AAFwk::LifeCycleStateInfo state; + state.state = ABILITY_STATE_INACTIVE; + serviceAbilityImpl_->HandleAbilityTransaction(want, state); + EXPECT_EQ(ABILITY_STATE_INACTIVE, serviceAbilityImpl_->GetCurrentState()); + + GTEST_LOG_(INFO) << "AaFwk_ServiceAbilityImpl_HandleAbilityTransaction_0200 end"; +} + +/** + * @tc.number: AaFwk_ServiceAbilityImpl_HandleAbilityTransaction_0300 + * @tc.name: HandleAbilityTransaction + * @tc.desc: Test whether handleabilitytransaction is called normally, + * and verify that getcurrentstate returns ABILITY_STATE_INITIAL. + */ +HWTEST_F(ServiceAbilityImplTest, AaFwk_ServiceAbilityImpl_HandleAbilityTransaction_0300, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_ServiceAbilityImpl_HandleAbilityTransaction_0300 start"; + + std::shared_ptr application = std::make_shared(); + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "MockServiceAbility"; + sptr token = nullptr; + std::shared_ptr record = std::make_shared(abilityInfo, token); + + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + + std::shared_ptr ability = std::make_shared(); + std::shared_ptr deal = std::make_shared(); + deal->SetAbilityInfo(abilityInfo); + ability->AttachBaseContext(deal); + + serviceAbilityImpl_->Init(application, record, ability, handler, token, deal); + + Want want; + AAFwk::LifeCycleStateInfo state; + state.state = ABILITY_STATE_INACTIVE; + serviceAbilityImpl_->HandleAbilityTransaction(want, state); + EXPECT_EQ(ABILITY_STATE_INITIAL, serviceAbilityImpl_->GetCurrentState()); + + GTEST_LOG_(INFO) << "AaFwk_ServiceAbilityImpl_HandleAbilityTransaction_0300 end"; +} + +/** + * @tc.number: AaFwk_ServiceAbilityImpl_HandleAbilityTransaction_0400 + * @tc.name: HandleAbilityTransaction + * @tc.desc: Test whether handleabilitytransaction is called normally, + * and verify that getcurrentstate returns ABILITY_STATE_INACTIVE. + */ +HWTEST_F(ServiceAbilityImplTest, AaFwk_ServiceAbilityImpl_HandleAbilityTransaction_0400, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_ServiceAbilityImpl_HandleAbilityTransaction_0400 start"; + + std::shared_ptr application = std::make_shared(); + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = "MockServiceAbility"; + abilityInfo->type = AppExecFwk::AbilityType::SERVICE; + sptr token = sptr(new (std::nothrow) MockAbilityToken()); + std::shared_ptr record = std::make_shared(abilityInfo, token); + + std::shared_ptr eventRunner = EventRunner::Create(abilityInfo->name); + sptr abilityThread = sptr(new (std::nothrow) AbilityThread()); + std::shared_ptr handler = std::make_shared(eventRunner, abilityThread); + + std::shared_ptr ability = std::make_shared(); + std::shared_ptr deal = std::make_shared(); + deal->SetAbilityInfo(abilityInfo); + ability->AttachBaseContext(deal); + + serviceAbilityImpl_->Init(application, record, ability, handler, token, deal); + + Want want; + AAFwk::LifeCycleStateInfo state; + state.state = ABILITY_STATE_INACTIVE; + serviceAbilityImpl_->HandleAbilityTransaction(want, state); + state.state = ABILITY_STATE_INITIAL; + serviceAbilityImpl_->HandleAbilityTransaction(want, state); + EXPECT_EQ(ABILITY_STATE_INACTIVE, serviceAbilityImpl_->GetCurrentState()); + + GTEST_LOG_(INFO) << "AaFwk_ServiceAbilityImpl_HandleAbilityTransaction_0400 end"; +} +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/ability/native/test/unittest/task_handler_client_test.cpp b/tools/frameworks/kits/ability/native/test/unittest/task_handler_client_test.cpp new file mode 100644 index 00000000000..c18b0855c70 --- /dev/null +++ b/tools/frameworks/kits/ability/native/test/unittest/task_handler_client_test.cpp @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "task_handler_client.h" +#include "app_log_wrapper.h" + +namespace OHOS { +namespace AppExecFwk { +using namespace testing::ext; +using namespace OHOS; +using namespace OHOS::AppExecFwk; + +class TaskHandlerClientTest : public testing::Test { +public: + TaskHandlerClientTest() + {} + ~TaskHandlerClientTest() + {} + + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void TaskHandlerClientTest::SetUpTestCase(void) +{} + +void TaskHandlerClientTest::TearDownTestCase(void) +{} + +void TaskHandlerClientTest::SetUp(void) +{} + +void TaskHandlerClientTest::TearDown(void) +{} + +/** + * @tc.number: AaFwk_TaskHandlerClient_GetInstance_0100 + * @tc.name: GetInstance + * @tc.desc: Test TaskHandlerClient::GetInstance is not empty, and test whether it is called normally. + */ +HWTEST_F(TaskHandlerClientTest, AaFwk_TaskHandlerClient_GetInstance_0100, Function | MediumTest | Level3) +{ + GTEST_LOG_(INFO) << "AaFwk_TaskHandlerClient_GetInstance_0100 start"; + + EXPECT_NE(TaskHandlerClient::GetInstance(), nullptr); + EXPECT_NE(TaskHandlerClient::GetInstance(), nullptr); + + GTEST_LOG_(INFO) << "AaFwk_TaskHandlerClient_GetInstance_0100 end"; +} + +/** + * @tc.number: AaFwk_TaskHandlerClient_CreateRunner_0100 + * @tc.name: CreateRunner + * @tc.desc: Test whether TaskHandlerClient::CreateRunner is true. + */ +HWTEST_F(TaskHandlerClientTest, AaFwk_TaskHandlerClient_CreateRunner_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_TaskHandlerClient_CreateRunner_0100 start"; + + EXPECT_EQ(TaskHandlerClient::GetInstance()->CreateRunner(), true); + + GTEST_LOG_(INFO) << "AaFwk_TaskHandlerClient_CreateRunner_0100 end"; +} + +/** + * @tc.number: AaFwk_TaskHandlerClient_PostTask_0100 + * @tc.name: PostTask + * @tc.desc: Test whether TaskHandlerClient::PostTask is true. + */ +HWTEST_F(TaskHandlerClientTest, AaFwk_TaskHandlerClient_PostTask_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_TaskHandlerClient_PostTask_0100 start"; + + auto task = []() { GTEST_LOG_(INFO) << "AaFwk_TaskHandlerClient_PostTask_0100 task called"; }; + + EXPECT_EQ(TaskHandlerClient::GetInstance()->PostTask(task, 1000), true); + + GTEST_LOG_(INFO) << "AaFwk_TaskHandlerClient_PostTask_0100 end"; +} +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/base/cpp/src/ohos/aafwk/base/array_wrapper.cpp b/tools/frameworks/kits/base/cpp/src/ohos/aafwk/base/array_wrapper.cpp new file mode 100644 index 00000000000..c89bc31c0e1 --- /dev/null +++ b/tools/frameworks/kits/base/cpp/src/ohos/aafwk/base/array_wrapper.cpp @@ -0,0 +1,387 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ohos/aafwk/base/array_wrapper.h" +#include +#include "ohos/aafwk/base/bool_wrapper.h" +#include "ohos/aafwk/base/zchar_wrapper.h" +#include "ohos/aafwk/base/byte_wrapper.h" +#include "ohos/aafwk/base/double_wrapper.h" +#include "ohos/aafwk/base/float_wrapper.h" +#include "ohos/aafwk/base/int_wrapper.h" +#include "ohos/aafwk/base/long_wrapper.h" +#include "ohos/aafwk/base/short_wrapper.h" +#include "ohos/aafwk/base/string_wrapper.h" + +namespace OHOS { +namespace AAFwk { +IINTERFACE_IMPL_1(Array, Object, IArray); + +Array::Array(long size, const InterfaceID &id) : size_(size), typeId_(id) +{ + for (long i = 0; i < size; i++) { + values_.push_back(nullptr); + } +} + +ErrCode Array::Get(long index, /* [in] */ + sptr &value) /* [out] */ +{ + if (index < 0 || index >= size_) { + value = nullptr; + return ERR_INVALID_VALUE; + } + value = values_[index]; + return ERR_OK; +} + +ErrCode Array::GetLength(long &size) /* [out] */ +{ + VALIDATE_NOT_NULL(&size); + + size = size_; + return ERR_OK; +} + +ErrCode Array::GetType(InterfaceID &id) /* [out] */ +{ + VALIDATE_NOT_NULL(&id); + + id = typeId_; + return ERR_OK; +} + +ErrCode Array::Set(long index, /* [in] */ + IInterface *value) /* [in] */ +{ + if (index < 0 || index >= size_) { + return ERR_INVALID_VALUE; + } + values_[index] = value; + return ERR_OK; +} + +bool Array::Equals(IObject &other) /* [in] */ +{ + Array *otherObj = static_cast(IArray::Query(&other)); + if (otherObj == nullptr) { + return false; + } + + if (this == otherObj) { + return true; + } + + if (otherObj->size_ != size_ || otherObj->typeId_ != typeId_) { + return false; + } + + for (long i = 0; i < size_; i++) { + if (!Object::Equals(*(values_[i].GetRefPtr()), *(otherObj->values_[i].GetRefPtr()))) { + return false; + } + } + return true; +} + +std::string Array::ToString() +{ + std::string result; + if (typeId_ == g_IID_IString) { + result += String::SIGNATURE; + } else if (typeId_ == g_IID_IBoolean) { + result += Boolean::SIGNATURE; + } else if (typeId_ == g_IID_IByte) { + result += Byte::SIGNATURE; + } else if (typeId_ == g_IID_IShort) { + result += Short::SIGNATURE; + } else if (typeId_ == g_IID_IInteger) { + result += Integer::SIGNATURE; + } else if (typeId_ == g_IID_ILong) { + result += Long::SIGNATURE; + } else if (typeId_ == g_IID_IFloat) { + result += Float::SIGNATURE; + } else if (typeId_ == g_IID_IDouble) { + result += Double::SIGNATURE; + } else if (typeId_ == g_IID_IArray) { + result += Array::SIGNATURE; + } else if (typeId_ == g_IID_IChar) { + result += Char::SIGNATURE; + } else { + result += ""; + } + + result += std::to_string(size_) + "{"; + for (long i = 0; i < size_; i++) { + result += Object::ToString(*(values_[i].GetRefPtr())); + if (i < size_ - 1) { + result += ","; + } + } + result += "}"; + return result; +} + +sptr Array::ParseString(const std::string &values, long size) +{ + sptr array = new (std::nothrow) Array(size, g_IID_IString); + if (array != nullptr) { + auto func = [](const std::string &str) -> sptr { return String::Parse(str); }; + ParseElement(array, func, values, size); + } + return array; +} + +sptr Array::ParseBoolean(const std::string &values, long size) +{ + sptr array = new (std::nothrow) Array(size, g_IID_IBoolean); + if (array != nullptr) { + auto func = [](const std::string &str) -> sptr { return Boolean::Parse(str); }; + ParseElement(array, func, values, size); + } + return array; +} + +sptr Array::ParseByte(const std::string &values, long size) +{ + sptr array = new (std::nothrow) Array(size, g_IID_IByte); + if (array != nullptr) { + auto func = [](const std::string &str) -> sptr { return Byte::Parse(str); }; + ParseElement(array, func, values, size); + } + return array; +} + +sptr Array::ParseShort(const std::string &values, long size) +{ + sptr array = new (std::nothrow) Array(size, g_IID_IShort); + if (array != nullptr) { + auto func = [](const std::string &str) -> sptr { return Short::Parse(str); }; + ParseElement(array, func, values, size); + } + return array; +} + +sptr Array::ParseInteger(const std::string &values, long size) +{ + sptr array = new (std::nothrow) Array(size, g_IID_IInteger); + if (array != nullptr) { + auto func = [](const std::string &str) -> sptr { return Integer::Parse(str); }; + ParseElement(array, func, values, size); + } + return array; +} + +sptr Array::ParseLong(const std::string &values, long size) +{ + sptr array = new (std::nothrow) Array(size, g_IID_ILong); + if (array != nullptr) { + auto func = [](const std::string &str) -> sptr { return Long::Parse(str); }; + ParseElement(array, func, values, size); + } + return array; +} + +sptr Array::ParseFloat(const std::string &values, long size) +{ + sptr array = new (std::nothrow) Array(size, g_IID_IFloat); + if (array != nullptr) { + auto func = [](const std::string &str) -> sptr { return Float::Parse(str); }; + ParseElement(array, func, values, size); + } + return array; +} + +sptr Array::ParseDouble(const std::string &values, long size) +{ + sptr array = new (std::nothrow) Array(size, g_IID_IDouble); + if (array != nullptr) { + auto func = [](const std::string &str) -> sptr { return Double::Parse(str); }; + ParseElement(array, func, values, size); + } + return array; +} +sptr Array::ParseChar(const std::string &values, long size) +{ + sptr array = new (std::nothrow) Array(size, g_IID_IChar); + if (array != nullptr) { + auto func = [](const std::string &str) -> sptr { return Char::Parse(str); }; + ParseElement(array, func, values, size); + } + return array; +} +sptr Array::ParseArray(const std::string &values, long size) +{ + sptr array = new (std::nothrow) Array(size, g_IID_IArray); + if (array != nullptr) { + auto func = [](const std::string &str) -> sptr { return Array::Parse(str); }; + ParseElement(array, func, values, size); + } + return array; +} + +sptr Array::Parse(const std::string &arrayStr) /* [in] */ +{ + char signature = arrayStr[0]; + if (signature != String::SIGNATURE && signature != Boolean::SIGNATURE && signature != Byte::SIGNATURE && + signature != Short::SIGNATURE && signature != Integer::SIGNATURE && signature != Long::SIGNATURE && + signature != Float::SIGNATURE && signature != Double::SIGNATURE && signature != Array::SIGNATURE && + signature != Char::SIGNATURE) { + return nullptr; + } + + std::size_t idx = arrayStr.find("{"); + if (idx == std::string::npos) { + return nullptr; + } + if (arrayStr[arrayStr.length() - 1] != '}') { + return nullptr; + } + + long size = std::stol(arrayStr.substr(1, idx - 1)); + idx += 1; + std::string values = arrayStr.substr(idx, arrayStr.length() - 1 - idx); + + switch (signature) { + case Char::SIGNATURE: + return ParseChar(values, size); + case String::SIGNATURE: + return ParseString(values, size); + case Boolean::SIGNATURE: + return ParseBoolean(values, size); + case Byte::SIGNATURE: + return ParseByte(values, size); + case Short::SIGNATURE: + return ParseShort(values, size); + case Integer::SIGNATURE: + return ParseInteger(values, size); + case Long::SIGNATURE: + return ParseLong(values, size); + case Float::SIGNATURE: + return ParseFloat(values, size); + case Double::SIGNATURE: + return ParseDouble(values, size); + case Array::SIGNATURE: + return ParseArray(values, size); + default: + break; + } + return nullptr; +} + +void Array::ParseElement(IArray *array, /* [in] */ + std::function(std::string &)> func, /* [in] */ + const std::string &values, /* [in] */ + long size) /* [in] */ +{ + if (array == nullptr) { + return; + } + + std::size_t beginIdx = 0; + std::size_t endIdx; + for (long i = 0; i < size; i++) { + std::string valueStr; + if (i < size - 1) { + endIdx = values.find(",", beginIdx); + if (endIdx == std::string::npos) { + valueStr = values.substr(beginIdx); + } else { + valueStr = values.substr(beginIdx, endIdx - beginIdx); + beginIdx = endIdx + 1; + } + } else { + valueStr = values.substr(beginIdx, values.length() - beginIdx); + } + array->Set(i, func(valueStr)); + } +} + +bool Array::IsBooleanArray(IArray *array) /* [in] */ +{ + InterfaceID typeId; + array->GetType(typeId); + return typeId == g_IID_IBoolean; +} + +bool Array::IsCharArray(IArray *array) /* [in] */ +{ + InterfaceID typeId; + array->GetType(typeId); + return typeId == g_IID_IChar; +} + +bool Array::IsByteArray(IArray *array) /* [in] */ +{ + InterfaceID typeId; + array->GetType(typeId); + return typeId == g_IID_IByte; +} + +bool Array::IsShortArray(IArray *array) /* [in] */ +{ + InterfaceID typeId; + array->GetType(typeId); + return typeId == g_IID_IShort; +} + +bool Array::IsIntegerArray(IArray *array) /* [in] */ +{ + InterfaceID typeId; + array->GetType(typeId); + return typeId == g_IID_IInteger; +} + +bool Array::IsLongArray(IArray *array) /* [in] */ +{ + InterfaceID typeId; + array->GetType(typeId); + return typeId == g_IID_ILong; +} + +bool Array::IsFloatArray(IArray *array) /* [in] */ +{ + InterfaceID typeId; + array->GetType(typeId); + return typeId == g_IID_IFloat; +} + +bool Array::IsDoubleArray(IArray *array) /* [in] */ +{ + InterfaceID typeId; + array->GetType(typeId); + return typeId == g_IID_IDouble; +} + +bool Array::IsStringArray(IArray *array) /* [in] */ +{ + InterfaceID typeId; + array->GetType(typeId); + return typeId == g_IID_IString; +} + +void Array::ForEach(IArray *array, /* [in] */ + std::function func) /* [in] */ +{ + long size; + array->GetLength(size); + for (long i = 0; i < size; i++) { + sptr object; + array->Get(i, object); + func(object); + } +} +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/base/cpp/src/ohos/aafwk/base/base.cpp b/tools/frameworks/kits/base/cpp/src/ohos/aafwk/base/base.cpp new file mode 100755 index 00000000000..49414160e66 --- /dev/null +++ b/tools/frameworks/kits/base/cpp/src/ohos/aafwk/base/base.cpp @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ohos/aafwk/base/base_def.h" +#include "ohos/aafwk/base/base_types.h" +#include "ohos/aafwk/base/base_interfaces.h" + +namespace OHOS { +namespace AAFwk { +const Uuid Uuid::Empty = { + 0x00000000, 0x0000, 0x0000, 0x0000, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0} +}; + +const InterfaceID g_IID_IInterface = { + 0x00000000, 0x0000, 0x0000, 0x0000, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1} +}; + +const InterfaceID g_IID_IBoolean = { + 0x492ef6c0, 0xe122, 0x401d, 0x80c4, {0xb, 0xb, 0x6, 0x5, 0xe, 0x2, 0x3, 0x2, 0x5, 0x7, 0x6, 0x6} +}; + +const InterfaceID g_IID_IChar = { + 0x6da72e7c, 0xd353, 0x4d7b, 0x85ef, {0x2, 0x1, 0x4, 0x6, 0xa, 0xd, 0xd, 0x3, 0x4, 0x2, 0x1, 0x9} +}; + +const InterfaceID g_IID_IByte = { + 0x2c9fd6ff, 0x73f7, 0x4a22, 0x9ea8, {0x1, 0xe, 0x3, 0x7, 0xb, 0x2, 0x2, 0x1, 0x3, 0xc, 0xa, 0x1} +}; + +const InterfaceID g_IID_IShort = { + 0x54fe1291, 0x0813, 0x43c9, 0xb6f7, {0xb, 0x0, 0x0, 0x8, 0xe, 0xd, 0xe, 0xf, 0x7, 0xf, 0x3, 0x4} +}; + +const InterfaceID g_IID_IInteger = { + 0x0672d282, 0x7cdb, 0x49b8, 0x92c7, {0x1, 0xa, 0xf, 0x3, 0x5, 0xe, 0x2, 0xd, 0x4, 0x9, 0x4, 0x9} +}; + +const InterfaceID g_IID_ILong = { + 0xd7550828, 0x2eaf, 0x4281, 0x8604, {0x4, 0x2, 0xa, 0x8, 0x2, 0xa, 0xb, 0x9, 0xb, 0xc, 0xd, 0xc} +}; + +const InterfaceID g_IID_IFloat = { + 0xb5428638, 0xca53, 0x4a27, 0x95a0, {0x3, 0xf, 0x2, 0x4, 0xe, 0x5, 0x4, 0xa, 0x5, 0x8, 0xd, 0x5} +}; + +const InterfaceID g_IID_IDouble = { + 0x596dc69a, 0xae7d, 0x42ad, 0xb00f, {0x0, 0xd, 0x5, 0xe, 0xb, 0x0, 0x1, 0xa, 0x2, 0x5, 0x5, 0x7} +}; + +const InterfaceID g_IID_IString = { + 0x69644bf4, 0xdd20, 0x417b, 0x9055, {0x5, 0xa, 0x2, 0x6, 0xe, 0x3, 0xe, 0x1, 0x7, 0x9, 0x3, 0xb} +}; + +const InterfaceID g_IID_IArray = { + 0x875b9da6, 0x9913, 0x4370, 0x8847, {0xe, 0x1, 0x9, 0x6, 0x1, 0xb, 0xe, 0x6, 0xe, 0x5, 0x6, 0x0} +}; + +const InterfaceID g_IID_IPacMap = { + 0xf92066fd, 0xfd0c, 0x401b, 0xa3f6, {0x6, 0x2, 0x6, 0xd, 0xa, 0x3, 0xb, 0xa, 0xc, 0x9, 0xd, 0x5} +}; + +const InterfaceID g_IID_IUserObject = { + 0x4edb325d, 0x8532, 0x4af7, 0xb42e, {0x8, 0x2, 0xf, 0x4, 0xf, 0x2, 0x9, 0xd, 0xf, 0xd, 0xe, 0xa} +}; +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/base/cpp/src/ohos/aafwk/base/base_object.cpp b/tools/frameworks/kits/base/cpp/src/ohos/aafwk/base/base_object.cpp new file mode 100644 index 00000000000..79ed9d9a455 --- /dev/null +++ b/tools/frameworks/kits/base/cpp/src/ohos/aafwk/base/base_object.cpp @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ohos/aafwk/base/base_object.h" + +#include + +#include "securec.h" + +#include "ohos/aafwk/base/light_refbase.h" + +namespace OHOS { +namespace AAFwk { +const InterfaceID g_IID_IObject = { + 0x8321f710, 0xa0c0, 0x4cbe, 0xbfbc, {0x5, 0xa, 0x7, 0x8, 0xf, 0x1, 0x3, 0x1, 0x2, 0xb, 0x1, 0xb} +}; + +const InterfaceID g_IID_IWeakReference = { + 0x26ab1978, 0x1d11, 0x4a4f, 0x826d, {0x6, 0x1, 0x7, 0x8, 0x5, 0xc, 0x0, 0x4, 0x8, 0xc, 0xc, 0xa} +}; + +const InterfaceID g_IID_IWeakReferenceSource = { + 0xbc3f5250, 0x34d7, 0x42d2, 0x9b40, {0xf, 0xf, 0xc, 0xe, 0x8, 0x3, 0xf, 0xd, 0x4, 0x0, 0x6, 0x1} +}; + +class WeakReferenceImpl final : public LightRefCountBase, public IWeakReference { +public: + WeakReferenceImpl(IInterface *object, WeakRefCounter *wkRef) : object_(object), wkRef_(wkRef) + {} + + virtual ~WeakReferenceImpl() + {} + + void IncStrongRef(const void *id = nullptr) override; + + void DecStrongRef(const void *id = nullptr) override; + + IInterface *Query(const InterfaceID &iid) override; + + InterfaceID GetInterfaceID(IInterface *object) override; + + ErrCode Resolve(const InterfaceID &iid, IInterface **object) override; + +private: + IInterface *object_ = nullptr; + WeakRefCounter *wkRef_ = nullptr; +}; + +void WeakReferenceImpl::IncStrongRef(const void *id) +{ + LightRefCountBase::IncStrongRef(id); +} + +void WeakReferenceImpl::DecStrongRef(const void *id) +{ + LightRefCountBase::DecStrongRef(id); +} + +IInterface *WeakReferenceImpl::Query(const InterfaceID &iid) +{ + if ((iid == g_IID_IWeakReference) || (iid == g_IID_IInterface)) { + return static_cast(this); + } + return nullptr; +} + +InterfaceID WeakReferenceImpl::GetInterfaceID(IInterface *object) +{ + if (object == static_cast(this)) { + return g_IID_IWeakReference; + } + return InterfaceID::Empty; +} + +ErrCode WeakReferenceImpl::Resolve(const InterfaceID &iid, IInterface **object) +{ + VALIDATE_NOT_NULL(object); + + if ((object_ != nullptr) && wkRef_->AttemptIncStrongRef(this)) { + *object = object_->Query(iid); + if (*object == nullptr) { + object_->DecStrongRef(this); + } + } else { + *object = nullptr; + } + return ERR_OK; +} + +void Object::IncStrongRef(const void *id) +{ + RefBase::IncStrongRef(id); +} + +void Object::DecStrongRef(const void *id) +{ + RefBase::DecStrongRef(id); +} + +IInterface *Object::Query(const InterfaceID &iid) +{ + if (iid == g_IID_IObject) { + return static_cast(this); + } + if (iid == g_IID_IWeakReferenceSource) { + return static_cast(this); + } + if (iid == g_IID_IInterface) { + return static_cast(this); + } + return nullptr; +} + +InterfaceID Object::GetInterfaceID(IInterface *object) +{ + if (object == static_cast(this)) { + return g_IID_IObject; + } + if (object == static_cast(this)) { + return g_IID_IWeakReferenceSource; + } + return InterfaceID::Empty; +} + +ClassID Object::GetClassID() +{ + return ClassID::Empty; +} + +int Object::GetHashCode() +{ + return reinterpret_cast(this); +} + +bool Object::Equals(IObject &other) +{ + Object *otherObj = nullptr; + otherObj = static_cast(&other); + return this == otherObj; +} + +ErrCode Object::GetWeakReference(sptr &weakRef) +{ + void *addr = calloc(sizeof(WeakReferenceImpl), 1); + if (addr == nullptr) { + return ERR_NO_MEMORY; + } + weakRef = new (addr) WeakReferenceImpl(static_cast(this), CreateWeakRef(addr)); + return ERR_OK; +} + +std::string Object::ToString() +{ + static constexpr int BUFFER_MAX = 1024; + std::string str(""); + char *buf = new (std::nothrow) char[BUFFER_MAX]; + if (buf != nullptr) { + int ret = snprintf_s(buf, BUFFER_MAX, BUFFER_MAX - 1, "[Object %p]", this); + if (ret >= 0) { + str = buf; + } + delete[] buf; + buf = nullptr; + } + return str; +} + +bool Object::Equals(IInterface &obj1, IInterface &obj2) +{ + if (IInterface::Query(&obj1) == IInterface::Query(&obj2)) { + return true; + } + + IObject *o1 = IObject::Query(obj1); + if (o1 == nullptr) { + return false; + } + return o1->Equals(*(IObject::Query(obj2))); +} + +std::string Object::ToString(IInterface &object) +{ + IObject *obj = IObject::Query(object); + return ((obj != nullptr) ? obj->ToString() : ""); +} +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/base/cpp/src/ohos/aafwk/base/bool_wrapper.cpp b/tools/frameworks/kits/base/cpp/src/ohos/aafwk/base/bool_wrapper.cpp new file mode 100644 index 00000000000..617c481da74 --- /dev/null +++ b/tools/frameworks/kits/base/cpp/src/ohos/aafwk/base/bool_wrapper.cpp @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ohos/aafwk/base/bool_wrapper.h" + +namespace OHOS { +namespace AAFwk { +IINTERFACE_IMPL_1(Boolean, Object, IBoolean); +ErrCode Boolean::GetValue(bool &value) /* [out] */ +{ + VALIDATE_NOT_NULL(&value); + + value = value_; + return ERR_OK; +} + +bool Boolean::Equals(IObject &other) /* [in] */ +{ + Boolean *otherObj = static_cast(IBoolean::Query(&other)); + return otherObj != nullptr && otherObj->value_ == value_; +} + +std::string Boolean::ToString() +{ + return value_ ? "true" : "false"; +} + +sptr Boolean::Box(bool value) /* [in] */ +{ + sptr object = new Boolean(value); + return object; +} + +bool Boolean::Unbox(IBoolean *object) /* [in] */ +{ + bool value = false; + object->GetValue(value); + return value; +} + +sptr Boolean::Parse(const std::string &str) /* [in] */ +{ + sptr object; + if (str == "true") { + object = new Boolean(true); + } else if (str == "false") { + object = new Boolean(false); + } + return object; +} +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/base/cpp/src/ohos/aafwk/base/byte_wrapper.cpp b/tools/frameworks/kits/base/cpp/src/ohos/aafwk/base/byte_wrapper.cpp new file mode 100644 index 00000000000..616b012d219 --- /dev/null +++ b/tools/frameworks/kits/base/cpp/src/ohos/aafwk/base/byte_wrapper.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ohos/aafwk/base/byte_wrapper.h" + +namespace OHOS { +namespace AAFwk { +IINTERFACE_IMPL_1(Byte, Object, IByte); + +ErrCode Byte::GetValue(byte &value) /* [out] */ +{ + VALIDATE_NOT_NULL(&value); + + value = value_; + return ERR_OK; +} + +bool Byte::Equals(IObject &other) /* [in] */ +{ + Byte *otherObj = static_cast(IByte::Query(&other)); + return otherObj != nullptr && otherObj->value_ == value_; +} + +std::string Byte::ToString() +{ + return std::to_string(value_); +} + +sptr Byte::Box(byte value) /* [in] */ +{ + sptr object = new Byte(value); + return object; +} + +byte Byte::Unbox(IByte *object) /* [in] */ +{ + byte value; + object->GetValue(value); + return value; +} + +sptr Byte::Parse(const std::string &str) /* [in] */ +{ + sptr object; + std::size_t idx; + byte value = (byte)std::stoi(str, &idx); + if (idx != 0) { + object = new Byte(value); + } + return object; +} +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/base/cpp/src/ohos/aafwk/base/double_wrapper.cpp b/tools/frameworks/kits/base/cpp/src/ohos/aafwk/base/double_wrapper.cpp new file mode 100644 index 00000000000..efc1accb325 --- /dev/null +++ b/tools/frameworks/kits/base/cpp/src/ohos/aafwk/base/double_wrapper.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ohos/aafwk/base/double_wrapper.h" + +namespace OHOS { +namespace AAFwk { +IINTERFACE_IMPL_1(Double, Object, IDouble); + +ErrCode Double::GetValue(double &value) /* [out] */ +{ + VALIDATE_NOT_NULL(&value); + + value = value_; + return ERR_OK; +} + +bool Double::Equals(IObject &other) /* [in] */ +{ + Double *otherObj = static_cast(IDouble::Query(&other)); + return otherObj != nullptr && otherObj->value_ == value_; +} + +std::string Double::ToString() +{ + return std::to_string(value_); +} + +sptr Double::Box(double value) /* [in] */ +{ + sptr object = new Double(value); + return object; +} + +double Double::Unbox(IDouble *object) /* [in] */ +{ + double value; + object->GetValue(value); + return value; +} + +sptr Double::Parse(const std::string &str) /* [in] */ +{ + sptr object; + std::size_t idx; + double value = std::stod(str, &idx); + if (idx != 0) { + object = new Double(value); + } + return object; +} +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/base/cpp/src/ohos/aafwk/base/float_wrapper.cpp b/tools/frameworks/kits/base/cpp/src/ohos/aafwk/base/float_wrapper.cpp new file mode 100644 index 00000000000..c0a4e5e454e --- /dev/null +++ b/tools/frameworks/kits/base/cpp/src/ohos/aafwk/base/float_wrapper.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ohos/aafwk/base/float_wrapper.h" + +namespace OHOS { +namespace AAFwk { +IINTERFACE_IMPL_1(Float, Object, IFloat); + +ErrCode Float::GetValue(float &value) /* [out] */ +{ + VALIDATE_NOT_NULL(&value); + + value = value_; + return ERR_OK; +} + +bool Float::Equals(IObject &other) /* [in] */ +{ + Float *otherObj = static_cast(IFloat::Query(&other)); + return otherObj != nullptr && otherObj->value_ == value_; +} + +std::string Float::ToString() +{ + return std::to_string(value_); +} + +sptr Float::Box(float value) /* [in] */ +{ + sptr object = new Float(value); + return object; +} + +float Float::Unbox(IFloat *object) /* [in] */ +{ + float value; + object->GetValue(value); + return value; +} + +sptr Float::Parse(const std::string &str) /* [in] */ +{ + sptr object; + std::size_t idx; + float value = std::stof(str, &idx); + if (idx != 0) { + object = new Float(value); + } + return object; +} +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/base/cpp/src/ohos/aafwk/base/int_wrapper.cpp b/tools/frameworks/kits/base/cpp/src/ohos/aafwk/base/int_wrapper.cpp new file mode 100644 index 00000000000..c913e135aea --- /dev/null +++ b/tools/frameworks/kits/base/cpp/src/ohos/aafwk/base/int_wrapper.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ohos/aafwk/base/int_wrapper.h" + +namespace OHOS { +namespace AAFwk { +IINTERFACE_IMPL_1(Integer, Object, IInteger); + +ErrCode Integer::GetValue(int &value) /* [out] */ +{ + VALIDATE_NOT_NULL(&value); + + value = value_; + return ERR_OK; +} + +bool Integer::Equals(IObject &other) /* [in] */ +{ + Integer *otherObj = static_cast(IInteger::Query(&other)); + return otherObj != nullptr && otherObj->value_ == value_; +} + +std::string Integer::ToString() +{ + return std::to_string(value_); +} + +sptr Integer::Box(int value) /* [in] */ +{ + sptr object = new Integer(value); + return object; +} + +int Integer::Unbox(IInteger *object) /* [in] */ +{ + int value; + object->GetValue(value); + return value; +} + +sptr Integer::Parse(const std::string &str) /* [in] */ +{ + sptr object; + std::size_t idx; + int value = std::stoi(str, &idx); + if (idx != 0) { + object = new Integer(value); + } + return object; +} +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/base/cpp/src/ohos/aafwk/base/long_wrapper.cpp b/tools/frameworks/kits/base/cpp/src/ohos/aafwk/base/long_wrapper.cpp new file mode 100644 index 00000000000..b681baa624e --- /dev/null +++ b/tools/frameworks/kits/base/cpp/src/ohos/aafwk/base/long_wrapper.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ohos/aafwk/base/long_wrapper.h" + +namespace OHOS { +namespace AAFwk { +IINTERFACE_IMPL_1(Long, Object, ILong); + +ErrCode Long::GetValue(long &value) /* [out] */ +{ + VALIDATE_NOT_NULL(&value); + + value = value_; + return ERR_OK; +} + +bool Long::Equals(IObject &other) /* [in] */ +{ + Long *otherObj = static_cast(ILong::Query(&other)); + return otherObj != nullptr && otherObj->value_ == value_; +} + +std::string Long::ToString() +{ + return std::to_string(value_); +} + +sptr Long::Box(long value) /* [in] */ +{ + sptr object = new Long(value); + return object; +} + +long Long::Unbox(ILong *object) /* [in] */ +{ + long value; + object->GetValue(value); + return value; +} + +sptr Long::Parse(const std::string &str) /* [in] */ +{ + sptr object; + std::size_t idx; + long value = std::stol(str, &idx); + if (idx != 0) { + object = new Long(value); + } + return object; +} +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/base/cpp/src/ohos/aafwk/base/short_wrapper.cpp b/tools/frameworks/kits/base/cpp/src/ohos/aafwk/base/short_wrapper.cpp new file mode 100644 index 00000000000..aaf0c2e0b00 --- /dev/null +++ b/tools/frameworks/kits/base/cpp/src/ohos/aafwk/base/short_wrapper.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ohos/aafwk/base/short_wrapper.h" + +namespace OHOS { +namespace AAFwk { +IINTERFACE_IMPL_1(Short, Object, IShort); + +ErrCode Short::GetValue(short &value) /* [out] */ +{ + VALIDATE_NOT_NULL(&value); + + value = value_; + return ERR_OK; +} + +bool Short::Equals(IObject &other) /* [in] */ +{ + Short *otherObj = static_cast(IShort::Query(&other)); + return otherObj != nullptr && otherObj->value_ == value_; +} + +std::string Short::ToString() +{ + return std::to_string(value_); +} + +sptr Short::Box(short value) /* [in] */ +{ + sptr object = new Short(value); + return object; +} + +short Short::Unbox(IShort *object) /* [in] */ +{ + short value; + object->GetValue(value); + return value; +} + +sptr Short::Parse(const std::string &str) /* [in] */ +{ + sptr object; + std::size_t idx; + short value = (short)std::stoi(str, &idx); + if (idx != 0) { + object = new Short(value); + } + return object; +} +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/base/cpp/src/ohos/aafwk/base/string_wrapper.cpp b/tools/frameworks/kits/base/cpp/src/ohos/aafwk/base/string_wrapper.cpp new file mode 100644 index 00000000000..8fc5be1d92c --- /dev/null +++ b/tools/frameworks/kits/base/cpp/src/ohos/aafwk/base/string_wrapper.cpp @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ohos/aafwk/base/string_wrapper.h" + +namespace OHOS { +namespace AAFwk { +IINTERFACE_IMPL_1(String, Object, IString); + +ErrCode String::GetString(std::string &str) /* [out] */ +{ + VALIDATE_NOT_NULL(&str); + + str = string_; + return ERR_OK; +} + +bool String::Equals(IObject &other) /* [in] */ +{ + String *otherObj = static_cast(IString::Query(&other)); + return otherObj != nullptr && otherObj->string_ == string_; +} + +std::string String::ToString() +{ + return string_; +} + +sptr String::Box(const std::string &str) /* [in] */ +{ + sptr object = new String(str); + return object; +} + +std::string String::Unbox(IString *object) /* [in] */ +{ + std::string str; + object->GetString(str); + return str; +} + +sptr String::Parse(const std::string &str) /* [in] */ +{ + sptr object = new String(str); + return object; +} +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/base/cpp/src/ohos/aafwk/base/user_object_wrapper.cpp b/tools/frameworks/kits/base/cpp/src/ohos/aafwk/base/user_object_wrapper.cpp new file mode 100755 index 00000000000..97488a565c4 --- /dev/null +++ b/tools/frameworks/kits/base/cpp/src/ohos/aafwk/base/user_object_wrapper.cpp @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "ohos/aafwk/base/user_object_wrapper.h" +#include "ohos/aafwk/base/user_object_base.h" + +namespace OHOS { +namespace AAFwk { +namespace { +const std::string SPLIT = "#"; +}; +IINTERFACE_IMPL_1(UserObject, Object, IUserObject); + +ErrCode UserObject::GetValue(std::shared_ptr &value) +{ + value = value_; + return ERR_OK; +} +bool UserObject::Equals(IObject &other) +{ + if (value_ == nullptr) { + return false; + } + + UserObject *otherObj = static_cast(IUserObject::Query(&other)); + if (otherObj == nullptr) { + return false; + } + if (value_->GetClassName() == otherObj->value_->GetClassName()) { + return otherObj->value_->Equals(value_); + } + return false; +} + +std::string UserObject::ToString() +{ + if (value_ == nullptr) { + return std::string(""); + } + return value_->GetClassName() + SPLIT + value_->ToString(); +} + +sptr UserObject::Box(const std::shared_ptr &value) +{ + if (value != nullptr) { + sptr object = new (std::nothrow) UserObject(value); + return object; + } else { + return nullptr; + } +} + +std::shared_ptr UserObject::Unbox(IUserObject *object) +{ + std::shared_ptr value = nullptr; + if (object == nullptr) { + return nullptr; + } + + object->GetValue(value); + return value; +} + +sptr UserObject::Parse(const std::string &str) +{ + std::size_t len = str.length(); + if (len < 1) { + return nullptr; + } + std::size_t splitPos = str.find(SPLIT); + if (splitPos == std::string::npos) { + return nullptr; + } + std::string className = str.substr(0, splitPos); + std::string content = str.substr(className.length() + 1, len - 1); + if (className.length() + SPLIT.length() + content.length() != len) { + return nullptr; + } + + UserObjectBase *userObjectBase = + static_cast(UserObjectBaseLoader::GetInstance().GetUserObjectByName(className)); + if (userObjectBase != nullptr) { + userObjectBase->Parse(content); + sptr ret = new UserObject(std::shared_ptr(userObjectBase)); + return ret; + } + return nullptr; +} + +UserObjectBaseLoader &UserObjectBaseLoader::GetInstance(void) +{ + static UserObjectBaseLoader gUserObjectBaseLoader; + return gUserObjectBaseLoader; +} + +/** + * @brief Registered user-defined serialization class. + * @param objectName The name of the custom class. + * @param createFun Function object that creates an instance of a custom class. + */ +void UserObjectBaseLoader::RegisterUserObject(const std::string &objectName, const CreateUserObjectBase &createFun) +{ + register_class_list_.emplace(objectName, createFun); +} + +/** + * @brief Represents obtaining an instance of an object of a registered serialization class. + * @param className The name of the custom class. + * + * @return Returns an instance of the object, or nullptr on failure. + */ +UserObjectBase *UserObjectBaseLoader::GetUserObjectByName(const std::string &className) +{ + auto iter = register_class_list_.find(className); + if (iter != register_class_list_.end()) { + return iter->second(); + } else { + return nullptr; + } +} + +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/base/cpp/src/ohos/aafwk/base/zchar_wrapper.cpp b/tools/frameworks/kits/base/cpp/src/ohos/aafwk/base/zchar_wrapper.cpp new file mode 100644 index 00000000000..33a2d3f30b9 --- /dev/null +++ b/tools/frameworks/kits/base/cpp/src/ohos/aafwk/base/zchar_wrapper.cpp @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ohos/aafwk/base/zchar_wrapper.h" + +namespace OHOS { +namespace AAFwk { +IINTERFACE_IMPL_1(Char, Object, IChar); + +ErrCode Char::GetValue(zchar &value) /* [out] */ +{ + VALIDATE_NOT_NULL(&value); + + value = value_; + return ERR_OK; +} + +bool Char::Equals(IObject &other) /* [in] */ +{ + Char *otherObj = static_cast(IChar::Query(&other)); + return otherObj != nullptr && otherObj->value_ == value_; +} + +std::string Char::ToString() +{ + constexpr int MAX_BYTE_SIZE = 4; + + int byteSize = GetByteSize(value_); + char buf[MAX_BYTE_SIZE + 1]; + WriteUTF8Bytes(buf, value_, byteSize); + buf[byteSize] = '\0'; + return std::string(buf); +} + +sptr Char::Box(zchar value) /* [in] */ +{ + sptr object = new Char(value); + return object; +} + +zchar Char::Unbox(IChar *object) /* [in] */ +{ + zchar value; + object->GetValue(value); + return value; +} + +sptr Char::Parse(const std::string &str) /* [in] */ +{ + return Box(GetChar(str, 0)); +} + +int Char::GetByteSize(zchar c) /* [in] */ +{ + if ((c > MAX_CODE_POINT) || (c >= MIN_HIGH_SURROGATE && c <= MAX_LOW_SURROGATE)) { + return 0; + } + + int bsize = BYTE_COUNT_4; + if (c < 0x00000080) { + bsize = BYTE_COUNT_1; + } else if (c < 0x00000800) { + bsize = BYTE_COUNT_2; + } else if (c < 0x00010000) { + bsize = BYTE_COUNT_3; + } + return bsize; +} + +void Char::WriteUTF8Bytes(char *dst, /* [in] */ + zchar c, /* [in] */ + int size) /* [in] */ +{ + uint32_t uc = (uint32_t)c; + dst += size; + switch (size) { + /* note: everything falls through. */ + case BYTE_COUNT_4: { + *(--dst) = ((uc | BYTE_MARK) & BYTE_MASK); + uc >>= BYTE_SHIFT; + } + [[clang::fallthrough]]; + case BYTE_COUNT_3: { + *(--dst) = ((uc | BYTE_MARK) & BYTE_MASK); + uc >>= BYTE_SHIFT; + } + [[clang::fallthrough]]; + case BYTE_COUNT_2: { + *(--dst) = ((uc | BYTE_MARK) & BYTE_MASK); + uc >>= BYTE_SHIFT; + } + [[clang::fallthrough]]; + case BYTE_COUNT_1: { + *(--dst) = (uc | FIRST_BYTE_MARK[size]); + } + [[clang::fallthrough]]; + default: + break; + } +} + +zchar Char::GetChar(const std::string &str, /* [in] */ + int index) /* [in] */ +{ + if (str.empty() || index < 0) { + return INVALID_CHAR; + } + + int bsize; + const char *p = str.c_str(); + const char *end = p + str.length() + 1; + while (*p && p < end) { + zchar unicode = GetCharInternal((unsigned char *)p, bsize); + if (bsize == 0 || p + bsize >= end) + break; + if (index == 0) { + return unicode; + } + p += bsize; + index -= 1; + } + + return INVALID_CHAR; +} + +zchar Char::GetCharInternal(const unsigned char *cur, /* [in] */ + int &size) /* [in] */ +{ + if (isascii(*cur) != 0) { + size = 1; + return *cur; + } + + const unsigned char firstChar = *cur++; + zchar result = firstChar; + zchar mask, ignoreMask; + unsigned int num2Read; + for (num2Read = 1, mask = 0x40, ignoreMask = 0xFFFFFF80; (firstChar & mask); + num2Read++, ignoreMask |= mask, mask >>= 1) { + result = (result << BYTE_SHIFT) + (*cur++ & 0x3F); + } + ignoreMask |= mask; + result &= ~(ignoreMask << (BYTE_SHIFT * (num2Read - 1))); + size = num2Read; + return result; +} +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/base/cpp/test/BUILD.gn b/tools/frameworks/kits/base/cpp/test/BUILD.gn new file mode 100644 index 00000000000..697aa3e8fd4 --- /dev/null +++ b/tools/frameworks/kits/base/cpp/test/BUILD.gn @@ -0,0 +1,60 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/test.gni") + +module_output_path = "aafwk/base_test" + +config("module_private_config") { + visibility = [ ":*" ] + include_dirs = [ "//utils/native/base/include" ] +} + +baseImpl = + "//foundation/aafwk/standard/frameworks/kits/base/cpp/src/ohos/aafwk/base" + +ohos_unittest("base_test") { + module_out_path = module_output_path + sources = [ + "${baseImpl}/array_wrapper.cpp", + "${baseImpl}/base.cpp", + "${baseImpl}/base_object.cpp", + "${baseImpl}/bool_wrapper.cpp", + "${baseImpl}/byte_wrapper.cpp", + "${baseImpl}/double_wrapper.cpp", + "${baseImpl}/float_wrapper.cpp", + "${baseImpl}/int_wrapper.cpp", + "${baseImpl}/long_wrapper.cpp", + "${baseImpl}/short_wrapper.cpp", + "${baseImpl}/string_wrapper.cpp", + "${baseImpl}/zchar_wrapper.cpp", + "unittest/common/base_test.cpp", + ] + + configs = [ + ":module_private_config", + "//foundation/aafwk/standard/interfaces/innerkits/base:base_public_config", + ] + + deps = [ + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] +} + +group("unittest") { + testonly = true + deps = [] + + deps += [ ":base_test" ] +} diff --git a/tools/frameworks/kits/base/cpp/test/unittest/common/base_test.cpp b/tools/frameworks/kits/base/cpp/test/unittest/common/base_test.cpp new file mode 100644 index 00000000000..40f182a0239 --- /dev/null +++ b/tools/frameworks/kits/base/cpp/test/unittest/common/base_test.cpp @@ -0,0 +1,1110 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "ohos/aafwk/base/light_refbase.h" +#include "ohos/aafwk/base/array_wrapper.h" +#include "ohos/aafwk/base/base_object.h" +#include "ohos/aafwk/base/bool_wrapper.h" +#include "ohos/aafwk/base/zchar_wrapper.h" +#include "ohos/aafwk/base/byte_wrapper.h" +#include "ohos/aafwk/base/short_wrapper.h" +#include "ohos/aafwk/base/int_wrapper.h" +#include "ohos/aafwk/base/long_wrapper.h" +#include "ohos/aafwk/base/float_wrapper.h" +#include "ohos/aafwk/base/double_wrapper.h" +#include "ohos/aafwk/base/string_wrapper.h" +#include "refbase.h" + +using namespace OHOS; +using namespace OHOS::AAFwk; +using testing::ext::TestSize; + +namespace OHOS { +namespace AAFwk { +class AAFwkBaseTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void AAFwkBaseTest::SetUpTestCase(void) +{} + +void AAFwkBaseTest::TearDownTestCase(void) +{} + +void AAFwkBaseTest::SetUp(void) +{} + +void AAFwkBaseTest::TearDown(void) +{} + +class LightRefCountBaseTestClass : public LightRefCountBase { +public: + LightRefCountBaseTestClass() + { + gDestructorCalled_ = false; + } + + virtual ~LightRefCountBaseTestClass() + { + gDestructorCalled_ = true; + } + +public: + static bool gDestructorCalled_; +}; + +bool LightRefCountBaseTestClass::gDestructorCalled_ = false; + +class RefBaseTestClass : public RefBase { +public: + RefBaseTestClass() + { + gDestructorCalled_ = false; + } + + virtual ~RefBaseTestClass() + { + gDestructorCalled_ = true; + } + +public: + static bool gDestructorCalled_; +}; + +bool RefBaseTestClass::gDestructorCalled_ = false; + +CLASS(ObjectTestClass, 5afc4756 - 8f3c - 4d80 - a88b - 54521890beca) +{ +public: + ObjectTestClass( + /* [in] */ int type) + : type_(type) + { + gDestructorCalled_ = false; + } + + ~ObjectTestClass() + { + gDestructorCalled_ = true; + } + + OBJECT_DECL(); + + int GetHashCode() override + { + return 19; + } + + bool Equals( + /* [in] */ + IObject * other) override + { + if (other == nullptr) { + return false; + } + + if (other->GetClassID() == CID_ObjectTestClass) { + return type_ == static_cast(other)->type_; + } + + return false; + } + + std::string ToString() override + { + return std::string("object[") + std::to_string(reinterpret_cast(this)) + std::string("]type_=") + + std::to_string(type_) + std::string(";"); + } + +public: + static bool gDestructorCalled_; + +private: + int type_; +}; + +const ClassID CID_ObjectTestClass = { + 0x5afc4756, 0x8f3c, 0x4d80, 0xa88b, { + 0x5, 0x4, 0x5, 0x2, 0x1, 0x8, 0x9, 0x0, 0xb, 0xe, 0xc, 0xa + } + }; + +bool ObjectTestClass::gDestructorCalled_ = false; + +OBJECT_IMPL(ObjectTestClass); + +/* + * Feature: LightRefCountBase + * Function: IncStrongRef, DecStrongRef and GetRefCount + * SubFunction: NA + * FunctionPoints: IncStrongRef, DecStrongRef and GetRefCount + * EnvConditions: NA + * CaseDescription: Verify IncStrongRef, DecStrongRef and GetRefCount methods of RefBase. + */ +HWTEST_F(AAFwkBaseTest, LightRefCountBase_test_001, TestSize.Level1) +{ + sptr testObject = new LightRefCountBaseTestClass(); + EXPECT_FALSE(LightRefCountBaseTestClass::gDestructorCalled_); + EXPECT_EQ(testObject->GetRefCount(), 1); + testObject = nullptr; + EXPECT_TRUE(LightRefCountBaseTestClass::gDestructorCalled_); +} + +/* + * Feature: RefBase + * Function: IncStrongRef and DecStrongRef + * SubFunction: NA + * FunctionPoints: IncStrongRef and DecStrongRef + * EnvConditions: NA + * CaseDescription: Verify IncStrongRef and DecStrongRef methods of RefBase. + */ +HWTEST_F(AAFwkBaseTest, RefBase_test_001, TestSize.Level1) +{ + sptr testObject = new RefBaseTestClass(); + EXPECT_FALSE(RefBaseTestClass::gDestructorCalled_); + testObject = nullptr; + EXPECT_TRUE(RefBaseTestClass::gDestructorCalled_); +} + +/* + * Feature: Object + * Function: GetInterfaceID + * SubFunction: NA + * FunctionPoints: GetInterfaceID + * EnvConditions: NA + * CaseDescription: Verify the GetInterfaceID method of subclass. + */ +HWTEST_F(AAFwkBaseTest, object_test_001, TestSize.Level1) +{ + sptr testObject = new ObjectTestClass(999); + sptr object = static_cast(testObject.GetRefPtr()); + EXPECT_EQ(g_IID_IObject, object->GetInterfaceID(object)); +} + +/* + * Feature: Object + * Function: GetClassID + * SubFunction: NA + * FunctionPoints: GetClassID + * EnvConditions: NA + * CaseDescription: Verify the override GetClassID method of subclass. + */ +HWTEST_F(AAFwkBaseTest, object_test_002, TestSize.Level1) +{ + sptr testObject = new ObjectTestClass(999); + EXPECT_EQ(CID_ObjectTestClass, testObject->GetClassID()); + testObject = nullptr; + EXPECT_TRUE(ObjectTestClass::gDestructorCalled_); +} + +/* + * Feature: Object + * Function: GetHashCode + * SubFunction: NA + * FunctionPoints: GetHashCode + * EnvConditions: NA + * CaseDescription: Verify the override GetHashCode method of subclass. + */ +HWTEST_F(AAFwkBaseTest, object_test_003, TestSize.Level1) +{ + sptr testObject = new ObjectTestClass(999); + EXPECT_EQ(19, testObject->GetHashCode()); + testObject = nullptr; + EXPECT_TRUE(ObjectTestClass::gDestructorCalled_); +} + +/* + * Feature: Object + * Function: Equal + * SubFunction: NA + * FunctionPoints: Equal + * EnvConditions: NA + * CaseDescription: Verify the override Equal method of subclass. + */ +HWTEST_F(AAFwkBaseTest, object_test_004, TestSize.Level1) +{ + sptr testObject1 = new ObjectTestClass(999); + sptr testObject2 = new ObjectTestClass(9999); + sptr testObject3 = new ObjectTestClass(999); + EXPECT_FALSE(testObject1->Equals(testObject2)); + EXPECT_TRUE(testObject1->Equals(testObject3)); +} + +/* + * Feature: Object + * Function: ToString + * SubFunction: NA + * FunctionPoints: ToString + * EnvConditions: NA + * CaseDescription: Verify the override ToString method of subclass. + */ +HWTEST_F(AAFwkBaseTest, object_test_005, TestSize.Level1) +{ + sptr testObject1 = new ObjectTestClass(999); + std::string objectStr = testObject1->ToString(); + EXPECT_TRUE(objectStr.find("type_=999") != std::string::npos); +} + +/* + * Feature: Object + * Function: GetWeakReference + * SubFunction: NA + * FunctionPoints: GetWeakReference + * EnvConditions: NA + * CaseDescription: Verify GetWeakReference method of subclass. + */ +HWTEST_F(AAFwkBaseTest, object_test_006, TestSize.Level1) +{ + sptr testObject1 = new ObjectTestClass(999); + EXPECT_FALSE(ObjectTestClass::gDestructorCalled_); + sptr weakRef; + testObject1->GetWeakReference(weakRef); + EXPECT_TRUE(weakRef != nullptr); + sptr object; + weakRef->Resolve(g_IID_IObject, reinterpret_cast(&object)); + EXPECT_TRUE(object != nullptr); + EXPECT_EQ(static_cast(object.GetRefPtr())->GetHashCode(), 19); + testObject1 = nullptr; + object = nullptr; + EXPECT_TRUE(ObjectTestClass::gDestructorCalled_); + weakRef->Resolve(g_IID_IObject, reinterpret_cast(&object)); + EXPECT_TRUE(object == nullptr); +} + +/* + * Feature: wptr + * Function: wptr + * SubFunction: NA + * FunctionPoints: wptr + * EnvConditions: NA + * CaseDescription: Verify wptr. + */ +HWTEST_F(AAFwkBaseTest, object_test_007, TestSize.Level1) +{ + sptr testObject1 = new ObjectTestClass(999); + EXPECT_FALSE(ObjectTestClass::gDestructorCalled_); + wptr weakObject(testObject1); + testObject1 = nullptr; + EXPECT_TRUE(ObjectTestClass::gDestructorCalled_); + EXPECT_TRUE(weakObject.promote() == nullptr); +} + +/* + * Feature: Boolean + * Function: GetValue + * SubFunction: NA + * FunctionPoints: GetValue + * EnvConditions: NA + * CaseDescription: Verify GetValue method of Boolean. + */ +HWTEST_F(AAFwkBaseTest, boolean_test_001, TestSize.Level1) +{ + sptr boolean = new Boolean(true); + bool value = false; + boolean->GetValue(&value); + EXPECT_TRUE(value); + boolean = new Boolean(false); + boolean->GetValue(&value); + EXPECT_FALSE(value); +} + +/* + * Feature: Boolean + * Function: Box and Unbox + * SubFunction: NA + * FunctionPoints: Box and Unbox + * EnvConditions: NA + * CaseDescription: Verify Box and Unbox method of Boolean. + */ +HWTEST_F(AAFwkBaseTest, boolean_test_002, TestSize.Level1) +{ + sptr boolean = Boolean::Box(true); + EXPECT_TRUE(Boolean::Unbox(boolean)); + boolean = Boolean::Box(false); + EXPECT_FALSE(Boolean::Unbox(boolean)); +} + +/* + * Feature: Boolean + * Function: Parse + * SubFunction: NA + * FunctionPoints: Parse + * EnvConditions: NA + * CaseDescription: Verify Parse method of Boolean. + */ +HWTEST_F(AAFwkBaseTest, boolean_test_003, TestSize.Level1) +{ + sptr boolean = Boolean::Parse("true"); + EXPECT_TRUE(Boolean::Unbox(boolean)); + boolean = Boolean::Parse("false"); + EXPECT_FALSE(Boolean::Unbox(boolean)); +} + +/* + * Feature: Boolean + * Function: Equals + * SubFunction: NA + * FunctionPoints: Equals + * EnvConditions: NA + * CaseDescription: Verify Equals method of Boolean. + */ +HWTEST_F(AAFwkBaseTest, boolean_test_004, TestSize.Level1) +{ + sptr boolean1 = new Boolean(true); + sptr boolean2 = new Boolean(false); + sptr boolean3 = new Boolean(true); + EXPECT_FALSE(boolean1->Equals(boolean2)); + EXPECT_TRUE(boolean1->Equals(boolean3)); +} + +/* + * Feature: Boolean + * Function: ToString + * SubFunction: NA + * FunctionPoints: ToString + * EnvConditions: NA + * CaseDescription: Verify ToString method of Boolean. + */ +HWTEST_F(AAFwkBaseTest, boolean_test_005, TestSize.Level1) +{ + EXPECT_EQ(Object::ToString(Boolean::Box(true)), "true"); + EXPECT_EQ(Object::ToString(Boolean::Box(false)), "false"); +} + +/* + * Feature: Char + * Function: GetValue + * SubFunction: NA + * FunctionPoints: GetValue + * EnvConditions: NA + * CaseDescription: Verify GetValue method of Char. + */ +HWTEST_F(AAFwkBaseTest, char_test_001, TestSize.Level1) +{ + sptr charObj = new Char(U'中'); + zchar value; + charObj->GetValue(&value); + EXPECT_EQ(value, U'中'); +} + +/* + * Feature: Char + * Function: Box and Unbox + * SubFunction: NA + * FunctionPoints: Box and Unbox + * EnvConditions: NA + * CaseDescription: Verify Box and Unbox method of Char. + */ +HWTEST_F(AAFwkBaseTest, char_test_002, TestSize.Level1) +{ + sptr charObj = Char::Box(U'天'); + EXPECT_EQ(Char::Unbox(charObj), U'天'); +} + +/* + * Feature: Char + * Function: Parse + * SubFunction: NA + * FunctionPoints: Parse + * EnvConditions: NA + * CaseDescription: Verify Parse method of Char. + */ +HWTEST_F(AAFwkBaseTest, char_test_003, TestSize.Level1) +{ + sptr charObj = Char::Parse("气"); + EXPECT_EQ(Char::Unbox(charObj), U'气'); +} + +/* + * Feature: Char + * Function: Equals + * SubFunction: NA + * FunctionPoints: Equals + * EnvConditions: NA + * CaseDescription: Verify Equals method of Char. + */ +HWTEST_F(AAFwkBaseTest, char_test_004, TestSize.Level1) +{ + sptr charObj1 = new Char(U'H'); + sptr charObj2 = new Char('I'); + sptr charObj3 = new Char(U'H'); + EXPECT_FALSE(charObj1->Equals(charObj2)); + EXPECT_TRUE(charObj1->Equals(charObj3)); +} + +/* + * Feature: Char + * Function: ToString + * SubFunction: NA + * FunctionPoints: ToString + * EnvConditions: NA + * CaseDescription: Verify ToString method of Char. + */ +HWTEST_F(AAFwkBaseTest, char_test_005, TestSize.Level1) +{ + EXPECT_EQ(Object::ToString(Char::Box(U'好')), "好"); +} + +/* + * Feature: Char + * Function: GetChar + * SubFunction: NA + * FunctionPoints: GetChar + * EnvConditions: NA + * CaseDescription: Verify GetChar method of Char. + */ +HWTEST_F(AAFwkBaseTest, char_test_006, TestSize.Level1) +{ + std::string str = "今天气温真不错有23摄氏度呢!"; + EXPECT_EQ(Char::GetChar(str, 0), U'今'); + EXPECT_EQ(Char::GetChar(str, 1), U'天'); + EXPECT_EQ(Char::GetChar(str, 2), U'气'); + EXPECT_EQ(Char::GetChar(str, 3), U'温'); + EXPECT_EQ(Char::GetChar(str, 4), U'真'); + EXPECT_EQ(Char::GetChar(str, 5), U'不'); + EXPECT_EQ(Char::GetChar(str, 6), U'错'); + EXPECT_EQ(Char::GetChar(str, 7), U'有'); + EXPECT_EQ(Char::GetChar(str, 8), '2'); + EXPECT_EQ(Char::GetChar(str, 9), '3'); + EXPECT_EQ(Char::GetChar(str, 10), U'摄'); + EXPECT_EQ(Char::GetChar(str, 11), U'氏'); + EXPECT_EQ(Char::GetChar(str, 12), U'度'); + EXPECT_EQ(Char::GetChar(str, 13), U'呢'); + EXPECT_EQ(Char::GetChar(str, 14), U'!'); +} + +/* + * Feature: Byte + * Function: GetValue + * SubFunction: NA + * FunctionPoints: GetValue + * EnvConditions: NA + * CaseDescription: Verify GetValue method of Byte. + */ +HWTEST_F(AAFwkBaseTest, byte_test_001, TestSize.Level1) +{ + sptr byteObj = new Byte(129); + byte value; + byteObj->GetValue(&value); + EXPECT_EQ(value, 129); +} + +/* + * Feature: Byte + * Function: Box and Unbox + * SubFunction: NA + * FunctionPoints: Box and Unbox + * EnvConditions: NA + * CaseDescription: Verify Box and Unbox method of Byte. + */ +HWTEST_F(AAFwkBaseTest, byte_test_002, TestSize.Level1) +{ + sptr byteObj = Byte::Box(129); + EXPECT_EQ(Byte::Unbox(byteObj), 129); +} + +/* + * Feature: Byte + * Function: Parse + * SubFunction: NA + * FunctionPoints: Parse + * EnvConditions: NA + * CaseDescription: Verify Parse method of Byte. + */ +HWTEST_F(AAFwkBaseTest, byte_test_003, TestSize.Level1) +{ + sptr byteObj = Byte::Parse("129"); + EXPECT_EQ(Byte::Unbox(byteObj), 129); +} + +/* + * Feature: Byte + * Function: Equals + * SubFunction: NA + * FunctionPoints: Equals + * EnvConditions: NA + * CaseDescription: Verify Equals method of Byte. + */ +HWTEST_F(AAFwkBaseTest, byte_test_004, TestSize.Level1) +{ + sptr byteObj1 = new Byte(129); + sptr byteObj2 = new Byte(130); + sptr byteObj3 = new Byte(129); + EXPECT_FALSE(byteObj1->Equals(byteObj2)); + EXPECT_TRUE(byteObj1->Equals(byteObj3)); +} + +/* + * Feature: Byte + * Function: ToString + * SubFunction: NA + * FunctionPoints: ToString + * EnvConditions: NA + * CaseDescription: Verify ToString method of Byte. + */ +HWTEST_F(AAFwkBaseTest, byte_test_005, TestSize.Level1) +{ + EXPECT_EQ(Object::ToString(Byte::Box(129)), "129"); +} + +/* + * Feature: Short + * Function: GetValue + * SubFunction: NA + * FunctionPoints: GetValue + * EnvConditions: NA + * CaseDescription: Verify GetValue method of Short. + */ +HWTEST_F(AAFwkBaseTest, short_test_001, TestSize.Level1) +{ + sptr shortObj = new Short(32767); + short value; + shortObj->GetValue(&value); + EXPECT_EQ(value, 32767); +} + +/* + * Feature: Short + * Function: Box and Unbox + * SubFunction: NA + * FunctionPoints: Box and Unbox + * EnvConditions: NA + * CaseDescription: Verify Box and Unbox method of Short. + */ +HWTEST_F(AAFwkBaseTest, short_test_002, TestSize.Level1) +{ + sptr shortObj = Short::Box(32767); + EXPECT_EQ(Short::Unbox(shortObj), 32767); +} + +/* + * Feature: Short + * Function: Parse + * SubFunction: NA + * FunctionPoints: Parse + * EnvConditions: NA + * CaseDescription: Verify Parse method of Short. + */ +HWTEST_F(AAFwkBaseTest, short_test_003, TestSize.Level1) +{ + sptr shortObj = Short::Parse("32767"); + EXPECT_EQ(Short::Unbox(shortObj), 32767); +} + +/* + * Feature: Short + * Function: Equals + * SubFunction: NA + * FunctionPoints: Equals + * EnvConditions: NA + * CaseDescription: Verify Equals method of Short. + */ +HWTEST_F(AAFwkBaseTest, short_test_004, TestSize.Level1) +{ + sptr shortObj1 = new Short(32767); + sptr shortObj2 = new Short(-32768); + sptr shortObj3 = new Short(32767); + EXPECT_FALSE(shortObj1->Equals(shortObj2)); + EXPECT_TRUE(shortObj1->Equals(shortObj3)); +} + +/* + * Feature: Short + * Function: ToString + * SubFunction: NA + * FunctionPoints: ToString + * EnvConditions: NA + * CaseDescription: Verify ToString method of Short. + */ +HWTEST_F(AAFwkBaseTest, short_test_005, TestSize.Level1) +{ + EXPECT_EQ(Object::ToString(Short::Box(32767)), "32767"); +} + +/* + * Feature: Integer + * Function: GetValue + * SubFunction: NA + * FunctionPoints: GetValue + * EnvConditions: NA + * CaseDescription: Verify GetValue method of Integer. + */ +HWTEST_F(AAFwkBaseTest, integer_test_001, TestSize.Level1) +{ + sptr intObj = new Integer(2147483647); + int value; + intObj->GetValue(&value); + EXPECT_EQ(value, 2147483647); +} + +/* + * Feature: Integer + * Function: Box and Unbox + * SubFunction: NA + * FunctionPoints: Box and Unbox + * EnvConditions: NA + * CaseDescription: Verify Box and Unbox method of Integer. + */ +HWTEST_F(AAFwkBaseTest, integer_test_002, TestSize.Level1) +{ + sptr intObj = Integer::Box(2147483647); + EXPECT_EQ(Integer::Unbox(intObj), 2147483647); +} + +/* + * Feature: Integer + * Function: Parse + * SubFunction: NA + * FunctionPoints: Parse + * EnvConditions: NA + * CaseDescription: Verify Parse method of Integer. + */ +HWTEST_F(AAFwkBaseTest, integer_test_003, TestSize.Level1) +{ + sptr intObj = Integer::Parse("-1"); + EXPECT_EQ(Integer::Unbox(intObj), -1); +} + +/* + * Feature: Integer + * Function: Equals + * SubFunction: NA + * FunctionPoints: Equals + * EnvConditions: NA + * CaseDescription: Verify Equals method of Integer. + */ +HWTEST_F(AAFwkBaseTest, integer_test_004, TestSize.Level1) +{ + sptr intObj1 = new Integer(2147483647); + sptr intObj2 = new Integer(-2147483648); + sptr intObj3 = new Integer(2147483647); + EXPECT_FALSE(intObj1->Equals(intObj2)); + EXPECT_TRUE(intObj1->Equals(intObj3)); +} + +/* + * Feature: Integer + * Function: ToString + * SubFunction: NA + * FunctionPoints: ToString + * EnvConditions: NA + * CaseDescription: Verify ToString method of Integer. + */ +HWTEST_F(AAFwkBaseTest, integer_test_005, TestSize.Level1) +{ + EXPECT_EQ(Object::ToString(Integer::Box(-2147483648)), "-2147483648"); +} + +/* + * Feature: Long + * Function: GetValue + * SubFunction: NA + * FunctionPoints: GetValue + * EnvConditions: NA + * CaseDescription: Verify GetValue method of Long. + */ +HWTEST_F(AAFwkBaseTest, long_test_001, TestSize.Level1) +{ + sptr longObj = new Long(2147483647L); + long value; + longObj->GetValue(&value); + EXPECT_EQ(value, 2147483647L); +} + +/* + * Feature: Long + * Function: Box and Unbox + * SubFunction: NA + * FunctionPoints: Box and Unbox + * EnvConditions: NA + * CaseDescription: Verify Box and Unbox method of Long. + */ +HWTEST_F(AAFwkBaseTest, long_test_002, TestSize.Level1) +{ + sptr longObj = Long::Box(2147483647L); + EXPECT_EQ(Long::Unbox(longObj), 2147483647L); +} + +/* + * Feature: Long + * Function: Parse + * SubFunction: NA + * FunctionPoints: Parse + * EnvConditions: NA + * CaseDescription: Verify Parse method of Long. + */ +HWTEST_F(AAFwkBaseTest, long_test_003, TestSize.Level1) +{ + sptr longObj = Long::Parse("-1"); + EXPECT_EQ(Long::Unbox(longObj), -1); +} + +/* + * Feature: Long + * Function: Equals + * SubFunction: NA + * FunctionPoints: Equals + * EnvConditions: NA + * CaseDescription: Verify Equals method of Long. + */ +HWTEST_F(AAFwkBaseTest, long_test_004, TestSize.Level1) +{ + sptr longObj1 = new Long(2147483647L); + sptr longObj2 = new Long(-2147483647L); + sptr longObj3 = new Long(2147483647L); + EXPECT_FALSE(longObj1->Equals(longObj2)); + EXPECT_TRUE(longObj1->Equals(longObj3)); +} + +/* + * Feature: Long + * Function: ToString + * SubFunction: NA + * FunctionPoints: ToString + * EnvConditions: NA + * CaseDescription: Verify ToString method of Long. + */ +HWTEST_F(AAFwkBaseTest, long_test_005, TestSize.Level1) +{ + EXPECT_EQ(Object::ToString(Long::Box(-2147483647L)), "-9223372036854775807"); +} + +/* + * Feature: Float + * Function: GetValue + * SubFunction: NA + * FunctionPoints: GetValue + * EnvConditions: NA + * CaseDescription: Verify GetValue method of Float. + */ +HWTEST_F(AAFwkBaseTest, float_test_001, TestSize.Level1) +{ + sptr floatObj = new Float(-1.020); + float value; + floatObj->GetValue(&value); + EXPECT_FLOAT_EQ(value, -1.020); +} + +/* + * Feature: Float + * Function: Box and Unbox + * SubFunction: NA + * FunctionPoints: Box and Unbox + * EnvConditions: NA + * CaseDescription: Verify Box and Unbox method of Float. + */ +HWTEST_F(AAFwkBaseTest, float_test_002, TestSize.Level1) +{ + sptr floatObj = Float::Box(-0.003); + EXPECT_FLOAT_EQ(Float::Unbox(floatObj), -0.003); +} + +/* + * Feature: Float + * Function: Parse + * SubFunction: NA + * FunctionPoints: Parse + * EnvConditions: NA + * CaseDescription: Verify Parse method of Float. + */ +HWTEST_F(AAFwkBaseTest, float_test_003, TestSize.Level1) +{ + sptr floatObj = Float::Parse("-1.000400"); + EXPECT_FLOAT_EQ(Float::Unbox(floatObj), -1.0004); +} + +/* + * Feature: Float + * Function: Equals + * SubFunction: NA + * FunctionPoints: Equals + * EnvConditions: NA + * CaseDescription: Verify Equals method of Float. + */ +HWTEST_F(AAFwkBaseTest, float_test_004, TestSize.Level1) +{ + sptr floatObj1 = new Float(0.009); + sptr floatObj2 = new Float(-0.001); + sptr floatObj3 = new Float(0.009); + EXPECT_FALSE(floatObj1->Equals(floatObj2)); + EXPECT_TRUE(floatObj1->Equals(floatObj3)); +} + +/* + * Feature: Float + * Function: ToString + * SubFunction: NA + * FunctionPoints: ToString + * EnvConditions: NA + * CaseDescription: Verify ToString method of Float. + */ +HWTEST_F(AAFwkBaseTest, float_test_005, TestSize.Level1) +{ + EXPECT_EQ(Object::ToString(Float::Box(-10.00006)), "-10.000060"); +} + +/* + * Feature: Double + * Function: GetValue + * SubFunction: NA + * FunctionPoints: GetValue + * EnvConditions: NA + * CaseDescription: Verify GetValue method of Double. + */ +HWTEST_F(AAFwkBaseTest, double_test_001, TestSize.Level1) +{ + sptr doubleObj = new Double(-1.00020); + double value; + doubleObj->GetValue(&value); + EXPECT_DOUBLE_EQ(value, -1.00020); +} + +/* + * Feature: Double + * Function: Box and Unbox + * SubFunction: NA + * FunctionPoints: Box and Unbox + * EnvConditions: NA + * CaseDescription: Verify Box and Unbox method of Double. + */ +HWTEST_F(AAFwkBaseTest, double_test_002, TestSize.Level1) +{ + sptr doubleObj = Double::Box(-0.00003); + EXPECT_DOUBLE_EQ(Double::Unbox(doubleObj), -0.00003); +} + +/* + * Feature: Double + * Function: Parse + * SubFunction: NA + * FunctionPoints: Parse + * EnvConditions: NA + * CaseDescription: Verify Parse method of Double. + */ +HWTEST_F(AAFwkBaseTest, double_test_003, TestSize.Level1) +{ + sptr doubleObj = Double::Parse("-1.0000000400"); + EXPECT_DOUBLE_EQ(Double::Unbox(doubleObj), -1.00000004); +} + +/* + * Feature: Double + * Function: Equals + * SubFunction: NA + * FunctionPoints: Equals + * EnvConditions: NA + * CaseDescription: Verify Equals method of Double. + */ +HWTEST_F(AAFwkBaseTest, double_test_004, TestSize.Level1) +{ + sptr doubleObj1 = new Double(0.000009); + sptr doubleObj2 = new Double(-0.000001); + sptr doubleObj3 = new Double(0.000009); + EXPECT_FALSE(doubleObj1->Equals(doubleObj2)); + EXPECT_TRUE(doubleObj1->Equals(doubleObj3)); +} + +/* + * Feature: Double + * Function: ToString + * SubFunction: NA + * FunctionPoints: ToString + * EnvConditions: NA + * CaseDescription: Verify ToString method of Double. + */ +HWTEST_F(AAFwkBaseTest, double_test_005, TestSize.Level1) +{ + EXPECT_EQ(Object::ToString(Double::Box(-10.000006)), "-10.000006"); +} + +/* + * Feature: String + * Function: GetString + * SubFunction: NA + * FunctionPoints: GetString + * EnvConditions: NA + * CaseDescription: Verify GetString method of String. + */ +HWTEST_F(AAFwkBaseTest, string_test_001, TestSize.Level1) +{ + sptr stringObj = new String("$hell0-w@rld#"); + std::string string; + stringObj->GetString(&string); + EXPECT_EQ(string, std::string("$hell0-w@rld#")); +} + +/* + * Feature: String + * Function: Box and Unbox + * SubFunction: NA + * FunctionPoints: Box and Unbox + * EnvConditions: NA + * CaseDescription: Verify Box and Unbox method of String. + */ +HWTEST_F(AAFwkBaseTest, string_test_002, TestSize.Level1) +{ + sptr stringObj = String::Box("1234567890"); + EXPECT_EQ(String::Unbox(stringObj), std::string("1234567890")); +} + +/* + * Feature: String + * Function: Parse + * SubFunction: NA + * FunctionPoints: Parse + * EnvConditions: NA + * CaseDescription: Verify Parse method of String. + */ +HWTEST_F(AAFwkBaseTest, string_test_003, TestSize.Level1) +{ + sptr stringObj = String::Parse("-1.0000000400"); + EXPECT_EQ(String::Unbox(stringObj), std::string("-1.0000000400")); +} + +/* + * Feature: String + * Function: Equals + * SubFunction: NA + * FunctionPoints: Equals + * EnvConditions: NA + * CaseDescription: Verify Equals method of String. + */ +HWTEST_F(AAFwkBaseTest, string_test_004, TestSize.Level1) +{ + sptr stringObj1 = new String("$hell0-w@rld#"); + sptr stringObj2 = new String("-1.0000000400"); + sptr stringObj3 = new String("$hell0-w@rld#"); + EXPECT_FALSE(stringObj1->Equals(stringObj2)); + EXPECT_TRUE(stringObj1->Equals(stringObj3)); +} + +/* + * Feature: String + * Function: ToString + * SubFunction: NA + * FunctionPoints: ToString + * EnvConditions: NA + * CaseDescription: Verify ToString method of String. + */ +HWTEST_F(AAFwkBaseTest, string_test_005, TestSize.Level1) +{ + EXPECT_EQ(Object::ToString(String::Box("-10.000006")), std::string("-10.000006")); +} + +/* + * Feature: Array + * Function: GetLength and GetType + * SubFunction: NA + * FunctionPoints: GetLength and GetType + * EnvConditions: NA + * CaseDescription: Verify GetLength and GetType method of Array. + */ +HWTEST_F(AAFwkBaseTest, array_test_001, TestSize.Level1) +{ + sptr arrayObj = new Array(9, g_IID_IInteger); + long size; + arrayObj->GetLength(&size); + EXPECT_EQ(size, 9); + InterfaceID type; + arrayObj->GetType(&type); + EXPECT_EQ(type, g_IID_IInteger); +} + +/* + * Feature: Array + * Function: Get and Set + * SubFunction: NA + * FunctionPoints: Get and Set + * EnvConditions: NA + * CaseDescription: Verify Get and Set method of Array. + */ +HWTEST_F(AAFwkBaseTest, array_test_002, TestSize.Level1) +{ + sptr arrayObj = new Array(19, g_IID_IInteger); + arrayObj->Set(0, Integer::Box(23)); + sptr valueObj; + arrayObj->Get(0, valueObj); + EXPECT_TRUE(valueObj != nullptr); + EXPECT_EQ(Integer::Unbox(IInteger::Query(valueObj)), 23); + arrayObj->Get(1, valueObj); + EXPECT_TRUE(valueObj == nullptr); +} + +/* + * Feature: Array + * Function: ToString + * SubFunction: NA + * FunctionPoints: ToString + * EnvConditions: NA + * CaseDescription: Verify ToString method of Array. + */ +HWTEST_F(AAFwkBaseTest, array_test_003, TestSize.Level1) +{ + sptr arrayObj = new Array(5, g_IID_IInteger); + arrayObj->Set(0, Integer::Box(2)); + arrayObj->Set(1, Integer::Box(3)); + arrayObj->Set(2, Integer::Box(5)); + arrayObj->Set(3, Integer::Box(7)); + arrayObj->Set(4, Integer::Box(11)); + EXPECT_EQ(arrayObj->ToString(), std::string("I5{2,3,5,7,11}")); +} + +/* + * Feature: Array + * Function: Parse + * SubFunction: NA + * FunctionPoints: Parse + * EnvConditions: NA + * CaseDescription: Verify Parse method of Array. + */ +HWTEST_F(AAFwkBaseTest, array_test_004, TestSize.Level1) +{ + sptr arrayObj = Array::Parse("I5{2,3,5,7,11}"); + sptr valueObj; + arrayObj->Get(0, valueObj); + EXPECT_EQ(Integer::Unbox(IInteger::Query(valueObj)), 2); + arrayObj->Get(1, valueObj); + EXPECT_EQ(Integer::Unbox(IInteger::Query(valueObj)), 3); + arrayObj->Get(2, valueObj); + EXPECT_EQ(Integer::Unbox(IInteger::Query(valueObj)), 5); + arrayObj->Get(3, valueObj); + EXPECT_EQ(Integer::Unbox(IInteger::Query(valueObj)), 7); + arrayObj->Get(4, valueObj); + EXPECT_EQ(Integer::Unbox(IInteger::Query(valueObj)), 11); +} + +/* + * Feature: Array + * Function: Equals + * SubFunction: NA + * FunctionPoints: Equals + * EnvConditions: NA + * CaseDescription: Verify Equals method of Array. + */ +HWTEST_F(AAFwkBaseTest, array_test_005, TestSize.Level1) +{ + sptr arrayObj1 = Array::Parse("I5{2,3,5,7,11}"); + sptr arrayObj2 = Array::Parse("I5{2,3,7,7,11}"); + sptr arrayObj3 = Array::Parse("I5{2,3,5,7,11}"); + EXPECT_FALSE(Object::Equals(arrayObj1, arrayObj2)); + EXPECT_TRUE(Object::Equals(arrayObj1, arrayObj3)); +} +} // namespace AAFwk +} // namespace OHOS diff --git a/tools/frameworks/kits/content/cpp/src/ohos/aafwk/content/extra_params.cpp b/tools/frameworks/kits/content/cpp/src/ohos/aafwk/content/extra_params.cpp new file mode 100755 index 00000000000..94099396a68 --- /dev/null +++ b/tools/frameworks/kits/content/cpp/src/ohos/aafwk/content/extra_params.cpp @@ -0,0 +1,264 @@ + +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "extra_params.h" +#include "string_ex.h" + +namespace OHOS { +namespace AppExecFwk { +/** + * @brief A default constructor used to create an empty {@code ExtraParams} instance. + * @param none + */ +ExtraParams::ExtraParams() +{} +/** + * @brief A copy constructor used to create an empty {@code ExtraParams} instance. + * @param other indicates object instance. + */ +ExtraParams::ExtraParams(const ExtraParams &other) +{ + devType_ = other.devType_; + targetBundleName_ = other.targetBundleName_; + description_ = other.description_; + jsonParams_ = other.jsonParams_; +} +/** + * @brief Overloading assignment operators to create the same object instance. + * @param other Indicates object instance. + */ +ExtraParams &ExtraParams::operator=(const ExtraParams &other) +{ + if (this != &other) { + devType_ = other.devType_; + targetBundleName_ = other.targetBundleName_; + description_ = other.description_; + jsonParams_ = other.jsonParams_; + } + return *this; +} +/** + * @brief Judge whether the parameter of extraparam instance is equal to that of other instance parameter + * @param other Indicates object instance. + * @return returns true the parameter of extraparam instance is equal to that of other instance parameter + * otherwise false + */ +bool ExtraParams::operator==(const ExtraParams &other) const +{ + if (targetBundleName_ == other.targetBundleName_ && description_ == other.description_ && + jsonParams_ == other.jsonParams_) { + + if (devType_.size() != other.devType_.size()) { + return false; + } else if (devType_.size() > 0 && other.devType_.size() > 0 && devType_.size() == other.devType_.size()) { + std::vector::const_iterator it1; + for (it1 = devType_.cbegin(); it1 != devType_.cend(); it1++) { + std::vector::const_iterator it2; + it2 = std::find(other.devType_.cbegin(), other.devType_.cend(), *it1); + if (it2 == other.devType_.cend()) { + return false; + } + } + return true; + } + return true; + } + return false; +} +/** + * @brief A constructor used to create an {@code ExtraParams} instance based on the input parameters{@code devType}, + * {@code targetBundleName}, and {@code description}. + * + * @param devType Indicates the type of devices to be matched. This parameter can be any combination of + * {@link #DEVICETYPE_SMART_PHONE}, {@link #DEVICETYPE_SMART_PAD}, {@link #DEVICETYPE_SMART_WATCH}, and + * {@link #DEVICETYPE_SMART_TV}. + * + * @param targetBundleName Indicates the bundle name of the target application where the ability will be migrated. + * + * @param description Indicates the description used for device filtering. + * + * @param jsonParams Indicates the custom JSON parameters to be used as filter conditions. + * + * @return none + */ +ExtraParams::ExtraParams(const std::vector &devType, const string &targetBundleName, const string &description, + const string &jsonParams) +{ + devType_ = devType; + targetBundleName_ = targetBundleName; + description_ = description; + jsonParams_ = jsonParams; +} + +/** + * @brief A destructor release an empty {@code ExtraParams} instance. + * @param none + */ +ExtraParams::~ExtraParams() +{} + +/** + * @brief Sets the list of device types. + * + * @param devType Indicates the type of devices to be matched. This parameter can be any combination of + * {@link #DEVICETYPE_SMART_PHONE}, {@link #DEVICETYPE_SMART_PAD}, {@link #DEVICETYPE_SMART_WATCH}, and + * {@link #DEVICETYPE_SMART_TV}. + * + * @return none + */ +void ExtraParams::SetDevType(const std::vector &devType) +{ + devType_ = devType; +} + +/** + * @brief Obtains the list of device types. + * + * @param none + * + * @return Returns the list of device types. + */ +std::vector ExtraParams::GetDevType() const +{ + return devType_; +} + +/** + * @brief Sets the bundle name of the target application where ability will be migrated. + * + * @param targetBundleName Indicates the bundle name of the target application to set. + * + * @return none + */ +void ExtraParams::SetTargetBundleName(const string &targetBundleName) +{ + targetBundleName_ = targetBundleName; +} + +/** + * @brief Obtains the bundle name of the target application where the ability will be migrated. + * + * @return Returns the bundle name of the target application. + * + * @return none + */ +string ExtraParams::GetTargetBundleName() const +{ + return targetBundleName_; +} +/** + * @brief Sets the description used for device filtering. + * + * @param jsonParams Indicates the device description to set. + * + * @return none + */ +void ExtraParams::SetJsonParams(const string &jsonParams) +{ + jsonParams_ = jsonParams; +} + +/** + * @brief Obtains the custom JSON parameters used as filter conditions. + * + * @param none + * + * @return Returns the custom JSON parameters. + */ +string ExtraParams::GetJsonParams() const +{ + return jsonParams_; +} + +/** + * @brief Sets the custom JSON parameters to be used as filter conditions. + * + * @param description Indicates the custom JSON parameters to set. + * + */ +void ExtraParams::SetDescription(const string &description) +{ + description_ = description; +} + +/** + * @brief Obtains the description used for device filtering. + * + * @param none + * + * @return Returns the description used for device filtering. + */ +string ExtraParams::GetDescription() const +{ + return description_; +} + +/** + * @brief Marshals this {@code ExtraParams} object into a {@link ohos.utils.Parcel} object. + * + * @param parcel Indicates the {@code Parcel} object for marshalling. + * + * @return Returns {@code true} if the marshalling is successful; returns {@code false} otherwise. + */ +bool ExtraParams::Marshalling(Parcel &parcel) const +{ + bool ret = true; + // devType + bool ret1 = parcel.WriteStringVector(devType_); + + // targetBundleName + bool ret2 = parcel.WriteString16(Str8ToStr16(targetBundleName_)); + + // description + bool ret3 = parcel.WriteString16(Str8ToStr16(description_)); + + // jsonParams + bool ret4 = parcel.WriteString16(Str8ToStr16(jsonParams_)); + + ret = (ret1 && ret2 && ret3 && ret4) ? true : false; + return ret; +} + +/** + * @brief Unmarshals this {@code ExtraParams} object from a {@link ohos.utils.Parcel} object. + * + * @param parcel Indicates the {@code Parcel} object for unmarshalling. + * + * @return Returns {@code true} if the unmarshalling is successful; returns {@code false} otherwise. + */ +ExtraParams *ExtraParams::Unmarshalling(Parcel &parcel) +{ + // devType. + std::vector devtype; + parcel.ReadStringVector(&devtype); + + // targetBundleName + string targetBundleName = Str16ToStr8(parcel.ReadString16()); + + // description + string description = Str16ToStr8(parcel.ReadString16()); + + // jsonParams + string jsonParams = Str16ToStr8(parcel.ReadString16()); + + ExtraParams *extraParams = new (std::nothrow) ExtraParams(devtype, targetBundleName, description, jsonParams); + + if (extraParams == nullptr) { + return nullptr; + } + return extraParams; +} +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/content/cpp/src/ohos/aafwk/content/intent.cpp b/tools/frameworks/kits/content/cpp/src/ohos/aafwk/content/intent.cpp new file mode 100644 index 00000000000..70a2979a14f --- /dev/null +++ b/tools/frameworks/kits/content/cpp/src/ohos/aafwk/content/intent.cpp @@ -0,0 +1,904 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ohos/aafwk/content/intent.h" +#include "ohos/aafwk/base/array_wrapper.h" +#include "ohos/aafwk/base/base_object.h" +#include "ohos/aafwk/base/bool_wrapper.h" +#include "ohos/aafwk/base/zchar_wrapper.h" +#include "ohos/aafwk/base/byte_wrapper.h" +#include "ohos/aafwk/base/short_wrapper.h" +#include "ohos/aafwk/base/int_wrapper.h" +#include "ohos/aafwk/base/long_wrapper.h" +#include "ohos/aafwk/base/float_wrapper.h" +#include "ohos/aafwk/base/double_wrapper.h" +#include "ohos/aafwk/base/string_wrapper.h" +#include "ohos/aafwk/base/zchar_wrapper.h" +#include "string_ex.h" + +#include +#include + +#include "parcel.h" + +using OHOS::AppExecFwk::ElementName; + +namespace OHOS { +namespace AAFwk { + +const std::string Intent::ACTION_PLAY("action.system.play"); + +const std::string Intent::ENTITY_HOME("entity.system.home"); +const std::string Intent::ENTITY_VIDEO("entity.system.video"); + +const std::string Intent::OCT_EQUALSTO("075"); // '=' +const std::string Intent::OCT_SEMICOLON("073"); // ';' + +static constexpr int HEX_STRING_BUF_LEN = 12; +static constexpr int HEX_STRING_LEN = 10; // "0xffffffff" + +Intent::Intent() : flags_(0) +{} + +std::string Intent::GetAction() const +{ + return action_; +} + +Intent &Intent::SetAction(const std::string &action) +{ + action_ = action; + return *this; +} + +std::string Intent::GetEntity() const +{ + return entity_; +} + +Intent &Intent::SetEntity(const std::string &entity) +{ + entity_ = entity; + return *this; +} + +unsigned int Intent::GetFlags() const +{ + return flags_; +} + +Intent &Intent::SetFlag(const unsigned int flag) +{ + flags_ = flag; + return *this; +} + +Intent &Intent::AddFlag(const unsigned int flag) +{ + flags_ |= flag; + return *this; +} + +void Intent::RemoveFlags(const unsigned int flag) +{ + flags_ &= ~flag; +} + +ElementName Intent::GetElement() const +{ + return element_; +} + +Intent &Intent::SetElement(const ElementName &element) +{ + element_ = element; + return *this; +} + +bool Intent::ParseFlag(const std::string &content, Intent &intent) +{ + std::string contentLower = LowerStr(content); + std::string prefix = "0x"; + if (!contentLower.empty()) { + if (contentLower.find(prefix) != 0) { + return false; + } + + for (std::size_t i = prefix.length(); i < contentLower.length(); i++) { + if (!isxdigit(contentLower[i])) { + return false; + } + } + int base = 16; // hex string + unsigned int flag = std::stoi(contentLower, nullptr, base); + intent.SetFlag(flag); + } + return true; +} + +std::string Intent::Decode(const std::string &str) +{ + std::string decode; + + for (std::size_t i = 0; i < str.length();) { + if (str[i] == '\\') { + if (++i >= str.length()) { + decode += "\\"; + break; + } + if (str[i] == '\\') { + decode += "\\"; + i++; + } else if (str[i] == '0') { + if (str.compare(i, OCT_EQUALSTO.length(), OCT_EQUALSTO) == 0) { + decode += "="; + i += OCT_EQUALSTO.length(); + } else if (str.compare(i, OCT_SEMICOLON.length(), OCT_SEMICOLON) == 0) { + decode += ";"; + i += OCT_SEMICOLON.length(); + } else { + decode += "\\" + str.substr(i, 1); + i++; + } + } else { + decode += "\\" + str.substr(i, 1); + i++; + } + } else { + decode += str[i]; + i++; + } + } + + return decode; +} + +std::string Intent::Encode(const std::string &str) +{ + std::string encode; + + for (std::size_t i = 0; i < str.length(); i++) { + if (str[i] == '\\') { + encode += "\\\\"; + } else if (str[i] == '=') { + encode += "\\" + OCT_EQUALSTO; + } else if (str[i] == ';') { + encode += "\\" + OCT_SEMICOLON; + } else { + encode += str[i]; + } + } + + return encode; +} + +bool Intent::ParseContent(const std::string &content, std::string &prop, std::string &value) +{ + std::string subString; + std::size_t pos = content.find("="); + if (pos != std::string::npos) { + subString = content.substr(0, pos); + prop = Decode(subString); + subString = content.substr(pos + 1, content.length() - pos - 1); + value = Decode(subString); + return true; + } + return false; +} + +bool Intent::ParseUriInternal(const std::string &content, ElementName &element, Intent &intent) +{ + static constexpr int TYPE_TAG_SIZE = 2; + + std::string prop; + std::string value; + + if (content.empty() || content[0] == '=') { + return true; + } + + if (!ParseContent(content, prop, value)) { + return false; + } + + if (value.empty()) { + return true; + } + + if (prop == "action") { + intent.SetAction(value); + } else if (prop == "entity") { + intent.SetEntity(value); + } else if (prop == "flag") { + if (!ParseFlag(value, intent)) { + return false; + } + } else if (prop == "device") { + element.SetDeviceID(value); + } else if (prop == "bundle") { + element.SetBundleName(value); + } else if (prop == "ability") { + element.SetAbilityName(value); + } else if (prop.length() > TYPE_TAG_SIZE) { + std::string key = prop.substr(TYPE_TAG_SIZE); + if (prop[0] == String::SIGNATURE && prop[1] == '.') { + sptr valueObj = String::Parse(value); + if (valueObj == nullptr) { + return false; + } + intent.parameters_.SetParam(key, valueObj); + } else if (prop[0] == Boolean::SIGNATURE && prop[1] == '.') { + sptr valueObj = Boolean::Parse(value); + if (valueObj == nullptr) { + return false; + } + intent.parameters_.SetParam(key, valueObj); + } else if (prop[0] == Char::SIGNATURE && prop[1] == '.') { + sptr valueObj = Char::Parse(value); + if (valueObj == nullptr) { + return false; + } + intent.parameters_.SetParam(key, valueObj); + } else if (prop[0] == Byte::SIGNATURE && prop[1] == '.') { + sptr valueObj = Byte::Parse(value); + if (valueObj == nullptr) { + return false; + } + intent.parameters_.SetParam(key, valueObj); + } else if (prop[0] == Short::SIGNATURE && prop[1] == '.') { + sptr valueObj = Short::Parse(value); + if (valueObj == nullptr) { + return false; + } + intent.parameters_.SetParam(key, valueObj); + } else if (prop[0] == Integer::SIGNATURE && prop[1] == '.') { + sptr valueObj = Integer::Parse(value); + if (valueObj == nullptr) { + return false; + } + intent.parameters_.SetParam(key, valueObj); + } else if (prop[0] == Long::SIGNATURE && prop[1] == '.') { + sptr valueObj = Long::Parse(value); + if (valueObj == nullptr) { + return false; + } + intent.parameters_.SetParam(key, valueObj); + } else if (prop[0] == Float::SIGNATURE && prop[1] == '.') { + sptr valueObj = Float::Parse(value); + if (valueObj == nullptr) { + return false; + } + intent.parameters_.SetParam(key, valueObj); + } else if (prop[0] == Double::SIGNATURE && prop[1] == '.') { + sptr valueObj = Double::Parse(value); + if (valueObj == nullptr) { + return false; + } + intent.parameters_.SetParam(key, valueObj); + } else if (prop[0] == Array::SIGNATURE && prop[1] == '.') { + sptr valueObj = Array::Parse(value); + if (valueObj == nullptr) { + return false; + } + intent.parameters_.SetParam(key, valueObj); + } + } + + return true; +} + +Intent *Intent::ParseUri(const std::string &uri) +{ + if (uri.length() <= 0) { + return nullptr; + } + + std::string head = "#Intent;"; + std::string end = ";end"; + + if (uri.find(head) != 0) { + return nullptr; + } + + if (uri.rfind(end) != (uri.length() - end.length())) { + return nullptr; + } + + bool ret = true; + std::string content; + std::size_t pos; + std::size_t begin = head.length(); + ElementName element; + Intent *intent = new Intent(); + + pos = uri.find_first_of(";", begin); + do { + if (pos != std::string::npos) { + content = uri.substr(begin, pos - begin); + ret = ParseUriInternal(content, element, *intent); + if (!ret) { + break; + } + begin = pos + 1; + pos = uri.find(";", begin); + if (pos == std::string::npos) { + break; + } + } else { + break; + } + } while (true); + + if (ret) { + intent->SetElement(element); + } else { + delete intent; + intent = nullptr; + } + + return intent; +} + +std::string Intent::ToUri() +{ + std::string uriString = "#Intent;"; + + if (action_.length() > 0) { + uriString += "action=" + Encode(action_) + ";"; + } + + if (entity_.length() > 0) { + uriString += "entity=" + Encode(entity_) + ";"; + } + + if (flags_ != 0) { + uriString += "flag="; + char buf[HEX_STRING_BUF_LEN]; + std::size_t len = snprintf_s(buf, sizeof(buf), HEX_STRING_LEN, "0x%08x", flags_); + if (len == HEX_STRING_LEN) { + std::string flag = buf; + uriString += Encode(flag); + uriString += ";"; + } + } + + std::string device = element_.GetDeviceID(); + if (device.length() > 0) { + uriString += "device=" + Encode(device) + ";"; + } + + std::string bundle = element_.GetBundleName(); + if (bundle.length() > 0) { + uriString += "bundle=" + Encode(bundle) + ";"; + } + + std::string ability = element_.GetAbilityName(); + if (ability.length() > 0) { + uriString += "ability=" + Encode(ability) + ";"; + } + + auto params = parameters_.GetParams(); + auto iter = params.cbegin(); + while (iter != params.cend()) { + sptr o = iter->second; + if (IString::Query(o) != nullptr) { + uriString += String::SIGNATURE; + } else if (IBoolean::Query(o) != nullptr) { + uriString += Boolean::SIGNATURE; + } else if (IChar::Query(o) != nullptr) { + uriString += Char::SIGNATURE; + } else if (IByte::Query(o) != nullptr) { + uriString += Byte::SIGNATURE; + } else if (IShort::Query(o) != nullptr) { + uriString += Short::SIGNATURE; + } else if (IInteger::Query(o) != nullptr) { + uriString += Integer::SIGNATURE; + } else if (ILong::Query(o) != nullptr) { + uriString += Long::SIGNATURE; + } else if (IFloat::Query(o) != nullptr) { + uriString += Float::SIGNATURE; + } else if (IDouble::Query(o) != nullptr) { + uriString += Double::SIGNATURE; + } else if (IArray::Query(o) != nullptr) { + uriString += Array::SIGNATURE; + } + uriString += "." + Encode(iter->first) + "=" + Encode(Object::ToString(*(o.GetRefPtr()))) + ";"; + iter++; + } + + uriString += "end"; + + return uriString; +} + +/* + * Intent format in Parcel. Java side should keep consistent. + * +----------+----+-----+------+-------+----+-----------+---- + * | Action | E1 | Uri | Type | Flags | E2 | Category1 | ... + * +----------+----+-----+------+-------+----+-----------+---- + * ----+-----------+---------+----+---------+----+------------+ + * ... | CategoryN | Package | E3 | Element | E4 | Parameters | + * ----+-----------+---------+----+---------+----+------------+ + * E1: If -1, no Uri after it. + * E2: Category count. If -1, no Category after it. + * E3: if -1, no element after it. + * E4: if -1, no parameters after it. + */ +bool Intent::Marshalling(Parcel &parcel) const +{ + // write action + if (!parcel.WriteString16(Str8ToStr16(action_))) { + return false; + } + + // write entity + if (!parcel.WriteString16(Str8ToStr16(entity_))) { + return false; + } + + // write flags + if (!parcel.WriteUint32(flags_)) { + return false; + } + + // write element + ElementName emptyElement; + if (element_ == emptyElement) { + if (!parcel.WriteInt32(VALUE_NULL)) { + return false; + } + } else { + if (!parcel.WriteInt32(VALUE_OBJECT)) { + return false; + } + if (!parcel.WriteParcelable(&element_)) { + return false; + } + } + + // write parameters + if (parameters_.GetParams().size() == 0) { + if (!parcel.WriteInt32(VALUE_NULL)) { + return false; + } + } else { + if (!parcel.WriteInt32(VALUE_OBJECT)) { + return false; + } + if (!parcel.WriteParcelable(¶meters_)) { + return false; + } + } + + return true; +} + +bool Intent::ReadFromParcel(Parcel &parcel) +{ + // read action + action_ = Str16ToStr8(parcel.ReadString16()); + + // read entity + entity_ = Str16ToStr8(parcel.ReadString16()); + + // read flags + if (!parcel.ReadUint32(flags_)) { + return false; + } + + int empty; + // read element + empty = VALUE_NULL; + if (!parcel.ReadInt32(empty)) { + return false; + } + + if (empty == VALUE_OBJECT) { + auto element = parcel.ReadParcelable(); + if (element != nullptr) { + element_ = *element; + delete element; + } else { + return false; + } + } + + // read parameters + empty = VALUE_NULL; + if (!parcel.ReadInt32(empty)) { + return false; + } + + if (empty == VALUE_OBJECT) { + auto params = parcel.ReadParcelable(); + if (params != nullptr) { + parameters_ = *params; + delete params; + } else { + return false; + } + } + + return true; +} + +Intent *Intent::Unmarshalling(Parcel &parcel) +{ + Intent *intent = new Intent(); + if (intent && !intent->ReadFromParcel(parcel)) { + delete intent; + intent = nullptr; + } + return intent; +} + +bool Intent::HasParameter(const std::string &key) const +{ + return parameters_.HasParam(key); +} + +bool Intent::GetBoolParam(const std::string &key, const bool defaultValue) +{ + auto value = parameters_.GetParam(key); + IBoolean *bo = IBoolean::Query(value); + if (bo != nullptr) { + return Boolean::Unbox(bo); + } + return defaultValue; +} + +Intent &Intent::SetBoolParam(const std::string &key, const bool value) +{ + parameters_.SetParam(key, Boolean::Box(value)); + return *this; +} + +std::vector Intent::GetBoolArrayParam(const std::string &key) +{ + std::vector array; + auto value = parameters_.GetParam(key); + IArray *ao = IArray::Query(value); + if (ao != nullptr && Array::IsBooleanArray(ao)) { + auto func = [&](IInterface *object) { array.push_back(Boolean::Unbox(IBoolean::Query(object))); }; + Array::ForEach(ao, func); + } + return array; +} + +Intent &Intent::SetBoolArrayParam(const std::string &key, const std::vector &value) +{ + long size = value.size(); + sptr ao = new Array(size, g_IID_IBoolean); + for (long i = 0; i < size; i++) { + ao->Set(i, Boolean::Box(value[i])); + } + parameters_.SetParam(key, ao); + return *this; +} + +Intent &Intent::SetCharParam(const std::string &key, const zchar value) +{ + parameters_.SetParam(key, Char::Box(value)); + return *this; +} + +Intent &Intent::SetCharArrayParam(const std::string &key, const std::vector &value) +{ + long size = value.size(); + sptr ao = new Array(size, g_IID_IChar); + for (long i = 0; i < size; i++) { + ao->Set(i, Char::Box(value[i])); + } + parameters_.SetParam(key, ao); + return *this; +} + +zchar Intent::GetCharParam(const std::string &key, const zchar defaultValue) +{ + auto value = parameters_.GetParam(key); + IChar *co = IChar::Query(value); + if (co != nullptr) { + return Char::Unbox(co); + } + return defaultValue; +} + +std::vector Intent::GetCharArrayParam(const std::string &key) +{ + std::vector array; + auto value = parameters_.GetParam(key); + IArray *ao = IArray::Query(value); + if (ao != nullptr && Array::IsCharArray(ao)) { + auto func = [&](IInterface *object) { array.push_back(Char::Unbox(IChar::Query(object))); }; + Array::ForEach(ao, func); + } + return array; +} + +Intent &Intent::SetByteParam(const std::string &key, const byte value) +{ + parameters_.SetParam(key, Byte::Box(value)); + return *this; +} + +Intent &Intent::SetByteArrayParam(const std::string &key, const std::vector &value) +{ + long size = value.size(); + sptr ao = new Array(size, g_IID_IByte); + for (long i = 0; i < size; i++) { + ao->Set(i, Byte::Box(value[i])); + } + parameters_.SetParam(key, ao); + return *this; +} + +byte Intent::GetByteParam(const std::string &key, const byte defaultValue) +{ + auto value = parameters_.GetParam(key); + IByte *bo = IByte::Query(value); + if (bo != nullptr) { + return Byte::Unbox(bo); + } + return defaultValue; +} + +std::vector Intent::GetByteArrayParam(const std::string &key) +{ + std::vector array; + auto value = parameters_.GetParam(key); + IArray *ao = IArray::Query(value); + if (ao != nullptr && Array::IsByteArray(ao)) { + auto func = [&](IInterface *object) { array.push_back(Byte::Unbox(IByte::Query(object))); }; + Array::ForEach(ao, func); + } + return array; +} + +Intent &Intent::SetShortParam(const std::string &key, const short value) +{ + parameters_.SetParam(key, Short::Box(value)); + return *this; +} + +Intent &Intent::SetShortArrayParam(const std::string &key, const std::vector &value) +{ + long size = value.size(); + sptr ao = new Array(size, g_IID_IShort); + for (long i = 0; i < size; i++) { + ao->Set(i, Short::Box(value[i])); + } + parameters_.SetParam(key, ao); + return *this; +} + +short Intent::GetShortParam(const std::string &key, const short defaultValue) +{ + auto value = parameters_.GetParam(key); + IShort *so = IShort::Query(value); + if (so != nullptr) { + return Short::Unbox(so); + } + return defaultValue; +} + +std::vector Intent::GetShortArrayParam(const std::string &key) +{ + std::vector array; + auto value = parameters_.GetParam(key); + IArray *ao = IArray::Query(value); + if (ao != nullptr && Array::IsShortArray(ao)) { + auto func = [&](IInterface *object) { array.push_back(Short::Unbox(IShort::Query(object))); }; + Array::ForEach(ao, func); + } + return array; +} + +Intent &Intent::SetIntParam(const std::string &key, const int value) +{ + parameters_.SetParam(key, Integer::Box(value)); + return *this; +} + +Intent &Intent::SetIntArrayParam(const std::string &key, const std::vector &value) +{ + long size = value.size(); + sptr ao = new Array(size, g_IID_IInteger); + for (long i = 0; i < size; i++) { + ao->Set(i, Integer::Box(value[i])); + } + parameters_.SetParam(key, ao); + return *this; +} + +int Intent::GetIntParam(const std::string &key, const int defaultValue) +{ + auto value = parameters_.GetParam(key); + IInteger *io = IInteger::Query(value); + if (io != nullptr) { + return Integer::Unbox(io); + } + return defaultValue; +} + +std::vector Intent::GetIntArrayParam(const std::string &key) +{ + std::vector array; + auto value = parameters_.GetParam(key); + IArray *ao = IArray::Query(value); + if (ao != nullptr && Array::IsIntegerArray(ao)) { + auto func = [&](IInterface *object) { array.push_back(Integer::Unbox(IInteger::Query(object))); }; + Array::ForEach(ao, func); + } + return array; +} + +long Intent::GetLongParam(const std::string &key, const long defaultValue) +{ + auto value = parameters_.GetParam(key); + ILong *lo = ILong::Query(value); + if (lo != nullptr) { + return Long::Unbox(lo); + } + return defaultValue; +} + +Intent &Intent::SetLongParam(const std::string &key, const long value) +{ + parameters_.SetParam(key, Long::Box(value)); + return *this; +} + +std::vector Intent::GetLongArrayParam(const std::string &key) +{ + std::vector array; + auto value = parameters_.GetParam(key); + IArray *ao = IArray::Query(value); + if (ao != nullptr && Array::IsLongArray(ao)) { + auto func = [&](IInterface *object) { array.push_back(Long::Unbox(ILong::Query(object))); }; + Array::ForEach(ao, func); + } + return array; +} + +Intent &Intent::SetLongArrayParam(const std::string &key, const std::vector &value) +{ + long size = value.size(); + sptr ao = new Array(size, g_IID_ILong); + for (long i = 0; i < size; i++) { + ao->Set(i, Long::Box(value[i])); + } + parameters_.SetParam(key, ao); + return *this; +} + +float Intent::GetFloatParam(const std::string &key, const float defaultValue) +{ + auto value = parameters_.GetParam(key); + IFloat *of = IFloat::Query(value); + if (of != nullptr) { + return Float::Unbox(of); + } + return defaultValue; +} + +Intent &Intent::SetFloatParam(const std::string &key, const float value) +{ + parameters_.SetParam(key, Float::Box(value)); + return *this; +} + +std::vector Intent::GetFloatArrayParam(const std::string &key) +{ + std::vector array; + auto value = parameters_.GetParam(key); + IArray *ao = IArray::Query(value); + if (ao != nullptr && Array::IsFloatArray(ao)) { + auto func = [&](IInterface *object) { array.push_back(Float::Unbox(IFloat::Query(object))); }; + Array::ForEach(ao, func); + } + return array; +} + +Intent &Intent::SetFloatArrayParam(const std::string &key, const std::vector &value) +{ + long size = value.size(); + sptr ao = new Array(size, g_IID_IFloat); + for (long i = 0; i < size; i++) { + ao->Set(i, Float::Box(value[i])); + } + parameters_.SetParam(key, ao); + return *this; +} + +double Intent::GetDoubleParam(const std::string &key, const double defaultValue) +{ + auto value = parameters_.GetParam(key); + IDouble *dbo = IDouble::Query(value); + if (dbo != nullptr) { + return Double::Unbox(dbo); + } + return defaultValue; +} + +Intent &Intent::SetDoubleParam(const std::string &key, const double value) +{ + parameters_.SetParam(key, Double::Box(value)); + return *this; +} + +std::vector Intent::GetDoubleArrayParam(const std::string &key) +{ + std::vector array; + auto value = parameters_.GetParam(key); + IArray *ao = IArray::Query(value); + if (ao != nullptr && Array::IsDoubleArray(ao)) { + auto func = [&](IInterface *object) { array.push_back(Double::Unbox(IDouble::Query(object))); }; + Array::ForEach(ao, func); + } + return array; +} + +Intent &Intent::SetDoubleArrayParam(const std::string &key, const std::vector &value) +{ + long size = value.size(); + sptr ao = new Array(size, g_IID_IDouble); + for (long i = 0; i < size; i++) { + ao->Set(i, Double::Box(value[i])); + } + parameters_.SetParam(key, ao); + return *this; +} + +std::string Intent::GetStringParam(const std::string &key) +{ + auto value = parameters_.GetParam(key); + IString *so = IString::Query(value); + if (so != nullptr) { + return String::Unbox(so); + } + return std::string(); +} + +Intent &Intent::SetStringParam(const std::string &key, const std::string &value) +{ + parameters_.SetParam(key, String::Box(value)); + return *this; +} + +std::vector Intent::GetStringArrayParam(const std::string &key) +{ + std::vector array; + auto value = parameters_.GetParam(key); + IArray *ao = IArray::Query(value); + if (ao != nullptr && Array::IsStringArray(ao)) { + auto func = [&](IInterface *object) { array.push_back(String::Unbox(IString::Query(object))); }; + Array::ForEach(ao, func); + } + return array; +} + +Intent &Intent::SetStringArrayParam(const std::string &key, const std::vector &value) +{ + long size = value.size(); + sptr ao = new Array(size, g_IID_IString); + for (long i = 0; i < size; i++) { + ao->Set(i, String::Box(value[i])); + } + parameters_.SetParam(key, ao); + return *this; +} + +} // namespace AAFwk +} // namespace OHOS diff --git a/tools/frameworks/kits/content/cpp/src/ohos/aafwk/content/intent_filter.cpp b/tools/frameworks/kits/content/cpp/src/ohos/aafwk/content/intent_filter.cpp new file mode 100644 index 00000000000..17f64fcd3b9 --- /dev/null +++ b/tools/frameworks/kits/content/cpp/src/ohos/aafwk/content/intent_filter.cpp @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ohos/aafwk/content/intent_filter.h" + +#include "string_ex.h" +#include "ohos/aafwk/content/intent.h" + +namespace OHOS { +namespace AAFwk { + +IntentFilter::IntentFilter() +{} + +std::string IntentFilter::GetEntity() const +{ + return entity_; +} + +void IntentFilter::SetEntity(const std::string &entity) +{ + entity_ = entity; +} + +void IntentFilter::AddAction(const std::string &action) +{ + auto it = std::find(actions_.cbegin(), actions_.cend(), action); + if (it == actions_.cend()) { + actions_.push_back(action); + } +} + +int IntentFilter::CountAction() const +{ + return actions_.size(); +} + +std::string IntentFilter::GetAction(int index) const +{ + std::string action; + if (index < static_cast(actions_.size())) { + action = actions_[index]; + } + return action; +} + +void IntentFilter::RemoveAction(const std::string &action) +{ + auto it = std::find(actions_.cbegin(), actions_.cend(), action); + if (it != actions_.cend()) { + actions_.erase(it); + } +} + +bool IntentFilter::HasAction(const std::string &action) const +{ + return std::find(actions_.cbegin(), actions_.cend(), action) != actions_.cend(); +} + +bool IntentFilter::Marshalling(Parcel &parcel) const +{ + // write entity + if (!parcel.WriteString16(Str8ToStr16(entity_))) { + return false; + } + + // write actions + std::vector actionU16; + for (std::vector::size_type i = 0; i < actions_.size(); i++) { + actionU16.push_back(Str8ToStr16(actions_[i])); + } + + if (!parcel.WriteString16Vector(actionU16)) { + return false; + } + + return true; +} + +bool IntentFilter::ReadFromParcel(Parcel &parcel) +{ + // read entity + entity_ = Str16ToStr8(parcel.ReadString16()); + + // read actions + std::vector actionU16; + if (!parcel.ReadString16Vector(&actionU16)) { + return false; + } + + actions_.clear(); + for (std::vector::size_type i = 0; i < actionU16.size(); i++) { + actions_.push_back(Str16ToStr8(actionU16[i])); + } + + return true; +} + +IntentFilter *IntentFilter::Unmarshalling(Parcel &parcel) +{ + IntentFilter *filter = new (std::nothrow) IntentFilter(); + if (filter && !filter->ReadFromParcel(parcel)) { + delete filter; + filter = nullptr; + } + return filter; +} + +bool IntentFilter::MatchAction(const std::string &action) const +{ + return HasAction(action); +} + +bool IntentFilter::MatchEntity(const std::string &entity) const +{ + return entity_ == entity; +} + +bool IntentFilter::Match(const Intent &intent) const +{ + return MatchAction(intent.GetAction()) && MatchEntity(intent.GetEntity()); +} + +} // namespace AAFwk +} // namespace OHOS diff --git a/tools/frameworks/kits/content/cpp/src/ohos/aafwk/content/intent_params.cpp b/tools/frameworks/kits/content/cpp/src/ohos/aafwk/content/intent_params.cpp new file mode 100755 index 00000000000..97f2961efef --- /dev/null +++ b/tools/frameworks/kits/content/cpp/src/ohos/aafwk/content/intent_params.cpp @@ -0,0 +1,475 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ohos/aafwk/content/intent_params.h" + +#include "ohos/aafwk/base/array_wrapper.h" +#include "ohos/aafwk/base/base_object.h" +#include "ohos/aafwk/base/bool_wrapper.h" +#include "ohos/aafwk/base/byte_wrapper.h" +#include "ohos/aafwk/base/short_wrapper.h" +#include "ohos/aafwk/base/int_wrapper.h" +#include "ohos/aafwk/base/long_wrapper.h" +#include "ohos/aafwk/base/float_wrapper.h" +#include "ohos/aafwk/base/double_wrapper.h" +#include "ohos/aafwk/base/string_wrapper.h" +#include "ohos/aafwk/base/zchar_wrapper.h" + +#include "parcel.h" +#include "string_ex.h" + +namespace OHOS { +namespace AAFwk { + +void IntentParams::SetParam(const std::string &key, IInterface *value) +{ + params_[key] = value; +} + +sptr IntentParams::GetParam(const std::string &key) const +{ + auto it = params_.find(key); + if (it == params_.cend()) { + return nullptr; + } + return it->second; +} + +const std::map> &IntentParams::GetParams() const +{ + return params_; +} + +bool IntentParams::HasParam(const std::string &key) const +{ + return params_.count(key) > 0; +} + +template +static void FillArray(IArray *ao, std::vector &array) +{ + auto func = [&](IInterface *object) { array.push_back(T2::Unbox(T3::Query(object))); }; + Array::ForEach(ao, func); +} + +bool IntentParams::WriteArrayToParcel(Parcel &parcel, IArray *ao) const +{ + if (Array::IsStringArray(ao)) { + std::vector array; + auto func = [&](IInterface *object) { + std::string s = String::Unbox(IString::Query(object)); + array.push_back(Str8ToStr16(s)); + }; + Array::ForEach(ao, func); + if (!parcel.WriteInt32(VALUE_TYPE_STRINGARRAY)) { + return false; + } + if (!parcel.WriteString16Vector(array)) { + return false; + } + } else if (Array::IsBooleanArray(ao)) { + std::vector array; + FillArray(ao, array); + if (!parcel.WriteInt32(VALUE_TYPE_BOOLEANARRAY)) { + return false; + } + if (!parcel.WriteInt8Vector(array)) { + return false; + } + } else if (Array::IsByteArray(ao)) { + std::vector array; + FillArray(ao, array); + if (!parcel.WriteInt32(VALUE_TYPE_BYTEARRAY)) { + return false; + } + if (!parcel.WriteInt8Vector(array)) { + return false; + } + } else if (Array::IsCharArray(ao)) { + std::vector array; + FillArray(ao, array); + if (!parcel.WriteInt32(VALUE_TYPE_CHARARRAY)) { + return false; + } + if (!parcel.WriteInt32Vector(array)) { + return false; + } + } else if (Array::IsShortArray(ao)) { + std::vector array; + FillArray(ao, array); + if (!parcel.WriteInt32(VALUE_TYPE_SHORTARRAY)) { + return false; + } + if (!parcel.WriteInt16Vector(array)) { + return false; + } + } else if (Array::IsIntegerArray(ao)) { + std::vector array; + FillArray(ao, array); + if (!parcel.WriteInt32(VALUE_TYPE_INTARRAY)) { + return false; + } + if (!parcel.WriteInt32Vector(array)) { + return false; + } + } else if (Array::IsLongArray(ao)) { + std::vector array; + FillArray(ao, array); + if (!parcel.WriteInt32(VALUE_TYPE_LONGARRAY)) { + return false; + } + if (!parcel.WriteInt64Vector(array)) { + return false; + } + } else if (Array::IsFloatArray(ao)) { + std::vector array; + FillArray(ao, array); + if (!parcel.WriteInt32(VALUE_TYPE_FLOATARRAY)) { + return false; + } + if (!parcel.WriteFloatVector(array)) { + return false; + } + } else if (Array::IsDoubleArray(ao)) { + std::vector array; + FillArray(ao, array); + if (!parcel.WriteInt32(VALUE_TYPE_DOUBLEARRAY)) { + return false; + } + if (!parcel.WriteDoubleVector(array)) { + return false; + } + } + + return true; +} + +bool IntentParams::Marshalling(Parcel &parcel) const +{ + size_t size = params_.size(); + + if (!parcel.WriteInt32(size)) { + return false; + } + + auto iter = params_.cbegin(); + while (iter != params_.cend()) { + std::string key = iter->first; + sptr o = iter->second; + if (!parcel.WriteString16(Str8ToStr16(key))) { + return false; + } + if (IString::Query(o) != nullptr) { + std::string value = String::Unbox(IString::Query(o)); + if (!parcel.WriteInt32(VALUE_TYPE_STRING)) { + return false; + } + if (!parcel.WriteString16(Str8ToStr16(value))) { + return false; + } + } else if (IBoolean::Query(o) != nullptr) { + bool value = Boolean::Unbox(IBoolean::Query(o)); + if (!parcel.WriteInt32(VALUE_TYPE_BOOLEAN)) { + return false; + } + if (!parcel.WriteInt8(value)) { + return false; + } + } else if (IByte::Query(o) != nullptr) { + byte value = Byte::Unbox(IByte::Query(o)); + if (!parcel.WriteInt32(VALUE_TYPE_BYTE)) { + return false; + } + if (!parcel.WriteInt8(value)) { + return false; + } + } else if (IChar::Query(o) != nullptr) { + zchar value = Char::Unbox(IChar::Query(o)); + if (!parcel.WriteInt32(VALUE_TYPE_CHAR)) { + return false; + } + if (!parcel.WriteInt32(value)) { + return false; + } + } else if (IShort::Query(o) != nullptr) { + short value = Short::Unbox(IShort::Query(o)); + if (!parcel.WriteInt32(VALUE_TYPE_SHORT)) { + return false; + } + if (!parcel.WriteInt16(value)) { + return false; + } + } else if (IInteger::Query(o) != nullptr) { + int value = Integer::Unbox(IInteger::Query(o)); + if (!parcel.WriteInt32(VALUE_TYPE_INT)) { + return false; + } + if (!parcel.WriteInt32(value)) { + return false; + } + } else if (ILong::Query(o) != nullptr) { + long value = Long::Unbox(ILong::Query(o)); + if (!parcel.WriteInt32(VALUE_TYPE_LONG)) { + return false; + } + if (!parcel.WriteInt64(value)) { + return false; + } + } else if (IFloat::Query(o) != nullptr) { + float value = Float::Unbox(IFloat::Query(o)); + if (!parcel.WriteInt32(VALUE_TYPE_FLOAT)) { + return false; + } + if (!parcel.WriteFloat(value)) { + return false; + } + } else if (IDouble::Query(o) != nullptr) { + double value = Double::Unbox(IDouble::Query(o)); + if (!parcel.WriteInt32(VALUE_TYPE_DOUBLE)) { + return false; + } + if (!parcel.WriteDouble(value)) { + return false; + } + } else { + IArray *ao = IArray::Query(o); + if (ao != nullptr && !WriteArrayToParcel(parcel, ao)) { + return false; + } + } + iter++; + } + + return true; +} + +template +static void SetArray(const InterfaceID &id, const std::vector &value, sptr &ao) +{ + typename std::vector::size_type size = value.size(); + ao = new (std::nothrow) Array(size, id); + for (typename std::vector::size_type i = 0; i < size; i++) { + ao->Set(i, T2::Box(value[i])); + } +} + +bool IntentParams::ReadArrayToParcel(Parcel &parcel, int type, sptr &ao) +{ + switch (type) { + case VALUE_TYPE_STRINGARRAY: { + std::vector value; + if (!parcel.ReadString16Vector(&value)) { + return false; + } + std::vector::size_type size = value.size(); + ao = new (std::nothrow) Array(size, g_IID_IString); + for (std::vector::size_type i = 0; i < size; i++) { + ao->Set(i, String::Box(Str16ToStr8(value[i]))); + } + break; + } + case VALUE_TYPE_BOOLEANARRAY: { + std::vector value; + if (!parcel.ReadInt8Vector(&value)) { + return false; + } + SetArray(g_IID_IBoolean, value, ao); + break; + } + case VALUE_TYPE_BYTEARRAY: { + std::vector value; + if (!parcel.ReadInt8Vector(&value)) { + return false; + } + SetArray(g_IID_IByte, value, ao); + break; + } + case VALUE_TYPE_CHARARRAY: { + std::vector value; + if (!parcel.ReadInt32Vector(&value)) { + return false; + } + SetArray(g_IID_IChar, value, ao); + break; + } + case VALUE_TYPE_SHORTARRAY: { + std::vector value; + if (!parcel.ReadInt16Vector(&value)) { + return false; + } + SetArray(g_IID_IShort, value, ao); + break; + } + case VALUE_TYPE_INTARRAY: { + std::vector value; + if (!parcel.ReadInt32Vector(&value)) { + return false; + } + SetArray(g_IID_IInteger, value, ao); + break; + } + case VALUE_TYPE_LONGARRAY: { + std::vector value; + if (!parcel.ReadInt64Vector(&value)) { + return false; + } + SetArray(g_IID_ILong, value, ao); + break; + } + case VALUE_TYPE_FLOATARRAY: { + std::vector value; + if (!parcel.ReadFloatVector(&value)) { + return false; + } + SetArray(g_IID_IFloat, value, ao); + break; + } + case VALUE_TYPE_DOUBLEARRAY: { + std::vector value; + if (!parcel.ReadDoubleVector(&value)) { + return false; + } + SetArray(g_IID_IDouble, value, ao); + break; + } + default: + // ignore + ; + } + + return true; +} + +bool IntentParams::ReadFromParcel(Parcel &parcel) +{ + int32_t size; + + if (!parcel.ReadInt32(size)) { + return false; + } + + for (int32_t i = 0; i < size; i++) { + std::u16string key; + key = parcel.ReadString16(); + + sptr intf = nullptr; + int type; + if (!parcel.ReadInt32(type)) { + return false; + } + + switch (type) { + case VALUE_TYPE_STRING: { + std::u16string value = parcel.ReadString16(); + intf = String::Box(Str16ToStr8(value)); + break; + } + case VALUE_TYPE_BOOLEAN: { + int8_t value; + if (!parcel.ReadInt8(value)) { + return false; + } + intf = Boolean::Box(value); + break; + } + case VALUE_TYPE_BYTE: { + int8_t value; + if (!parcel.ReadInt8(value)) { + return false; + } + intf = Byte::Box(value); + break; + } + case VALUE_TYPE_CHAR: { + int32_t value; + if (!parcel.ReadInt32(value)) { + return false; + } + intf = Char::Box(value); + break; + } + case VALUE_TYPE_SHORT: { + short value; + if (!parcel.ReadInt16(value)) { + return false; + } + intf = Short::Box(value); + break; + } + case VALUE_TYPE_INT: { + int value; + if (!parcel.ReadInt32(value)) { + return false; + } + intf = Integer::Box(value); + break; + } + case VALUE_TYPE_LONG: { + int64_t value; + if (!parcel.ReadInt64(value)) { + return false; + } + intf = Long::Box(value); + break; + } + case VALUE_TYPE_FLOAT: { + float value; + if (!parcel.ReadFloat(value)) { + return false; + } + intf = Float::Box(value); + break; + } + case VALUE_TYPE_DOUBLE: { + double value; + if (!parcel.ReadDouble(value)) { + return false; + } + intf = Double::Box(value); + break; + } + case VALUE_TYPE_NULL: + break; + default: { + // handle array + sptr ao = nullptr; + if (!ReadArrayToParcel(parcel, type, ao)) { + return false; + } + intf = ao; + break; + } + } + + if (intf) { + SetParam(Str16ToStr8(key), intf); + } + } + + return true; +} + +IntentParams *IntentParams::Unmarshalling(Parcel &parcel) +{ + IntentParams *intentParams = new (std::nothrow) IntentParams(); + if (intentParams && !intentParams->ReadFromParcel(parcel)) { + delete intentParams; + intentParams = nullptr; + } + return intentParams; +} + +} // namespace AAFwk +} // namespace OHOS diff --git a/tools/frameworks/kits/content/cpp/src/ohos/aafwk/content/operation.cpp b/tools/frameworks/kits/content/cpp/src/ohos/aafwk/content/operation.cpp new file mode 100755 index 00000000000..5b8c2f57e2c --- /dev/null +++ b/tools/frameworks/kits/content/cpp/src/ohos/aafwk/content/operation.cpp @@ -0,0 +1,393 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "operation.h" +#include "operation_builder.h" +#include "parcel_macro.h" +using namespace OHOS::AppExecFwk; +namespace OHOS { +namespace AAFwk { +Operation::Operation() : flags_(0), uri_("") +{ + entities_.clear(); +} + +Operation::Operation(const Operation &other) : flags_(0), uri_(other.uri_.ToString()) +{ + flags_ = other.flags_; + action_ = other.action_; + deviceId_ = other.deviceId_; + entities_ = other.entities_; + bundleName_ = other.bundleName_; + abilityName_ = other.abilityName_; + entities_.clear(); +} + +Operation::~Operation() +{} + +/** + * @description: Obtains the value of the abilityName attribute included in this Operation. + * @return Returns the ability name included in this Operation. + */ +std::string Operation::GetAbilityName() const +{ + return abilityName_; +} + +/** + * @description: Obtains the value of the action attribute included in this Operation. + * @return Returns the action included in this Operation. + */ +std::string Operation::GetAction() const +{ + return action_; +} +/** + * @description: Sets a bundle name in this Want. + * If a bundle name is specified in a Want, the Want will match only + * the abilities in the specified bundle. You cannot use this method and + * setPicker(ohos.aafwk.content.Want) on the same Want. + * @param bundleName Indicates the bundle name to set. + * @return Returns a Want object containing the specified bundle name. + */ +void Operation::SetBundleName(const std::string &bundleName) +{ + bundleName_ = bundleName; +} +/** + * @description: Obtains the value of the bundleName attribute included in this Operation. + * @return Returns the bundle name included in this Operation. + */ +std::string Operation::GetBundleName() const +{ + return bundleName_; +} + +/** + * @description: Obtains the value of the deviceId attribute included in this Operation. + * @return Returns the device ID included in this Operation. + */ +std::string Operation::GetDeviceId() const +{ + return deviceId_; +} + +/** + * @description: Obtains the value of the entities attribute included in this Operation. + * @return Returns the entities included in this Operation. + */ +const std::vector &Operation::GetEntities() const +{ + return entities_; +} +/** + * @description: Adds the description of an entity to a Want + * @param entity Indicates the entity description to add + * @return Returns this Want object containing the entity. + */ +void Operation::AddEntity(const std::string &entity) +{ + if (!HasEntity(entity)) { + entities_.emplace_back(entity); + } +} + +/** + * @description: Removes the description of an entity from a Want + * @param entity Indicates the entity description to remove. + * @return void + */ +void Operation::RemoveEntity(const std::string &entity) +{ + if (!entities_.empty()) { + auto it = std::find(entities_.begin(), entities_.end(), entity); + if (it != entities_.end()) { + entities_.erase(it); + } + } +} + +/** + * @description: Checks whether a Want contains the given entity + * @param entity Indicates the entity to check + * @return Returns true if the given entity is contained; returns false otherwise + */ +bool Operation::HasEntity(const std::string &entity) const +{ + return std::find(entities_.begin(), entities_.end(), entity) != entities_.end(); +} + +/** + * @description: Obtains the number of entities in a Want + * @return Returns the entity quantity + */ +int Operation::CountEntities() const +{ + return entities_.size(); +} +/** + * @description: Obtains the value of the flags attribute included in this Operation. + * @return Returns the flags included in this Operation. + */ +unsigned int Operation::GetFlags() const +{ + return flags_; +} + +/** + * @description: Sets a flag in a Want. + * @param flags Indicates the flag to set. + * @return Returns this Want object containing the flag. + */ +void Operation::SetFlags(unsigned int flags) +{ + flags_ = flags; +} +/** + * @description: Adds a flag to a Want. + * @param flags Indicates the flag to add. + * @return Returns the Want object with the added flag. + */ +void Operation::AddFlags(unsigned int flags) +{ + flags_ |= flags; +} + +/** + * @description: Removes the description of a flag from a Want. + * @param flags Indicates the flag to remove. + * @return Removes the description of a flag from a Want. + */ +void Operation::RemoveFlags(unsigned int flags) +{ + flags_ &= ~flags; +} + +/** + * @description: Obtains the value of the uri attribute included in this Operation. + * @return Returns the URI included in this Operation. + */ +Uri Operation::GetUri() const +{ + return uri_; +} + +bool Operation::operator==(const Operation &other) const +{ + if (abilityName_ != other.abilityName_) { + return false; + } + if (action_ != other.action_) { + return false; + } + if (bundleName_ != other.bundleName_) { + return false; + } + if (deviceId_ != other.deviceId_) { + return false; + } + long entitiesCount = entities_.size(); + long otherEntitiesCount = other.entities_.size(); + if (entitiesCount != otherEntitiesCount) { + return false; + } else { + for (long i = 0; i < entitiesCount; i++) { + if (entities_[i] != other.entities_[i]) { + return false; + } + } + } + if (flags_ != other.flags_) { + return false; + } + if (uri_.ToString() != other.uri_.ToString()) { + return false; + } + + return true; +} + +Operation &Operation::operator=(const Operation &other) +{ + if (this != &other) { + uri_ = other.uri_; + flags_ = other.flags_; + action_ = other.action_; + deviceId_ = other.deviceId_; + entities_ = other.entities_; + bundleName_ = other.bundleName_; + abilityName_ = other.abilityName_; + } + return *this; +} + +bool Operation::Marshalling(Parcel &parcel) const +{ + WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(String16, parcel, Str8ToStr16(abilityName_)); + WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(String16, parcel, Str8ToStr16(action_)); + WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(String16, parcel, Str8ToStr16(bundleName_)); + WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(String16, parcel, Str8ToStr16(deviceId_)); + WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(StringVector, parcel, entities_); + WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(Uint32, parcel, flags_); + + Uri uri(""); + if (uri_ == uri) { + WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(Int32, parcel, VALUE_NULL); + } else { + if (!parcel.WriteInt32(VALUE_OBJECT)) { + return false; + } + if (!parcel.WriteParcelable(&uri_)) { + return false; + } + } + + return true; +} + +Operation *Operation::Unmarshalling(Parcel &parcel) +{ + Operation *operation = new (std::nothrow) Operation(); + if (operation != nullptr && !operation->ReadFromParcel(parcel)) { + delete operation; + operation = nullptr; + } + + return operation; +} + +bool Operation::ReadFromParcel(Parcel &parcel) +{ + std::u16string readString16; + READ_PARCEL_AND_RETURN_FALSE_IF_FAIL(String16, parcel, readString16); + abilityName_ = Str16ToStr8(readString16); + readString16.clear(); + + READ_PARCEL_AND_RETURN_FALSE_IF_FAIL(String16, parcel, readString16); + action_ = Str16ToStr8(readString16); + readString16.clear(); + + READ_PARCEL_AND_RETURN_FALSE_IF_FAIL(String16, parcel, readString16); + bundleName_ = Str16ToStr8(readString16); + readString16.clear(); + + READ_PARCEL_AND_RETURN_FALSE_IF_FAIL(String16, parcel, readString16); + deviceId_ = Str16ToStr8(readString16); + readString16.clear(); + + READ_PARCEL_AND_RETURN_FALSE_IF_FAIL(StringVector, parcel, &entities_); + READ_PARCEL_AND_RETURN_FALSE_IF_FAIL(Uint32, parcel, flags_); + + // uri_ + int32_t empty = VALUE_NULL; + if (!parcel.ReadInt32(empty)) { + return false; + } + + if (empty == VALUE_OBJECT) { + auto uri = parcel.ReadParcelable(); + if (uri != nullptr) { + uri_ = *uri; + delete uri; + uri = nullptr; + } else { + return false; + } + } + + return true; +} + +/** + * @description: Sets a uri in this operation. + * @param uri Indicates uri object to set. + * @return - + */ +void Operation::SetUri(const Uri &uri) +{ + uri_ = uri; +} + +/** + * @description: Returns a uri in this operation. + * @param uri Indicates uri object to set. + * @return Returns a uri in this operation. + */ +Uri &Operation::GetUri(const Uri &uri) +{ + return uri_; +} + +/** + * @description: Sets the value of the abilityName attribute included in this Operation. + * @param abilityname + * @return - + */ +void Operation::SetAbilityName(const std::string &abilityname) +{ + abilityName_ = abilityname; +} +/** + * @description: Sets the value of the deviceId attribute included in this Operation. + * @param deviceid + * @return - + */ +void Operation::SetDeviceId(const std::string &deviceid) +{ + deviceId_ = deviceid; +} + +/** + * @description: Sets the value of the action attribute included in this Operation. + * @param deviceid Indicates deviceid object to set. + * @return - + */ +void Operation::SetAction(const std::string &action) +{ + action_ = action; +} + +/** + * @description: Sets the entities of this Operation. + * @param entities Indicates entities to set. + * @return - + */ +void Operation::SetEntities(const std::vector &entities) +{ + entities_.clear(); + entities_ = entities; +} + +void Operation::DumpInfo(int level) const +{ + APP_LOGI("=======Operation::DumpInfo level: %{public}d start=============", level); + + APP_LOGI("===Operation::abilityName_ %{public}s =============", abilityName_.c_str()); + APP_LOGI("===Operation::action_ %{public}s =============", action_.c_str()); + APP_LOGI("===Operation::bundleName_ %{public}s =============", bundleName_.c_str()); + APP_LOGI("===Operation::deviceId_ %{public}s =============", deviceId_.c_str()); + long entities_count = entities_.size(); + APP_LOGI("===Operation::entities_: count %{public}ld =============", entities_count); + for (long i = 0; i < entities_count; i++) { + APP_LOGI("=Operation::entities_[%{public}ld]:%{public}s =============", i, entities_[i].c_str()); + } + APP_LOGI("===Operation::flags_ %{public}ud =============", flags_); + APP_LOGI("===Operation::uri_ %{public}s =============", uri_.ToString().c_str()); + + APP_LOGI("=======Operation::DumpInfo level: %{public}d end=============", level); +} +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/content/cpp/src/ohos/aafwk/content/operation_builder.cpp b/tools/frameworks/kits/content/cpp/src/ohos/aafwk/content/operation_builder.cpp new file mode 100644 index 00000000000..9c689f65fa9 --- /dev/null +++ b/tools/frameworks/kits/content/cpp/src/ohos/aafwk/content/operation_builder.cpp @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "operation_builder.h" +#include "operation.h" + +namespace OHOS { +namespace AAFwk { + +OperationBuilder::OperationBuilder() + : abilityName_(""), action_(""), bundleName_(""), deviceId_(""), flags_(0), uri_("") +{ + entities_.clear(); +} + +OperationBuilder::~OperationBuilder() +{} + +/** + * @description: Sets a AbilityName in an OperationBuilder. + * @return Returns this OperationBuilder object containing the AbilityName. + */ +OperationBuilder &OperationBuilder::WithAbilityName(const std::string &abilityName) +{ + abilityName_ = abilityName; + return *this; +} + +/** + * @description: Sets a BundleName in an OperationBuilder. + * @return Returns this OperationBuilder object containing the BundleName. + */ +OperationBuilder &OperationBuilder::WithBundleName(const std::string &bundleName) +{ + bundleName_ = bundleName; + return *this; +} + +/** + * @description: Sets a DeviceId in an OperationBuilder. + * @return Returns this OperationBuilder object containing the DeviceId. + */ +OperationBuilder &OperationBuilder::WithDeviceId(const std::string &deviceID) +{ + deviceId_ = deviceID; + return *this; +} + +/** + * @description: Sets a Action in an OperationBuilder. + * @return Returns this OperationBuilder object containing the Action. + */ +OperationBuilder &OperationBuilder::WithAction(const std::string &action) +{ + action_ = action; + return *this; +} + +/** + * @description: Sets a Entities in an OperationBuilder. + * @return Returns this OperationBuilder object containing the Entities. + */ +OperationBuilder &OperationBuilder::WithEntities(const std::vector &entities) +{ + entities_ = entities; + return *this; +} + +/** + * @description: Sets a Flags in an OperationBuilder. + * @return Returns this OperationBuilder object containing the Flags. + */ +OperationBuilder &OperationBuilder::WithFlags(unsigned int flags) +{ + flags_ = flags; + return *this; +} + +/** + * @description: Sets a Uri in an OperationBuilder. + * @return Returns this OperationBuilder object containing the Uri. + */ +OperationBuilder &OperationBuilder::WithUri(const Uri &uri) +{ + uri_ = uri; + return *this; +} + +std::shared_ptr OperationBuilder::build() +{ + std::shared_ptr operation = std::make_shared(); + operation->abilityName_ = abilityName_; + operation->bundleName_ = bundleName_; + operation->deviceId_ = deviceId_; + operation->action_ = action_; + operation->entities_ = entities_; + operation->flags_ = flags_; + operation->uri_ = uri_; + + return operation; +} + +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/content/cpp/src/ohos/aafwk/content/pac_map.cpp b/tools/frameworks/kits/content/cpp/src/ohos/aafwk/content/pac_map.cpp new file mode 100755 index 00000000000..e71d2bbce63 --- /dev/null +++ b/tools/frameworks/kits/content/cpp/src/ohos/aafwk/content/pac_map.cpp @@ -0,0 +1,1783 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "pac_map.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include "parcel_macro.h" +#include "string_ex.h" +#include "ohos/aafwk/base/array_wrapper.h" +#include "ohos/aafwk/base/bool_wrapper.h" +#include "ohos/aafwk/base/zchar_wrapper.h" +#include "ohos/aafwk/base/byte_wrapper.h" +#include "ohos/aafwk/base/short_wrapper.h" +#include "ohos/aafwk/base/int_wrapper.h" +#include "ohos/aafwk/base/long_wrapper.h" + +#include "ohos/aafwk/base/float_wrapper.h" +#include "ohos/aafwk/base/double_wrapper.h" +#include "ohos/aafwk/base/string_wrapper.h" +#include "ohos/aafwk/base/zchar_wrapper.h" +#include "ohos/aafwk/base/user_object_base.h" +#include "ohos/aafwk/base/user_object_wrapper.h" + +using IUserObject = OHOS::AAFwk::IUserObject; +using InterfaceID = OHOS::AAFwk::InterfaceID; +using Short = OHOS::AAFwk::Short; +using Integer = OHOS::AAFwk::Integer; +using Long = OHOS::AAFwk::Long; +using Boolean = OHOS::AAFwk::Boolean; +using Char = OHOS::AAFwk::Char; +using Byte = OHOS::AAFwk::Byte; +using Float = OHOS::AAFwk::Float; +using Double = OHOS::AAFwk::Double; +using String = OHOS::AAFwk::String; + +namespace OHOS { +namespace AppExecFwk { +namespace { +const int FLOAT_PRECISION = 7; +const int DOUBLE_PRECISION = 17; +const std::regex NUMBER_REGEX("^[-+]?([0-9]+)([.]([0-9]+))?$"); +}; // namespace + +#define PAC_MAP_PUT_VALUE(id, iid, key, value, mapList) \ + do { \ + RemoveData(mapList, key); \ + sptr val = id::Box(value); \ + (mapList).emplace(key, val); \ + } while (0); + +#define PAC_MAP_GET_VALUE(id, key, value, mapList, defaultValue) \ + do { \ + auto it = (mapList).find(key); \ + if (it != (mapList).end()) { \ + if (id::Query(it->second.GetRefPtr()) != nullptr) { \ + sptr idValue = id::Query(it->second.GetRefPtr()); \ + value retVal = 0; \ + idValue->GetValue(retVal); \ + return retVal; \ + } \ + return defaultValue; \ + } \ + } while (0); + +#define PAC_MAP_GET_STRING_VALUE(id, key, value, mapList, defaultValue) \ + do { \ + auto it = (mapList).find(key); \ + if (it != (mapList).end()) { \ + if (id::Query((it)->second.GetRefPtr()) != nullptr) { \ + sptr idValue = id::Query(it->second.GetRefPtr()); \ + value retVal; \ + idValue->GetString(retVal); \ + return retVal; \ + } \ + return defaultValue; \ + } \ + } while (0); + +#define PAC_MAP_ADD_ARRAY(id, key, value, mapList) \ + do { \ + RemoveData(mapList, key); \ + std::size_t size = value.size(); \ + sptr ao = new Array(size, g_IID_##I##id); \ + for (std::size_t i = 0; i < size; i++) { \ + ao->Set(i, id::Box((value)[i])); \ + } \ + (mapList).emplace(key, sptr(static_cast(ao.GetRefPtr()))); \ + } while (0); + +#define GET_PAC_MAP_ARRAY(id, mapList, key, value) \ + do { \ + auto it = (mapList).find(key); \ + if (it != (mapList).end()) { \ + if (IArray::Query(it->second.GetRefPtr()) != nullptr) { \ + if (Array::Is##id##Array(IArray::Query(it->second.GetRefPtr()))) { \ + auto func = [ & ](IInterface * object) { \ + if (I##id::Query(object) != nullptr) { \ + (value).push_back(id::Unbox(I##id::Query(object))); \ + } \ + }; \ + Array::ForEach(IArray::Query(it->second.GetRefPtr()), func); \ + } \ + } \ + } \ + } while (0); + +template +static void GetBaseDataValue(OHOS::AAFwk::IInterface *baseObj, Json::Value &json, int type) +{ + IClassName *data = IClassName::Query(baseObj); + baseValue val = 0; + data->GetValue(val); + json["data"] = val; + json["type"] = type; +} +#define GET_BASE_DATA_VALUE(id, it, value, json, type) \ + do { \ + I##id *data = I##id::Query((it)->second.GetRefPtr()); \ + value val = 0; \ + data->GetValue(val); \ + (json)["data"] = val; \ + (json)["type"] = type; \ + } while (0); + +template +static std::string RawTypeToString(const RawType value, unsigned int precisionAfterPoint); + +template +static void GetBaseFloatDoubleDataValue(OHOS::AAFwk::IInterface *baseObj, Json::Value &json, int type, int precision) +{ + IClassName *data = IClassName::Query(baseObj); + if (data != nullptr) { + baseValue val = ClassName::Unbox(data); + json["data"] = RawTypeToString(val, precision); + json["type"] = type; + } +} +#define GET_BASE_FLOAT_DOUBLE_DATA_VALUE(iid, id, it, value, precision, json, type) \ + do { \ + iid *data = iid::Query((it)->second); \ + if (data != nullptr) { \ + value val = id::Unbox(data); \ + (json)["data"] = RawTypeToString(val, precision); \ + (json)["type"] = type; \ + } \ + } while (0); + +#define GET_BASE_STRING_DATA_VALUE(id, it, value, json, type) \ + do { \ + I##id *data = I##id::Query((it)->second.GetRefPtr()); \ + value val; \ + data->GetString(val); \ + (json)["data"] = val; \ + (json)["type"] = type; \ + } while (0); + +#define GET_BASE_LONG_DATA_VALUE(id, it, value, json, type) \ + do { \ + I##id *data = I##id::Query((it)->second.GetRefPtr()); \ + value val = 0; \ + data->GetValue(val); \ + (json)["data"] = std::to_string(val); \ + (json)["type"] = type; \ + } while (0); + +template +static void PacmapGetArrayVal(OHOS::AAFwk::IInterface *ao, std::vector &array) +{ + if (ao == nullptr) { + return; + } + if (IArray::Query(ao) != nullptr) { + auto func = [&](AAFwk::IInterface *object) { + if (object != nullptr) { + IClassName *value = IClassName::Query(object); + if (value != nullptr) { + array.emplace_back(ClassName::Unbox(value)); + } + } + }; + Array::ForEach(IArray::Query(ao), func); + } +} +#define PAC_MAP_GET_ARRAY_VAL(idInterface, id, ao, array) \ + do { \ + if ((ao) == nullptr) { \ + return false; \ + } \ + if (IArray::Query((it)->second.GetRefPtr()) != nullptr) { \ + auto func = [ & ](AAFwk::IInterface * object) { \ + if (object != nullptr) { \ + idInterface *value = idInterface::Query(object); \ + if (value != nullptr) { \ + (array).emplace_back(id::Unbox(value)); \ + } \ + } \ + }; \ + Array::ForEach(IArray::Query((it)->second.GetRefPtr()), func); \ + } \ + } while (0); + +using namespace OHOS::AAFwk; +IINTERFACE_IMPL_1(PacMap, Object, IPacMap); +/** + * @brief A replication structure with deep copy. + */ +PacMap::PacMap(const PacMap &other) +{ + std::lock_guard mLock(mapLock_); + dataList_.clear(); + std::string str = MapListToString(other.dataList_); + StringToMapList(str, dataList_); +} + +PacMap::~PacMap() +{ + Clear(); +} + +/** + * @brief A overload operation with shallow copy. + */ +PacMap &PacMap::operator=(const PacMap &other) +{ + if (&other != this) { + dataList_.clear(); + std::string str = MapListToString(other.dataList_); + StringToMapList(str, dataList_); + } + return *this; +} + +/** + * @brief Clear all key-value pairs and free resources. + */ +void PacMap::Clear(void) +{ + std::lock_guard mLock(mapLock_); + dataList_.clear(); +} + +/** + * @brief Creates and returns a copy of this object with shallow copy. + * + * @return A clone of this instance. + */ +PacMap PacMap::Clone(void) +{ + std::lock_guard mLock(mapLock_); + PacMap pac_map; + std::string currentString = MapListToString(dataList_); + StringToMapList(currentString, pac_map.dataList_); + return pac_map; +} + +/** + * @brief Creates a deep copy of this PacMap object with deep copy. + * + * @return + */ +PacMap PacMap::DeepCopy(void) +{ + std::lock_guard mLock(mapLock_); + PacMap pac_map; + std::string str = MapListToString(dataList_); + StringToMapList(str, pac_map.dataList_); + return pac_map; +} + +void PacMap::DeepCopy(PacMap &other) +{ + std::lock_guard mLock(mapLock_); + dataList_.clear(); + StringToMapList(MapListToString(other.dataList_), dataList_); +} + +/** + * @brief Adds a short value matching a specified key. + * @param key A specified key. + * @param value The value that matches the specified key. + */ +void PacMap::PutShortValue(const std::string &key, short value) +{ + std::lock_guard mLock(mapLock_); + InnerPutShortValue(dataList_, key, value); +} +void PacMap::InnerPutShortValue(PacMapList &mapList, const std::string &key, short value) +{ + PAC_MAP_PUT_VALUE(Short, IShort, key, value, mapList) +} +/** + * @brief Adds a integer value matching a specified key. + * @param key A specified key. + * @param value The value that matches the specified key. + */ +void PacMap::PutIntValue(const std::string &key, int value) +{ + std::lock_guard mLock(mapLock_); + InnerPutIntValue(dataList_, key, value); +} +void PacMap::InnerPutIntValue(PacMapList &mapList, const std::string &key, int value) +{ + PAC_MAP_PUT_VALUE(Integer, IInteger, key, value, mapList) +} +/** + * @brief Adds a long value matching a specified key. + * @param key A specified key. + * @param value The value that matches the specified key. + */ +void PacMap::PutLongValue(const std::string &key, long value) +{ + std::lock_guard mLock(mapLock_); + InnerPutLongValue(dataList_, key, value); +} +void PacMap::InnerPutLongValue(PacMapList &mapList, const std::string &key, long value) +{ + PAC_MAP_PUT_VALUE(Long, ILong, key, value, mapList) +} +/** + * @brief Adds a boolean value matching a specified key. + * @param key A specified key. + * @param value The value that matches the specified key. + */ +void PacMap::PutBooleanValue(const std::string &key, bool value) +{ + std::lock_guard mLock(mapLock_); + InnerPutBooleanValue(dataList_, key, value); +} +void PacMap::InnerPutBooleanValue(PacMapList &mapList, const std::string &key, bool value) +{ + PAC_MAP_PUT_VALUE(Boolean, IBoolean, key, value, mapList) +} +/** + * @brief Adds a char value matching a specified key. + * @param key A specified key. + * @param value The value that matches the specified key. + */ +void PacMap::PutCharValue(const std::string &key, char value) +{ + std::lock_guard mLock(mapLock_); + InnerPutCharValue(dataList_, key, value); +} +void PacMap::InnerPutCharValue(PacMapList &mapList, const std::string &key, char value) +{ + PAC_MAP_PUT_VALUE(Char, IChar, key, value, mapList) +} + +/** + * @brief Adds a byte value matching a specified key. + * @param key A specified key. + * @param value The value that matches the specified key. + */ +void PacMap::PutByteValue(const std::string &key, AAFwk::byte value) +{ + std::lock_guard mLock(mapLock_); + InnerPutByteValue(dataList_, key, value); +} +void PacMap::InnerPutByteValue(PacMapList &mapList, const std::string &key, AAFwk::byte value) +{ + PAC_MAP_PUT_VALUE(Byte, IByte, key, value, mapList) +} +/** + * @brief Adds a float value matching a specified key. + * @param key A specified key. + * @param value The value that matches the specified key. + */ +void PacMap::PutFloatValue(const std::string &key, float value) +{ + std::lock_guard mLock(mapLock_); + InnerPutFloatValue(dataList_, key, value); +} +void PacMap::InnerPutFloatValue(PacMapList &mapList, const std::string &key, float value) +{ + PAC_MAP_PUT_VALUE(Float, IFloat, key, value, mapList) +} + +/** + * @brief Adds a double value matching a specified key. + * @param key A specified key. + * @param value The value that matches the specified key. + */ +void PacMap::PutDoubleValue(const std::string &key, double value) +{ + std::lock_guard mLock(mapLock_); + InnerPutDoubleValue(dataList_, key, value); +} +void PacMap::InnerPutDoubleValue(PacMapList &mapList, const std::string &key, double value) +{ + PAC_MAP_PUT_VALUE(Double, IDouble, key, value, mapList) +} +/** + * @brief Adds a string {std::string} value matching a specified key. + * @param key A specified key. + * @param value The value that matches the specified key. + */ +void PacMap::PutStringValue(const std::string &key, const std::string &value) +{ + std::lock_guard mLock(mapLock_); + InnerPutStringValue(dataList_, key, value); +} +void PacMap::InnerPutStringValue(PacMapList &mapList, const std::string &key, const std::string &value) +{ + PAC_MAP_PUT_VALUE(String, IString, key, value, mapList); +} + +/** + * @brief Adds an object value matching a specified key. The object must be a subclass of UserObjectBase. + * @param key A specified key. + * @param value A smart pointer to the object that matches the specified key. + */ +void PacMap::PutObject(const std::string &key, const std::shared_ptr &value) +{ + if (value == nullptr) { + return; + } + std::lock_guard mLock(mapLock_); + InnerPutObject(dataList_, key, value); +} +void PacMap::InnerPutObject(PacMapList &mapList, const std::string &key, const std::shared_ptr &value) +{ + RemoveData(mapList, key); + sptr valObject = OHOS::AAFwk::UserObject::Box(value); + if (valObject == nullptr) { + return; + } + mapList.emplace(key, valObject); +} +/** + * @brief Adds an PacMap value matching a specified key. + * @param key A specified key. + * @param value The value that matches the specified key. + */ +bool PacMap::PutPacMap(const std::string &key, const PacMap &value) +{ + std::lock_guard mLock(mapLock_); + return InnerPutPacMap(dataList_, key, const_cast(value)); +} +bool PacMap::InnerPutPacMap(PacMapList &mapList, const std::string &key, PacMap &value) +{ + RemoveData(mapList, key); + sptr pacMap = new (std::nothrow) PacMap(value); + if (pacMap != nullptr) { + mapList.emplace(key, pacMap); + return true; + } + return false; +} +/** + * @brief Adds some short values matching a specified key. + * @param key A specified key. + * @param value Store a list of short values. + */ +void PacMap::PutShortValueArray(const std::string &key, const std::vector &value) +{ + std::lock_guard mLock(mapLock_); + InnerPutShortValueArray(dataList_, key, value); +} +void PacMap::InnerPutShortValueArray(PacMapList &mapList, const std::string &key, const std::vector &value) +{ + PAC_MAP_ADD_ARRAY(Short, key, value, mapList) +} +/** + * @brief Adds some integer values matching a specified key. + * @param key A specified key. + * @param value Store a list of integer values. + */ +void PacMap::PutIntValueArray(const std::string &key, const std::vector &value) +{ + std::lock_guard mLock(mapLock_); + InnerPutIntValueArray(dataList_, key, value); +} +void PacMap::InnerPutIntValueArray(PacMapList &mapList, const std::string &key, const std::vector &value) +{ + PAC_MAP_ADD_ARRAY(Integer, key, value, mapList) +} +/** + * @brief Adds some long values matching a specified key. + * @param key A specified key. + * @param value Store a list of long values. + */ +void PacMap::PutLongValueArray(const std::string &key, const std::vector &value) +{ + std::lock_guard mLock(mapLock_); + InnerPutLongValueArray(dataList_, key, value); +} +void PacMap::InnerPutLongValueArray(PacMapList &mapList, const std::string &key, const std::vector &value) +{ + PAC_MAP_ADD_ARRAY(Long, key, value, mapList) +} +/** + * @brief Adds some boolean values matching a specified key. + * @param key A specified key. + * @param value Store a list of boolean values. + */ +void PacMap::PutBooleanValueArray(const std::string &key, const std::vector &value) +{ + std::lock_guard mLock(mapLock_); + InnerPutBooleanValueArray(dataList_, key, value); +} +void PacMap::InnerPutBooleanValueArray(PacMapList &mapList, const std::string &key, const std::vector &value) +{ + PAC_MAP_ADD_ARRAY(Boolean, key, value, mapList) +} +/** + * @brief Adds some char values matching a specified key. + * @param key A specified key. + * @param value Store a list of char values. + */ +void PacMap::PutCharValueArray(const std::string &key, const std::vector &value) +{ + std::lock_guard mLock(mapLock_); + InnerPutCharValueArray(dataList_, key, value); +} +void PacMap::InnerPutCharValueArray(PacMapList &mapList, const std::string &key, const std::vector &value) +{ + PAC_MAP_ADD_ARRAY(Char, key, value, mapList) +} +/** + * @brief Adds some byte values matching a specified key. + * @param key A specified key. + * @param value Store a list of byte values. + */ +void PacMap::PutByteValueArray(const std::string &key, const std::vector &value) +{ + std::lock_guard mLock(mapLock_); + InnerPutByteValueArray(dataList_, key, value); +} +void PacMap::InnerPutByteValueArray(PacMapList &mapList, const std::string &key, const std::vector &value) +{ + PAC_MAP_ADD_ARRAY(Byte, key, value, mapList) +} +/** + * @brief Adds some float values matching a specified key. + * @param key A specified key. + * @param value Store a list of float values. + */ +void PacMap::PutFloatValueArray(const std::string &key, const std::vector &value) +{ + std::lock_guard mLock(mapLock_); + InnerPutFloatValueArray(dataList_, key, value); +} +void PacMap::InnerPutFloatValueArray(PacMapList &mapList, const std::string &key, const std::vector &value) +{ + PAC_MAP_ADD_ARRAY(Float, key, value, mapList) +} +/** + * @brief Adds some double values matching a specified key. + * @param key A specified key. + * @param value Store a list of double values. + */ +void PacMap::PutDoubleValueArray(const std::string &key, const std::vector &value) +{ + std::lock_guard mLock(mapLock_); + InnerPutDoubleValueArray(dataList_, key, value); +} +void PacMap::InnerPutDoubleValueArray(PacMapList &mapList, const std::string &key, const std::vector &value) +{ + PAC_MAP_ADD_ARRAY(Double, key, value, mapList) +} +/** + * @brief Adds some string {std::string} values matching a specified key. + * @param key A specified key. + * @param value Store a list of string values. + */ +void PacMap::PutStringValueArray(const std::string &key, const std::vector &value) +{ + std::lock_guard mLock(mapLock_); + InnerPutStringValueArray(dataList_, key, value); +} +void PacMap::InnerPutStringValueArray( + PacMapList &mapList, const std::string &key, const std::vector &value) +{ + PAC_MAP_ADD_ARRAY(String, key, value, mapList) +} +/** + * @brief Inserts all key-value pairs of a map object into the built-in data object. + * Duplicate key values will be replaced. + * @param mapData Store a list of key-value pairs. + */ +void PacMap::PutAll(std::map &mapData) +{ + std::lock_guard mLock(mapLock_); + dataList_.clear(); + StringToMapList(MapListToString(mapData), dataList_); +} + +/** + * @brief Saves the data in a PacMap object to the current object. Duplicate key values will be replaced. + * @param pacMap Store the date of PacMap. + */ +void PacMap::PutAll(PacMap &pacMap) +{ + std::lock_guard mLock(mapLock_); + dataList_.clear(); + StringToMapList(MapListToString(pacMap.dataList_), dataList_); +} + +/** + * @brief Obtains the int value matching a specified key. + * @param key A specified key. + * @param defaultValue The return value when the function fails. + * @return If the match is successful, return the value matching the key, otherwise return the @a defaultValue. + */ +int PacMap::GetIntValue(const std::string &key, int defaultValue) +{ + std::lock_guard mLock(mapLock_); + PAC_MAP_GET_VALUE(IInteger, key, int, dataList_, defaultValue) + return defaultValue; +} + +/** + * @brief Obtains the short value matching a specified key. + * @param key A specified key. + * @param defaultValue The return value when the function fails. + * @return If the match is successful, return the value matching the key, otherwise return the @a defaultValue. + */ +short PacMap::GetShortValue(const std::string &key, short defaultValue) +{ + std::lock_guard mLock(mapLock_); + PAC_MAP_GET_VALUE(IShort, key, short, dataList_, defaultValue) + return defaultValue; +} + +/** + * @brief Obtains the boolean value matching a specified key. + * @param key A specified key. + * @param defaultValue The return value when the function fails. + * @return If the match is successful, return the value matching the key, otherwise return the @a defaultValue. + */ +bool PacMap::GetBooleanValue(const std::string &key, bool defaultValue) +{ + std::lock_guard mLock(mapLock_); + PAC_MAP_GET_VALUE(IBoolean, key, bool, dataList_, defaultValue) + return defaultValue; +} + +/** + * @brief Obtains the long value matching a specified key. + * @param key A specified key. + * @param defaultValue The return value when the function fails. + * @return If the match is successful, return the value matching the key, otherwise return the @a defaultValue. + */ +long PacMap::GetLongValue(const std::string &key, long defaultValue) +{ + std::lock_guard mLock(mapLock_); + PAC_MAP_GET_VALUE(ILong, key, long, dataList_, defaultValue) + return defaultValue; +} + +/** + * @brief Obtains the char value matching a specified key. + * @param key A specified key. + * @param defaultValue The return value when the function fails. + * @return If the match is successful, return the value matching the key, otherwise return the @a defaultValue. + */ +char PacMap::GetCharValue(const std::string &key, char defaultValue) +{ + std::lock_guard mLock(mapLock_); + PAC_MAP_GET_VALUE(IChar, key, zchar, dataList_, defaultValue) + return defaultValue; +} + +/** + * @brief Obtains the byte value matching a specified key. + * @param key A specified key. + * @param defaultValue The return value when the function fails. + * @return If the match is successful, return the value matching the key, otherwise return the @a defaultValue. + */ +AAFwk::byte PacMap::GetByteValue(const std::string &key, AAFwk::byte defaultValue) +{ + std::lock_guard mLock(mapLock_); + PAC_MAP_GET_VALUE(IByte, key, byte, dataList_, defaultValue) + return defaultValue; +} + +/** + * @brief Obtains the float value matching a specified key. + * @param key A specified key. + * @param defaultValue The return value when the function fails. + * @return If the match is successful, return the value matching the key, otherwise return the @a defaultValue. + */ +float PacMap::GetFloatValue(const std::string &key, float defaultValue) +{ + std::lock_guard mLock(mapLock_); + PAC_MAP_GET_VALUE(IFloat, key, float, dataList_, defaultValue) + return defaultValue; +} + +/** + * @brief Obtains the double value matching a specified key. + * @param key A specified key. + * @param defaultValue The return value when the function fails. + * @return If the match is successful, return the value matching the key, otherwise return the @a defaultValue. + */ +double PacMap::GetDoubleValue(const std::string &key, double defaultValue) +{ + std::lock_guard mLock(mapLock_); + PAC_MAP_GET_VALUE(IDouble, key, double, dataList_, defaultValue) + return defaultValue; +} + +/** + * @brief Obtains the string {std::string} value matching a specified key. + * @param key A specified key. + * @param defaultValue The return value when the function fails. + * @return If the match is successful, return the value matching the key, otherwise return the @a defaultValue. + */ +std::string PacMap::GetStringValue(const std::string &key, const std::string &defaultValue) +{ + std::lock_guard mLock(mapLock_); + PAC_MAP_GET_STRING_VALUE(IString, key, std::string, dataList_, defaultValue) + return defaultValue; +} + +/** + * @brief Obtains some int values matching a specified key. + * @param key A specified key. + * @param value Save the returned int values. + */ +void PacMap::GetIntValueArray(const std::string &key, std::vector &value) +{ + std::lock_guard mLock(mapLock_); + GET_PAC_MAP_ARRAY(Integer, dataList_, key, value) +} + +/** + * @brief Obtains some short values matching a specified key. + * @param key A specified key. + * @param value Save the returned short values. + */ +void PacMap::GetShortValueArray(const std::string &key, std::vector &value) +{ + std::lock_guard mLock(mapLock_); + GET_PAC_MAP_ARRAY(Short, dataList_, key, value) +} +/** + * @brief Obtains some boolean values matching a specified key. + * @param key A specified key. + * @param value Save the returned boolean values. + */ +void PacMap::GetBooleanValueArray(const std::string &key, std::vector &value) +{ + std::lock_guard mLock(mapLock_); + GET_PAC_MAP_ARRAY(Boolean, dataList_, key, value) +} + +/** + * @brief Obtains some long values matching a specified key. + * @param key A specified key. + * @param value Save the returned long values. + */ +void PacMap::GetLongValueArray(const std::string &key, std::vector &value) +{ + std::lock_guard mLock(mapLock_); + GET_PAC_MAP_ARRAY(Long, dataList_, key, value) +} + +/** + * @brief Obtains some char values matching a specified key. + * @param key A specified key. + * @param value Save the returned char values. + */ +void PacMap::GetCharValueArray(const std::string &key, std::vector &value) +{ + std::lock_guard mLock(mapLock_); + GET_PAC_MAP_ARRAY(Char, dataList_, key, value) +} + +/** + * @brief Obtains some byte values matching a specified key. + * @param key A specified key. + * @param value Save the returned byte values. + */ +void PacMap::GetByteValueArray(const std::string &key, std::vector &value) +{ + std::lock_guard mLock(mapLock_); + GET_PAC_MAP_ARRAY(Byte, dataList_, key, value) +} + +/** + * @brief Obtains some float values matching a specified key. + * @param key A specified key. + * @param value Save the returned float values. + */ +void PacMap::GetFloatValueArray(const std::string &key, std::vector &value) +{ + std::lock_guard mLock(mapLock_); + GET_PAC_MAP_ARRAY(Float, dataList_, key, value) +} + +/** + * @brief Obtains some double values matching a specified key. + * @param key A specified key. + * @param value Save the returned double values. + */ +void PacMap::GetDoubleValueArray(const std::string &key, std::vector &value) +{ + std::lock_guard mLock(mapLock_); + GET_PAC_MAP_ARRAY(Double, dataList_, key, value) +} + +/** + * @brief Obtains some string {std::string} values matching a specified key. + * @param key A specified key. + * @param value Save the returned string {std::string} values. + */ +void PacMap::GetStringValueArray(const std::string &key, std::vector &value) +{ + std::lock_guard mLock(mapLock_); + GET_PAC_MAP_ARRAY(String, dataList_, key, value) +} + +/** + * @brief Obtains the object matching a specified key. + * @param key A specified key. + * @return Returns the smart pointer to object that matches the key. + */ +std::shared_ptr PacMap::GetObject(const std::string &key) +{ + std::lock_guard mLock(mapLock_); + auto it = dataList_.find(key); + if (it == dataList_.end()) { + return nullptr; + } + + if (it->second != nullptr) { + if (IUserObject::Query(it->second.GetRefPtr()) != nullptr) { + return UserObject::Unbox(static_cast(it->second.GetRefPtr())); + } + } + + return nullptr; +} + +/** + * @brief Obtains the PacMap matching a specified key. + * @param key A specified key. + * @return Returns PacMap that matches the key. + */ +PacMap PacMap::GetPacMap(const std::string &key) +{ + std::lock_guard mLock(mapLock_); + PacMap pacmap; + auto it = dataList_.find(key); + if (it != dataList_.end()) { + if (IPacMap::Query(it->second.GetRefPtr()) != nullptr) { + pacmap.DeepCopy(*static_cast(IPacMap::Query(it->second.GetRefPtr()))); + } + } + return pacmap; +} + +/** + * @brief Obtains all the data that has been stored with shallow copy. + * @return Returns all data in current PacMap. There is no dependency between the returned data and + * the original data. + */ +std::map PacMap::GetAll(void) +{ + std::lock_guard mLock(mapLock_); + + PacMapList tmpMapList; + StringToMapList(MapListToString(dataList_), tmpMapList); + + return tmpMapList; +} + +void PacMap::ShallowCopyData(PacMapList &desPacMap, const PacMapList &srcPacMap) +{ + desPacMap.clear(); + for (auto it = srcPacMap.begin(); it != srcPacMap.end(); it++) { + desPacMap.emplace(it->first, it->second); + } +} + +void PacMap::RemoveData(PacMapList &pacMapList, const std::string &key) +{ + auto it = pacMapList.find(key); + if (it != pacMapList.end()) { + pacMapList.erase(it); + } +} + +bool PacMap::EqualPacMapData(const PacMapList &leftPacMapList, const PacMapList &rightPacMapList) +{ + if (leftPacMapList.size() != rightPacMapList.size()) { + return false; + } + + for (auto right = rightPacMapList.begin(); right != rightPacMapList.end(); right++) { + auto left = leftPacMapList.find(right->first); + if (left == leftPacMapList.end()) { + return false; + } + if (left->second.GetRefPtr() == right->second.GetRefPtr()) { + continue; + } + + // PacMap Object + if (IPacMap::Query(right->second.GetRefPtr()) != nullptr) { + auto leftMapIt = leftPacMapList.find(right->first); + if (leftMapIt == leftPacMapList.end()) { + return false; + } + if (IPacMap::Query(leftMapIt->second.GetRefPtr()) == nullptr) { + return false; + } + + PacMap *rightMap = static_cast(IPacMap::Query(right->second.GetRefPtr())); + PacMap *leftMap = static_cast(IPacMap::Query(leftMapIt->second.GetRefPtr())); + if (!EqualPacMapData(leftMap->dataList_, rightMap->dataList_)) { + return false; + } + continue; + } + + if (!Object::Equals(*(right->second.GetRefPtr()), *(left->second.GetRefPtr()))) { + return false; + } + } + return true; +} + +template +static void GetArrayData( + AAFwk::IInterface *interface, std::vector &array, std::function IsArrayfunc) +{ + if (interface == nullptr) { + return; + } + if (IsArrayfunc(IArray::Query(interface))) { + auto func = [&](IInterface *object) { array.push_back(id::Unbox(iid::Query(object))); }; + Array::ForEach(IArray::Query(interface), func); + } +} + +template +static bool CompareTwoArrayData( + AAFwk::IInterface *one_interface, AAFwk::IInterface *two_interface, std::function IsArrayfunc) +{ + typename std::vector array; + GetArrayData(IArray::Query(one_interface), array, IsArrayfunc); + + if (!IsArrayfunc(IArray::Query(two_interface))) { + return false; + } + typename std::vector otherArray; + GetArrayData(IArray::Query(two_interface), otherArray, IsArrayfunc); + if (array.size() != 0 && otherArray.size() != 0 && array.size() != otherArray.size()) { + return false; + } + for (std::size_t i = 0; i < array.size(); i++) { + auto it = std::find(otherArray.begin(), otherArray.end(), array[i]); + if (it == array.end()) { + return false; + } + } + return true; +} +bool PacMap::CompareArrayData(AAFwk::IInterface *one_interface, AAFwk::IInterface *two_interface) +{ + if (IArray::Query(one_interface) != nullptr && IArray::Query(two_interface) != nullptr) { + IArray *array_one = IArray::Query(one_interface); + IArray *array_two = IArray::Query(two_interface); + long size1 = 0; + array_one->GetLength(size1); + long size2 = 0; + array_two->GetLength(size2); + + if (size1 != 0 && size2 != 0 && size1 != size2) { + return false; + } + if (AAFwk::Array::IsBooleanArray(IArray::Query(one_interface))) { + if (!CompareTwoArrayData( + one_interface, two_interface, AAFwk::Array::IsBooleanArray)) { + return false; + } + } else if (AAFwk::Array::IsCharArray(AAFwk::IArray::Query(one_interface))) { + return false; + } else if (AAFwk::Array::IsByteArray(IArray::Query(one_interface))) { + if (!CompareTwoArrayData( + one_interface, two_interface, AAFwk::Array::IsByteArray)) { + return false; + } + } else if (AAFwk::Array::IsShortArray(IArray::Query(one_interface))) { + if (!CompareTwoArrayData( + one_interface, two_interface, AAFwk::Array::IsShortArray)) { + return false; + } + } else if (AAFwk::Array::IsIntegerArray(IArray::Query(one_interface))) { + if (!CompareTwoArrayData( + one_interface, two_interface, AAFwk::Array::IsIntegerArray)) { + return false; + } + } else if (AAFwk::Array::IsLongArray(IArray::Query(one_interface))) { + if (!CompareTwoArrayData( + one_interface, two_interface, AAFwk::Array::IsLongArray)) { + return false; + } + } else if (AAFwk::Array::IsFloatArray(IArray::Query(one_interface))) { + if (!CompareTwoArrayData( + one_interface, two_interface, AAFwk::Array::IsFloatArray)) { + return false; + } + } else if (AAFwk::Array::IsDoubleArray(IArray::Query(one_interface))) { + if (!CompareTwoArrayData( + one_interface, two_interface, AAFwk::Array::IsDoubleArray)) { + return false; + } + } else if (AAFwk::Array::IsStringArray(IArray::Query(one_interface))) { + if (!CompareTwoArrayData( + one_interface, two_interface, AAFwk::Array::IsStringArray)) { + return false; + } + } else { + return false; + } + } + return true; +} +/** + * @brief Indicates whether some other object is "equal to" this one. + * @param pacMap The object with which to compare. + * @return Returns true if this object is the same as the pacMap argument; false otherwise. + */ +bool PacMap::Equals(const PacMap *pacMap) +{ + std::lock_guard mLock(mapLock_); + if (pacMap == nullptr) { + return false; + } + + if (this == pacMap) { + return true; + } + + if (dataList_.size() != pacMap->dataList_.size()) { + return false; + } + + if (!EqualPacMapData(dataList_, pacMap->dataList_)) { + return false; + } + + return true; +} + +bool PacMap::Equals(const PacMap &pacMap) +{ + return Equals(&pacMap); +} + +/** + * @brief Checks whether the current object is empty. + * @return If there is no data, return true, otherwise return false. + */ +bool PacMap::IsEmpty(void) const +{ + return dataList_.empty(); +} + +/** + * @brief Obtains the number of key-value pairs stored in the current object. + * @return Returns the number of key-value pairs. + */ +int PacMap::GetSize(void) const +{ + return dataList_.size(); +} + +/** + * @brief Obtains all the keys of the current object. + */ +const std::set PacMap::GetKeys(void) +{ + std::lock_guard mLock(mapLock_); + std::set keys; + + for (auto it = dataList_.begin(); it != dataList_.end(); it++) { + keys.emplace(it->first); + } + return keys; +} + +/** + * @brief Checks whether a specified key is contained. + * @param key Indicates the key in String + * @return Returns true if the key is contained; returns false otherwise. + */ +bool PacMap::HasKey(const std::string &key) +{ + std::lock_guard mLock(mapLock_); + return (dataList_.find(key) != dataList_.end()); +} + +/** + * @brief Deletes a key-value pair with a specified key. + * @param key Specifies the key of the deleted data. + */ +void PacMap::Remove(const std::string &key) +{ + std::lock_guard mLock(mapLock_); + auto it = dataList_.find(key); + if (it != dataList_.end()) { + dataList_.erase(it); + } +} + +bool PacMap::ReadFromParcel(Parcel &parcel) +{ + std::string value = parcel.ReadString(); + if (!value.empty()) { + return StringToMapList(value, dataList_); + } else { + return true; + } +} + +/** + * @brief Marshals this Sequenceable object to a Parcel. + * @param parcel Indicates the Parcel object into which the Sequenceable object has been marshaled. + * @return Marshals success returns true, otherwise returns false. + */ +bool PacMap::Marshalling(Parcel &parcel) const +{ + if (!parcel.WriteString("PACMAP")) { + return false; + } + std::string str = MapListToString(dataList_); + return parcel.WriteString(str); +} + +/** + * @brief Unmarshals this S`nceable object from a Parcel. + * @param parcel Indicates the Parcel object into which the Sequenceable object has been marshaled. + * @return Unmarshals success returns a smart pointer to PacMap, otherwise returns nullptr. + */ +PacMap *PacMap::Unmarshalling(Parcel &parcel) +{ + std::string value = parcel.ReadString(); + if (value != "PACMAP") { + return nullptr; + } + PacMap *pPacMap = new (std::nothrow) PacMap(); + if (pPacMap != nullptr && !pPacMap->ReadFromParcel(parcel)) { + delete pPacMap; + return nullptr; + } + return pPacMap; +} + +/** + * @brief Object serialization to string. + * @return Returns the serialized string. + */ +std::string PacMap::ToString() +{ + std::lock_guard mLock(mapLock_); + return MapListToString(dataList_); +} + +std::string PacMap::MapListToString(const PacMapList &mapList) const +{ + Json::Value root; + Json::Value dataObject; + + ToJson(mapList, dataObject); + root["pacmap"] = dataObject; + + std::ostringstream os; + Json::StreamWriterBuilder builder; + builder.settings_["indentation"] = ""; + std::unique_ptr jsonWriter(builder.newStreamWriter()); + if (jsonWriter != nullptr) { + jsonWriter->write(root, &os); + return os.str(); + } else { + return std::string(""); + } +} + +bool PacMap::ToJson(const PacMapList &mapList, Json::Value &dataObject) const +{ + bool isOK = false; + for (auto it = mapList.begin(); it != mapList.end(); it++) { + Json::Value item; + isOK = false; + if (IPacMap::Query(it->second.GetRefPtr()) != nullptr) { + PacMap *pacmap = static_cast(IPacMap::Query(it->second.GetRefPtr())); + if (pacmap != nullptr) { + Json::Value item2; + isOK = pacmap->ToJson(pacmap->dataList_, item2); + if (isOK) { + item["type"] = PACMAP_DATA_PACMAP; + item["data"] = item2; + } + } + } else { + isOK = GetBaseJsonValue(it, item); + } + if (isOK) { + dataObject[it->first] = item; + } else { + return false; + } + } + return true; +} + +template +static std::string RawTypeToString(const RawType value, unsigned int precisionAfterPoint) +{ + std::ostringstream out("RawTypeToString"); + out << std::setw(0) << std::setprecision(precisionAfterPoint) << value; + + std::string res = out.str(); + auto pos = res.find('.'); + if (pos == std::string::npos) + return res; + + auto splitLen = pos + 1 + precisionAfterPoint; + if (res.size() <= splitLen) + return res; + + return res.substr(0, splitLen); +} + +bool PacMap::GetBaseJsonValue(PacMapList::const_iterator &it, Json::Value &json) const +{ + // base data : short + if (IShort::Query(it->second.GetRefPtr()) != nullptr) { + GetBaseDataValue(it->second.GetRefPtr(), json, PACMAP_DATA_SHORT); + } else if (IInteger::Query(it->second.GetRefPtr()) != nullptr) { + GetBaseDataValue(it->second.GetRefPtr(), json, PACMAP_DATA_INTEGER); + } else if (ILong::Query(it->second.GetRefPtr()) != nullptr) { + // long:string + GET_BASE_LONG_DATA_VALUE(Long, it, long, json, PACMAP_DATA_LONG) + } else if (IChar::Query(it->second.GetRefPtr()) != nullptr) { + GetBaseDataValue(it->second.GetRefPtr(), json, PACMAP_DATA_CHAR); + } else if (IByte::Query(it->second.GetRefPtr()) != nullptr) { + GetBaseDataValue(it->second.GetRefPtr(), json, PACMAP_DATA_BYTE); + } else if (IBoolean::Query(it->second.GetRefPtr()) != nullptr) { + GetBaseDataValue(it->second.GetRefPtr(), json, PACMAP_DATA_BOOLEAN); + } else if (IFloat::Query(it->second.GetRefPtr()) != nullptr) { + // base long:string + GetBaseFloatDoubleDataValue( + it->second.GetRefPtr(), json, PACMAP_DATA_FLOAT, FLOAT_PRECISION); + } else if (IDouble::Query(it->second.GetRefPtr()) != nullptr) { + // base :double to string + GetBaseFloatDoubleDataValue( + it->second.GetRefPtr(), json, PACMAP_DATA_DOUBLE, DOUBLE_PRECISION); + } else if (IString::Query(it->second.GetRefPtr()) != nullptr) { + GET_BASE_STRING_DATA_VALUE(String, it, std::string, json, PACMAP_DATA_STRING) + } else if (IArray::Query(it->second.GetRefPtr()) != nullptr) { + // array data + return GetArrayJsonValue(it, json); + } else if (IUserObject::Query(it->second.GetRefPtr()) != nullptr) { + // Object data [UserObject--data:UserObjectBase] + return GetUserObjectJsonValue(it, json); + } else { + return false; + } + + return true; +} + +// Base data: short +bool PacMap::ToJsonArrayShort(std::vector &array, Json::Value &item, int type) const +{ + if (array.size() > 0) { + for (size_t i = 0; i < array.size(); i++) { + item["data"].append(array[i]); + } + item["type"] = type; + return true; + } + return false; +} +// Base data: Integer +bool PacMap::ToJsonArrayInt(std::vector &array, Json::Value &item, int type) const +{ + if (array.size() > 0) { + for (size_t i = 0; i < array.size(); i++) { + item["data"].append(array[i]); + } + item["type"] = type; + return true; + } + return false; +} +// Base data: long:sting +bool PacMap::ToJsonArrayLong(std::vector &array, Json::Value &item, int type) const +{ + if (array.size() > 0) { + for (size_t i = 0; i < array.size(); i++) { + item["data"].append(std::to_string(array[i])); + } + item["type"] = type; + return true; + } + return false; +} + +// Base data: byte +bool PacMap::ToJsonArrayByte(std::vector &array, Json::Value &item, int type) const +{ + if (array.size() > 0) { + for (size_t i = 0; i < array.size(); i++) { + item["data"].append(array[i]); + } + item["type"] = type; + return true; + } + return false; +} +// Base data: bool +bool PacMap::ToJsonArrayBoolean(std::vector &array, Json::Value &item, int type) const +{ + if (array.size() > 0) { + for (size_t i = 0; i < array.size(); i++) { + item["data"].append((int)array[i]); + } + item["type"] = type; + return true; + } + return false; +} +// Base data: Float to string +bool PacMap::ToJsonArrayFloat(std::vector &array, Json::Value &item, int type) const +{ + if (array.size() > 0) { + for (size_t i = 0; i < array.size(); i++) { + item["data"].append(RawTypeToString(array[i], FLOAT_PRECISION)); + } + item["type"] = type; + return true; + } + return false; +} +// Base data: Double to string +bool PacMap::ToJsonArrayDouble(std::vector &array, Json::Value &item, int type) const +{ + if (array.size() > 0) { + for (size_t i = 0; i < array.size(); i++) { + item["data"].append(RawTypeToString(array[i], DOUBLE_PRECISION)); + } + item["type"] = type; + return true; + } + return false; +} +// Base data: string +bool PacMap::ToJsonArrayString(std::vector &array, Json::Value &item, int type) const +{ + if (array.size() > 0) { + for (size_t i = 0; i < array.size(); i++) { + item["data"].append(array[i]); + } + item["type"] = type; + return true; + } + return false; +} + +bool PacMap::GetArrayJsonValue(PacMapList::const_iterator &it, Json::Value &json) const +{ + if (IArray::Query(it->second.GetRefPtr()) == nullptr) { + return false; + } + IArray *array = static_cast(it->second.GetRefPtr()); + if (array == nullptr) { + return false; + } + if (Array::IsShortArray(array)) { + std::vector arrayData; + PacmapGetArrayVal(it->second.GetRefPtr(), arrayData); + return ToJsonArrayShort(arrayData, json, PACMAP_DATA_ARRAY_SHORT); + } else if (Array::IsIntegerArray(array)) { + std::vector arrayData; + PacmapGetArrayVal(it->second.GetRefPtr(), arrayData); + return ToJsonArrayInt(arrayData, json, PACMAP_DATA_ARRAY_INTEGER); + } else if (Array::IsLongArray(array)) { + std::vector arrayData; + PacmapGetArrayVal(it->second.GetRefPtr(), arrayData); + return ToJsonArrayLong(arrayData, json, PACMAP_DATA_ARRAY_LONG); + } else if (Array::IsCharArray(array)) { + return false; + } else if (Array::IsByteArray(array)) { + std::vector arrayData; + PacmapGetArrayVal(it->second.GetRefPtr(), arrayData); + return ToJsonArrayByte(arrayData, json, PACMAP_DATA_ARRAY_BYTE); + } else if (Array::IsBooleanArray(array)) { + std::vector arrayData; + PacmapGetArrayVal(it->second.GetRefPtr(), arrayData); + return ToJsonArrayBoolean(arrayData, json, PACMAP_DATA_ARRAY_BOOLEAN); + } else if (Array::IsFloatArray(array)) { + std::vector arrayData; + PacmapGetArrayVal(it->second.GetRefPtr(), arrayData); + return ToJsonArrayFloat(arrayData, json, PACMAP_DATA_ARRAY_FLOAT); + } else if (Array::IsDoubleArray(array)) { + std::vector arrayData; + PacmapGetArrayVal(it->second.GetRefPtr(), arrayData); + return ToJsonArrayDouble(arrayData, json, PACMAP_DATA_ARRAY_DOUBLE); + } else if (Array::IsStringArray(array)) { + std::vector arrayData; + PacmapGetArrayVal(it->second.GetRefPtr(), arrayData); + return ToJsonArrayString(arrayData, json, PACMAP_DATA_ARRAY_STRING); + } else { + return false; + } + return true; +} +bool PacMap::GetUserObjectJsonValue(PacMapList::const_iterator &it, Json::Value &json) const +{ + std::shared_ptr myObjectBase = UserObject::Unbox(IUserObject::Query(it->second.GetRefPtr())); + if (myObjectBase == nullptr) { + return false; + } + + std::string userObjectString = myObjectBase->ToString(); + Json::Value objectData; + + json["type"] = PACMAP_DATA_USEROBJECT; + json["class"] = myObjectBase->GetClassName(); + json["data"] = userObjectString; + return true; +} + +/** + * @brief Restore pacmap from the string. + * @return Return true if successful, otherwise false. + */ +bool PacMap::FromString(const std::string &str) +{ + std::lock_guard mLock(mapLock_); + dataList_.clear(); + return StringToMapList(str, dataList_); +} + +bool PacMap::StringToMapList(const std::string &str, PacMapList &mapList) +{ + if (str.empty()) { + return false; + } + + JSONCPP_STRING err; + Json::Value root; + + const int rawJsonLength = static_cast(str.length()); + Json::CharReaderBuilder builder; + std::unique_ptr jsonReader(builder.newCharReader()); + if (!jsonReader->parse(str.c_str(), str.c_str() + rawJsonLength, &root, &err)) { + jsonReader.reset(); + return false; + } + + if (!root.isMember("pacmap")) { + return false; + } + + Json::Value dataObject = root["pacmap"]; + if (dataObject.isNull()) { + return true; + } + return ParseJson(dataObject, mapList); +} + +bool PacMap::ParseJson(Json::Value &data, PacMapList &mapList) +{ + Json::Value::Members keyList = data.getMemberNames(); + if (keyList.size() == 0) { + return false; + } + Json::Value item; + for (size_t i = 0; i < keyList.size(); i++) { + item = data[keyList[i]]; + if (!item.isNull()) { + ParseJsonItem(mapList, keyList[i], item); + } + } + return true; +} + +bool PacMap::ParseJsonItem(PacMapList &mapList, const std::string &key, Json::Value &item) +{ + // base data, object data, arry data + switch (item["type"].asInt()) { + case PACMAP_DATA_SHORT: + InnerPutShortValue(mapList, key, item["data"].asInt()); + break; + case PACMAP_DATA_INTEGER: + InnerPutIntValue(mapList, key, item["data"].asInt()); + break; + case PACMAP_DATA_LONG: + InnerPutLongValue(mapList, key, std::atol(item["data"].asString().c_str())); + break; + case PACMAP_DATA_CHAR: + InnerPutCharValue(mapList, key, item["data"].asInt()); + break; + case PACMAP_DATA_BYTE: + InnerPutByteValue(mapList, key, item["data"].asInt()); + break; + case PACMAP_DATA_BOOLEAN: + InnerPutBooleanValue(mapList, key, item["data"].asBool()); + break; + case PACMAP_DATA_FLOAT: + InnerPutFloatValue(mapList, key, std::atof(item["data"].asString().c_str())); + break; + case PACMAP_DATA_DOUBLE: + InnerPutDoubleValue(mapList, key, std::atof(item["data"].asString().c_str())); + break; + case PACMAP_DATA_STRING: + InnerPutStringValue(mapList, key, item["data"].asString()); + break; + case PACMAP_DATA_USEROBJECT: + InnerPutObjectValue(mapList, key, item); + break; + case PACMAP_DATA_PACMAP: + InnerPutPacMapValue(mapList, key, item); + break; + default: + return ParseJsonItemArray(mapList, key, item); + } + return true; +} + +bool PacMap::ParseJsonItemArray(PacMapList &mapList, const std::string &key, Json::Value &item) +{ + switch (item["type"].asInt()) { + case PACMAP_DATA_ARRAY_SHORT: + return ParseJsonItemArrayShort(mapList, key, item); + case PACMAP_DATA_ARRAY_INTEGER: + return ParseJsonItemArrayInteger(mapList, key, item); + case PACMAP_DATA_ARRAY_LONG: + return ParseJsonItemArrayLong(mapList, key, item); + case PACMAP_DATA_ARRAY_CHAR: + return ParseJsonItemArrayChar(mapList, key, item); + case PACMAP_DATA_ARRAY_BYTE: + return ParseJsonItemArrayByte(mapList, key, item); + case PACMAP_DATA_ARRAY_BOOLEAN: + return ParseJsonItemArrayBoolean(mapList, key, item); + case PACMAP_DATA_ARRAY_FLOAT: + return ParseJsonItemArrayFloat(mapList, key, item); + case PACMAP_DATA_ARRAY_DOUBLE: + return ParseJsonItemArrayDouble(mapList, key, item); + case PACMAP_DATA_ARRAY_STRING: + return ParseJsonItemArrayString(mapList, key, item); + default: + return false; + } +} + +bool PacMap::ParseJsonItemArrayShort(PacMapList &mapList, const std::string &key, Json::Value &item) +{ + Json::Value arrayValue = item["data"]; + if (arrayValue.isNull()) { + return true; + } + + std::vector shortList; + for (Json::ArrayIndex i = 0; i < arrayValue.size(); i++) { + shortList.push_back(arrayValue[i].asInt()); + } + InnerPutShortValueArray(mapList, key, shortList); + return true; +} + +bool PacMap::ParseJsonItemArrayInteger(PacMapList &mapList, const std::string &key, Json::Value &item) +{ + Json::Value arrayValue = item["data"]; + if (arrayValue.isNull()) { + return true; + } + + std::vector intList; + for (Json::ArrayIndex i = 0; i < arrayValue.size(); i++) { + intList.push_back(arrayValue[i].asInt()); + } + InnerPutIntValueArray(mapList, key, intList); + return true; +} +/** + * @brief Determine whether the string content is a numeric string + * @param str indicates stirng. + * @return bool + */ +bool PacMap::IsNumber(const std::string &str) +{ + return std::regex_match(str, NUMBER_REGEX); +} + +bool PacMap::ParseJsonItemArrayLong(PacMapList &mapList, const std::string &key, Json::Value &item) +{ + Json::Value arrayValue = item["data"]; + + if (arrayValue.isNull()) { + return true; + } + + std::vector longList; + for (Json::ArrayIndex i = 0; i < arrayValue.size(); i++) { + if (!IsNumber(arrayValue[i].asString())) { + return false; + } + long longVal = std::atol(arrayValue[i].asString().c_str()); + longList.push_back(longVal); + } + InnerPutLongValueArray(mapList, key, longList); + return true; +} + +bool PacMap::ParseJsonItemArrayChar(PacMapList &mapList, const std::string &key, Json::Value &item) +{ + Json::Value arrayValue = item["data"]; + if (arrayValue.isNull()) { + return true; + } + + std::vector charList; + for (Json::ArrayIndex i = 0; i < arrayValue.size(); i++) { + charList.push_back(arrayValue[i].asInt()); + } + InnerPutCharValueArray(mapList, key, charList); + return true; +} + +bool PacMap::ParseJsonItemArrayByte(PacMapList &mapList, const std::string &key, Json::Value &item) +{ + Json::Value arrayValue = item["data"]; + if (arrayValue.isNull()) { + return true; + } + + std::vector byteList; + for (Json::ArrayIndex i = 0; i < arrayValue.size(); i++) { + byteList.push_back(arrayValue[i].asInt()); + } + InnerPutByteValueArray(mapList, key, byteList); + return true; +} + +bool PacMap::ParseJsonItemArrayBoolean(PacMapList &mapList, const std::string &key, Json::Value &item) +{ + Json::Value arrayValue = item["data"]; + if (arrayValue.isNull()) { + return true; + } + + std::vector boolList; + for (Json::ArrayIndex i = 0; i < arrayValue.size(); i++) { + boolList.push_back(arrayValue[i].asBool()); + } + InnerPutBooleanValueArray(mapList, key, boolList); + return true; +} + +bool PacMap::ParseJsonItemArrayFloat(PacMapList &mapList, const std::string &key, Json::Value &item) +{ + Json::Value arrayValue = item["data"]; + if (arrayValue.isNull()) { + return true; + } + std::vector floatList; + for (Json::ArrayIndex i = 0; i < arrayValue.size(); i++) { + floatList.push_back(std::atof(arrayValue[i].asString().c_str())); + } + InnerPutFloatValueArray(mapList, key, floatList); + return true; +} + +bool PacMap::ParseJsonItemArrayDouble(PacMapList &mapList, const std::string &key, Json::Value &item) +{ + Json::Value arrayValue = item["data"]; + if (arrayValue.isNull()) { + return true; + } + + std::vector doubleList; + for (Json::ArrayIndex i = 0; i < arrayValue.size(); i++) { + doubleList.push_back(std::atof(arrayValue[i].asString().c_str())); + } + InnerPutDoubleValueArray(mapList, key, doubleList); + return true; +} + +bool PacMap::ParseJsonItemArrayString(PacMapList &mapList, const std::string &key, Json::Value &item) +{ + Json::Value arrayValue = item["data"]; + if (arrayValue.isNull()) { + return true; + } + + std::vector stringList; + for (Json::ArrayIndex i = 0; i < arrayValue.size(); i++) { + stringList.push_back(arrayValue[i].asString()); + } + InnerPutStringValueArray(mapList, key, stringList); + return true; +} + +bool PacMap::InnerPutObjectValue(PacMapList &mapList, const std::string &key, Json::Value &item) +{ + std::string className = item["class"].asString(); + if (className.empty()) { + return false; + } + + UserObjectBase *userObjectIns = UserObjectBaseLoader::GetInstance().GetUserObjectByName(className); + if (userObjectIns == nullptr) { + return false; + } + + std::string userObjectString = item["data"].asString(); + if (!userObjectString.empty()) { + userObjectIns->Parse(userObjectString); + } + + std::shared_ptr userObject(userObjectIns); + InnerPutObject(mapList, key, userObject); + return true; +} + +bool PacMap::InnerPutPacMapValue(PacMapList &mapList, const std::string &key, Json::Value &item) +{ + Json::Value value = item["data"]; + + if (value.isNull()) { + return false; + } + PacMap *p = new (std::nothrow) PacMap(); + if (p == nullptr) { + return false; + } + sptr sp = p; + if (p->ParseJson(value, p->dataList_)) { + mapList.emplace(key, sp); + return true; + } + + return false; +} + +bool PacMap::Equals(IObject &other) +{ + PacMap *otherObj = static_cast(IPacMap::Query(&other)); + if (otherObj == nullptr) { + return false; + } + + return Equals(otherObj); +} + +sptr PacMap::Parse(const std::string &str) +{ + PacMap *pacmap = new (std::nothrow) PacMap(); + if (pacmap != nullptr) { + pacmap->StringToMapList(str, pacmap->dataList_); + } + sptr ret = pacmap; + + return ret; +} + +} // namespace AppExecFwk +} // namespace OHOS diff --git a/tools/frameworks/kits/content/cpp/src/ohos/aafwk/content/patterns_matcher.cpp b/tools/frameworks/kits/content/cpp/src/ohos/aafwk/content/patterns_matcher.cpp new file mode 100755 index 00000000000..b2a07d762a3 --- /dev/null +++ b/tools/frameworks/kits/content/cpp/src/ohos/aafwk/content/patterns_matcher.cpp @@ -0,0 +1,208 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ohos/aafwk/content/patterns_matcher.h" +#include "parcel_macro.h" +using namespace OHOS::AppExecFwk; + +namespace OHOS { +namespace AAFwk { + +/** + * @brief A parameterized constructor used to create a PatternsMatcher instance. + * + */ +PatternsMatcher::PatternsMatcher() +{ + pattern_ = ""; + type_ = MatchType::DEFAULT; +} + +/** + * @brief A parameterized constructor used to create a PatternsMatcher instance. + * + * @param patternsMatcher Indicates patternsMatcher used to create a patternsMatcher instance. + */ +PatternsMatcher::PatternsMatcher(const PatternsMatcher &patternsMatcher) +{ + pattern_ = patternsMatcher.GetPattern(); + type_ = patternsMatcher.GetType(); +} + +/** + * @brief A parameterized constructor used to create a PatternsMatcher instance. + * + * @param pattern Indicates pattern used to create a patternsMatcher instance. + * @param type Indicates type used to create a patternsMatcher instance. + */ +PatternsMatcher::PatternsMatcher(std::string pattern, MatchType type) +{ + pattern_ = pattern; + type_ = type; +} + +PatternsMatcher::~PatternsMatcher() +{} + +/** + * @brief Obtains the pattern. + * + * @return the specified pattern. + */ +std::string PatternsMatcher::GetPattern() const +{ + return pattern_; +} + +/** + * @brief Obtains the specified type. + * + * @return the specified type. + */ +MatchType PatternsMatcher::GetType() const +{ + return type_; +} + +/** + * @brief Match this PatternsMatcher against a string data. + * + * @param str The desired string to look for. + * @return Returns either a valid match constant. + */ +bool PatternsMatcher::match(std::string match) +{ + return MatchPattern(pattern_, match, type_); +} + +/** + * @brief Match this PatternsMatcher against an Pattern's data. + * + * @param pattern The desired data to look for. + * @param match The full data string to match against. + * @param type The desired tyoe to look for. + * + * @return Returns either a valid match constant. + */ +bool PatternsMatcher::MatchPattern(std::string pattern, std::string match, MatchType type) +{ + if (match.empty()) { + return false; + } + switch (type) { + case MatchType::DEFAULT: { + return pattern == match; + } + case MatchType::PREFIX: { + return match.find(pattern) == 0; + } + case MatchType::PATTERN: { + std::regex regex_(pattern); + return regex_match(match, regex_); + } + case MatchType::GLOBAL: { + return GlobPattern(pattern, match); + } + default: { + APP_LOGE("MatchPattern::The other type"); + return false; + } + } +} + +/** + * @brief Match this PatternsMatcher against an Pattern's data. + * + * @param pattern The desired data to look for. + * @param match The full data string to match against. + * + * @return Returns either a valid match constant. + */ +bool PatternsMatcher::GlobPattern(std::string pattern, std::string match) +{ + size_t indexP = 0; + size_t find_pos = 0; + size_t indexM = 0; + while (indexP < pattern.length() && find_pos != std::string::npos) { + find_pos = pattern.find("*", indexP); + std::string p; + if (find_pos == std::string::npos) { + p = pattern.substr(indexP, pattern.length()); + } else { + p = pattern.substr(indexP, find_pos - indexP); + } + if (p.length() == 0) { + indexP = indexP + 1; + continue; + } + size_t find_pos_m = match.find(p, indexM); + if (find_pos_m == std::string::npos) { + return false; + } + indexP = find_pos; + indexM = find_pos_m + p.length(); + } + if (indexM < match.length() && !(pattern.rfind("*") == pattern.length() - 1)) { + return false; + } + return true; +} + +/** + * @brief Marshals this Sequenceable object into a Parcel. + * + * @param outParcel Indicates the Parcel object to which the Sequenceable object will be marshaled. + */ +bool PatternsMatcher::Marshalling(Parcel &parcel) const +{ + // write pattern_ + WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(String16, parcel, Str8ToStr16(pattern_)); + // type_ + WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(Int32, parcel, static_cast(type_)); + + return true; +} + +/** + * @brief Unmarshals this Sequenceable object from a Parcel. + * + * @param inParcel Indicates the Parcel object into which the Sequenceable object has been marshaled. + */ +PatternsMatcher *PatternsMatcher::Unmarshalling(Parcel &parcel) +{ + PatternsMatcher *patternsMatcher = new (std::nothrow) PatternsMatcher(); + if (patternsMatcher != nullptr && !patternsMatcher->ReadFromParcel(parcel)) { + delete patternsMatcher; + patternsMatcher = nullptr; + } + return patternsMatcher; +} + +bool PatternsMatcher::ReadFromParcel(Parcel &parcel) +{ + // pattern_ + std::u16string readString16; + READ_PARCEL_AND_RETURN_FALSE_IF_FAIL(String16, parcel, readString16); + pattern_ = Str16ToStr8(readString16); + + // flags_ + int32_t type; + READ_PARCEL_AND_RETURN_FALSE_IF_FAIL(Int32, parcel, type); + type_ = static_cast(type); + + return true; +} +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/content/cpp/src/ohos/aafwk/content/skills.cpp b/tools/frameworks/kits/content/cpp/src/ohos/aafwk/content/skills.cpp new file mode 100755 index 00000000000..d40eae1f17a --- /dev/null +++ b/tools/frameworks/kits/content/cpp/src/ohos/aafwk/content/skills.cpp @@ -0,0 +1,1066 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ohos/aafwk/content/skills.h" +#include "parcel_macro.h" +using namespace OHOS; +using namespace OHOS::AppExecFwk; +namespace OHOS { +namespace AAFwk { + +const int LENGTH_FOR_FINDMINETYPE = 3; +/** + * @brief Default constructor used to create a Skills instance. + */ +Skills::Skills() +{} + +/** + * @brief A parameterized constructor used to create a Skills instance. + * + * @param skills Indicates skills used to create a Skills instance. + */ +Skills::Skills(const Skills &skills) +{ + // entities_ + entities_ = skills.entities_; + // actions_ + actions_ = skills.actions_; + // authorities_ + authorities_ = skills.authorities_; + // schemes_ + schemes_ = skills.schemes_; + + // paths_ + paths_ = skills.paths_; + // schemeSpecificParts_ + schemeSpecificParts_ = skills.schemeSpecificParts_; + // types_ + types_ = skills.types_; +} + +Skills::~Skills() +{ + entities_.clear(); + actions_.clear(); + authorities_.clear(); + schemes_.clear(); + + paths_.clear(); + schemeSpecificParts_.clear(); + types_.clear(); +} + +/** + * @brief Obtains the list of entities. + * + * @return vector of Entities. + */ +std::vector Skills::GetEntities() const +{ + return entities_; +} + +/** + * @brief Obtains the specified entity. + * + * @param entity Id of the specified entity. + */ +std::string Skills::GetEntity(int index) const +{ + if (index < 0 || entities_.empty() || std::size_t(index) >= entities_.size()) { + return std::string(); + } + return entities_.at(index); +} + +/** + * @brief Adds an entity to this Skills object. + * + * @param entity Indicates the entity to add. + */ +void Skills::AddEntity(const std::string &entity) +{ + auto it = std::find(entities_.begin(), entities_.end(), entity); + if (it == entities_.end()) { + entities_.emplace_back(entity); + } +} + +/** + * @brief Checks whether the specified entity is exist. + * + * @param entity Name of the specified entity. + */ +bool Skills::HasEntity(const std::string &entity) +{ + return std::find(entities_.begin(), entities_.end(), entity) != entities_.end(); +} + +/** + * @brief Remove the specified entity. + * + * @param entity Name of the specified entity. + */ +void Skills::RemoveEntity(const std::string &entity) +{ + if (!entities_.empty()) { + auto it = std::find(entities_.begin(), entities_.end(), entity); + if (it != entities_.end()) { + entities_.erase(it); + } + } +} + +/** + * @brief Obtains the count of entities. + * + */ +int Skills::CountEntities() const +{ + return entities_.empty() ? 0 : entities_.size(); +} + +/** + * @brief Obtains the specified action. + * + * @param actionId Id of the specified action. + */ +std::string Skills::GetAction(int index) const +{ + if (index < 0 || actions_.empty() || std::size_t(index) >= actions_.size()) { + return std::string(); + } else { + return actions_.at(index); + } +} + +/** + * @brief Adds an action to this Skills object. + * + * @param action Indicates the action to add. + */ +void Skills::AddAction(const std::string &action) +{ + auto it = std::find(actions_.begin(), actions_.end(), action); + if (it == actions_.end()) { + actions_.emplace_back(action); + } +} + +/** + * @brief Checks whether the specified action is exist. + * + * @param action Name of the specified action. + */ +bool Skills::HasAction(const std::string &action) +{ + return std::find(actions_.begin(), actions_.end(), action) != actions_.end(); +} + +/** + * @brief Remove the specified action. + * + * @param action Name of the specified action. + */ +void Skills::RemoveAction(const std::string &action) +{ + if (!actions_.empty()) { + auto it = std::find(actions_.begin(), actions_.end(), action); + if (it != actions_.end()) { + actions_.erase(it); + } + } +} + +/** + * @brief Obtains the count of actions. + * + */ +int Skills::CountActions() const +{ + return actions_.empty() ? 0 : actions_.size(); +} + +/** + * @brief Obtains the iterator of Actions. + * + * @return iterator of Actions. + */ +std::vector::iterator Skills::ActionsIterator() +{ + return actions_.begin(); +} + +/** + * @brief Obtains the specified authority. + * + * @param authorityId Id of the specified authority. + */ +std::string Skills::GetAuthority(int index) const +{ + if (index < 0 || authorities_.empty() || std::size_t(index) >= authorities_.size()) { + return std::string(); + } else { + return authorities_.at(index); + } +} + +/** + * @brief Adds an authority to this Skills object. + * + * @param authority Indicates the authority to add. + */ +void Skills::AddAuthority(const std::string &authority) +{ + auto it = std::find(authorities_.begin(), authorities_.end(), authority); + if (it == authorities_.end()) { + authorities_.emplace_back(authority); + } +} + +/** + * @brief Checks whether the specified authority is exist. + * + * @param action Name of the specified authority. + */ +bool Skills::HasAuthority(const std::string &authority) +{ + return std::find(authorities_.begin(), authorities_.end(), authority) != authorities_.end(); +} + +/** + * @brief Remove the specified authority. + * + * @param authority Name of the specified authority. + */ +void Skills::RemoveAuthority(const std::string &authority) +{ + if (!authorities_.empty()) { + auto it = std::find(authorities_.begin(), authorities_.end(), authority); + if (it != authorities_.end()) { + authorities_.erase(it); + } + } +} + +/** + * @brief Obtains the count of authorities. + * + */ +int Skills::CountAuthorities() const +{ + return authorities_.empty() ? 0 : authorities_.size(); +} + +/** + * @brief Obtains the specified path. + * + * @param pathId Id of the specified path. + */ +std::string Skills::GetPath(int index) const +{ + if (index < 0 || paths_.empty() || std::size_t(index) >= paths_.size()) { + return std::string(); + } + return paths_.at(index).GetPattern(); +} + +/** + * @brief Adds a path to this Skills object. + * + * @param path Indicates the path to add. + */ +void Skills::AddPath(const std::string &path) +{ + PatternsMatcher pm(path, MatchType::DEFAULT); + AddPath(pm); +} + +/** + * @brief Adds a path to this Skills object. + * + * @param path Indicates the path to add. + */ +void Skills::AddPath(const PatternsMatcher &patternsMatcher) +{ + auto hasPath = std::find_if(paths_.begin(), paths_.end(), [&patternsMatcher](const PatternsMatcher pm) { + return (pm.GetPattern() == patternsMatcher.GetPattern()) && (pm.GetType() == patternsMatcher.GetType()); + }); + + if (hasPath == paths_.end()) { + paths_.emplace_back(patternsMatcher); + } +} + +/** + * @brief Adds a path to this Skills object. + * + * @param path Indicates the path to add. + * @param matchType the specified match type. + */ +void Skills::AddPath(const std::string &path, const MatchType &matchType) +{ + PatternsMatcher pm(path, matchType); + AddPath(pm); +} + +/** + * @brief Checks whether the specified path is exist. + * + * @param path Name of the specified path. + */ +bool Skills::HasPath(const std::string &path) +{ + auto hasPath = std::find_if( + paths_.begin(), paths_.end(), [&path](const PatternsMatcher pm) { return pm.GetPattern() == path; }); + return hasPath != paths_.end(); +} + +/** + * @brief Remove the specified path. + * + * @param path Name of the specified path. + */ +void Skills::RemovePath(const std::string &path) +{ + auto hasPath = std::find_if( + paths_.begin(), paths_.end(), [&path](const PatternsMatcher pm) { return pm.GetPattern() == path; }); + + if (hasPath != paths_.end()) { + paths_.erase(hasPath); + } +} + +/** + * @brief Remove the specified path. + * + * @param path The path to be added. + */ +void Skills::RemovePath(const PatternsMatcher &patternsMatcher) +{ + auto hasPath = std::find_if(paths_.begin(), paths_.end(), [&patternsMatcher](const PatternsMatcher pm) { + return (pm.GetPattern() == patternsMatcher.GetPattern()) && (pm.GetType() == patternsMatcher.GetType()); + }); + + if (hasPath != paths_.end()) { + paths_.erase(hasPath); + } +} + +/** + * @brief Remove the specified path. + * + * @param path Name of the specified path. + * @param matchType the specified match type. + */ +void Skills::RemovePath(const std::string &path, const MatchType &matchType) +{ + PatternsMatcher pm(path, matchType); + RemovePath(pm); +} + +/** + * @brief Obtains the count of paths. + * + */ +int Skills::CountPaths() const +{ + return paths_.empty() ? 0 : paths_.size(); +} + +/** + * @brief Obtains the specified scheme. + * + * @param schemeId Id of the specified scheme. + */ +std::string Skills::GetScheme(int index) const +{ + if (index < 0 || schemes_.empty() || std::size_t(index) >= schemes_.size()) { + return std::string(); + } + return schemes_.at(index); +} + +/** + * @brief Adds an scheme to this Skills object. + * + * @param scheme Indicates the scheme to add. + */ +void Skills::AddScheme(const std::string &scheme) +{ + auto it = std::find(schemes_.begin(), schemes_.end(), scheme); + if (it == schemes_.end()) { + schemes_.emplace_back(scheme); + } +} + +/** + * @brief Checks whether the specified scheme is exist. + * + * @param scheme Name of the specified scheme. + */ +bool Skills::HasScheme(const std::string &scheme) +{ + return std::find(schemes_.begin(), schemes_.end(), scheme) != schemes_.end(); +} + +/** + * @brief Remove the specified scheme. + * + * @param scheme Name of the specified scheme. + */ +void Skills::RemoveScheme(const std::string &scheme) +{ + if (!schemes_.empty()) { + auto it = std::find(schemes_.begin(), schemes_.end(), scheme); + if (it != schemes_.end()) { + schemes_.erase(it); + } + } +} + +/** + * @brief Obtains the count of schemes. + * + */ +int Skills::CountSchemes() const +{ + return schemes_.empty() ? 0 : schemes_.size(); +} + +/** + * @brief Obtains the specified scheme part. + * + * @param schemeId Id of the specified scheme part. + */ +std::string Skills::GetSchemeSpecificPart(int index) const +{ + if (index < 0 || schemeSpecificParts_.empty() || std::size_t(index) >= schemeSpecificParts_.size()) { + return std::string(); + } + return schemeSpecificParts_.at(index).GetPattern(); +} + +/** + * @brief Adds an scheme to this Skills object. + * + * @param scheme Indicates the scheme to add. + */ +void Skills::AddSchemeSpecificPart(const std::string &schemeSpecificPart) +{ + PatternsMatcher patternsMatcher(schemeSpecificPart, MatchType::DEFAULT); + auto it = std::find_if( + schemeSpecificParts_.begin(), schemeSpecificParts_.end(), [&patternsMatcher](const PatternsMatcher pm) { + return (pm.GetPattern() == patternsMatcher.GetPattern()) && (pm.GetType() == patternsMatcher.GetType()); + }); + + if (it == schemeSpecificParts_.end()) { + schemeSpecificParts_.emplace_back(patternsMatcher); + } +} + +/** + * @brief Checks whether the specified scheme part is exist. + * + * @param scheme Name of the specified scheme part. + */ +bool Skills::HasSchemeSpecificPart(const std::string &schemeSpecificPart) +{ + auto it = std::find_if(schemeSpecificParts_.begin(), + schemeSpecificParts_.end(), + [&schemeSpecificPart](const PatternsMatcher pm) { return pm.GetPattern() == schemeSpecificPart; }); + return it != schemeSpecificParts_.end(); +} + +/** + * @brief Remove the specified scheme part. + * + * @param scheme Name of the specified scheme part. + */ +void Skills::RemoveSchemeSpecificPart(const std::string &schemeSpecificPart) +{ + auto it = std::find_if(schemeSpecificParts_.begin(), + schemeSpecificParts_.end(), + [&schemeSpecificPart](const PatternsMatcher pm) { return pm.GetPattern() == schemeSpecificPart; }); + + if (it != schemeSpecificParts_.end()) { + schemeSpecificParts_.erase(it); + } +} + +/** + * @brief Obtains the count of scheme parts. + * + */ +int Skills::CountSchemeSpecificParts() const +{ + return schemeSpecificParts_.empty() ? 0 : schemeSpecificParts_.size(); +} + +/** + * @brief Obtains the specified type. + * + * @param typeId Id of the specified type. + */ +std::string Skills::GetType(int index) const +{ + if (index < 0 || types_.empty() || std::size_t(index) >= types_.size()) { + return std::string(); + } + return types_.at(index).GetPattern(); +} + +/** + * @brief Adds a type to this Skills object. + * + * @param type Indicates the type to add. + */ +void Skills::AddType(const std::string &type) +{ + PatternsMatcher pm(type, MatchType::DEFAULT); + AddType(pm); +} + +/** + * @brief Adds a type to this Skills object. + * + * @param type Indicates the type to add. + * @param matchType the specified match type. + */ +void Skills::AddType(const std::string &type, const MatchType &matchType) +{ + PatternsMatcher pm(type, matchType); + AddType(pm); +} + +/** + * @brief Adds a type to this Skills object. + * + * @param type Indicates the type to add. + */ +void Skills::AddType(const PatternsMatcher &patternsMatcher) +{ + const size_t posNext = 1; + const size_t posOffset = 2; + std::string type = patternsMatcher.GetPattern(); + size_t slashpos = type.find('/'); + size_t typelen = type.length(); + if (slashpos != std::string::npos && typelen >= slashpos + posOffset) { + if (typelen == slashpos + posOffset && type.at(slashpos + posNext) == '*') { + PatternsMatcher pm(type.substr(0, slashpos), patternsMatcher.GetType()); + auto it = std::find_if(types_.begin(), + types_.end(), + [type = pm.GetPattern(), matchType = pm.GetType()]( + const PatternsMatcher pm) { return (pm.GetPattern() == type) && (pm.GetType() == matchType); }); + if (it == types_.end()) { + types_.emplace_back(pm); + } + hasPartialTypes_ = true; + } else { + PatternsMatcher pm(patternsMatcher); + auto it = std::find_if(types_.begin(), + types_.end(), + [type = pm.GetPattern(), matchType = pm.GetType()]( + const PatternsMatcher pm) { return (pm.GetPattern() == type) && (pm.GetType() == matchType); }); + if (it == types_.end()) { + types_.emplace_back(pm); + } + } + } +} + +/** + * @brief Checks whether the specified type is exist. + * + * @param type Name of the specified type. + */ +bool Skills::HasType(const std::string &type) +{ + auto it = std::find_if( + types_.begin(), types_.end(), [&type](const PatternsMatcher pm) { return pm.GetPattern() == type; }); + return it != types_.end(); +} + +/** + * @brief Remove the specified type. + * + * @param type Name of the specified type. + */ +void Skills::RemoveType(const std::string &type) +{ + auto it = std::find_if( + types_.begin(), types_.end(), [&type](const PatternsMatcher pm) { return pm.GetPattern() == type; }); + + if (it != types_.end()) { + types_.erase(it); + } +} + +/** + * @brief Remove the specified scheme type. + * + * @param patternsMatcher The type to be added. + */ +void Skills::RemoveType(const PatternsMatcher &patternsMatcher) +{ + auto it = std::find_if(types_.begin(), types_.end(), [&patternsMatcher](const PatternsMatcher pm) { + return (pm.GetPattern() == patternsMatcher.GetPattern()) && (pm.GetType() == patternsMatcher.GetType()); + }); + + if (it != types_.end()) { + types_.erase(it); + } +} + +/** + * @brief Remove the specified scheme type. + * + * @param type Name of the specified type. + * @param matchType the specified match type. + */ +void Skills::RemoveType(const std::string &type, const MatchType &matchType) +{ + PatternsMatcher pm(type, matchType); + RemoveType(pm); +} + +/** + * @brief Obtains the count of types. + * + */ +int Skills::CountTypes() const +{ + return types_.empty() ? 0 : types_.size(); +} + +/** + * @brief Match this skill against a Want's data. + * + * @param want The desired want data to match for. + */ +bool Skills::Match(const Want &want) +{ + if (want.GetAction() != std::string() && !MatchAction(want.GetAction())) { + return false; + } + + int dataMatch = MatchData(want.GetType(), want.GetScheme(), want.GetUri()); + if (dataMatch < 0) { + return false; + } + + std::string entityMismatch = MatchEntities(want.GetEntities()); + if (entityMismatch == std::string()) { + return false; + } + + return true; +} + +/** + * @brief Match this skills against a Want's entities. Each entity in + * the Want must be specified by the skills; if any are not in the + * skills, the match fails. + * + * @param entities The entities included in the want, as returned by + * Want.getEntities(). + * + * @return If all entities match (success), null; else the name of the + * first entity that didn't match. + */ +std::string Skills::MatchEntities(const std::vector &entities) +{ + if (!entities.empty()) { + size_t size = entities.size(); + for (size_t i = 0; i < size; i++) { + auto it = std::find(entities_.begin(), entities_.end(), entities[i]); + if (it != entities_.end()) { + return entities[i]; + } + } + } + + return std::string(); +} + +/** + * @brief Match this skills against a Want's action. If the skills does not + * specify any actions, the match will always fail. + * + * @param action The desired action to look for. + * + * @return True if the action is listed in the skills. + */ +bool Skills::MatchAction(const std::string &action) +{ + return HasAction(action); +} + +/** + * @brief Match this skills against a Want's data (type, scheme and path). + * + * @param type The desired data type to look for. + * @param scheme The desired data scheme to look for. + * @param data The full data string to match against. + * + * @return Returns either a valid match constant. + */ +int Skills::MatchData(const std::string &type, const std::string &scheme, Uri data) +{ + std::vector types; + for (auto it = types_.begin(); it != types_.end(); it++) { + types.emplace_back(it->GetPattern()); + } + std::vector schemes = schemes_; + + int match = RESULT_EMPTY; + + if (types.empty() && schemes.empty()) { + return (type == std::string() ? (RESULT_EMPTY + RESULT_NORMAL) : DISMATCH_DATA); + } + + if (!schemes.empty()) { + auto it = std::find(schemes.begin(), schemes.end(), scheme); + if (it != schemes.end()) { + match = RESULT_SCHEME; + } else { + return DISMATCH_DATA; + } + + std::vector schemeSpecificParts = schemeSpecificParts_; + if (schemeSpecificParts.size() >= 0) { + match = HasSchemeSpecificPart(data.GetSchemeSpecificPart()) ? RESULT_SCHEME_SPECIFIC_PART : DISMATCH_DATA; + } + if (match != RESULT_SCHEME_SPECIFIC_PART) { + std::vector authorities = authorities_; + if (authorities.size() >= 0) { + bool authMatch = HasAuthority(data.GetAuthority()); + if (authMatch == true) { + std::vector paths = paths_; + if (paths.size() <= 0) { + match = authMatch; + } else if (HasPath(data.GetPath())) { + match = RESULT_PATH; + } else { + return DISMATCH_DATA; + } + } else { + return DISMATCH_DATA; + } + } + } + if (match == DISMATCH_DATA) { + return DISMATCH_DATA; + } + } else { + if (scheme != std::string() && scheme != "content" && scheme != "file") { + return DISMATCH_DATA; + } + } + + if (!types.empty()) { + if (FindMimeType(type)) { + match = RESULT_TYPE; + } else { + return DISMATCH_TYPE; + } + } else { + if (type != std::string()) { + return DISMATCH_TYPE; + } + } + + return match + RESULT_NORMAL; +} + +bool Skills::FindMimeType(const std::string &type) +{ + const int posNext = 1; + const int posOffset = 2; + std::vector types = types_; + + if (type == std::string()) { + return false; + } + auto it = types.begin(); + for (; it != types.end(); it++) { + if (it->GetPattern() == type) { + break; + } + } + if (it != types.end()) { + return true; + } + + int typeLength = type.length(); + if (typeLength == LENGTH_FOR_FINDMINETYPE && type == "*/*") { + return !types.empty(); + } + + auto hasType = + std::find_if(types.begin(), types.end(), [](const PatternsMatcher pm) { return pm.GetPattern() == "*"; }); + if (hasPartialTypes_ && hasType != types.end()) { + return true; + } + + auto typeIt = type.find(0, 1, '/'); + int slashpos = type.size() - typeIt; + if (slashpos > 0) { + std::string typeSubstr = type.substr(0, slashpos); + + auto hasType = std::find_if(types.begin(), types.end(), [&typeSubstr](const PatternsMatcher pm) { + return pm.GetPattern() == typeSubstr; + }); + if (hasPartialTypes_ && hasType != types.end()) { + return true; + } + + if (typeLength == slashpos + posOffset && type.at(slashpos + posNext) == '*') { + int numTypes = types.size(); + for (int i = 0; i < numTypes; i++) { + std::string value = types.at(i).GetPattern(); + if (RegionMatches(type, 0, value, 0, slashpos + posNext)) { + return true; + } + } + } + } + + return false; +} + +bool Skills::RegionMatches(const std::string &type, int toffset, const std::string &other, int ooffset, int len) +{ + int to = toffset; + int po = ooffset; + // Note: toffset, ooffset, or len might be near -1>>>1. + if ((ooffset < 0) || (toffset < 0) || (toffset > (long)type.size() - len) || + (ooffset > (long)other.length() - len)) { + return false; + } + while (len-- > 0) { + if (type.at(to++) != other.at(po++)) { + return false; + } + } + return true; +} + +/** + * @brief Obtains the want params data. + * + * @return the WantParams object. + */ +const WantParams &Skills::GetWantParams() const +{ + return wantParams_; +} + +/** + * @brief Sets a WantParams object in this MatchingSkills object. + * + * @param wantParams Indicates the WantParams object. + */ +void Skills::SetWantParams(const WantParams &wantParams) +{ + wantParams_ = wantParams; +} + +/** + * @brief Marshals this Sequenceable object into a Parcel. + * + * @param outParcel Indicates the Parcel object to which the Sequenceable object will be marshaled. + */ +bool Skills::Marshalling(Parcel &parcel) const +{ + // entities​_ + WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(StringVector, parcel, entities_); + // actions_ + WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(StringVector, parcel, actions_); + // authorities_ + WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(StringVector, parcel, authorities_); + // schemes_ + WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(StringVector, parcel, schemes_); + // paths_ + if (paths_.empty()) { + WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(Int32, parcel, VALUE_NULL); + } else { + if (!parcel.WriteInt32(VALUE_OBJECT)) { + return false; + } + WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(Int32, parcel, paths_.size()); + for (auto path : paths_) { + if (!parcel.WriteParcelable(&path)) { + return false; + } + } + } + // schemeSpecificParts_ + if (schemeSpecificParts_.empty()) { + WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(Int32, parcel, VALUE_NULL); + } else { + if (!parcel.WriteInt32(VALUE_OBJECT)) { + return false; + } + WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(Int32, parcel, schemeSpecificParts_.size()); + for (auto schemeSpecificPart : schemeSpecificParts_) { + if (!parcel.WriteParcelable(&schemeSpecificPart)) { + return false; + } + } + } + // types_ + if (types_.empty()) { + WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(Int32, parcel, VALUE_NULL); + } else { + if (!parcel.WriteInt32(VALUE_OBJECT)) { + return false; + } + WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(Int32, parcel, types_.size()); + for (auto type : types_) { + if (!parcel.WriteParcelable(&type)) { + return false; + } + } + } + + // parameters_ + if (wantParams_.GetParams().empty()) { + WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(Int32, parcel, VALUE_NULL); + } else { + if (!parcel.WriteInt32(VALUE_OBJECT)) { + return false; + } + if (!parcel.WriteParcelable(&wantParams_)) { + return false; + } + } + return true; +} + +/** + * @brief Unmarshals this Sequenceable object from a Parcel. + * + * @param inParcel Indicates the Parcel object into which the Sequenceable object has been marshaled. + */ +Skills *Skills::Unmarshalling(Parcel &parcel) +{ + Skills *skills = new (std::nothrow) Skills(); + if (skills != nullptr) { + if (!skills->ReadFromParcel(parcel)) { + delete skills; + skills = nullptr; + } + } + return skills; +} + +bool Skills::ReadFromParcel(Parcel &parcel) +{ + int32_t empty; + int32_t size = 0; + PatternsMatcher *pm = nullptr; + + // entities​_ + READ_PARCEL_AND_RETURN_FALSE_IF_FAIL(StringVector, parcel, &entities_); + // actions_ + READ_PARCEL_AND_RETURN_FALSE_IF_FAIL(StringVector, parcel, &actions_); + // authorities_ + READ_PARCEL_AND_RETURN_FALSE_IF_FAIL(StringVector, parcel, &authorities_); + // schemes_ + READ_PARCEL_AND_RETURN_FALSE_IF_FAIL(StringVector, parcel, &schemes_); + // paths_ + empty = VALUE_NULL; + if (!parcel.ReadInt32(empty)) { + return false; + } + + if (empty == VALUE_OBJECT) { + READ_PARCEL_AND_RETURN_FALSE_IF_FAIL(Int32, parcel, size); + for (int i = 0; i < size; i++) { + pm = parcel.ReadParcelable(); + if (pm == nullptr) { + return false; + } else { + paths_.emplace_back(*pm); + delete pm; + pm = nullptr; + } + } + } + + // schemeSpecificParts_ + empty = VALUE_NULL; + if (!parcel.ReadInt32(empty)) { + return false; + } + + if (empty == VALUE_OBJECT) { + READ_PARCEL_AND_RETURN_FALSE_IF_FAIL(Int32, parcel, size); + for (int i = 0; i < size; i++) { + pm = parcel.ReadParcelable(); + if (pm == nullptr) { + return false; + } else { + schemeSpecificParts_.emplace_back(*pm); + delete pm; + pm = nullptr; + } + } + } + + // types_ + empty = VALUE_NULL; + if (!parcel.ReadInt32(empty)) { + return false; + } + + if (empty == VALUE_OBJECT) { + READ_PARCEL_AND_RETURN_FALSE_IF_FAIL(Int32, parcel, size); + for (int i = 0; i < size; i++) { + pm = parcel.ReadParcelable(); + if (pm == nullptr) { + return false; + } else { + types_.emplace_back(*pm); + delete pm; + pm = nullptr; + } + } + } + + // parameters_ + empty = VALUE_NULL; + if (!parcel.ReadInt32(empty)) { + return false; + } + + if (empty == VALUE_OBJECT) { + auto params = parcel.ReadParcelable(); + if (params != nullptr) { + wantParams_ = *params; + delete params; + params = nullptr; + } else { + return false; + } + } + + return true; +} + +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/content/cpp/src/ohos/aafwk/content/want.cpp b/tools/frameworks/kits/content/cpp/src/ohos/aafwk/content/want.cpp new file mode 100755 index 00000000000..29d7e06d9e3 --- /dev/null +++ b/tools/frameworks/kits/content/cpp/src/ohos/aafwk/content/want.cpp @@ -0,0 +1,1893 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "want.h" +#include +#include +#include +#include "string_ex.h" +#include "parcel_macro.h" +#include "ohos/aafwk/base/array_wrapper.h" +#include "ohos/aafwk/base/base_object.h" +#include "ohos/aafwk/base/bool_wrapper.h" +#include "ohos/aafwk/base/zchar_wrapper.h" +#include "ohos/aafwk/base/byte_wrapper.h" +#include "ohos/aafwk/base/short_wrapper.h" +#include "ohos/aafwk/base/int_wrapper.h" +#include "ohos/aafwk/base/long_wrapper.h" +#include "ohos/aafwk/base/float_wrapper.h" +#include "ohos/aafwk/base/double_wrapper.h" +#include "ohos/aafwk/base/string_wrapper.h" +#include "ohos/aafwk/base/zchar_wrapper.h" + +using namespace OHOS::AppExecFwk; +using OHOS::AppExecFwk::ElementName; + +namespace OHOS { +namespace AAFwk { + +const std::string Want::ACTION_PLAY("action.system.play"); +const std::string Want::ACTION_HOME("action.system.home"); + +const std::string Want::ENTITY_HOME("entity.system.home"); +const std::string Want::ENTITY_VIDEO("entity.system.video"); +const std::string Want::FLAG_HOME_INTENT_FROM_SYSTEM("flag.home.intent.from.system"); + +const std::string Want::OCT_EQUALSTO("075"); // '=' +const std::string Want::OCT_SEMICOLON("073"); // ';' +const std::string Want::MIME_TYPE("mime-type"); +const std::string Want::WANT_HEADER("#Intent;"); + +/** + * @description:Default construcotr of Want class, which is used to initialzie flags and URI. + * @param None + * @return None + */ +Want::Want() : picker_(nullptr) +{} + +/** + * @description: Default deconstructor of Want class + * @param None + * @return None + */ +Want::~Want() +{} + +/** + * @description: Copy construcotr of Want class, which is used to initialzie flags, URI, etc. + * @param want the source instance of Want. + * @return None + */ +Want::Want(const Want &other) +{ + picker_ = other.picker_; + operation_ = other.operation_; + parameters_ = other.parameters_; +} + +Want &Want::operator=(const Want &other) +{ + picker_ = other.picker_; + operation_ = other.operation_; + parameters_ = other.parameters_; + return *this; +} + +/** + * @description: Obtains the description of flags in a Want. + * @return Returns the flag description in the Want. + */ +unsigned int Want::GetFlags() const +{ + return operation_.GetFlags(); +} + +/** + * @description: Sets a flag in a Want. + * @param flags Indicates the flag to set. + * @return Returns this Want object containing the flag. + */ +Want &Want::SetFlags(unsigned int flags) +{ + operation_.SetFlags(flags); + return *this; +} + +/** + * @description: Adds a flag to a Want. + * @param flags Indicates the flag to add. + * @return Returns the Want object with the added flag. + */ +Want &Want::AddFlags(unsigned int flags) +{ + operation_.AddFlags(flags); + return *this; +} + +/** + * @description: Removes the description of a flag from a Want. + * @param flags Indicates the flag to remove. + * @return Removes the description of a flag from a Want. + */ +void Want::RemoveFlags(unsigned int flags) +{ + operation_.RemoveFlags(flags); +} + +/** + * @description: Obtains the description of the ElementName object in a Want. + * @return Returns the ElementName description in the Want. + */ +OHOS::AppExecFwk::ElementName Want::GetElement() const +{ + return ElementName(operation_.GetDeviceId(), operation_.GetBundleName(), operation_.GetAbilityName()); +} + +/** + * @description: Sets the bundleName and abilityName attributes for this Want object. + * @param bundleName Indicates the bundleName to set for the operation attribute in the Want. + * @param abilityName Indicates the abilityName to set for the operation attribute in the Want. + * @return Returns this Want object that contains the specified bundleName and abilityName attributes. + */ +Want &Want::SetElementName(const std::string &bundleName, const std::string &abilityName) +{ + if (bundleName.empty() || abilityName.empty()) { + APP_LOGE("Want::SetElementName : The bundleName and abilityName can't be empty."); + return *this; + } + + operation_.SetBundleName(bundleName); + operation_.SetAbilityName(abilityName); + return *this; +} + +/** + * @description: Sets the bundleName and abilityName attributes for this Want object. + * @param deviceId Indicates the deviceId to set for the operation attribute in the Want. + * @param bundleName Indicates the bundleName to set for the operation attribute in the Want. + * @param abilityName Indicates the abilityName to set for the operation attribute in the Want. + * @return Returns this Want object that contains the specified bundleName and abilityName attributes. + */ +Want &Want::SetElementName(const std::string &deviceId, const std::string &bundleName, const std::string &abilityName) +{ + if (bundleName.empty() || abilityName.empty()) { + APP_LOGE("Want::SetElementName : The bundleName and abilityName can't be empty."); + return *this; + } + operation_.SetDeviceId(deviceId); + operation_.SetBundleName(bundleName); + operation_.SetAbilityName(abilityName); + return *this; +} + +/** + * @description: Sets an ElementName object in a Want. + * @param element Indicates the ElementName description. + * @return Returns this Want object containing the ElementName + */ +Want &Want::SetElement(const OHOS::AppExecFwk::ElementName &element) +{ + operation_.SetDeviceId(element.GetDeviceID()); + operation_.SetBundleName(element.GetBundleName()); + operation_.SetAbilityName(element.GetAbilityName()); + return *this; +} + +/** + * @description: Obtains the description of all entities in a Want. + * @return Returns a set of entities + */ +const std::vector &Want::GetEntities() const +{ + return operation_.GetEntities(); +} + +/** + * @description: Adds the description of an entity to a Want + * @param entity Indicates the entity description to add + * @return Returns this Want object containing the entity. + */ +Want &Want::AddEntity(const std::string &entity) +{ + operation_.AddEntity(entity); + return *this; +} + +/** + * @description: Removes the description of an entity from a Want + * @param entity Indicates the entity description to remove. + * @return void + */ +void Want::RemoveEntity(const std::string &entity) +{ + operation_.RemoveEntity(entity); +} + +/** + * @description: Checks whether a Want contains the given entity + * @param entity Indicates the entity to check + * @return Returns true if the given entity is contained; returns false otherwise + */ +bool Want::HasEntity(const std::string &entity) const +{ + return operation_.HasEntity(entity); +} + +/** + * @description: Obtains the number of entities in a Want + * @return Returns the entity quantity + */ +int Want::CountEntities() +{ + return operation_.CountEntities(); +} + +/** + * @description: Obtains the name of the bundle specified in a Want + * @return Returns the bundle name specified in the Want + */ +std::string Want::GetBundle() const +{ + return operation_.GetBundleName(); +} + +/** + * @description: Sets a bundle name in this Want. + * If a bundle name is specified in a Want, the Want will match only + * the abilities in the specified bundle. You cannot use this method and + * setPicker(ohos.aafwk.content.Want) on the same Want. + * @param bundleName Indicates the bundle name to set. + * @return Returns a Want object containing the specified bundle name. + */ +Want &Want::SetBundle(const std::string &bundleName) +{ + operation_.SetBundleName(bundleName); + return *this; +} + +/** + * @description: Obtains the description of the type in this Want + * @return Returns the type description in this Want + */ +std::string Want::GetType() const +{ + auto value = parameters_.GetParam(MIME_TYPE); + IString *ao = IString::Query(value); + if (ao != nullptr) { + return String::Unbox(ao); + } + return std::string(); +} + +/** + * @description: Sets the description of a type in this Want + * @param type Indicates the type description + * @return Returns this Want object containing the type + */ +Want &Want::SetType(const std::string &type) +{ + sptr valueObj = String::Parse(type); + parameters_.SetParam(MIME_TYPE, valueObj); + return *this; +} + +/** + * @description: Formats a specified MIME type. This method uses + * the formatMimeType(java.lang.String) method to format a MIME type + * and then saves the formatted type to this Want object. + * @param type Indicates the MIME type to format + * @return Returns this Want object that contains the formatted type attribute + */ +Want &Want::FormatType(const std::string &type) +{ + std::string typetemp = FormatMimeType(type); + SetType(typetemp); + + return *this; +} + +/** + * @description: Convert the scheme of URI to lower-case, and return the uri which be converted. + * @param uri Indicates the URI to format. + * @return Returns this URI Object. + */ +Uri Want::GetLowerCaseScheme(const Uri &uri) +{ + std::string strUri = const_cast(uri).ToString(); + std::string schemeStr = const_cast(uri).GetScheme(); + + if (strUri.empty() || schemeStr.empty()) { + return uri; + } + + std::string lowSchemeStr = schemeStr; + std::transform(lowSchemeStr.begin(), lowSchemeStr.end(), lowSchemeStr.begin(), [](unsigned char c) { + return std::tolower(c); + }); + + if (schemeStr == lowSchemeStr) { + return uri; + } + + std::size_t pos = strUri.find_first_of(schemeStr, 0); + if (pos != std::string::npos) { + strUri.replace(pos, schemeStr.length(), lowSchemeStr); + } + + return Uri(strUri); +} + +/** + * @description: Formats a specified URI and MIME type. + * This method works in the same way as formatUri(ohos.utils.net.URI) + * and formatType(java.lang.String). + * @param uri Indicates the URI to format. + * @param type Indicates the MIME type to format. + * @return Returns this Want object that contains the formatted URI and type attributes. + */ +Want &Want::FormatUriAndType(const Uri &uri, const std::string &type) +{ + return SetUriAndType(GetLowerCaseScheme(uri), FormatMimeType(type)); +} + +/** + * @description: This method formats data of a specified MIME type + * by removing spaces from the data and converting the data into + * lowercase letters. You can use this method to normalize + * the external data used to create Want information. + * @param type Indicates the MIME type to format + * @return Returns this Want object that contains the formatted type attribute + */ +std::string Want::FormatMimeType(const std::string &mimeType) +{ + std::string strMimeType = mimeType; + strMimeType.erase(std::remove(strMimeType.begin(), strMimeType.end(), ' '), strMimeType.end()); + + std::transform( + strMimeType.begin(), strMimeType.end(), strMimeType.begin(), [](unsigned char c) { return std::tolower(c); }); + + std::size_t pos = 0; + std::size_t begin = 0; + pos = strMimeType.find_first_of(";", begin); + if (pos != std::string::npos) { + strMimeType = strMimeType.substr(begin, pos - begin); + } + + return strMimeType; +} + +/** + * @description: Obtains the description of an action in a want. + * @return Returns the action description in the want. + */ +std::string Want::GetAction() const +{ + return operation_.GetAction(); +} + +/** + * @description: Sets the description of an action in a want. + * @param action Indicates the action description. + * @return Returns this want object containing the action. + */ +Want &Want::SetAction(const std::string &action) +{ + operation_.SetAction(action); + return *this; +} + +/** + * @description: Obtains the description of the URI scheme in this want. + * @return Returns the URI scheme description in this want. + */ +const std::string Want::GetScheme() const +{ + return operation_.GetUri().GetScheme(); +} + +/** + * @description: Creates a want with its corresponding attributes specified for starting the main ability of an + * application. + * @param ElementName Indicates the ElementName object defining the deviceId, bundleName, + * and abilityName sub-attributes of the operation attribute in a want. + * @return Returns the want object used to start the main ability of an application. + */ +Want *Want::MakeMainAbility(const OHOS::AppExecFwk::ElementName &elementName) +{ + Want *want = new (std::nothrow) Want(); + + if (want != nullptr) { + want->SetAction(ACTION_HOME); + want->AddEntity(ENTITY_HOME); + want->SetElement(elementName); + } else { + return nullptr; + } + + return want; +} + +/** + * @description: Obtains the description of the WantParams object in a Want + * @return Returns the WantParams description in the Want + */ +const WantParams &Want::GetParams() const +{ + return parameters_; +} + +/** + * @description: Sets a wantParams object in a want. + * @param wantParams Indicates the wantParams description. + * @return Returns this want object containing the wantParams. + */ +Want &Want::SetParams(const WantParams &wantParams) +{ + parameters_ = wantParams; + return *this; +} + +/** + * @description: Obtains a bool-type value matching the given key. + * @param key Indicates the key of IntentParams. + * @param defaultValue Indicates the default bool-type value. + * @return Returns the bool-type value of the parameter matching the given key; + * returns the default value if the key does not exist. + */ +bool Want::GetBoolParam(const std::string &key, bool defaultValue) const +{ + auto value = parameters_.GetParam(key); + IBoolean *bo = IBoolean::Query(value); + if (bo != nullptr) { + return Boolean::Unbox(bo); + } + return defaultValue; +} + +/** + * @description:Obtains a bool-type array matching the given key. + * @param key Indicates the key of IntentParams. + * @return Returns the bool-type array of the parameter matching the given key; + * returns null if the key does not exist. + */ +std::vector Want::GetBoolArrayParam(const std::string &key) const +{ + std::vector array; + auto value = parameters_.GetParam(key); + IArray *ao = IArray::Query(value); + if (ao != nullptr && Array::IsBooleanArray(ao)) { + auto func = [&](IInterface *object) { + if (object != nullptr) { + IBoolean *value = IBoolean::Query(object); + if (value != nullptr) { + array.push_back(Boolean::Unbox(value)); + } + } + }; + + Array::ForEach(ao, func); + } + return array; +} + +/** + * @description: Sets a parameter value of the boolean type. + * @param key Indicates the key matching the parameter. + * @param value Indicates the boolean value of the parameter. + * @return Returns this want object containing the parameter value. + */ +Want &Want::SetParam(const std::string &key, bool value) +{ + parameters_.SetParam(key, Boolean::Box(value)); + return *this; +} + +/** + * @description: Sets a parameter value of the boolean array type. + * @param key Indicates the key matching the parameter. + * @param value Indicates the boolean array of the parameter. + * @return Returns this want object containing the parameter value. + */ +Want &Want::SetParam(const std::string &key, const std::vector &value) +{ + long size = value.size(); + sptr ao = new (std::nothrow) Array(size, g_IID_IBoolean); + if (ao != nullptr) { + for (long i = 0; i < size; i++) { + ao->Set(i, Boolean::Box(value[i])); + } + parameters_.SetParam(key, ao); + } + + return *this; +} + +/** + * @description: Obtains a byte-type value matching the given key. + * @param key Indicates the key of IntentParams. + * @param defaultValue Indicates the default byte-type value. + * @return Returns the byte-type value of the parameter matching the given key; + * returns the default value if the key does not exist. + */ +byte Want::GetByteParam(const std::string &key, const byte defaultValue) const +{ + auto value = parameters_.GetParam(key); + IByte *bo = IByte::Query(value); + if (bo != nullptr) { + return Byte::Unbox(bo); + } + return defaultValue; +} + +/** + * @description: Obtains a byte-type array matching the given key. + * @param key Indicates the key of IntentParams. + * @return Returns the byte-type array of the parameter matching the given key; + * returns null if the key does not exist. + */ +std::vector Want::GetByteArrayParam(const std::string &key) const +{ + std::vector array; + auto value = parameters_.GetParam(key); + IArray *ao = IArray::Query(value); + if (ao != nullptr && Array::IsByteArray(ao)) { + auto func = [&](IInterface *object) { + if (object != nullptr) { + IByte *value = IByte::Query(object); + if (value != nullptr) { + array.push_back(Byte::Unbox(value)); + } + } + }; + Array::ForEach(ao, func); + } + return array; +} + +/** + * @description: Sets a parameter value of the byte type. + * @param key Indicates the key matching the parameter. + * @param value Indicates the byte-type value of the parameter. + * @return Returns this Intent object containing the parameter value. + */ +Want &Want::SetParam(const std::string &key, byte value) +{ + parameters_.SetParam(key, Byte::Box(value)); + return *this; +} + +/** + * @description: Sets a parameter value of the byte array type. + * @param key Indicates the key matching the parameter. + * @param value Indicates the byte array of the parameter. + * @return Returns this Intent object containing the parameter value. + */ +Want &Want::SetParam(const std::string &key, const std::vector &value) +{ + long size = value.size(); + sptr ao = new (std::nothrow) Array(size, g_IID_IByte); + if (ao == nullptr) { + return *this; + } + for (long i = 0; i < size; i++) { + ao->Set(i, Byte::Box(value[i])); + } + parameters_.SetParam(key, ao); + return *this; +} + +/** + * @description: Obtains a char value matching the given key. + * @param key Indicates the key of wnatParams. + * @param value Indicates the default char value. + * @return Returns the char value of the parameter matching the given key; + * returns the default value if the key does not exist. + */ +zchar Want::GetCharParam(const std::string &key, zchar defaultValue) const +{ + auto value = parameters_.GetParam(key); + IChar *ao = IChar::Query(value); + if (ao != nullptr) { + return Char::Unbox(ao); + } + return defaultValue; +} + +/** + * @description: Obtains a char array matching the given key. + * @param key Indicates the key of wantParams. + * @return Returns the char array of the parameter matching the given key; + * returns null if the key does not exist. + */ +std::vector Want::GetCharArrayParam(const std::string &key) const +{ + std::vector array; + auto value = parameters_.GetParam(key); + IArray *ao = IArray::Query(value); + if (ao != nullptr && Array::IsCharArray(ao)) { + auto func = [&](IInterface *object) { + if (object != nullptr) { + IChar *value = IChar::Query(object); + if (value != nullptr) { + array.push_back(Char::Unbox(value)); + } + } + }; + Array::ForEach(ao, func); + } + return array; +} + +/** + * @description: Sets a parameter value of the char type. + * @param key Indicates the key of wantParams. + * @param value Indicates the char value of the parameter. + * @return Returns this want object containing the parameter value. + */ +Want &Want::SetParam(const std::string &key, zchar value) +{ + parameters_.SetParam(key, Char::Box(value)); + return *this; +} + +/** + * @description: Sets a parameter value of the char array type. + * @param key Indicates the key of wantParams. + * @param value Indicates the char array of the parameter. + * @return Returns this want object containing the parameter value. + */ +Want &Want::SetParam(const std::string &key, const std::vector &value) +{ + long size = value.size(); + sptr ao = new (std::nothrow) Array(size, g_IID_IChar); + if (ao == nullptr) { + return *this; + } + for (long i = 0; i < size; i++) { + ao->Set(i, Char::Box(value[i])); + } + parameters_.SetParam(key, ao); + return *this; +} + +/** + * @description: Obtains an int value matching the given key. + * @param key Indicates the key of wantParams. + * @param value Indicates the default int value. + * @return Returns the int value of the parameter matching the given key; + * returns the default value if the key does not exist. + */ +int Want::GetIntParam(const std::string &key, const int defaultValue) const +{ + auto value = parameters_.GetParam(key); + IInteger *ao = IInteger::Query(value); + if (ao != nullptr) { + return Integer::Unbox(ao); + } + return defaultValue; +} + +/** + * @description: Obtains an int array matching the given key. + * @param key Indicates the key of wantParams. + * @return Returns the int array of the parameter matching the given key; + * returns null if the key does not exist. + */ +std::vector Want::GetIntArrayParam(const std::string &key) const +{ + std::vector array; + auto value = parameters_.GetParam(key); + IArray *ao = IArray::Query(value); + if (ao != nullptr && Array::IsIntegerArray(ao)) { + auto func = [&](IInterface *object) { + if (object != nullptr) { + IInteger *value = IInteger::Query(object); + if (value != nullptr) { + array.push_back(Integer::Unbox(value)); + } + } + }; + Array::ForEach(ao, func); + } + return array; +} + +/** + * @description: Sets a parameter value of the int type. + * @param key Indicates the key matching the parameter. + * @param value Indicates the int value of the parameter. + * @return Returns this Intent object containing the parameter value. + */ +Want &Want::SetParam(const std::string &key, int value) +{ + parameters_.SetParam(key, Integer::Box(value)); + return *this; +} + +/** + * @description: Sets a parameter value of the int array type. + * @param key Indicates the key matching the parameter. + * @param value Indicates the int array of the parameter. + * @return Returns this Intent object containing the parameter value. + */ +Want &Want::SetParam(const std::string &key, const std::vector &value) +{ + long size = value.size(); + sptr ao = new (std::nothrow) Array(size, g_IID_IInteger); + if (ao == nullptr) { + return *this; + } + for (long i = 0; i < size; i++) { + ao->Set(i, Integer::Box(value[i])); + } + parameters_.SetParam(key, ao); + return *this; +} + +/** + * @description: Obtains a double value matching the given key. + * @param key Indicates the key of wantParams. + * @param defaultValue Indicates the default double value. + * @return Returns the double value of the parameter matching the given key; + * returns the default value if the key does not exist. + */ +double Want::GetDoubleParam(const std::string &key, double defaultValue) const +{ + auto value = parameters_.GetParam(key); + IDouble *ao = IDouble::Query(value); + if (ao != nullptr) { + return Double::Unbox(ao); + } + return defaultValue; +} + +/** + * @description: Obtains a double array matching the given key. + * @param key Indicates the key of IntentParams. + * @return Returns the double array of the parameter matching the given key; + * returns null if the key does not exist. + */ +std::vector Want::GetDoubleArrayParam(const std::string &key) const +{ + std::vector array; + auto value = parameters_.GetParam(key); + IArray *ao = IArray::Query(value); + if (ao != nullptr && Array::IsDoubleArray(ao)) { + auto func = [&](IInterface *object) { + if (object != nullptr) { + IDouble *value = IDouble::Query(object); + if (value != nullptr) { + array.push_back(Double::Unbox(value)); + } + } + }; + Array::ForEach(ao, func); + } + return array; +} + +/** + * @description: Sets a parameter value of the double type. + * @param key Indicates the key matching the parameter. + * @param value Indicates the int value of the parameter. + * @return Returns this Intent object containing the parameter value. + */ +Want &Want::SetParam(const std::string &key, double value) +{ + parameters_.SetParam(key, Double::Box(value)); + return *this; +} + +/** + * @description: Sets a parameter value of the double array type. + * @param key Indicates the key matching the parameter. + * @param value Indicates the double array of the parameter. + * @return Returns this want object containing the parameter value. + */ +Want &Want::SetParam(const std::string &key, const std::vector &value) +{ + long size = value.size(); + sptr ao = new (std::nothrow) Array(size, g_IID_IDouble); + if (ao == nullptr) { + return *this; + } + for (long i = 0; i < size; i++) { + ao->Set(i, Double::Box(value[i])); + } + parameters_.SetParam(key, ao); + return *this; +} + +/** + * @description: Obtains a float value matching the given key. + * @param key Indicates the key of wnatParams. + * @param value Indicates the default float value. + * @return Returns the float value of the parameter matching the given key; + * returns the default value if the key does not exist. + */ +float Want::GetFloatParam(const std::string &key, float defaultValue) const +{ + auto value = parameters_.GetParam(key); + IFloat *ao = IFloat::Query(value); + if (ao != nullptr) { + return Float::Unbox(ao); + } + return defaultValue; +} + +/** + * @description: Obtains a float array matching the given key. + * @param key Indicates the key of IntentParams. + * @return Obtains a float array matching the given key. + */ +std::vector Want::GetFloatArrayParam(const std::string &key) const +{ + std::vector array; + auto value = parameters_.GetParam(key); + IArray *ao = IArray::Query(value); + if (ao != nullptr && Array::IsFloatArray(ao)) { + auto func = [&](IInterface *object) { + if (object != nullptr) { + IFloat *value = IFloat::Query(object); + if (value != nullptr) { + array.push_back(Float::Unbox(value)); + } + } + }; + Array::ForEach(ao, func); + } + return array; +} + +/** + * @description: Sets a parameter value of the float type. + * @param key Indicates the key matching the parameter. + * @param value Indicates the byte-type value of the parameter. + * @return Returns this Want object containing the parameter value. + */ +Want &Want::SetParam(const std::string &key, float value) +{ + parameters_.SetParam(key, Float::Box(value)); + return *this; +} + +/** + * @description: Sets a parameter value of the float array type. + * @param key Indicates the key matching the parameter. + * @param value Indicates the byte-type value of the parameter. + * @return Returns this Want object containing the parameter value. + */ +Want &Want::SetParam(const std::string &key, const std::vector &value) +{ + long size = value.size(); + sptr ao = new (std::nothrow) Array(size, g_IID_IFloat); + if (ao == nullptr) { + return *this; + } + + for (long i = 0; i < size; i++) { + ao->Set(i, Float::Box(value[i])); + } + parameters_.SetParam(key, ao); + return *this; +} + +/** + * @description: Obtains a long value matching the given key. + * @param key Indicates the key of wantParams. + * @param value Indicates the default long value. + * @return Returns the long value of the parameter matching the given key; + * returns the default value if the key does not exist. + */ +long Want::GetLongParam(const std::string &key, long defaultValue) const +{ + auto value = parameters_.GetParam(key); + ILong *ao = ILong::Query(value); + if (ao != nullptr) { + return Long::Unbox(ao); + } + return defaultValue; +} + +/** + * @description: Obtains a long array matching the given key. + * @param key Indicates the key of wantParams. + * @return Returns the long array of the parameter matching the given key; + * returns null if the key does not exist. + */ +std::vector Want::GetLongArrayParam(const std::string &key) const +{ + std::vector array; + auto value = parameters_.GetParam(key); + IArray *ao = IArray::Query(value); + if (ao != nullptr && Array::IsLongArray(ao)) { + auto func = [&](IInterface *object) { + if (object != nullptr) { + ILong *value = ILong::Query(object); + if (value != nullptr) { + array.push_back(Long::Unbox(value)); + } + } + }; + Array::ForEach(ao, func); + } + return array; +} + +/** + * @description: Sets a parameter value of the long type. + * @param key Indicates the key matching the parameter. + * @param value Indicates the byte-type value of the parameter. + * @return Returns this Want object containing the parameter value. + */ +Want &Want::SetParam(const std::string &key, long value) +{ + parameters_.SetParam(key, Long::Box(value)); + return *this; +} + +/** + * @description: Sets a parameter value of the long array type. + * @param key Indicates the key matching the parameter. + * @param value Indicates the byte-type value of the parameter. + * @return Returns this Want object containing the parameter value. + */ +Want &Want::SetParam(const std::string &key, const std::vector &value) +{ + long size = value.size(); + sptr ao = new (std::nothrow) Array(size, g_IID_ILong); + if (ao == nullptr) { + return *this; + } + for (long i = 0; i < size; i++) { + ao->Set(i, Long::Box(value[i])); + } + parameters_.SetParam(key, ao); + return *this; +} + +/** + * @description: a short value matching the given key. + * @param key Indicates the key of wantParams. + * @param defaultValue Indicates the default short value. + * @return Returns the short value of the parameter matching the given key; + * returns the default value if the key does not exist. + */ +short Want::GetShortParam(const std::string &key, short defaultValue) const +{ + auto value = parameters_.GetParam(key); + IShort *ao = IShort::Query(value); + if (ao != nullptr) { + return Short::Unbox(ao); + } + return defaultValue; +} + +/** + * @description: Obtains a short array matching the given key. + * @param key Indicates the key of wantParams. + * @return Returns the short array of the parameter matching the given key; + * returns null if the key does not exist. + */ +std::vector Want::GetShortArrayParam(const std::string &key) const +{ + std::vector array; + auto value = parameters_.GetParam(key); + IArray *ao = IArray::Query(value); + if (ao != nullptr && Array::IsShortArray(ao)) { + auto func = [&](IInterface *object) { + if (object != nullptr) { + IShort *value = IShort::Query(object); + if (value != nullptr) { + array.push_back(Short::Unbox(value)); + } + } + }; + Array::ForEach(ao, func); + } + return array; +} + +/** + * @description: Sets a parameter value of the short type. + * @param key Indicates the key matching the parameter. + * @param value Indicates the byte-type value of the parameter. + * @return Returns this Want object containing the parameter value. + */ +Want &Want::SetParam(const std::string &key, short value) +{ + parameters_.SetParam(key, Short::Box(value)); + return *this; +} + +/** + * @description: Sets a parameter value of the short array type. + * @param key Indicates the key matching the parameter. + * @param value Indicates the byte-type value of the parameter. + * @return Returns this Want object containing the parameter value. + */ +Want &Want::SetParam(const std::string &key, const std::vector &value) +{ + long size = value.size(); + sptr ao = new (std::nothrow) Array(size, g_IID_IShort); + if (ao == nullptr) { + return *this; + } + for (long i = 0; i < size; i++) { + ao->Set(i, Short::Box(value[i])); + } + parameters_.SetParam(key, ao); + return *this; +} + +/** + * @description: Obtains a string value matching the given key. + * @param key Indicates the key of wantParams. + * @return Returns the string value of the parameter matching the given key; + * returns null if the key does not exist. + */ +std::string Want::GetStringParam(const std::string &key) const +{ + auto value = parameters_.GetParam(key); + IString *ao = IString::Query(value); + if (ao != nullptr) { + return String::Unbox(ao); + } + return std::string(); +} + +/** + * @description: Obtains a string array matching the given key. + * @param key Indicates the key of wantParams. + * @return Returns the string array of the parameter matching the given key; + * returns null if the key does not exist. + */ +std::vector Want::GetStringArrayParam(const std::string &key) const +{ + std::vector array; + auto value = parameters_.GetParam(key); + IArray *ao = IArray::Query(value); + if (ao != nullptr && Array::IsStringArray(ao)) { + auto func = [&](IInterface *object) { + if (object != nullptr) { + IString *value = IString::Query(object); + if (value != nullptr) { + array.push_back(String::Unbox(value)); + } + } + }; + Array::ForEach(ao, func); + } + return array; +} + +/** + * @description: Sets a parameter value of the string type. + * @param key Indicates the key matching the parameter. + * @param value Indicates the byte-type value of the parameter. + * @return Returns this Want object containing the parameter value. + */ +Want &Want::SetParam(const std::string &key, const std::string &value) +{ + parameters_.SetParam(key, String::Box(value)); + return *this; +} + +/** + * @description: Sets a parameter value of the string array type. + * @param key Indicates the key matching the parameter. + * @param value Indicates the byte-type value of the parameter. + * @return Returns this Want object containing the parameter value. + */ +Want &Want::SetParam(const std::string &key, const std::vector &value) +{ + long size = value.size(); + sptr ao = new (std::nothrow) Array(size, g_IID_IString); + if (ao == nullptr) { + return *this; + } + for (long i = 0; i < size; i++) { + ao->Set(i, String::Box(value[i])); + } + parameters_.SetParam(key, ao); + return *this; +} + +/** + * @description: Gets the description of an operation in a Want. + * @return Returns the operation included in this Want. + */ +Operation Want::GetOperation() const +{ + return operation_; +} + +/** + * @description: Sets the description of an operation in a Want. + * @param operation Indicates the operation description. + */ +void Want::SetOperation(const OHOS::AAFwk::Operation &operation) +{ + operation_ = operation; +} + +/** + * @description: Sets the description of an operation in a Want. + * @param want Indicates the Want object to compare. + * @return Returns true if the operation components of the two objects are equal; returns false otherwise. + */ +bool Want::OperationEquals(const Want &want) +{ + return (operation_ == want.operation_); +} + +/** + * @description: Creates a Want object that contains only the operation component of this Want. + * @return Returns the created Want object. + */ +Want *Want::CloneOperation() +{ + Want *want = new (std::nothrow) Want(); + if (want == nullptr) { + return nullptr; + } + want->SetOperation(operation_); + return want; +} + +/** + * @description: Creates a Want instance by using a given Uniform Resource Identifier (URI). + * This method parses the input URI and saves it in a Want object. + * @param uri Indicates the URI to parse. + * @return Returns a Want object containing the URI. + */ +Want *Want::ParseUri(const std::string &uri) +{ + if (uri.length() <= 0) { + return nullptr; + } + std::string head = WANT_HEADER; + std::string end = ";end"; + if (uri.find(head) != 0) { + return nullptr; + } + if (uri.rfind(end) != (uri.length() - end.length())) { + return nullptr; + } + bool ret = true; + std::string content; + std::size_t pos; + std::size_t begin = head.length(); + ElementName element; + Want *want = new (std::nothrow) Want(); + if (want == nullptr) { + return nullptr; + } + Want *baseWant = want; + bool inPicker = false; + pos = uri.find_first_of(";", begin); + do { + if (pos != std::string::npos) { + content = uri.substr(begin, pos - begin); + if (content.compare("PICK") == 0) { + want = new (std::nothrow) Want(); + if (want == nullptr) { + return nullptr; + } + inPicker = true; + continue; + } + ret = ParseUriInternal(content, element, *want); + if (!ret) { + break; + } + begin = pos + 1; + pos = uri.find(";", begin); + if (pos == std::string::npos) { + break; + } + } else { + break; + } + } while (true); + if (inPicker) { + if (baseWant->GetBundle().empty()) { + } + want = baseWant; + } + if (ret) { + want->SetElement(element); + } else { + delete want; + want = nullptr; + } + return want; +} + +/** + * @description: Creates a Want instance by using a given Uniform Resource Identifier (URI). + * This method parses the input URI and saves it in a Want object. + * @param uri Indicates the URI to parse. + * @return Returns a Want object containing the URI. + */ +Want *Want::WantParseUri(const char *uri) +{ + if (uri == nullptr) { + return nullptr; + } + std::string strUri(uri); + + return ParseUri(strUri); +} + +/** + * @description: Obtains the string representation of the URI in this Want. + * @return Returns the string of the URI. + */ +std::string Want::GetUriString() const +{ + return operation_.GetUri().ToString(); +} + +/** + * @description: Obtains the description of a URI in a Want. + * @return Returns the URI description in the Want. + */ +Uri Want::GetUri() const +{ + return operation_.GetUri(); +} + +/** + * @description: Sets the description of a URI in a Want. + * @param uri Indicates the string of URI description. + * @return Returns this Want object containing the URI. + */ +Want &Want::SetUri(const std::string &uri) +{ + operation_.SetUri(Uri(uri)); + return *this; +} + +/** + * @description: Sets the description of a URI in a Want. + * @param uri Indicates the URI description. + * @return Returns this Want object containing the URI. + */ +Want &Want::SetUri(const Uri &uri) +{ + operation_.SetUri(uri); + return *this; +} + +/** + * @description: Sets the description of a URI and a type in this Want. + * @param uri Indicates the URI description. + * @param type Indicates the type description. + * @return Returns this Want object containing the URI and the type. + */ +Want &Want::SetUriAndType(const Uri &uri, const std::string &type) +{ + operation_.SetUri(uri); + return SetType(type); +} + +/** + * @description: Converts a Want into a URI string containing a representation of it. + * @param want Indicates the want description.--Want. + * @return Returns a encoding URI string describing the Want object. + */ +std::string Want::WantToUri(Want &want) +{ + return want.ToUri(); +} + +/** + * @description: Converts parameter information in a Want into a URI string. + * @return Returns the URI string. + */ +std::string Want::ToUri() const +{ + std::string uriString = WANT_HEADER; + ToUriStringInner(uriString); + + if (picker_ != nullptr) { + uriString.append("PICK;"); + picker_->ToUriStringInner(uriString); + } + uriString += "end"; + + return uriString; +} +void Want::ToUriStringInner(std::string &uriString) const +{ + if (operation_.GetAction().length() > 0) { + uriString += "action=" + Encode(operation_.GetAction()) + ";"; + } + if (GetUriString().length() > 0) { + uriString += "uri=" + Encode(GetUriString()) + ";"; + } + for (auto entity : operation_.GetEntities()) { + if (entity.length() > 0) { + uriString += "entity=" + Encode(entity) + ";"; + } + } + if (operation_.GetDeviceId().length() > 0) { + uriString += "device=" + Encode(operation_.GetDeviceId()) + ";"; + } + if (operation_.GetBundleName().length() > 0) { + uriString += "bundle=" + Encode(operation_.GetBundleName()) + ";"; + } + if (operation_.GetAbilityName().length() > 0) { + uriString += "ability=" + Encode(operation_.GetAbilityName()) + ";"; + } + if (operation_.GetFlags() != 0) { + uriString += "flag="; + char buf[HEX_STRING_BUF_LEN] {0}; + std::size_t len = snprintf_s(buf, HEX_STRING_BUF_LEN, HEX_STRING_BUF_LEN - 1, "0x%08x", operation_.GetFlags()); + if (len == HEX_STRING_LEN) { + std::string flag = buf; + uriString += Encode(flag); + uriString += ";"; + } + } + if (!operation_.GetBundleName().empty()) { + uriString.append("package="); + uriString.append(Encode(operation_.GetBundleName())); + uriString.append(";"); + } + auto params = parameters_.GetParams(); + auto iter = params.cbegin(); + while (iter != params.cend()) { + sptr o = iter->second; + if (IString::Query(o) != nullptr) { + uriString += String::SIGNATURE; + } else if (IBoolean::Query(o) != nullptr) { + uriString += Boolean::SIGNATURE; + } else if (IChar::Query(o) != nullptr) { + uriString += Char::SIGNATURE; + } else if (IByte::Query(o) != nullptr) { + uriString += Byte::SIGNATURE; + } else if (IShort::Query(o) != nullptr) { + uriString += Short::SIGNATURE; + } else if (IInteger::Query(o) != nullptr) { + uriString += Integer::SIGNATURE; + } else if (ILong::Query(o) != nullptr) { + uriString += Long::SIGNATURE; + } else if (IFloat::Query(o) != nullptr) { + uriString += Float::SIGNATURE; + } else if (IDouble::Query(o) != nullptr) { + uriString += Double::SIGNATURE; + } else if (IArray::Query(o) != nullptr) { + uriString += Array::SIGNATURE; + } + uriString += "." + Encode(iter->first) + "=" + Encode(Object::ToString(*(o.GetRefPtr()))) + ";"; + iter++; + } +} +/** + * @description: Formats a specified URI. + * This method uses the Uri.getLowerCaseScheme() method to format a URI and then saves + * the formatted URI to this Want object. + * @param uri Indicates the URI to format. + * @return Returns this Want object that contains the formatted uri attribute. + */ +Want &Want::FormatUri(const std::string &uri) +{ + return FormatUri(Uri(uri)); +} + +/** + * @description: Formats a specified URI. + * This method uses the GetLowerCaseScheme() method to format a URI and then saves + * the formatted URI to this Want object. + * @param uri Indicates the URI to format. + * @return Returns this Want object that contains the formatted uri attribute. + */ +Want &Want::FormatUri(const Uri &uri) +{ + operation_.SetUri(GetLowerCaseScheme(uri)); + return *this; +} + +/** + * @description: Checks whether a Want contains the parameter matching a given key. + * @param key Indicates the key. + * @return Returns true if the Want contains the parameter; returns false otherwise. + */ +bool Want::HasParameter(const std::string &key) const +{ + return parameters_.HasParam(key); +} + +/** + * @description: Replaces parameters in this Want object with those in the given WantParams object. + * @param wantParams Indicates the WantParams object containing the new parameters. + * @return Returns this Want object containing the new parameters. + */ +Want *Want::ReplaceParams(WantParams &wantParams) +{ + parameters_ = wantParams; + return this; +} + +/** + * @description: Replaces parameters in this Want object with those in the given Want object. + * @param want Indicates the Want object containing the new parameters. + * @return Returns this Want object containing the new parameters. + */ +Want *Want::ReplaceParams(Want &want) +{ + parameters_ = want.parameters_; + return this; +} + +/** + * @description: Removes the parameter matching the given key. + * @param key Indicates the key matching the parameter to be removed. + */ +void Want::RemoveParam(const std::string &key) +{ + parameters_.Remove(key); +} + +/** + * @description: clear the specific want object. + * @param want Indicates the want to clear + */ +void Want::ClearWant(Want *want) +{ + want->SetType(""); + want->SetAction(""); + want->SetFlags(0); + OHOS::AppExecFwk::ElementName elementName; + want->SetElement(elementName); + OHOS::AAFwk::Operation operation; + want->SetOperation(operation); + WantParams parameters; + want->SetParams(parameters); +} + +/** + * @description: Marshals a Want into a Parcel. + * Fields in the Want are marshalled separately. If any field fails to be marshalled, false is returned. + * @param parcel Indicates the Parcel object for marshalling. + * @return Returns true if the marshalling is successful; returns false otherwise. + */ +bool Want::Marshalling(Parcel &parcel) const +{ + // write action + if (!parcel.WriteString16(Str8ToStr16(GetAction()))) { + return false; + } + + // write uri + if (GetUriString().empty()) { + if (!parcel.WriteInt32(VALUE_NULL)) { + return false; + } + } else { + if (!parcel.WriteInt32(VALUE_OBJECT)) { + return false; + } + if (!parcel.WriteString16(Str8ToStr16(GetUriString()))) { + return false; + } + } + + // write entities + std::vector entityU16; + std::vector entities = GetEntities(); + for (std::vector::size_type i = 0; i < entities.size(); i++) { + entityU16.push_back(Str8ToStr16(entities[i])); + } + + if (entityU16.size() == 0) { + if (!parcel.WriteInt32(VALUE_NULL)) { + return false; + } + } else { + if (!parcel.WriteInt32(VALUE_OBJECT)) { + return false; + } + if (!parcel.WriteString16Vector(entityU16)) { + return false; + } + } + + // write flags + if (!parcel.WriteUint32(GetFlags())) { + return false; + } + + // write element + ElementName emptyElement; + ElementName element = GetElement(); + if (element == emptyElement) { + if (!parcel.WriteInt32(VALUE_NULL)) { + return false; + } + } else { + if (!parcel.WriteInt32(VALUE_OBJECT)) { + return false; + } + if (!parcel.WriteParcelable(&element)) { + return false; + } + } + + // write parameters + if (parameters_.Size() == 0) { + if (!parcel.WriteInt32(VALUE_NULL)) { + return false; + } + } else { + if (!parcel.WriteInt32(VALUE_OBJECT)) { + return false; + } + if (!parcel.WriteParcelable(¶meters_)) { + return false; + } + } + + // write package + if (!parcel.WriteString16(Str8ToStr16(GetBundle()))) { + return false; + } + + // write picker + if (picker_ == nullptr) { + if (!parcel.WriteInt32(VALUE_NULL)) { + return false; + } + } else { + if (!parcel.WriteInt32(VALUE_OBJECT)) { + return false; + } + if (!parcel.WriteParcelable(picker_)) { + return false; + } + } + + return true; +} + +/** + * @description: Unmarshals a Want from a Parcel. + * Fields in the Want are unmarshalled separately. If any field fails to be unmarshalled, false is returned. + * @param parcel Indicates the Parcel object for unmarshalling. + * @return Returns true if the unmarshalling is successful; returns false otherwise. + */ +Want *Want::Unmarshalling(Parcel &parcel) +{ + Want *want = new (std::nothrow) Want(); + if (want != nullptr && !want->ReadFromParcel(parcel)) { + delete want; + want = nullptr; + } + return want; +} + +bool Want::ReadFromParcel(Parcel &parcel) +{ + int empty; + std::string value; + std::vector entities; + // read action + operation_.SetAction(Str16ToStr8(parcel.ReadString16())); + + // read uri + empty = VALUE_NULL; + if (!parcel.ReadInt32(empty)) { + return false; + } + if (empty == VALUE_OBJECT) { + SetUri(Str16ToStr8(parcel.ReadString16())); + } + + // read entities + std::vector entityU16; + empty = VALUE_NULL; + if (!parcel.ReadInt32(empty)) { + return false; + } + if (empty == VALUE_OBJECT) { + if (!parcel.ReadString16Vector(&entityU16)) { + return false; + } + } + for (std::vector::size_type i = 0; i < entityU16.size(); i++) { + entities.push_back(Str16ToStr8(entityU16[i])); + } + operation_.SetEntities(entities); + + // read flags + unsigned int flags; + if (!parcel.ReadUint32(flags)) { + return false; + } + operation_.SetFlags(flags); + + // read element + empty = VALUE_NULL; + if (!parcel.ReadInt32(empty)) { + return false; + } + + if (empty == VALUE_OBJECT) { + auto element = parcel.ReadParcelable(); + if (element != nullptr) { + SetElement(*element); + delete element; + } else { + return false; + } + } + + // read parameters + empty = VALUE_NULL; + if (!parcel.ReadInt32(empty)) { + return false; + } + + if (empty == VALUE_OBJECT) { + auto params = parcel.ReadParcelable(); + if (params != nullptr) { + parameters_ = *params; + delete params; + params = nullptr; + } else { + return false; + } + } + + // read package + operation_.SetBundleName(Str16ToStr8(parcel.ReadString16())); + + // read picker + empty = VALUE_NULL; + if (!parcel.ReadInt32(empty)) { + return false; + } + + if (empty == VALUE_OBJECT) { + auto picker = parcel.ReadParcelable(); + if (picker != nullptr) { + picker_ = picker; + } else { + return false; + } + } + + return true; +} + +bool Want::ParseUriInternal(const std::string &content, ElementName &element, Want &want) +{ + static constexpr int TYPE_TAG_SIZE = 2; + + std::string prop; + std::string value; + + if (content.empty() || content[0] == '=') { + return true; + } + + if (!ParseContent(content, prop, value)) { + return false; + } + + if (value.empty()) { + return true; + } + + if (prop == "action") { + want.SetAction(value); + } else if (prop == "entity") { + want.AddEntity(value); + } else if (prop == "flag") { + if (!ParseFlag(value, want)) { + return false; + } + } else if (prop == "device") { + element.SetDeviceID(value); + } else if (prop == "bundle") { + element.SetBundleName(value); + } else if (prop == "ability") { + element.SetAbilityName(value); + } else if (prop == "package") { + want.SetBundle(Decode(value)); + } else if (prop.length() > TYPE_TAG_SIZE) { + std::string key = prop.substr(TYPE_TAG_SIZE); + if (!Want::CheckAndSetParameters(want, key, prop, value)) { + return false; + } + } + + return true; +} + +bool Want::ParseContent(const std::string &content, std::string &prop, std::string &value) +{ + std::string subString; + std::size_t pos = content.find("="); + if (pos != std::string::npos) { + subString = content.substr(0, pos); + prop = Decode(subString); + subString = content.substr(pos + 1, content.length() - pos - 1); + value = Decode(subString); + return true; + } + return false; +} + +bool Want::ParseFlag(const std::string &content, Want &want) +{ + std::string contentLower = LowerStr(content); + std::string prefix = "0x"; + if (!contentLower.empty()) { + if (contentLower.find(prefix) != 0) { + return false; + } + + for (std::size_t i = prefix.length(); i < contentLower.length(); i++) { + if (!isxdigit(contentLower[i])) { + return false; + } + } + int base = 16; // hex string + unsigned int flag = std::stoul(contentLower, nullptr, base); + want.SetFlags(flag); + } + return true; +} + +std::string Want::Decode(const std::string &str) +{ + std::string decode; + + for (std::size_t i = 0; i < str.length();) { + if (str[i] == '\\') { + if (++i >= str.length()) { + decode += "\\"; + break; + } + if (str[i] == '\\') { + decode += "\\"; + i++; + } else if (str[i] == '0') { + if (str.compare(i, OCT_EQUALSTO.length(), OCT_EQUALSTO) == 0) { + decode += "="; + i += OCT_EQUALSTO.length(); + } else if (str.compare(i, OCT_SEMICOLON.length(), OCT_SEMICOLON) == 0) { + decode += ";"; + i += OCT_SEMICOLON.length(); + } else { + decode += "\\" + str.substr(i, 1); + i++; + } + } else { + decode += "\\" + str.substr(i, 1); + i++; + } + } else { + decode += str[i]; + i++; + } + } + + return decode; +} + +std::string Want::Encode(const std::string &str) +{ + std::string encode; + + for (std::size_t i = 0; i < str.length(); i++) { + if (str[i] == '\\') { + encode += "\\\\"; + } else if (str[i] == '=') { + encode += "\\" + OCT_EQUALSTO; + } else if (str[i] == ';') { + encode += "\\" + OCT_SEMICOLON; + } else { + encode += str[i]; + } + } + + return encode; +} + +bool Want::CheckAndSetParameters(Want &want, const std::string &key, std::string &prop, const std::string &value) +{ + if (prop[0] == String::SIGNATURE && prop[1] == '.') { + sptr valueObj = String::Parse(value); + if (valueObj == nullptr) { + return false; + } + want.parameters_.SetParam(key, valueObj); + } else if (prop[0] == Boolean::SIGNATURE && prop[1] == '.') { + sptr valueObj = Boolean::Parse(value); + if (valueObj == nullptr) { + return false; + } + want.parameters_.SetParam(key, valueObj); + } else if (prop[0] == Char::SIGNATURE && prop[1] == '.') { + sptr valueObj = Char::Parse(value); + if (valueObj == nullptr) { + return false; + } + want.parameters_.SetParam(key, valueObj); + } else if (prop[0] == Byte::SIGNATURE && prop[1] == '.') { + sptr valueObj = Byte::Parse(value); + if (valueObj == nullptr) { + return false; + } + want.parameters_.SetParam(key, valueObj); + } else if (prop[0] == Short::SIGNATURE && prop[1] == '.') { + sptr valueObj = Short::Parse(value); + if (valueObj == nullptr) { + return false; + } + want.parameters_.SetParam(key, valueObj); + } else if (prop[0] == Integer::SIGNATURE && prop[1] == '.') { + sptr valueObj = Integer::Parse(value); + if (valueObj == nullptr) { + return false; + } + want.parameters_.SetParam(key, valueObj); + } else if (prop[0] == Long::SIGNATURE && prop[1] == '.') { + sptr valueObj = Long::Parse(value); + if (valueObj == nullptr) { + return false; + } + want.parameters_.SetParam(key, valueObj); + } else if (prop[0] == Float::SIGNATURE && prop[1] == '.') { + sptr valueObj = Float::Parse(value); + if (valueObj == nullptr) { + return false; + } + want.parameters_.SetParam(key, valueObj); + } else if (prop[0] == Double::SIGNATURE && prop[1] == '.') { + sptr valueObj = Double::Parse(value); + if (valueObj == nullptr) { + return false; + } + want.parameters_.SetParam(key, valueObj); + } else if (prop[0] == Array::SIGNATURE && prop[1] == '.') { + sptr valueObj = Array::Parse(value); + if (valueObj == nullptr) { + return false; + } + want.parameters_.SetParam(key, valueObj); + } + return true; +} + +void Want::DumpInfo(int level) const +{ + APP_LOGI("==================Want::DumpInfo level: %{public}d start=============", level); + operation_.DumpInfo(level); + parameters_.DumpInfo(level); + + if (picker_ != nullptr) { + picker_->DumpInfo(level + 1); + } + APP_LOGI("==================Want::DumpInfo level: %{public}d end=============", level); +} + +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/content/cpp/src/ohos/aafwk/content/want_params.cpp b/tools/frameworks/kits/content/cpp/src/ohos/aafwk/content/want_params.cpp new file mode 100755 index 00000000000..2002fe80a66 --- /dev/null +++ b/tools/frameworks/kits/content/cpp/src/ohos/aafwk/content/want_params.cpp @@ -0,0 +1,1274 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "want_params.h" +#include "parcel.h" +#include "string_ex.h" +#include "ohos/aafwk/base/base_interfaces.h" +#include "ohos/aafwk/base/array_wrapper.h" +#include "ohos/aafwk/base/base_object.h" +#include "ohos/aafwk/base/bool_wrapper.h" +#include "ohos/aafwk/base/byte_wrapper.h" +#include "ohos/aafwk/base/short_wrapper.h" +#include "ohos/aafwk/base/int_wrapper.h" +#include "ohos/aafwk/base/long_wrapper.h" +#include "ohos/aafwk/base/float_wrapper.h" +#include "ohos/aafwk/base/double_wrapper.h" +#include "ohos/aafwk/base/string_wrapper.h" +#include "want_params_wrapper.h" +#include "ohos/aafwk/base/zchar_wrapper.h" +#include "app_log_wrapper.h" +#include "securec.h" + +using namespace OHOS::AppExecFwk; + +namespace OHOS { +namespace AAFwk { +UnsupportedData::~UnsupportedData() +{ + if (buffer != nullptr) { + delete[] buffer; + buffer = nullptr; + } +} + +UnsupportedData::UnsupportedData() = default; + +UnsupportedData::UnsupportedData(const UnsupportedData &other) : key(other.key), type(other.type), size(other.size) +{ + buffer = new uint8_t[size]; + if (memcpy_s(buffer, size, other.buffer, size) != EOK) { + APP_LOGI("copy construct fail due to memcpy"); + + key.clear(); + type = 0; + size = 0; + delete[] buffer; + buffer = nullptr; + } +} + +UnsupportedData::UnsupportedData(UnsupportedData &&other) + : key(std::move(other.key)), type(other.type), size(other.size), buffer(other.buffer) +{ + other.type = 0; + other.size = 0; + other.buffer = nullptr; +} + +UnsupportedData &UnsupportedData::operator=(const UnsupportedData &other) +{ + if (this == &other) { + return *this; + } + key = other.key; + type = other.type; + size = other.size; + buffer = new uint8_t[size]; + if (memcpy_s(buffer, size, other.buffer, size) != EOK) { + APP_LOGI("copy assignment fail due to memcpy"); + + key.clear(); + type = 0; + size = 0; + delete[] buffer; + buffer = nullptr; + } + return *this; +} + +UnsupportedData &UnsupportedData::operator=(UnsupportedData &&other) +{ + key = std::move(other.key); + type = other.type; + size = other.size; + std::swap(buffer, other.buffer); + + other.type = 0; + other.size = 0; + if (other.buffer) { + delete[] other.buffer; + other.buffer = nullptr; + } + return *this; +} + +std::string WantParams::GetStringByType(const sptr iIt, int typeId) +{ + if (typeId == VALUE_TYPE_BOOLEAN) { + return static_cast(IBoolean::Query(iIt))->ToString(); + } else if (typeId == VALUE_TYPE_BYTE) { + return static_cast(IByte::Query(iIt))->ToString(); + } else if (typeId == VALUE_TYPE_CHAR) { + return static_cast(IChar::Query(iIt))->ToString(); + } else if (typeId == VALUE_TYPE_SHORT) { + return static_cast(IShort::Query(iIt))->ToString(); + } else if (typeId == VALUE_TYPE_INT) { + return static_cast(IInteger::Query(iIt))->ToString(); + } else if (typeId == VALUE_TYPE_LONG) { + return static_cast(ILong::Query(iIt))->ToString(); + } else if (typeId == VALUE_TYPE_FLOAT) { + return static_cast(IFloat::Query(iIt))->ToString(); + } else if (typeId == VALUE_TYPE_DOUBLE) { + return static_cast(IDouble::Query(iIt))->ToString(); + } else if (typeId == VALUE_TYPE_STRING) { + return static_cast(IString::Query(iIt))->ToString(); + } else if (typeId == VALUE_TYPE_ARRAY) { + return static_cast(IArray::Query(iIt))->ToString(); + } else if (typeId == VALUE_TYPE_WANTPARAMS) { + return static_cast(IWantParams::Query(iIt))->ToString(); + } else { + return ""; + } + return ""; +} +template +static void SetNewArray(const AAFwk::InterfaceID &id, AAFwk::IArray *orgIArray, sptr &ao); +/** + * @description: A constructor used to create an IntentParams instance by using the parameters of an existing + * IntentParams object. + * @param intentParams Indicates the existing IntentParams object. + */ +WantParams::WantParams(const WantParams &wantParams) +{ + params_.clear(); + NewParams(wantParams, *this); +} +// inner use function +bool WantParams::NewParams(const WantParams &source, WantParams &dest) +{ + // Deep copy + for (auto it = source.params_.begin(); it != source.params_.end(); it++) { + sptr o = it->second; + if (IString::Query(o) != nullptr) { + dest.params_[it->first] = String::Box(String::Unbox(IString::Query(o))); + } else if (IBoolean::Query(o) != nullptr) { + dest.params_[it->first] = Boolean::Box(Boolean::Unbox(IBoolean::Query(o))); + } else if (IByte::Query(o) != nullptr) { + dest.params_[it->first] = Byte::Box(Byte::Unbox(IByte::Query(o))); + } else if (IChar::Query(o) != nullptr) { + dest.params_[it->first] = Char::Box(Char::Unbox(IChar::Query(o))); + } else if (IShort::Query(o) != nullptr) { + dest.params_[it->first] = Short::Box(Short::Unbox(IShort::Query(o))); + } else if (IInteger::Query(o) != nullptr) { + dest.params_[it->first] = Integer::Box(Integer::Unbox(IInteger::Query(o))); + } else if (ILong::Query(o) != nullptr) { + dest.params_[it->first] = Long::Box(Long::Unbox(ILong::Query(o))); + } else if (IFloat::Query(o) != nullptr) { + dest.params_[it->first] = Float::Box(Float::Unbox(IFloat::Query(o))); + } else if (IDouble::Query(o) != nullptr) { + dest.params_[it->first] = Double::Box(Double::Unbox(IDouble::Query(o))); + } else if (IWantParams::Query(o) != nullptr) { + WantParams newDest(WantParamWrapper::Unbox(IWantParams::Query(o))); + dest.params_[it->first] = WantParamWrapper::Box(newDest); + } else if (IArray::Query(o) != nullptr) { + sptr destAO = nullptr; + if (!NewArrayData(IArray::Query(o), destAO)) { + continue; + } + dest.params_[it->first] = destAO; + } + } + return true; +} // namespace AAFwk +// inner use +bool WantParams::NewArrayData(IArray *source, sptr &dest) +{ + if (Array::IsBooleanArray(source)) { + SetNewArray(AAFwk::g_IID_IBoolean, source, dest); + } else if (Array::IsCharArray(source)) { + SetNewArray(AAFwk::g_IID_IChar, source, dest); + } else if (Array::IsByteArray(source)) { + SetNewArray(AAFwk::g_IID_IByte, source, dest); + } else if (Array::IsShortArray(source)) { + SetNewArray(AAFwk::g_IID_IShort, source, dest); + } else if (Array::IsIntegerArray(source)) { + SetNewArray(AAFwk::g_IID_IInteger, source, dest); + } else if (Array::IsLongArray(source)) { + SetNewArray(AAFwk::g_IID_ILong, source, dest); + } else if (Array::IsFloatArray(source)) { + SetNewArray(AAFwk::g_IID_IFloat, source, dest); + } else if (Array::IsDoubleArray(source)) { + SetNewArray(AAFwk::g_IID_IDouble, source, dest); + } else if (Array::IsStringArray(source)) { + SetNewArray(AAFwk::g_IID_IString, source, dest); + } else { + return false; + } + + if (dest == nullptr) { + return false; + } + + return true; +} +/** + * @description: A WantParams used to + * + * @param intentParams Indicates the existing IntentParams object. + */ +WantParams &WantParams::operator=(const WantParams &other) +{ + if (this != &other) { + params_.clear(); + NewParams(other, *this); + } + return *this; +} +bool WantParams::operator==(const WantParams &other) +{ + if (this->params_.size() != other.params_.size()) { + return false; + } + for (auto itthis : this->params_) { + auto itother = other.params_.find(itthis.first); + if (itother == other.params_.end()) { + return false; + } + if (!CompareInterface(itother->second, itthis.second, WantParams::GetDataType(itother->second))) { + return false; + } + } + return true; +} + +int WantParams::GetDataType(const sptr iIt) +{ + if (iIt != nullptr && IBoolean::Query(iIt) != nullptr) { + return VALUE_TYPE_BOOLEAN; + } else if (iIt != nullptr && IByte::Query(iIt) != nullptr) { + return VALUE_TYPE_BYTE; + } else if (iIt != nullptr && IChar::Query(iIt) != nullptr) { + return VALUE_TYPE_CHAR; + } else if (iIt != nullptr && IShort::Query(iIt) != nullptr) { + return VALUE_TYPE_SHORT; + } else if (iIt != nullptr && IInteger::Query(iIt) != nullptr) { + return VALUE_TYPE_INT; + } else if (iIt != nullptr && ILong::Query(iIt) != nullptr) { + return VALUE_TYPE_LONG; + } else if (iIt != nullptr && IFloat::Query(iIt) != nullptr) { + return VALUE_TYPE_FLOAT; + } else if (iIt != nullptr && IDouble::Query(iIt) != nullptr) { + return VALUE_TYPE_DOUBLE; + } else if (iIt != nullptr && IString::Query(iIt) != nullptr) { + return VALUE_TYPE_STRING; + } else if (iIt != nullptr && IArray::Query(iIt) != nullptr) { + return VALUE_TYPE_ARRAY; + } else if (iIt != nullptr && IWantParams::Query(iIt) != nullptr) { + return VALUE_TYPE_WANTPARAMS; + } + + return VALUE_TYPE_NULL; +} + +sptr WantParams::GetInterfaceByType(int typeId, const std::string &value) +{ + if (typeId == VALUE_TYPE_BOOLEAN) { + return Boolean::Parse(value); + } else if (typeId == VALUE_TYPE_BYTE) { + return Byte::Parse(value); + } else if (typeId == VALUE_TYPE_CHAR) { + return Char::Parse(value); + } else if (typeId == VALUE_TYPE_SHORT) { + return Short::Parse(value); + } else if (typeId == VALUE_TYPE_INT) { + return Integer::Parse(value); + } else if (typeId == VALUE_TYPE_LONG) { + return Long::Parse(value); + } else if (typeId == VALUE_TYPE_FLOAT) { + return Float::Parse(value); + } else if (typeId == VALUE_TYPE_DOUBLE) { + return Double::Parse(value); + } else if (typeId == VALUE_TYPE_STRING) { + return String::Parse(value); + } else if (typeId == VALUE_TYPE_ARRAY) { + return Array::Parse(value); + } + + return nullptr; +} + +bool WantParams::CompareInterface(const sptr iIt1, const sptr iIt2, int typeId) +{ + bool flag = false; + switch (typeId) { + case VALUE_TYPE_BOOLEAN: + flag = + static_cast(IBoolean::Query(iIt1))->Equals(*(static_cast(IBoolean::Query(iIt1)))); + break; + case VALUE_TYPE_BYTE: + flag = static_cast(IByte::Query(iIt1))->Equals(*(static_cast(IByte::Query(iIt1)))); + break; + case VALUE_TYPE_CHAR: + flag = static_cast(IChar::Query(iIt1))->Equals(*(static_cast(IChar::Query(iIt1)))); + break; + case VALUE_TYPE_SHORT: + flag = static_cast(IShort::Query(iIt1))->Equals(*(static_cast(IShort::Query(iIt1)))); + break; + case VALUE_TYPE_INT: + flag = + static_cast(IInteger::Query(iIt1))->Equals(*(static_cast(IInteger::Query(iIt1)))); + break; + case VALUE_TYPE_LONG: + flag = static_cast(ILong::Query(iIt1))->Equals(*(static_cast(ILong::Query(iIt1)))); + break; + case VALUE_TYPE_FLOAT: + flag = static_cast(IFloat::Query(iIt1))->Equals(*(static_cast(IFloat::Query(iIt1)))); + break; + case VALUE_TYPE_DOUBLE: + flag = static_cast(IDouble::Query(iIt1))->Equals(*(static_cast(IDouble::Query(iIt1)))); + break; + case VALUE_TYPE_STRING: + flag = static_cast(IString::Query(iIt1))->Equals(*(static_cast(IString::Query(iIt1)))); + break; + case VALUE_TYPE_ARRAY: + flag = static_cast(IArray::Query(iIt1))->Equals(*(static_cast(IArray::Query(iIt1)))); + break; + case VALUE_TYPE_WANTPARAMS: + flag = static_cast(IWantParams::Query(iIt1)) + ->Equals(*(static_cast(IWantParams::Query(iIt1)))); + break; + default: + break; + } + return flag; +} + +/** + * @description: Sets a parameter in key-value pair format. + * @param key Indicates the key matching the parameter. + */ +void WantParams::SetParam(const std::string &key, IInterface *value) +{ + params_[key] = value; +} + +/** + * @description: Obtains the parameter value based on a given key. + * @param key Indicates the key matching the parameter. + * @return Returns the value matching the given key. + */ +sptr WantParams::GetParam(const std::string &key) const +{ + auto it = params_.find(key); + if (it == params_.cend()) { + return nullptr; + } + return it->second; +} + +/** + * @description: Obtains the parameter value based on a given key. + * @param key Indicates the key matching the parameter. + * @return Returns the value matching the given key. + */ + +const std::map> &WantParams::GetParams() const +{ + return params_; +} + +/** + * @description: Obtains a set of the keys of all parameters. + * @param + * @return Returns a set of keys. + */ +const std::set WantParams::KeySet() const +{ + std::set keySet; + keySet.clear(); + + for (auto it : params_) { + keySet.emplace(it.first); + } + + return keySet; +} + +/** + * @description: Removes the parameter matching the given key. + * @param key Indicates the key matching the parameter to be removed. + */ +void WantParams::Remove(const std::string &key) +{ + params_.erase(key); +} + +/** + * @description: Checks whether the Intent contains the given key. + * @param key Indicates the key to check. + * @return Returns true if the Intent contains the key; returns false otherwise. + */ +bool WantParams::HasParam(const std::string &key) const +{ + return (params_.count(key) > 0); +} + +/** + * @description: Obtains the number of parameters contained in this IntentParams object. + * @return Returns the number of parameters. + */ +int WantParams::Size() const +{ + return params_.size(); +} + +/** + * @description: Checks whether this IntentParams object contains no parameters. + * @return Returns true if this object does not contain any parameters; returns false otherwise. + */ +bool WantParams::IsEmpty() const +{ + return (params_.size() == 0); +} + +bool WantParams::WriteToParcelString(Parcel &parcel, sptr &o) const +{ + std::string value = String::Unbox(IString::Query(o)); + if (!parcel.WriteInt32(VALUE_TYPE_STRING)) { + return false; + } + return parcel.WriteString16(Str8ToStr16(value)); +} + +bool WantParams::WriteToParcelBool(Parcel &parcel, sptr &o) const +{ + bool value = Boolean::Unbox(IBoolean::Query(o)); + if (!parcel.WriteInt32(VALUE_TYPE_BOOLEAN)) { + return false; + } + return parcel.WriteInt8(value); +} +bool WantParams::WriteToParcelWantParams(Parcel &parcel, sptr &o) const +{ + WantParams value = WantParamWrapper::Unbox(IWantParams::Query(o)); + if (!parcel.WriteInt32(VALUE_TYPE_WANTPARAMS)) { + return false; + } + return parcel.WriteString16(Str8ToStr16(static_cast(IWantParams::Query(o))->ToString())); +} +bool WantParams::WriteToParcelByte(Parcel &parcel, sptr &o) const +{ + byte value = Byte::Unbox(IByte::Query(o)); + if (!parcel.WriteInt32(VALUE_TYPE_BYTE)) { + return false; + } + return parcel.WriteInt8(value); +} + +bool WantParams::WriteToParcelChar(Parcel &parcel, sptr &o) const +{ + zchar value = Char::Unbox(IChar::Query(o)); + if (!parcel.WriteInt32(VALUE_TYPE_CHAR)) { + return false; + } + return parcel.WriteInt32(value); +} + +bool WantParams::WriteToParcelShort(Parcel &parcel, sptr &o) const +{ + short value = Short::Unbox(IShort::Query(o)); + if (!parcel.WriteInt32(VALUE_TYPE_SHORT)) { + return false; + } + return parcel.WriteInt16(value); +} + +bool WantParams::WriteToParcelInt(Parcel &parcel, sptr &o) const +{ + int value = Integer::Unbox(IInteger::Query(o)); + if (!parcel.WriteInt32(VALUE_TYPE_INT)) { + return false; + } + return parcel.WriteInt32(value); +} + +bool WantParams::WriteToParcelLong(Parcel &parcel, sptr &o) const +{ + long value = Long::Unbox(ILong::Query(o)); + if (!parcel.WriteInt32(VALUE_TYPE_LONG)) { + return false; + } + return parcel.WriteInt64(value); +} + +bool WantParams::WriteToParcelFloat(Parcel &parcel, sptr &o) const +{ + float value = Float::Unbox(IFloat::Query(o)); + if (!parcel.WriteInt32(VALUE_TYPE_FLOAT)) { + return false; + } + return parcel.WriteFloat(value); +} + +bool WantParams::WriteToParcelDouble(Parcel &parcel, sptr &o) const +{ + double value = Double::Unbox(IDouble::Query(o)); + if (!parcel.WriteInt32(VALUE_TYPE_DOUBLE)) { + return false; + } + return parcel.WriteDouble(value); +} + +bool WantParams::WriteMarshalling(Parcel &parcel, sptr &o) const +{ + if (IString::Query(o) != nullptr) { + return WriteToParcelString(parcel, o); + } else if (IBoolean::Query(o) != nullptr) { + return WriteToParcelBool(parcel, o); + } else if (IByte::Query(o) != nullptr) { + return WriteToParcelByte(parcel, o); + } else if (IChar::Query(o) != nullptr) { + return WriteToParcelChar(parcel, o); + } else if (IShort::Query(o) != nullptr) { + return WriteToParcelShort(parcel, o); + } else if (IInteger::Query(o) != nullptr) { + return WriteToParcelInt(parcel, o); + } else if (ILong::Query(o) != nullptr) { + return WriteToParcelLong(parcel, o); + } else if (IFloat::Query(o) != nullptr) { + return WriteToParcelFloat(parcel, o); + } else if (IDouble::Query(o) != nullptr) { + return WriteToParcelDouble(parcel, o); + } else { + IArray *ao = IArray::Query(o); + if (ao != nullptr) { + sptr array(ao); + return WriteArrayToParcel(parcel, array); + } else { + return true; + } + } +} + +bool WantParams::DoMarshalling(Parcel &parcel) const +{ + size_t size = params_.size(); + if (!cachedUnsupportedData_.empty()) { + size += cachedUnsupportedData_.size(); + } + + if (!parcel.WriteInt32(size)) { + return false; + } + + auto iter = params_.cbegin(); + while (iter != params_.cend()) { + std::string key = iter->first; + sptr o = iter->second; + if (!parcel.WriteString16(Str8ToStr16(key))) { + return false; + } + + if (!WriteMarshalling(parcel, o)) { + return false; + } + iter++; + } + + if (!cachedUnsupportedData_.empty()) { + for (const UnsupportedData &data : cachedUnsupportedData_) { + if (!parcel.WriteString16(data.key)) { + return false; + } + if (!parcel.WriteInt32(data.type)) { + return false; + } + if (!parcel.WriteInt32(data.size)) { + return false; + } + // Corresponding to Parcel#writeByteArray() in Java. + if (!parcel.WriteInt32(data.size)) { + return false; + } + if (!parcel.WriteBuffer(data.buffer, data.size)) { + return false; + } + } + } + return true; +} + +/** + * @description: Marshals an IntentParams object into a Parcel. + * @param Key-value pairs in the IntentParams are marshalled separately. + * @return If any key-value pair fails to be marshalled, false is returned. + */ +bool WantParams::Marshalling(Parcel &parcel) const +{ + Parcel tempParcel; + if (!DoMarshalling(tempParcel)) { + return false; + } + + int size = static_cast(tempParcel.GetDataSize()); + if (!parcel.WriteInt32(size)) { + return false; + } + const uint8_t *buffer = tempParcel.ReadUnpadBuffer(size); + if (buffer == nullptr) { + return false; + } + + // Corresponding to Parcel#writeByteArray() in Java. + if (!parcel.WriteInt32(size)) { + return false; + } + if (!parcel.WriteBuffer(buffer, size)) { + return false; + } + + return true; +} + +template +static bool SetArray(const InterfaceID &id, const std::vector &value, sptr &ao) +{ + typename std::vector::size_type size = value.size(); + ao = new (std::nothrow) Array(size, id); + if (ao != nullptr) { + for (typename std::vector::size_type i = 0; i < size; i++) { + ao->Set(i, className::Box(value[i])); + } + return true; + } + return false; +} + +template +static void FillArray(IArray *ao, std::vector &array) +{ + auto func = [&](IInterface *object) { + if (object != nullptr) { + T3 *value = T3::Query(object); + if (value != nullptr) { + array.push_back(T2::Unbox(value)); + } + } + }; + Array::ForEach(ao, func); +} +// inner use template function +template +static void SetNewArray(const AAFwk::InterfaceID &id, AAFwk::IArray *orgIArray, sptr &ao) +{ + if (orgIArray == nullptr) { + return; + } + std::vector array; + auto func = [&](IInterface *object) { + if (object != nullptr) { + T3 *value = T3::Query(object); + if (value != nullptr) { + array.push_back(T2::Unbox(value)); + } + } + }; + Array::ForEach(orgIArray, func); + + typename std::vector::size_type size = array.size(); + if (size > 0) { + ao = new (std::nothrow) AAFwk::Array(size, id); + if (ao != nullptr) { + for (typename std::vector::size_type i = 0; i < size; i++) { + ao->Set(i, T2::Box(array[i])); + } + } + } +} + +bool WantParams::WriteArrayToParcelString(Parcel &parcel, IArray *ao) const +{ + if (ao == nullptr) { + return false; + } + + std::vector array; + auto func = [&](IInterface *object) { + std::string s = String::Unbox(IString::Query(object)); + array.push_back(Str8ToStr16(s)); + }; + + Array::ForEach(ao, func); + + if (!parcel.WriteInt32(VALUE_TYPE_STRINGARRAY)) { + return false; + } + return parcel.WriteString16Vector(array); +} + +bool WantParams::WriteArrayToParcelBool(Parcel &parcel, IArray *ao) const +{ + if (ao == nullptr) { + return false; + } + + std::vector array; + FillArray(ao, array); + if (!parcel.WriteInt32(VALUE_TYPE_BOOLEANARRAY)) { + return false; + } + return parcel.WriteInt8Vector(array); +} + +bool WantParams::WriteArrayToParcelByte(Parcel &parcel, IArray *ao) const +{ + if (ao == nullptr) { + return false; + } + + std::vector array; + FillArray(ao, array); + if (!parcel.WriteInt32(VALUE_TYPE_BYTEARRAY)) { + return false; + } + return parcel.WriteInt8Vector(array); +} + +bool WantParams::WriteArrayToParcelChar(Parcel &parcel, IArray *ao) const +{ + if (ao == nullptr) { + return false; + } + + std::vector array; + FillArray(ao, array); + if (!parcel.WriteInt32(VALUE_TYPE_CHARARRAY)) { + return false; + } + return parcel.WriteInt32Vector(array); +} + +bool WantParams::WriteArrayToParcelShort(Parcel &parcel, IArray *ao) const +{ + if (ao == nullptr) { + return false; + } + + std::vector array; + FillArray(ao, array); + if (!parcel.WriteInt32(VALUE_TYPE_SHORTARRAY)) { + return false; + } + return parcel.WriteInt16Vector(array); +} + +bool WantParams::WriteArrayToParcelInt(Parcel &parcel, IArray *ao) const +{ + if (ao == nullptr) { + return false; + } + + std::vector array; + FillArray(ao, array); + if (!parcel.WriteInt32(VALUE_TYPE_INTARRAY)) { + return false; + } + return parcel.WriteInt32Vector(array); +} + +bool WantParams::WriteArrayToParcelLong(Parcel &parcel, IArray *ao) const +{ + if (ao == nullptr) { + return false; + } + + std::vector array; + FillArray(ao, array); + if (!parcel.WriteInt32(VALUE_TYPE_LONGARRAY)) { + return false; + } + return parcel.WriteInt64Vector(array); +} + +bool WantParams::WriteArrayToParcelFloat(Parcel &parcel, IArray *ao) const +{ + if (ao == nullptr) { + return false; + } + + std::vector array; + FillArray(ao, array); + if (!parcel.WriteInt32(VALUE_TYPE_FLOATARRAY)) { + return false; + } + return parcel.WriteFloatVector(array); +} + +bool WantParams::WriteArrayToParcelDouble(Parcel &parcel, IArray *ao) const +{ + if (ao == nullptr) { + return false; + } + + std::vector array; + FillArray(ao, array); + if (!parcel.WriteInt32(VALUE_TYPE_DOUBLEARRAY)) { + return false; + } + return parcel.WriteDoubleVector(array); +} + +bool WantParams::WriteArrayToParcel(Parcel &parcel, IArray *ao) const +{ + if (Array::IsStringArray(ao)) { + return WriteArrayToParcelString(parcel, ao); + } else if (Array::IsBooleanArray(ao)) { + return WriteArrayToParcelBool(parcel, ao); + } else if (Array::IsByteArray(ao)) { + return WriteArrayToParcelByte(parcel, ao); + } else if (Array::IsCharArray(ao)) { + return WriteArrayToParcelChar(parcel, ao); + } else if (Array::IsShortArray(ao)) { + return WriteArrayToParcelShort(parcel, ao); + } else if (Array::IsIntegerArray(ao)) { + return WriteArrayToParcelInt(parcel, ao); + } else if (Array::IsLongArray(ao)) { + return WriteArrayToParcelLong(parcel, ao); + } else if (Array::IsFloatArray(ao)) { + return WriteArrayToParcelFloat(parcel, ao); + } else if (Array::IsDoubleArray(ao)) { + return WriteArrayToParcelDouble(parcel, ao); + } else { + return true; + } +} + +bool WantParams::ReadFromParcelArrayString(Parcel &parcel, sptr &ao) +{ + std::vector value; + if (!parcel.ReadString16Vector(&value)) { + return false; + } + + std::vector::size_type size = value.size(); + ao = new (std::nothrow) Array(size, g_IID_IString); + if (ao != nullptr) { + for (std::vector::size_type i = 0; i < size; i++) { + ao->Set(i, String::Box(Str16ToStr8(value[i]))); + } + return true; + } + return false; +} + +bool WantParams::ReadFromParcelArrayBool(Parcel &parcel, sptr &ao) +{ + std::vector value; + if (!parcel.ReadInt8Vector(&value)) { + return false; + } + return SetArray(g_IID_IBoolean, value, ao); +} + +bool WantParams::ReadFromParcelArrayByte(Parcel &parcel, sptr &ao) +{ + std::vector value; + if (!parcel.ReadInt8Vector(&value)) { + return false; + } + return SetArray(g_IID_IByte, value, ao); +} + +bool WantParams::ReadFromParcelArrayChar(Parcel &parcel, sptr &ao) +{ + std::vector value; + if (!parcel.ReadInt32Vector(&value)) { + return false; + } + return SetArray(g_IID_IChar, value, ao); +} + +bool WantParams::ReadFromParcelArrayShort(Parcel &parcel, sptr &ao) +{ + std::vector value; + if (!parcel.ReadInt16Vector(&value)) { + return false; + } + return SetArray(g_IID_IShort, value, ao); +} + +bool WantParams::ReadFromParcelArrayInt(Parcel &parcel, sptr &ao) +{ + std::vector value; + if (!parcel.ReadInt32Vector(&value)) { + return false; + } + return SetArray(g_IID_IInteger, value, ao); +} + +bool WantParams::ReadFromParcelArrayLong(Parcel &parcel, sptr &ao) +{ + std::vector value; + if (!parcel.ReadInt64Vector(&value)) { + return false; + } + + #ifdef WANT_PARAM_USE_LONG + return SetArray(g_IID_ILong, value, ao); + #else + std::vector strList; + + for (size_t i=0; i(g_IID_IString, strList, ao); + #endif +} + +bool WantParams::ReadFromParcelArrayFloat(Parcel &parcel, sptr &ao) +{ + std::vector value; + if (!parcel.ReadFloatVector(&value)) { + return false; + } + return SetArray(g_IID_IFloat, value, ao); +} + +bool WantParams::ReadFromParcelArrayDouble(Parcel &parcel, sptr &ao) +{ + std::vector value; + if (!parcel.ReadDoubleVector(&value)) { + return false; + } + return SetArray(g_IID_IDouble, value, ao); +} + +bool WantParams::ReadArrayToParcel(Parcel &parcel, int type, sptr &ao) +{ + switch (type) { + case VALUE_TYPE_STRINGARRAY: + case VALUE_TYPE_CHARSEQUENCEARRAY: + return ReadFromParcelArrayString(parcel, ao); + case VALUE_TYPE_BOOLEANARRAY: + return ReadFromParcelArrayBool(parcel, ao); + case VALUE_TYPE_BYTEARRAY: + return ReadFromParcelArrayByte(parcel, ao); + case VALUE_TYPE_CHARARRAY: + return ReadFromParcelArrayChar(parcel, ao); + case VALUE_TYPE_SHORTARRAY: + return ReadFromParcelArrayShort(parcel, ao); + case VALUE_TYPE_INTARRAY: + return ReadFromParcelArrayInt(parcel, ao); + case VALUE_TYPE_LONGARRAY: + return ReadFromParcelArrayLong(parcel, ao); + case VALUE_TYPE_FLOATARRAY: + return ReadFromParcelArrayFloat(parcel, ao); + case VALUE_TYPE_DOUBLEARRAY: + return ReadFromParcelArrayDouble(parcel, ao); + default: + break; + } + + return true; +} + +bool WantParams::ReadFromParcelString(Parcel &parcel, const std::string &key) +{ + std::u16string value = parcel.ReadString16(); + sptr intf = String::Box(Str16ToStr8(value)); + if (intf) { + SetParam(key, intf); + } + return true; +} + +bool WantParams::ReadFromParcelBool(Parcel &parcel, const std::string &key) +{ + int8_t value; + if (parcel.ReadInt8(value)) { + sptr intf = Boolean::Box(value); + if (intf) { + SetParam(key, intf); + } + return true; + } else { + return false; + } +} + +bool WantParams::ReadFromParcelInt8(Parcel &parcel, const std::string &key) +{ + int8_t value; + if (parcel.ReadInt8(value)) { + sptr intf = Byte::Box(value); + if (intf) { + SetParam(key, intf); + } + return true; + } else { + return false; + } +} + +bool WantParams::ReadFromParcelChar(Parcel &parcel, const std::string &key) +{ + int32_t value; + if (parcel.ReadInt32(value)) { + sptr intf = Char::Box(value); + if (intf) { + SetParam(key, intf); + } + return true; + } else { + return false; + } +} + +bool WantParams::ReadFromParcelShort(Parcel &parcel, const std::string &key) +{ + short value; + if (parcel.ReadInt16(value)) { + sptr intf = Short::Box(value); + if (intf) { + SetParam(key, intf); + } + return true; + } else { + return false; + } +} + +bool WantParams::ReadFromParcelInt(Parcel &parcel, const std::string &key) +{ + int value; + if (parcel.ReadInt32(value)) { + sptr intf = Integer::Box(value); + if (intf) { + SetParam(key, intf); + } + return true; + } else { + return false; + } +} +bool WantParams::ReadFromParcelWantParamWrapper(Parcel &parcel, const std::string &key) +{ + std::u16string value = parcel.ReadString16(); + sptr intf = WantParamWrapper::Parse(Str16ToStr8(value)); + if (intf) { + SetParam(key, intf); + } + return true; +} +bool WantParams::ReadFromParcelLong(Parcel &parcel, const std::string &key) +{ + int64_t value; + if (parcel.ReadInt64(value)) { + #ifdef WANT_PARAM_USE_LONG + sptr intf = Long::Box(value); + #else + sptr intf = String::Box(std::to_string(value)); + #endif + if (intf) { + SetParam(key, intf); + } + return true; + } else { + return false; + } +} + +bool WantParams::ReadFromParcelFloat(Parcel &parcel, const std::string &key) +{ + float value; + if (parcel.ReadFloat(value)) { + sptr intf = Float::Box(value); + if (intf) { + SetParam(key, intf); + } + return true; + } else { + return false; + } +} + +bool WantParams::ReadFromParcelDouble(Parcel &parcel, const std::string &key) +{ + double value; + if (parcel.ReadDouble(value)) { + sptr intf = Double::Box(value); + if (intf) { + SetParam(key, intf); + } + return true; + } else { + return false; + } +} + +bool WantParams::ReadUnsupportedData(Parcel &parcel, const std::string &key, int type) +{ + int bufferSize = 0; + if (!parcel.ReadInt32(bufferSize)) { + return false; + } + if (bufferSize < 0) { + return false; + } + + // Corresponding to Parcel#writeByteArray() in Java. + int32_t length = 0; + if (!parcel.ReadInt32(length)) { + return false; + } + const uint8_t *bufferP = parcel.ReadUnpadBuffer(bufferSize); + if (bufferP == nullptr) { + return false; + } + + UnsupportedData data; + data.key = Str8ToStr16(key); + data.type = type; + data.size = bufferSize; + data.buffer = new (std::nothrow) uint8_t[bufferSize]; + if (data.buffer == nullptr) { + return false; + } + + if (memcpy_s(data.buffer, bufferSize, bufferP, bufferSize) != EOK) { + return false; + } + cachedUnsupportedData_.emplace_back(std::move(data)); + return true; +} + +bool WantParams::ReadFromParcelParam(Parcel &parcel, const std::string &key, int type) +{ + switch (type) { + case VALUE_TYPE_CHARSEQUENCE: + case VALUE_TYPE_STRING: + return ReadFromParcelString(parcel, key); + case VALUE_TYPE_BOOLEAN: + return ReadFromParcelBool(parcel, key); + case VALUE_TYPE_BYTE: + return ReadFromParcelInt8(parcel, key); + case VALUE_TYPE_CHAR: + return ReadFromParcelChar(parcel, key); + case VALUE_TYPE_SHORT: + return ReadFromParcelShort(parcel, key); + case VALUE_TYPE_INT: + return ReadFromParcelInt(parcel, key); + case VALUE_TYPE_LONG: + return ReadFromParcelLong(parcel, key); + case VALUE_TYPE_FLOAT: + return ReadFromParcelFloat(parcel, key); + case VALUE_TYPE_DOUBLE: + return ReadFromParcelDouble(parcel, key); + case VALUE_TYPE_NULL: + break; + case VALUE_TYPE_PARCELABLE: + case VALUE_TYPE_PARCELABLEARRAY: + case VALUE_TYPE_SERIALIZABLE: + case VALUE_TYPE_LIST: + if (!ReadUnsupportedData(parcel, key, type)) { + return false; + } + break; + default: { + // handle array + sptr ao = nullptr; + if (!ReadArrayToParcel(parcel, type, ao)) { + return false; + } + sptr intf = ao; + if (intf) { + SetParam(key, intf); + } + break; + } + } + return true; +} + +bool WantParams::ReadFromParcel(Parcel &parcel) +{ + int32_t size; + + if (!parcel.ReadInt32(size)) { + return false; + } + + for (int32_t i = 0; i < size; i++) { + std::u16string key = parcel.ReadString16(); + int type; + if (!parcel.ReadInt32(type)) { + return false; + } + + if (!ReadFromParcelParam(parcel, Str16ToStr8(key), type)) { + return false; + } + } + + return true; +} + +/** + * @description: Unmarshals an IntentParams object from a Parcel. + * @param Key-value pairs in the IntentParams are unmarshalled separately. + * @return If any key-value pair fails to be unmarshalled, false is returned. + */ +WantParams *WantParams::Unmarshalling(Parcel &parcel) +{ + int32_t bufferSize; + if (!parcel.ReadInt32(bufferSize)) { + return nullptr; + } + + // Corresponding to Parcel#writeByteArray() in Java. + int32_t length; + if (!parcel.ReadInt32(length)) { + return nullptr; + } + const uint8_t *dataInBytes = parcel.ReadUnpadBuffer(bufferSize); + if (dataInBytes == nullptr) { + return nullptr; + } + + Parcel tempParcel; + if (!tempParcel.WriteBuffer(dataInBytes, bufferSize)) { + return nullptr; + } + + WantParams *wantParams = new (std::nothrow) WantParams(); + if (wantParams != nullptr && !wantParams->ReadFromParcel(tempParcel)) { + delete wantParams; + wantParams = nullptr; + } + return wantParams; +} + +void WantParams::DumpInfo(int level) const +{ + APP_LOGI("=======WantParams::DumpInfo level: %{public}d start=============", level); + + int params_size = params_.size(); + APP_LOGI("===WantParams::params_: count %{public}d =============", params_size); + int typeId = VALUE_TYPE_NULL; + for (auto it : params_) { + typeId = VALUE_TYPE_NULL; + typeId = WantParams::GetDataType(it.second); + if (typeId != VALUE_TYPE_NULL) { + std::string value = WantParams::GetStringByType(it.second, typeId); + APP_LOGI("=WantParams::params_[%{public}s] : %{public}s =============", it.first.c_str(), value.c_str()); + } else { + APP_LOGI("=WantParams::params_[%{public}s] : type error =============", it.first.c_str()); + } + } + APP_LOGI("=======WantParams::DumpInfo level: %{public}d end=============", level); +} +} // namespace AAFwk +} // namespace OHOS diff --git a/tools/frameworks/kits/content/cpp/src/ohos/aafwk/content/want_params_wrapper.cpp b/tools/frameworks/kits/content/cpp/src/ohos/aafwk/content/want_params_wrapper.cpp new file mode 100755 index 00000000000..0158d50fa5b --- /dev/null +++ b/tools/frameworks/kits/content/cpp/src/ohos/aafwk/content/want_params_wrapper.cpp @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "ohos/aafwk/content/want_params_wrapper.h" +#include +namespace OHOS { +namespace AAFwk { +#define WANT_PARAM_WRAPPER_TWO 2 +IINTERFACE_IMPL_1(WantParamWrapper, Object, IWantParams); +const InterfaceID g_IID_IWantParams = { + 0xa75b9db6, 0x9813, 0x4371, 0x8848, {0xd, 0x2, 0x9, 0x6, 0x6, 0xc, 0xe, 0x6, 0xe, 0xc, 0x6, 0x8} +}; +ErrCode WantParamWrapper::GetValue(WantParams &value) +{ + + value = wantParams_; + return ERR_OK; +} + +bool WantParamWrapper::Equals(IObject &other) +{ + WantParamWrapper *otherObj = static_cast(IWantParams::Query(&other)); + return otherObj != nullptr && otherObj->wantParams_ == wantParams_; +} + +std::string WantParamWrapper::ToString() +{ + std::string result; + if (wantParams_.Size() != 0) { + result += "{"; + for (auto it : wantParams_.GetParams()) { + int typeId = WantParams::GetDataType(it.second); + result = result + "\"" + it.first + "\":{\"" + std::to_string(typeId) + "\":"; + if (IWantParams::Query(it.second) != nullptr) { + result = result + static_cast(IWantParams::Query(it.second))->ToString(); + } else { + result = result + "\"" + WantParams::GetStringByType(it.second, typeId) + "\""; + } + if (it == *wantParams_.GetParams().rbegin()) { + result += "}"; + } else { + result += "},"; + } + } + result += "}"; + } else { + result = "{}"; + } + return result; +} + +sptr WantParamWrapper::Box(const WantParams &value) +{ + sptr object = new (std::nothrow)WantParamWrapper(value); + return object; +} + +WantParams WantParamWrapper::Unbox(IWantParams *object) +{ + WantParams value; + if (object != nullptr) { + object->GetValue(value); + } + return value; +} +bool WantParamWrapper::ValidateStr(const std::string &str) +{ + if (str == "" || str == "{}" || str == "{\"\"}") { + return false; + } + if (count(str.begin(), str.end(), '\"') % WANT_PARAM_WRAPPER_TWO != 0) { + return false; + } + if (count(str.begin(), str.end(), '{') != count(str.begin(), str.end(), '}')) { + return false; + } + int count = 0; + for (auto it : str) { + if (it == '{') { + count++; + } + if (it == '}') { + count--; + } + if (count < 0) { + return false; + } + } + return true; +} +sptr WantParamWrapper::Parse(const std::string &str) +{ + WantParams wantPaqrams; + std::string key = ""; + int typeId = 0; + if (ValidateStr(str)) { + for (unsigned int strnum = 0; strnum < str.size(); strnum++) { + if (str[strnum] == '{' && key != "" && typeId == WantParams::VALUE_TYPE_WANTPARAMS) { + unsigned int num; + int count = 0; + for (num = strnum; num < str.size(); num++) { + if (str[num] == '{') { + count++; + } else if (str[num] == '}') { + count--; + } + if (count == 0) { + break; + } + } + wantPaqrams.SetParam(key, WantParamWrapper::Parse(str.substr(strnum, num - strnum))); + key = ""; + typeId = 0; + strnum = num + 1; + } else if (str[strnum] == '"') { + if (key == "") { + strnum++; + key = str.substr(strnum, str.find('"', strnum) - strnum); + strnum = str.find('"', strnum); + } else if (typeId == 0) { + strnum++; + typeId = atoi(str.substr(strnum, str.find('"', strnum) - strnum).c_str()); + if (errno == ERANGE) { + return nullptr; + } + strnum = str.find('"', strnum); + } else { + strnum++; + wantPaqrams.SetParam(key, + WantParams::GetInterfaceByType(typeId, str.substr(strnum, str.find('"', strnum) - strnum))); + strnum = str.find('"', strnum); + typeId = 0; + key = ""; + } + } + } + } + sptr iwantParams = new WantParamWrapper(wantPaqrams); + return iwantParams; +} +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/content/cpp/src/ohos/aafwk/content/want_params_wrapper.h b/tools/frameworks/kits/content/cpp/src/ohos/aafwk/content/want_params_wrapper.h new file mode 100755 index 00000000000..fd9bc2cbd73 --- /dev/null +++ b/tools/frameworks/kits/content/cpp/src/ohos/aafwk/content/want_params_wrapper.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef OHOS_AAFWK_WANT_PARAMS_WRAPPER_H +#define OHOS_AAFWK_WANT_PARAMS_WRAPPER_H +#include "ohos/aafwk/content/want_params.h" +#include "ohos/aafwk/base/base_def.h" +#include "ohos/aafwk/base/base_object.h" +namespace OHOS { +namespace AAFwk { +class WantParams; +INTERFACE(IWantParams, a75b9db6 - 9813 - 4371 - 8848 - d2966ce6ec68) +{ + inline static IWantParams *Query(IInterface * object) + { + if (object == nullptr) { + return nullptr; + } + return static_cast(object->Query(g_IID_IWantParams)); + } + + virtual ErrCode GetValue(WantParams & value) = 0; +}; +class WantParamWrapper final : public Object, public IWantParams { +public: + inline WantParamWrapper(const WantParams &value) : wantParams_(value) + {} + + inline ~WantParamWrapper() + {} + + IINTERFACE_DECL(); + + ErrCode GetValue(WantParams &value) override; + + bool Equals(IObject &other) override; + + std::string ToString() override; + + static sptr Box(const WantParams &value); + + static WantParams Unbox(IWantParams *object); + + static bool ValidateStr(const std::string &str); + + static sptr Parse(const std::string &str); + + static constexpr char SIGNATURE = 'W'; + +private: + WantParams wantParams_; +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_WANT_PARAMS_WRAPPER_H \ No newline at end of file diff --git a/tools/frameworks/kits/content/cpp/test/BUILD.gn b/tools/frameworks/kits/content/cpp/test/BUILD.gn new file mode 100755 index 00000000000..d0883d273b3 --- /dev/null +++ b/tools/frameworks/kits/content/cpp/test/BUILD.gn @@ -0,0 +1,351 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/test.gni") + +module_output_path = "aafwk_standard/intent_test" + +############################################################################### +config("module_private_config") { + visibility = [ ":*" ] + include_dirs = [ + "//utils/native/base/include", + "//sdk/appexecfwk/appexecfwk_base/include", + "//foundation/aafwk/standard/interfaces/innerkits/want/include", + "//foundation/aafwk/standard/interfaces/innerkits/intent/include", + ] + + defines = [ + "APP_LOG_TAG = \"WantUnitTest\"", + "LOG_DOMAIN = 0xD002210", + ] +} + +config("module_private_want_param_wrapper_config") { + visibility = [ ":*" ] + include_dirs = [ + "//utils/native/base/include", + "//sdk/appexecfwk/appexecfwk_base/include", + "//foundation/aafwk/standard/interfaces/innerkits/want/include", + "//foundation/aafwk/standard/frameworks/kits/content/cpp/src", + ] + + defines = [ + "APP_LOG_TAG = \"WantUnitTest\"", + "LOG_DOMAIN = 0xD002210", + ] +} + +ohos_unittest("intent_parcelable_test") { + module_out_path = module_output_path + sources = [] + + configs = [ + ":module_private_config", + #"//foundation/aafwk/standard/interfaces/innerkits/intent:intent_public_config", + ] + + deps = [ + "//foundation/aafwk/standard/interfaces/innerkits/base:base", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "appexecfwk_standard:appexecfwk_base", + "ipc:ipc_core", + ] +} + +ohos_unittest("intent_base_test") { + module_out_path = module_output_path + sources = [] + + configs = [ + ":module_private_config", + #"//foundation/aafwk/standard/interfaces/innerkits/intent:intent_public_config", + ] + + deps = [ + "//foundation/aafwk/standard/interfaces/innerkits/base:base", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "appexecfwk_standard:appexecfwk_base", + "ipc:ipc_core", + ] +} + +ohos_unittest("intent_parse_to_uri_test") { + module_out_path = module_output_path + sources = [] + + configs = [ + ":module_private_config", + #"//foundation/aafwk/standard/interfaces/innerkits/intent:intent_public_config", + ] + + deps = [ + "//foundation/aafwk/standard/interfaces/innerkits/base:base", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "appexecfwk_standard:appexecfwk_base", + "ipc:ipc_core", + ] +} + +ohos_unittest("intent_parameters_test") { + module_out_path = module_output_path + sources = [ + "../src/ohos/aafwk/content/intent.cpp", + "../src/ohos/aafwk/content/intent_params.cpp", + "unittest/common/intent_parameters_test.cpp", + ] + + configs = [ + ":module_private_config", + #"//foundation/aafwk/standard/interfaces/innerkits/intent:intent_public_config", + ] + + deps = [ + "//foundation/aafwk/standard/interfaces/innerkits/base:base", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "appexecfwk_standard:appexecfwk_base", + "ipc:ipc_core", + ] +} + +ohos_unittest("intent_params_test") { + module_out_path = module_output_path + sources = [] + + configs = [ + ":module_private_config", + #"//foundation/aafwk/standard/interfaces/innerkits/intent:intent_public_config", + ] + + deps = [ + "//foundation/aafwk/standard/interfaces/innerkits/base:base", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "appexecfwk_standard:appexecfwk_base", + "ipc:ipc_core", + ] +} + +ohos_unittest("intent_filter_test") { + module_out_path = module_output_path + sources = [ + "../src/ohos/aafwk/content/intent.cpp", + "../src/ohos/aafwk/content/intent_filter.cpp", + "../src/ohos/aafwk/content/intent_params.cpp", + "unittest/common/intent_filter_test.cpp", + ] + + configs = [ + ":module_private_config", + #"//foundation/aafwk/standard/interfaces/innerkits/intent:intent_public_config", + ] + + deps = [ + "//foundation/aafwk/standard/interfaces/innerkits/base:base", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ "appexecfwk_standard:appexecfwk_base" ] +} + +ohos_unittest("operation_test") { + module_out_path = module_output_path + sources = [ + "//foundation/aafwk/standard/interfaces/innerkits/want/include/ohos/aafwk/content/operation_builder.h", + "//foundation/distributedschedule/dmsfwk/services/dtbschedmgr/include/uri.h", + "unittest/common/operation_test.cpp", + ] + + configs = [ + ":module_private_config", + "//foundation/aafwk/standard/interfaces/innerkits/want:want_public_config", + ] + + deps = [ + "//foundation/aafwk/standard/interfaces/innerkits/base:base", + "//foundation/aafwk/standard/interfaces/innerkits/want:want", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ "appexecfwk_standard:appexecfwk_base" ] +} + +ohos_unittest("patterns_matcher_test") { + module_out_path = module_output_path + sources = [ + "../src/ohos/aafwk/content/patterns_matcher.cpp", + "unittest/common/patterns_matcher_test.cpp", + ] + + configs = [ + ":module_private_config", + "//foundation/aafwk/standard/interfaces/innerkits/want:want_public_config", + ] + + deps = [ + "//foundation/aafwk/standard/interfaces/innerkits/base:base", + "//foundation/appexecfwk/standard/common:libappexecfwk_common", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "appexecfwk_standard:appexecfwk_base", + "hiviewdfx_hilog_native:libhilog", + ] +} + +ohos_unittest("skills_test") { + module_out_path = module_output_path + sources = [ + "../src/ohos/aafwk/content/skills.cpp", + "unittest/common/skills_test.cpp", + ] + + configs = [ + ":module_private_config", + "//foundation/aafwk/standard/interfaces/innerkits/want:want_public_config", + ] + + deps = [ + "//foundation/aafwk/standard/interfaces/innerkits/base:base", + "//foundation/aafwk/standard/interfaces/innerkits/want:want", + "//foundation/appexecfwk/standard/common:libappexecfwk_common", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "appexecfwk_standard:appexecfwk_base", + "hiviewdfx_hilog_native:libhilog", + ] +} + +ohos_unittest("want_params_test") { + module_out_path = module_output_path + sources = [ + "../src/ohos/aafwk/content/want_params.cpp", + "../src/ohos/aafwk/content/want_params_wrapper.cpp", + "unittest/common/want_params_test.cpp", + ] + + configs = [ + ":module_private_config", + "//foundation/aafwk/standard/interfaces/innerkits/want:want_public_config", + ] + + deps = [ + "//foundation/aafwk/standard/interfaces/innerkits/base:base", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "appexecfwk_standard:appexecfwk_base", + "hiviewdfx_hilog_native:libhilog", + ] +} + +ohos_unittest("want_params_wrapper_test") { + module_out_path = module_output_path + sources = [ + "../src/ohos/aafwk/content/want_params.cpp", + "../src/ohos/aafwk/content/want_params_wrapper.cpp", + "unittest/common/want_params_wrapper_test.cpp", + ] + + configs = [ ":module_private_want_param_wrapper_config" ] + + deps = [ + "//foundation/aafwk/standard/interfaces/innerkits/base:base", + "//foundation/aafwk/standard/interfaces/innerkits/want:want", + "//foundation/appexecfwk/standard/common:libappexecfwk_common", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "appexecfwk_standard:appexecfwk_base", + "hiviewdfx_hilog_native:libhilog", + ] +} + +ohos_unittest("want_test") { + module_out_path = module_output_path + sources = [ "unittest/common/want_test.cpp" ] + + configs = [ + ":module_private_config", + "//foundation/aafwk/standard/interfaces/innerkits/want:want_public_config", + ] + + deps = [ + "//foundation/aafwk/standard/interfaces/innerkits/base:base", + "//foundation/aafwk/standard/interfaces/innerkits/want:want", + "//foundation/appexecfwk/standard/common:libappexecfwk_common", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "appexecfwk_standard:appexecfwk_base", + "hiviewdfx_hilog_native:libhilog", + ] +} + +############################################################################### + +group("unittest") { + testonly = true + deps = [] + + deps += [ + ## ":intent_params_test", + ## ":intent_parameters_test", + ## ":intent_parse_to_uri_test", + ## ":intent_base_test", + ## ":intent_filter_test", + ":operation_test", + ":patterns_matcher_test", + ":skills_test", + ":want_params_test", + ":want_params_wrapper_test", + ":want_test", + ] +} +############################################################################### diff --git a/tools/frameworks/kits/content/cpp/test/unittest/common/intent_filter_test.cpp b/tools/frameworks/kits/content/cpp/test/unittest/common/intent_filter_test.cpp new file mode 100644 index 00000000000..b95f41d59b8 --- /dev/null +++ b/tools/frameworks/kits/content/cpp/test/unittest/common/intent_filter_test.cpp @@ -0,0 +1,462 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "ohos/aafwk/content/intent.h" +#include "ohos/aafwk/content/intent_filter.h" + +using namespace testing::ext; +using namespace OHOS::AAFwk; +using OHOS::Parcel; + +static const int LARGE_STR_LEN = 65534; +static const int SET_COUNT = 20; +static const int LOOP_TEST = 1000; + +class IntentFilterBaseTest : public testing::Test { +public: + IntentFilterBaseTest() : filter_(nullptr) + {} + ~IntentFilterBaseTest() + { + filter_ = nullptr; + } + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + + IntentFilter *filter_; + void CompareFilter(IntentFilter &filter1, IntentFilter &filter2); + void SendParcelTest(IntentFilter &filter); +}; + +void IntentFilterBaseTest::SetUpTestCase(void) +{} + +void IntentFilterBaseTest::TearDownTestCase(void) +{} + +void IntentFilterBaseTest::SetUp(void) +{ + filter_ = new (std::nothrow) IntentFilter(); +} + +void IntentFilterBaseTest::TearDown(void) +{ + delete filter_; + filter_ = nullptr; +} + +/* + * Feature: IntentFilter + * Function: SetEntity/GetEntity + * SubFunction: NA + * FunctionPoints: SetEntity/GetEntity + * EnvConditions: NA + * CaseDescription: Verify the function when the input string is empty + */ +HWTEST_F(IntentFilterBaseTest, AaFwk_IntentFilter_Entity_001, TestSize.Level1) +{ + std::string setValue; + filter_->SetEntity(setValue); + EXPECT_EQ(setValue, filter_->GetEntity()); +} + +/* + * Feature: IntentFilter + * Function: SetEntity/GetEntity + * SubFunction: NA + * FunctionPoints: SetEntity/GetEntity + * EnvConditions: NA + * CaseDescription: Verify the function when the input string contains special characters + */ +HWTEST_F(IntentFilterBaseTest, AaFwk_IntentFilter_Entity_002, TestSize.Level1) +{ + std::string setValue("@#¥#3243adsafdf_中文"); + filter_->SetEntity(setValue); + EXPECT_EQ(setValue, filter_->GetEntity()); +} + +/* + * Feature: IntentFilter + * Function: SetEntity/GetEntity + * SubFunction: NA + * FunctionPoints: SetEntity/GetEntity + * EnvConditions: NA + * CaseDescription: Verify the function when the input string has a long size + */ +HWTEST_F(IntentFilterBaseTest, AaFwk_IntentFilter_Entity_003, TestSize.Level1) +{ + std::string setValue(LARGE_STR_LEN, 's'); + filter_->SetEntity(setValue); + EXPECT_EQ(setValue, filter_->GetEntity()); +} + +/* + * Feature: IntentFilter + * Function: SetEntity/GetEntity + * SubFunction: NA + * FunctionPoints: SetEntity/GetEntity + * EnvConditions: NA + * CaseDescription: Verify the function when the input string is overrode + */ +HWTEST_F(IntentFilterBaseTest, AaFwk_IntentFilter_Entity_004, TestSize.Level1) +{ + std::string setValue1("1234"); + filter_->SetEntity(setValue1); + + std::string setValue2("abcd"); + filter_->SetEntity(setValue2); + + EXPECT_EQ(setValue2, filter_->GetEntity()); +} + +/* + * Feature: IntentFilter + * Function: SetEntity/GetEntity + * SubFunction: NA + * FunctionPoints: SetEntity/GetEntity + * EnvConditions: NA + * CaseDescription: Verify the function when the input string is set 20 times + */ +HWTEST_F(IntentFilterBaseTest, AaFwk_IntentFilter_Entity_005, TestSize.Level1) +{ + std::string setValue("1234"); + for (int i = 0; i < SET_COUNT; i++) { + filter_->SetEntity(setValue); + } + EXPECT_EQ(setValue, filter_->GetEntity()); +} + +/* + * Feature: IntentFilter + * Function: SetEntity/GetEntity + * SubFunction: NA + * FunctionPoints: SetEntity/GetEntity + * EnvConditions: NA + * CaseDescription: Verify the function when the input string is default + */ +HWTEST_F(IntentFilterBaseTest, AaFwk_IntentFilter_Entity_006, TestSize.Level1) +{ + std::string setValue; + EXPECT_EQ(setValue, filter_->GetEntity()); +} + +/* + * Feature: IntentFilter + * Function: SetEntity/GetEntity + * SubFunction: NA + * FunctionPoints: SetEntity/GetEntity + * EnvConditions: NA + * CaseDescription: Verify the function when the input string contains special characters + */ +HWTEST_F(IntentFilterBaseTest, AaFwk_IntentFilter_Entity_007, TestSize.Level1) +{ + std::string setValue("@#¥#3243adsafdf_中文"); + for (int i = 0; i < LOOP_TEST; i++) { + filter_->SetEntity(setValue); + EXPECT_EQ(setValue, filter_->GetEntity()); + } +} + +/* + * Feature: IntentFilter + * Function: action + * SubFunction: NA + * FunctionPoints: action + * EnvConditions: NA + * CaseDescription: Verify the function when action is not exist + */ +HWTEST_F(IntentFilterBaseTest, AaFwk_IntentFilter_Action_001, TestSize.Level1) +{ + std::string empty; + std::string action = "action.system.test"; + EXPECT_EQ(0, filter_->CountAction()); + EXPECT_EQ(false, filter_->HasAction(action)); + EXPECT_EQ(empty, filter_->GetAction(0)); + + filter_->RemoveAction(action); + EXPECT_EQ(0, filter_->CountAction()); + EXPECT_EQ(false, filter_->HasAction(action)); +} + +/* + * Feature: IntentFilter + * Function: action + * SubFunction: NA + * FunctionPoints: action + * EnvConditions: NA + * CaseDescription: Verify the function when actions are same + */ +HWTEST_F(IntentFilterBaseTest, AaFwk_IntentFilter_Action_002, TestSize.Level1) +{ + std::string action = "action.system.test"; + int actionCount = 1; + + for (int i = 0; i < SET_COUNT; i++) { + filter_->AddAction(action); + } + + EXPECT_EQ(actionCount, filter_->CountAction()); + EXPECT_EQ(true, filter_->HasAction(action)); + EXPECT_EQ(action, filter_->GetAction(0)); + + filter_->RemoveAction(action); + EXPECT_EQ(0, filter_->CountAction()); + EXPECT_EQ(false, filter_->HasAction(action)); +} + +/* + * Feature: IntentFilter + * Function: action + * SubFunction: NA + * FunctionPoints: action + * EnvConditions: NA + * CaseDescription: Verify the function when actions are different + */ +HWTEST_F(IntentFilterBaseTest, AaFwk_IntentFilter_Action_003, TestSize.Level1) +{ + std::string actionPrefix = "action.system.test"; + + for (int i = 0; i < SET_COUNT; i++) { + std::string action = actionPrefix + std::to_string(i); + filter_->AddAction(action); + } + + EXPECT_EQ(SET_COUNT, filter_->CountAction()); + for (int i = 0; i < SET_COUNT; i++) { + std::string action = actionPrefix + std::to_string(i); + EXPECT_EQ(true, filter_->HasAction(action)); + EXPECT_EQ(action, filter_->GetAction(i)); + } + + int remove = SET_COUNT / 2; + for (int i = 0; i < remove; i++) { + std::string action = actionPrefix + std::to_string(i); + filter_->RemoveAction(action); + } + + EXPECT_EQ(remove, filter_->CountAction()); + for (int i = 0; i < remove; i++) { + std::string action = actionPrefix + std::to_string(i); + EXPECT_EQ(false, filter_->HasAction(action)); + } + + for (int i = remove; i < SET_COUNT; i++) { + std::string action = actionPrefix + std::to_string(i); + EXPECT_EQ(true, filter_->HasAction(action)); + EXPECT_EQ(action, filter_->GetAction(i - remove)); + } +} + +/* + * Feature: IntentFilter + * Function: action + * SubFunction: NA + * FunctionPoints: action + * EnvConditions: NA + * CaseDescription: Verify the function when actions are same + */ +HWTEST_F(IntentFilterBaseTest, AaFwk_IntentFilter_Action_004, TestSize.Level1) +{ + std::string action = "action.system.test"; + int actionCount = 1; + + for (int i = 0; i < LOOP_TEST; i++) { + filter_->AddAction(action); + EXPECT_EQ(actionCount, filter_->CountAction()); + EXPECT_EQ(true, filter_->HasAction(action)); + EXPECT_EQ(action, filter_->GetAction(0)); + + filter_->RemoveAction(action); + EXPECT_EQ(0, filter_->CountAction()); + EXPECT_EQ(false, filter_->HasAction(action)); + } +} + +void IntentFilterBaseTest::CompareFilter(IntentFilter &filter1, IntentFilter &filter2) +{ + EXPECT_EQ(filter1.GetEntity(), filter2.GetEntity()); + EXPECT_EQ(filter1.CountAction(), filter2.CountAction()); + + int count = filter1.CountAction(); + for (int i = 0; i < count; i++) { + EXPECT_EQ(filter1.GetAction(i), filter2.GetAction(i)); + } +} + +void IntentFilterBaseTest::SendParcelTest(IntentFilter &filter) +{ + Parcel data; + bool result; + + result = data.WriteParcelable(&filter); + EXPECT_EQ(result, true); + + IntentFilter *filterNew = nullptr; + filterNew = data.ReadParcelable(); + EXPECT_NE(filterNew, nullptr); + + if (filterNew) { + CompareFilter(filter, *filterNew); + delete filterNew; + } +} + +/* + * Feature: IntentFilter + * Function: marshall and unmarshall + * SubFunction: NA + * FunctionPoints: marshall and unmarshall + * EnvConditions: NA + * CaseDescription: Verify marshall and unmarshall when filter is empty + */ +HWTEST_F(IntentFilterBaseTest, AaFwk_IntentFilter_parcelable_001, TestSize.Level0) +{ + SendParcelTest(*filter_); +} + +/* + * Feature: IntentFilter + * Function: marshall and unmarshall + * SubFunction: NA + * FunctionPoints: marshall and unmarshall + * EnvConditions: NA + * CaseDescription: Verify marshall and unmarshall when filter has action and entity + */ +HWTEST_F(IntentFilterBaseTest, AaFwk_IntentFilter_parcelable_002, TestSize.Level0) +{ + filter_->SetEntity("entity.system.test"); + filter_->AddAction("action.system.test1"); + filter_->AddAction("action.system.test2"); + + SendParcelTest(*filter_); +} + +/* + * Feature: IntentFilter + * Function: marshall and unmarshall + * SubFunction: NA + * FunctionPoints: marshall and unmarshall + * EnvConditions: NA + * CaseDescription: Verify marshall and unmarshall. Pressure test. + */ +HWTEST_F(IntentFilterBaseTest, AaFwk_IntentFilter_parcelable_003, TestSize.Level0) +{ + filter_->SetEntity("entity.system.test"); + filter_->AddAction("action.system.test1"); + filter_->AddAction("action.system.test2"); + + for (int i = 0; i < LOOP_TEST; i++) { + SendParcelTest(*filter_); + } +} + +/* + * Feature: IntentFilter + * Function: Match + * SubFunction: NA + * FunctionPoints: Match + * EnvConditions: NA + * CaseDescription: Verify the function. Pressure test. + */ +HWTEST_F(IntentFilterBaseTest, AaFwk_IntentFilter_match_005, TestSize.Level1) +{ + for (int i = 0; i < LOOP_TEST; i++) { + Intent intent; + intent.SetAction("action.system.action1"); + intent.SetEntity("entity.system.entity1"); + + filter_->SetEntity("entity.system.entity1"); + filter_->AddAction("action.system.action1"); + filter_->AddAction("action.system.action2"); + + EXPECT_EQ(true, filter_->Match(intent)); + } +} + +using testFilterMatchType = std::tuple; +class IntentFilterMatchTest : public testing::TestWithParam { +public: + IntentFilterMatchTest() : filter_(nullptr) + {} + ~IntentFilterMatchTest() + { + filter_ = nullptr; + } + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + IntentFilter *filter_; +}; + +void IntentFilterMatchTest::SetUpTestCase(void) +{} + +void IntentFilterMatchTest::TearDownTestCase(void) +{} + +void IntentFilterMatchTest::SetUp(void) +{ + filter_ = new (std::nothrow) IntentFilter(); +} + +void IntentFilterMatchTest::TearDown(void) +{ + delete filter_; + filter_ = nullptr; +} + +/* + * Feature: IntentFilter + * Function: Match + * SubFunction: NA + * FunctionPoints: Match + * EnvConditions: NA + * CaseDescription: Verify whether parameter change. + * AaFwk_IntentFilter_match_001 + * AaFwk_IntentFilter_match_002 + * AaFwk_IntentFilter_match_003 + * AaFwk_IntentFilter_match_004 + */ + +HWTEST_P(IntentFilterMatchTest, AaFwk_IntentFilter_match, TestSize.Level0) +{ + std::string filterEntity = "entity.system.entity1"; + std::string filterAction1 = "action.system.action1"; + std::string filterAction2 = "action.system.action2"; + std::string intentEntity = std::get<0>(GetParam()); + std::string intentAction = std::get<1>(GetParam()); + bool result = std::get<2>(GetParam()); + + filter_->SetEntity(filterEntity); + filter_->AddAction(filterAction1); + filter_->AddAction(filterAction2); + + Intent intent; + intent.SetEntity(intentEntity); + intent.SetAction(intentAction); + + EXPECT_EQ(result, filter_->Match(intent)); +} + +INSTANTIATE_TEST_CASE_P(IntentFilterMatchTestP, IntentFilterMatchTest, + testing::Values(testFilterMatchType("entity.system.entityA", "action.system.actionA", false), + testFilterMatchType("entity.system.entity1", "action.system.actionA", false), + testFilterMatchType("entity.system.entityA", "action.system.action2", false), + testFilterMatchType("entity.system.entity1", "action.system.action1", true))); diff --git a/tools/frameworks/kits/content/cpp/test/unittest/common/intent_parameters_test.cpp b/tools/frameworks/kits/content/cpp/test/unittest/common/intent_parameters_test.cpp new file mode 100644 index 00000000000..89304940b3d --- /dev/null +++ b/tools/frameworks/kits/content/cpp/test/unittest/common/intent_parameters_test.cpp @@ -0,0 +1,2322 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include "ohos/aafwk/content/intent.h" + +using namespace testing::ext; +using namespace OHOS::AAFwk; + +using testBoolType = std::tuple; +class IntentParametersBoolTest : public testing::TestWithParam { +public: + IntentParametersBoolTest() : intent_(nullptr) + {} + ~IntentParametersBoolTest() + { + intent_ = nullptr; + } + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + Intent *intent_; +}; + +void IntentParametersBoolTest::SetUpTestCase(void) +{} + +void IntentParametersBoolTest::TearDownTestCase(void) +{} + +void IntentParametersBoolTest::SetUp(void) +{ + intent_ = new (std::nothrow) Intent(); +} + +void IntentParametersBoolTest::TearDown(void) +{ + delete intent_; + intent_ = nullptr; +} + +/* + * Feature: Intent + * Function: SetBoolParam/GetBoolParam + * SubFunction: NA + * FunctionPoints: SetBoolParam/GetBoolParam + * EnvConditions: NA + * CaseDescription: Verify when parameter change. + */ +HWTEST_P(IntentParametersBoolTest, AaFwk_Intent_Parameters_Bool, TestSize.Level1) +{ + std::string setKey = std::get<0>(GetParam()); + std::string getKey = std::get<1>(GetParam()); + bool setValue = std::get<2>(GetParam()); + bool defaultValue = std::get<3>(GetParam()); + bool result = std::get<4>(GetParam()); + intent_->SetBoolParam(setKey, setValue); + EXPECT_EQ(result, intent_->GetBoolParam(getKey, defaultValue)); +} + +INSTANTIATE_TEST_CASE_P(IntentParametersBoolTestCaseP, IntentParametersBoolTest, + testing::Values(testBoolType("", "aa", true, true, true), testBoolType("", "aa", true, false, false), + testBoolType("", "", true, true, true), testBoolType("", "", true, false, true), + testBoolType("123", "123", true, false, true), testBoolType("123", "aa", true, false, false), + testBoolType("-~*&%¥", "-~*&%¥", true, false, true), testBoolType("-~*&%¥", "aa", true, false, false), + testBoolType("中文", "中文", true, false, true), testBoolType("中文", "aa", true, false, false), + testBoolType("_中文ddPEJKJ#(&*~#^%", "_中文ddPEJKJ#(&*~#^%", true, false, true), + testBoolType("_中文ddPEJKJ#(&*~#^%", "123", true, false, false))); + +/* + * Feature: Intent + * Function: SetBoolParam/GetBoolParam + * SubFunction: NA + * FunctionPoints: SetBoolParam/GetBoolParam + * EnvConditions: NA + * CaseDescription: Verify when set twice and get twice + */ +HWTEST_F(IntentParametersBoolTest, AaFwk_Intent_Parameters_Bool_001, TestSize.Level1) +{ + std::string firstKey("_中文ddPEJKJ#(&*~#^%"); + std::string secondKey("key33"); + intent_->SetBoolParam(firstKey, true); + intent_->SetBoolParam(secondKey, true); + EXPECT_EQ(true, intent_->GetBoolParam(firstKey, false)); + EXPECT_EQ(true, intent_->GetBoolParam(secondKey, false)); +} + +/* + * Feature: Intent + * Function: SetBoolParam/GetBoolParam + * SubFunction: NA + * FunctionPoints: SetBoolParam/GetBoolParam + * EnvConditions: NA + * CaseDescription: Verify when set 20 times, and get once + */ +HWTEST_F(IntentParametersBoolTest, AaFwk_Intent_Parameters_Bool_002, TestSize.Level1) +{ + std::string keyStr("_中文ddPEJKJ#(&*~#^%"); + for (int i = 0; i < 20; i++) { + intent_->SetBoolParam(keyStr, true); + } + EXPECT_EQ(true, intent_->GetBoolParam(keyStr, false)); +} + +using testBoolArrayType = std::tuple, std::vector, std::vector>; +class IntentParametersBoolArrayTest : public testing::TestWithParam { +public: + IntentParametersBoolArrayTest() : intent_(nullptr) + {} + ~IntentParametersBoolArrayTest() + { + intent_ = nullptr; + } + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + Intent *intent_; +}; + +void IntentParametersBoolArrayTest::SetUpTestCase(void) +{} + +void IntentParametersBoolArrayTest::TearDownTestCase(void) +{} + +void IntentParametersBoolArrayTest::SetUp(void) +{ + intent_ = new (std::nothrow) Intent(); +} + +void IntentParametersBoolArrayTest::TearDown(void) +{ + delete intent_; + intent_ = nullptr; +} + +/* + * Feature: Intent + * Function: SetBoolArrayParam/GetBoolArrayParam + * SubFunction: NA + * FunctionPoints: SetBoolArrayParam/GetBoolArrayParam + * EnvConditions: NA + * CaseDescription: Verify when parameter change. + */ +HWTEST_P(IntentParametersBoolArrayTest, AaFwk_Intent_Parameters_BoolArray, TestSize.Level1) +{ + std::string setKey = std::get<0>(GetParam()); + std::string getKey = std::get<1>(GetParam()); + std::vector setValue = std::get<2>(GetParam()); + std::vector result = std::get<4>(GetParam()); + intent_->SetBoolArrayParam(setKey, setValue); + EXPECT_EQ(result, intent_->GetBoolArrayParam(getKey)); +} + +INSTANTIATE_TEST_CASE_P(IntentParametersBoolArrayTestCaseP, IntentParametersBoolArrayTest, + testing::Values(testBoolArrayType("", "aa", {true, false}, {}, {}), + testBoolArrayType("", "", {true, false}, {}, {true, false}), + testBoolArrayType("1*中_aR", "aa", {true, false}, {}, {}), + testBoolArrayType("1*中_aR", "1*中_aR", {false, true}, {}, {false, true}))); + +/* + * Feature: Intent + * Function: SetBoolArrayParam/GetBoolArrayParam + * SubFunction: NA + * FunctionPoints: SetBoolArrayParam/GetBoolArrayParam + * EnvConditions: NA + * CaseDescription: Verify when the value is bool array + */ +HWTEST_F(IntentParametersBoolArrayTest, AaFwk_Intent_Parameters_Bool_Array_001, TestSize.Level1) +{ + std::vector defaultValue; + std::string getKey("aa"); + EXPECT_EQ(defaultValue, intent_->GetBoolArrayParam(getKey)); +} + +/* + * Feature: Intent + * Function: SetBoolArrayParam/GetBoolArrayParam + * SubFunction: NA + * FunctionPoints: SetBoolArrayParam/GetBoolArrayParam + * EnvConditions: NA + * CaseDescription: Verify when the value is bool array + */ +HWTEST_F(IntentParametersBoolArrayTest, AaFwk_Intent_Parameters_Bool_Array_002, TestSize.Level1) +{ + std::string emptyStr(""); + std::vector firstValue({true, false}); + std::vector secondValue({true, true}); + std::vector firstDefaultValue({false, true}); + std::string keyStr("aa"); + intent_->SetBoolArrayParam(emptyStr, firstValue); + intent_->SetBoolArrayParam(emptyStr, firstValue); + intent_->SetBoolArrayParam(emptyStr, secondValue); + std::vector defaultValue; + EXPECT_EQ(defaultValue, intent_->GetBoolArrayParam(keyStr)); + intent_->SetBoolArrayParam(emptyStr, firstDefaultValue); + EXPECT_EQ(firstDefaultValue, intent_->GetBoolArrayParam(emptyStr)); +} + +/* + * Feature: Intent + * Function: SetBoolArrayParam/GetBoolArrayParam + * SubFunction: NA + * FunctionPoints: SetBoolArrayParam/GetBoolArrayParam + * EnvConditions: NA + * CaseDescription: Verify when the value is bool array + */ +HWTEST_F(IntentParametersBoolArrayTest, AaFwk_Intent_Parameters_Bool_Array_003, TestSize.Level1) +{ + std::string firstKey("%1uH3"); + std::vector firstValue({true, false}); + std::vector secondValue({true, true}); + std::string secondKey("aa"); + intent_->SetBoolArrayParam(firstKey, firstValue); + intent_->SetBoolArrayParam(firstKey, firstValue); + intent_->SetBoolArrayParam(firstKey, secondValue); + EXPECT_EQ(secondValue, intent_->GetBoolArrayParam(firstKey)); + intent_->SetBoolArrayParam(firstKey, firstValue); + std::vector defaultValue; + EXPECT_EQ(defaultValue, intent_->GetBoolArrayParam(secondKey)); +} + +using testByteType = std::tuple; +class IntentParametersByteTest : public testing::TestWithParam { +public: + IntentParametersByteTest() : intent_(nullptr) + {} + ~IntentParametersByteTest() + { + intent_ = nullptr; + } + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + Intent *intent_; +}; + +void IntentParametersByteTest::SetUpTestCase(void) +{} + +void IntentParametersByteTest::TearDownTestCase(void) +{} + +void IntentParametersByteTest::SetUp(void) +{ + intent_ = new (std::nothrow) Intent(); +} + +void IntentParametersByteTest::TearDown(void) +{ + delete intent_; + intent_ = nullptr; +} + +/* + * Feature: Intent + * Function: SetByteParam/GetByteParam + * SubFunction: NA + * FunctionPoints: SetByteParam/GetByteParam + * EnvConditions: NA + * CaseDescription: Verify when parameter change. + */ +HWTEST_P(IntentParametersByteTest, AaFwk_Intent_Parameters_Byte, TestSize.Level1) +{ + std::string setKey = std::get<0>(GetParam()); + std::string getKey = std::get<1>(GetParam()); + byte setValue = std::get<2>(GetParam()); + byte defaultValue = std::get<3>(GetParam()); + byte result = std::get<4>(GetParam()); + intent_->SetByteParam(setKey, setValue); + EXPECT_EQ(result, intent_->GetByteParam(getKey, defaultValue)); +} + +INSTANTIATE_TEST_CASE_P(IntentParametersByteTestCaseP, IntentParametersByteTest, + testing::Values(testByteType("", "aa", '#', 'U', 'U'), testByteType("", "", 'N', 'K', 'N'), + testByteType("1*中_aR", "aa", 'a', '%', '%'), testByteType("1*中_aR", "1*中_aR", 'a', 'z', 'a'))); + +/* + * Feature: Intent + * Function: SetByteParam/GetByteParam + * SubFunction: NA + * FunctionPoints: SetByteParam/GetByteParam + * EnvConditions: NA + * CaseDescription: Verify when the value is byte + */ +HWTEST_F(IntentParametersByteTest, AaFwk_Intent_Parameters_Byte_001, TestSize.Level1) +{ + byte defaultValue = '%'; + std::string getKey("aa"); + EXPECT_EQ(defaultValue, intent_->GetByteParam(getKey, defaultValue)); +} + +/* + * Feature: Intent + * Function: SetByteParam/GetByteParam + * SubFunction: NA + * FunctionPoints: SetByteParam/GetByteParam + * EnvConditions: NA + * CaseDescription: Verify when the value is byte + */ +HWTEST_F(IntentParametersByteTest, AaFwk_Intent_Parameters_Byte_002, TestSize.Level1) +{ + std::string emptyStr(""); + byte firstValue = 'a'; + byte secondValue = '1'; + byte thirdValue = '*'; + byte firstDefaultValue = '2'; + byte secondDefaultValue = '!'; + std::string keyStr("aa"); + intent_->SetByteParam(emptyStr, firstValue); + intent_->SetByteParam(emptyStr, firstValue); + intent_->SetByteParam(emptyStr, secondValue); + EXPECT_EQ(firstDefaultValue, intent_->GetByteParam(keyStr, firstDefaultValue)); + intent_->SetByteParam(emptyStr, thirdValue); + EXPECT_EQ(thirdValue, intent_->GetByteParam(emptyStr, secondDefaultValue)); +} + +/* + * Feature: Intent + * Function: SetByteParam/GetByteParam + * SubFunction: NA + * FunctionPoints: SetByteParam/GetByteParam + * EnvConditions: NA + * CaseDescription: Verify when the value is byte + */ +HWTEST_F(IntentParametersByteTest, AaFwk_Intent_Parameters_Byte_003, TestSize.Level1) +{ + std::string firstKey("%1uH3"); + byte firstValue = 'a'; + byte secondValue = '_'; + byte firstDefaultValue = 'W'; + byte secondDefaultValue = '%'; + std::string secondKey("aa"); + intent_->SetByteParam(firstKey, firstValue); + intent_->SetByteParam(firstKey, firstValue); + intent_->SetByteParam(firstKey, secondValue); + EXPECT_EQ(secondValue, intent_->GetByteParam(firstKey, firstDefaultValue)); + intent_->SetByteParam(firstKey, firstValue); + EXPECT_EQ(secondDefaultValue, intent_->GetByteParam(secondKey, secondDefaultValue)); +} + +using testByteArrayType = std::tuple, std::vector, std::vector>; +class IntentParametersByteArrayTest : public testing::TestWithParam { +public: + IntentParametersByteArrayTest() : intent_(nullptr) + {} + ~IntentParametersByteArrayTest() + { + intent_ = nullptr; + } + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + Intent *intent_; +}; + +void IntentParametersByteArrayTest::SetUpTestCase(void) +{} + +void IntentParametersByteArrayTest::TearDownTestCase(void) +{} + +void IntentParametersByteArrayTest::SetUp(void) +{ + intent_ = new (std::nothrow) Intent(); +} + +void IntentParametersByteArrayTest::TearDown(void) +{ + delete intent_; + intent_ = nullptr; +} + +/* + * Feature: Intent + * Function: SetByteArrayParam/GetByteArrayParam + * SubFunction: NA + * FunctionPoints: SetByteArrayParam/GetByteArrayParam + * EnvConditions: NA + * CaseDescription: Verify when parameter change. + */ +HWTEST_P(IntentParametersByteArrayTest, AaFwk_Intent_Parameters_ByteArray, TestSize.Level1) +{ + std::string setKey = std::get<0>(GetParam()); + std::string getKey = std::get<1>(GetParam()); + std::vector setValue = std::get<2>(GetParam()); + std::vector result = std::get<4>(GetParam()); + intent_->SetByteArrayParam(setKey, setValue); + EXPECT_EQ(result, intent_->GetByteArrayParam(getKey)); +} + +INSTANTIATE_TEST_CASE_P(IntentParametersByteArrayTestCaseP, IntentParametersByteArrayTest, + testing::Values(testByteArrayType("", "aa", {'*', 'D'}, {}, {}), + testByteArrayType("", "", {'%', ')'}, {}, {'%', ')'}), testByteArrayType("1*中_aR", "aa", {'R', '.'}, {}, {}), + testByteArrayType("1*中_aR", "1*中_aR", {'R', 'b'}, {}, {'R', 'b'}))); + +/* + * Feature: Intent + * Function: GetByteArrayParam + * SubFunction: NA + * FunctionPoints: GetByteArrayParam + * EnvConditions: NA + * CaseDescription: Verify when the value is byte array + */ +HWTEST_F(IntentParametersByteArrayTest, AaFwk_Intent_Parameters_Byte_Array_001, TestSize.Level1) +{ + std::vector defaultValue; + std::string getKey("aa"); + EXPECT_EQ(defaultValue, intent_->GetByteArrayParam(getKey)); +} + +/* + * Feature: Intent + * Function: SetByteArrayParam/GetByteArrayParam + * SubFunction: NA + * FunctionPoints: SetByteArrayParam/GetByteArrayParam + * EnvConditions: NA + * CaseDescription: Verify when the value is byte array + */ +HWTEST_F(IntentParametersByteArrayTest, AaFwk_Intent_Parameters_Byte_Array_002, TestSize.Level1) +{ + std::string emptyStr(""); + std::vector firstValue({'a', '2'}); + std::vector secondValue({'1', 'd'}); + std::vector thirdValue({'t', '3'}); + std::string keyStr("aa"); + intent_->SetByteArrayParam(emptyStr, firstValue); + intent_->SetByteArrayParam(emptyStr, firstValue); + intent_->SetByteArrayParam(emptyStr, secondValue); + std::vector defaultValue; + EXPECT_EQ(defaultValue, intent_->GetByteArrayParam(keyStr)); + intent_->SetByteArrayParam(emptyStr, thirdValue); + EXPECT_EQ(thirdValue, intent_->GetByteArrayParam(emptyStr)); +} + +/* + * Feature: Intent + * Function: SetByteArrayParam/GetByteArrayParam + * SubFunction: NA + * FunctionPoints: SetByteArrayParam/GetByteArrayParam + * EnvConditions: NA + * CaseDescription: Verify when the value is byte array + */ +HWTEST_F(IntentParametersByteArrayTest, AaFwk_Intent_Parameters_Byte_Array_003, TestSize.Level1) +{ + std::string firstKey("%1uH3"); + std::vector firstValue({'a', '2'}); + std::vector secondValue({'w', '$'}); + std::vector defaultValue; + std::string secondKey("aa"); + intent_->SetByteArrayParam(firstKey, firstValue); + intent_->SetByteArrayParam(firstKey, firstValue); + intent_->SetByteArrayParam(firstKey, secondValue); + EXPECT_EQ(secondValue, intent_->GetByteArrayParam(firstKey)); + intent_->SetByteArrayParam(firstKey, firstValue); + EXPECT_EQ(defaultValue, intent_->GetByteArrayParam(secondKey)); +} + +using testCharType = std::tuple; +class IntentParametersCharTest : public testing::TestWithParam { +public: + IntentParametersCharTest() : intent_(nullptr) + {} + ~IntentParametersCharTest() + { + intent_ = nullptr; + } + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + Intent *intent_; +}; + +void IntentParametersCharTest::SetUpTestCase(void) +{} + +void IntentParametersCharTest::TearDownTestCase(void) +{} + +void IntentParametersCharTest::SetUp(void) +{ + intent_ = new (std::nothrow) Intent(); +} + +void IntentParametersCharTest::TearDown(void) +{ + delete intent_; + intent_ = nullptr; +} + +/* + * Feature: Intent + * Function: SetCharParam/GetCharParam + * SubFunction: NA + * FunctionPoints: SetCharParam/GetCharParam + * EnvConditions: NA + * CaseDescription: Verify when parameter change. + */ +HWTEST_P(IntentParametersCharTest, AaFwk_Intent_Parameters_Char, TestSize.Level1) +{ + std::string setKey = std::get<0>(GetParam()); + std::string getKey = std::get<1>(GetParam()); + zchar setValue = std::get<2>(GetParam()); + zchar defaultValue = std::get<3>(GetParam()); + zchar result = std::get<4>(GetParam()); + intent_->SetCharParam(setKey, setValue); + EXPECT_EQ(result, intent_->GetCharParam(getKey, defaultValue)); +} + +INSTANTIATE_TEST_CASE_P(IntentParametersCharTestCaseP, IntentParametersCharTest, + testing::Values(testCharType("", "aa", U'#', U'中', U'中'), testCharType("", "", U'中', U'K', U'中'), + testCharType("1*中_aR", "aa", U'a', U'中', U'中'), testCharType("1*中_aR", "1*中_aR", U'中', U'z', U'中'))); + +/* + * Feature: Intent + * Function: SetCharParam/GetCharParam + * SubFunction: NA + * FunctionPoints: SetCharParam/GetCharParam + * EnvConditions: NA + * CaseDescription: Verify when the value is char + */ +HWTEST_F(IntentParametersCharTest, AaFwk_Intent_Parameters_Char_001, TestSize.Level1) +{ + zchar defaultValue = U'文'; + std::string getKey("aa"); + EXPECT_EQ(defaultValue, intent_->GetCharParam(getKey, defaultValue)); +} + +/* + * Feature: Intent + * Function: SetCharParam/GetCharParam + * SubFunction: NA + * FunctionPoints: SetCharParam/GetCharParam + * EnvConditions: NA + * CaseDescription: Verify when the value is char + */ +HWTEST_F(IntentParametersCharTest, AaFwk_Intent_Parameters_Char_002, TestSize.Level1) +{ + std::string emptyStr(""); + zchar firstValue = U'中'; + zchar secondValue = U'文'; + zchar thirdValue = U'字'; + zchar firstDefaultValue = U'符'; + zchar secondDefaultValue = U'集'; + std::string keyStr("aa"); + intent_->SetCharParam(emptyStr, firstValue); + intent_->SetCharParam(emptyStr, firstValue); + intent_->SetCharParam(emptyStr, secondValue); + EXPECT_EQ(firstDefaultValue, intent_->GetCharParam(keyStr, firstDefaultValue)); + intent_->SetCharParam(emptyStr, thirdValue); + EXPECT_EQ(thirdValue, intent_->GetCharParam(emptyStr, secondDefaultValue)); +} + +/* + * Feature: Intent + * Function: SetCharParam/GetCharParam + * SubFunction: NA + * FunctionPoints: SetCharParam/GetCharParam + * EnvConditions: NA + * CaseDescription: Verify when the value is char + */ +HWTEST_F(IntentParametersCharTest, AaFwk_Intent_Parameters_Char_003, TestSize.Level1) +{ + std::string firstKey("%1uH3"); + zchar firstValue = U'中'; + zchar secondValue = U'文'; + zchar firstDefaultValue = U'字'; + zchar secondDefaultValue = U'符'; + std::string secondKey("aa"); + intent_->SetCharParam(firstKey, firstValue); + intent_->SetCharParam(firstKey, firstValue); + intent_->SetCharParam(firstKey, secondValue); + EXPECT_EQ(secondValue, intent_->GetCharParam(firstKey, firstDefaultValue)); + intent_->SetCharParam(firstKey, firstValue); + EXPECT_EQ(secondDefaultValue, intent_->GetCharParam(secondKey, secondDefaultValue)); +} + +using testCharArrayType = + std::tuple, std::vector, std::vector>; +class IntentParametersCharArrayTest : public testing::TestWithParam { +public: + IntentParametersCharArrayTest() : intent_(nullptr) + {} + ~IntentParametersCharArrayTest() + { + intent_ = nullptr; + } + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + Intent *intent_; +}; + +void IntentParametersCharArrayTest::SetUpTestCase(void) +{} + +void IntentParametersCharArrayTest::TearDownTestCase(void) +{} + +void IntentParametersCharArrayTest::SetUp(void) +{ + intent_ = new (std::nothrow) Intent(); +} + +void IntentParametersCharArrayTest::TearDown(void) +{ + delete intent_; + intent_ = nullptr; +} + +/* + * Feature: Intent + * Function: SetCharArrayParam/GetCharArrayParam + * SubFunction: NA + * FunctionPoints: SetCharArrayParam/GetCharArrayParam + * EnvConditions: NA + * CaseDescription: Verify when parameter change. + */ +HWTEST_P(IntentParametersCharArrayTest, AaFwk_Intent_Parameters_CharArray, TestSize.Level1) +{ + std::string setKey = std::get<0>(GetParam()); + std::string getKey = std::get<1>(GetParam()); + std::vector setValue = std::get<2>(GetParam()); + std::vector result = std::get<4>(GetParam()); + intent_->SetCharArrayParam(setKey, setValue); + EXPECT_EQ(result, intent_->GetCharArrayParam(getKey)); +} + +INSTANTIATE_TEST_CASE_P(IntentParametersCharArrayTestCaseP, IntentParametersCharArrayTest, + testing::Values(testCharArrayType("", "aa", {U'中', U'文'}, {}, {}), + testCharArrayType("", "", {U'中', U'文'}, {}, {U'中', U'文'}), + testCharArrayType("1*中_aR", "aa", {U'中', U'文'}, {}, {}), + testCharArrayType("1*中_aR", "1*中_aR", {U'中', U'文'}, {}, {U'中', U'文'}))); + +/* + * Feature: Intent + * Function: GetCharArrayParam + * SubFunction: NA + * FunctionPoints: GetCharArrayParam + * EnvConditions: NA + * CaseDescription: Verify when the value is char array + */ +HWTEST_F(IntentParametersCharArrayTest, AaFwk_Intent_Parameters_Char_Array_001, TestSize.Level1) +{ + std::vector defaultValue; + std::string getKey("aa"); + EXPECT_EQ(defaultValue, intent_->GetCharArrayParam(getKey)); +} + +/* + * Feature: Intent + * Function: SetCharArrayParam/GetCharArrayParam + * SubFunction: NA + * FunctionPoints: SetCharArrayParam/GetCharArrayParam + * EnvConditions: NA + * CaseDescription: Verify when the value is char array + */ +HWTEST_F(IntentParametersCharArrayTest, AaFwk_Intent_Parameters_Char_Array_002, TestSize.Level1) +{ + std::string emptyStr(""); + std::vector firstValue({U'中', U'文'}); + std::vector secondValue({U'字', U'符'}); + std::vector thirdValue({U'集', U'英'}); + std::string keyStr("aa"); + intent_->SetCharArrayParam(emptyStr, firstValue); + intent_->SetCharArrayParam(emptyStr, firstValue); + intent_->SetCharArrayParam(emptyStr, secondValue); + std::vector defaultValue; + EXPECT_EQ(defaultValue, intent_->GetCharArrayParam(keyStr)); + intent_->SetCharArrayParam(emptyStr, thirdValue); + EXPECT_EQ(thirdValue, intent_->GetCharArrayParam(emptyStr)); +} + +/* + * Feature: Intent + * Function: SetCharArrayParam/GetCharArrayParam + * SubFunction: NA + * FunctionPoints: SetCharArrayParam/GetCharArrayParam + * EnvConditions: NA + * CaseDescription: Verify when the value is char array + */ +HWTEST_F(IntentParametersCharArrayTest, AaFwk_Intent_Parameters_Char_Array_003, TestSize.Level1) +{ + std::string firstKey("%1uH3"); + std::vector firstValue({U'中', U'文'}); + std::vector secondValue({U'字', U'符'}); + std::vector defaultValue; + std::string secondKey("aa"); + intent_->SetCharArrayParam(firstKey, firstValue); + intent_->SetCharArrayParam(firstKey, firstValue); + intent_->SetCharArrayParam(firstKey, secondValue); + EXPECT_EQ(secondValue, intent_->GetCharArrayParam(firstKey)); + intent_->SetCharArrayParam(firstKey, firstValue); + EXPECT_EQ(defaultValue, intent_->GetCharArrayParam(secondKey)); +} + +using testShortType = std::tuple; +class IntentParametersShortTest : public testing::TestWithParam { +public: + IntentParametersShortTest() : intent_(nullptr) + {} + ~IntentParametersShortTest() + { + intent_ = nullptr; + } + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + Intent *intent_; +}; + +void IntentParametersShortTest::SetUpTestCase(void) +{} + +void IntentParametersShortTest::TearDownTestCase(void) +{} + +void IntentParametersShortTest::SetUp(void) +{ + intent_ = new (std::nothrow) Intent(); +} + +void IntentParametersShortTest::TearDown(void) +{ + delete intent_; + intent_ = nullptr; +} + +/* + * Feature: Intent + * Function: SetShortParam/GetShortParam + * SubFunction: NA + * FunctionPoints: SetShortParam/GetShortParam + * EnvConditions: NA + * CaseDescription: Verify when parameter change. + */ +HWTEST_P(IntentParametersShortTest, AaFwk_Intent_Parameters_Short, TestSize.Level1) +{ + std::string setKey = std::get<0>(GetParam()); + std::string getKey = std::get<1>(GetParam()); + short setValue = std::get<2>(GetParam()); + short defaultValue = std::get<3>(GetParam()); + short result = std::get<4>(GetParam()); + intent_->SetShortParam(setKey, setValue); + EXPECT_EQ(result, intent_->GetShortParam(getKey, defaultValue)); +} + +INSTANTIATE_TEST_CASE_P(IntentParametersShortTestCaseP, IntentParametersShortTest, + testing::Values(testShortType("", "aa", -1, 100, 100), testShortType("", "", -9, -41, -9), + testShortType("1*中_aR", "aa", 50, 5, 5), testShortType("1*中_aR", "1*中_aR", -5000, 5000, -5000))); + +/* + * Feature: Intent + * Function: GetShortParam + * SubFunction: NA + * FunctionPoints: GetShortParam + * EnvConditions: NA + * CaseDescription: Verify when the value is short + */ +HWTEST_F(IntentParametersShortTest, AaFwk_Intent_Parameters_Short_001, TestSize.Level1) +{ + short defaultValue = 200; + std::string getKey("aa"); + EXPECT_EQ(defaultValue, intent_->GetShortParam(getKey, defaultValue)); +} + +/* + * Feature: Intent + * Function: SetShortParam/GetShortParam + * SubFunction: NA + * FunctionPoints: SetShortParam/GetShortParam + * EnvConditions: NA + * CaseDescription: Verify when the value is short + */ +HWTEST_F(IntentParametersShortTest, AaFwk_Intent_Parameters_Short_002, TestSize.Level1) +{ + std::string emptyStr(""); + short firstValue = 1; + short secondValue = 2; + short thirdValue = 4; + short firstDefaultValue = 3; + short secondDefaultValue = 5; + std::string keyStr("aa"); + intent_->SetShortParam(emptyStr, firstValue); + intent_->SetShortParam(emptyStr, firstValue); + intent_->SetShortParam(emptyStr, secondValue); + EXPECT_EQ(firstDefaultValue, intent_->GetShortParam(keyStr, firstDefaultValue)); + intent_->SetShortParam(emptyStr, thirdValue); + EXPECT_EQ(thirdValue, intent_->GetShortParam(emptyStr, secondDefaultValue)); +} + +/* + * Feature: Intent + * Function: SetShortParam/GetShortParam + * SubFunction: NA + * FunctionPoints: SetShortParam/GetShortParam + * EnvConditions: NA + * CaseDescription: Verify when the value is short + */ +HWTEST_F(IntentParametersShortTest, AaFwk_Intent_Parameters_Short_003, TestSize.Level1) +{ + std::string firstKey("%1uH3"); + short firstValue = -1; + short secondValue = 0; + short thirdValue = 4; + short firstDefaultValue = 9; + short secondDefaultValue = -10; + std::string secondKey("aa"); + intent_->SetShortParam(firstKey, firstValue); + intent_->SetShortParam(firstKey, firstValue); + intent_->SetShortParam(firstKey, secondValue); + EXPECT_EQ(secondValue, intent_->GetShortParam(firstKey, firstDefaultValue)); + intent_->SetShortParam(firstKey, thirdValue); + EXPECT_EQ(secondDefaultValue, intent_->GetShortParam(secondKey, secondDefaultValue)); +} + +using testShortArrayType = + std::tuple, std::vector, std::vector>; +class IntentParametersShortArrayTest : public testing::TestWithParam { +public: + IntentParametersShortArrayTest() : intent_(nullptr) + {} + ~IntentParametersShortArrayTest() + { + intent_ = nullptr; + } + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + Intent *intent_; +}; + +void IntentParametersShortArrayTest::SetUpTestCase(void) +{} + +void IntentParametersShortArrayTest::TearDownTestCase(void) +{} + +void IntentParametersShortArrayTest::SetUp(void) +{ + intent_ = new (std::nothrow) Intent(); +} + +void IntentParametersShortArrayTest::TearDown(void) +{ + delete intent_; + intent_ = nullptr; +} + +/* + * Feature: Intent + * Function: SetShortArrayParam/GetShortArrayParam + * SubFunction: NA + * FunctionPoints: SetShortArrayParam/GetShortArrayParam + * EnvConditions: NA + * CaseDescription: Verify when parameter change. + */ +HWTEST_P(IntentParametersShortArrayTest, AaFwk_Intent_Parameters_ShortArray, TestSize.Level1) +{ + std::string setKey = std::get<0>(GetParam()); + std::string getKey = std::get<1>(GetParam()); + std::vector setValue = std::get<2>(GetParam()); + std::vector defaultValue = std::get<3>(GetParam()); + std::vector result = std::get<4>(GetParam()); + intent_->SetShortArrayParam(setKey, setValue); + EXPECT_EQ(result, intent_->GetShortArrayParam(getKey)); +} + +INSTANTIATE_TEST_CASE_P(IntentParametersShortArrayTestCaseP, IntentParametersShortArrayTest, + testing::Values(testShortArrayType("", "aa", {-1, 3, 25, -9}, {}, {}), + testShortArrayType("", "", {-41, 0, 0, 9}, {}, {-41, 0, 0, 9}), + testShortArrayType("1*中_aR", "aa", {50, 2, -9}, {}, {}), + testShortArrayType("1*中_aR", "1*中_aR", {-5000}, {}, {-5000}))); + +/* + * Feature: Intent + * Function: GetShortArrayParam + * SubFunction: NA + * FunctionPoints: GetShortArrayParam + * EnvConditions: NA + * CaseDescription: Verify when the value is short array + */ +HWTEST_F(IntentParametersShortArrayTest, AaFwk_Intent_Parameters_Short_Array_001, TestSize.Level1) +{ + std::vector defaultValue; + std::string getKey("aa"); + EXPECT_EQ(defaultValue, intent_->GetShortArrayParam(getKey)); +} + +/* + * Feature: Intent + * Function: SetShortArrayParam/GetShortArrayParam + * SubFunction: NA + * FunctionPoints: SetShortArrayParam/GetShortArrayParam + * EnvConditions: NA + * CaseDescription: Verify when the value is short array + */ +HWTEST_F(IntentParametersShortArrayTest, AaFwk_Intent_Parameters_Short_Array_002, TestSize.Level1) +{ + std::string emptyStr(""); + std::vector firstValue({1, 4, -9}); + std::vector secondValue({1, 8, -9}); + std::vector thirdValue({1, 4, 9}); + std::string keyStr("aa"); + intent_->SetShortArrayParam(emptyStr, firstValue); + intent_->SetShortArrayParam(emptyStr, firstValue); + intent_->SetShortArrayParam(emptyStr, secondValue); + std::vector defaultValue; + EXPECT_EQ(defaultValue, intent_->GetShortArrayParam(keyStr)); + intent_->SetShortArrayParam(emptyStr, thirdValue); + EXPECT_EQ(thirdValue, intent_->GetShortArrayParam(emptyStr)); +} + +/* + * Feature: Intent + * Function: SetShortArrayParam/GetShortArrayParam + * SubFunction: NA + * FunctionPoints: SetShortArrayParam/GetShortArrayParam + * EnvConditions: NA + * CaseDescription: Verify when the value is short array + */ +HWTEST_F(IntentParametersShortArrayTest, AaFwk_Intent_Parameters_Short_Array_003, TestSize.Level1) +{ + std::string firstKey("%1uH3"); + std::vector firstValue({-1, -2}); + std::vector secondValue({-1, -2, -1, -2, 0}); + std::vector thirdValue({-1, -2, 100}); + std::string secondKey("aa"); + intent_->SetShortArrayParam(firstKey, firstValue); + intent_->SetShortArrayParam(firstKey, firstValue); + intent_->SetShortArrayParam(firstKey, secondValue); + EXPECT_EQ(secondValue, intent_->GetShortArrayParam(firstKey)); + intent_->SetShortArrayParam(firstKey, thirdValue); + std::vector defaultValue; + EXPECT_EQ(defaultValue, intent_->GetShortArrayParam(secondKey)); +} + +using testIntType = std::tuple; +class IntentParametersIntTest : public testing::TestWithParam { +public: + IntentParametersIntTest() : intent_(nullptr) + {} + ~IntentParametersIntTest() + { + intent_ = nullptr; + } + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + Intent *intent_; +}; + +void IntentParametersIntTest::SetUpTestCase(void) +{} + +void IntentParametersIntTest::TearDownTestCase(void) +{} + +void IntentParametersIntTest::SetUp(void) +{ + intent_ = new (std::nothrow) Intent(); +} + +void IntentParametersIntTest::TearDown(void) +{ + delete intent_; + intent_ = nullptr; +} + +/* + * Feature: Intent + * Function: SetIntParam/GetIntParam + * SubFunction: NA + * FunctionPoints: SetIntParam/GetIntParam + * EnvConditions: NA + * CaseDescription: Verify when parameter change. + */ +HWTEST_P(IntentParametersIntTest, AaFwk_Intent_Parameters_Int, TestSize.Level1) +{ + std::string setKey = std::get<0>(GetParam()); + std::string getKey = std::get<1>(GetParam()); + int setValue = std::get<2>(GetParam()); + int defaultValue = std::get<3>(GetParam()); + int result = std::get<4>(GetParam()); + intent_->SetIntParam(setKey, setValue); + EXPECT_EQ(result, intent_->GetIntParam(getKey, defaultValue)); +} + +INSTANTIATE_TEST_CASE_P(IntentParametersIntTestCaseP, IntentParametersIntTest, + testing::Values(testIntType("", "aa", -1, 100, 100), testIntType("", "", -9, -41, -9), + testIntType("1*中_aR", "aa", 50, 5, 5), testIntType("1*中_aR", "1*中_aR", -5000, 5000, -5000))); + +/* + * Feature: Intent + * Function: GetIntParam + * SubFunction: NA + * FunctionPoints: GetIntParam + * EnvConditions: NA + * CaseDescription: Verify when the value is integer + */ +HWTEST_F(IntentParametersIntTest, AaFwk_Intent_Parameters_Int_001, TestSize.Level1) +{ + int defaultValue = 200; + std::string getKey("aa"); + EXPECT_EQ(defaultValue, intent_->GetIntParam(getKey, defaultValue)); +} + +/* + * Feature: Intent + * Function: SetIntParam/GetIntParam + * SubFunction: NA + * FunctionPoints: SetIntParam/GetIntParam + * EnvConditions: NA + * CaseDescription: Verify when the value is integer + */ +HWTEST_F(IntentParametersIntTest, AaFwk_Intent_Parameters_Int_002, TestSize.Level1) +{ + std::string emptyStr(""); + int firstValue = 1; + int secondValue = 2; + int thirdValue = 4; + int firstDefaultValue = 3; + int secondDefaultValue = 5; + std::string keyStr("aa"); + intent_->SetIntParam(emptyStr, firstValue); + intent_->SetIntParam(emptyStr, firstValue); + intent_->SetIntParam(emptyStr, secondValue); + EXPECT_EQ(firstDefaultValue, intent_->GetIntParam(keyStr, firstDefaultValue)); + intent_->SetIntParam(emptyStr, thirdValue); + EXPECT_EQ(thirdValue, intent_->GetIntParam(emptyStr, secondDefaultValue)); +} + +/* + * Feature: Intent + * Function: SetIntParam/GetIntParam + * SubFunction: NA + * FunctionPoints: SetIntParam/GetIntParam + * EnvConditions: NA + * CaseDescription: Verify when the value is integer + */ +HWTEST_F(IntentParametersIntTest, AaFwk_Intent_Parameters_Int_003, TestSize.Level1) +{ + std::string firstKey("%1uH3"); + int firstValue = -1; + int secondValue = 0; + int thirdValue = 4; + int firstDefaultValue = 9; + int secondDefaultValue = -10; + std::string secondKey("aa"); + intent_->SetIntParam(firstKey, firstValue); + intent_->SetIntParam(firstKey, firstValue); + intent_->SetIntParam(firstKey, secondValue); + EXPECT_EQ(secondValue, intent_->GetIntParam(firstKey, firstDefaultValue)); + intent_->SetIntParam(firstKey, thirdValue); + EXPECT_EQ(secondDefaultValue, intent_->GetIntParam(secondKey, secondDefaultValue)); +} + +using testIntArrayType = std::tuple, std::vector, std::vector>; +class IntentParametersIntArrayTest : public testing::TestWithParam { +public: + IntentParametersIntArrayTest() : intent_(nullptr) + {} + ~IntentParametersIntArrayTest() + { + intent_ = nullptr; + } + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + Intent *intent_; +}; + +void IntentParametersIntArrayTest::SetUpTestCase(void) +{} + +void IntentParametersIntArrayTest::TearDownTestCase(void) +{} + +void IntentParametersIntArrayTest::SetUp(void) +{ + intent_ = new (std::nothrow) Intent(); +} + +void IntentParametersIntArrayTest::TearDown(void) +{ + delete intent_; + intent_ = nullptr; +} + +/* + * Feature: Intent + * Function: SetIntArrayParam/GetIntArrayParam + * SubFunction: NA + * FunctionPoints: SetIntArrayParam/GetIntArrayParam + * EnvConditions: NA + * CaseDescription: Verify when parameter change. + */ +HWTEST_P(IntentParametersIntArrayTest, AaFwk_Intent_Parameters_IntArray, TestSize.Level1) +{ + std::string setKey = std::get<0>(GetParam()); + std::string getKey = std::get<1>(GetParam()); + std::vector setValue = std::get<2>(GetParam()); + std::vector defaultValue = std::get<3>(GetParam()); + std::vector result = std::get<4>(GetParam()); + intent_->SetIntArrayParam(setKey, setValue); + EXPECT_EQ(result, intent_->GetIntArrayParam(getKey)); +} + +INSTANTIATE_TEST_CASE_P(IntentParametersIntArrayTestCaseP, IntentParametersIntArrayTest, + testing::Values(testIntArrayType("", "aa", {-1, 3, 25, -9}, {}, {}), + testIntArrayType("", "", {-41, 0, 0, 9}, {}, {-41, 0, 0, 9}), + testIntArrayType("1*中_aR", "aa", {50, 2, -9}, {}, {}), + testIntArrayType("1*中_aR", "1*中_aR", {-5000}, {}, {-5000}))); + +/* + * Feature: Intent + * Function: GetIntArrayParam + * SubFunction: NA + * FunctionPoints: GetIntArrayParam + * EnvConditions: NA + * CaseDescription: Verify when the value is integer array + */ +HWTEST_F(IntentParametersIntArrayTest, AaFwk_Intent_Parameters_Int_Array_001, TestSize.Level1) +{ + std::vector defaultValue; + std::string getKey("aa"); + EXPECT_EQ(defaultValue, intent_->GetIntArrayParam(getKey)); +} + +/* + * Feature: Intent + * Function: SetIntArrayParam/GetIntArrayParam + * SubFunction: NA + * FunctionPoints: SetIntArrayParam/GetIntArrayParam + * EnvConditions: NA + * CaseDescription: Verify when the value is integer array + */ +HWTEST_F(IntentParametersIntArrayTest, AaFwk_Intent_Parameters_Int_Array_002, TestSize.Level1) +{ + std::string emptyStr(""); + std::vector firstValue({1, 4, -9}); + std::vector secondValue({1, 8, -9}); + std::vector thirdValue({1, 4, 9}); + std::string keyStr("aa"); + intent_->SetIntArrayParam(emptyStr, firstValue); + intent_->SetIntArrayParam(emptyStr, firstValue); + intent_->SetIntArrayParam(emptyStr, secondValue); + std::vector defaultValue; + EXPECT_EQ(defaultValue, intent_->GetIntArrayParam(keyStr)); + intent_->SetIntArrayParam(emptyStr, thirdValue); + EXPECT_EQ(thirdValue, intent_->GetIntArrayParam(emptyStr)); +} + +/* + * Feature: Intent + * Function: SetIntArrayParam/GetIntArrayParam + * SubFunction: NA + * FunctionPoints: SetIntArrayParam/GetIntArrayParam + * EnvConditions: NA + * CaseDescription: Verify when the value is integer array + */ +HWTEST_F(IntentParametersIntArrayTest, AaFwk_Intent_Parameters_Int_Array_003, TestSize.Level1) +{ + std::string firstKey("%1uH3"); + std::vector firstValue({-1, -2}); + std::vector secondValue({-1, -2, -1, -2, 0}); + std::vector thirdValue({-1, -2, 100}); + std::string secondKey("aa"); + intent_->SetIntArrayParam(firstKey, firstValue); + intent_->SetIntArrayParam(firstKey, firstValue); + intent_->SetIntArrayParam(firstKey, secondValue); + EXPECT_EQ(secondValue, intent_->GetIntArrayParam(firstKey)); + intent_->SetIntArrayParam(firstKey, thirdValue); + std::vector defaultValue; + EXPECT_EQ(defaultValue, intent_->GetIntArrayParam(secondKey)); +} + +using testLongType = std::tuple; +class IntentParametersLongTest : public testing::TestWithParam { +public: + IntentParametersLongTest() : intent_(nullptr) + {} + ~IntentParametersLongTest() + { + intent_ = nullptr; + } + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + Intent *intent_; +}; + +void IntentParametersLongTest::SetUpTestCase(void) +{} + +void IntentParametersLongTest::TearDownTestCase(void) +{} + +void IntentParametersLongTest::SetUp(void) +{ + intent_ = new (std::nothrow) Intent(); +} + +void IntentParametersLongTest::TearDown(void) +{ + delete intent_; + intent_ = nullptr; +} + +/* + * Feature: Intent + * Function: SetLongParam/GetLongParam + * SubFunction: NA + * FunctionPoints: SetLongParam/GetLongParam + * EnvConditions: NA + * CaseDescription: Verify when parameter change. + */ +HWTEST_P(IntentParametersLongTest, AaFwk_Intent_Parameters_Long, TestSize.Level1) +{ + std::string setKey = std::get<0>(GetParam()); + std::string getKey = std::get<1>(GetParam()); + long setValue = std::get<2>(GetParam()); + long defaultValue = std::get<3>(GetParam()); + long result = std::get<4>(GetParam()); + intent_->SetLongParam(setKey, setValue); + EXPECT_EQ(result, intent_->GetLongParam(getKey, defaultValue)); +} + +INSTANTIATE_TEST_CASE_P(IntentParametersLongTestCaseP, IntentParametersLongTest, + testing::Values(testLongType("", "aa", -1, 100, 100), testLongType("", "", -9, -41, -9), + testLongType("1*中_aR", "aa", 50, 5, 5), testLongType("1*中_aR", "1*中_aR", -5000, 5000, -5000))); + +/* + * Feature: Intent + * Function: SetLongParam & GetLongParam + * SubFunction: NA + * FunctionPoints: SetLongParam & GetLongParam + * EnvConditions: NA + * CaseDescription: get param when IntentParam is empty + */ +HWTEST_F(IntentParametersLongTest, AaFwk_Intent_Parameters_Long_001, TestSize.Level1) +{ + long defaultValue = 100; + std::string key = "aa"; + EXPECT_EQ(defaultValue, intent_->GetLongParam(key, defaultValue)); +} + +/* + * Feature: Intent + * Function: SetLongParam & GetLongParam + * SubFunction: NA + * FunctionPoints: SetLongParam & GetLongParam + * EnvConditions: NA + * CaseDescription: set empty-string key repeatedly, but get param of another nonexistent key + */ +HWTEST_F(IntentParametersLongTest, AaFwk_Intent_Parameters_Long_002, TestSize.Level1) +{ + std::string setKey1 = ""; + std::string setKey2 = "aa"; + long setValue1 = 1; + long setValue2 = 5; + intent_->SetLongParam(setKey1, setValue1); + intent_->SetLongParam(setKey1, setValue1); + setValue1 = 2; + intent_->SetLongParam(setKey1, setValue1); + setValue1 = 3; + EXPECT_EQ(setValue1, intent_->GetLongParam(setKey2, setValue1)); + setValue1 = 4; + intent_->SetLongParam(setKey1, setValue1); + EXPECT_EQ(setValue1, intent_->GetLongParam(setKey1, setValue2)); +} + +/* + * Feature: Intent + * Function: SetLongParam & GetLongParam + * SubFunction: NA + * FunctionPoints: SetLongParam & GetLongParam + * EnvConditions: NA + * CaseDescription: set empty-string key repeatedly, then get param of the key + */ +HWTEST_F(IntentParametersLongTest, AaFwk_Intent_Parameters_Long_003, TestSize.Level1) +{ + std::string setKey1 = "%1uH3"; + std::string setKey2 = "aa"; + long setValue1 = -1; + long setValue2 = 9; + intent_->SetLongParam(setKey1, setValue1); + intent_->SetLongParam(setKey1, setValue1); + setValue1 = 0; + intent_->SetLongParam(setKey1, setValue1); + EXPECT_EQ(setValue1, intent_->GetLongParam(setKey1, setValue2)); + setValue1 = 4; + intent_->SetLongParam(setKey1, setValue1); + setValue1 = -10; + EXPECT_EQ(setValue1, intent_->GetLongParam(setKey2, setValue1)); +} + +using testLongArrayType = std::tuple, std::vector, std::vector>; +class IntentParametersLongArrayTest : public testing::TestWithParam { +public: + IntentParametersLongArrayTest() : intent_(nullptr) + {} + ~IntentParametersLongArrayTest() + { + intent_ = nullptr; + } + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + Intent *intent_; +}; + +void IntentParametersLongArrayTest::SetUpTestCase(void) +{} + +void IntentParametersLongArrayTest::TearDownTestCase(void) +{} + +void IntentParametersLongArrayTest::SetUp(void) +{ + intent_ = new (std::nothrow) Intent(); +} + +void IntentParametersLongArrayTest::TearDown(void) +{ + delete intent_; + intent_ = nullptr; +} + +/* + * Feature: Intent + * Function: SetLongArrayParam/GetLongArrayParam + * SubFunction: NA + * FunctionPoints: SetLongArrayParam/GetLongArrayParam + * EnvConditions: NA + * CaseDescription: Verify when parameter change. + */ +HWTEST_P(IntentParametersLongArrayTest, AaFwk_Intent_Parameters_LongArray, TestSize.Level1) +{ + std::string setKey = std::get<0>(GetParam()); + std::string getKey = std::get<1>(GetParam()); + std::vector setValue = std::get<2>(GetParam()); + std::vector defaultValue = std::get<3>(GetParam()); + std::vector result = std::get<4>(GetParam()); + intent_->SetLongArrayParam(setKey, setValue); + EXPECT_EQ(result, intent_->GetLongArrayParam(getKey)); +} + +INSTANTIATE_TEST_CASE_P(IntentParametersLongArrayTestCaseP, IntentParametersLongArrayTest, + testing::Values(testLongArrayType("", "aa", {-1, 3, 25, -9}, {}, {}), + testLongArrayType("", "", {-41, 0, 0, 9}, {}, {-41, 0, 0, 9}), + testLongArrayType("1*中_aR", "aa", {50, 2, -9}, {}, {}), + testLongArrayType("1*中_aR", "1*中_aR", {-5000}, {}, {-5000}))); + +/* + * Feature: Intent + * Function: SetLongArrayParam & GetLongArrayParam + * SubFunction: NA + * FunctionPoints: SetLongArrayParam & GetLongArrayParam + * EnvConditions: NA + * CaseDescription: get param when IntentParam is empty + */ +HWTEST_F(IntentParametersLongArrayTest, AaFwk_Intent_Parameters_Long_Array_001, TestSize.Level1) +{ + std::vector defaultValue; + std::string key = "aa"; + EXPECT_EQ(defaultValue, intent_->GetLongArrayParam(key)); +} + +/* + * Feature: Intent + * Function: SetLongArrayParam & GetLongArrayParam + * SubFunction: NA + * FunctionPoints: SetLongArrayParam & GetLongArrayParam + * EnvConditions: NA + * CaseDescription: set empty-string key repeatedly, but get param of another nonexistent key + */ +HWTEST_F(IntentParametersLongArrayTest, AaFwk_Intent_Parameters_Long_Array_002, TestSize.Level1) +{ + std::vector defaultValue; + std::string setKey1 = ""; + std::string setKey2 = "aa"; + std::vector setValue1 = {1, 2}; + intent_->SetLongArrayParam(setKey1, setValue1); + intent_->SetLongArrayParam(setKey1, setValue1); + setValue1 = {2, 3}; + intent_->SetLongArrayParam(setKey1, setValue1); + EXPECT_EQ(defaultValue, intent_->GetLongArrayParam(setKey2)); + setValue1 = {4, 5}; + intent_->SetLongArrayParam(setKey1, setValue1); + EXPECT_EQ(setValue1, intent_->GetLongArrayParam(setKey1)); +} + +/* + * Feature: Intent + * Function: SetLongArrayParam & GetLongArrayParam + * SubFunction: NA + * FunctionPoints: SetLongArrayParam & GetLongArrayParam + * EnvConditions: NA + * CaseDescription: set empty-string key repeatedly, then get param of the key + */ +HWTEST_F(IntentParametersLongArrayTest, AaFwk_Intent_Parameters_Long_Array_003, TestSize.Level1) +{ + std::vector defaultValue; + std::string setKey1 = "%1uH3"; + std::string setKey2 = "aa"; + std::vector setValue1 = {-1, -2}; + intent_->SetLongArrayParam(setKey1, setValue1); + intent_->SetLongArrayParam(setKey1, setValue1); + setValue1 = {0, 1}; + intent_->SetLongArrayParam(setKey1, setValue1); + EXPECT_EQ(setValue1, intent_->GetLongArrayParam(setKey1)); + setValue1 = {4, 5}; + intent_->SetLongArrayParam(setKey1, setValue1); + EXPECT_EQ(defaultValue, intent_->GetLongArrayParam(setKey2)); +} + +using testFloatType = std::tuple; +class IntentParametersFloatTest : public testing::TestWithParam { +public: + IntentParametersFloatTest() : intent_(nullptr) + {} + ~IntentParametersFloatTest() + { + intent_ = nullptr; + } + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + Intent *intent_; +}; + +void IntentParametersFloatTest::SetUpTestCase(void) +{} + +void IntentParametersFloatTest::TearDownTestCase(void) +{} + +void IntentParametersFloatTest::SetUp(void) +{ + intent_ = new (std::nothrow) Intent(); +} + +void IntentParametersFloatTest::TearDown(void) +{ + delete intent_; + intent_ = nullptr; +} + +/* + * Feature: Intent + * Function: SetFloatParam/GetFloatParam + * SubFunction: NA + * FunctionPoints: SetFloatParam/GetFloatParam + * EnvConditions: NA + * CaseDescription: Verify when parameter change. + */ +HWTEST_P(IntentParametersFloatTest, AaFwk_Intent_Parameters_Float, TestSize.Level1) +{ + std::string setKey = std::get<0>(GetParam()); + std::string getKey = std::get<1>(GetParam()); + float setValue = std::get<2>(GetParam()); + float defaultValue = std::get<3>(GetParam()); + float result = std::get<4>(GetParam()); + intent_->SetFloatParam(setKey, setValue); + EXPECT_EQ(result, intent_->GetFloatParam(getKey, defaultValue)); +} + +INSTANTIATE_TEST_CASE_P(IntentParametersFloatTestCaseP, IntentParametersFloatTest, + testing::Values(testFloatType("", "aa", -1.1, 100.1, 100.1), testFloatType("", "", -9.1, -41.1, -9.1), + testFloatType("1*中_aR", "aa", 50.1, 5.1, 5.1), testFloatType("1*中_aR", "1*中_aR", -5000.1, 5000.1, -5000.1))); + +/* + * Feature: Intent + * Function: SetFloatParam & GetFloatParam + * SubFunction: NA + * FunctionPoints: SetFloatParam & GetFloatParam + * EnvConditions: NA + * CaseDescription: get param when IntentParam is empty + */ +HWTEST_F(IntentParametersFloatTest, AaFwk_Intent_Parameters_Float_001, TestSize.Level1) +{ + float defaultValue = 100.1; + std::string key = "aa"; + EXPECT_EQ(defaultValue, intent_->GetFloatParam(key, defaultValue)); +} + +/* + * Feature: Intent + * Function: SetFloatParam & GetFloatParam + * SubFunction: NA + * FunctionPoints: SetFloatParam & GetFloatParam + * EnvConditions: NA + * CaseDescription: set empty-string key repeatedly, but get param of another nonexistent key + */ +HWTEST_F(IntentParametersFloatTest, AaFwk_Intent_Parameters_Float_002, TestSize.Level1) +{ + std::string setKey1 = ""; + std::string setKey2 = "aa"; + float setValue1 = 1.1; + float setValue2 = 5.1; + intent_->SetFloatParam(setKey1, setValue1); + intent_->SetFloatParam(setKey1, setValue1); + setValue1 = 2.1; + intent_->SetFloatParam(setKey1, setValue1); + setValue1 = 3.1; + EXPECT_EQ(setValue1, intent_->GetFloatParam(setKey2, setValue1)); + setValue1 = 4.1; + intent_->SetFloatParam(setKey1, setValue1); + EXPECT_EQ(setValue1, intent_->GetFloatParam(setKey1, setValue2)); +} + +/* + * Feature: Intent + * Function: SetFloatParam & GetFloatParam + * SubFunction: NA + * FunctionPoints: SetFloatParam & GetFloatParam + * EnvConditions: NA + * CaseDescription: set empty-string key repeatedly, then get param of the key + */ +HWTEST_F(IntentParametersFloatTest, AaFwk_Intent_Parameters_Float_003, TestSize.Level1) +{ + std::string setKey1 = "%1uH3"; + std::string setKey2 = "aa"; + float setValue1 = -1.1; + float setValue2 = 9.1; + intent_->SetFloatParam(setKey1, setValue1); + intent_->SetFloatParam(setKey1, setValue1); + setValue1 = 0.1; + intent_->SetFloatParam(setKey1, setValue1); + EXPECT_EQ(setValue1, intent_->GetFloatParam(setKey1, setValue2)); + setValue1 = 4.1; + intent_->SetFloatParam(setKey1, setValue1); + setValue1 = -10.1; + EXPECT_EQ(setValue1, intent_->GetFloatParam(setKey2, setValue1)); +} + +using testFloatArrayType = + std::tuple, std::vector, std::vector>; +class IntentParametersFloatArrayTest : public testing::TestWithParam { +public: + IntentParametersFloatArrayTest() : intent_(nullptr) + {} + ~IntentParametersFloatArrayTest() + { + intent_ = nullptr; + } + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + Intent *intent_; +}; + +void IntentParametersFloatArrayTest::SetUpTestCase(void) +{} + +void IntentParametersFloatArrayTest::TearDownTestCase(void) +{} + +void IntentParametersFloatArrayTest::SetUp(void) +{ + intent_ = new (std::nothrow) Intent(); +} + +void IntentParametersFloatArrayTest::TearDown(void) +{ + delete intent_; + intent_ = nullptr; +} + +/* + * Feature: Intent + * Function: SetFloatArrayParam/GetFloatArrayParam + * SubFunction: NA + * FunctionPoints: SetFloatArrayParam/GetFloatArrayParam + * EnvConditions: NA + * CaseDescription: Verify when parameter change. + */ +HWTEST_P(IntentParametersFloatArrayTest, AaFwk_Intent_Parameters_FloatArray, TestSize.Level1) +{ + std::string setKey = std::get<0>(GetParam()); + std::string getKey = std::get<1>(GetParam()); + std::vector setValue = std::get<2>(GetParam()); + std::vector defaultValue = std::get<3>(GetParam()); + std::vector result = std::get<4>(GetParam()); + intent_->SetFloatArrayParam(setKey, setValue); + EXPECT_EQ(result, intent_->GetFloatArrayParam(getKey)); +} + +INSTANTIATE_TEST_CASE_P(IntentParametersFloatArrayTestCaseP, IntentParametersFloatArrayTest, + testing::Values(testFloatArrayType("", "aa", {-1.1, -2.1}, {}, {}), + testFloatArrayType("", "", {-41.1, -42.1}, {}, {-41.1, -42.1}), + testFloatArrayType("1*中_aR", "aa", {50.1, 51.1}, {}, {}), + testFloatArrayType("1*中_aR", "1*中_aR", {5000.1, 5001.1}, {}, {5000.1, 5001.1}))); + +/* + * Feature: Intent + * Function: SetFloatArrayParam & GetFloatArrayParam + * SubFunction: NA + * FunctionPoints: SetFloatArrayParam & GetFloatArrayParam + * EnvConditions: NA + * CaseDescription: get param when IntentParam is empty + */ +HWTEST_F(IntentParametersFloatArrayTest, AaFwk_Intent_Parameters_Float_Array_001, TestSize.Level1) +{ + std::vector defaultValue; + std::string key = "aa"; + EXPECT_EQ(defaultValue, intent_->GetFloatArrayParam(key)); +} + +/* + * Feature: Intent + * Function: SetFloatArrayParam & GetFloatArrayParam + * SubFunction: NA + * FunctionPoints: SetFloatArrayParam & GetFloatArrayParam + * EnvConditions: NA + * CaseDescription: set empty-string key repeatedly, but get param of another nonexistent key + */ +HWTEST_F(IntentParametersFloatArrayTest, AaFwk_Intent_Parameters_Float_Array_002, TestSize.Level1) +{ + std::vector defaultValue; + std::string setKey1 = ""; + std::string setKey2 = "aa"; + std::vector setValue1 = {1.1, 2.1}; + intent_->SetFloatArrayParam(setKey1, setValue1); + intent_->SetFloatArrayParam(setKey1, setValue1); + setValue1 = {2.1, 3.1}; + intent_->SetFloatArrayParam(setKey1, setValue1); + EXPECT_EQ(defaultValue, intent_->GetFloatArrayParam(setKey2)); + setValue1 = {4.1, 5.1}; + intent_->SetFloatArrayParam(setKey1, setValue1); + EXPECT_EQ(setValue1, intent_->GetFloatArrayParam(setKey1)); +} + +/* + * Feature: Intent + * Function: SetFloatArrayParam & GetFloatArrayParam + * SubFunction: NA + * FunctionPoints: SetFloatArrayParam & GetFloatArrayParam + * EnvConditions: NA + * CaseDescription: set empty-string key repeatedly, then get param of the key + */ +HWTEST_F(IntentParametersFloatArrayTest, AaFwk_Intent_Parameters_Float_Array_003, TestSize.Level1) +{ + std::vector defaultValue; + std::string setKey1 = "%1uH3"; + std::string setKey2 = "aa"; + std::vector setValue1 = {-1.1, -2.1}; + intent_->SetFloatArrayParam(setKey1, setValue1); + intent_->SetFloatArrayParam(setKey1, setValue1); + setValue1 = {0.1, 1.1}; + intent_->SetFloatArrayParam(setKey1, setValue1); + EXPECT_EQ(setValue1, intent_->GetFloatArrayParam(setKey1)); + setValue1 = {4.1, 5.1}; + intent_->SetFloatArrayParam(setKey1, setValue1); + EXPECT_EQ(defaultValue, intent_->GetFloatArrayParam(setKey2)); +} + +using testDoubleType = std::tuple; +class IntentParametersDoubleTest : public testing::TestWithParam { +public: + IntentParametersDoubleTest() : intent_(nullptr) + {} + ~IntentParametersDoubleTest() + { + intent_ = nullptr; + } + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + Intent *intent_; +}; + +void IntentParametersDoubleTest::SetUpTestCase(void) +{} + +void IntentParametersDoubleTest::TearDownTestCase(void) +{} + +void IntentParametersDoubleTest::SetUp(void) +{ + intent_ = new (std::nothrow) Intent(); +} + +void IntentParametersDoubleTest::TearDown(void) +{ + delete intent_; + intent_ = nullptr; +} + +/* + * Feature: Intent + * Function: SetDoubleParam/GetDoubleParam + * SubFunction: NA + * FunctionPoints: SetDoubleParam/GetDoubleParam + * EnvConditions: NA + * CaseDescription: Verify when parameter change. + */ +HWTEST_P(IntentParametersDoubleTest, AaFwk_Intent_Parameters_Double, TestSize.Level1) +{ + std::string setKey = std::get<0>(GetParam()); + std::string getKey = std::get<1>(GetParam()); + double setValue = std::get<2>(GetParam()); + double defaultValue = std::get<3>(GetParam()); + double result = std::get<4>(GetParam()); + intent_->SetDoubleParam(setKey, setValue); + EXPECT_EQ(result, intent_->GetDoubleParam(getKey, defaultValue)); +} + +INSTANTIATE_TEST_CASE_P(IntentParametersDoubleTestCaseP, IntentParametersDoubleTest, + testing::Values(testDoubleType("", "aa", -1.1, 100.1, 100.1), testDoubleType("", "", -9.1, -41.1, -9.1), + testDoubleType("1*中_aR", "aa", 50.1, 5.1, 5.1), + testDoubleType("1*中_aR", "1*中_aR", -5000.1, 5000.1, -5000.1))); + +/* + * Feature: Intent + * Function: SetDoubleParam & GetDoubleParam + * SubFunction: NA + * FunctionPoints: SetDoubleParam & GetDoubleParam + * EnvConditions: NA + * CaseDescription: get param when IntentParam is empty + */ +HWTEST_F(IntentParametersDoubleTest, AaFwk_Intent_Parameters_Double_001, TestSize.Level1) +{ + double defaultValue = 100.1; + std::string key = "aa"; + EXPECT_EQ(defaultValue, intent_->GetDoubleParam(key, defaultValue)); +} + +/* + * Feature: Intent + * Function: SetDoubleParam & GetDoubleParam + * SubFunction: NA + * FunctionPoints: SetDoubleParam & GetDoubleParam + * EnvConditions: NA + * CaseDescription: set empty-string key repeatedly, but get param of another nonexistent key + */ +HWTEST_F(IntentParametersDoubleTest, AaFwk_Intent_Parameters_Double_002, TestSize.Level1) +{ + std::string setKey1 = ""; + std::string setKey2 = "aa"; + double setValue1 = 1.1; + double setValue2 = 5.1; + intent_->SetDoubleParam(setKey1, setValue1); + intent_->SetDoubleParam(setKey1, setValue1); + setValue1 = 2.1; + intent_->SetDoubleParam(setKey1, setValue1); + setValue1 = 3.1; + EXPECT_EQ(setValue1, intent_->GetDoubleParam(setKey2, setValue1)); + setValue1 = 4.1; + intent_->SetDoubleParam(setKey1, setValue1); + EXPECT_EQ(setValue1, intent_->GetDoubleParam(setKey1, setValue2)); +} + +/* + * Feature: Intent + * Function: SetDoubleParam & GetDoubleParam + * SubFunction: NA + * FunctionPoints: SetDoubleParam & GetDoubleParam + * EnvConditions: NA + * CaseDescription: set empty-string key repeatedly, then get param of the key + */ +HWTEST_F(IntentParametersDoubleTest, AaFwk_Intent_Parameters_Double_003, TestSize.Level1) +{ + std::string setKey1 = "%1uH3"; + std::string setKey2 = "aa"; + double setValue1 = -1.1; + double setValue2 = 9.1; + intent_->SetDoubleParam(setKey1, setValue1); + intent_->SetDoubleParam(setKey1, setValue1); + setValue1 = 0.1; + intent_->SetDoubleParam(setKey1, setValue1); + EXPECT_EQ(setValue1, intent_->GetDoubleParam(setKey1, setValue2)); + setValue1 = 4.1; + intent_->SetDoubleParam(setKey1, setValue1); + setValue1 = -10.1; + EXPECT_EQ(setValue1, intent_->GetDoubleParam(setKey2, setValue1)); +} + +using testDoubleArrayType = + std::tuple, std::vector, std::vector>; +class IntentParametersDoubleArrayTest : public testing::TestWithParam { +public: + IntentParametersDoubleArrayTest() : intent_(nullptr) + {} + ~IntentParametersDoubleArrayTest() + { + intent_ = nullptr; + } + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + Intent *intent_; +}; + +void IntentParametersDoubleArrayTest::SetUpTestCase(void) +{} + +void IntentParametersDoubleArrayTest::TearDownTestCase(void) +{} + +void IntentParametersDoubleArrayTest::SetUp(void) +{ + intent_ = new (std::nothrow) Intent(); +} + +void IntentParametersDoubleArrayTest::TearDown(void) +{ + delete intent_; + intent_ = nullptr; +} + +/* + * Feature: Intent + * Function: SetDoubleArrayParam/GetDoubleArrayParam + * SubFunction: NA + * FunctionPoints: SetDoubleArrayParam/GetDoubleArrayParam + * EnvConditions: NA + * CaseDescription: Verify when parameter change. + */ +HWTEST_P(IntentParametersDoubleArrayTest, AaFwk_Intent_Parameters_DoubleArray, TestSize.Level1) +{ + std::string setKey = std::get<0>(GetParam()); + std::string getKey = std::get<1>(GetParam()); + std::vector setValue = std::get<2>(GetParam()); + std::vector defaultValue = std::get<3>(GetParam()); + std::vector result = std::get<4>(GetParam()); + intent_->SetDoubleArrayParam(setKey, setValue); + EXPECT_EQ(result, intent_->GetDoubleArrayParam(getKey)); +} + +INSTANTIATE_TEST_CASE_P(IntentParametersDoubleArrayTestCaseP, IntentParametersDoubleArrayTest, + testing::Values(testDoubleArrayType("", "aa", {-1.1, -2.1}, {}, {}), + testDoubleArrayType("", "", {-41.1, -42.1}, {}, {-41.1, -42.1}), + testDoubleArrayType("1*中_aR", "aa", {50.1, 51.1}, {}, {}), + testDoubleArrayType("1*中_aR", "1*中_aR", {5000.1, 5001.1}, {}, {5000.1, 5001.1}))); + +/* + * Feature: Intent + * Function: SetDoubleArrayParam & GetDoubleArrayParam + * SubFunction: NA + * FunctionPoints: SetDoubleArrayParam & GetDoubleArrayParam + * EnvConditions: NA + * CaseDescription: get param when IntentParam is empty + */ +HWTEST_F(IntentParametersDoubleArrayTest, AaFwk_Intent_Parameters_Double_Array_001, TestSize.Level1) +{ + std::vector defaultValue; + std::string key = "aa"; + EXPECT_EQ(defaultValue, intent_->GetDoubleArrayParam(key)); +} + +/* + * Feature: Intent + * Function: SetDoubleArrayParam & GetDoubleArrayParam + * SubFunction: NA + * FunctionPoints: SetDoubleArrayParam & GetDoubleArrayParam + * EnvConditions: NA + * CaseDescription: set empty-string key repeatedly, but get param of another nonexistent key + */ +HWTEST_F(IntentParametersDoubleArrayTest, AaFwk_Intent_Parameters_Double_Array_002, TestSize.Level1) +{ + std::vector defaultValue; + std::string setKey1 = ""; + std::string setKey2 = "aa"; + std::vector setValue1 = {1.1, 2.1}; + std::vector setValue2 = {5.1, 6.1}; + intent_->SetDoubleArrayParam(setKey1, setValue1); + intent_->SetDoubleArrayParam(setKey1, setValue1); + setValue1 = {2.1, 3.1}; + intent_->SetDoubleArrayParam(setKey1, setValue1); + EXPECT_EQ(defaultValue, intent_->GetDoubleArrayParam(setKey2)); + setValue1 = {4.1, 5.1}; + intent_->SetDoubleArrayParam(setKey1, setValue1); + EXPECT_EQ(setValue1, intent_->GetDoubleArrayParam(setKey1)); +} + +/* + * Feature: Intent + * Function: SetDoubleArrayParam & GetDoubleArrayParam + * SubFunction: NA + * FunctionPoints: SetDoubleArrayParam & GetDoubleArrayParam + * EnvConditions: NA + * CaseDescription: set empty-string key repeatedly, then get param of the key + */ +HWTEST_F(IntentParametersDoubleArrayTest, AaFwk_Intent_Parameters_Double_Array_003, TestSize.Level1) +{ + std::vector defaultValue; + std::string setKey1 = "%1uH3"; + std::string setKey2 = "aa"; + std::vector setValue1 = {-1.1, -2.1}; + intent_->SetDoubleArrayParam(setKey1, setValue1); + intent_->SetDoubleArrayParam(setKey1, setValue1); + setValue1 = {0.1, 1.1}; + intent_->SetDoubleArrayParam(setKey1, setValue1); + EXPECT_EQ(setValue1, intent_->GetDoubleArrayParam(setKey1)); + setValue1 = {4.1, 5.1}; + intent_->SetDoubleArrayParam(setKey1, setValue1); + setValue1 = {-10.1, -11.1}; + EXPECT_EQ(defaultValue, intent_->GetDoubleArrayParam(setKey2)); +} + +using testStrType = std::tuple; +class IntentParametersStringTest : public testing::TestWithParam { +public: + IntentParametersStringTest() : intent_(nullptr) + {} + ~IntentParametersStringTest() + { + intent_ = nullptr; + } + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + Intent *intent_; +}; + +void IntentParametersStringTest::SetUpTestCase(void) +{} + +void IntentParametersStringTest::TearDownTestCase(void) +{} + +void IntentParametersStringTest::SetUp(void) +{ + intent_ = new (std::nothrow) Intent(); +} + +void IntentParametersStringTest::TearDown(void) +{ + delete intent_; + intent_ = nullptr; +} + +/* + * Feature: Intent + * Function: SetStringParam/GetStringParam + * SubFunction: NA + * FunctionPoints: SetStringParam/GetStringParam + * EnvConditions: NA + * CaseDescription: Verify when parameter change. + */ +HWTEST_P(IntentParametersStringTest, AaFwk_Intent_Parameters_String, TestSize.Level1) +{ + std::string setKey = std::get<0>(GetParam()); + std::string getKey = std::get<1>(GetParam()); + std::string setValue = std::get<2>(GetParam()); + std::string defaultValue = std::get<3>(GetParam()); + std::string result = std::get<4>(GetParam()); + intent_->SetStringParam(setKey, setValue); + EXPECT_EQ(result, intent_->GetStringParam(getKey)); +} + +INSTANTIATE_TEST_CASE_P(IntentParametersStringTestCaseP, IntentParametersStringTest, + testing::Values(testStrType("", "aa", "1*中_aR", "", ""), testStrType("", "", "1*中_aR", "", "1*中_aR"), + testStrType("1*中_aR", "aa", "aaa", "", ""), testStrType("1*中_aR", "1*中_aR", "aaa", "", "aaa"))); + +/* + * Feature: Intent + * Function: SetStringParam & GetStringParam + * SubFunction: NA + * FunctionPoints: SetStringParam & GetStringParam + * EnvConditions: NA + * CaseDescription: get param when IntentParam is empty + */ +HWTEST_F(IntentParametersStringTest, AaFwk_Intent_Parameters_String_001, TestSize.Level1) +{ + std::string defaultStrValue; + std::string key = "aa"; + EXPECT_EQ(defaultStrValue, intent_->GetStringParam(key)); +} + +/* + * Feature: Intent + * Function: SetStringParam & GetStringParam + * SubFunction: NA + * FunctionPoints: SetStringParam & GetStringParam + * EnvConditions: NA + * CaseDescription: set empty-string key repeatedly, but get param of another nonexistent key + */ +HWTEST_F(IntentParametersStringTest, AaFwk_Intent_Parameters_String_002, TestSize.Level1) +{ + std::string defaultStrValue; + std::string setValue1 = "aaa"; + std::string setValue2 = "1*中_aR"; + std::string key1 = ""; + std::string key2 = "aa"; + intent_->SetStringParam(key1, setValue1); + intent_->SetStringParam(key1, setValue1); + intent_->SetStringParam(key1, setValue2); + EXPECT_EQ(defaultStrValue, intent_->GetStringParam(key2)); + intent_->SetStringParam(key1, setValue1); + EXPECT_EQ(setValue1, intent_->GetStringParam(key1)); +} + +/* + * Feature: Intent + * Function: SetStringParam & GetStringParam + * SubFunction: NA + * FunctionPoints: SetStringParam & GetStringParam + * EnvConditions: NA + * CaseDescription: set empty-string key repeatedly, then get param of the key + */ +HWTEST_F(IntentParametersStringTest, AaFwk_Intent_Parameters_String_003, TestSize.Level1) +{ + std::string key1 = "%1uH3"; + std::string defaultStrValue; + std::string setValue1 = "aaa"; + std::string setValue2 = "1*中_aR"; + std::string key2 = "aa"; + intent_->SetStringParam(key1, setValue1); + intent_->SetStringParam(key1, setValue1); + intent_->SetStringParam(key1, setValue2); + EXPECT_EQ("1*中_aR", intent_->GetStringParam(key1)); + intent_->SetStringParam(key1, setValue1); + EXPECT_EQ(defaultStrValue, intent_->GetStringParam(key2)); +} + +using testStrArrayType = + std::tuple, std::vector, std::vector>; +class IntentParametersStringArrayTest : public testing::TestWithParam { +public: + IntentParametersStringArrayTest() : intent_(nullptr) + {} + ~IntentParametersStringArrayTest() + { + intent_ = nullptr; + } + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + Intent *intent_; +}; + +void IntentParametersStringArrayTest::SetUpTestCase(void) +{} + +void IntentParametersStringArrayTest::TearDownTestCase(void) +{} + +void IntentParametersStringArrayTest::SetUp(void) +{ + intent_ = new (std::nothrow) Intent(); +} + +void IntentParametersStringArrayTest::TearDown(void) +{ + delete intent_; + intent_ = nullptr; +} + +/* + * Feature: Intent + * Function: SetStringArrayParam/GetStringArrayParam + * SubFunction: NA + * FunctionPoints: SetStringArrayParam/GetStringArrayParam + * EnvConditions: NA + * CaseDescription: Verify when parameter change. + */ +HWTEST_P(IntentParametersStringArrayTest, AaFwk_Intent_Parameters_StringArray, TestSize.Level1) +{ + std::string setKey = std::get<0>(GetParam()); + std::string getKey = std::get<1>(GetParam()); + std::vector setValue = std::get<2>(GetParam()); + std::vector defaultValue = std::get<3>(GetParam()); + std::vector result = std::get<4>(GetParam()); + intent_->SetStringArrayParam(setKey, setValue); + EXPECT_EQ(result, intent_->GetStringArrayParam(getKey)); +} + +INSTANTIATE_TEST_CASE_P(IntentParametersStringArrayTestCaseP, IntentParametersStringArrayTest, + testing::Values(testStrArrayType("", "aa", {"1*中_aR", "dadb"}, {}, {}), + testStrArrayType("", "", {"1*中_aR", "dadb"}, {}, {"1*中_aR", "dadb"}), + testStrArrayType("1*中_aR", "aa", {"1*中_aR", "dadb"}, {}, {}), + testStrArrayType("1*中_aR", "1*中_aR", {"1*中_aR", "dadb"}, {}, {"1*中_aR", "dadb"}))); + +/* + * Feature: Intent + * Function: SetStringArrayParam & GetStringArrayParam + * SubFunction: NA + * FunctionPoints: SetStringArrayParam & GetStringArrayParam + * EnvConditions: NA + * CaseDescription: get param when IntentParam is empty + */ +HWTEST_F(IntentParametersStringArrayTest, AaFwk_Intent_Parameters_String_Array_001, TestSize.Level1) +{ + std::vector defaultValue; + std::string key = "aa"; + std::vector resultValue = intent_->GetStringArrayParam(key); + EXPECT_EQ(defaultValue, resultValue); +} + +/* + * Feature: Intent + * Function: SetStringArrayParam & GetStringArrayParam + * SubFunction: NA + * FunctionPoints: SetStringArrayParam & GetStringArrayParam + * EnvConditions: NA + * CaseDescription: set empty-string key repeatedly, but get param of another nonexistent key + */ +HWTEST_F(IntentParametersStringArrayTest, AaFwk_Intent_Parameters_String_Array_002, TestSize.Level1) +{ + std::vector defaultValue; + std::vector setValue1 = {"aaa", "2132"}; + std::vector setValue2 = {"1*中_aR", "dadb"}; + std::string key1 = ""; + std::string key2 = "aa"; + intent_->SetStringArrayParam(key1, setValue1); + intent_->SetStringArrayParam(key1, setValue1); + intent_->SetStringArrayParam(key1, setValue2); + std::vector resultValue = intent_->GetStringArrayParam(key2); + EXPECT_EQ(defaultValue, resultValue); + + intent_->SetStringArrayParam(key1, setValue1); + resultValue = intent_->GetStringArrayParam(key1); + EXPECT_EQ(setValue1, resultValue); +} + +/* + * Feature: Intent + * Function: SetStringArrayParam & GetStringArrayParam + * SubFunction: NA + * FunctionPoints: SetStringArrayParam & GetStringArrayParam + * EnvConditions: NA + * CaseDescription: set empty-string key repeatedly, then get param of the key + */ +HWTEST_F(IntentParametersStringArrayTest, AaFwk_Intent_Parameters_String_Array_003, TestSize.Level1) +{ + std::vector defaultValue; + std::vector setValue = {"aaa", "2132"}; + std::string key1 = "%1uH3"; + std::string key2 = "aa"; + intent_->SetStringArrayParam(key1, setValue); + intent_->SetStringArrayParam(key1, setValue); + setValue = {"1*中_aR", "3#$%"}; + intent_->SetStringArrayParam(key1, setValue); + std::vector resultValue = intent_->GetStringArrayParam(key1); + EXPECT_EQ(setValue, resultValue); + + setValue = {"aaa", "2132"}; + intent_->SetStringArrayParam(key1, setValue); + resultValue = intent_->GetStringArrayParam(key2); + EXPECT_EQ(defaultValue, resultValue); +} + +class IntentParametersHasParamTest : public testing::Test { +public: + IntentParametersHasParamTest() : intent_(nullptr) + {} + ~IntentParametersHasParamTest() + { + intent_ = nullptr; + } + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + Intent *intent_; +}; + +void IntentParametersHasParamTest::SetUpTestCase(void) +{} + +void IntentParametersHasParamTest::TearDownTestCase(void) +{} + +void IntentParametersHasParamTest::SetUp(void) +{ + intent_ = new (std::nothrow) Intent(); +} + +void IntentParametersHasParamTest::TearDown(void) +{ + delete intent_; + intent_ = nullptr; +} + +/* + * Feature: Intent + * Function: HasParameter + * SubFunction: NA + * FunctionPoints: HasParameter + * EnvConditions: NA + * CaseDescription: verify if parameter exists + */ +HWTEST_F(IntentParametersHasParamTest, AaFwk_Intent_Parameters_Has_Parameter_001, TestSize.Level1) +{ + std::string keyBool = "keyBool"; + std::string keyChar = "keyChar"; + std::string keyShort = "keyShort"; + std::string keyInt = "keyInt"; + std::string keyLong = "keyLong"; + std::string keyFloat = "keyFloat"; + std::string keyDouble = "keyDouble"; + std::string keyString = "keyString"; + std::string keyBoolArray = "keyBoolArray"; + std::string keyCharArray = "keyCharArray"; + std::string keyShortArray = "keyShortArray"; + std::string keyIntArray = "keyIntArray"; + std::string keyLongArray = "keyLongArray"; + std::string keyFloatArray = "keyFloatArray"; + std::string keyDoubleArray = "keyDoubleArray"; + std::string keyStringArray = "keyStringArray"; + + std::string keyBoolNotExist = "keyBoolNotExist"; + std::string keyCharNotExist = "keyCharNotExist"; + std::string keyShortNotExist = "keyShortNotExist"; + std::string keyIntNotExist = "keyIntNotExist"; + std::string keyLongNotExist = "keyLongNotExist"; + std::string keyFloatNotExist = "keyFloatNotExist"; + std::string keyDoubleNotExist = "keyDoubleNotExist"; + std::string keyStringNotExist = "keyStringNotExist"; + std::string keyBoolArrayNotExist = "keyBoolArrayNotExist"; + std::string keyCharArrayNotExist = "keyCharArrayNotExist"; + std::string keyShortArrayNotExist = "keyShortArrayNotExist"; + std::string keyIntArrayNotExist = "keyIntArrayNotExist"; + std::string keyLongArrayNotExist = "keyLongArrayNotExist"; + std::string keyFloatArrayNotExist = "keyFloatArrayNotExist"; + std::string keyDoubleArrayNotExist = "keyDoubleArrayNotExist"; + std::string keyStringArrayNotExist = "keyStringArrayNotExist"; + + bool valueBool = false; + zchar valueChar = 1; + short valueShort = 2; + int valueInt = 3; + long valueLong = 4; + float valueFloat = 5.1; + double valueDouble = 6.2; + std::string valueString = "1*中_aRabc"; + std::vector valueBoolArray = {true, false}; + std::vector valueCharArray = {1, 2}; + std::vector valueShortArray = {3, 4}; + std::vector valueIntArray = {5, 6}; + std::vector valueLongArray = {7, 8}; + std::vector valueFloatArray = {9.1, 10.2}; + std::vector valueDoubleArray = {11.3, 12.4}; + std::vector valueStringArray = {"1*中_aRabc", "1*中_aRpinyin"}; + + intent_->SetBoolParam(keyBool, valueBool); + intent_->SetCharParam(keyChar, valueChar); + intent_->SetShortParam(keyShort, valueShort); + intent_->SetIntParam(keyInt, valueInt); + intent_->SetLongParam(keyLong, valueLong); + intent_->SetFloatParam(keyFloat, valueFloat); + intent_->SetDoubleParam(keyDouble, valueDouble); + intent_->SetStringParam(keyString, valueString); + + intent_->SetBoolArrayParam(keyBoolArray, valueBoolArray); + intent_->SetCharArrayParam(keyCharArray, valueCharArray); + intent_->SetShortArrayParam(keyShortArray, valueShortArray); + intent_->SetIntArrayParam(keyIntArray, valueIntArray); + intent_->SetLongArrayParam(keyLongArray, valueLongArray); + intent_->SetFloatArrayParam(keyFloatArray, valueFloatArray); + intent_->SetDoubleArrayParam(keyDoubleArray, valueDoubleArray); + intent_->SetStringArrayParam(keyStringArray, valueStringArray); + + EXPECT_EQ(true, intent_->HasParameter(keyBool)); + EXPECT_EQ(true, intent_->HasParameter(keyChar)); + EXPECT_EQ(true, intent_->HasParameter(keyShort)); + EXPECT_EQ(true, intent_->HasParameter(keyInt)); + EXPECT_EQ(true, intent_->HasParameter(keyLong)); + EXPECT_EQ(true, intent_->HasParameter(keyFloat)); + EXPECT_EQ(true, intent_->HasParameter(keyDouble)); + EXPECT_EQ(true, intent_->HasParameter(keyString)); + EXPECT_EQ(true, intent_->HasParameter(keyBoolArray)); + EXPECT_EQ(true, intent_->HasParameter(keyCharArray)); + EXPECT_EQ(true, intent_->HasParameter(keyShortArray)); + EXPECT_EQ(true, intent_->HasParameter(keyIntArray)); + EXPECT_EQ(true, intent_->HasParameter(keyLongArray)); + EXPECT_EQ(true, intent_->HasParameter(keyFloatArray)); + EXPECT_EQ(true, intent_->HasParameter(keyDoubleArray)); + EXPECT_EQ(true, intent_->HasParameter(keyStringArray)); + + EXPECT_EQ(false, intent_->HasParameter(keyBoolNotExist)); + EXPECT_EQ(false, intent_->HasParameter(keyCharNotExist)); + EXPECT_EQ(false, intent_->HasParameter(keyShortNotExist)); + EXPECT_EQ(false, intent_->HasParameter(keyIntNotExist)); + EXPECT_EQ(false, intent_->HasParameter(keyLongNotExist)); + EXPECT_EQ(false, intent_->HasParameter(keyFloatNotExist)); + EXPECT_EQ(false, intent_->HasParameter(keyDoubleNotExist)); + EXPECT_EQ(false, intent_->HasParameter(keyStringNotExist)); + EXPECT_EQ(false, intent_->HasParameter(keyBoolArrayNotExist)); + EXPECT_EQ(false, intent_->HasParameter(keyCharArrayNotExist)); + EXPECT_EQ(false, intent_->HasParameter(keyShortArrayNotExist)); + EXPECT_EQ(false, intent_->HasParameter(keyIntArrayNotExist)); + EXPECT_EQ(false, intent_->HasParameter(keyLongArrayNotExist)); + EXPECT_EQ(false, intent_->HasParameter(keyFloatArrayNotExist)); + EXPECT_EQ(false, intent_->HasParameter(keyDoubleArrayNotExist)); + EXPECT_EQ(false, intent_->HasParameter(keyStringArrayNotExist)); +} diff --git a/tools/frameworks/kits/content/cpp/test/unittest/common/operation_test.cpp b/tools/frameworks/kits/content/cpp/test/unittest/common/operation_test.cpp new file mode 100755 index 00000000000..761e0cf0c8b --- /dev/null +++ b/tools/frameworks/kits/content/cpp/test/unittest/common/operation_test.cpp @@ -0,0 +1,339 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "ohos/aafwk/content/operation.h" +#include "ohos/aafwk/content/operation_builder.h" + +using namespace testing::ext; +using namespace OHOS::AAFwk; +using OHOS::Parcel; +using Uri = OHOS::Uri; +class OperationBaseTest : public testing::Test { +public: + OperationBaseTest() + {} + ~OperationBaseTest() + {} + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + + std::shared_ptr operationbuilder_ = nullptr; +}; + +void OperationBaseTest::SetUpTestCase(void) +{} + +void OperationBaseTest::TearDownTestCase(void) +{} + +void OperationBaseTest::SetUp(void) +{ + operationbuilder_ = std::make_shared(); +} + +void OperationBaseTest::TearDown(void) +{} + +/** + * @tc.number: AaFwk_Operation_GetAbilityName_0100 + * @tc.name: WithAbilityName/GetAbilityName. + * @tc.desc: Verify the function when the input string contains special characters. + */ +HWTEST_F(OperationBaseTest, AaFwk_Operation_GetAbilityName_0100, Function | MediumTest | Level1) +{ + std::string value = "enter"; + GTEST_LOG_(INFO) << "AaFwk_Operation_GetAbilityName_0100 start"; + + operationbuilder_->WithAbilityName(value); + std::shared_ptr operation = operationbuilder_->build(); + EXPECT_STREQ(value.c_str(), operation->GetAbilityName().c_str()); + + GTEST_LOG_(INFO) << "AaFwk_Operation_GetAbilityName_0100 end"; +} + +/** + * @tc.number: AaFwk_Operation_GetAbilityName_0200 + * @tc.name: WithAbilityName/GetAbilityName. + * @tc.desc: Verify the function when the input string is empty. + */ +HWTEST_F(OperationBaseTest, AaFwk_Operation_GetAbilityName_0200, Function | MediumTest | Level3) +{ + std::string value = ""; + operationbuilder_->WithAbilityName(value); + std::shared_ptr operation = operationbuilder_->build(); + + EXPECT_STREQ(value.c_str(), operation->GetAbilityName().c_str()); +} + +/** + * @tc.number: AaFwk_Operation_GetBundleName_0100 + * @tc.name: WithBundleName/GetBundleName + * @tc.desc: Verify the function when the input string contains special characters. + */ +HWTEST_F(OperationBaseTest, AaFwk_Operation_GetBundleName_0100, Function | MediumTest | Level1) +{ + std::string value = "value"; + operationbuilder_->WithBundleName(value); + std::shared_ptr operation = operationbuilder_->build(); + EXPECT_STREQ(value.c_str(), operation->GetBundleName().c_str()); +} + +/** + * @tc.number: AaFwk_Operation_GetBundleName_0200 + * @tc.name: WithBundleName/GetBundleName + * @tc.desc: Verify the function when the input string is empty. + */ +HWTEST_F(OperationBaseTest, AaFwk_Operation_GetBundleName_0200, Function | MediumTest | Level3) +{ + std::string value = ""; + operationbuilder_->WithBundleName(value); + std::shared_ptr operation = operationbuilder_->build(); + EXPECT_STREQ(value.c_str(), operation->GetBundleName().c_str()); +} + +/** + * @tc.number: AaFwk_Operation_GetDeviceId_0100 + * @tc.name: WithDeviceId/GetDeviceId + * @tc.desc: Verify the function when the input string contains special characters. + */ +HWTEST_F(OperationBaseTest, AaFwk_Operation_GetDeviceId_0100, Function | MediumTest | Level1) +{ + std::string value = "value"; + operationbuilder_->WithDeviceId(value); + std::shared_ptr operation = operationbuilder_->build(); + EXPECT_STREQ(value.c_str(), operation->GetDeviceId().c_str()); +} + +/** + * @tc.number: AaFwk_Operation_GetDeviceId_0200 + * @tc.name: WithDeviceId/GetDeviceId + * @tc.desc: Verify the function when the input string is empty. + */ +HWTEST_F(OperationBaseTest, AaFwk_Operation_GetDeviceId_0200, Function | MediumTest | Level3) +{ + std::string value = ""; + operationbuilder_->WithDeviceId(value); + std::shared_ptr operation = operationbuilder_->build(); + EXPECT_STREQ(value.c_str(), operation->GetDeviceId().c_str()); +} + +/** + * @tc.number: AaFwk_Operation_GetAction_0100 + * @tc.name: WithAction/GetAction + * @tc.desc: Verify the function when the input string contains special characters. + */ +HWTEST_F(OperationBaseTest, AaFwk_Operation_GetAction_0100, Function | MediumTest | Level1) +{ + std::string value = "value"; + operationbuilder_->WithAction(value); + std::shared_ptr operation = operationbuilder_->build(); + EXPECT_STREQ(value.c_str(), operation->GetAction().c_str()); +} + +/** + * @tc.number: AaFwk_Operation_GetAction_0200 + * @tc.name: WithAction/GetAction + * @tc.desc: Verify the function when the input string is empty. + */ +HWTEST_F(OperationBaseTest, AaFwk_Operation_GetAction_0200, Function | MediumTest | Level3) +{ + std::string value = ""; + operationbuilder_->WithAction(value); + std::shared_ptr operation = operationbuilder_->build(); + EXPECT_STREQ(value.c_str(), operation->GetAction().c_str()); +} + +/** + * @tc.number: AaFwk_Operation_GetEntities_0100 + * @tc.name: WithEntities/GetEntities + * @tc.desc: Verify the function when the input string contains special characters. + */ +HWTEST_F(OperationBaseTest, AaFwk_Operation_GetEntities_0100, Function | MediumTest | Level1) +{ + std::vector value; + value.push_back("string1"); + operationbuilder_->WithEntities(value); + std::shared_ptr operation = operationbuilder_->build(); + + std::vector revValue = operation->GetEntities(); + + if (value.size() > 0 && revValue.size() > 0) { + EXPECT_STREQ(value.at(0).c_str(), operation->GetEntities().at(0).c_str()); + } else { + EXPECT_EQ(true, revValue.size() > 0); + } +} + +/** + * @tc.number: AaFwk_Operation_GetEntities_0200 + * @tc.name: WithEntities/GetEntities + * @tc.desc: Verify the function when the input string is empty. + */ +HWTEST_F(OperationBaseTest, AaFwk_Operation_GetEntities_0200, Function | MediumTest | Level3) +{ + std::vector value; + operationbuilder_->WithEntities(value); + std::shared_ptr operation = operationbuilder_->build(); + EXPECT_EQ(true, operation->GetEntities().size() == 0); +} + +/** + * @tc.number: AaFwk_Operation_GetFlags_0100 + * @tc.name: WithFlags/GetFlags + * @tc.desc: Verify the function when the input string contains special characters. + */ +HWTEST_F(OperationBaseTest, AaFwk_Operation_GetFlags_0100, Function | MediumTest | Level1) +{ + unsigned int value = 1; + operationbuilder_->WithFlags(value); + std::shared_ptr operation = operationbuilder_->build(); + EXPECT_EQ(value, operation->GetFlags()); +} + +/** + * @tc.number: AaFwk_Operation_GetFlags_0200 + * @tc.name: WithFlags/GetFlags + * @tc.desc: Verify the function when the input string is empty. + */ +HWTEST_F(OperationBaseTest, AaFwk_Operation_GetFlags_0200, Function | MediumTest | Level3) +{ + unsigned int value = 0; + operationbuilder_->WithFlags(value); + std::shared_ptr operation = operationbuilder_->build(); + EXPECT_EQ(value, operation->GetFlags()); +} + +/** + * @tc.number: AaFwk_Operation_GetUri_0100 + * @tc.name: WithUri/GetUri + * @tc.desc: Verify the function when the input string contains special characters. + */ +HWTEST_F(OperationBaseTest, AaFwk_Operation_GetUri_0100, Function | MediumTest | Level1) +{ + std::string value = "scheme://authority/path1/path2/path3?id = 1&name = mingming&old#fragment"; + OHOS::Uri uri(value); + operationbuilder_->WithUri(uri); + std::shared_ptr operation = operationbuilder_->build(); + + EXPECT_EQ(uri, operation->GetUri()); +} + +/** + * @tc.number: AaFwk_Operation_GetUri_0200 + * @tc.name: WithUri/GetUri + * @tc.desc: Verify the function when the input string is empty. + */ +HWTEST_F(OperationBaseTest, AaFwk_Operation_GetUri_0200, Function | MediumTest | Level3) +{ + std::string value = ""; + OHOS::Uri uri(value); + operationbuilder_->WithUri(uri); + std::shared_ptr operation = operationbuilder_->build(); + EXPECT_EQ(uri, operation->GetUri()); +} + +/** + * @tc.number: AaFwk_Operation_build_0100 + * @tc.name: build + * @tc.desc: Verify that the parameters are correct. + */ +HWTEST_F(OperationBaseTest, AaFwk_Operation_build_0100, Function | MediumTest | Level1) +{ + std::string value = "value"; + OHOS::Uri uri(value); + std::vector columns; + columns.push_back("string1"); + operationbuilder_->WithUri(uri); + operationbuilder_->WithAction(value); + operationbuilder_->WithEntities(columns); + operationbuilder_->WithDeviceId(value); + operationbuilder_->WithBundleName(value); + operationbuilder_->WithAbilityName(value); + + std::shared_ptr operation = operationbuilder_->build(); + + EXPECT_EQ(uri, operation->GetUri()); + EXPECT_STREQ(value.c_str(), operation->GetAction().c_str()); + + std::vector revValue = operation->GetEntities(); + + if (columns.size() > 0 && revValue.size() > 0) { + EXPECT_STREQ(columns.at(0).c_str(), operation->GetEntities().at(0).c_str()); + } else { + EXPECT_EQ(true, revValue.size() > 0); + } + EXPECT_STREQ(value.c_str(), operation->GetDeviceId().c_str()); + EXPECT_STREQ(value.c_str(), operation->GetBundleName().c_str()); + EXPECT_STREQ(value.c_str(), operation->GetAbilityName().c_str()); +} + +/** + * @tc.number: AaFwk_Operation_Marshalling_0100 + * @tc.name: Marshalling/Unmarshalling + * @tc.desc: Validation serialization. + */ +HWTEST_F(OperationBaseTest, AaFwk_Operation_Marshalling_0100, Function | MediumTest | Level1) +{ + std::string value = "value"; + OHOS::Uri uri(value); + std::vector columns; + columns.push_back("string1"); + operationbuilder_->WithUri(uri); + operationbuilder_->WithAction(value); + operationbuilder_->WithEntities(columns); + operationbuilder_->WithDeviceId(value); + operationbuilder_->WithBundleName(value); + operationbuilder_->WithAbilityName(value); + + std::shared_ptr operation = operationbuilder_->build(); + Parcel in; + operation->Marshalling(in); + + Operation *pOperation = operation->Unmarshalling(in); + if (pOperation != nullptr) { + EXPECT_EQ(true, *pOperation == *(operation.get())); + } else { + EXPECT_EQ(true, pOperation != nullptr); + } +} + +/** + * @tc.number: AaFwk_Operation_Operator_0100 + * @tc.name: Operator + * @tc.desc: Verify string overload. + */ +HWTEST_F(OperationBaseTest, AaFwk_Operation_Operator_0100, Function | MediumTest | Level1) +{ + Operation operation_; + std::string value = "value"; + OHOS::Uri uri(value); + std::vector columns; + columns.push_back("string1"); + operationbuilder_->WithUri(uri); + operationbuilder_->WithAction(value); + operationbuilder_->WithEntities(columns); + operationbuilder_->WithDeviceId(value); + operationbuilder_->WithBundleName(value); + operationbuilder_->WithAbilityName(value); + + std::shared_ptr operation = operationbuilder_->build(); + operation_ = *(operation.get()); + + EXPECT_EQ(true, operation_ == *(operation.get())); +} diff --git a/tools/frameworks/kits/content/cpp/test/unittest/common/patterns_matcher_test.cpp b/tools/frameworks/kits/content/cpp/test/unittest/common/patterns_matcher_test.cpp new file mode 100755 index 00000000000..5bc1ad5a108 --- /dev/null +++ b/tools/frameworks/kits/content/cpp/test/unittest/common/patterns_matcher_test.cpp @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "ohos/aafwk/content/patterns_matcher.h" + +using namespace testing::ext; +using namespace OHOS::AAFwk; +using OHOS::Parcel; + +namespace OHOS { +namespace AAFwk { +class PatternsMatcherBaseTest : public testing::Test { +public: + PatternsMatcherBaseTest() + {} + ~PatternsMatcherBaseTest() + {} + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + std::shared_ptr PatternsMatcherIn_ = nullptr; + std::shared_ptr PatternsMatcherOut_ = nullptr; +}; + +void PatternsMatcherBaseTest::SetUpTestCase(void) +{} + +void PatternsMatcherBaseTest::TearDownTestCase(void) +{} + +void PatternsMatcherBaseTest::SetUp(void) +{ + PatternsMatcherIn_ = std::make_shared(); + PatternsMatcherOut_ = std::make_shared(); +} + +void PatternsMatcherBaseTest::TearDown(void) +{} + +/** + * @tc.number: AaFwk_PatternsMatcher_Parcelable_0100 + * @tc.name: Marshalling/Unmarshalling + * @tc.desc: marshalling PatternMatcher, and then check result. + */ +HWTEST_F(PatternsMatcherBaseTest, AaFwk_PatternsMatcher_Parcelable_0100, Function | MediumTest | Level1) +{ + PatternsMatcherIn_ = std::make_shared("1234", MatchType::DEFAULT); + if (PatternsMatcherIn_ != nullptr) { + Parcel in; + PatternsMatcherIn_->Marshalling(in); + std::shared_ptr PatternsMatcherOut_(PatternsMatcher::Unmarshalling(in)); + if (PatternsMatcherOut_ != nullptr) { + EXPECT_EQ(PatternsMatcherIn_->GetPattern(), (PatternsMatcherOut_->GetPattern())); + EXPECT_EQ(PatternsMatcherIn_->GetType(), (PatternsMatcherOut_->GetType())); + } + } +} + +/** + * @tc.number: AaFwk_PatternsMatcher_Parcelable_0200 + * @tc.name: Marshalling/Unmarshalling + * @tc.desc: marshalling PatternMatcher, and then check result. + */ +HWTEST_F(PatternsMatcherBaseTest, AaFwk_PatternsMatcher_Parcelable_0200, Function | MediumTest | Level1) +{ + PatternsMatcherIn_ = std::make_shared("@#¥#3243adsafdf_中文", MatchType::PREFIX); + if (PatternsMatcherIn_ != nullptr) { + Parcel in; + PatternsMatcherIn_->Marshalling(in); + std::shared_ptr PatternsMatcherOut_(PatternsMatcher::Unmarshalling(in)); + if (PatternsMatcherOut_ != nullptr) { + EXPECT_EQ(PatternsMatcherIn_->GetPattern(), (PatternsMatcherOut_->GetPattern())); + EXPECT_EQ(PatternsMatcherIn_->GetType(), (PatternsMatcherOut_->GetType())); + } + } +} + +/** + * @tc.number: AaFwk_PatternsMatcher_Parcelable_0300 + * @tc.name: Marshalling/Unmarshalling + * @tc.desc: marshalling PatternMatcher, and then check result. + */ +HWTEST_F(PatternsMatcherBaseTest, AaFwk_PatternsMatcher_Parcelable_0300, Function | MediumTest | Level1) +{ + PatternsMatcherIn_ = std::make_shared("", MatchType::GLOBAL); + if (PatternsMatcherIn_ != nullptr) { + Parcel in; + PatternsMatcherIn_->Marshalling(in); + std::shared_ptr PatternsMatcherOut_(PatternsMatcher::Unmarshalling(in)); + if (PatternsMatcherOut_ != nullptr) { + EXPECT_EQ(PatternsMatcherIn_->GetPattern(), (PatternsMatcherOut_->GetPattern())); + EXPECT_EQ(PatternsMatcherIn_->GetType(), (PatternsMatcherOut_->GetType())); + } + } +} + +/** + * @tc.number: AaFwk_PatternsMatcher_Match_0100 + * @tc.name: Match + * @tc.desc: Match this PatternsMatcher against an Pattern's data, and then check result. + */ +HWTEST_F(PatternsMatcherBaseTest, AaFwk_PatternsMatcher_Match_0100, Function | MediumTest | Level1) +{ + PatternsMatcherIn_ = std::make_shared("abcdefg", MatchType::DEFAULT); + if (PatternsMatcherIn_ != nullptr) { + EXPECT_EQ(PatternsMatcherIn_->match("abcdefg"), true); + EXPECT_EQ(PatternsMatcherIn_->match("Abcdefg"), false); + } +} + +/** + * @tc.number: AaFwk_PatternsMatcher_Match_0200 + * @tc.name: Match + * @tc.desc: Match this PatternsMatcher against an Pattern's data, and then check result. + */ +HWTEST_F(PatternsMatcherBaseTest, AaFwk_PatternsMatcher_Match_0200, Function | MediumTest | Level1) +{ + PatternsMatcherIn_ = std::make_shared("abcdefg", MatchType::PREFIX); + if (PatternsMatcherIn_ != nullptr) { + EXPECT_EQ(PatternsMatcherIn_->match("abcdefgABCDEFG"), true); + EXPECT_EQ(PatternsMatcherIn_->match("AbcdefgABCDEFG"), false); + } +} + +/** + * @tc.number: AaFwk_PatternsMatcher_Match_0300 + * @tc.name: Match + * @tc.desc: Match this PatternsMatcher against an Pattern's data, and then check result. + */ +HWTEST_F(PatternsMatcherBaseTest, AaFwk_PatternsMatcher_Match_0300, Function | MediumTest | Level1) +{ + PatternsMatcherIn_ = std::make_shared("abc*defg.", MatchType::PATTERN); + if (PatternsMatcherIn_ != nullptr) { + EXPECT_EQ(PatternsMatcherIn_->match("abcdefgG"), true); + EXPECT_EQ(PatternsMatcherIn_->match("abcccccdefgG"), true); + EXPECT_EQ(PatternsMatcherIn_->match("abcdefg"), false); + EXPECT_EQ(PatternsMatcherIn_->match("ABCDEFG"), false); + } +} + +/** + * @tc.number: AaFwk_PatternsMatcher_Match_0400 + * @tc.name: Match + * @tc.desc: Match this PatternsMatcher against an Pattern's data, and then check result. + */ +HWTEST_F(PatternsMatcherBaseTest, AaFwk_PatternsMatcher_Match_0400, Function | MediumTest | Level1) +{ + PatternsMatcherIn_ = std::make_shared("abc*ABC*123", MatchType::GLOBAL); + if (PatternsMatcherIn_ != nullptr) { + EXPECT_EQ(PatternsMatcherIn_->match("abcABC123"), true); + EXPECT_EQ(PatternsMatcherIn_->match("abcdefgABCDEFG123"), true); + EXPECT_EQ(PatternsMatcherIn_->match("000abcdefg000ABCDEFG000123"), true); + EXPECT_EQ(PatternsMatcherIn_->match("aBc123"), false); + EXPECT_EQ(PatternsMatcherIn_->match("AbC123"), false); + EXPECT_EQ(PatternsMatcherIn_->match("abcABC12345"), false); + } +} +} // namespace AAFwk +} // namespace OHOS diff --git a/tools/frameworks/kits/content/cpp/test/unittest/common/skills_test.cpp b/tools/frameworks/kits/content/cpp/test/unittest/common/skills_test.cpp new file mode 100755 index 00000000000..eaa0ba86be1 --- /dev/null +++ b/tools/frameworks/kits/content/cpp/test/unittest/common/skills_test.cpp @@ -0,0 +1,906 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "ohos/aafwk/content/skills.h" +#include "ohos/aafwk/base/string_wrapper.h" +#include "ohos/aafwk/base/bool_wrapper.h" +#include "ohos/aafwk/base/int_wrapper.h" +#include "ohos/aafwk/base/long_wrapper.h" +#include "utils/native/base/include/refbase.h" + +using namespace testing::ext; +using namespace OHOS::AAFwk; +using OHOS::Parcel; + +namespace OHOS { +namespace AAFwk { +static const int LARGE_STR_LEN = 65534; +static const int SET_COUNT = 20; +class SkillsBaseTest : public testing::Test { +public: + SkillsBaseTest() + {} + ~SkillsBaseTest() + {} + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + + std::shared_ptr base_ = nullptr; + void CompareSkills(const std::shared_ptr &skills1, const std::shared_ptr &skills2) const; +}; + +void SkillsBaseTest::SetUpTestCase(void) +{} + +void SkillsBaseTest::TearDownTestCase(void) +{} + +void SkillsBaseTest::SetUp(void) +{ + base_ = std::make_shared(); +} + +void SkillsBaseTest::TearDown(void) +{} + +/** + * @tc.number: AaFwk_Skills_Parcelable_0100 + * @tc.name: Marshalling/Unmarshalling + * @tc.desc: marshalling Skills, and then check result. + */ +HWTEST_F(SkillsBaseTest, AaFwk_Skills_Parcelable_0100, Function | MediumTest | Level1) +{ + std::shared_ptr SkillsIn_ = std::make_shared(); + if (SkillsIn_ == nullptr) { + return; + } + SkillsIn_->AddEntity("12345"); + SkillsIn_->AddAction("12345"); + SkillsIn_->AddAuthority("12345"); + SkillsIn_->AddScheme("12345"); + SkillsIn_->AddPath("12345"); + SkillsIn_->AddSchemeSpecificPart("12345"); + SkillsIn_->AddType("12345"); + WantParams wantParams; + std::string keyStr = "12345667"; + bool valueBool = true; + wantParams.SetParam(keyStr, Boolean::Box(valueBool)); + SkillsIn_->SetWantParams(wantParams); + + Parcel in; + std::shared_ptr SkillsOut_(Skills::Unmarshalling(in)); + SkillsIn_->Marshalling(in); + if (SkillsOut_ != nullptr) { + CompareSkills(SkillsIn_, SkillsOut_); + EXPECT_EQ(valueBool, Boolean::Unbox(IBoolean::Query(SkillsOut_->GetWantParams().GetParam(keyStr)))); + } +} + +/** + * @tc.number: AaFwk_Skills_Parcelable_0200 + * @tc.name: Marshalling/Unmarshalling + * @tc.desc: marshalling Skills, and then check result. + */ +HWTEST_F(SkillsBaseTest, AaFwk_Skills_Parcelable_0200, Function | MediumTest | Level1) +{ + std::shared_ptr SkillsIn_ = std::make_shared(); + if (SkillsIn_ == nullptr) { + return; + } + + SkillsIn_->AddEntity("@#¥#3243adsafdf_中文"); + SkillsIn_->AddAction("@#¥#3243adsafdf_中文"); + SkillsIn_->AddAuthority("@#¥#3243adsafdf_中文"); + SkillsIn_->AddScheme("@#¥#3243adsafdf_中文"); + SkillsIn_->AddPath("@#¥#3243adsafdf_中文"); + SkillsIn_->AddSchemeSpecificPart("@#¥#3243adsafdf_中文"); + SkillsIn_->AddType("@#¥#3243adsafdf_中文"); + WantParams wantParams; + std::string keyStr = "@#¥#3243adsafdf_中文"; + long valueLong = 12345L; + wantParams.SetParam(keyStr, Long::Box(valueLong)); + EXPECT_EQ(valueLong, Long::Unbox(ILong::Query(wantParams.GetParam(keyStr)))); + + SkillsIn_->SetWantParams(wantParams); + + Parcel in; + SkillsIn_->Marshalling(in); + std::shared_ptr SkillsOut_(Skills::Unmarshalling(in)); + + if (SkillsOut_ != nullptr) { + CompareSkills(SkillsIn_, SkillsOut_); + EXPECT_EQ(valueLong, Long::Unbox(ILong::Query(SkillsOut_->GetWantParams().GetParam(keyStr)))); + } +} + +/** + * @tc.number: AaFwk_Skills_Parcelable_0300 + * @tc.name: Marshalling/Unmarshalling + * @tc.desc: marshalling Skills, and then check result. + */ +HWTEST_F(SkillsBaseTest, AaFwk_Skills_Parcelable_0300, Function | MediumTest | Level1) +{ + std::shared_ptr SkillsIn_ = std::make_shared(); + if (SkillsIn_ == nullptr) { + return; + } + + SkillsIn_->AddEntity(""); + SkillsIn_->AddAction(""); + SkillsIn_->AddAuthority(""); + SkillsIn_->AddScheme(""); + SkillsIn_->AddPath(""); + SkillsIn_->AddSchemeSpecificPart(""); + SkillsIn_->AddType(""); + WantParams wantParams; + std::string keyStr = ""; + int valueInt = 123; + wantParams.SetParam(keyStr, Integer::Box(valueInt)); + + SkillsIn_->SetWantParams(wantParams); + EXPECT_EQ(valueInt, Integer::Unbox(IInteger::Query(wantParams.GetParam(keyStr)))); + + Parcel in; + SkillsIn_->Marshalling(in); + std::shared_ptr SkillsOut_(Skills::Unmarshalling(in)); + + if (SkillsOut_ != nullptr) { + CompareSkills(SkillsIn_, SkillsOut_); + EXPECT_EQ(valueInt, Integer::Unbox(IInteger::Query(SkillsOut_->GetWantParams().GetParam(keyStr)))); + } +} + +/** + * @tc.number: AaFwk_Skills_Parcelable_0400 + * @tc.name: Marshalling/Unmarshalling + * @tc.desc: marshalling Skills, and then check result. + */ +HWTEST_F(SkillsBaseTest, AaFwk_Skills_Parcelable_0400, Function | MediumTest | Level1) +{ + std::shared_ptr SkillsIn_ = std::make_shared(); + if (SkillsIn_ == nullptr) { + return; + } + SkillsIn_->AddEntity("12345"); + SkillsIn_->AddAction("12345"); + SkillsIn_->AddAuthority("12345"); + SkillsIn_->AddScheme("12345"); + SkillsIn_->AddPath("12345"); + SkillsIn_->AddSchemeSpecificPart("12345"); + SkillsIn_->AddType("12345"); + SkillsIn_->AddEntity("@#¥#3243adsafdf_中文"); + SkillsIn_->AddAction("@#¥#3243adsafdf_中文"); + SkillsIn_->AddAuthority("@#¥#3243adsafdf_中文"); + SkillsIn_->AddScheme("@#¥#3243adsafdf_中文"); + SkillsIn_->AddPath("@#¥#3243adsafdf_中文"); + SkillsIn_->AddSchemeSpecificPart("@#¥#3243adsafdf_中文"); + SkillsIn_->AddType("@#¥#3243adsafdf_中文"); + SkillsIn_->AddEntity(""); + SkillsIn_->AddAction(""); + SkillsIn_->AddAuthority(""); + SkillsIn_->AddScheme(""); + SkillsIn_->AddPath(""); + SkillsIn_->AddSchemeSpecificPart(""); + SkillsIn_->AddType(""); + WantParams wantParams; + std::string keyStr = "12345667"; + std::string valueString = "123"; + wantParams.SetParam(keyStr, String::Box(valueString)); + SkillsIn_->SetWantParams(wantParams); + + Parcel in; + SkillsIn_->Marshalling(in); + std::shared_ptr SkillsOut_(Skills::Unmarshalling(in)); + + if (SkillsOut_ != nullptr) { + CompareSkills(SkillsIn_, SkillsOut_); + EXPECT_EQ(valueString, String::Unbox(IString::Query(SkillsOut_->GetWantParams().GetParam(keyStr)))); + } +} + +void SkillsBaseTest::CompareSkills(const std::shared_ptr &skills1, const std::shared_ptr &skills2) const +{ + EXPECT_EQ(skills1->CountEntities(), skills2->CountEntities()); + EXPECT_EQ(skills1->CountActions(), skills2->CountActions()); + EXPECT_EQ(skills1->CountAuthorities(), skills2->CountAuthorities()); + EXPECT_EQ(skills1->CountSchemes(), skills2->CountSchemes()); + EXPECT_EQ(skills1->CountPaths(), skills2->CountPaths()); + EXPECT_EQ(skills1->CountSchemeSpecificParts(), skills2->CountSchemeSpecificParts()); + EXPECT_EQ(skills1->CountTypes(), skills2->CountTypes()); + + int count = skills1->CountEntities(); + for (int i = 0; i < count; i++) { + EXPECT_EQ(skills1->GetEntity(i), skills1->GetEntity(i)); + } + count = skills1->CountActions(); + for (int i = 0; i < count; i++) { + EXPECT_EQ(skills1->GetAction(i), skills1->GetAction(i)); + } + count = skills1->CountAuthorities(); + for (int i = 0; i < count; i++) { + EXPECT_EQ(skills1->GetAuthority(i), skills1->GetAuthority(i)); + } + count = skills1->CountSchemes(); + for (int i = 0; i < count; i++) { + EXPECT_EQ(skills1->GetScheme(i), skills1->GetScheme(i)); + } + count = skills1->CountPaths(); + for (int i = 0; i < count; i++) { + EXPECT_EQ(skills1->GetPath(i), skills1->GetPath(i)); + } + count = skills1->CountSchemeSpecificParts(); + for (int i = 0; i < count; i++) { + EXPECT_EQ(skills1->GetSchemeSpecificPart(i), skills1->GetSchemeSpecificPart(i)); + } + count = skills1->CountTypes(); + for (int i = 0; i < count; i++) { + EXPECT_EQ(skills1->GetType(i), skills1->GetType(i)); + } + + std::set key1; + std::set key2; + key1 = skills1->GetWantParams().KeySet(); + key2 = skills2->GetWantParams().KeySet(); + EXPECT_EQ(key1.size(), key2.size()); + + if (key1.size() > 0 && key2.size() > 0) { + std::set::iterator iter1 = key1.begin(); + std::set::iterator iter2 = key2.begin(); + for (; (iter1 != key1.end() && iter2 != key2.end()); iter1++, iter2++) { + EXPECT_EQ(*iter1, *iter2); + } + } +} + +/** + * @tc.number: AaFwk_Skills_Entities_0100 + * @tc.name: CountEntitie/HasEntity/GetEntity + * @tc.desc: Verify the function when the input string contains special characters. + */ +HWTEST_F(SkillsBaseTest, AaFwk_Skills_Entities_0100, Function | MediumTest | Level1) +{ + std::string empty; + std::string entities = "entities.system.test"; + EXPECT_EQ(0, base_->CountEntities()); + EXPECT_EQ(false, base_->HasEntity(entities)); + EXPECT_EQ(empty, base_->GetEntity(0)); + + base_->RemoveEntity(entities); + EXPECT_EQ(0, base_->CountEntities()); + EXPECT_EQ(false, base_->HasEntity(entities)); +} +/** + * @tc.number: AaFwk_Skills_GetEntities_0100 + * @tc.name: AddEntity and GetEntities + * @tc.desc: Verify AddEntity and GetEntities. + */ +HWTEST_F(SkillsBaseTest, AaFwk_Skills_GetEntities_0100, Function | MediumTest | Level1) +{ + + std::string entity = "12345667"; + base_->AddEntity(entity); + + size_t length = base_->GetEntities().size(); + + EXPECT_EQ((size_t)1, length); + EXPECT_EQ(entity, base_->GetEntities().at(0)); +} + +/** + * @tc.number: AaFwk_Skills_Authorities_0100 + * @tc.name: CountEntitie/HasEntity/GetEntity + * @tc.desc: Verify the function when the input string has a long size. + */ +HWTEST_F(SkillsBaseTest, AaFwk_Skills_Authorities_0100, Function | MediumTest | Level1) +{ + std::string empty; + std::string authorities = "authorities.system.test"; + EXPECT_EQ(0, base_->CountAuthorities()); + EXPECT_EQ(false, base_->HasAuthority(authorities)); + EXPECT_EQ(empty, base_->GetAuthority(0)); + + base_->RemoveAuthority(authorities); + EXPECT_EQ(0, base_->CountAuthorities()); + EXPECT_EQ(false, base_->HasAuthority(authorities)); +} + +/** + * @tc.number: AaFwk_Skills_Path_0300 + * @tc.name: CountPaths/HasPath/GetPath + * @tc.desc: Verify the function when the input string is overrided. + */ +HWTEST_F(SkillsBaseTest, AaFwk_Skills_Path_0300, Function | MediumTest | Level1) +{ + std::string empty; + std::string path = "paths.system.test"; + PatternsMatcher pm(path, MatchType::DEFAULT); + base_->AddPath(pm); + + EXPECT_EQ(1, base_->CountPaths()); + EXPECT_EQ(true, base_->HasPath(path)); + EXPECT_EQ(path, base_->GetPath(0)); + + base_->RemovePath(pm); + EXPECT_EQ(0, base_->CountPaths()); + EXPECT_EQ(false, base_->HasPath(path)); +} + +/** + * @tc.number: AaFwk_Skills_Action_0100 + * @tc.name: AddAction/CountActions/HasAction/GetAction + * @tc.desc: Verify the function when the input string is set 20 times. + */ +HWTEST_F(SkillsBaseTest, AaFwk_Skills_Action_0100, Function | MediumTest | Level1) +{ + std::string empty; + std::string action = "action.system.test"; + int actionCount = 1; + + for (int i = 0; i < SET_COUNT; i++) { + base_->AddAction(action); + } + + EXPECT_EQ(actionCount, base_->CountActions()); + EXPECT_EQ(true, base_->HasAction(action)); + EXPECT_EQ(action, base_->GetAction(0)); + + base_->RemoveAction(action); + EXPECT_EQ(0, base_->CountActions()); + EXPECT_EQ(false, base_->HasAction(action)); +} + +/** + * @tc.number: AaFwk_Skills_Entity_0100 + * @tc.name: CountEntities/HasEntity/CountEntities/GetEntity + * @tc.desc: Verify the function when the input string is default. + */ +HWTEST_F(SkillsBaseTest, AaFwk_Skills_Entity_0100, Function | MediumTest | Level1) +{ + std::string empty; + std::string entity = "entity.system.test"; + int entityCount = 1; + + for (int i = 0; i < SET_COUNT; i++) { + base_->AddEntity(entity); + } + + EXPECT_EQ(entityCount, base_->CountEntities()); + EXPECT_EQ(true, base_->HasEntity(entity)); + EXPECT_EQ(entity, base_->GetEntity(0)); + + base_->RemoveEntity(entity); + EXPECT_EQ(0, base_->CountEntities()); + EXPECT_EQ(false, base_->HasEntity(entity)); +} + +/** + * @tc.number: AaFwk_Skills_Authority_0100 + * @tc.name: CountAuthorities/HasAuthority/GetAuthority + * @tc.desc: Verify the function when the input string contains special characters. + */ +HWTEST_F(SkillsBaseTest, AaFwk_Skills_Authority_0100, Function | MediumTest | Level1) +{ + std::string empty; + std::string authority = "Authority.system.test"; + int authorityCount = 1; + + for (int i = 0; i < SET_COUNT; i++) { + base_->AddAuthority(authority); + } + + EXPECT_EQ(authorityCount, base_->CountAuthorities()); + EXPECT_EQ(true, base_->HasAuthority(authority)); + EXPECT_EQ(authority, base_->GetAuthority(0)); + + base_->RemoveAuthority(authority); + EXPECT_EQ(0, base_->CountAuthorities()); + EXPECT_EQ(false, base_->HasAuthority(authority)); +} + +/** + * @tc.number: AaFwk_Skills_Path_0100 + * @tc.name: CountPaths/HasPath/GetPath + * @tc.desc: Verify the function when the input string contains special characters. + */ +HWTEST_F(SkillsBaseTest, AaFwk_Skills_Path_0100, Function | MediumTest | Level1) +{ + std::string empty; + std::string path = "Path.system.test"; + int pathCount = 1; + + for (int i = 0; i < SET_COUNT; i++) { + base_->AddPath(path); + } + + EXPECT_EQ(pathCount, base_->CountPaths()); + EXPECT_EQ(true, base_->HasPath(path)); + EXPECT_EQ(path, base_->GetPath(0)); + + base_->RemovePath(path); + EXPECT_EQ(0, base_->CountPaths()); + EXPECT_EQ(false, base_->HasPath(path)); +} + +/** + * @tc.number: AaFwk_Skills_Scheme_0100 + * @tc.name: CountSchemes/HasScheme/GetScheme + * @tc.desc: Verify the function when the input string contains special characters. + */ +HWTEST_F(SkillsBaseTest, AaFwk_Skills_Scheme_0100, Function | MediumTest | Level1) +{ + std::string empty; + std::string scheme = "scheme.system.test"; + int schemeCount = 1; + + for (int i = 0; i < SET_COUNT; i++) { + base_->AddScheme(scheme); + } + + EXPECT_EQ(schemeCount, base_->CountSchemes()); + EXPECT_EQ(true, base_->HasScheme(scheme)); + EXPECT_EQ(scheme, base_->GetScheme(0)); + + base_->RemoveScheme(scheme); + EXPECT_EQ(0, base_->CountSchemes()); + EXPECT_EQ(false, base_->HasScheme(scheme)); +} + +/** + * @tc.number: AaFwk_Skills_SchemeSpecificPart_0100 + * @tc.name: CountSchemeSpecificParts/HasSchemeSpecificPart/GetSchemeSpecificPart + * @tc.desc: Verify the function when the input string contains special characters. + */ +HWTEST_F(SkillsBaseTest, AaFwk_Skills_SchemeSpecificPart_0100, Function | MediumTest | Level1) +{ + std::string empty; + std::string schemespecificpart = "schemespecificpart.system.test"; + int schemespecificpartCount = 1; + + for (int i = 0; i < SET_COUNT; i++) { + base_->AddSchemeSpecificPart(schemespecificpart); + } + + EXPECT_EQ(schemespecificpartCount, base_->CountSchemeSpecificParts()); + EXPECT_EQ(true, base_->HasSchemeSpecificPart(schemespecificpart)); + EXPECT_EQ(schemespecificpart, base_->GetSchemeSpecificPart(0)); + + base_->RemoveSchemeSpecificPart(schemespecificpart); + EXPECT_EQ(0, base_->CountSchemeSpecificParts()); + EXPECT_EQ(false, base_->HasSchemeSpecificPart(schemespecificpart)); +} + +/** + * @tc.number: AaFwk_Skills_Type_0100 + * @tc.name: CountTypes/HasType/GetType + * @tc.desc: Verify the function when the input string contains special characters. + */ +HWTEST_F(SkillsBaseTest, AaFwk_Skills_Type_0100, Function | MediumTest | Level1) +{ + std::string empty; + std::string type = "type/system.test"; + int typeCount = 1; + + for (int i = 0; i < SET_COUNT; i++) { + base_->AddType(type); + } + + EXPECT_EQ(typeCount, base_->CountTypes()); + EXPECT_EQ(true, base_->HasType(type)); + EXPECT_EQ(type, base_->GetType(0)); + + base_->RemoveType(type); + EXPECT_EQ(0, base_->CountTypes()); + EXPECT_EQ(false, base_->HasType(type)); +} + +/** + * @tc.number: AaFwk_Skills_Actions_0100 + * @tc.name: CountActions/HasAuthority/GetAuthority + * @tc.desc: Verify the function when the input string contains special characters. + */ +HWTEST_F(SkillsBaseTest, AaFwk_Skills_Actions_0100, Function | MediumTest | Level1) +{ + std::string empty; + std::string actions = "actions.system.test"; + EXPECT_EQ(0, base_->CountActions()); + EXPECT_EQ(false, base_->HasAuthority(actions)); + EXPECT_EQ(empty, base_->GetAuthority(0)); + + base_->RemoveAuthority(actions); + EXPECT_EQ(0, base_->CountActions()); + EXPECT_EQ(false, base_->HasAuthority(actions)); +} + +/** + * @tc.number: AaFwk_Skills_Schemes_0100 + * @tc.name: CountSchemes/HasAuthority/GetAuthority + * @tc.desc: Verify the function when the input string contains special characters. + */ +HWTEST_F(SkillsBaseTest, AaFwk_Skills_Schemes_0100, Function | MediumTest | Level1) +{ + std::string empty; + std::string schemes = "schemes.system.test"; + EXPECT_EQ(0, base_->CountSchemes()); + EXPECT_EQ(false, base_->HasAuthority(schemes)); + EXPECT_EQ(empty, base_->GetAuthority(0)); + + base_->RemoveAuthority(schemes); + EXPECT_EQ(0, base_->CountSchemes()); + EXPECT_EQ(false, base_->HasAuthority(schemes)); +} + +/** + * @tc.number: AaFwk_Skills_SchemeSpecificParts_0100 + * @tc.name: CountSchemeSpecificParts/HasAuthority/GetAuthority + * @tc.desc: Verify the function when the input string contains special characters. + */ +HWTEST_F(SkillsBaseTest, AaFwk_Skills_SchemeSpecificParts_0100, Function | MediumTest | Level1) +{ + std::string empty; + std::string schemespecificparts = "schemespecificparts.system.test"; + EXPECT_EQ(0, base_->CountSchemeSpecificParts()); + EXPECT_EQ(false, base_->HasAuthority(schemespecificparts)); + EXPECT_EQ(empty, base_->GetAuthority(0)); + + base_->RemoveAuthority(schemespecificparts); + EXPECT_EQ(0, base_->CountSchemeSpecificParts()); + EXPECT_EQ(false, base_->HasAuthority(schemespecificparts)); +} + +/** + * @tc.number: AaFwk_Skills_Types_0100 + * @tc.name: CountTypes/HasAuthority/GetAuthority + * @tc.desc: Verify the function when the input string contains special characters. + */ +HWTEST_F(SkillsBaseTest, AaFwk_Skills_Types_0100, Function | MediumTest | Level1) +{ + std::string empty; + std::string types = "types.system.test"; + GTEST_LOG_(INFO) << "---------------a "; + EXPECT_EQ(0, base_->CountTypes()); + GTEST_LOG_(INFO) << "---------------b "; + EXPECT_EQ(false, base_->HasAuthority(types)); + GTEST_LOG_(INFO) << "---------------1 "; + EXPECT_EQ(empty, base_->GetAuthority(0)); + GTEST_LOG_(INFO) << "---------------2 "; + + base_->RemoveAuthority(types); + EXPECT_EQ(0, base_->CountTypes()); + EXPECT_EQ(false, base_->HasAuthority(types)); +} + +/** + * @tc.number: AaFwk_Skills_Action_0200 + * @tc.name: CountActions/HasAction/GetAction + * @tc.desc: Verify the function when action is not exist. + */ +HWTEST_F(SkillsBaseTest, AaFwk_Skills_Action_0200, Function | MediumTest | Level1) +{ + std::string empty; + std::string action = "action.system.test"; + EXPECT_EQ(0, base_->CountActions()); + EXPECT_EQ(false, base_->HasAction(action)); + EXPECT_EQ(empty, base_->GetAction(0)); + + base_->RemoveAction(action); + EXPECT_EQ(0, base_->CountActions()); + EXPECT_EQ(false, base_->HasAction(action)); +} + +/** + * @tc.number: AaFwk_Skills_Authority_0200 + * @tc.name: CountAuthorities/HasAuthority/GetAuthority + * @tc.desc: Verify the function when action is not exist. + */ +HWTEST_F(SkillsBaseTest, AaFwk_Skills_Authority_0200, Function | MediumTest | Level1) +{ + std::string empty; + std::string authority = "authority.system.test"; + EXPECT_EQ(0, base_->CountAuthorities()); + EXPECT_EQ(false, base_->HasAuthority(authority)); + EXPECT_EQ(empty, base_->GetAuthority(0)); + + base_->RemoveAuthority(authority); + EXPECT_EQ(0, base_->CountAuthorities()); + EXPECT_EQ(false, base_->HasAuthority(authority)); +} + +/** + * @tc.number: AaFwk_Skills_Path_0200 + * @tc.name: CountPaths/HasPath/GetPath + * @tc.desc: Verify the function when action is not exist. + */ +HWTEST_F(SkillsBaseTest, AaFwk_Skills_Path_0200, Function | MediumTest | Level1) +{ + std::string empty; + std::string path = "path.system.test"; + base_->AddPath(path, MatchType::DEFAULT); + + EXPECT_EQ(1, base_->CountPaths()); + EXPECT_EQ(true, base_->HasPath(path)); + EXPECT_EQ(path, base_->GetPath(0)); + + base_->RemovePath(path, MatchType::DEFAULT); + EXPECT_EQ(0, base_->CountPaths()); + EXPECT_EQ(false, base_->HasPath(path)); +} + +/** + * @tc.number: AaFwk_Skills_Scheme_0200 + * @tc.name: CountSchemes/HasScheme/GetScheme + * @tc.desc: Verify the function when action is not exist. + */ +HWTEST_F(SkillsBaseTest, AaFwk_Skills_Scheme_0200, Function | MediumTest | Level1) +{ + std::string empty; + std::string scheme = "scheme.system.test"; + EXPECT_EQ(0, base_->CountSchemes()); + EXPECT_EQ(false, base_->HasScheme(scheme)); + EXPECT_EQ(empty, base_->GetScheme(0)); + + base_->RemoveScheme(scheme); + EXPECT_EQ(0, base_->CountSchemes()); + EXPECT_EQ(false, base_->HasScheme(scheme)); +} + +/** + * @tc.number: AaFwk_Skills_SchemeSpecificPart_0200 + * @tc.name: CountSchemeSpecificParts/HasSchemeSpecificPart/GetSchemeSpecificPart + * @tc.desc: Verify the function when action is not exist. + */ +HWTEST_F(SkillsBaseTest, AaFwk_Skills_SchemeSpecificPart_0200, Function | MediumTest | Level1) +{ + std::string empty; + std::string schemespecificpart = "schemespecificpart.system.test"; + EXPECT_EQ(0, base_->CountSchemeSpecificParts()); + EXPECT_EQ(false, base_->HasSchemeSpecificPart(schemespecificpart)); + EXPECT_EQ(empty, base_->GetSchemeSpecificPart(0)); + + base_->RemoveSchemeSpecificPart(schemespecificpart); + EXPECT_EQ(0, base_->CountSchemeSpecificParts()); + EXPECT_EQ(false, base_->HasSchemeSpecificPart(schemespecificpart)); +} + +/** + * @tc.number: AaFwk_Skills_Type_0300 + * @tc.name: CountTypes/HasType/GetType + * @tc.desc: Verify the function when action is not exist. + */ +HWTEST_F(SkillsBaseTest, AaFwk_Skills_Type_0300, Function | MediumTest | Level1) +{ + std::string empty; + std::string type = "type.system.test"; + EXPECT_EQ(0, base_->CountTypes()); + + EXPECT_EQ(false, base_->HasType(type)); + EXPECT_EQ(empty, base_->GetType(0)); + + base_->RemoveType(type); + EXPECT_EQ(0, base_->CountTypes()); + EXPECT_EQ(false, base_->HasType(type)); +} + +using SkillsMatchType = std::tuple; +class SkillsMatchTest : public testing::TestWithParam { +public: + SkillsMatchTest() + {} + ~SkillsMatchTest() + {} + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + std::shared_ptr skills_ = nullptr; +}; + +void SkillsMatchTest::SetUpTestCase(void) +{} + +void SkillsMatchTest::TearDownTestCase(void) +{} + +void SkillsMatchTest::SetUp(void) +{ + skills_ = std::make_shared(); +} + +void SkillsMatchTest::TearDown(void) +{} + +/** + * @tc.number: AaFwk_Skills_match_0100 + * @tc.name: CountTypes/HasType/GetType + * @tc.desc: Verify whether parameter change. + */ +HWTEST_P(SkillsMatchTest, AaFwk_Skills_match_0100, Function | MediumTest | Level1) +{ + std::string filterEntity = "entity.system.entity1"; + std::string filterAction1 = "action.system.action1"; + std::string filterAction2 = "action.system.action2"; + std::string intentEntity = std::get<0>(GetParam()); + std::string intentAction = std::get<1>(GetParam()); + bool result = std::get<2>(GetParam()); + + skills_->AddEntity(filterEntity); + skills_->AddAction(filterAction1); + skills_->AddAction(filterAction2); + + Want want; + want.AddEntity(intentEntity); + want.SetAction(intentAction); + + EXPECT_EQ(result, skills_->Match(want)); +} + +INSTANTIATE_TEST_CASE_P(SkillsMatchTestP, SkillsMatchTest, + testing::Values(SkillsMatchType("entity.system.entityA", "action.system.actionA", false), + SkillsMatchType("entity.system.entity1", "action.system.actionA", false), + SkillsMatchType("entity.system.entityA", "action.system.action2", false), + SkillsMatchType("entity.system.entity1", "action.system.action1", true))); + +/** + * @tc.number: AaFwk_Skills_Skills_0100 + * @tc.name: Skills() and Skills(Skills) + * @tc.desc: Verify Skills(). + */ +HWTEST_F(SkillsBaseTest, AaFwk_Skills_Skills_0100, Function | MediumTest | Level1) +{ + Skills skills; + + EXPECT_EQ(0, skills.CountEntities()); + EXPECT_EQ(0, skills.CountActions()); + EXPECT_EQ(0, skills.CountAuthorities()); + EXPECT_EQ(0, skills.CountSchemes()); + + EXPECT_EQ(0, skills.CountPaths()); + EXPECT_EQ(0, skills.CountSchemeSpecificParts()); + EXPECT_EQ(0, skills.CountTypes()); + EXPECT_EQ(0, skills.GetWantParams().Size()); +} + +/** + * @tc.number: AaFwk_Skills_Skills_0200 + * @tc.name: Skills() and Skills(Skills) + * @tc.desc: Verify Skills(). + */ +HWTEST_F(SkillsBaseTest, AaFwk_Skills_Skills_0200, Function | MediumTest | Level1) +{ + Skills skillsBase; + std::string entityString = "entity"; + skillsBase.AddEntity(entityString); + std::string actionString = "action"; + skillsBase.AddAction(actionString); + std::string authorityString = "authority"; + skillsBase.AddAuthority(authorityString); + std::string schemeString = "scheme"; + skillsBase.AddScheme(schemeString); + std::string pathString = "path"; + skillsBase.AddPath(pathString); + std::string schemeSpecificPartsString = "schemeSpecificParts"; + skillsBase.AddSchemeSpecificPart(schemeSpecificPartsString); + std::string typeString = "/type"; + skillsBase.AddType(typeString); + Skills skills(skillsBase); + + EXPECT_EQ(entityString, skills.GetEntity(0)); + EXPECT_EQ(actionString, skills.GetAction(0)); + EXPECT_EQ(authorityString, skills.GetAuthority(0)); + EXPECT_EQ(schemeString, skills.GetScheme(0)); + + EXPECT_EQ(pathString, skills.GetPath(0)); + EXPECT_EQ(schemeSpecificPartsString, skills.GetSchemeSpecificPart(0)); + EXPECT_EQ(typeString, skills.GetType(0)); +} + +/** + * @tc.number: AaFwk_Skills_addremoveType_0100 + * @tc.name: addType(PatternsMatcher)/ removeType(PatternsMatcher) + * @tc.desc: Verify addType/removeType result. + */ +HWTEST_F(SkillsBaseTest, AaFwk_Skills_addremoveType_0100, Function | MediumTest | Level1) +{ + std::string patternStr = std::string("systems/*t"); + + PatternsMatcher pattern(patternStr, MatchType::DEFAULT); + + base_->AddType(pattern); + std::string type1 = base_->GetType(0); + EXPECT_EQ(patternStr, type1); + + base_->RemoveType(patternStr); + + EXPECT_EQ(0, base_->CountEntities()); + + base_->AddType(pattern); + + std::string patternStr2 = std::string("systems/*test"); + PatternsMatcher pattern2(patternStr2, MatchType::PREFIX); + base_->AddType(pattern2); + std::string type2 = base_->GetType(1); + EXPECT_EQ(patternStr2, type2); + + base_->RemoveType(pattern2); + EXPECT_EQ(0, base_->CountEntities()); + + std::string patternStr3 = std::string("systems/*test3"); + base_->AddType(patternStr3, MatchType::GLOBAL); + + std::string type3 = base_->GetType(1); + EXPECT_EQ(patternStr3, type3); + + base_->RemoveType(patternStr3, MatchType::GLOBAL); + + EXPECT_EQ(0, base_->CountEntities()); +} + +using testParamsType = std::tuple; +class SkillsParamsTest : public testing::TestWithParam { +public: + SkillsParamsTest() + {} + ~SkillsParamsTest() + {} + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + std::shared_ptr skills_ = nullptr; +}; + +void SkillsParamsTest::SetUpTestCase(void) +{} + +void SkillsParamsTest::TearDownTestCase(void) +{} + +void SkillsParamsTest::SetUp(void) +{ + skills_ = std::make_shared(); +} + +void SkillsParamsTest::TearDown(void) +{} + +/** + * @tc.number: AaFwk_Skills_Params_0100 + * @tc.name: SetWantParams/GetWantParams + * @tc.desc: Verify addType/removeType result. + */ +HWTEST_P(SkillsParamsTest, AaFwk_Skills_Params_0100, Function | MediumTest | Level1) +{ + std::string keyStr = std::get<0>(GetParam()); + std::string valueStr = std::get<1>(GetParam()); + WantParams wantParams; + wantParams.SetParam(keyStr, String::Box(valueStr)); + skills_->SetWantParams(wantParams); + EXPECT_EQ(valueStr, String::Unbox(IString::Query(skills_->GetWantParams().GetParam(keyStr)))); +} + +INSTANTIATE_TEST_CASE_P(SkillsParamsTestCaseP, SkillsParamsTest, + testing::Values(testParamsType("", "asdsdsdasa"), testParamsType(std::string(LARGE_STR_LEN + 1, 's'), "sadsdsdads"), + testParamsType("#$%^&*(!@\":<>{}", "asdsdsdasa"), testParamsType("3456677", ""), + testParamsType("1234", std::string(LARGE_STR_LEN + 1, 's')), + testParamsType("2323sdasdZ", "#$%^&*(!@\":<>{}sadsdasdsaf"), testParamsType("12345667", "sdasdfdsffdgfdg"), + testParamsType("", ""), + testParamsType(std::string(LARGE_STR_LEN + 1, 'k'), std::string(LARGE_STR_LEN + 1, 'k')), + testParamsType("#$%^&*(!@\":<>{},/", "#$%^&*(!@\":<>{},/"))); + +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/content/cpp/test/unittest/common/want_params_test.cpp b/tools/frameworks/kits/content/cpp/test/unittest/common/want_params_test.cpp new file mode 100644 index 00000000000..ce882da200d --- /dev/null +++ b/tools/frameworks/kits/content/cpp/test/unittest/common/want_params_test.cpp @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "ohos/aafwk/base/string_wrapper.h" +#include "ohos/aafwk/base/bool_wrapper.h" +#include "ohos/aafwk/base/int_wrapper.h" +#include "ohos/aafwk/base/long_wrapper.h" + +#include "ohos/aafwk/content/want_params.h" + +using namespace testing::ext; +using namespace OHOS::AAFwk; +using OHOS::Parcel; + +namespace OHOS { +namespace AAFwk { +class WantParamsBaseTest : public testing::Test { +public: + WantParamsBaseTest() + {} + ~WantParamsBaseTest() + { + } + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + + std::shared_ptr wantParamsIn_ = nullptr; + std::shared_ptr wantParamsOut_ = nullptr; +}; + +void WantParamsBaseTest::SetUpTestCase(void) +{} + +void WantParamsBaseTest::TearDownTestCase(void) +{} + +void WantParamsBaseTest::SetUp(void) +{ + wantParamsIn_ = std::make_shared(); + wantParamsOut_ = std::make_shared(); +} + +void WantParamsBaseTest::TearDown(void) +{ +} + +/** + * @tc.number: AaFwk_WantParams_Parcelable_0100 + * @tc.name: Marshalling/Unmarshalling + * @tc.desc: marshalling WantParams, and then check result. + */ +HWTEST_F(WantParamsBaseTest, AaFwk_WantParams_Parcelable_0100, Function | MediumTest | Level1) +{ + std::string keyStr = "12345667"; + std::string valueStr = "sdasdfdsffdgfdg"; + wantParamsIn_->SetParam(keyStr, String::Box(valueStr)); + + Parcel in; + if(wantParamsOut_ != nullptr){ + wantParamsIn_->Marshalling(in); + std::shared_ptr wantParamsOut_(WantParams::Unmarshalling(in)); + EXPECT_EQ(valueStr, String::Unbox(IString::Query(wantParamsOut_->GetParam(keyStr)))); + } +} + +/** + * @tc.number: AaFwk_WantParams_Parcelable_0200 + * @tc.name: Marshalling/Unmarshalling + * @tc.desc: marshalling WantParams, and then check result. + */ +HWTEST_F(WantParamsBaseTest, AaFwk_WantParams_Parcelable_0200, Function | MediumTest | Level1) +{ + std::string keyStr = "12345667"; + bool valueBool = true; + wantParamsIn_->SetParam(keyStr, Boolean::Box(valueBool)); + + Parcel in; + if(wantParamsOut_ != nullptr){ + wantParamsIn_->Marshalling(in); + std::shared_ptr wantParamsOut_(WantParams::Unmarshalling(in)); + EXPECT_EQ(valueBool, Boolean::Unbox(IBoolean::Query(wantParamsOut_->GetParam(keyStr)))); + } +} + +/** + * @tc.number: AaFwk_WantParams_Parcelable_0300 + * @tc.name: Marshalling/Unmarshalling + * @tc.desc: marshalling WantParams, and then check result. + */ +HWTEST_F(WantParamsBaseTest, AaFwk_WantParams_Parcelable_0300, Function | MediumTest | Level1) +{ + std::string keyStr = "12345667"; + int valueInteger = 12345; + wantParamsIn_->SetParam(keyStr, Integer::Box(valueInteger)); + int right = Integer::Unbox(IInteger::Query(wantParamsIn_->GetParam(keyStr))); + + Parcel in; + wantParamsIn_->Marshalling(in); + std::shared_ptr wantParamsOut_(WantParams::Unmarshalling(in)); + if (wantParamsOut_ != nullptr) { + right = Integer::Unbox(IInteger::Query(wantParamsOut_->GetParam(keyStr))); + EXPECT_EQ(valueInteger, right); + + wantParamsOut_ = nullptr; + } +} + +/** + * @tc.number: AaFwk_WantParams_Parcelable_0400 + * @tc.name: Marshalling/Unmarshalling + * @tc.desc: marshalling WantParams, and then check result. + */ +HWTEST_F(WantParamsBaseTest, AaFwk_WantParams_Parcelable_0400, Function | MediumTest | Level1) +{ + std::string keyStr = "12345667"; + long valueLong = 1234567; + wantParamsIn_->SetParam(keyStr, Long::Box(valueLong)); + + Parcel in; + wantParamsIn_->Marshalling(in); + std::shared_ptr wantParamsOut_(WantParams::Unmarshalling(in)); + EXPECT_EQ(valueLong, Long::Unbox(ILong::Query(wantParamsOut_->GetParam(keyStr)))); +} +} +} \ No newline at end of file diff --git a/tools/frameworks/kits/content/cpp/test/unittest/common/want_params_wrapper_test.cpp b/tools/frameworks/kits/content/cpp/test/unittest/common/want_params_wrapper_test.cpp new file mode 100755 index 00000000000..c64ec237f10 --- /dev/null +++ b/tools/frameworks/kits/content/cpp/test/unittest/common/want_params_wrapper_test.cpp @@ -0,0 +1,339 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#define private public +#include "ohos/aafwk/content/want_params_wrapper.h" +#undef protected +#include "ohos/aafwk/base/string_wrapper.h" + +using namespace testing::ext; +using namespace OHOS; +using namespace AAFwk; + +namespace { +const std::string STRING_WANT_PARAMS_KEY_01 = "key01"; +const std::string STRING_WANT_PARAMS_VALUE_01 = "value01"; +const std::string STRING_WANT_PARAMS_STRING_01 = "{\"key01\":{\"9\":\"value01\"}}"; + +const std::string STRING_WANT_PARAMS_KEY_02 = "key02"; +const std::string STRING_WANT_PARAMS_VALUE_02 = "value02"; +const std::string STRING_WANT_PARAMS_STRING_0201 = + "{\"key01\":{\"21\":{\"key02\":{\"9\":\"value02\"}}},\"key02\":{\"9\":\"value02\"}}"; +} // namespace + +class WantParamWrapperBaseTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp() override; + void TearDown() override; + + WantParams wantParams_; + std::shared_ptr wantParamWrapperPtr_; +}; + +void WantParamWrapperBaseTest::SetUpTestCase() +{} + +void WantParamWrapperBaseTest::TearDownTestCase(void) +{} + +void WantParamWrapperBaseTest::SetUp(void) +{ + wantParams_ = {}; + wantParams_.SetParam(STRING_WANT_PARAMS_KEY_01, String::Box(STRING_WANT_PARAMS_VALUE_01)); + wantParamWrapperPtr_ = std::make_shared(wantParams_); +} + +void WantParamWrapperBaseTest::TearDown(void) +{} + +/** + * @tc.number: Want_Param_Wrapper_0100 + * @tc.name: GetValue + * @tc.desc: Verify the "GetValue" function. + */ +HWTEST_F(WantParamWrapperBaseTest, Want_Param_Wrapper_0100, Function | MediumTest | Level1) +{ + WantParams wantParams; + ErrCode result = wantParamWrapperPtr_->GetValue(wantParams); + + EXPECT_EQ(result, ERR_OK); + + EXPECT_EQ(wantParams_ == wantParams, true); +} + +/** + * @tc.number: Want_Param_Wrapper_0200 + * @tc.name: GetValue + * @tc.desc: Verify the "GetValue" function. + */ +HWTEST_F(WantParamWrapperBaseTest, Want_Param_Wrapper_0200, Function | MediumTest | Level1) +{ + WantParams wantParams; + ErrCode result = wantParamWrapperPtr_->GetValue(wantParams); + + EXPECT_EQ(result, ERR_OK); + + // make another empty WantParams + WantParams wantParamsEmpty = {}; + + EXPECT_EQ(wantParams_ == wantParamsEmpty, false); +} + +/** + * @tc.number: Want_Param_Wrapper_0300 + * @tc.name: Equals + * @tc.desc: Verify the "Equals" function. + */ +HWTEST_F(WantParamWrapperBaseTest, Want_Param_Wrapper_0300, Function | MediumTest | Level1) +{ + WantParams wantParams; + wantParams.SetParam(STRING_WANT_PARAMS_KEY_01, String::Box(STRING_WANT_PARAMS_VALUE_01)); + WantParamWrapper wantParamWrapper(wantParams); + + bool result = wantParamWrapperPtr_->Equals(wantParamWrapper); + + EXPECT_EQ(result, true); +} + +/** + * @tc.number: Want_Param_Wrapper_0400 + * @tc.name: Equals + * @tc.desc: Verify the "Equals" function. + */ +HWTEST_F(WantParamWrapperBaseTest, Want_Param_Wrapper_0400, Function | MediumTest | Level1) +{ + WantParams wantParams; + WantParamWrapper wantParamWrapper(wantParams); + + bool result = wantParamWrapperPtr_->Equals(wantParamWrapper); + + EXPECT_EQ(result, false); +} + +/** + * @tc.number: Want_Param_Wrapper_0500 + * @tc.name: Box + * @tc.desc: Verify the "Box" function. + */ +HWTEST_F(WantParamWrapperBaseTest, Want_Param_Wrapper_0500, Function | MediumTest | Level1) +{ + auto wantParamsPtr = WantParamWrapper::Box(wantParams_); + + WantParams wantParams; + ErrCode result = wantParamsPtr->GetValue(wantParams); + + EXPECT_EQ(result, ERR_OK); + + EXPECT_EQ(wantParams_ == wantParams, true); +} + +/** + * @tc.number: Want_Param_Wrapper_0600 + * @tc.name: Box + * @tc.desc: Verify the "Box" function with am empty object. + */ +HWTEST_F(WantParamWrapperBaseTest, Want_Param_Wrapper_0600, Function | MediumTest | Level1) +{ + auto wantParamsPtr = WantParamWrapper::Box({}); + + EXPECT_NE(wantParamsPtr, nullptr); + + WantParams wantParams; + ErrCode result = wantParamsPtr->GetValue(wantParams); + + EXPECT_EQ(result, ERR_OK); + + // make another empty WantParams + WantParams wantParamsEmpty = {}; + + EXPECT_EQ(wantParams == wantParamsEmpty, true); +} + +/** + * @tc.number: Want_Param_Wrapper_0700 + * @tc.name: Unbox + * @tc.desc: Verify the "Unbox" function. + */ +HWTEST_F(WantParamWrapperBaseTest, Want_Param_Wrapper_0700, Function | MediumTest | Level1) +{ + auto wantParamsPtr = WantParamWrapper::Box(wantParams_); + + auto wantParams = WantParamWrapper::Unbox(wantParamsPtr); + + EXPECT_EQ(wantParams_ == wantParams, true); +} + +/** + * @tc.number: Want_Param_Wrapper_0800 + * @tc.name: Unbox + * @tc.desc: Verify the "Unbox" function with a nullptr + */ +HWTEST_F(WantParamWrapperBaseTest, Want_Param_Wrapper_0800, Function | MediumTest | Level1) +{ + auto wantParams = WantParamWrapper::Unbox(nullptr); + + // make another empty WantParams + WantParams wantParamsEmpty = {}; + + EXPECT_EQ(wantParams == wantParamsEmpty, true); +} + +/** + * @tc.number: Want_Param_Wrapper_0900 + * @tc.name: ValidateStr + * @tc.desc: Verify the "ValidateStr" function. + */ +HWTEST_F(WantParamWrapperBaseTest, Want_Param_Wrapper_0900, Function | MediumTest | Level1) +{ + bool result = WantParamWrapper::ValidateStr("{"); + + EXPECT_EQ(result, false); +} + +/** + * @tc.number: Want_Param_Wrapper_1000 + * @tc.name: ValidateStr + * @tc.desc: Verify the "ValidateStr" function. + */ +HWTEST_F(WantParamWrapperBaseTest, Want_Param_Wrapper_1000, Function | MediumTest | Level1) +{ + bool result = WantParamWrapper::ValidateStr("}"); + + EXPECT_EQ(result, false); +} + +/** + * @tc.number: Want_Param_Wrapper_1100 + * @tc.name: ValidateStr + * @tc.desc: Verify the "ValidateStr" function. + */ +HWTEST_F(WantParamWrapperBaseTest, Want_Param_Wrapper_1100, Function | MediumTest | Level1) +{ + bool result = WantParamWrapper::ValidateStr("}{"); + + EXPECT_EQ(result, false); +} + +/** + * @tc.number: Want_Param_Wrapper_1200 + * @tc.name: ValidateStr + * @tc.desc: Verify the "ValidateStr" function. + */ +HWTEST_F(WantParamWrapperBaseTest, Want_Param_Wrapper_1200, Function | MediumTest | Level1) +{ + bool result = WantParamWrapper::ValidateStr("{\"\"}"); + + EXPECT_EQ(result, false); +} + +/** + * @tc.number: Want_Param_Wrapper_1300 + * @tc.name: Parse + * @tc.desc: Verify the "Parse" function. + */ +HWTEST_F(WantParamWrapperBaseTest, Want_Param_Wrapper_1300, Function | MediumTest | Level1) +{ + auto wantParamsPtr = WantParamWrapper::Parse(""); + + auto wantParams = WantParamWrapper::Unbox(wantParamsPtr); + + // make another empty WantParams + WantParams wantParamsEmpty = {}; + + EXPECT_EQ(wantParams == wantParamsEmpty, true); +} + +/** + * @tc.number: Want_Param_Wrapper_1400 + * @tc.name: Parse + * @tc.desc: Verify the "Parse" function. + */ +HWTEST_F(WantParamWrapperBaseTest, Want_Param_Wrapper_1400, Function | MediumTest | Level1) +{ + auto wantParamsPtr = WantParamWrapper::Parse("{}"); + + auto wantParams = WantParamWrapper::Unbox(wantParamsPtr); + + // make another empty WantParams + WantParams wantParamsEmpty = {}; + + EXPECT_EQ(wantParams == wantParamsEmpty, true); +} + +/** + * @tc.number: Want_Param_Wrapper_1500 + * @tc.name: ToString + * @tc.desc: Verify the "ToString" function. + */ +HWTEST_F(WantParamWrapperBaseTest, Want_Param_Wrapper_1500, Function | MediumTest | Level1) +{ + auto wantParamsString = wantParamWrapperPtr_->ToString(); + + EXPECT_EQ(wantParamsString, STRING_WANT_PARAMS_STRING_01); +} + +/** + * @tc.number: Want_Param_Wrapper_1600 + * @tc.name: ToString + * @tc.desc: Verify the "ToString" function. + */ +HWTEST_F(WantParamWrapperBaseTest, Want_Param_Wrapper_1600, Function | MediumTest | Level1) +{ + WantParams wantParams = {}; + WantParamWrapper wantParamWrapper(wantParams); + + auto wantParamsString = wantParamWrapper.ToString(); + + EXPECT_EQ(wantParamsString, "{}"); +} + +/** + * @tc.number: Want_Param_Wrapper_1700 + * @tc.name: ToString + * @tc.desc: Verify the "ToString" function. + */ +HWTEST_F(WantParamWrapperBaseTest, Want_Param_Wrapper_1700, Function | MediumTest | Level1) +{ + WantParams wantParams = {}; + wantParams.SetParam(STRING_WANT_PARAMS_KEY_02, String::Box(STRING_WANT_PARAMS_VALUE_02)); + wantParams.SetParam(STRING_WANT_PARAMS_KEY_01, WantParamWrapper::Box(wantParams)); + WantParamWrapper wantParamWrapper(wantParams); + + auto wantParamsString = wantParamWrapper.ToString(); + + EXPECT_EQ(wantParamsString, STRING_WANT_PARAMS_STRING_0201); +} + +/** + * @tc.number: Want_Param_Wrapper_1800 + * @tc.name: from ToString to Parse + * @tc.desc: Verify the "from ToString to Parse" function. + */ +HWTEST_F(WantParamWrapperBaseTest, Want_Param_Wrapper_1800, Function | MediumTest | Level1) +{ + auto wantParamsString = wantParamWrapperPtr_->ToString(); + + EXPECT_EQ(wantParamsString, STRING_WANT_PARAMS_STRING_01); + + auto wantParamsPtr = WantParamWrapper::Parse(wantParamsString); + + auto wantParams = WantParamWrapper::Unbox(wantParamsPtr); + + EXPECT_EQ(wantParams_ == wantParams, true); +} diff --git a/tools/frameworks/kits/content/cpp/test/unittest/common/want_test.cpp b/tools/frameworks/kits/content/cpp/test/unittest/common/want_test.cpp new file mode 100755 index 00000000000..d98e772feb7 --- /dev/null +++ b/tools/frameworks/kits/content/cpp/test/unittest/common/want_test.cpp @@ -0,0 +1,3830 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "ohos/aafwk/content/want.h" +#include "ohos/aafwk/base/string_wrapper.h" +#include "ohos/aafwk/base/bool_wrapper.h" +#include "ohos/aafwk/base/int_wrapper.h" +#include "ohos/aafwk/base/float_wrapper.h" +#include "ohos/aafwk/base/array_wrapper.h" +#include "ohos/aafwk/base/long_wrapper.h" + +using namespace testing::ext; +using namespace OHOS::AAFwk; +using namespace OHOS; +using OHOS::Parcel; +using OHOS::AppExecFwk::ElementName; + +namespace OHOS { +namespace AAFwk { +class WantBaseTest : public testing::Test { +public: + WantBaseTest() + {} + ~WantBaseTest() + {} + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + + std::shared_ptr want_ = nullptr; + + void CompareWant(const std::shared_ptr &want1, const std::shared_ptr &want2) const; + bool CompareWant(const std::shared_ptr &want1, const std::shared_ptr &want2, + std::map &keys) const; + void SendParcelTest(const std::shared_ptr &want, std::map &keys) const; + void AddBoolParams(Want &want, std::map &keys, int loop, unsigned int flag) const; + void AddByteParams(Want &want, std::map &keys, int loop, unsigned int flag) const; + void AddCharParams(Want &want, std::map &keys, int loop, unsigned int flag) const; + void AddShortParams(Want &want, std::map &keys, int loop, unsigned int flag) const; + void AddIntParams(Want &want, std::map &keys, int loop, unsigned int flag) const; + void AddLongParams(Want &want, std::map &keys, int loop, unsigned int flag) const; + void AddFloatParams(Want &want, std::map &keys, int loop, unsigned int flag) const; + void AddDoubleParams(Want &want, std::map &keys, int loop, unsigned int flag) const; + void AddStringParams(Want &want, std::map &keys, int loop, unsigned int flag) const; + + std::string boolType = "bool"; + std::string boolArrayType = "boolArray"; + std::string byteType = "byte"; + std::string byteArrayType = "byteArray"; + std::string charType = "char"; + std::string charArrayType = "charArray"; + std::string shortType = "short"; + std::string shortArrayType = "shortArray"; + std::string intType = "int"; + std::string intArrayType = "intArray"; + std::string longType = "long"; + std::string longArrayType = "longArray"; + std::string floatType = "float"; + std::string floatArrayType = "floatArray"; + std::string doubleType = "double"; + std::string doubleArrayType = "doubleArray"; + std::string stringType = "string"; + std::string stringArrayType = "stringArray"; + + static const std::string URI_STRING_HEAD; + static const std::string URI_STRING_END; +}; + +template +bool CompareArrayData(const std::vector &arr1, const std::vector &arr2) +{ + if (arr1.size() != arr2.size()) { + return false; + } + + for (std::uint32_t i = 0; i < arr1.size(); i++) { + if (arr1[i] != arr2[i]) { + return false; + } + } + + return true; +}; + +enum type { FLAG_TEST_SINGLE = 0x01, FLAG_TEST_ARRAY, FLAG_TEST_BOTH }; + +void WantBaseTest::SetUpTestCase(void) +{} + +void WantBaseTest::TearDownTestCase(void) +{} + +void WantBaseTest::SetUp(void) +{ + want_ = std::make_shared(); +} + +void WantBaseTest::TearDown(void) +{} + +const std::string WantBaseTest::URI_STRING_HEAD("#Intent;"); +const std::string WantBaseTest::URI_STRING_END(";end"); + +/** + * @tc.number: AaExecFwk_Want_Type_0100 + * @tc.name: SetType/GetType + * @tc.desc: Validate when normally entering a string + */ +HWTEST_F(WantBaseTest, AaExecFwk_Want_Type_0100, Function | MediumTest | Level1) +{ + if (want_ != nullptr) { + std::string description = "liuuy"; + want_->SetType(description); + EXPECT_STREQ(description.c_str(), want_->GetType().c_str()); + } +} + +/** + * @tc.number: AaFwk_Want_Action_0100 + * @tc.name: SetAction/GetAction + * @tc.desc: Validate when normally entering a string + */ +HWTEST_F(WantBaseTest, AaFwk_Want_Action_0100, Function | MediumTest | Level1) +{ + if (want_ != nullptr) { + std::string actiondescription = "liuuy"; + want_->SetAction(actiondescription); + EXPECT_STREQ(actiondescription.c_str(), want_->GetAction().c_str()); + } +} + +/** + * @tc.number: AaFwk_Want_Bundle_0100 + * @tc.name: SetBundle/GetBundle + * @tc.desc: Validate when normally entering a string + */ +HWTEST_F(WantBaseTest, AaFwk_Want_Bundle_0100, Function | MediumTest | Level1) +{ + if (want_ != nullptr) { + std::string bundleName = "liuuy"; + want_->SetBundle(bundleName); + EXPECT_STREQ(bundleName.c_str(), want_->GetBundle().c_str()); + } +} + +/** + * @tc.number: AaFwk_Want_Parcelable_0100 + * @tc.name: Marshalling/Unmarshalling + * @tc.desc: marshalling Want, and then check result. + */ +HWTEST_F(WantBaseTest, AaFwk_Want_Parcelable_0100, Function | MediumTest | Level1) +{ + std::shared_ptr WantIn_ = std::make_shared(); + if (WantIn_ == nullptr) { + return; + } + + WantIn_->SetAction("12345"); + WantIn_->SetFlags(123); + + WantIn_->SetAction("12345"); + WantIn_->SetFlags(123); + WantIn_->AddEntity("12345"); + WantParams wantParams; + std::string keyStr = "12345667"; + bool valueBool = true; + wantParams.SetParam(keyStr, Boolean::Box(valueBool)); + WantIn_->SetParams(wantParams); + OHOS::AppExecFwk::ElementName element; + element.SetAbilityName("12345"); + element.SetBundleName("12345"); + element.SetDeviceID("12345"); + WantIn_->SetElement(element); + WantIn_->SetType("12345"); + size_t pos1; + size_t pos2; + bool result = false; + + Parcel in; + pos1 = in.GetWritePosition(); + result = WantIn_->Marshalling(in); + pos2 = in.GetWritePosition(); + EXPECT_EQ(result, true); + GTEST_LOG_(INFO) << " Marshalling: pos1: " << pos1 << ", pos2: " << pos2 << ", result: " << result; + + pos1 = in.GetWritePosition(); + result = WantIn_->Marshalling(in); + pos2 = in.GetWritePosition(); + EXPECT_EQ(result, true); + GTEST_LOG_(INFO) << " Marshalling: pos1: " << pos1 << ", pos2: " << pos2 << ", result: " << result; + + pos1 = in.GetReadPosition(); + std::shared_ptr WantOut_(Want::Unmarshalling(in)); + if (WantOut_ != nullptr) { + pos2 = in.GetReadPosition(); + CompareWant(WantIn_, WantOut_); + EXPECT_EQ(valueBool, Boolean::Unbox(IBoolean::Query(WantOut_->GetParams().GetParam(keyStr)))); + GTEST_LOG_(INFO) << " Unmarshalling: pos1: " << pos1 << ", pos2: " << pos2 << ", result: " << result; + } + + pos1 = in.GetReadPosition(); + std::shared_ptr WantOut2_(Want::Unmarshalling(in)); + if (WantOut2_ != nullptr) { + pos2 = in.GetReadPosition(); + CompareWant(WantIn_, WantOut2_); + EXPECT_EQ(valueBool, Boolean::Unbox(IBoolean::Query(WantOut2_->GetParams().GetParam(keyStr)))); + GTEST_LOG_(INFO) << " Unmarshalling: pos1: " << pos1 << ", pos2: " << pos2 << ", result: " << result; + } +} +/** + * @tc.number: AaFwk_Want_Parcelable_0200 + * @tc.name: Marshalling/Unmarshalling + * @tc.desc: marshalling Want, and then check result. + */ +HWTEST_F(WantBaseTest, AaFwk_Want_Parcelable_0200, Function | MediumTest | Level1) +{ + std::shared_ptr WantIn_ = std::make_shared(); + if (WantIn_ == nullptr) { + return; + } + + WantIn_->SetAction("@#¥#3243adsafdf_中文"); + WantIn_->SetFlags(123); + WantIn_->AddEntity("@#¥#3243adsafdf_中文"); + WantParams wantParams; + std::string keyStr = "@#¥#3243adsafdf_中文"; + long valueLong = 123; + wantParams.SetParam(keyStr, Long::Box(valueLong)); + WantIn_->SetParams(wantParams); + OHOS::AppExecFwk::ElementName element; + element.SetAbilityName("@#¥#3243adsafdf_中文"); + element.SetBundleName("@#¥#3243adsafdf_中文"); + element.SetDeviceID("@#¥#3243adsafdf_中文"); + WantIn_->SetElement(element); + WantIn_->SetType("@#¥#3243adsafdf_中文"); + + size_t pos1; + size_t pos2; + bool result = false; + + Parcel in; + pos1 = in.GetWritePosition(); + result = WantIn_->Marshalling(in); + pos2 = in.GetWritePosition(); + EXPECT_EQ(result, true); + GTEST_LOG_(INFO) << "Marshalling: pos1: " << pos1 << ", pos2: " << pos2 << ", result: " << result; + + pos1 = in.GetWritePosition(); + result = WantIn_->Marshalling(in); + pos2 = in.GetWritePosition(); + EXPECT_EQ(result, true); + GTEST_LOG_(INFO) << "Marshalling: pos1: " << pos1 << ", pos2: " << pos2 << ", result: " << result; + + pos1 = in.GetReadPosition(); + + std::shared_ptr WantOut_(Want::Unmarshalling(in)); + if (WantOut_ != nullptr) { + pos2 = in.GetReadPosition(); + CompareWant(WantIn_, WantOut_); + EXPECT_EQ(valueLong, Long::Unbox(ILong::Query(WantOut_->GetParams().GetParam(keyStr)))); + GTEST_LOG_(INFO) << "Unmarshalling: pos1: " << pos1 << ", pos2: " << pos2 << ", result: " << result; + } + + pos1 = in.GetReadPosition(); + std::shared_ptr WantOut2_(Want::Unmarshalling(in)); + if (WantOut2_ != nullptr) { + pos2 = in.GetReadPosition(); + CompareWant(WantIn_, WantOut2_); + EXPECT_EQ(valueLong, Long::Unbox(ILong::Query(WantOut2_->GetParams().GetParam(keyStr)))); + GTEST_LOG_(INFO) << "Unmarshalling: pos1: " << pos1 << ", pos2: " << pos2 << ", result: " << result; + } +} + +/** + * @tc.number: AaFwk_Want_Parcelable_0300 + * @tc.name: Marshalling/Unmarshalling + * @tc.desc: marshalling Want, and then check result. + */ +HWTEST_F(WantBaseTest, AaFwk_Want_Parcelable_0300, Function | MediumTest | Level1) +{ + std::shared_ptr WantIn_ = std::make_shared(); + if (WantIn_ == nullptr) { + return; + } + + WantIn_->SetAction(""); + WantIn_->SetFlags(123); + WantIn_->AddEntity(""); + WantParams wantParams; + std::string keyStr = ""; + int valueInt = 123; + wantParams.SetParam(keyStr, Integer::Box(valueInt)); + WantIn_->SetParams(wantParams); + OHOS::AppExecFwk::ElementName element; + element.SetAbilityName(""); + element.SetBundleName(""); + element.SetDeviceID(""); + WantIn_->SetElement(element); + WantIn_->SetType(""); + + size_t pos1; + size_t pos2; + bool result = false; + + Parcel in; + pos1 = in.GetWritePosition(); + result = WantIn_->Marshalling(in); + pos2 = in.GetWritePosition(); + EXPECT_EQ(result, true); + GTEST_LOG_(INFO) << "Marshalling: pos1: " << pos1 << ", pos2: " << pos2 << ", result: " << result; + + pos1 = in.GetWritePosition(); + result = WantIn_->Marshalling(in); + pos2 = in.GetWritePosition(); + EXPECT_EQ(result, true); + GTEST_LOG_(INFO) << "Marshalling: pos1: " << pos1 << ", pos2: " << pos2 << ", result: " << result; + + pos1 = in.GetReadPosition(); + std::shared_ptr WantOut_(Want::Unmarshalling(in)); + if (WantOut_ != nullptr) { + pos2 = in.GetReadPosition(); + CompareWant(WantIn_, WantOut_); + EXPECT_EQ(valueInt, Integer::Unbox(IInteger::Query(WantOut_->GetParams().GetParam(keyStr)))); + GTEST_LOG_(INFO) << "Unmarshalling: pos1: " << pos1 << ", pos2: " << pos2 << ", result: " << result; + } + + pos1 = in.GetReadPosition(); + std::shared_ptr WantOut2_(Want::Unmarshalling(in)); + if (WantOut2_ != nullptr) { + pos2 = in.GetReadPosition(); + CompareWant(WantIn_, WantOut2_); + EXPECT_EQ(valueInt, Integer::Unbox(IInteger::Query(WantOut2_->GetParams().GetParam(keyStr)))); + GTEST_LOG_(INFO) << "Unmarshalling: pos1: " << pos1 << ", pos2: " << pos2 << ", result: " << result; + } +} + +/** + * @tc.number: AaFwk_Want_Parcelable_0400 + * @tc.name: Marshalling/Unmarshalling + * @tc.desc: marshalling Want, and then check result. + */ +HWTEST_F(WantBaseTest, AaFwk_Want_Parcelable_0400, Function | MediumTest | Level1) +{ + std::shared_ptr WantIn_ = std::make_shared(); + if (WantIn_ == nullptr) { + return; + } + + WantIn_->SetAction("12345"); + WantIn_->SetFlags(123); + WantIn_->AddEntity("12345"); + WantIn_->AddEntity("@#¥#3243adsafdf_中文"); + WantIn_->AddEntity(""); + WantParams wantParams; + std::string keyStr = "12345667"; + std::string valueString = "123"; + wantParams.SetParam(keyStr, String::Box(valueString)); + WantIn_->SetParams(wantParams); + OHOS::AppExecFwk::ElementName element; + element.SetAbilityName("12345"); + element.SetBundleName("12345"); + element.SetDeviceID("12345"); + WantIn_->SetElement(element); + WantIn_->SetType("12345"); + + size_t pos1; + size_t pos2; + bool result = false; + + Parcel in; + pos1 = in.GetWritePosition(); + result = WantIn_->Marshalling(in); + pos2 = in.GetWritePosition(); + EXPECT_EQ(result, true); + GTEST_LOG_(INFO) << "Marshalling: pos1: " << pos1 << ", pos2: " << pos2 << ", result: " << result; + + pos1 = in.GetWritePosition(); + result = WantIn_->Marshalling(in); + pos2 = in.GetWritePosition(); + EXPECT_EQ(result, true); + GTEST_LOG_(INFO) << "Marshalling: pos1: " << pos1 << ", pos2: " << pos2 << ", result: " << result; + + pos1 = in.GetReadPosition(); + std::shared_ptr WantOut_(Want::Unmarshalling(in)); + if (WantOut_ != nullptr) { + pos2 = in.GetReadPosition(); + CompareWant(WantIn_, WantOut_); + EXPECT_EQ(valueString, String::Unbox(IString::Query(WantOut_->GetParams().GetParam(keyStr)))); + GTEST_LOG_(INFO) << "Unmarshalling: pos1: " << pos1 << ", pos2: " << pos2 << ", result: " << result; + } + + pos1 = in.GetReadPosition(); + std::shared_ptr WantOut2_(Want::Unmarshalling(in)); + if (WantOut2_ != nullptr) { + pos2 = in.GetReadPosition(); + CompareWant(WantIn_, WantOut2_); + EXPECT_EQ(valueString, String::Unbox(IString::Query(WantOut2_->GetParams().GetParam(keyStr)))); + GTEST_LOG_(INFO) << "Unmarshalling: pos1: " << pos1 << ", pos2: " << pos2 << ", result: " << result; + } +} + +/** + * @tc.number: AaFwk_Want_Parcelable_0500 + * @tc.name: Marshalling/Unmarshalling + * @tc.desc: marshalling Want, and then check result. + */ +HWTEST_F(WantBaseTest, AaFwk_Want_Parcelable_0500, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_Want_Parcelable_005 start"; + std::shared_ptr WantIn_ = std::make_shared(); + if (WantIn_ == nullptr) { + return; + } + + WantIn_->SetAction("system.test.action"); + WantIn_->SetFlags(64); + WantIn_->AddEntity("system.test.entity"); + + OHOS::AppExecFwk::ElementName element; + element.SetAbilityName("system.test.abilityname"); + element.SetBundleName("system.test.bundlename"); + element.SetDeviceID("system.test.deviceid"); + WantIn_->SetElement(element); + + WantParams wantParams; + std::string keyStr = "system.test.wantparams.key"; + std::string MIMEKEY = "mime-type"; + wantParams.SetParam(MIMEKEY, String::Box("system.test.uritype")); + + std::string valueString = "system.wantparams.value.content.test"; + wantParams.SetParam(keyStr, String::Box(valueString)); + WantIn_->SetParams(wantParams); + + // want SetParam arraydata test + std::vector boolArrayValue = {true, false, true}; + WantIn_->SetParam(std::string("bool_arraykey"), boolArrayValue); + + std::vector byteArrayValue = {'?', 'a', '\\'}; + WantIn_->SetParam(std::string("byte_arraykey"), byteArrayValue); + + std::vector charArrayValue = {U'e', U'l', U'l', U'o'}; + WantIn_->SetParam(std::string("char_arraykey"), charArrayValue); + + std::vector shortArrayValue = {-1, 0, 1}; + WantIn_->SetParam(std::string("short_arraykey"), shortArrayValue); + + std::vector intArrayValue = {-10, 0, 10}; + WantIn_->SetParam(std::string("int_arraykey"), intArrayValue); + + std::vector longArrayValue = {-100, 0, 100}; + WantIn_->SetParam(std::string("long_arraykey"), longArrayValue); + + std::vector floatArrayValue = {-100.1, 0.1, 100.1}; + WantIn_->SetParam(std::string("float_arraykey"), floatArrayValue); + + std::vector doubleArrayValue = {-1000.1, 0.1, 1000.1}; + WantIn_->SetParam(std::string("double_arraykey"), doubleArrayValue); + + std::vector stringArrayValue = {"stringtest1", "string@test2", "string@!#test2"}; + WantIn_->SetParam(std::string("string_arraykey"), stringArrayValue); + + Want wantCopy(*WantIn_); + std::vector teststringArrayValue1 = WantIn_->GetStringArrayParam(std::string("string_arraykey")); + std::vector teststringArrayValue2 = wantCopy.GetStringArrayParam(std::string("string_arraykey")); + bool copyarraycompare = CompareArrayData(teststringArrayValue1, teststringArrayValue1); + EXPECT_EQ(copyarraycompare, true); + std::string str = (copyarraycompare == true) ? "true" : "false"; + GTEST_LOG_(INFO) << "copyarraycompare=" << str.c_str(); + + Parcel in; + bool result = false; + result = WantIn_->Marshalling(in); + EXPECT_EQ(result, true); + std::shared_ptr WantOut_(Want::Unmarshalling(in)); + if (WantOut_ != nullptr) { + GTEST_LOG_(INFO) << "WantOut_->GetAction().c_str(): " << WantOut_->GetAction().c_str(); + EXPECT_STREQ(WantOut_->GetAction().c_str(), std::string("system.test.action").c_str()); + + int flags = WantOut_->GetFlags(); + GTEST_LOG_(INFO) << "WantOut_->GetFlags(): " << flags; + EXPECT_EQ(((int)(flags)), 64); + + bool hasentity = WantOut_->HasEntity("system.test.entity"); + GTEST_LOG_(INFO) << "WantOut_->HasEntity(system.test.entity)" << hasentity; + EXPECT_EQ(hasentity, true); + + WantOut_->RemoveEntity(std::string("system.test.entity")); + hasentity = WantOut_->HasEntity(std::string("system.test.entity")); + GTEST_LOG_(INFO) << "WantOut_->RemoveEntity(system.test.entity)" << hasentity; + EXPECT_EQ(hasentity, false); + + std::string outtype = WantOut_->GetType(); + GTEST_LOG_(INFO) << "WantOut_->GetType()" << outtype.c_str(); + EXPECT_STREQ(outtype.c_str(), std::string("system.test.uritype").c_str()); + + element = WantOut_->GetElement(); + GTEST_LOG_(INFO) << "element.GetAbilityName().c_str(): " << element.GetAbilityName().c_str(); + EXPECT_STREQ(element.GetAbilityName().c_str(), std::string("system.test.abilityname").c_str()); + + GTEST_LOG_(INFO) << "element->GetBundleName().c_str(): " << element.GetBundleName().c_str(); + EXPECT_STREQ(element.GetBundleName().c_str(), std::string("system.test.bundlename").c_str()); + + GTEST_LOG_(INFO) << "element.GetDeviceID().c_str(): " << element.GetDeviceID().c_str(); + EXPECT_STREQ(element.GetDeviceID().c_str(), std::string("system.test.deviceid").c_str()); + + std::string param_content = WantOut_->GetStringParam(keyStr); + GTEST_LOG_(INFO) << "WantOut_->GetStringParam(keyStr): " << param_content.c_str(); + + // want SetParam arraydata test + std::vector retboolArray; + retboolArray = WantOut_->GetBoolArrayParam(std::string("bool_arraykey")); + + bool arraycompare = CompareArrayData(retboolArray, boolArrayValue); + EXPECT_EQ(arraycompare, true); + + std::vector retbyteArrayValue; + retbyteArrayValue = WantOut_->GetByteArrayParam(std::string("byte_arraykey")); + arraycompare = CompareArrayData(retbyteArrayValue, byteArrayValue); + EXPECT_EQ(arraycompare, true); + + std::vector retcharArrayValue; + retcharArrayValue = WantOut_->GetCharArrayParam(std::string("char_arraykey")); + arraycompare = CompareArrayData(retcharArrayValue, charArrayValue); + EXPECT_EQ(arraycompare, true); + + std::vector retshortArrayValue; + retshortArrayValue = WantOut_->GetShortArrayParam(std::string("short_arraykey")); + arraycompare = CompareArrayData(retshortArrayValue, shortArrayValue); + EXPECT_EQ(arraycompare, true); + + std::vector retintArrayValue; + retintArrayValue = WantOut_->GetIntArrayParam(std::string("int_arraykey")); + arraycompare = CompareArrayData(retintArrayValue, intArrayValue); + EXPECT_EQ(arraycompare, true); + + std::vector retlonArrayValue; + retlonArrayValue = WantOut_->GetLongArrayParam(std::string("long_arraykey")); + arraycompare = CompareArrayData(retlonArrayValue, longArrayValue); + EXPECT_EQ(arraycompare, true); + + std::vector retfloatArrayValue; + retfloatArrayValue = WantOut_->GetFloatArrayParam(std::string("float_arraykey")); + arraycompare = CompareArrayData(retfloatArrayValue, floatArrayValue); + EXPECT_EQ(arraycompare, true); + + std::vector retdoubleArrayValue; + retdoubleArrayValue = WantOut_->GetDoubleArrayParam(std::string("double_arraykey")); + arraycompare = CompareArrayData(retdoubleArrayValue, doubleArrayValue); + EXPECT_EQ(arraycompare, true); + + std::vector retstringArrayValue; + retstringArrayValue = WantOut_->GetStringArrayParam(std::string("string_arraykey")); + arraycompare = CompareArrayData(retstringArrayValue, stringArrayValue); + EXPECT_EQ(arraycompare, true); + + GTEST_LOG_(INFO) << "AaFwk_Want_Parcelable_005 end"; + } +} + +void WantBaseTest::CompareWant(const std::shared_ptr &want1, const std::shared_ptr &want2) const +{ + EXPECT_EQ(want1->GetAction(), want2->GetAction()); + EXPECT_EQ(want1->GetFlags(), want2->GetFlags()); + EXPECT_EQ(want1->GetType(), want2->GetType()); + EXPECT_EQ(want1->CountEntities(), want2->CountEntities()); + + int count = want1->CountEntities(); + std::vector entities1 = want1->GetEntities(); + std::vector entities2 = want2->GetEntities(); + for (int i = 0; i < count; i++) { + EXPECT_EQ(entities1.at(i), entities2.at(i)); + } + + OHOS::AppExecFwk::ElementName element1 = want1->GetElement(); + OHOS::AppExecFwk::ElementName element2 = want2->GetElement(); + EXPECT_EQ(element1.GetURI(), element1.GetURI()); + + std::set key1; + std::set key2; + key1 = want1->GetParams().KeySet(); + key2 = want2->GetParams().KeySet(); + EXPECT_EQ(key1.size(), key2.size()); + + std::set::iterator iter1 = key1.begin(); + std::set::iterator iter2 = key2.begin(); + for (; (iter1 != key1.end() && iter2 != key2.end()); iter1++, iter2++) { + EXPECT_EQ(*iter1, *iter2); + } +} + +bool WantBaseTest::CompareWant(const std::shared_ptr &want1, const std::shared_ptr &want2, + std::map &keys) const +{ + if (want1 == nullptr || want2 == nullptr) { + return false; + } + EXPECT_STREQ(want1->GetAction().c_str(), want2->GetAction().c_str()); + EXPECT_EQ(want1->CountEntities(), want2->CountEntities()); + + if (want1->CountEntities() != want2->CountEntities()) { + return false; + } + + int count = want1->CountEntities(); + + std::vector entities1 = want1->GetEntities(); + std::vector entities2 = want2->GetEntities(); + for (int i = 0; i < count; i++) { + EXPECT_EQ(entities1.at(i), entities2.at(i)); + } + EXPECT_EQ(want1->GetFlags(), want2->GetFlags()); + EXPECT_EQ(want1->GetElement(), want2->GetElement()); + + for (auto it = keys.begin(); it != keys.end(); it++) { + if (it->second == boolType) { + bool v1 = want1->GetBoolParam(it->first, false); + bool v2 = want2->GetBoolParam(it->first, false); + EXPECT_EQ(v1, v2); + EXPECT_EQ(v1, true); + } else if (it->second == boolArrayType) { + std::vector v1 = want1->GetBoolArrayParam(it->first); + std::vector v2 = want2->GetBoolArrayParam(it->first); + EXPECT_EQ(v1, v2); + } else if (it->second == byteType) { + byte v1 = want1->GetByteParam(it->first, 'j'); + byte v2 = want2->GetByteParam(it->first, 'k'); + EXPECT_EQ(v1, v2); + } else if (it->second == byteArrayType) { + std::vector v1 = want1->GetByteArrayParam(it->first); + std::vector v2 = want2->GetByteArrayParam(it->first); + EXPECT_EQ(v1, v2); + } else if (it->second == charType) { + zchar v1 = want1->GetCharParam(it->first, 0x01AB); + zchar v2 = want2->GetCharParam(it->first, 0x02CD); + EXPECT_EQ(v1, v2); + } else if (it->second == charArrayType) { + std::vector v1 = want1->GetCharArrayParam(it->first); + std::vector v2 = want2->GetCharArrayParam(it->first); + EXPECT_EQ(v1, v2); + } else if (it->second == shortType) { + short default1 = 123; + short default2 = 456; + short v1 = want1->GetShortParam(it->first, default1); + short v2 = want2->GetShortParam(it->first, default2); + EXPECT_EQ(v1, v2); + } else if (it->second == shortArrayType) { + std::vector v1 = want1->GetShortArrayParam(it->first); + std::vector v2 = want2->GetShortArrayParam(it->first); + EXPECT_EQ(v1, v2); + } else if (it->second == intType) { + int default1 = 1230000; + int default2 = 4560000; + int v1 = want1->GetIntParam(it->first, default1); + int v2 = want2->GetIntParam(it->first, default2); + EXPECT_EQ(v1, v2); + } else if (it->second == intArrayType) { + std::vector v1 = want1->GetIntArrayParam(it->first); + std::vector v2 = want2->GetIntArrayParam(it->first); + EXPECT_EQ(v1, v2); + } else if (it->second == longType) { + long default1 = 1e8; + long default2 = 2e8; + long v1 = want1->GetLongParam(it->first, default1); + long v2 = want2->GetLongParam(it->first, default2); + EXPECT_EQ(v1, v2); + } else if (it->second == longArrayType) { + std::vector v1 = want1->GetLongArrayParam(it->first); + std::vector v2 = want2->GetLongArrayParam(it->first); + EXPECT_EQ(v1, v2); + } else if (it->second == floatType) { + float default1 = 12.3; + float default2 = 45.6; + float v1 = want1->GetFloatParam(it->first, default1); + float v2 = want2->GetFloatParam(it->first, default2); + EXPECT_EQ(v1, v2); + } else if (it->second == floatArrayType) { + std::vector v1 = want1->GetFloatArrayParam(it->first); + std::vector v2 = want2->GetFloatArrayParam(it->first); + EXPECT_EQ(v1, v2); + } else if (it->second == doubleType) { + double default1 = 12.3; + double default2 = 45.6; + double v1 = want1->GetDoubleParam(it->first, default1); + double v2 = want2->GetDoubleParam(it->first, default2); + EXPECT_EQ(v1, v2); + } else if (it->second == doubleArrayType) { + std::vector v1 = want1->GetDoubleArrayParam(it->first); + std::vector v2 = want2->GetDoubleArrayParam(it->first); + EXPECT_EQ(v1, v2); + } else if (it->second == stringType) { + std::string v1 = want1->GetStringParam(it->first); + std::string v2 = want2->GetStringParam(it->first); + EXPECT_EQ(v1, v2); + } else if (it->second == stringArrayType) { + std::vector v1 = want1->GetStringArrayParam(it->first); + std::vector v2 = want2->GetStringArrayParam(it->first); + EXPECT_EQ(v1, v2); + } + } + + return true; +} + +void WantBaseTest::SendParcelTest(const std::shared_ptr &want, std::map &keys) const +{ + size_t pos1; + size_t pos2; + Parcel data; + bool result = false; + + pos1 = data.GetWritePosition(); + result = data.WriteParcelable(want.get()); + pos2 = data.GetWritePosition(); + EXPECT_EQ(result, true); + GTEST_LOG_(INFO) << "SendParcelTest: pos1: " << pos1 << ", pos2: " << pos2 << ", result: " << result; + + std::shared_ptr wantNew(data.ReadParcelable()); + EXPECT_NE(wantNew, nullptr); + + if (wantNew != nullptr) { + result = CompareWant(want, wantNew, keys); + EXPECT_EQ(result, true); + } +} + +void WantBaseTest::AddBoolParams( + Want &want, std::map &keys, int loop, unsigned int flag) const +{ + std::string key; + std::string boolKey = "boolKey"; + std::string boolArrayKey = "boolArrayKey"; + for (int i = 0; i < loop; i++) { + if (flag & FLAG_TEST_SINGLE) { + bool boolValue = true; + keys[boolKey + std::to_string(i)] = boolType; + want.SetParam(boolKey + std::to_string(i), boolValue); + } + + if (flag & FLAG_TEST_ARRAY) { + std::vector boolArrayValue = {true, false, true}; + keys[key] = boolArrayType; + want.SetParam(key, boolArrayValue); + } + } +} + +void WantBaseTest::AddByteParams( + Want &want, std::map &keys, int loop, unsigned int flag) const +{ + std::string key; + std::string byteKey = "byteKey"; + std::string byteArrayKey = "byteArrayKey"; + for (int i = 0; i < loop; i++) { + if (flag & FLAG_TEST_SINGLE) { + byte byteValue = 'z'; + key = byteKey + std::to_string(i); + keys[key] = byteType; + want.SetParam(key, byteValue); + } + + if (flag & FLAG_TEST_ARRAY) { + std::vector byteArrayValue = {'?', 'a', '\\'}; + key = byteArrayKey + std::to_string(i); + keys[key] = byteArrayType; + want.SetParam(key, byteArrayValue); + } + } +} + +void WantBaseTest::AddCharParams( + Want &want, std::map &keys, int loop, unsigned int flag) const +{ + std::string key; + std::string charKey = "charKey"; + std::string charArrayKey = "charArrayKey"; + for (int i = 0; i < loop; i++) { + if (flag & FLAG_TEST_SINGLE) { + zchar charValue = U'h'; + key = charKey + std::to_string(i); + keys[key] = charType; + want.SetParam(key, charValue); + } + + if (flag & FLAG_TEST_ARRAY) { + std::vector charArrayValue = {U'e', U'l', U'l', U'o'}; + key = charArrayKey + std::to_string(i); + keys[key] = charArrayType; + want.SetParam(key, charArrayValue); + } + } +} + +void WantBaseTest::AddShortParams( + Want &want, std::map &keys, int loop, unsigned int flag) const +{ + std::string key; + std::string shortKey = "shortKey"; + std::string shortArrayKey = "shortArrayKey"; + for (int i = 0; i < loop; i++) { + if (flag & FLAG_TEST_SINGLE) { + short shortValue = 1; + key = shortKey + std::to_string(i); + keys[key] = shortType; + want.SetParam(key, shortValue); + } + + if (flag & FLAG_TEST_ARRAY) { + std::vector shortArrayValue = {-1, 0, 1}; + key = shortArrayKey + std::to_string(i); + keys[key] = shortArrayType; + want.SetParam(key, shortArrayValue); + } + } +} + +void WantBaseTest::AddIntParams(Want &want, std::map &keys, int loop, unsigned int flag) const +{ + std::string key; + std::string intKey = "intKey"; + std::string intArrayKey = "intArrayKey"; + for (int i = 0; i < loop; i++) { + if (flag & FLAG_TEST_SINGLE) { + int intValue = 10; + key = intKey + std::to_string(i); + keys[key] = intType; + want.SetParam(key, intValue); + } + + if (flag & FLAG_TEST_ARRAY) { + std::vector intArrayValue = {-10, 0, 10}; + key = intArrayKey + std::to_string(i); + keys[key] = intArrayType; + want.SetParam(key, intArrayValue); + } + } +} + +void WantBaseTest::AddLongParams( + Want &want, std::map &keys, int loop, unsigned int flag) const +{ + std::string key; + std::string longKey = "longKey"; + std::string longArrayKey = "longArrayKey"; + for (int i = 0; i < loop; i++) { + if (flag & FLAG_TEST_SINGLE) { + long longValue = 100L; + key = longKey + std::to_string(i); + keys[key] = longType; + want.SetParam(key, longValue); + } + + if (flag & FLAG_TEST_ARRAY) { + std::vector longArrayValue = {-100, 0, 100}; + key = longArrayKey + std::to_string(i); + keys[key] = longArrayType; + want.SetParam(key, longArrayValue); + } + } +} + +void WantBaseTest::AddFloatParams( + Want &want, std::map &keys, int loop, unsigned int flag) const +{ + std::string key; + std::string floatKey = "floatKey"; + std::string floatArrayKey = "floatArrayKey"; + for (int i = 0; i < loop; i++) { + if (flag & FLAG_TEST_SINGLE) { + float floatValue = 100.1f; + key = floatKey + std::to_string(i); + keys[key] = floatType; + want.SetParam(key, floatValue); + } + + if (flag & FLAG_TEST_ARRAY) { + std::vector floatArrayValue = {-100.1, 0.1, 100.1}; + key = floatArrayKey + std::to_string(i); + keys[key] = floatArrayType; + want.SetParam(key, floatArrayValue); + } + } +} + +void WantBaseTest::AddDoubleParams( + Want &want, std::map &keys, int loop, unsigned int flag) const +{ + std::string key; + std::string doubleKey = "doubleKey"; + std::string doubleArrayKey = "doubleArrayKey"; + for (int i = 0; i < loop; i++) { + if (flag & FLAG_TEST_SINGLE) { + double doubleValue = 1000.1; + key = doubleKey + std::to_string(i); + keys[key] = doubleType; + want.SetParam(key, doubleValue); + } + + if (flag & FLAG_TEST_ARRAY) { + std::vector doubleArrayValue = {-1000.1, 0.1, 1000.1}; + key = doubleArrayKey + std::to_string(i); + keys[key] = doubleArrayType; + want.SetParam(key, doubleArrayValue); + } + } +} + +void WantBaseTest::AddStringParams( + Want &want, std::map &keys, int loop, unsigned int flag) const +{ + std::string key; + std::string stringKey = "stringKey"; + std::string stringArrayKey = "stringArrayKey"; + for (int i = 0; i < loop; i++) { + if (flag & FLAG_TEST_SINGLE) { + string stringValue = "zzzz"; + key = stringKey + std::to_string(i); + keys[key] = stringType; + want.SetParam(key, stringValue); + } + + if (flag & FLAG_TEST_ARRAY) { + std::vector stringArrayValue = {"??", "aa", "\\\\"}; + key = stringArrayKey + std::to_string(i); + keys[key] = stringArrayType; + want.SetParam(key, stringArrayValue); + } + } +} + +/** + * @tc.number: AaFwk_Want_Parcelable_0600 + * @tc.name: parcelable + * @tc.desc: Verify parcelable. + */ +HWTEST_F(WantBaseTest, AaFwk_Want_Parcelable_0600, Function | MediumTest | Level1) +{ + std::string action = "want.action.test"; + unsigned int flag = 0x789; + std::string entity = "want.entity.test"; + OHOS::AppExecFwk::ElementName element("bundlename", "appname", "abilityname"); + + std::shared_ptr want = std::make_shared(); + if (want != nullptr) { + want->SetAction(action); + want->AddEntity(entity); + want->AddFlags(flag); + want->SetElement(element); + + std::map keys; + + SendParcelTest(want, keys); + } +} + +/** + * @tc.number: AaFwk_Want_Parcelable_0700 + * @tc.name: parcelable + * @tc.desc: Verify parcelable. + */ +HWTEST_F(WantBaseTest, AaFwk_Want_Parcelable_0700, Function | MediumTest | Level1) +{ + std::string action = "want.action.test"; + unsigned int flag = 0x789; + std::string entity = "want.entity.test"; + OHOS::AppExecFwk::ElementName element("bundlename", "appname", "abilityname"); + + std::shared_ptr want = std::make_shared(); + if (want != nullptr) { + want->SetAction(action); + want->AddEntity(entity); + want->AddFlags(flag); + want->SetElement(element); + + int loop = 1; + std::map keys; + + AddByteParams(*(want.get()), keys, loop, FLAG_TEST_BOTH); + AddCharParams(*(want.get()), keys, loop, FLAG_TEST_BOTH); + AddShortParams(*(want.get()), keys, loop, FLAG_TEST_BOTH); + AddIntParams(*(want.get()), keys, loop, FLAG_TEST_BOTH); + AddLongParams(*(want.get()), keys, loop, FLAG_TEST_BOTH); + AddFloatParams(*(want.get()), keys, loop, FLAG_TEST_BOTH); + AddDoubleParams(*(want.get()), keys, loop, FLAG_TEST_BOTH); + AddStringParams(*(want.get()), keys, loop, FLAG_TEST_BOTH); + + SendParcelTest(want, keys); + } +} + +/** + * @tc.number: AaFwk_Want_Parcelable_0800 + * @tc.name: parcelable + * @tc.desc: Verify parcelable. + */ +HWTEST_F(WantBaseTest, AaFwk_Want_Parcelable_0800, Function | MediumTest | Level1) +{ + std::string action = "want.action.test"; + unsigned int flag = 0x789; + std::string entity = "want.entity.test"; + OHOS::AppExecFwk::ElementName element("bundlename", "appname", "abilityname"); + + std::shared_ptr want = std::make_shared(); + if (want != nullptr) { + want->SetAction(action); + want->AddEntity(entity); + want->AddFlags(flag); + want->SetElement(element); + std::map keys; + + SendParcelTest(want, keys); + } +} + +/** + * @tc.number: AaFwk_Want_FormatMimeType_0100 + * @tc.name: formatMimeType + * @tc.desc: formats data of a specified MIME type. + */ +HWTEST_F(WantBaseTest, AaFwk_Want_FormatMimeType_0100, Function | MediumTest | Level1) +{ + std::string mimeType = "Application/Envoy"; + std::string mimeTypeResult = "application/envoy"; + + EXPECT_EQ(mimeTypeResult, Want::FormatMimeType(mimeType)); +} + +/** + * @tc.number: AaFwk_Want_FormatMimeType_0200 + * @tc.name: formatMimeType + * @tc.desc: formats data of a specified MIME type. + */ +HWTEST_F(WantBaseTest, AaFwk_Want_FormatMimeType_0200, Function | MediumTest | Level1) +{ + std::string mimeType = "APPLICATION/ENVOY"; + std::string mimeTypeResult = "application/envoy"; + + EXPECT_EQ(mimeTypeResult, Want::FormatMimeType(mimeType)); +} + +/** + * @tc.number: AaFwk_Want_FormatMimeType_0300 + * @tc.name: formatMimeType + * @tc.desc: formats data of a specified MIME type. + */ +HWTEST_F(WantBaseTest, AaFwk_Want_FormatMimeType_0300, Function | MediumTest | Level1) +{ + std::string mimeType = " Appl icati on/ Envoy "; + std::string mimeTypeResult = "application/envoy"; + + EXPECT_EQ(mimeTypeResult, Want::FormatMimeType(mimeType)); +} + +/** + * @tc.number: AaFwk_Want_FormatMimeType_0400 + * @tc.name: formatMimeType + * @tc.desc: formats data of a specified MIME type. + */ +HWTEST_F(WantBaseTest, AaFwk_Want_FormatMimeType_0400, Function | MediumTest | Level1) +{ + std::string mimeType = " Appl icati on/ Envoy ; yovnE ;no itaci lppA "; + std::string mimeTypeResult = "application/envoy"; + + EXPECT_EQ(mimeTypeResult, Want::FormatMimeType(mimeType)); +} + +/** + * @tc.number: AaFwk_Want_ParseUri_ToUri_0100 + * @tc.name: ParseUri and ToUri + * @tc.desc: Verify the function when Want is empty. + */ +HWTEST_F(WantBaseTest, AaFwk_Want_ParseUri_ToUri_0100, Function | MediumTest | Level1) +{ + std::size_t pos = 0; + std::size_t content = 0; + std::size_t head = 0; + Want wantOrigin; + + std::string uri = wantOrigin.ToUri(); + + head = uri.find(WantBaseTest::URI_STRING_HEAD, pos); + EXPECT_EQ(head, pos); + if (head != std::string::npos) { + pos += head + WantBaseTest::URI_STRING_HEAD.length() - 1; + } + + content = uri.find(WantBaseTest::URI_STRING_END, pos); + EXPECT_EQ(content, pos); + if (content != std::string::npos) { + pos += WantBaseTest::URI_STRING_END.length(); + } + + EXPECT_EQ(uri.length(), pos); + + Want *wantNew = Want::ParseUri(uri); + EXPECT_NE(wantNew, nullptr); + + if (wantNew != nullptr) { + EXPECT_EQ(wantNew->GetAction(), std::string("")); + for (auto entity : wantNew->GetEntities()) { + EXPECT_EQ(entity, std::string("")); + } + OHOS::AppExecFwk::ElementName element; + EXPECT_EQ(wantNew->GetElement(), element); + EXPECT_EQ(static_cast(wantNew->GetFlags()), 0); + + delete wantNew; + } +} + +/** + * @tc.number: AaFwk_Want_ParseUri_ToUri_0200 + * @tc.name: ParseUri and ToUri + * @tc.desc: Verify the function when Want only has action/entity/flag/element. + */ +HWTEST_F(WantBaseTest, AaFwk_Want_ParseUri_ToUri_0200, Function | MediumTest | Level1) +{ + std::string search; + + std::string action = Want::ACTION_PLAY; + std::string entity = Want::ENTITY_VIDEO; + unsigned int flag = 0x0f0f0f0f; + std::string flagStr = "0x0f0f0f0f"; + std::string device = "device1"; + std::string bundle = "bundle1"; + std::string ability = "ability1"; + OHOS::AppExecFwk::ElementName element(device, bundle, ability); + + Want wantOrigin; + wantOrigin.SetAction(action); + wantOrigin.AddEntity(entity); + wantOrigin.AddFlags(flag); + wantOrigin.SetElement(element); + + std::string uri = wantOrigin.ToUri(); + Want *wantNew = Want::ParseUri(uri); + EXPECT_NE(wantNew, nullptr); + + if (wantNew != nullptr) { + EXPECT_EQ(wantNew->GetAction(), action); + for (auto entityItem : wantNew->GetEntities()) { + EXPECT_EQ(entityItem, entity); + } + EXPECT_EQ(wantNew->GetElement().GetDeviceID(), device); + EXPECT_EQ(wantNew->GetElement().GetBundleName(), bundle); + EXPECT_EQ(wantNew->GetElement().GetAbilityName(), ability); + EXPECT_EQ(wantNew->GetFlags(), flag); + + delete wantNew; + wantNew = nullptr; + } +} + +/** + * @tc.number: AaFwk_Want_ParseUri_ToUri_0300 + * @tc.name: ParseUri and ToUri + * @tc.desc: Verify the function when Want only has parameter and the parameter + * has only 1 float type element. + */ +HWTEST_F(WantBaseTest, AaFwk_Want_ParseUri_ToUri_0300, Function | MediumTest | Level1) +{ + std::string search; + std::string substring; + std::size_t pos = 0; + std::size_t length = 0; + std::size_t result = 0; + std::size_t delims = 0; + std::size_t head = 0; + Want wantOrigin; + std::string keyFloat = "keyFloat"; + float valueFloatOrigin = 123.4; + wantOrigin.SetParam(keyFloat, valueFloatOrigin); + + std::string uri = wantOrigin.ToUri(); + + search = WantBaseTest::URI_STRING_HEAD; + result = uri.find(search, pos); + EXPECT_EQ(result, pos); + if (result != std::string::npos) { + head = result + search.length(); + } + length += head; + + search = Float::SIGNATURE + std::string(".") + keyFloat + std::string("="); + result = uri.find(search); + EXPECT_NE(result, std::string::npos); + EXPECT_GE(result, head); + length += search.length(); + if (result != std::string::npos) { + pos = result + search.length(); + delims = uri.find(";", pos); + if (delims != std::string::npos) { + substring = uri.substr(pos, delims - pos); + float valueFloatNew = Float::Unbox(Float::Parse(substring)); + EXPECT_EQ(valueFloatNew, valueFloatOrigin); + length += substring.length() + 1; + } + } + + search = WantBaseTest::URI_STRING_END; + result = uri.find(search); + EXPECT_NE(result, std::string::npos); + EXPECT_GE(result, head); + if (result != std::string::npos) { + length += search.length() - 1; + } + + EXPECT_EQ(uri.length(), length); + + Want *wantNew = Want::ParseUri(uri); + EXPECT_NE(wantNew, nullptr); + + if (wantNew != nullptr) { + float floatNew = wantNew->GetFloatParam(keyFloat, 0.1); + float floatOld = wantOrigin.GetFloatParam(keyFloat, 1.1); + EXPECT_EQ(floatNew, floatOld); + delete wantNew; + } +} + +/** + * @tc.number: AaFwk_Want_ParseUri_ToUri_0400 + * @tc.name: ParseUri and ToUri + * @tc.desc: Verify the function when Want only has parameter and the parameter + * has only one float and one string type element. + */ +HWTEST_F(WantBaseTest, AaFwk_Want_ParseUri_ToUri_0400, Function | MediumTest | Level1) +{ + std::string search; + std::string substring; + std::size_t pos = 0; + std::size_t length = 0; + std::size_t result = 0; + std::size_t delims = 0; + std::size_t head = 0; + Want wantOrigin; + std::string keyFloat = "keyFloat"; + std::string keyString = "keyString"; + float valueFloatOrigin = 123.4; + std::string valueStringOrigin = "abcd"; + wantOrigin.SetParam(keyFloat, valueFloatOrigin); + wantOrigin.SetParam(keyString, valueStringOrigin); + + std::string uri = wantOrigin.ToUri(); + + search = WantBaseTest::URI_STRING_HEAD; + result = uri.find(search, pos); + EXPECT_NE(result, std::string::npos); + EXPECT_EQ(result, pos); + if (result != std::string::npos) { + head = result + search.length(); + } + length += head; + + search = Float::SIGNATURE + std::string(".") + keyFloat + std::string("="); + result = uri.find(search); + EXPECT_NE(result, std::string::npos); + EXPECT_GE(result, head); + length += search.length(); + if (result != std::string::npos) { + pos = result + search.length(); + delims = uri.find(";", pos); + if (delims != std::string::npos) { + substring = uri.substr(pos, delims - pos); + float valueFloatNew = Float::Unbox(Float::Parse(substring)); + EXPECT_EQ(valueFloatNew, valueFloatOrigin); + length += substring.length() + 1; + } + } + + search = String::SIGNATURE + std::string(".") + keyString + std::string("="); + result = uri.find(search); + EXPECT_NE(result, std::string::npos); + EXPECT_GE(result, head); + length += search.length(); + if (result != std::string::npos) { + pos = result + search.length(); + delims = uri.find(";", result); + if (delims != std::string::npos) { + std::string substring = uri.substr(pos, delims - pos); + std::string valueStringNew = String::Unbox(String::Parse(substring)); + EXPECT_EQ(valueStringNew, valueStringOrigin); + length += substring.length() + 1; + } + } + + search = WantBaseTest::URI_STRING_END; + result = uri.find(search); + EXPECT_NE(result, std::string::npos); + EXPECT_GE(result, head); + if (result != std::string::npos) { + length += search.length() - 1; + } + + EXPECT_EQ(uri.length(), length); + + Want *wantNew = Want::ParseUri(uri); + EXPECT_NE(wantNew, nullptr); + + if (wantNew != nullptr) { + float floatNew = wantNew->GetFloatParam(keyFloat, 0); + float floatOld = wantOrigin.GetFloatParam(keyFloat, 1); + EXPECT_EQ(floatNew, floatOld); + + std::string stringNew = wantNew->GetStringParam(keyString); + std::string stringOld = wantOrigin.GetStringParam(keyString); + EXPECT_EQ(stringNew, stringOld); + + delete wantNew; + } +} + +/** + * @tc.number: AaFwk_Want_ParseUri_ToUri_0500 + * @tc.name: ParseUri and ToUri + * @tc.desc: Verify the function when Want only has parameter and the parameter + * has only one float array type element. + */ +HWTEST_F(WantBaseTest, AaFwk_Want_ParseUri_ToUri_0500, Function | MediumTest | Level1) +{ + std::string search; + std::string substring; + std::size_t pos = 0; + std::size_t length = 0; + std::size_t result = 0; + std::size_t delims = 0; + std::size_t head = 0; + Want wantOrigin; + std::string keyFloatArray = "keyFloatArray"; + std::vector valueFloatArrayOrigin = {1.1, 2.1, 3.1}; + wantOrigin.SetParam(keyFloatArray, valueFloatArrayOrigin); + + std::string uri = wantOrigin.ToUri(); + + search = WantBaseTest::URI_STRING_HEAD; + result = uri.find(search, pos); + EXPECT_NE(result, std::string::npos); + EXPECT_EQ(result, pos); + if (result != std::string::npos) { + head = result + search.length(); + } + length += head; + + search = Array::SIGNATURE + std::string(".") + keyFloatArray + std::string("="); + result = uri.find(search); + EXPECT_NE(result, std::string::npos); + EXPECT_GE(result, head); + length += search.length(); + if (result != std::string::npos) { + pos = result + search.length(); + delims = uri.find(";", result); + if (delims != std::string::npos) { + std::string substring = uri.substr(pos, delims - pos); + sptr array = Array::Parse(substring); + std::vector valueFloatArrayNew; + auto func = [&valueFloatArrayNew]( + IInterface *object) { valueFloatArrayNew.push_back(Float::Unbox(IFloat::Query(object))); }; + Array::ForEach(array, func); + EXPECT_EQ(valueFloatArrayNew, valueFloatArrayOrigin); + length += substring.length() + 1; + } + } + + search = WantBaseTest::URI_STRING_END; + result = uri.find(search); + EXPECT_NE(result, std::string::npos); + EXPECT_GE(result, head); + if (result != std::string::npos) { + length += search.length() - 1; + } + + EXPECT_EQ(uri.length(), length); + + Want *wantNew = Want::ParseUri(uri); + EXPECT_NE(wantNew, nullptr); + + if (wantNew != nullptr) { + std::vector arrayNew = wantNew->GetFloatArrayParam(keyFloatArray); + std::vector arrayOld = wantOrigin.GetFloatArrayParam(keyFloatArray); + EXPECT_EQ(arrayNew, arrayOld); + delete wantNew; + } +} + +/** + * @tc.number: AaFwk_Want_ParseUri_ToUri_0600 + * @tc.name: ParseUri and ToUri + * @tc.desc: Verify the function when Want only has parameter and the parameter + * has only one int array and one string array type element + */ +HWTEST_F(WantBaseTest, AaFwk_Want_ParseUri_ToUri_0600, Function | MediumTest | Level1) +{ + std::string search; + std::string substring; + std::size_t pos = 0; + std::size_t length = 0; + std::size_t result = 0; + std::size_t delims = 0; + std::size_t head = 0; + Want wantOrigin; + std::string keyFloatArray = "keyFloatArray"; + std::string keyStringArray = "keyStringArray"; + std::vector valueFloatArrayOrigin = {1.1, 2.1, 3.1}; + std::vector valueStringArrayOrigin = {"aa", "bb", "cc"}; + wantOrigin.SetParam(keyFloatArray, valueFloatArrayOrigin); + wantOrigin.SetParam(keyStringArray, valueStringArrayOrigin); + + std::string uri = wantOrigin.ToUri(); + + search = WantBaseTest::URI_STRING_HEAD; + result = uri.find(search, pos); + EXPECT_NE(result, std::string::npos); + EXPECT_EQ(result, pos); + if (result != std::string::npos) { + head = result + search.length(); + } + length += head; + + search = Array::SIGNATURE + std::string(".") + keyFloatArray + std::string("="); + result = uri.find(search); + EXPECT_NE(result, std::string::npos); + EXPECT_GE(result, head); + length += search.length(); + if (result != std::string::npos) { + pos = result + search.length(); + delims = uri.find(";", result); + if (delims != std::string::npos) { + std::string substring = uri.substr(pos, delims - pos); + sptr array = Array::Parse(substring); + std::vector valueFloatArrayNew; + auto func = [&valueFloatArrayNew]( + IInterface *object) { valueFloatArrayNew.push_back(Float::Unbox(IFloat::Query(object))); }; + Array::ForEach(array, func); + EXPECT_EQ(valueFloatArrayNew, valueFloatArrayOrigin); + length += substring.length() + 1; + } + } + + search = Array::SIGNATURE + std::string(".") + keyStringArray + std::string("="); + result = uri.find(search); + EXPECT_NE(result, std::string::npos); + EXPECT_GE(result, head); + length += search.length(); + if (result != std::string::npos) { + pos = result + search.length(); + delims = uri.find(";", result); + if (delims != std::string::npos) { + std::string substring = uri.substr(pos, delims - pos); + sptr array = Array::Parse(substring); + std::vector valueStringArrayNew; + auto func = [&valueStringArrayNew](IInterface *object) { + valueStringArrayNew.push_back(String::Unbox(IString::Query(object))); + }; + Array::ForEach(array, func); + EXPECT_EQ(valueStringArrayNew, valueStringArrayOrigin); + length += substring.length() + 1; + } + } + + search = WantBaseTest::URI_STRING_END; + result = uri.find(search); + EXPECT_NE(result, std::string::npos); + EXPECT_GE(result, head); + if (result != std::string::npos) { + length += search.length() - 1; + } + + EXPECT_EQ(uri.length(), length); + + Want *wantNew = Want::ParseUri(uri); + EXPECT_NE(wantNew, nullptr); + + if (wantNew != nullptr) { + std::vector arrayFloatNew = wantNew->GetFloatArrayParam(keyFloatArray); + std::vector arrayFloatOld = wantOrigin.GetFloatArrayParam(keyFloatArray); + EXPECT_EQ(arrayFloatNew, arrayFloatOld); + + std::vector arrayStringNew = wantNew->GetStringArrayParam(keyStringArray); + std::vector arrayStringOld = wantOrigin.GetStringArrayParam(keyStringArray); + EXPECT_EQ(arrayStringNew, arrayStringOld); + + delete wantNew; + } +} + +/** + * @tc.number: AaFwk_Want_ParseUri_ToUri_0700 + * @tc.name: ParseUri and ToUri + * @tc.desc: Verify the function when the length of input string is 0. + */ +HWTEST_F(WantBaseTest, AaFwk_Want_ParseUri_ToUri_0700, Function | MediumTest | Level1) +{ + std::string uri; + EXPECT_EQ(static_cast(uri.length()), 0); + + Want *want = Want::ParseUri(uri); + EXPECT_EQ(want, nullptr); + + if (want != nullptr) { + delete want; + } +} + +/** + * @tc.number: AaFwk_Want_ParseUri_ToUri_0800 + * @tc.name: ParseUri and ToUri + * @tc.desc: Verify the function when the action etc. are empty. + */ +HWTEST_F(WantBaseTest, AaFwk_Want_ParseUri_ToUri_0800, Function | MediumTest | Level1) +{ + std::string empty; + std::string uri = "#Intent;action=;entity=;device=;bundle=;ability=;flag=;end"; + EXPECT_NE(static_cast(uri.length()), 0); + + Want *want = Want::ParseUri(uri); + EXPECT_NE(want, nullptr); + + if (want != nullptr) { + EXPECT_EQ(want->GetAction(), empty); + for (auto entityItem : want->GetEntities()) { + EXPECT_EQ(entityItem, empty); + } + EXPECT_EQ(want->GetFlags(), (unsigned int)0); + OHOS::AppExecFwk::ElementName element; + EXPECT_EQ(want->GetElement(), element); + EXPECT_EQ(want->HasParameter(empty), false); + delete want; + } +} + +/** + * @tc.number: AaFwk_Want_ParseUri_ToUri_0900 + * @tc.name: ParseUri and ToUri + * @tc.desc: Verify the function when flag is not number. + */ +HWTEST_F(WantBaseTest, AaFwk_Want_ParseUri_ToUri_0900, Function | MediumTest | Level1) +{ + std::string empty; + std::string uri = "#Intent;action=want.action.VIEW;flag=\"123\";end"; + EXPECT_NE(static_cast(uri.length()), 0); + + Want *want = Want::ParseUri(uri); + EXPECT_EQ(want, nullptr); + if (want != nullptr) { + delete want; + want = nullptr; + } +} + +/** + * @tc.number: AaFwk_Want_ParseUri_ToUri_1000 + * @tc.name: ParseUri and ToUri + * @tc.desc: Verify the function when head is not "#Intent". + */ +HWTEST_F(WantBaseTest, AaFwk_Want_ParseUri_ToUri_1000, Function | MediumTest | Level1) +{ + std::string empty; + std::string uri = "action=want.action.VIEW;end"; + EXPECT_NE(static_cast(uri.length()), 0); + + Want *want = Want::ParseUri(uri); + EXPECT_EQ(want, nullptr); + if (want != nullptr) { + delete want; + want = nullptr; + } +} + +/** + * @tc.number: AaFwk_Want_ParseUri_ToUri_1100 + * @tc.name: ParseUri and ToUri + * @tc.desc: Verify the function when flag is empty. + */ +HWTEST_F(WantBaseTest, AaFwk_Want_ParseUri_ToUri_1100, Function | MediumTest | Level1) +{ + std::string empty; + std::string uri = "#Intent;flag=;end"; + EXPECT_NE(static_cast(uri.length()), 0); + + Want *want = Want::ParseUri(uri); + EXPECT_NE(want, nullptr); + + if (want != nullptr) { + EXPECT_EQ(want->GetFlags(), static_cast(0)); + delete want; + } +} + +/** + * @tc.number: AaFwk_Want_ParseUri_ToUri_1200 + * @tc.name: ParseUri and ToUri + * @tc.desc: Verify the function when x is capital. + */ +HWTEST_F(WantBaseTest, AaFwk_Want_ParseUri_ToUri_1200, Function | MediumTest | Level1) +{ + std::string empty; + unsigned int flag = 0X12345678; + std::string uri = "#Intent;flag=0X12345678;end"; + EXPECT_NE(static_cast(uri.length()), 0); + + Want *want = Want::ParseUri(uri); + EXPECT_NE(want, nullptr); + + if (want != nullptr) { + EXPECT_EQ(want->GetFlags(), flag); + delete want; + } +} + +/** + * @tc.number: AaFwk_Want_ParseUri_ToUri_1300 + * @tc.name: ParseUri and ToUri + * @tc.desc: Verify the function when special character. + */ +HWTEST_F(WantBaseTest, AaFwk_Want_ParseUri_ToUri_1300, Function | MediumTest | Level1) +{ + std::string action = "\\"; + std::string entity = "../../../jj/j=075/./.;;/07507399/\\\\;;--==.com.\a\b\tfoobar.vide\073\\075"; + unsigned int flag = 0x0f0f0f0f; + std::string flagStr = "0x0f0f0f0f"; + std::string key = "\\kkk=.=;"; + std::string value = "==\\\\\\.;\\;\\;\\=\\\073075\\\\075073"; + + Want wantOrigin; + wantOrigin.SetAction(action); + wantOrigin.AddEntity(entity); + wantOrigin.AddFlags(flag); + wantOrigin.SetParam(key, value); + + std::string uri = wantOrigin.ToUri(); + + Want *wantNew = Want::ParseUri(uri); + EXPECT_NE(wantNew, nullptr); + + if (wantNew != nullptr) { + EXPECT_STREQ(wantNew->GetAction().c_str(), action.c_str()); + for (auto entityItem : wantNew->GetEntities()) { + EXPECT_EQ(entityItem, entity); + } + EXPECT_EQ(wantNew->GetFlags(), flag); + EXPECT_EQ(wantNew->GetStringParam(key), value); + + delete wantNew; + wantNew = nullptr; + } +} + +/** + * @tc.number: AaFwk_Want_ParseUri_ToUri_1400 + * @tc.name: ParseUri and ToUri + * @tc.desc: Verify the function when no '=' or only has a '='. + */ +HWTEST_F(WantBaseTest, AaFwk_Want_ParseUri_ToUri_1400, Function | MediumTest | Level1) +{ + std::string uri = "#Intent;action;end"; + Want *want = Want::ParseUri(uri); + EXPECT_EQ(want, nullptr); + if (want != nullptr) { + delete want; + want = nullptr; + } + + uri = "#Intent;entity;end"; + want = Want::ParseUri(uri); + EXPECT_EQ(want, nullptr); + if (want != nullptr) { + delete want; + want = nullptr; + } + + uri = "#Intent;device;end"; + want = Want::ParseUri(uri); + EXPECT_EQ(want, nullptr); + if (want != nullptr) { + delete want; + want = nullptr; + } + + uri = "#Intent;bundle;end"; + want = Want::ParseUri(uri); + EXPECT_EQ(want, nullptr); + if (want != nullptr) { + delete want; + want = nullptr; + } + + uri = "#Intent;ability;end"; + want = Want::ParseUri(uri); + EXPECT_EQ(want, nullptr); + if (want != nullptr) { + delete want; + want = nullptr; + } + + uri = "#Intent;flag;end"; + want = Want::ParseUri(uri); + EXPECT_EQ(want, nullptr); + if (want != nullptr) { + delete want; + want = nullptr; + } + + uri = "#Intent;param;end"; + want = Want::ParseUri(uri); + EXPECT_EQ(want, nullptr); + if (want != nullptr) { + delete want; + want = nullptr; + } + + uri = "#Intent;=;end"; + want = Want::ParseUri(uri); + EXPECT_NE(want, nullptr); + if (want != nullptr) { + delete want; + want = nullptr; + } + + uri = "#Intent;abc=;end"; + want = Want::ParseUri(uri); + EXPECT_NE(want, nullptr); + if (want != nullptr) { + delete want; + want = nullptr; + } + + uri = "#Intent;=abc;end"; + want = Want::ParseUri(uri); + EXPECT_NE(want, nullptr); + if (want != nullptr) { + delete want; + want = nullptr; + } + + uri = "#Intent;xxxx=yyy;end"; + want = Want::ParseUri(uri); + EXPECT_NE(want, nullptr); + if (want != nullptr) { + delete want; + want = nullptr; + } + + uri = "#Intent;;;;;;end"; + want = Want::ParseUri(uri); + EXPECT_NE(want, nullptr); + if (want != nullptr) { + delete want; + want = nullptr; + } +} + +/** + * @tc.number: AaFwk_Want_Flags_0100 + * @tc.name: SetFlags/AddFlags/GetFlags/RemoveFlags + * @tc.desc: Verify SetFlags/AddFlags/GetFlags/RemoveFlags. + */ +HWTEST_F(WantBaseTest, AaFwk_Want_Flags_0100, Function | MediumTest | Level1) +{ + int flags = 3; + int returnsflags; + int description = 8; + + want_->SetFlags(description); + want_->AddFlags(flags); + returnsflags = want_->GetFlags(); + EXPECT_EQ(11, returnsflags); + + want_->RemoveFlags(flags); + returnsflags = want_->GetFlags(); + EXPECT_EQ(description, returnsflags); +} + +/** + * @tc.number: AaFwk_Want_MakeMainAbility_0100 + * @tc.name: MakeMainAbility + * @tc.desc: Verify MakeMainAbility. + */ +HWTEST_F(WantBaseTest, AaFwk_Want_MakeMainAbility_0100, Function | MediumTest | Level1) +{ + ElementName elementName; + + std::string action("action.system.home"); + std::string entity("entity.system.home"); + + Want *wantNew = want_->MakeMainAbility(elementName); + if (wantNew != nullptr) { + std::vector entities = wantNew->GetEntities(); + + EXPECT_EQ((size_t)1, entities.size()); + if (entities.size() > 0) { + EXPECT_EQ(entity, entities.at(0)); + } + EXPECT_EQ(action, wantNew->GetAction()); + EXPECT_EQ(elementName, wantNew->GetElement()); + + delete wantNew; + wantNew = nullptr; + } +} + +/** + * @tc.number: AaFwk_Want_ClearWant_0100 + * @tc.name: ClearWant + * @tc.desc: Verify ClearWant. + */ +HWTEST_F(WantBaseTest, AaFwk_Want_ClearWant_0100, Function | MediumTest | Level1) +{ + Want want; + ElementName elementName; + std::string empty = ""; + want_->ClearWant(&want); + + EXPECT_EQ((uint)0, want_->GetFlags()); + EXPECT_EQ(empty, want_->GetType()); + EXPECT_EQ(empty, want_->GetAction()); + EXPECT_EQ(elementName, want_->GetElement()); + EXPECT_EQ((size_t)0, want_->GetEntities().size()); + EXPECT_EQ(0, want_->CountEntities()); +} + +/** + * @tc.number: AaFwk_Want_replaceParams_0100 + * @tc.name: replaceParams(wantParams) + * @tc.desc: Verify the function when the input string is empty. + */ +HWTEST_F(WantBaseTest, AaFwk_Want_replaceParams_0100, Function | MediumTest | Level1) +{ + WantParams wantParams; + std::string keyStr = "123"; + std::string valueStr = "123"; + wantParams.SetParam(keyStr, String::Box(valueStr)); + want_->ReplaceParams(wantParams); + + EXPECT_EQ(valueStr, String::Unbox(IString::Query(want_->GetParams().GetParam(keyStr)))); +} + +/** + * @tc.number: AaFwk_Want_setElement_0100 + * @tc.name:setElement / setElementName + * @tc.desc: Verify the function when the input string is empty. + */ +HWTEST_F(WantBaseTest, AaFwk_Want_setElement_0100, Function | MediumTest | Level1) +{ + std::string valueStr1 = "xxxxx"; + std::string valueStr2 = "uaid"; + std::string valueStr3 = "uaygfi"; + + OHOS::AppExecFwk::ElementName elementname1; + OHOS::AppExecFwk::ElementName elementname2; + OHOS::AppExecFwk::ElementName elementname3; + ElementName elementname4; + elementname1.SetAbilityName(valueStr1); + elementname2.SetDeviceID(valueStr2); + elementname3.SetBundleName(valueStr3); + want_->SetElement(elementname1); + EXPECT_EQ(valueStr1, want_->GetElement().GetAbilityName()); + + want_->SetElement(elementname2); + EXPECT_EQ(valueStr2, want_->GetElement().GetDeviceID()); + + want_->SetElement(elementname3); + EXPECT_EQ(valueStr3, want_->GetElement().GetBundleName()); + + want_->SetElementName(valueStr3, valueStr1); + EXPECT_EQ(valueStr1, want_->GetElement().GetAbilityName()); + EXPECT_EQ(valueStr3, want_->GetElement().GetBundleName()); + + want_->SetElementName(valueStr2, valueStr3, valueStr1); + EXPECT_EQ(valueStr1, want_->GetElement().GetAbilityName()); + EXPECT_EQ(valueStr2, want_->GetElement().GetDeviceID()); + EXPECT_EQ(valueStr3, want_->GetElement().GetBundleName()); +} + +/** + * @tc.number: AaFwk_Want_Action_0200 + * @tc.name:SetAction / GetAction + * @tc.desc: Verify the function when the input string is empty. + */ +HWTEST_F(WantBaseTest, AaFwk_Want_Action_0200, Function | MediumTest | Level1) +{ + std::string setValue; + want_->SetAction(setValue); + EXPECT_EQ(setValue, want_->GetAction()); +} + +/** + * @tc.number: AaFwk_Want_Action_0300 + * @tc.name:SetAction / GetAction + * @tc.desc: Verify the function when the input string contains special characters. + */ +HWTEST_F(WantBaseTest, AaFwk_Want_Action_0300, Function | MediumTest | Level1) +{ + std::string setValue("action.system.com"); + want_->SetAction(setValue); + EXPECT_STREQ(setValue.c_str(), want_->GetAction().c_str()); +} + +using testByteType = std::tuple; +class WantParametersBoolArrayTest : public testing::TestWithParam { +public: + WantParametersBoolArrayTest() + { + want_ = nullptr; + } + ~WantParametersBoolArrayTest() + { + want_ = nullptr; + } + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + std::shared_ptr want_; +}; + +void WantParametersBoolArrayTest::SetUpTestCase(void) +{} + +void WantParametersBoolArrayTest::TearDownTestCase(void) +{} + +void WantParametersBoolArrayTest::SetUp(void) +{ + want_ = std::make_shared(); +} + +void WantParametersBoolArrayTest::TearDown(void) +{} + +/** + * @tc.number: AaFwk_Want_BoolArray_0100 + * @tc.name:SetBoolArrayParam/GetBoolArrayParam + * @tc.desc: Verify when parameter change. + */ +HWTEST_P(WantParametersBoolArrayTest, AaFwk_Want_BoolArray_0100, Function | MediumTest | Level1) +{ + std::string setKey = std::get<0>(GetParam()); + std::string getKey = std::get<1>(GetParam()); + byte setValue = std::get<2>(GetParam()); + byte defaultValue = std::get<3>(GetParam()); + byte result = std::get<4>(GetParam()); + want_->SetParam(setKey, setValue); + EXPECT_EQ(result, want_->GetByteParam(getKey, defaultValue)); +} + +INSTANTIATE_TEST_CASE_P(WantParametersBoolArrayTestCaseP, WantParametersBoolArrayTest, + testing::Values(testByteType("", "aa", '#', 'U', 'U'), testByteType("", "", 'N', 'K', 'N'), + testByteType("1*中_aR", "aa", 'a', '%', '%'), testByteType("1*中_aR", "1*中_aR", 'a', 'z', 'a'))); + +using testBoolArrayType = std::tuple, std::vector, std::vector>; +class WantBoolArrayParamTest : public testing::TestWithParam { +public: + WantBoolArrayParamTest() + { + want_ = nullptr; + } + ~WantBoolArrayParamTest() + { + want_ = nullptr; + } + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + std::shared_ptr want_; +}; + +void WantBoolArrayParamTest::SetUpTestCase(void) +{} + +void WantBoolArrayParamTest::TearDownTestCase(void) +{} + +void WantBoolArrayParamTest::SetUp(void) +{ + want_ = std::make_shared(); +} + +void WantBoolArrayParamTest::TearDown(void) +{} + +/** + * @tc.number: AaFwk_Want_BoolArray_0200 + * @tc.name:SetBoolArrayParam/GetBoolArrayParam + * @tc.desc: Verify when parameter change. + */ +HWTEST_P(WantBoolArrayParamTest, AaFwk_Want_BoolArray_0200, Function | MediumTest | Level1) +{ + std::string setKey = std::get<0>(GetParam()); + std::string getKey = std::get<1>(GetParam()); + std::vector setValue = std::get<2>(GetParam()); + std::vector defaultValue = std::get<3>(GetParam()); + std::vector result = std::get<4>(GetParam()); + want_->SetParam(setKey, setValue); + EXPECT_EQ(result, want_->GetBoolArrayParam(getKey)); +} + +INSTANTIATE_TEST_CASE_P(WantBoolArrayParamTestCaseP, WantBoolArrayParamTest, + testing::Values(testBoolArrayType("", "aa", {true, false}, {}, {}), + testBoolArrayType("", "", {true, false}, {}, {true, false}), + testBoolArrayType("1*中_aR", "aa", {true, false}, {}, {}), + testBoolArrayType("1*中_aR", "1*中_aR", {false, true}, {}, {false, true}))); + +using testCharArrayType = + std::tuple, std::vector, std::vector>; +class WantCharArrayParamTest : public testing::TestWithParam { +public: + WantCharArrayParamTest() + { + want_ = nullptr; + } + ~WantCharArrayParamTest() + { + want_ = nullptr; + } + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + std::shared_ptr want_; +}; + +void WantCharArrayParamTest::SetUpTestCase(void) +{} + +void WantCharArrayParamTest::TearDownTestCase(void) +{} + +void WantCharArrayParamTest::SetUp(void) +{ + want_ = std::make_shared(); +} + +void WantCharArrayParamTest::TearDown(void) +{} + +/** + * @tc.number: AaFwk_Want_Parameters_CharArray_0100 + * @tc.name: SetParam/GetCharArrayParam + * @tc.desc: Verify when parameter change. + */ +HWTEST_P(WantCharArrayParamTest, AaFwk_Want_Parameters_CharArray_0100, Function | MediumTest | Level1) +{ + std::string setKey = std::get<0>(GetParam()); + std::string getKey = std::get<1>(GetParam()); + std::vector setValue = std::get<2>(GetParam()); + std::vector defaultValue = std::get<3>(GetParam()); + std::vector result = std::get<4>(GetParam()); + want_->SetParam(setKey, setValue); + EXPECT_EQ(result, want_->GetCharArrayParam(getKey)); +} + +INSTANTIATE_TEST_CASE_P(WantCharArrayParamTestCaseP, WantCharArrayParamTest, + testing::Values(testCharArrayType("", "aa", {U'中', U'文'}, {}, {}), + testCharArrayType("", "", {U'中', U'文'}, {}, {U'中', U'文'}), + testCharArrayType("1*中_aR", "aa", {U'中', U'文'}, {}, {}), + testCharArrayType("1*中_aR", "1*中_aR", {U'中', U'文'}, {}, {U'中', U'文'}))); + +/** + * @tc.number: AaFwk_Want_Parameters_CharArray_0200 + * @tc.name: GetCharArrayParam + * @tc.desc: Verify when the value is char array. + */ +HWTEST_F(WantCharArrayParamTest, AaFwk_Want_Parameters_CharArray_0200, Function | MediumTest | Level1) +{ + std::vector defaultValue; + std::string getKey("aa"); + EXPECT_EQ(defaultValue, want_->GetCharArrayParam(getKey)); +} + +/** + * @tc.number: AaFwk_Want_Parameters_CharArray_0300 + * @tc.name: SetParam/GetCharArrayParam + * @tc.desc: Verify when the value is char array. + */ +HWTEST_F(WantCharArrayParamTest, AaFwk_Want_Parameters_CharArray_0300, Function | MediumTest | Level1) +{ + std::string emptyStr("ff"); + std::vector firstValue({U'中', U'文'}); + std::vector secondValue({U'字', U'符'}); + std::vector thirdValue({U'集', U'英'}); + std::string keyStr("aa"); + want_->SetParam(emptyStr, firstValue); + want_->SetParam(emptyStr, firstValue); + want_->SetParam(emptyStr, secondValue); + std::vector defaultValue; + EXPECT_EQ(defaultValue, want_->GetCharArrayParam(keyStr)); + want_->SetParam(emptyStr, thirdValue); + EXPECT_EQ(thirdValue, want_->GetCharArrayParam(emptyStr)); +} + +/** + * @tc.number: AaFwk_Want_Parameters_CharArray_0400 + * @tc.name: SetParam/GetCharArrayParam + * @tc.desc: Verify when the value is char array. + */ +HWTEST_F(WantCharArrayParamTest, AaFwk_Want_Parameters_CharArray_0400, Function | MediumTest | Level1) +{ + std::string firstKey("%1uH3"); + std::vector firstValue({U'中', U'文'}); + std::vector secondValue({U'字', U'符'}); + std::vector defaultValue; + std::string secondKey("aa"); + want_->SetParam(firstKey, firstValue); + want_->SetParam(firstKey, firstValue); + want_->SetParam(firstKey, secondValue); + EXPECT_EQ(secondValue, want_->GetCharArrayParam(firstKey)); + want_->SetParam(firstKey, firstValue); + EXPECT_EQ(defaultValue, want_->GetCharArrayParam(secondKey)); +} + +using testCharType = std::tuple; +class WantCharParamTest : public testing::TestWithParam { +public: + WantCharParamTest() + { + want_ = nullptr; + } + ~WantCharParamTest() + { + want_ = nullptr; + } + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + std::shared_ptr want_; +}; + +void WantCharParamTest::SetUpTestCase(void) +{} + +void WantCharParamTest::TearDownTestCase(void) +{} + +void WantCharParamTest::SetUp(void) +{ + want_ = std::make_shared(); +} + +void WantCharParamTest::TearDown(void) +{} + +/** + * @tc.number: AaFwk_Want_Parameters_Char_0100 + * @tc.name: SetParam/GetCharParam + * @tc.desc: Verify when the value is char array. + */ +HWTEST_P(WantCharParamTest, AaFwk_Want_Parameters_Char_0100, Function | MediumTest | Level1) +{ + std::string setKey = std::get<0>(GetParam()); + std::string getKey = std::get<1>(GetParam()); + zchar setValue = std::get<2>(GetParam()); + zchar defaultValue = std::get<3>(GetParam()); + zchar result = std::get<4>(GetParam()); + want_->SetParam(setKey, setValue); + EXPECT_EQ(result, want_->GetCharParam(getKey, defaultValue)); +} + +INSTANTIATE_TEST_CASE_P(WantParametersCharTestCaseP, WantCharParamTest, + testing::Values(testCharType("", "aa", U'#', U'中', U'中'), testCharType("", "", U'中', U'K', U'中'), + testCharType("1*中_aR", "aa", U'a', U'中', U'中'), testCharType("1*中_aR", "1*中_aR", U'中', U'z', U'中'))); + +/** + * @tc.number: AaFwk_Want_Parameters_Char_0200 + * @tc.name: SetParam/GetCharParam + * @tc.desc: Verify when the value is char + */ +HWTEST_F(WantCharParamTest, AaFwk_Want_Parameters_Char_0200, Function | MediumTest | Level1) +{ + zchar defaultValue = U'文'; + std::string getKey("aa"); + EXPECT_EQ(defaultValue, want_->GetCharParam(getKey, defaultValue)); +} + +/** + * @tc.number: AaFwk_Want_Parameters_Char_0300 + * @tc.name: SetParam/GetCharParam + * @tc.desc: Verify when the value is char. + */ +HWTEST_F(WantCharParamTest, AaFwk_Want_Parameters_Char_0300, Function | MediumTest | Level1) +{ + std::string emptyStr("jj"); + zchar firstValue = U'中'; + zchar secondValue = U'文'; + zchar thirdValue = U'字'; + zchar firstDefaultValue = U'符'; + zchar secondDefaultValue = U'集'; + std::string keyStr("aa"); + want_->SetParam(emptyStr, firstValue); + want_->SetParam(emptyStr, firstValue); + want_->SetParam(emptyStr, secondValue); + EXPECT_EQ(firstDefaultValue, want_->GetCharParam(keyStr, firstDefaultValue)); + want_->SetParam(emptyStr, thirdValue); + EXPECT_EQ(thirdValue, want_->GetCharParam(emptyStr, secondDefaultValue)); +} + +/** + * @tc.number: AaFwk_Want_Parameters_Char_0400 + * @tc.name: SetParam/GetCharParam + * @tc.desc: Verify when the value is char. + */ +HWTEST_F(WantCharParamTest, AaFwk_Want_Parameters_Char_0400, Function | MediumTest | Level1) +{ + std::string firstKey("%1uH3"); + zchar firstValue = U'中'; + zchar secondValue = U'文'; + zchar firstDefaultValue = U'字'; + zchar secondDefaultValue = U'符'; + std::string secondKey("aa"); + want_->SetParam(firstKey, firstValue); + want_->SetParam(firstKey, firstValue); + want_->SetParam(firstKey, secondValue); + EXPECT_EQ(secondValue, want_->GetCharParam(firstKey, firstDefaultValue)); + want_->SetParam(firstKey, firstValue); + EXPECT_EQ(secondDefaultValue, want_->GetCharParam(secondKey, secondDefaultValue)); +} + +using testDoubleArrayType = + std::tuple, std::vector, std::vector>; +class WantDoubleArrayParamTest : public testing::TestWithParam { +public: + WantDoubleArrayParamTest() + { + want_ = nullptr; + } + ~WantDoubleArrayParamTest() + { + want_ = nullptr; + } + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + std::shared_ptr want_; +}; + +void WantDoubleArrayParamTest::SetUpTestCase(void) +{} + +void WantDoubleArrayParamTest::TearDownTestCase(void) +{} + +void WantDoubleArrayParamTest::SetUp(void) +{ + want_ = std::make_shared(); +} + +void WantDoubleArrayParamTest::TearDown(void) +{} + +/** + * @tc.number: AaFwk_Want_DoubleArray_0100 + * @tc.name: SetParam/GetDoubleArrayParam + * @tc.desc: Verify when parameter change. + */ +HWTEST_P(WantDoubleArrayParamTest, AaFwk_Want_DoubleArray_0100, Function | MediumTest | Level1) +{ + std::string setKey = std::get<0>(GetParam()); + std::string getKey = std::get<1>(GetParam()); + std::vector setValue = std::get<2>(GetParam()); + std::vector defaultValue = std::get<3>(GetParam()); + std::vector result = std::get<4>(GetParam()); + want_->SetParam(setKey, setValue); + EXPECT_EQ(result, want_->GetDoubleArrayParam(getKey)); +} + +INSTANTIATE_TEST_CASE_P(WantDoubleArrayParamTestCaseP, WantDoubleArrayParamTest, + testing::Values(testDoubleArrayType("", "aa", {-1.1, -2.1}, {}, {}), + testDoubleArrayType("", "", {-41.1, -42.1}, {}, {-41.1, -42.1}), + testDoubleArrayType("1*中_aR", "aa", {50.1, 51.1}, {}, {}), + testDoubleArrayType("1*中_aR", "1*中_aR", {5000.1, 5001.1}, {}, {5000.1, 5001.1}))); + +/** + * @tc.number: AaFwk_Want_DoubleArray_0200 + * @tc.name: SetParam/GetDoubleArrayParam + * @tc.desc: Verify when parameter change. + */ +HWTEST_F(WantDoubleArrayParamTest, AaFwk_Want_DoubleArray_0200, Function | MediumTest | Level1) +{ + std::vector defaultValue; + std::string key = "aa"; + EXPECT_EQ(defaultValue, want_->GetDoubleArrayParam(key)); +} + +/** + * @tc.number: AaFwk_Want_DoubleArray_0300 + * @tc.name: SetParam/GetDoubleArrayParam + * @tc.desc: set empty-string key repeatedly, but get param of another nonexistent key + */ +HWTEST_F(WantDoubleArrayParamTest, AaFwk_Want_DoubleArray_0300, Function | MediumTest | Level1) +{ + std::vector defaultValue; + std::string setKey1 = "cc"; + std::string setKey2 = "aa"; + std::vector setValue1 = {1.1, 2.1}; + std::vector setValue2 = {5.1, 6.1}; + want_->SetParam(setKey1, setValue1); + want_->SetParam(setKey1, setValue1); + setValue1 = {2.1, 3.1}; + want_->SetParam(setKey1, setValue1); + EXPECT_EQ(defaultValue, want_->GetDoubleArrayParam(setKey2)); + setValue1 = {4.1, 5.1}; + want_->SetParam(setKey1, setValue1); + EXPECT_EQ(setValue1, want_->GetDoubleArrayParam(setKey1)); +} + +/** + * @tc.number: AaFwk_Want_DoubleArray_0400 + * @tc.name: SetParam/GetDoubleArrayParam + * @tc.desc: set empty-string key repeatedly, then get param of the key + */ +HWTEST_F(WantDoubleArrayParamTest, AaFwk_Want_DoubleArray_0400, Function | MediumTest | Level1) +{ + std::vector defaultValue; + std::string setKey1 = "%1uH3"; + std::string setKey2 = "aa"; + std::vector setValue1 = {-1.1, -2.1}; + std::vector setValue2 = {9.1, 10.1}; + want_->SetParam(setKey1, setValue1); + want_->SetParam(setKey1, setValue1); + setValue1 = {0.1, 1.1}; + want_->SetParam(setKey1, setValue1); + EXPECT_EQ(setValue1, want_->GetDoubleArrayParam(setKey1)); + setValue1 = {4.1, 5.1}; + want_->SetParam(setKey1, setValue1); + setValue1 = {-10.1, -11.1}; + EXPECT_EQ(defaultValue, want_->GetDoubleArrayParam(setKey2)); +} + +using testFloatArrayType = + std::tuple, std::vector, std::vector>; +class WantFloatArrayParamTest : public testing::TestWithParam { +public: + WantFloatArrayParamTest() + { + want_ = nullptr; + } + ~WantFloatArrayParamTest() + { + want_ = nullptr; + } + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + std::shared_ptr want_; +}; + +void WantFloatArrayParamTest::SetUpTestCase(void) +{} + +void WantFloatArrayParamTest::TearDownTestCase(void) +{} + +void WantFloatArrayParamTest::SetUp(void) +{ + want_ = std::make_shared(); +} + +void WantFloatArrayParamTest::TearDown(void) +{} + +/** + * @tc.number: AaFwk_Want_FloatArray_0100 + * @tc.name: SetParam/GetFloatArrayParam + * @tc.desc: Verify when parameter change. + */ +HWTEST_P(WantFloatArrayParamTest, AaFwk_Want_FloatArray_0100, Function | MediumTest | Level1) +{ + std::string setKey = std::get<0>(GetParam()); + std::string getKey = std::get<1>(GetParam()); + std::vector setValue = std::get<2>(GetParam()); + std::vector defaultValue = std::get<3>(GetParam()); + std::vector result = std::get<4>(GetParam()); + want_->SetParam(setKey, setValue); + EXPECT_EQ(result, want_->GetFloatArrayParam(getKey)); +} + +INSTANTIATE_TEST_CASE_P(WantFloatArrayParamTestCaseP, WantFloatArrayParamTest, + testing::Values(testFloatArrayType("", "aa", {-1.1, -2.1}, {}, {}), + testFloatArrayType("", "", {-41.1, -42.1}, {}, {-41.1, -42.1}), + testFloatArrayType("1*中_aR", "aa", {50.1, 51.1}, {}, {}), + testFloatArrayType("1*中_aR", "1*中_aR", {5000.1, 5001.1}, {}, {5000.1, 5001.1}))); + +/** + * @tc.number: AaFwk_Want_FloatArray_0200 + * @tc.name: SetParam/GetFloatArrayParam + * @tc.desc: get param when WantParam is empty + */ +HWTEST_F(WantFloatArrayParamTest, AaFwk_Want_FloatArray_0200, Function | MediumTest | Level1) +{ + std::vector defaultValue; + std::string key = "aa"; + EXPECT_EQ(defaultValue, want_->GetFloatArrayParam(key)); +} + +/** + * @tc.number: AaFwk_Want_FloatArray_0300 + * @tc.name: SetParam & GetFloatArrayParam + * @tc.desc: set empty-string key repeatedly, but get param of another nonexistent key + */ +HWTEST_F(WantFloatArrayParamTest, AaFwk_Want_FloatArray_0300, Function | MediumTest | Level1) +{ + std::vector defaultValue; + std::string setKey1 = "hh"; + std::string setKey2 = "aa"; + std::vector setValue1 = {1.1, 2.1}; + want_->SetParam(setKey1, setValue1); + want_->SetParam(setKey1, setValue1); + setValue1 = {2.1, 3.1}; + want_->SetParam(setKey1, setValue1); + EXPECT_EQ(defaultValue, want_->GetFloatArrayParam(setKey2)); + setValue1 = {4.1, 5.1}; + want_->SetParam(setKey1, setValue1); + EXPECT_EQ(setValue1, want_->GetFloatArrayParam(setKey1)); +} + +/** + * @tc.number: AaFwk_Want_FloatArray_0400 + * @tc.name: SetParam & GetFloatArrayParam + * @tc.desc: set empty-string key repeatedly, then get param of the key + */ +HWTEST_F(WantFloatArrayParamTest, AaFwk_Want_FloatArray_0400, Function | MediumTest | Level1) +{ + std::vector defaultValue; + std::string setKey1 = "%1uH3"; + std::string setKey2 = "aa"; + std::vector setValue1 = {-1.1, -2.1}; + std::vector setValue2 = {9.1, 10.1}; + want_->SetParam(setKey1, setValue1); + want_->SetParam(setKey1, setValue1); + setValue1 = {0.1, 1.1}; + want_->SetParam(setKey1, setValue1); + EXPECT_EQ(setValue1, want_->GetFloatArrayParam(setKey1)); + setValue1 = {4.1, 5.1}; + want_->SetParam(setKey1, setValue1); + EXPECT_EQ(defaultValue, want_->GetFloatArrayParam(setKey2)); +} + +using testLongArrayType = std::tuple, std::vector, std::vector>; +class WantLongArrayParamTest : public testing::TestWithParam { +public: + WantLongArrayParamTest() + { + want_ = nullptr; + } + ~WantLongArrayParamTest() + { + want_ = nullptr; + } + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + std::shared_ptr want_; +}; + +void WantLongArrayParamTest::SetUpTestCase(void) +{} + +void WantLongArrayParamTest::TearDownTestCase(void) +{} + +void WantLongArrayParamTest::SetUp(void) +{ + want_ = std::make_shared(); +} + +void WantLongArrayParamTest::TearDown(void) +{} + +/** + * @tc.number: AaFwk_Want_LongArray_0100 + * @tc.name: SetParam & GetLongArrayParam + * @tc.desc: Verify when parameter change. + */ +HWTEST_P(WantLongArrayParamTest, AaFwk_Want_LongArray_0100, Function | MediumTest | Level1) +{ + std::string setKey = std::get<0>(GetParam()); + std::string getKey = std::get<1>(GetParam()); + std::vector setValue = std::get<2>(GetParam()); + std::vector defaultValue = std::get<3>(GetParam()); + std::vector result = std::get<4>(GetParam()); + want_->SetParam(setKey, setValue); + EXPECT_EQ(result, want_->GetLongArrayParam(getKey)); +} + +INSTANTIATE_TEST_CASE_P(WantLongArrayParamTestCaseP, WantLongArrayParamTest, + testing::Values(testLongArrayType("", "aa", {-1, 3, 25, -9}, {}, {}), + testLongArrayType("", "", {-41, 0, 0, 9}, {}, {-41, 0, 0, 9}), + testLongArrayType("1*中_aR", "aa", {50, 2, -9}, {}, {}), + testLongArrayType("1*中_aR", "1*中_aR", {-5000}, {}, {-5000}))); + +/** + * @tc.number: AaFwk_Want_LongArray_0200 + * @tc.name: SetParam & GetLongArrayParam + * @tc.desc: get param when WantParam is empty + */ +HWTEST_F(WantLongArrayParamTest, AaFwk_Want_LongArray_0200, Function | MediumTest | Level1) +{ + std::vector defaultValue; + std::string key = "aa"; + EXPECT_EQ(defaultValue, want_->GetLongArrayParam(key)); +} + +/** + * @tc.number: AaFwk_Want_LongArray_0300 + * @tc.name: SetParam & GetLongArrayParam + * @tc.desc: set empty-string key repeatedly, but get param of another nonexistent key + */ +HWTEST_F(WantLongArrayParamTest, AaFwk_Want_LongArray_0300, Function | MediumTest | Level1) +{ + std::vector defaultValue; + std::string setKey1 = "bb"; + std::string setKey2 = "aa"; + std::vector setValue1 = {1, 2}; + want_->SetParam(setKey1, setValue1); + want_->SetParam(setKey1, setValue1); + setValue1 = {2, 3}; + want_->SetParam(setKey1, setValue1); + EXPECT_EQ(defaultValue, want_->GetLongArrayParam(setKey2)); + setValue1 = {4, 5}; + want_->SetParam(setKey1, setValue1); + EXPECT_EQ(setValue1, want_->GetLongArrayParam(setKey1)); +} + +/** + * @tc.number: AaFwk_Want_LongArray_0400 + * @tc.name: SetParam & GetLongArrayParam + * @tc.desc: set empty-string key repeatedly, then get param of the key + */ +HWTEST_F(WantLongArrayParamTest, AaFwk_Want_LongArray_0400, Function | MediumTest | Level1) +{ + std::vector defaultValue; + std::string setKey1 = "%1uH3"; + std::string setKey2 = "aa"; + std::vector setValue1 = {-1, -2}; + want_->SetParam(setKey1, setValue1); + want_->SetParam(setKey1, setValue1); + setValue1 = {0, 1}; + want_->SetParam(setKey1, setValue1); + EXPECT_EQ(setValue1, want_->GetLongArrayParam(setKey1)); + setValue1 = {4, 5}; + want_->SetParam(setKey1, setValue1); + EXPECT_EQ(defaultValue, want_->GetLongArrayParam(setKey2)); +} + +using testShortArrayType = + std::tuple, std::vector, std::vector>; +class WantShortArrayParamTest : public testing::TestWithParam { +public: + WantShortArrayParamTest() + { + want_ = nullptr; + } + ~WantShortArrayParamTest() + { + want_ = nullptr; + } + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + std::shared_ptr want_; +}; + +void WantShortArrayParamTest::SetUpTestCase(void) +{} + +void WantShortArrayParamTest::TearDownTestCase(void) +{} + +void WantShortArrayParamTest::SetUp(void) +{ + want_ = std::make_shared(); +} + +void WantShortArrayParamTest::TearDown(void) +{} + +/** + * @tc.number: AaFwk_Want_ShortArray_0100 + * @tc.name: SetParam/GetShortArrayParam + * @tc.desc: Verify when parameter change. + */ +HWTEST_P(WantShortArrayParamTest, AaFwk_Want_ShortArray_0100, Function | MediumTest | Level1) +{ + std::string setKey = std::get<0>(GetParam()); + std::string getKey = std::get<1>(GetParam()); + std::vector setValue = std::get<2>(GetParam()); + std::vector defaultValue = std::get<3>(GetParam()); + std::vector result = std::get<4>(GetParam()); + want_->SetParam(setKey, setValue); + EXPECT_EQ(result, want_->GetShortArrayParam(getKey)); +} + +INSTANTIATE_TEST_CASE_P(WantShortArrayParamTestCaseP, WantShortArrayParamTest, + testing::Values(testShortArrayType("", "aa", {-1, 3, 25, -9}, {}, {}), + testShortArrayType("", "", {-41, 0, 0, 9}, {}, {-41, 0, 0, 9}), + testShortArrayType("1*中_aR", "aa", {50, 2, -9}, {}, {}), + testShortArrayType("1*中_aR", "1*中_aR", {-5000}, {}, {-5000}))); + +/** + * @tc.number: AaFwk_Want_ShortArray_0200 + * @tc.name: SetParam/GetShortArrayParam + * @tc.desc: Verify when the value is short array + */ +HWTEST_F(WantShortArrayParamTest, AaFwk_Want_ShortArray_0200, Function | MediumTest | Level1) +{ + std::vector defaultValue; + std::string getKey("aa"); + EXPECT_EQ(defaultValue, want_->GetShortArrayParam(getKey)); +} + +/** + * @tc.number: AaFwk_Want_ShortArray_0300 + * @tc.name: SetParam/GetShortArrayParam + * @tc.desc: Verify when the value is short array + */ +HWTEST_F(WantShortArrayParamTest, AaFwk_Want_ShortArray_0300, Function | MediumTest | Level1) +{ + std::string emptyStr("hh"); + std::vector firstValue({1, 4, -9}); + std::vector secondValue({1, 8, -9}); + std::vector thirdValue({1, 4, 9}); + std::string keyStr("aa"); + want_->SetParam(emptyStr, firstValue); + want_->SetParam(emptyStr, firstValue); + want_->SetParam(emptyStr, secondValue); + std::vector defaultValue; + EXPECT_EQ(defaultValue, want_->GetShortArrayParam(keyStr)); + want_->SetParam(emptyStr, thirdValue); + EXPECT_EQ(thirdValue, want_->GetShortArrayParam(emptyStr)); +} + +/** + * @tc.number: AaFwk_Want_ShortArray_0400 + * @tc.name: SetParam/GetShortArrayParam + * @tc.desc: Verify when the value is short array + */ +HWTEST_F(WantShortArrayParamTest, AaFwk_Want_ShortArray_0400, Function | MediumTest | Level1) +{ + std::string firstKey("%1uH3"); + std::vector firstValue({-1, -2}); + std::vector secondValue({-1, -2, -1, -2, 0}); + std::vector thirdValue({-1, -2, 100}); + std::string secondKey("aa"); + want_->SetParam(firstKey, firstValue); + want_->SetParam(firstKey, firstValue); + want_->SetParam(firstKey, secondValue); + EXPECT_EQ(secondValue, want_->GetShortArrayParam(firstKey)); + want_->SetParam(firstKey, thirdValue); + std::vector defaultValue; + EXPECT_EQ(defaultValue, want_->GetShortArrayParam(secondKey)); +} + +using testShortType = std::tuple; +class WantShortParamTest : public testing::TestWithParam { +public: + WantShortParamTest() + { + want_ = nullptr; + } + ~WantShortParamTest() + {} + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + std::shared_ptr want_; +}; + +void WantShortParamTest::SetUpTestCase(void) +{} + +void WantShortParamTest::TearDownTestCase(void) +{} + +void WantShortParamTest::SetUp(void) +{ + want_ = std::make_shared(); +} + +void WantShortParamTest::TearDown(void) +{} + +/** + * @tc.number: AaFwk_Want_Short_0100 + * @tc.name: SetParam/GetShortParam + * @tc.desc: Verify when parameter change. + */ +HWTEST_P(WantShortParamTest, AaFwk_Want_Short_0100, Function | MediumTest | Level1) +{ + std::string setKey = std::get<0>(GetParam()); + std::string getKey = std::get<1>(GetParam()); + short setValue = std::get<2>(GetParam()); + short defaultValue = std::get<3>(GetParam()); + short result = std::get<4>(GetParam()); + want_->SetParam(setKey, setValue); + EXPECT_EQ(result, want_->GetShortParam(getKey, defaultValue)); +} + +INSTANTIATE_TEST_CASE_P(WantShortParamTestCaseP, WantShortParamTest, + testing::Values(testShortType("", "aa", -1, 100, 100), testShortType("", "", -9, -41, -9), + testShortType("1*中_aR", "aa", 50, 5, 5), testShortType("1*中_aR", "1*中_aR", -5000, 5000, -5000))); + +/** + * @tc.number: AaFwk_Want_Short_0200 + * @tc.name: SetParam/GetShortParam + * @tc.desc: Verify when the value is short + */ +HWTEST_F(WantShortParamTest, AaFwk_Want_Short_0200, Function | MediumTest | Level1) +{ + short defaultValue = 200; + std::string getKey("aa"); + EXPECT_EQ(defaultValue, want_->GetShortParam(getKey, defaultValue)); +} +/** + * @tc.number: AaFwk_Want_Short_0300 + * @tc.name: SetParam/GetShortParam + * @tc.desc: Verify when the value is short + */ +HWTEST_F(WantShortParamTest, AaFwk_Want_Short_0300, Function | MediumTest | Level1) +{ + std::string emptyStr("bb"); + short firstValue = 1; + short secondValue = 2; + short thirdValue = 4; + short firstDefaultValue = 3; + short secondDefaultValue = 5; + std::string keyStr("aa"); + want_->SetParam(emptyStr, firstValue); + want_->SetParam(emptyStr, firstValue); + want_->SetParam(emptyStr, secondValue); + EXPECT_EQ(firstDefaultValue, want_->GetShortParam(keyStr, firstDefaultValue)); + want_->SetParam(emptyStr, thirdValue); + EXPECT_EQ(thirdValue, want_->GetShortParam(emptyStr, secondDefaultValue)); +} + +/** + * @tc.number: AaFwk_Want_Short_0400 + * @tc.name: SetParam/GetShortParam + * @tc.desc: Verify when the value is short + */ +HWTEST_F(WantShortParamTest, AaFwk_Want_Short_0400, Function | MediumTest | Level1) +{ + std::string firstKey("%1uH3"); + short firstValue = -1; + short secondValue = 0; + short thirdValue = 4; + short firstDefaultValue = 9; + short secondDefaultValue = -10; + std::string secondKey("aa"); + want_->SetParam(firstKey, firstValue); + want_->SetParam(firstKey, firstValue); + want_->SetParam(firstKey, secondValue); + EXPECT_EQ(secondValue, want_->GetShortParam(firstKey, firstDefaultValue)); + want_->SetParam(firstKey, thirdValue); + EXPECT_EQ(secondDefaultValue, want_->GetShortParam(secondKey, secondDefaultValue)); +} + +using testStrArrayType = + std::tuple, std::vector, std::vector>; +class WantStringArrayParamTest : public testing::TestWithParam { +public: + WantStringArrayParamTest() + { + want_ = nullptr; + } + ~WantStringArrayParamTest() + {} + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + std::shared_ptr want_ = nullptr; +}; + +void WantStringArrayParamTest::SetUpTestCase(void) +{} + +void WantStringArrayParamTest::TearDownTestCase(void) +{} + +void WantStringArrayParamTest::SetUp(void) +{ + want_ = std::make_shared(); +} + +void WantStringArrayParamTest::TearDown(void) +{} + +/** + * @tc.number: AaFwk_Want_StringArray_0100 + * @tc.name: SetParam/GetStringArrayParam + * @tc.desc: Verify when parameter change. + */ +HWTEST_P(WantStringArrayParamTest, AaFwk_Want_StringArray_0100, Function | MediumTest | Level1) +{ + std::string setKey = std::get<0>(GetParam()); + std::string getKey = std::get<1>(GetParam()); + std::vector setValue = std::get<2>(GetParam()); + std::vector defaultValue = std::get<3>(GetParam()); + std::vector result = std::get<4>(GetParam()); + want_->SetParam(setKey, setValue); + EXPECT_EQ(result, want_->GetStringArrayParam(getKey)); +} + +INSTANTIATE_TEST_CASE_P(WantStringArrayParamTestCaseP, WantStringArrayParamTest, + testing::Values(testStrArrayType("", "aa", {"1*中_aR", "dbdb"}, {}, {}), + testStrArrayType("", "", {"1*中_aR", "dbdb"}, {}, {"1*中_aR", "dbdb"}), + testStrArrayType("1*中_aR", "aa", {"1*中_aR", "dbdb"}, {}, {}), + testStrArrayType("1*中_aR", "1*中_aR", {"1*中_aR", "dbdb"}, {}, {"1*中_aR", "dbdb"}))); + +/** + * @tc.number: AaFwk_Want_StringArray_0200 + * @tc.name: SetParam/GetStringArrayParam + * @tc.desc: get param when WantParam is empty + */ +HWTEST_F(WantStringArrayParamTest, AaFwk_Want_StringArray_0200, Function | MediumTest | Level1) +{ + std::vector defaultValue; + std::string key = "aa"; + std::vector resultValue = want_->GetStringArrayParam(key); + EXPECT_EQ(defaultValue, resultValue); +} + +/** + * @tc.number: AaFwk_Want_StringArray_0300 + * @tc.name: SetParam/GetStringArrayParam + * @tc.desc: set empty-string key repeatedly, but get param of another nonexistent key + */ +HWTEST_F(WantStringArrayParamTest, AaFwk_Want_StringArray_0300, Function | MediumTest | Level1) +{ + std::vector defaultValue; + std::vector setValue1 = {"aaa", "2132"}; + std::vector setValue2 = {"1*中_aR", "dbdb"}; + std::string key1 = "cc"; + std::string key2 = "aa"; + want_->SetParam(key1, setValue1); + want_->SetParam(key1, setValue1); + want_->SetParam(key1, setValue2); + std::vector resultValue = want_->GetStringArrayParam(key2); + EXPECT_EQ(defaultValue, resultValue); + + want_->SetParam(key1, setValue1); + resultValue = want_->GetStringArrayParam(key1); + EXPECT_EQ(setValue1, resultValue); +} + +/** + * @tc.number: AaFwk_Want_StringArray_0400 + * @tc.name: SetParam/GetStringArrayParam + * @tc.desc: set empty-string key repeatedly, then get param of the key + */ +HWTEST_F(WantStringArrayParamTest, AaFwk_Want_StringArray_0400, Function | MediumTest | Level1) +{ + std::vector defaultValue; + std::vector setValue = {"aaa", "2132"}; + std::string key1 = "%1uH3"; + std::string key2 = "aa"; + want_->SetParam(key1, setValue); + want_->SetParam(key1, setValue); + setValue = {"1*中_aR", "3#$%"}; + want_->SetParam(key1, setValue); + std::vector resultValue = want_->GetStringArrayParam(key1); + EXPECT_EQ(setValue, resultValue); + + setValue = {"aaa", "2132"}; + want_->SetParam(key1, setValue); + resultValue = want_->GetStringArrayParam(key2); + EXPECT_EQ(defaultValue, resultValue); +} + +using testStrType = std::tuple; +class WantStringParamTest : public testing::TestWithParam { +public: + WantStringParamTest() + { + want_ = nullptr; + } + ~WantStringParamTest() + {} + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + std::shared_ptr want_; +}; + +void WantStringParamTest::SetUpTestCase(void) +{} + +void WantStringParamTest::TearDownTestCase(void) +{} + +void WantStringParamTest::SetUp(void) +{ + want_ = std::make_shared(); +} + +void WantStringParamTest::TearDown(void) +{} + +/** + * @tc.number: AaFwk_Want_String_0100 + * @tc.name: SetParam/GetStringParam + * @tc.desc: Verify when parameter change. + */ +HWTEST_P(WantStringParamTest, AaFwk_Want_String_0100, Function | MediumTest | Level1) +{ + std::string setKey = std::get<0>(GetParam()); + std::string getKey = std::get<1>(GetParam()); + std::string setValue = std::get<2>(GetParam()); + std::string defaultValue = std::get<3>(GetParam()); + std::string result = std::get<4>(GetParam()); + want_->SetParam(setKey, setValue); + EXPECT_EQ(result, want_->GetStringParam(getKey)); +} + +INSTANTIATE_TEST_CASE_P(WantStringParamTestCaseP, WantStringParamTest, + testing::Values(testStrType("", "aa", "1*中_aR", "", ""), testStrType("", "", "1*中_aR", "", "1*中_aR"), + testStrType("1*中_aR", "aa", "aaa", "", ""), testStrType("1*中_aR", "1*中_aR", "aaa", "", "aaa"))); + +/** + * @tc.number: AaFwk_Want_String_0200 + * @tc.name: SetParam/GetStringParam + * @tc.desc: get param when WantParam is empty. + */ +HWTEST_F(WantStringParamTest, AaFwk_Want_String_0200, Function | MediumTest | Level1) +{ + std::string defaultStrValue; + std::string key = "aa"; + EXPECT_EQ(defaultStrValue, want_->GetStringParam(key)); +} + +/** + * @tc.number: AaFwk_Want_String_0300 + * @tc.name: SetParam/GetStringParam + * @tc.desc: set empty-string key repeatedly, but get param of another nonexistent key. + */ +HWTEST_F(WantStringParamTest, AaFwk_Want_String_0300, Function | MediumTest | Level1) +{ + std::string defaultStrValue; + std::string setValue1 = "aaa"; + std::string setValue2 = "1*中_aR"; + std::string key1 = "dd"; + std::string key2 = "aa"; + want_->SetParam(key1, setValue1); + want_->SetParam(key1, setValue1); + want_->SetParam(key1, setValue2); + EXPECT_EQ(defaultStrValue, want_->GetStringParam(key2)); + want_->SetParam(key1, setValue1); + EXPECT_EQ(setValue1, want_->GetStringParam(key1)); +} + +/** + * @tc.number: AaFwk_Want_String_0400 + * @tc.name: SetParam/GetStringParam + * @tc.desc: set empty-string key repeatedly, then get param of the key. + */ +HWTEST_F(WantStringParamTest, AaFwk_Want_String_0400, Function | MediumTest | Level1) +{ + std::string key1 = "%1uH3"; + std::string defaultStrValue; + std::string setValue1 = "aaa"; + std::string setValue2 = "1*中_aR"; + std::string key2 = "aa"; + want_->SetParam(key1, setValue1); + want_->SetParam(key1, setValue1); + want_->SetParam(key1, setValue2); + EXPECT_EQ("1*中_aR", want_->GetStringParam(key1)); + want_->SetParam(key1, setValue1); + EXPECT_EQ(defaultStrValue, want_->GetStringParam(key2)); +} + +using testLongType = std::tuple; +class WantLongParamTest : public testing::TestWithParam { +public: + WantLongParamTest() + { + want_ = nullptr; + } + ~WantLongParamTest() + {} + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + std::shared_ptr want_ = nullptr; +}; + +void WantLongParamTest::SetUpTestCase(void) +{} + +void WantLongParamTest::TearDownTestCase(void) +{} + +void WantLongParamTest::SetUp(void) +{ + want_ = std::make_shared(); +} + +void WantLongParamTest::TearDown(void) +{} + +/** + * @tc.number: AaFwk_Want_LongParam_0100 + * @tc.name: SetParam/GetLongParam + * @tc.desc: Verify when parameter change. + */ +HWTEST_P(WantLongParamTest, AaFwk_Want_LongParam_0100, Function | MediumTest | Level1) +{ + std::string setKey = std::get<0>(GetParam()); + std::string getKey = std::get<1>(GetParam()); + long setValue = std::get<2>(GetParam()); + long defaultValue = std::get<3>(GetParam()); + long result = std::get<4>(GetParam()); + want_->SetParam(setKey, setValue); + EXPECT_EQ(result, want_->GetLongParam(getKey, defaultValue)); +} + +INSTANTIATE_TEST_CASE_P(WantLongParamTestCaseP, WantLongParamTest, + testing::Values(testLongType("b1", "b1", -1, 100, -1), testLongType("b3", "b4", 600, 200, 200), + testLongType("b5", "b5", 50, 6, 50), testLongType("b6", "b7", 1000, 2200, 2200))); + +/** + * @tc.number: AaFwk_Want_LongParam_0200 + * @tc.name: SetParam/GetLongParam + * @tc.desc: get param when WantParam is empty. + */ +HWTEST_F(WantLongParamTest, AaFwk_Want_LongParam_0200, Function | MediumTest | Level1) +{ + long defaultValue = 100; + std::string key = "aa"; + EXPECT_EQ(defaultValue, want_->GetLongParam(key, defaultValue)); +} + +/** + * @tc.number: AaFwk_Want_LongParam_0300 + * @tc.name: SetParam/GetLongParam + * @tc.desc: set empty-string key repeatedly, but get param of another nonexistent key. + */ +HWTEST_F(WantLongParamTest, AaFwk_Want_LongParam_0300, Function | MediumTest | Level1) +{ + std::string setKey1 = "dd"; + std::string setKey2 = "aa"; + long setValue1 = 1; + long setValue2 = 5; + want_->SetParam(setKey1, setValue1); + want_->SetParam(setKey1, setValue1); + setValue1 = 2; + want_->SetParam(setKey1, setValue1); + setValue1 = 3; + EXPECT_EQ(setValue1, want_->GetLongParam(setKey2, setValue1)); + setValue1 = 4; + want_->SetParam(setKey1, setValue1); + EXPECT_EQ(setValue1, want_->GetLongParam(setKey1, setValue2)); +} + +/** + * @tc.number: AaFwk_Want_LongParam_0400 + * @tc.name: SetParam/GetLongParam + * @tc.desc: set empty-string key repeatedly, then get param of the key. + */ +HWTEST_F(WantLongParamTest, AaFwk_Want_LongParam_0400, Function | MediumTest | Level1) +{ + std::string setKey1 = "%1uH3"; + std::string setKey2 = "aa"; + long setValue1 = -1; + long setValue2 = 9; + want_->SetParam(setKey1, setValue1); + want_->SetParam(setKey1, setValue1); + setValue1 = 0; + want_->SetParam(setKey1, setValue1); + EXPECT_EQ(setValue1, want_->GetLongParam(setKey1, setValue2)); + setValue1 = 4; + want_->SetParam(setKey1, setValue1); + setValue1 = -10; + EXPECT_EQ(setValue1, want_->GetLongParam(setKey2, setValue1)); +} + +using testIntType = std::tuple; +class WantIntParamTest : public testing::TestWithParam { +public: + WantIntParamTest() + { + want_ = nullptr; + } + ~WantIntParamTest() + { + want_ = nullptr; + } + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + std::shared_ptr want_; +}; + +void WantIntParamTest::SetUpTestCase(void) +{} + +void WantIntParamTest::TearDownTestCase(void) +{} + +void WantIntParamTest::SetUp(void) +{ + want_ = std::make_shared(); +} + +void WantIntParamTest::TearDown(void) +{} + +/** + * @tc.number: AaFwk_Want_IntParam_0100 + * @tc.name: SetParam/GetIntParam + * @tc.desc: Verify when parameter change. + */ +HWTEST_P(WantIntParamTest, AaFwk_Want_IntParam_0100, Function | MediumTest | Level1) +{ + std::string setKey = std::get<0>(GetParam()); + std::string getKey = std::get<1>(GetParam()); + int setValue = std::get<2>(GetParam()); + int defaultValue = std::get<3>(GetParam()); + int result = std::get<4>(GetParam()); + want_->SetParam(setKey, setValue); + EXPECT_EQ(result, want_->GetIntParam(getKey, defaultValue)); +} + +INSTANTIATE_TEST_CASE_P(WantParametersIntTestCaseP, WantIntParamTest, + testing::Values(testIntType("", "aa", -1, 100, 100), testIntType("", "", -9, -41, -9), + testIntType("1*中_aR", "aa", 50, 5, 5), testIntType("1*中_aR", "1*中_aR", -5000, 5000, -5000))); + +/** + * @tc.number: AaFwk_Want_IntParam_0200 + * @tc.name: SetParam/GetIntParam + * @tc.desc: Verify when the value is integer. + */ +HWTEST_F(WantIntParamTest, AaFwk_Want_IntParam_0200, Function | MediumTest | Level1) +{ + int defaultValue = 200; + std::string getKey("aa"); + EXPECT_EQ(defaultValue, want_->GetIntParam(getKey, defaultValue)); +} + +/** + * @tc.number: AaFwk_Want_IntParam_0300 + * @tc.name: SetParam/GetIntParam + * @tc.desc: Verify when the value is integer. + */ +HWTEST_F(WantIntParamTest, AaFwk_Want_IntParam_0300, Function | MediumTest | Level1) +{ + std::string emptyStr("bb"); + int firstValue = 1; + int secondValue = 2; + int thirdValue = 4; + int firstDefaultValue = 3; + int secondDefaultValue = 5; + std::string keyStr("aa"); + want_->SetParam(emptyStr, firstValue); + want_->SetParam(emptyStr, firstValue); + want_->SetParam(emptyStr, secondValue); + EXPECT_EQ(firstDefaultValue, want_->GetIntParam(keyStr, firstDefaultValue)); + want_->SetParam(emptyStr, thirdValue); + EXPECT_EQ(thirdValue, want_->GetIntParam(emptyStr, secondDefaultValue)); +} + +/** + * @tc.number: AaFwk_Want_IntParam_0400 + * @tc.name: SetParam/GetIntParam + * @tc.desc: Verify when the value is integer. + */ +HWTEST_F(WantIntParamTest, AaFwk_Want_IntParam_0400, Function | MediumTest | Level1) +{ + std::string firstKey("%1uH3"); + int firstValue = -1; + int secondValue = 0; + int thirdValue = 4; + int firstDefaultValue = 9; + int secondDefaultValue = -10; + std::string secondKey("aa"); + want_->SetParam(firstKey, firstValue); + want_->SetParam(firstKey, firstValue); + want_->SetParam(firstKey, secondValue); + EXPECT_EQ(secondValue, want_->GetIntParam(firstKey, firstDefaultValue)); + want_->SetParam(firstKey, thirdValue); + EXPECT_EQ(secondDefaultValue, want_->GetIntParam(secondKey, secondDefaultValue)); +} + +using testIntArrayType = std::tuple, std::vector, std::vector>; +class WantIntArrayParamTest : public testing::TestWithParam { +public: + WantIntArrayParamTest() + { + want_ = nullptr; + } + ~WantIntArrayParamTest() + { + want_ = nullptr; + } + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + std::shared_ptr want_; +}; + +void WantIntArrayParamTest::SetUpTestCase(void) +{} + +void WantIntArrayParamTest::TearDownTestCase(void) +{} + +void WantIntArrayParamTest::SetUp(void) +{ + want_ = std::make_shared(); +} + +void WantIntArrayParamTest::TearDown(void) +{} + +/** + * @tc.number: AaFwk_Want_IntArrayParam_0100 + * @tc.name: SetParam/GetIntArrayParam + * @tc.desc: Verify when parameter change. + */ +HWTEST_P(WantIntArrayParamTest, AaFwk_Want_IntArrayParam_0100, Function | MediumTest | Level1) +{ + std::string setKey = std::get<0>(GetParam()); + std::string getKey = std::get<1>(GetParam()); + std::vector setValue = std::get<2>(GetParam()); + std::vector defaultValue = std::get<3>(GetParam()); + std::vector result = std::get<4>(GetParam()); + want_->SetParam(setKey, setValue); + EXPECT_EQ(result, want_->GetIntArrayParam(getKey)); +} + +INSTANTIATE_TEST_CASE_P(WantIntArrayParamTestCaseP, WantIntArrayParamTest, + testing::Values(testIntArrayType("", "aa", {-1, 3, 25, -9}, {}, {}), + testIntArrayType("", "", {-41, 0, 0, 9}, {}, {-41, 0, 0, 9}), + testIntArrayType("1*中_aR", "aa", {50, 2, -9}, {}, {}), + testIntArrayType("1*中_aR", "1*中_aR", {-5000}, {}, {-5000}))); + +/** + * @tc.number: AaFwk_Want_IntArrayParam_0200 + * @tc.name: SetParam/GetIntArrayParam + * @tc.desc: Verify when the value is integer array. + */ +HWTEST_F(WantIntArrayParamTest, AaFwk_Want_IntArrayParam_0200, Function | MediumTest | Level1) +{ + std::vector defaultValue; + std::string getKey("aa"); + EXPECT_EQ(defaultValue, want_->GetIntArrayParam(getKey)); +} + +/** + * @tc.number: AaFwk_Want_IntArrayParam_0300 + * @tc.name: SetParam/GetIntArrayParam + * @tc.desc: Verify when the value is integer array. + */ +HWTEST_F(WantIntArrayParamTest, AaFwk_Want_IntArrayParam_0300, Function | MediumTest | Level1) +{ + std::string emptyStr("cc"); + std::vector firstValue({1, 4, -9}); + std::vector secondValue({1, 8, -9}); + std::vector thirdValue({1, 4, 9}); + std::string keyStr("aa"); + want_->SetParam(emptyStr, firstValue); + want_->SetParam(emptyStr, firstValue); + want_->SetParam(emptyStr, secondValue); + std::vector defaultValue; + EXPECT_EQ(defaultValue, want_->GetIntArrayParam(keyStr)); + want_->SetParam(emptyStr, thirdValue); + EXPECT_EQ(thirdValue, want_->GetIntArrayParam(emptyStr)); +} + +/** + * @tc.number: AaFwk_Want_IntArrayParam_0400 + * @tc.name: SetParam/GetIntArrayParam + * @tc.desc: Verify when the value is integer array. + */ +HWTEST_F(WantIntArrayParamTest, AaFwk_Want_IntArrayParam_0400, Function | MediumTest | Level1) +{ + std::string firstKey("%1uH3"); + std::vector firstValue({-1, -2}); + std::vector secondValue({-1, -2, -1, -2, 0}); + std::vector thirdValue({-1, -2, 100}); + std::string secondKey("aa"); + want_->SetParam(firstKey, firstValue); + want_->SetParam(firstKey, firstValue); + want_->SetParam(firstKey, secondValue); + EXPECT_EQ(secondValue, want_->GetIntArrayParam(firstKey)); + want_->SetParam(firstKey, thirdValue); + std::vector defaultValue; + EXPECT_EQ(defaultValue, want_->GetIntArrayParam(secondKey)); +} + +using testFloatType = std::tuple; +class WantFloatParamTest : public testing::TestWithParam { +public: + WantFloatParamTest() + { + want_ = nullptr; + } + ~WantFloatParamTest() + { + want_ = nullptr; + } + + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + std::shared_ptr want_; +}; + +void WantFloatParamTest::SetUpTestCase(void) +{} + +void WantFloatParamTest::TearDownTestCase(void) +{} + +void WantFloatParamTest::SetUp(void) +{ + want_ = std::make_shared(); +} + +void WantFloatParamTest::TearDown(void) +{} + +/** + * @tc.number: AaFwk_Want_FloatParam_0100 + * @tc.name: SetParam/GetFloatParam + * @tc.desc: Verify when parameter change. + */ +HWTEST_P(WantFloatParamTest, AaFwk_Want_FloatParam_0100, Function | MediumTest | Level1) +{ + std::string setKey = std::get<0>(GetParam()); + std::string getKey = std::get<1>(GetParam()); + float setValue = std::get<2>(GetParam()); + float defaultValue = std::get<3>(GetParam()); + float result = std::get<4>(GetParam()); + want_->SetParam(setKey, setValue); + EXPECT_EQ(result, want_->GetFloatParam(getKey, defaultValue)); +} + +INSTANTIATE_TEST_CASE_P(WantFloatParamTestCaseP, WantFloatParamTest, + testing::Values(testFloatType("", "aa", -1.1, 100.1, 100.1), testFloatType("", "", -9.1, -41.1, -9.1), + testFloatType("1*中_aR", "aa", 50.1, 5.1, 5.1), testFloatType("1*中_aR", "1*中_aR", -5000.1, 5000.1, -5000.1))); + +/** + * @tc.number: AaFwk_Want_FloatParam_0200 + * @tc.name: SetParam/GetFloatParam + * @tc.desc: get param when WantParam is empty. + */ +HWTEST_F(WantFloatParamTest, AaFwk_Want_FloatParam_0200, Function | MediumTest | Level1) +{ + float defaultValue = 100.1; + std::string key = "aa"; + EXPECT_EQ(defaultValue, want_->GetFloatParam(key, defaultValue)); +} + +/** + * @tc.number: AaFwk_Want_FloatParam_0300 + * @tc.name: SetParam/GetFloatParam + * @tc.desc: set empty-string key repeatedly, but get param of another nonexistent key. + */ +HWTEST_F(WantFloatParamTest, AaFwk_Want_FloatParam_0300, Function | MediumTest | Level1) +{ + std::string setKey1 = "ee"; + std::string setKey2 = "aa"; + float setValue1 = 1.1; + float setValue2 = 5.1; + want_->SetParam(setKey1, setValue1); + want_->SetParam(setKey1, setValue1); + setValue1 = 2.1; + want_->SetParam(setKey1, setValue1); + setValue1 = 3.1; + EXPECT_EQ(setValue1, want_->GetFloatParam(setKey2, setValue1)); + setValue1 = 4.1; + want_->SetParam(setKey1, setValue1); + EXPECT_EQ(setValue1, want_->GetFloatParam(setKey1, setValue2)); +} + +/** + * @tc.number: AaFwk_Want_FloatParam_0400 + * @tc.name: SetParam/GetFloatParam + * @tc.desc: set empty-string key repeatedly, but get param of another nonexistent key. + */ +HWTEST_F(WantFloatParamTest, AaFwk_Want_FloatParam_0400, Function | MediumTest | Level1) +{ + std::string setKey1 = "%1uH3"; + std::string setKey2 = "aa"; + float setValue1 = -1.1; + float setValue2 = 9.1; + want_->SetParam(setKey1, setValue1); + want_->SetParam(setKey1, setValue1); + setValue1 = 0.1; + want_->SetParam(setKey1, setValue1); + EXPECT_EQ(setValue1, want_->GetFloatParam(setKey1, setValue2)); + setValue1 = 4.1; + want_->SetParam(setKey1, setValue1); + setValue1 = -10.1; + EXPECT_EQ(setValue1, want_->GetFloatParam(setKey2, setValue1)); +} + +using testDoubleType = std::tuple; +class WantDoubleParamTest : public testing::TestWithParam { +public: + WantDoubleParamTest() + { + want_ = nullptr; + } + ~WantDoubleParamTest() + { + want_ = nullptr; + } + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + std::shared_ptr want_; +}; + +void WantDoubleParamTest::SetUpTestCase(void) +{} + +void WantDoubleParamTest::TearDownTestCase(void) +{} + +void WantDoubleParamTest::SetUp(void) +{ + want_ = std::make_shared(); +} + +void WantDoubleParamTest::TearDown(void) +{} + +/** + * @tc.number: AaFwk_Want_DoubleParam_0100 + * @tc.name: SetParam/GetDoubleParam + * @tc.desc: Verify when parameter change. + */ +HWTEST_P(WantDoubleParamTest, AaFwk_Want_DoubleParam_0100, Function | MediumTest | Level1) +{ + std::string setKey = std::get<0>(GetParam()); + std::string getKey = std::get<1>(GetParam()); + double setValue = std::get<2>(GetParam()); + double defaultValue = std::get<3>(GetParam()); + double result = std::get<4>(GetParam()); + want_->SetParam(setKey, setValue); + EXPECT_EQ(result, want_->GetDoubleParam(getKey, defaultValue)); +} + +INSTANTIATE_TEST_CASE_P(WantDoubleParamTestCaseP, WantDoubleParamTest, + testing::Values(testDoubleType("", "aa", -1.1, 100.1, 100.1), testDoubleType("", "", -9.1, -41.1, -9.1), + testDoubleType("1*中_aR", "aa", 50.1, 5.1, 5.1), + testDoubleType("1*中_aR", "1*中_aR", -5000.1, 5000.1, -5000.1))); + +/** + * @tc.number: AaFwk_Want_DoubleParam_0300 + * @tc.name: SetParam & GetDoubleParam + * @tc.desc: set empty-string key repeatedly, but get param of another nonexistent key. + */ +HWTEST_F(WantDoubleParamTest, AaFwk_Want_DoubleParam_0300, Function | MediumTest | Level1) +{ + double defaultValue = 100.1; + std::string key = "aa"; + EXPECT_EQ(defaultValue, want_->GetDoubleParam(key, defaultValue)); +} + +/** + * @tc.number: AaFwk_Want_DoubleParam_0400 + * @tc.name: SetParam & GetDoubleParam + * @tc.desc: set empty-string key repeatedly, then get param of the key. + */ +HWTEST_F(WantDoubleParamTest, AaFwk_Want_DoubleParam_0400, Function | MediumTest | Level1) +{ + std::string setKey1 = "ff"; + std::string setKey2 = "aa"; + double setValue1 = 1.1; + double setValue2 = 5.1; + want_->SetParam(setKey1, setValue1); + want_->SetParam(setKey1, setValue1); + setValue1 = 2.1; + want_->SetParam(setKey1, setValue1); + setValue1 = 3.1; + EXPECT_EQ(setValue1, want_->GetDoubleParam(setKey2, setValue1)); + setValue1 = 4.1; + want_->SetParam(setKey1, setValue1); + EXPECT_EQ(setValue1, want_->GetDoubleParam(setKey1, setValue2)); +} + +/** + * @tc.number: AaFwk_Want_ByteArray_0100 + * @tc.name: SetParam/GetByteArrayParam + * @tc.desc: Verify when parameter change. + */ +HWTEST_F(WantDoubleParamTest, AaFwk_Want_ByteArray_0100, Function | MediumTest | Level1) +{ + std::string setKey1 = "%1uH3"; + std::string setKey2 = "aa"; + double setValue1 = -1.1; + double setValue2 = 9.1; + want_->SetParam(setKey1, setValue1); + want_->SetParam(setKey1, setValue1); + setValue1 = 0.1; + want_->SetParam(setKey1, setValue1); + EXPECT_EQ(setValue1, want_->GetDoubleParam(setKey1, setValue2)); + setValue1 = 4.1; + want_->SetParam(setKey1, setValue1); + setValue1 = -10.1; + EXPECT_EQ(setValue1, want_->GetDoubleParam(setKey2, setValue1)); +} + +using testByteArrayType = std::tuple, std::vector, std::vector>; +class WantByteArrayParamTest : public testing::TestWithParam { +public: + WantByteArrayParamTest() + { + want_ = nullptr; + } + ~WantByteArrayParamTest() + { + want_ = nullptr; + } + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + std::shared_ptr want_; +}; + +void WantByteArrayParamTest::SetUpTestCase(void) +{} + +void WantByteArrayParamTest::TearDownTestCase(void) +{} + +void WantByteArrayParamTest::SetUp(void) +{ + want_ = std::make_shared(); +} + +void WantByteArrayParamTest::TearDown(void) +{} + +/** + * @tc.number: AaFwk_Want_ByteArray_0100 + * @tc.name: SetParam/GetByteArrayParam + * @tc.desc: Verify when parameter change. + */ +HWTEST_P(WantByteArrayParamTest, AaFwk_Want_ByteArray_0100, Function | MediumTest | Level1) +{ + std::string setKey = std::get<0>(GetParam()); + std::string getKey = std::get<1>(GetParam()); + std::vector setValue = std::get<2>(GetParam()); + std::vector defaultValue = std::get<3>(GetParam()); + std::vector result = std::get<4>(GetParam()); + want_->SetParam(setKey, setValue); + EXPECT_EQ(result, want_->GetByteArrayParam(getKey)); +} + +INSTANTIATE_TEST_CASE_P(WantByteArrayParamTestCaseP, WantByteArrayParamTest, + testing::Values(testByteArrayType("", "aa", {'*', 'D'}, {}, {}), + testByteArrayType("", "", {'%', ')'}, {}, {'%', ')'}), testByteArrayType("1*中_aR", "aa", {'R', '.'}, {}, {}), + testByteArrayType("1*中_aR", "1*中_aR", {'R', 'b'}, {}, {'R', 'b'}))); + +/** + * @tc.number: AaFwk_Want_ByteArray_0200 + * @tc.name: SetParam/GetByteArrayParam + * @tc.desc: Verify when the value is byte array. + */ +HWTEST_F(WantByteArrayParamTest, AaFwk_Want_ByteArray_0200, Function | MediumTest | Level1) +{ + std::vector defaultValue; + std::string getKey("aa"); + EXPECT_EQ(defaultValue, want_->GetByteArrayParam(getKey)); +} + +/** + * @tc.number: AaFwk_Want_ByteArray_0300 + * @tc.name: SetParam/GetByteArrayParam + * @tc.desc: Verify when the value is byte array. + */ +HWTEST_F(WantByteArrayParamTest, AaFwk_Want_ByteArray_0300, Function | MediumTest | Level1) +{ + std::string emptyStr("gg"); + std::vector firstValue({'a', '2'}); + std::vector secondValue({'1', 'd'}); + std::vector thirdValue({'t', '3'}); + std::string keyStr("aa"); + want_->SetParam(emptyStr, firstValue); + want_->SetParam(emptyStr, firstValue); + want_->SetParam(emptyStr, secondValue); + std::vector defaultValue; + EXPECT_EQ(defaultValue, want_->GetByteArrayParam(keyStr)); + want_->SetParam(emptyStr, thirdValue); + EXPECT_EQ(thirdValue, want_->GetByteArrayParam(emptyStr)); +} + +/** + * @tc.number: AaFwk_Want_ByteArray_0400 + * @tc.name: SetParam/GetByteArrayParam + * @tc.desc: Verify when the value is byte array. + */ +HWTEST_F(WantByteArrayParamTest, AaFwk_Want_ByteArray_0400, Function | MediumTest | Level1) +{ + std::string firstKey("%1uH3"); + std::vector firstValue({'a', '2'}); + std::vector secondValue({'w', '$'}); + std::vector defaultValue; + std::string secondKey("aa"); + want_->SetParam(firstKey, firstValue); + want_->SetParam(firstKey, firstValue); + want_->SetParam(firstKey, secondValue); + EXPECT_EQ(secondValue, want_->GetByteArrayParam(firstKey)); + want_->SetParam(firstKey, firstValue); + EXPECT_EQ(defaultValue, want_->GetByteArrayParam(secondKey)); +} + +using testBoolType = std::tuple; +class WantBoolParamTest : public testing::TestWithParam { +public: + WantBoolParamTest() + { + want_ = nullptr; + } + ~WantBoolParamTest() + { + want_ = nullptr; + } + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + std::shared_ptr want_; +}; + +void WantBoolParamTest::SetUpTestCase(void) +{} + +void WantBoolParamTest::TearDownTestCase(void) +{} + +void WantBoolParamTest::SetUp(void) +{ + want_ = std::make_shared(); +} + +void WantBoolParamTest::TearDown(void) +{} + +/** + * @tc.number: AaFwk_Want_BoolParam_0100 + * @tc.name: SetParam/GetBoolParam + * @tc.desc: Verify when parameter change. + */ +HWTEST_P(WantBoolParamTest, AaFwk_Want_BoolParam_0100, Function | MediumTest | Level1) +{ + std::string setKey = std::get<0>(GetParam()); + std::string getKey = std::get<1>(GetParam()); + bool setValue = std::get<2>(GetParam()); + bool defaultValue = std::get<3>(GetParam()); + bool result = std::get<4>(GetParam()); + want_->SetParam(setKey, setValue); + EXPECT_EQ(result, want_->GetBoolParam(getKey, defaultValue)); +} + +INSTANTIATE_TEST_CASE_P(WantBoolParamTestCaseP, WantBoolParamTest, + testing::Values(testBoolType("b1", "aa", true, true, true), testBoolType("b1", "aa", true, false, false), + testBoolType("b2", "b2", true, true, true), testBoolType("b3", "b3", true, false, true), + testBoolType("123", "123", true, false, true), testBoolType("123", "aa", true, false, false), + testBoolType("-~*&%¥", "-~*&%¥", true, false, true), testBoolType("-~*&%¥", "aa", true, false, false), + testBoolType("中文", "中文", true, false, true), testBoolType("中文", "aa", true, false, false), + testBoolType("_中文ddPEJKJ#(&*~#^%", "_中文ddPEJKJ#(&*~#^%", true, false, true), + testBoolType("_中文ddPEJKJ#(&*~#^%", "123", true, false, false))); + +/** + * @tc.number: AaFwk_Want_BoolParam_0200 + * @tc.name: SetParam/GetBoolParam + * @tc.desc: Verify when set twice and get twice. + */ +HWTEST_F(WantBoolParamTest, AaFwk_Want_BoolParam_0200, Function | MediumTest | Level1) +{ + std::string firstKey("_中文ddPEJKJ#(&*~#^%"); + std::string secondKey("key33"); + want_->SetParam(firstKey, true); + want_->SetParam(secondKey, true); + EXPECT_EQ(true, want_->GetBoolParam(firstKey, false)); + EXPECT_EQ(true, want_->GetBoolParam(secondKey, false)); +} + +/** + * @tc.number: AaFwk_Want_BoolParam_0300 + * @tc.name: SetParam/GetBoolParam + * @tc.desc: Verify when set 20 times, and get once. + */ +HWTEST_F(WantBoolParamTest, AaFwk_Want_BoolParam_0300, Function | MediumTest | Level1) +{ + std::string keyStr("_中文ddPEJKJ#(&*~#^%"); + for (int i = 0; i < 20; i++) { + want_->SetParam(keyStr, true); + } + EXPECT_EQ(true, want_->GetBoolParam(keyStr, false)); +} + +/** + * @tc.number: AaFwk_Want_Want_0100 + * @tc.name: Want() and Want(want) + * @tc.desc: Verify Want() + */ +HWTEST_F(WantBaseTest, AaFwk_Want_Want_0100, Function | MediumTest | Level1) +{ + Want want; + + EXPECT_EQ((uint)0, want.GetFlags()); + EXPECT_EQ(std::string(""), want.GetAction()); + + std::vector vect = want.GetEntities(); + EXPECT_EQ((size_t)0, vect.size()); + EXPECT_EQ(std::string(""), want.GetType()); + + want.SetFlags(10); + want.SetAction("system.Action.test"); + want.AddEntity("system.Entity.test"); + want.SetType("system.Type.test"); + + Want want2(want); + EXPECT_EQ("system.Action.test", want2.GetAction()); + EXPECT_EQ(true, want2.HasEntity("system.Entity.test")); + EXPECT_EQ("system.Type.test", want2.GetType()); +} + +/** + * @tc.number: AaFwk_Want_Entity_0100 + * @tc.name: [AddEntity or RemoveEntity] & HasEntity &CountEntities + * @tc.desc: Verify [AddEntity or RemoveEntity] & HasEntity &CountEntities + */ +HWTEST_F(WantBaseTest, AaFwk_Want_Entity_0100, Function | MediumTest | Level1) +{ + std::string entity1 = "entity.system.entity1"; + + want_->AddEntity(entity1); + + EXPECT_EQ(true, want_->HasEntity(entity1)); + EXPECT_EQ(1, want_->CountEntities()); + want_->RemoveEntity(entity1); + EXPECT_EQ(false, want_->HasEntity(entity1)); + EXPECT_EQ(0, want_->CountEntities()); + int length = want_->GetEntities().size(); + EXPECT_EQ(0, length); + + std::string entity2 = "entity.system.entity2"; + + want_->AddEntity(entity1); + want_->AddEntity(entity2); + + EXPECT_EQ(true, want_->HasEntity(entity1)); + EXPECT_EQ(2, want_->CountEntities()); + EXPECT_EQ(true, want_->HasEntity(entity2)); + EXPECT_EQ(2, want_->CountEntities()); + + want_->RemoveEntity(entity1); + want_->RemoveEntity(entity2); + EXPECT_EQ(0, want_->CountEntities()); + int length2 = want_->GetEntities().size(); + + EXPECT_EQ(0, length2); +} + +/** + * @tc.number: AaFwk_Want_HasParameter_0100 + * @tc.name: SetParam and HasParameter + * @tc.desc: Verify HasParameter() + */ +HWTEST_F(WantBaseTest, AaFwk_Want_HasParameter_0100, Function | MediumTest | Level1) +{ + + std::vector vector; + std::string key = "system.want.test.key"; + std::string key2 = "system.want.test.key2"; + + vector.push_back("system.want.test.content"); + want_->SetParam(key, vector); + EXPECT_EQ(true, want_->HasParameter(key)); + + want_->SetParam(key2, vector); + EXPECT_EQ(true, want_->HasParameter(key2)); +} +/** + * @tc.number: AaFwk_Want_HasParameter_0200 + * @tc.name: SetParam and HasParameter + * @tc.desc: Verify HasParameter() + */ +HWTEST_F(WantBaseTest, AaFwk_Want_HasParameter_0200, Function | MediumTest | Level1) +{ + std::string key = std::to_string(Array::SIGNATURE) + ".#Intent;key=3{\"\\b\\\";end"; + std::vector arrayValue = {'.', '=', ';'}; + std::shared_ptr p1 = std::make_shared(); + if (p1 == nullptr) { + return; + } + p1->SetParam(key, arrayValue); + Want *newWant = nullptr; + newWant = Want::ParseUri(p1->ToUri()); + if (newWant == nullptr) { + return; + } + std::shared_ptr p2(newWant); + CompareWant(p1, p2); +} +} // namespace AAFwk +} // namespace OHOS diff --git a/tools/frameworks/kits/test/BUILD.gn b/tools/frameworks/kits/test/BUILD.gn new file mode 100755 index 00000000000..173a8cc511e --- /dev/null +++ b/tools/frameworks/kits/test/BUILD.gn @@ -0,0 +1,292 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/test.gni") + +module_output_path = "aafwk_standard/aafwk_L2" + +############################################################################### +#1. intent(c++) get/set test without transport + +config("module_private_config") { + visibility = [ ":*" ] + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + include_dirs = [ + "//third_party/json/include", + "//utils/native/base/include", + "//sdk/appexecfwk_L2/appexecfwk_base/include", + "//foundation/aafwk/standard/interfaces/innerkits/ability_manager/include", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler/include", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy/include", + "//utils/system/safwk/native/include", + "//foundation/aafwk/standard/services/common/include", + "//foundation/aafwk/standard/frameworks/kits/test/mock/AMS", + "//foundation/aafwk/standard/services/common/include", + "//foundation/aafwk/standard/frameworks/kits/ability/native/test/mock/include", + "//foundation/aafwk/standard/frameworks/kits/test/mock/DemoAbility", + "//foundation/aafwk/standard/services/abilitymgr/include", + "//third_party/jsoncpp/include", + "//foundation/aafwk/standard/interfaces/innerkits/dataobs_manager/include", + ] +} + +ohos_moduletest("ability_moduletest") { + module_out_path = module_output_path + sources = [ + "//foundation/aafwk/standard/frameworks/kits/ability/native/test/mock/include/mock_bundle_manager.cpp", + "//foundation/aafwk/standard/frameworks/kits/ability/native/test/mock/include/sys_mgr_client_mock.cpp", + "//foundation/aafwk/standard/frameworks/kits/test/mock/AMS/mock_ability_manager_client.cpp", + "//foundation/aafwk/standard/frameworks/kits/test/mock/AMS/mock_ability_manager_service.cpp", + "//foundation/aafwk/standard/frameworks/kits/test/mock/DemoAbility/demo_ability_test.cpp", + "//foundation/aafwk/standard/frameworks/kits/test/mock/DemoAbility/mock_lifecycle_observer.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/aafwk_dummy_configuration.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/ability_connect_callback_stub.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/ability_manager_proxy.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/ability_manager_stub.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/ability_mission_info.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/ability_record_info.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/ability_scheduler_proxy.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/ability_scheduler_stub.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/caller_info.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/image_info.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/lifecycle_state_info.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/mission_description_info.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/mission_option.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/mission_record_info.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/mission_snapshot_info.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/mission_stack_info.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/sender_info.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/stack_info.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/stack_setting.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/want_sender_info.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/wants_info.cpp", + "moduletest/cpp/abilitytest/ability_test.cpp", + ] + + configs = [ + ":module_private_config", + "//foundation/aafwk/standard/interfaces/innerkits/want:want_public_config", + "//foundation/aafwk/standard/frameworks/kits/ability/native:ability_config", + ] + + deps = [ + "//base/global/resmgr_standard/frameworks/resmgr:global_resmgr", + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/frameworks/kits/ability/native:dummy_classes", + "//foundation/aafwk/standard/interfaces/innerkits/base:base", + "//foundation/aafwk/standard/interfaces/innerkits/want:want", + "//foundation/appexecfwk/standard/common:libappexecfwk_common", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/kits:appkit_native", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy:samgr_proxy", + "//third_party/googletest:gmock_main", + "//third_party/googletest:gtest_main", + "//third_party/jsoncpp:jsoncpp", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + "native_appdatamgr:native_appdatafwk", + "native_appdatamgr:native_dataability", + "native_appdatamgr:native_rdb", + ] +} + +ohos_moduletest("ability_conetxt_test") { + module_out_path = module_output_path + sources = [ + "//foundation/aafwk/standard/frameworks/kits/ability/native/test/mock/include/mock_bundle_manager.cpp", + "//foundation/aafwk/standard/frameworks/kits/ability/native/test/mock/include/sys_mgr_client_mock.cpp", + "//foundation/aafwk/standard/frameworks/kits/test/mock/AMS/mock_ability_manager_client.cpp", + "//foundation/aafwk/standard/frameworks/kits/test/mock/AMS/mock_serviceability_manager_service.cpp", + "//foundation/aafwk/standard/frameworks/kits/test/mock/DemoAbility/demo_ability_test.cpp", + "//foundation/aafwk/standard/frameworks/kits/test/mock/DemoAbility/mock_lifecycle_observer.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/aafwk_dummy_configuration.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/ability_connect_callback_stub.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/ability_manager_proxy.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/ability_manager_stub.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/ability_record_info.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/ability_scheduler_proxy.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/ability_scheduler_stub.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/caller_info.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/lifecycle_state_info.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/mission_record_info.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/mission_stack_info.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/stack_info.cpp", + "//foundation/distributedschedule/dmsfwk/utils/native/source/uri.cpp", + "moduletest/cpp/abilitytest/ability_context_test.cpp", + ] + + configs = [ + ":module_private_config", + "//foundation/aafwk/standard/interfaces/innerkits/want:want_public_config", + "//foundation/aafwk/standard/frameworks/kits/ability/native:ability_config", + ] + + deps = [ + "//base/global/resmgr_standard/frameworks/resmgr:global_resmgr", + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/frameworks/kits/ability/native:dummy_classes", + "//foundation/aafwk/standard/interfaces/innerkits/ability_manager:ability_manager", + "//foundation/aafwk/standard/interfaces/innerkits/base:base", + "//foundation/aafwk/standard/interfaces/innerkits/want:want", + "//foundation/appexecfwk/standard/common:libappexecfwk_common", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/kits:appkit_native", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy:samgr_proxy", + "//third_party/googletest:gmock_main", + "//third_party/googletest:gtest_main", + "//third_party/jsoncpp:jsoncpp", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + "native_appdatamgr:native_appdatafwk", + "native_appdatamgr:native_dataability", + "native_appdatamgr:native_rdb", + ] +} + +ohos_moduletest("data_ability_operation_moduletest") { + module_out_path = module_output_path + sources = [ + "//foundation/aafwk/standard/frameworks/kits/ability/native/src/data_ability_operation.cpp", + "//foundation/aafwk/standard/frameworks/kits/ability/native/src/data_ability_operation_builder.cpp", + "//foundation/aafwk/standard/frameworks/kits/ability/native/test/mock/include/mock_bundle_manager.cpp", + "//foundation/aafwk/standard/frameworks/kits/ability/native/test/mock/include/sys_mgr_client_mock.cpp", + "//foundation/aafwk/standard/frameworks/kits/test/mock/AMS/mock_ability_manager_client.cpp", + "//foundation/aafwk/standard/frameworks/kits/test/mock/AMS/mock_ability_manager_service.cpp", + "//foundation/aafwk/standard/frameworks/kits/test/mock/DemoAbility/demo_ability_test.cpp", + "//foundation/aafwk/standard/frameworks/kits/test/mock/DemoAbility/mock_lifecycle_observer.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/aafwk_dummy_configuration.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/ability_connect_callback_stub.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/ability_manager_proxy.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/ability_manager_stub.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/ability_mission_info.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/ability_record_info.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/ability_scheduler_proxy.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/ability_scheduler_stub.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/caller_info.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/image_info.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/lifecycle_state_info.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/mission_description_info.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/mission_record_info.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/mission_snapshot_info.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/mission_stack_info.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/sender_info.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/stack_info.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/want_sender_info.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/wants_info.cpp", + "moduletest/cpp/abilitytest/data_ability_operation_module_test.cpp", + ] + + configs = [ + ":module_private_config", + "//foundation/aafwk/standard/interfaces/innerkits/want:want_public_config", + "//foundation/aafwk/standard/frameworks/kits/ability/native:ability_config", + ] + + deps = [ + "//base/global/resmgr_standard/frameworks/resmgr:global_resmgr", + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/frameworks/kits/ability/native:dummy_classes", + "//foundation/aafwk/standard/interfaces/innerkits/ability_manager:ability_manager", + "//foundation/aafwk/standard/interfaces/innerkits/base:base", + "//foundation/aafwk/standard/interfaces/innerkits/want:want", + "//foundation/appexecfwk/standard/common:libappexecfwk_common", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/kits:appkit_native", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy:samgr_proxy", + "//third_party/googletest:gmock_main", + "//third_party/googletest:gtest_main", + "//third_party/jsoncpp:jsoncpp", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + "native_appdatamgr:native_appdatafwk", + "native_appdatamgr:native_dataability", + "native_appdatamgr:native_rdb", + ] +} + +ohos_moduletest("data_ability_helper_module_test") { + module_out_path = module_output_path + + include_dirs = [ + "//foundation/aafwk/standard/frameworks/kits/test/mock/DemoAbility", + "//foundation/aafwk/standard/frameworks/kits/test/mock/DemoObServer", + "//foundation/aafwk/standard/frameworks/kits/ability/native/test/mock/include", + "//foundation/aafwk/standard/services/dataobsmgr/include", + "//foundation/aafwk/standard/interfaces/innerkits/dataobs_manager/include", + "//foundation/distributedschedule/samgr/services/samgr/native/include", + "//foundation/communication/ipc/interfaces/innerkits/libdbinder/include", + ] + + sources = [ "//foundation/aafwk/standard/frameworks/kits/test/moduletest/cpp/abilitytest/data_ability_helper_module_test.cpp" ] + + configs = [ + ":module_private_config", + "//foundation/aafwk/standard/interfaces/innerkits/want:want_public_config", + "//foundation/aafwk/standard/frameworks/kits/ability/native:ability_config", + ] + + deps = [ + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/interfaces/innerkits/ability_manager:ability_manager", + "//foundation/aafwk/standard/interfaces/innerkits/base:base", + "//foundation/aafwk/standard/interfaces/innerkits/want:want", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/appexecfwk/standard/kits:appkit_native", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//third_party/googletest:gmock_main", + "//third_party/googletest:gtest_main", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + "native_appdatamgr:native_appdatafwk", + "native_appdatamgr:native_dataability", + "native_appdatamgr:native_rdb", + ] +} + +################################################################################ +group("moduletest") { + testonly = true + + deps = [] + + if (is_phone_product) { + deps += [ + ":ability_conetxt_test", + ":ability_moduletest", + ":data_ability_helper_module_test", + ":data_ability_operation_moduletest", + ] + } +} diff --git a/tools/frameworks/kits/test/mock/AMS/mock_ability_manager_client.cpp b/tools/frameworks/kits/test/mock/AMS/mock_ability_manager_client.cpp new file mode 100755 index 00000000000..70d929b0a37 --- /dev/null +++ b/tools/frameworks/kits/test/mock/AMS/mock_ability_manager_client.cpp @@ -0,0 +1,229 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ability_manager_client.h" +#include "ability_manager_interface.h" +#include "string_ex.h" +#include "hilog_wrapper.h" +#include "ipc_skeleton.h" +#include "if_system_ability_manager.h" +#include "iservice_registry.h" +#include "system_ability_definition.h" +#include "sys_mgr_client.h" + +namespace OHOS { +namespace AAFwk { +std::shared_ptr mockMTInstance_ = nullptr; +std::mutex mockMTMutex_; + +std::shared_ptr AbilityManagerClient::GetInstance() +{ + if (mockMTInstance_ == nullptr) { + std::lock_guard lock_l(mockMTMutex_); + if (mockMTInstance_ == nullptr) { + mockMTInstance_ = std::make_shared(); + } + } + return mockMTInstance_; +} + +AbilityManagerClient::AbilityManagerClient() +{} + +AbilityManagerClient::~AbilityManagerClient() +{} + +ErrCode AbilityManagerClient::AttachAbilityThread( + const sptr &scheduler, const sptr &token) +{ + HILOG_INFO("AbilityManagerClient::AttachAbilityThread start"); + ErrCode err = Connect(); + if (err != ERR_OK) { + return ABILITY_SERVICE_NOT_CONNECTED; + } + + sptr abms = iface_cast(remoteObject_); + return abms->AttachAbilityThread(scheduler, token); +} + +ErrCode AbilityManagerClient::AbilityTransitionDone(const sptr &token, int state) +{ + if (remoteObject_ == nullptr) { + return ABILITY_SERVICE_NOT_CONNECTED; + } + sptr abms = iface_cast(remoteObject_); + return abms->AbilityTransitionDone(token, state); +} + +ErrCode AbilityManagerClient::ScheduleConnectAbilityDone( + const sptr &token, const sptr &remoteObject) +{ + if (remoteObject_ == nullptr) { + return ABILITY_SERVICE_NOT_CONNECTED; + } + sptr abms = iface_cast(remoteObject_); + return abms->ScheduleConnectAbilityDone(token, remoteObject); +} + +ErrCode AbilityManagerClient::ScheduleDisconnectAbilityDone(const sptr &token) +{ + if (remoteObject_ == nullptr) { + return ABILITY_SERVICE_NOT_CONNECTED; + } + sptr abms = iface_cast(remoteObject_); + return abms->ScheduleDisconnectAbilityDone(token); +} + +ErrCode AbilityManagerClient::ScheduleCommandAbilityDone(const sptr &token) +{ + if (remoteObject_ == nullptr) { + HILOG_ERROR("%{private}s:ability service not command", __func__); + return ABILITY_SERVICE_NOT_CONNECTED; + } + sptr abms = iface_cast(remoteObject_); + return abms->ScheduleCommandAbilityDone(token); +} + +void AbilityManagerClient::AddWindowInfo(const sptr &token, int32_t windowToken) +{ + if (remoteObject_ == nullptr) { + return; + } + sptr abms = iface_cast(remoteObject_); + abms->AddWindowInfo(token, windowToken); +} + +ErrCode AbilityManagerClient::StartAbility(const Want &want, int requestCode) +{ + if (remoteObject_ == nullptr) { + return ABILITY_SERVICE_NOT_CONNECTED; + } + sptr abms = iface_cast(remoteObject_); + return abms->StartAbility(want, requestCode); +} + +ErrCode AbilityManagerClient::TerminateAbility(const sptr &token, int resultCode, const Want *resultWant) +{ + HILOG_INFO("AbilityManagerClient::TerminateAbility start"); + if (remoteObject_ == nullptr) { + remoteObject_ = + OHOS::DelayedSingleton::GetInstance()->GetSystemAbility(ABILITY_MGR_SERVICE_ID); + } + sptr abms = iface_cast(remoteObject_); + HILOG_INFO("AbilityManagerClient::TerminateAbility end"); + return abms->TerminateAbility(token, resultCode, resultWant); +} + +ErrCode AbilityManagerClient::TerminateAbility(const sptr &callerToken, int requestCode) +{ + if (remoteObject_ == nullptr) { + HILOG_ERROR("%{private}s:ability service not connect", __func__); + return ABILITY_SERVICE_NOT_CONNECTED; + } + sptr abms = iface_cast(remoteObject_); + return abms->TerminateAbility(callerToken, requestCode); +} + +ErrCode AbilityManagerClient::ConnectAbility( + const Want &want, const sptr &connect, const sptr &callerToken) +{ + if (remoteObject_ == nullptr) { + remoteObject_ = + OHOS::DelayedSingleton::GetInstance()->GetSystemAbility(ABILITY_MGR_SERVICE_ID); + } + sptr abms = iface_cast(remoteObject_); + return abms->ConnectAbility(want, connect, callerToken); +} + +ErrCode AbilityManagerClient::DisconnectAbility(const sptr &connect) +{ + if (remoteObject_ == nullptr) { + remoteObject_ = + OHOS::DelayedSingleton::GetInstance()->GetSystemAbility(ABILITY_MGR_SERVICE_ID); + } + sptr abms = iface_cast(remoteObject_); + return abms->DisconnectAbility(connect); +} + +ErrCode AbilityManagerClient::DumpState(const std::string &args, std::vector &state) +{ + if (remoteObject_ == nullptr) { + return ABILITY_SERVICE_NOT_CONNECTED; + } + sptr abms = iface_cast(remoteObject_); + abms->DumpState(args, state); + return ERR_OK; +} + +ErrCode AbilityManagerClient::Connect() +{ + std::lock_guard lock(mockMTMutex_); + remoteObject_ = + OHOS::DelayedSingleton::GetInstance()->GetSystemAbility(ABILITY_MGR_SERVICE_ID); + if (remoteObject_ == nullptr) { + HILOG_ERROR("AbilityManagerClient::Connect remoteObject_ == nullptr"); + return ERR_NO_MEMORY; + } + + return ERR_OK; +} + +ErrCode AbilityManagerClient::GetAllStackInfo(StackInfo &stackInfo) +{ + if (remoteObject_ == nullptr) { + return ABILITY_SERVICE_NOT_CONNECTED; + } + + sptr abms = iface_cast(remoteObject_); + return abms->GetAllStackInfo(stackInfo); +} + +ErrCode AbilityManagerClient::StopServiceAbility(const Want &want) +{ + if (remoteObject_ == nullptr) { + remoteObject_ = + OHOS::DelayedSingleton::GetInstance()->GetSystemAbility(ABILITY_MGR_SERVICE_ID); + } + sptr abms = iface_cast(remoteObject_); + return abms->StopServiceAbility(want); +} + +sptr AbilityManagerClient::AcquireDataAbility( + const Uri &uri, bool tryBind, const sptr &callerToken) +{ + remoteObject_ = + OHOS::DelayedSingleton::GetInstance()->GetSystemAbility(ABILITY_MGR_SERVICE_ID); + if (remoteObject_ == nullptr) { + return nullptr; + } + + sptr abms = iface_cast(remoteObject_); + return abms->AcquireDataAbility(uri, tryBind, callerToken); +} + +ErrCode AbilityManagerClient::ReleaseDataAbility( + sptr dataAbilityScheduler, const sptr &callerToken) +{ + remoteObject_ = + OHOS::DelayedSingleton::GetInstance()->GetSystemAbility(ABILITY_MGR_SERVICE_ID); + if (remoteObject_ == nullptr) { + return -1; + } + + sptr abms = iface_cast(remoteObject_); + return abms->ReleaseDataAbility(dataAbilityScheduler, callerToken); +} +} // namespace AAFwk +} // namespace OHOS diff --git a/tools/frameworks/kits/test/mock/AMS/mock_ability_manager_service.cpp b/tools/frameworks/kits/test/mock/AMS/mock_ability_manager_service.cpp new file mode 100644 index 00000000000..cde12b1ab22 --- /dev/null +++ b/tools/frameworks/kits/test/mock/AMS/mock_ability_manager_service.cpp @@ -0,0 +1,238 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "mock_ability_manager_service.h" +#include + +#include +#include +#include +#include + +using OHOS::AppExecFwk::ElementName; + +namespace OHOS { +namespace AAFwk { +MockAbilityManagerService::MockAbilityManagerService() : abilityScheduler_(nullptr) +{ + abilityScheduler_ = nullptr; +} + +MockAbilityManagerService::~MockAbilityManagerService() +{} + +int MockAbilityManagerService::StartAbility(const Want &want, int requestCode) +{ + GTEST_LOG_(INFO) << "MockAbilityManagerService::StartAbility called"; + curstate_ = AbilityLifeCycleState::ABILITY_STATE_INITIAL; + switch (requestCode) { + case AbilityLifeCycleState::ABILITY_STATE_INITIAL: + curstate_ = AbilityLifeCycleState::ABILITY_STATE_INITIAL; + break; + case AbilityLifeCycleState::ABILITY_STATE_INACTIVE: + curstate_ = AbilityLifeCycleState::ABILITY_STATE_INACTIVE; + break; + case AbilityLifeCycleState::ABILITY_STATE_ACTIVE: + curstate_ = AbilityLifeCycleState::ABILITY_STATE_ACTIVE; + break; + case AbilityLifeCycleState::ABILITY_STATE_BACKGROUND: + curstate_ = AbilityLifeCycleState::ABILITY_STATE_BACKGROUND; + break; + case AbilityLifeCycleState::ABILITY_STATE_SUSPENDED: + curstate_ = AbilityLifeCycleState::ABILITY_STATE_SUSPENDED; + break; + default: + break; + } + + if (abilityScheduler_ != nullptr) { + want_ = want; + want_.SetElementName("BundleName", "abilityName"); + LifeCycleStateInfo stateInfo; + stateInfo.state = curstate_; + abilityScheduler_->ScheduleAbilityTransaction(want_, stateInfo); + } + + return 0; +} + +int MockAbilityManagerService::StartAbility(const Want &want, const sptr &callerToken, int requestCode) +{ + return 0; +} + +int MockAbilityManagerService::TerminateAbility( + const sptr &token, int resultCode, const Want *resultWant) +{ + GTEST_LOG_(INFO) << "MockAbilityManagerService::TerminateAbility"; + + if (abilityScheduler_ != nullptr) { + LifeCycleStateInfo stateInfo; + stateInfo.state = AbilityLifeCycleState::ABILITY_STATE_INITIAL; + curstate_ = AbilityLifeCycleState::ABILITY_STATE_INITIAL; + abilityScheduler_->ScheduleAbilityTransaction(want_, stateInfo); + + int ceode = 250; + abilityScheduler_->SendResult(ceode, resultCode, *resultWant); + } + return 0; +} + +int MockAbilityManagerService::ConnectAbility( + const Want &want, const sptr &connect, const sptr &callerToken) +{ + if (abilityScheduler_ != nullptr) { + PacMap inState; + abilityScheduler_->ScheduleSaveAbilityState(inState); + abilityScheduler_->ScheduleRestoreAbilityState(inState); + } + return 0; +} + +int MockAbilityManagerService::DisconnectAbility(const sptr &connect) +{ + GTEST_LOG_(INFO) << "MockAbilityManagerService::DisconnectAbility"; + AbilityLifeCycleState lifeState = AbilityLifeCycleState::ABILITY_STATE_ACTIVE; + + if (abilityScheduler_ != nullptr) { + LifeCycleStateInfo stateInfo; + stateInfo.state = lifeState; + stateInfo.isNewWant = true; + want_.SetElementName("BundleName", "abilityName"); + curstate_ = AbilityLifeCycleState::ABILITY_STATE_ACTIVE; + abilityScheduler_->ScheduleAbilityTransaction(want_, stateInfo); + } + return 0; +} + +int MockAbilityManagerService::AttachAbilityThread( + const sptr &scheduler, const sptr &token) +{ + abilityScheduler_ = scheduler; + EXPECT_NE(nullptr, token); + return 0; +} + +void MockAbilityManagerService::DumpState(const std::string &args, std::vector &info) +{} + +int MockAbilityManagerService::AbilityTransitionDone(const sptr &token, int state) +{ + GTEST_LOG_(INFO) << "MockAbilityManagerService::AbilityTransitionDone called"; + EXPECT_EQ(curstate_, state); + return 0; +} + +int MockAbilityManagerService::ScheduleConnectAbilityDone( + const sptr &token, const sptr &remoteObject) +{ + return 0; +} + +int MockAbilityManagerService::ScheduleDisconnectAbilityDone(const sptr &token) +{ + return 0; +} + +int MockAbilityManagerService::ScheduleCommandAbilityDone(const sptr &token) +{ + return 0; +} + +void MockAbilityManagerService::AddWindowInfo(const sptr &token, int32_t windowToken) +{} + +int MockAbilityManagerService::TerminateAbilityByCaller(const sptr &callerToken, int requestCode) +{ + return 0; +} + +int MockAbilityManagerService::TerminateAbilityResult(const sptr &token, int startId) +{ + return 0; +} + +int MockAbilityManagerService::StopServiceAbility(const Want &want) +{ + return 0; +} + +int MockAbilityManagerService::GetRecentMissions( + const int32_t numMax, const int32_t flags, std::vector &recentList) +{ + return 0; +} + +int MockAbilityManagerService::GetMissionSnapshot(const int32_t missionId, MissionSnapshotInfo &snapshot) +{ + return 0; +} + +int MockAbilityManagerService::RemoveMission(int id) +{ + return 0; +} + +int MockAbilityManagerService::RemoveStack(int id) +{ + return 0; +} + +sptr MockAbilityManagerService::AcquireDataAbility( + const Uri &uri, bool tryBind, const sptr &callerToken) +{ + if (abilityScheduler_ != nullptr) { + return abilityScheduler_; + } + return nullptr; +} + +ErrCode MockAbilityManagerService::ReleaseDataAbility( + sptr dataAbilityScheduler, const sptr &callerToken) +{ + if (abilityScheduler_ != nullptr) { + abilityScheduler_ = nullptr; + return 0; + } + return -1; +} + +int MockAbilityManagerService::MoveMissionToEnd(const sptr &token, const bool nonFirst) +{ + return 0; +} + +bool MockAbilityManagerService::IsFirstInMission(const sptr &token) +{ + return true; +} + +int MockAbilityManagerService::CompelVerifyPermission( + const std::string &permission, int pid, int uid, std::string &message) +{ + return 0; +} + +int MockAbilityManagerService::PowerOff() +{ + return 0; +} +int MockAbilityManagerService::PowerOn() +{ + return 0; +} + +} // namespace AAFwk +} // namespace OHOS diff --git a/tools/frameworks/kits/test/mock/AMS/mock_ability_manager_service.h b/tools/frameworks/kits/test/mock/AMS/mock_ability_manager_service.h new file mode 100644 index 00000000000..1d1f45d272a --- /dev/null +++ b/tools/frameworks/kits/test/mock/AMS/mock_ability_manager_service.h @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_ABILITY_MOCK_MANAGER_SERVICE_H +#define OHOS_AAFWK_ABILITY_MOCK_MANAGER_SERVICE_H + +#include +#include +#include +#include + +#include "ability_manager_stub.h" +#include "iremote_object.h" + +#include "gmock/gmock.h" + +namespace OHOS { +namespace AAFwk { +enum class ServiceRunningState { STATE_NOT_START, STATE_RUNNING }; + +class MockAbilityManagerService : public AbilityManagerStub, + public std::enable_shared_from_this { +public: + MockAbilityManagerService(); + ~MockAbilityManagerService(); + int StartAbility(const Want &want, int requestCode = -1) override; + int StartAbility(const Want &want, const sptr &callerToken, int requestCode = -1) override; + int TerminateAbility( + const sptr &token, int resultCode = -1, const Want *resultWant = nullptr) override; + int ConnectAbility( + const Want &want, const sptr &connect, const sptr &callerToken) override; + int DisconnectAbility(const sptr &connect) override; + + sptr AcquireDataAbility(const Uri &uri, bool tryBind, const sptr &callerToken); + + ErrCode ReleaseDataAbility(sptr dataAbilityScheduler, const sptr &callerToken); + + void AddWindowInfo(const sptr &token, int32_t windowToken) override; + + int AttachAbilityThread(const sptr &scheduler, const sptr &token) override; + + int AbilityTransitionDone(const sptr &token, int state) override; + int ScheduleConnectAbilityDone(const sptr &token, const sptr &remoteObject) override; + int ScheduleDisconnectAbilityDone(const sptr &token) override; + int ScheduleCommandAbilityDone(const sptr &token) override; + + void DumpState(const std::string &args, std::vector &info) override; + int TerminateAbilityByCaller(const sptr &callerToken, int requestCode) override; + int TerminateAbilityResult(const sptr &token, int startId) override; + int StopServiceAbility(const Want &want) override; + + MOCK_METHOD1(GetAllStackInfo, int(StackInfo &stackInfo)); + + MOCK_METHOD1(MoveMissionToTop, int(int32_t missionId)); + MOCK_METHOD1(KillProcess, int(const std::string &bundleName)); + MOCK_METHOD1(UninstallApp, int(const std::string &bundleName)); + MOCK_METHOD2( + GetWantSender, sptr(const WantSenderInfo &wantSenderInfo, const sptr &callerToken)); + MOCK_METHOD2(SendWantSender, int(const sptr &target, const SenderInfo &senderInfo)); + MOCK_METHOD1(CancelWantSender, void(const sptr &sender)); + MOCK_METHOD1(GetPendingWantUid, int(const sptr &target)); + MOCK_METHOD1(GetPendingWantUserId, int(const sptr &target)); + MOCK_METHOD1(GetPendingWantBundleName, std::string(const sptr &target)); + MOCK_METHOD1(GetPendingWantCode, int(const sptr &target)); + MOCK_METHOD1(GetPendingWantType, int(const sptr &target)); + MOCK_METHOD2(RegisterCancelListener, void(const sptr &sender, const sptr &receiver)); + MOCK_METHOD2(UnregisterCancelListener, void(const sptr &sender, const sptr &receiver)); + MOCK_METHOD2(GetPendingRequestWant, int(const sptr &target, std::shared_ptr &want)); + MOCK_METHOD4(StartAbility, int(const Want &want, const AbilityStartSetting &abilityStartSetting, + const sptr &callerToken, int requestCode)); + MOCK_METHOD1(MoveMissionToFloatingStack, int(const MissionOption &missionOption)); + MOCK_METHOD1(MoveMissionToSplitScreenStack, int(const MissionOption &missionOption)); + MOCK_METHOD2( + ChangeFocusAbility, int(const sptr &lostFocusToken, const sptr &getFocusToken)); + MOCK_METHOD1(MinimizeMultiWindow, int(int missionId)); + MOCK_METHOD1(MaximizeMultiWindow, int(int missionId)); + MOCK_METHOD1(GetFloatingMissions, int(std::vector &list)); + MOCK_METHOD1(CloseMultiWindow, int(int missionId)); + MOCK_METHOD1(SetMissionStackSetting, int(const StackSetting &stackSetting)); + MOCK_METHOD1(GetPendinTerminateAbilityTestgRequestWant, void(int id)); + + int MoveMissionToEnd(const sptr &token, const bool nonFirst) override; + bool IsFirstInMission(const sptr &token) override; + int CompelVerifyPermission(const std::string &permission, int pid, int uid, std::string &message) override; + + int GetRecentMissions( + const int32_t numMax, const int32_t flags, std::vector &recentList) override; + + int GetMissionSnapshot(const int32_t missionId, MissionSnapshotInfo &snapshot) override; + + int RemoveMission(int id) override; + + int RemoveStack(int id) override; + int PowerOff() override; + int PowerOn() override; + int LockMission(int missionId) override + { + return 0; + }; + int UnlockMission(int missionId) override + { + return 0; + }; + int SetMissionDescriptionInfo( + const sptr &token, const MissionDescriptionInfo &missionDescriptionInfo) override + { + return 0; + }; + int GetMissionLockModeState() + { + return 0; + } + + int UpdateConfiguration(const DummyConfiguration &config) + { + return 0; + } + + AbilityLifeCycleState curstate_ = AbilityLifeCycleState::ABILITY_STATE_INITIAL; + sptr abilityScheduler_; // kit interface used to schedule ability life + Want want_; +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_ABILITY_MANAGER_SERVICE_H diff --git a/tools/frameworks/kits/test/mock/AMS/mock_serviceability_manager_service.cpp b/tools/frameworks/kits/test/mock/AMS/mock_serviceability_manager_service.cpp new file mode 100644 index 00000000000..a6c139f2c7a --- /dev/null +++ b/tools/frameworks/kits/test/mock/AMS/mock_serviceability_manager_service.cpp @@ -0,0 +1,209 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "mock_serviceability_manager_service.h" +#include + +#include +#include +#include +#include + +using OHOS::AppExecFwk::ElementName; + +namespace OHOS { +namespace AAFwk { +MockServiceAbilityManagerService::MockServiceAbilityManagerService() +{} + +MockServiceAbilityManagerService::~MockServiceAbilityManagerService() +{} + +int MockServiceAbilityManagerService::StartAbility(const Want &want, int requestCode) +{ + GTEST_LOG_(INFO) << "MockServiceAbilityManagerService::StartAbility"; + if (abilityScheduler_ != nullptr) { + startAbility = true; + LifeCycleStateInfo stateInfo; + stateInfo.state = AbilityLifeCycleState::ABILITY_STATE_INACTIVE; + want_.SetElementName("BundleName", "abilityName"); + abilityScheduler_->ScheduleAbilityTransaction(want_, stateInfo); + return ERR_OK; + } + return 0; +} + +int MockServiceAbilityManagerService::StartAbility( + const Want &want, const sptr &callerToken, int requestCode) +{ + return 0; +} + +int MockServiceAbilityManagerService::TerminateAbility( + const sptr &token, int resultCode, const Want *resultWant) +{ + GTEST_LOG_(INFO) << "MockServiceAbilityManagerService::TerminateAbility"; + if (abilityScheduler_ != nullptr) { + startAbility = false; + LifeCycleStateInfo stateInfo; + stateInfo.state = AbilityLifeCycleState::ABILITY_STATE_INITIAL; + want_.SetElementName("BundleName", "abilityName"); + abilityScheduler_->ScheduleAbilityTransaction(want_, stateInfo); + return ERR_OK; + } + return 0; +} + +int MockServiceAbilityManagerService::ConnectAbility( + const Want &want, const sptr &connect, const sptr &callerToken) +{ + GTEST_LOG_(INFO) << "MockServiceAbilityManagerService::connectAbility"; + if (abilityScheduler_ != nullptr) { + startAbility = false; + LifeCycleStateInfo stateInfo; + stateInfo.state = AbilityLifeCycleState::ABILITY_STATE_INACTIVE; + want_.SetElementName("BundleName", "abilityName"); + abilityScheduler_->ScheduleAbilityTransaction(want_, stateInfo); + return ERR_OK; + } + return -1; +} + +int MockServiceAbilityManagerService::DisconnectAbility(const sptr &connect) +{ + GTEST_LOG_(INFO) << "MockServiceAbilityManagerService::DisconnectAbility"; + if (abilityScheduler_ != nullptr) { + Want want; + want.SetElementName("BundleName", "abilityName"); + abilityScheduler_->ScheduleDisconnectAbility(want_); + return ERR_OK; + } + return 0; +} + +int MockServiceAbilityManagerService::AttachAbilityThread( + const sptr &scheduler, const sptr &token) +{ + abilityScheduler_ = scheduler; + EXPECT_NE(nullptr, token); + return 0; +} + +void MockServiceAbilityManagerService::DumpState(const std::string &args, std::vector &info) +{} + +int MockServiceAbilityManagerService::AbilityTransitionDone(const sptr &token, int state) +{ + GTEST_LOG_(INFO) << "MockServiceAbilityManagerService::AbilityTransitionDone startAbility is " << startAbility; + want_.SetElementName("BundleName", "abilityName"); + if (abilityScheduler_ != nullptr && state == AAFwk::ABILITY_STATE_INACTIVE) { + want_.SetElementName("BundleName", "abilityName"); + if (startAbility) { + abilityScheduler_->ScheduleCommandAbility(want_, false, -1); + } else { + abilityScheduler_->ScheduleConnectAbility(want_); + } + } + return 0; +} + +int MockServiceAbilityManagerService::ScheduleConnectAbilityDone( + const sptr &token, const sptr &remoteObject) +{ + GTEST_LOG_(INFO) << "MockServiceAbilityManagerService::ScheduleConnectAbilityDone"; + return 0; +} + +int MockServiceAbilityManagerService::ScheduleDisconnectAbilityDone(const sptr &token) +{ + GTEST_LOG_(INFO) << "MockServiceAbilityManagerService::ScheduleDisconnectAbilityDone"; + + if (abilityScheduler_ != nullptr) { + LifeCycleStateInfo stateInfo; + stateInfo.state = AbilityLifeCycleState::ABILITY_STATE_INITIAL; + abilityScheduler_->ScheduleAbilityTransaction(want_, stateInfo); + return ERR_OK; + } + return 0; +} + +int MockServiceAbilityManagerService::ScheduleCommandAbilityDone(const sptr &token) +{ + return 0; +} + +void MockServiceAbilityManagerService::AddWindowInfo(const sptr &token, int32_t windowToken) +{} + +int MockServiceAbilityManagerService::TerminateAbilityResult(const sptr &token, int startId) +{ + return 0; +} + +int MockServiceAbilityManagerService::TerminateAbilityByCaller(const sptr &callerToken, int requestCode) +{ + return 0; +} + +int MockServiceAbilityManagerService::StopServiceAbility(const Want &want) +{ + GTEST_LOG_(INFO) << "MockServiceAbilityManagerService::StopServiceAbility"; + if (abilityScheduler_ != nullptr) { + startAbility = false; + LifeCycleStateInfo stateInfo; + stateInfo.state = AbilityLifeCycleState::ABILITY_STATE_INITIAL; + want_.SetElementName("BundleName", "abilityName"); + abilityScheduler_->ScheduleAbilityTransaction(want_, stateInfo); + return ERR_OK; + } + return -1; +} + +int MockServiceAbilityManagerService::RemoveMission(int id) +{ + return 0; +} + +int MockServiceAbilityManagerService::RemoveStack(int id) +{ + return 0; +} + +int MockServiceAbilityManagerService::MoveMissionToEnd(const sptr &token, const bool nonFirst) +{ + return 0; +} + +bool MockServiceAbilityManagerService::IsFirstInMission(const sptr &token) +{ + return true; +} + +int MockServiceAbilityManagerService::CompelVerifyPermission(const std::string &permission, int pid, int uid, std::string &message) +{ + return 0; +} + +int MockServiceAbilityManagerService::PowerOff() +{ + return 0; +} +int MockServiceAbilityManagerService::PowerOn() +{ + return 0; +} + +} // namespace AAFwk +} // namespace OHOS diff --git a/tools/frameworks/kits/test/mock/AMS/mock_serviceability_manager_service.h b/tools/frameworks/kits/test/mock/AMS/mock_serviceability_manager_service.h new file mode 100644 index 00000000000..7fea6a0c2db --- /dev/null +++ b/tools/frameworks/kits/test/mock/AMS/mock_serviceability_manager_service.h @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_SERVICEABILITY_MOCK_MANAGER_SERVICE_H +#define OHOS_AAFWK_SERVICEABILITY_MOCK_MANAGER_SERVICE_H + +#include +#include +#include +#include + +#include "ability_manager_stub.h" +#include "iremote_object.h" + +#include "gmock/gmock.h" + +namespace OHOS { +namespace AAFwk { +enum class ServiceRunningState { STATE_NOT_START, STATE_RUNNING }; +class MockServiceAbilityManagerService : public AbilityManagerStub, + public std::enable_shared_from_this { +public: + MockServiceAbilityManagerService(); + ~MockServiceAbilityManagerService(); + int StartAbility(const Want &want, int requestCode = -1) override; + int StartAbility(const Want &want, const sptr &callerToken, int requestCode = -1) override; + int TerminateAbility( + const sptr &token, int resultCode = -1, const Want *resultWant = nullptr) override; + int ConnectAbility( + const Want &want, const sptr &connect, const sptr &callerToken) override; + int DisconnectAbility(const sptr &connect) override; + + void AddWindowInfo(const sptr &token, int32_t windowToken) override; + + int AttachAbilityThread(const sptr &scheduler, const sptr &token) override; + + int AbilityTransitionDone(const sptr &token, int state) override; + int ScheduleConnectAbilityDone(const sptr &token, const sptr &remoteObject) override; + int ScheduleDisconnectAbilityDone(const sptr &token) override; + int ScheduleCommandAbilityDone(const sptr &token) override; + + void DumpState(const std::string &args, std::vector &info) override; + + int TerminateAbilityResult(const sptr &token, int startId) override; + int StopServiceAbility(const Want &want) override; + + int TerminateAbilityByCaller(const sptr &callerToken, int requestCode) override; + + MOCK_METHOD1(GetAllStackInfo, int(StackInfo &stackInfo)); + MOCK_METHOD1(MoveMissionToTop, int(int32_t missionId)); + MOCK_METHOD1(KillProcess, int(const std::string &bundleName)); + MOCK_METHOD1(UninstallApp, int(const std::string &bundleName)); + MOCK_METHOD2( + GetWantSender, sptr(const WantSenderInfo &wantSenderInfo, const sptr &callerToken)); + MOCK_METHOD2(SendWantSender, int(const sptr &target, const SenderInfo &senderInfo)); + MOCK_METHOD1(CancelWantSender, void(const sptr &sender)); + MOCK_METHOD1(GetPendingWantUid, int(const sptr &target)); + MOCK_METHOD1(GetPendingWantUserId, int(const sptr &target)); + MOCK_METHOD1(GetPendingWantBundleName, std::string(const sptr &target)); + MOCK_METHOD1(GetPendingWantCode, int(const sptr &target)); + MOCK_METHOD1(GetPendingWantType, int(const sptr &target)); + MOCK_METHOD2(RegisterCancelListener, void(const sptr &sender, const sptr &receiver)); + MOCK_METHOD2(UnregisterCancelListener, void(const sptr &sender, const sptr &receiver)); + MOCK_METHOD2(GetPendingRequestWant, int(const sptr &target, std::shared_ptr &want)); + MOCK_METHOD4(StartAbility, int(const Want &want, const AbilityStartSetting &abilityStartSetting, + const sptr &callerToken, int requestCode)); + MOCK_METHOD1(MoveMissionToFloatingStack, int(const MissionOption &missionOption)); + MOCK_METHOD1(MoveMissionToSplitScreenStack, int(const MissionOption &missionOption)); + MOCK_METHOD2( + ChangeFocusAbility, int(const sptr &lostFocusToken, const sptr &getFocusToken)); + MOCK_METHOD1(MinimizeMultiWindow, int(int missionId)); + MOCK_METHOD1(MaximizeMultiWindow, int(int missionId)); + MOCK_METHOD1(GetFloatingMissions, int(std::vector &list)); + MOCK_METHOD1(CloseMultiWindow, int(int missionId)); + MOCK_METHOD1(SetMissionStackSetting, int(const StackSetting &stackSetting)); + MOCK_METHOD1(GetPendinTerminateAbilityTestgRequestWant, void(int id)); + + int MoveMissionToEnd(const sptr &token, const bool nonFirst) override; + bool IsFirstInMission(const sptr &token) override; + int CompelVerifyPermission(const std::string &permission, int pid, int uid, std::string &message) override; + + int RemoveMission(int id) override; + + int RemoveStack(int id) override; + int PowerOff() override; + int PowerOn() override; + int LockMission(int missionId) override + { + return 0; + } + int UnlockMission(int missionId) override + { + return 0; + } + int SetMissionDescriptionInfo( + const sptr &token, const MissionDescriptionInfo &missionDescriptionInfo) override + { + return 0; + } + int GetMissionLockModeState() + { + return 0; + } + int UpdateConfiguration(const DummyConfiguration &config) + { + return 0; + } + + sptr AcquireDataAbility( + const Uri &uri, bool tryBind, const sptr &callerToken) override + { + return nullptr; + } + + int ReleaseDataAbility( + sptr dataAbilityScheduler, const sptr &callerToken) override + { + return 0; + } + + int GetRecentMissions( + const int32_t numMax, const int32_t flags, std::vector &recentList) override + { + return 0; + } + + int GetMissionSnapshot(const int32_t missionId, MissionSnapshotInfo &snapshot) + { + return 0; + } + + sptr abilityScheduler_ = nullptr; // kit interface used to schedule ability life + Want want_; + bool startAbility = false; +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_SERVICEABILITY_MOCK_MANAGER_SERVICE_H diff --git a/tools/frameworks/kits/test/mock/DemoAbility/demo_ability_test.cpp b/tools/frameworks/kits/test/mock/DemoAbility/demo_ability_test.cpp new file mode 100644 index 00000000000..a69a0a1eda1 --- /dev/null +++ b/tools/frameworks/kits/test/mock/DemoAbility/demo_ability_test.cpp @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "abs_shared_result_set.h" +#include "data_ability_predicates.h" +#include "values_bucket.h" +#include "demo_ability_test.h" +#include +#include +#include +#include "mock_lifecycle_observer.h" + +using namespace std; +const int openfileValue = 123; +const int deleteValue = 234; +const int insertValue = 345; +const int updateValue = 456; +const int openRawFileValue = 567; +const int batchInsertValue = 789; +const int resultCodeCompare = 1992; + +namespace OHOS { +namespace AppExecFwk { +void DemoAbility::OnStart(const Want &want) +{ + GTEST_LOG_(INFO) << "DemoAbility::OnStart called"; + std::shared_ptr observer = std::make_shared(); + Ability::GetLifecycle()->AddObserver(observer); + Ability::OnStart(want); + EXPECT_STREQ(std::string("abilityName").c_str(), want.GetElement().GetAbilityName().c_str()); +} +void DemoAbility::OnStop() +{ + GTEST_LOG_(INFO) << "DemoAbility::OnStop called"; + Ability::OnStop(); +} +void DemoAbility::OnActive() +{ + GTEST_LOG_(INFO) << "DemoAbility::OnActive called"; + Ability::OnActive(); + std::shared_ptr abilityInfo = GetAbilityInfo(); + if (AppExecFwk::AbilityType::PAGE == abilityInfo->type) { + EXPECT_NE(nullptr, Ability::GetWindow()); + } +} +void DemoAbility::OnInactive() +{ + GTEST_LOG_(INFO) << "DemoAbility::OnInactive called"; + Ability::OnInactive(); +} +void DemoAbility::OnBackground() +{ + GTEST_LOG_(INFO) << "DemoAbility::OnBackground called"; + Ability::OnBackground(); +} + +void DemoAbility::OnForeground(const Want &want) +{ + GTEST_LOG_(INFO) << "DemoAbility::OnForeground called"; + Ability::OnForeground(want); +} + +void DemoAbility::OnNewWant(const Want &want) +{ + GTEST_LOG_(INFO) << "DemoAbility::OnNewWant called"; +} + +void DemoAbility::OnRestoreAbilityState(const PacMap &inState) +{ + GTEST_LOG_(INFO) << "DemoAbility::OnRestoreAbilityState called"; +} + +void DemoAbility::OnSaveAbilityState(PacMap &outState) +{ + std::shared_ptr appInfo = GetApplicationInfo(); + std::shared_ptr abilityInfo = GetAbilityInfo(); + + EXPECT_STREQ(abilityInfo->resourcePath.c_str(), std::string("resourcePath").c_str()); + EXPECT_STREQ(appInfo->dataDir.c_str(), std::string("dataDir").c_str()); + EXPECT_STREQ(GetCodeCacheDir().c_str(), std::string("dataDir/code_cache").c_str()); + EXPECT_STREQ(GetCacheDir().c_str(), std::string("cacheDir").c_str()); + EXPECT_STREQ(GetDatabaseDir().c_str(), std::string("dataBaseDir").c_str()); + EXPECT_STREQ(GetDataDir().c_str(), std::string("dataDir").c_str()); + EXPECT_STREQ(GetBundleCodePath().c_str(), std::string("codePath").c_str()); + EXPECT_STREQ(GetBundleName().c_str(), std::string("bundleName").c_str()); + EXPECT_STREQ(GetBundleResourcePath().c_str(), std::string("resourcePath").c_str()); + EXPECT_STREQ(GetAppType().c_str(), std::string("system").c_str()); + + EXPECT_NE(GetBundleManager(), nullptr); + EXPECT_NE(GetApplicationContext(), nullptr); + EXPECT_NE(GetContext(), nullptr); + EXPECT_NE(GetAbilityManager(), nullptr); + EXPECT_NE(GetProcessInfo(), nullptr); + + GTEST_LOG_(INFO) << "DemoAbility::OnSaveAbilityState called"; +} + +void DemoAbility::OnAbilityResult(int requestCode, int resultCode, const Want &resultData) +{ + GTEST_LOG_(INFO) << "DemoAbility::OnAbilityResult called"; + EXPECT_EQ(resultCodeCompare, resultCode); +} + +sptr DemoAbility::OnConnect(const Want &want) +{ + GTEST_LOG_(INFO) << "DemoAbility::OnConnect called"; + Ability::OnConnect(want); + EXPECT_STREQ(std::string("abilityName").c_str(), want.GetElement().GetAbilityName().c_str()); + return nullptr; +} + +void DemoAbility::OnDisconnect(const Want &want) +{ + GTEST_LOG_(INFO) << "DemoAbility::OnDisconnect called"; + Ability::OnDisconnect(want); + EXPECT_STREQ(std::string("abilityName").c_str(), want.GetElement().GetAbilityName().c_str()); +} + +void DemoAbility::OnCommand(const AAFwk::Want &want, bool restart, int startId) +{ + GTEST_LOG_(INFO) << "DemoAbility::OnCommand called"; + EXPECT_STREQ(std::string("abilityName").c_str(), want.GetElement().GetAbilityName().c_str()); + Ability::OnCommand(want, restart, startId); +} + +std::vector DemoAbility::GetFileTypes(const Uri &uri, const std::string &mimeTypeFilter) +{ + GTEST_LOG_(INFO) << "DemoAbility::GetFileTypes called"; + std::vector types; + types.push_back("Type1"); + types.push_back("Type2"); + types.push_back("Type3"); + return types; +} + +int DemoAbility::OpenFile(const Uri &uri, const std::string &mode) +{ + GTEST_LOG_(INFO) << "DemoAbility::OpenFile called"; + return openfileValue; +} + +int DemoAbility::Delete(const Uri &uri, const NativeRdb::DataAbilityPredicates &predicates) +{ + GTEST_LOG_(INFO) << "DemoAbility::Delete called"; + return deleteValue; +} + +int DemoAbility::Insert(const Uri &uri, const NativeRdb::ValuesBucket &value) +{ + GTEST_LOG_(INFO) << "DemoAbility::Insert called"; + return insertValue; +} + +int DemoAbility::Update(const Uri &uri, const NativeRdb::ValuesBucket &value, const NativeRdb::DataAbilityPredicates &predicates) +{ + GTEST_LOG_(INFO) << "DemoAbility::Update called"; + return updateValue; +} + +int DemoAbility::OpenRawFile(const Uri &uri, const std::string &mode) +{ + GTEST_LOG_(INFO) << "DemoAbility::OpenRawFile called"; + return openRawFileValue; +} + +bool DemoAbility::Reload(const Uri &uri, const PacMap &extras) +{ + GTEST_LOG_(INFO) << "DemoAbility::Reload called"; + return true; +} + +int DemoAbility::BatchInsert(const Uri &uri, const std::vector &values) +{ + GTEST_LOG_(INFO) << "DemoAbility::BatchInsert called"; + return batchInsertValue; +} + +std::string DemoAbility::GetType(const Uri &uri) +{ + GTEST_LOG_(INFO) << "DemoAbility::GetType called"; + std::string type("Type1"); + return type; +} + +std::shared_ptr DemoAbility::Query( + const Uri &uri, const std::vector &columns, const NativeRdb::DataAbilityPredicates &predicates) +{ + GTEST_LOG_(INFO) << "DemoAbility::Query called"; + std::shared_ptr resultset = std::make_shared("resultset"); + return resultset; +} + +REGISTER_AA(DemoAbility) +} // namespace AppExecFwk +} // namespace OHOS diff --git a/tools/frameworks/kits/test/mock/DemoAbility/demo_ability_test.h b/tools/frameworks/kits/test/mock/DemoAbility/demo_ability_test.h new file mode 100644 index 00000000000..1830d503005 --- /dev/null +++ b/tools/frameworks/kits/test/mock/DemoAbility/demo_ability_test.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DEMO_ABILITY_H +#define DEMO_ABILITY_H +#include "ability.h" +#include "ability_loader.h" +#include "want.h" + +namespace OHOS { +namespace AppExecFwk { +class DemoAbility : public Ability { +protected: + virtual void OnStart(const Want &want) override; + virtual void OnStop() override; + virtual void OnActive() override; + virtual void OnInactive() override; + virtual void OnBackground() override; + virtual void OnForeground(const Want &want) override; + virtual void OnNewWant(const Want &want) override; + virtual sptr OnConnect(const Want &want) override; + virtual void OnDisconnect(const Want &want) override; + virtual void OnCommand(const AAFwk::Want &want, bool restart, int startId) override; + + virtual void OnRestoreAbilityState(const PacMap &inState); + virtual void OnSaveAbilityState(PacMap &outState); + virtual void OnAbilityResult(int requestCode, int resultCode, const Want &resultData); + + virtual std::vector GetFileTypes(const Uri &uri, const std::string &mimeTypeFilter); + virtual int OpenFile(const Uri &uri, const std::string &mode); + virtual int Delete(const Uri &uri, const NativeRdb::DataAbilityPredicates &predicates); + virtual int Insert(const Uri &uri, const NativeRdb::ValuesBucket &value); + virtual int Update(const Uri &uri, const NativeRdb::ValuesBucket &value, const NativeRdb::DataAbilityPredicates &predicates); + virtual int OpenRawFile(const Uri &uri, const std::string &mode); + virtual bool Reload(const Uri &uri, const PacMap &extras); + virtual int BatchInsert(const Uri &uri, const std::vector &values); + virtual std::string GetType(const Uri &uri); + virtual std::shared_ptr Query( + const Uri &uri, const std::vector &columns, const NativeRdb::DataAbilityPredicates &predicates); +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif // DEMO_ABILITY_H \ No newline at end of file diff --git a/tools/frameworks/kits/test/mock/DemoAbility/mock_ability_test.h b/tools/frameworks/kits/test/mock/DemoAbility/mock_ability_test.h new file mode 100644 index 00000000000..2211492767c --- /dev/null +++ b/tools/frameworks/kits/test/mock/DemoAbility/mock_ability_test.h @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MOCK_ABILITY_TEST_H +#define MOCK_ABILITY_TEST_H + +#include "gmock/gmock.h" + +#include "ability.h" +#include "ability_loader.h" +#include "want.h" + +namespace OHOS { +namespace AppExecFwk { + +#define INSERT 20 +#define UPDATE 33 +#define OPENRAWFILE 122 +#define BATCHINSERT 115 +#define DELETE 234 + +class MockAbilityTest : public Ability { +public: + + int Insert(const Uri &uri, const NativeRdb::ValuesBucket &value) + { + GTEST_LOG_(INFO) << "MockAbilityTest::Insert called"; + return INSERT; + } + int Update(const Uri &uri, const NativeRdb::ValuesBucket &value, const NativeRdb::DataAbilityPredicates &predicates) + { + GTEST_LOG_(INFO) << "MockAbilityTest::Update called"; + return UPDATE; + } + + std::vector GetFileTypes(const Uri &uri, const std::string &mimeTypeFilter) + { + std::vector result; + result.push_back("Type1"); + result.push_back("Type2"); + result.push_back("Type3"); + return result; + } + + int OpenFile(const Uri &uri, const std::string &mode) + { + int fd; + GTEST_LOG_(INFO) << "MockAbilityTest::OpenFile called"; + FILE *fd1 = fopen("/dataability_openfile_test.txt", "w+"); + if (fd1 == nullptr) { + GTEST_LOG_(INFO) << "MockAbilityTest::OpenFile fd1 == nullptr"; + return -1; + } + fputs("123456", fd1); + fclose(fd1); + + FILE *fd2 = fopen("/dataability_openfile_test.txt", "r"); + if (fd2 == nullptr) { + GTEST_LOG_(INFO) << "MockAbilityTest::OpenFile fd2 == nullptr"; + return -1; + } + fd = fileno(fd2); + + return fd; + } + + int OpenRawFile(const Uri &uri, const std::string &mode) + { + GTEST_LOG_(INFO) << "MockAbilityTest::OpenRawFile called"; + + return OPENRAWFILE; + } + + int BatchInsert(const Uri &uri, const std::vector &values) + { + GTEST_LOG_(INFO) << "MockAbilityTest::BatchInsert called"; + return BATCHINSERT; + } + + bool Reload(const Uri &uri, const PacMap &extras) + { + GTEST_LOG_(INFO) << "MockAbilityTest::Reload called"; + return true; + } + + int Delete(const Uri &uri, const NativeRdb::DataAbilityPredicates &predicates) + { + GTEST_LOG_(INFO) << "MockAbilityTest::Delete called"; + return DELETE; + } + + std::string GetType(const Uri &uri) + { + GTEST_LOG_(INFO) << "MockAbilityTest::GetType called"; + std::string type("Type1"); + return type; + } + + std::shared_ptr Query( + const Uri &uri, const std::vector &columns, const NativeRdb::DataAbilityPredicates &predicates) + { + GTEST_LOG_(INFO) << "MockDataAbility::Query called"; + std::shared_ptr set = std::make_shared("QueryTest"); + return set; + } + + Uri NormalizeUri(const Uri &uri) + { + GTEST_LOG_(INFO) << "MockAbilityTest::NormalizeUri called"; + return uri; + } + + Uri DenormalizeUri(const Uri &uri) + { + GTEST_LOG_(INFO) << "MockAbilityTest::DenormalizeUri called"; + return uri; + } + +}; + +} // namespace AppExecFwk +} // namespace OHOS +#endif // MOCK_ABILITY_TEST_H \ No newline at end of file diff --git a/tools/frameworks/kits/test/mock/DemoAbility/mock_lifecycle_observer.cpp b/tools/frameworks/kits/test/mock/DemoAbility/mock_lifecycle_observer.cpp new file mode 100644 index 00000000000..3141fca51f1 --- /dev/null +++ b/tools/frameworks/kits/test/mock/DemoAbility/mock_lifecycle_observer.cpp @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "mock_lifecycle_observer.h" +#include + +namespace OHOS { +namespace AppExecFwk { +void MockLifecycleObserver::OnActive() +{ + GTEST_LOG_(INFO) << "MockLifecycleObserver::OnActive called"; +} + +void MockLifecycleObserver::OnBackground() +{ + GTEST_LOG_(INFO) << "MockLifecycleObserver::OnBackground called"; +} + +void MockLifecycleObserver::OnForeground(const Want &want) +{ + GTEST_LOG_(INFO) << "MockLifecycleObserver::OnForeground called"; +} + +void MockLifecycleObserver::OnInactive() +{ + GTEST_LOG_(INFO) << "MockLifecycleObserver::OnInactive called"; +} + +void MockLifecycleObserver::OnStart(const Want &want) +{ + GTEST_LOG_(INFO) << "MockLifecycleObserver::OnStart called"; +} + +void MockLifecycleObserver::OnStop() +{ + GTEST_LOG_(INFO) << "MockLifecycleObserver::OnStop called"; +} + +void MockLifecycleObserver::OnStateChanged(LifeCycle::Event event, const Want &want) +{ + GTEST_LOG_(INFO) << "MockLifecycleObserver::OnStateChanged called"; +} + +void MockLifecycleObserver::OnStateChanged(LifeCycle::Event event) +{ + GTEST_LOG_(INFO) << "MockLifecycleObserver::OnStateChanged called"; +} +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/test/mock/DemoAbility/mock_lifecycle_observer.h b/tools/frameworks/kits/test/mock/DemoAbility/mock_lifecycle_observer.h new file mode 100644 index 00000000000..c55508db8ff --- /dev/null +++ b/tools/frameworks/kits/test/mock/DemoAbility/mock_lifecycle_observer.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_APPEXECFWK_OHOS_MOCKLIFECYCLE_OBSERVER_INTERFACE_H +#define FOUNDATION_APPEXECFWK_OHOS_MOCKLIFECYCLE_OBSERVER_INTERFACE_H + +#include "ability_lifecycle_observer_interface.h" +#include "ability_lifecycle.h" +#include "want.h" + +namespace OHOS { +namespace AppExecFwk { +using Want = OHOS::AAFwk::Want; + +class MockLifecycleObserver : public ILifecycleObserver { +public: + MockLifecycleObserver() = default; + virtual ~MockLifecycleObserver() = default; + + void OnActive() override; + + void OnBackground() override; + + void OnForeground(const Want &want) override; + + void OnInactive() override; + + void OnStart(const Want &want) override; + + void OnStop() override; + + void OnStateChanged(LifeCycle::Event event, const Want &want) override; + + void OnStateChanged(LifeCycle::Event event) override; +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_APPEXECFWK_OHOS_MOCKLIFECYCLE_OBSERVER_INTERFACE_H \ No newline at end of file diff --git a/tools/frameworks/kits/test/mock/DemoObServer/mock_ability_hancle_for_data_observer.h b/tools/frameworks/kits/test/mock/DemoObServer/mock_ability_hancle_for_data_observer.h new file mode 100644 index 00000000000..7c00c904308 --- /dev/null +++ b/tools/frameworks/kits/test/mock/DemoObServer/mock_ability_hancle_for_data_observer.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MOCK_ABILIT_HANCLDE_FOR_DATA_OBSERVER_H +#define MOCK_ABILIT_HANCLDE_FOR_DATA_OBSERVER_H + +#include + +#include "gtest/gtest.h" + +#include "event_handler.h" + +namespace OHOS { +namespace AppExecFwk { + +bool EventHandler::SendEvent(InnerEvent::Pointer &event, int64_t delayTime, Priority priority) +{ + auto callback = event->GetTaskCallback(); + callback(); + return true; +} + +} // namespace AppExecFwk +} // namespace OHOS + +#endif // MOCK_ABILIT_HANCLDE_FOR_DATA_OBSERVER_H \ No newline at end of file diff --git a/tools/frameworks/kits/test/mock/DemoObServer/mock_ability_manager_client.h b/tools/frameworks/kits/test/mock/DemoObServer/mock_ability_manager_client.h new file mode 100644 index 00000000000..6e3444409f1 --- /dev/null +++ b/tools/frameworks/kits/test/mock/DemoObServer/mock_ability_manager_client.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MOCK_ABILITY_MANAGER_CLIENT_H +#define MOCK_ABILITY_MANAGER_CLIENT_H + +#include +#include + +#include "gtest/gtest.h" + +#include "ability_manager_client.h" +#include "ability_scheduler_proxy.h" + +#include +#include + +#include "mock_ability_thread_for_data_observer.h" + +namespace OHOS { +namespace AAFwk { + +class DemoAbilityManagerClientData { +public: + DemoAbilityManagerClientData(){}; + virtual ~DemoAbilityManagerClientData(){}; + + std::map> data; +}; + +static DemoAbilityManagerClientData demoAbilityMgrClientData; + +sptr AAFwk::AbilityManagerClient::AcquireDataAbility( + const Uri &uri, bool tryBind, const sptr &callerToken) +{ + sptr retval = nullptr; + auto iter = demoAbilityMgrClientData.data.find(uri.ToString()); + if (iter == demoAbilityMgrClientData.data.end()) { + GTEST_LOG_(INFO) << "mock_ability_manager_client:find data is null called"; + sptr abilityThread = AppExecFwk::MockCreateAbilityThread(); + sptr remoteProxy(new (std::nothrow) AAFwk::AbilitySchedulerProxy(abilityThread)); + demoAbilityMgrClientData.data.emplace(uri.ToString(), remoteProxy); + + retval = remoteProxy; + + if (retval == nullptr) { + GTEST_LOG_(INFO) << "mock_ability_thread_for_data_observer:mock result retval is nullptr called"; + } + } else { + retval = iter->second; + GTEST_LOG_(INFO) << "mock_ability_manager_client:find data is not null called"; + } + + return retval; +} + +ErrCode AbilityManagerClient::ReleaseDataAbility( + sptr dataAbilityScheduler, const sptr &callerToken) +{ + return ERR_OK; +} + + + +} // namespace AAFwk +} // namespace OHOS + +#endif // MOCK_ABILITY_MANAGER_CLIENT_H diff --git a/tools/frameworks/kits/test/mock/DemoObServer/mock_ability_thread_for_data_observer.h b/tools/frameworks/kits/test/mock/DemoObServer/mock_ability_thread_for_data_observer.h new file mode 100644 index 00000000000..6c5f002d4a4 --- /dev/null +++ b/tools/frameworks/kits/test/mock/DemoObServer/mock_ability_thread_for_data_observer.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MOCK_ABILITY_THREAD_FOR_DATA_OBSERVER_H +#define MOCK_ABILITY_THREAD_FOR_DATA_OBSERVER_H + +#include +#include + +#include "gtest/gtest.h" + +#include "mock_ability_test.h" +#include "ohos_application.h" +#include "ability_thread.h" +#include "event_runner.h" +#include "ability_info.h" +#include "ability_local_record.h" +#include // +namespace OHOS { +namespace AppExecFwk { + +sptr MockCreateAbilityThread() +{ + sptr abilitythread(new (std::nothrow) AppExecFwk::AbilityThread()); + if (abilitythread == nullptr) { + GTEST_LOG_(INFO) << "mock_ability_thread_for_data_observer:mock abilityhreadptr is nullptr called"; + } + + std::shared_ptr application = std::make_shared(); + if (application == nullptr) { + GTEST_LOG_(INFO) << "mock_ability_thread_for_data_observer:mock applicationptr is nullptr called"; + } + + std::shared_ptr info = std::make_shared(); + if (info == nullptr) { + GTEST_LOG_(INFO) << "mock_ability_thread_for_data_observer:mock AbilityInfo::info is nullptr called"; + } + + info->name = std::string("MockAbilityTest"); + info->type = AbilityType::DATA; + info->isNativeAbility = true; + std::cout << "info->name : " << (*info).name < token = sptr(new AbilityThread()); + + std::shared_ptr abilityRecord = std::make_shared(info, token); + std::shared_ptr mainRunner = EventRunner::Create(info->name); + + abilitythread->Attach(application, abilityRecord, mainRunner); + + return abilitythread; +} + +} // namespace AppExecFwk +} // namespace OHOS +#endif // MOCK_ABILITY_THREAD_FOR_DATA_OBSERVER_H \ No newline at end of file diff --git a/tools/frameworks/kits/test/moduletest/cpp/abilitytest/ability_context_test.cpp b/tools/frameworks/kits/test/moduletest/cpp/abilitytest/ability_context_test.cpp new file mode 100644 index 00000000000..72ec7abd046 --- /dev/null +++ b/tools/frameworks/kits/test/moduletest/cpp/abilitytest/ability_context_test.cpp @@ -0,0 +1,248 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "ability_thread.h" +#include "ability_context.h" +#include "ability_manager_client.h" +#include "context_deal.h" +#include "mock_serviceability_manager_service.h" +#include "ohos_application.h" +#include "system_ability_definition.h" +#include "sys_mgr_client.h" + +namespace OHOS { +namespace AppExecFwk { +using namespace testing::ext; +using namespace OHOS::AppExecFwk; +using namespace OHOS; +using namespace AAFwk; + +class AbilityContextTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + static constexpr int TEST_WAIT_TIME = 500 * 1000; // 500 ms +public: + std::unique_ptr context_ = nullptr; +}; + +void AbilityContextTest::SetUpTestCase(void) +{ + OHOS::sptr abilityObject = new (std::nothrow) MockServiceAbilityManagerService(); + + auto sysMgr = OHOS::DelayedSingleton::GetInstance(); + if (sysMgr == NULL) { + GTEST_LOG_(ERROR) << "fail to get ISystemAbilityManager"; + return; + } + + sysMgr->RegisterSystemAbility(OHOS::ABILITY_MGR_SERVICE_ID, abilityObject); +} + +void AbilityContextTest::TearDownTestCase(void) +{} + +void AbilityContextTest::SetUp(void) +{ + context_ = std::make_unique(); +} + +void AbilityContextTest::TearDown(void) +{} + +/** + * @tc.number: AaFwk_Ability_Context_ConnectAbility_0100 + * @tc.name: AbilityFwk + * @tc.desc: When connecting ability, AMS will inform ability to process OnStart in the life cycle, and then inform + * ability to process onconnect, and the connection is successful + */ +HWTEST_F(AbilityContextTest, AaFwk_Ability_Context_ConnectAbility_0100, Function | MediumTest | Level1) +{ + std::shared_ptr application = std::make_shared(); + sptr abilityToken = sptr(new AbilityThread()); + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->type = AppExecFwk::AbilityType::SERVICE; + abilityInfo->name = "DemoAbility"; + std::shared_ptr abilityRecord = std::make_shared(abilityInfo, abilityToken); + + AbilityThread::AbilityThreadMain(application, abilityRecord); + + std::shared_ptr deal = std::make_shared(); + deal->SetAbilityInfo(abilityInfo); + context_->AttachBaseContext(deal); + + Want want; + bool ret = context_->ConnectAbility(want, nullptr); + EXPECT_TRUE(ret); + usleep(AbilityContextTest::TEST_WAIT_TIME); +} + +/** + * @tc.number: AaFwk_Ability_Context_DisconnectAbility_0100 + * @tc.name: AbilityFwk + * @tc.desc: AMS notifies the abilityondisconnect event when disconnectservice. + */ +HWTEST_F(AbilityContextTest, AaFwk_Ability_Context_DisconnectAbility_0100, Function | MediumTest | Level1) +{ + std::shared_ptr application = std::make_shared(); + sptr abilityToken = sptr(new AbilityThread()); + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->type = AppExecFwk::AbilityType::SERVICE; + abilityInfo->name = "DemoAbility"; + std::shared_ptr abilityRecord = std::make_shared(abilityInfo, abilityToken); + + AbilityThread::AbilityThreadMain(application, abilityRecord); + + std::shared_ptr deal = std::make_shared(); + deal->SetAbilityInfo(abilityInfo); + context_->AttachBaseContext(deal); + + Want want; + context_->ConnectAbility(want, nullptr); + context_->DisconnectAbility(nullptr); + usleep(AbilityContextTest::TEST_WAIT_TIME); +} + +/** + * @tc.number: AaFwk_Ability_Context_StartAbility_0100 + * @tc.name: AbilityFwk + * @tc.desc: Starting ability service, AMS will inform ability to perform OnStart lifecycle conversion, and then inform + * oncommand event. + */ +HWTEST_F(AbilityContextTest, AaFwk_Ability_Context_StartAbility_0100, Function | MediumTest | Level1) +{ + std::shared_ptr application = std::make_shared(); + sptr abilityToken = sptr(new AbilityThread()); + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->type = AppExecFwk::AbilityType::SERVICE; + abilityInfo->name = "DemoAbility"; + std::shared_ptr abilityRecord = std::make_shared(abilityInfo, abilityToken); + + AbilityThread::AbilityThreadMain(application, abilityRecord); + Want want; + context_->StartAbility(want, -1); + usleep(AbilityContextTest::TEST_WAIT_TIME); +} + +/** + * @tc.number: AaFwk_Ability_Context_TerminateAbility_0100 + * @tc.name: AbilityFwk + * @tc.desc: To terminate ability service, AMS will notify ability to perform onbackground lifecycle conversion, and + * then notify onstop event. + */ +HWTEST_F(AbilityContextTest, AaFwk_Ability_Context_TerminateAbility_0100, Function | MediumTest | Level1) +{ + std::shared_ptr application = std::make_shared(); + sptr abilityToken = sptr(new AbilityThread()); + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->type = AppExecFwk::AbilityType::SERVICE; + abilityInfo->name = "DemoAbility"; + std::shared_ptr abilityRecord = std::make_shared(abilityInfo, abilityToken); + + AbilityThread::AbilityThreadMain(application, abilityRecord); + Want want; + context_->StartAbility(want, -1); + usleep(AbilityContextTest::TEST_WAIT_TIME); + + std::shared_ptr deal = std::make_shared(); + deal->SetAbilityInfo(abilityInfo); + context_->AttachBaseContext(deal); + context_->TerminateAbility(); + usleep(AbilityContextTest::TEST_WAIT_TIME); +} + +/** + * @tc.number: AaFwk_Ability_Context_TerminateAbility_0200 + * @tc.name: AbilityFwk + * @tc.desc: When there is no startability, calling terminateability directly will not respond to onbackground and + * onstop events. + */ +HWTEST_F(AbilityContextTest, AaFwk_Ability_Context_TerminateAbility_0200, Function | MediumTest | Level1) +{ + std::shared_ptr application = std::make_shared(); + sptr abilityToken = sptr(new AbilityThread()); + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->type = AppExecFwk::AbilityType::SERVICE; + abilityInfo->name = "DemoAbility"; + std::shared_ptr abilityRecord = std::make_shared(abilityInfo, abilityToken); + + AbilityThread::AbilityThreadMain(application, abilityRecord); + + std::shared_ptr deal = std::make_shared(); + deal->SetAbilityInfo(abilityInfo); + context_->AttachBaseContext(deal); + context_->TerminateAbility(); + usleep(AbilityContextTest::TEST_WAIT_TIME); +} + +/** + * @tc.number: AaFwk_Ability_Context_StopService_0100 + * @tc.name: AbilityFwk + * @tc.desc: To stop ability service, AMS will notify ability to perform onbackground lifecycle conversion, and then + * notify onstop event. + */ +HWTEST_F(AbilityContextTest, AaFwk_Ability_Context_StopService_0100, Function | MediumTest | Level1) +{ + std::shared_ptr application = std::make_shared(); + sptr abilityToken = sptr(new AbilityThread()); + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->type = AppExecFwk::AbilityType::SERVICE; + abilityInfo->name = "DemoAbility"; + std::shared_ptr abilityRecord = std::make_shared(abilityInfo, abilityToken); + + AbilityThread::AbilityThreadMain(application, abilityRecord); + + std::shared_ptr deal = std::make_shared(); + deal->SetAbilityInfo(abilityInfo); + context_->AttachBaseContext(deal); + + Want want; + context_->StartAbility(want, -1); + usleep(AbilityContextTest::TEST_WAIT_TIME); + bool ret = context_->StopAbility(want); + EXPECT_TRUE(ret); + usleep(AbilityContextTest::TEST_WAIT_TIME); +} + +/** + * @tc.number: AaFwk_Ability_Context_StopService_0200 + * @tc.name: AbilityFwk + * @tc.desc: When there is no startability, calling stop ability directly will not respond to onbackground and onstop + * events. + */ +HWTEST_F(AbilityContextTest, AaFwk_Ability_Context_StopService_0200, Function | MediumTest | Level1) +{ + std::shared_ptr application = std::make_shared(); + sptr abilityToken = sptr(new AbilityThread()); + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->type = AppExecFwk::AbilityType::SERVICE; + abilityInfo->name = "DemoAbility"; + std::shared_ptr abilityRecord = std::make_shared(abilityInfo, abilityToken); + + AbilityThread::AbilityThreadMain(application, abilityRecord); + std::shared_ptr deal = std::make_shared(); + deal->SetAbilityInfo(abilityInfo); + context_->AttachBaseContext(deal); + + Want want; + bool ret = context_->StopAbility(want); + EXPECT_TRUE(ret); + usleep(AbilityContextTest::TEST_WAIT_TIME); +} +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/test/moduletest/cpp/abilitytest/ability_test.cpp b/tools/frameworks/kits/test/moduletest/cpp/abilitytest/ability_test.cpp new file mode 100755 index 00000000000..c0cfad0fdf7 --- /dev/null +++ b/tools/frameworks/kits/test/moduletest/cpp/abilitytest/ability_test.cpp @@ -0,0 +1,1065 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include "ability_thread.h" +#include "ability_local_record.h" +#include "ability_loader.h" +#include "ability_impl_factory.h" +#include "data_ability_helper.h" +#include "context_deal.h" +#include "ohos_application.h" +#include "sys_mgr_client.h" +#include "ability_manager_interface.h" +#include "ability_manager_client.h" +#include "system_ability_definition.h" +#include "demo_ability_test.h" +#include "mock_bundle_manager.h" +#include "mock_ability_manager_service.h" + +namespace OHOS { +namespace AppExecFwk { +using namespace testing::ext; +using namespace OHOS; +using namespace AAFwk; +using OHOS::AppExecFwk::ElementName; +using namespace OHOS::AppExecFwk; +/* + * Parameters: + * Action + * Entity + * Flag + * ElementName + */ +const std::string ABILITY_NAME("DemoAbility"); +class AbilityBaseTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + OHOS::sptr abilityObject_; + static constexpr int TEST_WAIT_TIME = 500 * 1000; // 500 ms + static const int RESULT_CODE = 1992; + +public: +}; + +void AbilityBaseTest::SetUpTestCase(void) +{} + +void AbilityBaseTest::TearDownTestCase(void) +{} + +void AbilityBaseTest::SetUp(void) +{ + abilityObject_ = new MockAbilityManagerService(); + OHOS::sptr bundleObject = new BundleMgrService(); + auto sysMgr = OHOS::DelayedSingleton::GetInstance(); + if (sysMgr == NULL) { + GTEST_LOG_(ERROR) << "fail to get ISystemAbilityManager"; + return; + } + + sysMgr->RegisterSystemAbility(OHOS::ABILITY_MGR_SERVICE_ID, abilityObject_); + sysMgr->RegisterSystemAbility(OHOS::BUNDLE_MGR_SERVICE_SYS_ABILITY_ID, bundleObject); +} + +void AbilityBaseTest::TearDown(void) +{} + +/** + * @tc.number: AaFwk_Ability_AbilityFwk_Start_Test_0100 + * @tc.name: AbilityFwk Start + * @tc.desc: The first step of startability is the attach AMS. + */ +HWTEST_F(AbilityBaseTest, AaFwk_Ability_AbilityFwk_Start_Test_0100, Function | MediumTest | Level1) +{ + std::shared_ptr application = std::make_shared(); + + sptr abilityToken = sptr(new AbilityThread()); + EXPECT_NE(abilityToken, nullptr); + if (abilityToken != nullptr) { + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->type = AppExecFwk::AbilityType::PAGE; + abilityInfo->name = ABILITY_NAME; + abilityInfo->isNativeAbility = true; + std::shared_ptr abilityRecord = + std::make_shared(abilityInfo, abilityToken); + + AbilityThread::AbilityThreadMain(application, abilityRecord); + usleep(AbilityBaseTest::TEST_WAIT_TIME); + } +} + +/** + * @tc.number: AaFwk_Ability_AbilityFwk_Start_Test_0200 + * @tc.name: AbilityFwk Start + * @tc.desc: When connecting AMS,the instance of application is empty. + */ +HWTEST_F(AbilityBaseTest, AaFwk_Ability_AbilityFwk_Start_Test_0200, Function | MediumTest | Level1) +{ + std::shared_ptr application = nullptr; + + sptr abilityToken = sptr(new AbilityThread()); + EXPECT_NE(abilityToken, nullptr); + if (abilityToken != nullptr) { + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->type = AppExecFwk::AbilityType::PAGE; + abilityInfo->name = ABILITY_NAME; + abilityInfo->isNativeAbility = true; + std::shared_ptr abilityRecord = + std::make_shared(abilityInfo, abilityToken); + + AbilityThread::AbilityThreadMain(application, abilityRecord); + usleep(AbilityBaseTest::TEST_WAIT_TIME); + } +} + +/** + * @tc.number: AaFwk_Ability_AbilityFwk_Start_Test_0300 + * @tc.name: AbilityFwk Start + * @tc.desc: When connecting AMS,the instance of abilityRecord is empty + */ +HWTEST_F(AbilityBaseTest, AaFwk_Ability_AbilityFwk_Start_Test_0300, Function | MediumTest | Level1) +{ + std::shared_ptr application = std::make_shared(); + + std::shared_ptr abilityRecord = nullptr; + + AbilityThread::AbilityThreadMain(application, abilityRecord); + usleep(AbilityBaseTest::TEST_WAIT_TIME); +} + +/** + * @tc.number: AaFwk_Ability_AbilityFwk_Start_Test_0400 + * @tc.name: AbilityFwk Start + * @tc.desc: The ability name is empty, so the ability instance cannot be created. + */ +HWTEST_F(AbilityBaseTest, AaFwk_Ability_AbilityFwk_Start_Test_0400, Function | MediumTest | Level1) +{ + std::shared_ptr application = std::make_shared(); + + sptr abilityToken = sptr(new AbilityThread()); + EXPECT_NE(abilityToken, nullptr); + if (abilityToken != nullptr) { + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->type = AppExecFwk::AbilityType::PAGE; + std::shared_ptr abilityRecord = + std::make_shared(abilityInfo, abilityToken); + + AbilityThread::AbilityThreadMain(application, abilityRecord); + usleep(AbilityBaseTest::TEST_WAIT_TIME); + } +} + +/** + * @tc.number: AaFwk_Ability_AbilityFwk_Start_Test_0500 + * @tc.name: AbilityFwk Start + * @tc.desc: The ability type is unknown, so the AbilityImpl instance cannot be created. + */ +HWTEST_F(AbilityBaseTest, AaFwk_Ability_AbilityFwk_Start_Test_0500, Function | MediumTest | Level1) +{ + std::shared_ptr application = std::make_shared(); + + sptr abilityToken = sptr(new AbilityThread()); + EXPECT_NE(abilityToken, nullptr); + if (abilityToken != nullptr) { + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->name = ABILITY_NAME; + abilityInfo->isNativeAbility = true; + std::shared_ptr abilityRecord = + std::make_shared(abilityInfo, abilityToken); + + AbilityThread::AbilityThreadMain(application, abilityRecord); + usleep(AbilityBaseTest::TEST_WAIT_TIME); + } +} + +/** + * @tc.number: AaFwk_Ability_AbilityFwk_Start_Test_0600 + * @tc.name: AbilityFwk Start + * @tc.desc: The interface OnSaveAbilityState()/OnRestoreAbilityState() of demoability was called. + */ +HWTEST_F(AbilityBaseTest, AaFwk_Ability_AbilityFwk_Start_Test_0600, Function | MediumTest | Level1) +{ + std::shared_ptr contextDeal = std::make_shared(); + std::shared_ptr application = std::make_shared(); + std::shared_ptr appInfo = std::make_shared(); + std::shared_ptr processInfo = std::make_shared(); + + appInfo->codePath = "codePath"; + appInfo->dataBaseDir = "dataBaseDir"; + appInfo->dataDir = "dataDir"; + appInfo->cacheDir = "cacheDir"; + appInfo->bundleName = "bundleName"; + + contextDeal->SetProcessInfo(processInfo); + contextDeal->SetApplicationInfo(appInfo); + contextDeal->SetApplicationContext(application); + application->AttachBaseContext(contextDeal); + + sptr abilityToken = sptr(new AbilityThread()); + EXPECT_NE(abilityToken, nullptr); + if (abilityToken != nullptr) { + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->codePath = "codePath"; + abilityInfo->resourcePath = "resourcePath"; + + abilityInfo->type = AppExecFwk::AbilityType::PAGE; + abilityInfo->name = ABILITY_NAME; + abilityInfo->isNativeAbility = true; + std::shared_ptr abilityRecord = + std::make_shared(abilityInfo, abilityToken); + + AbilityThread::AbilityThreadMain(application, abilityRecord); + + sptr remoteObject_ = + OHOS::DelayedSingleton::GetInstance()->GetSystemAbility(ABILITY_MGR_SERVICE_ID); + sptr abms = iface_cast(remoteObject_); + Want want; + sptr connect = nullptr; + + // Just to test two interfaces OnRestoreAbilityState/OnSaveAbilityState + abms->ConnectAbility(want, connect, abilityToken); + usleep(AbilityBaseTest::TEST_WAIT_TIME); + } +} + +/** + * @tc.number: AaFwk_Ability_Lifecycle_Test_0100 + * @tc.name: Ability Lifecycle + * @tc.desc: The ability life cycle will change from initial state initial to inactive by calling the interface + * OnnStart(), and then to active by calling OnActive(). + */ +HWTEST_F(AbilityBaseTest, AaFwk_Ability_Lifecycle_Test_0100, Function | MediumTest | Level1) +{ + std::shared_ptr application = std::make_shared(); + + sptr abilityToken = sptr(new AbilityThread()); + EXPECT_NE(abilityToken, nullptr); + if (abilityToken != nullptr) { + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->type = AppExecFwk::AbilityType::PAGE; + abilityInfo->name = ABILITY_NAME; + abilityInfo->isNativeAbility = true; + std::shared_ptr abilityRecord = + std::make_shared(abilityInfo, abilityToken); + + AbilityThread::AbilityThreadMain(application, abilityRecord); + + sptr remoteObject_ = + OHOS::DelayedSingleton::GetInstance()->GetSystemAbility(ABILITY_MGR_SERVICE_ID); + sptr abms = iface_cast(remoteObject_); + Want want; + abms->StartAbility(want, AbilityLifeCycleState::ABILITY_STATE_ACTIVE); + usleep(AbilityBaseTest::TEST_WAIT_TIME); + } +} + +/** + * @tc.number: AaFwk_Ability_AbilityFwk_Lifecycle_Test_0200 + * @tc.name: Ability Lifecycle + * @tc.desc: The ability life cycle will change from initial state initial to inactive by calling the interface + * OnnStart(), and then to active by calling OnNewWant()+OnActive(). + */ +HWTEST_F(AbilityBaseTest, AaFwk_Ability_AbilityFwk_Lifecycle_Test_0200, Function | MediumTest | Level1) +{ + std::shared_ptr application = std::make_shared(); + + sptr abilityToken = sptr(new AbilityThread()); + EXPECT_NE(abilityToken, nullptr); + if (abilityToken != nullptr) { + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->type = AppExecFwk::AbilityType::PAGE; + abilityInfo->name = ABILITY_NAME; + abilityInfo->isNativeAbility = true; + std::shared_ptr abilityRecord = + std::make_shared(abilityInfo, abilityToken); + + AbilityThread::AbilityThreadMain(application, abilityRecord); + + sptr remoteObject_ = + OHOS::DelayedSingleton::GetInstance()->GetSystemAbility(ABILITY_MGR_SERVICE_ID); + sptr abms = iface_cast(remoteObject_); + + abms->DisconnectAbility(nullptr); + usleep(AbilityBaseTest::TEST_WAIT_TIME); + } +} + +/** + * @tc.number: AaFwk_Ability_AbilityFwk_Lifecycle_Test_0300 + * @tc.name: Ability Lifecycle + * @tc.desc: Ability life cycle changes: initial - > active - > background, the interface of demoability will be + called: + * OnStart()->OnActive()->OnInactive()->OnBackground(). + */ +HWTEST_F(AbilityBaseTest, AaFwk_Ability_AbilityFwk_Lifecycle_Test_0300, Function | MediumTest | Level1) +{ + std::shared_ptr application = std::make_shared(); + + sptr abilityToken = sptr(new AbilityThread()); + EXPECT_NE(abilityToken, nullptr); + if (abilityToken != nullptr) { + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->type = AppExecFwk::AbilityType::PAGE; + abilityInfo->name = ABILITY_NAME; + abilityInfo->isNativeAbility = true; + std::shared_ptr abilityRecord = + std::make_shared(abilityInfo, abilityToken); + + AbilityThread::AbilityThreadMain(application, abilityRecord); + + sptr remoteObject_ = + OHOS::DelayedSingleton::GetInstance()->GetSystemAbility(ABILITY_MGR_SERVICE_ID); + sptr abms = iface_cast(remoteObject_); + Want want; + + abms->StartAbility(want, AbilityLifeCycleState::ABILITY_STATE_ACTIVE); + usleep(AbilityBaseTest::TEST_WAIT_TIME); + abms->StartAbility(want, AbilityLifeCycleState::ABILITY_STATE_BACKGROUND); + usleep(AbilityBaseTest::TEST_WAIT_TIME); + } +} + +/** + * @tc.number: AaFwk_Ability_AbilityFwk_Lifecycle_Test_0400 + * @tc.name: Ability Lifecycle + * @tc.desc: Ability life cycle changes: initial - > active - > inactive, the interface of demoability will be + called: + * OnStart()->OnActive()->OnInactive(). + */ +HWTEST_F(AbilityBaseTest, AaFwk_Ability_AbilityFwk_Lifecycle_Test_0400, Function | MediumTest | Level1) +{ + std::shared_ptr application = std::make_shared(); + + sptr abilityToken = sptr(new AbilityThread()); + EXPECT_NE(abilityToken, nullptr); + if (abilityToken != nullptr) { + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->type = AppExecFwk::AbilityType::PAGE; + abilityInfo->name = ABILITY_NAME; + abilityInfo->isNativeAbility = true; + std::shared_ptr abilityRecord = + std::make_shared(abilityInfo, abilityToken); + + AbilityThread::AbilityThreadMain(application, abilityRecord); + + sptr remoteObject_ = + OHOS::DelayedSingleton::GetInstance()->GetSystemAbility(ABILITY_MGR_SERVICE_ID); + sptr abms = iface_cast(remoteObject_); + Want want; + + abms->StartAbility(want, AbilityLifeCycleState::ABILITY_STATE_ACTIVE); + usleep(AbilityBaseTest::TEST_WAIT_TIME); + abms->StartAbility(want, AbilityLifeCycleState::ABILITY_STATE_INACTIVE); + usleep(AbilityBaseTest::TEST_WAIT_TIME); + } +} + +/** + * @tc.number: AaFwk_Ability_AbilityFwk_Lifecycle_Test_0500 + * @tc.name: Ability Lifecycle + * @tc.desc: Ability life cycle changes: initial - > active , the interface of demoability will be called: + * OnStart()->OnActive()->OnInactive()->OnBackground()->OnForeground(). + */ +HWTEST_F(AbilityBaseTest, AaFwk_Ability_AbilityFwk_Lifecycle_Test_0500, Function | MediumTest | Level1) +{ + std::shared_ptr application = std::make_shared(); + + sptr abilityToken = sptr(new AbilityThread()); + EXPECT_NE(abilityToken, nullptr); + if (abilityToken != nullptr) { + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->type = AppExecFwk::AbilityType::PAGE; + abilityInfo->name = ABILITY_NAME; + abilityInfo->isNativeAbility = true; + std::shared_ptr abilityRecord = + std::make_shared(abilityInfo, abilityToken); + + AbilityThread::AbilityThreadMain(application, abilityRecord); + + sptr remoteObject_ = + OHOS::DelayedSingleton::GetInstance()->GetSystemAbility(ABILITY_MGR_SERVICE_ID); + sptr abms = iface_cast(remoteObject_); + Want want; + + abms->StartAbility(want, AbilityLifeCycleState::ABILITY_STATE_ACTIVE); + usleep(AbilityBaseTest::TEST_WAIT_TIME); + abms->StartAbility(want, AbilityLifeCycleState::ABILITY_STATE_BACKGROUND); + usleep(AbilityBaseTest::TEST_WAIT_TIME); + abms->StartAbility(want, AbilityLifeCycleState::ABILITY_STATE_INACTIVE); + usleep(AbilityBaseTest::TEST_WAIT_TIME); + } +} + +/** + * @tc.number: AaFwk_Ability_AbilityFwk_Lifecycle_Test_0600 + * @tc.name: Ability Lifecycle + * @tc.desc: Ability life cycle changes: initial - > active , the interface of demoability will be called: + * OnStart()->OnActive()->OnInactive()->OnBackground()->OnStop(). + */ +HWTEST_F(AbilityBaseTest, AaFwk_Ability_AbilityFwk_Lifecycle_Test_0600, Function | MediumTest | Level1) +{ + std::shared_ptr application = std::make_shared(); + + sptr abilityToken = sptr(new AbilityThread()); + EXPECT_NE(abilityToken, nullptr); + if (abilityToken != nullptr) { + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->type = AppExecFwk::AbilityType::PAGE; + abilityInfo->name = ABILITY_NAME; + abilityInfo->isNativeAbility = true; + std::shared_ptr abilityRecord = + std::make_shared(abilityInfo, abilityToken); + + AbilityThread::AbilityThreadMain(application, abilityRecord); + + sptr remoteObject_ = + OHOS::DelayedSingleton::GetInstance()->GetSystemAbility(ABILITY_MGR_SERVICE_ID); + sptr abms = iface_cast(remoteObject_); + Want want; + + abms->StartAbility(want, AbilityLifeCycleState::ABILITY_STATE_ACTIVE); + usleep(AbilityBaseTest::TEST_WAIT_TIME); + abms->StartAbility(want, AbilityLifeCycleState::ABILITY_STATE_BACKGROUND); + usleep(AbilityBaseTest::TEST_WAIT_TIME); + abms->StartAbility(want, AbilityLifeCycleState::ABILITY_STATE_INITIAL); + usleep(AbilityBaseTest::TEST_WAIT_TIME); + } +} + +/** + * @tc.number: AaFwk_Ability_TerminateAbility_ForResult_Test_0100 + * @tc.name: TerminateAbility_ForResult + * @tc.desc: 1. TerminateAbility with parameters + * 2. AMS returns parameters through sendresult + * 3. Compare the returned parameters with the passed in parameters. + */ +HWTEST_F(AbilityBaseTest, AaFwk_Ability_TerminateAbility_ForResult_Test_0100, Function | MediumTest | Level1) +{ + std::shared_ptr application = std::make_shared(); + + sptr abilityToken = sptr(new AbilityThread()); + EXPECT_NE(abilityToken, nullptr); + if (abilityToken != nullptr) { + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->type = AppExecFwk::AbilityType::PAGE; + abilityInfo->name = ABILITY_NAME; + abilityInfo->isNativeAbility = true; + std::shared_ptr abilityRecord = + std::make_shared(abilityInfo, abilityToken); + + AbilityThread::AbilityThreadMain(application, abilityRecord); + + sptr remoteObject_ = + OHOS::DelayedSingleton::GetInstance()->GetSystemAbility(ABILITY_MGR_SERVICE_ID); + sptr abms = iface_cast(remoteObject_); + Want want; + sptr connect = nullptr; + + abms->TerminateAbility(nullptr, RESULT_CODE, &want); + usleep(AbilityBaseTest::TEST_WAIT_TIME); + } +} + +/* + * Parameters: + * Action + * Entity + * Flag + * ElementName + */ +class AbilityTerminateTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + +public: + OHOS::sptr abilityObject_; + static constexpr int TEST_WAIT_TIME = 500 * 1000; // 500 ms + static const int RESULT_CODE = 1992; +}; + +void AbilityTerminateTest::SetUpTestCase(void) +{} + +void AbilityTerminateTest::TearDownTestCase(void) +{} + +void AbilityTerminateTest::SetUp(void) +{ + abilityObject_ = new MockAbilityManagerService(); + + auto sysMgr = OHOS::DelayedSingleton::GetInstance(); + + if (sysMgr == NULL) { + GTEST_LOG_(ERROR) << "fail to get ISystemAbilityManager"; + return; + } + + sysMgr->RegisterSystemAbility(OHOS::ABILITY_MGR_SERVICE_ID, abilityObject_); +} + +void AbilityTerminateTest::TearDown(void) +{} + +/** + * @tc.number: AaFwk_Ability_Terminate_test_0100 + * @tc.name: TerminateAbility + * @tc.desc: When the ability state is inactive, the call to terminateability terminates. + */ +HWTEST_F(AbilityTerminateTest, AaFwk_Ability_Terminate_test_0100, Function | MediumTest | Level1) +{ + std::shared_ptr application = std::make_shared(); + sptr abilityToken = sptr(new AbilityThread()); + EXPECT_NE(abilityToken, nullptr); + if (abilityToken != nullptr) { + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->type = AppExecFwk::AbilityType::PAGE; + abilityInfo->name = ABILITY_NAME; + abilityInfo->isNativeAbility = true; + std::shared_ptr abilityRecord = + std::make_shared(abilityInfo, abilityToken); + + GTEST_LOG_(INFO) << "AaFwk_Ability_Terminate_test_001 AbilityThreadMain"; + AbilityThread::AbilityThreadMain(application, abilityRecord); + + Want want; + MockAbilityManagerService *mockAMS = iface_cast(abilityObject_); + mockAMS->StartAbility(want, AbilityLifeCycleState::ABILITY_STATE_INACTIVE); + usleep(AbilityTerminateTest::TEST_WAIT_TIME); + + auto ability = AbilityLoader::GetInstance().GetAbilityByName(abilityInfo->name); + EXPECT_NE(ability, nullptr); + if (ability != nullptr) { + ability->SetResult(RESULT_CODE, want); + ability->TerminateAbility(); + } + usleep(AbilityTerminateTest::TEST_WAIT_TIME); + } + GTEST_LOG_(INFO) << "AaFwk_Ability_Terminate_test_001 TerminateAbility"; +} + +/** + * @tc.number: AaFwk_Ability_Terminate_test_0200 + * @tc.name: TerminateAbility + * @tc.desc: When the ability state is active, the call to terminateability terminates. + */ +HWTEST_F(AbilityTerminateTest, AaFwk_Ability_Terminate_test_0200, Function | MediumTest | Level1) +{ + std::shared_ptr application = std::make_shared(); + sptr abilityToken = sptr(new AbilityThread()); + EXPECT_NE(abilityToken, nullptr); + if (abilityToken != nullptr) { + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->type = AppExecFwk::AbilityType::PAGE; + abilityInfo->name = ABILITY_NAME; + abilityInfo->isNativeAbility = true; + std::shared_ptr abilityRecord = + std::make_shared(abilityInfo, abilityToken); + + GTEST_LOG_(INFO) << "AaFwk_Ability_Terminate_test_002 AbilityThreadMain"; + AbilityThread::AbilityThreadMain(application, abilityRecord); + + Want want; + MockAbilityManagerService *mockAMS = iface_cast(abilityObject_); + mockAMS->StartAbility(want, AbilityLifeCycleState::ABILITY_STATE_ACTIVE); + usleep(AbilityTerminateTest::TEST_WAIT_TIME); + + auto ability = AbilityLoader::GetInstance().GetAbilityByName(abilityInfo->name); + EXPECT_NE(ability, nullptr); + if (ability != nullptr) { + ability->SetResult(RESULT_CODE, want); + ability->TerminateAbility(); + } + usleep(AbilityTerminateTest::TEST_WAIT_TIME); + } + GTEST_LOG_(INFO) << "AaFwk_Ability_Terminate_test_002 TerminateAbility"; +} + +/** + * @tc.number: AaFwk_Ability_Terminate_test_0300 + * @tc.name: TerminateAbility + * @tc.desc: When the ability state is BACKGROUND, the call to terminateability terminates. + */ +HWTEST_F(AbilityTerminateTest, AaFwk_Ability_Terminate_test_0300, Function | MediumTest | Level1) +{ + std::shared_ptr application = std::make_shared(); + sptr abilityToken = sptr(new AbilityThread()); + EXPECT_NE(abilityToken, nullptr); + if (abilityToken != nullptr) { + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->type = AppExecFwk::AbilityType::PAGE; + abilityInfo->name = ABILITY_NAME; + abilityInfo->isNativeAbility = true; + std::shared_ptr abilityRecord = + std::make_shared(abilityInfo, abilityToken); + + GTEST_LOG_(INFO) << "AaFwk_Ability_Terminate_test_0300 AbilityThreadMain"; + AbilityThread::AbilityThreadMain(application, abilityRecord); + + Want want; + MockAbilityManagerService *mockAMS = iface_cast(abilityObject_); + mockAMS->StartAbility(want, AbilityLifeCycleState::ABILITY_STATE_BACKGROUND); + usleep(AbilityTerminateTest::TEST_WAIT_TIME); + + auto ability = AbilityLoader::GetInstance().GetAbilityByName(abilityInfo->name); + EXPECT_NE(ability, nullptr); + if (ability != nullptr) { + ability->SetResult(RESULT_CODE, want); + ability->TerminateAbility(); + } + usleep(AbilityTerminateTest::TEST_WAIT_TIME); + } + GTEST_LOG_(INFO) << "AaFwk_Ability_Terminate_test_0300 TerminateAbility"; +} + +/** + * @tc.number: AaFwk_Ability_Terminate_test_0400 + * @tc.name: TerminateAbility + * @tc.desc: When the ability state is ABILITY_STATE_INITIAL, the call to terminateability terminates. + */ +HWTEST_F(AbilityTerminateTest, AaFwk_Ability_Terminate_test_0400, Function | MediumTest | Level1) +{ + std::shared_ptr application = std::make_shared(); + sptr abilityToken = sptr(new AbilityThread()); + EXPECT_NE(abilityToken, nullptr); + if (abilityToken != nullptr) { + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->type = AppExecFwk::AbilityType::PAGE; + abilityInfo->name = ABILITY_NAME; + abilityInfo->isNativeAbility = true; + std::shared_ptr abilityRecord = + std::make_shared(abilityInfo, abilityToken); + + GTEST_LOG_(INFO) << "AaFwk_Ability_Terminate_test_0400 AbilityThreadMain"; + AbilityThread::AbilityThreadMain(application, abilityRecord); + + Want want; + MockAbilityManagerService *mockAMS = iface_cast(abilityObject_); + mockAMS->StartAbility(want, AbilityLifeCycleState::ABILITY_STATE_INITIAL); + usleep(AbilityTerminateTest::TEST_WAIT_TIME); + + auto ability = AbilityLoader::GetInstance().GetAbilityByName(abilityInfo->name); + EXPECT_NE(ability, nullptr); + if (ability != nullptr) { + ability->SetResult(RESULT_CODE, want); + ability->TerminateAbility(); + } + usleep(AbilityTerminateTest::TEST_WAIT_TIME); + } + GTEST_LOG_(INFO) << "AaFwk_Ability_Terminate_test_0400 TerminateAbility"; +} + +/** + * @tc.number: AaFwk_Ability_Terminate_test_0500 + * @tc.name: TerminateAbility + * @tc.desc: When the ability state is inactive, the call to terminateability terminates. + */ +HWTEST_F(AbilityTerminateTest, AaFwk_Ability_Terminate_test_0500, Function | MediumTest | Level1) +{ + std::shared_ptr application = std::make_shared(); + sptr abilityToken = sptr(new AbilityThread()); + EXPECT_NE(abilityToken, nullptr); + if (abilityToken != nullptr) { + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->type = AppExecFwk::AbilityType::PAGE; + abilityInfo->name = ABILITY_NAME; + abilityInfo->isNativeAbility = true; + std::shared_ptr abilityRecord = + std::make_shared(abilityInfo, abilityToken); + + GTEST_LOG_(INFO) << "AaFwk_Ability_Terminate_test_005 AbilityThreadMain"; + AbilityThread::AbilityThreadMain(application, abilityRecord); + + Want want; + MockAbilityManagerService *mockAMS = iface_cast(abilityObject_); + mockAMS->StartAbility(want, AbilityLifeCycleState::ABILITY_STATE_INACTIVE); + usleep(AbilityTerminateTest::TEST_WAIT_TIME); + + mockAMS->TerminateAbility(nullptr, RESULT_CODE, &want); + usleep(AbilityTerminateTest::TEST_WAIT_TIME); + } + GTEST_LOG_(INFO) << "AaFwk_Ability_Terminate_test_005 TerminateAbility"; +} + +/** + * @tc.number: AaFwk_Ability_Terminate_test_0600 + * @tc.name: TerminateAbility + * @tc.desc: When the ability state is active, the call to terminateability terminates. + */ +HWTEST_F(AbilityTerminateTest, AaFwk_Ability_Terminate_test_0600, Function | MediumTest | Level1) +{ + std::shared_ptr application = std::make_shared(); + sptr abilityToken = sptr(new AbilityThread()); + EXPECT_NE(abilityToken, nullptr); + if (abilityToken != nullptr) { + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->type = AppExecFwk::AbilityType::PAGE; + abilityInfo->name = ABILITY_NAME; + abilityInfo->isNativeAbility = true; + std::shared_ptr abilityRecord = + std::make_shared(abilityInfo, abilityToken); + + GTEST_LOG_(INFO) << "AaFwk_Ability_Terminate_test_006 AbilityThreadMain"; + AbilityThread::AbilityThreadMain(application, abilityRecord); + + Want want; + MockAbilityManagerService *mockAMS = iface_cast(abilityObject_); + mockAMS->StartAbility(want, AbilityLifeCycleState::ABILITY_STATE_ACTIVE); + usleep(AbilityTerminateTest::TEST_WAIT_TIME); + + mockAMS->TerminateAbility(nullptr, RESULT_CODE, &want); + usleep(AbilityTerminateTest::TEST_WAIT_TIME); + } + GTEST_LOG_(INFO) << "AaFwk_Ability_Terminate_test_006 TerminateAbility"; +} + +/** + * @tc.number: AaFwk_Ability_Terminate_test_0700 + * @tc.name: TerminateAbility + * @tc.desc: When the ability state is background, the call to terminateability terminates. + */ +HWTEST_F(AbilityTerminateTest, AaFwk_Ability_Terminate_test_0700, Function | MediumTest | Level1) +{ + std::shared_ptr application = std::make_shared(); + sptr abilityToken = sptr(new AbilityThread()); + EXPECT_NE(abilityToken, nullptr); + if (abilityToken != nullptr) { + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->type = AppExecFwk::AbilityType::PAGE; + abilityInfo->name = ABILITY_NAME; + abilityInfo->isNativeAbility = true; + std::shared_ptr abilityRecord = + std::make_shared(abilityInfo, abilityToken); + + GTEST_LOG_(INFO) << "AaFwk_Ability_Terminate_test_007 AbilityThreadMain"; + AbilityThread::AbilityThreadMain(application, abilityRecord); + + Want want; + MockAbilityManagerService *mockAMS = iface_cast(abilityObject_); + mockAMS->StartAbility(want, AbilityLifeCycleState::ABILITY_STATE_BACKGROUND); + usleep(AbilityTerminateTest::TEST_WAIT_TIME); + + mockAMS->TerminateAbility(nullptr, RESULT_CODE, &want); + usleep(AbilityTerminateTest::TEST_WAIT_TIME); + } + GTEST_LOG_(INFO) << "AaFwk_Ability_Terminate_test_007 TerminateAbility"; +} + +/** + * @tc.number: AaFwk_Ability_Terminate_test_0800 + * @tc.name: TerminateAbility + * @tc.desc: When the ability state is initial, the call to terminateability terminates. + */ +HWTEST_F(AbilityTerminateTest, AaFwk_Ability_Terminate_test_0800, Function | MediumTest | Level1) +{ + std::shared_ptr application = std::make_shared(); + sptr abilityToken = sptr(new AbilityThread()); + EXPECT_NE(abilityToken, nullptr); + if (abilityToken != nullptr) { + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->type = AppExecFwk::AbilityType::PAGE; + abilityInfo->name = ABILITY_NAME; + abilityInfo->isNativeAbility = true; + std::shared_ptr abilityRecord = + std::make_shared(abilityInfo, abilityToken); + + GTEST_LOG_(INFO) << "AaFwk_Ability_Terminate_test_008 AbilityThreadMain"; + AbilityThread::AbilityThreadMain(application, abilityRecord); + + Want want; + MockAbilityManagerService *mockAMS = iface_cast(abilityObject_); + mockAMS->StartAbility(want, AbilityLifeCycleState::ABILITY_STATE_INITIAL); + usleep(AbilityTerminateTest::TEST_WAIT_TIME); + + mockAMS->TerminateAbility(nullptr, RESULT_CODE, &want); + usleep(AbilityTerminateTest::TEST_WAIT_TIME); + } + GTEST_LOG_(INFO) << "AaFwk_Ability_Terminate_test_008 TerminateAbility"; +} + +/** + * @tc.number: AaFwk_WMS_window_test_0100 + * @tc.name: WMS Link + * @tc.desc: Start pageability and call GetWindow to get the window handle. + */ +HWTEST_F(AbilityTerminateTest, AaFwk_WMS_window_test_0100, Function | MediumTest | Level1) +{ + std::shared_ptr application = std::make_shared(); + sptr abilityToken = sptr(new AbilityThread()); + EXPECT_NE(abilityToken, nullptr); + if (abilityToken != nullptr) { + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->type = AppExecFwk::AbilityType::PAGE; + abilityInfo->name = ABILITY_NAME; + abilityInfo->isNativeAbility = true; + std::shared_ptr abilityRecord = + std::make_shared(abilityInfo, abilityToken); + + GTEST_LOG_(INFO) << "AaFwk_WMS_window_test_001 AbilityThreadMain"; + AbilityThread::AbilityThreadMain(application, abilityRecord); + + Want want; + MockAbilityManagerService *mockAMS = iface_cast(abilityObject_); + GTEST_LOG_(INFO) << "AaFwk_WMS_window_test_001 StartAbility"; + mockAMS->StartAbility(want, AbilityLifeCycleState::ABILITY_STATE_ACTIVE); + usleep(AbilityTerminateTest::TEST_WAIT_TIME); + mockAMS->TerminateAbility(nullptr, RESULT_CODE, &want); + usleep(AbilityTerminateTest::TEST_WAIT_TIME); + } + GTEST_LOG_(INFO) << "AaFwk_WMS_window_test_001 TerminateAbility"; +} + +/** + * @tc.number: AaFwk_WMS_window_test_0200 + * @tc.name: WMS Link + * @tc.desc: Pageability switches to the foreground and calls Window.show. + * Pageability switches to the background and calls Window.hide. + */ +HWTEST_F(AbilityTerminateTest, AaFwk_WMS_window_test_0200, Function | MediumTest | Level1) +{ + std::shared_ptr application = std::make_shared(); + sptr abilityToken = sptr(new AbilityThread()); + EXPECT_NE(abilityToken, nullptr); + if (abilityToken != nullptr) { + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->type = AppExecFwk::AbilityType::PAGE; + abilityInfo->name = ABILITY_NAME; + abilityInfo->isNativeAbility = true; + std::shared_ptr abilityRecord = + std::make_shared(abilityInfo, abilityToken); + + GTEST_LOG_(INFO) << "AaFwk_WMS_window_test_002 AbilityThreadMain"; + AbilityThread::AbilityThreadMain(application, abilityRecord); + + Want want; + MockAbilityManagerService *mockAMS = iface_cast(abilityObject_); + mockAMS->StartAbility(want, AbilityLifeCycleState::ABILITY_STATE_BACKGROUND); + GTEST_LOG_(INFO) << "AaFwk_WMS_window_test_002 BackGround"; + usleep(AbilityTerminateTest::TEST_WAIT_TIME); + mockAMS->StartAbility(want, AbilityLifeCycleState::ABILITY_STATE_ACTIVE); + GTEST_LOG_(INFO) << "AaFwk_WMS_window_test_002 Active"; + usleep(AbilityTerminateTest::TEST_WAIT_TIME); + + mockAMS->TerminateAbility(nullptr, RESULT_CODE, &want); + } + GTEST_LOG_(INFO) << "AaFwk_WMS_window_test_002 TerminateAbility"; +} + +/** + * @tc.number: AaFwk_DataAbility_Launch_0100 + * @tc.name: DataAbilityHelper + * @tc.desc: The AbilityManager could receive the shelder of abilitythread for dataability when the dataability + * launched. + */ +HWTEST_F(AbilityTerminateTest, AaFwk_DataAbility_Launch_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbility_Launch_0100"; + + std::shared_ptr application = std::make_shared(); + sptr abilityToken = sptr(new AbilityThread()); + EXPECT_NE(abilityToken, nullptr); + if (abilityToken != nullptr) { + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->type = AppExecFwk::AbilityType::DATA; + abilityInfo->name = "DemoAbility"; + std::shared_ptr abilityRecord = + std::make_shared(abilityInfo, abilityToken); + + AbilityThread::AbilityThreadMain(application, abilityRecord); + + sptr remoteObject_ = + OHOS::DelayedSingleton::GetInstance()->GetSystemAbility(ABILITY_MGR_SERVICE_ID); + sptr abms = iface_cast(remoteObject_); + + Uri uri("testuri"); + EXPECT_NE(abms->AcquireDataAbility(uri, false, nullptr), nullptr); + } + GTEST_LOG_(INFO) << "AaFwk_DataAbility_Launch_0100"; +} + +/** + * @tc.number: AaFwk_DataAbility_Start_0100 + * @tc.name: DataAbilityHelper + * @tc.desc: The AbilityManager could receive the inactive state from abilitythread for dataability when the + dataability + * change its lifecycle state to inactive. + */ +HWTEST_F(AbilityTerminateTest, AaFwk_DataAbility_Start_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbility_Start_0100"; + + std::shared_ptr application = std::make_shared(); + sptr abilityToken = sptr(new AbilityThread()); + EXPECT_NE(abilityToken, nullptr); + if (abilityToken != nullptr) { + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->type = AppExecFwk::AbilityType::DATA; + abilityInfo->name = "DemoAbility"; + std::shared_ptr abilityRecord = + std::make_shared(abilityInfo, abilityToken); + + AbilityThread::AbilityThreadMain(application, abilityRecord); + + sptr remoteObject_ = + OHOS::DelayedSingleton::GetInstance()->GetSystemAbility(ABILITY_MGR_SERVICE_ID); + sptr abms = iface_cast(remoteObject_); + Want want; + abms->StartAbility(want, AbilityLifeCycleState::ABILITY_STATE_INACTIVE); + + usleep(AbilityBaseTest::TEST_WAIT_TIME); + } + GTEST_LOG_(INFO) << "AaFwk_DataAbility_Start_0100"; +} + +/** + * @tc.number: AaFwk_DataAbility_Start_0200 + * @tc.name: DataAbilityHelper + * @tc.desc: The AbilityManager could not receive the initial state from abilitythread for dataability. + * And the OnStop coulde be called. When the dataability change its lifecycle state to initial. + */ +HWTEST_F(AbilityTerminateTest, AaFwk_DataAbility_Start_0200, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbility_Start_0200"; + + std::shared_ptr application = std::make_shared(); + sptr abilityToken = sptr(new AbilityThread()); + EXPECT_NE(abilityToken, nullptr); + if (abilityToken != nullptr) { + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->type = AppExecFwk::AbilityType::DATA; + abilityInfo->name = "DemoAbility"; + std::shared_ptr abilityRecord = + std::make_shared(abilityInfo, abilityToken); + + AbilityThread::AbilityThreadMain(application, abilityRecord); + + sptr remoteObject_ = + OHOS::DelayedSingleton::GetInstance()->GetSystemAbility(ABILITY_MGR_SERVICE_ID); + sptr abms = iface_cast(remoteObject_); + Want want; + abms->StartAbility(want, AbilityLifeCycleState::ABILITY_STATE_INITIAL); + + usleep(AbilityBaseTest::TEST_WAIT_TIME); + } + GTEST_LOG_(INFO) << "AaFwk_DataAbility_Start_0200"; +} + +/** + * @tc.number: AaFwk_DataAbility_Start_0300 + * @tc.name: DataAbilityHelper + * @tc.desc: The AbilityManager could not receive the active state from abilitythread for dataability. + * And the OnActive coulde be called. When the dataability change its lifecycle state to active. + */ +HWTEST_F(AbilityTerminateTest, AaFwk_DataAbility_Start_0300, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbility_Start_0300"; + + std::shared_ptr application = std::make_shared(); + sptr abilityToken = sptr(new AbilityThread()); + EXPECT_NE(abilityToken, nullptr); + if (abilityToken != nullptr) { + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->type = AppExecFwk::AbilityType::DATA; + abilityInfo->name = "DemoAbility"; + std::shared_ptr abilityRecord = + std::make_shared(abilityInfo, abilityToken); + + AbilityThread::AbilityThreadMain(application, abilityRecord); + + sptr remoteObject_ = + OHOS::DelayedSingleton::GetInstance()->GetSystemAbility(ABILITY_MGR_SERVICE_ID); + sptr abms = iface_cast(remoteObject_); + Want want; + abms->StartAbility(want, AbilityLifeCycleState::ABILITY_STATE_ACTIVE); + + usleep(AbilityBaseTest::TEST_WAIT_TIME); + } + GTEST_LOG_(INFO) << "AaFwk_DataAbility_Start_0300"; +} + +/** + * @tc.number: AaFwk_DataAbility_Start_0400 + * @tc.name: DataAbilityHelper + * @tc.desc: The AbilityManager could not receive the background state from abilitythread for dataability. + * And the OnBackground coulde be called. When the dataability change its lifecycle state to background. + */ +HWTEST_F(AbilityTerminateTest, AaFwk_DataAbility_Start_0400, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbility_Start_0400"; + + std::shared_ptr application = std::make_shared(); + sptr abilityToken = sptr(new AbilityThread()); + EXPECT_NE(abilityToken, nullptr); + if (abilityToken != nullptr) { + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->type = AppExecFwk::AbilityType::DATA; + abilityInfo->name = "DemoAbility"; + std::shared_ptr abilityRecord = + std::make_shared(abilityInfo, abilityToken); + + AbilityThread::AbilityThreadMain(application, abilityRecord); + + sptr remoteObject_ = + OHOS::DelayedSingleton::GetInstance()->GetSystemAbility(ABILITY_MGR_SERVICE_ID); + sptr abms = iface_cast(remoteObject_); + Want want; + abms->StartAbility(want, AbilityLifeCycleState::ABILITY_STATE_BACKGROUND); + + usleep(AbilityBaseTest::TEST_WAIT_TIME); + } + GTEST_LOG_(INFO) << "AaFwk_DataAbility_Start_0400"; +} + +/** + * @tc.number: AaFwk_DataAbility_Start_0500 + * @tc.name: DataAbilityHelper + * @tc.desc: The AbilityManager could not receive the suspended state from abilitythread for dataability. + * When the dataability change its lifecycle state to suspended. + */ +HWTEST_F(AbilityTerminateTest, AaFwk_DataAbility_Start_0500, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbility_Start_0500"; + + std::shared_ptr application = std::make_shared(); + sptr abilityToken = sptr(new AbilityThread()); + EXPECT_NE(abilityToken, nullptr); + if (abilityToken != nullptr) { + std::shared_ptr abilityInfo = std::make_shared(); + abilityInfo->type = AppExecFwk::AbilityType::DATA; + abilityInfo->name = "DemoAbility"; + std::shared_ptr abilityRecord = + std::make_shared(abilityInfo, abilityToken); + + AbilityThread::AbilityThreadMain(application, abilityRecord); + + sptr remoteObject_ = + OHOS::DelayedSingleton::GetInstance()->GetSystemAbility(ABILITY_MGR_SERVICE_ID); + sptr abms = iface_cast(remoteObject_); + Want want; + abms->StartAbility(want, AbilityLifeCycleState::ABILITY_STATE_SUSPENDED); + + usleep(AbilityBaseTest::TEST_WAIT_TIME); + } + GTEST_LOG_(INFO) << "AaFwk_DataAbility_Start_0500"; +} +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/test/moduletest/cpp/abilitytest/data_ability_helper_module_test.cpp b/tools/frameworks/kits/test/moduletest/cpp/abilitytest/data_ability_helper_module_test.cpp new file mode 100644 index 00000000000..4438b5e5305 --- /dev/null +++ b/tools/frameworks/kits/test/moduletest/cpp/abilitytest/data_ability_helper_module_test.cpp @@ -0,0 +1,682 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "abs_shared_result_set.h" +#include "data_ability_predicates.h" +#include "values_bucket.h" +#include "gtest/gtest.h" +#include "mock_ability_test.h" +#include "mock_ability_manager_client.h" +#include "mock_ability_thread_for_data_observer.h" +#include "context.h" +#include "ability_context.h" +#include "data_ability_helper.h" + +namespace OHOS { +namespace AppExecFwk { + +using namespace testing::ext; +REGISTER_AA(MockAbilityTest) +/* + * Parameters: + * Action + * Entity + * Flag + * ElementName + */ +class DataAbilityHelperTest : public testing::Test { +public: + DataAbilityHelperTest(){}; + virtual ~DataAbilityHelperTest(){}; + + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + +public: +}; + +void DataAbilityHelperTest::SetUpTestCase(void) +{} + +void DataAbilityHelperTest::TearDownTestCase(void) +{} + +void DataAbilityHelperTest::SetUp(void) +{} + +void DataAbilityHelperTest::TearDown(void) +{} + +/** + * @tc.number: AaFwk_DataAbilityHelper_Insert_Test_0100 + * @tc.name: DataAbilityHelper + * @tc.desc: Insert with DataAbilityHelper which created with uri. + */ +HWTEST_F(DataAbilityHelperTest, AaFwk_DataAbilityHelper_Insert_Test_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_Insert_Test_0100 start"; + + sptr thread = nullptr; + std::shared_ptr context = std::make_shared(); + std::shared_ptr uri = + std::make_shared("dataability://device_id/com.domainname.dataability.persondata/person/10"); + + std::shared_ptr dataAbilityHelper = DataAbilityHelper::Creator(context, uri); + NativeRdb::ValuesBucket val; + val.PutInt("22", 22); + Uri urivalue("dataability://device_id/com.domainname.dataability.persondata/person/10"); + + int value = dataAbilityHelper->Insert(urivalue, val); + + EXPECT_EQ(value, 20); + + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_Insert_Test_0100 end"; +} + +/** + * @tc.number: AaFwk_DataAbilityHelper_Insert_Test_0200 + * @tc.name: DataAbilityHelper + * @tc.desc: Insert with DataAbilityHelper which created without uri. + */ +HWTEST_F(DataAbilityHelperTest, AaFwk_DataAbilityHelper_Insert_Test_0200, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_Insert_Test_0200 start"; + + sptr thread = nullptr; + std::shared_ptr context = std::make_shared(); + std::shared_ptr uri = + std::make_shared("dataability://device_id/com.domainname.dataability.persondata/person/10"); + + std::shared_ptr dataAbilityHelper = DataAbilityHelper::Creator(context); + NativeRdb::ValuesBucket val; + val.PutInt("22", 20); + Uri urivalue("dataability://device_id/com.domainname.dataability.persondata/person/10"); + + int value = dataAbilityHelper->Insert(urivalue, val); + + EXPECT_EQ(value, 20); + + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_Insert_Test_0200 end"; +} + +/** + * @tc.number: AaFwk_DataAbilityHelper_Update_Test_0100 + * @tc.name: DataAbilityHelper + * @tc.desc: Update with DataAbilityHelper which created with uri. + */ +HWTEST_F(DataAbilityHelperTest, AaFwk_DataAbilityHelper_Update_Test_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_Update_Test_0100 start"; + + std::shared_ptr context = std::make_shared(); + std::shared_ptr uri = + std::make_shared("dataability://device_id/com.domainname.dataability.persondata/person/10"); + + std::shared_ptr dataAbilityHelper = DataAbilityHelper::Creator(context, uri); + + NativeRdb::ValuesBucket val; + val.PutInt("22", 22); + Uri urivalue("dataability://device_id/com.domainname.dataability.persondata/person/10"); + NativeRdb::DataAbilityPredicates predicates; + int value = dataAbilityHelper->Update(urivalue, val, predicates); + EXPECT_EQ(value, 33); + + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_Update_Test_0100 end"; +} + +/** + * @tc.number: AaFwk_DataAbilityHelper_Update_Test_0200 + * @tc.name: DataAbilityHelper + * @tc.desc: Update with DataAbilityHelper which created without uri. + */ +HWTEST_F(DataAbilityHelperTest, AaFwk_DataAbilityHelper_Update_Test_0200, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_Insert_Test_0200 start"; + std::shared_ptr context = std::make_shared(); + std::shared_ptr uri = + std::make_shared("dataability://device_id/com.domainname.dataability.persondata/person/10"); + std::shared_ptr dataAbilityHelper = DataAbilityHelper::Creator(context); + + NativeRdb::ValuesBucket val; + val.PutInt("22", 22); + Uri urivalue("dataability://device_id/com.domainname.dataability.persondata/person/10"); + NativeRdb::DataAbilityPredicates predicates; + int value = dataAbilityHelper->Update(urivalue, val, predicates); + EXPECT_EQ(value, 33); + + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_Insert_Test_0200 end"; +} + +/** + * @tc.number: AaFwk_DataAbilityHelper_GetFileTypes_Test_0100 + * @tc.name: DataAbilityHelper + * @tc.desc: GetFileTypes with DataAbilityHelper which created with uri. + */ +HWTEST_F(DataAbilityHelperTest, AaFwk_DataAbilityHelper_GetFileTypes_Test_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_GetFileTypes_Test_0100 start"; + + std::shared_ptr context = std::make_shared(); + std::shared_ptr uri = + std::make_shared("dataability://device_id/com.domainname.dataability.persondata/person/10"); + std::shared_ptr dataAbilityHelper = DataAbilityHelper::Creator(context, uri); + + std::string mimeTypeFilter("mimeTypeFiltertest"); + Uri urivalue("dataability://device_id/com.domainname.dataability.persondata/person/10"); + std::vector result = dataAbilityHelper->GetFileTypes(urivalue, mimeTypeFilter); + + std::vector list; + list.push_back("Type1"); + list.push_back("Type2"); + list.push_back("Type3"); + + for (size_t i = 0; i < result.size(); i++) { + EXPECT_STREQ(result.at(i).c_str(), list.at(i).c_str()); + } + + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_GetFileTypes_Test_0100 end"; +} + +/** + * @tc.number: AaFwk_DataAbilityHelper_GetFileTypes_Test_0200 + * @tc.name: DataAbilityHelper + * @tc.desc: GetFileTypes with DataAbilityHelper which created without uri. + */ +HWTEST_F(DataAbilityHelperTest, AaFwk_DataAbilityHelper_GetFileTypes_Test_0200, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_GetFileTypes_Test_0200 start"; + + std::shared_ptr context = std::make_shared(); + std::shared_ptr uri = + std::make_shared("dataability://device_id/com.domainname.dataability.persondata/person/10"); + std::shared_ptr dataAbilityHelper = DataAbilityHelper::Creator(context); + + Uri urivalue("dataability://device_id/com.domainname.dataability.persondata/person/10"); + std::string mimeTypeFilter("mimeTypeFiltertest"); + std::vector result = dataAbilityHelper->GetFileTypes(urivalue, mimeTypeFilter); + + std::vector list; + list.push_back("Type1"); + list.push_back("Type2"); + list.push_back("Type3"); + + for (unsigned int i = 0; i < result.size(); i++) { + EXPECT_STREQ(result.at(i).c_str(), list.at(i).c_str()); + } + + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_GetFileTypes_Test_0200 end"; +} + +/** + * @tc.number: AaFwk_DataAbilityHelper_OpenFile_Test_0100 + * @tc.name: DataAbilityHelper + * @tc.desc: Openfile with DataAbilityHelper which created with uri. + */ +HWTEST_F(DataAbilityHelperTest, AaFwk_DataAbilityHelper_OpenFile_Test_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_OpenFile_Test_0100 start"; + + std::shared_ptr context = std::make_shared(); + std::shared_ptr uri = + std::make_shared("dataability://device_id/com.domainname.dataability.persondata/person/10"); + std::shared_ptr dataAbilityHelper = DataAbilityHelper::Creator(context, uri); + + Uri urivalue("dataability://device_id/com.domainname.dataability.persondata/person/10?test/te.txt"); + std::string mode("r"); + int fd = dataAbilityHelper->OpenFile(urivalue, mode); + EXPECT_NE(fd, -1); + + if (fd > 0) { + std::string result = "123456"; + FILE *file = nullptr; + file = fdopen(fd, "r"); + EXPECT_NE(file, nullptr); + + if (file != nullptr) { + int strSize = 7; + std::string str(""); + str.resize(strSize); + if (!feof(file)) { + fgets(&str[0], strSize, file); + } + string stringstr(str); + EXPECT_STREQ(stringstr.c_str(), result.c_str()); + fclose(file); + system("rm /dataability_openfile_test.txt"); + } + } + + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_OpenFile_Test_0100 end"; +} + +/** + * @tc.number: AaFwk_DataAbilityHelper_OpenFile_Test_0200 + * @tc.name: DataAbilityHelper Insert + * @tc.desc: Openfile with DataAbilityHelper which created without uri. + */ +HWTEST_F(DataAbilityHelperTest, AaFwk_DataAbilityHelper_OpenFile_Test_0200, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_OpenFile_Test_0200 start"; + + std::shared_ptr context = std::make_shared(); + std::shared_ptr uri = + std::make_shared("dataability://device_id/com.domainname.dataability.persondata/person/10"); + std::shared_ptr dataAbilityHelper = DataAbilityHelper::Creator(context); + + Uri urivalue("dataability://device_id/com.domainname.dataability.persondata/person/10?test/te.txt"); + std::string mode("r"); + int fd = dataAbilityHelper->OpenFile(urivalue, mode); + EXPECT_NE(fd, -1); + + if (fd > 0) { + std::string result = "123456"; + FILE *file = nullptr; + file = fdopen(fd, "r"); + EXPECT_NE(file, nullptr); + + if (file != nullptr) { + int strSize = 7; + std::string str(""); + str.resize(strSize); + if (!feof(file)) { + fgets(&str[0], strSize, file); + } + string stringstr(str); + EXPECT_STREQ(stringstr.c_str(), result.c_str()); + fclose(file); + system("rm /dataability_openfile_test.txt"); + } + } + + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_OpenFile_Test_0200 end"; +} + +/** + * @tc.number: AaFwk_DataAbilityHelper_OpenRawFile_Test_0100 + * @tc.name: DataAbilityHelper + * @tc.desc: OpenRawFile with DataAbilityHelper which created with uri. + */ +HWTEST_F(DataAbilityHelperTest, AaFwk_DataAbilityHelper_OpenRawFile_Test_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_OpenRawFile_Test_0100 start"; + + std::shared_ptr context = std::make_shared(); + std::shared_ptr uri = + std::make_shared("dataability://device_id/com.domainname.dataability.persondata/person/10"); + std::shared_ptr dataAbilityHelper = DataAbilityHelper::Creator(context, uri); + + Uri urivalue("dataability://device_id/com.domainname.dataability.persondata/person/10"); + std::string mode("modetest"); + int fd = dataAbilityHelper->OpenRawFile(urivalue, mode); + + EXPECT_EQ(fd, 122); + + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_OpenRawFile_Test_0100 end"; +} + +/** + * @tc.number: AaFwk_DataAbilityHelper_OpenRawFile_Test_0200 + * @tc.name: DataAbilityHelper Insert + * @tc.desc: OpenRawFile with DataAbilityHelper which created without uri. + */ +HWTEST_F(DataAbilityHelperTest, AaFwk_DataAbilityHelper_OpenRawFile_Test_0200, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_OpenRawFile_Test_0200 start"; + + std::shared_ptr context = std::make_shared(); + std::shared_ptr uri = + std::make_shared("dataability://device_id/com.domainname.dataability.persondata/person/10"); + std::shared_ptr dataAbilityHelper = DataAbilityHelper::Creator(context); + + Uri urivalue("dataability://device_id/com.domainname.dataability.persondata/person/10"); + std::string mode("modetest"); + int fd = dataAbilityHelper->OpenRawFile(urivalue, mode); + + EXPECT_EQ(fd, 122); + + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_OpenRawFile_Test_0200 end"; +} + +/** + * @tc.number: AaFwk_DataAbilityHelper_BatchInsert_Test_0100 + * @tc.name: DataAbilityHelper + * @tc.desc: BatchInsert with DataAbilityHelper which created with uri. + */ +HWTEST_F(DataAbilityHelperTest, AaFwk_DataAbilityHelper_BatchInsert_Test_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_BatchInsert_Test_0100 start"; + + std::shared_ptr context = std::make_shared(); + std::shared_ptr uri = + std::make_shared("dataability://device_id/com.domainname.dataability.persondata/person/10"); + std::shared_ptr dataAbilityHelper = DataAbilityHelper::Creator(context, uri); + + Uri urivalue("dataability://device_id/com.domainname.dataability.persondata/person/10"); + std::vector values; + int fd = dataAbilityHelper->BatchInsert(urivalue, values); + + EXPECT_EQ(fd, 115); + + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_BatchInsert_Test_0100 end"; +} + +/** + * @tc.number: AaFwk_DataAbilityHelper_BatchInsert_Test_0200 + * @tc.name: DataAbilityHelper Insert + * @tc.desc: BatchInsert with DataAbilityHelper which created without uri. + */ +HWTEST_F(DataAbilityHelperTest, AaFwk_DataAbilityHelper_BatchInsert_Test_0200, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_BatchInsert_Test_0200 start"; + + std::shared_ptr context = std::make_shared(); + std::shared_ptr uri = + std::make_shared("dataability://device_id/com.domainname.dataability.persondata/person/10"); + std::shared_ptr dataAbilityHelper = DataAbilityHelper::Creator(context); + + Uri urivalue("dataability://device_id/com.domainname.dataability.persondata/person/10"); + std::vector values; + int fd = dataAbilityHelper->BatchInsert(urivalue, values); + + EXPECT_EQ(fd, 115); + + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_BatchInsert_Test_0200 end"; +} + +/** + * @tc.number: AaFwk_DataAbilityHelper_Reload_Test_0100 + * @tc.name: DataAbilityHelper + * @tc.desc: Reload with DataAbilityHelper which created with uri. + */ +HWTEST_F(DataAbilityHelperTest, AaFwk_DataAbilityHelper_Reload_Test_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_Reload_Test_0100 start"; + + std::shared_ptr context = std::make_shared(); + std::shared_ptr uri = + std::make_shared("dataability://device_id/com.domainname.dataability.persondata/person/10"); + std::shared_ptr dataAbilityHelper = DataAbilityHelper::Creator(context, uri); + + Uri urivalue("dataability://device_id/com.domainname.dataability.persondata/person/10"); + PacMap extras; + int fd = dataAbilityHelper->Reload(urivalue, extras); + + EXPECT_EQ(fd, true); + + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_Reload_Test_0100 end"; +} + +/** + * @tc.number: AaFwk_DataAbilityHelper_Reload_Test_0200 + * @tc.name: DataAbilityHelper + * @tc.desc: Reload with DataAbilityHelper which created without uri. + */ +HWTEST_F(DataAbilityHelperTest, AaFwk_DataAbilityHelper_Reload_Test_0200, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_Reload_Test_0200 start"; + + std::shared_ptr context = std::make_shared(); + std::shared_ptr uri = + std::make_shared("dataability://device_id/com.domainname.dataability.persondata/person/10"); + std::shared_ptr dataAbilityHelper = DataAbilityHelper::Creator(context); + + Uri urivalue("dataability://device_id/com.domainname.dataability.persondata/person/10"); + PacMap extras; + int fd = dataAbilityHelper->Reload(urivalue, extras); + + EXPECT_EQ(fd, true); + + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_Reload_Test_0200 end"; +} + +/** + * @tc.number: AaFwk_DataAbilityHelper_Delete_Test_0100 + * @tc.name: DataAbilityHelper + * @tc.desc: Delete with DataAbilityHelper which created with uri. + */ +HWTEST_F(DataAbilityHelperTest, AaFwk_DataAbilityHelper_Delete_Test_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_Delete_Test_0100 start"; + + std::shared_ptr context = std::make_shared(); + std::shared_ptr uri = + std::make_shared("dataability://device_id/com.domainname.dataability.persondata/person/10"); + std::shared_ptr dataAbilityHelper = DataAbilityHelper::Creator(context, uri); + + Uri urivalue("dataability://device_id/com.domainname.dataability.persondata/person/10"); + NativeRdb::DataAbilityPredicates predicates; + int index = dataAbilityHelper->Delete(urivalue, predicates); + + EXPECT_EQ(index, 234); + + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_Delete_Test_0100 end"; +} + +/** + * @tc.number: AaFwk_DataAbilityHelper_Delete_Test_0200 + * @tc.name: DataAbilityHelper + * @tc.desc: Delete with DataAbilityHelper which created without uri. + */ +HWTEST_F(DataAbilityHelperTest, AaFwk_DataAbilityHelper_Delete_Test_0200, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_Delete_Test_0200 start"; + + std::shared_ptr context = std::make_shared(); + std::shared_ptr uri = + std::make_shared("dataability://device_id/com.domainname.dataability.persondata/person/10"); + std::shared_ptr dataAbilityHelper = DataAbilityHelper::Creator(context); + + Uri urivalue("dataability://device_id/com.domainname.dataability.persondata/person/10"); + NativeRdb::DataAbilityPredicates predicates; + int index = dataAbilityHelper->Delete(urivalue, predicates); + + EXPECT_EQ(index, 234); + + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_Delete_Test_0200 end"; +} +/** + * @tc.number: AaFwk_DataAbilityHelper_Query_Test_0100 + * @tc.name: DataAbilityHelper + * @tc.desc: Query with DataAbilityHelper which created with uri. + */ +HWTEST_F(DataAbilityHelperTest, AaFwk_DataAbilityHelper_Query_Test_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_Query_Test_0100 start"; + + std::shared_ptr context = std::make_shared(); + std::shared_ptr uri = + std::make_shared("dataability://device_id/com.domainname.dataability.persondata/person/10"); + std::shared_ptr dataAbilityHelper = DataAbilityHelper::Creator(context, uri); + + Uri urivalue("dataability://device_id/com.domainname.dataability.persondata/person/10"); + + std::vector columns; + columns.push_back("string1"); + columns.push_back("string2"); + columns.push_back("string3"); + NativeRdb::DataAbilityPredicates predicates; + + EXPECT_NE(nullptr, dataAbilityHelper->Query(urivalue, columns, predicates)); + + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_Query_Test_0100 end"; +} + +/** + * @tc.number: AaFwk_DataAbilityHelper_Query_Test_0200 + * @tc.name: DataAbilityHelper Insert + * @tc.desc: Query with DataAbilityHelper which created without uri. + */ +HWTEST_F(DataAbilityHelperTest, AaFwk_DataAbilityHelper_Query_Test_0200, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_Query_Test_0200 start"; + + std::shared_ptr context = std::make_shared(); + std::shared_ptr uri = + std::make_shared("dataability://device_id/com.domainname.dataability.persondata/person/10"); + std::shared_ptr dataAbilityHelper = DataAbilityHelper::Creator(context); + + Uri urivalue("dataability://device_id/com.domainname.dataability.persondata/person/10"); + + std::vector columns; + columns.push_back("string1"); + columns.push_back("string2"); + columns.push_back("string3"); + NativeRdb::DataAbilityPredicates predicates; + + EXPECT_NE(nullptr, dataAbilityHelper->Query(urivalue, columns, predicates)); + + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_Query_Test_0200 end"; +} + +/** + * @tc.number: AaFwk_DataAbilityHelper_GetType_Test_0100 + * @tc.name: DataAbilityHelper + * @tc.desc: Gettype with DataAbilityHelper which created with uri. + */ +HWTEST_F(DataAbilityHelperTest, AaFwk_DataAbilityHelper_GetType_Test_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_GetType_Test_0100 start"; + + std::shared_ptr context = std::make_shared(); + std::shared_ptr uri = + std::make_shared("dataability://device_id/com.domainname.dataability.persondata/person/10"); + std::shared_ptr dataAbilityHelper = DataAbilityHelper::Creator(context, uri); + + Uri urivalue("dataability://device_id/com.domainname.dataability.persondata/person/10"); + std::string type = dataAbilityHelper->GetType(urivalue); + + EXPECT_STREQ(type.c_str(), "Type1"); + + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_GetType_Test_0100 end"; +} + +/** + * @tc.number: AaFwk_DataAbilityHelper_GetType_Test_0200 + * @tc.name: DataAbilityHelper + * @tc.desc: GetType with DataAbilityHelper which created without uri. + */ +HWTEST_F(DataAbilityHelperTest, AaFwk_DataAbilityHelper_GetType_Test_0200, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_GetType_Test_0200 start"; + + std::shared_ptr context = std::make_shared(); + std::shared_ptr uri = + std::make_shared("dataability://device_id/com.domainname.dataability.persondata/person/10"); + std::shared_ptr dataAbilityHelper = DataAbilityHelper::Creator(context); + + Uri urivalue("dataability://device_id/com.domainname.dataability.persondata/person/10"); + std::string type = dataAbilityHelper->GetType(urivalue); + + EXPECT_STREQ(type.c_str(), "Type1"); + + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_GetType_Test_0200 end"; +} + +/** + * @tc.number: AaFwk_DataAbilityHelper_NormalizeUri_Test_0100 + * @tc.name: DataAbilityHelper NormalizeUri + * @tc.desc: NormalizeUri with DataAbilityHelper which created without uri. + */ +HWTEST_F(DataAbilityHelperTest, AaFwk_DataAbilityHelper_NormalizeUri_Test_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_NormalizeUri_Test_0100 start"; + + std::shared_ptr context = std::make_shared(); + std::shared_ptr uri = + std::make_shared("dataability://device_id/com.domainname.dataability.persondata/person/10"); + std::shared_ptr dataAbilityHelper = DataAbilityHelper::Creator(context, uri); + + Uri urivalue("dataability://device_id/com.domainname.dataability.persondata/person/10"); + Uri type(""); + type = dataAbilityHelper->NormalizeUri(urivalue); + + EXPECT_STREQ(type.ToString().c_str(), urivalue.ToString().c_str()); + + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_NormalizeUri_Test_0100 end"; +} + +/** + * @tc.number: AaFwk_DataAbilityHelper_NormalizeUri_Test_0200 + * @tc.name: DataAbilityHelper NormalizeUri + * @tc.desc: NormalizeUri with DataAbilityHelper which created without uri. + */ +HWTEST_F(DataAbilityHelperTest, AaFwk_DataAbilityHelper_NormalizeUri_Test_0200, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_NormalizeUri_Test_0200 start"; + + std::shared_ptr context = std::make_shared(); + std::shared_ptr uri = + std::make_shared("dataability://device_id/com.domainname.dataability.persondata/person/10"); + std::shared_ptr dataAbilityHelper = DataAbilityHelper::Creator(context); + + Uri urivalue("dataability://device_id/com.domainname.dataability.persondata/person/10"); + Uri type(""); + type = dataAbilityHelper->NormalizeUri(urivalue); + + EXPECT_STREQ(type.ToString().c_str(), urivalue.ToString().c_str()); + + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_NormalizeUri_Test_0200 end"; +} + +/** + * @tc.number: AaFwk_DataAbilityHelper_DenormalizeUri_Test_0100 + * @tc.name: DataAbilityHelper + * @tc.desc: DenormalizeUri with DataAbilityHelper which created without uri. + */ +HWTEST_F(DataAbilityHelperTest, AaFwk_DataAbilityHelper_DenormalizeUri_Test_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_DenormalizeUri_Test_0100 start"; + + std::shared_ptr context = std::make_shared(); + std::shared_ptr uri = + std::make_shared("dataability://device_id/com.domainname.dataability.persondata/person/10"); + std::shared_ptr dataAbilityHelper = DataAbilityHelper::Creator(context, uri); + + Uri urivalue("dataability://device_id/com.domainname.dataability.persondata/person/10"); + Uri type(""); + type = dataAbilityHelper->DenormalizeUri(urivalue); + + EXPECT_STREQ(type.ToString().c_str(), urivalue.ToString().c_str()); + + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_DenormalizeUri_Test_0100 end"; +} + +/** + * @tc.number: AaFwk_DataAbilityHelper_DenormalizeUri_Test_0200 + * @tc.name: DataAbilityHelper DenormalizeUri + * @tc.desc: DenormalizeUri with DataAbilityHelper which created without uri. + */ +HWTEST_F(DataAbilityHelperTest, AaFwk_DataAbilityHelper_DenormalizeUri_Test_0200, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_DenormalizeUri_Test_0200 start"; + + std::shared_ptr context = std::make_shared(); + std::shared_ptr uri = + std::make_shared("dataability://device_id/com.domainname.dataability.persondata/person/10"); + std::shared_ptr dataAbilityHelper = DataAbilityHelper::Creator(context); + + Uri urivalue("dataability://device_id/com.domainname.dataability.persondata/person/10"); + Uri type(""); + type = dataAbilityHelper->DenormalizeUri(urivalue); + + EXPECT_STREQ(type.ToString().c_str(), urivalue.ToString().c_str()); + + GTEST_LOG_(INFO) << "AaFwk_DataAbilityHelper_DenormalizeUri_Test_0200 end"; +} + +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/frameworks/kits/test/moduletest/cpp/abilitytest/data_ability_operation_module_test.cpp b/tools/frameworks/kits/test/moduletest/cpp/abilitytest/data_ability_operation_module_test.cpp new file mode 100644 index 00000000000..c645ec882ca --- /dev/null +++ b/tools/frameworks/kits/test/moduletest/cpp/abilitytest/data_ability_operation_module_test.cpp @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include "abs_shared_result_set.h" +#include "data_ability_predicates.h" +#include "values_bucket.h" +#include "data_ability_operation.h" +#include "data_ability_operation_builder.h" + +namespace OHOS { +namespace AppExecFwk { +using namespace testing::ext; +using namespace OHOS; +using namespace OHOS::AppExecFwk; +class DataAbilityOperationModuleTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void DataAbilityOperationModuleTest::SetUpTestCase(void) +{} + +void DataAbilityOperationModuleTest::TearDownTestCase(void) +{} + +void DataAbilityOperationModuleTest::SetUp(void) +{} + +void DataAbilityOperationModuleTest::TearDown(void) +{} + +/** + * @tc.number: AaFwk_DataAbilityOperation_InsertBuilder_0100 + * @tc.name: DataAbilityOperation + * @tc.desc: Get the file types in the dataability. + + */ +HWTEST_F(DataAbilityOperationModuleTest, AaFwk_DataAbilityOperation_InsertBuilder_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_InsertBuilder_0100"; + std::shared_ptr values = std::make_shared(); + std::shared_ptr uri = std::make_shared("dataability://com.example.myapplication5.DataAbilityTest"); + std::shared_ptr operation = + DataAbilityOperation::NewInsertBuilder(uri)->WithValuesBucket(values)->Build(); + EXPECT_NE(operation, nullptr); + + bool isInsertOperation = operation->IsInsertOperation(); + EXPECT_TRUE(isInsertOperation); + + std::shared_ptr operationUri = operation->GetUri(); + EXPECT_EQ(operationUri->ToString(), "dataability://com.example.myapplication5.DataAbilityTest"); + + int type = operation->GetType(); + EXPECT_EQ(type, DataAbilityOperation::TYPE_INSERT); + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_InsertBuilder_0100"; +} + +/** + * @tc.number: AaFwk_DataAbilityOperation_UpdateBuilder_0100 + * @tc.name: DataAbilityOperation + * @tc.desc: Get the file types in the dataability. + + */ +HWTEST_F(DataAbilityOperationModuleTest, AaFwk_DataAbilityOperation_UpdateBuilder_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_UpdateBuilder_0100"; + std::shared_ptr values = std::make_shared(); + std::shared_ptr predicates = std::make_shared(); + std::shared_ptr uri = std::make_shared("dataability://com.example.myapplication5.DataAbilityTest"); + std::shared_ptr operation = DataAbilityOperation::NewUpdateBuilder(uri) + ->WithValuesBucket(values) + ->WithPredicatesBackReference(0, 0) + ->WithPredicates(predicates) + ->WithInterruptionAllowed(true) + ->Build(); + EXPECT_NE(operation, nullptr); + + bool isUpdateOperation = operation->IsUpdateOperation(); + EXPECT_TRUE(isUpdateOperation); + + bool isInterruptionAllowed = operation->IsInterruptionAllowed(); + EXPECT_TRUE(isInterruptionAllowed); + + std::shared_ptr valuesBucket = operation->GetValuesBucket(); + EXPECT_NE(valuesBucket, nullptr); + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_UpdateBuilder_0100"; +} + +/** + * @tc.number: AaFwk_DataAbilityOperation_AssertBuilder_0100 + * @tc.name: DataAbilityOperation + * @tc.desc: Get the file types in the dataability. + + */ +HWTEST_F(DataAbilityOperationModuleTest, AaFwk_DataAbilityOperation_AssertBuilder_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_AssertBuilder_0100"; + std::shared_ptr uri = std::make_shared("dataability://com.example.myapplication5.DataAbilityTest"); + std::shared_ptr operation = + DataAbilityOperation::NewAssertBuilder(uri)->WithExpectedCount(2)->Build(); + EXPECT_NE(operation, nullptr); + + bool isAssertOperation = operation->IsAssertOperation(); + EXPECT_TRUE(isAssertOperation); + + int count = operation->GetExpectedCount(); + EXPECT_EQ(count, 2); + + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_AssertBuilder_0100"; +} + +/** + * @tc.number: AaFwk_DataAbilityOperation_DeleteBuilder_0100 + * @tc.name: DataAbilityOperation + * @tc.desc: Get the file types in the dataability. + + */ +HWTEST_F(DataAbilityOperationModuleTest, AaFwk_DataAbilityOperation_DeleteBuilder_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_DeleteBuilder_0100"; + std::shared_ptr predicates = std::make_shared(); + EXPECT_NE(predicates, nullptr); + std::shared_ptr uri = std::make_shared("dataability://com.example.myapplication5.DataAbilityTest"); + std::shared_ptr builder = DataAbilityOperation::NewDeleteBuilder(uri); + EXPECT_NE(builder, nullptr); + std::shared_ptr operation = builder->WithPredicates(predicates)->Build(); + EXPECT_NE(operation, nullptr); + bool isDeleteOperation = operation->IsDeleteOperation(); + EXPECT_TRUE(isDeleteOperation); + + GTEST_LOG_(INFO) << "AaFwk_DataAbilityOperation_DeleteBuilder_0100"; +} + +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/interfaces/innerkits/BUILD.gn b/tools/interfaces/innerkits/BUILD.gn new file mode 100644 index 00000000000..f3c7715eaea --- /dev/null +++ b/tools/interfaces/innerkits/BUILD.gn @@ -0,0 +1,22 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +group("innerkits_target") { + deps = [ + "ability_manager:ability_manager", + "base:base", + "dataobs_manager:dataobs_manager", + "intent:intent", + "want:want", + ] +} diff --git a/tools/interfaces/innerkits/ability_manager/BUILD.gn b/tools/interfaces/innerkits/ability_manager/BUILD.gn new file mode 100755 index 00000000000..94e9671a700 --- /dev/null +++ b/tools/interfaces/innerkits/ability_manager/BUILD.gn @@ -0,0 +1,103 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") +import("//foundation/aafwk/standard/aafwk.gni") + +config("ability_manager_public_config") { + visibility = [ ":*" ] + include_dirs = [ + "include/", + "//third_party/jsoncpp/include", + "${innerkits_path}/want/include", + "//utils/native/base/include", + "//utils/system/safwk/native/include", + "//foundation/aafwk/standard/interfaces/innerkits/want/include/ohos/aafwk/content", + "//foundation/aafwk/standard/frameworks/kits/ability/native/include", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler/include", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_core/include/bundlemgr", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_core/include/appmgr", + "//foundation/appexecfwk/standard/kits/appkit/native/app/include", + "//foundation/distributeddatamgr/appdatamgr/interfaces/innerkits/native_rdb/include", + "//foundation/distributeddatamgr/appdatamgr/interfaces/innerkits/native_appdatafwk/include", + "//foundation/distributeddatamgr/appdatamgr/interfaces/innerkits/native_dataability/include", + "//foundation/aafwk/standard/interfaces/innerkits/dataobs_manager/include", + ] + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } +} + +ohos_shared_library("ability_manager") { + sources = [ + "${services_path}/abilitymgr/src/aafwk_dummy_configuration.cpp", + "${services_path}/abilitymgr/src/ability_connect_callback_stub.cpp", + "${services_path}/abilitymgr/src/ability_manager_client.cpp", + "${services_path}/abilitymgr/src/ability_manager_proxy.cpp", + "${services_path}/abilitymgr/src/ability_manager_stub.cpp", + "${services_path}/abilitymgr/src/ability_mission_info.cpp", + "${services_path}/abilitymgr/src/ability_record_info.cpp", + "${services_path}/abilitymgr/src/ability_scheduler_proxy.cpp", + "${services_path}/abilitymgr/src/ability_scheduler_stub.cpp", + "${services_path}/abilitymgr/src/ability_start_setting.cpp", + "${services_path}/abilitymgr/src/caller_info.cpp", + "${services_path}/abilitymgr/src/image_info.cpp", + "${services_path}/abilitymgr/src/lifecycle_state_info.cpp", + "${services_path}/abilitymgr/src/mission_description_info.cpp", + "${services_path}/abilitymgr/src/mission_option.cpp", + "${services_path}/abilitymgr/src/mission_record_info.cpp", + "${services_path}/abilitymgr/src/mission_snapshot_info.cpp", + "${services_path}/abilitymgr/src/mission_stack_info.cpp", + "${services_path}/abilitymgr/src/sender_info.cpp", + "${services_path}/abilitymgr/src/stack_info.cpp", + "${services_path}/abilitymgr/src/stack_setting.cpp", + "${services_path}/abilitymgr/src/want_sender_info.cpp", + "${services_path}/abilitymgr/src/wants_info.cpp", + "//foundation/aafwk/standard/frameworks/kits/ability/native/src/data_ability_operation.cpp", + "//foundation/aafwk/standard/frameworks/kits/ability/native/src/data_ability_operation_builder.cpp", + "//foundation/aafwk/standard/frameworks/kits/ability/native/src/data_ability_result.cpp", + "//foundation/aafwk/standard/frameworks/kits/ability/native/src/task_handler.cpp", + "//foundation/aafwk/standard/frameworks/kits/ability/native/src/task_handler_client.cpp", + ] + + public_configs = [ + ":ability_manager_public_config", + "${services_path}/abilitymgr:abilityms_config", + ] + + deps = [ + "${innerkits_path}/want:want", + "//foundation/aafwk/standard/frameworks/kits/ability/native:dummy_classes", + "//foundation/appexecfwk/standard/common:libappexecfwk_common", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/distributeddatamgr/appdatamgr/interfaces/innerkits/native_dataability:native_dataability", + "//foundation/distributeddatamgr/appdatamgr/interfaces/innerkits/native_rdb:native_rdb", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy:samgr_proxy", + "//third_party/jsoncpp:jsoncpp", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + "native_appdatamgr:native_appdatafwk", + "native_appdatamgr:native_dataability", + "native_appdatamgr:native_rdb", + ] + + subsystem_name = "aafwk" + part_name = "aafwk_standard" +} diff --git a/tools/interfaces/innerkits/ability_manager/ability_manager_headers.gni b/tools/interfaces/innerkits/ability_manager/ability_manager_headers.gni new file mode 100644 index 00000000000..23efb8011db --- /dev/null +++ b/tools/interfaces/innerkits/ability_manager/ability_manager_headers.gni @@ -0,0 +1,39 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +ability_manager_headers = { + header_files = [ + "ability_connect_callback_interface.h", + "ability_connect_callback_stub.h", + "ability_manager_client.h", + "ability_manager_errors.h", + "ability_manager_interface.h", + "ability_scheduler_interface.h", + "lifecycle_state_info.h", + "mission_stack_info.h", + "stack_info.h", + "mission_record_info.h", + "ability_record_info.h", + "wants_info.h", + "sender_info.h", + "want_sender_info.h", + "want_sender_interface.h", + "want_receiver_interface.h", + "aafwk_dummy_configuration.h", + "ability_window_configuration.h", + "ability_start_setting.h", + "mission_option.h", + "stack_setting.h", + ] + header_base = "interfaces/innerkits/ability_manager/include" +} diff --git a/tools/interfaces/innerkits/ability_manager/include/aafwk_dummy_configuration.h b/tools/interfaces/innerkits/ability_manager/include/aafwk_dummy_configuration.h new file mode 100644 index 00000000000..405dda501d0 --- /dev/null +++ b/tools/interfaces/innerkits/ability_manager/include/aafwk_dummy_configuration.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_INTERFACES_INNERKITS_CONFIGURATION_H +#define OHOS_AAFWK_INTERFACES_INNERKITS_CONFIGURATION_H + +#include + +#include "nocopyable.h" +#include "parcel.h" + +namespace OHOS { +namespace AAFwk { + +class DummyConfiguration : public Parcelable { +public: + DummyConfiguration() = default; + explicit DummyConfiguration(const std::string &name); + virtual ~DummyConfiguration() = default; + + /** + * @brief Obtains the name of the Configuration. + * + * @return Returns the Configuration name. + */ + inline const std::string &GetName() const + { + return testInfostr_; + } + + unsigned int Differ(const std::shared_ptr config) const; + + /** + * @brief read this Sequenceable object from a Parcel. + * + * @param inParcel Indicates the Parcel object into which the Sequenceable object has been marshaled. + * @return Returns true if read successed; returns false otherwise. + */ + bool ReadFromParcel(Parcel &parcel); + + /** + * @brief Marshals this Sequenceable object into a Parcel. + * + * @param outParcel Indicates the Parcel object to which the Sequenceable object will be marshaled. + */ + virtual bool Marshalling(Parcel &parcel) const override; + + /** + * @brief Unmarshals this Sequenceable object from a Parcel. + * + * @param inParcel Indicates the Parcel object into which the Sequenceable object has been marshaled. + */ + static DummyConfiguration *Unmarshalling(Parcel &parcel); + +private: + std::string testInfostr_; +}; + +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_INTERFACES_INNERKITS_CONFIGURATION_H \ No newline at end of file diff --git a/tools/interfaces/innerkits/ability_manager/include/ability_connect_callback_interface.h b/tools/interfaces/innerkits/ability_manager/include/ability_connect_callback_interface.h new file mode 100644 index 00000000000..f978006ad1b --- /dev/null +++ b/tools/interfaces/innerkits/ability_manager/include/ability_connect_callback_interface.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_ABILITY_CONNECT_CALLBACK_INTERFACE_H +#define OHOS_AAFWK_ABILITY_CONNECT_CALLBACK_INTERFACE_H + +#include "want.h" +#include "element_name.h" + +#include "iremote_broker.h" + +namespace OHOS { +namespace AAFwk { +/** + * @class IAbilityConnection + * IAbilityConnection is used to notify caller ability that connect or disconnect is complete. + */ +class IAbilityConnection : public OHOS::IRemoteBroker { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"ohos.aafwk.AbilityConnection"); + + /** + * OnAbilityConnectDone, AbilityMs notify caller ability the result of connect. + * + * @param element, service ability's ElementName. + * @param remoteObject,.the session proxy of service ability. + * @param resultCode, ERR_OK on success, others on failure. + */ + virtual void OnAbilityConnectDone( + const AppExecFwk::ElementName &element, const sptr &remoteObject, int resultCode) = 0; + + /** + * OnAbilityDisconnectDone, AbilityMs notify caller ability the result of disconnect. + * + * @param element, service ability's ElementName. + * @param resultCode, ERR_OK on success, others on failure. + */ + virtual void OnAbilityDisconnectDone(const AppExecFwk::ElementName &element, int resultCode) = 0; + + enum { + // ipc id for OnAbilityConnectDone + ON_ABILITY_CONNECT_DONE = 0, + + // ipc id for OnAbilityDisConnectDone + ON_ABILITY_DISCONNECT_DONE + }; +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_ABILITY_CONNECT_CALLBACK_INTERFACE_H diff --git a/tools/interfaces/innerkits/ability_manager/include/ability_connect_callback_stub.h b/tools/interfaces/innerkits/ability_manager/include/ability_connect_callback_stub.h new file mode 100644 index 00000000000..c004dd7abf3 --- /dev/null +++ b/tools/interfaces/innerkits/ability_manager/include/ability_connect_callback_stub.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_ABILITY_CONNECT_CALLBACK_STUB_H +#define OHOS_AAFWK_ABILITY_CONNECT_CALLBACK_STUB_H + +#include +#include + +#include "ability_connect_callback_interface.h" +#include "nocopyable.h" + +namespace OHOS { +namespace AAFwk { +/** + * @class AbilityConnectionStub + * AbilityConnect Stub. + */ +class AbilityConnectionStub : public IRemoteStub { +public: + AbilityConnectionStub(); + virtual ~AbilityConnectionStub(); + + virtual int OnRemoteRequest( + uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override; + +private: + DISALLOW_COPY_AND_MOVE(AbilityConnectionStub); +}; + +/** + * @class AbilityConnectCallbackRecipient + * AbilityConnectCallbackRecipient notices IRemoteBroker died. + */ +class AbilityConnectCallbackRecipient : public IRemoteObject::DeathRecipient { +public: + using RemoteDiedHandler = std::function &)>; + AbilityConnectCallbackRecipient(RemoteDiedHandler handler); + virtual ~AbilityConnectCallbackRecipient(); + virtual void OnRemoteDied(const wptr &remote); + +private: + RemoteDiedHandler handler_; +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_ABILITY_CONNECT_CALLBACK_STUB_H diff --git a/tools/interfaces/innerkits/ability_manager/include/ability_manager_client.h b/tools/interfaces/innerkits/ability_manager/include/ability_manager_client.h new file mode 100644 index 00000000000..792ca21fd8d --- /dev/null +++ b/tools/interfaces/innerkits/ability_manager/include/ability_manager_client.h @@ -0,0 +1,427 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_ABILITY_MANAGER_CLIENT_H +#define OHOS_AAFWK_ABILITY_MANAGER_CLIENT_H + +#include + +#include "ability_connect_callback_interface.h" +#include "ability_manager_errors.h" +#include "ability_scheduler_interface.h" +#include "ability_manager_interface.h" +#include "want.h" + +#include "iremote_object.h" + +namespace OHOS { +namespace AAFwk { +/** + * @class AbilityManagerClient + * AbilityManagerClient is used to access ability manager services. + */ +class AbilityManagerClient { +public: + AbilityManagerClient(); + virtual ~AbilityManagerClient(); + static std::shared_ptr GetInstance(); + + /** + * AttachAbilityThread, ability call this interface after loaded. + * + * @param scheduler,.the interface handler of kit ability. + * @param token,.ability's token. + * @return Returns ERR_OK on success, others on failure. + */ + ErrCode AttachAbilityThread(const sptr &scheduler, const sptr &token); + + /** + * AbilityTransitionDone, ability call this interface after lift cycle was changed. + * + * @param token,.ability's token. + * @param state,.the state of ability lift cycle. + * @return Returns ERR_OK on success, others on failure. + */ + ErrCode AbilityTransitionDone(const sptr &token, int state); + + /** + * ScheduleConnectAbilityDone, service ability call this interface while session was connected. + * + * @param token,.service ability's token. + * @param remoteObject,.the session proxy of service ability. + * @return Returns ERR_OK on success, others on failure. + */ + ErrCode ScheduleConnectAbilityDone(const sptr &token, const sptr &remoteObject); + + /** + * ScheduleDisconnectAbilityDone, service ability call this interface while session was disconnected. + * + * @param token,.service ability's token. + * @return Returns ERR_OK on success, others on failure. + */ + ErrCode ScheduleDisconnectAbilityDone(const sptr &token); + + /** + * ScheduleCommandAbilityDone, service ability call this interface while session was commanded. + * + * @param token,.service ability's token. + * @return Returns ERR_OK on success, others on failure. + */ + ErrCode ScheduleCommandAbilityDone(const sptr &token); + + /** + * AddWindowInfo, add windowToken to AbilityRecord. + * + * @param token, the token of the ability. + * @param windowToken, window id of the ability. + */ + void AddWindowInfo(const sptr &token, int32_t windowToken); + + /** + * StartAbility with want, send want to ability manager service. + * + * @param want Ability want. + * @param requestCode Ability request code. + * @return Returns ERR_OK on success, others on failure. + */ + ErrCode StartAbility(const Want &want, int requestCode = DEFAULT_INVAL_VALUE); + + /** + * StartAbility with want, send want to ability manager service. + * + * @param want Ability want. + * @param callerToken, caller ability token. + * @param requestCode Ability request code. + * @return Returns ERR_OK on success, others on failure. + */ + ErrCode StartAbility( + const Want &want, const sptr &callerToken, int requestCode = DEFAULT_INVAL_VALUE); + + /** + * Starts a new ability with specific start settings. + * + * @param want Indicates the ability to start. + * @param requestCode the resultCode of the ability to start. + * @param abilityStartSetting Indicates the setting ability used to start. + * @return Returns ERR_OK on success, others on failure. + */ + ErrCode StartAbility(const Want &want, const AbilityStartSetting &abilityStartSetting, + const sptr &callerToken, int requestCode = DEFAULT_INVAL_VALUE); + + /** + * TerminateAbility with want, return want from ability manager service. + * + * @param token Ability token. + * @param resultCode resultCode. + * @param Want Ability want returned. + * @return Returns ERR_OK on success, others on failure. + */ + ErrCode TerminateAbility(const sptr &token, int resultCode, const Want *resultWant); + + /** + * TerminateAbility, terminate the special ability. + * + * @param callerToken, caller ability token. + * @param requestCode Ability request code. + * @return Returns ERR_OK on success, others on failure. + */ + ErrCode TerminateAbility(const sptr &callerToken, int requestCode); + + /** + * Destroys this Service ability if the number of times it + * has been started equals the number represented by + * the given startId. + * + * @param token ability's token. + * @param startId is incremented by 1 every time this ability is started. + * @return Returns true if the startId matches the number of startup times + * and this Service ability will be destroyed; returns false otherwise. + */ + ErrCode TerminateAbilityResult(const sptr &token, int startId); + /** + * ConnectAbility, connect session with service ability. + * + * @param want, Special want for service type's ability. + * @param connect, Callback used to notify caller the result of connecting or disconnecting. + * @param callerToken, caller ability token. + * @return Returns ERR_OK on success, others on failure. + */ + ErrCode ConnectAbility( + const Want &want, const sptr &connect, const sptr &callerToken); + + /** + * DisconnectAbility, disconnect session with service ability. + * + * @param connect, Callback used to notify caller the result of connecting or disconnecting. + * @return Returns ERR_OK on success, others on failure. + */ + ErrCode DisconnectAbility(const sptr &connect); + + /** + * AcquireDataAbility, acquire a data ability by its authority, if it not existed, + * AMS loads it synchronously. + * + * @param uri, data ability uri. + * @param tryBind, true: when a data ability is died, ams will kill this client, or do nothing. + * @param callerToken, specifies the caller ability token. + * @return returns the data ability ipc object, or nullptr for failed. + */ + sptr AcquireDataAbility(const Uri &uri, bool tryBind, const sptr &callerToken); + + /** + * ReleaseDataAbility, release the data ability that referenced by 'dataAbilityToken'. + * + * @param dataAbilityToken, specifies the data ability that will be released. + * @param callerToken, specifies the caller ability token. + * @return returns ERR_OK if succeeded, or error codes for failed. + */ + ErrCode ReleaseDataAbility(sptr dataAbilityScheduler, const sptr &callerToken); + + /** + * dump ability stack info, about userID, mission stack info, + * mission record info and ability info. + * + * @param state Ability stack info. + * @return Returns ERR_OK on success, others on failure. + */ + ErrCode DumpState(const std::string &args, std::vector &state); + + /** + * Connect ability manager service. + * + * @return Returns ERR_OK on success, others on failure. + */ + ErrCode Connect(); + + /** + * Get all stack info from ability manager service. + * + * @return Returns ERR_OK on success, others on failure. + */ + ErrCode GetAllStackInfo(StackInfo &stackInfo); + + /** + * Destroys this Service ability by Want. + * + * @param want, Special want for service type's ability. + * @return Returns true if this Service ability will be destroyed; returns false otherwise. + */ + ErrCode StopServiceAbility(const Want &want); + + /** + * Get the list of the missions that the user has recently launched, + * with the most recent being first and older ones after in order. + * + * @param recentList recent mission info + * @param numMax The maximum number of entries to return in the list. The + * actual number returned may be smaller, depending on how many tasks the + * user has started and the maximum number the system can remember. + * @param falgs Information about what to return. May be any combination + * of {@link #RECENT_WITH_EXCLUDED} and {@link #RECENT_IGNORE_UNAVAILABLE}. + * @return Returns ERR_OK on success, others on failure. + */ + ErrCode GetRecentMissions(const int32_t numMax, const int32_t flags, std::vector &recentList); + + /** + * Get mission snapshot by mission id + * + * @param missionId the id of the mission to retrieve the sAutoapshots + * @return Returns ERR_OK on success, others on failure. + */ + ErrCode GetMissionSnapshot(const int32_t missionId, MissionSnapshotInfo &snapshot); + + /** + * Ask that the mission associated with a given mission ID be moved to the + * front of the stack, so it is now visible to the user. + * + * @param missionId. + * @return Returns ERR_OK on success, others on failure. + */ + ErrCode MoveMissionToTop(int32_t missionId); + + /** + * Requires that tasks associated with a given capability token be moved to the background + * + * @param token ability token + * @param nonFirst If nonfirst is false and not the lowest ability of the mission, you cannot move mission to end + * @return Returns ERR_OK on success, others on failure. + */ + ErrCode MoveMissionToEnd(const sptr &token, const bool nonFirst); + + /** + * Remove the specified mission from the stack by missionid + * + * @param id. + * @return Returns ERR_OK on success, others on failure. + */ + ErrCode RemoveMissions(std::vector missionId); + + /** + * Remove the specified mission stack by stack id + * + * @param id. + * @return Returns ERR_OK on success, others on failure. + */ + ErrCode RemoveStack(int id); + + /** + * Kill the process immediately. + * + * @param bundleName. + * @return Returns ERR_OK on success, others on failure. + */ + ErrCode KillProcess(const std::string &bundleName); + + /** + * @brief Checks whether this ability is the first ability in a mission. + * + * @return Returns true is first in Mission. + */ + ErrCode IsFirstInMission(const sptr &token); + + ErrCode CompelVerifyPermission(const std::string &permission, int pid, int uid, std::string &message); + + /** + * Save the top ability States and move them to the background + * @return Returns ERR_OK on success, others on failure. + */ + ErrCode PowerOff(); + + /** + * Restore the state before top ability poweroff + * @return Returns ERR_OK on success, others on failure. + */ + ErrCode PowerOn(); + + /** + * Sets the application to start its ability in lock mission mode. + * @param missionId luck mission id + * @return Returns ERR_OK on success, others on failure. + */ + ErrCode LockMission(int missionId); + + /** + * Unlocks this ability by exiting the lock mission mode. + * @param missionId unluck mission id + * @return Returns ERR_OK on success, others on failure. + */ + ErrCode UnlockMission(int missionId); + + /** + * Sets description information about the mission containing this ability. + * + * @param description Indicates the object containing information about the + * mission. This parameter cannot be null. + * @return Returns ERR_OK on success, others on failure. + */ + ErrCode SetMissionDescriptionInfo( + const sptr &token, const MissionDescriptionInfo &description); + + /** + * get current system mission lock mode state. + * + * @return Returns 0: LOCK_MISSION_STATE_NONE, 1: LOCK_MISSION_STATE_LOCKED + */ + int GetMissionLockModeState(); + + int UpdateConfiguration(const DummyConfiguration &config); + + sptr GetWantSender(const WantSenderInfo &wantSenderInfo, const sptr &callerToken); + + ErrCode SendWantSender(const sptr &target, const SenderInfo &senderInfo); + + void CancelWantSender(const sptr &sender); + + ErrCode GetPendingWantUid(const sptr &target, int32_t &uid); + + ErrCode GetPendingWantUserId(const sptr &target, int32_t &userId); + + ErrCode GetPendingWantBundleName(const sptr &target, std::string &bundleName); + + ErrCode GetPendingWantCode(const sptr &target, int32_t &code); + + ErrCode GetPendingWantType(const sptr &target, int32_t &type); + + void RegisterCancelListener(const sptr &sender, const sptr &recevier); + + void UnregisterCancelListener(const sptr &sender, const sptr &recevier); + + ErrCode GetPendingRequestWant(const sptr &target, std::shared_ptr &want); + + /** + * Moving mission to the specified stack by mission option(Enter floating window mode). + * @param missionOption, target mission option + * @return Returns ERR_OK on success, others on failure. + */ + ErrCode MoveMissionToFloatingStack(const MissionOption &missionOption); + + /** + * Moving mission to the specified stack by mission option(Enter floating window mode). + * @param missionOption, target mission option + * @return Returns ERR_OK on success, others on failure. + */ + ErrCode MoveMissionToSplitScreenStack(const MissionOption &missionOption); + + /** + * minimize multiwindow by mission id. + * @param missionId, the id of target mission + * @return Returns ERR_OK on success, others on failure. + */ + ErrCode MinimizeMultiWindow(int missionId); + + /** + * maximize multiwindow by mission id. + * @param missionId, the id of target mission + * @return Returns ERR_OK on success, others on failure. + */ + ErrCode MaximizeMultiWindow(int missionId); + + /** + * Change the focus of ability in the mission stack. + * @param lostToken, the token of lost focus ability + * @param getToken, the token of get focus ability + * @return Returns ERR_OK on success, others on failure. + */ + ErrCode ChangeFocusAbility(const sptr &lostFocusToken, const sptr &getFocusToken); + + /** + * get missions info of floating mission stack. + * @param list, mission info. + * @return Returns ERR_OK on success, others on failure. + */ + ErrCode GetFloatingMissions(std::vector &list); + + /** + * close multiwindow by mission id. + * @param missionId, the id of target mission. + * @return Returns ERR_OK on success, others on failure. + */ + ErrCode CloseMultiWindow(int missionId); + + /** + * set special mission stack default settings. + * @param stackSetting, mission stack default settings. + * @return Returns ERR_OK on success, others on failure. + */ + ErrCode SetMissionStackSetting(const StackSetting &stackSetting); + +private: + static std::mutex mutex_; + static std::shared_ptr instance_; + sptr remoteObject_; +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_ABILITY_MANAGER_H diff --git a/tools/interfaces/innerkits/ability_manager/include/ability_manager_errors.h b/tools/interfaces/innerkits/ability_manager/include/ability_manager_errors.h new file mode 100644 index 00000000000..4133e2d9cc4 --- /dev/null +++ b/tools/interfaces/innerkits/ability_manager/include/ability_manager_errors.h @@ -0,0 +1,312 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_ABILITY_MANAGER_ERRORS_H +#define OHOS_AAFWK_ABILITY_MANAGER_ERRORS_H + +#include "errors.h" + +namespace OHOS { +namespace AAFwk { +enum { + /** + * Module type: Ability Manager Service side + */ + ABILITY_MODULE_TYPE_SERVICE = 0, + /** + * Module type: ABility Kit side + */ + ABILITY_MODULE_TYPE_KIT = 1 +}; + +// offset of aafwk error, only be used in this file. +constexpr ErrCode AAFWK_SERVICE_ERR_OFFSET = ErrCodeOffset(SUBSYS_AAFWK, ABILITY_MODULE_TYPE_SERVICE); + +enum { + /** + * Result(2097152) for StartAbility: An error of the Want could not be resolved + * to ability info from BMS or DistributedMS. + */ + RESOLVE_ABILITY_ERR = AAFWK_SERVICE_ERR_OFFSET, + /** + * Result(2097153) for Connect: An error of the get ability service. + */ + GET_ABILITY_SERVICE_FAILED, + /** + * Result(2097154) for Connect State: An error of the the ability service not connect. + */ + ABILITY_SERVICE_NOT_CONNECTED, + /** + * Result(2097155) for StartAbility: An error of the Want could not be resolved + * to app info from BMS or DistributedMS. + */ + RESOLVE_APP_ERR, + /** + * Result(2097156) for StartAbility: An error of getting ability stack manager object. + */ + STACK_MANAGER_NOT_EXIST, + /** + * Result(2097157) for StartAbility: The ability to start is already at the top. + */ + ABILITY_EXISTED, + /** + * Result(2097158) for StartAbility: An error to create mission stack. + */ + CREATE_MISSION_STACK_FAILED, + /** + * Result(2097159) for StartAbility: An error to create mission record. + */ + CREATE_MISSION_RECORD_FAILED, + /** + * Result(2097160) for StartAbility: An error to create ability record. + */ + CREATE_ABILITY_RECORD_FAILED, + /** + * Result(2097161) for StartAbility: The ability to start is waiting. + */ + START_ABILITY_WAITING, + /** + * Result(2097162) for TerminateAbility: Don't allow to terminate launcher. + */ + TERMINATE_LAUNCHER_DENIED, + /** + * Result(2097163) for DisconnectAbility: Connection not exist. + */ + CONNECTION_NOT_EXIST, + /** + * Result(2097164) for DisconnectAbility:Connection is invalid state. + */ + INVALID_CONNECTION_STATE, + /** + * Result(2097165) for LoadctAbility:LoadAbility timeout. + */ + LOAD_ABILITY_TIMEOUT, + /** + * Result(2097166) for DisconnectAbility:Connection timeout. + */ + CONNECTION_TIMEOUT, + /** + * Result(2097167) for start service: An error of the get BundleManagerService. + */ + GET_BUNDLE_MANAGER_SERVICE_FAILED, + /** + * Result(2097168) for Remove mission: target mission is not in default stack. + */ + REMOVE_MISSION_ID_NOT_EXIST, + /** + * Result(2097169) for Remove mission: Don't allow to remove mission which has launcher ability. + */ + REMOVE_MISSION_LAUNCHER_DENIED, + /** + * Result(2097170) for Remove mission: Don't allow to remove mission which has active ability. + */ + REMOVE_MISSION_ACTIVE_DENIED, + /** + * Result(2097171) for Remove mission: An error of removing mission. + */ + REMOVE_MISSION_FAILED, + /** + * Result(2097172) for All: An error occurs in server. + */ + INNER_ERR, + /** + * Result(2097173) for Get recent mission: get recent missions failed + */ + GET_RECENT_MISSIONS_FAILED, + /** + * Result(2097174) for Remove stack: Don't allow to remove stack which has launcher ability. + */ + REMOVE_STACK_LAUNCHER_DENIED, + /** + * Result(2097175) for Remove stack: An error of removing stack. + */ + REMOVE_STACK_FAILED, + /** + * Result(2097176) for Remove stack: mission stack is empty + */ + MISSION_STACK_LIST_IS_EMPTY, + /** + * Result(2097177) for Remove stack: target stack is not exist. + */ + REMOVE_STACK_ID_NOT_EXIST, + /** + * Result(2097178) for ConnectAbility:target ability is not service ability. + */ + TARGET_ABILITY_NOT_SERVICE, + /** + * Result(2097179) for TerminateAbility:target service has a record of connect. It cannot be stopped. + */ + TERMINATE_SERVICE_IS_CONNECTED, + /** + * Result(2097180) for StartAbility:The ability to start is already activing.. + */ + START_SERVICE_ABILITY_ACTIVING, + /** + * Result(2097181) for move mission to top: An error of moving stack. + */ + MOVE_MISSION_FAILED, + /** + * Result(2097182) for kill process: An error of kill process. + */ + KILL_PROCESS_FAILED, + /** + * Result(2097183) for uninstall app: An error of uninstall app. + */ + UNINSTALL_APP_FAILED, + /** + * Result(2097184) for terminate ability result: An error of terminate servce. + */ + TERMINATE_ABILITY_RESULT_FAILED, + /** + * Result(2097185) for check permission failed. + */ + CHECK_PERMISSION_FAILED, + /** + * Result(2097186) for waiting ability lifecycle complete. + */ + POWER_OFF_WAITING, + /** + * Result(2097187) for power off failed. + */ + POWER_OFF_FAILED, + /** + * Result(2097188) for power on failed. + */ + POWER_ON_FAILED, + /** + * Result(2097189) for ability no first in mission. + */ + NO_FIRST_IN_MISSION, + + /** + * Result(2097190) for lock mission errors. + */ + LOCK_MISSION_DENY_FAILED, + + /** + * Result(2097191) for unlock mission errors. + */ + UNLOCK_MISSION_DENY_FAILED, + + /** + * Result(2097192) for set mission info errors. + */ + SET_MISSION_INFO_FAILED, + + /** + * Result(2097193) for system is lock mission state. + */ + LOCK_MISSION_STATE_DENY_REQUEST, + + /** + * Result(2097194) for move mission to stack: out of size of moving mission. + */ + MOVE_MISSION_TO_STACK_OUT_OF_SIZE, + + /** + * Result(2097195) for move mission to stack: moving missions are not same window mode. + */ + MOVE_MISSION_TO_STACK_NOT_SAME_WIN_MODE, + + /** + * Result(2097196) for move mission to stack: moving mission is not exist. + */ + MOVE_MISSION_TO_STACK_NOT_EXIST_MISSION, + + /** + * Result(2097197) for move mission to stack: target mission or ability can't support multi window display. + */ + MOVE_MISSION_TO_STACK_NOT_SUPPORT_MULTI_WIN, + + /** + * Result(2097198) for move mission to stack: target mission stack size is overflow. + */ + MOVE_MISSION_TO_STACK_TARGET_STACK_OVERFLOW, + + /** + * Result(2097199) for move mission to stack: already in moving state, request is denied. + */ + MOVE_MISSION_TO_STACK_MOVING_DENIED, + + /** + * Result(2097200) for minimize multi window failed. + */ + MINIMIZE_MULTI_WINDOW_FAILED, + + /** + * Result(2097201) for maximize multiwindow: target mission is not exist in multiwindow stack. + */ + MAXIMIZE_MULTIWINDOW_NOT_EXIST, + + /** + * Result(2097202) for maximize multi window failed. + */ + MAXIMIZE_MULTIWINDOW_FAILED, + + /** + * Result(2097203) for change focus ability failed. + */ + CHANGE_FOCUS_ABILITY_FAILED, + + /** + * Result(2097204) for get floating stack failed + */ + GET_FLOATING_STACK_FAILED, + + /** + * Result(2097205) for close mutli window failed + */ + CLOSE_MULTI_WINDOW_FAILED, + + /** + * Result(2097202) for start ability by setting failed + */ + START_ABILITY_SETTING_FAILED, + + /** + * Result(2097206) for start ability by setting ,the ability not support multiwindow. + */ + START_ABILITY_SETTING_NOT_SUPPORT_MULTI_WIN, + + /** + * Result(2097207) for no found abilityrecord by caller + */ + NO_FOUND_ABILITY_BY_CALLER, + + /** + * Result(2097208) for ability visible attribute is false. + */ + ABILITY_VISIBLE_FALSE_DENY_REQUEST, + + /** + * Result(2097209) for caller is not systemapp. + */ + CALLER_ISNOT_SYSTEMAPP, +}; + +enum { + /** + * Flag for use with {@link #GetRecentMissions}: return all missions + */ + RECENT_WITH_EXCLUDED = 0x0001, + /** + * Provides a list that does not contain any + * recent missions that currently are not available to the user. + */ + RECENT_IGNORE_UNAVAILABLE = 0x0002, +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_ABILITY_MANAGER_ERRORS_H diff --git a/tools/interfaces/innerkits/ability_manager/include/ability_manager_interface.h b/tools/interfaces/innerkits/ability_manager/include/ability_manager_interface.h new file mode 100644 index 00000000000..bfe7045417f --- /dev/null +++ b/tools/interfaces/innerkits/ability_manager/include/ability_manager_interface.h @@ -0,0 +1,617 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_ABILITY_MANAGER_INTERFACE_H +#define OHOS_AAFWK_ABILITY_MANAGER_INTERFACE_H + +#include + +#include +#include + +#include "ability_connect_callback_interface.h" +#include "ability_scheduler_interface.h" +#include "ability_start_setting.h" +#include "mission_snapshot_info.h" +#include "ability_mission_info.h" +#include "mission_option.h" +#include "stack_info.h" +#include "stack_setting.h" +#include "uri.h" +#include "want.h" +#include "want_sender_info.h" +#include "sender_info.h" +#include "want_sender_interface.h" +#include "want_receiver_interface.h" +#include "aafwk_dummy_configuration.h" + +namespace OHOS { +namespace AAFwk { +const std::string ABILITY_MANAGER_SERVICE_NAME = "AbilityManagerService"; +const int DEFAULT_INVAL_VALUE = -1; +/** + * @class IAbilityManager + * IAbilityManager interface is used to access ability manager services. + */ +class IAbilityManager : public OHOS::IRemoteBroker { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"ohos.aafwk.AbilityManager") + + /** + * StartAbility with want, send want to ability manager service. + * + * @param want, the want of the ability to start. + * @param requestCode, Ability request code. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int StartAbility(const Want &want, int requestCode = DEFAULT_INVAL_VALUE) = 0; + + /** + * StartAbility with want, send want to ability manager service. + * + * @param want, the want of the ability to start. + * @param callerToken, caller ability token. + * @param requestCode, Ability request code. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int StartAbility( + const Want &want, const sptr &callerToken, int requestCode = DEFAULT_INVAL_VALUE) = 0; + + /** + * Starts a new ability with specific start settings. + * + * @param want Indicates the ability to start. + * @param requestCode the resultCode of the ability to start. + * @param abilityStartSetting Indicates the setting ability used to start. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int StartAbility(const Want &want, const AbilityStartSetting &abilityStartSetting, + const sptr &callerToken, int requestCode = DEFAULT_INVAL_VALUE) = 0; + + /** + * TerminateAbility, terminate the special ability. + * + * @param token, the token of the ability to terminate. + * @param resultCode, the resultCode of the ability to terminate. + * @param resultWant, the Want of the ability to return. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int TerminateAbility( + const sptr &token, int resultCode, const Want *resultWant = nullptr) = 0; + + /** + * TerminateAbility, terminate the special ability. + * + * @param callerToken, caller ability token. + * @param requestCode, Ability request code. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int TerminateAbilityByCaller(const sptr &callerToken, int requestCode) = 0; + + /** + * ConnectAbility, connect session with service ability. + * + * @param want, Special want for service type's ability. + * @param connect, Callback used to notify caller the result of connecting or disconnecting. + * @param callerToken, caller ability token. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int ConnectAbility( + const Want &want, const sptr &connect, const sptr &callerToken) = 0; + + /** + * DisconnectAbility, disconnect session with service ability. + * + * @param connect, Callback used to notify caller the result of connecting or disconnecting. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int DisconnectAbility(const sptr &connect) = 0; + + /** + * AcquireDataAbility, acquire a data ability by its authority, if it not existed, + * AMS loads it synchronously. + * + * @param authority, a string to identify a data ability, decoded from uri. + * @param tryBind, true: when a data ability is died, ams will kill this client, or do nothing. + * @param callerToken, specifies the caller ability token. + * @return returns the data ability ipc object, or nullptr for failed. + */ + virtual sptr AcquireDataAbility( + const Uri &uri, bool tryBind, const sptr &callerToken) = 0; + + /** + * ReleaseDataAbility, release the data ability that referenced by 'dataAbilityToken'. + * + * @param dataAbilityScheduler, specifies the data ability that will be released. + * @param callerToken, specifies the caller ability token. + * @return returns ERR_OK if succeeded, or error codes for failed. + */ + virtual int ReleaseDataAbility( + sptr dataAbilityScheduler, const sptr &callerToken) = 0; + + /** + * AddWindowInfo, add windowToken to AbilityRecord. + * + * @param token, the token of the ability. + * @param windowToken, window id of the ability. + */ + virtual void AddWindowInfo(const sptr &token, int32_t windowToken) = 0; + + /** + * AttachAbilityThread, ability call this interface after loaded. + * + * @param scheduler,.the interface handler of kit ability. + * @param token,.ability's token. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int AttachAbilityThread(const sptr &scheduler, const sptr &token) = 0; + + /** + * AbilityTransitionDone, ability call this interface after lift cycle was changed. + * + * @param token,.ability's token. + * @param state,.the state of ability lift cycle. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int AbilityTransitionDone(const sptr &token, int state) = 0; + + /** + * ScheduleConnectAbilityDone, service ability call this interface while session was connected. + * + * @param token,.service ability's token. + * @param remoteObject,.the session proxy of service ability. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int ScheduleConnectAbilityDone( + const sptr &token, const sptr &remoteObject) = 0; + + /** + * ScheduleDisconnectAbilityDone, service ability call this interface while session was disconnected. + * + * @param token,.service ability's token. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int ScheduleDisconnectAbilityDone(const sptr &token) = 0; + + /** + * ScheduleCommandAbilityDone, service ability call this interface while session was commanded. + * + * @param token,.service ability's token. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int ScheduleCommandAbilityDone(const sptr &token) = 0; + + /** + * dump ability stack info, about userID, mission stack info, + * mission record info and ability info. + * + * @param state Ability stack info. + * @return Returns ERR_OK on success, others on failure. + */ + virtual void DumpState(const std::string &args, std::vector &state) = 0; + + /** + * Destroys this Service ability if the number of times it + * has been started equals the number represented by + * the given startId. + * + * @param token ability's token. + * @param startId is incremented by 1 every time this ability is started. + * @return Returns true if the startId matches the number of startup times + * and this Service ability will be destroyed; returns false otherwise. + */ + virtual int TerminateAbilityResult(const sptr &token, int startId) = 0; + + /** + * Destroys this Service ability by Want. + * + * @param want, Special want for service type's ability. + * @return Returns true if this Service ability will be destroyed; returns false otherwise. + */ + virtual int StopServiceAbility(const Want &want) = 0; + + /** + * Obtains information about ability stack that are running on the device. + * + * @param stackInfo Ability stack info. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int GetAllStackInfo(StackInfo &stackInfo) = 0; + + /** + * Get the list of the missions that the user has recently launched, + * with the most recent being first and older ones after in order. + * + * @param recentList recent mission info + * @param numMax The maximum number of entries to return in the list. The + * actual number returned may be smaller, depending on how many tasks the + * user has started and the maximum number the system can remember. + * @param falgs Information about what to return. May be any combination + * of {@link #RECENT_WITH_EXCLUDED} and {@link #RECENT_IGNORE_UNAVAILABLE}. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int GetRecentMissions( + const int32_t numMax, const int32_t flags, std::vector &recentList) = 0; + + /** + * Get mission snapshot by mission id + * + * @param missionId the id of the mission to retrieve the sAutoapshots + * @return Returns ERR_OK on success, others on failure. + */ + virtual int GetMissionSnapshot(const int32_t missionId, MissionSnapshotInfo &snapshot) = 0; + + /** + * Ask that the mission associated with a given mission ID be moved to the + * front of the stack, so it is now visible to the user. + * + * @param missionId. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int MoveMissionToTop(int32_t missionId) = 0; + + /** + * Requires that tasks associated with a given capability token be moved to the background + * + * @param token ability token + * @param nonFirst If nonfirst is false and not the lowest ability of the mission, you cannot move mission to end + * @return Returns ERR_OK on success, others on failure. + */ + virtual int MoveMissionToEnd(const sptr &token, const bool nonFirst) = 0; + + /** + * Remove the specified mission from the stack by missionid + * + * @param id. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int RemoveMission(int id) = 0; + + /** + * Remove the specified mission stack by stack id + * + * @param id. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int RemoveStack(int id) = 0; + + /** + * Kill the process immediately. + * + * @param bundleName. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int KillProcess(const std::string &bundleName) = 0; + + /** + * Uninstall app + * + * @param bundleName. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int UninstallApp(const std::string &bundleName) = 0; + + /** + * Moving mission to the specified stack by mission option(Enter floating window mode). + * @param missionOption, target mission option + * @return Returns ERR_OK on success, others on failure. + */ + virtual int MoveMissionToFloatingStack(const MissionOption &missionOption) = 0; + + /** + * Moving mission to the specified stack by mission option(Enter floating window mode). + * @param missionOption, target mission option + * @return Returns ERR_OK on success, others on failure. + */ + virtual int MoveMissionToSplitScreenStack(const MissionOption &missionOption) = 0; + + /** + * Change the focus of ability in the mission stack. + * @param lostToken, the token of lost focus ability + * @param getToken, the token of get focus ability + * @return Returns ERR_OK on success, others on failure. + */ + virtual int ChangeFocusAbility( + const sptr &lostFocusToken, const sptr &getFocusToken) = 0; + + /** + * minimize multiwindow by mission id. + * @param missionId, the id of target mission + * @return Returns ERR_OK on success, others on failure. + */ + virtual int MinimizeMultiWindow(int missionId) = 0; + + /** + * maximize multiwindow by mission id. + * @param missionId, the id of target mission + * @return Returns ERR_OK on success, others on failure. + */ + virtual int MaximizeMultiWindow(int missionId) = 0; + + /** + * get missions info of floating mission stack. + * @param list, mission info. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int GetFloatingMissions(std::vector &list) = 0; + + /** + * close multiwindow by mission id. + * @param missionId, the id of target mission. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int CloseMultiWindow(int missionId) = 0; + + /** + * set special mission stack default settings. + * @param stackSetting, mission stack default settings. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int SetMissionStackSetting(const StackSetting &stackSetting) = 0; + + /** Checks whether this ability is the first ability in a mission. + * @param lostToken, the token of ability + * @return Returns true is first in Mission. + */ + virtual bool IsFirstInMission(const sptr &token) = 0; + + /** + * Checks whether a specified permission has been granted to the process identified by pid and uid + * + * @param permission Indicates the permission to check. + * @param pid Indicates the ID of the process to check. + * @param uid Indicates the UID of the process to check. + * @param message Describe success or failure + * + * @return Returns ERR_OK on success, others on failure. + */ + virtual int CompelVerifyPermission(const std::string &permission, int pid, int uid, std::string &message) = 0; + + /** + * Save the top ability States and move them to the background + * @return Returns ERR_OK on success, others on failure. + */ + virtual int PowerOff() = 0; + + /** + * Restore the state before top ability poweroff + * @return Returns ERR_OK on success, others on failure. + */ + virtual int PowerOn() = 0; + + /** + * Sets the application to start its ability in lock mission mode. + * @param missionId luck mission id + * @return Returns ERR_OK on success, others on failure. + */ + virtual int LockMission(int missionId) = 0; + + /** + * Unlocks this ability by exiting the lock mission mode. + * @param missionId unluck mission id + * @return Returns ERR_OK on success, others on failure. + */ + virtual int UnlockMission(int missionId) = 0; + + /** + * Sets description information about the mission containing this ability. + * + * @param description Indicates the object containing information about the + * mission. This parameter cannot be null. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int SetMissionDescriptionInfo( + const sptr &token, const MissionDescriptionInfo &description) = 0; + + /** + * get current system mission lock mode state. + * + * @return Returns 0: LOCK_MISSION_STATE_NONE, 1: LOCK_MISSION_STATE_LOCKED + */ + virtual int GetMissionLockModeState() = 0; + + /** + * Updates the configuration by modifying the configuration. + * + * @param config Indicates the new configuration + * @return Returns ERR_OK on success, others on failure. + */ + virtual int UpdateConfiguration(const DummyConfiguration &config) = 0; + + virtual sptr GetWantSender( + const WantSenderInfo &wantSenderInfo, const sptr &callerToken) = 0; + + virtual int SendWantSender(const sptr &target, const SenderInfo &senderInfo) = 0; + + virtual void CancelWantSender(const sptr &sender) = 0; + + virtual int GetPendingWantUid(const sptr &target) = 0; + + virtual int GetPendingWantUserId(const sptr &target) = 0; + + virtual std::string GetPendingWantBundleName(const sptr &target) = 0; + + virtual int GetPendingWantCode(const sptr &target) = 0; + + virtual int GetPendingWantType(const sptr &target) = 0; + + virtual void RegisterCancelListener(const sptr &sender, const sptr &receiver) = 0; + + virtual void UnregisterCancelListener(const sptr &sender, const sptr &receiver) = 0; + + virtual int GetPendingRequestWant(const sptr &target, std::shared_ptr &want) = 0; + + enum { + // ipc id 1-1000 for kit + // ipc id for terminating ability (1) + TERMINATE_ABILITY = 1, + + // ipc id for attaching ability thread (2) + ATTACH_ABILITY_THREAD, + + // ipc id for ability transition done (3) + ABILITY_TRANSITION_DONE, + + // ipc id for connecting ability done (4) + CONNECT_ABILITY_DONE, + + // ipc id for disconnecting ability done (5) + DISCONNECT_ABILITY_DONE, + + // ipc id for add window token (6) + ADD_WINDOW_INFO, + + // ipc id for terminating ability for result (7) + TERMINATE_ABILITY_RESULT, + + // ipc id for list stack info (8) + LIST_STACK_INFO, + + // ipc id for get recent mission (9) + GET_RECENT_MISSION, + + // ipc id for removing mission (10) + REMOVE_MISSION, + + // ipc id for removing mission (11) + REMOVE_STACK, + + // ipc id for removing mission (12) + COMMAND_ABILITY_DONE, + + // ipc id for get mission snapshot (13) + GET_MISSION_SNAPSHOT, + + // ipc id for acquire data ability (14) + ACQUIRE_DATA_ABILITY, + + // ipc id for release data ability (15) + RELEASE_DATA_ABILITY, + + // ipc id for move mission to top (16) + MOVE_MISSION_TO_TOP, + + // ipc id for kill process (17) + KILL_PROCESS, + + // ipc id for uninstall app (18) + UNINSTALL_APP, + + // ipc id for terminate ability by callerToken and request code (19) + TERMINATE_ABILITY_BY_CALLER, + + // ipc id for move mission to floating stack (20) + MOVE_MISSION_TO_FLOATING_STACK, + + // ipc id for move mission to floating stack (21) + MOVE_MISSION_TO_SPLITSCREEN_STACK, + + // ipc id for change focus ability (22) + CHANGE_FOCUS_ABILITY, + + // ipc id for Minimize MultiWindow (23) + MINIMIZE_MULTI_WINDOW, + + // ipc id for Maximize MultiWindow (24) + MAXIMIZE_MULTI_WINDOW, + + // ipc id for get floating missions (25) + GET_FLOATING_MISSIONS, + + // ipc id for get floating missions (26) + CLOSE_MULTI_WINDOW, + + // ipc id for set mission stack setting (27) + SET_STACK_SETTING, + + // ipc id for isfirstinmission app (28) + IS_FIRST_IN_MISSION, + + // ipc id for move mission to end (29) + MOVE_MISSION_TO_END, + + // ipc id for compel verify permission (30) + COMPEL_VERIFY_PERMISSION, + + // ipc id for power off (31) + POWER_OFF, + + // ipc id for power off (32) + POWER_ON, + + // ipc id for luck mission (33) + LUCK_MISSION, + + // ipc id for unluck mission (34) + UNLUCK_MISSION, + + // ipc id for set mission info (35) + SET_MISSION_INFO, + + // ipc id for get mission lock mode state (36) + GET_MISSION_LOCK_MODE_STATE, + + // ipc id for update configuration (37) + UPDATE_CONFIGURATION, + + // ipc id 1001-2000 for DMS + // ipc id for starting ability (1001) + START_ABILITY = 1001, + + // ipc id for connecting ability (1002) + CONNECT_ABILITY, + + // ipc id for disconnecting ability (1003) + DISCONNECT_ABILITY, + + // ipc id for disconnecting ability (1004) + STOP_SERVICE_ABILITY, + + // ipc id for starting ability by caller(1005) + START_ABILITY_ADD_CALLER, + + GET_PENDING_WANT_SENDER, + + SEND_PENDING_WANT_SENDER, + + CANCEL_PENDING_WANT_SENDER, + + GET_PENDING_WANT_UID, + + GET_PENDING_WANT_BUNDLENAME, + + GET_PENDING_WANT_USERID, + + GET_PENDING_WANT_TYPE, + + GET_PENDING_WANT_CODE, + + REGISTER_CANCEL_LISTENER, + + UNREGISTER_CANCEL_LISTENER, + + GET_PENDING_REQUEST_WANT, + + // ipc id for starting ability by settings(1006) + START_ABILITY_FOR_SETTINGS, + + // ipc id 2001-3000 for tools + // ipc id for dumping state (2001) + DUMP_STATE = 2001, + }; +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_ABILITY_MANAGER_INTERFACE_H diff --git a/tools/interfaces/innerkits/ability_manager/include/ability_mission_info.h b/tools/interfaces/innerkits/ability_manager/include/ability_mission_info.h new file mode 100644 index 00000000000..8958a551db0 --- /dev/null +++ b/tools/interfaces/innerkits/ability_manager/include/ability_mission_info.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_INTERFACES_INNERKITS_ABILITY_MISSION_INFO_H +#define OHOS_AAFWK_INTERFACES_INNERKITS_ABILITY_MISSION_INFO_H + +#include + +#include "ability_record_info.h" +#include "mission_description_info.h" +#include "parcel.h" +#include "want.h" + +namespace OHOS { +namespace AAFwk { +/** + * @struct AbilityMissionInfo + * AbilityMissionInfo is used to save informations about ability mission. + */ +struct AbilityMissionInfo : public Parcelable { + int32_t id = -1; + int32_t runingState = -1; + int32_t missionStackId = -1; + Want baseWant; + AppExecFwk::ElementName baseAbility; + AppExecFwk::ElementName topAbility; + int32_t size; + MissionDescriptionInfo missionDescription; + + bool ReadFromParcel(Parcel &parcel); + virtual bool Marshalling(Parcel &parcel) const override; + static AbilityMissionInfo *Unmarshalling(Parcel &parcel); +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_INTERFACES_INNERKITS_ABILITY_MISSION_INFO_H \ No newline at end of file diff --git a/tools/interfaces/innerkits/ability_manager/include/ability_record_info.h b/tools/interfaces/innerkits/ability_manager/include/ability_record_info.h new file mode 100644 index 00000000000..876ebd47c6b --- /dev/null +++ b/tools/interfaces/innerkits/ability_manager/include/ability_record_info.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_INTERFACES_INNERKITS_ABILITY_RECORD_INFO_H +#define OHOS_AAFWK_INTERFACES_INNERKITS_ABILITY_RECORD_INFO_H + +#include + +#include "parcel.h" + +namespace OHOS { +namespace AAFwk { +/** + * @enum AbilityState + * AbilityState defines the life cycle state of ability. + */ +enum AbilityState { + INITIAL = 0, + INACTIVE, + ACTIVE, + BACKGROUND, + SUSPENDED, + INACTIVATING, + ACTIVATING, + MOVING_BACKGROUND, + TERMINATING, +}; + +/** + * @struct AbilityRecordInfo + * AbilityRecordInfo is used to save informations about ability record. + */ +struct AbilityRecordInfo : public Parcelable { + int32_t id = -1; + std::string elementName; + std::string appName; + std::string mainName; + int32_t abilityType = 1; // Page=1,Service=2,Data=3 + std::string previousAppName; + std::string previousMainName; + std::string nextAppName; + std::string nextMainName; + AbilityState state = AbilityState::INITIAL; + std::string startTime; + bool ready = false; + bool windowAttached = false; + bool lanucher = false; + + bool ReadFromParcel(Parcel &parcel); + virtual bool Marshalling(Parcel &parcel) const override; + static AbilityRecordInfo *Unmarshalling(Parcel &parcel); +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_INTERFACES_INNERKITS_ABILITY_RECORD_INFO_H \ No newline at end of file diff --git a/tools/interfaces/innerkits/ability_manager/include/ability_scheduler_interface.h b/tools/interfaces/innerkits/ability_manager/include/ability_scheduler_interface.h new file mode 100644 index 00000000000..1f8b1e354f1 --- /dev/null +++ b/tools/interfaces/innerkits/ability_manager/include/ability_scheduler_interface.h @@ -0,0 +1,358 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_ABILITY_SCHEDULER_INTERFACE_H +#define OHOS_AAFWK_ABILITY_SCHEDULER_INTERFACE_H + +#include + + +#include "aafwk_dummy_configuration.h" +#include "lifecycle_state_info.h" +#include "pac_map.h" +#include "want.h" + +namespace OHOS { +namespace NativeRdb { +class AbsSharedResultSet; +class DataAbilityPredicates; +class ValuesBucket; +} +namespace AppExecFwk { +class DataAbilityResult; +class DataAbilityOperation; +} +namespace AAFwk { +using OHOS::AppExecFwk::PacMap; + +class IDataAbilityObserver; + +/** + * @class IAbilityScheduler + * IAbilityScheduler is used to schedule ability kit lifecycle. + */ +class IAbilityScheduler : public OHOS::IRemoteBroker { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"ohos.aafwk.AbilityScheduler"); + + /* + * ScheduleAbilityTransaction, schedule ability to transform life state. + * + * @param Want, Special Want for service type's ability. + * @param targetState, The lifecycle state to be transformed + */ + virtual void ScheduleAbilityTransaction(const Want &want, const LifeCycleStateInfo &targetState) = 0; + + /* + * SendResult, Send result to app when ability is terminated with result want. + * + * @param requestCode, the requestCode of the ability to start. + * @param resultCode, the resultCode of the ability to terminate. + * @param resultWant, the want of the ability to terminate. + */ + virtual void SendResult(int requestCode, int resultCode, const Want &resultWant) = 0; + + /* + * ScheduleConnectAbility, schedule service ability to connect. + * + * @param Want, Special Want for service type's ability. + */ + virtual void ScheduleConnectAbility(const Want &want) = 0; + + /* + * ScheduleDisconnectAbility, schedule service ability to disconnect. + */ + virtual void ScheduleDisconnectAbility(const Want &want) = 0; + + /* + * ScheduleCommandAbility, schedule service ability to command. + */ + virtual void ScheduleCommandAbility(const Want &want, bool restart, int startId) = 0; + + /* + * ScheduleSaveAbilityState, scheduling save ability state. + */ + virtual void ScheduleSaveAbilityState(PacMap &outState) = 0; + + /* + * ScheduleRestoreAbilityState, scheduling restore ability state. + */ + virtual void ScheduleRestoreAbilityState(const PacMap &inState) = 0; + + /* + * ScheduleUpdateConfiguration, scheduling update configuration. + */ + virtual void ScheduleUpdateConfiguration(const DummyConfiguration &config) = 0; + + /** + * @brief Obtains the MIME types of files supported. + * + * @param uri Indicates the path of the files to obtain. + * @param mimeTypeFilter Indicates the MIME types of the files to obtain. This parameter cannot be null. + * + * @return Returns the matched MIME types. If there is no match, null is returned. + */ + virtual std::vector GetFileTypes(const Uri &uri, const std::string &mimeTypeFilter) = 0; + + /** + * @brief Opens a file in a specified remote path. + * + * @param uri Indicates the path of the file to open. + * @param mode Indicates the file open mode, which can be "r" for read-only access, "w" for write-only access + * (erasing whatever data is currently in the file), "wt" for write access that truncates any existing file, + * "wa" for write-only access to append to any existing data, "rw" for read and write access on any existing data, + * or "rwt" for read and write access that truncates any existing file. + * + * @return Returns the file descriptor. + */ + virtual int OpenFile(const Uri &uri, const std::string &mode) = 0; + + /** + * @brief This is like openFile, open a file that need to be able to return sub-sections of files,often assets + * inside of their .hap. + * + * @param uri Indicates the path of the file to open. + * @param mode Indicates the file open mode, which can be "r" for read-only access, "w" for write-only access + * (erasing whatever data is currently in the file), "wt" for write access that truncates any existing file, + * "wa" for write-only access to append to any existing data, "rw" for read and write access on any existing + * data, or "rwt" for read and write access that truncates any existing file. + * + * @return Returns the RawFileDescriptor object containing file descriptor. + */ + virtual int OpenRawFile(const Uri &uri, const std::string &mode) = 0; + + /** + * @brief Inserts a single data record into the database. + * + * @param uri Indicates the path of the data to operate. + * @param value Indicates the data record to insert. If this parameter is null, a blank row will be inserted. + * + * @return Returns the index of the inserted data record. + */ + virtual int Insert(const Uri &uri, const NativeRdb::ValuesBucket &value) = 0; + + /** + * @brief Updates data records in the database. + * + * @param uri Indicates the path of data to update. + * @param value Indicates the data to update. This parameter can be null. + * @param predicates Indicates filter criteria. You should define the processing logic when this parameter is null. + * + * @return Returns the number of data records updated. + */ + virtual int Update(const Uri &uri, const NativeRdb::ValuesBucket &value, const NativeRdb::DataAbilityPredicates &predicates) = 0; + + /** + * @brief Deletes one or more data records from the database. + * + * @param uri Indicates the path of the data to operate. + * @param predicates Indicates filter criteria. You should define the processing logic when this parameter is null. + * + * @return Returns the number of data records deleted. + */ + virtual int Delete(const Uri &uri, const NativeRdb::DataAbilityPredicates &predicates) = 0; + + /** + * @brief Deletes one or more data records from the database. + * + * @param uri Indicates the path of data to query. + * @param columns Indicates the columns to query. If this parameter is null, all columns are queried. + * @param predicates Indicates filter criteria. You should define the processing logic when this parameter is null. + * + * @return Returns the query result. + */ + virtual std::shared_ptr Query( + const Uri &uri, std::vector &columns, const NativeRdb::DataAbilityPredicates &predicates) = 0; + + /** + * @brief Obtains the MIME type matching the data specified by the URI of the Data ability. This method should be + * implemented by a Data ability. Data abilities supports general data types, including text, HTML, and JPEG. + * + * @param uri Indicates the URI of the data. + * + * @return Returns the MIME type that matches the data specified by uri. + */ + virtual std::string GetType(const Uri &uri) = 0; + + /** + * @brief Reloads data in the database. + * + * @param uri Indicates the position where the data is to reload. This parameter is mandatory. + * @param extras Indicates the PacMap object containing the additional parameters to be passed in this call. This + * parameter can be null. If a custom Sequenceable object is put in the PacMap object and will be transferred across + * processes, you must call BasePacMap.setClassLoader(ClassLoader) to set a class loader for the custom object. + * + * @return Returns true if the data is successfully reloaded; returns false otherwise. + */ + virtual bool Reload(const Uri &uri, const PacMap &extras) = 0; + + /** + * @brief Inserts multiple data records into the database. + * + * @param uri Indicates the path of the data to operate. + * @param values Indicates the data records to insert. + * + * @return Returns the number of data records inserted. + */ + virtual int BatchInsert(const Uri &uri, const std::vector &values) = 0; + + /** + * @brief Registers an observer to DataObsMgr specified by the given Uri. + * + * @param uri, Indicates the path of the data to operate. + * @param dataObserver, Indicates the IDataAbilityObserver object. + * + * @return Return true if success. otherwise return false. + */ + virtual bool ScheduleRegisterObserver(const Uri &uri, const sptr &dataObserver) = 0; + + /** + * @brief Deregisters an observer used for DataObsMgr specified by the given Uri. + * + * @param uri, Indicates the path of the data to operate. + * @param dataObserver, Indicates the IDataAbilityObserver object. + * + * @return Return true if success. otherwise return false. + */ + virtual bool ScheduleUnregisterObserver(const Uri &uri, const sptr &dataObserver) = 0; + + virtual void NotifyMultiWinModeChanged(int32_t winModeKey, bool flag) = 0; + + + /** + * @brief notify this ability is top active ability. + * + * @param flag true: Indicates this ability is top active ability + */ + virtual void NotifyTopActiveAbilityChanged(bool flag) = 0; + + /** + * @brief Notifies the registered observers of a change to the data resource specified by Uri. + * + * @param uri, Indicates the path of the data to operate. + * + * @return Return true if success. otherwise return false. + */ + virtual bool ScheduleNotifyChange(const Uri &uri) = 0; + /** + * @brief Converts the given uri that refer to the Data ability into a normalized URI. A normalized URI can be used + * across devices, persisted, backed up, and restored. It can refer to the same item in the Data ability even if the + * context has changed. If you implement URI normalization for a Data ability, you must also implement + * denormalizeUri(ohos.utils.net.Uri) to enable URI denormalization. After this feature is enabled, URIs passed to + * any method that is called on the Data ability must require normalization verification and denormalization. The + * default implementation of this method returns null, indicating that this Data ability does not support URI + * normalization. + * + * @param uri Indicates the Uri object to normalize. + * + * @return Returns the normalized Uri object if the Data ability supports URI normalization; returns null otherwise. + */ + virtual Uri NormalizeUri(const Uri &uri) = 0; + + /** + * @brief Converts the given normalized uri generated by normalizeUri(ohos.utils.net.Uri) into a denormalized one. + * The default implementation of this method returns the original URI passed to it. + * + * @param uri uri Indicates the Uri object to denormalize. + * + * @return Returns the denormalized Uri object if the denormalization is successful; returns the original Uri passed + * to this method if there is nothing to do; returns null if the data identified by the original Uri cannot be found + * in the current environment. + */ + virtual Uri DenormalizeUri(const Uri &uri) = 0; + virtual std::vector> ExecuteBatch( + const std::vector> &operations) = 0; + enum { + // ipc id for scheduling ability to a state of life cycle + SCHEDULE_ABILITY_TRANSACTION = 0, + + // ipc id for sending result to caller + SEND_RESULT, + + // ipc id for scheduling service ability to connect + SCHEDULE_ABILITY_CONNECT, + + // ipc id for scheduling service ability to disconnect + SCHEDULE_ABILITY_DISCONNECT, + + // ipc id for scheduling service ability to command + SCHEDULE_ABILITY_COMMAND, + + // ipc id for scheduling save ability state + SCHEDULE_SAVE_ABILITY_STATE, + + // ipc id for scheduling restore ability state + SCHEDULE_RESTORE_ABILITY_STATE, + + // ipc id for scheduling getFileTypes + SCHEDULE_GETFILETYPES, + + // ipc id for scheduling openFile + SCHEDULE_OPENFILE, + + // ipc id for scheduling openRawFile + SCHEDULE_OPENRAWFILE, + + // ipc id for scheduling insert + SCHEDULE_INSERT, + + // ipc id for scheduling update + SCHEDULE_UPDATE, + + // ipc id for scheduling delete + SCHEDULE_DELETE, + + // ipc id for scheduling query + SCHEDULE_QUERY, + + // ipc id for scheduling getType + SCHEDULE_GETTYPE, + + // ipc id for scheduling Reload + SCHEDULE_RELOAD, + + // ipc id for scheduling BatchInsert​ + SCHEDULE_BATCHINSERT, + + // ipc id for dataAbilityObServer Reguster + SCHEDULE_REGISTEROBSERVER, + + // ipc id for dataAbilityObServer UnReguster + SCHEDULE_UNREGISTEROBSERVER, + + // ipc id for dataAbilityObServer change + SCHEDULE_NOTIFYCHANGE, + + // ipc id for scheduling multi window changed + MULTI_WIN_CHANGED, + + // ipc id for scheduling update configuration + SCHEDULE_UPDATE_CONFIGURATION, + + // ipc id for notify this ability is top active + TOP_ACTIVE_ABILITY_CHANGED, + // ipc id for scheduling NormalizeUri + SCHEDULE_NORMALIZEURI, + + // ipc id for scheduling DenormalizeUri + SCHEDULE_DENORMALIZEURI, + + // ipc id for scheduling ExecuteBatch + SCHEDULE_EXECUTEBATCH, + }; +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_ABILITY_SCHEDULER_INTERFACE_H diff --git a/tools/interfaces/innerkits/ability_manager/include/ability_start_setting.h b/tools/interfaces/innerkits/ability_manager/include/ability_start_setting.h new file mode 100644 index 00000000000..56ed2a09a71 --- /dev/null +++ b/tools/interfaces/innerkits/ability_manager/include/ability_start_setting.h @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_ABILITY_START_SETTING_H +#define OHOS_AAFWK_ABILITY_START_SETTING_H + +#include +#include +#include +#include +#include "parcel.h" + +namespace OHOS { +namespace AAFwk { + +class AbilityStartSetting final : public Parcelable, public std::enable_shared_from_this { +public: + static const std::string BOUNDS_KEY; + static const std::string WINDOW_DISPLAY_ID_KEY; + static const std::string WINDOW_MODE_KEY; + + /** + * @brief Construct copy function. + * @param other indicates instance of abilitystartsetting object + * @return none. + */ + AbilityStartSetting(const AbilityStartSetting &other); + /** + * @brief Overload assignment operation. + * @param other indicates instance of abilitystartsetting object. + * @return Returns current instance of abilitystartsetting object. + */ + AbilityStartSetting &operator=(const AbilityStartSetting &other); + + virtual ~AbilityStartSetting() = default; + + /** + * @brief Obtains the names of all the attributes that have been added to this AbilityStartSetting object. + * + * @return Returns the set of attribute names included in this AbilityStartSetting object. + */ + std::set GetPropertiesKey(); + + /** + * @brief Obtains the names of all the attributes that have been added to this AbilityStartSetting object. + * + * @return Returns the set of attribute names included in this AbilityStartSetting object. + */ + static std::shared_ptr GetEmptySetting(); + + /** + * @brief Checks whether this AbilityStartSetting object is empty. + * + * @return Returns true if this AbilityStartSetting object is empty and animatorOption is null; returns false + * otherwise. + */ + bool IsEmpty(); + /** + * @brief Sets the names of all the attributes of the AbilityStartSetting object. + * + * @param key Indicates the name of the key. + * @param value The window display mode of the values. + */ + void AddProperty(const std::string &key, const std::string &value); + + /** + * @brief Gets the name of the attributes of the AbilityStartSetting object. + * + * @param key Indicates the name of the key. + * @return Returns value Indicates the value of the attributes of the AbilityStartSetting object + */ + std::string GetProperty(const std::string &key); + + /* + * @brief Write the data of AbilityStartSetting to the file stream + * @param parcel indicates write the data of AbilityStartSetting to the file stream through parcel + * @return bool + */ + bool Marshalling(Parcel &parcel) const; + + /** + * @brief Reading file stream through parcel to generate AbilityStartSetting instance + * @param parcel indicates reading file stream through parcel to generate AbilityStartSetting instance + * @return AbilityStartSetting shared_ptr + */ + static AbilityStartSetting *Unmarshalling(Parcel &parcel); + +protected: + AbilityStartSetting() = default; + friend std::shared_ptr AbilityStartSettingCreator(); + +private: + std::map abilityStarKey_; +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_ABILITY_START_SETTING_H diff --git a/tools/interfaces/innerkits/ability_manager/include/ability_window_configuration.h b/tools/interfaces/innerkits/ability_manager/include/ability_window_configuration.h new file mode 100644 index 00000000000..9075e3ece44 --- /dev/null +++ b/tools/interfaces/innerkits/ability_manager/include/ability_window_configuration.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef OHOS_AAFWK_ABILITY_WINDOW_CONFIGURATION_H +#define OHOS_AAFWK_ABILITY_WINDOW_CONFIGURATION_H + +namespace OHOS { +namespace AAFwk { +enum AbilityWindowConfiguration { + /** + * Indicates that the Page ability is in an undefined window display mode. + */ + MULTI_WINDOW_DISPLAY_UNDEFINED = 0, + /** + * Indicates that the Page ability is in the fullscreen display mode. + */ + MULTI_WINDOW_DISPLAY_FULLSCREEN = 1, + /** + * Indicates that the Page ability is displayed in the primary window when it is in split-screen mode. + * The primary window, which triggers the split-screen mode, refers to the top window in the + * top/bottom split-screen mode or the left window in the left/right screen mode. + */ + MULTI_WINDOW_DISPLAY_PRIMARY = 100, + /** + * Indicates that the Page ability is displayed in the secondary window when it is in split-screen mode. + * The secondary window refers to the bottom window in the top/bottom split-screen mode or + * the right window in the left/right screen mode. + */ + MULTI_WINDOW_DISPLAY_SECONDARY = 101, + /** + * Indicates that the Page ability is in floating window display mode. + */ + MULTI_WINDOW_DISPLAY_FLOATING = 102 +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_ABILITY_WINDOW_CONFIGURATION_H \ No newline at end of file diff --git a/tools/interfaces/innerkits/ability_manager/include/caller_info.h b/tools/interfaces/innerkits/ability_manager/include/caller_info.h new file mode 100644 index 00000000000..f877b3c94a7 --- /dev/null +++ b/tools/interfaces/innerkits/ability_manager/include/caller_info.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_INTERFACES_INNERKITS_CALLER_INFO_H +#define OHOS_AAFWK_INTERFACES_INNERKITS_CALLER_INFO_H + +#include +#include "parcel.h" +#include "want.h" + +namespace OHOS { +namespace AAFwk { +/** + * @struct CallerInfo + * Defines caller ability record info. + */ +struct CallerInfo : public Parcelable { + int requestCode = -1; + std::string deviceId; + std::string bundleName; + std::string abilityName; + + bool ReadFromParcel(Parcel &parcel); + virtual bool Marshalling(Parcel &parcel) const override; + static CallerInfo *Unmarshalling(Parcel &parcel); +}; + +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_INTERFACES_INNERKITS_CALLER_INFO_H \ No newline at end of file diff --git a/tools/interfaces/innerkits/ability_manager/include/continuation/ability_distributed_connection_interface.h b/tools/interfaces/innerkits/ability_manager/include/continuation/ability_distributed_connection_interface.h new file mode 100644 index 00000000000..f5a17384fce --- /dev/null +++ b/tools/interfaces/innerkits/ability_manager/include/continuation/ability_distributed_connection_interface.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_ABILITY_DISTRIBUTE_CONNECT_CALLBACK_INTERFACE_H +#define OHOS_AAFWK_ABILITY_DISTRIBUTE_CONNECT_CALLBACK_INTERFACE_H + +#include "want.h" +#include "element_name.h" + +#include "iremote_broker.h" + +namespace OHOS { +namespace AAFwk { +/** + * @class IAbilityDistributedConnection + * IAbilityDistributedConnection is used to notify caller ability that connect or disconnect is complete. + */ +class IAbilityDistributedConnection : public OHOS::IRemoteBroker { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"ohos.abilityshell.DistributedConnection"); + + /** + * OnAbilityDistributeConnectDone, AbilityMs notify caller ability the result of connect. + * + * @param element, service ability's ElementName. + * @param remoteObject,.the session proxy of service ability. + * @param resultCode, ERR_OK on success, others on failure. + */ + virtual void OnAbilityConnectDone( + const AppExecFwk::ElementName &element, const sptr &remoteObject, int resultCode) = 0; + + /** + * OnAbilityDistributeDisconnectDone, AbilityMs notify caller ability the result of disconnect. + * + * @param element, service ability's ElementName. + * @param resultCode, ERR_OK on success, others on failure. + */ + virtual void OnAbilityDisconnectDone(const AppExecFwk::ElementName &element, int resultCode) = 0; + + enum { + // ipc id for OnAbilityDistributeConnectDone + ON_ABILITY_DISTRIBUTE_CONNECT_DONE = 0, + + // ipc id for OnAbilityDistributeDisConnectDone + ON_ABILITY_DISTRIBUTE_DISCONNECT_DONE + }; +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_ABILITY_CONNECT_CALLBACK_INTERFACE_H diff --git a/tools/interfaces/innerkits/ability_manager/include/continuation/connect_callback_interface.h b/tools/interfaces/innerkits/ability_manager/include/continuation/connect_callback_interface.h new file mode 100644 index 00000000000..9e6316a8b24 --- /dev/null +++ b/tools/interfaces/innerkits/ability_manager/include/continuation/connect_callback_interface.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef FOUNDATION_APPEXECFWK_OHOS_ICONNECT_CALLBACK_H +#define FOUNDATION_APPEXECFWK_OHOS_ICONNECT_CALLBACK_H +#include +#include "iremote_broker.h" + +using string = std::string; +namespace OHOS { +namespace AppExecFwk { +/** + * interface for device connect callback. + */ +class IConnectCallback : public IRemoteBroker { +public: + IConnectCallback() = default; + virtual ~IConnectCallback() = default; + DECLARE_INTERFACE_DESCRIPTOR(u"ohos.appexecfwk.iconnectcallback"); + /** + * @brief Connect device interface. + * @param deviceId indicates the device ID of the connection. + * @param deviceType indicates the device type of the connection. + * @return none. + */ + virtual void Connect(const string &deviceId, const string &deviceType) = 0; + /** + * @brief disconnect device interface. + * @param deviceId indicates the device ID of the disconnect. + * @param deviceType indicates the device type of the connectdisconnection. + * @return none. + */ + virtual void Disconnect(const string &deviceId) = 0; + + // connect status + enum { + COMMAND_CONNECT = 1, + COMMAND_DISCONNECT, + }; +}; + +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_APPEXECFWK_OHOS_ICONNECT_CALLBACK_H diff --git a/tools/interfaces/innerkits/ability_manager/include/continuation/remote_register_service_interface.h b/tools/interfaces/innerkits/ability_manager/include/continuation/remote_register_service_interface.h new file mode 100644 index 00000000000..68117321bbf --- /dev/null +++ b/tools/interfaces/innerkits/ability_manager/include/continuation/remote_register_service_interface.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_APPEXECFWK_OHOS_REMOTE_REGISTER_SERVICE_INTERFACE_H +#define FOUNDATION_APPEXECFWK_OHOS_REMOTE_REGISTER_SERVICE_INTERFACE_H + +#include +#include +#include "iremote_broker.h" +#include "extra_params.h" +#include "connect_callback_interface.h" + +namespace OHOS { +namespace AppExecFwk { +class IRemoteRegisterService : public IRemoteBroker { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"ohos.appexecfwk.RemoteRegisterService"); + + IRemoteRegisterService() = default; + virtual ~IRemoteRegisterService() = default; + + /** + * register to controlcenter continuation register service. + * + * @param bundleName bundlename of ability. + * @param extras filter with supported device list. + * @param callback callback for device connect and disconnect. + */ + virtual int Register(const std::string &bundleName, const sptr &token, const ExtraParams &extras, + const sptr &callback) = 0; + + /** + * unregister to controlcenter continuation register service. + * + * @param registerToken token from register return value. + */ + virtual bool Unregister(int registerToken) = 0; + + /** + * notify continuation status to controlcenter continuation register service. + * + * @param registerToken token from register. + * @param deviceId deviceid. + * @param status device status. + */ + virtual bool UpdateConnectStatus(int registerToken, const std::string &deviceId, int status) = 0; + + /** + * notify controlcenter continuation register service to show device list. + * + * @param registerToken token from register + * @param extras filter with supported device list. + */ + virtual bool ShowDeviceList(int registerToken, const ExtraParams &extras) = 0; + + enum { + // ipc id for register + COMMAND_REGISTER = 1, + COMMAND_UNREGISTER, + COMMAND_UPDATE_CONNECT_STATUS, + COMMAND_SHOW_DEVICE_LIST + }; +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_APPEXECFWK_OHOS_REMOTE_REGISTER_SERVICE_INTERFACE_H diff --git a/tools/interfaces/innerkits/ability_manager/include/image_info.h b/tools/interfaces/innerkits/ability_manager/include/image_info.h new file mode 100644 index 00000000000..508c2655d2f --- /dev/null +++ b/tools/interfaces/innerkits/ability_manager/include/image_info.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_INTERFACES_INNERKITS_IMAGE_INFO_H +#define OHOS_AAFWK_INTERFACES_INNERKITS_IMAGE_INFO_H + +#include + +#include "ability_record_info.h" +#include "mission_description_info.h" +#include "parcel.h" +#include "want.h" + +namespace OHOS { +namespace AAFwk { +/** + * @struct ImageInfo + * Defines image header information. + */ +struct ImageHeader : public Parcelable { + /** + * Color format, which is used to match image type. This variable is important. + */ + uint32_t colorMode = 8; + + uint32_t reserved = 24; + + uint16_t width; + + uint16_t height; + + bool ReadFromParcel(Parcel &parcel); + virtual bool Marshalling(Parcel &parcel) const override; + static ImageHeader *Unmarshalling(Parcel &parcel); +}; + +/** + * @struct ImageInfo + * Defines image information. + */ +struct ImageInfo : public Parcelable { + ImageHeader header; + + /** + * Size of the image data (in bytes) + */ + uint32_t dataSize; + + uint8_t *data; + + uint32_t userDataSize; + /** + * User-defined data + */ + void *userData; + + bool ReadFromParcel(Parcel &parcel); + virtual bool Marshalling(Parcel &parcel) const override; + static ImageInfo *Unmarshalling(Parcel &parcel); +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_INTERFACES_INNERKITS_IMAGE_INFO_H \ No newline at end of file diff --git a/tools/interfaces/innerkits/ability_manager/include/lifecycle_state_info.h b/tools/interfaces/innerkits/ability_manager/include/lifecycle_state_info.h new file mode 100644 index 00000000000..858410bf59a --- /dev/null +++ b/tools/interfaces/innerkits/ability_manager/include/lifecycle_state_info.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_INTERFACES_INNERKITS_LIFECYCLE_STATE_INFO_H +#define OHOS_AAFWK_INTERFACES_INNERKITS_LIFECYCLE_STATE_INFO_H + +#include + +#include "parcel.h" +#include "ability_start_setting.h" +#include "caller_info.h" + +namespace OHOS { +namespace AAFwk { +/** + * @enum AbilityLifeCycleState + * AbilityLifeCycleState defines the life cycle state of ability. + */ +enum AbilityLifeCycleState { + ABILITY_STATE_INITIAL = 0, + ABILITY_STATE_INACTIVE, + ABILITY_STATE_ACTIVE, + ABILITY_STATE_BACKGROUND, + ABILITY_STATE_SUSPENDED +}; + +/** + * @struct LifeCycleStateInfo + * LifeCycleStateInfo is used to save informations about ability life cycle state. + */ +struct LifeCycleStateInfo : public Parcelable { + AbilityLifeCycleState state = AbilityLifeCycleState::ABILITY_STATE_INITIAL; + bool isNewWant = false; + int missionId = -1; + int stackId = -1; + CallerInfo caller; + std::shared_ptr setting = nullptr; + + bool ReadFromParcel(Parcel &parcel); + virtual bool Marshalling(Parcel &parcel) const override; + static LifeCycleStateInfo *Unmarshalling(Parcel &parcel); +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_INTERFACES_INNERKITS_LIFECYCLE_STATE_INFO_H \ No newline at end of file diff --git a/tools/interfaces/innerkits/ability_manager/include/mission_description_info.h b/tools/interfaces/innerkits/ability_manager/include/mission_description_info.h new file mode 100644 index 00000000000..c127e139365 --- /dev/null +++ b/tools/interfaces/innerkits/ability_manager/include/mission_description_info.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_INTERFACES_INNERKITS_MISSION_DESCRIPTION_INFO_H +#define OHOS_AAFWK_INTERFACES_INNERKITS_MISSION_DESCRIPTION_INFO_H + +#include + +#include "parcel.h" + +namespace OHOS { +namespace AAFwk { +/** + * @struct MissionDescriptionInfo + * MissionDescriptionInfo is used to save informations about mission description. + */ +struct MissionDescriptionInfo : public Parcelable { + std::string label; + std::string iconPath; + + bool ReadFromParcel(Parcel &parcel); + virtual bool Marshalling(Parcel &parcel) const override; + static MissionDescriptionInfo *Unmarshalling(Parcel &parcel); +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_INTERFACES_INNERKITS_MISSION_DESCRIPTION_INFO_H \ No newline at end of file diff --git a/tools/interfaces/innerkits/ability_manager/include/mission_option.h b/tools/interfaces/innerkits/ability_manager/include/mission_option.h new file mode 100644 index 00000000000..ca294b28197 --- /dev/null +++ b/tools/interfaces/innerkits/ability_manager/include/mission_option.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_MISSION_OPTION_H +#define OHOS_AAFWK_MISSION_OPTION_H + +#include "ability_window_configuration.h" +#include "parcel.h" + +#include + +namespace OHOS { +namespace AAFwk { +const int32_t DISPLAY_DEFAULT_ID = 0; +const int32_t MISSION_INVAL_VALUE = -1; +const int32_t DEFAULT_USER_ID = 0; +/** + * @class MissionOption + * MissionOption contains option information for mission which one needs to be moved. + */ +class MissionOption final : public Parcelable { +public: + MissionOption() = default; + virtual ~MissionOption() = default; + + bool IsSameWindowMode(const AbilityWindowConfiguration &key) const; + bool ReadFromParcel(Parcel &parcel); + virtual bool Marshalling(Parcel &parcel) const override; + static MissionOption *Unmarshalling(Parcel &parcel); + + int32_t userId = DEFAULT_USER_ID; // stack 's user id ,default value is 0 + int32_t missionId = MISSION_INVAL_VALUE; // mission record id + // multi window mode key , default in an undefined + AbilityWindowConfiguration winModeKey = AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_UNDEFINED; + int32_t displayKey = DISPLAY_DEFAULT_ID; // display screen device id + + void AddProperty(const std::string &key, const std::string &value); + void GetProperty(const std::string &key, std::string &value); + +private: + std::map properties_; +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_MISSION_OPTION_H \ No newline at end of file diff --git a/tools/interfaces/innerkits/ability_manager/include/mission_record_info.h b/tools/interfaces/innerkits/ability_manager/include/mission_record_info.h new file mode 100644 index 00000000000..c2905527220 --- /dev/null +++ b/tools/interfaces/innerkits/ability_manager/include/mission_record_info.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_INTERFACES_INNERKITS_MISSION_RECORD_INFO_H +#define OHOS_AAFWK_INTERFACES_INNERKITS_MISSION_RECORD_INFO_H + +#include + +#include "ability_record_info.h" +#include "parcel.h" + +namespace OHOS { +namespace AAFwk { +/** + * @struct MissionRecordInfo + * MissionRecordInfo is used to save informations about mission record. + */ +struct MissionRecordInfo : public Parcelable { + int32_t id = -1; + std::vector abilityRecordInfos; + + bool ReadFromParcel(Parcel &parcel); + virtual bool Marshalling(Parcel &parcel) const override; + static MissionRecordInfo *Unmarshalling(Parcel &parcel); +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_INTERFACES_INNERKITS_MISSION_RECORD_INFO_H \ No newline at end of file diff --git a/tools/interfaces/innerkits/ability_manager/include/mission_snapshot_info.h b/tools/interfaces/innerkits/ability_manager/include/mission_snapshot_info.h new file mode 100644 index 00000000000..63dd9ee0849 --- /dev/null +++ b/tools/interfaces/innerkits/ability_manager/include/mission_snapshot_info.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_INTERFACES_INNERKITS_MISSION_SNAPSHOT_INFO_H +#define OHOS_AAFWK_INTERFACES_INNERKITS_MISSION_SNAPSHOT_INFO_H + +#include + +#include "image_info.h" +#include "parcel.h" + +namespace OHOS { +namespace AAFwk { +/** + * @struct MissionSnapshotInfo + * MissionSnapshotInfo is used to save informations about mission sanpshot. + */ +struct MissionSnapshotInfo : public Parcelable { + ImageInfo snapshot; + + bool ReadFromParcel(Parcel &parcel); + virtual bool Marshalling(Parcel &parcel) const override; + static MissionSnapshotInfo *Unmarshalling(Parcel &parcel); +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_INTERFACES_INNERKITS_MISSION_SNAPSHOT_INFO_H \ No newline at end of file diff --git a/tools/interfaces/innerkits/ability_manager/include/mission_stack_info.h b/tools/interfaces/innerkits/ability_manager/include/mission_stack_info.h new file mode 100644 index 00000000000..cbc902c103f --- /dev/null +++ b/tools/interfaces/innerkits/ability_manager/include/mission_stack_info.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_INTERFACES_INNERKITS_MISSION_STACK_INFO_H +#define OHOS_AAFWK_INTERFACES_INNERKITS_MISSION_STACK_INFO_H + +#include + +#include "mission_record_info.h" +#include "parcel.h" + +namespace OHOS { +namespace AAFwk { +/** + * @struct MissionStackInfo + * MissionStackInfo is used to save informations about mission stack. + */ +struct MissionStackInfo : public Parcelable { + int32_t id = -1; + std::vector missionRecords; + + bool ReadFromParcel(Parcel &parcel); + virtual bool Marshalling(Parcel &parcel) const override; + static MissionStackInfo *Unmarshalling(Parcel &parcel); +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_INTERFACES_INNERKITS_MISSION_STACK_INFO_H \ No newline at end of file diff --git a/tools/interfaces/innerkits/ability_manager/include/sender_info.h b/tools/interfaces/innerkits/ability_manager/include/sender_info.h new file mode 100644 index 00000000000..edbf7445c2f --- /dev/null +++ b/tools/interfaces/innerkits/ability_manager/include/sender_info.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_INTERFACES_SENDER_INFO_H +#define OHOS_AAFWK_INTERFACES_SENDER_INFO_H + +#include + +#include "parcel.h" + +#include "want.h" + +#include "want_receiver_interface.h" + +namespace OHOS { +namespace AAFwk { +struct SenderInfo : public Parcelable { + int32_t code; + Want want; + std::string resolvedType; + sptr finishedReceiver; + std::string requiredPermission; + + bool ReadFromParcel(Parcel &parcel); + virtual bool Marshalling(Parcel &parcel) const override; + static SenderInfo *Unmarshalling(Parcel &parcel); +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_INTERFACES_SENDER_INFO_H \ No newline at end of file diff --git a/tools/interfaces/innerkits/ability_manager/include/stack_info.h b/tools/interfaces/innerkits/ability_manager/include/stack_info.h new file mode 100644 index 00000000000..03e4fbff1f9 --- /dev/null +++ b/tools/interfaces/innerkits/ability_manager/include/stack_info.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_INTERFACES_INNERKITS_STACK_INFO_H +#define OHOS_AAFWK_INTERFACES_INNERKITS_STACK_INFO_H + +#include + +#include "parcel.h" +#include "mission_stack_info.h" + +namespace OHOS { +namespace AAFwk { +/** + * @struct StackInfo + * StackInfo is used to save informations about stack. + */ +struct StackInfo : public Parcelable { + + std::vector missionStackInfos; + + bool ReadFromParcel(Parcel &parcel); + virtual bool Marshalling(Parcel &parcel) const override; + static StackInfo *Unmarshalling(Parcel &parcel); +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_INTERFACES_INNERKITS_STACK_INFO_H \ No newline at end of file diff --git a/tools/interfaces/innerkits/ability_manager/include/stack_setting.h b/tools/interfaces/innerkits/ability_manager/include/stack_setting.h new file mode 100644 index 00000000000..4e7da3f1592 --- /dev/null +++ b/tools/interfaces/innerkits/ability_manager/include/stack_setting.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_STACK_SETTING_H +#define OHOS_AAFWK_STACK_SETTING_H + +#include "ability_window_configuration.h" +#include "parcel.h" + +#include + +namespace OHOS { +namespace AAFwk { +enum STACK_ID { + LAUNCHER_MISSION_STACK_ID = 0, + DEFAULT_MISSION_STACK_ID, + SPLIT_SCREEN_MISSION_STACK_ID, + FLOATING_MISSION_STACK_ID +}; +/** + * @struct StackSetting + * StackSetting contains default setting for mission stack. + */ +struct StackSetting final : public Parcelable { + + int32_t userId = 0; // stack 's user id ,default value is 0 + // multi window mode key , default in an undefined + STACK_ID stackId = DEFAULT_MISSION_STACK_ID; + int32_t maxHoldMission = -1; // default unlimited. + bool isSyncVisual = false; // default don'r support synchronous visualization when multiwindow + + bool ReadFromParcel(Parcel &parcel); + virtual bool Marshalling(Parcel &parcel) const override; + static StackSetting *Unmarshalling(Parcel &parcel); +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_STACK_SETTING_H \ No newline at end of file diff --git a/tools/interfaces/innerkits/ability_manager/include/task_handler.h b/tools/interfaces/innerkits/ability_manager/include/task_handler.h new file mode 100644 index 00000000000..8749ae38db7 --- /dev/null +++ b/tools/interfaces/innerkits/ability_manager/include/task_handler.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_APPEXECFWK_TASK_HANDLER_H +#define FOUNDATION_APPEXECFWK_TASK_HANDLER_H + +#include "event_handler.h" +#include "task_handler_client.h" +#include "refbase.h" + +namespace OHOS { +namespace AppExecFwk { +class TaskHandler : public EventHandler { +public: + TaskHandler(const std::shared_ptr &runner); + ~TaskHandler() + {} + + /** + * Process the event. Developers should override this method. + * + * @param event The event should be processed. + */ + void ProcessEvent(const InnerEvent::Pointer &event) override; +}; + +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_APPEXECFWK_TASK_HANDLER_H diff --git a/tools/interfaces/innerkits/ability_manager/include/task_handler_client.h b/tools/interfaces/innerkits/ability_manager/include/task_handler_client.h new file mode 100644 index 00000000000..11b7ef37155 --- /dev/null +++ b/tools/interfaces/innerkits/ability_manager/include/task_handler_client.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_TASK_HANDLER_CLIENT_H +#define OHOS_AAFWK_TASK_HANDLER_CLIENT_H + +#include +#include "task_handler.h" + +namespace OHOS { +namespace AppExecFwk { +/** + * @class TaskHandlerClient + * TaskHandlerClient is used to access TaskHandler. + */ +class TaskHandler; +class TaskHandlerClient { +public: + TaskHandlerClient(); + virtual ~TaskHandlerClient(); + static std::shared_ptr GetInstance(); + bool PostTask(std::function task, long delayTime); + bool CreateRunner(); + +private: + static std::mutex mutex_; + static std::shared_ptr instance_; + std::shared_ptr taskHandler_; +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif // OHOS_AAFWK_TASK_HANDLER_CLIENT_H diff --git a/tools/interfaces/innerkits/ability_manager/include/want_receiver_interface.h b/tools/interfaces/innerkits/ability_manager/include/want_receiver_interface.h new file mode 100644 index 00000000000..8d0c5f2023f --- /dev/null +++ b/tools/interfaces/innerkits/ability_manager/include/want_receiver_interface.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_WANT_RECEIVER_INTERFACE_H +#define OHOS_AAFWK_WANT_RECEIVER_INTERFACE_H + +#include +#include "want.h" +#include "want_params.h" + +namespace OHOS { +namespace AAFwk { +class IWantReceiver : public OHOS::IRemoteBroker { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"ohos.aafwk.WantReceiver"); + virtual void Send(const int32_t resultCode) = 0; + virtual void PerformReceive(const Want &want, int resultCode, const std::string &data, const WantParams &extras, + bool serialized, bool sticky, int sendingUser) = 0; + enum { + WANT_RECEIVER_SEND = 0, + WANT_RECEIVER_PERFORM_RECEIVE, + }; +}; +} // namespace AAFwk +} // namespace OHOS + +#endif // OHOS_AAFWK_WANT_RECEIVER_INTERFACE_H \ No newline at end of file diff --git a/tools/interfaces/innerkits/ability_manager/include/want_sender_info.h b/tools/interfaces/innerkits/ability_manager/include/want_sender_info.h new file mode 100644 index 00000000000..55ffdc875e3 --- /dev/null +++ b/tools/interfaces/innerkits/ability_manager/include/want_sender_info.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_INTERFACES_INNERKITS_WANT_SENDER_INFO_H +#define OHOS_AAFWK_INTERFACES_INNERKITS_WANT_SENDER_INFO_H + +#include +#include + +#include "parcel.h" + +#include "wants_info.h" + +namespace OHOS { +namespace AAFwk { + +struct WantSenderInfo : public Parcelable { + int32_t type; + std::string bundleName; + std::string resultWho; + int32_t requestCode; + std::vector allWants; + uint32_t flags; + int32_t userId; + + bool ReadFromParcel(Parcel &parcel); + virtual bool Marshalling(Parcel &parcel) const override; + static WantSenderInfo *Unmarshalling(Parcel &parcel); +}; +} // namespace AAFwk +} // namespace OHOS + +#endif // OHOS_AAFWK_INTERFACES_INNERKITS_WANT_SENDER_INFO_H \ No newline at end of file diff --git a/tools/interfaces/innerkits/ability_manager/include/want_sender_interface.h b/tools/interfaces/innerkits/ability_manager/include/want_sender_interface.h new file mode 100644 index 00000000000..d20961608d2 --- /dev/null +++ b/tools/interfaces/innerkits/ability_manager/include/want_sender_interface.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_WANT_SENDER_INTERFACE_H +#define OHOS_AAFWK_WANT_SENDER_INTERFACE_H + +#include + +#include "want.h" +#include "sender_info.h" + +namespace OHOS { +namespace AAFwk { +class IWantSender : public OHOS::IRemoteBroker { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"ohos.aafwk.WantSender"); + virtual void Send(SenderInfo &senderInfo) = 0; + enum { + WANT_SENDER_SEND = 0, + }; +}; +} // namespace AAFwk +} // namespace OHOS + +#endif // OHOS_AAFWK_WANT_SENDER_INTERFACE_H \ No newline at end of file diff --git a/tools/interfaces/innerkits/ability_manager/include/wants_info.h b/tools/interfaces/innerkits/ability_manager/include/wants_info.h new file mode 100644 index 00000000000..15c03fd033e --- /dev/null +++ b/tools/interfaces/innerkits/ability_manager/include/wants_info.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_INTERFACES_INNERKITS_WANTS_INFO_H +#define OHOS_AAFWK_INTERFACES_INNERKITS_WANTS_INFO_H + +#include +#include "parcel.h" + +#include "want.h" + +namespace OHOS { +namespace AAFwk { + +struct WantsInfo : public Parcelable { + Want want; + std::string resolvedTypes; + + bool ReadFromParcel(Parcel &parcel); + virtual bool Marshalling(Parcel &parcel) const override; + static WantsInfo *Unmarshalling(Parcel &parcel); +}; + +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_INTERFACES_INNERKITS_WANTS_INFO_H \ No newline at end of file diff --git a/tools/interfaces/innerkits/base/BUILD.gn b/tools/interfaces/innerkits/base/BUILD.gn new file mode 100755 index 00000000000..071b0770b7a --- /dev/null +++ b/tools/interfaces/innerkits/base/BUILD.gn @@ -0,0 +1,60 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") + +config("base_config") { + visibility = [ ":*" ] + include_dirs = [ "//utils/native/base/include" ] +} + +config("base_public_config") { + visibility = [ ":*" ] + include_dirs = [ + "//foundation/aafwk/standard/interfaces/innerkits/base/include", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base/include", + "//foundation/appexecfwk/standard/common/log/include", + "//third_party/jsoncpp/include", + "//utils/native/base/include", + ] +} + +baseImpl = + "//foundation/aafwk/standard/frameworks/kits/base/cpp/src/ohos/aafwk/base" + +ohos_shared_library("base") { + sources = [ + "${baseImpl}/array_wrapper.cpp", + "${baseImpl}/base.cpp", + "${baseImpl}/base_object.cpp", + "${baseImpl}/bool_wrapper.cpp", + "${baseImpl}/byte_wrapper.cpp", + "${baseImpl}/double_wrapper.cpp", + "${baseImpl}/float_wrapper.cpp", + "${baseImpl}/int_wrapper.cpp", + "${baseImpl}/long_wrapper.cpp", + "${baseImpl}/short_wrapper.cpp", + "${baseImpl}/string_wrapper.cpp", + "${baseImpl}/user_object_wrapper.cpp", + "${baseImpl}/zchar_wrapper.cpp", + ] + configs = [ ":base_config" ] + public_configs = [ ":base_public_config" ] + deps = [ + "//third_party/jsoncpp:jsoncpp", + "//utils/native/base:utils", + ] + + subsystem_name = "aafwk" + part_name = "aafwk_standard" +} diff --git a/tools/interfaces/innerkits/base/include/ohos/aafwk/base/array_wrapper.h b/tools/interfaces/innerkits/base/include/ohos/aafwk/base/array_wrapper.h new file mode 100644 index 00000000000..e392ac04ffe --- /dev/null +++ b/tools/interfaces/innerkits/base/include/ohos/aafwk/base/array_wrapper.h @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_ARRAY_H +#define OHOS_AAFWK_ARRAY_H + +#include +#include + +#include "ohos/aafwk/base/base_object.h" + +namespace OHOS { +namespace AAFwk { +class Array : public Object, public IArray { +public: + Array(long size, const InterfaceID &id); + + inline ~Array() + {} + + IINTERFACE_DECL(); + + ErrCode Get(long index, /* [in] */ + sptr &value) override; /* [out] */ + + ErrCode GetLength(long &size) override; /* [out] */ + + ErrCode GetType(InterfaceID &id) override; /* [out] */ + + ErrCode Set(long index, /* [in] */ + IInterface *value) override; /* [in] */ + + bool Equals(IObject &other) override; /* [in] */ + + std::string ToString() override; + + static sptr Parse(const std::string &arrayStr); /* [in] */ + + static bool IsBooleanArray(IArray *array); /* [in] */ + + static bool IsCharArray(IArray *array); /* [in] */ + + static bool IsByteArray(IArray *array); /* [in] */ + + static bool IsShortArray(IArray *array); /* [in] */ + + static bool IsIntegerArray(IArray *array); /* [in] */ + + static bool IsLongArray(IArray *array); /* [in] */ + + static bool IsFloatArray(IArray *array); /* [in] */ + + static bool IsDoubleArray(IArray *array); /* [in] */ + + static bool IsStringArray(IArray *array); /* [in] */ + + static void ForEach(IArray *array, /* [in] */ + std::function func); /* [in] */ + + static constexpr char SIGNATURE = '['; + +private: + static void ParseElement(IArray *array, /* [in] */ + std::function(std::string &)> func, /* [in] */ + const std::string &values, /* [in] */ + long size); /* [in] */ + + std::vector> values_; + const long size_; + InterfaceID typeId_; + + static sptr ParseString(const std::string &values, long size); + static sptr ParseBoolean(const std::string &values, long size); + static sptr ParseByte(const std::string &values, long size); + static sptr ParseShort(const std::string &values, long size); + static sptr ParseInteger(const std::string &values, long size); + static sptr ParseLong(const std::string &values, long size); + static sptr ParseFloat(const std::string &values, long size); + static sptr ParseDouble(const std::string &values, long size); + static sptr ParseChar(const std::string &values, long size); + static sptr ParseArray(const std::string &values, long size); +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_DOUBLE_H diff --git a/tools/interfaces/innerkits/base/include/ohos/aafwk/base/base_def.h b/tools/interfaces/innerkits/base/include/ohos/aafwk/base/base_def.h new file mode 100644 index 00000000000..8b2d353c827 --- /dev/null +++ b/tools/interfaces/innerkits/base/include/ohos/aafwk/base/base_def.h @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef OHOS_AAFWK_BASE_DEF_H +#define OHOS_AAFWK_BASE_DEF_H + +#include "base_types.h" +#include "errors.h" + +namespace OHOS { +namespace AAFwk { +#define INTERFACE_INNER struct + +#define REFCOUNT_ADD(i) \ + if (i) { \ + (i)->IncStrongRef(); \ + } + +#define REFCOUNT_RELEASE(i) \ + if (i) { \ + (i)->DecStrongRef(); \ + } + +#define VALIDATE_NOT_NULL(i) \ + if ((i) == nullptr) { \ + return ERR_INVALID_VALUE; \ + } + +#define INTERFACEID(id) extern const InterfaceID g_IID_##id; + +#define INTERFACE(id, x) \ + extern const InterfaceID g_IID_##id; \ + INTERFACE_INNER id : public IInterface + +#define INTERFACE2(id, pid, x) \ + do { \ + extern const InterfaceID g_IID_##id; \ + INTERFACE_INNER id : public##pid \ + } while (0); + +#define CLASS(id, x) \ + do { \ + extern const ClassID CID_##id; \ + class id : public Object \ + } while (0); + +#define INTERFACE_ID(x) +#define CLASS_ID(x) + +#ifndef IINTERFACE_DECL +#define IINTERFACE_DECL() \ + void IncStrongRef(const void *id = nullptr) override; \ + \ + void DecStrongRef(const void *id = nullptr) override; \ + \ + IInterface *Query(const InterfaceID & iid) override; \ + \ + InterfaceID GetInterfaceID(IInterface *object) override; + +#endif + +#ifndef IINTERFACE_IMPL_1 +#define IINTERFACE_IMPL_1(ClassName, SuperclassName, InterfaceName) \ + void ClassName::IncStrongRef(const void *id) \ + { \ + Object::IncStrongRef(id); \ + } \ + \ + void ClassName::DecStrongRef(const void *id) \ + { \ + Object::DecStrongRef(id); \ + } \ + \ + IInterface *ClassName::Query(const InterfaceID & iid) \ + { \ + if (iid == g_IID_##InterfaceName) { \ + return static_cast(this); \ + } \ + if (iid == g_IID_IInterface) { \ + return static_cast(this); \ + } \ + return SuperclassName::Query(iid); \ + } \ + \ + InterfaceID ClassName::GetInterfaceID(IInterface *object) \ + { \ + if (object == static_cast(this)) { \ + return g_IID_##InterfaceName; \ + } \ + return SuperclassName::GetInterfaceID(object); \ + } +#endif + +#ifndef IINTERFACE_IMPL_2 +#define IINTERFACE_IMPL_2(ClassName, SuperclassName, InterfaceName1, InterfaceName2) \ + void ClassName::IncStrongRef(const void *id) \ + { \ + Object::IncStrongRef(id); \ + } \ + \ + void ClassName::DecStrongRef(const void *id) \ + { \ + Object::DecStrongRef(id); \ + } \ + IInterface *ClassName::Query(const InterfaceID & iid) \ + { \ + if (iid == g_IID_##InterfaceName1) { \ + return static_cast(this); \ + } \ + if (iid == g_IID_##InterfaceName2) { \ + return static_cast(this); \ + } \ + if (iid == g_IID_IInterface) { \ + return static_cast(this); \ + } \ + return SuperclassName::Query(iid); \ + } \ + InterfaceID ClassName::GetInterfaceID(IInterface *object) \ + { \ + if (object == static_cast(this)) { \ + return g_IID_##InterfaceName1; \ + } \ + if (object == static_cast(this)) { \ + return g_IID_##InterfaceName2; \ + } \ + return SuperclassName::GetInterfaceID(object); \ + } +#endif + +#ifndef OBJECT_DECL +#define OBJECT_DECL() ClassID GetClassID() override; +#endif + +#ifndef OBJECT_IMPL +#define OBJECT_IMPL(ClassName) \ + do { \ + ClassID(ClassName)::GetClassID() \ + { \ + return CID_##ClassName; \ + } \ + } while (0); +#endif +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_BASE_DEF_H diff --git a/tools/interfaces/innerkits/base/include/ohos/aafwk/base/base_interfaces.h b/tools/interfaces/innerkits/base/include/ohos/aafwk/base/base_interfaces.h new file mode 100755 index 00000000000..d0f31baf5db --- /dev/null +++ b/tools/interfaces/innerkits/base/include/ohos/aafwk/base/base_interfaces.h @@ -0,0 +1,213 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef OHOS_AAFWK_BASE_IINTERFACE_H +#define OHOS_AAFWK_BASE_IINTERFACE_H +#include +#include + +#include "base_def.h" +#include "refbase.h" +#include "user_object_base.h" + +namespace OHOS { +namespace AAFwk { +INTERFACEID(IInterface) +INTERFACE_ID(00000000 - 0000 - 0000 - 0000 - 000000000001) +INTERFACE_INNER IInterface +{ + inline static IInterface *Query(IInterface * object) /* [in] */ + { + if (object == nullptr) { + return nullptr; + } + return object->Query(g_IID_IInterface); + } + + virtual void IncStrongRef(const void *id = nullptr) = 0; /* [in] */ + + virtual void DecStrongRef(const void *id = nullptr) = 0; /* [in] */ + + virtual IInterface *Query(const InterfaceID &iid) = 0; /* [in] */ + + virtual InterfaceID GetInterfaceID(IInterface * object) = 0; /* [in] */ +}; + +INTERFACE(IBoolean, 492ef6c0 - e122 - 401d - 80c4 - bb65e2325766) +{ + inline static IBoolean *Query(IInterface * object) /* [in] */ + { + if (object == nullptr) { + return nullptr; + } + return static_cast(object->Query(g_IID_IBoolean)); + } + + virtual ErrCode GetValue(bool &value) = 0; /* [out] */ +}; + +INTERFACE(IChar, 6da72e7c - d353 - 4d7b - 85ef - 2146add34219) +{ + inline static IChar *Query(IInterface * object) /* [in] */ + { + if (object == nullptr) { + return nullptr; + } + return static_cast(object->Query(g_IID_IChar)); + } + + virtual ErrCode GetValue(zchar & value) = 0; /* [out] */ +}; + +INTERFACE(IByte, 2c9fd6ff - 73f7 - 4a22 - 9ea8 - 1e37b2213ca1) +{ + inline static IByte *Query(IInterface * object) /* [in] */ + { + if (object == nullptr) { + return nullptr; + } + return static_cast(object->Query(g_IID_IByte)); + } + + virtual ErrCode GetValue(byte & value) = 0; /* [out] */ +}; + +INTERFACE(IShort, 54fe1291 - 0813 - 43c9 - b6f7 - b008edef7f34) +{ + inline static IShort *Query(IInterface * object) /* [in] */ + { + if (object == nullptr) { + return nullptr; + } + return static_cast(object->Query(g_IID_IShort)); + } + + virtual ErrCode GetValue(short &value) = 0; /* [out] */ +}; + +INTERFACE(IInteger, 0672d282 - 7cdb - 49b8 - 92c7 - 1af35e2d4949) +{ + inline static IInteger *Query(IInterface * object) /* [in] */ + { + if (object == nullptr) { + return nullptr; + } + return static_cast(object->Query(g_IID_IInteger)); + } + + virtual ErrCode GetValue(int &value) = 0; /* [out] */ +}; + +INTERFACE(ILong, d7550828 - 2eaf - 4281 - 8604 - 42a82ab9bcdc) +{ + inline static ILong *Query(IInterface * object) /* [in] */ + { + if (object == nullptr) { + return nullptr; + } + return static_cast(object->Query(g_IID_ILong)); + } + + virtual ErrCode GetValue(long &value) = 0; /* [out] */ +}; + +INTERFACE(IFloat, b5428638 - ca53 - 4a27 - 95a0 - 3f24e54a58d5) +{ + inline static IFloat *Query(IInterface * object) /* [in] */ + { + if (object == nullptr) { + return nullptr; + } + return static_cast(object->Query(g_IID_IFloat)); + } + + virtual ErrCode GetValue(float &value) = 0; /* [out] */ +}; + +INTERFACE(IDouble, 596dc69a - ae7d - 42ad - b00f - 0d5eb01a2557) +{ + inline static IDouble *Query(IInterface * object) /* [in] */ + { + if (object == nullptr) { + return nullptr; + } + return static_cast(object->Query(g_IID_IDouble)); + } + + virtual ErrCode GetValue(double &value) = 0; /* [out] */ +}; + +INTERFACE(IString, 69644bf4 - dd20 - 417b - 9055 - 5a26e3e1793b) +{ + inline static IString *Query(IInterface * object) /* [in] */ + { + if (object == nullptr) { + return nullptr; + } + return static_cast(object->Query(g_IID_IString)); + } + + virtual ErrCode GetString(std::string & str) = 0; /* [out] */ +}; + +INTERFACE(IArray, 875b9da6 - 9913 - 4370 - 8847 - e1961be6e560) +{ + inline static IArray *Query(IInterface * object) /* [in] */ + { + if (object == nullptr) { + return nullptr; + } + return static_cast(object->Query(g_IID_IArray)); + } + + virtual ErrCode Get(long index, /* [in] */ + sptr &value) = 0; /* [out] */ + + virtual ErrCode GetLength(long &size) = 0; /* [out] */ + + virtual ErrCode GetType(InterfaceID & id) = 0; /* [out] */ + + virtual ErrCode Set(long index, /* [in] */ + IInterface *value) = 0; /* [in] */ +}; + +INTERFACE(IPacMap, f92066fd - fd0c - 401b - a3f6 - 626da3bac9d5) +{ + inline static IPacMap *Query(IInterface * object) + { + if (object == nullptr) { + return nullptr; + } + return static_cast(object->Query(g_IID_IPacMap)); + } + + virtual bool FromString(const std::string &str) = 0; +}; + +INTERFACE(IUserObject, 4edb325d - 8532 - 4af7 - b42e - 82f4f29dfdea) +{ + inline static IUserObject *Query(IInterface * object) + { + if (object == nullptr) { + return nullptr; + } + return static_cast(object->Query(g_IID_IUserObject)); + } + + virtual ErrCode GetValue(std::shared_ptr & value) = 0; /* [out] */ +}; + +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_BASE_IINTERFACE_H diff --git a/tools/interfaces/innerkits/base/include/ohos/aafwk/base/base_object.h b/tools/interfaces/innerkits/base/include/ohos/aafwk/base/base_object.h new file mode 100644 index 00000000000..58173befa30 --- /dev/null +++ b/tools/interfaces/innerkits/base/include/ohos/aafwk/base/base_object.h @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef OHOS_AAFWK_BASE_OBJECT_H +#define OHOS_AAFWK_BASE_OBJECT_H + +#include + +#include "base_interfaces.h" +#include "refbase.h" + +namespace OHOS { +namespace AAFwk { +INTERFACE(IObject, 8321f710 - a0c0 - 4cbe-bfbc - 5a78f1312b1b) +{ + inline static IObject *Query(IInterface & object) /* [in] */ + { + return static_cast(object.Query(g_IID_IObject)); + } + + virtual ClassID GetClassID() = 0; + + virtual int GetHashCode() = 0; + + virtual bool Equals(IObject & other) = 0; /* [in] */ + + virtual std::string ToString() = 0; +}; + +INTERFACE(IWeakReference, 26ab1978 - 1d11 - 4a4f - 826d - 61785c048cca) +{ + inline static IWeakReference *Query(IInterface * object) /* [in] */ + { + if (object == nullptr) { + return nullptr; + } + return static_cast(object->Query(g_IID_IWeakReference)); + } + + virtual ErrCode Resolve(const InterfaceID &iid, /* [in] */ + IInterface **object) = 0; /* [out] */ +}; + +INTERFACE(IWeakReferenceSource, bc3f5250 - 34d7 - 42d2 - 9b40 - ffce83fd4061) +{ + inline static IWeakReferenceSource *Query(IInterface * object) /* [in] */ + { + if (object == nullptr) { + return nullptr; + } + return static_cast(object->Query(g_IID_IWeakReferenceSource)); + } + + virtual ErrCode GetWeakReference(sptr & weakRef) = 0; /* [out] */ +}; + +class Object : public RefBase, public IObject, public IWeakReferenceSource { +public: + void IncStrongRef(const void *id = nullptr) override; /* [in] */ + + void DecStrongRef(const void *id = nullptr) override; /* [in] */ + + IInterface *Query(const InterfaceID &iid) override; /* [in] */ + + InterfaceID GetInterfaceID(IInterface *object) override; /* [in] */ + + ClassID GetClassID() override; + + int GetHashCode() override; + + bool Equals(IObject &other) override; /* [in] */ + + ErrCode GetWeakReference(sptr &weakRef) override; /* [out] */ + + std::string ToString() override; + + static bool Equals(IInterface &obj1, /* [in] */ + IInterface &obj2); /* [in] */ + + static std::string ToString(IInterface &object); /* [in] */ +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_BASE_OBJECT_H diff --git a/tools/interfaces/innerkits/base/include/ohos/aafwk/base/base_types.h b/tools/interfaces/innerkits/base/include/ohos/aafwk/base/base_types.h new file mode 100644 index 00000000000..e0b02a8cfd1 --- /dev/null +++ b/tools/interfaces/innerkits/base/include/ohos/aafwk/base/base_types.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef OHOS_AAFWK_BASE_TYPES_H +#define OHOS_AAFWK_BASE_TYPES_H + +#include +#include + +namespace OHOS { +namespace AAFwk { +using HANDLE = uintptr_t; +using byte = char; +using zchar = char32_t; + +using Uuid = struct Uuid { + static constexpr int UUID_SUB5_SIZE = 12; + + unsigned int mData1; + unsigned short mData2; + unsigned short mData3; + unsigned short mData4; + unsigned char mData5[UUID_SUB5_SIZE]; + + static const struct Uuid Empty; +}; + +using InterfaceID = Uuid; +using ClassID = Uuid; + +inline bool operator==(const InterfaceID &iid1, /* [in] */ + const InterfaceID &iid2) /* [in] */ +{ + return !memcmp(&iid1, &iid2, sizeof(InterfaceID)); +} + +inline bool operator!=(const InterfaceID &iid1, /* [in] */ + const InterfaceID &iid2) /* [in] */ +{ + return memcmp(&iid1, &iid2, sizeof(InterfaceID)); +} +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_BASE_TYPES_H diff --git a/tools/interfaces/innerkits/base/include/ohos/aafwk/base/bool_wrapper.h b/tools/interfaces/innerkits/base/include/ohos/aafwk/base/bool_wrapper.h new file mode 100644 index 00000000000..18e9dc1680e --- /dev/null +++ b/tools/interfaces/innerkits/base/include/ohos/aafwk/base/bool_wrapper.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef OHOS_AAFWK_BOOLEAN_H +#define OHOS_AAFWK_BOOLEAN_H + +#include "ohos/aafwk/base/base_object.h" +#include "refbase.h" + +namespace OHOS { +namespace AAFwk { +class Boolean final : public Object, public IBoolean { +public: + inline Boolean(bool value) : value_(value) + {} + + inline ~Boolean() + {} + + IINTERFACE_DECL(); + + ErrCode GetValue(bool &value) override; /* [out] */ + + bool Equals(IObject &other) override; /* [in] */ + + std::string ToString() override; + + static sptr Box(bool value); /* [in] */ + + static bool Unbox(IBoolean *object); /* [in] */ + + static sptr Parse(const std::string &str); /* [in] */ + +public: + static constexpr char SIGNATURE = 'Z'; + +private: + bool value_; +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_BOOLEAN_H diff --git a/tools/interfaces/innerkits/base/include/ohos/aafwk/base/byte_wrapper.h b/tools/interfaces/innerkits/base/include/ohos/aafwk/base/byte_wrapper.h new file mode 100644 index 00000000000..b7e29e33240 --- /dev/null +++ b/tools/interfaces/innerkits/base/include/ohos/aafwk/base/byte_wrapper.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef OHOS_AAFWK_BYTE_H +#define OHOS_AAFWK_BYTE_H + +#include "ohos/aafwk/base/base_object.h" +#include "refbase.h" + +namespace OHOS { +namespace AAFwk { +class Byte final : public Object, public IByte { +public: + inline Byte(byte value) : value_(value) + {} + + inline ~Byte() + {} + + IINTERFACE_DECL(); + + ErrCode GetValue(byte &value) override; /* [out] */ + + bool Equals(IObject &other) override; /* [in] */ + + std::string ToString() override; + + static sptr Box(byte value); /* [in] */ + + static byte Unbox(IByte *object); /* [in] */ + + static sptr Parse(const std::string &str); /* [in] */ + +public: + static constexpr char SIGNATURE = 'B'; + +private: + byte value_; +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_BYTE_H diff --git a/tools/interfaces/innerkits/base/include/ohos/aafwk/base/double_wrapper.h b/tools/interfaces/innerkits/base/include/ohos/aafwk/base/double_wrapper.h new file mode 100644 index 00000000000..f60db3d4f8a --- /dev/null +++ b/tools/interfaces/innerkits/base/include/ohos/aafwk/base/double_wrapper.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef OHOS_AAFWK_DOUBLE_H +#define OHOS_AAFWK_DOUBLE_H + +#include "ohos/aafwk/base/base_object.h" +#include "refbase.h" + +namespace OHOS { +namespace AAFwk { +class Double final : public Object, public IDouble { +public: + inline Double(double value) : value_(value) + {} + + inline ~Double() + {} + + IINTERFACE_DECL(); + + ErrCode GetValue(double &value) override; /* [out] */ + + bool Equals(IObject &other) override; /* [in] */ + + std::string ToString() override; + + static sptr Box(double value); /* [in] */ + + static double Unbox(IDouble *object); /* [in] */ + + static sptr Parse(const std::string &str); /* [in] */ + +public: + static constexpr char SIGNATURE = 'D'; + +private: + double value_; +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_DOUBLE_H \ No newline at end of file diff --git a/tools/interfaces/innerkits/base/include/ohos/aafwk/base/float_wrapper.h b/tools/interfaces/innerkits/base/include/ohos/aafwk/base/float_wrapper.h new file mode 100644 index 00000000000..2beecc73d0a --- /dev/null +++ b/tools/interfaces/innerkits/base/include/ohos/aafwk/base/float_wrapper.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef OHOS_AAFWK_FLOAT_H +#define OHOS_AAFWK_FLOAT_H + +#include "ohos/aafwk/base/base_object.h" +#include "refbase.h" + +namespace OHOS { +namespace AAFwk { +class Float final : public Object, public IFloat { +public: + inline Float(float value) : value_(value) + {} + + inline ~Float() + {} + + IINTERFACE_DECL(); + + ErrCode GetValue(float &value) override; /* [out] */ + + bool Equals(IObject &other) override; /* [in] */ + + std::string ToString() override; + + static sptr Box(float value); /* [in] */ + + static float Unbox(IFloat *object); /* [in] */ + + static sptr Parse(const std::string &str); /* [in] */ + +public: + static constexpr char SIGNATURE = 'F'; + +private: + float value_; +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_FLOAT_H \ No newline at end of file diff --git a/tools/interfaces/innerkits/base/include/ohos/aafwk/base/int_wrapper.h b/tools/interfaces/innerkits/base/include/ohos/aafwk/base/int_wrapper.h new file mode 100644 index 00000000000..cb64fd7a987 --- /dev/null +++ b/tools/interfaces/innerkits/base/include/ohos/aafwk/base/int_wrapper.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef OHOS_AAFWK_INTEGER_H +#define OHOS_AAFWK_INTEGER_H + +#include "ohos/aafwk/base/base_object.h" +#include "refbase.h" + +namespace OHOS { +namespace AAFwk { +class Integer final : public Object, public IInteger { +public: + inline Integer(int value) : value_(value) + {} + + inline ~Integer() + {} + + IINTERFACE_DECL(); + + ErrCode GetValue(int &value) override; /* [out] */ + + bool Equals(IObject &other) override; /* [in] */ + + std::string ToString() override; + + static sptr Box(int value); /* [in] */ + + static int Unbox(IInteger *object); /* [in] */ + + static sptr Parse(const std::string &str); /* [in] */ + +public: + static constexpr char SIGNATURE = 'I'; + +private: + int value_; +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_INTEGER_H \ No newline at end of file diff --git a/tools/interfaces/innerkits/base/include/ohos/aafwk/base/ipc_singleton.h b/tools/interfaces/innerkits/base/include/ohos/aafwk/base/ipc_singleton.h new file mode 100644 index 00000000000..6ab3516a632 --- /dev/null +++ b/tools/interfaces/innerkits/base/include/ohos/aafwk/base/ipc_singleton.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_IPCSINGLETON_H +#define OHOS_AAFWK_IPCSINGLETON_H + +#include "nocopyable.h" +#include +#include + +namespace OHOS { +namespace AppExecFwk { +#define DECLARE_DELAYED_IPCSINGLETON(MyClass) \ +public: \ + (~MyClass)(); \ + \ +private: \ + friend DelayedIPCSingleton; \ + MyClass(); + +template +class DelayedIPCSingleton : public NoCopyable { +public: + static sptr GetInstance() + { + if (instance_ == nullptr) { + std::lock_guard lock(mutex_); + if (instance_ == nullptr) { + sptr temp(new T); + instance_ = temp; + } + } + + return instance_; + }; + static void DestroyInstance(); + +private: + static sptr instance_; + static std::mutex mutex_; +}; + +template +sptr DelayedIPCSingleton::instance_ = nullptr; + +template +std::mutex DelayedIPCSingleton::mutex_; + +template +void DelayedIPCSingleton::DestroyInstance() +{ + std::lock_guard lock(mutex_); + if (instance_ != nullptr) { + instance_.reset(); + instance_ = nullptr; + } +} +} // namespace AppExecFwk +} // namespace OHOS +#endif // OHOS_AAFWK_IPCSINGLETON_H \ No newline at end of file diff --git a/tools/interfaces/innerkits/base/include/ohos/aafwk/base/light_refbase.h b/tools/interfaces/innerkits/base/include/ohos/aafwk/base/light_refbase.h new file mode 100644 index 00000000000..3e23a9e22a0 --- /dev/null +++ b/tools/interfaces/innerkits/base/include/ohos/aafwk/base/light_refbase.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef OHOS_AAFWK_LIGHTREFBASE_H +#define OHOS_AAFWK_LIGHTREFBASE_H + +#include + +namespace OHOS { +namespace AAFwk { +class LightRefCountBase { +public: + inline LightRefCountBase(); + + inline int IncStrongRef(const void *id = nullptr); /* [in] */ + + inline int DecStrongRef(const void *id = nullptr); /* [in] */ + + inline int GetRefCount() const; + +protected: + inline virtual ~LightRefCountBase(); + +private: + std::atomic refCount_; +}; + +LightRefCountBase::LightRefCountBase() : refCount_(0) +{} + +LightRefCountBase::~LightRefCountBase() +{} + +int LightRefCountBase::IncStrongRef(const void *id) /* [in] */ +{ + const int beforeCount = refCount_.fetch_add(1, std::memory_order_relaxed); + return beforeCount + 1; +} + +int LightRefCountBase::DecStrongRef(const void *id) /* [in] */ +{ + const int beforeCount = refCount_.fetch_sub(1, std::memory_order_release); + if (beforeCount - 1 == 0) { + delete this; + } + return beforeCount - 1; +} + +int LightRefCountBase::GetRefCount() const +{ + return refCount_.load(std::memory_order_relaxed); +} +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_LIGHTREFBASE_H diff --git a/tools/interfaces/innerkits/base/include/ohos/aafwk/base/long_wrapper.h b/tools/interfaces/innerkits/base/include/ohos/aafwk/base/long_wrapper.h new file mode 100644 index 00000000000..311af51103e --- /dev/null +++ b/tools/interfaces/innerkits/base/include/ohos/aafwk/base/long_wrapper.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef OHOS_AAFWK_LONG_H +#define OHOS_AAFWK_LONG_H + +#include "ohos/aafwk/base/base_object.h" +#include "refbase.h" + +namespace OHOS { +namespace AAFwk { +class Long final : public Object, public ILong { +public: + inline Long(long value) : value_(value) + {} + + inline ~Long() + {} + + IINTERFACE_DECL(); + + ErrCode GetValue(long &value) override; /* [out] */ + + bool Equals(IObject &other) override; /* [in] */ + + std::string ToString() override; + + static sptr Box(long value); /* [in] */ + + static long Unbox(ILong *object); /* [in] */ + + static sptr Parse(const std::string &str); /* [in] */ + +public: + static constexpr char SIGNATURE = 'J'; + +private: + long value_; +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_LONG_H diff --git a/tools/interfaces/innerkits/base/include/ohos/aafwk/base/short_wrapper.h b/tools/interfaces/innerkits/base/include/ohos/aafwk/base/short_wrapper.h new file mode 100644 index 00000000000..e80800d5c75 --- /dev/null +++ b/tools/interfaces/innerkits/base/include/ohos/aafwk/base/short_wrapper.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef OHOS_AAFWK_SHORT_H +#define OHOS_AAFWK_SHORT_H + +#include "ohos/aafwk/base/base_object.h" +#include "refbase.h" + +namespace OHOS { +namespace AAFwk { +class Short final : public Object, public IShort { +public: + inline Short(short value) : value_(value) + {} + + inline ~Short() + {} + + IINTERFACE_DECL(); + + ErrCode GetValue(short &value) override; /* [out] */ + + bool Equals(IObject &other) override; /* [in] */ + + std::string ToString() override; + + static sptr Box(short value); /* [in] */ + + static short Unbox(IShort *object); /* [in] */ + + static sptr Parse(const std::string &str); /* [in] */ + +public: + static constexpr char SIGNATURE = 'S'; + +private: + short value_; +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_SHORT_H diff --git a/tools/interfaces/innerkits/base/include/ohos/aafwk/base/string_wrapper.h b/tools/interfaces/innerkits/base/include/ohos/aafwk/base/string_wrapper.h new file mode 100644 index 00000000000..f904eb77516 --- /dev/null +++ b/tools/interfaces/innerkits/base/include/ohos/aafwk/base/string_wrapper.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef OHOS_AAFWK_STRING_H +#define OHOS_AAFWK_STRING_H + +#include "ohos/aafwk/base/base_object.h" +#include "refbase.h" + +namespace OHOS { +namespace AAFwk { +class String final : public Object, public IString { +public: + inline String(const std::string &str) : string_(str) + {} + + inline ~String() + {} + + IINTERFACE_DECL(); + + ErrCode GetString(std::string &str) override; /* [out] */ + + bool Equals(IObject &other) override; /* [in] */ + + std::string ToString() override; + + static sptr Box(const std::string &str); /* [in] */ + + static std::string Unbox(IString *object); /* [in] */ + + static sptr Parse(const std::string &str); /* [in] */ + +public: + static constexpr char SIGNATURE = 'T'; + +private: + std::string string_; +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_STRING_H diff --git a/tools/interfaces/innerkits/base/include/ohos/aafwk/base/user_object_base.h b/tools/interfaces/innerkits/base/include/ohos/aafwk/base/user_object_base.h new file mode 100755 index 00000000000..91c97c633ac --- /dev/null +++ b/tools/interfaces/innerkits/base/include/ohos/aafwk/base/user_object_base.h @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef OHOS_APPEXECFWK_USER_OBJECT_BASE_H +#define OHOS_APPEXECFWK_USER_OBJECT_BASE_H +#include +#include "parcel.h" +#include "string_ex.h" +namespace OHOS { +namespace AAFwk { +class UserObjectBase : public Parcelable { +public: + UserObjectBase(const std::string &className) : class_name_(className) + {} + virtual ~UserObjectBase() = default; + + inline void SetClassName(const std::string &className) + { + class_name_ = className; + } + inline std::string GetClassName(void) + { + return class_name_; + } + /** + * @brief The current object parameter is converted to a string + * @param none + * @return returns string of current object parameter + */ + virtual std::string ToString() const = 0; + + /** + * @brief The current object parameter is converted to a string + * @param none + * @return returns string of current object parameter + */ + virtual void Parse(const std::string &str) = 0; + + /** + * @brief Copy the data of the specified object to the current object with deepcopy + */ + virtual void DeepCopy(std::shared_ptr &other) = 0; + + /** + * @brief Indicates whether some other object is "equal to" this one. + * @param other The object with which to compare. + * @return true if this object is the same as the obj argument; false otherwise. + */ + virtual bool Equals(std::shared_ptr &other) = 0; + + /** + * @brief Writes a parcelable object to the given parcel. + * @param parcel indicates Parcel object + * @return Returns true being written on success or false if any error occur. + */ + virtual bool Marshalling(Parcel &parcel) const + { + std::string tostring = ToString(); + return parcel.WriteString16(Str8ToStr16(tostring)); + } + /** + * @brief Read a parcelable object to the given parcel. + * @param parcel indicates Parcel object + * @return Returns true being read on success or false if any error occur. + */ + virtual bool Unmarshalling(Parcel &parcel) + { + std::string tostring = Str16ToStr8(parcel.ReadString16()); + Parse(tostring); + return true; + } + +protected: + std::string class_name_; +}; + +using CreateUserObjectBase = std::function; +class UserObjectBaseLoader { +public: + static UserObjectBaseLoader &GetInstance(void); + ~UserObjectBaseLoader() = default; + /** + * @brief Registered user-defined serialization class. + * @param objectName The name of the custom class. + * @param createFun Function object that creates an instance of a custom class. + */ + void RegisterUserObject(const std::string &objectName, const CreateUserObjectBase &createFun); + + /** + * @brief Represents obtaining an instance of an object of a registered serialization class. + * @param className The name of the custom class {UserObjectBase subClass}. + * + * @return Returns an instance of the object, or nullptr on failure. + */ + UserObjectBase *GetUserObjectByName(const std::string &className); + +private: + std::unordered_map register_class_list_; + UserObjectBaseLoader() = default; + UserObjectBaseLoader(const UserObjectBaseLoader &) = delete; + UserObjectBaseLoader &operator=(const UserObjectBaseLoader &) = delete; + UserObjectBaseLoader(UserObjectBaseLoader &&) = delete; + UserObjectBaseLoader &operator=(UserObjectBaseLoader &&) = delete; +}; + +/** + * @brief Register the object's deserialization class, which must be a child UserObjectBase. + * + * @param className The name of class. + */ +#define REGISTER_USER_OBJECT_BASE(className) \ + static __attribute__((constructor)) void RegisterUserMapObject_##className() \ + { \ + UserObjectBaseLoader::GetInstance().RegisterUserObject( \ + #className, []()->UserObjectBase * { return new (std::nothrow)(className); }); \ + } + +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_APPEXECFWK_USER_OBJECT_BASE_H diff --git a/tools/interfaces/innerkits/base/include/ohos/aafwk/base/user_object_wrapper.h b/tools/interfaces/innerkits/base/include/ohos/aafwk/base/user_object_wrapper.h new file mode 100755 index 00000000000..0ea0a8c22dd --- /dev/null +++ b/tools/interfaces/innerkits/base/include/ohos/aafwk/base/user_object_wrapper.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef OHOS_AAFWK_USER_OBJECT_WRAPPER_H +#define OHOS_AAFWK_USER_OBJECT_WRAPPER_H +#include +#include +#include "ohos/aafwk/base/base_object.h" +#include "refbase.h" +#include "ohos/aafwk/base/user_object_base.h" + +namespace OHOS { +namespace AAFwk { + +class UserObject final : public Object, public IUserObject { +public: + inline UserObject(const std::shared_ptr &value) : value_(value) + {} + + virtual ~UserObject() = default; + + IINTERFACE_DECL(); + + ErrCode GetValue(std::shared_ptr &value) override; /* [out] */ + + bool Equals(IObject &other) override; /* [in] */ + + std::string ToString() override; + + static sptr Box(const std::shared_ptr &value); /* [in] */ + + static std::shared_ptr Unbox(IUserObject *object); /* [in] */ + + static sptr Parse(const std::string &str); /* [in] */ + +public: + static constexpr char SIGNATURE = 'O'; + +private: + std::shared_ptr value_ = nullptr; +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_USER_OBJECT_WRAPPER_H diff --git a/tools/interfaces/innerkits/base/include/ohos/aafwk/base/zchar_wrapper.h b/tools/interfaces/innerkits/base/include/ohos/aafwk/base/zchar_wrapper.h new file mode 100644 index 00000000000..aaabb8d83b2 --- /dev/null +++ b/tools/interfaces/innerkits/base/include/ohos/aafwk/base/zchar_wrapper.h @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef OHOS_AAFWK_CHAR_H +#define OHOS_AAFWK_CHAR_H + +#include "ohos/aafwk/base/base_object.h" +#include "refbase.h" + +namespace OHOS { +namespace AAFwk { +class Char final : public Object, public IChar { +public: + inline Char(zchar value) : value_(value) + {} + + inline ~Char() + {} + + IINTERFACE_DECL(); + + ErrCode GetValue(zchar &value) override; /* [out] */ + + bool Equals(IObject &other) override; /* [in] */ + + std::string ToString() override; + + static sptr Box(zchar value); /* [in] */ + + static zchar Unbox(IChar *object); /* [in] */ + + static sptr Parse(const std::string &str); /* [in] */ + + static int GetByteSize(zchar c); /* [in] */ + + static void WriteUTF8Bytes(char *dst, /* [in] */ + zchar c, /* [in] */ + int size); /* [in] */ + + static zchar GetChar(const std::string &str, /* [in] */ + int index); /* [in] */ + + static constexpr char SIGNATURE = 'C'; + + static constexpr zchar INVALID_CHAR = 0x110000; + +private: + static zchar GetCharInternal(const unsigned char *cur, /* [in] */ + int &size); /* [in] */ + + static constexpr int MIN_CODE_POINT = 0x000000; + static constexpr int MAX_CODE_POINT = 0x10FFFF; + static constexpr int MIN_HIGH_SURROGATE = 0xD800; + static constexpr int MAX_HIGH_SURROGATE = 0xDBFF; + static constexpr int MIN_LOW_SURROGATE = 0xDC00; + static constexpr int MAX_LOW_SURROGATE = 0xDFFF; + + static constexpr int BYTE_COUNT_1 = 1; + static constexpr int BYTE_COUNT_2 = 2; + static constexpr int BYTE_COUNT_3 = 3; + static constexpr int BYTE_COUNT_4 = 4; + + static constexpr zchar BYTE_MASK = 0x000000BF; + static constexpr zchar BYTE_MARK = 0x00000080; + static constexpr int BYTE_SHIFT = 6; + + // (00-7f) 7bit -> 0xxxxxxx, bit mask is 0x00000000 + // (c0-df)(80-bf) 11bit -> 110yyyyx 10xxxxxx, bit mask is 0x000000C0 + // (e0-ef)(80-bf)(80-bf) 16bit -> 1110yyyy 10yxxxxx 10xxxxxx, bit mask is 0x000000E0 + // (f0-f7)(80-bf)(80-bf)(80-bf) 21bit -> 11110yyy 10yyxxxx 10xxxxxx 10xxxxxx, bit mask is 0x000000F0 + static constexpr zchar FIRST_BYTE_MARK[] = {0x00000000, 0x00000000, 0x000000C0, 0x000000E0, 0x000000F0}; + + zchar value_; +}; +} // namespace AAFwk +} // namespace OHOS + +#endif diff --git a/tools/interfaces/innerkits/dataobs_manager/BUILD.gn b/tools/interfaces/innerkits/dataobs_manager/BUILD.gn new file mode 100644 index 00000000000..7ed24574369 --- /dev/null +++ b/tools/interfaces/innerkits/dataobs_manager/BUILD.gn @@ -0,0 +1,61 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") +import("//foundation/aafwk/standard/aafwk.gni") + +config("dataobs_manager_public_config") { + visibility = [ ":*" ] + include_dirs = [ + "include/", + "//utils/native/base/include", + "//utils/system/safwk/native/include", + "//foundation/aafwk/standard/frameworks/kits/ability/native/include", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler/include", + "//foundation/aafwk/standard/services/dataobsmgr/include", + ] + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } +} + +ohos_shared_library("dataobs_manager") { + sources = [ + "${services_path}/dataobsmgr/src/data_ability_observer_proxy.cpp", + "${services_path}/dataobsmgr/src/data_ability_observer_stub.cpp", + "${services_path}/dataobsmgr/src/dataobs_mgr_client.cpp", + "${services_path}/dataobsmgr/src/dataobs_mgr_proxy.cpp", + ] + + public_configs = [ + ":dataobs_manager_public_config", + "${services_path}/dataobsmgr:dataobsms_config", + ] + + deps = [ + "//foundation/appexecfwk/standard/common:libappexecfwk_common", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy:samgr_proxy", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] + + subsystem_name = "aafwk" + part_name = "aafwk_standard" +} diff --git a/tools/interfaces/innerkits/dataobs_manager/dataobs_manager_headers.gni b/tools/interfaces/innerkits/dataobs_manager/dataobs_manager_headers.gni new file mode 100644 index 00000000000..30f27510295 --- /dev/null +++ b/tools/interfaces/innerkits/dataobs_manager/dataobs_manager_headers.gni @@ -0,0 +1,23 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +dataobs_manager_headers = { + header_files = [ + "dataobs_mgr_errors.h", + "dataobs_mgr_client.h", + "dataobs_mgr_interface.h", + "data_ability_observer_interface.h", + "data_ability_observer_stub.h", + ] + header_base = "interfaces/innerkits/dataobs_manager/include" +} diff --git a/tools/interfaces/innerkits/dataobs_manager/include/data_ability_observer_interface.h b/tools/interfaces/innerkits/dataobs_manager/include/data_ability_observer_interface.h new file mode 100644 index 00000000000..d0f4070a5d7 --- /dev/null +++ b/tools/interfaces/innerkits/dataobs_manager/include/data_ability_observer_interface.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef OHOS_AAFWK_DATA_ABILITY_OBSERVER_INTERFACE_H +#define OHOS_AAFWK_DATA_ABILITY_OBSERVER_INTERFACE_H + +#include +#include "uri.h" + +namespace OHOS { +namespace AAFwk { + +class IDataAbilityObserver : public OHOS::IRemoteBroker { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"ohos.aafwk.DataAbilityObserver"); + + enum { + DATA_ABILITY_OBSERVER_CHANGE, + }; + + /** + * @brief Called back to notify that the data being observed has changed. + * + * @param uri Indicates the path of the data to operate. + */ + virtual void OnChange() = 0; +}; + +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_DATA_ABILITY_OBSERVER_INTERFACE_H \ No newline at end of file diff --git a/tools/interfaces/innerkits/dataobs_manager/include/data_ability_observer_stub.h b/tools/interfaces/innerkits/dataobs_manager/include/data_ability_observer_stub.h new file mode 100644 index 00000000000..45b2cb6ae6b --- /dev/null +++ b/tools/interfaces/innerkits/dataobs_manager/include/data_ability_observer_stub.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef OHOS_AAFWK_DATA_ABILITY_OBSERVER_STUB_H +#define OHOS_AAFWK_DATA_ABILITY_OBSERVER_STUB_H + +#include +#include + +#include "data_ability_observer_interface.h" +#include "nocopyable.h" + +#include +#include + +namespace OHOS { +namespace AAFwk { + +class DataAbilityObserverStub : public IRemoteStub { +public: + DataAbilityObserverStub(); + virtual ~DataAbilityObserverStub(); + + int OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override; + +private: + /** + * @brief Called back to notify that the data being observed has changed. + * + * @param uri Indicates the path of the data to operate. + * + * @return Returns 0 on success, others on failure. + * + */ + int OnChangeInner(MessageParcel &data, MessageParcel &reply); + + using RequestFuncType = int (DataAbilityObserverStub::*)(MessageParcel &data, MessageParcel &reply); + std::map requestFuncMap_; + + DISALLOW_COPY_AND_MOVE(DataAbilityObserverStub); +}; + +/** + * @class DataObsCallbackRecipient + * DataObsCallbackRecipient notices IRemoteBroker died. + */ +class DataObsCallbackRecipient : public IRemoteObject::DeathRecipient { +public: + using RemoteDiedHandler = std::function &)>; + DataObsCallbackRecipient(RemoteDiedHandler handler); + virtual ~DataObsCallbackRecipient(); + virtual void OnRemoteDied(const wptr &remote); + +private: + RemoteDiedHandler handler_; +}; + +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_DATA_ABILITY_OBSERVER_STUB_H \ No newline at end of file diff --git a/tools/interfaces/innerkits/dataobs_manager/include/dataobs_mgr_client.h b/tools/interfaces/innerkits/dataobs_manager/include/dataobs_mgr_client.h new file mode 100644 index 00000000000..10cf6125f05 --- /dev/null +++ b/tools/interfaces/innerkits/dataobs_manager/include/dataobs_mgr_client.h @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_DATAOBS_MANAGER_CLIENT_H +#define OHOS_AAFWK_DATAOBS_MANAGER_CLIENT_H + +#include + +#include "data_ability_observer_interface.h" +#include "dataobs_mgr_errors.h" +#include "dataobs_mgr_interface.h" +#include "uri.h" + +#include "iremote_object.h" + +namespace OHOS { +namespace AAFwk { +/** + * @class DataObsMgrClient + * DataObsMgrClient is used to access dataobs manager services. + */ +class DataObsMgrClient { +public: + DataObsMgrClient(); + virtual ~DataObsMgrClient(); + static std::shared_ptr GetInstance(); + + /** + * Registers an observer to DataObsMgr specified by the given Uri. + * + * @param uri, Indicates the path of the data to operate. + * @param dataObserver, Indicates the IDataAbilityObserver object. + * + * @return Returns ERR_OK on success, others on failure. + */ + ErrCode RegisterObserver(const Uri &uri, const sptr &dataObserver); + + /** + * Deregisters an observer used for DataObsMgr specified by the given Uri. + * + * @param uri, Indicates the path of the data to operate. + * @param dataObserver, Indicates the IDataAbilityObserver object. + * + * @return Returns ERR_OK on success, others on failure. + */ + ErrCode UnregisterObserver(const Uri &uri, const sptr &dataObserver); + + /** + * Notifies the registered observers of a change to the data resource specified by Uri. + * + * @param uri, Indicates the path of the data to operate. + * + * @return Returns ERR_OK on success, others on failure. + */ + ErrCode NotifyChange(const Uri &uri); + +private: + /** + * Connect dataobs manager service. + * + * @return Returns ERR_OK on success, others on failure. + */ + ErrCode Connect(); + + static std::mutex mutex_; + static std::shared_ptr instance_; + sptr remoteObject_; +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_DATAOBS_MANAGER_CLIENT_H diff --git a/tools/interfaces/innerkits/dataobs_manager/include/dataobs_mgr_errors.h b/tools/interfaces/innerkits/dataobs_manager/include/dataobs_mgr_errors.h new file mode 100644 index 00000000000..24c3e5aa726 --- /dev/null +++ b/tools/interfaces/innerkits/dataobs_manager/include/dataobs_mgr_errors.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_DATAOBS_MANAGER_ERRORS_H +#define OHOS_AAFWK_DATAOBS_MANAGER_ERRORS_H + +#include "errors.h" + +namespace OHOS { +namespace AAFwk { +enum { + /** + * Module type: Dataobs Manager Service side + */ + DATAOBS_MODULE_TYPE_SERVICE = 2, +}; + +// offset of aafwk error, only be used in this file. +constexpr ErrCode AAFWK_DATAOBS_SERVICE_ERR_OFFSET = ErrCodeOffset(SUBSYS_AAFWK, DATAOBS_MODULE_TYPE_SERVICE); + +enum { + /** + * Result(2228224) + */ + DATAOBS_SERVICE_NOT_CONNECTED = AAFWK_DATAOBS_SERVICE_ERR_OFFSET, + GET_DATAOBS_SERVICE_FAILED, + DATAOBS_PROXY_INNER_ERR, + DATA_OBSERVER_IS_NULL, + DATAOBS_SERVICE_HANDLER_IS_NULL, + DATAOBS_SERVICE_INNER_IS_NULL, + DATAOBS_SERVICE_TASK_LIMMIT, + DATAOBS_SERVICE_OBS_LIMMIT, + DATAOBS_SERVICE_POST_TASK_FAILED, + NO_OBS_FOR_URI, + OBS_EXIST, +}; + +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_DATAOBS_MANAGER_ERRORS_H diff --git a/tools/interfaces/innerkits/dataobs_manager/include/dataobs_mgr_interface.h b/tools/interfaces/innerkits/dataobs_manager/include/dataobs_mgr_interface.h new file mode 100644 index 00000000000..bb6e7bdd99f --- /dev/null +++ b/tools/interfaces/innerkits/dataobs_manager/include/dataobs_mgr_interface.h @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_DATAOBS_MANAGER_INTERFACE_H +#define OHOS_AAFWK_DATAOBS_MANAGER_INTERFACE_H + +#include + +#include +#include + +#include "data_ability_observer_interface.h" +#include "uri.h" + +namespace OHOS { +namespace AAFwk { +using Uri = OHOS::Uri; +const std::string DATAOBS_MANAGER_SERVICE_NAME = "DataObsMgrService"; +/** + * @class IDataObsMgr + * IDataObsMgr interface is used to access dataobs manager services. + */ +class IDataObsMgr : public OHOS::IRemoteBroker { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"ohos.aafwk.DataObsMgr") + + /** + * Registers an observer to DataObsMgr specified by the given Uri. + * + * @param uri, Indicates the path of the data to operate. + * @param dataObserver, Indicates the IDataAbilityObserver object. + * + * @return Returns ERR_OK on success, others on failure. + */ + virtual int RegisterObserver(const Uri &uri, const sptr &dataObserver) = 0; + + /** + * Deregisters an observer used for DataObsMgr specified by the given Uri. + * + * @param uri, Indicates the path of the data to operate. + * @param dataObserver, Indicates the IDataAbilityObserver object. + * + * @return Returns ERR_OK on success, others on failure. + */ + virtual int UnregisterObserver(const Uri &uri, const sptr &dataObserver) = 0; + + /** + * Notifies the registered observers of a change to the data resource specified by Uri. + * + * @param uri, Indicates the path of the data to operate. + * + * @return Returns ERR_OK on success, others on failure. + */ + virtual int NotifyChange(const Uri &uri) = 0; + + enum { + // ipc id 1-1000 for kit + // ipc id for RegisterObserver (1) + REGISTER_OBSERVER = 1, + + // ipc id for UnregisterObserver (2) + UNREGISTER_OBSERVER, + + // ipc id for NotifyChange (3) + NOTIFY_CHANGE, + }; +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_DATAOBS_MANAGER_INTERFACE_H diff --git a/tools/interfaces/innerkits/intent/BUILD.gn b/tools/interfaces/innerkits/intent/BUILD.gn new file mode 100644 index 00000000000..176dd580ba0 --- /dev/null +++ b/tools/interfaces/innerkits/intent/BUILD.gn @@ -0,0 +1,73 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") + +config("intent_config") { + visibility = [ ":*" ] + include_dirs = [ "//sdk/appexecfwk/appexecfwk_base/include" ] + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + defines = [ + "APP_LOG_TAG = \"Ability\"", + "LOG_DOMAIN = 0xD002200", + ] +} + +config("intent_public_config") { + visibility = [ ":*" ] + include_dirs = [ + "//utils/native/base/include", + "//foundation/aafwk/standard/interfaces/innerkits/intent/include", + "//foundation/distributedschedule/dmsfwk/services/dtbschedmgr/include", + "//foundation/appexecfwk/standard/common/log/include", + ] +} + +intentImpl = "//foundation/aafwk/standard/frameworks/kits/content/cpp/src/ohos/aafwk/content" + +ohos_shared_library("intent") { + sources = [ + "${intentImpl}/intent.cpp", + "${intentImpl}/intent_filter.cpp", + "${intentImpl}/intent_params.cpp", + + #"${intentImpl}/operation.cpp", + #"${intentImpl}/patterns_matcher.cpp", + #"${intentImpl}/skills.cpp", + #"${intentImpl}/want_params.cpp", + #"${intentImpl}/want.cpp", + ] + + deps = [ + "//foundation/aafwk/standard/interfaces/innerkits/base:base", + "//foundation/appexecfwk/standard/common:libappexecfwk_common", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//foundation/distributedschedule/safwk/interfaces/innerkits/safwk:system_ability_fwk", + "//foundation/distributedschedule/samgr/interfaces/innerkits/lsamgr:lsamgr", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] + + configs = [ ":intent_config" ] + public_configs = [ ":intent_public_config" ] + subsystem_name = "aafwk" + part_name = "aafwk_standard" +} diff --git a/tools/interfaces/innerkits/intent/include/ohos/aafwk/content/intent.h b/tools/interfaces/innerkits/intent/include/ohos/aafwk/content/intent.h new file mode 100644 index 00000000000..84f67e0fbd2 --- /dev/null +++ b/tools/interfaces/innerkits/intent/include/ohos/aafwk/content/intent.h @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef OHOS_AAFWK_INTENT_H +#define OHOS_AAFWK_INTENT_H + +#include +#include + +#include "intent_params.h" + +#include "element_name.h" +#include "parcel.h" + +namespace OHOS { +namespace AAFwk { + +class Intent final : public Parcelable { +public: + Intent(); + inline ~Intent() + {} + + static Intent *ParseUri(const std::string &uri); + std::string ToUri(); + + std::string GetAction() const; + Intent &SetAction(const std::string &action); + + unsigned int GetFlags() const; + Intent &SetFlag(const unsigned int flag); + Intent &AddFlag(const unsigned int flag); + void RemoveFlags(const unsigned int flag); + + std::string GetEntity() const; + Intent &SetEntity(const std::string &entity); + + OHOS::AppExecFwk::ElementName GetElement() const; + Intent &SetElement(const OHOS::AppExecFwk::ElementName &element); + + bool GetBoolParam(const std::string &key, const bool defaultValue); + Intent &SetBoolParam(const std::string &key, const bool value); + std::vector GetBoolArrayParam(const std::string &key); + Intent &SetBoolArrayParam(const std::string &key, const std::vector &value); + + zchar GetCharParam(const std::string &key, const zchar defaultValue); + Intent &SetCharParam(const std::string &key, const zchar value); + std::vector GetCharArrayParam(const std::string &key); + Intent &SetCharArrayParam(const std::string &key, const std::vector &value); + + byte GetByteParam(const std::string &key, const byte defaultValue); + Intent &SetByteParam(const std::string &key, const byte value); + std::vector GetByteArrayParam(const std::string &key); + Intent &SetByteArrayParam(const std::string &key, const std::vector &value); + + short GetShortParam(const std::string &key, const short defaultValue); + Intent &SetShortParam(const std::string &key, const short value); + std::vector GetShortArrayParam(const std::string &key); + Intent &SetShortArrayParam(const std::string &key, const std::vector &value); + + int GetIntParam(const std::string &key, const int defaultValue); + Intent &SetIntParam(const std::string &key, const int value); + std::vector GetIntArrayParam(const std::string &key); + Intent &SetIntArrayParam(const std::string &key, const std::vector &value); + + long GetLongParam(const std::string &key, const long defaultValue); + Intent &SetLongParam(const std::string &key, const long value); + std::vector GetLongArrayParam(const std::string &key); + Intent &SetLongArrayParam(const std::string &key, const std::vector &value); + + float GetFloatParam(const std::string &key, const float defaultValue); + Intent &SetFloatParam(const std::string &key, const float value); + std::vector GetFloatArrayParam(const std::string &key); + Intent &SetFloatArrayParam(const std::string &key, const std::vector &value); + + double GetDoubleParam(const std::string &key, const double defaultValue); + Intent &SetDoubleParam(const std::string &key, const double value); + std::vector GetDoubleArrayParam(const std::string &key); + Intent &SetDoubleArrayParam(const std::string &key, const std::vector &value); + + std::string GetStringParam(const std::string &key); + Intent &SetStringParam(const std::string &key, const std::string &value); + std::vector GetStringArrayParam(const std::string &key); + Intent &SetStringArrayParam(const std::string &key, const std::vector &value); + + bool HasParameter(const std::string &key) const; + + virtual bool Marshalling(Parcel &parcel) const; + + static Intent *Unmarshalling(Parcel &parcel); + +public: + // action definition + static const std::string ACTION_PLAY; + + // entity definition + static const std::string ENTITY_HOME; + static const std::string ENTITY_VIDEO; + + // flag definition + static constexpr unsigned int FLAG_ABILITY_NEW_MISSION = 0x00000001; + +private: + std::string action_; + unsigned int flags_; + std::string entity_; + IntentParams parameters_; + + OHOS::AppExecFwk::ElementName element_; + + static const std::string OCT_EQUALSTO; + static const std::string OCT_SEMICOLON; + + // no object in parcel + static constexpr int VALUE_NULL = -1; + // object exist in parcel + static constexpr int VALUE_OBJECT = 1; + +private: + static bool ParseFlag(const std::string &content, Intent &intent); + static std::string Decode(const std::string &str); + static std::string Encode(const std::string &str); + static bool ParseContent(const std::string &content, std::string &prop, std::string &value); + static bool ParseUriInternal(const std::string &content, OHOS::AppExecFwk::ElementName &element, Intent &intent); + bool ReadFromParcel(Parcel &parcel); +}; + +} // namespace AAFwk +} // namespace OHOS + +#endif // OHOS_AAFWK_INTENT_H diff --git a/tools/interfaces/innerkits/intent/include/ohos/aafwk/content/intent_filter.h b/tools/interfaces/innerkits/intent/include/ohos/aafwk/content/intent_filter.h new file mode 100644 index 00000000000..f45469483ce --- /dev/null +++ b/tools/interfaces/innerkits/intent/include/ohos/aafwk/content/intent_filter.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_INTENT_FILTER_H +#define OHOS_AAFWK_INTENT_FILTER_H + +#include +#include + +#include "parcel.h" + +namespace OHOS { +namespace AAFwk { + +class Intent; +class IntentFilter final : public Parcelable { +public: + IntentFilter(); + inline ~IntentFilter() + {} + + std::string GetEntity() const; + + void SetEntity(const std::string &entity); + + void AddAction(const std::string &action); + + int CountAction() const; + + std::string GetAction(int index) const; + + void RemoveAction(const std::string &action); + + bool HasAction(const std::string &action) const; + + bool Match(const Intent &intent) const; + + virtual bool Marshalling(Parcel &parcel) const; + + static IntentFilter *Unmarshalling(Parcel &parcel); + +private: + bool ReadFromParcel(Parcel &parcel); + bool MatchAction(const std::string &action) const; + bool MatchEntity(const std::string &entity) const; + + std::string entity_; + std::vector actions_; +}; + +} // namespace AAFwk +} // namespace OHOS + +#endif // OHOS_AAFWK_INTENT_FILTER_H diff --git a/tools/interfaces/innerkits/intent/include/ohos/aafwk/content/intent_params.h b/tools/interfaces/innerkits/intent/include/ohos/aafwk/content/intent_params.h new file mode 100644 index 00000000000..0936f8943f6 --- /dev/null +++ b/tools/interfaces/innerkits/intent/include/ohos/aafwk/content/intent_params.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef OHOS_AAFWK_INTENT_PARAMS_H +#define OHOS_AAFWK_INTENT_PARAMS_H + +#include +#include + +#include "ohos/aafwk/base/base_interfaces.h" +#include "refbase.h" +#include "parcel.h" + +namespace OHOS { +namespace AAFwk { + +class IntentParams final : public Parcelable { +public: + void SetParam(const std::string &key, IInterface *value); + + sptr GetParam(const std::string &key) const; + + const std::map> &GetParams() const; + + bool HasParam(const std::string &key) const; + + virtual bool Marshalling(Parcel &parcel) const; + + static IntentParams *Unmarshalling(Parcel &parcel); + +private: + // Java side should keep consistent. + enum { + VALUE_TYPE_NULL = -1, + VALUE_TYPE_BOOLEAN = 1, + VALUE_TYPE_BYTE = 2, + VALUE_TYPE_CHAR = 3, + VALUE_TYPE_SHORT = 4, + VALUE_TYPE_INT = 5, + VALUE_TYPE_LONG = 6, + VALUE_TYPE_FLOAT = 7, + VALUE_TYPE_DOUBLE = 8, + VALUE_TYPE_STRING = 9, + VALUE_TYPE_CHARSEQUENCE = 10, + VALUE_TYPE_BOOLEANARRAY = 11, + VALUE_TYPE_BYTEARRAY = 12, + VALUE_TYPE_CHARARRAY = 13, + VALUE_TYPE_SHORTARRAY = 14, + VALUE_TYPE_INTARRAY = 15, + VALUE_TYPE_LONGARRAY = 16, + VALUE_TYPE_FLOATARRAY = 17, + VALUE_TYPE_DOUBLEARRAY = 18, + VALUE_TYPE_STRINGARRAY = 19, + VALUE_TYPE_CHARSEQUENCEARRAY = 20, + }; + + bool WriteArrayToParcel(Parcel &parcel, IArray *ao) const; + bool ReadArrayToParcel(Parcel &parcel, int type, sptr &ao); + bool ReadFromParcel(Parcel &parcel); + + /* params_ has default construct function, + no need explicit initialization in the construct function */ + std::map> params_; +}; + +} // namespace AAFwk +} // namespace OHOS + +#endif // OHOS_AAFWK_INTENT_PARAMS_H diff --git a/tools/interfaces/innerkits/want/BUILD.gn b/tools/interfaces/innerkits/want/BUILD.gn new file mode 100755 index 00000000000..961ca8d9add --- /dev/null +++ b/tools/interfaces/innerkits/want/BUILD.gn @@ -0,0 +1,81 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") + +config("want_config") { + visibility = [ ":*" ] + include_dirs = [] + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + defines = [ + "APP_LOG_TAG = \"Ability\"", + "LOG_DOMAIN = 0xD002200", + ] +} + +config("want_public_config") { + visibility = [ ":*" ] + include_dirs = [ + "//utils/native/base/include", + "//foundation/aafwk/standard/interfaces/innerkits/want/include", + "//foundation/aafwk/standard/interfaces/innerkits/base/include", + "//foundation/appexecfwk/standard/common/log/include", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base/include", + "//foundation/distributedschedule/dmsfwk/services/dtbschedmgr/include", + "//foundation/aafwk/standard/interfaces/innerkits/want/include/ohos/aafwk/content", + "//foundation/aafwk/standard/frameworks/kits/content/cpp/src", + "//third_party/jsoncpp/include", + ] +} + +wantImpl = "//foundation/aafwk/standard/frameworks/kits/content/cpp/src/ohos/aafwk/content" + +ohos_shared_library("want") { + sources = [ + "${wantImpl}/extra_params.cpp", + "${wantImpl}/operation.cpp", + "${wantImpl}/operation_builder.cpp", + "${wantImpl}/pac_map.cpp", + "${wantImpl}/patterns_matcher.cpp", + "${wantImpl}/skills.cpp", + "${wantImpl}/want.cpp", + "${wantImpl}/want_params.cpp", + "${wantImpl}/want_params_wrapper.cpp", + ] + + deps = [ + "//foundation/aafwk/standard/interfaces/innerkits/base:base", + "//foundation/appexecfwk/standard/common:libappexecfwk_common", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//foundation/distributedschedule/safwk/interfaces/innerkits/safwk:system_ability_fwk", + + #"//foundation/distributeddatamgr/distributeddatamgr:build_module", + "//foundation/distributedschedule/samgr/interfaces/innerkits/lsamgr:lsamgr", + "//third_party/jsoncpp:jsoncpp", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] + + configs = [ ":want_config" ] + public_configs = [ ":want_public_config" ] + subsystem_name = "aafwk" + part_name = "aafwk_standard" +} diff --git a/tools/interfaces/innerkits/want/include/ohos/aafwk/content/extra_params.h b/tools/interfaces/innerkits/want/include/ohos/aafwk/content/extra_params.h new file mode 100644 index 00000000000..2e2d1b308c7 --- /dev/null +++ b/tools/interfaces/innerkits/want/include/ohos/aafwk/content/extra_params.h @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef FOUNDATION_APPEXECFWK_OHOS_EXTRA_PARAMS_H +#define FOUNDATION_APPEXECFWK_OHOS_EXTRA_PARAMS_H +#include "parcel.h" +#include + +using string = std::string; + +namespace OHOS { +namespace AppExecFwk { +class ExtraParams : public Parcelable { +public: + /** + * @brief A default constructor used to create an empty {@code ExtraParams} instance. + * @param none + */ + ExtraParams(); + /** + * @brief A copy constructor used to create an empty {@code ExtraParams} instance. + * @param other indicates object instance. + */ + ExtraParams(const ExtraParams &other); + /** + * @brief Overloading assignment operators to create the same object instance. + * @param other Indicates object instance. + */ + ExtraParams &operator=(const ExtraParams &other); + + /** + * @brief Judge whether the parameter of extraparam instance is equal to that of other instance parameter + * @param other Indicates object instance. + * @return returns true the parameter of extraparam instance is equal to that of other instance parameter + * otherwise false + */ + bool operator==(const ExtraParams &other) const; + + /** + * @brief A constructor used to create an {@code ExtraParams} instance based on the input parameters{@code devType}, + * {@code targetBundleName}, and {@code description}. + * + * @param devType Indicates the type of devices to be matched. This parameter can be any combination of + * {@link #DEVICETYPE_SMART_PHONE}, {@link #DEVICETYPE_SMART_PAD}, {@link #DEVICETYPE_SMART_WATCH}, and + * {@link #DEVICETYPE_SMART_TV}. + * + * @param targetBundleName Indicates the bundle name of the target application where the ability will be migrated. + * + * @param description Indicates the description used for device filtering. + * + * @param jsonParams Indicates the custom JSON parameters to be used as filter conditions. + * + * @return none + */ + ExtraParams(const std::vector &devType, const string &targetBundleName, const string &description, + const string &jsonParams); + + /** + * @brief A destructor release an empty {@code ExtraParams} instance. + * @param none + */ + ~ExtraParams(); + + /** + * @brief Sets the list of device types. + * + * @param devType Indicates the type of devices to be matched. This parameter can be any combination of + * {@link #DEVICETYPE_SMART_PHONE}, {@link #DEVICETYPE_SMART_PAD}, {@link #DEVICETYPE_SMART_WATCH}, and + * {@link #DEVICETYPE_SMART_TV}. + * + * @return none + */ + void SetDevType(const std::vector &devType); + + /** + * @brief Obtains the list of device types. + * + * @param none + * + * @return Returns the list of device types. + */ + std::vector GetDevType() const; + + /** + * @brief Sets the bundle name of the target application where ability will be migrated. + * + * @param targetBundleName Indicates the bundle name of the target application to set. + * + * @return none + */ + void SetTargetBundleName(const string &targetBundleName); + + /** + * @brief Obtains the bundle name of the target application where the ability will be migrated. + * + * @return Returns the bundle name of the target application. + * + * @return none + */ + string GetTargetBundleName() const; + + /** + * @brief Sets the description used for device filtering. + * + * @param jsonParams Indicates the device description to set. + * + * @return none + */ + void SetJsonParams(const string &jsonParams); + + /** + * @brief Obtains the custom JSON parameters used as filter conditions. + * + * @param none + * + * @return Returns the custom JSON parameters. + */ + string GetJsonParams() const; + + /** + * @brief Sets the custom JSON parameters to be used as filter conditions. + * + * @param description Indicates the custom JSON parameters to set. + * + */ + void SetDescription(const string &description); + + /** + * @brief Obtains the description used for device filtering. + * + * @param none + * + * @return Returns the description used for device filtering. + */ + string GetDescription() const; + + /** + * @brief Marshals this {@code ExtraParams} object into a {@link ohos.utils.Parcel} object. + * + * @param parcel Indicates the {@code Parcel} object for marshalling. + * + * @return Returns {@code true} if the marshalling is successful; returns {@code false} otherwise. + */ + virtual bool Marshalling(Parcel &parcel) const override; + + /** + * @brief Unmarshals this {@code ExtraParams} object from a {@link ohos.utils.Parcel} object. + * + * @param parcel Indicates the {@code Parcel} object for unmarshalling. + * + * @return Returns {@code true} if the unmarshalling is successful; returns {@code false} otherwise. + */ + static ExtraParams *Unmarshalling(Parcel &parcel); + +public: + // Indicates a smart speaker. + static constexpr char DEVICETYPE_SMART_SPEAKER[] = "00A"; + + // Indicates a desktop computer. + static constexpr char DEVICETYPE_DESKTOP_PC[] = "00B"; + + // Indicates a laptop. + static constexpr char DEVICETYPE_LAPTOP[] = "00C"; + + // Indicates a smartphone. + static constexpr char DEVICETYPE_SMART_PHONE[] = "00E"; + + // Indicates a tablet. + static constexpr char DEVICETYPE_SMART_PAD[] = "011"; + + // Indicates a smart watch. + static constexpr char DEVICETYPE_SMART_WATCH[] = "06D"; + + // Indicates a smart car. + static constexpr char DEVICETYPE_SMART_CAR[] = "083"; + + // Indicates a kids smart watch. + static constexpr char DEVICETYPE_CHILDREN_WATCH[] = "085"; + + // Indicates a smart TV. + static constexpr char DEVICETYPE_SMART_TV[] = "09C"; + +private: + string targetBundleName_; + string description_; + string jsonParams_; + std::vector devType_; +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_APPEXECFWK_OHOS_EXTRA_PARAMS_H diff --git a/tools/interfaces/innerkits/want/include/ohos/aafwk/content/match_type.h b/tools/interfaces/innerkits/want/include/ohos/aafwk/content/match_type.h new file mode 100755 index 00000000000..39d83e8e258 --- /dev/null +++ b/tools/interfaces/innerkits/want/include/ohos/aafwk/content/match_type.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef OHOS_AAFWK_MATCH_TYPE_H +#define OHOS_AAFWK_MATCH_TYPE_H + +namespace OHOS { +namespace AAFwk { +enum class MatchType { + DEFAULT = 0, + PREFIX = 1, + PATTERN = 2, + GLOBAL = 3, +}; +} +} // namespace OHOS + +#endif // OHOS_AAFWK_MATCH_TYPE_H diff --git a/tools/interfaces/innerkits/want/include/ohos/aafwk/content/operation.h b/tools/interfaces/innerkits/want/include/ohos/aafwk/content/operation.h new file mode 100644 index 00000000000..5ae563f548a --- /dev/null +++ b/tools/interfaces/innerkits/want/include/ohos/aafwk/content/operation.h @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_OPERATION_H +#define OHOS_AAFWK_OPERATION_H + +#include +#include "uri.h" +#include "parcel.h" +#include "string_ex.h" + +namespace OHOS { +namespace AAFwk { + +class OperationBuilder; + +class Operation : public Parcelable { + friend class OperationBuilder; + friend class Want; + +public: + Operation(); + ~Operation(); + Operation(const Operation &other); + /** + * @description: Obtains the value of the abilityName attribute included in this Operation. + * @return Returns the ability name included in this Operation. + */ + std::string GetAbilityName() const; + + /** + * @description: Obtains the value of the action attribute included in this Operation. + * @return Returns the action included in this Operation. + */ + std::string GetAction() const; + + /** + * @description: Obtains the value of the bundleName attribute included in this Operation. + * @return Returns the bundle name included in this Operation. + */ + std::string GetBundleName() const; + + /** + * @description: Obtains the value of the deviceId attribute included in this Operation. + * @return Returns the device ID included in this Operation. + */ + std::string GetDeviceId() const; + + /** + * @description: Obtains the value of the entities attribute included in this Operation. + * @return Returns the entities included in this Operation. + */ + const std::vector &GetEntities() const; + + /** + * @description: Obtains the value of the flags attribute included in this Operation. + * @return Returns the flags included in this Operation. + */ + unsigned int GetFlags() const; + + /** + * @description: Obtains the value of the uri attribute included in this Operation. + * @return Returns the URI included in this Operation. + */ + OHOS::Uri GetUri() const; + + bool operator==(const Operation &other) const; + Operation &operator=(const Operation &other); + + bool Marshalling(Parcel &parcel) const; + static Operation *Unmarshalling(Parcel &parcel); + + void DumpInfo(int level) const; + +private: + /** + * @description: Sets a flag in a Want. + * @param flags Indicates the flag to set. + * @return Returns this Want object containing the flag. + */ + void SetFlags(unsigned int flags); + /** + * @description: Adds a flag to a Want. + * @param flags Indicates the flag to add. + * @return Returns the Want object with the added flag. + */ + void AddFlags(unsigned int flags); + /** + * @description: Removes the description of a flag from a Want. + * @param flags Indicates the flag to remove. + * @return Removes the description of a flag from a Want. + */ + void RemoveFlags(unsigned int flags); + + /** + * @description: Adds the description of an entity to a Want + * @param entity Indicates the entity description to add + * @return Returns this Want object containing the entity. + */ + void AddEntity(const std::string &entity); + + /** + * @description: Removes the description of an entity from a Want + * @param entity Indicates the entity description to remove. + * @return void + */ + void RemoveEntity(const std::string &entity); + + /** + * @description: Checks whether a Want contains the given entity + * @param entity Indicates the entity to check + * @return Returns true if the given entity is contained; returns false otherwise + */ + bool HasEntity(const std::string &entity) const; + + /** + * @description: Obtains the number of entities in a Want + * @return Returns the entity quantity + */ + int CountEntities() const; + + /** + * @description: Sets a bundle name in this Want. + * If a bundle name is specified in a Want, the Want will match only + * the abilities in the specified bundle. You cannot use this method and + * setPicker(ohos.aafwk.content.Want) on the same Want. + * @param bundleName Indicates the bundle name to set. + * @return Returns a Want object containing the specified bundle name. + */ + void SetBundleName(const std::string &bundleName); + + /** + * @description: Sets a uri in this operation. + * @param uri Indicates uri object to set. + * @return - + */ + void SetUri(const Uri &uri); + + /** + * @description: Gets a uri in this operation. + * @param uri Indicates uri object to set. + * @return Returns a uri in this operation. + */ + Uri &GetUri(const Uri &uri); + + /** + * @description: Sets the value of the abilityName attribute included in this Operation. + * @return Returns the ability name included in this Operation. + */ + void SetAbilityName(const std::string &abilityname); + + /** + * @description: Sets the value of the deviceId attribute included in this Operation. + * @param deviceid Indicates deviceid object to set. + * @return - + */ + void SetDeviceId(const std::string &deviceid); + + /** + * @description: Sets the value of the action attribute included in this Operation. + * @param deviceid Indicates deviceid object to set. + * @return - + */ + void SetAction(const std::string &action); + + /** + * @description: Sets the entities of this Operation. + * @param entities Indicates entities to set. + * @return - + */ + void SetEntities(const std::vector &entities); + +private: + std::string abilityName_; + std::string action_; + std::string bundleName_; + std::string deviceId_; + std::vector entities_; + unsigned int flags_; + Uri uri_; + friend class OperationBuilder; + + // no object in parcel + static constexpr int VALUE_NULL = -1; + // object exist in parcel + static constexpr int VALUE_OBJECT = 1; + + bool ReadFromParcel(Parcel &parcel); +}; +} // namespace AAFwk +} // namespace OHOS + +#endif // OHOS_AAFWK_WANT_PARAMS_H \ No newline at end of file diff --git a/tools/interfaces/innerkits/want/include/ohos/aafwk/content/operation_builder.h b/tools/interfaces/innerkits/want/include/ohos/aafwk/content/operation_builder.h new file mode 100644 index 00000000000..cb887da73c2 --- /dev/null +++ b/tools/interfaces/innerkits/want/include/ohos/aafwk/content/operation_builder.h @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_OPERATION_BUILDER_H +#define OHOS_AAFWK_OPERATION_BUILDER_H +#include +#include +#include +#include "uri.h" +#include "string_ex.h" + +namespace OHOS { +namespace AAFwk { +class Operation; +class OperationBuilder { +public: + OperationBuilder(); + ~OperationBuilder(); + + /** + * @description: Sets a AbilityName in an OperationBuilder. + * @return Returns this OperationBuilder object containing the AbilityName. + */ + OperationBuilder &WithAbilityName(const std::string &abilityName); + + /** + * @description: Sets a BundleName in an OperationBuilder. + * @return Returns this OperationBuilder object containing the BundleName. + */ + OperationBuilder &WithBundleName(const std::string &bundleName); + + /** + * @description: Sets a DeviceId in an OperationBuilder. + * @return Returns this OperationBuilder object containing the DeviceId. + */ + OperationBuilder &WithDeviceId(const std::string &deviceID); + + /** + * @description: Sets a Action in an OperationBuilder. + * @return Returns this OperationBuilder object containing the Action. + */ + OperationBuilder &WithAction(const std::string &action); + + /** + * @description: Sets a Entities in an OperationBuilder. + * @return Returns this OperationBuilder object containing the Entities. + */ + OperationBuilder &WithEntities(const std::vector &entities); + + /** + * @description: Sets a Flags in an OperationBuilder. + * @return Returns this OperationBuilder object containing the Flags. + */ + OperationBuilder &WithFlags(unsigned int flags); + + /** + * @description: Sets a Uri in an OperationBuilder. + * @return Returns this OperationBuilder object containing the Uri. + */ + OperationBuilder &WithUri(const Uri &uri); + std::shared_ptr build(); + +private: + std::string abilityName_ = ""; + std::string action_ = ""; + std::string bundleName_ = ""; + std::string deviceId_ = ""; + std::vector entities_ = {}; + unsigned int flags_ = 0; + Uri uri_; +}; + +} // namespace AAFwk +} // namespace OHOS + +#endif // OHOS_AAFWK_OPERATION_BUILDER_H \ No newline at end of file diff --git a/tools/interfaces/innerkits/want/include/ohos/aafwk/content/pac_map.h b/tools/interfaces/innerkits/want/include/ohos/aafwk/content/pac_map.h new file mode 100755 index 00000000000..bc9cd164e7a --- /dev/null +++ b/tools/interfaces/innerkits/want/include/ohos/aafwk/content/pac_map.h @@ -0,0 +1,563 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_APPEXECFWK_PAC_MAP_H +#define OHOS_APPEXECFWK_PAC_MAP_H + +#include +#include +#include +#include +#include +#include +#include +#include "securec.h" +#include "json/json.h" +#include "parcel.h" +#include "ohos/aafwk/base/base_def.h" +#include "ohos/aafwk/base/base_object.h" +#include "ohos/aafwk/base/base_interfaces.h" + +// json key define +// base: 0x00000001 ~ 0x000000FF +// array: 0x00000100 ~ 0x0000FF00 +// boject: 0x00010000 ~ 0x00FF0000 +#define PACMAP_DATA_NONE 0x00 +// base data +#define PACMAP_DATA_SHORT 0x00000001 +#define PACMAP_DATA_INTEGER 0x00000002 +#define PACMAP_DATA_LONG 0x00000003 +#define PACMAP_DATA_CHAR 0x00000004 +#define PACMAP_DATA_BYTE 0x00000005 +#define PACMAP_DATA_BOOLEAN 0x00000007 +#define PACMAP_DATA_FLOAT 0x00000008 +#define PACMAP_DATA_DOUBLE 0x00000009 +#define PACMAP_DATA_STRING 0x0000000A +// array data +#define PACMAP_DATA_ARRAY_SHORT 0x00000100 +#define PACMAP_DATA_ARRAY_INTEGER 0x00000200 +#define PACMAP_DATA_ARRAY_LONG 0x00000300 +#define PACMAP_DATA_ARRAY_CHAR 0x00000400 +#define PACMAP_DATA_ARRAY_BYTE 0x00000500 +#define PACMAP_DATA_ARRAY_BOOLEAN 0x00000600 +#define PACMAP_DATA_ARRAY_FLOAT 0x00000700 +#define PACMAP_DATA_ARRAY_DOUBLE 0x00000800 +#define PACMAP_DATA_ARRAY_STRING 0x00000900 +// object data +#define PACMAP_DATA_USEROBJECT 0x00010000 +#define PACMAP_DATA_PACMAP 0x00020000 + +namespace OHOS { +namespace AppExecFwk { +namespace PacMapObject { +using INTERFACE = sptr; +}; // namespace PacMapObject + +using namespace AAFwk; +using UserObjectBase = AAFwk::UserObjectBase; +using PacMapList = std::map; + +class PacMap final : public Parcelable, public Object, public IPacMap { +public: + /** + * @brief Default constructor used to create a PacMap instance, in which the Map object has no key-value pair. + */ + PacMap() = default; + + /** + * @brief A replication structure with deep copy. + */ + PacMap(const PacMap &other); + + ~PacMap(); + + IINTERFACE_DECL(); + + /** + * @brief A overload operation with shallow copy. + */ + PacMap &operator=(const PacMap &other); + + /** + * @brief Clear all key-value pairs and free resources. + */ + void Clear(void); + + /** + * @brief Creates and returns a copy of this object with shallow copy. + * + * @return A clone of this instance. + */ + PacMap Clone(void); + + /** + * @brief Creates a deep copy of this PacMap object with deep copy. + * @param pacMap Returns the constructed object. + */ + PacMap DeepCopy(void); + void DeepCopy(PacMap &other); + + /** + * @brief Adds a short value matching a specified key. + * @param key A specified key. + * @param value The value that matches the specified key. + */ + void PutShortValue(const std::string &key, short value); + + /** + * @brief Adds a integer value matching a specified key. + * @param key A specified key. + * @param value The value that matches the specified key. + */ + void PutIntValue(const std::string &key, int value); + + /** + * @brief Adds a long value matching a specified key. + * @param key A specified key. + * @param value The value that matches the specified key. + */ + void PutLongValue(const std::string &key, long value); + + /** + * @brief Adds a boolean value matching a specified key. + * @param key A specified key. + * @param value The value that matches the specified key. + */ + void PutBooleanValue(const std::string &key, bool value); + + /** + * @brief Adds a char value matching a specified key. + * @param key A specified key. + * @param value The value that matches the specified key. + */ + void PutCharValue(const std::string &key, char value); + + /** + * @brief Adds a byte value matching a specified key. + * @param key A specified key. + * @param value The value that matches the specified key. + */ + void PutByteValue(const std::string &key, AAFwk::byte value); + + /** + * @brief Adds a float value matching a specified key. + * @param key A specified key. + * @param value The value that matches the specified key. + */ + void PutFloatValue(const std::string &key, float value); + + /** + * @brief Adds a double value matching a specified key. + * @param key A specified key. + * @param value The value that matches the specified key. + */ + void PutDoubleValue(const std::string &key, double value); + + /** + * @brief Adds a string {std::string} value matching a specified key. + * @param key A specified key. + * @param value The value that matches the specified key. + */ + void PutStringValue(const std::string &key, const std::string &value); + + /** + * @brief Adds an object value matching a specified key. The object must be a subclass of UserObjectBase. + * @param key A specified key. + * @param value A smart pointer to the object that matches the specified key. + */ + void PutObject(const std::string &key, const std::shared_ptr &value); + + /** + * @brief Adds an PacMap value matching a specified key. + * @param key A specified key. + * @param value The value that matches the specified key. + */ + bool PutPacMap(const std::string &key, const PacMap &value); + + /** + * @brief Adds some short values matching a specified key. + * @param key A specified key. + * @param value Store a list of short values. + */ + void PutShortValueArray(const std::string &key, const std::vector &value); + + /** + * @brief Adds some integer values matching a specified key. + * @param key A specified key. + * @param value Store a list of integer values. + */ + void PutIntValueArray(const std::string &key, const std::vector &value); + + /** + * @brief Adds some long values matching a specified key. + * @param key A specified key. + * @param value Store a list of long values. + */ + void PutLongValueArray(const std::string &key, const std::vector &value); + + /** + * @brief Adds some boolean values matching a specified key. + * @param key A specified key. + * @param value Store a list of boolean values. + */ + void PutBooleanValueArray(const std::string &key, const std::vector &value); + + /** + * @brief Adds some char values matching a specified key. + * @param key A specified key. + * @param value Store a list of char values. + */ + void PutCharValueArray(const std::string &key, const std::vector &value); + + /** + * @brief Adds some byte values matching a specified key. + * @param key A specified key. + * @param value Store a list of byte values. + */ + void PutByteValueArray(const std::string &key, const std::vector &value); + + /** + * @brief Adds some float values matching a specified key. + * @param key A specified key. + * @param value Store a list of float values. + */ + void PutFloatValueArray(const std::string &key, const std::vector &value); + + /** + * @brief Adds some double values matching a specified key. + * @param key A specified key. + * @param value Store a list of double values. + */ + void PutDoubleValueArray(const std::string &key, const std::vector &value); + + /** + * @brief Adds some string {std::string} values matching a specified key. + * @param key A specified key. + * @param value Store a list of string values. + */ + void PutStringValueArray(const std::string &key, const std::vector &value); + + /** + * @brief Inserts all key-value pairs of a map object into the built-in data object. + * Duplicate key values will be replaced. + * @param mapData Store a list of key-value pairs. + */ + void PutAll(std::map &mapData); + + /** + * @brief Saves the data in a PacMap object to the current object. Duplicate key values will be replaced. + * @param pacMap Store the date of PacMap. + */ + void PutAll(PacMap &pacMap); + + /** + * @brief Obtains the int value matching a specified key. + * @param key A specified key. + * @param defaultValue The return value when the function fails. + * @return If the match is successful, return the value matching the key, otherwise return the @a defaultValue. + */ + int GetIntValue(const std::string &key, int defaultValue = 0); + + /** + * @brief Obtains the short value matching a specified key. + * @param key A specified key. + * @param defaultValue The return value when the function fails. + * @return If the match is successful, return the value matching the key, otherwise return the @a defaultValue. + */ + short GetShortValue(const std::string &key, short defaultValue = 0); + + /** + * @brief Obtains the boolean value matching a specified key. + * @param key A specified key. + * @param defaultValue The return value when the function fails. + * @return If the match is successful, return the value matching the key, otherwise return the @a defaultValue. + */ + bool GetBooleanValue(const std::string &key, bool defaultValue = false); + + /** + * @brief Obtains the long value matching a specified key. + * @param key A specified key. + * @param defaultValue The return value when the function fails. + * @return If the match is successful, return the value matching the key, otherwise return the @a defaultValue. + */ + long GetLongValue(const std::string &key, long defaultValue = 0); + + /** + * @brief Obtains the char value matching a specified key. + * @param key A specified key. + * @param defaultValue The return value when the function fails. + * @return If the match is successful, return the value matching the key, otherwise return the @a defaultValue. + */ + char GetCharValue(const std::string &key, char defaultValue = 0x00); + + /** + * @brief Obtains the byte value matching a specified key. + * @param key A specified key. + * @param defaultValue The return value when the function fails. + * @return If the match is successful, return the value matching the key, otherwise return the @a defaultValue. + */ + AAFwk::byte GetByteValue(const std::string &key, AAFwk::byte defaultValue = 0x00); + + /** + * @brief Obtains the float value matching a specified key. + * @param key A specified key. + * @param defaultValue The return value when the function fails. + * @return If the match is successful, return the value matching the key, otherwise return the @a defaultValue. + */ + float GetFloatValue(const std::string &key, float defaultValue = 0.0f); + + /** + * @brief Obtains the double value matching a specified key. + * @param key A specified key. + * @param defaultValue The return value when the function fails. + * @return If the match is successful, return the value matching the key, otherwise return the @a defaultValue. + */ + double GetDoubleValue(const std::string &key, double defaultValue = 0.0); + + /** + * @brief Obtains the string {std::string} value matching a specified key. + * @param key A specified key. + * @param defaultValue The return value when the function fails. + * @return If the match is successful, return the value matching the key, otherwise return the @a defaultValue. + */ + std::string GetStringValue(const std::string &key, const std::string &defaultValue = ""); + + /** + * @brief Obtains some int values matching a specified key. + * @param key A specified key. + * @param value Save the returned int values. + */ + void GetIntValueArray(const std::string &key, std::vector &value); + + /** + * @brief Obtains some short values matching a specified key. + * @param key A specified key. + * @param value Save the returned short values. + */ + void GetShortValueArray(const std::string &key, std::vector &value); + + /** + * @brief Obtains some boolean values matching a specified key. + * @param key A specified key. + * @param value Save the returned boolean values. + */ + void GetBooleanValueArray(const std::string &key, std::vector &value); + + /** + * @brief Obtains some long values matching a specified key. + * @param key A specified key. + * @param value Save the returned long values. + */ + void GetLongValueArray(const std::string &key, std::vector &value); + + /** + * @brief Obtains some char values matching a specified key. + * @param key A specified key. + * @param value Save the returned char values. + */ + void GetCharValueArray(const std::string &key, std::vector &value); + + /** + * @brief Obtains some byte values matching a specified key. + * @param key A specified key. + * @param value Save the returned byte values. + */ + void GetByteValueArray(const std::string &key, std::vector &value); + + /** + * @brief Obtains some float values matching a specified key. + * @param key A specified key. + * @param value Save the returned float values. + */ + void GetFloatValueArray(const std::string &key, std::vector &value); + + /** + * @brief Obtains some double values matching a specified key. + * @param key A specified key. + * @param value Save the returned double values. + */ + void GetDoubleValueArray(const std::string &key, std::vector &value); + + /** + * @brief Obtains some string {std::string} values matching a specified key. + * @param key A specified key. + * @param value Save the returned string {std::string} values. + */ + void GetStringValueArray(const std::string &key, std::vector &value); + + /** + * @brief Obtains the object matching a specified key. + * @param key A specified key. + * @return Returns the smart pointer to object that matches the key. + */ + std::shared_ptr GetObject(const std::string &key); + + /** + * @brief Obtains the PacMap matching a specified key. + * @param key A specified key. + * @return Returns PacMap that matches the key. + */ + PacMap GetPacMap(const std::string &key); + + /** + * @brief Obtains all the data that has been stored with shallow copy. + * @return Returns all data in current PacMap. There is no dependency between the returned data and + * the original data. + */ + std::map GetAll(void); + + /** + * @brief Indicates whether some other object is "equal to" this one. + * @param pacMap The object with which to compare. + * @return Returns true if this object is the same as the pacMap argument; false otherwise. + */ + bool Equals(const PacMap *pacMap); + bool Equals(const PacMap &pacMap); + + /** + * @brief Checks whether the current object is empty. + * @return If there is no data, return true, otherwise return false. + */ + bool IsEmpty(void) const; + + /** + * @brief Obtains the number of key-value pairs stored in the current object. + * @return Returns the number of key-value pairs. + */ + int GetSize(void) const; + + /** + * @brief Obtains all the keys of the current object. + */ + const std::set GetKeys(void); + + /** + * @brief Checks whether a specified key is contained. + * @param key Indicates the key in String + * @return Returns true if the key is contained; returns false otherwise. + */ + bool HasKey(const std::string &key); + + /** + * @brief Deletes a key-value pair with a specified key. + * @param key Specifies the key of the deleted data. + */ + void Remove(const std::string &key); + + /** + * @brief Marshals this Sequenceable object to a Parcel. + * @param parcel Indicates the Parcel object into which the Sequenceable object has been marshaled. + * @return Marshals success returns true, otherwise returns false. + */ + virtual bool Marshalling(Parcel &parcel) const override; + + /** + * @brief Unmarshals this Sequenceable object from a Parcel. + * @param parcel Indicates the Parcel object into which the Sequenceable object has been marshaled. + * @return Unmarshals success returns a smart pointer to PacMap, otherwise returns nullptr. + */ + static PacMap *Unmarshalling(Parcel &parcel); + + /** + * @brief Save pacmap to string. + * @return Returns the string. + */ + virtual std::string ToString() override; + + /** + * @brief Restore pacmap from the string. + * @return Return true if successful, otherwise false. + */ + virtual bool FromString(const std::string &str) override; + + ErrCode GetValue(PacMap &value); + + virtual bool Equals(IObject &other) override; + + static sptr Parse(const std::string &str); + + static constexpr char SIGNATURE = 'P'; + +private: + PacMapList dataList_; + std::mutex mapLock_; + bool GetBaseJsonValue(PacMapList::const_iterator &it, Json::Value &json) const; + bool GetArrayJsonValue(PacMapList::const_iterator &it, Json::Value &json) const; + bool GetUserObjectJsonValue(PacMapList::const_iterator &it, Json::Value &json) const; + void ShallowCopyData(PacMapList &desPacMap, const PacMapList &srcPacMap); + void RemoveData(PacMapList &srcPacMap, const std::string &key); + bool EqualPacMapData(const PacMapList &leftPacMapList, const PacMapList &rightPacMapList); + bool ReadFromParcel(Parcel &parcel); + + bool ParseJson(Json::Value &data, PacMapList &mapList); + bool ParseJsonItem(PacMapList &mapList, const std::string &key, Json::Value &item); + bool ParseJsonItemArray(PacMapList &mapList, const std::string &key, Json::Value &item); + bool ParseJsonItemArrayShort(PacMapList &mapList, const std::string &key, Json::Value &item); + bool ParseJsonItemArrayInteger(PacMapList &mapList, const std::string &key, Json::Value &item); + bool ParseJsonItemArrayLong(PacMapList &mapList, const std::string &key, Json::Value &item); + bool ParseJsonItemArrayChar(PacMapList &mapList, const std::string &key, Json::Value &item); + bool ParseJsonItemArrayByte(PacMapList &mapList, const std::string &key, Json::Value &item); + bool ParseJsonItemArrayBoolean(PacMapList &mapList, const std::string &key, Json::Value &item); + bool ParseJsonItemArrayFloat(PacMapList &mapList, const std::string &key, Json::Value &item); + bool ParseJsonItemArrayDouble(PacMapList &mapList, const std::string &key, Json::Value &item); + bool ParseJsonItemArrayString(PacMapList &mapList, const std::string &key, Json::Value &item); + + bool InnerPutObjectValue(PacMapList &mapList, const std::string &key, Json::Value &item); + bool InnerPutPacMapValue(PacMapList &mapList, const std::string &key, Json::Value &item); + + bool ToJson(const PacMapList &mapList, Json::Value &dataObject) const; + + std::string MapListToString(const PacMapList &mapList) const; + bool StringToMapList(const std::string &str, PacMapList &mapList); + + void InnerPutShortValue(PacMapList &mapList, const std::string &key, short value); + void InnerPutIntValue(PacMapList &mapList, const std::string &key, int value); + void InnerPutLongValue(PacMapList &mapList, const std::string &key, long value); + void InnerPutBooleanValue(PacMapList &mapList, const std::string &key, bool value); + void InnerPutCharValue(PacMapList &mapList, const std::string &key, char value); + void InnerPutByteValue(PacMapList &mapList, const std::string &key, AAFwk::byte value); + void InnerPutFloatValue(PacMapList &mapList, const std::string &key, float value); + void InnerPutDoubleValue(PacMapList &mapList, const std::string &key, double value); + void InnerPutStringValue(PacMapList &mapList, const std::string &key, const std::string &value); + void InnerPutObject(PacMapList &mapList, const std::string &key, const std::shared_ptr &value); + bool InnerPutPacMap(PacMapList &mapList, const std::string &key, PacMap &value); + + void InnerPutShortValueArray(PacMapList &mapList, const std::string &key, const std::vector &value); + void InnerPutIntValueArray(PacMapList &mapList, const std::string &key, const std::vector &value); + void InnerPutLongValueArray(PacMapList &mapList, const std::string &key, const std::vector &value); + void InnerPutBooleanValueArray(PacMapList &mapList, const std::string &key, const std::vector &value); + void InnerPutCharValueArray(PacMapList &mapList, const std::string &key, const std::vector &value); + void InnerPutByteValueArray(PacMapList &mapList, const std::string &key, const std::vector &value); + void InnerPutFloatValueArray(PacMapList &mapList, const std::string &key, const std::vector &value); + void InnerPutDoubleValueArray(PacMapList &mapList, const std::string &key, const std::vector &value); + void InnerPutStringValueArray(PacMapList &mapList, const std::string &key, const std::vector &value); + + // char data:none + bool ToJsonArrayShort(std::vector &array, Json::Value &item, int type) const; + bool ToJsonArrayInt(std::vector &array, Json::Value &item, int type) const; + bool ToJsonArrayLong(std::vector &array, Json::Value &item, int type) const; + bool ToJsonArrayByte(std::vector &array, Json::Value &item, int type) const; + bool ToJsonArrayBoolean(std::vector &array, Json::Value &item, int type) const; + bool ToJsonArrayFloat(std::vector &array, Json::Value &item, int type) const; + bool ToJsonArrayDouble(std::vector &array, Json::Value &item, int type) const; + bool ToJsonArrayString(std::vector &array, Json::Value &item, int type) const; + + bool IsNumber(const std::string &str); + bool CompareArrayData(AAFwk::IInterface *one_interface, AAFwk::IInterface *two_interface); +}; +} // namespace AppExecFwk +} // namespace OHOS + +#endif \ No newline at end of file diff --git a/tools/interfaces/innerkits/want/include/ohos/aafwk/content/patterns_matcher.h b/tools/interfaces/innerkits/want/include/ohos/aafwk/content/patterns_matcher.h new file mode 100644 index 00000000000..ebe96cee3d5 --- /dev/null +++ b/tools/interfaces/innerkits/want/include/ohos/aafwk/content/patterns_matcher.h @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef OHOS_AAFWK_PATTERN_MATCHER_H +#define OHOS_AAFWK_PATTERN_MATCHER_H + +#include "match_type.h" + +#include +#include +#include +#include "parcel.h" +#include "string_ex.h" + +namespace OHOS { +namespace AAFwk { +class PatternsMatcher : public Parcelable, public std::enable_shared_from_this { + +public: + /** + * @brief A parameterized constructor used to create a PatternsMatcher instance. + * + */ + PatternsMatcher(); + + /** + * @brief A parameterized constructor used to create a PatternsMatcher instance. + * + * @param patternsMatcher Indicates patternsMatcher used to create a patternsMatcher instance. + */ + PatternsMatcher(const PatternsMatcher &patternsMatcher); + + /** + * @brief A parameterized constructor used to create a PatternsMatcher instance. + * + * @param pattern Indicates pattern used to create a patternsMatcher instance. + * @param type Indicates type used to create a patternsMatcher instance. + */ + PatternsMatcher(std::string pattern, MatchType type); + ~PatternsMatcher(); + + /** + * @brief Obtains the pattern. + * + * @return the specified pattern. + */ + std::string GetPattern() const; + + /** + * @brief Obtains the specified type. + * + * @return the specified type. + */ + MatchType GetType() const; + + /** + * @brief Match this PatternsMatcher against a string data. + * + * @param str The desired string to look for. + * @return Returns either a valid match constant. + */ + bool match(std::string str); + + /** + * @brief Match this PatternsMatcher against an Pattern's data. + * + * @param pattern The desired data to look for. + * @param match The full data string to match against. + * @param type The desired tyoe to look for. + * + * @return Returns either a valid match constant. + */ + static bool MatchPattern(std::string pattern, std::string match, MatchType type); + + /** + * @brief Marshals this Sequenceable object into a Parcel. + * + * @param outParcel Indicates the Parcel object to which the Sequenceable object will be marshaled. + */ + bool Marshalling(Parcel &parcel) const; + + /** + * @brief Unmarshals this Sequenceable object from a Parcel. + * + * @param inParcel Indicates the Parcel object into which the Sequenceable object has been marshaled. + */ + static PatternsMatcher *Unmarshalling(Parcel &parcel); + +private: + std::string pattern_; + MatchType type_; + +private: + /** + * @brief Match this PatternsMatcher against an Pattern's data. + * + * @param pattern The desired data to look for. + * @param match The full data string to match against. + * + * @return Returns either a valid match constant. + */ + static bool GlobPattern(std::string pattern, std::string match); + + bool ReadFromParcel(Parcel &parcel); +}; + +} // namespace AAFwk +} // namespace OHOS + +#endif // OHOS_AAFWK_PATTERN_MATCHER_H \ No newline at end of file diff --git a/tools/interfaces/innerkits/want/include/ohos/aafwk/content/skills.h b/tools/interfaces/innerkits/want/include/ohos/aafwk/content/skills.h new file mode 100755 index 00000000000..ecee7aca2c3 --- /dev/null +++ b/tools/interfaces/innerkits/want/include/ohos/aafwk/content/skills.h @@ -0,0 +1,511 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_SKILLS_H +#define OHOS_AAFWK_SKILLS_H + +#include +#include +#include "want.h" +#include "want_params.h" +#include "parcel.h" +#include "parcel_macro.h" +#include "match_type.h" +#include "patterns_matcher.h" +#include "uri.h" + +namespace OHOS { +namespace AAFwk { +class Skills final : public Parcelable { +public: + /** + * @brief Default constructor used to create a Skills instance. + * + */ + Skills(); + + /** + * @brief A parameterized constructor used to create a Skills instance. + * + * @param skills Indicates skills used to create a Skills instance. + */ + Skills(const Skills &skills); + ~Skills(); + + /** + * @brief Obtains the list of entities. + * + * @return vector of Entities. + */ + std::vector GetEntities() const; + + /** + * @brief Obtains the specified entity. + * + * @param entity Id of the specified entity. + */ + std::string GetEntity(int index) const; + + /** + * @brief Adds an entity to this Skills object. + * + * @param entity Indicates the entity to add. + */ + void AddEntity(const std::string &entity); + + /** + * @brief Checks whether the specified entity is exist. + * + * @param entity Name of the specified entity. + */ + bool HasEntity(const std::string &entity); + + /** + * @brief Remove the specified entity. + * + * @param entity Name of the specified entity. + */ + void RemoveEntity(const std::string &entity); + + /** + * @brief Obtains the count of entities. + * + */ + int CountEntities() const; + + /** + * @brief Obtains the specified action. + * + * @param actionId Id of the specified action. + */ + std::string GetAction(int index) const; + + /** + * @brief Adds an action to this Skills object. + * + * @param action Indicates the action to add. + */ + void AddAction(const std::string &action); + + /** + * @brief Checks whether the specified action is exist. + * + * @param action Name of the specified action. + */ + bool HasAction(const std::string &action); + + /** + * @brief Remove the specified action. + * + * @param action Name of the specified action. + */ + void RemoveAction(const std::string &action); + + /** + * @brief Obtains the count of actions. + * + */ + int CountActions() const; + + /** + * @brief Obtains the iterator of Actions. + * + * @return iterator of Actions. + */ + std::vector::iterator ActionsIterator(); + + /** + * @brief Obtains the iterator of Authorities. + * + * @return iterator of Authorities. + */ + std::vector::iterator AuthoritiesIterator(); + + /** + * @brief Obtains the iterator of Entities. + * + * @return iterator of Entities. + */ + std::vector::iterator EntitiesIterator(); + + /** + * @brief Obtains the iterator of Paths. + * + * @return iterator of Paths. + */ + std::vector::iterator PathsIterator(); + + /** + * @brief Obtains the iterator of Schemes parts. + * + * @return iterator of Schemes parts. + */ + std::vector::iterator SchemeSpecificPartsIterator(); + + /** + * @brief Obtains the iterator of Schemes. + * + * @return iterator of Schemes. + */ + std::vector::iterator SchemesIterator(); + + /** + * @brief Obtains the iterator of Types. + * + * @return iterator of Types. + */ + std::vector::iterator TypesIterator(); + + /** + * @brief Obtains the specified authority. + * + * @param authorityId Id of the specified authority. + */ + std::string GetAuthority(int index) const; + + /** + * @brief Adds an authority to this Skills object. + * + * @param authority Indicates the authority to add. + */ + void AddAuthority(const std::string &authority); + + /** + * @brief Checks whether the specified authority is exist. + * + * @param authority Name of the specified authority. + */ + bool HasAuthority(const std::string &authority); + + /** + * @brief Remove the specified authority. + * + * @param authority Name of the specified authority. + */ + void RemoveAuthority(const std::string &authority); + + /** + * @brief Obtains the count of authorities. + * + */ + int CountAuthorities() const; + + /** + * @brief Obtains the specified path. + * + * @param pathId Id of the specified path. + */ + std::string GetPath(int index) const; + + /** + * @brief Adds a path to this Skills object. + * + * @param path Indicates the path to add. + */ + void AddPath(const std::string &path); + + /** + * @brief Adds a path to this Skills object. + * + * @param path Indicates the path to add. + */ + void AddPath(const PatternsMatcher &patternsMatcher); + + /** + * @brief Adds a path to this Skills object. + * + * @param path Indicates the path to add. + * @param matchType the specified match type. + */ + void AddPath(const std::string &path, const MatchType &matchType); + + /** + * @brief Checks whether the specified path is exist. + * + * @param path Name of the specified path. + */ + bool HasPath(const std::string &path); + + /** + * @brief Remove the specified path. + * + * @param path Name of the specified path. + */ + void RemovePath(const std::string &path); + + /** + * @brief Remove the specified path. + * + * @param path The path to be added. + */ + void RemovePath(const PatternsMatcher &patternsMatcher); + + /** + * @brief Remove the specified path. + * + * @param path Name of the specified path. + * @param matchType the specified match type. + */ + void RemovePath(const std::string &path, const MatchType &matchType); + + /** + * @brief Obtains the count of paths. + * + */ + int CountPaths() const; + + /** + * @brief Obtains the specified scheme. + * + * @param schemeId Id of the specified scheme. + */ + std::string GetScheme(int index) const; + + /** + * @brief Adds an scheme to this Skills object. + * + * @param scheme Indicates the scheme to add. + */ + void AddScheme(const std::string &scheme); + + /** + * @brief Checks whether the specified scheme is exist. + * + * @param scheme Name of the specified scheme. + */ + bool HasScheme(const std::string &scheme); + + /** + * @brief Remove the specified scheme. + * + * @param scheme Name of the specified scheme. + */ + void RemoveScheme(const std::string &scheme); + + /** + * @brief Obtains the count of schemes. + * + */ + int CountSchemes() const; + + /** + * @brief Obtains the specified scheme part. + * + * @param schemeId Id of the specified scheme part. + */ + std::string GetSchemeSpecificPart(int index) const; + + /** + * @brief Adds an scheme to this Skills object. + * + * @param scheme Indicates the scheme to add. + */ + void AddSchemeSpecificPart(const std::string &schemeSpecificPart); + + /** + * @brief Checks whether the specified scheme part is exist. + * + * @param scheme Name of the specified scheme part. + */ + bool HasSchemeSpecificPart(const std::string &schemeSpecificPart); + + /** + * @brief Remove the specified scheme part. + * + * @param scheme Name of the specified scheme part. + */ + void RemoveSchemeSpecificPart(const std::string &schemeSpecificPart); + + /** + * @brief Obtains the count of scheme parts. + * + */ + int CountSchemeSpecificParts() const; + + /** + * @brief Obtains the specified type. + * + * @param typeId Id of the specified type. + */ + std::string GetType(int index) const; + + /** + * @brief Adds a type to this Skills object. + * + * @param type Indicates the type to add. + */ + void AddType(const std::string &type); + + /** + * @brief Adds a type to this Skills object. + * + * @param type Indicates the type to add. + */ + void AddType(const PatternsMatcher &patternsMatcher); + + /** + * @brief Adds a type to this Skills object. + * + * @param type Indicates the type to add. + * @param matchType the specified match type. + */ + void AddType(const std::string &type, const MatchType &matchType); + + /** + * @brief Checks whether the specified type is exist. + * + * @param type Name of the specified type. + */ + bool HasType(const std::string &type); + + /** + * @brief Remove the specified type. + * + * @param type Name of the specified type. + */ + void RemoveType(const std::string &type); + + /** + * @brief Remove the specified scheme type. + * + * @param type The type to be added. + */ + void RemoveType(const PatternsMatcher &patternsMatcher); + + /** + * @brief Remove the specified scheme type. + * + * @param type Name of the specified type. + * @param matchType the specified match type. + */ + void RemoveType(const std::string &type, const MatchType &matchType); + + /** + * @brief Obtains the count of types. + * + */ + int CountTypes() const; + + /** + * @brief Match this skill against a Want's data. + * + * @param want The desired want data to match for. + */ + bool Match(const Want &want); + + /** + * @brief Obtains the want params data. + * + * @return the WantParams object. + */ + const WantParams &GetWantParams() const; + + /** + * @brief Sets a WantParams object in this MatchingSkills object. + * + * @param wantParams Indicates the WantParams object. + */ + void SetWantParams(const WantParams &wantParams); + + /** + * @brief Marshals this Sequenceable object into a Parcel. + * + * @param outParcel Indicates the Parcel object to which the Sequenceable object will be marshaled. + */ + bool Marshalling(Parcel &parcel) const; + + /** + * @brief Unmarshals this Sequenceable object from a Parcel. + * + * @param inParcel Indicates the Parcel object into which the Sequenceable object has been marshaled. + */ + static Skills *Unmarshalling(Parcel &parcel); + +private: + static const int DISMATCH_TYPE = -101; + static const int DISMATCH_DATA = -102; + static const int DISMATCH_ACTION = -103; + static const int DISMATCH_ENTITIES = -104; + + static const int RESULT_EMPTY = 0x10000; + static const int RESULT_SCHEME = 0x20000; + static const int RESULT_PATH = 0x50000; + static const int RESULT_SCHEME_SPECIFIC_PART = 0x58000; + static const int RESULT_TYPE = 0x60000; + static const int RESULT_NORMAL = 0x800; + + std::vector entities_; + std::vector actions_; + std::vector authorities_; + std::vector schemes_; + + std::vector paths_; + std::vector schemeSpecificParts_; + std::vector types_; + + WantParams wantParams_; + bool hasPartialTypes_ = false; + + // no object in parcel + static constexpr int VALUE_NULL = -1; + // object exist in parcel + static constexpr int VALUE_OBJECT = 1; + +private: + bool ReadFromParcel(Parcel &parcel); + + /** + * @brief Match this skills against a Want's action. If the skills does not + * specify any actions, the match will always fail. + * + * @param action The desired action to look for. + * + * @return True if the action is listed in the skills. + */ + bool MatchAction(const std::string &action); + + /** + * @brief Match this skills against a Want's data (type, scheme and path). + * + * @param type The desired data type to look for. + * @param scheme The desired data scheme to look for. + * @param data The full data string to match against. + * + * @return Returns either a valid match constant. + */ + int MatchData(const std::string &type, const std::string &scheme, Uri data); + + bool FindMimeType(const std::string &type); + + bool RegionMatches(const std::string &type, int toffset, const std::string &other, int ooffset, int len); + + /** + * @brief Match this skills against a Want's entities. Each entity in + * the Want must be specified by the skills; if any are not in the + * skills, the match fails. + * + * @param entities The entities included in the want, as returned by + * Want.getEntities(). + * + * @return If all entities match (success), null; else the name of the + * first entity that didn't match. + */ + std::string MatchEntities(const std::vector &entities); +}; + +} // namespace AAFwk +} // namespace OHOS + +#endif // OHOS_AAFWK_SKILLS_H diff --git a/tools/interfaces/innerkits/want/include/ohos/aafwk/content/want.h b/tools/interfaces/innerkits/want/include/ohos/aafwk/content/want.h new file mode 100755 index 00000000000..c09b1dd4419 --- /dev/null +++ b/tools/interfaces/innerkits/want/include/ohos/aafwk/content/want.h @@ -0,0 +1,804 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_WANT_H +#define OHOS_AAFWK_WANT_H + +#include +#include +#include + +#include "uri.h" +#include "want_params.h" +#include "element_name.h" +#include "operation.h" +#include "parcel.h" + +using Operation = OHOS::AAFwk::Operation; + +namespace OHOS { +namespace AAFwk { +class Want final : public Parcelable { +public: + /** + * Indicates the grant to perform read operations on the URI. + */ + static constexpr unsigned int FLAG_AUTH_READ_URI_PERMISSION = 0x00000001; + /** + * Indicates the grant to perform write operations on the URI. + */ + static constexpr unsigned int FLAG_AUTH_WRITE_URI_PERMISSION = 0x00000002; + /** + * Returns the result to the source ability. + */ + static constexpr unsigned int FLAG_ABILITY_FORWARD_RESULT = 0x00000004; + /** + * Determines whether an ability on the local device can be migrated to a remote device. + */ + static constexpr unsigned int FLAG_ABILITY_CONTINUATION = 0x00000008; + /** + * Specifies whether a component does not belong to OHOS. + */ + static constexpr unsigned int FLAG_NOT_OHOS_COMPONENT = 0x00000010; + /** + * Specifies whether an ability is started. + */ + static constexpr unsigned int FLAG_ABILITY_FORM_ENABLED = 0x00000020; + /** + * Indicates the grant for possible persisting on the URI. + */ + static constexpr unsigned int FLAG_AUTH_PERSISTABLE_URI_PERMISSION = 0x00000040; + /** + * Returns the result to the source ability slice. + */ + static constexpr unsigned int FLAG_AUTH_PREFIX_URI_PERMISSION = 0x00000080; + /** + * Supports multi-device startup in the distributed scheduling system. + */ + static constexpr unsigned int FLAG_ABILITYSLICE_MULTI_DEVICE = 0x00000100; + /** + * Indicates that an ability using the Service template is started regardless of whether the host application has + * been started. + */ + static constexpr unsigned int FLAG_START_FOREGROUND_ABILITY = 0x00000200; + + /** + * Indicates the continuation is reversible. + */ + static constexpr unsigned int FLAG_ABILITY_CONTINUATION_REVERSIBLE = 0x00000400; + + /** + * Install the specified ability if it's not installed. + */ + static constexpr unsigned int FLAG_INSTALL_ON_DEMAND = 0x00000800; + /** + * Returns the result to the source ability slice. + */ + static constexpr unsigned int FLAG_ABILITYSLICE_FORWARD_RESULT = 0x04000000; + /** + * Install the specifiedi ability with background mode if it's not installed. + */ + static constexpr unsigned int FLAG_INSTALL_WITH_BACKGROUND_MODE = 0x80000000; + + /** + * @description: Default construcotr of Want class, which is used to initialzie flags and URI. + * @param None + * @return None + */ + Want(); + + /** + * @description: Default deconstructor of Want class + * @param None + * @return None + */ + ~Want(); + + /** + * @description: Copy construcotr of Want class, which is used to initialzie flags, URI, etc. + * @param want the source instance of Want. + * @return None + */ + Want(const Want &want); + Want &operator=(const Want &); + + /** + * @description: Sets a flag in a Want. + * @param flags Indicates the flag to set. + * @return Returns this Want object containing the flag. + */ + Want &SetFlags(unsigned int flags); + + /** + * @description: Obtains the description of flags in a Want. + * @return Returns the flag description in the Want. + */ + unsigned int GetFlags() const; + + /** + * @description: Adds a flag to a Want. + * @param flags Indicates the flag to add. + * @return Returns the Want object with the added flag. + */ + Want &AddFlags(unsigned int flags); + + /** + * @description: Removes the description of a flag from a Want. + * @param flags Indicates the flag to remove. + * @return Removes the description of a flag from a Want. + */ + void RemoveFlags(unsigned int flag); + + /** + * @description: Sets the bundleName and abilityName attributes for this Want object. + * @param bundleName Indicates the bundleName to set for the operation attribute in the Want. + * @param abilityName Indicates the abilityName to set for the operation attribute in the Want. + * @return Returns this Want object that contains the specified bundleName and abilityName attributes. + */ + Want &SetElementName(const std::string &bundleName, const std::string &abilityName); + + /** + * @description: Sets the bundleName and abilityName attributes for this Want object. + * @param deviceId Indicates the deviceId to set for the operation attribute in the Want. + * @param bundleName Indicates the bundleName to set for the operation attribute in the Want. + * @param abilityName Indicates the abilityName to set for the operation attribute in the Want. + * @return Returns this Want object that contains the specified bundleName and abilityName attributes. + */ + Want &SetElementName(const std::string &deviceId, const std::string &bundleName, const std::string &abilityName); + + /** + * @description: Sets an ElementName object in a Want. + * @param element Indicates the ElementName description. + * @return Returns this Want object containing the ElementName + */ + Want &SetElement(const OHOS::AppExecFwk::ElementName &element); + + /** + * @description: Obtains the description of the ElementName object in a Want. + * @return Returns the ElementName description in the Want. + */ + OHOS::AppExecFwk::ElementName GetElement() const; + + /** + * @description: Creates a want with its corresponding attributes specified for starting the main ability of an + * application. + * @param ElementName Indicates the ElementName object defining the deviceId, bundleName, + * and abilityName sub-attributes of the operation attribute in a want. + * @return Returns the want object used to start the main ability of an application. + */ + static Want *MakeMainAbility(const OHOS::AppExecFwk::ElementName &elementName); + + /** + * @description: Creates a Want instance by using a given Uniform Resource Identifier (URI). + * This method parses the input URI and saves it in a Want object. + * @param uri Indicates the URI to parse. + * @return Returns a Want object containing the URI. + */ + static Want *WantParseUri(const char *uri); + + /** + * @description: Creates a Want instance by using a given Uniform Resource Identifier (URI). + * This method parses the input URI and saves it in a Want object. + * @param uri Indicates the URI to parse. + * @return Returns a Want object containing the URI. + */ + static Want *ParseUri(const std::string &uri); + + /** + * @description: Obtains the description of a URI in a Want. + * @return Returns the URI description in the Want. + */ + Uri GetUri() const; + + /** + * @description: Obtains the string representation of the URI in this Want. + * @return Returns the string of the URI. + */ + std::string GetUriString() const; + + /** + * @description: Sets the description of a URI in a Want. + * @param uri Indicates the URI description. + * @return Returns this Want object containing the URI. + */ + Want &SetUri(const std::string &uri); + + /** + * @description: Sets the description of a URI in a Want. + * @param uri Indicates the URI description. + * @return Returns this Want object containing the URI. + */ + Want &SetUri(const Uri &uri); + + /** + * @description: Sets the description of a URI and a type in this Want. + * @param uri Indicates the URI description. + * @param type Indicates the type description. + * @return Returns the Want object containing the URI and the type by setting. + */ + Want &SetUriAndType(const Uri &uri, const std::string &type); + + /** + * @description: Converts a Want into a URI string containing a representation of it. + * @param want Indicates the want description.--Want. + * @return Returns a encoding URI string describing the Want object. + */ + std::string WantToUri(Want &want); + + /** + * @description: Converts parameter information in a Want into a URI string. + * @return Returns the URI string. + */ + std::string ToUri() const; + + /** + * @description: Formats a specified URI. + * This method uses the Uri.getLowerCaseScheme() method to format a URI and then saves + * the formatted URI to this Want object. + * @param uri Indicates the string of URI to format. + * @return Returns this Want object that contains the formatted uri attribute. + */ + Want &FormatUri(const std::string &uri); + + /** + * @description: Formats a specified URI. + * This method uses the Uri.getLowerCaseScheme() method to format a URI and then saves + * the formatted URI to this Want object. + * @param uri Indicates the URI to format. + * @return Returns this Want object that contains the formatted URI attribute. + */ + Want &FormatUri(const Uri &uri); + + /** + * @description: Obtains the description of an action in a want. + * @return Returns a Want object that contains the action description. + */ + std::string GetAction() const; + + /** + * @description: Sets the description of an action in a want. + * @param action Indicates the action description to set. + * @return Returns a Want object that contains the action description. + */ + Want &SetAction(const std::string &action); + + /** + * @description: Obtains the name of the specified bundle in a Want. + * @return Returns the specified bundle name in the Want. + */ + std::string GetBundle() const; + + /** + * @description: Sets a bundle name in this Want. + * If a bundle name is specified in a Want, the Want will match only + * the abilities in the specified bundle. You cannot use this method and + * setPicker(ohos.aafwk.content.Want) on the same Want. + * @param bundleName Indicates the bundle name to set. + * @return Returns a Want object containing the specified bundle name. + */ + Want &SetBundle(const std::string &bundleName); + + /** + * @description: Obtains the description of all entities in a Want + * @return Returns a set of entities + */ + const std::vector &GetEntities() const; + + /** + * @description: Adds the description of an entity to a Want + * @param entity Indicates the entity description to add + * @return {Want} Returns this Want object containing the entity. + */ + Want &AddEntity(const std::string &entity); + + /** + * @description: Removes the description of an entity from a Want + * @param entity Indicates the entity description to remove. + * @return void + */ + void RemoveEntity(const std::string &entity); + + /** + * @description: Checks whether a Want contains the given entity + * @param entity Indicates the entity to check + * @return Returns true if the given entity is contained; returns false otherwise + */ + bool HasEntity(const std::string &key) const; + + /** + * @description: Obtains the number of entities in a Want + * @return Returns the entity quantity + */ + int CountEntities(); + + /** + * @description: Obtains the description of the URI scheme in this want. + * @return Returns the URI scheme description in this want. + */ + const std::string GetScheme() const; + + /** + * @description: Obtains the description of the type in this Want + * @return Returns the type description in this Want + */ + std::string GetType() const; + + /** + * @description: Sets the description of a type in this Want + * @param type Indicates the type description + * @return Returns this Want object containing the type + */ + Want &SetType(const std::string &type); + + /** + * @description: Formats a specified MIME type. This method uses + * the formatMimeType(java.lang.String) method to format a MIME type + * and then saves the formatted type to this Want object. + * @param type Indicates the MIME type to format + * @return Returns this Want object that contains the formatted type attribute + */ + Want &FormatType(const std::string &type); + + /** + * @description: Formats a specified URI and MIME type. + * This method works in the same way as formatUri(ohos.utils.net.URI) + * and formatType(java.lang.String). + * @param uri Indicates the URI to format. + * @param type Indicates the MIME type to format. + * @return Returns this Want object that contains the formatted URI and type attributes. + */ + Want &FormatUriAndType(const Uri &uri, const std::string &type); + + /** + * @description: This method formats data of a specified MIME type + * by removing spaces from the data and converting the data into + * lowercase letters. You can use this method to normalize + * the external data used to create Want information. + * @param type Indicates the MIME type to format + * @return Returns this Want object that contains the formatted type attribute + */ + static std::string FormatMimeType(const std::string &mimeType); + + /** + * @description: clear the specific want object. + * @param want Indicates the want to clear + */ + static void ClearWant(Want *want); + + /** + * @description: Obtains the description of the WantParams object in a Want + * @return Returns the WantParams description in the Want + */ + const WantParams &GetParams() const; + + /** + * @description: Sets a wantParams object in a want. + * @param wantParams Indicates the wantParams description. + * @return Returns this want object containing the wantParams. + */ + Want &SetParams(const WantParams &wantParams); + + /** + * @description: Obtains a bool-type value matching the given key. + * @param key Indicates the key of WantParams. + * @param defaultValue Indicates the default bool-type value. + * @return Returns the bool-type value of the parameter matching the given key; + * returns the default value if the key does not exist. + */ + bool GetBoolParam(const std::string &key, bool defaultValue) const; + + /** + * @description: Obtains a bool-type array matching the given key. + * @param key Indicates the key of WantParams. + * @return Returns the bool-type array of the parameter matching the given key; + * returns null if the key does not exist. + */ + std::vector GetBoolArrayParam(const std::string &key) const; + + /** + * @description: Sets a parameter value of the boolean type. + * @param key Indicates the key matching the parameter. + * @param value Indicates the boolean value of the parameter. + * @return Returns this want object containing the parameter value. + */ + Want &SetParam(const std::string &key, bool value); + + /** + * @description: Sets a parameter value of the boolean array type. + * @param key Indicates the key matching the parameter. + * @param value Indicates the boolean array of the parameter. + * @return Returns this want object containing the parameter value. + */ + Want &SetParam(const std::string &key, const std::vector &value); + + /** + * @description: Obtains a byte-type value matching the given key. + * @param key Indicates the key of WantParams. + * @param defaultValue Indicates the default byte-type value. + * @return Returns the byte-type value of the parameter matching the given key; + * returns the default value if the key does not exist. + */ + byte GetByteParam(const std::string &key, byte defaultValue) const; + + /** + * @description: Obtains a byte-type array matching the given key. + * @param key Indicates the key of WantParams. + * @return Returns the byte-type array of the parameter matching the given key; + * returns null if the key does not exist. + */ + std::vector GetByteArrayParam(const std::string &key) const; + + /** + * @description: Sets a parameter value of the byte type. + * @param key Indicates the key matching the parameter. + * @param value Indicates the byte-type value of the parameter. + * @return Returns this Want object containing the parameter value. + */ + Want &SetParam(const std::string &key, byte value); + + /** + * @description: Sets a parameter value of the byte array type. + * @param key Indicates the key matching the parameter. + * @param value Indicates the byte array of the parameter. + * @return Returns this Want object containing the parameter value. + */ + Want &SetParam(const std::string &key, const std::vector &value); + + /** + * @description: Obtains a char value matching the given key. + * @param key Indicates the key of wnatParams. + * @param value Indicates the default char value. + * @return Returns the char value of the parameter matching the given key; + * returns the default value if the key does not exist. + */ + zchar GetCharParam(const std::string &key, zchar defaultValue) const; + + /** + * @description: Obtains a char array matching the given key. + * @param key Indicates the key of wantParams. + * @return Returns the char array of the parameter matching the given key; + * returns null if the key does not exist. + */ + std::vector GetCharArrayParam(const std::string &key) const; + + /** + * @description: Sets a parameter value of the char type. + * @param key Indicates the key of wantParams. + * @param value Indicates the char value of the parameter. + * @return Returns this want object containing the parameter value. + */ + Want &SetParam(const std::string &key, zchar value); + + /** + * @description: Sets a parameter value of the char array type. + * @param key Indicates the key of wantParams. + * @param value Indicates the char array of the parameter. + * @return Returns this want object containing the parameter value. + */ + Want &SetParam(const std::string &key, const std::vector &value); + + /** + * @description: Obtains an int value matching the given key. + * @param key Indicates the key of wantParams. + * @param value Indicates the default int value. + * @return Returns the int value of the parameter matching the given key; + * returns the default value if the key does not exist. + */ + int GetIntParam(const std::string &key, int defaultValue) const; + + /** + * @description: Obtains an int array matching the given key. + * @param key Indicates the key of wantParams. + * @return Returns the int array of the parameter matching the given key; + * returns null if the key does not exist. + */ + std::vector GetIntArrayParam(const std::string &key) const; + + /** + * @description: Sets a parameter value of the int type. + * @param key Indicates the key matching the parameter. + * @param value Indicates the int value of the parameter. + * @return Returns this Want object containing the parameter value. + */ + Want &SetParam(const std::string &key, int value); + + /** + * @description: Sets a parameter value of the int array type. + * @param key Indicates the key matching the parameter. + * @param value Indicates the int array of the parameter. + * @return Returns this Want object containing the parameter value. + */ + Want &SetParam(const std::string &key, const std::vector &value); + + /** + * @description: Obtains a double value matching the given key. + * @param key Indicates the key of wantParams. + * @param defaultValue Indicates the default double value. + * @return Returns the double value of the parameter matching the given key; + * returns the default value if the key does not exist. + */ + double GetDoubleParam(const std::string &key, double defaultValue) const; + + /** + * @description: Obtains a double array matching the given key. + * @param key Indicates the key of WantParams. + * @return Returns the double array of the parameter matching the given key; + * returns null if the key does not exist. + */ + std::vector GetDoubleArrayParam(const std::string &key) const; + + /** + * @description: Sets a parameter value of the double type. + * @param key Indicates the key matching the parameter. + * @param value Indicates the int value of the parameter. + * @return Returns this Want object containing the parameter value. + */ + Want &SetParam(const std::string &key, double value); + + /** + * @description: Sets a parameter value of the double array type. + * @param key Indicates the key matching the parameter. + * @param value Indicates the double array of the parameter. + * @return Returns this want object containing the parameter value. + */ + Want &SetParam(const std::string &key, const std::vector &value); + + /** + * @description: Obtains a float value matching the given key. + * @param key Indicates the key of wnatParams. + * @param value Indicates the default float value. + * @return Returns the float value of the parameter matching the given key; + * returns the default value if the key does not exist. + */ + float GetFloatParam(const std::string &key, float defaultValue) const; + + /** + * @description: Obtains a float array matching the given key. + * @param key Indicates the key of WantParams. + * @return Obtains a float array matching the given key. + */ + std::vector GetFloatArrayParam(const std::string &key) const; + + /** + * @description: Sets a parameter value of the float type. + * @param key Indicates the key matching the parameter. + * @param value Indicates the byte-type value of the parameter. + * @return Returns this Want object containing the parameter value. + */ + Want &SetParam(const std::string &key, float value); + + /** + * @description: Sets a parameter value of the float array type. + * @param key Indicates the key matching the parameter. + * @param value Indicates the byte-type value of the parameter. + * @return Returns this Want object containing the parameter value. + */ + Want &SetParam(const std::string &key, const std::vector &value); + + /** + * @description: Obtains a long value matching the given key. + * @param key Indicates the key of wantParams. + * @param value Indicates the default long value. + * @return Returns the long value of the parameter matching the given key; + * returns the default value if the key does not exist. + */ + long GetLongParam(const std::string &key, long defaultValue) const; + + /** + * @description: Obtains a long array matching the given key. + * @param key Indicates the key of wantParams. + * @return Returns the long array of the parameter matching the given key; + * returns null if the key does not exist. + */ + std::vector GetLongArrayParam(const std::string &key) const; + + /** + * @description: Sets a parameter value of the long type. + * @param key Indicates the key matching the parameter. + * @param value Indicates the byte-type value of the parameter. + * @return Returns this Want object containing the parameter value. + */ + Want &SetParam(const std::string &key, long value); + + /** + * @description: Sets a parameter value of the long array type. + * @param key Indicates the key matching the parameter. + * @param value Indicates the byte-type value of the parameter. + * @return Returns this Want object containing the parameter value. + */ + Want &SetParam(const std::string &key, const std::vector &value); + + /** + * @description: a short value matching the given key. + * @param key Indicates the key of wantParams. + * @param defaultValue Indicates the default short value. + * @return Returns the short value of the parameter matching the given key; + * returns the default value if the key does not exist. + */ + short GetShortParam(const std::string &key, short defaultValue) const; + + /** + * @description: Obtains a short array matching the given key. + * @param key Indicates the key of wantParams. + * @return Returns the short array of the parameter matching the given key; + * returns null if the key does not exist. + */ + std::vector GetShortArrayParam(const std::string &key) const; + + /** + * @description: Sets a parameter value of the short type. + * @param key Indicates the key matching the parameter. + * @param value Indicates the byte-type value of the parameter. + * @return Returns this Want object containing the parameter value. + */ + Want &SetParam(const std::string &key, short value); + + /** + * @description: Sets a parameter value of the short array type. + * @param key Indicates the key matching the parameter. + * @param value Indicates the byte-type value of the parameter. + * @return Returns this Want object containing the parameter value. + */ + Want &SetParam(const std::string &key, const std::vector &value); + + /** + * @description: Obtains a string value matching the given key. + * @param key Indicates the key of wantParams. + * @return Returns the string value of the parameter matching the given key; + * returns null if the key does not exist. + */ + std::string GetStringParam(const std::string &key) const; + + /** + * @description: Obtains a string array matching the given key. + * @param key Indicates the key of wantParams. + * @return Returns the string array of the parameter matching the given key; + * returns null if the key does not exist. + */ + std::vector GetStringArrayParam(const std::string &key) const; + + /** + * @description: Sets a parameter value of the string type. + * @param key Indicates the key matching the parameter. + * @param value Indicates the byte-type value of the parameter. + * @return Returns this Want object containing the parameter value. + */ + Want &SetParam(const std::string &key, const std::string &value); + + /** + * @description: Sets a parameter value of the string array type. + * @param key Indicates the key matching the parameter. + * @param value Indicates the byte-type value of the parameter. + * @return Returns this Want object containing the parameter value. + */ + Want &SetParam(const std::string &key, const std::vector &value); + + /** + * @description: Checks whether a Want contains the parameter matching a given key. + * @param key Indicates the key. + * @return Returns true if the Want contains the parameter; returns false otherwise. + */ + bool HasParameter(const std::string &key) const; + + /** + * @description: Replaces parameters in this Want object with those in the given WantParams object. + * @param wantParams Indicates the WantParams object containing the new parameters. + * @return Returns this Want object containing the new parameters. + */ + Want *ReplaceParams(WantParams &wantParams); + + /** + * @description: Replaces parameters in this Want object with those in the given Want object. + * @param want Indicates the Want object containing the new parameters. + * @return Returns this Want object containing the new parameters. + */ + Want *ReplaceParams(Want &want); + + /** + * @description: Removes the parameter matching the given key. + * @param key Indicates the key matching the parameter to be removed. + */ + void RemoveParam(const std::string &key); + + /** + * @description: Gets the description of an operation in a Want. + * @return Returns the operation included in this Want. + */ + Operation GetOperation() const; + + /** + * @description: Sets the description of an operation in a Want. + * @param operation Indicates the operation description. + */ + void SetOperation(const OHOS::AAFwk::Operation &operation); + + /** + * @description: Sets the description of an operation in a Want. + * @param want Indicates the Want object to compare. + * @return Returns true if the operation components of the two objects are equal; returns false otherwise. + */ + bool OperationEquals(const Want &want); + + /** + * @description: Creates a Want object that contains only the operation component of this Want. + * @return Returns the created Want object. + */ + Want *CloneOperation(); + + /** + * @description: Marshals a Want into a Parcel. + * Fields in the Want are marshalled separately. If any field fails to be marshalled, false is returned. + * @param parcel Indicates the Parcel object for marshalling. + * @return Returns true if the marshalling is successful; returns false otherwise. + */ + virtual bool Marshalling(Parcel &parcel) const; + + /** + * @description: Unmarshals a Want from a Parcel. + * Fields in the Want are unmarshalled separately. If any field fails to be unmarshalled, false is returned. + * @param parcel Indicates the Parcel object for unmarshalling. + * @return Returns true if the unmarshalling is successful; returns false otherwise. + */ + static Want *Unmarshalling(Parcel &parcel); + + void DumpInfo(int level) const; + +public: + // action definition + static const std::string ACTION_PLAY; + static const std::string ACTION_HOME; + + // entity definition + static const std::string ENTITY_HOME; + static const std::string ENTITY_VIDEO; + static const std::string FLAG_HOME_INTENT_FROM_SYSTEM; + + // flag definition + static unsigned int FLAG_ABILITY_NEW_MISSION; + static unsigned int FLAG_ABILITY_CLEAR_MISSION; + + static constexpr int HEX_STRING_BUF_LEN = 36; + static constexpr int HEX_STRING_LEN = 10; + +private: + WantParams parameters_; + Operation operation_; + Want *picker_; + + static const std::string OCT_EQUALSTO; + static const std::string OCT_SEMICOLON; + static const std::string MIME_TYPE; + static const std::string WANT_HEADER; + + // no object in parcel + static constexpr int VALUE_NULL = -1; + // object exist in parcel + static constexpr int VALUE_OBJECT = 1; + +private: + static bool ParseFlag(const std::string &content, Want &want); + static std::string Decode(const std::string &str); + static std::string Encode(const std::string &str); + static bool ParseContent(const std::string &content, std::string &prop, std::string &value); + static bool ParseUriInternal(const std::string &content, OHOS::AppExecFwk::ElementName &element, Want &want); + bool ReadFromParcel(Parcel &parcel); + static bool CheckAndSetParameters(Want &want, const std::string &key, std::string &prop, const std::string &value); + Uri GetLowerCaseScheme(const Uri &uri); + void ToUriStringInner(std::string &uriString) const; +}; +} // namespace AAFwk +} // namespace OHOS + +#endif // OHOS_AAFWK_WANT_H \ No newline at end of file diff --git a/tools/interfaces/innerkits/want/include/ohos/aafwk/content/want_params.h b/tools/interfaces/innerkits/want/include/ohos/aafwk/content/want_params.h new file mode 100755 index 00000000000..dac9a378195 --- /dev/null +++ b/tools/interfaces/innerkits/want/include/ohos/aafwk/content/want_params.h @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef OHOS_AAFWK_WANT_PARAMS_H +#define OHOS_AAFWK_WANT_PARAMS_H + +#include +#include +#include +#include +#include "ohos/aafwk/base/base_interfaces.h" +#include "refbase.h" +#include "parcel.h" + +namespace OHOS { +namespace AAFwk { +class UnsupportedData { +public: + std::u16string key; + int type = 0; + int size = 0; + uint8_t *buffer = nullptr; + + ~UnsupportedData(); + + UnsupportedData(); + UnsupportedData(const UnsupportedData &other); + UnsupportedData(UnsupportedData &&other); + + UnsupportedData &operator=(const UnsupportedData &other); + UnsupportedData &operator=(UnsupportedData &&other); +}; + +class WantParams final : public Parcelable { +public: + WantParams() = default; + WantParams(const WantParams &wantParams); + inline ~WantParams() + {} + WantParams &operator=(const WantParams &other); + + bool operator==(const WantParams &other); + + static sptr GetInterfaceByType(int typeId, const std::string &value); + + static bool CompareInterface(const sptr iIt1, const sptr iIt2, int typeId); + + static int GetDataType(const sptr iIt); + + static std::string GetStringByType(const sptr iIt, int typeId); + + void SetParam(const std::string &key, IInterface *value); + + sptr GetParam(const std::string &key) const; + + const std::map> &GetParams() const; + + const std::set KeySet() const; + + void Remove(const std::string &key); + + bool HasParam(const std::string &key) const; + + int Size() const; + + bool IsEmpty() const; + + virtual bool Marshalling(Parcel &parcel) const; + + static WantParams *Unmarshalling(Parcel &parcel); + + void DumpInfo(int level) const; + +private: + enum { + VALUE_TYPE_NULL = -1, + VALUE_TYPE_BOOLEAN = 1, + VALUE_TYPE_BYTE = 2, + VALUE_TYPE_CHAR = 3, + VALUE_TYPE_SHORT = 4, + VALUE_TYPE_INT = 5, + VALUE_TYPE_LONG = 6, + VALUE_TYPE_FLOAT = 7, + VALUE_TYPE_DOUBLE = 8, + VALUE_TYPE_STRING = 9, + VALUE_TYPE_CHARSEQUENCE = 10, + VALUE_TYPE_BOOLEANARRAY = 11, + VALUE_TYPE_BYTEARRAY = 12, + VALUE_TYPE_CHARARRAY = 13, + VALUE_TYPE_SHORTARRAY = 14, + VALUE_TYPE_INTARRAY = 15, + VALUE_TYPE_LONGARRAY = 16, + VALUE_TYPE_FLOATARRAY = 17, + VALUE_TYPE_DOUBLEARRAY = 18, + VALUE_TYPE_STRINGARRAY = 19, + VALUE_TYPE_CHARSEQUENCEARRAY = 20, + + VALUE_TYPE_PARCELABLE = 21, + VALUE_TYPE_PARCELABLEARRAY = 22, + VALUE_TYPE_SERIALIZABLE = 23, + VALUE_TYPE_LIST = 50, + + VALUE_TYPE_WANTPARAMS = 101, + VALUE_TYPE_ARRAY = 102, + }; + + bool WriteArrayToParcel(Parcel &parcel, IArray *ao) const; + bool ReadArrayToParcel(Parcel &parcel, int type, sptr &ao); + bool ReadFromParcel(Parcel &parcel); + bool ReadFromParcelParam(Parcel &parcel, const std::string &key, int type); + bool ReadFromParcelString(Parcel &parcel, const std::string &key); + bool ReadFromParcelBool(Parcel &parcel, const std::string &key); + bool ReadFromParcelInt8(Parcel &parcel, const std::string &key); + bool ReadFromParcelChar(Parcel &parcel, const std::string &key); + bool ReadFromParcelShort(Parcel &parcel, const std::string &key); + bool ReadFromParcelInt(Parcel &parcel, const std::string &key); + bool ReadFromParcelLong(Parcel &parcel, const std::string &key); + bool ReadFromParcelFloat(Parcel &parcel, const std::string &key); + bool ReadFromParcelDouble(Parcel &parcel, const std::string &key); + + bool ReadFromParcelArrayString(Parcel &parcel, sptr &ao); + bool ReadFromParcelArrayBool(Parcel &parcel, sptr &ao); + bool ReadFromParcelArrayByte(Parcel &parcel, sptr &ao); + bool ReadFromParcelArrayChar(Parcel &parcel, sptr &ao); + bool ReadFromParcelArrayShort(Parcel &parcel, sptr &ao); + + bool ReadFromParcelArrayInt(Parcel &parcel, sptr &ao); + bool ReadFromParcelArrayLong(Parcel &parcel, sptr &ao); + bool ReadFromParcelArrayFloat(Parcel &parcel, sptr &ao); + bool ReadFromParcelArrayDouble(Parcel &parcel, sptr &ao); + bool ReadFromParcelWantParamWrapper(Parcel &parcel, const std::string &key); + + bool WriteArrayToParcelString(Parcel &parcel, IArray *ao) const; + bool WriteArrayToParcelBool(Parcel &parcel, IArray *ao) const; + bool WriteArrayToParcelByte(Parcel &parcel, IArray *ao) const; + bool WriteArrayToParcelChar(Parcel &parcel, IArray *ao) const; + bool WriteArrayToParcelShort(Parcel &parcel, IArray *ao) const; + bool WriteArrayToParcelInt(Parcel &parcel, IArray *ao) const; + bool WriteArrayToParcelLong(Parcel &parcel, IArray *ao) const; + bool WriteArrayToParcelFloat(Parcel &parcel, IArray *ao) const; + bool WriteArrayToParcelDouble(Parcel &parcel, IArray *ao) const; + + bool WriteMarshalling(Parcel &parcel, sptr &o) const; + bool WriteToParcelString(Parcel &parcel, sptr &o) const; + bool WriteToParcelBool(Parcel &parcel, sptr &o) const; + bool WriteToParcelByte(Parcel &parcel, sptr &o) const; + bool WriteToParcelChar(Parcel &parcel, sptr &o) const; + bool WriteToParcelShort(Parcel &parcel, sptr &o) const; + bool WriteToParcelInt(Parcel &parcel, sptr &o) const; + bool WriteToParcelLong(Parcel &parcel, sptr &o) const; + bool WriteToParcelFloat(Parcel &parcel, sptr &o) const; + bool WriteToParcelDouble(Parcel &parcel, sptr &o) const; + bool WriteToParcelWantParams(Parcel &parcel, sptr &o) const; + + bool DoMarshalling(Parcel &parcel) const; + bool ReadUnsupportedData(Parcel &parcel, const std::string &key, int type); + + friend class WantParamWrapper; + // inner use function + bool NewArrayData(IArray *source, sptr &dest); + bool NewParams(const WantParams &source, WantParams &dest); + std::map> params_; + std::vector cachedUnsupportedData_; +}; +} // namespace AAFwk +} // namespace OHOS + +#endif // OHOS_AAFWK_WANT_PARAMS_H \ No newline at end of file diff --git a/tools/interfaces/kits/js/@ohos.ability.dataUriUtils.d.ts b/tools/interfaces/kits/js/@ohos.ability.dataUriUtils.d.ts new file mode 100644 index 00000000000..912ae82a7cf --- /dev/null +++ b/tools/interfaces/kits/js/@ohos.ability.dataUriUtils.d.ts @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +declare namespace dataUriUtils { + /** + * Obtains the ID attached to the end of the path component of the given URI. + * @devices phone, tablet + * @since 7 + * @SysCap AAFwk + * @param dataUri Indicates the Uri object from which the ID is to be obtained. + * @return Returns the ID attached to the end of the path component; + * returns -1 if the given dataUri does not contain a path component. + */ + function getIdSync(URI: string): number; + + /** + * Attaches the given ID to the end of the path component of the given URI. + * @devices phone, tablet + * @since 7 + * @SysCap AAFwk + * @param dataUri Indicates the Uri object to which the ID is to be attached. + * @param id Indicates the ID to attach. + * @return Returns the Uri object with the given ID attached. + */ + function attachIdSync(URI: string, id: number): string; + + /** + * Deletes the ID from the end of the path component of the given URI. + * @devices phone, tablet + * @since 7 + * @SysCap AAFwk + * @param dataUri Indicates the Uri object from which the ID is to be deleted. + * @return Returns the Uri object with the ID deleted. + */ + function deleteIdSync(URI: string): string; + + /** + * Updates the ID in the specified dataUri. + * @devices phone, tablet + * @since 7 + * @SysCap AAFwk + * @param dataUri Indicates the Uri object to be updated. + * @param id Indicates the new ID. + * @return Returns the updated Uri object. + */ + function updateIdSync(URI: string, id: number): string; +} + +export default dataUriUtils; \ No newline at end of file diff --git a/tools/interfaces/kits/js/@ohos.ability.featureAbility.d.ts b/tools/interfaces/kits/js/@ohos.ability.featureAbility.d.ts new file mode 100644 index 00000000000..d92e73b8404 --- /dev/null +++ b/tools/interfaces/kits/js/@ohos.ability.featureAbility.d.ts @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { AsyncCallback } from './basic'; +import { Want } from './ability/want'; +import { StartAbilityParameter } from './ability/startAbilityParameter'; +import { AbilityResult } from './ability/abilityResult'; +import { Context } from './app/context'; +import { DataAbilityHelper } from './ability/dataAbilityHelper'; +import { ConnectOptions } from './ability/connectOptions'; + +/** + * A Feature Ability represents an ability with a UI and is designed to interact with users. + * @name featureAbility + * @since 6 + * @sysCap AAFwk + * @devices phone, tablet + * @permission N/A + */ +declare namespace featureAbility { + /** + * Obtain the want sended from the source ability. + * @devices phone, tablet + * @since 6 + * @sysCap AAFwk + * @param parameter Indicates the ability to start. + * @return - + */ + function getWant(callback: AsyncCallback): void; + function getWant(): Promise; + + /** + * Starts a new ability. + * @devices phone, tablet + * @since 6 + * @sysCap AAFwk + * @param parameter Indicates the ability to start. + * @return - + */ + function startAbility(parameter: StartAbilityParameter, callback: AsyncCallback): void; + function startAbility(parameter: StartAbilityParameter): Promise; + + /** + * Obtains the application context. + * + * @return Returns the application context. + * @since 6 + */ + function getContext(): Context; + + /** + * Starts an ability and returns the execution result when the ability is destroyed. + * @devices phone, tablet + * @since 7 + * @sysCap AAFwk + * @param parameter Indicates the ability to start. + * @return - + */ + function startAbilityForResult(parameter: StartAbilityParameter, callback: AsyncCallback): void; + function startAbilityForResult(parameter: StartAbilityParameter): Promise; + + /** + * Sets the result code and data to be returned by this Page ability to the caller + * and destroys this Page ability. + * @devices phone, tablet + * @since 7 + * @sysCap AAFwk + * @param parameter Indicates the result to return. + * @return - + */ + function terminateSelfWithResult(parameter: AbilityResult, callback: AsyncCallback): void; + function terminateSelfWithResult(parameter: AbilityResult): Promise; + + /** + * Destroys this Page ability. + * @devices phone, tablet + * @since 7 + * @sysCap AAFwk + * @return - + */ + function terminateSelf(callback: AsyncCallback): void; + + /** + * Obtains the dataAbilityHelper. + * @devices phone, tablet + * @since 7 + * @sysCap AAFwk + * @param uri Indicates the path of the file to open. + * @return Returns the dataAbilityHelper. + */ + function acquireDataAbilityHelper(uri: string): DataAbilityHelper; + + /** + * Checks whether the main window of this ability has window focus. + * @devices phone, tablet + * @since 7 + * @sysCap AAFwk + */ + function hasWindowFocus(callback: AsyncCallback): void; + function hasWindowFocus(): Promise; + + /** + * Connects the current ability to an ability using the AbilityInfo.AbilityType.SERVICE template. + * @default - + * @devices phone, tablet + * @since 7 + * @SysCap aafwk + * @param request The element name of the service ability + * @param options The remote object instance + * @return Returns the number of the ability connected + */ + function connectAbility(request: Want, options:ConnectOptions ): number; + + /** + * The callback interface was connect successfully. + * @default - + * @devices phone, tablet + * @since 7 + * @SysCap aafwk + * @param connection The number of the ability connected + */ + function disconnectAbility(connection: number, callback:AsyncCallback): void; + function disconnectAbility(connection: number): Promise; + + export enum AbilityWindowConfiguration { + WINDOW_MODE_UNDEFINED = 0, + WINDOW_MODE_FULLSCREEN = 1, + WINDOW_MODE_SPLIT_PRIMARY = 100, + WINDOW_MODE_SPLIT_SECONDARY = 101, + WINDOW_MODE_FLOATING = 102 + } + + export enum AbilityStartSetting { + BOUNDS_KEY = "abilityBounds", + WINDOW_MODE_KEY = "windowMode", + DISPLAY_ID_KEY = "displayId" + } +} +export default featureAbility; diff --git a/tools/interfaces/kits/js/@ohos.ability.formmanager.d.ts b/tools/interfaces/kits/js/@ohos.ability.formmanager.d.ts new file mode 100644 index 00000000000..77a22265be0 --- /dev/null +++ b/tools/interfaces/kits/js/@ohos.ability.formmanager.d.ts @@ -0,0 +1,292 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { AsyncCallback } from './.basic'; +import { Want } from './ability/want'; +import { FormInfo } from './ability/forminfo'; + +/** + * Provides utilities for system application components to access ability form + * on the OHOS OS. + * @name formManager + * @since 7 + * @sysCap AAFwk + * @devices phone, tablet + * @permission N/A + */ +declare namespace formManager { + /** + * user need to force refresh form. + * + *

You can use this method to ask for newly form from service.

+ * + * @param formId the specify form id. + * @since 7 + */ + function requestForm(formId: number, callback: AsyncCallback): void; + function requestForm(formId: number): Promise; + + /** + * delete forms. + * + *

You can use this method to delete ability form.

+ * + * @param formId Indicates the form to be deleted. + * @since 7 + */ + function deleteForm(formId: number, callback: AsyncCallback): void; + function deleteForm(formId: number): Promise; + + /** + * release form. + * + *

You can use this method to release ability form, it does not delete form cache in + * form manager.

+ * + * @param formId Indicates the form to be released. + * @param isReleaseCache Indicates whether to delete cache in service. + * @since 7 + */ + function releaseForm(formId: number, isReleaseCache: boolean, callback: AsyncCallback): void; + function releaseForm(formId: number, isReleaseCache: boolean): Promise; + + /** + * Sends a notification to the form framework to make the specified forms visible. + * + * @param formIds Indicates the IDs of the forms to be made visible. + * @since 7 + */ + function notifyVisibleForms(formIds: Array, callback: AsyncCallback): void; + function notifyVisibleForms(formIds: Array): Promise; + + /** + * Sends a notification to the form framework to make the specified forms invisible. + * + * @param formIds Indicates the IDs of the forms to be made invisible. + * @since 7 + */ + function notifyInvisibleForms(formIds: Array, callback: AsyncCallback): void; + function notifyInvisibleForms(formIds: Array): Promise; + + /** + * set form refresh state to true. + * + *

You can use this method to set form refresh state to true, the form can receive new + * update from service.

+ * + * @param formIds the specify form id. + * @since 7 + */ + function enableFormsUpdate(formIds: Array, callback: AsyncCallback): void; + function enableFormsUpdate(formIds: Array): Promise; + + /** + * set form refresh state to false. + * + *

You can use this method to set form refresh state to false, the form do not receive + * new update from service.

+ * + * @param formIds the specify form id. + * @since 7 + */ + function disableFormsUpdate(formIds: Array, callback: AsyncCallback): void; + function disableFormsUpdate(formIds: Array): Promise; + + /** + * Check form manager service ready. + * + *

You can use this method to check if form manager service is ready.

+ * + * @return Returns {@code true} form manager service ready; returns {@code false} otherwise. + * @since 7 + */ + function checkFMSReady(callback: AsyncCallback): void; + function checkFMSReady(): Promise; + + /** + * Cast temp form to narmal form. + * + *

You can use this method to cast a temp form to normal form.

+ * + * @param formId the specify form id to be casted. + * @since 7 + */ + function castTempForm(formId: number, callback: AsyncCallback): void; + function castTempForm(formId: number): Promise; + + /** + * Checks for and deletes invalid forms of the application in the Form Manager Service based on the list of valid + * form IDs passed. + * + *

If an empty list is passed to this method, the Form Manager Service will delete all forms of the + * application.

+ * + * @param persistedIds Indicates the list of valid forms with persisted IDs. + * @since 7 + */ + function checkAndDeleteInvalidForms(persistedIds: Array, callback: AsyncCallback): void; + function checkAndDeleteInvalidForms(persistedIds: Array): Promise; + + /** + * Updates the content of a specified JS form. + * + *

This method is called by a form provider to update JS form data as needed. + * + * @param formId Indicates the ID of the JS form to update. + * @param formBindingData Indicates the object used to update the JS form displayed + * on the client. + * @return Returns {@code true} if the update is successful; returns {@code false} otherwise. + * @throws FormException Throws this exception if the form fails to be obtained due to any of the following reasons: + *

    + *
  • The passed {@code formID} or {@code component} is invalid. The value of {@code formID} must be larger than 0, + * and {@code component} must not be null.
  • + *
  • An error occurred when connecting to the Form Manager Service.
  • + *
  • The specified form ID does not exist.
  • + *
  • The form has been obtained by another application and cannot be updated by the current application.
  • + *
  • The form is being restored.
  • + *
+ * @since 7 + */ + function updateForm(formid: number, data: FormBindingData, callback: AsyncCallback): void; + function updateForm(formid: number, data: FormBindingData): Promise; + + /** + * Set next refresh time since now. + * + *

This method is called by a form provider to set refresh time. + * + * @param formId Indicates the ID of the form to set refreshTime. + * @param bundleName Indicates the bundleName of current form. + * @param nextTime Indicates the next time gap now in seconds, can not be litter than 5 mins. + * @return Returns {@code true} if seting succeed; returns {@code false} otherwise. + * @throws FormException Throws this exception if the form fails to be obtained due to any of the following reasons: + *

    + *
  • The passed {@code formId} or {@code nextTime} is invalid. The value of {@code formId} must be larger + * than 0, and {@code nextTime} must at least be 120 (5min).
  • + *
  • An error occurred when connecting to the Form Manager Service.
  • + *
  • The specified form ID does not exist.
  • + *
  • The form has been obtained by another application and cannot be updated by the current application.
  • + *
  • The form is being restored.
  • + *
+ * @since 7 + */ + function setFormNextRefreshTime(formid: number, nextTime: number, callback: AsyncCallback): boolean; + function setFormNextRefreshTime(formid: number, nextTime: number): Promise; + + /** + * get all forms info. + * + *

You can use this method to get all forms info.

+ * + * @return Returns the forms' information of all forms provided + * @since 7 + */ + function getAllFormsInfo(callback: AsyncCallback>): void; + function getAllFormsInfo(): Promise>; + + /** + * get forms info by application name. + * + *

You can use this method to get all forms info of the specify application name.

+ * + * @param bundleName application name. + * @return Returns the forms' information of the specify application name. + * @since 7 + */ + function getFormsInfoByApp(bundleName: string, callback: AsyncCallback): void; + function getFormsInfoByApp(bundleName: string): Promise; + + /** + * get forms info by application name and module name. + * + *

You can use this method to get all forms info of the specify application name and module name.

+ * + * @param bundleName application name. + * @param moduleName module name of hap + * @return Returns the forms' information of the specify application name and module name + * @since 7 + */ + function getFormsInfoByModule(bundleName: string, moduleName: string, callback: AsyncCallback): void; + function getFormsInfoByModule(bundleName: string, moduleName: string): Promise; + + on(type: "formUninstalled", formID: number, callback: AsyncCallback): void; + off(type: "formUninstalled", formID: number, callback?: AsyncCallback): void; + + on(type: "getAnimation", callback: AsyncCallback): void; + off(type: "getAnimation", callback?: AsyncCallback): void; + + export enum FromParam { + /** + * Indicates the key specifying the ID of the form to be obtained, which is represented as + * {@code intent.setParam(PARAM_FORM_IDENTITY_KEY, 1L)}. + */ + IDENTITY_KEY = "ohos.extra.param.key.form_identity", + /** + * Indicates the form dimension, now value support 1,2,3,4. + */ + DIMENSION_KEY = "ohos.extra.param.key.form_dimension", + /** + * Indicates the form name. + */ + NAME_KEY = "ohos.extra.param.key.form_name", + /** + * Indicates the module name of the form. + */ + NAME_KEY = "ohos.extra.param.key.module_name", + /** + * Indicates the form view width. + */ + WIDTH_KEY = "ohos.extra.param.key.form_width", + /** + * Indicates the form view height. + */ + HEIGHT_KEY = "ohos.extra.param.key.form_height", + /** + * Indicates the temporary flag of form to be obtained + */ + TEMPORARY_KEY = "ohos.extra.param.key.form_temporary" + } + + export enum FormError { + ERR_CODE_COMMON = 1, + ERR_PERMISSION_DENY = 2, + ERR_GET_INFO_FAILED = 4, + ERR_GET_BUNDLE_FAILED = 5, + ERR_GET_LAYOUT_FAILED = 6, + ERR_ADD_INVALID_PARAM = 7, + ERR_CFG_NOT_MATCH_ID = 8, + ERR_NOT_EXIST_ID = 9, + ERR_BIND_PROVIDER_FAILED = 10, + ERR_MAX_SYSTEM_FORMS = 11, + ERR_MAX_INSTANCES_PER_FORM = 12, + ERR_OPERATION_FORM_NOT_SELF = 13, + ERR_PROVIDER_DEL_FAIL = 14, + ERR_MAX_FORMS_PER_CLIENT = 15, + ERR_MAX_SYSTEM_TEMP_FORMS = 16, + ERR_FORM_NO_SUCH_MODULE = 17, + ERR_FORM_NO_SUCH_ABILITY = 18, + ERR_FORM_NO_SUCH_DIMENSION = 19, + ERR_FORM_FA_NOT_INSTALLED = 20, + + // error code in sdk + ERR_GET_FMS_RPC = 30, + ERR_FORM_DUPLICATE_ADDED = 31, + ERR_SEND_FMS_MSG = 32, + ERR_GET_BMS_RPC = 33, + ERR_SEND_BMS_MSG = 34, + ERR_START_ABILITY = 35, + ERR_IN_RECOVER = 36 + } +} +export default formManager; \ No newline at end of file diff --git a/tools/interfaces/kits/js/@ohos.ability.particleAbility.d.ts b/tools/interfaces/kits/js/@ohos.ability.particleAbility.d.ts new file mode 100644 index 00000000000..44e794c32b5 --- /dev/null +++ b/tools/interfaces/kits/js/@ohos.ability.particleAbility.d.ts @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { AsyncCallback } from './basic'; +import { StartAbilityParameter } from './ability/startAbilityParameter'; +import { Want } from './ability/want'; +import { ConnectOptions } from './ability/connectOptions'; + +/** + * A Particle Ability represents an ability with service. + * @name particleAbility + * @since 7 + * @sysCap AAFwk + * @devices phone, tablet + * @permission N/A + */ +declare namespace particleAbility { + + /** + * Service ability uses this method to start a specific ability. + * @devices phone, tablet + * @since 7 + * @sysCap AAFwk + * @param parameter Indicates the ability to start. + * @return - + */ + function startAbility(parameter: StartAbilityParameter, callback: AsyncCallback): void; + function startAbility(parameter: StartAbilityParameter): Promise; + + /** + * Connects the current ability to an ability using the AbilityInfo.AbilityType.SERVICE template. + * @default - + * @devices phone, tablet + * @since 7 + * @SysCap aafwk + * @param request The element name of the service ability + * @param options The remote object instance + * @return Returns the number of the ability connected + */ + function connectAbility(request: Want, options:ConnectOptions ): number; + + /** + * The callback interface was connect successfully. + * @default - + * @devices phone, tablet + * @since 7 + * @SysCap aafwk + * @param connection The number of the ability connected + */ + function disconnectAbility(connection: number, callback:AsyncCallback): void; + function disconnectAbility(connection: number): Promise; +} +export default particleAbility; \ No newline at end of file diff --git a/tools/interfaces/kits/js/@ohos.ability.wantConstant.d.ts b/tools/interfaces/kits/js/@ohos.ability.wantConstant.d.ts new file mode 100644 index 00000000000..edae0e993c1 --- /dev/null +++ b/tools/interfaces/kits/js/@ohos.ability.wantConstant.d.ts @@ -0,0 +1,341 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"), + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * the constant for action and entity in the want + * @name wantConstant + * @since 6 + * @sysCap aafwk + * @devices phone, tablet + * @permission N/A + */ +declare namespace wantConstant { + /** + * the constant for action of the want + * @name Action + * @since 6 + * @sysCap aafwk + * @devices phone, tablet + * @permission N/A + */ + export enum Action { + /** + * Indicates the action of backing home. + * + * @since 1 + */ + ACTION_HOME = "ohos.want.action.home", + + /** + * Indicates the action of starting a Page ability that displays a keypad. + * + * @since 6 + */ + ACTION_DIAL = "ohos.want.action.dial", + + /** + * Indicates the action of starting a Page ability for search. + * + * @since 6 + */ + ACTION_SEARCH = "ohos.want.action.search", + + /** + * Indicates the action of starting a Page ability that provides wireless network settings, for example, + * Wi-Fi options. + * + * @since 6 + */ + ACTION_WIRELESS_SETTINGS = "ohos.settings.wireless", + + /** + * Indicates the action of starting a Page ability that manages installed applications. + * + * @since 6 + */ + ACTION_MANAGE_APPLICATIONS_SETTINGS = "ohos.settings.manage.applications", + + /** + * Indicates the action of starting a Page ability that displays details of a specified application. + * + *

You must specify the application bundle name in the {@code package} attribute of the {@code Intent} + * containing this action. + * + * @since 6 + */ + ACTION_APPLICATION_DETAILS_SETTINGS = "ohos.settings.application.details", + + /** + * Indicates the action of starting a Page ability for setting an alarm clock. + * + * @since 6 + */ + ACTION_SET_ALARM = "ohos.want.action.setAlarm", + + /** + * Indicates the action of starting a Page ability that displays all alarm + * clocks. + * + * @since 6 + */ + ACTION_SHOW_ALARMS = "ohos.want.action.showAlarms", + + /** + * Indicates the action of starting a Page ability for snoozing an alarm clock. + * + * @since 6 + */ + ACTION_SNOOZE_ALARM = "ohos.want.action.snoozeAlarm", + + /** + * Indicates the action of starting a Page ability for deleting an alarm clock. + * + * @since 6 + */ + ACTION_DISMISS_ALARM = "ohos.want.action.dismissAlarm", + + /** + * Indicates the action of starting a Page ability for dismissing a timer. + * + * @since 6 + */ + ACTION_DISMISS_TIMER = "ohos.want.action.dismissTimer", + + /** + * Indicates the action of starting a Page ability for sending a sms. + * + * @since 6 + */ + ACTION_SEND_SMS = "ohos.want.action.sendSms", + + /** + * Indicates the action of starting a Page ability for opening contacts or pictures. + * + * @since 6 + */ + ACTION_CHOOSE = "ohos.want.action.choose", + + /** + * Indicates the action of showing the application selection dialog box. + * + * @since 6 + */ + ACTION_SELECT = "ohos.want.action.select", + + /** + * Indicates the action of sending a single data record. + * + * @since 6 + */ + ACTION_SEND_DATA = "ohos.want.action.sendData", + + /** + * Indicates the action of sending multiple data records. + * + * @since 6 + */ + ACTION_SEND_MULTIPLE_DATA = "ohos.want.action.sendMultipleData", + + /** + * Indicates the action of requesting the media scanner to scan files and adding the files to the media library. + * + * @since 6 + */ + ACTION_SCAN_MEDIA_FILE = "ohos.want.action.scanMediaFile", + + /** + * Indicates the action of viewing data. + * + * @since 6 + */ + ACTION_VIEW_DATA = "ohos.want.action.viewData", + + /** + * Indicates the action of editing data. + * + * @since 6 + */ + ACTION_EDIT_DATA = "ohos.want.action.editData", + + /** + * Indicates the choices you will show with {@link #ACTION_PICKER}. + * + * @since 6 + */ + INTENT_PARAMS_INTENT = "ability.want.params.INTENT", + + /** + * Indicates the CharSequence dialog title when used with a {@link #ACTION_PICKER}. + * + * @since 6 + */ + INTENT_PARAMS_TITLE = "ability.want.params.TITLE", + + /** + * Indicates the action of select file. + * + * @since 7 + */ + ACTION_FILE_SELECT = "ohos.action.fileSelect", + + /** + * Indicates the URI holding a stream of data associated with the Intent when used with a {@link #ACTION_SEND_DATA}. + * + * @since 7 + */ + PARAMS_STREAM = "ability.params.stream", + } + + /** + * the constant for Entity of the want + * @name Action + * @since 6 + * @sysCap aafwk + * @devices phone, tablet + * @permission N/A + */ + export enum Entity { + /** + * Indicates the default entity, which is used if the entity is not specified. + * + * @since 6 + */ + ENTITY_DEFAULT = "entity.system.default", + + /** + * Indicates the home screen entity. + * + * @since 6 + */ + ENTITY_HOME = "entity.system.home", + + /** + * Indicates the voice interaction entity. + * + * @since 6 + */ + ENTITY_VOICE = "entity.system.voice", + + /** + * Indicates the browser category. + * + * @since 6 + */ + ENTITY_BROWSABLE = "entity.system.browsable", + + /** + * Indicates the video category. + */ + ENTITY_VIDEO = "entity.system.video" + } + + export enum Flags { + /** + * Indicates the grant to perform read operations on the URI. + * + * @hide + */ + FLAG_AUTH_READ_URI_PERMISSION = 0x00000001, + + /** + * Indicates the grant to perform write operations on the URI. + * + * @hide + */ + FLAG_AUTH_WRITE_URI_PERMISSION = 0x00000002, + + /** + * Returns the result to the source ability. + */ + FLAG_ABILITY_FORWARD_RESULT = 0x00000004, + + /** + * Determines whether an ability on the local device can be migrated to a remote device. + */ + FLAG_ABILITY_CONTINUATION = 0x00000008, + + /** + * Specifies whether a component does not belong to OHOS. + */ + FLAG_NOT_OHOS_COMPONENT = 0x00000010, + + /** + * Specifies whether an ability is started. + */ + FLAG_ABILITY_FORM_ENABLED = 0x00000020, + + /** + * Indicates the grant for possible persisting on the URI. + * + * @hide + */ + FLAG_AUTH_PERSISTABLE_URI_PERMISSION = 0x00000040, + + /** + * Returns the result to the source ability slice. + * + * @hide + */ + FLAG_AUTH_PREFIX_URI_PERMISSION = 0x00000080, + + /** + * Supports multi-device startup in the distributed scheduling system. + */ + FLAG_ABILITYSLICE_MULTI_DEVICE = 0x00000100, + + /** + * Indicates that an ability using the Service template is started regardless of whether the host application has + * been started. + */ + FLAG_START_FOREGROUND_ABILITY = 0x00000200, + + /** + * Indicates the continuation is reversible. + * + * @hide + */ + FLAG_ABILITY_CONTINUATION_REVERSIBLE = 0x00000400, + + /** + * Install the specified ability if it's not installed. + */ + FLAG_INSTALL_ON_DEMAND = 0x00000800, + + /** + * Install the specifiedi ability with background mode if it's not installed. + */ + FLAG_INSTALL_WITH_BACKGROUND_MODE = 0x80000000, + + /** + * Indicates the operation of clearing other missions. This flag can be set for the {@code Intent} passed to + * {@link ohos.app.Context#startAbility} and must be used together with {@link FLAG_ABILITY_NEW_MISSION}. + */ + FLAG_ABILITY_CLEAR_MISSION = 0x00008000, + + /** + * Indicates the operation of creating a task on the historical mission stack. + */ + FLAG_ABILITY_NEW_MISSION = 0x10000000, + + /** + * Indicates that the existing instance of the ability to start will be reused if it is already at the top of + * the mission stack. Otherwise, a new ability instance will be created. + * + */ + FLAG_ABILITY_MISSION_TOP = 0x20000000 + } +} + +export default wantConstant; \ No newline at end of file diff --git a/tools/interfaces/kits/js/@ohos.app.abilityManager.d.ts b/tools/interfaces/kits/js/@ohos.app.abilityManager.d.ts new file mode 100644 index 00000000000..f5b7ce142bb --- /dev/null +++ b/tools/interfaces/kits/js/@ohos.app.abilityManager.d.ts @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { AsyncCallback } from './basic'; +import { AbilityMissionInfo } from './app/abilityMissionInfo'; +import { ActiveProcessInfo } from './app/activeProcessInfo'; + +/** + * This module provides the capability to manage abilities and obtaining system task information. + * + * @since 7 + * @SysCap SystemCapability.Appexecfwk + * @devices phone, tablet, tv, wearable, car + * @import import abilityManager from '@ohos.app.abilityManager' + * @permission N/A + */ +declare namespace abilityManager { + + enum ProcessErrCode { + NO_ERROR = 0, + CRASHED, + NO_RESPONSE, + } + + + /** + * Get information about running processes + * @since 7 + * @SysCap SystemCapability.Appexecfwk + * @devices phone, tablet, tv, wearable, car + * @return a list of ActiveProcessInfo records describing each process. + * @permission ohos.permission.INTERACT_ACROSS_LOCAL_ACCOUNTS_EXTENSION + * @systemapi hide this for inner system use + */ + function getActiveProcessInfos(): Promise>; + function getActiveProcessInfos(callback: AsyncCallback>): void; + + /** + * Get information about the running ability missions + * @since 7 + * @SysCap SystemCapability.Appexecfwk + * @devices phone, tablet, tv, wearable, car + * @param upperLimit The maximum number of mission infos to return in the array. + * @return an array of AbilityMissionInfo records describing each active mission. + * @permission ohos.permission.ACCESS_MISSIONS + * @systemapi hide this for inner system use + */ + function getActiveAbilityMissionInfos(upperLimit: number): Promise>; + function getActiveAbilityMissionInfos(upperLimit: number, callback: AsyncCallback>): void; + + /** + * Get information about recently run missions + * @since 7 + * @SysCap SystemCapability.Appexecfwk + * @devices phone, tablet, tv, wearable, car + * @param upperLimit The maximum number of previous mission infos to return in the array. + * @return an array of AbilityMissionInfo records describing each of the previous mission. + * @permission ohos.permission.ACCESS_MISSIONS_EXTRA + * @systemapi hide this for inner system use + */ + function getPreviousAbilityMissionInfos(upperLimit: number): Promise>; + function getPreviousAbilityMissionInfos(upperLimit: number, callback: AsyncCallback>): void; + + /** + * Delete the specified missions + * @since 7 + * @SysCap SystemCapability.Appexecfwk + * @devices phone, tablet, tv, wearable, car + * @param missionIds An array of missions, representing the missions that need to be deleted. + * @permission ohos.permission.DELETE_MISSIONS + * @systemapi hide this for inner system use + */ + function deleteMissions(missionIds: Array): Promise; + function deleteMissions(missionIds: Array, callback: AsyncCallback): void; + +} + +export default abilityManager; diff --git a/tools/interfaces/kits/js/@ohos.bundle.d.ts b/tools/interfaces/kits/js/@ohos.bundle.d.ts new file mode 100644 index 00000000000..6e9ff46b8dd --- /dev/null +++ b/tools/interfaces/kits/js/@ohos.bundle.d.ts @@ -0,0 +1,347 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { AsyncCallback, Callback } from './basic'; +import { ApplicationInfo } from './bundle/applicationInfo'; +import { BundleInfo } from './bundle/bundleInfo'; +import { AbilityInfo } from './bundle/abilityInfo'; +import { Want } from './ability/want'; +import { BundleInstaller } from './bundle/bundleInstaller'; +import { ElementName } from './bundle/elementName'; +import { ShortcutInfo } from './bundle/shortcutInfo'; +import { ModuleUsageRecord } from './bundle/moduleUsageRecord'; + +/** + * bundle. + * @name bundle + * @since 7 + * @sysCap SystemCapability.Appexecfwk + * @devices phone, tablet, tv, wearable + * @permission NA + */ +declare namespace bundle { + +/** + * @name BundleFlag + * @since 7 + * @SysCap SystemCapability.Appexecfwk + * @import NA + * @permission NA + * @devices phone, tablet, tv, wearable + */ + enum BundleFlag { + GET_BUNDLE_DEFAULT = 0x00000000, + GET_BUNDLE_WITH_ABILITIES = 0x00000001, + GET_APPLICATION_INFO_WITH_PERMISSION = 0x00000008, + } + +/** + * @name GrantStatus + * @since 7 + * @SysCap SystemCapability.Appexecfwk + * @import NA + * @permission NA + * @devices phone, tablet, tv, wearable + */ + export enum GrantStatus { + PERMISSION_DENIED = -1, + PERMISSION_GRANTED = 0, + } + + /** + * @name AbilityType + * @since 7 + * @SysCap SystemCapability.Appexecfwk + * @import NA + * @permission NA + * @devices phone, tablet, tv, wearable + */ + export enum AbilityType { + /** + * @default Indicates an unknown ability type + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + UNKNOWN, + + /** + * @default Indicates that the ability has a UI + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + PAGE, + + /** + * @default Indicates that the ability does not have a UI + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + SERVICE, + + /** + * @default Indicates that the ability is used to provide data access services + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + DATA, + } + + /** + * @name AbilitySubType + * @since 7 + * @SysCap SystemCapability.Appexecfwk + * @import NA + * @permission NA + * @devices phone, tablet, tv, wearable + */ + export enum AbilitySubType { + UNSPECIFIED = 0, + CA = 1, + } + + /** + * @name DisplayOrientation + * @since 7 + * @SysCap SystemCapability.Appexecfwk + * @import NA + * @permission NA + * @devices phone, tablet, tv, wearable + */ + export enum DisplayOrientation { + /** + * @default Indicates that the system automatically determines the display orientation + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + UNSPECIFIED, + + /** + * @default Indicates the landscape orientation + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + LANDSCAPE, + + /** + * @default Indicates the portrait orientation + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + PORTRAIT, + + /** + * @default Indicates the page ability orientation is the same as that of the nearest ability in the stack + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + FOLLOW_RECENT, + } + + /** + * @name LaunchMode + * @since 7 + * @SysCap SystemCapability.Appexecfwk + * @import NA + * @permission NA + * @devices phone, tablet, tv, wearable + */ + export enum LaunchMode { + /** + * @default Indicates that the ability has only one instance + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + SINGLETON = 0, + + /** + * @default Indicates that the ability can have multiple instances + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + STANDARD = 1, + } + + /** + * @name InstallErrorCode + * @since 7 + * @SysCap SystemCapability.Appexecfwk + * @import NA + * @permission NA + * @devices phone, tablet, tv, wearable + */ + export enum InstallErrorCode{ + SUCCESS = 0, + STATUS_INSTALL_FAILURE = 1, + STATUS_INSTALL_FAILURE_ABORTED = 2, + STATUS_INSTALL_FAILURE_INVALID = 3, + STATUS_INSTALL_FAILURE_CONFLICT = 4, + STATUS_INSTALL_FAILURE_STORAGE = 5, + STATUS_INSTALL_FAILURE_INCOMPATIBLE = 6, + STATUS_UNINSTALL_FAILURE = 7, + STATUS_UNINSTALL_FAILURE_BLOCKED = 8, + STATUS_UNINSTALL_FAILURE_ABORTED = 9, + STATUS_UNINSTALL_FAILURE_CONFLICT = 10, + STATUS_INSTALL_FAILURE_DOWNLOAD_TIMEOUT = 0x0B, + STATUS_INSTALL_FAILURE_DOWNLOAD_FAILED = 0x0C, + STATUS_ABILITY_NOT_FOUND = 0x40, + STATUS_BMS_SERVICE_ERROR = 0x41 + } + + /** + * Obtains based on a given networkId and bundle name. + * + * @devices phone, tablet, tv, wearable + * @since 7 + * @SysCap SystemCapability.Appexecfwk + * @param networkId Indicates the device networkId in area network. + * @param bundleName Indicates the application bundle name to be queried. + * @param flags Indicates the flag used to specify information contained in that will be + * returned. + * @return Returns the BundleInfo object. + * @permission ohos.permission.GET_BUNDLE_INFO_PRIVILEGED,ohos.permission.GET_BUNDLE_INFO + */ + function getBundleInfo(bundleName: string, bundleFlags: number, callback: AsyncCallback): void; + function getBundleInfo(bundleName: string, bundleFlags: number): Promise; + + /** + * Obtains the interface used to install bundles. + * + * @devices phone, tablet, tv, wearable + * @since 7 + * @SysCap SystemCapability.Appexecfwk + * @return Returns the IBundleInstaller interface. + * @permission ohos.permission.INSTALL_BUNDLE + */ + function getBundleInstaller(callback: AsyncCallback): void; + function getBundleInstaller(): Promise; + + /** + * Obtains based on a given bundle name. + * + * @devices phone, tablet, tv, wearable + * @since 7 + * @SysCap SystemCapability.Appexecfwk + * @param bundleName Indicates the application bundle name to be queried. + * @param flags Indicates the flag used to specify information contained in the ApplicationInfo object + * that will be returned. + * @param userId Indicates the user ID. + * @return Returns the ApplicationInfo object. + * @permission ohos.permission.GET_BUNDLE_INFO_PRIVILEGED, ohos.permission.GET_BUNDLE_INFO + */ + function getApplicationInfo(bundleName: string, bundleFlags: number, userId: number, callback: AsyncCallback) : void; + function getApplicationInfo(bundleName: string, bundleFlags: number, userId: number) : Promise; + + /** + * Checks whether a specified bundle has been granted a specific permission. + * + * @devices phone, tablet, tv, wearable + * @since 7 + * @SysCap SystemCapability.Appexecfwk + * @param bundleName Indicates the name of the bundle to check. + * @param permission Indicates the permission to check. + * @return Returns 0 if the bundle has the permission; returns -1 otherwise. + */ + function checkPermission(bundleName: string, permission: string, callback: AsyncCallback): void; + function checkPermission(bundleName: string, permission: string): Promise; + + /** + * Query the AbilityInfo by the given Want. + * + * @devices phone, tablet, tv, wearable + * @since 7 + * @SysCap SystemCapability.Appexecfwk + * @param intent Indicates the Intent containing the application bundle name to + * be queried. + * @param flags Indicates the flag used to specify information contained in the AbilityInfo objects that + * will be returned. + * @param userId Indicates the user ID. + * @return Returns a list of AbilityInfo objects. + * @permission ohos.permission.GET_BUNDLE_INFO_PRIVILEGED, ohos.permission.GET_BUNDLE_INFO + */ + function queryAbilityByWant(want: Want, bundleFlags: number, userId: number, callback: AsyncCallback>): void; + function queryAbilityByWant(want: Want, bundleFlags: number, userId:number): Promise>; + + /** + * Obtains BundleInfo of all bundles available in the system. + * + * @devices phone, tablet, tv, wearable + * @since 7 + * @SysCap SystemCapability.Appexecfwk + * @param flags Indicates the flag used to specify information contained in the BundleInfo that will be + * returned. + * @return Returns a list of BundleInfo objects. + * @permission ohos.permission.GET_BUNDLE_INFO_PRIVILEGED + */ + function getAllBundleInfo(bundlelFlag: BundleFlag, callback: AsyncCallback>) : void; + function getAllBundleInfo(bundlelFlag: BundleFlag) : Promise>; + + /** + * Obtains information about all installed applications of a specified user. + * + * @devices phone, tablet, tv, wearable + * @since 7 + * @SysCap SystemCapability.Appexecfwk + * @param flags Indicates the flag used to specify information contained in the ApplicationInfo objects + * that will be returned. + * @param userId Indicates the user ID. + * @return Returns a list of ApplicationInfo objects. + * @permission ohos.permission.GET_BUNDLE_INFO_PRIVILEGED + */ + function getAllApplicationInfo(bundleFlags: number, userId: number, callback: AsyncCallback>) : void; + function getAllApplicationInfo(bundleFlags: number, userId: number) : Promise>; + + /** + * Obtains information about an application bundle contained in an ohos Ability Package (HAP). + * + * @devices phone, tablet, tv, wearable + * @since 7 + * @SysCap SystemCapability.Appexecfwk + * @param hapFilePath Indicates the path storing the HAP. The path should be the relative path to the data + * directory of the current application. + * @param flags Indicates the flag used to specify information contained in the BundleInfo object to be + * returned. + * @return Returns the BundleInfo object. + */ + function getBundleArchiveInfo(hapFilePath: string, bundleFlags: number, callback: AsyncCallback) : void + function getBundleArchiveInfo(hapFilePath: string, bundleFlags: number) : Promise; + + /** + * Obtains information about the shortcuts of the application. + * + * @devices phone, tablet, tv, wearable + * @since 7 + * @SysCap SystemCapability.Appexecfwk + * @param bundleName Indicates the bundle name of the application. + * @return Returns a list of ShortcutInfo objects containing shortcut information about the application. + * @permission ohos.permission.MANAGE_SHORTCUTS + */ + function getAllShortcutInfo(bundleName: string, callback: AsyncCallback>): void; + function getAllShortcutInfo(bundleName: string): Promise>; + + /** + * get module usage record list in descending order of lastLaunchTime. + * + * @devices phone, tablet, tv, wearable + * @since 7 + * @SysCap SystemCapability.Appexecfwk + * @param maxNum the return size of the records, must be in range of 1 to 1000. + * @return Returns ability usage record list. + * @systemapi hide this for inner system use + */ + function getModuleUsageRecords(maxNum: number, callback: AsyncCallback>): void; + function getModuleUsageRecords(maxNum: number): Promise>; +} + +export default bundle; diff --git a/tools/interfaces/kits/js/ability/abilityResult.d.ts b/tools/interfaces/kits/js/ability/abilityResult.d.ts new file mode 100644 index 00000000000..834f9b505de --- /dev/null +++ b/tools/interfaces/kits/js/ability/abilityResult.d.ts @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { Want } from './want'; + +export interface AbilityResult { + /** + * Indicates the result code returned after the ability is destroyed. You can define the result + * code to identify an error. + * @default - + * @devices phone, tablet + * @since 7 + * @sysCap AAFwk + */ + resultCode: number; + + /** + * Indicates the data returned after the ability is destroyed. You can define the data returned. + * This parameter can be null. + * @default - + * @devices phone, tablet + * @since 7 + * @sysCap AAFwk + */ + want?: Want; +} \ No newline at end of file diff --git a/tools/interfaces/kits/js/ability/connectOptions.d.ts b/tools/interfaces/kits/js/ability/connectOptions.d.ts new file mode 100644 index 00000000000..c718f678c3b --- /dev/null +++ b/tools/interfaces/kits/js/ability/connectOptions.d.ts @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { ElementName } from '../bundle/elementName'; +import rpc from './../@ohos.rpc'; + +export interface ConnectOptions { + /** + * The callback interface was connect successfully. + * + * @default - + * @devices phone, tablet + * @since 7 + * @SysCap aafwk + * @param elementName The element name of the service ability + * @param remoteObject The remote object instance + */ + onConnect: (elementName: ElementName, remoteObject: RemoteObject) => void; + + /** + * The callback interface was disconnect successfully. + * + * @default - + * @devices phone, tablet + * @since 7 + * @SysCap aafwk + * @param elementName The element name of the service ability + */ + onDisconnect: (elementName: ElementName) => void; + + /** + * The callback interface was connect failed. + * + * @default - + * @devices phone, tablet + * @since 7 + * @SysCap aafwk + * @param code The error code of the failed. + */ + onFailed: (code: number) => void; +} diff --git a/tools/interfaces/kits/js/ability/dataAbilityHelper.d.ts b/tools/interfaces/kits/js/ability/dataAbilityHelper.d.ts new file mode 100644 index 00000000000..71dd47e5b0f --- /dev/null +++ b/tools/interfaces/kits/js/ability/dataAbilityHelper.d.ts @@ -0,0 +1,224 @@ +/* +* Copyright (c) 2021 Huawei Device Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import { AsyncCallback } from './../basic'; +import { DataAbilityOperation } from './dataAbilityOperation'; +import { ValuesBucket, ResultSet, DataAbilityPredicates } from './../@ohos.data.rdb'; + +/** + * DataAbilityHelper + * @devices phone, tablet + * + * @since 7 + */ +export interface DataAbilityHelper { + /** + * Opens a file in a specified remote path. + * @devices phone, tablet + * @since 7 + * @SysCap AAFwk + * @param uri Indicates the path of the file to open. + * @param mode Indicates the file open mode, which can be "r" for read-only access, "w" for write-only access + * (erasing whatever data is currently in the file), "wt" for write access that truncates any existing + * file, "wa" for write-only access to append to any existing data, "rw" for read and write access on + * any existing data, or "rwt" for read and write access that truncates any existing file. + * @param callback Indicates the callback when openfile success + */ + openFile(uri: string, mode: string, callback: AsyncCallback): void; + openFile(uri: string, mode: string): Promise; + + /** + * Registers an observer to observe data specified by the given uri. + * @devices phone, tablet + * @since 7 + * @SysCap AAFwk + * @param type dataChange. + * @param uri Indicates the path of the data to operate. + * @param callback Indicates the callback when dataChange. + */ + on(type: 'dataChange', uri: string, callback: AsyncCallback): void; + + /** + * Deregisters an observer used for monitoring data specified by the given uri. + * @devices phone, tablet + * @since 7 + * @SysCap AAFwk + * @param type dataChange. + * @param uri Indicates the path of the data to operate. + * @param callback Indicates the registered callback. + */ + off(type: 'dataChange', uri: string, callback?: AsyncCallback): void; + + /** + * Inserts a single data record into the database. + * @devices phone, tablet + * @since 7 + * @SysCap AAFwk + * @param uri Indicates the path of the data to operate. + * @param value Indicates the data record to insert. If this parameter is null, a blank row will be inserted. + * @return Returns the index of the inserted data record. + */ + insert(URI: string, values: ValuesBucket, callback: AsyncCallback): void; + insert(URI: string, values: ValuesBucket): Promise; + + /** + * Deletes one or more data records from the database. + * @devices phone, tablet + * @since 7 + * @SysCap AAFwk + * @param uri Indicates the path of the data to operate. + * @param predicates Indicates filter criteria. You should define the processing logic when this parameter is null. + * @return Returns the number of data records deleted. + */ + delete(URI: string, predicates: DataAbilityPredicates, callback: AsyncCallback): void; + delete(URI: string, predicates: DataAbilityPredicates): Promise; + + /** + * Queries data in the database. + * @devices phone, tablet + * @since 7 + * @SysCap AAFwk + * @param uri Indicates the path of data to query. + * @param columns Indicates the columns to query. If this parameter is null, all columns are queried. + * @param predicates Indicates filter criteria. You should define the processing logic when this parameter is null. + * @return Returns the query result. + */ + query(URI: string, columns: Array, predicates: DataAbilityPredicates, callback: AsyncCallback): void; + query(URI: string, columns: Array, predicates: DataAbilityPredicates): Promise; + + /** + * Updates data records in the database. + * @devices phone, tablet + * @since 7 + * @SysCap AAFwk + * @param uri Indicates the path of data to update. + * @param value Indicates the data to update. This parameter can be null. + * @param predicates Indicates filter criteria. You should define the processing logic when this parameter is null. + * @return Returns the number of data records updated. + */ + update(URI: string, values: ValuesBucket, predicates: DataAbilityPredicates, callback: AsyncCallback): void; + update(URI: string, values: ValuesBucket, predicates: DataAbilityPredicates): Promise; + + /** + * Inserts multiple data records into the database. + * @devices phone, tablet + * @since 7 + * @SysCap AAFwk + * @param uri Indicates the path of the data to operate. + * @param values Indicates the data records to insert. + * @return Returns the number of data records inserted. + */ + batchInsert(URI: string, values: Array, callback: AsyncCallback): void; + batchInsert(URI: string, values: Array): Promise; + + /** + * Performs batch operations on the database. + * @devices phone, tablet + * @since 7 + * @SysCap AAFwk + * @param uri Indicates the path of data to operate. + * @param operations Indicates a list of database operations on the database. + * @return Returns the result of each operation, in array. + */ + executeBatch(URI: string, operations: Array, callback: AsyncCallback>): void; + executeBatch(URI: string, operations: Array): Promise>; + + /** + * Obtains the MIME type of the date specified by the given URI. + * @devices phone, tablet + * @since 7 + * @SysCap AAFwk + * @param uri Indicates the path of the data to operate. + * @return Returns the MIME type that matches the data specified by uri. + */ + getType(URI: string, callback: AsyncCallback): void; + getType(URI: string): Promise; + + /** + * Obtains the MIME types of files supported. + * @devices phone, tablet + * @since 7 + * @SysCap AAFwk + * @param uri Indicates the path of the files to obtain. + * @param mimeTypeFilter Indicates the MIME types of the files to obtain. This parameter cannot be null. + *

1. "*/*": Obtains all types supported by Data abilities. + *

2. "image/*": Obtains files whose main type is image of any subtype. + *

3. "*/jpg": Obtains files whose subtype is JPG of any main type. + * @return Returns the matched MIME types. If there is no match, {@code null} is returned. + */ + getFileTypes(uri: string, mimeTypeFilter:string, callback: AsyncCallback>): void; + getFileTypes(uri: string, mimeTypeFilter): Promise>; + + /** + * Converts the given {@code uri} that refers to the Data ability into a normalized {@link ohos.utils.net.Uri}. + * A normalized URI can be used across devices, persisted, backed up, and restored. + *

To transfer a normalized URI from another environment to the current environment, you should call this + * method again to re-normalize the URI for the current environment or call {@link #denormalizeUri(Uri)} + * to convert it to a denormalized URI that can be used only in the current environment. + * @devices phone, tablet + * @since 7 + * @SysCap AAFwk + * @param uri Indicates the {@link ohos.utils.net.Uri} object to normalize. + * @return Returns the normalized {@code Uri} object if the Data ability supports URI normalization; + * returns {@code null} otherwise. + * @throws DataAbilityRemoteException Throws this exception if the remote process exits. + * @throws NullPointerException Throws this exception if {@code uri} is null. + * @see #denormalizeUri + */ + normalizeUri(uri: string, callback: AsyncCallback): void; + normalizeUri(uri: string): Promise; + + /** + * Converts the given normalized {@code uri} generated by {@link #normalizeUri(Uri)} into a denormalized one. + * @devices phone, tablet + * @since 7 + * @SysCap AAFwk + * @param uri Indicates the {@link ohos.utils.net.Uri} object to denormalize. + * @return Returns the denormalized {@code Uri} object if the denormalization is successful; returns the + * original {@code Uri} passed to this method if there is nothing to do; returns {@code null} if the data + * identified by the normalized {@code Uri} cannot be found in the current environment. + * @throws DataAbilityRemoteException Throws this exception if the remote process exits. + * @throws NullPointerException Throws this exception if {@code uri} is null. + * @see #normalizeUri + */ + denormalizeUri(uri: string, callback: AsyncCallback): void; + denormalizeUri(uri: string): Promise; + + /** + * Releases the client resource of the Data ability. + *

You should call this method to releases client resource after the data operations are complete.

+ * @devices phone, tablet + * @since 7 + * @SysCap AAFwk + * @return Returns {@code true} if the resource is successfully released; returns {@code false} otherwise. + */ + release(callback: AsyncCallback): void; + release(): Promise; + + /** + * Notifies the registered observers of a change to the data resource specified by Uri. + * @devices phone, tablet + * @since 7 + * @SysCap AAFwk + * @param uri Indicates the {@link ohos.utils.net.Uri} object to notifyChange. + */ + notifyChange(URI: string, callback: AsyncCallback): void; + notifyChange(URI: string): Promise; +} + +export interface DataAbilityResult { + uri?: string; + count?: number; +} \ No newline at end of file diff --git a/tools/interfaces/kits/js/ability/dataAbilityOperation.d.ts b/tools/interfaces/kits/js/ability/dataAbilityOperation.d.ts new file mode 100644 index 00000000000..99074f992c9 --- /dev/null +++ b/tools/interfaces/kits/js/ability/dataAbilityOperation.d.ts @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { ValuesBucket, DataAbilityPredicates } from './../@ohos.data.rdb'; + +/** + * Performs an operation on the database. + * @devices phone, tablet + * + * @since 7 + */ +export interface DataAbilityOperation { + /** + * Obtains the data path of the operation. + * @devices phone, tablet + * @since 7 + * @SysCap AAFwk + */ + uri: string; + /** + * Creates a DataAbilityOperation instance. + * @devices phone, tablet + * @since 7 + * @SysCap AAFwk + */ + type: DataAbilityOperationType; + /** + * Sets the data records to be inserted or updated. + * @devices phone, tablet + * @since 7 + * @SysCap AAFwk + */ + valuesBucket: ValuesBucket; + /** + * Sets filter criteria used for deleting updating or assert query data. + * @devices phone, tablet + * @since 7 + * @SysCap AAFwk + */ + predicates: DataAbilityPredicates; + /** + * Sets the expected number of rows to update ,delete or assert query. + * @devices phone, tablet + * @since 7 + * @SysCap AAFwk + */ + expectedCount: number; + /** + * Back reference to be used as a filter criterion in setPredicates(DataAbilityPredicates). + * This method can be used only for update, delete, and assert operations. + * @devices phone, tablet + * @since 7 + * @SysCap AAFwk + */ + PredicatesBackReferences: {[key: number]: any}; + /** + * Sets an interrupt flag bit for a batch operation, which can be insert, update, delete, or assert. + * + * interrupted Specifies whether a batch operation can be interrupted. + * @devices phone, tablet + * @since 7 + * @SysCap AAFwk + */ + interrupted: boolean; +} + +export enum DataAbilityOperationType { + /** + * Indicates an insert operation. + * @devices phone, tablet + * @since 7 + * @SysCap AAFwk + */ + TYPE_INSERT = 1, + /** + * Indicates an update operation. + * @devices phone, tablet + * @since 7 + * @SysCap AAFwk + */ + TYPE_UPDATE = 2, + /** + * Indicates a delete operation. + * @devices phone, tablet + * @since 7 + * @SysCap AAFwk + */ + TYPE_DELETE = 3, + /** + * Indicates an assert operation. + * @devices phone, tablet + * @since 7 + * @SysCap AAFwk + */ + TYPE_ASSERT = 4 +} \ No newline at end of file diff --git a/tools/interfaces/kits/js/ability/startAbilityParameter.d.ts b/tools/interfaces/kits/js/ability/startAbilityParameter.d.ts new file mode 100644 index 00000000000..a628cffd1d3 --- /dev/null +++ b/tools/interfaces/kits/js/ability/startAbilityParameter.d.ts @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { Want } from './want'; +import { TaskSyncAnimationOptions } from './taskSyncAnimator' + +export interface StartAbilityParameter { + /** + * Indicates the Want containing information about the target ability to start. + * + * @default - + * @devices phone, tablet + * @since 3 + * @SysCap aafwk + */ + want: Want; + + /** + * Indicates the special start setting used in starting ability. + * + * @default - + * @devices phone, tablet + * @since 3 + * @SysCap aafwk + */ + abilityStartSetting?: {[key: string]: any}; + + /** + * Indicates the special start setting used in starting ability with TaskSyncAnimation. + *

Requires Permission: {@code ohos.permission.CONTROL_TASK_SYNC_ANIMATOR} + * + * @default - + * @devices phone, tablet + * @permission ohos.permission.CONTROL_TASK_SYNC_ANIMATOR + * @since 7 + * @SysCap aafwk + */ + taskSyncAnimationOptions?: TaskSyncAnimationOptions; +} diff --git a/tools/interfaces/kits/js/ability/want.d.ts b/tools/interfaces/kits/js/ability/want.d.ts new file mode 100644 index 00000000000..af2183ded2e --- /dev/null +++ b/tools/interfaces/kits/js/ability/want.d.ts @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Want is the basic communication component of the system. + * @name Want + * @since 6 + * @sysCap AAFwk + * @devices phone, tablet + * @permission N/A + */ +export declare interface Want { + /** + * device id + * @default - + * @devices phone, tablet + * @since 6 + * @sysCap AAFwk + */ + deviceId?: string; + + /** + * bundle name + * @default - + * @devices phone, tablet + * @since 6 + * @sysCap AAFwk + */ + bundleName?: string; + + /** + * ability name + * @default - + * @devices phone, tablet + * @since 6 + * @sysCap AAFwk + */ + abilityName?: string; + + /** + * The description of a URI in a Want. + * @devices phone, tablet + * @since 6 + * @sysCap AAFwk + * @default - + */ + uri?: string; + + /** + * The description of the type in this Want. + * @devices phone, tablet + * @since 6 + * @sysCap AAFwk + * @default - + */ + type?: string; + + /** + * The options of the flags in this Want. + * @devices phone, tablet + * @since 6 + * @sysCap AAFwk + * @default - + */ + flags?: number; + + /** + * The description of an action in an want. + * @devices phone, tablet + * @since 6 + * @sysCap AAFwk + * @default - + */ + action?: string; + + /** + * The description of the WantParams object in an Want + * @devices phone, tablet + * @since 6 + * @sysCap AAFwk + * @default - + */ + parameters?: {[key: string]: any}; + + /** + * The description of a entities in a Want. + * @devices phone, tablet + * @since 6 + * @sysCap AAFwk + * @default - + */ + entities?: Array; +} \ No newline at end of file diff --git a/tools/interfaces/kits/js/app/abilityMissionInfo.d.ts b/tools/interfaces/kits/js/app/abilityMissionInfo.d.ts new file mode 100755 index 00000000000..bd219349286 --- /dev/null +++ b/tools/interfaces/kits/js/app/abilityMissionInfo.d.ts @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ElementName } from '../bundle/elementName'; + +/** + * @name Mission information corresponding to ability + * @since 7 + * @SysCap SystemCapability.Appexecfwk + * @import import AbilityMissionInfo from 'app/abilityMissionInfo' + * @permission N/A + * @devices phone, tablet, tv, wearable, car + */ +export interface AbilityMissionInfo { + /** + * @default Unique identification of task stack information corresponding to ability + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + missionId: number; + + /** + * @default The component launched as the first ability in the task stack + * This can be considered the "application" of this task stack + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + bottomAbility: ElementName; + + /** + * @default The ability component at the top of the history stack of the task + * This is what the user is currently doing + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + topAbility: ElementName; + + /** + * @default The corresponding ability description information in the task stack + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + windowMode: number; +} + diff --git a/tools/interfaces/kits/js/app/activeProcessInfo.d.ts b/tools/interfaces/kits/js/app/activeProcessInfo.d.ts new file mode 100755 index 00000000000..4ab5a6aa3d1 --- /dev/null +++ b/tools/interfaces/kits/js/app/activeProcessInfo.d.ts @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @name This class saves process information about an application + * @since 7 + * @SysCap SystemCapability.Appexecfwk + * @import import app from 'app/activeProcessInfo' + * @permission N/A + * @devices phone, tablet, tv, wearable, car + */ +export interface ActiveProcessInfo { + /** + * @default process id + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + pid: number; + + /** + * @default user id + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + uid: number; + + /** + * @default the name of the process + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + processName: string; + + /** + * @default an array of the bundleNames running in the process + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + bundleNames: Array; +} diff --git a/tools/interfaces/kits/js/app/activeServiceAbilityInfo.d.ts b/tools/interfaces/kits/js/app/activeServiceAbilityInfo.d.ts new file mode 100755 index 00000000000..8e9c14e1142 --- /dev/null +++ b/tools/interfaces/kits/js/app/activeServiceAbilityInfo.d.ts @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ElementName } from '../bundle/elementName'; + +/** + * @name information corresponding to active service ability + * @since 7 + * @SysCap SystemCapability.Appexecfwk + * @import import AbilityMissionInfo from 'app/activeServiceAbilityInfo' + * @permission N/A + * @devices phone, tablet, tv, wearable, car + */ +export interface ActiveServiceAbilityInfo { + /** + * @default process id + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + pid: number; + + /** + * @default user id + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + uid: number; + + /** + * @default the name of the process + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + processName: string; + + /** + * @default The element name of the service ability + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + serviceAbility: ElementName; +} + diff --git a/tools/interfaces/kits/js/app/context.d.ts b/tools/interfaces/kits/js/app/context.d.ts new file mode 100755 index 00000000000..4ccb5f05a9e --- /dev/null +++ b/tools/interfaces/kits/js/app/context.d.ts @@ -0,0 +1,105 @@ +/* +* Copyright (c) 2021 Huawei Device Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import { AsyncCallback } from '../basic'; + +/** + * The context of an ability or an application. It allows access to + * application-specific resources, request and verification permissions. + * Can only be obtained through the ability. + * + * @since 6 + * @SysCap SystemCapability.Appexecfwk + * @devices phone, tablet, tv, wearable, car + * @import import abilityManager from 'app/context' + * @permission N/A + */ +export interface Context { + + /** + * Verify whether the specified permission is allowed for a particular + * pid and uid running in the system. + * @param permission The name of the specified permission + * @param pid process id + * @param uid user id + * @note Pid and uid are optional. If you do not pass in pid and uid, + * it will check your own permission. + * @since 7 + * @sysCap SystemCapability.Appexecfwk + * @devices phone, tablet, tv, wearable, car + * @return asynchronous callback with {@code 0} if the PID + * and UID have the permission; callback with {@code -1} otherwise. + */ + verifyPermission(permission: string, options?: PermissionOptions): Promise; + verifyPermission(permission: string, options: PermissionOptions, callback: AsyncCallback): void; + verifyPermission(permission: string, callback: AsyncCallback): void; + + /** + * Requests certain permissions from the system. + * @param permissions Indicates the list of permissions to be requested. This parameter cannot be null. + * @param requestCode Indicates the request code to be passed to the PermissionRequestResult + * @since 7 + * @sysCap SystemCapability.Appexecfwk + * @devices phone, tablet, tv, wearable, car + */ + requestPermissionsFromUser(permissions: Array, requestCode: number, resultCallback: AsyncCallback): void; + +} + +/** + * @name the result of requestPermissionsFromUser with asynchronous callback + * @since 7 + * @SysCap SystemCapability.Appexecfwk + * @permission N/A + * @devices phone, tablet, tv, wearable, car + */ +interface PermissionRequestResult { + /** + * @default The request code passed in by the user + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + requestCode: number; + + /** + * @default The permissions passed in by the user + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + permissions: Array; + + /** + * @default The results for the corresponding request permissions + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + authResults: Array; +} + +interface PermissionOptions { + /** + * @default The process id + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + pid?: number; + + /** + * @default The user id + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + uid?: number; +} diff --git a/tools/interfaces/kits/js/app/memoryMapInfo.d.ts b/tools/interfaces/kits/js/app/memoryMapInfo.d.ts new file mode 100755 index 00000000000..4c8ab45c3b1 --- /dev/null +++ b/tools/interfaces/kits/js/app/memoryMapInfo.d.ts @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @name This class saves memory map information about an application. + * All results are in kB. + * @since 7 + * @SysCap SystemCapability.Appexecfwk + * @import import MemoryMapInfo from 'app/memoryMapInfo' + * @permission N/A + * @devices phone, tablet, tv, wearable, car + * @systemapi hide this for inner system use + */ +export interface MemoryMapInfo { + /** + * @default The pss page size for virtual machine heap + */ + vmPss: number; + /** + * @default The private dirty page size for virtual machine heap + */ + vmPrivateDirty: number; + /** + * @default The shared dirty page size for virtual machine heap + */ + vmSharedDirty: number; + /** + * @default The pss page size for native heap + */ + nativePss: number; + /** + * @default The private dirty page size for native heap + */ + nativePrivateDirty: number; + /** + * @default The shared dirty page size for native heap + */ + nativeSharedDirty: number; + /** + * @default The pss page size for others + */ + otherPss: number; + /** + * @default The private dirty page size for others + */ + otherPrivateDirty: number; + /** + * @default The shared dirty page size for others + */ + otherSharedDirty: number; +} diff --git a/tools/interfaces/kits/js/app/missionSnapshot.d.ts b/tools/interfaces/kits/js/app/missionSnapshot.d.ts new file mode 100755 index 00000000000..01ae787ee8c --- /dev/null +++ b/tools/interfaces/kits/js/app/missionSnapshot.d.ts @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ElementName } from '../bundle/elementName'; +import { image } from '../@ohos.multimedia.image'; + +/** + * @name This class represents a mission snapshot. + * @since 7 + * @SysCap appexecfwk + * @import import MissionSnapshot from 'app/missionSnapshot' + * @devices phone, tablet + * @systemapi hide this for inner system use + */ +export interface MissionSnapshot { + /** + * @default The top ability in this mission snapshot + */ + topAbility: ElementName; + + /** + * @default The entity of snapshot + */ + snapshot: image.PixelMap; +} diff --git a/tools/interfaces/kits/js/app/processErrorInfo.d.ts b/tools/interfaces/kits/js/app/processErrorInfo.d.ts new file mode 100755 index 00000000000..f08a28f7059 --- /dev/null +++ b/tools/interfaces/kits/js/app/processErrorInfo.d.ts @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ProcessErrCode } from '../@ohos.app.abilityManager.d.ts'; + +/** + * @name This class saves process error information + * @since 7 + * @SysCap appexecfwk + * @import import app from 'app/processErrorInfo' + * @devices phone, tablet + * @systemapi hide this for inner system use + */ +export interface ProcessErrorInfo { + /** + * @default Error reason, see { ProcessErrCode } in abilityManager + */ + errStatus: ProcessErrCode; + /** + * @default the name of the error process + */ + processName: string; + /** + * @default the process ID + */ + pid: number; + /** + * @default the user ID + */ + uid: number; + /** + * @default the name of the ability corresponding with the error + */ + abilityName: string; + /** + * @default the error message + */ + errMsg: string; + /** + * @default the error trace, for you to find the original error + */ + backTrace: string; +} + diff --git a/tools/interfaces/kits/js/app/splitMissionInfo.d.ts b/tools/interfaces/kits/js/app/splitMissionInfo.d.ts new file mode 100755 index 00000000000..6f911d73360 --- /dev/null +++ b/tools/interfaces/kits/js/app/splitMissionInfo.d.ts @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { RectBounds } from '../wallpaper'; + +/** + * @name This class is the input param for { moveMissionToFirstSplitScreen }. + * @since 7 + * @SysCap appexecfwk + * @import import app from 'app/splitMissionInfo' + * @devices phone, tablet + * @systemapi hide this for inner system use + */ +export interface SplitMissionInfo { + /** + * @default the mission id that you want to move + */ + missionId: number; + /** + * @default whether the target window is the first one + */ + isFirstWindow: boolean; + /** + * @default whether to move the mission to top + */ + isToTop: boolean; + /** + * @default Whether you want an animation when moving the task + */ + isAnimating: boolean; + /** + * @default The bounds of the split window + */ + initialBounds: RectBounds; +} diff --git a/tools/interfaces/kits/js/app/systemMemoryAttr.d.ts b/tools/interfaces/kits/js/app/systemMemoryAttr.d.ts new file mode 100755 index 00000000000..eee6e70681a --- /dev/null +++ b/tools/interfaces/kits/js/app/systemMemoryAttr.d.ts @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @name This class saves system memory attributes + * @since 7 + * @SysCap SystemCapability.Appexecfwk + * @import import MemoryMapInfo from 'app/systemMemoryAttr' + * @devices phone, tablet, tv, wearable, car + * @systemapi hide this for inner system use + */ + export interface SystemMemoryAttr { + /** + * @default The available memory on the system + */ + availSysMem: number; + /** + * @default The total memory on the system + */ + totalSysMem: number; + /** + * @default The low memory threshold under which the system + * will kill background processes + */ + threshold: number; + /** + * @default Whether the system is in low memory status + */ + isSysInlowMem: boolean; +} + + diff --git a/tools/interfaces/kits/js/bundle/abilityInfo.d.ts b/tools/interfaces/kits/js/bundle/abilityInfo.d.ts new file mode 100644 index 00000000000..7e6904ab2e9 --- /dev/null +++ b/tools/interfaces/kits/js/bundle/abilityInfo.d.ts @@ -0,0 +1,244 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ApplicationInfo } from './applicationInfo'; +import { CustomizeData } from './customizeData' +import bundle from './../@ohos.bundle'; + +/** + * @name Obtains configuration information about an ability + * @since 7 + * @SysCap SystemCapability.Appexecfwk + * @permission NA + * @devices phone, tablet, tv, wearable, car + */ +export interface AbilityInfo { + /** + * @default Indicates the name of the bundle containing the ability + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly bundleName: string; + + /** + * @default Ability simplified class name + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly name: string; + + /** + * @default Indicates the label of the ability + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly label: string; + + /** + * @default Describes the ability + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly description: string; + + /** + * @default Indicates the icon of the ability + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly icon: string; + + /** + * @default Indicates the label id of the ability + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly labelId: number; + + /** + * @default Indicates the description id of the ability + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly descriptionId: number; + + /** + * @default Indicates the icon id of the ability + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly iconId: number; + + /** + * @default Indicates the name of the .hap package to which the capability belongs + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly moduleName: string; + + /** + * @default Process of ability, if user do not set it ,the value equal application process + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly process: string; + + /** + * @default Info about which ability is this nick point to + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly targetAbility: string; + + /** + * @default Indicates the background service addressing a specific usage scenario + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly backgroundModes: number; + + /** + * @default Indicates whether an ability can be called by other abilities + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly isVisible: boolean; + + /** + * @default Indicates whether the ability provides the embedded card capability + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly formEnabled: boolean; + + /** + * @default Enumerates types of templates that can be used by an ability + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly type: bundle.AbilityType; + + /** + * @default Enumerates the subType of templates used by an ability + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly subType: bundle.AbilitySubType; + + /** + * @default Enumerates ability display orientations + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly orientation: bundle.DisplayOrientation; + + /** + * @default Enumerates ability launch modes + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly launchMode: bundle.LaunchMode; + + /** + * @default The permissions that others need to launch this ability + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly permissions: Array; + + /** + * @default The device types that this ability can run on + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly deviceTypes: Array; + + /** + * @default The device capability that this ability needs + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly deviceCapabilities: Array; + + /** + * @default Indicates the permission required for reading ability data + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly readPermission: string; + + /** + * @default Indicates the permission required for writing data to the ability + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly writePermission: string; + + /** + * @default Obtains configuration information about an application + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly applicationInfo: ApplicationInfo; + + /** + * @default Where form can be displayed + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly formEntity: number; + + /** + * @default Minimum height of ability. + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly minFormHeight: number; + + /** + * @default Default height of ability + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly defaultFormHeight: number; + + /** + * @default Minimum width of ability + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly minFormWidth: number; + + /** + * @default Default width of ability + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly defaultFormWidth: number; + + /** + * @default Uri of ability + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly uri: string; + + /** + * @default Indicates the custom metadata of ability + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + customizeData: Map>; +} diff --git a/tools/interfaces/kits/js/bundle/applicationInfo.d.ts b/tools/interfaces/kits/js/bundle/applicationInfo.d.ts new file mode 100644 index 00000000000..4820474ef88 --- /dev/null +++ b/tools/interfaces/kits/js/bundle/applicationInfo.d.ts @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ModuleInfo } from './moduleInfo'; +import { CustomizeData } from './customizeData' + +/** + * @name Obtains configuration information about an application + * @since 7 + * @SysCap SystemCapability.Appexecfwk + * @permission NA + * @devices phone, tablet, tv, wearable, car + */ +export interface ApplicationInfo { + /** + * @default Indicates the application name, which is the same as {@code bundleName} + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly name: string; + + /** + * @default Description of application + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly description: string; + + /** + * @default Indicates the description id of the application + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly descriptionId: number; + + /** + * @default Indicates whether the application is a system application + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly systemApp: boolean; + + /** + * @default Indicates whether or not this application may be instantiated + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly enabled: boolean; + + /** + * @default Indicates the label of the application + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly label: string; + + /** + * @default Indicates the label id of the application + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly labelId: string; + + /** + * @default Indicates the icon of the application + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly icon: string; + + /** + * @default Indicates the icon id of the application + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly iconId: string; + + /** + * @default Process of application, if user do not set it ,the value equal bundleName + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly process: string; + + /** + * @default Indicates the running mode supported by the application + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly supportedModes: number; + + /** + * @default Indicates the path storing the module resources of the application + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly moduleSourceDirs: Array; + + /** + * @default Indicates the permissions required for accessing the application. + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly permissions: Array; + + /** + * @default Indicates module information about an application + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly moduleInfo: Array; + + /** + * @default Indicates the path where the {@code Entry.hap} file of the application is saved + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly entryDir: string; + + /** + * @default Indicates the custom metadata of the application + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + customizeData: Map; +} \ No newline at end of file diff --git a/tools/interfaces/kits/js/bundle/bundleInfo.d.ts b/tools/interfaces/kits/js/bundle/bundleInfo.d.ts new file mode 100644 index 00000000000..6353eaef993 --- /dev/null +++ b/tools/interfaces/kits/js/bundle/bundleInfo.d.ts @@ -0,0 +1,237 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { AbilityInfo } from './abilityInfo'; +import { ApplicationInfo } from './applicationInfo'; +import { HapModuleInfo } from './hapModuleInfo'; + +/** + * @name The scene which is used + * @since 7 + * @SysCap SystemCapability.Appexecfwk + * @permission NA + * @devices phone, tablet, tv, wearable, car + */ +export interface UsedScene { + /** + * @default Indicates the abilities that need the permission + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + abilities: Array; + + /** + * @default Indicates the time when the permission is used + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + when: string; +} + +/** + * @name Indicates the required permissions details defined in file config.json + * @since 7 + * @SysCap SystemCapability.Appexecfwk + * @permission NA + * @devices phone, tablet, tv, wearable, car + */ +export interface ReqPermissionDetail { + /** + * @default Indicates the name of this required permissions + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + name: string; + + /** + * @default Indicates the reason of this required permissions + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + reason: string; + + /** + * @default Indicates the used scene of this required permissions + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + usedScene: UsedScene; +} + +/** + * @name Obtains configuration information about a bundle + * @since 7 + * @SysCap SystemCapability.Appexecfwk + * @permission NA + * @devices phone, tablet, tv, wearable, car + */ +export interface BundleInfo { + /** + * @default Indicates the name of this bundle + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly name: string; + + /** + * @default Indicates the name of this original bundle + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly type: string; + + /** + * @default Indicates the ID of the application to which this bundle belongs + * The application ID uniquely identifies an application. It is determined by the bundle name and signature + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly appId: string; + + /** + * @default Indicates the UID of the application to which this bundle belongs + * The UID uniquely identifies an application. It is determined by the process and user IDs of the application + * After an application is installed, its UID remains unchanged unless it is uninstalled and then reinstalled + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly uid: number; + + /** + * @default Indicates the hap install time + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly installTime: number; + + /** + * @default Indicates the hap update time + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly updateTime: number; + + /** + * @default Obtains configuration information about an application + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly appInfo: ApplicationInfo; + + /** + * @default Obtains configuration information about an ability + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly abilityInfo: Array; + + /** + * @default Indicates the required permissions name defined in file config.json + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly reqPermissions: Array; + + /** + * @default Indicates the required permissions details defined in file config.json + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly reqPermissionDetails: Array; + + /** + * @default Describes the bundle vendor + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly vendor: string; + + /** + * @default Indicates the version number of the bundle + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly versionCode: number; + + /** + * @default Indicates the text description of the bundle version + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly versionName: string; + + /** + * @default Indicates the compatible version number of the bundle + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly compatibleVersion: number; + + /** + * @default Indicates the target version number of the bundle + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly targetVersion: number; + + /** + * @default Indicates is compress native libs + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly isCompressNativeLibs: boolean; + + /** + * @default Obtains configuration information about an module + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly hapModuleInfo: Array; + + /** + * @default Indicates entry module name + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly entryModuleName: string; + + /** + * @default Indicates the cpuAbi information of this bundle. + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly cpuAbi: string; + + /** + * @default Indicates is silent installation + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly isSilentInstallation: string; + + /** + * @default Indicates the earliest historical version compatible with the bundle + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly minCompatibleVersionCode: number; + + /** + * @default Indicates whether free installation of the entry is supported + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly entryInstallationFree: boolean; +} diff --git a/tools/interfaces/kits/js/bundle/bundleInstaller.d.ts b/tools/interfaces/kits/js/bundle/bundleInstaller.d.ts new file mode 100644 index 00000000000..5cdfc48f780 --- /dev/null +++ b/tools/interfaces/kits/js/bundle/bundleInstaller.d.ts @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { AsyncCallback } from './../basic'; +import bundle from './../@ohos.bundle'; + +/** + * @name Provides parameters required for installing or uninstalling an application. + * @since 7 + * @SysCap SystemCapability.Appexecfwk + * @permission NA + * @devices phone, tablet, tv, wearable, car + */ +export interface InstallParam { + /** + * @default Indicates the user id + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + userId: number; + + /** + * @default Indicates the install flag + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + installFlag: number; + + /** + * @default Indicates whether the param has data + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + isKeepData: boolean; +} + +/** + * @name Indicates the install or uninstall status + * @since 7 + * @SysCap SystemCapability.Appexecfwk + * @permission NA + * @devices phone, tablet, tv, wearable, car + */ +export interface InstallStatus { + + /** + * @default Indicates the install or uninstall error code + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + status: bundle.InstallErrorCode; + + /** + * @default Indicates the install or uninstall result string message + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + statusMessage: string; +} + +/** + * @name Offers install, upgrade, and remove bundles on the devices. + * @since 7 + * @SysCap SystemCapability.Appexecfwk + * @permission NA + * @devices phone, tablet, tv, wearable, car + */ +export interface BundleInstaller { + /** + * Install an application in a HAP. + * + * @since 7 + * @SysCap SystemCapability.Appexecfwk + * @devices phone, tablet, tv, wearable, car + * @param bundleFilePaths Indicates the path where the bundle of the application is stored. The path should be the + * relative path to the data directory of the current application. + * @param installParam Indicates other parameters required for the installation. + * @return InstallStatus + * @permission ohos.permission.INSTALL_BUNDLE + */ + install(bundleFilePaths: Array, param: InstallParam, callback: AsyncCallback): void; + + /** + * Uninstall an application. + * + * @since 7 + * @SysCap SystemCapability.Appexecfwk + * @devices phone, tablet, tv, wearable, car + * @param bundleName Indicates the bundle name of the application to be uninstalled. + * @param installParam Indicates other parameters required for the uninstallation. + * @return InstallStatus + * @permission ohos.permission.INSTALL_BUNDLE + */ + uninstall(bundleName: string, param: InstallParam, callback: AsyncCallback): void; +} \ No newline at end of file diff --git a/tools/interfaces/kits/js/bundle/customizeData.d.ts b/tools/interfaces/kits/js/bundle/customizeData.d.ts new file mode 100644 index 00000000000..17393229f1f --- /dev/null +++ b/tools/interfaces/kits/js/bundle/customizeData.d.ts @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + /** + * @name Indicates the custom metadata + * @since 7 + * @SysCap SystemCapability.Appexecfwk + * @permission NA + * @devices phone, tablet, tv, wearable, car + */ +export interface CustomizeData { + /** + * @default Indicates the custom metadata name + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + name: string; + + /** + * @default Indicates the custom metadata value + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + value: string; +} \ No newline at end of file diff --git a/tools/interfaces/kits/js/bundle/elementName.d.ts b/tools/interfaces/kits/js/bundle/elementName.d.ts new file mode 100644 index 00000000000..68fe8ddda30 --- /dev/null +++ b/tools/interfaces/kits/js/bundle/elementName.d.ts @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Contains basic Ability information, which uniquely identifies an ability. + * You can use this class to obtain values of the fields set in an element, + * such as the device ID, bundle name, and ability name. + * @name Contains basic Ability information, which uniquely identifies an ability + * @since 7 + * @sysCap SystemCapability.Appexecfwk + * @devices phone, tablet, tv, wearable, car + * @permission N/A + */ +export interface ElementName { + /** + * device id + * @default - + * @devices phone, tablet, tv, wearable, car + * @since 7 + * @sysCap SystemCapability.Appexecfwk + */ + deviceId?: string; + + /** + * bundle name + * @default - + * @devices phone, tablet, tv, wearable, car + * @since 7 + * @sysCap SystemCapability.Appexecfwk + */ + bundleName: string; + + /** + * ability name + * @default ability class name. + * @devices phone, tablet, tv, wearable, car + * @since 7 + * @sysCap SystemCapability.Appexecfwk + */ + abilityName: string; + + /** + * uri + * @default - + * @devices phone, tablet, tv, wearable, car + * @since 7 + * @sysCap SystemCapability.Appexecfwk + */ + uri?: string; + + /** + * shortName + * @default - + * @devices phone, tablet, tv, wearable, car + * @since 7 + * @sysCap SystemCapability.Appexecfwk + */ + shortName?: string; +} diff --git a/tools/interfaces/kits/js/bundle/hapModuleInfo.d.ts b/tools/interfaces/kits/js/bundle/hapModuleInfo.d.ts new file mode 100644 index 00000000000..a62a66955d3 --- /dev/null +++ b/tools/interfaces/kits/js/bundle/hapModuleInfo.d.ts @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { AbilityInfo } from "./abilityInfo"; + +/** + * @name Obtains configuration information about an module. + * @since 7 + * @SysCap SystemCapability.Appexecfwk + * @permission NA + * @devices phone, tablet, tv, wearable, car + */ +export interface HapModuleInfo { + /** + * @default Indicates the name of this hapmodule + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly name: string; + /** + * @default Describes the hapmodule + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly description: string; + /** + * @default Indicates the description of this hapmodule + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly descriptionId: number; + /** + * @default Indicates the icon of this hapmodule + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly icon: string; + /** + * @default Indicates the label of this hapmodule + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly label: string; + /** + * @default Indicates the label id of this hapmodule + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly labelId: number; + /** + * @default Indicates the icon id of this hapmodule + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly iconId: number; + /** + * @default Indicates the background img of this hapmodule + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly backgroundImg: string; + /** + * @default Indicates the supported modes of this hapmodule + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly supportedModes: number; + /** + * @default Indicates the req capabilities of this hapmodule + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly reqCapabilities: Array; + /** + * @default The device types that this hapmodule can run on + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly deviceTypes: Array; + /** + * @default Obtains configuration information about ability + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly abilityInfo: Array; + /** + * @default Indicates the name of the .hap package to which the capability belongs + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly moduleName: string; + /** + * @default Indicates the main ability name of this hapmodule + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly mainAbilityName: string; + /** + * @default Indicates whether free installation of the hapmodule is supported + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly installationFree: boolean; +} \ No newline at end of file diff --git a/tools/interfaces/kits/js/bundle/moduleInfo.d.ts b/tools/interfaces/kits/js/bundle/moduleInfo.d.ts new file mode 100644 index 00000000000..437ca90fa90 --- /dev/null +++ b/tools/interfaces/kits/js/bundle/moduleInfo.d.ts @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @name Stores module information about an application. + * @since 7 + * @SysCap SystemCapability.Appexecfwk + * @permission NA + * @devices phone, tablet, tv, wearable, car + */ +export interface ModuleInfo { + /** + * The module name. + * + * @default Indicates the name of the .hap package to which the capability belongs + * @devices phone, tablet, tv, wearable, car + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly moduleName: string; + + /** + * The module source path. + * + * @default Indicates the module source dir of this module + * @devices phone, tablet, tv, wearable, car + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly moduleSourceDir: string; +} \ No newline at end of file diff --git a/tools/interfaces/kits/js/bundle/moduleUsageRecord.d.ts b/tools/interfaces/kits/js/bundle/moduleUsageRecord.d.ts new file mode 100644 index 00000000000..0bc3620102c --- /dev/null +++ b/tools/interfaces/kits/js/bundle/moduleUsageRecord.d.ts @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @name Stores FA usage information. + * @since 7 + * @SysCap SystemCapability.Appexecfwk + * @permission NA + * @devices phone, tablet, tv, wearable, car + * @systemapi hide this for inner system use + */ +export interface ModuleUsageRecord { + /** + * @default Indicates the name of the bundle containing the module + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly bundleName: string; + /** + * @default Indicates the app label id of this module + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly appLabelId: number; + /** + * @default Indicates the name of this module + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly name: string; + /** + * @default Indicates the label id of this module + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly labelId: number; + /** + * @default Indicates the description id of this module + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly descriptionId: number; + /** + * @default Indicates the ability name of this module + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly abilityName: string; + /** + * @default Indicates the ability label id of this module + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly abilityLabelId: number; + /** + * @default Indicates the ability description id of this module + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly abilityDescriptionId: number; + /** + * @default Indicates the ability icon id of this module + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly abilityIconId: number; + /** + * @default Indicates the launched count of this module + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly launchedCount: number; + /** + * @default Indicates the last launch time of this module + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly lastLaunchTime: number; + /** + * @default Indicates whether the module is removed + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly isRemoved: boolean; + /** + * @default Indicates whether free installation of the module is supported + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly installationFreeSupported: boolean; +} \ No newline at end of file diff --git a/tools/interfaces/kits/js/bundle/shortcutInfo.d.ts b/tools/interfaces/kits/js/bundle/shortcutInfo.d.ts new file mode 100644 index 00000000000..0caaa904588 --- /dev/null +++ b/tools/interfaces/kits/js/bundle/shortcutInfo.d.ts @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + /** + * @name Provides methods for obtaining information about the ability that a shortcut will start, including the target + * bundle name and ability class name. + * @since 7 + * @SysCap SystemCapability.Appexecfwk + * @permission NA + * @devices phone, tablet, tv, wearable, car + */ +export interface ShortcutWant{ + /** + * @default Indicates the target bundle of the shortcut want + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly targetBundle: string; + /** + * @default Indicates the target class of the shortcut want + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly targetClass: string; +} + + /** + * @name Provides information about a shortcut, including the shortcut ID and label. + * @since 7 + * @SysCap SystemCapability.Appexecfwk + * @permission NA + * @devices phone, tablet, tv, wearable, car + */ +export interface ShortcutInfo { + /** + * @default Indicates the ID of the application to which this shortcut belongs + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly id: string; + /** + * @default Indicates the name of the bundle containing the shortcut + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly bundleName: string; + /** + * @default Indicates the host ability of the shortcut + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly hostAbility: string; + /** + * @default Indicates the icon of the shortcut + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly icon: string; + /** + * @default Indicates the label of the shortcut + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly label: string; + /** + * @default Indicates the disableMessage of the shortcut + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly disableMessage: string; + /** + * @default Indicates the wants of the shortcut + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly wants: Array; + /** + * @default Indicates whether the shortcut is static + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly isStatic?: boolean + /** + * @default Indicates whether the shortcut is homeshortcut + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly isHomeShortcut?: boolean; + /** + * @default Indicates whether the shortcut is enabled + * @since 7 + * @SysCap SystemCapability.Appexecfwk + */ + readonly isEnabled?: boolean; +} \ No newline at end of file diff --git a/tools/interfaces/kits/napi/BUILD.gn b/tools/interfaces/kits/napi/BUILD.gn new file mode 100644 index 00000000000..a1c784f492f --- /dev/null +++ b/tools/interfaces/kits/napi/BUILD.gn @@ -0,0 +1,26 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") + +group("napi_packages") { + deps = [ + "//foundation/aafwk/standard/interfaces/kits/napi/aafwk/abilityManager:abilitymanager", + "//foundation/aafwk/standard/interfaces/kits/napi/aafwk/dataUriUtils:datauriutils", + "//foundation/aafwk/standard/interfaces/kits/napi/aafwk/featureAbility:featureability", + "//foundation/aafwk/standard/interfaces/kits/napi/aafwk/formManager:formmanager", + "//foundation/aafwk/standard/interfaces/kits/napi/aafwk/inner/napi_common:napi_common", + "//foundation/aafwk/standard/interfaces/kits/napi/aafwk/particleAbility:particleability", + "//foundation/aafwk/standard/interfaces/kits/napi/aafwk/wantConstant:wantconstant", + ] +} diff --git a/tools/interfaces/kits/napi/aafwk/abilityManager/BUILD.gn b/tools/interfaces/kits/napi/aafwk/abilityManager/BUILD.gn new file mode 100644 index 00000000000..85dcab01731 --- /dev/null +++ b/tools/interfaces/kits/napi/aafwk/abilityManager/BUILD.gn @@ -0,0 +1,57 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") + +ohos_shared_library("abilitymanager") { + include_dirs = [ + "//foundation/ace/napi/interfaces/kits", + "//third_party/node/src", + "//foundation/aafwk/standard/services/common/include", + "//utils/system/safwk/native/include", + "./", + ] + + sources = [ + "napi_ability_manager.cpp", + "native_module.cpp", + ] + + deps = [ + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/interfaces/innerkits/ability_manager:ability_manager", + "//foundation/aafwk/standard/interfaces/innerkits/base:base", + "//foundation/aafwk/standard/interfaces/innerkits/want:want", + "//foundation/ace/napi:ace_napi", + "//foundation/appexecfwk/standard/common:libappexecfwk_common", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_core:appexecfwk_core", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/appexecfwk/standard/kits:appkit_native", + "//foundation/appexecfwk/standard/libs/libeventhandler:libeventhandler_target", + "//foundation/appexecfwk/standard/services/appmgr:libams", + "//foundation/distributedschedule/safwk/interfaces/innerkits/safwk:system_ability_fwk", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy:samgr_proxy", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] + + relative_install_dir = "module/app" + + subsystem_name = "aafwk" + part_name = "aafwk_standard" +} diff --git a/tools/interfaces/kits/napi/aafwk/abilityManager/napi_ability_manager.cpp b/tools/interfaces/kits/napi/aafwk/abilityManager/napi_ability_manager.cpp new file mode 100644 index 00000000000..011988f3f81 --- /dev/null +++ b/tools/interfaces/kits/napi/aafwk/abilityManager/napi_ability_manager.cpp @@ -0,0 +1,1869 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "napi_ability_manager.h" + +#include +#include + +#include "hilog_wrapper.h" +#include "ipc_skeleton.h" +#include "system_ability_definition.h" +#include "if_system_ability_manager.h" +#include "iservice_registry.h" +#include "app_mgr_interface.h" +#include "ability_manager_interface.h" + +using namespace OHOS::AAFwk; + +namespace OHOS { +namespace AppExecFwk { +OHOS::sptr GetAbilityManagerInstance() +{ + OHOS::sptr systemAbilityManager = + OHOS::SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + OHOS::sptr abilityObject = + systemAbilityManager->GetSystemAbility(OHOS::ABILITY_MGR_SERVICE_ID); + return OHOS::iface_cast(abilityObject); +} + +OHOS::sptr GetAppManagerInstance() +{ + OHOS::sptr systemAbilityManager = + OHOS::SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + OHOS::sptr appObject = systemAbilityManager->GetSystemAbility(OHOS::APP_MGR_SERVICE_ID); + return OHOS::iface_cast(appObject); +} + +napi_value ParseBundleName(napi_env env, std::string &bundleName, napi_value args) +{ + napi_valuetype valuetype = napi_valuetype::napi_null; + NAPI_CALL(env, napi_typeof(env, args, &valuetype)); + NAPI_ASSERT(env, valuetype == napi_string, "Wrong argument type. String expected."); + char buf[BUFFER_LENGTH_MAX] = {0}; + size_t len = 0; + napi_get_value_string_utf8(env, args, buf, BUFFER_LENGTH_MAX, &len); + HILOG_INFO("bundleName= [%{public}s].", buf); + bundleName = std::string(buf); + // create reutrn + napi_value ret = 0; + NAPI_CALL(env, napi_create_int32(env, 0, &ret)); + return ret; +} + +void GetRecentMissionsForResult( + napi_env env, const std::vector &recentMissionInfos, napi_value result) +{ + int32_t index = 0; + for (const auto &item : recentMissionInfos) { + napi_value objRecentMissionInfo = nullptr; + NAPI_CALL_RETURN_VOID(env, napi_create_object(env, &objRecentMissionInfo)); + + napi_value id = nullptr; + NAPI_CALL_RETURN_VOID(env, napi_create_int32(env, item.id, &id)); + NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, objRecentMissionInfo, "id", id)); + + napi_value baseAbility = nullptr; + NAPI_CALL_RETURN_VOID(env, napi_create_object(env, &baseAbility)); + + napi_value deviceId = nullptr; + NAPI_CALL_RETURN_VOID( + env, napi_create_string_utf8(env, item.baseAbility.GetDeviceID().c_str(), NAPI_AUTO_LENGTH, &deviceId)); + NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, baseAbility, "deviceId", deviceId)); + + napi_value bundleName = nullptr; + NAPI_CALL_RETURN_VOID( + env, napi_create_string_utf8(env, item.baseAbility.GetBundleName().c_str(), NAPI_AUTO_LENGTH, &bundleName)); + NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, baseAbility, "bundleName", bundleName)); + + napi_value abilityName = nullptr; + NAPI_CALL_RETURN_VOID(env, + napi_create_string_utf8(env, item.baseAbility.GetAbilityName().c_str(), NAPI_AUTO_LENGTH, &abilityName)); + NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, baseAbility, "abilityName", abilityName)); + + NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, objRecentMissionInfo, "baseAbility", baseAbility)); + + napi_value topAbility = nullptr; + NAPI_CALL_RETURN_VOID(env, napi_create_object(env, &topAbility)); + + NAPI_CALL_RETURN_VOID( + env, napi_create_string_utf8(env, item.topAbility.GetDeviceID().c_str(), NAPI_AUTO_LENGTH, &deviceId)); + NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, topAbility, "deviceId", deviceId)); + + NAPI_CALL_RETURN_VOID( + env, napi_create_string_utf8(env, item.topAbility.GetBundleName().c_str(), NAPI_AUTO_LENGTH, &bundleName)); + NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, topAbility, "bundleName", bundleName)); + + NAPI_CALL_RETURN_VOID(env, + napi_create_string_utf8(env, item.topAbility.GetAbilityName().c_str(), NAPI_AUTO_LENGTH, &abilityName)); + NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, topAbility, "abilityName", abilityName)); + NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, objRecentMissionInfo, "topAbility", topAbility)); + + napi_value missionDescription = nullptr; + NAPI_CALL_RETURN_VOID(env, napi_create_object(env, &missionDescription)); + + napi_value label = nullptr; + NAPI_CALL_RETURN_VOID( + env, napi_create_string_utf8(env, item.missionDescription.label.c_str(), NAPI_AUTO_LENGTH, &label)); + NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, missionDescription, "label", label)); + + napi_value iconPath = nullptr; + NAPI_CALL_RETURN_VOID( + env, napi_create_string_utf8(env, item.missionDescription.iconPath.c_str(), NAPI_AUTO_LENGTH, &iconPath)); + NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, missionDescription, "iconPath", iconPath)); + + NAPI_CALL_RETURN_VOID( + env, napi_set_named_property(env, objRecentMissionInfo, "missionDescription", missionDescription)); + + NAPI_CALL_RETURN_VOID(env, napi_set_element(env, result, index, objRecentMissionInfo)); + index++; + } +} + +void GetAbilityMissionInfosForResult( + napi_env env, const std::vector &recentMissionInfos, napi_value result) +{ + int32_t index = 0; + for (const auto &item : recentMissionInfos) { + napi_value objRecentMissionInfo = nullptr; + NAPI_CALL_RETURN_VOID(env, napi_create_object(env, &objRecentMissionInfo)); + + napi_value id = nullptr; + NAPI_CALL_RETURN_VOID(env, napi_create_int32(env, item.id, &id)); + NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, objRecentMissionInfo, "missionId", id)); + + napi_value baseAbility = nullptr; + NAPI_CALL_RETURN_VOID(env, napi_create_object(env, &baseAbility)); + + napi_value deviceId = nullptr; + NAPI_CALL_RETURN_VOID( + env, napi_create_string_utf8(env, item.baseAbility.GetDeviceID().c_str(), NAPI_AUTO_LENGTH, &deviceId)); + NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, baseAbility, "deviceId", deviceId)); + + napi_value bundleName = nullptr; + NAPI_CALL_RETURN_VOID( + env, napi_create_string_utf8(env, item.baseAbility.GetBundleName().c_str(), NAPI_AUTO_LENGTH, &bundleName)); + NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, baseAbility, "bundleName", bundleName)); + + napi_value abilityName = nullptr; + NAPI_CALL_RETURN_VOID(env, + napi_create_string_utf8(env, item.baseAbility.GetAbilityName().c_str(), NAPI_AUTO_LENGTH, &abilityName)); + NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, baseAbility, "abilityName", abilityName)); + + napi_value uri = nullptr; + NAPI_CALL_RETURN_VOID(env, napi_create_string_utf8(env, "", NAPI_AUTO_LENGTH, &uri)); + NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, baseAbility, "uri", uri)); + + napi_value shortName = nullptr; + NAPI_CALL_RETURN_VOID(env, napi_create_string_utf8(env, "", NAPI_AUTO_LENGTH, &shortName)); + NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, baseAbility, "shortName", shortName)); + + NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, objRecentMissionInfo, "bottomAbility", baseAbility)); + + napi_value topAbility = nullptr; + NAPI_CALL_RETURN_VOID(env, napi_create_object(env, &topAbility)); + + NAPI_CALL_RETURN_VOID( + env, napi_create_string_utf8(env, item.topAbility.GetDeviceID().c_str(), NAPI_AUTO_LENGTH, &deviceId)); + NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, topAbility, "deviceId", deviceId)); + + NAPI_CALL_RETURN_VOID( + env, napi_create_string_utf8(env, item.topAbility.GetBundleName().c_str(), NAPI_AUTO_LENGTH, &bundleName)); + NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, topAbility, "bundleName", bundleName)); + + NAPI_CALL_RETURN_VOID(env, + napi_create_string_utf8(env, item.topAbility.GetAbilityName().c_str(), NAPI_AUTO_LENGTH, &abilityName)); + NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, topAbility, "abilityName", abilityName)); + + NAPI_CALL_RETURN_VOID(env, napi_create_string_utf8(env, "", NAPI_AUTO_LENGTH, &uri)); + NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, topAbility, "uri", uri)); + + NAPI_CALL_RETURN_VOID(env, napi_create_string_utf8(env, "", NAPI_AUTO_LENGTH, &shortName)); + NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, topAbility, "shortName", shortName)); + + NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, objRecentMissionInfo, "topAbility", topAbility)); + + napi_value nWindowMode = nullptr; + int32_t windowMode = 0; + NAPI_CALL_RETURN_VOID(env, napi_create_int32(env, windowMode, &nWindowMode)); + NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, objRecentMissionInfo, "windowMode", nWindowMode)); + + NAPI_CALL_RETURN_VOID(env, napi_set_element(env, result, index, objRecentMissionInfo)); + index++; + } +} + +void GetAllRunningProcessesForResult(napi_env env, const std::vector &info, napi_value result) +{ + int32_t index = 0; + + for (const auto &item : info) { + napi_value objAppProcessInfo = nullptr; + NAPI_CALL_RETURN_VOID(env, napi_create_object(env, &objAppProcessInfo)); + + napi_value nPid = nullptr; + NAPI_CALL_RETURN_VOID(env, napi_create_int32(env, item.pid_, &nPid)); + NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, objAppProcessInfo, "pid", nPid)); + + napi_value nProcessName = nullptr; + NAPI_CALL_RETURN_VOID( + env, napi_create_string_utf8(env, item.processName_.c_str(), NAPI_AUTO_LENGTH, &nProcessName)); + NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, objAppProcessInfo, "processName", nProcessName)); + + napi_value nPkgList = nullptr; + NAPI_CALL_RETURN_VOID(env, napi_create_array(env, &nPkgList)); + NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, objAppProcessInfo, "pkgList", nPkgList)); + + napi_value nUid = nullptr; + NAPI_CALL_RETURN_VOID(env, napi_create_int32(env, item.uid_, &nUid)); + NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, objAppProcessInfo, "uid", nUid)); + + napi_value nLastMemoryLevel = nullptr; + NAPI_CALL_RETURN_VOID(env, napi_create_int32(env, DEFAULT_LAST_MEMORY_LEVEL, &nLastMemoryLevel)); + NAPI_CALL_RETURN_VOID( + env, napi_set_named_property(env, objAppProcessInfo, "lastMemoryLevel", nLastMemoryLevel)); + + napi_value nWeight = nullptr; + NAPI_CALL_RETURN_VOID(env, napi_create_int32(env, DEFAULT_WEIGHT, &nWeight)); + NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, objAppProcessInfo, "weight", nWeight)); + + napi_value nWeightReasonCode = nullptr; + NAPI_CALL_RETURN_VOID( + env, napi_create_int32(env, static_cast(WeightReasonCode::REASON_UNKNOWN), &nWeightReasonCode)); + NAPI_CALL_RETURN_VOID( + env, napi_set_named_property(env, objAppProcessInfo, "weightReasonCode", nWeightReasonCode)); + + NAPI_CALL_RETURN_VOID(env, napi_set_element(env, result, index, objAppProcessInfo)); + index++; + } +} + +void GetActiveProcessInfosForResult(napi_env env, const std::vector &info, napi_value result) +{ + int32_t index = 0; + + for (const auto &item : info) { + napi_value objAppProcessInfo = nullptr; + NAPI_CALL_RETURN_VOID(env, napi_create_object(env, &objAppProcessInfo)); + + napi_value nPid = nullptr; + NAPI_CALL_RETURN_VOID(env, napi_create_int32(env, item.pid_, &nPid)); + NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, objAppProcessInfo, "pid", nPid)); + + napi_value nUid = nullptr; + NAPI_CALL_RETURN_VOID(env, napi_create_int32(env, item.uid_, &nUid)); + NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, objAppProcessInfo, "uid", nUid)); + + napi_value nProcessName = nullptr; + NAPI_CALL_RETURN_VOID( + env, napi_create_string_utf8(env, item.processName_.c_str(), NAPI_AUTO_LENGTH, &nProcessName)); + NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, objAppProcessInfo, "processName", nProcessName)); + + napi_value nBundleNames = nullptr; + NAPI_CALL_RETURN_VOID(env, napi_create_array(env, &nBundleNames)); + NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, objAppProcessInfo, "bundleNames", nBundleNames)); + + NAPI_CALL_RETURN_VOID(env, napi_set_element(env, result, index, objAppProcessInfo)); + index++; + } +} + +int32_t RemoveMissionsForResult(const std::vector &missionIds) +{ + int32_t error = 0; + for (auto item : missionIds) { + error = GetAbilityManagerInstance()->RemoveMission(item); + if (error != 0) { + return error; + } + } + return error; +} + +auto NAPI_QueryRecentAbilityMissionInfosAsyncExecuteCallback = [](napi_env env, void *data) { + HILOG_INFO("queryRecentAbilityMissionInfos called(CallBack Mode)..."); + AsyncMissionInfosCallbackInfo *async_callback_info = (AsyncMissionInfosCallbackInfo *)data; + HILOG_INFO("maxMissionNum = [%{public}d]", async_callback_info->maxMissionNum); + HILOG_INFO("queryType = [%{public}d]", async_callback_info->queryType); + + GetAbilityManagerInstance()->GetRecentMissions( + async_callback_info->maxMissionNum, async_callback_info->queryType, async_callback_info->recentMissionInfo); +}; + +auto NAPI_QueryRecentAbilityMissionInfosAsyncCompleteCallback = [](napi_env env, napi_status status, void *data) { + HILOG_INFO("queryRecentAbilityMissionInfos compeleted(CallBack Mode)..."); + AsyncMissionInfosCallbackInfo *async_callback_info = (AsyncMissionInfosCallbackInfo *)data; + napi_value result[NUMBER_OF_PARAMETERS_TWO] = {0}; + napi_value callback = nullptr; + napi_value undefined = nullptr; + napi_value callResult = nullptr; + + result[0] = GetCallbackErrorValue(async_callback_info->env, BUSINESS_ERROR_CODE_OK); + napi_create_array(env, &result[1]); + GetRecentMissionsForResult(env, async_callback_info->recentMissionInfo, result[1]); + napi_get_undefined(env, &undefined); + napi_get_reference_value(env, async_callback_info->callback[0], &callback); + napi_call_function(env, undefined, callback, NUMBER_OF_PARAMETERS_TWO, &result[0], &callResult); + + if (async_callback_info->callback[0] != nullptr) { + napi_delete_reference(env, async_callback_info->callback[0]); + } + napi_delete_async_work(env, async_callback_info->asyncWork); + delete async_callback_info; +}; + +auto NAPI_QueryRecentAbilityMissionInfosPromiseCompleteCallback = [](napi_env env, napi_status status, void *data) { + HILOG_INFO("queryRecentAbilityMissionInfos compeleted(Promise Mode)..."); + AsyncMissionInfosCallbackInfo *async_callback_info = (AsyncMissionInfosCallbackInfo *)data; + napi_value result = nullptr; + napi_create_array(env, &result); + GetRecentMissionsForResult(env, async_callback_info->recentMissionInfo, result); + napi_resolve_deferred(async_callback_info->env, async_callback_info->deferred, result); + napi_delete_async_work(env, async_callback_info->asyncWork); + delete async_callback_info; +}; + +napi_value NAPI_QueryRecentAbilityMissionInfosWrap( + napi_env env, napi_callback_info info, bool callBackMode, AsyncMissionInfosCallbackInfo &async_callback_info) +{ + HILOG_INFO("NAPI_QueryRecentAbilityMissionInfos called..."); + if (callBackMode) { + napi_value resourceName = nullptr; + napi_create_string_latin1(env, "NAPI_QueryRecentAbilityMissionInfosCallBack", NAPI_AUTO_LENGTH, &resourceName); + + napi_create_async_work(env, + nullptr, + resourceName, + NAPI_QueryRecentAbilityMissionInfosAsyncExecuteCallback, + NAPI_QueryRecentAbilityMissionInfosAsyncCompleteCallback, + (void *)&async_callback_info, + &async_callback_info.asyncWork); + + NAPI_CALL(env, napi_queue_async_work(env, async_callback_info.asyncWork)); + // create reutrn + napi_value ret = 0; + NAPI_CALL(env, napi_create_int32(env, 1, &ret)); + return ret; + } else { + napi_value resourceName = nullptr; + napi_create_string_latin1(env, "NAPI_QueryRecentAbilityMissionInfosPromise", NAPI_AUTO_LENGTH, &resourceName); + + napi_deferred deferred = nullptr; + napi_value promise = nullptr; + NAPI_CALL(env, napi_create_promise(env, &deferred, &promise)); + async_callback_info.deferred = deferred; + + napi_create_async_work(env, + nullptr, + resourceName, + NAPI_QueryRecentAbilityMissionInfosAsyncExecuteCallback, + NAPI_QueryRecentAbilityMissionInfosPromiseCompleteCallback, + (void *)&async_callback_info, + &async_callback_info.asyncWork); + napi_queue_async_work(env, async_callback_info.asyncWork); + return promise; + } +} + +napi_value NAPI_QueryRecentAbilityMissionInfos(napi_env env, napi_callback_info info) +{ + size_t argc = NUMBER_OF_PARAMETERS_THREE; + napi_value argv[NUMBER_OF_PARAMETERS_THREE] = {}; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL)); + HILOG_INFO("argc = [%{public}zu]", argc); + + napi_valuetype valuetype0 = napi_valuetype::napi_null; + NAPI_CALL(env, napi_typeof(env, argv[0], &valuetype0)); + NAPI_ASSERT(env, valuetype0 == napi_number, "Wrong argument type. Numbers expected."); + + napi_valuetype valuetype1 = napi_valuetype::napi_null; + NAPI_CALL(env, napi_typeof(env, argv[1], &valuetype1)); + NAPI_ASSERT(env, valuetype1 == napi_number, "Wrong argument type. Numbers expected."); + + int32_t value0 = 0; + NAPI_CALL(env, napi_get_value_int32(env, argv[0], &value0)); + int32_t value1 = 0; + NAPI_CALL(env, napi_get_value_int32(env, argv[1], &value1)); + + bool callBackMode = false; + if (argc >= NUMBER_OF_PARAMETERS_THREE) { + napi_valuetype valuetype = napi_valuetype::napi_null; + NAPI_CALL(env, napi_typeof(env, argv[NUMBER_OF_PARAMETERS_TWO], &valuetype)); + NAPI_ASSERT(env, valuetype == napi_function, "Wrong argument type. Function expected."); + callBackMode = true; + } + + AsyncMissionInfosCallbackInfo *async_callback_info = new (std::nothrow) AsyncMissionInfosCallbackInfo{ + .env = env, + .asyncWork = nullptr, + .deferred = nullptr, + }; + if (async_callback_info == nullptr) { + return nullptr; + } + + async_callback_info->maxMissionNum = value0; + async_callback_info->queryType = value1; + if (callBackMode) { + napi_create_reference(env, argv[NUMBER_OF_PARAMETERS_TWO], 1, &async_callback_info->callback[0]); + } + + napi_value ret = NAPI_QueryRecentAbilityMissionInfosWrap(env, info, callBackMode, *async_callback_info); + if (ret == nullptr) { + delete async_callback_info; + async_callback_info = nullptr; + } + + return ((callBackMode) ? (nullptr) : (ret)); +} + +auto NAPI_GetpreviousAbilityMissionInfosAsyncExecuteCallback = [](napi_env env, void *data) { + HILOG_INFO("getpreviousAbilityMissionInfos called(CallBack Mode)..."); + AsyncPreviousMissionInfosCallbackInfo *async_callback_info = (AsyncPreviousMissionInfosCallbackInfo *)data; + HILOG_INFO("maxMissionNum = [%{public}d]", async_callback_info->maxMissionNum); + + GetAbilityManagerInstance()->GetRecentMissions( + async_callback_info->maxMissionNum, 1, async_callback_info->previousMissionInfo); +}; + +auto NAPI_GetpreviousAbilityMissionInfosAsyncCompleteCallback = [](napi_env env, napi_status status, void *data) { + HILOG_INFO("getpreviousAbilityMissionInfos compeleted(CallBack Mode)..."); + AsyncPreviousMissionInfosCallbackInfo *async_callback_info = (AsyncPreviousMissionInfosCallbackInfo *)data; + napi_value result[NUMBER_OF_PARAMETERS_TWO] = {0}; + napi_value callback = nullptr; + napi_value undefined = nullptr; + napi_value callResult = nullptr; + + result[0] = GetCallbackErrorValue(async_callback_info->env, BUSINESS_ERROR_CODE_OK); + napi_create_array(env, &result[1]); + GetAbilityMissionInfosForResult(env, async_callback_info->previousMissionInfo, result[1]); + napi_get_undefined(env, &undefined); + napi_get_reference_value(env, async_callback_info->callback[0], &callback); + napi_call_function(env, undefined, callback, NUMBER_OF_PARAMETERS_TWO, &result[0], &callResult); + + if (async_callback_info->callback[0] != nullptr) { + napi_delete_reference(env, async_callback_info->callback[0]); + } + napi_delete_async_work(env, async_callback_info->asyncWork); + delete async_callback_info; +}; + +auto NAPI_GetpreviousAbilityMissionInfosPromiseCompleteCallback = [](napi_env env, napi_status status, void *data) { + HILOG_INFO("getpreviousAbilityMissionInfos compeleted(Promise Mode)..."); + AsyncPreviousMissionInfosCallbackInfo *async_callback_info = (AsyncPreviousMissionInfosCallbackInfo *)data; + napi_value result = nullptr; + napi_create_array(env, &result); + GetAbilityMissionInfosForResult(env, async_callback_info->previousMissionInfo, result); + napi_resolve_deferred(async_callback_info->env, async_callback_info->deferred, result); + napi_delete_async_work(env, async_callback_info->asyncWork); + delete async_callback_info; +}; + +napi_value NAPI_GetpreviousAbilityMissionInfosWrap(napi_env env, napi_callback_info info, bool callBackMode, + AsyncPreviousMissionInfosCallbackInfo &async_callback_info) +{ + HILOG_INFO("NAPI_GetpreviousAbilityMissionInfosWrap called..."); + if (callBackMode) { + napi_value resourceName = nullptr; + napi_create_string_latin1(env, "NAPI_GetpreviousAbilityMissionInfosWrap", NAPI_AUTO_LENGTH, &resourceName); + + napi_value resource = nullptr; + napi_create_async_work(env, + resource, + resourceName, + NAPI_GetpreviousAbilityMissionInfosAsyncExecuteCallback, + NAPI_GetpreviousAbilityMissionInfosAsyncCompleteCallback, + (void *)&async_callback_info, + &async_callback_info.asyncWork); + + NAPI_CALL(env, napi_queue_async_work(env, async_callback_info.asyncWork)); + // create reutrn + napi_value ret = 0; + NAPI_CALL(env, napi_create_int32(env, 1, &ret)); + return ret; + } else { + napi_value resourceName = nullptr; + napi_create_string_latin1( + env, "NAPI_GetpreviousAbilityMissionInfosWrapPromise", NAPI_AUTO_LENGTH, &resourceName); + + napi_deferred deferred = nullptr; + napi_value promise = nullptr; + NAPI_CALL(env, napi_create_promise(env, &deferred, &promise)); + async_callback_info.deferred = deferred; + + napi_create_async_work(env, + nullptr, + resourceName, + NAPI_GetpreviousAbilityMissionInfosAsyncExecuteCallback, + NAPI_GetpreviousAbilityMissionInfosPromiseCompleteCallback, + (void *)&async_callback_info, + &async_callback_info.asyncWork); + napi_queue_async_work(env, async_callback_info.asyncWork); + return promise; + } +} + +napi_value NAPI_GetPreviousAbilityMissionInfos(napi_env env, napi_callback_info info) +{ + size_t argc = NUMBER_OF_PARAMETERS_TWO; + napi_value argv[NUMBER_OF_PARAMETERS_TWO] = {}; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL)); + HILOG_INFO("argc = [%{public}zu]", argc); + + napi_valuetype valuetype0 = napi_valuetype::napi_null; + NAPI_CALL(env, napi_typeof(env, argv[0], &valuetype0)); + NAPI_ASSERT(env, valuetype0 == napi_number, "Wrong argument type. Numbers expected."); + + int32_t value0 = 0; + NAPI_CALL(env, napi_get_value_int32(env, argv[0], &value0)); + + bool callBackMode = false; + if (argc >= NUMBER_OF_PARAMETERS_TWO) { + napi_valuetype valuetype = napi_valuetype::napi_null; + NAPI_CALL(env, napi_typeof(env, argv[1], &valuetype)); + NAPI_ASSERT(env, valuetype == napi_function, "Wrong argument type. Function expected."); + callBackMode = true; + } + + AsyncPreviousMissionInfosCallbackInfo *async_callback_info = + new (std::nothrow) AsyncPreviousMissionInfosCallbackInfo{ + .env = env, + .asyncWork = nullptr, + .deferred = nullptr, + }; + if (async_callback_info == nullptr) { + return nullptr; + } + + async_callback_info->maxMissionNum = value0; + if (callBackMode) { + napi_create_reference(env, argv[1], 1, &async_callback_info->callback[0]); + } + + napi_value ret = NAPI_GetpreviousAbilityMissionInfosWrap(env, info, callBackMode, *async_callback_info); + if (ret == nullptr) { + delete async_callback_info; + async_callback_info = nullptr; + } + + return ((callBackMode) ? (nullptr) : (ret)); +} + +auto NAPI_QueryRunningAbilityMissionInfosAsyncExecuteCallback = [](napi_env env, void *data) { + HILOG_INFO("NAPI_QueryRunningAbilityMissionInfosWrap called(CallBack Mode)..."); + AsyncMissionInfosCallbackInfo *async_callback_info = (AsyncMissionInfosCallbackInfo *)data; + HILOG_INFO("maxMissionNum = [%{public}d]", async_callback_info->maxMissionNum); + HILOG_INFO("queryType = [%{public}d]", async_callback_info->queryType); + + GetAbilityManagerInstance()->GetRecentMissions( + async_callback_info->maxMissionNum, async_callback_info->queryType, async_callback_info->recentMissionInfo); + HILOG_INFO("size = [%{public}zu]", async_callback_info->recentMissionInfo.size()); +}; + +auto NAPI_QueryRunningAbilityMissionInfosAsyncCompleteCallback = [](napi_env env, napi_status status, void *data) { + HILOG_INFO("NAPI_QueryRunningAbilityMissionInfosWrap compeleted(CallBack Mode)..."); + AsyncMissionInfosCallbackInfo *async_callback_info = (AsyncMissionInfosCallbackInfo *)data; + napi_value result[NUMBER_OF_PARAMETERS_TWO] = {0}; + napi_value callback = nullptr; + napi_value undefined = nullptr; + napi_value callResult = nullptr; + + result[0] = GetCallbackErrorValue(async_callback_info->env, BUSINESS_ERROR_CODE_OK); + napi_create_array(env, &result[1]); + GetRecentMissionsForResult(env, async_callback_info->recentMissionInfo, result[1]); + napi_get_undefined(env, &undefined); + napi_get_reference_value(env, async_callback_info->callback[0], &callback); + napi_call_function(env, undefined, callback, NUMBER_OF_PARAMETERS_TWO, &result[0], &callResult); + + if (async_callback_info->callback[0] != nullptr) { + napi_delete_reference(env, async_callback_info->callback[0]); + } + napi_delete_async_work(env, async_callback_info->asyncWork); + delete async_callback_info; +}; + +auto NAPI_QueryRunningAbilityMissionInfosPromiseCompleteCallback = [](napi_env env, napi_status status, void *data) { + HILOG_INFO("queryRunningAbilityMissionInfos compeleted(Promise Mode)..."); + AsyncMissionInfosCallbackInfo *async_callback_info = (AsyncMissionInfosCallbackInfo *)data; + napi_value result = nullptr; + napi_create_array(env, &result); + GetRecentMissionsForResult(env, async_callback_info->recentMissionInfo, result); + napi_resolve_deferred(async_callback_info->env, async_callback_info->deferred, result); + napi_delete_async_work(env, async_callback_info->asyncWork); + delete async_callback_info; +}; + +napi_value NAPI_QueryRunningAbilityMissionInfosWrap( + napi_env env, napi_callback_info info, bool callBackMode, AsyncMissionInfosCallbackInfo &async_callback_info) +{ + HILOG_INFO("NAPI_QueryRunningAbilityMissionInfosWrap called..."); + if (callBackMode) { + napi_value resourceName = nullptr; + napi_create_string_latin1(env, "NAPI_QueryRunningAbilityMissionInfosCallBack", NAPI_AUTO_LENGTH, &resourceName); + + napi_create_async_work(env, + nullptr, + resourceName, + NAPI_QueryRunningAbilityMissionInfosAsyncExecuteCallback, + NAPI_QueryRunningAbilityMissionInfosAsyncCompleteCallback, + (void *)&async_callback_info, + &async_callback_info.asyncWork); + + NAPI_CALL(env, napi_queue_async_work(env, async_callback_info.asyncWork)); + // create reutrn + napi_value ret = 0; + NAPI_CALL(env, napi_create_int32(env, 0, &ret)); + return ret; + } else { + napi_value resourceName = nullptr; + napi_create_string_latin1(env, "NAPI_QueryRunningAbilityMissionInfosPromise", NAPI_AUTO_LENGTH, &resourceName); + + napi_deferred deferred = nullptr; + napi_value promise = nullptr; + NAPI_CALL(env, napi_create_promise(env, &deferred, &promise)); + async_callback_info.deferred = deferred; + + napi_create_async_work(env, + nullptr, + resourceName, + NAPI_QueryRunningAbilityMissionInfosAsyncExecuteCallback, + NAPI_QueryRunningAbilityMissionInfosPromiseCompleteCallback, + (void *)&async_callback_info, + &async_callback_info.asyncWork); + napi_queue_async_work(env, async_callback_info.asyncWork); + return promise; + } +} + +napi_value NAPI_QueryRunningAbilityMissionInfos(napi_env env, napi_callback_info info) +{ + size_t argc = NUMBER_OF_PARAMETERS_TWO; + napi_value argv[NUMBER_OF_PARAMETERS_TWO] = {}; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL)); + HILOG_INFO("argc = [%{public}zu]", argc); + + napi_valuetype valuetype0 = napi_valuetype::napi_null; + NAPI_CALL(env, napi_typeof(env, argv[0], &valuetype0)); + NAPI_ASSERT(env, valuetype0 == napi_number, "Wrong argument type. Numbers expected."); + + int32_t value0 = 0; + NAPI_CALL(env, napi_get_value_int32(env, argv[0], &value0)); + + bool callBackMode = false; + if (argc >= NUMBER_OF_PARAMETERS_TWO) { + napi_valuetype valuetype = napi_valuetype::napi_null; + NAPI_CALL(env, napi_typeof(env, argv[1], &valuetype)); + NAPI_ASSERT(env, valuetype == napi_function, "Wrong argument type. Function expected."); + callBackMode = true; + } + + AsyncMissionInfosCallbackInfo *async_callback_info = new (std::nothrow) AsyncMissionInfosCallbackInfo{ + .env = env, + .asyncWork = nullptr, + .deferred = nullptr, + }; + if (async_callback_info == nullptr) { + return nullptr; + } + + async_callback_info->maxMissionNum = value0; + async_callback_info->queryType = QUERY_RECENT_RUNNING_MISSION_INFO_TYPE; + + if (callBackMode) { + napi_create_reference(env, argv[1], 1, &async_callback_info->callback[0]); + } + + napi_value ret = NAPI_QueryRunningAbilityMissionInfosWrap(env, info, callBackMode, *async_callback_info); + if (ret == nullptr) { + delete async_callback_info; + async_callback_info = nullptr; + } + + return ((callBackMode) ? (nullptr) : (ret)); +} + +auto NAPI_GetActiveAbilityMissionInfosAsyncExecuteCallback = [](napi_env env, void *data) { + HILOG_INFO("NAPI_GetActiveAbilityMissionInfosWrap called(CallBack Mode)..."); + AsyncMissionInfosCallbackInfo *async_callback_info = (AsyncMissionInfosCallbackInfo *)data; + HILOG_INFO("maxMissionNum = [%{public}d]", async_callback_info->maxMissionNum); + HILOG_INFO("queryType = [%{public}d]", async_callback_info->queryType); + + GetAbilityManagerInstance()->GetRecentMissions( + async_callback_info->maxMissionNum, async_callback_info->queryType, async_callback_info->recentMissionInfo); + HILOG_INFO("size = [%{public}zu]", async_callback_info->recentMissionInfo.size()); +}; + +auto NAPI_GetActiveAbilityMissionInfosAsyncCompleteCallback = [](napi_env env, napi_status status, void *data) { + HILOG_INFO("NAPI_GetActiveAbilityMissionInfosWrap compeleted(CallBack Mode)..."); + AsyncMissionInfosCallbackInfo *async_callback_info = (AsyncMissionInfosCallbackInfo *)data; + napi_value result[NUMBER_OF_PARAMETERS_TWO] = {0}; + napi_value callback = nullptr; + napi_value undefined = nullptr; + napi_value callResult = nullptr; + + result[0] = GetCallbackErrorValue(async_callback_info->env, BUSINESS_ERROR_CODE_OK); + napi_create_array(env, &result[1]); + GetAbilityMissionInfosForResult(env, async_callback_info->recentMissionInfo, result[1]); + napi_get_undefined(env, &undefined); + napi_get_reference_value(env, async_callback_info->callback[0], &callback); + napi_call_function(env, undefined, callback, NUMBER_OF_PARAMETERS_TWO, &result[0], &callResult); + + if (async_callback_info->callback[0] != nullptr) { + napi_delete_reference(env, async_callback_info->callback[0]); + } + napi_delete_async_work(env, async_callback_info->asyncWork); + delete async_callback_info; +}; + +auto NAPI_GetActiveAbilityMissionInfosPromiseCompleteCallback = [](napi_env env, napi_status status, void *data) { + HILOG_INFO("getActiveAbilityMissionInfos compeleted(Promise Mode)..."); + AsyncMissionInfosCallbackInfo *async_callback_info = (AsyncMissionInfosCallbackInfo *)data; + napi_value result = nullptr; + napi_create_array(env, &result); + GetAbilityMissionInfosForResult(env, async_callback_info->recentMissionInfo, result); + napi_resolve_deferred(async_callback_info->env, async_callback_info->deferred, result); + napi_delete_async_work(env, async_callback_info->asyncWork); + delete async_callback_info; +}; + +napi_value NAPI_GetActiveAbilityMissionInfosWrap( + napi_env env, napi_callback_info info, bool callBackMode, AsyncMissionInfosCallbackInfo &async_callback_info) +{ + HILOG_INFO("NAPI_GetActiveAbilityMissionInfosWrap called..."); + if (callBackMode) { + napi_value resourceName = nullptr; + napi_create_string_latin1(env, "NAPI_GetActiveAbilityMissionInfosCallBack", NAPI_AUTO_LENGTH, &resourceName); + + napi_create_async_work(env, + nullptr, + resourceName, + NAPI_GetActiveAbilityMissionInfosAsyncExecuteCallback, + NAPI_GetActiveAbilityMissionInfosAsyncCompleteCallback, + (void *)&async_callback_info, + &async_callback_info.asyncWork); + + NAPI_CALL(env, napi_queue_async_work(env, async_callback_info.asyncWork)); + // create reutrn + napi_value ret = 0; + NAPI_CALL(env, napi_create_int32(env, 0, &ret)); + return ret; + } else { + napi_value resourceName = nullptr; + napi_create_string_latin1(env, "NAPI_GetActiveAbilityMissionInfosPromise", NAPI_AUTO_LENGTH, &resourceName); + + napi_deferred deferred = nullptr; + napi_value promise = nullptr; + NAPI_CALL(env, napi_create_promise(env, &deferred, &promise)); + async_callback_info.deferred = deferred; + + napi_create_async_work(env, + nullptr, + resourceName, + NAPI_GetActiveAbilityMissionInfosAsyncExecuteCallback, + NAPI_GetActiveAbilityMissionInfosPromiseCompleteCallback, + (void *)&async_callback_info, + &async_callback_info.asyncWork); + napi_queue_async_work(env, async_callback_info.asyncWork); + return promise; + } +} + +napi_value NAPI_GetActiveAbilityMissionInfos(napi_env env, napi_callback_info info) +{ + size_t argc = NUMBER_OF_PARAMETERS_TWO; + napi_value argv[NUMBER_OF_PARAMETERS_TWO] = {}; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL)); + HILOG_INFO("argc = [%{public}zu]", argc); + + napi_valuetype valuetype0 = napi_valuetype::napi_null; + NAPI_CALL(env, napi_typeof(env, argv[0], &valuetype0)); + NAPI_ASSERT(env, valuetype0 == napi_number, "Wrong argument type. Numbers expected."); + + int32_t value0 = 0; + NAPI_CALL(env, napi_get_value_int32(env, argv[0], &value0)); + + bool callBackMode = false; + if (argc >= NUMBER_OF_PARAMETERS_TWO) { + napi_valuetype valuetype = napi_valuetype::napi_null; + NAPI_CALL(env, napi_typeof(env, argv[1], &valuetype)); + NAPI_ASSERT(env, valuetype == napi_function, "Wrong argument type. Function expected."); + callBackMode = true; + } + + AsyncMissionInfosCallbackInfo *async_callback_info = new (std::nothrow) AsyncMissionInfosCallbackInfo{ + .env = env, + .asyncWork = nullptr, + .deferred = nullptr, + }; + if (async_callback_info == nullptr) { + return nullptr; + } + + async_callback_info->maxMissionNum = value0; + async_callback_info->queryType = QUERY_RECENT_RUNNING_MISSION_INFO_TYPE; + + if (callBackMode) { + napi_create_reference(env, argv[1], 1, &async_callback_info->callback[0]); + } + + napi_value ret = NAPI_GetActiveAbilityMissionInfosWrap(env, info, callBackMode, *async_callback_info); + if (ret == nullptr) { + delete async_callback_info; + async_callback_info = nullptr; + } + + return ((callBackMode) ? (nullptr) : (ret)); +} + +auto NAPI_GetAllRunningProcessesAsyncExecuteCallback = [](napi_env env, void *data) { + HILOG_INFO("getAllRunningProcesses called(CallBack Mode)..."); + AsyncCallbackInfo *async_callback_info = (AsyncCallbackInfo *)data; + GetAppManagerInstance()->GetAllRunningProcesses(async_callback_info->info); +}; + +auto NAPI_GetAllRunningProcessesAsyncCompleteCallback = [](napi_env env, napi_status status, void *data) { + HILOG_INFO("getAllRunningProcesses compeleted(CallBack Mode)..."); + AsyncCallbackInfo *async_callback_info = (AsyncCallbackInfo *)data; + napi_value result[NUMBER_OF_PARAMETERS_TWO] = {0}; + napi_value callback = nullptr; + napi_value undefined = nullptr; + napi_value callResult = nullptr; + + result[0] = GetCallbackErrorValue(async_callback_info->env, BUSINESS_ERROR_CODE_OK); + napi_create_array(env, &result[1]); + GetAllRunningProcessesForResult(env, async_callback_info->info, result[1]); + napi_get_undefined(env, &undefined); + napi_get_reference_value(env, async_callback_info->callback[0], &callback); + napi_call_function(env, undefined, callback, NUMBER_OF_PARAMETERS_TWO, &result[0], &callResult); + + if (async_callback_info->callback[0] != nullptr) { + napi_delete_reference(env, async_callback_info->callback[0]); + } + napi_delete_async_work(env, async_callback_info->asyncWork); + delete async_callback_info; +}; + +auto NAPI_GetAllRunningProcessesPromiseCompleteCallback = [](napi_env env, napi_status status, void *data) { + HILOG_INFO("getAllRunningProcesses compeleted(Promise Mode)..."); + AsyncCallbackInfo *async_callback_info = (AsyncCallbackInfo *)data; + napi_value result = nullptr; + napi_create_array(env, &result); + GetAllRunningProcessesForResult(env, async_callback_info->info, result); + napi_resolve_deferred(async_callback_info->env, async_callback_info->deferred, result); + napi_delete_async_work(env, async_callback_info->asyncWork); + delete async_callback_info; +}; + +napi_value NAPI_GetAllRunningProcessesWrap( + napi_env env, napi_callback_info info, bool callBackMode, AsyncCallbackInfo &async_callback_info) +{ + HILOG_INFO("NAPI_GetAllRunningProcessesWrap called..."); + if (callBackMode) { + napi_value resourceName = nullptr; + napi_create_string_latin1(env, "NAPI_GetAllRunningProcessesCallBack", NAPI_AUTO_LENGTH, &resourceName); + + napi_create_async_work(env, + nullptr, + resourceName, + NAPI_GetAllRunningProcessesAsyncExecuteCallback, + NAPI_GetAllRunningProcessesAsyncCompleteCallback, + (void *)&async_callback_info, + &async_callback_info.asyncWork); + + NAPI_CALL(env, napi_queue_async_work(env, async_callback_info.asyncWork)); + // create reutrn + napi_value ret = 0; + NAPI_CALL(env, napi_create_int32(env, 0, &ret)); + return ret; + } else { + napi_value resourceName = nullptr; + napi_create_string_latin1(env, "NAPI_GetAllRunningProcessesPromise", NAPI_AUTO_LENGTH, &resourceName); + + napi_deferred deferred = nullptr; + napi_value promise = nullptr; + NAPI_CALL(env, napi_create_promise(env, &deferred, &promise)); + async_callback_info.deferred = deferred; + + napi_create_async_work(env, + nullptr, + resourceName, + NAPI_GetAllRunningProcessesAsyncExecuteCallback, + NAPI_GetAllRunningProcessesPromiseCompleteCallback, + (void *)&async_callback_info, + &async_callback_info.asyncWork); + napi_queue_async_work(env, async_callback_info.asyncWork); + return promise; + } +} + +napi_value NAPI_GetAllRunningProcesses(napi_env env, napi_callback_info info) +{ + size_t argc = 1; + napi_value argv[1] = {}; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL)); + HILOG_INFO("argc = [%{public}zu]", argc); + + bool callBackMode = false; + if (argc >= 1) { + napi_valuetype valuetype = napi_valuetype::napi_null; + NAPI_CALL(env, napi_typeof(env, argv[0], &valuetype)); + NAPI_ASSERT(env, valuetype == napi_function, "Wrong argument type. Function expected."); + callBackMode = true; + } + + AsyncCallbackInfo *async_callback_info = new (std::nothrow) AsyncCallbackInfo{ + .env = env, + .asyncWork = nullptr, + .deferred = nullptr, + }; + if (async_callback_info == nullptr) { + return nullptr; + } + + if (callBackMode) { + napi_create_reference(env, argv[0], 1, &async_callback_info->callback[0]); + } + + napi_value ret = NAPI_GetAllRunningProcessesWrap(env, info, callBackMode, *async_callback_info); + if (ret == nullptr) { + delete async_callback_info; + async_callback_info = nullptr; + } + + return ((callBackMode) ? (nullptr) : (ret)); +} + +auto NAPI_GetActiveProcessInfosAsyncExecuteCallback = [](napi_env env, void *data) { + HILOG_INFO("getActiveProcessInfos called(CallBack Mode)..."); + AsyncCallbackInfo *async_callback_info = (AsyncCallbackInfo *)data; + GetAppManagerInstance()->GetAllRunningProcesses(async_callback_info->info); +}; + +auto NAPI_GetActiveProcessInfosAsyncCompleteCallback = [](napi_env env, napi_status status, void *data) { + HILOG_INFO("getActiveProcessInfos compeleted(CallBack Mode)..."); + AsyncCallbackInfo *async_callback_info = (AsyncCallbackInfo *)data; + napi_value result[NUMBER_OF_PARAMETERS_TWO] = {0}; + napi_value callback = nullptr; + napi_value undefined = nullptr; + napi_value callResult = nullptr; + + result[0] = GetCallbackErrorValue(async_callback_info->env, BUSINESS_ERROR_CODE_OK); + napi_create_array(env, &result[1]); + GetActiveProcessInfosForResult(env, async_callback_info->info, result[1]); + napi_get_undefined(env, &undefined); + napi_get_reference_value(env, async_callback_info->callback[0], &callback); + napi_call_function(env, undefined, callback, NUMBER_OF_PARAMETERS_TWO, &result[0], &callResult); + + if (async_callback_info->callback[0] != nullptr) { + napi_delete_reference(env, async_callback_info->callback[0]); + } + napi_delete_async_work(env, async_callback_info->asyncWork); + delete async_callback_info; +}; + +auto NAPI_GetActiveProcessInfosPromiseCompleteCallback = [](napi_env env, napi_status status, void *data) { + HILOG_INFO("getActiveProcessInfos compeleted(Promise Mode)..."); + AsyncCallbackInfo *async_callback_info = (AsyncCallbackInfo *)data; + napi_value result = nullptr; + napi_create_array(env, &result); + GetActiveProcessInfosForResult(env, async_callback_info->info, result); + napi_resolve_deferred(async_callback_info->env, async_callback_info->deferred, result); + napi_delete_async_work(env, async_callback_info->asyncWork); + delete async_callback_info; +}; + +napi_value NAPI_GetActiveProcessInfosWrap( + napi_env env, napi_callback_info info, bool callBackMode, AsyncCallbackInfo &async_callback_info) +{ + HILOG_INFO("NAPI_GetActiveProcessInfosWrap called..."); + if (callBackMode) { + napi_value resourceName = nullptr; + napi_create_string_latin1(env, "NAPI_GetActiveProcessInfosCallBack", NAPI_AUTO_LENGTH, &resourceName); + + napi_create_async_work(env, + nullptr, + resourceName, + NAPI_GetActiveProcessInfosAsyncExecuteCallback, + NAPI_GetActiveProcessInfosAsyncCompleteCallback, + (void *)&async_callback_info, + &async_callback_info.asyncWork); + + NAPI_CALL(env, napi_queue_async_work(env, async_callback_info.asyncWork)); + // create reutrn + napi_value ret = 0; + NAPI_CALL(env, napi_create_int32(env, 0, &ret)); + return ret; + } else { + napi_value resourceName = nullptr; + napi_create_string_latin1(env, "NAPI_GetActiveProcessInfosPromise", NAPI_AUTO_LENGTH, &resourceName); + + napi_deferred deferred = nullptr; + napi_value promise = nullptr; + NAPI_CALL(env, napi_create_promise(env, &deferred, &promise)); + async_callback_info.deferred = deferred; + + napi_create_async_work(env, + nullptr, + resourceName, + NAPI_GetActiveProcessInfosAsyncExecuteCallback, + NAPI_GetActiveProcessInfosPromiseCompleteCallback, + (void *)&async_callback_info, + &async_callback_info.asyncWork); + napi_queue_async_work(env, async_callback_info.asyncWork); + return promise; + } +} + +napi_value NAPI_GetActiveProcessInfos(napi_env env, napi_callback_info info) +{ + size_t argc = 1; + napi_value argv[1] = {}; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL)); + HILOG_INFO("argc = [%{public}zu]", argc); + + bool callBackMode = false; + if (argc >= 1) { + napi_valuetype valuetype = napi_valuetype::napi_null; + NAPI_CALL(env, napi_typeof(env, argv[0], &valuetype)); + NAPI_ASSERT(env, valuetype == napi_function, "Wrong argument type. Function expected."); + callBackMode = true; + } + + AsyncCallbackInfo *async_callback_info = new (std::nothrow) AsyncCallbackInfo{ + .env = env, + .asyncWork = nullptr, + .deferred = nullptr, + }; + if (async_callback_info == nullptr) { + return nullptr; + } + + if (callBackMode) { + napi_create_reference(env, argv[0], 1, &async_callback_info->callback[0]); + } + + napi_value ret = NAPI_GetActiveProcessInfosWrap(env, info, callBackMode, *async_callback_info); + if (ret == nullptr) { + delete async_callback_info; + async_callback_info = nullptr; + } + + return ((callBackMode) ? (nullptr) : (ret)); +} + +auto NAPI_RemoveMissionAsyncExecuteCallback = [](napi_env env, void *data) { + HILOG_INFO("removeMission called(CallBack Mode)..."); + AsyncRemoveMissionCallbackInfo *async_callback_info = (AsyncRemoveMissionCallbackInfo *)data; + async_callback_info->result = GetAbilityManagerInstance()->RemoveMission(async_callback_info->index); +}; + +auto NAPI_RemoveMissionAsyncCompleteCallback = [](napi_env env, napi_status status, void *data) { + HILOG_INFO("removeMission compeleted(CallBack Mode)..."); + AsyncRemoveMissionCallbackInfo *async_callback_info = (AsyncRemoveMissionCallbackInfo *)data; + napi_value result[NUMBER_OF_PARAMETERS_TWO] = {0}; + napi_value callback = nullptr; + napi_value undefined = nullptr; + napi_value callResult = nullptr; + + result[0] = GetCallbackErrorValue(async_callback_info->env, BUSINESS_ERROR_CODE_OK); + napi_create_int32(async_callback_info->env, async_callback_info->result, &result[1]); + napi_get_undefined(env, &undefined); + + napi_get_reference_value(env, async_callback_info->callback[0], &callback); + napi_call_function(env, undefined, callback, NUMBER_OF_PARAMETERS_TWO, &result[0], &callResult); + + if (async_callback_info->callback[0] != nullptr) { + napi_delete_reference(env, async_callback_info->callback[0]); + } + + napi_delete_async_work(env, async_callback_info->asyncWork); + delete async_callback_info; +}; + +auto NAPI_RemoveMissionPromiseCompleteCallback = [](napi_env env, napi_status status, void *data) { + HILOG_INFO("removeMission compeleted(Promise Mode)..."); + AsyncRemoveMissionCallbackInfo *async_callback_info = (AsyncRemoveMissionCallbackInfo *)data; + napi_value result = nullptr; + napi_create_int32(async_callback_info->env, async_callback_info->result, &result); + napi_resolve_deferred(async_callback_info->env, async_callback_info->deferred, result); + napi_delete_async_work(env, async_callback_info->asyncWork); + delete async_callback_info; +}; + +napi_value NAPI_RemoveMissionWrap( + napi_env env, napi_callback_info info, bool callBackMode, AsyncRemoveMissionCallbackInfo &async_callback_info) +{ + HILOG_INFO("NAPI_RemoveMission called..."); + if (callBackMode) { + napi_value resourceName = nullptr; + napi_create_string_latin1(env, "NAPI_RemoveMissionCallBack", NAPI_AUTO_LENGTH, &resourceName); + + napi_create_async_work(env, + nullptr, + resourceName, + NAPI_RemoveMissionAsyncExecuteCallback, + NAPI_RemoveMissionAsyncCompleteCallback, + (void *)&async_callback_info, + &async_callback_info.asyncWork); + + NAPI_CALL(env, napi_queue_async_work(env, async_callback_info.asyncWork)); + // create reutrn + napi_value ret = 0; + NAPI_CALL(env, napi_create_int32(env, 0, &ret)); + return ret; + } else { + napi_value resourceName = nullptr; + napi_create_string_latin1(env, "NAPI_RemoveMissionPromise", NAPI_AUTO_LENGTH, &resourceName); + + napi_deferred deferred = nullptr; + napi_value promise = nullptr; + NAPI_CALL(env, napi_create_promise(env, &deferred, &promise)); + async_callback_info.deferred = deferred; + + napi_create_async_work(env, + nullptr, + resourceName, + NAPI_RemoveMissionAsyncExecuteCallback, + NAPI_RemoveMissionPromiseCompleteCallback, + (void *)&async_callback_info, + &async_callback_info.asyncWork); + napi_queue_async_work(env, async_callback_info.asyncWork); + return promise; + } +} + +napi_value NAPI_RemoveMission(napi_env env, napi_callback_info info) +{ + size_t argc = NUMBER_OF_PARAMETERS_TWO; + napi_value argv[NUMBER_OF_PARAMETERS_TWO] = {}; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL)); + HILOG_INFO("argc = [%{public}zu]", argc); + + napi_valuetype valuetype0 = napi_valuetype::napi_null; + NAPI_CALL(env, napi_typeof(env, argv[0], &valuetype0)); + NAPI_ASSERT(env, valuetype0 == napi_number, "Wrong argument type. Numbers expected."); + + int32_t value0 = 0; + NAPI_CALL(env, napi_get_value_int32(env, argv[0], &value0)); + + bool callBackMode = false; + if (argc >= NUMBER_OF_PARAMETERS_TWO) { + napi_valuetype valuetype = napi_valuetype::napi_null; + NAPI_CALL(env, napi_typeof(env, argv[1], &valuetype)); + NAPI_ASSERT(env, valuetype == napi_function, "Wrong argument type. Function expected."); + callBackMode = true; + } + + AsyncRemoveMissionCallbackInfo *async_callback_info = new (std::nothrow) AsyncRemoveMissionCallbackInfo{ + .env = env, + .asyncWork = nullptr, + .deferred = nullptr, + }; + if (async_callback_info == nullptr) { + return nullptr; + } + + async_callback_info->index = value0; + if (callBackMode) { + napi_create_reference(env, argv[1], 1, &async_callback_info->callback[0]); + } + + napi_value ret = NAPI_RemoveMissionWrap(env, info, callBackMode, *async_callback_info); + if (ret == nullptr) { + delete async_callback_info; + async_callback_info = nullptr; + } + + return ((callBackMode) ? (nullptr) : (ret)); +} + +auto NAPI_RemoveMissionsAsyncExecuteCallback = [](napi_env env, void *data) { + HILOG_INFO("removeMissions called(CallBack Mode)..."); + AsyncRemoveMissionsCallbackInfo *async_callback_info = (AsyncRemoveMissionsCallbackInfo *)data; + async_callback_info->result = RemoveMissionsForResult(async_callback_info->missionIds); +}; + +auto NAPI_RemoveMissionsAsyncCompleteCallback = [](napi_env env, napi_status status, void *data) { + HILOG_INFO("removeMissions compeleted(CallBack Mode)..."); + AsyncRemoveMissionsCallbackInfo *async_callback_info = (AsyncRemoveMissionsCallbackInfo *)data; + napi_value result[NUMBER_OF_PARAMETERS_TWO] = {0}; + napi_value callback = nullptr; + napi_value undefined = nullptr; + napi_value callResult = nullptr; + + result[0] = GetCallbackErrorValue(async_callback_info->env, BUSINESS_ERROR_CODE_OK); + napi_create_int32(async_callback_info->env, async_callback_info->result, &result[1]); + napi_get_undefined(env, &undefined); + + napi_get_reference_value(env, async_callback_info->callback[0], &callback); + napi_call_function(env, undefined, callback, NUMBER_OF_PARAMETERS_TWO, &result[0], &callResult); + + if (async_callback_info->callback[0] != nullptr) { + napi_delete_reference(env, async_callback_info->callback[0]); + } + + napi_delete_async_work(env, async_callback_info->asyncWork); + delete async_callback_info; +}; + +auto NAPI_RemoveMissionsPromiseCompleteCallback = [](napi_env env, napi_status status, void *data) { + HILOG_INFO("removeMissions compeleted(Promise Mode)..."); + AsyncRemoveMissionsCallbackInfo *async_callback_info = (AsyncRemoveMissionsCallbackInfo *)data; + napi_value result = nullptr; + napi_create_int32(async_callback_info->env, async_callback_info->result, &result); + napi_resolve_deferred(async_callback_info->env, async_callback_info->deferred, result); + napi_delete_async_work(env, async_callback_info->asyncWork); + delete async_callback_info; +}; + +napi_value NAPI_RemoveMissionsWrap( + napi_env env, napi_callback_info info, bool callBackMode, AsyncRemoveMissionsCallbackInfo &async_callback_info) +{ + HILOG_INFO("NAPI_RemoveMissions called..."); + if (callBackMode) { + napi_value resourceName = nullptr; + napi_create_string_latin1(env, "NAPI_RemoveMissionsCallBack", NAPI_AUTO_LENGTH, &resourceName); + + napi_create_async_work(env, + nullptr, + resourceName, + NAPI_RemoveMissionsAsyncExecuteCallback, + NAPI_RemoveMissionsAsyncCompleteCallback, + (void *)&async_callback_info, + &async_callback_info.asyncWork); + + NAPI_CALL(env, napi_queue_async_work(env, async_callback_info.asyncWork)); + // create reutrn + napi_value ret = 0; + NAPI_CALL(env, napi_create_int32(env, 0, &ret)); + return ret; + } else { + napi_value resourceName = nullptr; + napi_create_string_latin1(env, "NAPI_RemoveMissionsPromise", NAPI_AUTO_LENGTH, &resourceName); + + napi_deferred deferred = nullptr; + napi_value promise = nullptr; + NAPI_CALL(env, napi_create_promise(env, &deferred, &promise)); + async_callback_info.deferred = deferred; + + napi_create_async_work(env, + nullptr, + resourceName, + NAPI_RemoveMissionsAsyncExecuteCallback, + NAPI_RemoveMissionsPromiseCompleteCallback, + (void *)&async_callback_info, + &async_callback_info.asyncWork); + napi_queue_async_work(env, async_callback_info.asyncWork); + return promise; + } +} + +napi_value NAPI_RemoveMissions(napi_env env, napi_callback_info info) +{ + size_t argc = NUMBER_OF_PARAMETERS_TWO; + napi_value argv[NUMBER_OF_PARAMETERS_TWO] = {}; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL)); + HILOG_INFO("argc = [%{public}zu]", argc); + + uint32_t arrayLength = 0; + NAPI_CALL(env, napi_get_array_length(env, argv[0], &arrayLength)); + HILOG_INFO("property is array, length=%{public}d", arrayLength); + NAPI_ASSERT(env, arrayLength > 0, "The array is empty."); + + std::vector missionIds = {}; + for (size_t i = 0; i < arrayLength; i++) { + napi_value napiMissionIds = nullptr; + napi_get_element(env, argv[0], i, &napiMissionIds); + + napi_valuetype valuetype0 = napi_valuetype::napi_null; + NAPI_CALL(env, napi_typeof(env, napiMissionIds, &valuetype0)); + NAPI_ASSERT(env, valuetype0 == napi_number, "Wrong argument type. Numbers expected."); + int32_t value0 = 0; + NAPI_CALL(env, napi_get_value_int32(env, napiMissionIds, &value0)); + missionIds.push_back(value0); + } + + bool callBackMode = false; + if (argc >= NUMBER_OF_PARAMETERS_TWO) { + napi_valuetype valuetype = napi_valuetype::napi_null; + NAPI_CALL(env, napi_typeof(env, argv[1], &valuetype)); + NAPI_ASSERT(env, valuetype == napi_function, "Wrong argument type. Function expected."); + callBackMode = true; + } + + AsyncRemoveMissionsCallbackInfo *async_callback_info = new (std::nothrow) AsyncRemoveMissionsCallbackInfo{ + .env = env, + .asyncWork = nullptr, + .deferred = nullptr, + }; + if (async_callback_info == nullptr) { + return nullptr; + } + + async_callback_info->missionIds = missionIds; + if (callBackMode) { + napi_create_reference(env, argv[1], 1, &async_callback_info->callback[0]); + } + + napi_value ret = NAPI_RemoveMissionsWrap(env, info, callBackMode, *async_callback_info); + if (ret == nullptr) { + delete async_callback_info; + async_callback_info = nullptr; + } + + return ((callBackMode) ? (nullptr) : (ret)); +} + +auto NAPI_ClearMissionsAsyncExecuteCallback = [](napi_env env, void *data) { + HILOG_INFO("clearMissions called(CallBack Mode)..."); + AsyncClearMissionsCallbackInfo *async_callback_info = (AsyncClearMissionsCallbackInfo *)data; + async_callback_info->result = GetAbilityManagerInstance()->RemoveStack(DEFAULT_STACK_ID); +}; + +auto NAPI_ClearMissionsAsyncCompleteCallback = [](napi_env env, napi_status status, void *data) { + HILOG_INFO("clearMissions compeleted(CallBack Mode)..."); + AsyncClearMissionsCallbackInfo *async_callback_info = (AsyncClearMissionsCallbackInfo *)data; + napi_value result[NUMBER_OF_PARAMETERS_TWO] = {0}; + napi_value callback = nullptr; + napi_value undefined = nullptr; + napi_value callResult = nullptr; + + result[0] = GetCallbackErrorValue(async_callback_info->env, BUSINESS_ERROR_CODE_OK); + napi_create_int32(async_callback_info->env, async_callback_info->result, &result[1]); + napi_get_undefined(env, &undefined); + + napi_get_reference_value(env, async_callback_info->callback[0], &callback); + napi_call_function(env, undefined, callback, NUMBER_OF_PARAMETERS_TWO, &result[0], &callResult); + + if (async_callback_info->callback[0] != nullptr) { + napi_delete_reference(env, async_callback_info->callback[0]); + } + + napi_delete_async_work(env, async_callback_info->asyncWork); + delete async_callback_info; +}; + +auto NAPI_ClearMissionsPromiseCompleteCallback = [](napi_env env, napi_status status, void *data) { + HILOG_INFO("clearMissions compeleted(Promise Mode)..."); + AsyncClearMissionsCallbackInfo *async_callback_info = (AsyncClearMissionsCallbackInfo *)data; + napi_value result = nullptr; + napi_create_int32(async_callback_info->env, async_callback_info->result, &result); + napi_resolve_deferred(async_callback_info->env, async_callback_info->deferred, result); + napi_delete_async_work(env, async_callback_info->asyncWork); + delete async_callback_info; +}; + +napi_value NAPI_ClearMissionsWrap( + napi_env env, napi_callback_info info, bool callBackMode, AsyncClearMissionsCallbackInfo &async_callback_info) +{ + HILOG_INFO("NAPI_ClearMissions called..."); + if (callBackMode) { + napi_value resourceName = nullptr; + napi_create_string_latin1(env, "NAPI_ClearMissionsCallBack", NAPI_AUTO_LENGTH, &resourceName); + + napi_create_async_work(env, + nullptr, + resourceName, + NAPI_ClearMissionsAsyncExecuteCallback, + NAPI_ClearMissionsAsyncCompleteCallback, + (void *)&async_callback_info, + &async_callback_info.asyncWork); + + NAPI_CALL(env, napi_queue_async_work(env, async_callback_info.asyncWork)); + // create reutrn + napi_value ret = 0; + NAPI_CALL(env, napi_create_int32(env, 0, &ret)); + return ret; + } else { + napi_value resourceName = nullptr; + napi_create_string_latin1(env, "NAPI_ClearMissionsPromise", NAPI_AUTO_LENGTH, &resourceName); + + napi_deferred deferred; + napi_value promise; + NAPI_CALL(env, napi_create_promise(env, &deferred, &promise)); + async_callback_info.deferred = deferred; + + napi_create_async_work(env, + nullptr, + resourceName, + NAPI_ClearMissionsAsyncExecuteCallback, + NAPI_ClearMissionsPromiseCompleteCallback, + (void *)&async_callback_info, + &async_callback_info.asyncWork); + napi_queue_async_work(env, async_callback_info.asyncWork); + return promise; + } +} + +napi_value NAPI_ClearMissions(napi_env env, napi_callback_info info) +{ + size_t argc = 1; + napi_value argv[1] = {}; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL)); + HILOG_INFO("argc = [%{public}zu]", argc); + + bool callBackMode = false; + if (argc >= 1) { + napi_valuetype valuetype = napi_valuetype::napi_null; + NAPI_CALL(env, napi_typeof(env, argv[0], &valuetype)); + NAPI_ASSERT(env, valuetype == napi_function, "Wrong argument type. Function expected."); + callBackMode = true; + } + + AsyncClearMissionsCallbackInfo *async_callback_info = new (std::nothrow) AsyncClearMissionsCallbackInfo{ + .env = env, + .asyncWork = nullptr, + .deferred = nullptr, + }; + if (async_callback_info == nullptr) { + return nullptr; + } + + if (callBackMode) { + napi_create_reference(env, argv[0], 1, &async_callback_info->callback[0]); + } + + napi_value ret = NAPI_ClearMissionsWrap(env, info, callBackMode, *async_callback_info); + if (ret == nullptr) { + delete async_callback_info; + async_callback_info = nullptr; + } + + return ((callBackMode) ? (nullptr) : (ret)); +} + +auto NAPI_MoveMissionToTopAsyncExecuteCallback = [](napi_env env, void *data) { + HILOG_INFO("moveMissionToTop called(CallBack Mode)..."); + AsyncMoveMissionToTopCallbackInfo *async_callback_info = (AsyncMoveMissionToTopCallbackInfo *)data; + async_callback_info->result = GetAbilityManagerInstance()->MoveMissionToTop(async_callback_info->index); +}; + +auto NAPI_MoveMissionToTopAsyncCompleteCallback = [](napi_env env, napi_status status, void *data) { + HILOG_INFO("moveMissionToTop compeleted(CallBack Mode)..."); + AsyncMoveMissionToTopCallbackInfo *async_callback_info = (AsyncMoveMissionToTopCallbackInfo *)data; + napi_value result[NUMBER_OF_PARAMETERS_TWO] = {0}; + napi_value callback = nullptr; + napi_value undefined = nullptr; + napi_value callResult = nullptr; + + result[0] = GetCallbackErrorValue(async_callback_info->env, BUSINESS_ERROR_CODE_OK); + napi_create_int32(async_callback_info->env, async_callback_info->result, &result[1]); + napi_get_undefined(env, &undefined); + + napi_get_reference_value(env, async_callback_info->callback[0], &callback); + napi_call_function(env, undefined, callback, NUMBER_OF_PARAMETERS_TWO, &result[0], &callResult); + + if (async_callback_info->callback[0] != nullptr) { + napi_delete_reference(env, async_callback_info->callback[0]); + } + + napi_delete_async_work(env, async_callback_info->asyncWork); + delete async_callback_info; +}; + +auto NAPI_MoveMissionToTopPromiseCompleteCallback = [](napi_env env, napi_status status, void *data) { + HILOG_INFO("moveMissionToTop compeleted(Promise Mode)..."); + AsyncMoveMissionToTopCallbackInfo *async_callback_info = (AsyncMoveMissionToTopCallbackInfo *)data; + napi_value result = nullptr; + napi_create_int32(async_callback_info->env, async_callback_info->result, &result); + napi_resolve_deferred(async_callback_info->env, async_callback_info->deferred, result); + napi_delete_async_work(env, async_callback_info->asyncWork); + delete async_callback_info; +}; + +napi_value NAPI_MoveMissionToTopWrap( + napi_env env, napi_callback_info info, bool callBackMode, AsyncMoveMissionToTopCallbackInfo &async_callback_info) +{ + HILOG_INFO("NAPI_MoveMissionToTop called..."); + if (callBackMode) { + napi_value resourceName = nullptr; + napi_create_string_latin1(env, "NAPI_MoveMissionToTopCallBack", NAPI_AUTO_LENGTH, &resourceName); + + napi_create_async_work(env, + nullptr, + resourceName, + NAPI_MoveMissionToTopAsyncExecuteCallback, + NAPI_MoveMissionToTopAsyncCompleteCallback, + (void *)&async_callback_info, + &async_callback_info.asyncWork); + + NAPI_CALL(env, napi_queue_async_work(env, async_callback_info.asyncWork)); + // create reutrn + napi_value ret = 0; + NAPI_CALL(env, napi_create_int32(env, 0, &ret)); + return ret; + } else { + napi_value resourceName = nullptr; + napi_create_string_latin1(env, "NAPI_MoveMissionToTopPromise", NAPI_AUTO_LENGTH, &resourceName); + + napi_deferred deferred = nullptr; + napi_value promise = nullptr; + NAPI_CALL(env, napi_create_promise(env, &deferred, &promise)); + async_callback_info.deferred = deferred; + + napi_create_async_work(env, + nullptr, + resourceName, + NAPI_MoveMissionToTopAsyncExecuteCallback, + NAPI_MoveMissionToTopPromiseCompleteCallback, + (void *)&async_callback_info, + &async_callback_info.asyncWork); + napi_queue_async_work(env, async_callback_info.asyncWork); + return promise; + } +} + +napi_value NAPI_MoveMissionToTop(napi_env env, napi_callback_info info) +{ + size_t argc = NUMBER_OF_PARAMETERS_TWO; + napi_value argv[NUMBER_OF_PARAMETERS_TWO] = {}; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL)); + HILOG_INFO("argc = [%{public}zu]", argc); + + napi_valuetype valuetype0 = napi_valuetype::napi_null; + NAPI_CALL(env, napi_typeof(env, argv[0], &valuetype0)); + NAPI_ASSERT(env, valuetype0 == napi_number, "Wrong argument type. Numbers expected."); + int32_t value0 = 0; + NAPI_CALL(env, napi_get_value_int32(env, argv[0], &value0)); + + bool callBackMode = false; + if (argc >= NUMBER_OF_PARAMETERS_TWO) { + napi_valuetype valuetype = napi_valuetype::napi_null; + NAPI_CALL(env, napi_typeof(env, argv[1], &valuetype)); + NAPI_ASSERT(env, valuetype == napi_function, "Wrong argument type. Function expected."); + callBackMode = true; + } + + AsyncMoveMissionToTopCallbackInfo *async_callback_info = new (std::nothrow) AsyncMoveMissionToTopCallbackInfo{ + .env = env, + .asyncWork = nullptr, + .deferred = nullptr, + }; + if (async_callback_info == nullptr) { + return nullptr; + } + + async_callback_info->index = value0; + if (callBackMode) { + napi_create_reference(env, argv[1], 1, &async_callback_info->callback[0]); + } + + napi_value ret = NAPI_MoveMissionToTopWrap(env, info, callBackMode, *async_callback_info); + if (ret == nullptr) { + delete async_callback_info; + async_callback_info = nullptr; + } + + return ((callBackMode) ? (nullptr) : (ret)); +} + +auto NAPI_KillProcessesByBundleNameAsyncExecuteCallback = [](napi_env env, void *data) { + HILOG_INFO("killProcessesByBundleName called(CallBack Mode)..."); + AsyncKillProcessCallbackInfo *async_callback_info = (AsyncKillProcessCallbackInfo *)data; + async_callback_info->result = GetAbilityManagerInstance()->KillProcess(async_callback_info->bundleName); +}; + +auto NAPI_KillProcessesByBundleNameAsyncCompleteCallback = [](napi_env env, napi_status status, void *data) { + HILOG_INFO("killProcessesByBundleName compeleted(CallBack Mode)..."); + AsyncKillProcessCallbackInfo *async_callback_info = (AsyncKillProcessCallbackInfo *)data; + napi_value result[NUMBER_OF_PARAMETERS_TWO] = {0}; + napi_value callback = nullptr; + napi_value undefined = nullptr; + napi_value callResult = nullptr; + + result[0] = GetCallbackErrorValue(async_callback_info->env, BUSINESS_ERROR_CODE_OK); + napi_create_int32(async_callback_info->env, async_callback_info->result, &result[1]); + napi_get_undefined(env, &undefined); + + napi_get_reference_value(env, async_callback_info->callback[0], &callback); + napi_call_function(env, undefined, callback, NUMBER_OF_PARAMETERS_TWO, &result[0], &callResult); + + if (async_callback_info->callback[0] != nullptr) { + napi_delete_reference(env, async_callback_info->callback[0]); + } + + napi_delete_async_work(env, async_callback_info->asyncWork); + delete async_callback_info; +}; + +auto NAPI_KillProcessesByBundleNamePromiseCompleteCallback = [](napi_env env, napi_status status, void *data) { + HILOG_INFO("killProcessesByBundleName compeleted(Promise Mode)..."); + AsyncKillProcessCallbackInfo *async_callback_info = (AsyncKillProcessCallbackInfo *)data; + napi_value result = nullptr; + napi_create_int32(async_callback_info->env, async_callback_info->result, &result); + napi_resolve_deferred(async_callback_info->env, async_callback_info->deferred, result); + napi_delete_async_work(env, async_callback_info->asyncWork); + delete async_callback_info; +}; + +napi_value NAPI_KillProcessesByBundleNameWrap( + napi_env env, napi_callback_info info, bool callBackMode, AsyncKillProcessCallbackInfo &async_callback_info) +{ + HILOG_INFO("NAPI_KillProcessesByBundleName called..."); + if (callBackMode) { + napi_value resourceName = nullptr; + napi_create_string_latin1(env, "NAPI_KillProcessesByBundleNameCallBack", NAPI_AUTO_LENGTH, &resourceName); + + napi_create_async_work(env, + nullptr, + resourceName, + NAPI_KillProcessesByBundleNameAsyncExecuteCallback, + NAPI_KillProcessesByBundleNameAsyncCompleteCallback, + (void *)&async_callback_info, + &async_callback_info.asyncWork); + + NAPI_CALL(env, napi_queue_async_work(env, async_callback_info.asyncWork)); + // create reutrn + napi_value ret = 0; + NAPI_CALL(env, napi_create_int32(env, 0, &ret)); + return ret; + } else { + napi_value resourceName = nullptr; + napi_create_string_latin1(env, "NAPI_KillProcessesByBundleNamePromise", NAPI_AUTO_LENGTH, &resourceName); + + napi_deferred deferred = nullptr; + napi_value promise = nullptr; + NAPI_CALL(env, napi_create_promise(env, &deferred, &promise)); + async_callback_info.deferred = deferred; + + napi_create_async_work(env, + nullptr, + resourceName, + NAPI_KillProcessesByBundleNameAsyncExecuteCallback, + NAPI_KillProcessesByBundleNamePromiseCompleteCallback, + (void *)&async_callback_info, + &async_callback_info.asyncWork); + napi_queue_async_work(env, async_callback_info.asyncWork); + return promise; + } +} + +napi_value NAPI_KillProcessesByBundleName(napi_env env, napi_callback_info info) +{ + size_t argc = NUMBER_OF_PARAMETERS_TWO; + napi_value argv[NUMBER_OF_PARAMETERS_TWO] = {}; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL)); + HILOG_INFO("argc = [%{public}zu]", argc); + + std::string bundleName = ""; + ParseBundleName(env, bundleName, argv[0]); + + bool callBackMode = false; + if (argc >= NUMBER_OF_PARAMETERS_TWO) { + napi_valuetype valuetype = napi_valuetype::napi_null; + NAPI_CALL(env, napi_typeof(env, argv[1], &valuetype)); + NAPI_ASSERT(env, valuetype == napi_function, "Wrong argument type. Function expected."); + callBackMode = true; + } + + AsyncKillProcessCallbackInfo *async_callback_info = new (std::nothrow) AsyncKillProcessCallbackInfo{ + .env = env, + .asyncWork = nullptr, + .deferred = nullptr, + }; + if (async_callback_info == nullptr) { + return nullptr; + } + + async_callback_info->bundleName = bundleName; + if (callBackMode) { + napi_create_reference(env, argv[1], 1, &async_callback_info->callback[0]); + } + + napi_value ret = NAPI_KillProcessesByBundleNameWrap(env, info, callBackMode, *async_callback_info); + if (ret == nullptr) { + delete async_callback_info; + async_callback_info = nullptr; + } + + return ((callBackMode) ? (nullptr) : (ret)); +} + +auto NAPI_ClearUpApplicationDataAsyncExecuteCallback = [](napi_env env, void *data) { + HILOG_INFO("clearUpApplicationData called(CallBack Mode)..."); + AsyncClearUpApplicationDataCallbackInfo *async_callback_info = (AsyncClearUpApplicationDataCallbackInfo *)data; + async_callback_info->result = GetAppManagerInstance()->ClearUpApplicationData(async_callback_info->bundleName); +}; + +auto NAPI_ClearUpApplicationDataAsyncCompleteCallback = [](napi_env env, napi_status status, void *data) { + HILOG_INFO("clearUpApplicationData compeleted(CallBack Mode)..."); + AsyncClearUpApplicationDataCallbackInfo *async_callback_info = (AsyncClearUpApplicationDataCallbackInfo *)data; + napi_value result[NUMBER_OF_PARAMETERS_TWO] = {0}; + napi_value callback = nullptr; + napi_value undefined = nullptr; + napi_value callResult = nullptr; + result[0] = GetCallbackErrorValue(async_callback_info->env, BUSINESS_ERROR_CODE_OK); + napi_create_int32(async_callback_info->env, async_callback_info->result, &result[1]); + napi_get_undefined(env, &undefined); + + napi_get_reference_value(env, async_callback_info->callback[0], &callback); + napi_call_function(env, undefined, callback, NUMBER_OF_PARAMETERS_TWO, &result[0], &callResult); + if (async_callback_info->callback[0] != nullptr) { + napi_delete_reference(env, async_callback_info->callback[0]); + } + + napi_delete_async_work(env, async_callback_info->asyncWork); + delete async_callback_info; +}; + +auto NAPI_ClearUpApplicationDataPromiseCompleteCallback = [](napi_env env, napi_status status, void *data) { + HILOG_INFO("clearUpApplicationData compeleted(Promise Mode)..."); + AsyncClearUpApplicationDataCallbackInfo *async_callback_info = (AsyncClearUpApplicationDataCallbackInfo *)data; + napi_value result = nullptr; + napi_create_int32(async_callback_info->env, async_callback_info->result, &result); + napi_resolve_deferred(async_callback_info->env, async_callback_info->deferred, result); + napi_delete_async_work(env, async_callback_info->asyncWork); + delete async_callback_info; +}; + +napi_value NAPI_ClearUpApplicationDataWrap(napi_env env, napi_callback_info info, bool callBackMode, + AsyncClearUpApplicationDataCallbackInfo &async_callback_info) +{ + HILOG_INFO("NAPI_ClearUpApplicationData called..."); + if (callBackMode) { + napi_value resourceName = nullptr; + napi_create_string_latin1(env, "NAPI_ClearUpApplicationDataCallBack", NAPI_AUTO_LENGTH, &resourceName); + + napi_create_async_work(env, + nullptr, + resourceName, + NAPI_ClearUpApplicationDataAsyncExecuteCallback, + NAPI_ClearUpApplicationDataAsyncCompleteCallback, + (void *)&async_callback_info, + &async_callback_info.asyncWork); + + NAPI_CALL(env, napi_queue_async_work(env, async_callback_info.asyncWork)); + // create reutrn + napi_value ret = 0; + NAPI_CALL(env, napi_create_int32(env, 0, &ret)); + return ret; + } else { + napi_value resourceName = nullptr; + napi_create_string_latin1(env, "NAPI_ClearUpApplicationDataPromise", NAPI_AUTO_LENGTH, &resourceName); + + napi_deferred deferred = nullptr; + napi_value promise = nullptr; + NAPI_CALL(env, napi_create_promise(env, &deferred, &promise)); + async_callback_info.deferred = deferred; + + napi_create_async_work(env, + nullptr, + resourceName, + NAPI_ClearUpApplicationDataAsyncExecuteCallback, + NAPI_ClearUpApplicationDataPromiseCompleteCallback, + (void *)&async_callback_info, + &async_callback_info.asyncWork); + napi_queue_async_work(env, async_callback_info.asyncWork); + return promise; + } +} // namespace AppExecFwk + +napi_value NAPI_ClearUpApplicationData(napi_env env, napi_callback_info info) +{ + size_t argc = NUMBER_OF_PARAMETERS_TWO; + napi_value argv[NUMBER_OF_PARAMETERS_TWO] = {}; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL)); + HILOG_INFO("argc = [%{public}zu]", argc); + + std::string bundleName = ""; + ParseBundleName(env, bundleName, argv[0]); + + bool callBackMode = false; + if (argc >= NUMBER_OF_PARAMETERS_TWO) { + napi_valuetype valuetype = napi_valuetype::napi_null; + NAPI_CALL(env, napi_typeof(env, argv[1], &valuetype)); + NAPI_ASSERT(env, valuetype == napi_function, "Wrong argument type. Function expected."); + callBackMode = true; + } + + AsyncClearUpApplicationDataCallbackInfo *async_callback_info = + new (std::nothrow) AsyncClearUpApplicationDataCallbackInfo{ + .env = env, + .asyncWork = nullptr, + .deferred = nullptr, + }; + if (async_callback_info == nullptr) { + return nullptr; + } + + async_callback_info->bundleName = bundleName; + if (callBackMode) { + napi_create_reference(env, argv[1], 1, &async_callback_info->callback[0]); + } + + napi_value ret = NAPI_ClearUpApplicationDataWrap(env, info, callBackMode, *async_callback_info); + if (ret == nullptr) { + delete async_callback_info; + async_callback_info = nullptr; + } + + return ((callBackMode) ? (nullptr) : (ret)); +} + +void CreateWeightReasonCodeObject(napi_env env, napi_value value) +{ + napi_value nUnknow = nullptr; + NAPI_CALL_RETURN_VOID( + env, napi_create_int32(env, static_cast(WeightReasonCode::REASON_UNKNOWN), &nUnknow)); + NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, value, "REASON_UNKNOWN", nUnknow)); + napi_value nForeground = nullptr; + NAPI_CALL_RETURN_VOID( + env, napi_create_int32(env, static_cast(WeightReasonCode::WEIGHT_FOREGROUND), &nForeground)); + NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, value, "WEIGHT_FOREGROUND", nForeground)); + napi_value nForegroundService = nullptr; + NAPI_CALL_RETURN_VOID(env, + napi_create_int32(env, static_cast(WeightReasonCode::WEIGHT_FOREGROUND_SERVICE), &nForegroundService)); + NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, value, "WEIGHT_FOREGROUND_SERVICE", nForegroundService)); + napi_value nVisible = nullptr; + NAPI_CALL_RETURN_VOID( + env, napi_create_int32(env, static_cast(WeightReasonCode::WEIGHT_VISIBLE), &nVisible)); + NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, value, "WEIGHT_VISIBLE", nVisible)); + napi_value nPerceptible = nullptr; + NAPI_CALL_RETURN_VOID( + env, napi_create_int32(env, static_cast(WeightReasonCode::WEIGHT_PERCEPTIBLE), &nPerceptible)); + NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, value, "WEIGHT_PERCEPTIBLE", nPerceptible)); + napi_value nService = nullptr; + NAPI_CALL_RETURN_VOID( + env, napi_create_int32(env, static_cast(WeightReasonCode::WEIGHT_SERVICE), &nService)); + NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, value, "WEIGHT_SERVICE", nService)); + napi_value nTopSleeping = nullptr; + NAPI_CALL_RETURN_VOID( + env, napi_create_int32(env, static_cast(WeightReasonCode::WEIGHT_TOP_SLEEPING), &nTopSleeping)); + NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, value, "WEIGHT_TOP_SLEEPING", nTopSleeping)); + napi_value nCantSaveState = nullptr; + NAPI_CALL_RETURN_VOID( + env, napi_create_int32(env, static_cast(WeightReasonCode::WEIGHT_CANT_SAVE_STATE), &nCantSaveState)); + NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, value, "WEIGHT_CANT_SAVE_STATE", nCantSaveState)); + napi_value nWeightCached = nullptr; + NAPI_CALL_RETURN_VOID( + env, napi_create_int32(env, static_cast(WeightReasonCode::WEIGHT_CACHED), &nWeightCached)); + NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, value, "WEIGHT_CACHED", nWeightCached)); + napi_value nWeightGone = nullptr; + NAPI_CALL_RETURN_VOID( + env, napi_create_int32(env, static_cast(WeightReasonCode::WEIGHT_GONE), &nWeightGone)); + NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, value, "WEIGHT_GONE", nWeightGone)); +} + +napi_value GetCallbackErrorValue(napi_env env, int errCode) +{ + napi_value result = nullptr; + napi_value eCode = nullptr; + NAPI_CALL(env, napi_create_int32(env, errCode, &eCode)); + NAPI_CALL(env, napi_create_object(env, &result)); + NAPI_CALL(env, napi_set_named_property(env, result, "code", eCode)); + return result; +} +} // namespace AppExecFwk +} // namespace OHOS diff --git a/tools/interfaces/kits/napi/aafwk/abilityManager/napi_ability_manager.h b/tools/interfaces/kits/napi/aafwk/abilityManager/napi_ability_manager.h new file mode 100644 index 00000000000..914c94dd812 --- /dev/null +++ b/tools/interfaces/kits/napi/aafwk/abilityManager/napi_ability_manager.h @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef NAPI_ABILITY_MANAGER_H +#define NAPI_ABILITY_MANAGER_H + +#include + +#include "napi/native_common.h" +#include "napi/native_node_api.h" + +#include "running_process_info.h" +#include "ability_mission_info.h" + +using RunningProcessInfo = OHOS::AppExecFwk::RunningProcessInfo; +using AbilityMissionInfo = OHOS::AAFwk::AbilityMissionInfo; + +#define BUFFER_LENGTH_MAX (128) +#define DEFAULT_STACK_ID (1) +#define DEFAULT_LAST_MEMORY_LEVEL (-1) +#define DEFAULT_WEIGHT (-1) + +#define MAX_MISSION_NUM (65535) +#define QUERY_RECENT_RUNNING_MISSION_INFO_TYPE (2) + +#define BUSINESS_ERROR_CODE_OK 0 + +namespace OHOS { +namespace AppExecFwk { +const uint8_t NUMBER_OF_PARAMETERS_TWO = 2; +const uint8_t NUMBER_OF_PARAMETERS_THREE = 3; + +struct AsyncCallbackInfo { + napi_env env; + napi_async_work asyncWork; + napi_deferred deferred; + napi_ref callback[2] = {0}; + std::vector info; +}; + +struct AsyncMissionInfosCallbackInfo { + napi_env env; + napi_async_work asyncWork; + napi_deferred deferred; + napi_ref callback[2] = {0}; + int32_t maxMissionNum = 0; + int32_t queryType = 0; + std::vector recentMissionInfo; +}; + +struct AsyncRemoveMissionCallbackInfo { + napi_env env; + napi_async_work asyncWork; + napi_deferred deferred; + napi_ref callback[2] = {0}; + int32_t index = -1; + int32_t result = -1; +}; + +struct AsyncRemoveMissionsCallbackInfo { + napi_env env; + napi_async_work asyncWork; + napi_deferred deferred; + napi_ref callback[2] = {0}; + std::vector missionIds; + int32_t result = -1; +}; + +struct AsyncClearMissionsCallbackInfo { + napi_env env; + napi_async_work asyncWork; + napi_deferred deferred; + napi_ref callback[2] = {0}; + int32_t result = -1; +}; + +struct AsyncMoveMissionToTopCallbackInfo { + napi_env env; + napi_async_work asyncWork; + napi_deferred deferred; + napi_ref callback[2] = {0}; + int32_t index = -1; + int32_t result = -1; +}; + +struct AsyncKillProcessCallbackInfo { + napi_env env; + napi_async_work asyncWork; + napi_deferred deferred; + napi_ref callback[2] = {0}; + std::string bundleName; + int32_t result = -1; +}; + +struct AsyncClearUpApplicationDataCallbackInfo { + napi_env env; + napi_async_work asyncWork; + napi_deferred deferred; + napi_ref callback[2] = {0}; + std::string bundleName; + int32_t result = -1; +}; + +struct AsyncPreviousMissionInfosCallbackInfo { + napi_env env; + napi_async_work asyncWork; + napi_deferred deferred; + napi_ref callback[2] = {0}; + int32_t maxMissionNum = 0; + std::vector previousMissionInfo; +}; + +napi_value NAPI_GetAllRunningProcesses(napi_env env, napi_callback_info info); +napi_value NAPI_GetActiveProcessInfos(napi_env env, napi_callback_info info); +napi_value NAPI_QueryRunningAbilityMissionInfos(napi_env env, napi_callback_info info); +napi_value NAPI_GetActiveAbilityMissionInfos(napi_env env, napi_callback_info info); +napi_value NAPI_QueryRecentAbilityMissionInfos(napi_env env, napi_callback_info info); +napi_value NAPI_GetPreviousAbilityMissionInfos(napi_env env, napi_callback_info info); +napi_value NAPI_RemoveMission(napi_env env, napi_callback_info info); +napi_value NAPI_RemoveMissions(napi_env env, napi_callback_info info); +napi_value NAPI_ClearMissions(napi_env env, napi_callback_info info); +napi_value NAPI_MoveMissionToTop(napi_env env, napi_callback_info info); +napi_value NAPI_KillProcessesByBundleName(napi_env env, napi_callback_info info); +napi_value NAPI_ClearUpApplicationData(napi_env env, napi_callback_info info); +void CreateWeightReasonCodeObject(napi_env env, napi_value value); +napi_value GetCallbackErrorValue(napi_env env, int errCode); +} // namespace AppExecFwk +} // namespace OHOS +#endif // NAPI_ABILITY_MANAGER_H \ No newline at end of file diff --git a/tools/interfaces/kits/napi/aafwk/abilityManager/native_module.cpp b/tools/interfaces/kits/napi/aafwk/abilityManager/native_module.cpp new file mode 100644 index 00000000000..7d38a6dd9d5 --- /dev/null +++ b/tools/interfaces/kits/napi/aafwk/abilityManager/native_module.cpp @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +#include "napi_ability_manager.h" +#include "napi/native_api.h" +#include "napi/native_node_api.h" + +#include "hilog_wrapper.h" + +namespace OHOS { +namespace AppExecFwk { +EXTERN_C_START +/* + * function for module exports + */ +static napi_value Init(napi_env env, napi_value exports) +{ + HILOG_INFO("napi_moudule Init start..."); + + napi_value nWeightReasonCode = nullptr; + NAPI_CALL(env, napi_create_object(env, &nWeightReasonCode)); + CreateWeightReasonCodeObject(env, nWeightReasonCode); + + napi_property_descriptor desc[] = { + DECLARE_NAPI_FUNCTION("getAllRunningProcesses", NAPI_GetAllRunningProcesses), + DECLARE_NAPI_FUNCTION("getActiveProcessInfos", NAPI_GetActiveProcessInfos), + DECLARE_NAPI_FUNCTION("queryRunningAbilityMissionInfos", NAPI_QueryRunningAbilityMissionInfos), + DECLARE_NAPI_FUNCTION("getActiveAbilityMissionInfos", NAPI_GetActiveAbilityMissionInfos), + DECLARE_NAPI_FUNCTION("queryRecentAbilityMissionInfos", NAPI_QueryRecentAbilityMissionInfos), + DECLARE_NAPI_FUNCTION("getPreviousAbilityMissionInfos", NAPI_GetPreviousAbilityMissionInfos), + DECLARE_NAPI_FUNCTION("removeMission", NAPI_RemoveMission), + DECLARE_NAPI_FUNCTION("removeMissions", NAPI_RemoveMissions), + DECLARE_NAPI_FUNCTION("deleteMissions", NAPI_RemoveMissions), + DECLARE_NAPI_FUNCTION("clearMissions", NAPI_ClearMissions), + DECLARE_NAPI_FUNCTION("moveMissionToTop", NAPI_MoveMissionToTop), + DECLARE_NAPI_FUNCTION("killProcessesByBundleName", NAPI_KillProcessesByBundleName), + DECLARE_NAPI_FUNCTION("clearUpApplicationData", NAPI_ClearUpApplicationData), + DECLARE_NAPI_PROPERTY("WeightReasonCode", nWeightReasonCode), + }; + + NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc)); + HILOG_INFO("napi_moudule Init end..."); + return exports; +} +EXTERN_C_END + +/* + * Module define + */ +static napi_module _module = { + .nm_version = 1, + .nm_flags = 0, + .nm_filename = nullptr, + .nm_register_func = Init, + .nm_modname = "app.abilityManager", + .nm_priv = ((void *)0), + .reserved = {0}, +}; + +/* + * Module register function + */ +extern "C" __attribute__((constructor)) void RegisterModule(void) +{ + napi_module_register(&_module); +} +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/interfaces/kits/napi/aafwk/dataUriUtils/BUILD.gn b/tools/interfaces/kits/napi/aafwk/dataUriUtils/BUILD.gn new file mode 100755 index 00000000000..e7987859215 --- /dev/null +++ b/tools/interfaces/kits/napi/aafwk/dataUriUtils/BUILD.gn @@ -0,0 +1,55 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# import("//build/config/ohos/rules.gni") +import("//build/ohos.gni") +ohos_shared_library("datauriutils") { + include_dirs = [ + "//foundation/ace/napi/interfaces/kits", + "//foundation/aafwk/standard/frameworks/kits/ability/native/include", + "//foundation/aafwk/standard/interfaces/kits/napi/aafwk/dataUriUtils", + "//foundation/aafwk/standard/interfaces/kits/napi/aafwk/featureAbility", + "//third_party/node/src", + "//foundation/aafwk/standard/interfaces/kits/napi/aafwk/inner/napi_common", + ] + + sources = [ + "napi_data_uri_utils.cpp", + "native_module.cpp", + ] + + deps = [ + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/interfaces/innerkits/base:base", + "//foundation/aafwk/standard/interfaces/kits/napi/aafwk/inner/napi_common:napi_common", + "//foundation/ace/napi:ace_napi", + "//foundation/appexecfwk/standard/kits:appkit_native", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//utils/native/base:utils", + ] + + external_deps = [ + "aafwk_standard:ability_manager", + "aafwk_standard:want", + "appexecfwk_standard:appexecfwk_base", + "appexecfwk_standard:appexecfwk_core", + "appexecfwk_standard:libeventhandler", + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] + + relative_install_dir = "module/ability" + + subsystem_name = "aafwk" + part_name = "aafwk_standard" +} diff --git a/tools/interfaces/kits/napi/aafwk/dataUriUtils/napi_data_uri_utils.cpp b/tools/interfaces/kits/napi/aafwk/dataUriUtils/napi_data_uri_utils.cpp new file mode 100644 index 00000000000..a2c0d04b63e --- /dev/null +++ b/tools/interfaces/kits/napi/aafwk/dataUriUtils/napi_data_uri_utils.cpp @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "napi_data_uri_utils.h" +#include "data_uri_utils.h" +#include "feature_ability_common.h" +#include "uri.h" +#include +#include +#include +#include "securec.h" +#include "hilog_wrapper.h" + +namespace OHOS { +namespace AppExecFwk { +/** + * @brief DataUriUtilsInit NAPI module registration. + * + * @param env The environment that the Node-API call is invoked under. + * @param exports An empty object via the exports parameter as a convenience. + * + * @return The return value from Init is treated as the exports object for the module. + */ +napi_value DataUriUtilsInit(napi_env env, napi_value exports) +{ + HILOG_INFO("%{public}s,called", __func__); + napi_property_descriptor properties[] = { + DECLARE_NAPI_FUNCTION("getIdSync", NAPI_GetIdSync), + DECLARE_NAPI_FUNCTION("attachIdSync", NAPI_AttachIdSync), + DECLARE_NAPI_FUNCTION("deleteIdSync", NAPI_DeleteIdSync), + DECLARE_NAPI_FUNCTION("updateIdSync", NAPI_UpdateIdSync), + }; + NAPI_CALL(env, napi_define_properties(env, exports, sizeof(properties) / sizeof(properties[0]), properties)); + + return exports; +} + +/** + * @brief DataUriUtils NAPI method : getIdSync. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_GetIdSync(napi_env env, napi_callback_info info) +{ + HILOG_INFO("%{public}s,called", __func__); + size_t requireArgc = 1; + size_t argc = 1; + napi_value args[1] = {nullptr}; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, nullptr, nullptr)); + if (argc > requireArgc) { + HILOG_ERROR("%{public}s, Wrong argument count.", __func__); + return WrapVoidToJS(env); + } + + napi_valuetype valuetype; + NAPI_CALL(env, napi_typeof(env, args[0], &valuetype)); + NAPI_ASSERT(env, valuetype == napi_string, "Wrong argument type. Numbers expected."); + + Uri uri(NapiValueToStringUtf8(env, args[0])); + + napi_value id = nullptr; + int64_t result = DataUriUtils::GetId(uri); + NAPI_CALL(env, napi_create_int64(env, result, &id)); + HILOG_INFO("%{public}s, uri=%{public}s, id=%{public}" PRId64, __func__, uri.ToString().c_str(), result); + + return id; +} + +/** + * @brief DataUriUtils NAPI method : attachIdSync. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_AttachIdSync(napi_env env, napi_callback_info info) +{ + HILOG_INFO("%{public}s,called", __func__); + size_t requireArgc = 2; + size_t argc = 2; + napi_value args[2] = {nullptr}; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, nullptr, nullptr)); + if (argc > requireArgc) { + HILOG_ERROR("%{public}s, Wrong argument count.", __func__); + return WrapVoidToJS(env); + } + + napi_valuetype valuetype; + NAPI_CALL(env, napi_typeof(env, args[0], &valuetype)); + NAPI_ASSERT(env, valuetype == napi_string, "Wrong argument type. Numbers expected."); + + Uri uri(NapiValueToStringUtf8(env, args[0])); + + int64_t id; + NAPI_CALL(env, napi_get_value_int64(env, args[1], &id)); + std::string result = DataUriUtils::AttachId(uri, id).ToString(); + + napi_value uriAttached = nullptr; + NAPI_CALL(env, napi_create_string_utf8(env, result.c_str(), NAPI_AUTO_LENGTH, &uriAttached)); + HILOG_INFO("%{public}s, uri=%{public}s, result=%{public}s, id=%{public}" PRId64, + __func__, + uri.ToString().c_str(), + result.c_str(), + id); + + return uriAttached; +} + +/** + * @brief DataUriUtils NAPI method : deleteIdSync. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_DeleteIdSync(napi_env env, napi_callback_info info) +{ + HILOG_INFO("%{public}s,called", __func__); + size_t requireArgc = 1; + size_t argc = 1; + napi_value args[1] = {nullptr}; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, nullptr, nullptr)); + if (argc > requireArgc) { + HILOG_ERROR("%{public}s, Wrong argument count.", __func__); + return WrapVoidToJS(env); + } + + napi_valuetype valuetype; + NAPI_CALL(env, napi_typeof(env, args[0], &valuetype)); + NAPI_ASSERT(env, valuetype == napi_string, "Wrong argument type. Numbers expected."); + + Uri uri(NapiValueToStringUtf8(env, args[0])); + + std::string result = DataUriUtils::DeleteId(uri).ToString(); + napi_value uriDeleted = nullptr; + NAPI_CALL(env, napi_create_string_utf8(env, result.c_str(), NAPI_AUTO_LENGTH, &uriDeleted)); + + HILOG_INFO("%{public}s, uri=%{public}s, result=%{public}s.", __func__, uri.ToString().c_str(), result.c_str()); + + return uriDeleted; +} + +/** + * @brief DataUriUtils NAPI method : updateIdSync. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_UpdateIdSync(napi_env env, napi_callback_info info) +{ + HILOG_INFO("%{public}s,called", __func__); + size_t requireArgc = 2; + size_t argc = 2; + napi_value args[2] = {nullptr}; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, nullptr, nullptr)); + if (argc > requireArgc) { + HILOG_ERROR("%{public}s, Wrong argument count.", __func__); + return WrapVoidToJS(env); + } + + napi_valuetype valuetype; + NAPI_CALL(env, napi_typeof(env, args[0], &valuetype)); + NAPI_ASSERT(env, valuetype == napi_string, "Wrong argument type. Numbers expected."); + + Uri uri(NapiValueToStringUtf8(env, args[0])); + + int64_t id; + NAPI_CALL(env, napi_get_value_int64(env, args[1], &id)); + + std::string result = DataUriUtils::UpdateId(uri, id).ToString(); + + napi_value uriUpdated = nullptr; + NAPI_CALL(env, napi_create_string_utf8(env, result.c_str(), NAPI_AUTO_LENGTH, &uriUpdated)); + + HILOG_INFO("%{public}s, uri=%{public}s, result=%{public}s, id=%{public}" PRId64, + __func__, + uri.ToString().c_str(), + result.c_str(), + id); + + return uriUpdated; +} +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/interfaces/kits/napi/aafwk/dataUriUtils/napi_data_uri_utils.h b/tools/interfaces/kits/napi/aafwk/dataUriUtils/napi_data_uri_utils.h new file mode 100644 index 00000000000..d7c85294e7f --- /dev/null +++ b/tools/interfaces/kits/napi/aafwk/dataUriUtils/napi_data_uri_utils.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_APPEXECFWK_NAPI_DATA_URI_UTILS_H +#define OHOS_APPEXECFWK_NAPI_DATA_URI_UTILS_H +#include "napi/native_common.h" +#include "napi/native_node_api.h" + +namespace OHOS { +namespace AppExecFwk { +/** + * @brief DataUriUtilsInit NAPI module registration. + * + * @param env The environment that the Node-API call is invoked under. + * @param exports An empty object via the exports parameter as a convenience. + * + * @return The return value from Init is treated as the exports object for the module. + */ +napi_value DataUriUtilsInit(napi_env env, napi_value exports); + +/** + * @brief DataUriUtils NAPI method : getIdSync. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_GetIdSync(napi_env env, napi_callback_info info); + +/** + * @brief DataUriUtils NAPI method : attachIdSync. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_AttachIdSync(napi_env env, napi_callback_info info); + +/** + * @brief DataUriUtils NAPI method : deleteIdSync. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_DeleteIdSync(napi_env env, napi_callback_info info); + +/** + * @brief DataUriUtils NAPI method : updateIdSync. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_UpdateIdSync(napi_env env, napi_callback_info info); +} // namespace AppExecFwk +} // namespace OHOS +#endif /* OHOS_APPEXECFWK_NAPI_DATA_URI_UTILS */ diff --git a/tools/interfaces/kits/napi/aafwk/dataUriUtils/native_module.cpp b/tools/interfaces/kits/napi/aafwk/dataUriUtils/native_module.cpp new file mode 100644 index 00000000000..f4baa0c8514 --- /dev/null +++ b/tools/interfaces/kits/napi/aafwk/dataUriUtils/native_module.cpp @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +#include "napi_data_uri_utils.h" +#include "napi/native_api.h" +#include "napi/native_node_api.h" +namespace OHOS { +namespace AppExecFwk { +EXTERN_C_START +/* + * The module initialization. + */ +static napi_value Init(napi_env env, napi_value exports) +{ + DataUriUtilsInit(env, exports); + return exports; +} +EXTERN_C_END + +/* + * The module definition. + */ +static napi_module _module = { + .nm_version = 1, + .nm_flags = 0, + .nm_filename = nullptr, + .nm_register_func = Init, + .nm_modname = "ability.dataUriUtils", + .nm_priv = ((void *)0), + .reserved = {0} +}; + +/* + * The module registration. + */ +extern "C" __attribute__((constructor)) void RegisterModule(void) +{ + napi_module_register(&_module); +} +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/interfaces/kits/napi/aafwk/featureAbility/BUILD.gn b/tools/interfaces/kits/napi/aafwk/featureAbility/BUILD.gn new file mode 100755 index 00000000000..b3dc9c51e9f --- /dev/null +++ b/tools/interfaces/kits/napi/aafwk/featureAbility/BUILD.gn @@ -0,0 +1,74 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# import("//build/config/ohos/rules.gni") +import("//build/ohos.gni") +ohos_shared_library("featureability") { + include_dirs = [ + "//foundation/ace/napi/interfaces/kits", + "//third_party/node/src", + "//third_party/libuv/include", + "//foundation/aafwk/standard/frameworks/kits/ability/native/include", + "//foundation/aafwk/standard/interfaces/kits/napi/aafwk/featureAbility", + "//foundation/aafwk/standard/interfaces/kits/napi/aafwk/inner/napi_common", + "//foundation/distributeddatamgr/appdatamgr/frameworks/jskitsimpl/native_rdb", + "//foundation/distributeddatamgr/appdatamgr/frameworks/jskitsimpl/common", + "//foundation/distributeddatamgr/appdatamgr/frameworks/jskitsimpl/native_dataability", + ] + + sources = [ + "//foundation/distributeddatamgr/appdatamgr/frameworks/jskitsimpl/common/js_utils.cpp", + + #"//foundation/distributeddatamgr/appdatamgr/frameworks/jskitsimpl/native_rdb/napi_rdb_predicates.cpp", + "//foundation/distributeddatamgr/appdatamgr/frameworks/jskitsimpl/native_dataability/napi_data_ability_predicates.cpp", + "//foundation/distributeddatamgr/appdatamgr/frameworks/jskitsimpl/native_rdb/napi_result_set.cpp", + "feature_ability.cpp", + "feature_ability_constant.cpp", + "napi_context.cpp", + "napi_data_ability_helper.cpp", + "napi_data_ability_operation.cpp", + "native_module.cpp", + ] + + deps = [ + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/interfaces/innerkits/base:base", + "//foundation/aafwk/standard/interfaces/innerkits/dataobs_manager:dataobs_manager", + "//foundation/aafwk/standard/interfaces/kits/napi/aafwk/inner/napi_common:napi_common", + "//foundation/ace/napi:ace_napi", + "//foundation/appexecfwk/standard/kits:appkit_native", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//third_party/libuv:uv_static", + "//utils/native/base:utils", + ] + + external_deps = [ + "aafwk_standard:ability_manager", + "aafwk_standard:want", + "appexecfwk_standard:appexecfwk_base", + "appexecfwk_standard:appexecfwk_core", + "appexecfwk_standard:libeventhandler", + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + "native_appdatamgr:native_appdatafwk", + "native_appdatamgr:native_dataability", + "native_appdatamgr:native_rdb", + + #"appdatamgr_jskits:rdb", + ] + + relative_install_dir = "module/ability" + + subsystem_name = "aafwk" + part_name = "aafwk_standard" +} diff --git a/tools/interfaces/kits/napi/aafwk/featureAbility/feature_ability.cpp b/tools/interfaces/kits/napi/aafwk/featureAbility/feature_ability.cpp new file mode 100755 index 00000000000..432cbfa63e7 --- /dev/null +++ b/tools/interfaces/kits/napi/aafwk/featureAbility/feature_ability.cpp @@ -0,0 +1,1558 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "feature_ability.h" +#include +#include +#include +#include "securec.h" +#include "ability_process.h" +#include "hilog_wrapper.h" +#include "napi_context.h" +#include "element_name.h" +#include "napi_data_ability_helper.h" +#include "../inner/napi_common/napi_common_ability.h" + +using namespace OHOS::AAFwk; +using namespace OHOS::AppExecFwk; + +namespace OHOS { +namespace AppExecFwk { +static int64_t dummyRequestCode_ = 0; +CallbackInfo g_aceCallbackInfo; + +const int PARA_SIZE_IS_ONE = 1; +const int PARA_SIZE_IS_TWO = 2; + +/** + * @brief FeatureAbility NAPI module registration. + * + * @param env The environment that the Node-API call is invoked under. + * @param exports An empty object via the exports parameter as a convenience. + * + * @return The return value from Init is treated as the exports object for the module. + */ +napi_value FeatureAbilityInit(napi_env env, napi_value exports) +{ + HILOG_INFO("%{public}s,called", __func__); + napi_property_descriptor properties[] = { + DECLARE_NAPI_FUNCTION("startAbility", NAPI_StartAbility), + DECLARE_NAPI_FUNCTION("startAbilityForResult", NAPI_StartAbilityForResult), + DECLARE_NAPI_FUNCTION("finishWithResult", NAPI_SetResult), + DECLARE_NAPI_FUNCTION("terminateSelfWithResult", NAPI_SetResult), + DECLARE_NAPI_FUNCTION("terminateAbility", NAPI_TerminateAbility), + DECLARE_NAPI_FUNCTION("terminateSelf", NAPI_TerminateAbility), + DECLARE_NAPI_FUNCTION("hasWindowFocus", NAPI_HasWindowFocus), + DECLARE_NAPI_FUNCTION("getContext", NAPI_GetContext), + DECLARE_NAPI_FUNCTION("getWant", NAPI_GetWant), + DECLARE_NAPI_FUNCTION("getAppType", NAPI_GetAppType), + DECLARE_NAPI_FUNCTION("getAbilityName", NAPI_GetAbilityName), + DECLARE_NAPI_FUNCTION("getAbilityInfo", NAPI_GetAbilityInfo), + DECLARE_NAPI_FUNCTION("getHapModuleInfo", NAPI_GetHapModuleInfo), + DECLARE_NAPI_FUNCTION("getDataAbilityHelper", NAPI_GetDataAbilityHelper), + DECLARE_NAPI_FUNCTION("acquireDataAbilityHelper", NAPI_AcquireDataAbilityHelper), + DECLARE_NAPI_FUNCTION("connectAbility", NAPI_FAConnectAbility), + DECLARE_NAPI_FUNCTION("disconnectAbility", NAPI_FADisConnectAbility), + DECLARE_NAPI_FUNCTION("continueAbility", NAPI_FAContinueAbility), + DECLARE_NAPI_FUNCTION("getWantSync", NAPI_GetWantSync), + }; + NAPI_CALL(env, napi_define_properties(env, exports, sizeof(properties) / sizeof(properties[0]), properties)); + + return exports; +} + +/** + * @brief FeatureAbility NAPI method : startAbility. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_StartAbility(napi_env env, napi_callback_info info) +{ + HILOG_INFO("%{public}s called.", __func__); + return NAPI_StartAbilityCommon(env, info, AbilityType::PAGE); +} + +/** + * @brief FeatureAbility NAPI method : startAbilityForResult. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_StartAbilityForResult(napi_env env, napi_callback_info info) +{ + HILOG_INFO("%{public}s,called.", __func__); + AsyncCallbackInfo *asyncCallbackInfo = CreateAsyncCallbackInfo(env); + if (asyncCallbackInfo == nullptr) { + return WrapVoidToJS(env); + } + + napi_value ret = StartAbilityForResultWrap(env, info, asyncCallbackInfo); + if (ret == nullptr) { + if (asyncCallbackInfo != nullptr) { + delete asyncCallbackInfo; + asyncCallbackInfo = nullptr; + } + ret = WrapVoidToJS(env); + } + HILOG_INFO("%{public}s,end.", __func__); + return ret; +} + +/** + * @brief StartAbilityForResult processing function. + * + * @param env The environment that the Node-API call is invoked under. + * @param asyncCallbackInfo Process data asynchronously. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value StartAbilityForResultWrap(napi_env env, napi_callback_info info, AsyncCallbackInfo *asyncCallbackInfo) +{ + HILOG_INFO("%{public}s,called", __func__); + size_t argcAsync = 2; + const size_t argcPromise = 1; + const size_t argCountWithAsync = argcPromise + ARGS_ASYNC_COUNT; + napi_value args[ARGS_MAX_COUNT] = {nullptr}; + napi_value ret = 0; + + NAPI_CALL(env, napi_get_cb_info(env, info, &argcAsync, args, nullptr, nullptr)); + if (argcAsync > argCountWithAsync || argcAsync > ARGS_MAX_COUNT) { + HILOG_ERROR("%{public}s, Wrong argument count.", __func__); + return nullptr; + } + + CallAbilityParam param; + if (UnwrapForResultParam(param, env, args[0]) == nullptr) { + HILOG_ERROR("%{public}s, call UnwrapForResultParam failed.", __func__); + return nullptr; + } + asyncCallbackInfo->param = param; + asyncCallbackInfo->aceCallback.env = env; + if (argcAsync > PARAM1) { + napi_valuetype valuetype = napi_undefined; + napi_typeof(env, args[PARAM1], &valuetype); + if (valuetype == napi_function) { + // resultCallback: AsyncCallback + napi_create_reference(env, args[PARAM1], 1, &(asyncCallbackInfo->aceCallback.callback)); + } + } + + if (argcAsync > argcPromise) { + ret = StartAbilityForResultAsync(env, asyncCallbackInfo); + } else { + ret = StartAbilityForResultPromise(env, asyncCallbackInfo); + } + HILOG_INFO("%{public}s,end.", __func__); + return ret; +} + +napi_value StartAbilityForResultAsync(napi_env env, AsyncCallbackInfo *asyncCallbackInfo) +{ + HILOG_INFO("%{public}s, asyncCallback.", __func__); + if (asyncCallbackInfo == nullptr) { + HILOG_ERROR("%{public}s, param == nullptr.", __func__); + return nullptr; + } + napi_value resourceName = 0; + napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName); + + napi_create_async_work( + env, + nullptr, + resourceName, + [](napi_env env, void *data) { + HILOG_INFO("NAPI_StartAbilityForResult, worker pool thread execute."); + AsyncCallbackInfo *asyncCallbackInfo = static_cast(data); + if (asyncCallbackInfo != nullptr) { + AbilityProcess::GetInstance()->StartAbility( + asyncCallbackInfo->ability, asyncCallbackInfo->param, asyncCallbackInfo->aceCallback); + } else { + HILOG_ERROR("NAPI_StartAbilityForResult, asyncCallbackInfo == nullptr"); + } + HILOG_INFO("NAPI_StartAbilityForResult, worker pool thread execute end."); + }, + [](napi_env env, napi_status status, void *data) { + HILOG_INFO("NAPI_StartAbilityForResult, main event thread complete."); + AsyncCallbackInfo *asyncCallbackInfo = static_cast(data); + // remove asynccallback from startabilityforresult + if (asyncCallbackInfo->cbInfo.callback != nullptr) { + napi_delete_reference(env, asyncCallbackInfo->cbInfo.callback); + } + napi_delete_async_work(env, asyncCallbackInfo->asyncWork); + delete asyncCallbackInfo; + HILOG_INFO("NAPI_StartAbilityForResult, main event thread complete end."); + }, + (void *)asyncCallbackInfo, + &asyncCallbackInfo->asyncWork); + napi_queue_async_work(env, asyncCallbackInfo->asyncWork); + napi_value result = 0; + napi_get_null(env, &result); + HILOG_INFO("%{public}s, asyncCallback end.", __func__); + return result; +} + +napi_value StartAbilityForResultPromise(napi_env env, AsyncCallbackInfo *asyncCallbackInfo) +{ + HILOG_INFO("%{public}s, promise.", __func__); + if (asyncCallbackInfo == nullptr) { + HILOG_ERROR("%{public}s, param == nullptr.", __func__); + return nullptr; + } + napi_value resourceName = 0; + napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName); + napi_deferred deferred; + napi_value promise = 0; + napi_create_promise(env, &deferred, &promise); + asyncCallbackInfo->aceCallback.callback = nullptr; + asyncCallbackInfo->aceCallback.deferred = deferred; + + napi_create_async_work( + env, + nullptr, + resourceName, + [](napi_env env, void *data) { + HILOG_INFO("NAPI_StartAbilityForResult, worker pool thread execute."); + AsyncCallbackInfo *asyncCallbackInfo = static_cast(data); + if (asyncCallbackInfo != nullptr) { + AbilityProcess::GetInstance()->StartAbility( + asyncCallbackInfo->ability, asyncCallbackInfo->param, asyncCallbackInfo->aceCallback); + } else { + HILOG_ERROR("NAPI_StartAbilityForResult, asyncCallbackInfo == nullptr"); + } + HILOG_INFO("NAPI_StartAbilityForResult, worker pool thread execute end."); + }, + [](napi_env env, napi_status status, void *data) { + HILOG_INFO("NAPI_StartAbilityForResult, main event thread complete."); + AsyncCallbackInfo *asyncCallbackInfo = static_cast(data); + // resolve it when call onAbilityResult + napi_delete_async_work(env, asyncCallbackInfo->asyncWork); + delete asyncCallbackInfo; + HILOG_INFO("NAPI_StartAbilityForResult, main event thread complete end."); + }, + (void *)asyncCallbackInfo, + &asyncCallbackInfo->asyncWork); + napi_queue_async_work(env, asyncCallbackInfo->asyncWork); + HILOG_INFO("%{public}s, promise end.", __func__); + return promise; +} + +/** + * @brief FeatureAbility NAPI method : setResult. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_SetResult(napi_env env, napi_callback_info info) +{ + HILOG_INFO("%{public}s,called", __func__); + AsyncCallbackInfo *asyncCallbackInfo = CreateAsyncCallbackInfo(env); + if (asyncCallbackInfo == nullptr) { + HILOG_ERROR("%{public}s,asyncCallbackInfo == nullptr", __func__); + return WrapVoidToJS(env); + } + + napi_value ret = SetResultWrap(env, info, asyncCallbackInfo); + if (ret == nullptr) { + HILOG_ERROR("%{public}s,ret == nullptr", __func__); + if (asyncCallbackInfo != nullptr) { + delete asyncCallbackInfo; + asyncCallbackInfo = nullptr; + } + ret = WrapVoidToJS(env); + } + HILOG_INFO("%{public}s,end", __func__); + return ret; +} + +/** + * @brief SetResult processing function. + * + * @param env The environment that the Node-API call is invoked under. + * @param asyncCallbackInfo Process data asynchronously. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value SetResultWrap(napi_env env, napi_callback_info info, AsyncCallbackInfo *asyncCallbackInfo) +{ + HILOG_INFO("%{public}s,called", __func__); + size_t argcAsync = 2; + const size_t argcPromise = 1; + const size_t argCountWithAsync = argcPromise + ARGS_ASYNC_COUNT; + napi_value args[ARGS_MAX_COUNT] = {nullptr}; + napi_value ret = 0; + + NAPI_CALL(env, napi_get_cb_info(env, info, &argcAsync, args, nullptr, nullptr)); + if (argcAsync > argCountWithAsync || argcAsync > ARGS_MAX_COUNT) { + HILOG_ERROR("%{public}s, Wrong argument count.", __func__); + return nullptr; + } + + CallAbilityParam param; + if (UnwrapAbilityResult(param, env, args[0]) == nullptr) { + HILOG_ERROR("%{public}s, call unwrapWant failed.", __func__); + return nullptr; + } + asyncCallbackInfo->param = param; + + if (argcAsync > argcPromise) { + ret = SetResultAsync(env, args, 1, asyncCallbackInfo); + } else { + ret = SetResultPromise(env, asyncCallbackInfo); + } + HILOG_INFO("%{public}s,end", __func__); + return ret; +} + +napi_value SetResultAsync( + napi_env env, napi_value *args, const size_t argCallback, AsyncCallbackInfo *asyncCallbackInfo) +{ + HILOG_INFO("%{public}s, asyncCallback.", __func__); + if (args == nullptr || asyncCallbackInfo == nullptr) { + HILOG_ERROR("%{public}s, param == nullptr.", __func__); + return nullptr; + } + napi_value resourceName = 0; + napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName); + + napi_valuetype valuetype = napi_undefined; + napi_typeof(env, args[argCallback], &valuetype); + if (valuetype == napi_function) { + napi_create_reference(env, args[argCallback], 1, &asyncCallbackInfo->cbInfo.callback); + } + + napi_create_async_work( + env, + nullptr, + resourceName, + [](napi_env env, void *data) { + HILOG_INFO("NAPI_SetResult, worker pool thread execute."); + AsyncCallbackInfo *asyncCallbackInfo = static_cast(data); + if (asyncCallbackInfo->ability != nullptr) { + asyncCallbackInfo->ability->SetResult( + asyncCallbackInfo->param.requestCode, asyncCallbackInfo->param.want); + asyncCallbackInfo->ability->TerminateAbility(); + } else { + HILOG_ERROR("NAPI_SetResult, ability == nullptr"); + } + HILOG_INFO("NAPI_SetResult, worker pool thread execute end."); + }, + [](napi_env env, napi_status status, void *data) { + HILOG_INFO("NAPI_SetResult, main event thread complete."); + AsyncCallbackInfo *asyncCallbackInfo = static_cast(data); + napi_value result[ARGS_TWO] = {0}; + napi_value callback = 0; + napi_value undefined = 0; + napi_value callResult = 0; + napi_get_undefined(env, &undefined); + result[PARAM0] = GetCallbackErrorValue(env, NO_ERROR); + napi_get_null(env, &result[PARAM1]); + napi_get_reference_value(env, asyncCallbackInfo->cbInfo.callback, &callback); + napi_call_function(env, undefined, callback, ARGS_TWO, &result[PARAM0], &callResult); + + if (asyncCallbackInfo->cbInfo.callback != nullptr) { + napi_delete_reference(env, asyncCallbackInfo->cbInfo.callback); + } + napi_delete_async_work(env, asyncCallbackInfo->asyncWork); + delete asyncCallbackInfo; + HILOG_INFO("NAPI_SetResult, main event thread complete end."); + }, + (void *)asyncCallbackInfo, + &asyncCallbackInfo->asyncWork); + napi_queue_async_work(env, asyncCallbackInfo->asyncWork); + napi_value result = 0; + napi_get_null(env, &result); + HILOG_INFO("%{public}s, asyncCallback end", __func__); + return result; +} + +napi_value SetResultPromise(napi_env env, AsyncCallbackInfo *asyncCallbackInfo) +{ + HILOG_INFO("%{public}s, promise.", __func__); + if (asyncCallbackInfo == nullptr) { + HILOG_ERROR("%{public}s, param == nullptr.", __func__); + return nullptr; + } + napi_value resourceName = 0; + napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName); + napi_deferred deferred; + napi_value promise = 0; + napi_create_promise(env, &deferred, &promise); + asyncCallbackInfo->deferred = deferred; + + napi_create_async_work( + env, + nullptr, + resourceName, + [](napi_env env, void *data) { + HILOG_INFO("NAPI_SetResult, worker pool thread execute."); + AsyncCallbackInfo *asyncCallbackInfo = static_cast(data); + if (asyncCallbackInfo->ability != nullptr) { + asyncCallbackInfo->ability->SetResult( + asyncCallbackInfo->param.requestCode, asyncCallbackInfo->param.want); + asyncCallbackInfo->ability->TerminateAbility(); + } else { + HILOG_ERROR("NAPI_SetResult, ability == nullptr"); + } + HILOG_INFO("NAPI_SetResult, worker pool thread execute end."); + }, + [](napi_env env, napi_status status, void *data) { + HILOG_INFO("NAPI_SetResult, main event thread complete."); + AsyncCallbackInfo *asyncCallbackInfo = static_cast(data); + napi_value result = 0; + napi_get_null(env, &result); + napi_resolve_deferred(env, asyncCallbackInfo->deferred, result); + napi_delete_async_work(env, asyncCallbackInfo->asyncWork); + delete asyncCallbackInfo; + HILOG_INFO("NAPI_SetResult, main event thread complete end."); + }, + (void *)asyncCallbackInfo, + &asyncCallbackInfo->asyncWork); + napi_queue_async_work(env, asyncCallbackInfo->asyncWork); + HILOG_INFO("%{public}s, promise end", __func__); + return promise; +} + +/** + * @brief FeatureAbility NAPI method : terminateAbility. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_TerminateAbility(napi_env env, napi_callback_info info) +{ + HILOG_INFO("%{public}s,called", __func__); + AsyncCallbackInfo *asyncCallbackInfo = CreateAsyncCallbackInfo(env); + if (asyncCallbackInfo == nullptr) { + HILOG_ERROR("%{public}s,asyncCallbackInfo == nullptr", __func__); + return WrapVoidToJS(env); + } + + napi_value ret = TerminateAbilityWrap(env, info, asyncCallbackInfo); + if (ret == nullptr) { + HILOG_ERROR("%{public}s,ret == nullptr", __func__); + if (asyncCallbackInfo != nullptr) { + delete asyncCallbackInfo; + asyncCallbackInfo = nullptr; + } + ret = WrapVoidToJS(env); + } + HILOG_INFO("%{public}s,end", __func__); + return ret; +} + +/** + * @brief TerminateAbility processing function. + * + * @param env The environment that the Node-API call is invoked under. + * @param asyncCallbackInfo Process data asynchronously. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value TerminateAbilityWrap(napi_env env, napi_callback_info info, AsyncCallbackInfo *asyncCallbackInfo) +{ + HILOG_INFO("%{public}s, asyncCallback.", __func__); + if (asyncCallbackInfo == nullptr) { + HILOG_ERROR("%{public}s, asyncCallbackInfo == nullptr.", __func__); + return nullptr; + } + + size_t argcAsync = 1; + const size_t argcPromise = 0; + const size_t argCountWithAsync = argcPromise + ARGS_ASYNC_COUNT; + napi_value args[ARGS_MAX_COUNT] = {nullptr}; + napi_value ret = 0; + + NAPI_CALL(env, napi_get_cb_info(env, info, &argcAsync, args, nullptr, nullptr)); + if (argcAsync > argCountWithAsync || argcAsync > ARGS_MAX_COUNT) { + HILOG_ERROR("%{public}s, Wrong argument count.", __func__); + return nullptr; + } + + if (argcAsync > argcPromise) { + ret = TerminateAbilityAsync(env, args, 0, asyncCallbackInfo); + } else { + ret = TerminateAbilityPromise(env, asyncCallbackInfo); + } + HILOG_INFO("%{public}s, asyncCallback end", __func__); + return ret; +} + +napi_value TerminateAbilityAsync( + napi_env env, napi_value *args, const size_t argCallback, AsyncCallbackInfo *asyncCallbackInfo) +{ + HILOG_INFO("%{public}s, asyncCallback.", __func__); + if (args == nullptr || asyncCallbackInfo == nullptr) { + HILOG_ERROR("%{public}s, param == nullptr.", __func__); + return nullptr; + } + napi_value resourceName = 0; + napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName); + + napi_valuetype valuetype = napi_undefined; + napi_typeof(env, args[argCallback], &valuetype); + if (valuetype == napi_function) { + napi_create_reference(env, args[argCallback], 1, &asyncCallbackInfo->cbInfo.callback); + } + + napi_create_async_work( + env, + nullptr, + resourceName, + [](napi_env env, void *data) { + HILOG_INFO("NAPI_TerminateAbility, worker pool thread execute."); + AsyncCallbackInfo *asyncCallbackInfo = static_cast(data); + if (asyncCallbackInfo->ability != nullptr) { + asyncCallbackInfo->ability->TerminateAbility(); + } else { + HILOG_ERROR("NAPI_TerminateAbility, ability == nullptr"); + } + HILOG_INFO("NAPI_TerminateAbility, worker pool thread execute end."); + }, + [](napi_env env, napi_status status, void *data) { + HILOG_INFO("NAPI_TerminateAbility, main event thread complete."); + AsyncCallbackInfo *asyncCallbackInfo = static_cast(data); + napi_value callback = 0; + napi_value undefined = 0; + napi_value result[ARGS_TWO] = {0}; + napi_value callResult = 0; + napi_get_undefined(env, &undefined); + result[PARAM0] = GetCallbackErrorValue(env, NO_ERROR); + napi_get_null(env, &result[PARAM1]); + napi_get_reference_value(env, asyncCallbackInfo->cbInfo.callback, &callback); + napi_call_function(env, undefined, callback, ARGS_TWO, &result[PARAM0], &callResult); + + if (asyncCallbackInfo->cbInfo.callback != nullptr) { + napi_delete_reference(env, asyncCallbackInfo->cbInfo.callback); + } + napi_delete_async_work(env, asyncCallbackInfo->asyncWork); + delete asyncCallbackInfo; + HILOG_INFO("NAPI_TerminateAbility, main event thread complete end."); + }, + (void *)asyncCallbackInfo, + &asyncCallbackInfo->asyncWork); + napi_queue_async_work(env, asyncCallbackInfo->asyncWork); + napi_value result = 0; + napi_get_null(env, &result); + HILOG_INFO("%{public}s, asyncCallback end", __func__); + return result; +} + +napi_value TerminateAbilityPromise(napi_env env, AsyncCallbackInfo *asyncCallbackInfo) +{ + HILOG_INFO("%{public}s, promise.", __func__); + if (asyncCallbackInfo == nullptr) { + HILOG_ERROR("%{public}s, param == nullptr.", __func__); + return nullptr; + } + napi_value resourceName = 0; + napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName); + napi_deferred deferred; + napi_value promise = 0; + napi_create_promise(env, &deferred, &promise); + + asyncCallbackInfo->deferred = deferred; + + napi_create_async_work( + env, + nullptr, + resourceName, + [](napi_env env, void *data) { + HILOG_INFO("NAPI_TerminateAbility, worker pool thread execute."); + AsyncCallbackInfo *asyncCallbackInfo = static_cast(data); + if (asyncCallbackInfo->ability != nullptr) { + asyncCallbackInfo->ability->TerminateAbility(); + } else { + HILOG_INFO("NAPI_TerminateAbility, ability == nullptr"); + } + HILOG_INFO("NAPI_TerminateAbility, worker pool thread execute end."); + }, + [](napi_env env, napi_status status, void *data) { + HILOG_INFO("NAPI_TerminateAbility, main event thread complete."); + AsyncCallbackInfo *asyncCallbackInfo = static_cast(data); + napi_value result = 0; + napi_get_null(env, &result); + napi_resolve_deferred(env, asyncCallbackInfo->deferred, result); + napi_delete_async_work(env, asyncCallbackInfo->asyncWork); + delete asyncCallbackInfo; + HILOG_INFO("NAPI_TerminateAbility, main event thread complete end."); + }, + (void *)asyncCallbackInfo, + &asyncCallbackInfo->asyncWork); + napi_queue_async_work(env, asyncCallbackInfo->asyncWork); + HILOG_INFO("%{public}s, promise end", __func__); + return promise; +} + +/** + * @brief Checks whether the main window of this ability has window focus. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_HasWindowFocus(napi_env env, napi_callback_info info) +{ + HILOG_INFO("%{public}s,called", __func__); + AsyncCallbackInfo *asyncCallbackInfo = CreateAsyncCallbackInfo(env); + if (asyncCallbackInfo == nullptr) { + HILOG_ERROR("%{public}s,asyncCallbackInfo == nullptr", __func__); + return WrapVoidToJS(env); + } + + napi_value ret = HasWindowFocusWrap(env, info, asyncCallbackInfo); + if (ret == nullptr) { + HILOG_ERROR("%{public}s,ret == nullptr", __func__); + if (asyncCallbackInfo != nullptr) { + delete asyncCallbackInfo; + asyncCallbackInfo = nullptr; + } + ret = WrapVoidToJS(env); + } + HILOG_INFO("%{public}s,end", __func__); + return ret; +} + +/** + * @brief Get context. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_GetContext(napi_env env, napi_callback_info info) +{ + HILOG_INFO("%{public}s called.", __func__); + return NAPI_GetContextCommon(env, info, AbilityType::PAGE); +} + +/** + * @brief HasWindowFocus processing function. + * + * @param env The environment that the Node-API call is invoked under. + * @param asyncCallbackInfo Process data asynchronously. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value HasWindowFocusWrap(napi_env env, napi_callback_info info, AsyncCallbackInfo *asyncCallbackInfo) +{ + HILOG_INFO("%{public}s, asyncCallback.", __func__); + if (asyncCallbackInfo == nullptr) { + HILOG_ERROR("%{public}s, asyncCallbackInfo == nullptr.", __func__); + return nullptr; + } + + size_t argcAsync = 1; + const size_t argcPromise = 0; + const size_t argCountWithAsync = argcPromise + ARGS_ASYNC_COUNT; + napi_value args[ARGS_MAX_COUNT] = {nullptr}; + napi_value ret = 0; + + NAPI_CALL(env, napi_get_cb_info(env, info, &argcAsync, args, nullptr, nullptr)); + if (argcAsync > argCountWithAsync || argcAsync > ARGS_MAX_COUNT) { + HILOG_ERROR("%{public}s, Wrong argument count.", __func__); + return nullptr; + } + + if (argcAsync > argcPromise) { + ret = HasWindowFocusAsync(env, args, 0, asyncCallbackInfo); + } else { + ret = HasWindowFocusPromise(env, asyncCallbackInfo); + } + HILOG_INFO("%{public}s, asyncCallback end.", __func__); + return ret; +} + +napi_value HasWindowFocusAsync( + napi_env env, napi_value *args, const size_t argCallback, AsyncCallbackInfo *asyncCallbackInfo) +{ + HILOG_INFO("%{public}s, asyncCallback.", __func__); + if (args == nullptr || asyncCallbackInfo == nullptr) { + HILOG_ERROR("%{public}s, param == nullptr.", __func__); + return nullptr; + } + napi_value resourceName = 0; + napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName); + + napi_valuetype valuetype = napi_undefined; + napi_typeof(env, args[argCallback], &valuetype); + if (valuetype == napi_function) { + napi_create_reference(env, args[argCallback], 1, &asyncCallbackInfo->cbInfo.callback); + } + napi_create_async_work( + env, + nullptr, + resourceName, + [](napi_env env, void *data) { + HILOG_INFO("NAPI_HasWindowFocus, worker pool thread execute."); + AsyncCallbackInfo *asyncCallbackInfo = static_cast(data); + if (asyncCallbackInfo->ability != nullptr) { + asyncCallbackInfo->native_result = asyncCallbackInfo->ability->HasWindowFocus(); + } else { + HILOG_ERROR("NAPI_HasWindowFocus, ability == nullptr"); + } + HILOG_INFO("NAPI_HasWindowFocus, worker pool thread execute end."); + }, + [](napi_env env, napi_status status, void *data) { + HILOG_INFO("NAPI_HasWindowFocus, main event thread complete."); + AsyncCallbackInfo *asyncCallbackInfo = static_cast(data); + napi_value callback = 0; + napi_value undefined = 0; + napi_value result[ARGS_TWO] = {0}; + napi_value callResult = 0; + napi_get_undefined(env, &undefined); + result[PARAM0] = GetCallbackErrorValue(env, NO_ERROR); + napi_get_boolean(env, asyncCallbackInfo->native_result, &result[PARAM1]); + napi_get_reference_value(env, asyncCallbackInfo->cbInfo.callback, &callback); + napi_call_function(env, undefined, callback, ARGS_TWO, &result[PARAM0], &callResult); + + if (asyncCallbackInfo->cbInfo.callback != nullptr) { + napi_delete_reference(env, asyncCallbackInfo->cbInfo.callback); + } + napi_delete_async_work(env, asyncCallbackInfo->asyncWork); + delete asyncCallbackInfo; + asyncCallbackInfo = nullptr; + HILOG_INFO("NAPI_HasWindowFocus, main event thread complete end."); + }, + (void *)asyncCallbackInfo, + &asyncCallbackInfo->asyncWork); + napi_queue_async_work(env, asyncCallbackInfo->asyncWork); + napi_value result = 0; + napi_get_null(env, &result); + HILOG_INFO("%{public}s, asyncCallback end.", __func__); + return result; +} + +napi_value HasWindowFocusPromise(napi_env env, AsyncCallbackInfo *asyncCallbackInfo) +{ + HILOG_INFO("%{public}s, promise.", __func__); + if (asyncCallbackInfo == nullptr) { + HILOG_ERROR("%{public}s, param == nullptr.", __func__); + return nullptr; + } + napi_value resourceName = 0; + napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName); + napi_deferred deferred; + napi_value promise = 0; + napi_create_promise(env, &deferred, &promise); + asyncCallbackInfo->deferred = deferred; + + napi_create_async_work( + env, + nullptr, + resourceName, + [](napi_env env, void *data) { + HILOG_INFO("NAPI_HasWindowFocus, worker pool thread execute."); + AsyncCallbackInfo *asyncCallbackInfo = static_cast(data); + if (asyncCallbackInfo->ability != nullptr) { + asyncCallbackInfo->native_result = asyncCallbackInfo->ability->HasWindowFocus(); + } else { + HILOG_INFO("NAPI_HasWindowFocus, ability == nullptr"); + } + HILOG_INFO("NAPI_HasWindowFocus, worker pool thread execute end."); + }, + [](napi_env env, napi_status status, void *data) { + HILOG_INFO("NAPI_HasWindowFocus, main event thread complete."); + AsyncCallbackInfo *asyncCallbackInfo = static_cast(data); + napi_value result = 0; + napi_get_boolean(env, asyncCallbackInfo->native_result, &result); + napi_resolve_deferred(env, asyncCallbackInfo->deferred, result); + napi_delete_async_work(env, asyncCallbackInfo->asyncWork); + delete asyncCallbackInfo; + asyncCallbackInfo = nullptr; + HILOG_INFO("NAPI_HasWindowFocus, main event thread complete end."); + }, + (void *)asyncCallbackInfo, + &asyncCallbackInfo->asyncWork); + napi_queue_async_work(env, asyncCallbackInfo->asyncWork); + HILOG_INFO("%{public}s, promise end.", __func__); + return promise; +} + +EXTERN_C_START +/** + * @brief The interface of onAbilityResult provided for ACE to call back to JS. + * + * @param requestCode Indicates the request code returned after the ability is started. + * @param resultCode Indicates the result code returned after the ability is started. + * @param resultData Indicates the data returned after the ability is started. + * @param cb The environment and call back info that the Node-API call is invoked under. + * + * @return The return value from NAPI C++ to JS for the module. + */ +void CallOnAbilityResult(int requestCode, int resultCode, const Want &resultData, CallbackInfo cb) +{ + HILOG_INFO("%{public}s,called", __func__); + uv_loop_s *loop = nullptr; + + napi_get_uv_event_loop(cb.env, &loop); + if (loop == nullptr) { + return; + } + + uv_work_t *work = new (std::nothrow) uv_work_t; + if (work == nullptr) { + HILOG_ERROR("%{public}s, work == nullptr.", __func__); + return; + } + OnAbilityCallback *onAbilityCB = new (std::nothrow) OnAbilityCallback; + if (onAbilityCB == nullptr) { + HILOG_ERROR("%{public}s, onAbilityCB == nullptr.", __func__); + if (work != nullptr) { + delete work; + work = nullptr; + } + return; + } + onAbilityCB->requestCode = requestCode; + onAbilityCB->resultCode = resultCode; + onAbilityCB->resultData = resultData; + onAbilityCB->cb = cb; + + work->data = (void *)onAbilityCB; + + int rev = uv_queue_work( + loop, + work, + [](uv_work_t *work) {}, + [](uv_work_t *work, int status) { + HILOG_INFO("CallOnAbilityResult, uv_queue_work"); + // JS Thread + OnAbilityCallback *onAbilityCB = static_cast(work->data); + napi_value result[ARGS_TWO] = {0}; + result[PARAM0] = GetCallbackErrorValue(onAbilityCB->cb.env, NO_ERROR); + + napi_create_object(onAbilityCB->cb.env, &result[PARAM1]); + // create resultCode + napi_value jsValue = 0; + napi_create_int32(onAbilityCB->cb.env, onAbilityCB->resultCode, &jsValue); + napi_set_named_property(onAbilityCB->cb.env, result[PARAM1], "resultCode", jsValue); + // create want + napi_value jsWant = WrapWant(onAbilityCB->cb.env, onAbilityCB->resultData); + napi_set_named_property(onAbilityCB->cb.env, result[PARAM1], "want", jsWant); + + if (onAbilityCB->cb.callback != nullptr) { + // asynccallback + HILOG_INFO("CallOnAbilityResult, asynccallback"); + napi_value callback = 0; + napi_value undefined = 0; + napi_get_undefined(onAbilityCB->cb.env, &undefined); + napi_value callResult = 0; + napi_get_reference_value(onAbilityCB->cb.env, onAbilityCB->cb.callback, &callback); + + napi_call_function(onAbilityCB->cb.env, undefined, callback, ARGS_TWO, &result[PARAM0], &callResult); + if (onAbilityCB->cb.callback != nullptr) { + napi_delete_reference(onAbilityCB->cb.env, onAbilityCB->cb.callback); + } + HILOG_INFO("CallOnAbilityResult, asynccallback end"); + } else { + // promise + HILOG_INFO("CallOnAbilityResult, promise"); + napi_resolve_deferred(onAbilityCB->cb.env, onAbilityCB->cb.deferred, result[PARAM1]); + HILOG_INFO("CallOnAbilityResult, promise end"); + } + + if (onAbilityCB != nullptr) { + delete onAbilityCB; + onAbilityCB = nullptr; + } + if (work != nullptr) { + delete work; + work = nullptr; + } + HILOG_INFO("CallOnAbilityResult, uv_queue_work end"); + }); + + if (rev != 0) { + if (onAbilityCB != nullptr) { + delete onAbilityCB; + onAbilityCB = nullptr; + } + if (work != nullptr) { + delete work; + work = nullptr; + } + } + HILOG_INFO("%{public}s,end", __func__); +} +EXTERN_C_END + +bool InnerUnwrapWant(napi_env env, napi_value args, Want &want) +{ + HILOG_INFO("%{public}s called", __func__); + napi_valuetype valueType = napi_undefined; + NAPI_CALL_BASE(env, napi_typeof(env, args, &valueType), false); + if (valueType != napi_object) { + HILOG_ERROR("%{public}s wrong argument type", __func__); + return false; + } + + napi_value jsWant = GetPropertyValueByPropertyName(env, args, "want", napi_object); + if (jsWant == nullptr) { + HILOG_ERROR("%{public}s jsWant == nullptr", __func__); + return false; + } + + return UnwrapWant(env, jsWant, want); +} + +/** + * @brief Parse the parameters. + * + * @param param Indicates the parameters saved the parse result. + * @param env The environment that the Node-API call is invoked under. + * @param args Indicates the arguments passed into the callback. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value UnwrapForResultParam(CallAbilityParam ¶m, napi_env env, napi_value args) +{ + HILOG_INFO("%{public}s,called", __func__); + // unwrap the param : want object + InnerUnwrapWant(env, args, param.want); + + // dummy requestCode for NativeC++ interface and onabilityresult callback + param.requestCode = dummyRequestCode_; + param.forResultOption = true; + dummyRequestCode_ = (dummyRequestCode_ < INT64_MAX) ? (dummyRequestCode_ + 1) : 0; + HILOG_INFO("%{public}s, reqCode=%{public}d forResultOption=%{public}d.", + __func__, + param.requestCode, + param.forResultOption); + + // unwrap the param : abilityStartSetting (optional) + napi_value jsSettingObj = GetPropertyValueByPropertyName(env, args, "abilityStartSetting", napi_object); + if (jsSettingObj != nullptr) { + param.setting = AbilityStartSetting::GetEmptySetting(); + if (!UnwrapAbilityStartSetting(env, jsSettingObj, *(param.setting))) { + HILOG_ERROR("%{public}s, unwrap abilityStartSetting falied.", __func__); + } + HILOG_INFO("%{public}s abilityStartSetting = %{public}p.", __func__, param.setting.get()); + } + + napi_value result; + NAPI_CALL(env, napi_create_int32(env, 1, &result)); + HILOG_INFO("%{public}s,end", __func__); + return result; +} + +/** + * @brief Parse the abilityResult parameters. + * + * @param param Indicates the want parameters saved the parse result. + * @param env The environment that the Node-API call is invoked under. + * @param args Indicates the arguments passed into the callback. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value UnwrapAbilityResult(CallAbilityParam ¶m, napi_env env, napi_value args) +{ + HILOG_INFO("%{public}s,called", __func__); + // unwrap the param + napi_valuetype valueType = napi_undefined; + NAPI_CALL(env, napi_typeof(env, args, &valueType)); + NAPI_ASSERT(env, valueType == napi_object, "param type mismatch!"); + // get resultCode property + napi_value property = nullptr; + NAPI_CALL(env, napi_get_named_property(env, args, "resultCode", &property)); + NAPI_CALL(env, napi_typeof(env, property, &valueType)); + NAPI_ASSERT(env, valueType == napi_number, "property type mismatch!"); + NAPI_CALL(env, napi_get_value_int32(env, property, ¶m.requestCode)); + HILOG_INFO("%{public}s, requestCode=%{public}d.", __func__, param.requestCode); + + // unwrap the param : want object + InnerUnwrapWant(env, args, param.want); + + napi_value result; + NAPI_CALL(env, napi_create_int32(env, 1, &result)); + HILOG_INFO("%{public}s,end", __func__); + return result; +} + +/** + * @brief GetWantSyncWrap processing function. + * + * @param env The environment that the Node-API call is invoked under. + * @param CallingBundleCB Process data asynchronously. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value GetWantSyncWrap(napi_env env, napi_callback_info info, AsyncCallbackInfo *asyncCallbackInfo) +{ + HILOG_INFO("%{public}s, called.", __func__); + if (asyncCallbackInfo == nullptr) { + HILOG_ERROR("%{public}s, asyncCallbackInfo == nullptr.", __func__); + return nullptr; + } + + asyncCallbackInfo->errCode = NAPI_ERR_NO_ERROR; + if (asyncCallbackInfo->ability == nullptr) { + HILOG_ERROR("%{public}s, ability == nullptr", __func__); + asyncCallbackInfo->errCode = NAPI_ERR_ACE_ABILITY; + return nullptr; + } + + std::shared_ptr ptrWant = asyncCallbackInfo->ability->GetWant(); + if (ptrWant != nullptr) { + asyncCallbackInfo->param.want = *ptrWant; + } else { + asyncCallbackInfo->errCode = NAPI_ERR_ABILITY_CALL_INVALID; + } + + napi_value result = nullptr; + if (asyncCallbackInfo->errCode == NAPI_ERR_NO_ERROR) { + result = WrapWant(env, asyncCallbackInfo->param.want); + } else { + result = WrapVoidToJS(env); + } + HILOG_INFO("%{public}s, end.", __func__); + return result; +} + +/** + * @brief Get want(Sync). + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_GetWantSync(napi_env env, napi_callback_info info) +{ + HILOG_INFO("%{public}s called.", __func__); + AsyncCallbackInfo *asyncCallbackInfo = CreateAsyncCallbackInfo(env); + if (asyncCallbackInfo == nullptr) { + return WrapVoidToJS(env); + } + + asyncCallbackInfo->errCode = NAPI_ERR_NO_ERROR; + napi_value ret = GetWantSyncWrap(env, info, asyncCallbackInfo); + + delete asyncCallbackInfo; + asyncCallbackInfo = nullptr; + + if (ret == nullptr) { + ret = WrapVoidToJS(env); + HILOG_ERROR("%{public}s ret == nullptr", __func__); + } else { + HILOG_INFO("%{public}s, end.", __func__); + } + return ret; +} + +/** + * @brief Get want. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_GetWant(napi_env env, napi_callback_info info) +{ + HILOG_INFO("%{public}s called.", __func__); + return NAPI_GetWantCommon(env, info, AbilityType::PAGE); +} + +/** + * @brief Obtains the type of this application. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_GetAppType(napi_env env, napi_callback_info info) +{ + HILOG_INFO("%{public}s called.", __func__); + return NAPI_GetAppTypeCommon(env, info, AbilityType::PAGE); +} + +/** + * @brief Obtains the class name in this ability name, without the prefixed bundle name. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_GetAbilityName(napi_env env, napi_callback_info info) +{ + HILOG_INFO("%{public}s called.", __func__); + return NAPI_GetAbilityNameCommon(env, info, AbilityType::PAGE); +} + +/** + * @brief Obtains information about the current ability. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_GetAbilityInfo(napi_env env, napi_callback_info info) +{ + HILOG_INFO("%{public}s called.", __func__); + return NAPI_GetAbilityInfoCommon(env, info, AbilityType::PAGE); +} + +/** + * @brief Obtains the HapModuleInfo object of the application. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_GetHapModuleInfo(napi_env env, napi_callback_info info) +{ + HILOG_INFO("%{public}s called.", __func__); + return NAPI_GetHapModuleInfoCommon(env, info, AbilityType::PAGE); +} + +/** + * @brief FeatureAbility NAPI method : getDataAbilityHelper. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_GetDataAbilityHelper(napi_env env, napi_callback_info info) +{ + HILOG_INFO("%{public}s,called", __func__); + DataAbilityHelperCB *dataAbilityHelperCB = new (std::nothrow) DataAbilityHelperCB; + dataAbilityHelperCB->cbBase.cbInfo.env = env; + if (dataAbilityHelperCB == nullptr) { + HILOG_ERROR("%{public}s, dataAbilityHelperCB == nullptr", __func__); + return WrapVoidToJS(env); + } + napi_value ret = GetDataAbilityHelperWrap(env, info, dataAbilityHelperCB); + if (ret == nullptr) { + HILOG_ERROR("%{public}s, ret == nullptr", __func__); + if (dataAbilityHelperCB != nullptr) { + delete dataAbilityHelperCB; + dataAbilityHelperCB = nullptr; + } + ret = WrapVoidToJS(env); + } + HILOG_INFO("%{public}s,end", __func__); + return ret; +} + +/** + * @brief getDataAbilityHelper processing function. + * + * @param env The environment that the Node-API call is invoked under. + * @param dataAbilityHelperCB Process data asynchronously. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value GetDataAbilityHelperWrap(napi_env env, napi_callback_info info, DataAbilityHelperCB *dataAbilityHelperCB) +{ + HILOG_INFO("%{public}s,called", __func__); + if (dataAbilityHelperCB == nullptr) { + HILOG_ERROR("%{public}s,dataAbilityHelperCB == nullptr", __func__); + return nullptr; + } + + size_t argcAsync = 2; + const size_t argcPromise = 1; + const size_t argCountWithAsync = argcPromise + ARGS_ASYNC_COUNT; + napi_value args[ARGS_MAX_COUNT] = {nullptr}; + napi_value ret = 0; + + NAPI_CALL(env, napi_get_cb_info(env, info, &argcAsync, args, nullptr, nullptr)); + if (argcAsync > argCountWithAsync || argcAsync > ARGS_MAX_COUNT) { + HILOG_ERROR("%{public}s, Wrong argument count.", __func__); + return nullptr; + } + + napi_valuetype valuetype = napi_undefined; + NAPI_CALL(env, napi_typeof(env, args[PARAM0], &valuetype)); + if (valuetype == napi_string) { + NAPI_CALL(env, napi_create_reference(env, args[PARAM0], 1, &dataAbilityHelperCB->uri)); + } + + if (argcAsync > argcPromise) { + ret = GetDataAbilityHelperAsync(env, args, 1, dataAbilityHelperCB); + } else { + ret = GetDataAbilityHelperPromise(env, dataAbilityHelperCB); + } + HILOG_INFO("%{public}s,end", __func__); + return ret; +} + +napi_value GetDataAbilityHelperAsync( + napi_env env, napi_value *args, const size_t argCallback, DataAbilityHelperCB *dataAbilityHelperCB) +{ + HILOG_INFO("%{public}s, asyncCallback.", __func__); + if (args == nullptr || dataAbilityHelperCB == nullptr) { + HILOG_ERROR("%{public}s, param == nullptr.", __func__); + return nullptr; + } + napi_value resourceName = 0; + NAPI_CALL(env, napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName)); + + napi_valuetype valuetype = napi_undefined; + NAPI_CALL(env, napi_typeof(env, args[argCallback], &valuetype)); + if (valuetype == napi_function) { + NAPI_CALL(env, napi_create_reference(env, args[argCallback], 1, &dataAbilityHelperCB->cbBase.cbInfo.callback)); + } + + NAPI_CALL(env, + napi_create_async_work( + env, + nullptr, + resourceName, + [](napi_env env, void *data) { HILOG_INFO("NAPI_GetDataAbilityHelper, worker pool thread execute."); }, + GetDataAbilityHelperAsyncCompleteCB, + (void *)dataAbilityHelperCB, + &dataAbilityHelperCB->cbBase.asyncWork)); + NAPI_CALL(env, napi_queue_async_work(env, dataAbilityHelperCB->cbBase.asyncWork)); + napi_value result = 0; + NAPI_CALL(env, napi_get_null(env, &result)); + HILOG_INFO("%{public}s, asyncCallback end", __func__); + return result; +} + +napi_value GetDataAbilityHelperPromise(napi_env env, DataAbilityHelperCB *dataAbilityHelperCB) +{ + HILOG_INFO("%{public}s, promise.", __func__); + if (dataAbilityHelperCB == nullptr) { + HILOG_ERROR("%{public}s, param == nullptr.", __func__); + return nullptr; + } + napi_value resourceName; + NAPI_CALL(env, napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName)); + napi_deferred deferred; + napi_value promise = 0; + NAPI_CALL(env, napi_create_promise(env, &deferred, &promise)); + dataAbilityHelperCB->cbBase.deferred = deferred; + + NAPI_CALL(env, + napi_create_async_work( + env, + nullptr, + resourceName, + [](napi_env env, void *data) { HILOG_INFO("NAPI_GetDataAbilityHelper, worker pool thread execute."); }, + GetDataAbilityHelperPromiseCompleteCB, + (void *)dataAbilityHelperCB, + &dataAbilityHelperCB->cbBase.asyncWork)); + NAPI_CALL(env, napi_queue_async_work(env, dataAbilityHelperCB->cbBase.asyncWork)); + HILOG_INFO("%{public}s, promise end.", __func__); + return promise; +} + +void GetDataAbilityHelperAsyncCompleteCB(napi_env env, napi_status status, void *data) +{ + HILOG_INFO("NAPI_GetDataAbilityHelper, main event thread complete."); + DataAbilityHelperCB *dataAbilityHelperCB = static_cast(data); + napi_value uri = nullptr; + napi_value callback = nullptr; + napi_value undefined = nullptr; + napi_value result[ARGS_TWO] = {nullptr}; + napi_value callResult = nullptr; + NAPI_CALL_RETURN_VOID(env, napi_get_undefined(env, &undefined)); + NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, dataAbilityHelperCB->uri, &uri)); + NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, dataAbilityHelperCB->cbBase.cbInfo.callback, &callback)); + NAPI_CALL_RETURN_VOID( + env, napi_new_instance(env, GetGlobalDataAbilityHelper(), 1, &uri, &dataAbilityHelperCB->result)); + + result[PARAM0] = GetCallbackErrorValue(env, NO_ERROR); + result[PARAM1] = dataAbilityHelperCB->result; + NAPI_CALL_RETURN_VOID(env, napi_call_function(env, undefined, callback, ARGS_TWO, &result[PARAM0], &callResult)); + + if (dataAbilityHelperCB->cbBase.cbInfo.callback != nullptr) { + NAPI_CALL_RETURN_VOID(env, napi_delete_reference(env, dataAbilityHelperCB->cbBase.cbInfo.callback)); + } + NAPI_CALL_RETURN_VOID(env, napi_delete_async_work(env, dataAbilityHelperCB->cbBase.asyncWork)); + delete dataAbilityHelperCB; + dataAbilityHelperCB = nullptr; + HILOG_INFO("NAPI_GetDataAbilityHelper, main event thread complete end."); +} + +void GetDataAbilityHelperPromiseCompleteCB(napi_env env, napi_status status, void *data) +{ + HILOG_INFO("NAPI_GetDataAbilityHelper, main event thread complete."); + DataAbilityHelperCB *dataAbilityHelperCB = static_cast(data); + napi_value uri = nullptr; + napi_value result = nullptr; + NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, dataAbilityHelperCB->uri, &uri)); + NAPI_CALL_RETURN_VOID( + env, napi_new_instance(env, GetGlobalDataAbilityHelper(), 1, &uri, &dataAbilityHelperCB->result)); + result = dataAbilityHelperCB->result; + + NAPI_CALL_RETURN_VOID(env, napi_resolve_deferred(env, dataAbilityHelperCB->cbBase.deferred, result)); + NAPI_CALL_RETURN_VOID(env, napi_delete_async_work(env, dataAbilityHelperCB->cbBase.asyncWork)); + delete dataAbilityHelperCB; + dataAbilityHelperCB = nullptr; + HILOG_INFO("NAPI_GetDataAbilityHelper, main event thread complete end."); +} + +/** + * @brief FeatureAbility NAPI method : acquireDataAbilityHelper. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_AcquireDataAbilityHelper(napi_env env, napi_callback_info info) +{ + HILOG_INFO("%{public}s,called", __func__); + return NAPI_AcquireDataAbilityHelperCommon(env, info, AbilityType::PAGE); +} + +/** + * @brief FeatureAbility NAPI method : connectAbility. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_FAConnectAbility(napi_env env, napi_callback_info info) +{ + HILOG_INFO("%{public}s called.", __func__); + return NAPI_ConnectAbilityCommon(env, info, AbilityType::PAGE); +} + +/** + * @brief FeatureAbility NAPI method : disConnectAbility. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_FADisConnectAbility(napi_env env, napi_callback_info info) +{ + HILOG_INFO("%{public}s called.", __func__); + return NAPI_DisConnectAbilityCommon(env, info, AbilityType::PAGE); +} + +/** + * @brief FeatureAbility NAPI method : continueAbility. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_FAContinueAbility(napi_env env, napi_callback_info info) +{ + HILOG_INFO("%{public}s,called", __func__); + AsyncCallbackInfo *asyncCallbackInfo = CreateAsyncCallbackInfo(env); + if (asyncCallbackInfo == nullptr) { + HILOG_ERROR("%{public}s, asyncCallbackInfo == nullptr.", __func__); + return WrapVoidToJS(env); + } + + napi_value ret = ContinueAbilityWrap(env, info, asyncCallbackInfo); + if (ret == nullptr) { + if (asyncCallbackInfo != nullptr) { + delete asyncCallbackInfo; + asyncCallbackInfo = nullptr; + } + ret = WrapVoidToJS(env); + } + HILOG_INFO("%{public}s,end.", __func__); + return ret; +} + +/** + * @brief ContinueAbilityWrap processing function. + * + * @param env The environment that the Node-API call is invoked under. + * @param asyncCallbackInfo Process data asynchronously. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value ContinueAbilityWrap(napi_env env, napi_callback_info info, AsyncCallbackInfo *asyncCallbackInfo) +{ + HILOG_INFO("%{public}s, called.", __func__); + size_t argc = 2; + napi_value args[ARGS_MAX_COUNT] = {nullptr}; + napi_value ret = 0; + napi_valuetype valueType = napi_undefined; + + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, nullptr, nullptr)); + NAPI_CALL(env, napi_typeof(env, args[0], &valueType)); + NAPI_ASSERT(env, + (valueType == napi_object || valueType == napi_function), + "Wrong argument type. Object or function expected."); + if (0 == argc) { + ret = ContinueAbilityPromise(env, args, asyncCallbackInfo, argc); + } else if (PARA_SIZE_IS_ONE == argc) { + if (valueType == napi_function) { + ret = ContinueAbilityAsync(env, args, asyncCallbackInfo, argc); + } else { + ret = ContinueAbilityPromise(env, args, asyncCallbackInfo, argc); + } + } else if (PARA_SIZE_IS_TWO == argc) { + ret = ContinueAbilityAsync(env, args, asyncCallbackInfo, argc); + } else { + HILOG_ERROR("%{public}s, Wrong argument count.", __func__); + } + HILOG_INFO("%{public}s,end.", __func__); + return ret; +} + +napi_value ContinueAbilityAsync(napi_env env, napi_value *args, AsyncCallbackInfo *asyncCallbackInfo, size_t argc) +{ + HILOG_INFO("%{public}s, asyncCallback.", __func__); + if (args == nullptr || asyncCallbackInfo == nullptr) { + HILOG_ERROR("%{public}s, param == nullptr.", __func__); + return nullptr; + } + napi_value resourceName = 0; + napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName); + + if (PARA_SIZE_IS_TWO == argc) { + // args[0] : ContinueAbilityOptions + napi_valuetype valueTypeOptions = napi_undefined; + NAPI_CALL(env, napi_typeof(env, args[0], &valueTypeOptions)); + NAPI_ASSERT(env, valueTypeOptions == napi_object, "Wrong argument type. Object expected."); + if (GetContinueAbilityOptionsInfoCommon(env, args[0], asyncCallbackInfo->optionInfo) == nullptr) { + HILOG_ERROR("%{public}s, GetContinueAbilityOptionsInfoCommonFail", __func__); + return nullptr; + } + + // args[1] : callback + napi_valuetype valueTypeCallBack = napi_undefined; + napi_typeof(env, args[1], &valueTypeCallBack); + if (valueTypeCallBack == napi_function) { + napi_create_reference(env, args[1], 1, &asyncCallbackInfo->cbInfo.callback); + } + } else { + // args[0] : callback + napi_valuetype valueTypeCallBack = napi_undefined; + napi_typeof(env, args[1], &valueTypeCallBack); + if (valueTypeCallBack == napi_function) { + napi_create_reference(env, args[0], 1, &asyncCallbackInfo->cbInfo.callback); + } + } + + napi_create_async_work( + env, + nullptr, + resourceName, + [](napi_env env, void *data) { + HILOG_INFO("NAPI_ContinueAbility, worker pool thread execute."); + AsyncCallbackInfo *asyncCallbackInfo = (AsyncCallbackInfo *)data; + if (asyncCallbackInfo->ability != nullptr) { + asyncCallbackInfo->ability->ContinueAbility(asyncCallbackInfo->optionInfo.deviceId); + } else { + HILOG_ERROR("NAPI_ContinueAbilityForResult, asyncCallbackInfo == nullptr"); + } + HILOG_INFO("NAPI_ContinueAbilityForResult, worker pool thread execute end."); + }, + [](napi_env env, napi_status status, void *data) { + HILOG_INFO("NAPI_ContinueAbility, main event thread complete."); + AsyncCallbackInfo *asyncCallbackInfo = (AsyncCallbackInfo *)data; + napi_value callback = 0; + napi_value undefined = 0; + napi_value result[ARGS_TWO] = {0}; + napi_value callResult = 0; + napi_get_undefined(env, &undefined); + result[PARAM0] = GetCallbackErrorValue(env, NO_ERROR); + napi_get_null(env, &result[PARAM1]); + napi_get_reference_value(env, asyncCallbackInfo->cbInfo.callback, &callback); + napi_call_function(env, undefined, callback, ARGS_TWO, &result[PARAM0], &callResult); + + if (asyncCallbackInfo->cbInfo.callback != nullptr) { + napi_delete_reference(env, asyncCallbackInfo->cbInfo.callback); + } + napi_delete_async_work(env, asyncCallbackInfo->asyncWork); + delete asyncCallbackInfo; + HILOG_INFO("NAPI_ContinueAbilityForResult, main event thread complete end."); + }, + (void *)asyncCallbackInfo, + &asyncCallbackInfo->asyncWork); + napi_queue_async_work(env, asyncCallbackInfo->asyncWork); + napi_value result = 0; + napi_get_null(env, &result); + HILOG_INFO("%{public}s, asyncCallback end.", __func__); + return result; +} + +napi_value ContinueAbilityPromise(napi_env env, napi_value *args, AsyncCallbackInfo *asyncCallbackInfo, size_t argc) +{ + HILOG_INFO("%{public}s, promise.", __func__); + if (asyncCallbackInfo == nullptr) { + HILOG_ERROR("%{public}s, param == nullptr.", __func__); + return nullptr; + } + + if (argc == PARA_SIZE_IS_ONE) { + // args[0] : ContinueAbilityOptions + napi_valuetype valueTypeOptions = napi_undefined; + NAPI_CALL(env, napi_typeof(env, args[0], &valueTypeOptions)); + NAPI_ASSERT(env, valueTypeOptions == napi_object, "Wrong argument type. Object expected."); + if (GetContinueAbilityOptionsInfoCommon(env, args[0], asyncCallbackInfo->optionInfo) == nullptr) { + return nullptr; + } + } + + napi_value resourceName = 0; + napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName); + napi_deferred deferred; + napi_value promise = 0; + napi_create_promise(env, &deferred, &promise); + + asyncCallbackInfo->deferred = deferred; + + napi_create_async_work( + env, + nullptr, + resourceName, + [](napi_env env, void *data) { + HILOG_INFO("NAPI_ContinueAbility, worker pool thread execute."); + AsyncCallbackInfo *asyncCallbackInfo = (AsyncCallbackInfo *)data; + if (asyncCallbackInfo->ability != nullptr) { + asyncCallbackInfo->ability->ContinueAbility(asyncCallbackInfo->optionInfo.deviceId); + } else { + HILOG_ERROR("NAPI_ContinueAbilityForResult, asyncCallbackInfo == nullptr"); + } + HILOG_INFO("NAPI_ContinueAbilityForResult, worker pool thread execute end."); + }, + [](napi_env env, napi_status status, void *data) { + HILOG_INFO("NAPI_ContinueAbility, main event thread complete."); + AsyncCallbackInfo *asyncCallbackInfo = (AsyncCallbackInfo *)data; + napi_value result = 0; + napi_get_null(env, &result); + napi_resolve_deferred(env, asyncCallbackInfo->deferred, result); + napi_delete_async_work(env, asyncCallbackInfo->asyncWork); + delete asyncCallbackInfo; + HILOG_INFO("NAPI_ContinueAbilityForResult, main event thread complete end."); + }, + (void *)asyncCallbackInfo, + &asyncCallbackInfo->asyncWork); + napi_queue_async_work(env, asyncCallbackInfo->asyncWork); + HILOG_INFO("%{public}s, promise end.", __func__); + return promise; +} +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/interfaces/kits/napi/aafwk/featureAbility/feature_ability.h b/tools/interfaces/kits/napi/aafwk/featureAbility/feature_ability.h new file mode 100755 index 00000000000..4752cb6e6e6 --- /dev/null +++ b/tools/interfaces/kits/napi/aafwk/featureAbility/feature_ability.h @@ -0,0 +1,361 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_APPEXECFWK_FEATURE_ABILITY_H +#define OHOS_APPEXECFWK_FEATURE_ABILITY_H +#include "../inner/napi_common/feature_ability_common.h" +using Want = OHOS::AAFwk::Want; + +namespace OHOS { +namespace AppExecFwk { +/** + * @brief FeatureAbility NAPI module registration. + * + * @param env The environment that the Node-API call is invoked under. + * @param exports An empty object via the exports parameter as a convenience. + * + * @return The return value from Init is treated as the exports object for the module. + */ +napi_value FeatureAbilityInit(napi_env env, napi_value exports); + +EXTERN_C_START +/** + * @brief The interface of onAbilityResult provided for ACE to call back to JS. + * + * @param requestCode Indicates the request code returned after the ability is started. + * @param resultCode Indicates the result code returned after the ability is started. + * @param resultData Indicates the data returned after the ability is started. + * @param callbackInfo The environment and call back info that the Node-API call is invoked under. + * + * @return The return value from NAPI C++ to JS for the module. + */ +void CallOnAbilityResult(int requestCode, int resultCode, const Want &resultData, CallbackInfo callbackInfo); +EXTERN_C_END + +/** + * @brief FeatureAbility NAPI method : startAbility. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_StartAbility(napi_env env, napi_callback_info info); + +/** + * @brief FeatureAbility NAPI method : startAbilityForResult. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_StartAbilityForResult(napi_env env, napi_callback_info info); + +/** + * @brief FeatureAbility NAPI method : setResult. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_SetResult(napi_env env, napi_callback_info info); + +/** + * @brief FeatureAbility NAPI method : terminateAbility. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_TerminateAbility(napi_env env, napi_callback_info info); + +/** + * @brief Checks whether the main window of this ability has window focus. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_HasWindowFocus(napi_env env, napi_callback_info info); + +/** + * @brief Get context. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_GetContext(napi_env env, napi_callback_info info); + +/** + * @brief Get want. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_GetWant(napi_env env, napi_callback_info info); + +/** + * @brief Get want(sync). + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_GetWantSync(napi_env env, napi_callback_info info); + +/** + * @brief Obtains the type of this application. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_GetAppType(napi_env env, napi_callback_info info); + +/** + * @brief Obtains the class name in this ability name, without the prefixed bundle name. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_GetAbilityName(napi_env env, napi_callback_info info); + +/** + * @brief Obtains information about the current ability. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_GetAbilityInfo(napi_env env, napi_callback_info info); + +/** + * @brief FeatureAbility NAPI method : getDataAbilityHelper. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_GetDataAbilityHelper(napi_env env, napi_callback_info info); + +/** + * @brief FeatureAbility NAPI method : acquireDataAbilityHelper. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_AcquireDataAbilityHelper(napi_env env, napi_callback_info info); + +/** + * @brief Parse the parameters. + * + * @param param Indicates the parameters saved the parse result. + * @param env The environment that the Node-API call is invoked under. + * @param args Indicates the arguments passed into the callback. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value UnwrapForResultParam(CallAbilityParam ¶m, napi_env env, napi_value args); + +/** + * @brief Parse the abilityResult parameters. + * + * @param param Indicates the abilityResult parameters saved the parse result. + * @param env The environment that the Node-API call is invoked under. + * @param args Indicates the arguments passed into the callback. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value UnwrapAbilityResult(CallAbilityParam ¶m, napi_env env, napi_value args); + +/** + * @brief Create asynchronous data. + * + * @param env The environment that the Node-API call is invoked under. + * + * @return Return a pointer to AppInfoCB on success, nullptr on failure. + */ +AppInfoCB *CreateAppInfoCBInfo(napi_env env); + +/** + * @brief HasWindowFocus processing function. + * + * @param env The environment that the Node-API call is invoked under. + * @param asyncCallbackInfo Process data asynchronously. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value HasWindowFocusWrap(napi_env env, napi_callback_info info, AsyncCallbackInfo *asyncCallbackInfo); +napi_value HasWindowFocusAsync( + napi_env env, napi_value *args, const size_t argCallback, AsyncCallbackInfo *asyncCallbackInfo); +napi_value HasWindowFocusPromise(napi_env env, AsyncCallbackInfo *asyncCallbackInfo); + +/** + * @brief TerminateAbility processing function. + * + * @param env The environment that the Node-API call is invoked under. + * @param asyncCallbackInfo Process data asynchronously. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value TerminateAbilityWrap(napi_env env, napi_callback_info info, AsyncCallbackInfo *asyncCallbackInfo); +napi_value TerminateAbilityAsync( + napi_env env, napi_value *args, const size_t argCallback, AsyncCallbackInfo *asyncCallbackInfo); +napi_value TerminateAbilityPromise(napi_env env, AsyncCallbackInfo *asyncCallbackInfo); + +/** + * @brief SetResult processing function. + * + * @param env The environment that the Node-API call is invoked under. + * @param asyncCallbackInfo Process data asynchronously. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value SetResultWrap(napi_env env, napi_callback_info info, AsyncCallbackInfo *asyncCallbackInfo); +napi_value SetResultAsync( + napi_env env, napi_value *args, const size_t argCallback, AsyncCallbackInfo *asyncCallbackInfo); +napi_value SetResultPromise(napi_env env, AsyncCallbackInfo *asyncCallbackInfo); + +/** + * @brief StartAbilityForResult processing function. + * + * @param env The environment that the Node-API call is invoked under. + * @param asyncCallbackInfo Process data asynchronously. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value StartAbilityForResultWrap(napi_env env, napi_callback_info info, AsyncCallbackInfo *asyncCallbackInfo); +napi_value StartAbilityForResultAsync(napi_env env, AsyncCallbackInfo *asyncCallbackInfo); +napi_value StartAbilityForResultPromise(napi_env env, AsyncCallbackInfo *asyncCallbackInfo); + +/** + * @brief TerminateAbility processing function. + * + * @param env The environment that the Node-API call is invoked under. + * @param asyncCallbackInfo Process data asynchronously. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value ContinueAbilityWrap(napi_env env, napi_callback_info info, AsyncCallbackInfo *asyncCallbackInfo); +napi_value ContinueAbilityAsync(napi_env env, napi_value *args, AsyncCallbackInfo *asyncCallbackInfo, size_t argc); +napi_value ContinueAbilityPromise(napi_env env, napi_value *args, AsyncCallbackInfo *asyncCallbackInfo, size_t argc); + +/** + * @brief Obtains the HapModuleInfo object of the application. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_GetHapModuleInfo(napi_env env, napi_callback_info info); + +/** + * @brief getDataAbilityHelper processing function. + * + * @param env The environment that the Node-API call is invoked under. + * @param dataAbilityHelperCB Process data asynchronously. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value GetDataAbilityHelperWrap(napi_env env, napi_callback_info info, DataAbilityHelperCB *dataAbilityHelperCB); + +/** + * @brief GetDataAbilityHelper Async. + * + * @param env The environment that the Node-API call is invoked under. + * @param args Indicates the arguments passed into the callback. + * @param argcPromise Asynchronous data processing. + * @param dataAbilityHelperCB Process data asynchronously. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value GetDataAbilityHelperAsync( + napi_env env, napi_value *args, const size_t argCallback, DataAbilityHelperCB *dataAbilityHelperCB); + +/** + * @brief GetDataAbilityHelper Promise. + * + * @param env The environment that the Node-API call is invoked under. + * @param dataAbilityHelperCB Process data asynchronously. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value GetDataAbilityHelperPromise(napi_env env, DataAbilityHelperCB *dataAbilityHelperCB); + +/** + * @brief The callback at the end of the asynchronous callback. + * + * @param env The environment that the Node-API call is invoked under. + * @param data Point to asynchronous processing of data. + */ +void GetDataAbilityHelperAsyncCompleteCB(napi_env env, napi_status status, void *data); + +/** + * @brief The callback at the end of the Promise callback. + * + * @param env The environment that the Node-API call is invoked under. + * @param data Point to asynchronous processing of data. + */ +void GetDataAbilityHelperPromiseCompleteCB(napi_env env, napi_status status, void *data); + +/** + * @brief FeatureAbility NAPI method : connectAbility. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_FAConnectAbility(napi_env env, napi_callback_info info); + +/** + * @brief FeatureAbility NAPI method : disconnectAbility. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_FADisConnectAbility(napi_env env, napi_callback_info info); + +/** + * @brief FeatureAbility NAPI method : continueAbility. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_FAContinueAbility(napi_env env, napi_callback_info info); +} // namespace AppExecFwk +} // namespace OHOS +#endif /* OHOS_APPEXECFWK_FEATURE_ABILITY_H */ diff --git a/tools/interfaces/kits/napi/aafwk/featureAbility/feature_ability_constant.cpp b/tools/interfaces/kits/napi/aafwk/featureAbility/feature_ability_constant.cpp new file mode 100644 index 00000000000..12859241055 --- /dev/null +++ b/tools/interfaces/kits/napi/aafwk/featureAbility/feature_ability_constant.cpp @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "feature_ability_constant.h" +#include +#include +#include "securec.h" +#include "hilog_wrapper.h" + +namespace OHOS { +namespace AppExecFwk { +/** + * @brief FeatureAbilityConstantInit NAPI module registration. + * + * @param env The environment that the Node-API call is invoked under. + * @param exports An empty object via the exports parameter as a convenience. + * + * @return The return value from Init is treated as the exports object for the module. + */ +napi_value FAConstantInit(napi_env env, napi_value exports) +{ + const int Window_Configuration_Zero = 100; + const int Window_Configuration_One = 101; + const int Window_Configuration_Two = 102; + HILOG_INFO("%{public}s,called", __func__); + napi_value abilityStartSetting = nullptr; + napi_value abilityWindowConfiguration = nullptr; + napi_create_object(env, &abilityStartSetting); + napi_create_object(env, &abilityWindowConfiguration); + + SetNamedProperty(env, abilityStartSetting, "abilityBounds", "BOUNDS_KEY"); + SetNamedProperty(env, abilityStartSetting, "windowMode", "WINDOW_MODE_KEY"); + SetNamedProperty(env, abilityStartSetting, "displayId", "DISPLAY_ID_KEY"); + + SetNamedProperty(env, abilityWindowConfiguration, 0, "WINDOW_MODE_UNDEFINED"); + SetNamedProperty(env, abilityWindowConfiguration, 1, "WINDOW_MODE_FULLSCREEN"); + SetNamedProperty(env, abilityWindowConfiguration, Window_Configuration_Zero, "WINDOW_MODE_SPLIT_PRIMARY"); + SetNamedProperty(env, abilityWindowConfiguration, Window_Configuration_One, "WINDOW_MODE_SPLIT_SECONDARY"); + SetNamedProperty(env, abilityWindowConfiguration, Window_Configuration_Two, "WINDOW_MODE_FLOATING"); + + napi_property_descriptor exportFuncs[] = { + DECLARE_NAPI_PROPERTY("AbilityStartSetting", abilityStartSetting), + DECLARE_NAPI_PROPERTY("AbilityWindowConfiguration", abilityWindowConfiguration), + }; + napi_define_properties(env, exports, sizeof(exportFuncs) / sizeof(*exportFuncs), exportFuncs); + + return exports; +} + +void SetNamedProperty(napi_env env, napi_value dstObj, const char *objName, const char *propName) +{ + napi_value prop = nullptr; + napi_create_string_utf8(env, objName, NAPI_AUTO_LENGTH, &prop); + napi_set_named_property(env, dstObj, propName, prop); +} + +void SetNamedProperty(napi_env env, napi_value dstObj, const int32_t objValue, const char *propName) +{ + napi_value prop = nullptr; + napi_create_int32(env, objValue, &prop); + napi_set_named_property(env, dstObj, propName, prop); +} + +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/interfaces/kits/napi/aafwk/featureAbility/feature_ability_constant.h b/tools/interfaces/kits/napi/aafwk/featureAbility/feature_ability_constant.h new file mode 100644 index 00000000000..a2eb59c82b3 --- /dev/null +++ b/tools/interfaces/kits/napi/aafwk/featureAbility/feature_ability_constant.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_APPEXECFWK_FEATURE_ABILITY_CONSTANT_H +#define OHOS_APPEXECFWK_FEATURE_ABILITY_CONSTANT_H +#include "napi/native_common.h" +#include "napi/native_node_api.h" + +namespace OHOS { +namespace AppExecFwk { +/** + * @brief FeatureAbilityConstantInit NAPI module registration. + * + * @param env The environment that the Node-API call is invoked under. + * @param exports An empty object via the exports parameter as a convenience. + * + * @return The return value from Init is treated as the exports object for the module. + */ +napi_value FAConstantInit(napi_env env, napi_value exports); +void SetNamedProperty(napi_env env, napi_value dstObj, const char *objName, const char *propName); +void SetNamedProperty(napi_env env, napi_value dstObj, const int32_t objValue, const char *propName); +} // namespace AppExecFwk +} // namespace OHOS +#endif /* OHOS_APPEXECFWK_FEATURE_ABILITY_CONSTANT_H */ diff --git a/tools/interfaces/kits/napi/aafwk/featureAbility/napi_context.cpp b/tools/interfaces/kits/napi/aafwk/featureAbility/napi_context.cpp new file mode 100755 index 00000000000..fa595d3fd55 --- /dev/null +++ b/tools/interfaces/kits/napi/aafwk/featureAbility/napi_context.cpp @@ -0,0 +1,2962 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include +#include "securec.h" +#include "napi_context.h" +#include "hilog_wrapper.h" +#include "ability_process.h" +#include "feature_ability_common.h" +#include "../inner/napi_common/napi_common_ability.h" +#include "file_ex.h" +#include "directory_ex.h" + +using namespace OHOS::AAFwk; +using namespace OHOS::AppExecFwk; + +namespace OHOS { +namespace AppExecFwk { +const std::string NAPI_CONTEXT_FILE_SEPARATOR = std::string("/"); +const std::string NAPI_CONTEXT_DATABASE = std::string("database"); +const std::string NAPI_CONTEXT_PREFERENCES = std::string("preferences"); +CallbackInfo aceCallbackInfoPermission; + +napi_value ContextConstructor(napi_env env, napi_callback_info info) +{ + napi_value jsthis = nullptr; + NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &jsthis, nullptr)); + return jsthis; +} + +bool UnwrapParamVerifySelfPermission( + napi_env env, size_t argc, napi_value *argv, AsyncJSCallbackInfo *asyncCallbackInfo) +{ + HILOG_INFO("%{public}s called, argc=%{public}zu", __func__, argc); + + const size_t argcMax = 2; + if (argc > argcMax || argc < argcMax - 1) { + HILOG_INFO("%{public}s called, Params is invalid.", __func__); + return false; + } + + if (argc == argcMax) { + if (!CreateAsyncCallback(env, argv[PARAM1], asyncCallbackInfo)) { + HILOG_INFO("%{public}s called, the second parameter is invalid.", __func__); + return false; + } + } + + std::string permission(""); + if (!UnwrapStringFromJS2(env, argv[PARAM0], permission)) { + HILOG_INFO("%{public}s called, the first parameter is invalid.", __func__); + return false; + } + + asyncCallbackInfo->param.paramArgs.PutStringValue("permission", permission); + return true; +} + +void VerifySelfPermissionExecuteCallbackWork(napi_env env, void *data) +{ + HILOG_INFO("%{public}s called.", __func__); + + AsyncJSCallbackInfo *asyncCallbackInfo = static_cast(data); + if (asyncCallbackInfo == nullptr) { + HILOG_INFO("%{public}s called. asyncCallbackInfo is null", __func__); + return; + } + + asyncCallbackInfo->error_code = NAPI_ERR_NO_ERROR; + asyncCallbackInfo->native_data.data_type = NVT_NONE; + + if (asyncCallbackInfo->ability == nullptr) { + asyncCallbackInfo->error_code = NAPI_ERR_ACE_ABILITY; + return; + } + + asyncCallbackInfo->native_data.data_type = NVT_INT32; + asyncCallbackInfo->native_data.int32_value = asyncCallbackInfo->ability->VerifySelfPermission( + asyncCallbackInfo->param.paramArgs.GetStringValue("permission")); +} + +/** + * @brief VerifySelfPermission processing function. + * + * @param env The environment that the Node-API call is invoked under. + * @param asyncCallbackInfo Process data asynchronously. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value NAPI_VerifySelfPermissionWrap(napi_env env, napi_callback_info info, AsyncJSCallbackInfo *asyncCallbackInfo) +{ + HILOG_INFO("%{public}s called.", __func__); + size_t argc = ARGS_MAX_COUNT; + napi_value args[ARGS_MAX_COUNT] = {nullptr}; + napi_value jsthis = 0; + void *data = nullptr; + + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, &jsthis, &data)); + + if (!UnwrapParamVerifySelfPermission(env, argc, args, asyncCallbackInfo)) { + HILOG_INFO("%{public}s called. Invoke UnwrapParamVerifySelfPermission fail", __func__); + return nullptr; + } + + AsyncParamEx asyncParamEx; + if (asyncCallbackInfo->cbInfo.callback != nullptr) { + HILOG_INFO("%{public}s called. asyncCallback.", __func__); + asyncParamEx.resource = "NAPI_VerifySelfPermissionCallback"; + asyncParamEx.execute = VerifySelfPermissionExecuteCallbackWork; + asyncParamEx.complete = CompleteAsyncCallbackWork; + + return ExecuteAsyncCallbackWork(env, asyncCallbackInfo, &asyncParamEx); + } else { + HILOG_INFO("%{public}s called. promise.", __func__); + asyncParamEx.resource = "NAPI_VerifySelfPermissionPromise"; + asyncParamEx.execute = VerifySelfPermissionExecuteCallbackWork; + asyncParamEx.complete = CompletePromiseCallbackWork; + + return ExecutePromiseCallbackWork(env, asyncCallbackInfo, &asyncParamEx); + } +} + +/** + * @brief Checks whether the current process has the given permission. + * You need to call requestPermissionsFromUser(java.lang.std::string[],int) to request a permission only + * if the current process does not have the specific permission. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return Returns 0 (IBundleManager.PERMISSION_GRANTED) if the current process has the permission; + * returns -1 (IBundleManager.PERMISSION_DENIED) otherwise. + */ +napi_value NAPI_VerifySelfPermission(napi_env env, napi_callback_info info) +{ + HILOG_INFO("%{public}s called.", __func__); + + AsyncJSCallbackInfo *asyncCallbackInfo = CreateAsyncJSCallbackInfo(env); + if (asyncCallbackInfo == nullptr) { + return nullptr; + } + + napi_value rev = NAPI_VerifySelfPermissionWrap(env, info, asyncCallbackInfo); + if (rev == nullptr) { + FreeAsyncJSCallbackInfo(&asyncCallbackInfo); + rev = WrapVoidToJS(env); + } + return rev; +} + +bool UnwrapRequestPermissionsFromUser( + napi_env env, size_t argc, napi_value *argv, AsyncJSCallbackInfo *asyncCallbackInfo) +{ + HILOG_INFO("%{public}s called, argc=%{public}zu", __func__, argc); + + const size_t argcMax = 3; + if (argc != argcMax) { + HILOG_INFO("%{public}s called, parameters is invalid", __func__); + return false; + } + + aceCallbackInfoPermission.env = env; + napi_valuetype valuetype = napi_undefined; + NAPI_CALL_BASE(env, napi_typeof(env, argv[PARAM2], &valuetype), false); + if (valuetype != napi_function) { + HILOG_INFO("%{public}s called, parameters is invalid", __func__); + return false; + } + NAPI_CALL_BASE(env, napi_create_reference(env, argv[PARAM2], 1, &aceCallbackInfoPermission.callback), false); + + std::vector permissionList; + if (!UnwrapArrayStringFromJS(env, argv[PARAM0], permissionList)) { + HILOG_INFO("%{public}s called, the first parameter is invalid.", __func__); + return false; + } + + int requestCode = 0; + if (!UnwrapInt32FromJS2(env, argv[PARAM1], requestCode)) { + HILOG_INFO("%{public}s called, the second parameter is invalid.", __func__); + return false; + } + + asyncCallbackInfo->param.paramArgs.PutIntValue("requestCode", requestCode); + asyncCallbackInfo->param.paramArgs.PutStringValueArray("permissionList", permissionList); + return true; +} + +void RequestPermissionsFromUserExecuteCallbackWork(napi_env env, void *data) +{ + HILOG_INFO("%{public}s called.", __func__); + AsyncJSCallbackInfo *asyncCallbackInfo = static_cast(data); + if (asyncCallbackInfo == nullptr) { + HILOG_INFO("%{public}s called. asyncCallbackInfo is null", __func__); + return; + } + + asyncCallbackInfo->error_code = NAPI_ERR_NO_ERROR; + asyncCallbackInfo->native_data.data_type = NVT_NONE; + if (asyncCallbackInfo->ability == nullptr) { + asyncCallbackInfo->error_code = NAPI_ERR_ACE_ABILITY; + return; + } + + CallAbilityPermissionParam permissionParam; + permissionParam.requestCode = asyncCallbackInfo->param.paramArgs.GetIntValue("requestCode"); + asyncCallbackInfo->param.paramArgs.GetStringValueArray("permissionList", permissionParam.permission_list); + if (permissionParam.permission_list.size() == 0) { + asyncCallbackInfo->error_code = NAPI_ERR_PARAM_INVALID; + return; + } + + AbilityProcess::GetInstance()->RequestPermissionsFromUser( + asyncCallbackInfo->ability, permissionParam, *asyncCallbackInfo->aceCallback); + asyncCallbackInfo->native_data.data_type = NVT_INT32; + asyncCallbackInfo->native_data.int32_value = 1; +} + +void RequestPermissionsFromUserExecutePromiseWork(napi_env env, void *data) +{ + HILOG_INFO("%{public}s called.", __func__); + AsyncJSCallbackInfo *asyncCallbackInfo = static_cast(data); + if (asyncCallbackInfo == nullptr) { + HILOG_INFO("%{public}s called. asyncCallbackInfo is null", __func__); + return; + } + + asyncCallbackInfo->error_code = NAPI_ERR_NO_ERROR; + asyncCallbackInfo->native_data.data_type = NVT_NONE; + if (asyncCallbackInfo->ability == nullptr) { + asyncCallbackInfo->error_code = NAPI_ERR_ACE_ABILITY; + return; + } + + CallAbilityPermissionParam permissionParam; + permissionParam.requestCode = asyncCallbackInfo->param.paramArgs.GetIntValue("requestCode"); + asyncCallbackInfo->param.paramArgs.GetStringValueArray("permissionList", permissionParam.permission_list); + if (permissionParam.permission_list.size() == 0) { + asyncCallbackInfo->error_code = NAPI_ERR_PARAM_INVALID; + return; + } + + AbilityProcess::GetInstance()->RequestPermissionsFromUser( + asyncCallbackInfo->ability, permissionParam, *asyncCallbackInfo->aceCallback); +} + +void RequestPermissionsFromUserCompleteAsyncCallbackWork(napi_env env, napi_status status, void *data) +{ + HILOG_INFO("%{public}s called.", __func__); + + AsyncJSCallbackInfo *asyncCallbackInfo = static_cast(data); + if (asyncCallbackInfo == nullptr) { + HILOG_INFO("%{public}s called, asyncCallbackInfo is null", __func__); + return; + } + + if (asyncCallbackInfo->error_code != NAPI_ERR_NO_ERROR && asyncCallbackInfo->aceCallback != nullptr) { + napi_value callback = 0; + napi_value undefined = 0; + napi_get_undefined(env, &undefined); + napi_value callResult = 0; + napi_value revParam[ARGS_TWO] = {nullptr}; + + revParam[PARAM0] = GetCallbackErrorValue(env, asyncCallbackInfo->error_code); + revParam[PARAM1] = WrapVoidToJS(env); + + if (asyncCallbackInfo->aceCallback->callback != nullptr) { + napi_get_reference_value(env, asyncCallbackInfo->aceCallback->callback, &callback); + napi_call_function(env, undefined, callback, ARGS_TWO, revParam, &callResult); + napi_delete_reference(env, asyncCallbackInfo->aceCallback->callback); + + asyncCallbackInfo->aceCallback->callback = nullptr; + asyncCallbackInfo->aceCallback->env = nullptr; + } + } + + napi_delete_async_work(env, asyncCallbackInfo->asyncWork); + delete asyncCallbackInfo; + asyncCallbackInfo = nullptr; +} + +/** + * @brief RequestPermissionsFromUser processing function. + * + * @param env The environment that the Node-API call is invoked under. + * @param asyncCallbackInfo Process data asynchronously. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value NAPI_RequestPermissionsFromUserWrap( + napi_env env, napi_callback_info info, AsyncJSCallbackInfo *asyncCallbackInfo) +{ + HILOG_INFO("%{public}s called.", __func__); + size_t argc = ARGS_MAX_COUNT; + napi_value args[ARGS_MAX_COUNT] = {nullptr}; + napi_value jsthis = 0; + void *data = nullptr; + + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, &jsthis, &data)); + + if (!UnwrapRequestPermissionsFromUser(env, argc, args, asyncCallbackInfo)) { + HILOG_INFO("%{public}s called. Invoke UnwrapRequestPermissionsFromUser failed.", __func__); + return nullptr; + } + + asyncCallbackInfo->aceCallback = &aceCallbackInfoPermission; + AsyncParamEx asyncParamEx; + asyncParamEx.resource = "NAPI_RequestPermissionsFromUserCallback"; + asyncParamEx.execute = RequestPermissionsFromUserExecuteCallbackWork; + asyncParamEx.complete = RequestPermissionsFromUserCompleteAsyncCallbackWork; + + return ExecuteAsyncCallbackWork(env, asyncCallbackInfo, &asyncParamEx); +} + +/** + * @brief Requests certain permissions from the system. + * This method is called for permission request. This is an asynchronous method. When it is executed, + * the Ability.onRequestPermissionsFromUserResult(int, String[], int[]) method will be called back. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + */ +napi_value NAPI_RequestPermissionsFromUser(napi_env env, napi_callback_info info) +{ + HILOG_INFO("%{public}s called.", __func__); + + AsyncJSCallbackInfo *asyncCallbackInfo = CreateAsyncJSCallbackInfo(env); + if (asyncCallbackInfo == nullptr) { + HILOG_INFO("%{public}s called. Invoke CreateAsyncJSCallbackInfo failed.", __func__); + return WrapVoidToJS(env); + } + + napi_value rev = NAPI_RequestPermissionsFromUserWrap(env, info, asyncCallbackInfo); + if (rev == nullptr) { + if (aceCallbackInfoPermission.callback != nullptr && aceCallbackInfoPermission.env != nullptr) { + napi_delete_reference(aceCallbackInfoPermission.env, aceCallbackInfoPermission.callback); + } + aceCallbackInfoPermission.env = nullptr; + aceCallbackInfoPermission.callback = nullptr; + + FreeAsyncJSCallbackInfo(&asyncCallbackInfo); + rev = WrapVoidToJS(env); + } + return rev; +} + +EXTERN_C_START +/** + * @brief The interface of onRequestPermissionsFromUserResult provided for ACE to call back to JS. + * + * @param requestCode Indicates the request code returned after the ability is started. + * @param permissions Indicates list of permission. + * @param grantResults Indicates List of authorization results. + * @param callbackInfo The environment and call back info that the Node-API call is invoked under. + */ +void CallOnRequestPermissionsFromUserResult(int requestCode, const std::vector &permissions, + const std::vector &grantResults, CallbackInfo callbackInfo) +{ + HILOG_INFO("%{public}s,called env=%{public}p", __func__, callbackInfo.env); + + if (permissions.empty()) { + HILOG_ERROR("%{public}s, the string vector permissions is empty.", __func__); + } + uv_loop_s *loop = nullptr; + + napi_get_uv_event_loop(callbackInfo.env, &loop); + if (loop == nullptr) { + return; + } + + uv_work_t *work = new (std::nothrow) uv_work_t; + if (work == nullptr) { + HILOG_ERROR("%{public}s, work==null.", __func__); + return; + } + OnRequestPermissionsFromUserResultCallback *onRequestPermissionCB = + new (std::nothrow) OnRequestPermissionsFromUserResultCallback; + if (onRequestPermissionCB == nullptr) { + HILOG_ERROR("%{public}s, the string vector permissions is empty.", __func__); + if (work != nullptr) { + delete work; + work = nullptr; + } + return; + } + onRequestPermissionCB->requestCode = requestCode; + onRequestPermissionCB->permissions = permissions; + onRequestPermissionCB->grantResults = grantResults; + onRequestPermissionCB->cb = callbackInfo; + + work->data = (void *)onRequestPermissionCB; + + int rev = uv_queue_work( + loop, + work, + [](uv_work_t *work) {}, + [](uv_work_t *work, int status) { + OnRequestPermissionsFromUserResultCallback *onRequestPermissionCB = + (OnRequestPermissionsFromUserResultCallback *)work->data; + if (onRequestPermissionCB == nullptr) { + if (work != nullptr) { + delete work; + work = nullptr; + } + return; + } + + napi_value result[ARGS_TWO] = {0}; + result[PARAM0] = GetCallbackErrorValue(onRequestPermissionCB->cb.env, 0); + napi_create_object(onRequestPermissionCB->cb.env, &result[PARAM1]); + + // create requestCode + napi_value jsValue = 0; + napi_create_int32(onRequestPermissionCB->cb.env, onRequestPermissionCB->requestCode, &jsValue); + napi_set_named_property(onRequestPermissionCB->cb.env, result[PARAM1], "requestCode", jsValue); + + // create permissions + napi_value perValue = 0; + napi_value perArray = 0; + napi_create_array(onRequestPermissionCB->cb.env, &perArray); + + for (size_t i = 0; i < onRequestPermissionCB->permissions.size(); i++) { + napi_create_string_utf8(onRequestPermissionCB->cb.env, + onRequestPermissionCB->permissions[i].c_str(), + NAPI_AUTO_LENGTH, + &perValue); + napi_set_element(onRequestPermissionCB->cb.env, perArray, i, perValue); + } + napi_set_named_property(onRequestPermissionCB->cb.env, result[PARAM1], "permissions", perArray); + + // create grantResults + napi_value grantArray; + napi_create_array(onRequestPermissionCB->cb.env, &grantArray); + + for (size_t j = 0; j < onRequestPermissionCB->grantResults.size(); j++) { + napi_create_int32(onRequestPermissionCB->cb.env, onRequestPermissionCB->grantResults[j], &perValue); + napi_set_element(onRequestPermissionCB->cb.env, grantArray, j, perValue); + } + napi_set_named_property(onRequestPermissionCB->cb.env, result[PARAM1], "authResults", grantArray); + + // call CB function + napi_value callback = 0; + napi_value undefined = 0; + napi_get_undefined(onRequestPermissionCB->cb.env, &undefined); + + napi_value callResult = 0; + napi_get_reference_value(onRequestPermissionCB->cb.env, onRequestPermissionCB->cb.callback, &callback); + napi_call_function( + onRequestPermissionCB->cb.env, undefined, callback, ARGS_TWO, &result[PARAM0], &callResult); + + if (onRequestPermissionCB->cb.callback != nullptr) { + napi_delete_reference(onRequestPermissionCB->cb.env, onRequestPermissionCB->cb.callback); + } + if (onRequestPermissionCB != nullptr) { + delete onRequestPermissionCB; + onRequestPermissionCB = nullptr; + } + if (work != nullptr) { + delete work; + work = nullptr; + } + }); + + if (rev != 0) { + if (onRequestPermissionCB != nullptr) { + delete onRequestPermissionCB; + onRequestPermissionCB = nullptr; + } + if (work != nullptr) { + delete work; + work = nullptr; + } + } +} +EXTERN_C_END + +/** + * @brief Get Diles Dir. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_GetFilesDir(napi_env env, napi_callback_info info) +{ + HILOG_INFO("%{public}s called", __func__); + return NAPI_GetFilesDirCommon(env, info, AbilityType::PAGE); +} + +void CanRequestPermissionExecuteCallback(napi_env env, void *data) +{ + HILOG_INFO("%{public}s called.", __func__); + + AsyncJSCallbackInfo *asyncCallbackInfo = (AsyncJSCallbackInfo *)data; + if (asyncCallbackInfo == nullptr) { + HILOG_INFO("%{public}s called. asyncCallbackInfo is null", __func__); + return; + } + + asyncCallbackInfo->error_code = NAPI_ERR_NO_ERROR; + asyncCallbackInfo->native_data.data_type = NVT_NONE; + + if (asyncCallbackInfo->ability == nullptr) { + asyncCallbackInfo->error_code = NAPI_ERR_ACE_ABILITY; + return; + } + + std::string permission(asyncCallbackInfo->param.paramArgs.GetStringValue("permission")); + asyncCallbackInfo->native_data.data_type = NVT_BOOL; + asyncCallbackInfo->native_data.bool_value = asyncCallbackInfo->ability->CanRequestPermission(permission); +} + +napi_value NAPI_CanRequestPermissionWrap(napi_env env, napi_callback_info info, AsyncJSCallbackInfo *asyncCallbackInfo) +{ + HILOG_INFO("%{public}s called.", __func__); + size_t argc = ARGS_MAX_COUNT; + napi_value args[ARGS_MAX_COUNT] = {nullptr}; + napi_value jsthis = 0; + void *data = nullptr; + + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, &jsthis, &data)); + + if (!UnwrapParamVerifySelfPermission(env, argc, args, asyncCallbackInfo)) { + HILOG_INFO("%{public}s called. Invoke UnwrapParamVerifySelfPermission fail", __func__); + return nullptr; + } + + AsyncParamEx asyncParamEx; + if (asyncCallbackInfo->cbInfo.callback != nullptr) { + HILOG_INFO("%{public}s called. asyncCallback.", __func__); + asyncParamEx.resource = "NAPI_CanRequestPermissionCallback"; + asyncParamEx.execute = CanRequestPermissionExecuteCallback; + asyncParamEx.complete = CompleteAsyncCallbackWork; + + return ExecuteAsyncCallbackWork(env, asyncCallbackInfo, &asyncParamEx); + } else { + HILOG_INFO("%{public}s called. promise.", __func__); + asyncParamEx.resource = "NAPI_CanRequestPermissionPromise"; + asyncParamEx.execute = CanRequestPermissionExecuteCallback; + asyncParamEx.complete = CompletePromiseCallbackWork; + + return ExecutePromiseCallbackWork(env, asyncCallbackInfo, &asyncParamEx); + } +} + +napi_value NAPI_CanRequestPermission(napi_env env, napi_callback_info info) +{ + HILOG_INFO("%{public}s called.", __func__); + + AsyncJSCallbackInfo *asyncCallbackInfo = CreateAsyncJSCallbackInfo(env); + if (asyncCallbackInfo == nullptr) { + HILOG_INFO("%{public}s called. Invoke CreateAsyncJSCallbackInfo failed.", __func__); + return WrapVoidToJS(env); + } + + napi_value rev = NAPI_CanRequestPermissionWrap(env, info, asyncCallbackInfo); + if (rev == nullptr) { + FreeAsyncJSCallbackInfo(&asyncCallbackInfo); + rev = WrapVoidToJS(env); + } + return rev; +} + +bool UnwrapVerifyPermissionOptions(napi_env env, napi_value argv, AsyncJSCallbackInfo *asyncCallbackInfo) +{ + HILOG_INFO("%{public}s called", __func__); + if (asyncCallbackInfo == nullptr) { + HILOG_INFO("%{public}s called, asyncCallbackInfo is null", __func__); + return false; + } + + if (!IsTypeForNapiValue(env, argv, napi_object)) { + HILOG_INFO("%{public}s called, type of parameter is error.", __func__); + return false; + } + + int value = 0; + if (UnwrapInt32ByPropertyName(env, argv, "pid", value)) { + asyncCallbackInfo->param.paramArgs.PutIntValue("pid", value); + } + + value = 0; + if (UnwrapInt32ByPropertyName(env, argv, "uid", value)) { + asyncCallbackInfo->param.paramArgs.PutIntValue("uid", value); + } + return true; +} + +bool UnwrapParamVerifyPermission(napi_env env, size_t argc, napi_value *argv, AsyncJSCallbackInfo *asyncCallbackInfo) +{ + HILOG_INFO("%{public}s called, argc=%{public}zu", __func__, argc); + + const size_t argcMax = ARGS_THREE; + if (argc > argcMax || argc < 1) { + HILOG_INFO("%{public}s called, Params is invalid.", __func__); + return false; + } + + std::string permission(""); + if (!UnwrapStringFromJS2(env, argv[PARAM0], permission)) { + HILOG_INFO("%{public}s called, the first parameter is invalid.", __func__); + return false; + } + asyncCallbackInfo->param.paramArgs.PutStringValue("permission", permission); + + if (argc == argcMax) { + if (!CreateAsyncCallback(env, argv[PARAM2], asyncCallbackInfo)) { + HILOG_INFO("%{public}s called, the second parameter is invalid.", __func__); + return false; + } + + if (!UnwrapVerifyPermissionOptions(env, argv[PARAM1], asyncCallbackInfo)) { + HILOG_INFO("%{public}s called, the second parameter is invalid.", __func__); + return false; + } + } else if (argc == ARGS_TWO) { + if (!CreateAsyncCallback(env, argv[PARAM1], asyncCallbackInfo)) { + if (!UnwrapVerifyPermissionOptions(env, argv[PARAM1], asyncCallbackInfo)) { + HILOG_INFO("%{public}s called, the second parameter is invalid.", __func__); + return false; + } + } + } else if (argc == ARGS_ONE) { + asyncCallbackInfo->cbInfo.callback = nullptr; + } else { + HILOG_INFO("%{public}s called, the parameter is invalid.", __func__); + return false; + } + return true; +} + +void VerifyPermissionExecuteCallback(napi_env env, void *data) +{ + HILOG_INFO("%{public}s called.", __func__); + + AsyncJSCallbackInfo *asyncCallbackInfo = (AsyncJSCallbackInfo *)data; + if (asyncCallbackInfo == nullptr) { + HILOG_INFO("%{public}s called. asyncCallbackInfo is null", __func__); + return; + } + + asyncCallbackInfo->error_code = NAPI_ERR_NO_ERROR; + asyncCallbackInfo->native_data.data_type = NVT_NONE; + + if (asyncCallbackInfo->ability == nullptr) { + asyncCallbackInfo->error_code = NAPI_ERR_ACE_ABILITY; + return; + } + + std::string permission(asyncCallbackInfo->param.paramArgs.GetStringValue("permission").c_str()); + bool hasUid = asyncCallbackInfo->param.paramArgs.HasKey("uid"); + int pid = asyncCallbackInfo->param.paramArgs.GetIntValue("pid"); + int uid = asyncCallbackInfo->param.paramArgs.GetIntValue("uid"); + + asyncCallbackInfo->native_data.data_type = NVT_INT32; + + if (hasUid) { + asyncCallbackInfo->native_data.int32_value = asyncCallbackInfo->ability->VerifyPermission(permission, pid, uid); + } else { + asyncCallbackInfo->native_data.int32_value = asyncCallbackInfo->ability->VerifySelfPermission(permission); + } +} + +napi_value NAPI_VerifyPermissionWrap(napi_env env, napi_callback_info info, AsyncJSCallbackInfo *asyncCallbackInfo) +{ + HILOG_INFO("%{public}s called.", __func__); + size_t argc = ARGS_MAX_COUNT; + napi_value args[ARGS_MAX_COUNT] = {nullptr}; + napi_value jsthis = 0; + void *data = nullptr; + + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, &jsthis, &data)); + + if (!UnwrapParamVerifyPermission(env, argc, args, asyncCallbackInfo)) { + HILOG_INFO("%{public}s called. Invoke UnwrapParamVerifyPermission fail", __func__); + return nullptr; + } + + AsyncParamEx asyncParamEx; + if (asyncCallbackInfo->cbInfo.callback != nullptr) { + HILOG_INFO("%{public}s called. asyncCallback.", __func__); + asyncParamEx.resource = "NAPI_VerifyPermissionCallback"; + asyncParamEx.execute = VerifyPermissionExecuteCallback; + asyncParamEx.complete = CompleteAsyncCallbackWork; + + return ExecuteAsyncCallbackWork(env, asyncCallbackInfo, &asyncParamEx); + } else { + HILOG_INFO("%{public}s called. promise.", __func__); + asyncParamEx.resource = "NAPI_VerifyPermissionPromise"; + asyncParamEx.execute = VerifyPermissionExecuteCallback; + asyncParamEx.complete = CompletePromiseCallbackWork; + + return ExecutePromiseCallbackWork(env, asyncCallbackInfo, &asyncParamEx); + } +} + +napi_value NAPI_VerifyPermission(napi_env env, napi_callback_info info) +{ + HILOG_INFO("%{public}s called.", __func__); + AsyncJSCallbackInfo *asyncCallbackInfo = CreateAsyncJSCallbackInfo(env); + if (asyncCallbackInfo == nullptr) { + HILOG_INFO("%{public}s called. Invoke CreateAsyncJSCallbackInfo failed.", __func__); + return WrapVoidToJS(env); + } + + napi_value rev = NAPI_VerifyPermissionWrap(env, info, asyncCallbackInfo); + if (rev == nullptr) { + FreeAsyncJSCallbackInfo(&asyncCallbackInfo); + rev = WrapVoidToJS(env); + } + return rev; +} + +void VerifyCallingPermissionExecuteCallback(napi_env env, void *data) +{ + HILOG_INFO("%{public}s called.", __func__); + + AsyncJSCallbackInfo *asyncCallbackInfo = (AsyncJSCallbackInfo *)data; + if (asyncCallbackInfo == nullptr) { + HILOG_INFO("%{public}s called. asyncCallbackInfo is null", __func__); + return; + } + + asyncCallbackInfo->error_code = NAPI_ERR_NO_ERROR; + asyncCallbackInfo->native_data.data_type = NVT_NONE; + + if (asyncCallbackInfo->ability == nullptr) { + asyncCallbackInfo->error_code = NAPI_ERR_ACE_ABILITY; + return; + } + + asyncCallbackInfo->native_data.data_type = NVT_INT32; + std::string permission(asyncCallbackInfo->param.paramArgs.GetStringValue("permission").c_str()); + asyncCallbackInfo->native_data.int32_value = asyncCallbackInfo->ability->VerifyCallingPermission(permission); +} + +napi_value NAPI_VerifyCallingPermissionWrap( + napi_env env, napi_callback_info info, AsyncJSCallbackInfo *asyncCallbackInfo) +{ + HILOG_INFO("%{public}s called.", __func__); + size_t argc = ARGS_MAX_COUNT; + napi_value args[ARGS_MAX_COUNT] = {nullptr}; + napi_value jsthis = 0; + void *data = nullptr; + + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, &jsthis, &data)); + + if (!UnwrapParamVerifySelfPermission(env, argc, args, asyncCallbackInfo)) { + HILOG_INFO("%{public}s called. Invoke UnwrapParamVerifySelfPermission fail", __func__); + return nullptr; + } + + AsyncParamEx asyncParamEx; + if (asyncCallbackInfo->cbInfo.callback != nullptr) { + HILOG_INFO("%{public}s called. asyncCallback.", __func__); + asyncParamEx.resource = "NAPI_VerifyCallingPermissionCallback"; + asyncParamEx.execute = VerifyCallingPermissionExecuteCallback; + asyncParamEx.complete = CompleteAsyncCallbackWork; + + return ExecuteAsyncCallbackWork(env, asyncCallbackInfo, &asyncParamEx); + } else { + HILOG_INFO("%{public}s called. promise.", __func__); + asyncParamEx.resource = "NAPI_VerifyCallingPermissionPromise"; + asyncParamEx.execute = VerifyCallingPermissionExecuteCallback; + asyncParamEx.complete = CompletePromiseCallbackWork; + + return ExecutePromiseCallbackWork(env, asyncCallbackInfo, &asyncParamEx); + } +} + +napi_value NAPI_VerifyCallingPermission(napi_env env, napi_callback_info info) +{ + HILOG_INFO("%{public}s called.", __func__); + + AsyncJSCallbackInfo *asyncCallbackInfo = CreateAsyncJSCallbackInfo(env); + if (asyncCallbackInfo == nullptr) { + HILOG_INFO("%{public}s called. Invoke CreateAsyncJSCallbackInfo failed.", __func__); + return WrapVoidToJS(env); + } + + napi_value rev = NAPI_VerifyCallingPermissionWrap(env, info, asyncCallbackInfo); + if (rev == nullptr) { + FreeAsyncJSCallbackInfo(&asyncCallbackInfo); + rev = WrapVoidToJS(env); + } + return rev; +} + +void VerifyCallingOrSelfPermissionExecuteCallback(napi_env env, void *data) +{ + HILOG_INFO("%{public}s called.", __func__); + + AsyncJSCallbackInfo *asyncCallbackInfo = static_cast(data); + if (asyncCallbackInfo == nullptr) { + HILOG_INFO("%{public}s called. asyncCallbackInfo is null", __func__); + return; + } + + asyncCallbackInfo->error_code = NAPI_ERR_NO_ERROR; + asyncCallbackInfo->native_data.data_type = NVT_NONE; + + if (asyncCallbackInfo->ability == nullptr) { + asyncCallbackInfo->error_code = NAPI_ERR_ACE_ABILITY; + return; + } + + asyncCallbackInfo->native_data.data_type = NVT_INT32; + std::string permission(asyncCallbackInfo->param.paramArgs.GetStringValue("permission").c_str()); + asyncCallbackInfo->native_data.int32_value = asyncCallbackInfo->ability->VerifyCallingOrSelfPermission(permission); +} + +napi_value NAPI_VerifyCallingOrSelfPermissionWrap( + napi_env env, napi_callback_info info, AsyncJSCallbackInfo *asyncCallbackInfo) +{ + HILOG_INFO("%{public}s called.", __func__); + size_t argc = ARGS_MAX_COUNT; + napi_value args[ARGS_MAX_COUNT] = {nullptr}; + napi_value jsthis = 0; + void *data = nullptr; + + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, &jsthis, &data)); + + if (!UnwrapParamVerifySelfPermission(env, argc, args, asyncCallbackInfo)) { + HILOG_INFO("%{public}s called. Invoke UnwrapParamVerifySelfPermission fail", __func__); + return nullptr; + } + + AsyncParamEx asyncParamEx; + if (asyncCallbackInfo->cbInfo.callback != nullptr) { + HILOG_INFO("%{public}s called. asyncCallback.", __func__); + asyncParamEx.resource = "NAPI_VerifyCallingOrSelfPermissionCallback"; + asyncParamEx.execute = VerifyCallingOrSelfPermissionExecuteCallback; + asyncParamEx.complete = CompleteAsyncCallbackWork; + + return ExecuteAsyncCallbackWork(env, asyncCallbackInfo, &asyncParamEx); + } else { + HILOG_INFO("%{public}s called. promise.", __func__); + asyncParamEx.resource = "NAPI_VerifyCallingOrSelfPermissionPromise"; + asyncParamEx.execute = VerifyCallingOrSelfPermissionExecuteCallback; + asyncParamEx.complete = CompletePromiseCallbackWork; + + return ExecutePromiseCallbackWork(env, asyncCallbackInfo, &asyncParamEx); + } +} + +napi_value NAPI_VerifyCallingOrSelfPermission(napi_env env, napi_callback_info info) +{ + HILOG_INFO("%{public}s called.", __func__); + + AsyncJSCallbackInfo *asyncCallbackInfo = CreateAsyncJSCallbackInfo(env); + if (asyncCallbackInfo == nullptr) { + HILOG_INFO("%{public}s called. Invoke CreateAsyncJSCallbackInfo failed.", __func__); + return WrapVoidToJS(env); + } + + napi_value rev = NAPI_VerifyCallingOrSelfPermissionWrap(env, info, asyncCallbackInfo); + if (rev == nullptr) { + FreeAsyncJSCallbackInfo(&asyncCallbackInfo); + rev = WrapVoidToJS(env); + } + return rev; +} + +/** + * @brief GetApplicationInfo asynchronous processing function. + * + * @param env The environment that the Node-API call is invoked under. + * @param data Point to asynchronous processing of data. + */ +void GetAppInfoExecuteCB(napi_env env, void *data) +{ + HILOG_INFO("NAPI_GetApplicationInfo, worker pool thread execute."); + AppInfoCB *appInfoCB = static_cast(data); + appInfoCB->cbBase.errCode = NAPI_ERR_NO_ERROR; + + if (appInfoCB->cbBase.ability == nullptr) { + HILOG_ERROR("NAPI_GetApplicationInfo, ability == nullptr"); + appInfoCB->cbBase.errCode = NAPI_ERR_ACE_ABILITY; + return; + } + + std::shared_ptr appInfoPtr = appInfoCB->cbBase.ability->GetApplicationInfo(); + if (appInfoPtr != nullptr) { + SaveAppInfo(appInfoCB->appInfo, *appInfoPtr); + } else { + HILOG_ERROR("NAPI_GetApplicationInfo, appInfoPtr == nullptr"); + appInfoCB->cbBase.errCode = NAPI_ERR_ABILITY_CALL_INVALID; + } + HILOG_INFO("NAPI_GetApplicationInfo, worker pool thread execute end."); +} + +/** + * @brief The callback at the end of the asynchronous callback. + * + * @param env The environment that the Node-API call is invoked under. + * @param data Point to asynchronous processing of data. + */ +void GetAppInfoAsyncCompleteCB(napi_env env, napi_status status, void *data) +{ + HILOG_INFO("NAPI_GetApplicationInfo, main event thread complete."); + AppInfoCB *appInfoCB = static_cast(data); + napi_value callback = nullptr; + napi_value undefined = nullptr; + napi_value result[ARGS_TWO] = {nullptr}; + napi_value callResult = nullptr; + NAPI_CALL_RETURN_VOID(env, napi_get_undefined(env, &undefined)); + result[PARAM0] = GetCallbackErrorValue(env, appInfoCB->cbBase.errCode); + if (appInfoCB->cbBase.errCode == NAPI_ERR_NO_ERROR) { + result[PARAM1] = WrapAppInfo(env, appInfoCB->appInfo); + } else { + result[PARAM1] = WrapUndefinedToJS(env); + } + NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, appInfoCB->cbBase.cbInfo.callback, &callback)); + NAPI_CALL_RETURN_VOID(env, napi_call_function(env, undefined, callback, ARGS_TWO, &result[PARAM0], &callResult)); + + if (appInfoCB->cbBase.cbInfo.callback != nullptr) { + NAPI_CALL_RETURN_VOID(env, napi_delete_reference(env, appInfoCB->cbBase.cbInfo.callback)); + } + NAPI_CALL_RETURN_VOID(env, napi_delete_async_work(env, appInfoCB->cbBase.asyncWork)); + delete appInfoCB; + appInfoCB = nullptr; + HILOG_INFO("NAPI_GetApplicationInfo, main event thread complete end."); +} + +/** + * @brief GetApplicationInfo Async. + * + * @param env The environment that the Node-API call is invoked under. + * @param args Indicates the arguments passed into the callback. + * @param argcPromise Asynchronous data processing. + * @param appInfoCB Process data asynchronously. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value GetApplicationInfoAsync(napi_env env, napi_value *args, const size_t argCallback, AppInfoCB *appInfoCB) +{ + HILOG_INFO("%{public}s, asyncCallback.", __func__); + if (args == nullptr || appInfoCB == nullptr) { + HILOG_ERROR("%{public}s, param == nullptr.", __func__); + return nullptr; + } + napi_value resourceName = nullptr; + NAPI_CALL(env, napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName)); + + napi_valuetype valuetype = napi_undefined; + NAPI_CALL(env, napi_typeof(env, args[argCallback], &valuetype)); + if (valuetype == napi_function) { + NAPI_CALL(env, napi_create_reference(env, args[argCallback], 1, &appInfoCB->cbBase.cbInfo.callback)); + } + NAPI_CALL(env, + napi_create_async_work(env, + nullptr, + resourceName, + GetAppInfoExecuteCB, + GetAppInfoAsyncCompleteCB, + (void *)appInfoCB, + &appInfoCB->cbBase.asyncWork)); + NAPI_CALL(env, napi_queue_async_work(env, appInfoCB->cbBase.asyncWork)); + napi_value result = nullptr; + NAPI_CALL(env, napi_get_null(env, &result)); + HILOG_INFO("%{public}s, asyncCallback end.", __func__); + return result; +} + +/** + * @brief The callback at the end of the Promise callback. + * + * @param env The environment that the Node-API call is invoked under. + * @param data Point to asynchronous processing of data. + */ +void GetAppInfoPromiseCompleteCB(napi_env env, napi_status status, void *data) +{ + HILOG_INFO("NAPI_GetApplicationInfo, main event thread complete."); + AppInfoCB *appInfoCB = static_cast(data); + if (appInfoCB == nullptr) { + HILOG_ERROR("NAPI_GetApplicationInfo, appInfoCB == nullptr"); + return; + } + + napi_value result = nullptr; + if (appInfoCB->cbBase.errCode == NAPI_ERR_NO_ERROR) { + result = WrapAppInfo(env, appInfoCB->appInfo); + napi_resolve_deferred(env, appInfoCB->cbBase.deferred, result); + } else { + result = GetCallbackErrorValue(env, appInfoCB->cbBase.errCode); + napi_reject_deferred(env, appInfoCB->cbBase.deferred, result); + } + + napi_delete_async_work(env, appInfoCB->cbBase.asyncWork); + delete appInfoCB; + appInfoCB = nullptr; + HILOG_INFO("NAPI_GetApplicationInfo, main event thread complete end."); +} + +/** + * @brief GetApplicationInfo Promise. + * + * @param env The environment that the Node-API call is invoked under. + * @param appInfoCB Process data asynchronously. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value GetApplicationInfoPromise(napi_env env, AppInfoCB *appInfoCB) +{ + HILOG_INFO("%{public}s, promise.", __func__); + if (appInfoCB == nullptr) { + HILOG_ERROR("%{public}s, param == nullptr.", __func__); + return nullptr; + } + napi_value resourceName = nullptr; + NAPI_CALL(env, napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName)); + napi_deferred deferred; + napi_value promise = nullptr; + NAPI_CALL(env, napi_create_promise(env, &deferred, &promise)); + appInfoCB->cbBase.deferred = deferred; + + NAPI_CALL(env, + napi_create_async_work(env, + nullptr, + resourceName, + GetAppInfoExecuteCB, + GetAppInfoPromiseCompleteCB, + (void *)appInfoCB, + &appInfoCB->cbBase.asyncWork)); + NAPI_CALL(env, napi_queue_async_work(env, appInfoCB->cbBase.asyncWork)); + HILOG_INFO("%{public}s, promise end.", __func__); + return promise; +} + +/** + * @brief GetApplicationInfo processing function. + * + * @param env The environment that the Node-API call is invoked under. + * @param appInfoCB Process data asynchronously. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value GetApplicationInfoWrap(napi_env env, napi_callback_info info, AppInfoCB *appInfoCB) +{ + HILOG_INFO("%{public}s, asyncCallback.", __func__); + if (appInfoCB == nullptr) { + HILOG_ERROR("%{public}s, appInfoCB == nullptr.", __func__); + return nullptr; + } + + size_t argcAsync = 1; + const size_t argcPromise = 0; + const size_t argCountWithAsync = argcPromise + ARGS_ASYNC_COUNT; + napi_value args[ARGS_MAX_COUNT] = {nullptr}; + napi_value ret = nullptr; + + NAPI_CALL(env, napi_get_cb_info(env, info, &argcAsync, args, nullptr, nullptr)); + if (argcAsync > argCountWithAsync || argcAsync > ARGS_MAX_COUNT) { + HILOG_ERROR("%{public}s, Wrong argument count.", __func__); + return nullptr; + } + + if (argcAsync > argcPromise) { + ret = GetApplicationInfoAsync(env, args, 0, appInfoCB); + } else { + ret = GetApplicationInfoPromise(env, appInfoCB); + } + HILOG_INFO("%{public}s, asyncCallback end.", __func__); + return ret; +} + +/** + * @brief Create asynchronous data. + * + * @param env The environment that the Node-API call is invoked under. + * + * @return Return a pointer to AppInfoCB on success, nullptr on failure. + */ +AppInfoCB *CreateAppInfoCBInfo(napi_env env) +{ + HILOG_INFO("%{public}s, called.", __func__); + napi_value global = nullptr; + NAPI_CALL(env, napi_get_global(env, &global)); + + napi_value abilityObj = nullptr; + NAPI_CALL(env, napi_get_named_property(env, global, "ability", &abilityObj)); + + Ability *ability = nullptr; + NAPI_CALL(env, napi_get_value_external(env, abilityObj, (void **)&ability)); + + AppInfoCB *appInfoCB = new (std::nothrow) AppInfoCB; + if (appInfoCB == nullptr) { + HILOG_ERROR("%{public}s, appInfoCB == nullptr.", __func__); + return nullptr; + } + appInfoCB->cbBase.cbInfo.env = env; + appInfoCB->cbBase.asyncWork = nullptr; + appInfoCB->cbBase.deferred = nullptr; + appInfoCB->cbBase.ability = ability; + appInfoCB->cbBase.abilityType = AbilityType::UNKNOWN; + appInfoCB->cbBase.errCode = NAPI_ERR_NO_ERROR; + + HILOG_INFO("%{public}s, end.", __func__); + return appInfoCB; +} + +/** + * @brief GetBundleName asynchronous processing function. + * + * @param env The environment that the Node-API call is invoked under. + * @param data Point to asynchronous processing of data. + */ +void GetBundleNameExecuteCallback(napi_env env, void *data) +{ + HILOG_INFO("%{public}s called", __func__); + AsyncJSCallbackInfo *asyncCallbackInfo = static_cast(data); + if (asyncCallbackInfo == nullptr) { + HILOG_ERROR("%{public}s. asyncCallbackInfo is null", __func__); + return; + } + + asyncCallbackInfo->error_code = NAPI_ERR_NO_ERROR; + asyncCallbackInfo->native_data.data_type = NVT_NONE; + if (asyncCallbackInfo->ability == nullptr) { + HILOG_ERROR("%{public}s ability == nullptr", __func__); + asyncCallbackInfo->error_code = NAPI_ERR_ACE_ABILITY; + return; + } + + asyncCallbackInfo->native_data.data_type = NVT_STRING; + asyncCallbackInfo->native_data.str_value = asyncCallbackInfo->ability->GetBundleName(); + HILOG_INFO("%{public}s end. bundleName=%{public}s", __func__, asyncCallbackInfo->native_data.str_value.c_str()); +} + +/** + * @brief GetBundleName processing function. + * + * @param env The environment that the Node-API call is invoked under. + * @param asyncCallbackInfo Process data asynchronously. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value NAPI_GetBundleNameWrap(napi_env env, napi_callback_info info, AsyncJSCallbackInfo *asyncCallbackInfo) +{ + HILOG_INFO("%{public}s called", __func__); + size_t argc = ARGS_MAX_COUNT; + napi_value args[ARGS_MAX_COUNT] = {nullptr}; + napi_value jsthis = 0; + void *data = nullptr; + + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, &jsthis, &data)); + + if (argc > ARGS_ONE) { + HILOG_INFO("%{public}s called, parameters is invalid.", __func__); + return nullptr; + } + + if (argc == ARGS_ONE) { + if (!CreateAsyncCallback(env, args[PARAM0], asyncCallbackInfo)) { + HILOG_INFO("%{public}s called, the first parameter is invalid.", __func__); + return nullptr; + } + } + + AsyncParamEx asyncParamEx; + if (asyncCallbackInfo->cbInfo.callback != nullptr) { + HILOG_INFO("%{public}s called. asyncCallback.", __func__); + asyncParamEx.resource = "NAPI_GetBundleNameCallback"; + asyncParamEx.execute = GetBundleNameExecuteCallback; + asyncParamEx.complete = CompleteAsyncCallbackWork; + + return ExecuteAsyncCallbackWork(env, asyncCallbackInfo, &asyncParamEx); + } else { + HILOG_INFO("%{public}s called. promise.", __func__); + asyncParamEx.resource = "NAPI_GetBundleNamePromise"; + asyncParamEx.execute = GetBundleNameExecuteCallback; + asyncParamEx.complete = CompletePromiseCallbackWork; + + return ExecutePromiseCallbackWork(env, asyncCallbackInfo, &asyncParamEx); + } +} + +napi_value WrapProcessInfo(napi_env env, ProcessInfoCB *processInfoCB) +{ + HILOG_INFO("%{public}s called", __func__); + if (processInfoCB == nullptr) { + HILOG_ERROR("%{public}s Invalid param(processInfoCB == nullptr)", __func__); + return nullptr; + } + napi_value result = nullptr; + napi_value proValue = nullptr; + NAPI_CALL(env, napi_create_object(env, &result)); + NAPI_CALL(env, napi_create_int32(env, processInfoCB->pid, &proValue)); + NAPI_CALL(env, napi_set_named_property(env, result, "pid", proValue)); + + NAPI_CALL(env, napi_create_string_utf8(env, processInfoCB->processName.c_str(), NAPI_AUTO_LENGTH, &proValue)); + NAPI_CALL(env, napi_set_named_property(env, result, "processName", proValue)); + HILOG_INFO("%{public}s end", __func__); + return result; +} + +/** + * @brief GetProcessInfo asynchronous processing function. + * + * @param env The environment that the Node-API call is invoked under. + * @param data Point to asynchronous processing of data. + */ +void GetProcessInfoExecuteCB(napi_env env, void *data) +{ + HILOG_INFO("NAPI_GetProcessInfo, worker pool thread execute."); + ProcessInfoCB *processInfoCB = static_cast(data); + if (processInfoCB == nullptr) { + return; + } + + processInfoCB->cbBase.errCode = NAPI_ERR_NO_ERROR; + if (processInfoCB->cbBase.ability == nullptr) { + HILOG_ERROR("NAPI_GetProcessInfo, ability == nullptr"); + processInfoCB->cbBase.errCode = NAPI_ERR_ACE_ABILITY; + return; + } + + std::shared_ptr processInfoPtr = processInfoCB->cbBase.ability->GetProcessInfo(); + if (processInfoPtr != nullptr) { + processInfoCB->processName = processInfoPtr->GetProcessName(); + processInfoCB->pid = processInfoPtr->GetPid(); + } else { + HILOG_ERROR("NAPI_GetProcessInfo, processInfoPtr == nullptr"); + processInfoCB->cbBase.errCode = NAPI_ERR_ABILITY_CALL_INVALID; + } + HILOG_INFO("NAPI_GetProcessInfo, worker pool thread execute end."); +} + +/** + * @brief The callback at the end of the asynchronous callback. + * + * @param env The environment that the Node-API call is invoked under. + * @param data Point to asynchronous processing of data. + */ +void GetProcessInfoAsyncCompleteCB(napi_env env, napi_status status, void *data) +{ + HILOG_INFO("NAPI_GetProcessInfo, main event thread complete."); + ProcessInfoCB *processInfoCB = static_cast(data); + napi_value callback = nullptr; + napi_value undefined = nullptr; + napi_value result[ARGS_TWO] = {nullptr}; + napi_value callResult = nullptr; + NAPI_CALL_RETURN_VOID(env, napi_get_undefined(env, &undefined)); + result[PARAM0] = GetCallbackErrorValue(env, processInfoCB->cbBase.errCode); + if (processInfoCB->cbBase.errCode == NAPI_ERR_NO_ERROR) { + result[PARAM1] = WrapProcessInfo(env, processInfoCB); + } else { + result[PARAM1] = WrapUndefinedToJS(env); + } + + NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, processInfoCB->cbBase.cbInfo.callback, &callback)); + NAPI_CALL_RETURN_VOID(env, napi_call_function(env, undefined, callback, ARGS_TWO, &result[PARAM0], &callResult)); + + if (processInfoCB->cbBase.cbInfo.callback != nullptr) { + NAPI_CALL_RETURN_VOID(env, napi_delete_reference(env, processInfoCB->cbBase.cbInfo.callback)); + } + NAPI_CALL_RETURN_VOID(env, napi_delete_async_work(env, processInfoCB->cbBase.asyncWork)); + delete processInfoCB; + processInfoCB = nullptr; + HILOG_INFO("NAPI_GetProcessInfo, main event thread complete end."); +} + +/** + * @brief GetProcessInfo Async. + * + * @param env The environment that the Node-API call is invoked under. + * @param args Indicates the arguments passed into the callback. + * @param argcPromise Asynchronous data processing. + * @param ProcessInfoCB Process data asynchronously. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value GetProcessInfoAsync(napi_env env, napi_value *args, const size_t argCallback, ProcessInfoCB *processInfoCB) +{ + HILOG_INFO("%{public}s, asyncCallback.", __func__); + if (args == nullptr || processInfoCB == nullptr) { + HILOG_ERROR("%{public}s, param == nullptr.", __func__); + return nullptr; + } + napi_value resourceName = nullptr; + NAPI_CALL(env, napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName)); + + napi_valuetype valuetype = napi_undefined; + NAPI_CALL(env, napi_typeof(env, args[argCallback], &valuetype)); + if (valuetype == napi_function) { + NAPI_CALL(env, napi_create_reference(env, args[argCallback], 1, &processInfoCB->cbBase.cbInfo.callback)); + } + NAPI_CALL(env, + napi_create_async_work(env, + nullptr, + resourceName, + GetProcessInfoExecuteCB, + GetProcessInfoAsyncCompleteCB, + (void *)processInfoCB, + &processInfoCB->cbBase.asyncWork)); + NAPI_CALL(env, napi_queue_async_work(env, processInfoCB->cbBase.asyncWork)); + napi_value result = nullptr; + NAPI_CALL(env, napi_get_null(env, &result)); + HILOG_INFO("%{public}s, asyncCallback end.", __func__); + return result; +} + +/** + * @brief The callback at the end of the Promise callback. + * + * @param env The environment that the Node-API call is invoked under. + * @param data Point to asynchronous processing of data. + */ +void GetProcessInfoPromiseCompleteCB(napi_env env, napi_status status, void *data) +{ + HILOG_INFO("NAPI_GetProcessInfo, main event thread complete."); + ProcessInfoCB *processInfoCB = static_cast(data); + napi_value result = nullptr; + if (processInfoCB->cbBase.errCode == NAPI_ERR_NO_ERROR) { + result = WrapProcessInfo(env, processInfoCB); + napi_resolve_deferred(env, processInfoCB->cbBase.deferred, result); + } else { + result = GetCallbackErrorValue(env, processInfoCB->cbBase.errCode); + napi_reject_deferred(env, processInfoCB->cbBase.deferred, result); + } + + napi_delete_async_work(env, processInfoCB->cbBase.asyncWork); + delete processInfoCB; + processInfoCB = nullptr; + HILOG_INFO("NAPI_GetProcessInfo, main event thread complete end."); +} + +/** + * @brief GetProcessInfo Promise. + * + * @param env The environment that the Node-API call is invoked under. + * @param ProcessInfoCB Process data asynchronously. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value GetProcessInfoPromise(napi_env env, ProcessInfoCB *processInfoCB) +{ + HILOG_INFO("%{public}s, promise.", __func__); + if (processInfoCB == nullptr) { + HILOG_ERROR("%{public}s, param == nullptr.", __func__); + return nullptr; + } + napi_value resourceName = nullptr; + NAPI_CALL(env, napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName)); + napi_deferred deferred; + napi_value promise = nullptr; + NAPI_CALL(env, napi_create_promise(env, &deferred, &promise)); + processInfoCB->cbBase.deferred = deferred; + + NAPI_CALL(env, + napi_create_async_work(env, + nullptr, + resourceName, + GetProcessInfoExecuteCB, + GetProcessInfoPromiseCompleteCB, + (void *)processInfoCB, + &processInfoCB->cbBase.asyncWork)); + NAPI_CALL(env, napi_queue_async_work(env, processInfoCB->cbBase.asyncWork)); + HILOG_INFO("%{public}s, promise end.", __func__); + return promise; +} + +/** + * @brief GetProcessInfo processing function. + * + * @param env The environment that the Node-API call is invoked under. + * @param ProcessInfoCB Process data asynchronously. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value GetProcessInfoWrap(napi_env env, napi_callback_info info, ProcessInfoCB *processInfoCB) +{ + HILOG_INFO("%{public}s, asyncCallback.", __func__); + if (processInfoCB == nullptr) { + HILOG_ERROR("%{public}s, processInfoCB == nullptr.", __func__); + return nullptr; + } + + size_t argcAsync = 1; + const size_t argcPromise = 0; + const size_t argCountWithAsync = argcPromise + ARGS_ASYNC_COUNT; + napi_value args[ARGS_MAX_COUNT] = {nullptr}; + napi_value ret = nullptr; + + NAPI_CALL(env, napi_get_cb_info(env, info, &argcAsync, args, nullptr, nullptr)); + if (argcAsync > argCountWithAsync || argcAsync > ARGS_MAX_COUNT) { + HILOG_ERROR("%{public}s, Wrong argument count.", __func__); + return nullptr; + } + + if (argcAsync > argcPromise) { + ret = GetProcessInfoAsync(env, args, 0, processInfoCB); + } else { + ret = GetProcessInfoPromise(env, processInfoCB); + } + HILOG_INFO("%{public}s, asyncCallback end.", __func__); + return ret; +} + +/** + * @brief Create asynchronous data. + * + * @param env The environment that the Node-API call is invoked under. + * + * @return Return a pointer to ProcessInfoCB on success, nullptr on failure. + */ +ProcessInfoCB *CreateProcessInfoCBInfo(napi_env env) +{ + HILOG_INFO("%{public}s, called.", __func__); + napi_value global = nullptr; + NAPI_CALL(env, napi_get_global(env, &global)); + + napi_value abilityObj = nullptr; + NAPI_CALL(env, napi_get_named_property(env, global, "ability", &abilityObj)); + + Ability *ability = nullptr; + NAPI_CALL(env, napi_get_value_external(env, abilityObj, (void **)&ability)); + + ProcessInfoCB *processInfoCB = new (std::nothrow) ProcessInfoCB; + if (processInfoCB == nullptr) { + HILOG_ERROR("%{public}s, processInfoCB == nullptr.", __func__); + return nullptr; + } + processInfoCB->cbBase.cbInfo.env = env; + processInfoCB->cbBase.asyncWork = nullptr; + processInfoCB->cbBase.deferred = nullptr; + processInfoCB->cbBase.ability = ability; + + HILOG_INFO("%{public}s, end.", __func__); + return processInfoCB; +} + +/** + * @brief Create asynchronous data. + * + * @param env The environment that the Node-API call is invoked under. + * + * @return Return a pointer to ElementNameCB on success, nullptr on failure. + */ +ElementNameCB *CreateElementNameCBInfo(napi_env env) +{ + HILOG_INFO("%{public}s, called.", __func__); + napi_value global = nullptr; + NAPI_CALL(env, napi_get_global(env, &global)); + + napi_value abilityObj = nullptr; + NAPI_CALL(env, napi_get_named_property(env, global, "ability", &abilityObj)); + + Ability *ability = nullptr; + NAPI_CALL(env, napi_get_value_external(env, abilityObj, (void **)&ability)); + + ElementNameCB *elementNameCB = new (std::nothrow) ElementNameCB; + if (elementNameCB == nullptr) { + HILOG_ERROR("%{public}s, elementNameCB == nullptr.", __func__); + return nullptr; + } + elementNameCB->cbBase.cbInfo.env = env; + elementNameCB->cbBase.asyncWork = nullptr; + elementNameCB->cbBase.deferred = nullptr; + elementNameCB->cbBase.ability = ability; + + HILOG_INFO("%{public}s, end.", __func__); + return elementNameCB; +} + +napi_value WrapElementName(napi_env env, ElementNameCB *elementNameCB) +{ + HILOG_INFO("%{public}s, called.", __func__); + if (elementNameCB == nullptr) { + HILOG_ERROR("%{public}s,Invalid param(appInfoCB = nullptr)", __func__); + return nullptr; + } + napi_value result = nullptr; + napi_value proValue = nullptr; + NAPI_CALL(env, napi_create_object(env, &result)); + NAPI_CALL(env, napi_create_string_utf8(env, elementNameCB->abilityName.c_str(), NAPI_AUTO_LENGTH, &proValue)); + NAPI_CALL(env, napi_set_named_property(env, result, "abilityName", proValue)); + + NAPI_CALL(env, napi_create_string_utf8(env, elementNameCB->bundleName.c_str(), NAPI_AUTO_LENGTH, &proValue)); + NAPI_CALL(env, napi_set_named_property(env, result, "bundleName", proValue)); + + NAPI_CALL(env, napi_create_string_utf8(env, elementNameCB->deviceId.c_str(), NAPI_AUTO_LENGTH, &proValue)); + NAPI_CALL(env, napi_set_named_property(env, result, "deviceId", proValue)); + + NAPI_CALL(env, napi_create_string_utf8(env, elementNameCB->shortName.c_str(), NAPI_AUTO_LENGTH, &proValue)); + NAPI_CALL(env, napi_set_named_property(env, result, "shortName", proValue)); + + NAPI_CALL(env, napi_create_string_utf8(env, elementNameCB->uri.c_str(), NAPI_AUTO_LENGTH, &proValue)); + NAPI_CALL(env, napi_set_named_property(env, result, "uri", proValue)); + HILOG_INFO("%{public}s, end.", __func__); + return result; +} + +/** + * @brief GetElementName asynchronous processing function. + * + * @param env The environment that the Node-API call is invoked under. + * @param data Point to asynchronous processing of data. + */ +void GetElementNameExecuteCB(napi_env env, void *data) +{ + HILOG_INFO("NAPI_GetElementName, worker pool thread execute."); + if (data == nullptr) { + HILOG_ERROR("%{public}s, data == nullptr.", __func__); + return; + } + ElementNameCB *elementNameCB = static_cast(data); + if (elementNameCB == nullptr) { + HILOG_ERROR("NAPI_GetElementName, elementNameCB == nullptr"); + return; + } + + elementNameCB->cbBase.errCode = NAPI_ERR_NO_ERROR; + if (elementNameCB->cbBase.ability == nullptr) { + HILOG_ERROR("NAPI_GetElementName, ability == nullptr"); + elementNameCB->cbBase.errCode = NAPI_ERR_ACE_ABILITY; + return; + } + + std::shared_ptr elementName = elementNameCB->cbBase.ability->GetElementName(); + if (elementNameCB != nullptr) { + elementNameCB->deviceId = elementName->GetDeviceID(); + elementNameCB->bundleName = elementName->GetBundleName(); + elementNameCB->abilityName = elementName->GetAbilityName(); + elementNameCB->uri = elementNameCB->cbBase.ability->GetWant()->GetUriString(); + elementNameCB->shortName = ""; + } else { + elementNameCB->cbBase.errCode = NAPI_ERR_ABILITY_CALL_INVALID; + } + HILOG_INFO("NAPI_GetElementName, worker pool thread execute end."); +} + +/** + * @brief The callback at the end of the asynchronous callback. + * + * @param env The environment that the Node-API call is invoked under. + * @param data Point to asynchronous processing of data. + */ +void GetElementNameAsyncCompleteCB(napi_env env, napi_status status, void *data) +{ + HILOG_INFO("NAPI_GetElementName, main event thread complete."); + ElementNameCB *elementNameCB = static_cast(data); + napi_value callback = nullptr; + napi_value undefined = nullptr; + napi_value result[ARGS_TWO] = {nullptr}; + napi_value callResult = nullptr; + NAPI_CALL_RETURN_VOID(env, napi_get_undefined(env, &undefined)); + result[PARAM0] = GetCallbackErrorValue(env, elementNameCB->cbBase.errCode); + if (elementNameCB->cbBase.errCode == NAPI_ERR_NO_ERROR) { + result[PARAM1] = WrapElementName(env, elementNameCB); + } else { + result[PARAM1] = WrapUndefinedToJS(env); + } + NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, elementNameCB->cbBase.cbInfo.callback, &callback)); + NAPI_CALL_RETURN_VOID(env, napi_call_function(env, undefined, callback, ARGS_TWO, &result[PARAM0], &callResult)); + + if (elementNameCB->cbBase.cbInfo.callback != nullptr) { + NAPI_CALL_RETURN_VOID(env, napi_delete_reference(env, elementNameCB->cbBase.cbInfo.callback)); + } + NAPI_CALL_RETURN_VOID(env, napi_delete_async_work(env, elementNameCB->cbBase.asyncWork)); + delete elementNameCB; + elementNameCB = nullptr; + HILOG_INFO("NAPI_GetElementName, main event thread complete end."); +} + +/** + * @brief The callback at the end of the Promise callback. + * + * @param env The environment that the Node-API call is invoked under. + * @param data Point to asynchronous processing of data. + */ +void GetElementNamePromiseCompleteCB(napi_env env, napi_status status, void *data) +{ + HILOG_INFO("NAPI_GetElementName, main event thread complete."); + ElementNameCB *elementNameCB = static_cast(data); + napi_value result = nullptr; + if (elementNameCB->cbBase.errCode == NAPI_ERR_NO_ERROR) { + result = WrapElementName(env, elementNameCB); + napi_resolve_deferred(env, elementNameCB->cbBase.deferred, result); + } else { + result = GetCallbackErrorValue(env, elementNameCB->cbBase.errCode); + napi_reject_deferred(env, elementNameCB->cbBase.deferred, result); + } + + napi_delete_async_work(env, elementNameCB->cbBase.asyncWork); + delete elementNameCB; + elementNameCB = nullptr; + HILOG_INFO("NAPI_GetElementName, main event thread complete end."); +} + +/** + * @brief GetElementName Promise. + * + * @param env The environment that the Node-API call is invoked under. + * @param elementNameCB Process data asynchronously. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value GetElementNamePromise(napi_env env, ElementNameCB *elementNameCB) +{ + HILOG_INFO("%{public}s, promise.", __func__); + if (elementNameCB == nullptr) { + HILOG_ERROR("%{public}s, param == nullptr.", __func__); + return nullptr; + } + napi_value resourceName = nullptr; + NAPI_CALL(env, napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName)); + napi_deferred deferred; + napi_value promise = nullptr; + NAPI_CALL(env, napi_create_promise(env, &deferred, &promise)); + elementNameCB->cbBase.deferred = deferred; + + NAPI_CALL(env, + napi_create_async_work(env, + nullptr, + resourceName, + GetElementNameExecuteCB, + GetElementNamePromiseCompleteCB, + (void *)elementNameCB, + &elementNameCB->cbBase.asyncWork)); + NAPI_CALL(env, napi_queue_async_work(env, elementNameCB->cbBase.asyncWork)); + HILOG_INFO("%{public}s, promise end.", __func__); + return promise; +} + +/** + * @brief GetElementName Async. + * + * @param env The environment that the Node-API call is invoked under. + * @param args Indicates the arguments passed into the callback. + * @param argcPromise Asynchronous data processing. + * @param elementNameCB Process data asynchronously. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value GetElementNameAsync(napi_env env, napi_value *args, const size_t argCallback, ElementNameCB *elementNameCB) +{ + HILOG_INFO("%{public}s, asyncCallback.", __func__); + if (args == nullptr || elementNameCB == nullptr) { + HILOG_ERROR("%{public}s, param == nullptr.", __func__); + return nullptr; + } + napi_value resourceName = nullptr; + NAPI_CALL(env, napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName)); + + napi_valuetype valuetype = napi_undefined; + NAPI_CALL(env, napi_typeof(env, args[argCallback], &valuetype)); + if (valuetype == napi_function) { + NAPI_CALL(env, napi_create_reference(env, args[argCallback], 1, &elementNameCB->cbBase.cbInfo.callback)); + } + NAPI_CALL(env, + napi_create_async_work(env, + nullptr, + resourceName, + GetElementNameExecuteCB, + GetElementNameAsyncCompleteCB, + (void *)elementNameCB, + &elementNameCB->cbBase.asyncWork)); + NAPI_CALL(env, napi_queue_async_work(env, elementNameCB->cbBase.asyncWork)); + napi_value result = nullptr; + NAPI_CALL(env, napi_get_null(env, &result)); + return result; + HILOG_INFO("%{public}s, asyncCallback end.", __func__); +} + +/** + * @brief GetElementName processing function. + * + * @param env The environment that the Node-API call is invoked under. + * @param elementNameCB Process data asynchronously. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value GetElementNameWrap(napi_env env, napi_callback_info info, ElementNameCB *elementNameCB) +{ + HILOG_INFO("%{public}s, asyncCallback.", __func__); + if (elementNameCB == nullptr) { + HILOG_ERROR("%{public}s, appInfoCB == nullptr.", __func__); + return nullptr; + } + + size_t argcAsync = 1; + const size_t argcPromise = 0; + const size_t argCountWithAsync = argcPromise + ARGS_ASYNC_COUNT; + napi_value args[ARGS_MAX_COUNT] = {nullptr}; + napi_value ret = nullptr; + + NAPI_CALL(env, napi_get_cb_info(env, info, &argcAsync, args, nullptr, nullptr)); + if (argcAsync > argCountWithAsync || argcAsync > ARGS_MAX_COUNT) { + HILOG_ERROR("%{public}s, Wrong argument count.", __func__); + return nullptr; + } + + if (argcAsync > argcPromise) { + ret = GetElementNameAsync(env, args, 0, elementNameCB); + } else { + ret = GetElementNamePromise(env, elementNameCB); + } + HILOG_INFO("%{public}s, asyncCallback end.", __func__); + return ret; +} + +/** + * @brief Create asynchronous data. + * + * @param env The environment that the Node-API call is invoked under. + * + * @return Return a pointer to ProcessNameCB on success, nullptr on failure. + */ +ProcessNameCB *CreateProcessNameCBInfo(napi_env env) +{ + HILOG_INFO("%{public}s called.", __func__); + napi_value global = nullptr; + NAPI_CALL(env, napi_get_global(env, &global)); + + napi_value abilityObj = nullptr; + NAPI_CALL(env, napi_get_named_property(env, global, "ability", &abilityObj)); + + Ability *ability = nullptr; + NAPI_CALL(env, napi_get_value_external(env, abilityObj, (void **)&ability)); + + ProcessNameCB *processNameCB = new (std::nothrow) ProcessNameCB; + if (processNameCB == nullptr) { + HILOG_ERROR("%{public}s, processNameCB == nullptr.", __func__); + return nullptr; + } + processNameCB->cbBase.cbInfo.env = env; + processNameCB->cbBase.asyncWork = nullptr; + processNameCB->cbBase.deferred = nullptr; + processNameCB->cbBase.ability = ability; + + HILOG_INFO("%{public}s end.", __func__); + return processNameCB; +} + +/** + * @brief GetProcessName asynchronous processing function. + * + * @param env The environment that the Node-API call is invoked under. + * @param data Point to asynchronous processing of data. + */ +void GetProcessNameExecuteCB(napi_env env, void *data) +{ + HILOG_INFO("NAPI_GetProcessName, worker pool thread execute."); + ProcessNameCB *processNameCB = static_cast(data); + if (processNameCB == nullptr) { + HILOG_ERROR("NAPI_GetProcessName, processNameCB == nullptr"); + return; + } + + processNameCB->cbBase.errCode = NAPI_ERR_NO_ERROR; + if (processNameCB->cbBase.ability == nullptr) { + HILOG_ERROR("NAPI_GetProcessName, ability == nullptr"); + processNameCB->cbBase.errCode = NAPI_ERR_ACE_ABILITY; + return; + } + + processNameCB->processName = processNameCB->cbBase.ability->GetProcessName(); + HILOG_INFO("NAPI_GetProcessName, worker pool thread execute end."); +} + +napi_value WrapProcessName(napi_env env, ProcessNameCB *processNameCB) +{ + HILOG_INFO("%{public}s, called.", __func__); + if (processNameCB == nullptr) { + HILOG_ERROR("%{public}s, Invalid param(processNameCB == nullptr)", __func__); + return nullptr; + } + napi_value result = nullptr; + NAPI_CALL(env, napi_create_string_utf8(env, processNameCB->processName.c_str(), NAPI_AUTO_LENGTH, &result)); + HILOG_INFO("%{public}s, end.", __func__); + return result; +} + +/** + * @brief The callback at the end of the asynchronous callback. + * + * @param env The environment that the Node-API call is invoked under. + * @param data Point to asynchronous processing of data. + */ +void GetProcessNameAsyncCompleteCB(napi_env env, napi_status status, void *data) +{ + HILOG_INFO("NAPI_GetProcessName, main event thread complete."); + ProcessNameCB *processNameCB = static_cast(data); + napi_value callback = nullptr; + napi_value undefined = nullptr; + napi_value result[ARGS_TWO] = {nullptr}; + napi_value callResult = nullptr; + NAPI_CALL_RETURN_VOID(env, napi_get_undefined(env, &undefined)); + result[PARAM0] = GetCallbackErrorValue(env, processNameCB->cbBase.errCode); + if (processNameCB->cbBase.errCode == NAPI_ERR_NO_ERROR) { + result[PARAM1] = WrapProcessName(env, processNameCB); + } else { + result[PARAM1] = WrapUndefinedToJS(env); + } + NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, processNameCB->cbBase.cbInfo.callback, &callback)); + NAPI_CALL_RETURN_VOID(env, napi_call_function(env, undefined, callback, ARGS_TWO, &result[PARAM0], &callResult)); + + if (processNameCB->cbBase.cbInfo.callback != nullptr) { + NAPI_CALL_RETURN_VOID(env, napi_delete_reference(env, processNameCB->cbBase.cbInfo.callback)); + } + NAPI_CALL_RETURN_VOID(env, napi_delete_async_work(env, processNameCB->cbBase.asyncWork)); + delete processNameCB; + processNameCB = nullptr; + HILOG_INFO("NAPI_GetProcessName, main event thread complete end."); +} + +/** + * @brief The callback at the end of the Promise callback. + * + * @param env The environment that the Node-API call is invoked under. + * @param data Point to asynchronous processing of data. + */ +void GetProcessNamePromiseCompleteCB(napi_env env, napi_status status, void *data) +{ + HILOG_INFO("NAPI_GetProcessName, main event thread complete."); + ProcessNameCB *processNameCB = static_cast(data); + napi_value result = nullptr; + if (processNameCB->cbBase.errCode == NAPI_ERR_NO_ERROR) { + result = WrapProcessName(env, processNameCB); + napi_resolve_deferred(env, processNameCB->cbBase.deferred, result); + } else { + result = GetCallbackErrorValue(env, processNameCB->cbBase.errCode); + napi_reject_deferred(env, processNameCB->cbBase.deferred, result); + } + + napi_delete_async_work(env, processNameCB->cbBase.asyncWork); + delete processNameCB; + processNameCB = nullptr; + HILOG_INFO("NAPI_GetProcessName, main event thread complete end."); +} + +/** + * @brief GetProcessName Async. + * + * @param env The environment that the Node-API call is invoked under. + * @param args Indicates the arguments passed into the callback. + * @param argcPromise Asynchronous data processing. + * @param ProcessNameCB Process data asynchronously. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value GetProcessNameAsync(napi_env env, napi_value *args, const size_t argCallback, ProcessNameCB *processNameCB) +{ + HILOG_INFO("%{public}s, asyncCallback.", __func__); + if (args == nullptr || processNameCB == nullptr) { + HILOG_ERROR("%{public}s, param == nullptr.", __func__); + return nullptr; + } + napi_value resourceName = nullptr; + NAPI_CALL(env, napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName)); + + napi_valuetype valuetype = napi_undefined; + NAPI_CALL(env, napi_typeof(env, args[argCallback], &valuetype)); + if (valuetype == napi_function) { + NAPI_CALL(env, napi_create_reference(env, args[argCallback], 1, &processNameCB->cbBase.cbInfo.callback)); + } + NAPI_CALL(env, + napi_create_async_work(env, + nullptr, + resourceName, + GetProcessNameExecuteCB, + GetProcessNameAsyncCompleteCB, + (void *)processNameCB, + &processNameCB->cbBase.asyncWork)); + NAPI_CALL(env, napi_queue_async_work(env, processNameCB->cbBase.asyncWork)); + napi_value result = nullptr; + NAPI_CALL(env, napi_get_null(env, &result)); + HILOG_INFO("%{public}s, asyncCallback end.", __func__); + return result; +} + +/** + * @brief GetProcessName Promise. + * + * @param env The environment that the Node-API call is invoked under. + * @param ProcessNameCB Process data asynchronously. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value GetProcessNamePromise(napi_env env, ProcessNameCB *processNameCB) +{ + HILOG_INFO("%{public}s, promise.", __func__); + if (processNameCB == nullptr) { + HILOG_ERROR("%{public}s, param == nullptr.", __func__); + return nullptr; + } + napi_value resourceName = nullptr; + NAPI_CALL(env, napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName)); + napi_deferred deferred; + napi_value promise = nullptr; + NAPI_CALL(env, napi_create_promise(env, &deferred, &promise)); + processNameCB->cbBase.deferred = deferred; + + NAPI_CALL(env, + napi_create_async_work(env, + nullptr, + resourceName, + GetProcessNameExecuteCB, + GetProcessNamePromiseCompleteCB, + (void *)processNameCB, + &processNameCB->cbBase.asyncWork)); + NAPI_CALL(env, napi_queue_async_work(env, processNameCB->cbBase.asyncWork)); + HILOG_INFO("%{public}s, promise end.", __func__); + return promise; +} + +/** + * @brief GetProcessName processing function. + * + * @param env The environment that the Node-API call is invoked under. + * @param ProcessNameCB Process data asynchronously. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value GetProcessNameWrap(napi_env env, napi_callback_info info, ProcessNameCB *processNameCB) +{ + HILOG_INFO("%{public}s, asyncCallback.", __func__); + if (processNameCB == nullptr) { + HILOG_ERROR("%{public}s, processNameCB == nullptr.", __func__); + return nullptr; + } + + size_t argcAsync = 1; + const size_t argcPromise = 0; + const size_t argCountWithAsync = argcPromise + ARGS_ASYNC_COUNT; + napi_value args[ARGS_MAX_COUNT] = {nullptr}; + napi_value ret = nullptr; + + NAPI_CALL(env, napi_get_cb_info(env, info, &argcAsync, args, nullptr, nullptr)); + if (argcAsync > argCountWithAsync || argcAsync > ARGS_MAX_COUNT) { + HILOG_ERROR("%{public}s, Wrong argument count.", __func__); + return nullptr; + } + + if (argcAsync > argcPromise) { + ret = GetProcessNameAsync(env, args, 0, processNameCB); + } else { + ret = GetProcessNamePromise(env, processNameCB); + } + HILOG_INFO("%{public}s, asyncCallback end.", __func__); + return ret; +} + +/** + * @brief Create asynchronous data. + * + * @param env The environment that the Node-API call is invoked under. + * + * @return Return a pointer to CallingBundleCB on success, nullptr on failure. + */ +CallingBundleCB *CreateCallingBundleCBInfo(napi_env env) +{ + HILOG_INFO("%{public}s called.", __func__); + napi_value global = nullptr; + NAPI_CALL(env, napi_get_global(env, &global)); + + napi_value abilityObj = nullptr; + NAPI_CALL(env, napi_get_named_property(env, global, "ability", &abilityObj)); + + Ability *ability = nullptr; + NAPI_CALL(env, napi_get_value_external(env, abilityObj, (void **)&ability)); + + CallingBundleCB *callingBundleCB = new (std::nothrow) CallingBundleCB; + if (callingBundleCB == nullptr) { + HILOG_ERROR("%{public}s, callingBundleCB == nullptr.", __func__); + return nullptr; + } + callingBundleCB->cbBase.cbInfo.env = env; + callingBundleCB->cbBase.asyncWork = nullptr; + callingBundleCB->cbBase.deferred = nullptr; + callingBundleCB->cbBase.ability = ability; + + HILOG_INFO("%{public}s end.", __func__); + return callingBundleCB; +} + +/** + * @brief GetCallingBundle asynchronous processing function. + * + * @param env The environment that the Node-API call is invoked under. + * @param data Point to asynchronous processing of data. + */ +void GetCallingBundleExecuteCB(napi_env env, void *data) +{ + HILOG_INFO("NAPI_GetCallingBundle, worker pool thread execute."); + CallingBundleCB *callingBundleCB = static_cast(data); + if (callingBundleCB == nullptr) { + HILOG_ERROR("NAPI_GetCallingBundle, callingBundleCB == nullptr"); + return; + } + + callingBundleCB->cbBase.errCode = NAPI_ERR_NO_ERROR; + if (callingBundleCB->cbBase.ability == nullptr) { + HILOG_ERROR("NAPI_GetCallingBundle, ability == nullptr"); + callingBundleCB->cbBase.errCode = NAPI_ERR_ACE_ABILITY; + return; + } + + callingBundleCB->callingBundleName = callingBundleCB->cbBase.ability->GetCallingBundle(); + HILOG_INFO("NAPI_GetCallingBundle, worker pool thread execute end."); +} + +napi_value WrapCallingBundle(napi_env env, CallingBundleCB *callingBundleCB) +{ + HILOG_INFO("%{public}s, called.", __func__); + if (callingBundleCB == nullptr) { + HILOG_ERROR("%{public}s,Invalid param(callingBundleCB == nullptr)", __func__); + return nullptr; + } + napi_value result = nullptr; + NAPI_CALL(env, napi_create_string_utf8(env, callingBundleCB->callingBundleName.c_str(), NAPI_AUTO_LENGTH, &result)); + HILOG_INFO("%{public}s, end.", __func__); + return result; +} + +/** + * @brief The callback at the end of the asynchronous callback. + * + * @param env The environment that the Node-API call is invoked under. + * @param data Point to asynchronous processing of data. + */ +void GetCallingBundleAsyncCompleteCB(napi_env env, napi_status status, void *data) +{ + HILOG_INFO("NAPI_GetCallingBundle, main event thread complete."); + CallingBundleCB *callingBundleCB = static_cast(data); + napi_value callback = nullptr; + napi_value undefined = nullptr; + napi_value result[ARGS_TWO] = {nullptr}; + napi_value callResult = nullptr; + NAPI_CALL_RETURN_VOID(env, napi_get_undefined(env, &undefined)); + result[PARAM0] = GetCallbackErrorValue(env, callingBundleCB->cbBase.errCode); + if (callingBundleCB->cbBase.errCode == NAPI_ERR_NO_ERROR) { + result[PARAM1] = WrapCallingBundle(env, callingBundleCB); + } else { + result[PARAM1] = WrapUndefinedToJS(env); + } + NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, callingBundleCB->cbBase.cbInfo.callback, &callback)); + NAPI_CALL_RETURN_VOID(env, napi_call_function(env, undefined, callback, ARGS_TWO, &result[PARAM0], &callResult)); + + if (callingBundleCB->cbBase.cbInfo.callback != nullptr) { + NAPI_CALL_RETURN_VOID(env, napi_delete_reference(env, callingBundleCB->cbBase.cbInfo.callback)); + } + NAPI_CALL_RETURN_VOID(env, napi_delete_async_work(env, callingBundleCB->cbBase.asyncWork)); + delete callingBundleCB; + callingBundleCB = nullptr; + HILOG_INFO("NAPI_GetCallingBundle, main event thread complete end."); +} + +/** + * @brief The callback at the end of the Promise callback. + * + * @param env The environment that the Node-API call is invoked under. + * @param data Point to asynchronous processing of data. + */ +void GetCallingBundlePromiseCompleteCB(napi_env env, napi_status status, void *data) +{ + HILOG_INFO("NAPI_GetCallingBundle, main event thread complete."); + CallingBundleCB *callingBundleCB = static_cast(data); + napi_value result = nullptr; + if (callingBundleCB->cbBase.errCode == NAPI_ERR_NO_ERROR) { + result = WrapCallingBundle(env, callingBundleCB); + napi_resolve_deferred(env, callingBundleCB->cbBase.deferred, result); + } else { + result = GetCallbackErrorValue(env, callingBundleCB->cbBase.errCode); + napi_reject_deferred(env, callingBundleCB->cbBase.deferred, result); + } + + napi_delete_async_work(env, callingBundleCB->cbBase.asyncWork); + delete callingBundleCB; + callingBundleCB = nullptr; + HILOG_INFO("NAPI_GetCallingBundle, main event thread complete end."); +} + +/** + * @brief GetCallingBundle Async. + * + * @param env The environment that the Node-API call is invoked under. + * @param args Indicates the arguments passed into the callback. + * @param argcPromise Asynchronous data processing. + * @param CallingBundleCB Process data asynchronously. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value GetCallingBundleAsync( + napi_env env, napi_value *args, const size_t argCallback, CallingBundleCB *callingBundleCB) +{ + HILOG_INFO("%{public}s, asyncCallback.", __func__); + if (args == nullptr || callingBundleCB == nullptr) { + HILOG_ERROR("%{public}s, param == nullptr.", __func__); + return nullptr; + } + napi_value resourceName = nullptr; + NAPI_CALL(env, napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName)); + + napi_valuetype valuetype = napi_undefined; + NAPI_CALL(env, napi_typeof(env, args[argCallback], &valuetype)); + if (valuetype == napi_function) { + NAPI_CALL(env, napi_create_reference(env, args[argCallback], 1, &callingBundleCB->cbBase.cbInfo.callback)); + } + NAPI_CALL(env, + napi_create_async_work(env, + nullptr, + resourceName, + GetCallingBundleExecuteCB, + GetCallingBundleAsyncCompleteCB, + (void *)callingBundleCB, + &callingBundleCB->cbBase.asyncWork)); + NAPI_CALL(env, napi_queue_async_work(env, callingBundleCB->cbBase.asyncWork)); + napi_value result = nullptr; + NAPI_CALL(env, napi_get_null(env, &result)); + HILOG_INFO("%{public}s, asyncCallback end.", __func__); + return result; +} + +/** + * @brief GetCallingBundle Promise. + * + * @param env The environment that the Node-API call is invoked under. + * @param CallingBundleCB Process data asynchronously. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value GetCallingBundlePromise(napi_env env, CallingBundleCB *callingBundleCB) +{ + HILOG_INFO("%{public}s, promise.", __func__); + if (callingBundleCB == nullptr) { + HILOG_ERROR("%{public}s, param == nullptr.", __func__); + return nullptr; + } + napi_value resourceName = nullptr; + NAPI_CALL(env, napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName)); + napi_deferred deferred; + napi_value promise = nullptr; + NAPI_CALL(env, napi_create_promise(env, &deferred, &promise)); + callingBundleCB->cbBase.deferred = deferred; + + NAPI_CALL(env, + napi_create_async_work(env, + nullptr, + resourceName, + GetCallingBundleExecuteCB, + GetCallingBundlePromiseCompleteCB, + (void *)callingBundleCB, + &callingBundleCB->cbBase.asyncWork)); + NAPI_CALL(env, napi_queue_async_work(env, callingBundleCB->cbBase.asyncWork)); + HILOG_INFO("%{public}s, promise end.", __func__); + return promise; +} + +/** + * @brief GetCallingBundle processing function. + * + * @param env The environment that the Node-API call is invoked under. + * @param CallingBundleCB Process data asynchronously. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value GetCallingBundleWrap(napi_env env, napi_callback_info info, CallingBundleCB *callingBundleCB) +{ + HILOG_INFO("%{public}s, asyncCallback.", __func__); + if (callingBundleCB == nullptr) { + HILOG_ERROR("%{public}s, callingBundleCB == nullptr.", __func__); + return nullptr; + } + + size_t argcAsync = 1; + const size_t argcPromise = 0; + const size_t argCountWithAsync = argcPromise + ARGS_ASYNC_COUNT; + napi_value args[ARGS_MAX_COUNT] = {nullptr}; + napi_value ret = nullptr; + + NAPI_CALL(env, napi_get_cb_info(env, info, &argcAsync, args, nullptr, nullptr)); + if (argcAsync > argCountWithAsync || argcAsync > ARGS_MAX_COUNT) { + HILOG_ERROR("%{public}s, Wrong argument count.", __func__); + return nullptr; + } + + if (argcAsync > argcPromise) { + ret = GetCallingBundleAsync(env, args, 0, callingBundleCB); + } else { + ret = GetCallingBundlePromise(env, callingBundleCB); + } + HILOG_INFO("%{public}s, asyncCallback end.", __func__); + return ret; +} + +/** + * @brief Create asynchronous data. + * + * @param env The environment that the Node-API call is invoked under. + * + * @return Return a pointer to CallingBundleCB on success, nullptr on failure. + */ +GetOrCreateLocalDirCB *CreateGetOrCreateLocalDirCBInfo(napi_env env) +{ + HILOG_INFO("%{public}s called.", __func__); + napi_value global = nullptr; + NAPI_CALL(env, napi_get_global(env, &global)); + + napi_value abilityObj = nullptr; + NAPI_CALL(env, napi_get_named_property(env, global, "ability", &abilityObj)); + + Ability *ability = nullptr; + NAPI_CALL(env, napi_get_value_external(env, abilityObj, (void **)&ability)); + + GetOrCreateLocalDirCB *getOrCreateLocalDirCB = new (std::nothrow) GetOrCreateLocalDirCB; + if (getOrCreateLocalDirCB == nullptr) { + HILOG_ERROR("%{public}s, getOrCreateLocalDirCB == nullptr.", __func__); + return nullptr; + } + getOrCreateLocalDirCB->cbBase.cbInfo.env = env; + getOrCreateLocalDirCB->cbBase.asyncWork = nullptr; + getOrCreateLocalDirCB->cbBase.deferred = nullptr; + getOrCreateLocalDirCB->cbBase.ability = ability; + + HILOG_INFO("%{public}s end.", __func__); + return getOrCreateLocalDirCB; +} + +/** + * @brief GetOrCreateLocalDir asynchronous processing function. + * + * @param env The environment that the Node-API call is invoked under. + * @param data Point to asynchronous processing of data. + */ +void GetOrCreateLocalDirExecuteCB(napi_env env, void *data) +{ + HILOG_INFO("NAPI_GetOrCreateLocalDir, worker pool thread execute."); + GetOrCreateLocalDirCB *getOrCreateLocalDirCB = static_cast(data); + if (getOrCreateLocalDirCB == nullptr) { + HILOG_ERROR("NAPI_GetOrCreateLocalDir, callingBundleCB == nullptr"); + return; + } + + getOrCreateLocalDirCB->cbBase.errCode = NAPI_ERR_NO_ERROR; + if (getOrCreateLocalDirCB->cbBase.ability == nullptr) { + HILOG_ERROR("NAPI_GetOrCreateLocalDir, ability == nullptr"); + getOrCreateLocalDirCB->cbBase.errCode = NAPI_ERR_ACE_ABILITY; + return; + } + + std::string abilityName = getOrCreateLocalDirCB->cbBase.ability->GetAbilityInfo()->name; + std::string dataDir = getOrCreateLocalDirCB->cbBase.ability->GetAbilityInfo()->applicationInfo.dataDir; + std::shared_ptr hap = getOrCreateLocalDirCB->cbBase.ability->GetHapModuleInfo(); + std::string moduleName = (hap != nullptr) ? hap->name : std::string(); + std::string dataDirWithModuleName = dataDir + NAPI_CONTEXT_FILE_SEPARATOR + moduleName; + HILOG_INFO("NAPI_GetOrCreateLocalDir, dataDir:%{public}s moduleName:%{public}s abilityName:%{public}s", + dataDir.c_str(), + moduleName.c_str(), + abilityName.c_str()); + + // if dataDirWithModuleName is not exits, do nothing and return. + if (!OHOS::FileExists(dataDirWithModuleName)) { + getOrCreateLocalDirCB->rootDir = ""; + HILOG_INFO("NAPI_GetOrCreateLocalDir, dirWithModuleName is not exits:%{public}s, do nothing and return null.", + dataDirWithModuleName.c_str()); + return; + } + + getOrCreateLocalDirCB->rootDir = dataDirWithModuleName + NAPI_CONTEXT_FILE_SEPARATOR + abilityName; + HILOG_INFO("NAPI_GetOrCreateLocalDir, GetDir rootDir:%{public}s", getOrCreateLocalDirCB->rootDir.c_str()); + if (!OHOS::FileExists(getOrCreateLocalDirCB->rootDir)) { + HILOG_INFO("NAPI_GetOrCreateLocalDir dir is not exits, create dir."); + OHOS::ForceCreateDirectory(getOrCreateLocalDirCB->rootDir); + OHOS::ChangeModeDirectory(getOrCreateLocalDirCB->rootDir, MODE); + } + HILOG_INFO("NAPI_GetOrCreateLocalDir, worker pool thread execute end."); +} + +napi_value WrapGetOrCreateLocalDir(napi_env env, GetOrCreateLocalDirCB *getOrCreateLocalDirCB) +{ + HILOG_INFO("%{public}s, called.", __func__); + if (getOrCreateLocalDirCB == nullptr) { + HILOG_ERROR("%{public}s,Invalid param(getOrCreateLocalDirCB == nullptr)", __func__); + return nullptr; + } + napi_value result = nullptr; + NAPI_CALL(env, napi_create_string_utf8(env, getOrCreateLocalDirCB->rootDir.c_str(), NAPI_AUTO_LENGTH, &result)); + HILOG_INFO("%{public}s, end.", __func__); + return result; +} + +/** + * @brief The callback at the end of the asynchronous callback. + * + * @param env The environment that the Node-API call is invoked under. + * @param data Point to asynchronous processing of data. + */ +void GetOrCreateLocalDirAsyncCompleteCB(napi_env env, napi_status status, void *data) +{ + HILOG_INFO("NAPI_GetOrCreateLocalDir, main event thread complete."); + GetOrCreateLocalDirCB *getOrCreateLocalDirCB = static_cast(data); + napi_value callback = nullptr; + napi_value undefined = nullptr; + napi_value result[ARGS_TWO] = {nullptr}; + napi_value callResult = nullptr; + NAPI_CALL_RETURN_VOID(env, napi_get_undefined(env, &undefined)); + result[PARAM0] = GetCallbackErrorValue(env, getOrCreateLocalDirCB->cbBase.errCode); + if (getOrCreateLocalDirCB->cbBase.errCode == NAPI_ERR_NO_ERROR) { + result[PARAM1] = WrapGetOrCreateLocalDir(env, getOrCreateLocalDirCB); + } else { + result[PARAM1] = WrapUndefinedToJS(env); + } + NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, getOrCreateLocalDirCB->cbBase.cbInfo.callback, &callback)); + NAPI_CALL_RETURN_VOID(env, napi_call_function(env, undefined, callback, ARGS_TWO, &result[PARAM0], &callResult)); + + if (getOrCreateLocalDirCB->cbBase.cbInfo.callback != nullptr) { + NAPI_CALL_RETURN_VOID(env, napi_delete_reference(env, getOrCreateLocalDirCB->cbBase.cbInfo.callback)); + } + NAPI_CALL_RETURN_VOID(env, napi_delete_async_work(env, getOrCreateLocalDirCB->cbBase.asyncWork)); + delete getOrCreateLocalDirCB; + getOrCreateLocalDirCB = nullptr; + HILOG_INFO("NAPI_GetOrCreateLocalDir, main event thread complete end."); +} + +/** + * @brief The callback at the end of the Promise callback. + * + * @param env The environment that the Node-API call is invoked under. + * @param data Point to asynchronous processing of data. + */ +void GetOrCreateLocalDirPromiseCompleteCB(napi_env env, napi_status status, void *data) +{ + HILOG_INFO("NAPI_GetOrCreateLocalDir, main event thread complete."); + GetOrCreateLocalDirCB *getOrCreateLocalDirCB = static_cast(data); + napi_value result = nullptr; + if (getOrCreateLocalDirCB->cbBase.errCode == NAPI_ERR_NO_ERROR) { + result = WrapGetOrCreateLocalDir(env, getOrCreateLocalDirCB); + napi_resolve_deferred(env, getOrCreateLocalDirCB->cbBase.deferred, result); + } else { + result = GetCallbackErrorValue(env, getOrCreateLocalDirCB->cbBase.errCode); + napi_reject_deferred(env, getOrCreateLocalDirCB->cbBase.deferred, result); + } + + napi_delete_async_work(env, getOrCreateLocalDirCB->cbBase.asyncWork); + delete getOrCreateLocalDirCB; + getOrCreateLocalDirCB = nullptr; + HILOG_INFO("NAPI_GetOrCreateLocalDir, main event thread complete end."); +} + +/** + * @brief GetOrCreateLocalDir Async. + * + * @param env The environment that the Node-API call is invoked under. + * @param args Indicates the arguments passed into the callback. + * @param argcPromise Asynchronous data processing. + * @param CallingBundleCB Process data asynchronously. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value GetOrCreateLocalDirAsync( + napi_env env, napi_value *args, const size_t argCallback, GetOrCreateLocalDirCB *getOrCreateLocalDirCB) +{ + HILOG_INFO("%{public}s, asyncCallback.", __func__); + if (args == nullptr || getOrCreateLocalDirCB == nullptr) { + HILOG_ERROR("%{public}s, param == nullptr.", __func__); + return nullptr; + } + napi_value resourceName = nullptr; + NAPI_CALL(env, napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName)); + + napi_valuetype valuetype = napi_undefined; + NAPI_CALL(env, napi_typeof(env, args[argCallback], &valuetype)); + if (valuetype == napi_function) { + NAPI_CALL( + env, napi_create_reference(env, args[argCallback], 1, &getOrCreateLocalDirCB->cbBase.cbInfo.callback)); + } + NAPI_CALL(env, + napi_create_async_work(env, + nullptr, + resourceName, + GetOrCreateLocalDirExecuteCB, + GetOrCreateLocalDirAsyncCompleteCB, + (void *)getOrCreateLocalDirCB, + &getOrCreateLocalDirCB->cbBase.asyncWork)); + NAPI_CALL(env, napi_queue_async_work(env, getOrCreateLocalDirCB->cbBase.asyncWork)); + napi_value result = nullptr; + NAPI_CALL(env, napi_get_null(env, &result)); + HILOG_INFO("%{public}s, asyncCallback end.", __func__); + return result; +} + +/** + * @brief GetOrCreateLocalDir Promise. + * + * @param env The environment that the Node-API call is invoked under. + * @param CallingBundleCB Process data asynchronously. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value GetOrCreateLocalDirPromise(napi_env env, GetOrCreateLocalDirCB *getOrCreateLocalDirCB) +{ + HILOG_INFO("%{public}s, promise.", __func__); + if (getOrCreateLocalDirCB == nullptr) { + HILOG_ERROR("%{public}s, param == nullptr.", __func__); + return nullptr; + } + napi_value resourceName = nullptr; + NAPI_CALL(env, napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName)); + napi_deferred deferred; + napi_value promise = nullptr; + NAPI_CALL(env, napi_create_promise(env, &deferred, &promise)); + getOrCreateLocalDirCB->cbBase.deferred = deferred; + + NAPI_CALL(env, + napi_create_async_work(env, + nullptr, + resourceName, + GetOrCreateLocalDirExecuteCB, + GetOrCreateLocalDirPromiseCompleteCB, + (void *)getOrCreateLocalDirCB, + &getOrCreateLocalDirCB->cbBase.asyncWork)); + NAPI_CALL(env, napi_queue_async_work(env, getOrCreateLocalDirCB->cbBase.asyncWork)); + HILOG_INFO("%{public}s, promise end.", __func__); + return promise; +} + +/** + * @brief GetOrCreateLocalDir processing function. + * + * @param env The environment that the Node-API call is invoked under. + * @param CallingBundleCB Process data asynchronously. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value GetOrCreateLocalDirWrap(napi_env env, napi_callback_info info, GetOrCreateLocalDirCB *getOrCreateLocalDirCB) +{ + HILOG_INFO("%{public}s, asyncCallback.", __func__); + if (getOrCreateLocalDirCB == nullptr) { + HILOG_ERROR("%{public}s, getOrCreateLocalDirCB == nullptr.", __func__); + return nullptr; + } + + size_t argcAsync = 1; + const size_t argcPromise = 0; + const size_t argCountWithAsync = argcPromise + ARGS_ASYNC_COUNT; + napi_value args[ARGS_MAX_COUNT] = {nullptr}; + napi_value ret = nullptr; + + NAPI_CALL(env, napi_get_cb_info(env, info, &argcAsync, args, nullptr, nullptr)); + if (argcAsync > argCountWithAsync || argcAsync > ARGS_MAX_COUNT) { + HILOG_ERROR("%{public}s, Wrong argument count.", __func__); + return nullptr; + } + + if (argcAsync > argcPromise) { + ret = GetOrCreateLocalDirAsync(env, args, 0, getOrCreateLocalDirCB); + } else { + ret = GetOrCreateLocalDirPromise(env, getOrCreateLocalDirCB); + } + HILOG_INFO("%{public}s, asyncCallback end.", __func__); + return ret; +} + +/** + * @brief Get bundle name. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_GetBundleName(napi_env env, napi_callback_info info) +{ + HILOG_INFO("%{public}s called", __func__); + AsyncJSCallbackInfo *asyncCallbackInfo = CreateAsyncJSCallbackInfo(env); + if (asyncCallbackInfo == nullptr) { + HILOG_INFO("%{public}s called. Invoke CreateAsyncJSCallbackInfo failed.", __func__); + return WrapVoidToJS(env); + } + + napi_value ret = NAPI_GetBundleNameWrap(env, info, asyncCallbackInfo); + if (ret == nullptr) { + HILOG_ERROR("%{public}s ret == nullptr", __func__); + FreeAsyncJSCallbackInfo(&asyncCallbackInfo); + ret = WrapVoidToJS(env); + } + HILOG_INFO("%{public}s end", __func__); + return ret; +} + +/** + * @brief Obtains information about the current application. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_GetApplicationInfo(napi_env env, napi_callback_info info) +{ + HILOG_INFO("%{public}s,called", __func__); + AppInfoCB *appInfoCB = CreateAppInfoCBInfo(env); + if (appInfoCB == nullptr) { + return WrapVoidToJS(env); + } + + napi_value ret = GetApplicationInfoWrap(env, info, appInfoCB); + if (ret == nullptr) { + HILOG_ERROR("%{public}s,ret == nullptr", __func__); + if (appInfoCB != nullptr) { + delete appInfoCB; + appInfoCB = nullptr; + } + ret = WrapVoidToJS(env); + } + HILOG_INFO("%{public}s,end", __func__); + return ret; +} + +/** + * @brief Obtains the process Info this application. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_GetProcessInfo(napi_env env, napi_callback_info info) +{ + HILOG_INFO("%{public}s called.", __func__); + ProcessInfoCB *processInfoCB = CreateProcessInfoCBInfo(env); + if (processInfoCB == nullptr) { + return WrapVoidToJS(env); + } + + processInfoCB->cbBase.errCode = NAPI_ERR_NO_ERROR; + napi_value ret = GetProcessInfoWrap(env, info, processInfoCB); + if (ret == nullptr) { + HILOG_ERROR("%{public}s, ret == nullptr.", __func__); + if (processInfoCB != nullptr) { + delete processInfoCB; + processInfoCB = nullptr; + } + ret = WrapVoidToJS(env); + } + HILOG_INFO("%{public}s, end.", __func__); + return ret; +} + +/** + * @brief Obtains the elementName object of the current ability. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_GetElementName(napi_env env, napi_callback_info info) +{ + HILOG_INFO("%{public}s called.", __func__); + ElementNameCB *elementNameCB = CreateElementNameCBInfo(env); + if (elementNameCB == nullptr) { + return WrapVoidToJS(env); + } + + elementNameCB->cbBase.errCode = NAPI_ERR_NO_ERROR; + napi_value ret = GetElementNameWrap(env, info, elementNameCB); + if (ret == nullptr) { + HILOG_ERROR("%{public}s ret == nullptr.", __func__); + if (elementNameCB != nullptr) { + delete elementNameCB; + elementNameCB = nullptr; + } + ret = WrapVoidToJS(env); + } + HILOG_INFO("%{public}s end.", __func__); + return ret; +} + +/** + * @brief Obtains the name of the current process. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_GetProcessName(napi_env env, napi_callback_info info) +{ + HILOG_INFO("%{public}s called.", __func__); + ProcessNameCB *processNameCB = CreateProcessNameCBInfo(env); + if (processNameCB == nullptr) { + return WrapVoidToJS(env); + } + + processNameCB->cbBase.errCode = NAPI_ERR_NO_ERROR; + napi_value ret = GetProcessNameWrap(env, info, processNameCB); + if (ret == nullptr) { + HILOG_ERROR("%{public}s ret == nullptr.", __func__); + if (processNameCB != nullptr) { + delete processNameCB; + processNameCB = nullptr; + } + ret = WrapVoidToJS(env); + } + HILOG_INFO("%{public}s end.", __func__); + return ret; +} + +/** + * @brief Obtains the bundle name of the ability that called the current ability. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_GetCallingBundle(napi_env env, napi_callback_info info) +{ + HILOG_INFO("%{public}s called.", __func__); + CallingBundleCB *callingBundleCB = CreateCallingBundleCBInfo(env); + if (callingBundleCB == nullptr) { + return WrapVoidToJS(env); + } + + callingBundleCB->cbBase.errCode = NAPI_ERR_NO_ERROR; + napi_value ret = GetCallingBundleWrap(env, info, callingBundleCB); + if (ret == nullptr) { + HILOG_ERROR("%{public}s ret == nullptr", __func__); + if (callingBundleCB != nullptr) { + delete callingBundleCB; + callingBundleCB = nullptr; + } + ret = WrapVoidToJS(env); + } + HILOG_INFO("%{public}s end.", __func__); + return ret; +} + +/** + * @brief Get the local root dir of an app. If it is the first call, the dir will be created. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_GetOrCreateLocalDir(napi_env env, napi_callback_info info) +{ + HILOG_INFO("%{public}s called.", __func__); + GetOrCreateLocalDirCB *getOrCreateLocalDirCB = CreateGetOrCreateLocalDirCBInfo(env); + if (getOrCreateLocalDirCB == nullptr) { + return WrapVoidToJS(env); + } + + getOrCreateLocalDirCB->cbBase.errCode = NAPI_ERR_NO_ERROR; + napi_value ret = GetOrCreateLocalDirWrap(env, info, getOrCreateLocalDirCB); + if (ret == nullptr) { + HILOG_ERROR("%{public}s ret == nullptr", __func__); + if (getOrCreateLocalDirCB != nullptr) { + delete getOrCreateLocalDirCB; + getOrCreateLocalDirCB = nullptr; + } + ret = WrapVoidToJS(env); + } + HILOG_INFO("%{public}s end.", __func__); + return ret; +} + +/** + * @brief Create asynchronous data. + * + * @param env The environment that the Node-API call is invoked under. + * + * @return Return a pointer to CallingBundleCB on success, nullptr on failure. + */ +DatabaseDirCB *CreateGetDatabaseDirCBInfo(napi_env env) +{ + HILOG_INFO("%{public}s called.", __func__); + napi_value global = nullptr; + NAPI_CALL(env, napi_get_global(env, &global)); + + napi_value abilityObj = nullptr; + NAPI_CALL(env, napi_get_named_property(env, global, "ability", &abilityObj)); + + Ability *ability = nullptr; + NAPI_CALL(env, napi_get_value_external(env, abilityObj, (void **)&ability)); + + DatabaseDirCB *getDatabaseDirCB = new (std::nothrow) DatabaseDirCB; + if (getDatabaseDirCB == nullptr) { + HILOG_ERROR("%{public}s, getDatabaseDirCB == nullptr.", __func__); + return nullptr; + } + getDatabaseDirCB->cbBase.cbInfo.env = env; + getDatabaseDirCB->cbBase.asyncWork = nullptr; + getDatabaseDirCB->cbBase.deferred = nullptr; + getDatabaseDirCB->cbBase.ability = ability; + + HILOG_INFO("%{public}s end.", __func__); + return getDatabaseDirCB; +} + +/** + * @brief GetOrCreateLocalDir processing function. + * + * @param env The environment that the Node-API call is invoked under. + * @param CallingBundleCB Process data asynchronously. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value GetDatabaseDirWrap(napi_env env, napi_callback_info info, DatabaseDirCB *getDatabaseDirCB) +{ + HILOG_INFO("%{public}s, called.", __func__); + if (getDatabaseDirCB == nullptr) { + HILOG_ERROR("%{public}s, getDatabaseDirCB == nullptr.", __func__); + return nullptr; + } + + getDatabaseDirCB->cbBase.errCode = NAPI_ERR_NO_ERROR; + if (getDatabaseDirCB->cbBase.ability == nullptr) { + HILOG_ERROR("NAPI_GetDatabaseDir, ability == nullptr"); + getDatabaseDirCB->cbBase.errCode = NAPI_ERR_ACE_ABILITY; + return nullptr; + } + + std::string abilityName = getDatabaseDirCB->cbBase.ability->GetAbilityInfo()->name; + std::string dataDir = getDatabaseDirCB->cbBase.ability->GetAbilityInfo()->applicationInfo.dataDir; + std::shared_ptr hap = getDatabaseDirCB->cbBase.ability->GetHapModuleInfo(); + std::string moduleName = (hap != nullptr) ? hap->name : std::string(); + std::string dataDirWithModuleName = dataDir + NAPI_CONTEXT_FILE_SEPARATOR + moduleName; + HILOG_INFO("%{public}s, dataDir:%{public}s moduleName:%{public}s abilityName:%{public}s", + __func__, + dataDir.c_str(), + moduleName.c_str(), + abilityName.c_str()); + + // if dataDirWithModuleName is not exits, do nothing and return. + if (!OHOS::FileExists(dataDirWithModuleName)) { + getDatabaseDirCB->dataBaseDir = ""; + HILOG_INFO("%{public}s, dirWithModuleName is not exits:%{public}s, do nothing and return null.", + __func__, + dataDirWithModuleName.c_str()); + } else { + getDatabaseDirCB->dataBaseDir = dataDirWithModuleName + NAPI_CONTEXT_FILE_SEPARATOR + abilityName + + NAPI_CONTEXT_FILE_SEPARATOR + NAPI_CONTEXT_DATABASE; + HILOG_INFO("%{public}s, GetDir dataBaseDir:%{public}s", __func__, getDatabaseDirCB->dataBaseDir.c_str()); + if (!OHOS::FileExists(getDatabaseDirCB->dataBaseDir)) { + HILOG_INFO("NAPI_GetDatabaseDir dir is not exits, create dir."); + OHOS::ForceCreateDirectory(getDatabaseDirCB->dataBaseDir); + OHOS::ChangeModeDirectory(getDatabaseDirCB->dataBaseDir, MODE); + } + } + napi_value result = nullptr; + NAPI_CALL(env, napi_create_string_utf8(env, getDatabaseDirCB->dataBaseDir.c_str(), NAPI_AUTO_LENGTH, &result)); + + HILOG_INFO("%{public}s, end.", __func__); + return result; +} + +/** + * @brief Obtains the local database path. If it is the first call, the dir will be created. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_GetDatabaseDirSync(napi_env env, napi_callback_info info) +{ + HILOG_INFO("%{public}s called.", __func__); + DatabaseDirCB *getDatabaseDirCB = CreateGetDatabaseDirCBInfo(env); + if (getDatabaseDirCB == nullptr) { + return WrapVoidToJS(env); + } + + getDatabaseDirCB->cbBase.errCode = NAPI_ERR_NO_ERROR; + napi_value ret = GetDatabaseDirWrap(env, info, getDatabaseDirCB); + + delete getDatabaseDirCB; + getDatabaseDirCB = nullptr; + + if (ret == nullptr) { + ret = WrapVoidToJS(env); + HILOG_ERROR("%{public}s ret == nullptr", __func__); + } else { + HILOG_INFO("%{public}s, end.", __func__); + } + return ret; +} + +/** + * @brief Create asynchronous data. + * + * @param env The environment that the Node-API call is invoked under. + * + * @return Return a pointer to CallingBundleCB on success, nullptr on failure. + */ +PreferencesDirCB *CreateGetPreferencesDirCBInfo(napi_env env) +{ + HILOG_INFO("%{public}s called.", __func__); + napi_value global = nullptr; + NAPI_CALL(env, napi_get_global(env, &global)); + + napi_value abilityObj = nullptr; + NAPI_CALL(env, napi_get_named_property(env, global, "ability", &abilityObj)); + + Ability *ability = nullptr; + NAPI_CALL(env, napi_get_value_external(env, abilityObj, (void **)&ability)); + + PreferencesDirCB *getPreferencesDirCB = new (std::nothrow) PreferencesDirCB; + if (getPreferencesDirCB == nullptr) { + HILOG_ERROR("%{public}s, getPreferencesDirCB == nullptr.", __func__); + return nullptr; + } + getPreferencesDirCB->cbBase.cbInfo.env = env; + getPreferencesDirCB->cbBase.asyncWork = nullptr; + getPreferencesDirCB->cbBase.deferred = nullptr; + getPreferencesDirCB->cbBase.ability = ability; + + HILOG_INFO("%{public}s end.", __func__); + return getPreferencesDirCB; +} + +/** + * @brief GetOrCreateLocalDir processing function. + * + * @param env The environment that the Node-API call is invoked under. + * @param CallingBundleCB Process data asynchronously. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value GetPreferencesDirWrap(napi_env env, napi_callback_info info, PreferencesDirCB *getPreferencesDirCB) +{ + HILOG_INFO("%{public}s, called.", __func__); + if (getPreferencesDirCB == nullptr) { + HILOG_ERROR("%{public}s, getPreferencesDirCB == nullptr.", __func__); + return nullptr; + } + + getPreferencesDirCB->cbBase.errCode = NAPI_ERR_NO_ERROR; + if (getPreferencesDirCB->cbBase.ability == nullptr) { + HILOG_ERROR("%{public}s, ability == nullptr", __func__); + getPreferencesDirCB->cbBase.errCode = NAPI_ERR_ACE_ABILITY; + return nullptr; + } + + std::string abilityName = getPreferencesDirCB->cbBase.ability->GetAbilityInfo()->name; + std::string dataDir = getPreferencesDirCB->cbBase.ability->GetAbilityInfo()->applicationInfo.dataDir; + std::shared_ptr hap = getPreferencesDirCB->cbBase.ability->GetHapModuleInfo(); + std::string moduleName = (hap != nullptr) ? hap->name : std::string(); + std::string dataDirWithModuleName = dataDir + NAPI_CONTEXT_FILE_SEPARATOR + moduleName; + HILOG_INFO("%{public}s, dataDir:%{public}s moduleName:%{public}s abilityName:%{public}s", + __func__, + dataDir.c_str(), + moduleName.c_str(), + abilityName.c_str()); + + // if dataDirWithModuleName is not exits, do nothing and return. + if (!OHOS::FileExists(dataDirWithModuleName)) { + getPreferencesDirCB->preferencesDir = ""; + HILOG_INFO("%{public}s, dirWithModuleName is not exits:%{public}s, do nothing and return null.", + __func__, + dataDirWithModuleName.c_str()); + } else { + getPreferencesDirCB->preferencesDir = dataDirWithModuleName + NAPI_CONTEXT_FILE_SEPARATOR + abilityName + + NAPI_CONTEXT_FILE_SEPARATOR + NAPI_CONTEXT_PREFERENCES; + HILOG_INFO( + "%{public}s, GetDir preferencesDir:%{public}s", __func__, getPreferencesDirCB->preferencesDir.c_str()); + if (!OHOS::FileExists(getPreferencesDirCB->preferencesDir)) { + HILOG_INFO("NAPI_GetPreferencesDir dir is not exits, create dir."); + OHOS::ForceCreateDirectory(getPreferencesDirCB->preferencesDir); + OHOS::ChangeModeDirectory(getPreferencesDirCB->preferencesDir, MODE); + } + } + napi_value result = nullptr; + NAPI_CALL( + env, napi_create_string_utf8(env, getPreferencesDirCB->preferencesDir.c_str(), NAPI_AUTO_LENGTH, &result)); + + HILOG_INFO("%{public}s, end.", __func__); + return result; +} + +/** + * @brief Obtains the local database path. If it is the first call, the dir will be created. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_GetPreferencesDirSync(napi_env env, napi_callback_info info) +{ + HILOG_INFO("%{public}s called.", __func__); + PreferencesDirCB *preferencesDirCB = CreateGetPreferencesDirCBInfo(env); + if (preferencesDirCB == nullptr) { + return WrapVoidToJS(env); + } + + preferencesDirCB->cbBase.errCode = NAPI_ERR_NO_ERROR; + napi_value ret = GetPreferencesDirWrap(env, info, preferencesDirCB); + + delete preferencesDirCB; + preferencesDirCB = nullptr; + + if (ret == nullptr) { + ret = WrapVoidToJS(env); + HILOG_ERROR("%{public}s ret == nullptr", __func__); + } else { + HILOG_INFO("%{public}s, end.", __func__); + } + return ret; +} + +/** + * @brief Context NAPI module registration. + * + * @param env The environment that the Node-API call is invoked under. + * @param exports An empty object via the exports parameter as a convenience. + * + * @return The return value from Init is treated as the exports object for the module. + */ +napi_value ContextPermissionInit(napi_env env, napi_value exports) +{ + HILOG_INFO("Context::ContextPermissionInit called."); + + napi_property_descriptor properties[] = { + DECLARE_NAPI_FUNCTION("verifySelfPermission", NAPI_VerifySelfPermission), + DECLARE_NAPI_FUNCTION("requestPermissionsFromUser", NAPI_RequestPermissionsFromUser), + DECLARE_NAPI_FUNCTION("getBundleName", NAPI_GetBundleName), + DECLARE_NAPI_FUNCTION("canRequestPermission", NAPI_CanRequestPermission), + DECLARE_NAPI_FUNCTION("verifyPermission", NAPI_VerifyPermission), + DECLARE_NAPI_FUNCTION("verifyCallingPermission", NAPI_VerifyCallingPermission), + DECLARE_NAPI_FUNCTION("verifyCallingOrSelfPermission", NAPI_VerifyCallingOrSelfPermission), + DECLARE_NAPI_FUNCTION("getApplicationInfo", NAPI_GetApplicationInfo), + DECLARE_NAPI_FUNCTION("getProcessInfo", NAPI_GetProcessInfo), + DECLARE_NAPI_FUNCTION("getElementName", NAPI_GetElementName), + DECLARE_NAPI_FUNCTION("getProcessName", NAPI_GetProcessName), + DECLARE_NAPI_FUNCTION("getCallingBundle", NAPI_GetCallingBundle), + DECLARE_NAPI_FUNCTION("getOrCreateLocalDir", NAPI_GetOrCreateLocalDir), + DECLARE_NAPI_FUNCTION("getFilesDir", NAPI_GetFilesDir), + DECLARE_NAPI_FUNCTION("getDatabaseDirSync", NAPI_GetDatabaseDirSync), + DECLARE_NAPI_FUNCTION("getPreferencesDirSync", NAPI_GetPreferencesDirSync), + }; + + NAPI_CALL(env, + napi_define_class(env, + "context", + NAPI_AUTO_LENGTH, + ContextConstructor, + nullptr, + sizeof(properties) / sizeof(*properties), + properties, + GetGlobalClassContext())); + + return exports; +} +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/interfaces/kits/napi/aafwk/featureAbility/napi_context.h b/tools/interfaces/kits/napi/aafwk/featureAbility/napi_context.h new file mode 100755 index 00000000000..aa26368a7c1 --- /dev/null +++ b/tools/interfaces/kits/napi/aafwk/featureAbility/napi_context.h @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_APPEXECFWK_NAPI_CONTEXT_H +#define OHOS_APPEXECFWK_NAPI_CONTEXT_H +#include "napi/native_common.h" +#include "napi/native_node_api.h" +#include "ability.h" +#include "../inner/napi_common/napi_common.h" + +using Ability = OHOS::AppExecFwk::Ability; +#define MODE 0771 +namespace OHOS { +namespace AppExecFwk { + +struct CallAbilityPermissionParam { + std::vector permission_list; + int requestCode = 0; + int syncOption = false; +}; + +struct OnRequestPermissionsFromUserResultCallback { + int requestCode = 0; + std::vector permissions; + std::vector grantResults; + CallbackInfo cb; +}; + +/** + * @brief Context NAPI module registration. + * + * @param env The environment that the Node-API call is invoked under. + * @param exports An empty object via the exports parameter as a convenience. + * + * @return The return value from Init is treated as the exports object for the module. + */ +napi_value ContextPermissionInit(napi_env env, napi_value exports); + +EXTERN_C_START +/** + * @brief The interface of onRequestPermissionsFromUserResult provided for ACE to call back to JS. + * + * @param requestCode Indicates the request code returned after the ability is started. + * @param permissions Indicates list of permission. + * @param grantResults Indicates List of authorization results. + * @param callbackInfo The environment and call back info that the Node-API call is invoked under. + */ +void CallOnRequestPermissionsFromUserResult(int requestCode, const std::vector &permissions, + const std::vector &grantResults, OHOS::AppExecFwk::CallbackInfo callbackInfo); +EXTERN_C_END +napi_value ContextConstructor(napi_env env, napi_callback_info info); + +/** + * @brief Obtains information about the current application. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_GetApplicationInfo(napi_env env, napi_callback_info info); + +/** + * @brief Obtains the elementName object of the current ability. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_GetElementName(napi_env env, napi_callback_info info); + +/** + * @brief Obtains the process Info this application. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_GetProcessInfo(napi_env env, napi_callback_info info); + +/** + * @brief Obtains the name of the current process. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_GetProcessName(napi_env env, napi_callback_info info); + +/** + * @brief Obtains the bundle name of the ability that called the current ability. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_GetCallingBundle(napi_env env, napi_callback_info info); +} // namespace AppExecFwk +} // namespace OHOS +#endif /* OHOS_APPEXECFWK_NAPI_CONTEXT_H */ diff --git a/tools/interfaces/kits/napi/aafwk/featureAbility/napi_data_ability_helper.cpp b/tools/interfaces/kits/napi/aafwk/featureAbility/napi_data_ability_helper.cpp new file mode 100644 index 00000000000..8bc0572b92a --- /dev/null +++ b/tools/interfaces/kits/napi/aafwk/featureAbility/napi_data_ability_helper.cpp @@ -0,0 +1,3204 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "napi_data_ability_helper.h" +#include "data_ability_observer_interface.h" +#include "data_ability_helper.h" +#include "uri.h" +#include +#include +#include +#include "securec.h" +#include "hilog_wrapper.h" +#include "napi_result_set.h" +#include "napi_rdb_predicates.h" +#include "napi_data_ability_predicates.h" +#include "data_ability_result.h" +#include "data_ability_operation.h" +#include "napi_data_ability_operation.h" + +#include "message_parcel.h" + +using namespace OHOS::AAFwk; +using namespace OHOS::AppExecFwk; + +namespace OHOS { +namespace AppExecFwk { +extern napi_value g_dataAbilityHelper; +std::list> g_dataAbilityHelperList; + +/** + * @brief DataAbilityHelper NAPI module registration. + * + * @param env The environment that the Node-API call is invoked under. + * @param exports An empty object via the exports parameter as a convenience. + * + * @return The return value from Init is treated as the exports object for the module. + */ +napi_value DataAbilityHelperInit(napi_env env, napi_value exports) +{ + HILOG_INFO("%{public}s,called", __func__); + napi_property_descriptor properties[] = { + DECLARE_NAPI_FUNCTION("insert", NAPI_Insert), + DECLARE_NAPI_FUNCTION("notifyChange", NAPI_NotifyChange), + DECLARE_NAPI_FUNCTION("on", NAPI_Register), + DECLARE_NAPI_FUNCTION("off", NAPI_UnRegister), + DECLARE_NAPI_FUNCTION("delete", NAPI_Delete), + DECLARE_NAPI_FUNCTION("query", NAPI_Query), + DECLARE_NAPI_FUNCTION("update", NAPI_Update), + DECLARE_NAPI_FUNCTION("batchInsert", NAPI_BatchInsert), + DECLARE_NAPI_FUNCTION("openFile", NAPI_OpenFile), + DECLARE_NAPI_FUNCTION("getType", NAPI_GetType), + DECLARE_NAPI_FUNCTION("getFileTypes", NAPI_GetFileTypes), + DECLARE_NAPI_FUNCTION("normalizeUri", NAPI_NormalizeUri), + DECLARE_NAPI_FUNCTION("denormalizeUri", NAPI_DenormalizeUri), + DECLARE_NAPI_FUNCTION("release", NAPI_Release), + DECLARE_NAPI_FUNCTION("executeBatch", NAPI_ExecuteBatch), + }; + NAPI_CALL(env, + napi_define_class(env, + "dataAbilityHelper", + NAPI_AUTO_LENGTH, + DataAbilityHelperConstructor, + nullptr, + sizeof(properties) / sizeof(*properties), + properties, + &g_dataAbilityHelper)); + g_dataAbilityHelperList.clear(); + return exports; +} + +napi_value DataAbilityHelperConstructor(napi_env env, napi_callback_info info) +{ + HILOG_INFO("%{public}s,called", __func__); + size_t argc = 1; + napi_value argv[1] = {nullptr}; + napi_value thisVar = nullptr; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr)); + NAPI_ASSERT(env, argc > 0, "Wrong number of arguments"); + std::string strUri = NapiValueToStringUtf8(env, argv[0]); + + napi_value global = nullptr; + NAPI_CALL(env, napi_get_global(env, &global)); + + napi_value abilityObj = nullptr; + NAPI_CALL(env, napi_get_named_property(env, global, "ability", &abilityObj)); + + Ability *ability = nullptr; + NAPI_CALL(env, napi_get_value_external(env, abilityObj, (void **)&ability)); + + HILOG_INFO("ability = %{public}p strUri = %{public}s", ability, strUri.c_str()); + HILOG_INFO("dataAbilityHelperList.size = %{public}zu", g_dataAbilityHelperList.size()); + std::shared_ptr dataAbilityHelper = + DataAbilityHelper::Creator(ability->GetContext(), std::make_shared(strUri)); + HILOG_INFO("dataAbilityHelper = %{public}p", dataAbilityHelper.get()); + g_dataAbilityHelperList.emplace_back(dataAbilityHelper); + HILOG_INFO("dataAbilityHelperList.size = %{public}zu", g_dataAbilityHelperList.size()); + + napi_wrap( + env, + thisVar, + dataAbilityHelper.get(), + [](napi_env env, void *data, void *hint) { + DataAbilityHelper *objectInfo = static_cast(data); + HILOG_INFO("DAHelper finalize_cb objectInfo = %{public}p", objectInfo); + HILOG_INFO("DAHelper finalize_cb regInstances_.size = %{public}zu", registerInstances_.size()); + auto helper = std::find_if(registerInstances_.begin(), + registerInstances_.end(), + [&objectInfo](const DAHelperOnOffCB *helper) { return helper->dataAbilityHelper == objectInfo; }); + if (helper != registerInstances_.end()) { + HILOG_INFO("DataAbilityHelper finalize_cb find helper"); + (*helper)->dataAbilityHelper->Release(); + delete *helper; + registerInstances_.erase(helper); + } + HILOG_INFO("DAHelper finalize_cb regInstances_.size = %{public}zu", registerInstances_.size()); + g_dataAbilityHelperList.remove_if( + [objectInfo](const std::shared_ptr &dataAbilityHelper) { + return objectInfo == dataAbilityHelper.get(); + }); + HILOG_INFO("DAHelper finalize_cb dataAbilityHelperList.size = %{public}zu", g_dataAbilityHelperList.size()); + }, + nullptr, + nullptr); + + HILOG_INFO("%{public}s,called end", __func__); + return thisVar; +} + +/** + * @brief DataAbilityHelper NAPI method : insert. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_Insert(napi_env env, napi_callback_info info) +{ + HILOG_INFO("%{public}s,called", __func__); + DAHelperInsertCB *insertCB = new (std::nothrow) DAHelperInsertCB; + if (insertCB == nullptr) { + HILOG_ERROR("%{public}s, insertCB == nullptr.", __func__); + return WrapVoidToJS(env); + } + insertCB->cbBase.cbInfo.env = env; + insertCB->cbBase.asyncWork = nullptr; + insertCB->cbBase.deferred = nullptr; + insertCB->cbBase.ability = nullptr; + + napi_value ret = InsertWrap(env, info, insertCB); + if (ret == nullptr) { + HILOG_ERROR("%{public}s, ret == nullptr.", __func__); + if (insertCB != nullptr) { + delete insertCB; + insertCB = nullptr; + } + ret = WrapVoidToJS(env); + } + HILOG_INFO("%{public}s,called end", __func__); + return ret; +} + +/** + * @brief Insert processing function. + * + * @param env The environment that the Node-API call is invoked under. + * @param insertCB Process data asynchronously. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value InsertWrap(napi_env env, napi_callback_info info, DAHelperInsertCB *insertCB) +{ + HILOG_INFO("%{public}s,called", __func__); + size_t argcAsync = ARGS_THREE; + const size_t argcPromise = ARGS_TWO; + const size_t argCountWithAsync = argcPromise + ARGS_ASYNC_COUNT; + napi_value args[ARGS_MAX_COUNT] = {nullptr}; + napi_value ret = 0; + napi_value thisVar = nullptr; + + NAPI_CALL(env, napi_get_cb_info(env, info, &argcAsync, args, &thisVar, nullptr)); + if (argcAsync > argCountWithAsync || argcAsync > ARGS_MAX_COUNT) { + HILOG_ERROR("%{public}s, Wrong argument count.", __func__); + return nullptr; + } + + napi_valuetype valuetype = napi_undefined; + NAPI_CALL(env, napi_typeof(env, args[PARAM0], &valuetype)); + if (valuetype == napi_string) { + insertCB->uri = NapiValueToStringUtf8(env, args[PARAM0]); + HILOG_INFO("%{public}s,uri=%{public}s", __func__, insertCB->uri.c_str()); + } else { + HILOG_ERROR("%{public}s, Wrong argument type.", __func__); + return nullptr; + } + + insertCB->valueBucket.Clear(); + AnalysisValuesBucket(insertCB->valueBucket, env, args[PARAM1]); + + DataAbilityHelper *objectInfo = nullptr; + napi_unwrap(env, thisVar, (void **)&objectInfo); + HILOG_INFO("%{public}s,DataAbilityHelper objectInfo = %{public}p", __func__, objectInfo); + insertCB->dataAbilityHelper = objectInfo; + + if (argcAsync > argcPromise) { + ret = InsertAsync(env, args, ARGS_TWO, insertCB); + } else { + ret = InsertPromise(env, insertCB); + } + HILOG_INFO("%{public}s,end", __func__); + return ret; +} + +void AnalysisValuesBucket(NativeRdb::ValuesBucket &valuesBucket, const napi_env &env, const napi_value &arg) +{ + napi_value keys = 0; + napi_get_property_names(env, arg, &keys); + uint32_t arrLen = 0; + napi_status status = napi_get_array_length(env, keys, &arrLen); + if (status != napi_ok) { + HILOG_ERROR("ValuesBucket errr"); + return; + } + HILOG_INFO("ValuesBucket num:%{public}d ", arrLen); + for (size_t i = 0; i < arrLen; ++i) { + napi_value key = 0; + status = napi_get_element(env, keys, i, &key); + std::string keyStr = UnwrapStringFromJS(env, key); + napi_value value = 0; + napi_get_property(env, arg, key, &value); + + SetValuesBucketObject(valuesBucket, env, keyStr, value); + } +} + +void SetValuesBucketObject( + NativeRdb::ValuesBucket &valuesBucket, const napi_env &env, std::string keyStr, napi_value value) +{ + napi_valuetype valueType = napi_undefined; + napi_typeof(env, value, &valueType); + if (valueType == napi_string) { + std::string valueString = UnwrapStringFromJS(env, value); + HILOG_INFO("ValueObject type:%{public}d, key:%{public}s, value:%{public}s", + valueType, + keyStr.c_str(), + valueString.c_str()); + valuesBucket.PutString(keyStr, valueString); + } else if (valueType == napi_number) { + double valueNumber = 0; + napi_get_value_double(env, value, &valueNumber); + valuesBucket.PutDouble(keyStr, valueNumber); + HILOG_INFO( + "ValueObject type:%{public}d, key:%{public}s, value:%{public}lf", valueType, keyStr.c_str(), valueNumber); + } else if (valueType == napi_boolean) { + bool valueBool = false; + napi_get_value_bool(env, value, &valueBool); + HILOG_INFO( + "ValueObject type:%{public}d, key:%{public}s, value:%{public}d", valueType, keyStr.c_str(), valueBool); + valuesBucket.PutBool(keyStr, valueBool); + } else if (valueType == napi_null) { + valuesBucket.PutNull(keyStr); + HILOG_INFO("ValueObject type:%{public}d, key:%{public}s, value:null", valueType, keyStr.c_str()); + } else if (valueType == napi_object) { + HILOG_INFO("ValueObject type:%{public}d, key:%{public}s, value:Uint8Array", valueType, keyStr.c_str()); + valuesBucket.PutBlob(keyStr, ConvertU8Vector(env, value)); + } else { + HILOG_ERROR("valuesBucket error"); + } +} +napi_value InsertAsync(napi_env env, napi_value *args, const size_t argCallback, DAHelperInsertCB *insertCB) +{ + HILOG_INFO("%{public}s, asyncCallback.", __func__); + if (args == nullptr || insertCB == nullptr) { + HILOG_ERROR("%{public}s, param == nullptr.", __func__); + return nullptr; + } + napi_value resourceName = 0; + NAPI_CALL(env, napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName)); + + napi_valuetype valuetype = napi_undefined; + NAPI_CALL(env, napi_typeof(env, args[argCallback], &valuetype)); + if (valuetype == napi_function) { + NAPI_CALL(env, napi_create_reference(env, args[argCallback], 1, &insertCB->cbBase.cbInfo.callback)); + } + + NAPI_CALL(env, + napi_create_async_work(env, + nullptr, + resourceName, + InsertExecuteCB, + InsertAsyncCompleteCB, + (void *)insertCB, + &insertCB->cbBase.asyncWork)); + NAPI_CALL(env, napi_queue_async_work(env, insertCB->cbBase.asyncWork)); + napi_value result = 0; + NAPI_CALL(env, napi_get_null(env, &result)); + HILOG_INFO("%{public}s, asyncCallback end", __func__); + return result; +} + +napi_value InsertPromise(napi_env env, DAHelperInsertCB *insertCB) +{ + HILOG_INFO("%{public}s, promise.", __func__); + if (insertCB == nullptr) { + HILOG_ERROR("%{public}s, param == nullptr.", __func__); + return nullptr; + } + napi_value resourceName; + NAPI_CALL(env, napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName)); + napi_deferred deferred; + napi_value promise = 0; + NAPI_CALL(env, napi_create_promise(env, &deferred, &promise)); + insertCB->cbBase.deferred = deferred; + + NAPI_CALL(env, + napi_create_async_work(env, + nullptr, + resourceName, + InsertExecuteCB, + InsertPromiseCompleteCB, + (void *)insertCB, + &insertCB->cbBase.asyncWork)); + NAPI_CALL(env, napi_queue_async_work(env, insertCB->cbBase.asyncWork)); + HILOG_INFO("%{public}s, promise end", __func__); + return promise; +} + +void InsertExecuteCB(napi_env env, void *data) +{ + HILOG_INFO("NAPI_Insert, worker pool thread execute."); + DAHelperInsertCB *insertCB = static_cast(data); + if (insertCB->dataAbilityHelper != nullptr) { + OHOS::Uri uri(insertCB->uri); + insertCB->result = insertCB->dataAbilityHelper->Insert(uri, insertCB->valueBucket); + } else { + HILOG_ERROR("NAPI_Insert, dataAbilityHelper == nullptr."); + } + HILOG_INFO("NAPI_Insert, worker pool thread execute end."); +} + +void InsertAsyncCompleteCB(napi_env env, napi_status status, void *data) +{ + HILOG_INFO("NAPI_Insert, main event thread complete."); + DAHelperInsertCB *insertCB = static_cast(data); + napi_value callback = nullptr; + napi_value undefined = nullptr; + napi_value result[ARGS_TWO] = {nullptr}; + napi_value callResult = nullptr; + NAPI_CALL_RETURN_VOID(env, napi_get_undefined(env, &undefined)); + NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, insertCB->cbBase.cbInfo.callback, &callback)); + + result[PARAM0] = GetCallbackErrorValue(env, NO_ERROR); + napi_create_int32(env, insertCB->result, &result[PARAM1]); + NAPI_CALL_RETURN_VOID(env, napi_call_function(env, undefined, callback, ARGS_TWO, &result[PARAM0], &callResult)); + + if (insertCB->cbBase.cbInfo.callback != nullptr) { + NAPI_CALL_RETURN_VOID(env, napi_delete_reference(env, insertCB->cbBase.cbInfo.callback)); + } + NAPI_CALL_RETURN_VOID(env, napi_delete_async_work(env, insertCB->cbBase.asyncWork)); + delete insertCB; + insertCB = nullptr; + HILOG_INFO("NAPI_Insert, main event thread complete end."); +} + +void InsertPromiseCompleteCB(napi_env env, napi_status status, void *data) +{ + HILOG_INFO("NAPI_Insert, main event thread complete."); + DAHelperInsertCB *insertCB = static_cast(data); + napi_value result = nullptr; + napi_create_int32(env, insertCB->result, &result); + NAPI_CALL_RETURN_VOID(env, napi_resolve_deferred(env, insertCB->cbBase.deferred, result)); + NAPI_CALL_RETURN_VOID(env, napi_delete_async_work(env, insertCB->cbBase.asyncWork)); + delete insertCB; + insertCB = nullptr; + HILOG_INFO("NAPI_Insert, main event thread complete end."); +} + +/** + * @brief Parse the ValuesBucket parameters. + * + * @param param Indicates the want parameters saved the parse result. + * @param env The environment that the Node-API call is invoked under. + * @param args Indicates the arguments passed into the callback. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value UnwrapValuesBucket(std::string &value, napi_env env, napi_value args) +{ + HILOG_INFO("%{public}s,called", __func__); + napi_valuetype valueType = napi_undefined; + napi_typeof(env, args, &valueType); + if (valueType != napi_object) { + HILOG_ERROR("%{public}s, valueType != napi_object.", __func__); + return nullptr; + } + + std::string strValue = ""; + if (UnwrapStringByPropertyName(env, args, "value", strValue)) { + HILOG_INFO("%{public}s,strValue=%{public}s", __func__, strValue.c_str()); + value = strValue; + } else { + HILOG_ERROR("%{public}s, value == nullptr.", __func__); + return nullptr; + } + + napi_value result; + NAPI_CALL(env, napi_create_int32(env, 1, &result)); + HILOG_INFO("%{public}s,end", __func__); + return result; +} + +/** + * @brief DataAbilityHelper NAPI method : notifyChange. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_NotifyChange(napi_env env, napi_callback_info info) +{ + HILOG_INFO("%{public}s,called", __func__); + DAHelperNotifyChangeCB *notifyChangeCB = new (std::nothrow) DAHelperNotifyChangeCB; + if (notifyChangeCB == nullptr) { + HILOG_ERROR("%{public}s, notifyChangeCB == nullptr.", __func__); + return WrapVoidToJS(env); + } + notifyChangeCB->cbBase.cbInfo.env = env; + notifyChangeCB->cbBase.asyncWork = nullptr; + notifyChangeCB->cbBase.deferred = nullptr; + notifyChangeCB->cbBase.ability = nullptr; + + napi_value ret = NotifyChangeWrap(env, info, notifyChangeCB); + if (ret == nullptr) { + HILOG_ERROR("%{public}s, ret == nullptr.", __func__); + if (notifyChangeCB != nullptr) { + delete notifyChangeCB; + notifyChangeCB = nullptr; + } + ret = WrapVoidToJS(env); + } + HILOG_INFO("%{public}s,end", __func__); + return ret; +} + +/** + * @brief NotifyChange processing function. + * + * @param env The environment that the Node-API call is invoked under. + * @param notifyChangeCB Process data asynchronously. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value NotifyChangeWrap(napi_env env, napi_callback_info info, DAHelperNotifyChangeCB *notifyChangeCB) +{ + + HILOG_INFO("%{public}s,called", __func__); + size_t argcAsync = ARGS_TWO; + const size_t argcPromise = ARGS_ONE; + const size_t argCountWithAsync = argcPromise + ARGS_ASYNC_COUNT; + napi_value args[ARGS_MAX_COUNT] = {nullptr}; + napi_value ret = 0; + napi_value thisVar = nullptr; + + NAPI_CALL(env, napi_get_cb_info(env, info, &argcAsync, args, &thisVar, nullptr)); + if (argcAsync > argCountWithAsync || argcAsync > ARGS_MAX_COUNT) { + HILOG_ERROR("%{public}s, Wrong argument count.", __func__); + return nullptr; + } + + napi_valuetype valuetype = napi_undefined; + NAPI_CALL(env, napi_typeof(env, args[PARAM0], &valuetype)); + if (valuetype == napi_string) { + notifyChangeCB->uri = NapiValueToStringUtf8(env, args[PARAM0]); + HILOG_INFO("%{public}s,uri=%{public}s", __func__, notifyChangeCB->uri.c_str()); + } else { + HILOG_ERROR("%{public}s, Wrong argument type.", __func__); + return nullptr; + } + + DataAbilityHelper *objectInfo = nullptr; + napi_unwrap(env, thisVar, (void **)&objectInfo); + HILOG_INFO("DataAbilityHelper objectInfo = %{public}p", objectInfo); + notifyChangeCB->dataAbilityHelper = objectInfo; + + if (argcAsync > argcPromise) { + ret = NotifyChangeAsync(env, args, argcAsync, argcPromise, notifyChangeCB); + } else { + ret = NotifyChangePromise(env, notifyChangeCB); + } + return ret; +} + +napi_value NotifyChangeAsync( + napi_env env, napi_value *args, size_t argcAsync, const size_t argcPromise, DAHelperNotifyChangeCB *notifyChangeCB) +{ + HILOG_INFO("%{public}s, asyncCallback.", __func__); + if (args == nullptr || notifyChangeCB == nullptr) { + HILOG_ERROR("%{public}s, param == nullptr.", __func__); + return nullptr; + } + napi_value resourceName = 0; + NAPI_CALL(env, napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName)); + + napi_valuetype valuetype = napi_undefined; + NAPI_CALL(env, napi_typeof(env, args[argcPromise], &valuetype)); + if (valuetype == napi_function) { + NAPI_CALL(env, napi_create_reference(env, args[argcPromise], 1, ¬ifyChangeCB->cbBase.cbInfo.callback)); + } + + NAPI_CALL(env, + napi_create_async_work(env, + nullptr, + resourceName, + NotifyChangeExecuteCB, + NotifyChangeAsyncCompleteCB, + (void *)notifyChangeCB, + ¬ifyChangeCB->cbBase.asyncWork)); + NAPI_CALL(env, napi_queue_async_work(env, notifyChangeCB->cbBase.asyncWork)); + napi_value result = 0; + NAPI_CALL(env, napi_get_null(env, &result)); + return result; +} + +napi_value NotifyChangePromise(napi_env env, DAHelperNotifyChangeCB *notifyChangeCB) +{ + HILOG_INFO("%{public}s, promise.", __func__); + if (notifyChangeCB == nullptr) { + HILOG_ERROR("%{public}s, param == nullptr.", __func__); + return nullptr; + } + napi_value resourceName; + NAPI_CALL(env, napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName)); + napi_deferred deferred; + napi_value promise = 0; + NAPI_CALL(env, napi_create_promise(env, &deferred, &promise)); + notifyChangeCB->cbBase.deferred = deferred; + + NAPI_CALL(env, + napi_create_async_work(env, + nullptr, + resourceName, + NotifyChangeExecuteCB, + NotifyChangePromiseCompleteCB, + (void *)notifyChangeCB, + ¬ifyChangeCB->cbBase.asyncWork)); + NAPI_CALL(env, napi_queue_async_work(env, notifyChangeCB->cbBase.asyncWork)); + return promise; +} + +void NotifyChangeExecuteCB(napi_env env, void *data) +{ + HILOG_INFO("NAPI_NotifyChange, worker pool thread execute."); + DAHelperNotifyChangeCB *notifyChangeCB = static_cast(data); + if (notifyChangeCB->dataAbilityHelper != nullptr) { + OHOS::Uri uri(notifyChangeCB->uri); + notifyChangeCB->dataAbilityHelper->NotifyChange(uri); + } +} + +void NotifyChangeAsyncCompleteCB(napi_env env, napi_status status, void *data) +{ + HILOG_INFO("NAPI_NotifyChange, main event thread complete."); + DAHelperNotifyChangeCB *notifyChangeCB = static_cast(data); + napi_value callback = nullptr; + napi_value undefined = nullptr; + napi_value result[ARGS_TWO] = {nullptr}; + napi_value callResult = nullptr; + NAPI_CALL_RETURN_VOID(env, napi_get_undefined(env, &undefined)); + NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, notifyChangeCB->cbBase.cbInfo.callback, &callback)); + + result[PARAM0] = GetCallbackErrorValue(env, NO_ERROR); + napi_create_int32(env, 0, &result[PARAM1]); + NAPI_CALL_RETURN_VOID(env, napi_call_function(env, undefined, callback, ARGS_TWO, &result[PARAM0], &callResult)); + + if (notifyChangeCB->cbBase.cbInfo.callback != nullptr) { + NAPI_CALL_RETURN_VOID(env, napi_delete_reference(env, notifyChangeCB->cbBase.cbInfo.callback)); + } + NAPI_CALL_RETURN_VOID(env, napi_delete_async_work(env, notifyChangeCB->cbBase.asyncWork)); + delete notifyChangeCB; + notifyChangeCB = nullptr; +} + +void NotifyChangePromiseCompleteCB(napi_env env, napi_status status, void *data) +{ + HILOG_INFO("NAPI_NotifyChange, main event thread complete."); + DAHelperNotifyChangeCB *notifyChangeCB = static_cast(data); + napi_value result = nullptr; + napi_create_int32(env, 0, &result); + NAPI_CALL_RETURN_VOID(env, napi_resolve_deferred(env, notifyChangeCB->cbBase.deferred, result)); + NAPI_CALL_RETURN_VOID(env, napi_delete_async_work(env, notifyChangeCB->cbBase.asyncWork)); + delete notifyChangeCB; + notifyChangeCB = nullptr; +} + +/** + * @brief DataAbilityHelper NAPI method : on. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_Register(napi_env env, napi_callback_info info) +{ + HILOG_INFO("%{public}s,called", __func__); + DAHelperOnOffCB *onCB = new (std::nothrow) DAHelperOnOffCB; + if (onCB == nullptr) { + HILOG_ERROR("%{public}s, onCB == nullptr.", __func__); + return WrapVoidToJS(env); + } + onCB->cbBase.cbInfo.env = env; + onCB->cbBase.asyncWork = nullptr; + onCB->cbBase.deferred = nullptr; + onCB->cbBase.ability = nullptr; + + napi_value ret = RegisterWrap(env, info, onCB); + if (ret == nullptr) { + HILOG_ERROR("%{public}s, ret == nullptr.", __func__); + if (onCB != nullptr) { + delete onCB; + onCB = nullptr; + } + ret = WrapVoidToJS(env); + } + HILOG_INFO("%{public}s,called end", __func__); + return ret; +} + +/** + * @brief On processing function. + * + * @param env The environment that the Node-API call is invoked under. + * @param insertCB Process data asynchronously. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value RegisterWrap(napi_env env, napi_callback_info info, DAHelperOnOffCB *onCB) +{ + HILOG_INFO("%{public}s,called", __func__); + size_t argcAsync = ARGS_THREE; + const size_t argcPromise = ARGS_TWO; + const size_t argCountWithAsync = argcPromise + ARGS_ASYNC_COUNT; + napi_value args[ARGS_MAX_COUNT] = {nullptr}; + napi_value ret = 0; + napi_value thisVar = nullptr; + + NAPI_CALL(env, napi_get_cb_info(env, info, &argcAsync, args, &thisVar, nullptr)); + if (argcAsync > argCountWithAsync || argcAsync > ARGS_MAX_COUNT) { + HILOG_ERROR("%{public}s, Wrong argument count.", __func__); + return nullptr; + } + + napi_valuetype valuetype = napi_undefined; + NAPI_CALL(env, napi_typeof(env, args[PARAM0], &valuetype)); + if (valuetype == napi_string) { + std::string type = NapiValueToStringUtf8(env, args[PARAM0]); + if (type != "dataChange") { + HILOG_ERROR("%{public}s, Wrong type=%{public}s", __func__, type.c_str()); + return nullptr; + } + } else { + HILOG_ERROR("%{public}s, Wrong argument type.", __func__); + return nullptr; + } + + NAPI_CALL(env, napi_typeof(env, args[PARAM1], &valuetype)); + if (valuetype == napi_string) { + onCB->uri = NapiValueToStringUtf8(env, args[PARAM1]); + HILOG_INFO("%{public}s,uri=%{public}s", __func__, onCB->uri.c_str()); + } else { + HILOG_ERROR("%{public}s, Wrong argument type.", __func__); + return nullptr; + } + + DataAbilityHelper *objectInfo = nullptr; + napi_unwrap(env, thisVar, (void **)&objectInfo); + HILOG_INFO("DataAbilityHelper objectInfo = %{public}p", objectInfo); + onCB->dataAbilityHelper = objectInfo; + + sptr observer(new (std::nothrow) NAPIDataAbilityObserver()); + onCB->observer = observer; + + registerInstances_.emplace_back(onCB); + HILOG_INFO("regInstances_ emplace_back size = %{public}zu", registerInstances_.size()); + ret = RegisterAsync(env, args, argcAsync, argcPromise, onCB); + return ret; +} + +napi_value RegisterAsync( + napi_env env, napi_value *args, size_t argcAsync, const size_t argcPromise, DAHelperOnOffCB *onCB) +{ + HILOG_INFO("%{public}s, asyncCallback.", __func__); + if (args == nullptr || onCB == nullptr) { + HILOG_ERROR("%{public}s, param == nullptr.", __func__); + return nullptr; + } + napi_value resourceName = 0; + NAPI_CALL(env, napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName)); + + napi_valuetype valuetype = napi_undefined; + NAPI_CALL(env, napi_typeof(env, args[argcPromise], &valuetype)); + if (valuetype == napi_function) { + NAPI_CALL(env, napi_create_reference(env, args[argcPromise], 1, &onCB->cbBase.cbInfo.callback)); + } + + NAPI_CALL(env, + napi_create_async_work( + env, + nullptr, + resourceName, + RegisterExecuteCB, + [](napi_env env, napi_status status, void *data) { + HILOG_INFO("NAPI_Register, main event thread complete."); + DAHelperOnOffCB *onCB = static_cast(data); + if (onCB != nullptr) { + delete onCB; + onCB = nullptr; + } + }, + (void *)onCB, + &onCB->cbBase.asyncWork)); + NAPI_CALL(env, napi_queue_async_work(env, onCB->cbBase.asyncWork)); + napi_value result = 0; + NAPI_CALL(env, napi_get_null(env, &result)); + return result; +} + +void RegisterExecuteCB(napi_env env, void *data) +{ + HILOG_INFO("NAPI_Register, worker pool thread execute."); + DAHelperOnOffCB *onCB = static_cast(data); + if (onCB->dataAbilityHelper != nullptr) { + onCB->observer->SetEnv(env); + onCB->observer->SetCallbackRef(onCB->cbBase.cbInfo.callback); + + OHOS::Uri uri(onCB->uri); + onCB->dataAbilityHelper->RegisterObserver(uri, onCB->observer); + } +} + +/** + * @brief DataAbilityHelper NAPI method : Off. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_UnRegister(napi_env env, napi_callback_info info) +{ + HILOG_INFO("%{public}s,called", __func__); + DAHelperOnOffCB *offCB = new (std::nothrow) DAHelperOnOffCB; + if (offCB == nullptr) { + HILOG_ERROR("%{public}s, offCB == nullptr.", __func__); + return WrapVoidToJS(env); + } + offCB->cbBase.cbInfo.env = env; + offCB->cbBase.asyncWork = nullptr; + offCB->cbBase.deferred = nullptr; + offCB->cbBase.ability = nullptr; + + napi_value ret = UnRegisterWrap(env, info, offCB); + if (ret == nullptr) { + HILOG_ERROR("%{public}s, ret == nullptr.", __func__); + if (offCB != nullptr) { + delete offCB; + offCB = nullptr; + } + ret = WrapVoidToJS(env); + } + HILOG_INFO("%{public}s,called end", __func__); + return ret; +} + +/** + * @brief Off processing function. + * + * @param env The environment that the Node-API call is invoked under. + * @param insertCB Process data asynchronously. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value UnRegisterWrap(napi_env env, napi_callback_info info, DAHelperOnOffCB *offCB) +{ + HILOG_INFO("%{public}s,called", __func__); + size_t argcAsync = ARGS_THREE; + const size_t argcPromise = ARGS_TWO; + const size_t argCountWithAsync = argcPromise + ARGS_ASYNC_COUNT; + napi_value args[ARGS_MAX_COUNT] = {nullptr}; + napi_value ret = 0; + napi_value thisVar = nullptr; + + NAPI_CALL(env, napi_get_cb_info(env, info, &argcAsync, args, &thisVar, nullptr)); + if (argcAsync > argCountWithAsync || argcAsync > ARGS_MAX_COUNT) { + HILOG_ERROR("%{public}s, Wrong argument count.", __func__); + return nullptr; + } + + napi_valuetype valuetype = napi_undefined; + NAPI_CALL(env, napi_typeof(env, args[PARAM0], &valuetype)); + if (valuetype == napi_string) { + std::string type = NapiValueToStringUtf8(env, args[PARAM0]); + if (type != "dataChange") { + HILOG_ERROR("%{public}s, Wrong type=%{public}s", __func__, type.c_str()); + return nullptr; + } + } else { + HILOG_ERROR("%{public}s, Wrong argument type.", __func__); + return nullptr; + } + + offCB->uri = ""; + if (argcAsync > ARGS_TWO) { + // parse uri and callback + NAPI_CALL(env, napi_typeof(env, args[PARAM1], &valuetype)); + if (valuetype == napi_string) { + offCB->uri = NapiValueToStringUtf8(env, args[PARAM1]); + HILOG_INFO("%{public}s,uri=%{public}s", __func__, offCB->uri.c_str()); + } else { + HILOG_ERROR("%{public}s, Wrong argument type.", __func__); + return nullptr; + } + NAPI_CALL(env, napi_typeof(env, args[PARAM2], &valuetype)); + if (valuetype == napi_function) { + NAPI_CALL(env, napi_create_reference(env, args[PARAM2], 1, &offCB->cbBase.cbInfo.callback)); + } + } else { + // parse uri or callback + NAPI_CALL(env, napi_typeof(env, args[PARAM1], &valuetype)); + if (valuetype == napi_string) { + offCB->uri = NapiValueToStringUtf8(env, args[PARAM1]); + HILOG_INFO("%{public}s,uri=%{public}s", __func__, offCB->uri.c_str()); + } else if (valuetype == napi_function) { + NAPI_CALL(env, napi_create_reference(env, args[PARAM1], 1, &offCB->cbBase.cbInfo.callback)); + } else { + HILOG_ERROR("%{public}s, Wrong argument type.", __func__); + return nullptr; + } + } + + DataAbilityHelper *objectInfo = nullptr; + napi_unwrap(env, thisVar, (void **)&objectInfo); + HILOG_INFO("DataAbilityHelper objectInfo = %{public}p", objectInfo); + offCB->dataAbilityHelper = objectInfo; + + ret = UnRegisterAsync(env, args, argcAsync, argcPromise, offCB); + return ret; +} + +napi_value UnRegisterAsync( + napi_env env, napi_value *args, size_t argcAsync, const size_t argcPromise, DAHelperOnOffCB *offCB) +{ + HILOG_INFO("%{public}s, asyncCallback.", __func__); + if (args == nullptr || offCB == nullptr) { + HILOG_ERROR("%{public}s, param == nullptr.", __func__); + return nullptr; + } + napi_value resourceName = 0; + NAPI_CALL(env, napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName)); + + NAPI_CALL(env, + napi_create_async_work( + env, + nullptr, + resourceName, + [](napi_env env, void *data) { HILOG_INFO("NAPI_UnRegister, worker pool thread execute."); }, + UnRegisterCompleteCB, + (void *)offCB, + &offCB->cbBase.asyncWork)); + NAPI_CALL(env, napi_queue_async_work(env, offCB->cbBase.asyncWork)); + napi_value result = 0; + NAPI_CALL(env, napi_get_null(env, &result)); + return result; +} + +void UnRegisterCompleteCB(napi_env env, napi_status status, void *data) +{ + HILOG_INFO("NAPI_UnRegister, main event thread complete."); + // cannot run it in executeCB, because need to use napi_strict_equals compare callbacks. + DAHelperOnOffCB *offCB = static_cast(data); + if (offCB == nullptr || offCB->dataAbilityHelper == nullptr) { + HILOG_ERROR("NAPI_UnRegister, param is null."); + if (offCB != nullptr) { + delete offCB; + offCB = nullptr; + } + return; + } + if (offCB->cbBase.cbInfo.callback != nullptr) { + HILOG_INFO("NAPI_UnRegister, callback is not null."); + // if match callback ,or match both callback and uri + napi_ref callback = offCB->cbBase.cbInfo.callback; + do { + auto helper = std::find_if( + registerInstances_.begin(), registerInstances_.end(), [callback](const DAHelperOnOffCB *helper) { + bool result = false; + napi_value callbackA = 0; + napi_value callbackB = 0; + napi_get_reference_value(helper->cbBase.cbInfo.env, callback, &callbackA); + napi_get_reference_value(helper->cbBase.cbInfo.env, helper->cbBase.cbInfo.callback, &callbackA); + auto ret = napi_strict_equals(helper->cbBase.cbInfo.env, callbackA, callbackB, &result); + HILOG_INFO("NAPI_UnRegister cb equals status=%{public}d result=%{public}d.", ret, result); + return result; + }); + if (helper != registerInstances_.end()) { + OHOS::Uri uri((*helper)->uri); + // if uri is not empty, uri and callback has to be equal at the same time. + if (offCB->uri == uri.ToString()) { + // match callback, or match both callback and uri + (*helper)->dataAbilityHelper->UnregisterObserver(uri, (*helper)->observer); + registerInstances_.erase(helper); + delete *helper; + *helper = nullptr; + HILOG_INFO("NAPI_UnRegister Instances erase size = %{public}zu", registerInstances_.size()); + } else { + HILOG_INFO("NAPI_UnRegister uri=%{public}s,helper.Uri=%{public}s", + offCB->uri.c_str(), + uri.ToString().c_str()); + } + } else { + HILOG_INFO("NAPI_UnRegister not match any callback."); + break; // not match any callback + } + } while (true); + } else { + HILOG_INFO("NAPI_UnRegister, uri=%{public}s.", offCB->uri.c_str()); + if (offCB->uri != "") { + // if match uri, unregister all observers corresponding the uri + std::string strUri = offCB->uri; + do { + auto helper = std::find_if(registerInstances_.begin(), + registerInstances_.end(), + [strUri](const DAHelperOnOffCB *helper) { return helper->uri == strUri; }); + if (helper != registerInstances_.end()) { + // match uri + OHOS::Uri uri((*helper)->uri); + (*helper)->dataAbilityHelper->UnregisterObserver(uri, (*helper)->observer); + registerInstances_.erase(helper); + delete *helper; + *helper = nullptr; + HILOG_INFO("NAPI_UnRegister Instances erase size = %{public}zu", registerInstances_.size()); + } else { + HILOG_INFO("NAPI_UnRegister not match any uri."); + break; // not match any uri + } + } while (true); + } else { + HILOG_ERROR("NAPI_UnRegister, error: uri is null."); + } + } + if (offCB != nullptr) { + delete offCB; + offCB = nullptr; + } +} + +void NAPIDataAbilityObserver::SetEnv(const napi_env &env) +{ + env_ = env; +} + +void NAPIDataAbilityObserver::SetCallbackRef(const napi_ref &ref) +{ + ref_ = ref; +} + +void NAPIDataAbilityObserver::OnChange() +{ + HILOG_INFO("%{public}s, called.", __func__); + + uv_loop_s *loop = nullptr; + napi_get_uv_event_loop(env_, &loop); + if (loop == nullptr) { + HILOG_ERROR("%{public}s, loop == nullptr.", __func__); + return; + } + + uv_work_t *work = new uv_work_t; + if (work == nullptr) { + HILOG_ERROR("%{public}s, work==nullptr.", __func__); + return; + } + + DAHelperOnOffCB *onCB = new (std::nothrow) DAHelperOnOffCB; + if (onCB == nullptr) { + HILOG_ERROR("%{public}s, onCB == nullptr.", __func__); + if (work != nullptr) { + delete work; + work = nullptr; + } + return; + } + onCB->cbBase.cbInfo.env = env_; + onCB->cbBase.cbInfo.callback = ref_; + work->data = (void *)onCB; + + int rev = uv_queue_work( + loop, + work, + [](uv_work_t *work) {}, + [](uv_work_t *work, int status) { + HILOG_INFO("OnChange, uv_queue_work"); + // JS Thread + DAHelperOnOffCB *onCB = (DAHelperOnOffCB *)work->data; + napi_value result[ARGS_TWO] = {0}; + result[PARAM0] = GetCallbackErrorValue(onCB->cbBase.cbInfo.env, NO_ERROR); + + napi_value callback = 0; + napi_value undefined = 0; + napi_get_undefined(onCB->cbBase.cbInfo.env, &undefined); + napi_value callResult = 0; + napi_get_reference_value(onCB->cbBase.cbInfo.env, onCB->cbBase.cbInfo.callback, &callback); + + napi_call_function(onCB->cbBase.cbInfo.env, undefined, callback, ARGS_TWO, &result[PARAM0], &callResult); + if (onCB->cbBase.cbInfo.callback != nullptr) { + napi_delete_reference(onCB->cbBase.cbInfo.env, onCB->cbBase.cbInfo.callback); + } + if (onCB != nullptr) { + delete onCB; + onCB = nullptr; + } + if (work != nullptr) { + delete work; + work = nullptr; + } + }); + if (rev != 0) { + if (onCB != nullptr) { + delete onCB; + onCB = nullptr; + } + if (work != nullptr) { + delete work; + work = nullptr; + } + } +} + +napi_value NAPI_GetType(napi_env env, napi_callback_info info) +{ + HILOG_INFO("%{public}s,called", __func__); + DAHelperGetTypeCB *gettypeCB = new (std::nothrow) DAHelperGetTypeCB; + if (gettypeCB == nullptr) { + HILOG_ERROR("%{public}s, gettypeCB == nullptr.", __func__); + return WrapVoidToJS(env); + } + gettypeCB->cbBase.cbInfo.env = env; + gettypeCB->cbBase.asyncWork = nullptr; + gettypeCB->cbBase.deferred = nullptr; + gettypeCB->cbBase.ability = nullptr; + + napi_value ret = GetTypeWrap(env, info, gettypeCB); + if (ret == nullptr) { + HILOG_ERROR("%{public}s,ret == nullptr", __func__); + if (gettypeCB != nullptr) { + delete gettypeCB; + gettypeCB = nullptr; + } + ret = WrapVoidToJS(env); + } + HILOG_INFO("%{public}s,end", __func__); + return ret; +} + +napi_value GetTypeWrap(napi_env env, napi_callback_info info, DAHelperGetTypeCB *gettypeCB) +{ + HILOG_INFO("%{public}s,called", __func__); + size_t argcAsync = ARGS_TWO; + const size_t argcPromise = ARGS_ONE; + const size_t argCountWithAsync = argcPromise + ARGS_ASYNC_COUNT; + napi_value args[ARGS_MAX_COUNT] = {nullptr}; + napi_value ret = 0; + napi_value thisVar = nullptr; + + NAPI_CALL(env, napi_get_cb_info(env, info, &argcAsync, args, &thisVar, nullptr)); + if (argcAsync > argCountWithAsync || argcAsync > ARGS_MAX_COUNT) { + HILOG_ERROR("%{public}s, Wrong argument count.", __func__); + return nullptr; + } + + napi_valuetype valuetype = napi_undefined; + NAPI_CALL(env, napi_typeof(env, args[PARAM0], &valuetype)); + if (valuetype == napi_string) { + gettypeCB->uri = NapiValueToStringUtf8(env, args[PARAM0]); + HILOG_INFO("%{public}s,uri=%{public}s", __func__, gettypeCB->uri.c_str()); + } else { + HILOG_ERROR("%{public}s, Wrong argument type.", __func__); + return nullptr; + } + + DataAbilityHelper *objectInfo = nullptr; + napi_unwrap(env, thisVar, (void **)&objectInfo); + HILOG_INFO("%{public}s,DataAbilityHelper objectInfo = %{public}p", __func__, objectInfo); + gettypeCB->dataAbilityHelper = objectInfo; + + if (argcAsync > argcPromise) { + ret = GetTypeAsync(env, args, ARGS_ONE, gettypeCB); + } else { + ret = GetTypePromise(env, gettypeCB); + } + HILOG_INFO("%{public}s,end", __func__); + return ret; +} + +napi_value GetTypeAsync(napi_env env, napi_value *args, const size_t argCallback, DAHelperGetTypeCB *gettypeCB) +{ + HILOG_INFO("%{public}s, asyncCallback.", __func__); + if (args == nullptr || gettypeCB == nullptr) { + HILOG_ERROR("%{public}s, param == nullptr.", __func__); + return nullptr; + } + napi_value resourceName = 0; + NAPI_CALL(env, napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName)); + + napi_valuetype valuetype = napi_undefined; + NAPI_CALL(env, napi_typeof(env, args[argCallback], &valuetype)); + if (valuetype == napi_function) { + NAPI_CALL(env, napi_create_reference(env, args[argCallback], 1, &gettypeCB->cbBase.cbInfo.callback)); + } + + NAPI_CALL(env, + napi_create_async_work(env, + nullptr, + resourceName, + GetTypeExecuteCB, + GetTypeAsyncCompleteCB, + (void *)gettypeCB, + &gettypeCB->cbBase.asyncWork)); + NAPI_CALL(env, napi_queue_async_work(env, gettypeCB->cbBase.asyncWork)); + napi_value result = 0; + NAPI_CALL(env, napi_get_null(env, &result)); + HILOG_INFO("%{public}s, asyncCallback end", __func__); + return result; +} + +napi_value GetTypePromise(napi_env env, DAHelperGetTypeCB *gettypeCB) +{ + HILOG_INFO("%{public}s, promise.", __func__); + if (gettypeCB == nullptr) { + HILOG_ERROR("%{public}s, param == nullptr.", __func__); + return nullptr; + } + napi_value resourceName; + NAPI_CALL(env, napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName)); + napi_deferred deferred; + napi_value promise = 0; + NAPI_CALL(env, napi_create_promise(env, &deferred, &promise)); + gettypeCB->cbBase.deferred = deferred; + + NAPI_CALL(env, + napi_create_async_work(env, + nullptr, + resourceName, + GetTypeExecuteCB, + GetTypePromiseCompleteCB, + (void *)gettypeCB, + &gettypeCB->cbBase.asyncWork)); + NAPI_CALL(env, napi_queue_async_work(env, gettypeCB->cbBase.asyncWork)); + HILOG_INFO("%{public}s, promise end.", __func__); + return promise; +} + +void GetTypeExecuteCB(napi_env env, void *data) +{ + HILOG_INFO("NAPI_GetType, worker pool thread execute."); + DAHelperGetTypeCB *gettypeCB = static_cast(data); + if (gettypeCB->dataAbilityHelper != nullptr) { + OHOS::Uri uri(gettypeCB->uri); + gettypeCB->result = gettypeCB->dataAbilityHelper->GetType(uri); + } else { + HILOG_ERROR("NAPI_GetType, dataAbilityHelper == nullptr."); + } + HILOG_INFO("NAPI_GetType, worker pool thread execute end."); +} + +void GetTypeAsyncCompleteCB(napi_env env, napi_status status, void *data) +{ + HILOG_INFO("NAPI_GetType, main event thread complete."); + DAHelperGetTypeCB *gettypeCB = static_cast(data); + napi_value callback = nullptr; + napi_value undefined = nullptr; + napi_value result[ARGS_TWO] = {nullptr}; + napi_value callResult = nullptr; + NAPI_CALL_RETURN_VOID(env, napi_get_undefined(env, &undefined)); + NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, gettypeCB->cbBase.cbInfo.callback, &callback)); + + result[PARAM0] = GetCallbackErrorValue(env, NO_ERROR); + napi_create_string_utf8(env, gettypeCB->result.c_str(), NAPI_AUTO_LENGTH, &result[PARAM1]); + + NAPI_CALL_RETURN_VOID(env, napi_call_function(env, undefined, callback, ARGS_TWO, &result[PARAM0], &callResult)); + + if (gettypeCB->cbBase.cbInfo.callback != nullptr) { + NAPI_CALL_RETURN_VOID(env, napi_delete_reference(env, gettypeCB->cbBase.cbInfo.callback)); + } + NAPI_CALL_RETURN_VOID(env, napi_delete_async_work(env, gettypeCB->cbBase.asyncWork)); + delete gettypeCB; + gettypeCB = nullptr; + HILOG_INFO("NAPI_GetType, main event thread complete end."); +} + +void GetTypePromiseCompleteCB(napi_env env, napi_status status, void *data) +{ + HILOG_INFO("NAPI_GetType, main event thread complete."); + DAHelperGetTypeCB *gettypeCB = static_cast(data); + napi_value result = nullptr; + NAPI_CALL_RETURN_VOID(env, napi_create_string_utf8(env, gettypeCB->result.c_str(), NAPI_AUTO_LENGTH, &result)); + NAPI_CALL_RETURN_VOID(env, napi_resolve_deferred(env, gettypeCB->cbBase.deferred, result)); + NAPI_CALL_RETURN_VOID(env, napi_delete_async_work(env, gettypeCB->cbBase.asyncWork)); + delete gettypeCB; + gettypeCB = nullptr; + HILOG_INFO("NAPI_GetType, main event thread complete end."); +} + +napi_value NAPI_GetFileTypes(napi_env env, napi_callback_info info) +{ + HILOG_INFO("%{public}s,called", __func__); + DAHelperGetFileTypesCB *getfiletypesCB = new (std::nothrow) DAHelperGetFileTypesCB; + if (getfiletypesCB == nullptr) { + HILOG_ERROR("%{public}s, getfiletypesCB == nullptr.", __func__); + return WrapVoidToJS(env); + } + getfiletypesCB->cbBase.cbInfo.env = env; + getfiletypesCB->cbBase.asyncWork = nullptr; + getfiletypesCB->cbBase.deferred = nullptr; + getfiletypesCB->cbBase.ability = nullptr; + + napi_value ret = GetFileTypesWrap(env, info, getfiletypesCB); + if (ret == nullptr) { + HILOG_ERROR("%{public}s,ret == nullptr", __func__); + if (getfiletypesCB != nullptr) { + delete getfiletypesCB; + getfiletypesCB = nullptr; + } + ret = WrapVoidToJS(env); + } + HILOG_INFO("%{public}s,end", __func__); + return ret; +} + +napi_value GetFileTypesWrap(napi_env env, napi_callback_info info, DAHelperGetFileTypesCB *getfiletypesCB) +{ + HILOG_INFO("%{public}s,called", __func__); + size_t argcAsync = ARGS_THREE; + const size_t argcPromise = ARGS_TWO; + const size_t argCountWithAsync = argcPromise + ARGS_ASYNC_COUNT; + napi_value args[ARGS_MAX_COUNT] = {nullptr}; + napi_value ret = 0; + napi_value thisVar = nullptr; + + NAPI_CALL(env, napi_get_cb_info(env, info, &argcAsync, args, &thisVar, nullptr)); + if (argcAsync > argCountWithAsync || argcAsync > ARGS_MAX_COUNT) { + HILOG_ERROR("%{public}s, Wrong argument count.", __func__); + return nullptr; + } + + napi_valuetype valuetype = napi_undefined; + NAPI_CALL(env, napi_typeof(env, args[PARAM0], &valuetype)); + if (valuetype == napi_string) { + getfiletypesCB->uri = NapiValueToStringUtf8(env, args[PARAM0]); + HILOG_INFO("%{public}s,uri=%{public}s", __func__, getfiletypesCB->uri.c_str()); + } + + NAPI_CALL(env, napi_typeof(env, args[PARAM1], &valuetype)); + if (valuetype == napi_string) { + getfiletypesCB->mimeTypeFilter = NapiValueToStringUtf8(env, args[PARAM1]); + HILOG_INFO("%{public}s,mimeTypeFilter=%{public}s", __func__, getfiletypesCB->mimeTypeFilter.c_str()); + } + + DataAbilityHelper *objectInfo = nullptr; + napi_unwrap(env, thisVar, (void **)&objectInfo); + HILOG_INFO("%{public}s,DataAbilityHelper objectInfo = %{public}p", __func__, objectInfo); + getfiletypesCB->dataAbilityHelper = objectInfo; + + if (argcAsync > argcPromise) { + ret = GetFileTypesAsync(env, args, ARGS_TWO, getfiletypesCB); + } else { + ret = GetFileTypesPromise(env, getfiletypesCB); + } + HILOG_INFO("%{public}s,end", __func__); + return ret; +} +napi_value GetFileTypesAsync( + napi_env env, napi_value *args, const size_t argCallback, DAHelperGetFileTypesCB *getfiletypesCB) +{ + HILOG_INFO("%{public}s, asyncCallback.", __func__); + if (args == nullptr || getfiletypesCB == nullptr) { + HILOG_ERROR("%{public}s, param == nullptr.", __func__); + return nullptr; + } + napi_value resourceName = 0; + NAPI_CALL(env, napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName)); + + napi_valuetype valuetype = napi_undefined; + NAPI_CALL(env, napi_typeof(env, args[argCallback], &valuetype)); + if (valuetype == napi_function) { + NAPI_CALL(env, napi_create_reference(env, args[argCallback], 1, &getfiletypesCB->cbBase.cbInfo.callback)); + } + + NAPI_CALL(env, + napi_create_async_work(env, + nullptr, + resourceName, + GetFileTypesExecuteCB, + GetFileTypesAsyncCompleteCB, + (void *)getfiletypesCB, + &getfiletypesCB->cbBase.asyncWork)); + NAPI_CALL(env, napi_queue_async_work(env, getfiletypesCB->cbBase.asyncWork)); + napi_value result = 0; + NAPI_CALL(env, napi_get_null(env, &result)); + HILOG_INFO("%{public}s, asyncCallback end.", __func__); + return result; +} + +napi_value GetFileTypesPromise(napi_env env, DAHelperGetFileTypesCB *getfiletypesCB) +{ + HILOG_INFO("%{public}s, promise.", __func__); + if (getfiletypesCB == nullptr) { + HILOG_ERROR("%{public}s, param == nullptr.", __func__); + return nullptr; + } + napi_value resourceName; + NAPI_CALL(env, napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName)); + napi_deferred deferred; + napi_value promise = 0; + NAPI_CALL(env, napi_create_promise(env, &deferred, &promise)); + getfiletypesCB->cbBase.deferred = deferred; + + NAPI_CALL(env, + napi_create_async_work(env, + nullptr, + resourceName, + GetFileTypesExecuteCB, + GetFileTypesPromiseCompleteCB, + (void *)getfiletypesCB, + &getfiletypesCB->cbBase.asyncWork)); + NAPI_CALL(env, napi_queue_async_work(env, getfiletypesCB->cbBase.asyncWork)); + HILOG_INFO("%{public}s, promise end.", __func__); + return promise; +} + +void GetFileTypesExecuteCB(napi_env env, void *data) +{ + HILOG_INFO("NAPI_GetFileTypes, worker pool thread execute."); + DAHelperGetFileTypesCB *getfiletypesCB = static_cast(data); + if (getfiletypesCB->dataAbilityHelper != nullptr) { + OHOS::Uri uri(getfiletypesCB->uri); + HILOG_INFO("NAPI_GetFileTypes, uri:%{public}s", uri.ToString().c_str()); + HILOG_INFO("NAPI_GetFileTypes, mimeTypeFilter:%{public}s", getfiletypesCB->mimeTypeFilter.c_str()); + getfiletypesCB->result = getfiletypesCB->dataAbilityHelper->GetFileTypes(uri, getfiletypesCB->mimeTypeFilter); + } else { + HILOG_INFO("NAPI_GetFileTypes, dataAbilityHelper == nullptr."); + } + HILOG_INFO("NAPI_GetFileTypes, worker pool thread execute end."); +} + +void GetFileTypesAsyncCompleteCB(napi_env env, napi_status status, void *data) +{ + HILOG_INFO("NAPI_GetFileTypes, main event thread complete."); + DAHelperGetFileTypesCB *getfiletypesCB = static_cast(data); + napi_value callback = nullptr; + napi_value undefined = nullptr; + napi_value result[ARGS_TWO] = {nullptr}; + napi_value callResult = nullptr; + + NAPI_CALL_RETURN_VOID(env, napi_get_undefined(env, &undefined)); + NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, getfiletypesCB->cbBase.cbInfo.callback, &callback)); + + result[PARAM0] = GetCallbackErrorValue(env, NO_ERROR); + result[PARAM1] = WrapGetFileTypesCB(env, *getfiletypesCB); + + NAPI_CALL_RETURN_VOID(env, napi_call_function(env, undefined, callback, ARGS_TWO, &result[PARAM0], &callResult)); + + if (getfiletypesCB->cbBase.cbInfo.callback != nullptr) { + NAPI_CALL_RETURN_VOID(env, napi_delete_reference(env, getfiletypesCB->cbBase.cbInfo.callback)); + } + NAPI_CALL_RETURN_VOID(env, napi_delete_async_work(env, getfiletypesCB->cbBase.asyncWork)); + delete getfiletypesCB; + getfiletypesCB = nullptr; + HILOG_INFO("NAPI_GetFileTypes, main event thread complete end."); +} + +napi_value WrapGetFileTypesCB(napi_env env, const DAHelperGetFileTypesCB &getfiletypesCB) +{ + HILOG_INFO("WrapGetFileTypesCB, called."); + HILOG_INFO("NAPI_GetFileTypes, result.size:%{public}zu", getfiletypesCB.result.size()); + for (size_t i = 0; i < getfiletypesCB.result.size(); i++) { + HILOG_INFO("NAPI_GetFileTypes, result[%{public}zu]:%{public}s", i, getfiletypesCB.result.at(i).c_str()); + } + napi_value proValue = nullptr; + + napi_value jsArrayresult = nullptr; + NAPI_CALL(env, napi_create_array(env, &jsArrayresult)); + for (size_t i = 0; i < getfiletypesCB.result.size(); i++) { + proValue = nullptr; + NAPI_CALL(env, napi_create_string_utf8(env, getfiletypesCB.result.at(i).c_str(), NAPI_AUTO_LENGTH, &proValue)); + NAPI_CALL(env, napi_set_element(env, jsArrayresult, i, proValue)); + } + HILOG_INFO("WrapGetFileTypesCB, end."); + return jsArrayresult; +} + +void GetFileTypesPromiseCompleteCB(napi_env env, napi_status status, void *data) +{ + HILOG_INFO("NAPI_GetFileTypes, main event thread complete."); + DAHelperGetFileTypesCB *getfiletypesCB = static_cast(data); + napi_value result = nullptr; + + result = WrapGetFileTypesCB(env, *getfiletypesCB); + NAPI_CALL_RETURN_VOID(env, napi_resolve_deferred(env, getfiletypesCB->cbBase.deferred, result)); + NAPI_CALL_RETURN_VOID(env, napi_delete_async_work(env, getfiletypesCB->cbBase.asyncWork)); + delete getfiletypesCB; + getfiletypesCB = nullptr; + HILOG_INFO("NAPI_GetFileTypes, main event thread complete end."); +} + +napi_value NAPI_NormalizeUri(napi_env env, napi_callback_info info) +{ + HILOG_INFO("%{public}s,called", __func__); + DAHelperNormalizeUriCB *normalizeuriCB = new (std::nothrow) DAHelperNormalizeUriCB; + if (normalizeuriCB == nullptr) { + HILOG_ERROR("%{public}s, normalizeuriCB == nullptr.", __func__); + return WrapVoidToJS(env); + } + normalizeuriCB->cbBase.cbInfo.env = env; + normalizeuriCB->cbBase.asyncWork = nullptr; + normalizeuriCB->cbBase.deferred = nullptr; + normalizeuriCB->cbBase.ability = nullptr; + + napi_value ret = NormalizeUriWrap(env, info, normalizeuriCB); + if (ret == nullptr) { + HILOG_ERROR("%{public}s,ret == nullptr", __func__); + if (normalizeuriCB != nullptr) { + delete normalizeuriCB; + normalizeuriCB = nullptr; + } + ret = WrapVoidToJS(env); + } + HILOG_INFO("%{public}s,end", __func__); + return ret; +} + +napi_value NormalizeUriWrap(napi_env env, napi_callback_info info, DAHelperNormalizeUriCB *normalizeuriCB) +{ + HILOG_INFO("%{public}s,called", __func__); + size_t argcAsync = ARGS_TWO; + const size_t argcPromise = ARGS_ONE; + const size_t argCountWithAsync = argcPromise + ARGS_ASYNC_COUNT; + napi_value args[ARGS_MAX_COUNT] = {nullptr}; + napi_value ret = 0; + napi_value thisVar = nullptr; + + NAPI_CALL(env, napi_get_cb_info(env, info, &argcAsync, args, &thisVar, nullptr)); + if (argcAsync > argCountWithAsync || argcAsync > ARGS_MAX_COUNT) { + HILOG_ERROR("%{public}s, Wrong argument count.", __func__); + return nullptr; + } + + napi_valuetype valuetype = napi_undefined; + NAPI_CALL(env, napi_typeof(env, args[PARAM0], &valuetype)); + if (valuetype == napi_string) { + normalizeuriCB->uri = NapiValueToStringUtf8(env, args[PARAM0]); + HILOG_INFO("%{public}s,uri=%{public}s", __func__, normalizeuriCB->uri.c_str()); + } + + DataAbilityHelper *objectInfo = nullptr; + napi_unwrap(env, thisVar, (void **)&objectInfo); + HILOG_INFO("%{public}s,DataAbilityHelper objectInfo = %{public}p", __func__, objectInfo); + normalizeuriCB->dataAbilityHelper = objectInfo; + + if (argcAsync > argcPromise) { + ret = NormalizeUriAsync(env, args, ARGS_ONE, normalizeuriCB); + } else { + ret = NormalizeUriPromise(env, normalizeuriCB); + } + HILOG_INFO("%{public}s,end", __func__); + return ret; +} +napi_value NormalizeUriAsync( + napi_env env, napi_value *args, const size_t argCallback, DAHelperNormalizeUriCB *normalizeuriCB) +{ + HILOG_INFO("%{public}s, asyncCallback.", __func__); + if (args == nullptr || normalizeuriCB == nullptr) { + HILOG_ERROR("%{public}s, param == nullptr.", __func__); + return nullptr; + } + napi_value resourceName = 0; + NAPI_CALL(env, napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName)); + + napi_valuetype valuetype = napi_undefined; + NAPI_CALL(env, napi_typeof(env, args[argCallback], &valuetype)); + if (valuetype == napi_function) { + NAPI_CALL(env, napi_create_reference(env, args[argCallback], 1, &normalizeuriCB->cbBase.cbInfo.callback)); + } + + NAPI_CALL(env, + napi_create_async_work(env, + nullptr, + resourceName, + NormalizeUriExecuteCB, + NormalizeUriAsyncCompleteCB, + (void *)normalizeuriCB, + &normalizeuriCB->cbBase.asyncWork)); + NAPI_CALL(env, napi_queue_async_work(env, normalizeuriCB->cbBase.asyncWork)); + napi_value result = 0; + NAPI_CALL(env, napi_get_null(env, &result)); + HILOG_INFO("%{public}s, asyncCallback end.", __func__); + return result; +} + +napi_value NormalizeUriPromise(napi_env env, DAHelperNormalizeUriCB *normalizeuriCB) +{ + HILOG_INFO("%{public}s, promise.", __func__); + if (normalizeuriCB == nullptr) { + HILOG_ERROR("%{public}s, param == nullptr.", __func__); + return nullptr; + } + napi_value resourceName; + NAPI_CALL(env, napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName)); + napi_deferred deferred; + napi_value promise = 0; + NAPI_CALL(env, napi_create_promise(env, &deferred, &promise)); + normalizeuriCB->cbBase.deferred = deferred; + + NAPI_CALL(env, + napi_create_async_work(env, + nullptr, + resourceName, + NormalizeUriExecuteCB, + NormalizeUriPromiseCompleteCB, + (void *)normalizeuriCB, + &normalizeuriCB->cbBase.asyncWork)); + NAPI_CALL(env, napi_queue_async_work(env, normalizeuriCB->cbBase.asyncWork)); + HILOG_INFO("%{public}s, promise end.", __func__); + return promise; +} + +void NormalizeUriExecuteCB(napi_env env, void *data) +{ + HILOG_INFO("NAPI_NormalizeUri, worker pool thread execute."); + DAHelperNormalizeUriCB *normalizeuriCB = static_cast(data); + Uri uriValue(normalizeuriCB->uri); + if (normalizeuriCB->dataAbilityHelper != nullptr) { + OHOS::Uri uri(normalizeuriCB->uri); + uriValue = normalizeuriCB->dataAbilityHelper->NormalizeUri(uri); + normalizeuriCB->result = uriValue.ToString(); + } else { + HILOG_INFO("NAPI_NormalizeUri, dataAbilityHelper == nullptr"); + } + HILOG_INFO("NAPI_NormalizeUri, worker pool thread execute end."); +} + +void NormalizeUriAsyncCompleteCB(napi_env env, napi_status status, void *data) +{ + HILOG_INFO("NAPI_NormalizeUri, main event thread complete."); + DAHelperNormalizeUriCB *normalizeuriCB = static_cast(data); + napi_value callback = nullptr; + napi_value undefined = nullptr; + napi_value result[ARGS_TWO] = {nullptr}; + napi_value callResult = nullptr; + NAPI_CALL_RETURN_VOID(env, napi_get_undefined(env, &undefined)); + NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, normalizeuriCB->cbBase.cbInfo.callback, &callback)); + + result[PARAM0] = GetCallbackErrorValue(env, NO_ERROR); + NAPI_CALL_RETURN_VOID( + env, napi_create_string_utf8(env, normalizeuriCB->result.c_str(), NAPI_AUTO_LENGTH, &result[PARAM1])); + + NAPI_CALL_RETURN_VOID(env, napi_call_function(env, undefined, callback, ARGS_TWO, &result[PARAM0], &callResult)); + + if (normalizeuriCB->cbBase.cbInfo.callback != nullptr) { + NAPI_CALL_RETURN_VOID(env, napi_delete_reference(env, normalizeuriCB->cbBase.cbInfo.callback)); + } + NAPI_CALL_RETURN_VOID(env, napi_delete_async_work(env, normalizeuriCB->cbBase.asyncWork)); + delete normalizeuriCB; + normalizeuriCB = nullptr; + HILOG_INFO("NAPI_NormalizeUri, main event thread complete end."); +} + +void NormalizeUriPromiseCompleteCB(napi_env env, napi_status status, void *data) +{ + HILOG_INFO("NAPI_NormalizeUri, main event thread complete."); + DAHelperNormalizeUriCB *normalizeuriCB = static_cast(data); + napi_value result = nullptr; + NAPI_CALL_RETURN_VOID(env, napi_create_string_utf8(env, normalizeuriCB->result.c_str(), NAPI_AUTO_LENGTH, &result)); + NAPI_CALL_RETURN_VOID(env, napi_resolve_deferred(env, normalizeuriCB->cbBase.deferred, result)); + NAPI_CALL_RETURN_VOID(env, napi_delete_async_work(env, normalizeuriCB->cbBase.asyncWork)); + delete normalizeuriCB; + normalizeuriCB = nullptr; + HILOG_INFO("NAPI_NormalizeUri, main event thread complete end."); +} + +napi_value NAPI_DenormalizeUri(napi_env env, napi_callback_info info) +{ + HILOG_INFO("%{public}s,called", __func__); + DAHelperDenormalizeUriCB *denormalizeuriCB = new (std::nothrow) DAHelperDenormalizeUriCB; + if (denormalizeuriCB == nullptr) { + HILOG_ERROR("%{public}s, denormalizeuriCB == nullptr.", __func__); + return WrapVoidToJS(env); + } + denormalizeuriCB->cbBase.cbInfo.env = env; + denormalizeuriCB->cbBase.asyncWork = nullptr; + denormalizeuriCB->cbBase.deferred = nullptr; + denormalizeuriCB->cbBase.ability = nullptr; + + napi_value ret = DenormalizeUriWrap(env, info, denormalizeuriCB); + if (ret == nullptr) { + HILOG_ERROR("%{public}s,ret == nullptr", __func__); + if (denormalizeuriCB != nullptr) { + delete denormalizeuriCB; + denormalizeuriCB = nullptr; + } + ret = WrapVoidToJS(env); + } + HILOG_INFO("%{public}s,end", __func__); + return ret; +} + +napi_value DenormalizeUriWrap(napi_env env, napi_callback_info info, DAHelperDenormalizeUriCB *denormalizeuriCB) +{ + HILOG_INFO("%{public}s,called", __func__); + size_t argcAsync = ARGS_TWO; + const size_t argcPromise = ARGS_ONE; + const size_t argCountWithAsync = argcPromise + ARGS_ASYNC_COUNT; + napi_value args[ARGS_MAX_COUNT] = {nullptr}; + napi_value ret = 0; + napi_value thisVar = nullptr; + + NAPI_CALL(env, napi_get_cb_info(env, info, &argcAsync, args, &thisVar, nullptr)); + if (argcAsync > argCountWithAsync || argcAsync > ARGS_MAX_COUNT) { + HILOG_ERROR("%{public}s, Wrong argument count.", __func__); + return nullptr; + } + + napi_valuetype valuetype = napi_undefined; + NAPI_CALL(env, napi_typeof(env, args[PARAM0], &valuetype)); + if (valuetype == napi_string) { + denormalizeuriCB->uri = NapiValueToStringUtf8(env, args[PARAM0]); + HILOG_INFO("%{public}s,uri=%{public}s", __func__, denormalizeuriCB->uri.c_str()); + } + + DataAbilityHelper *objectInfo = nullptr; + napi_unwrap(env, thisVar, (void **)&objectInfo); + HILOG_INFO("%{public}s,DataAbilityHelper objectInfo = %{public}p", __func__, objectInfo); + denormalizeuriCB->dataAbilityHelper = objectInfo; + + if (argcAsync > argcPromise) { + ret = DenormalizeUriAsync(env, args, ARGS_ONE, denormalizeuriCB); + } else { + ret = DenormalizeUriPromise(env, denormalizeuriCB); + } + HILOG_INFO("%{public}s,end", __func__); + return ret; +} +napi_value DenormalizeUriAsync( + napi_env env, napi_value *args, const size_t argCallback, DAHelperDenormalizeUriCB *denormalizeuriCB) +{ + HILOG_INFO("%{public}s, asyncCallback.", __func__); + if (args == nullptr || denormalizeuriCB == nullptr) { + HILOG_ERROR("%{public}s, param == nullptr.", __func__); + return nullptr; + } + napi_value resourceName = 0; + NAPI_CALL(env, napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName)); + + napi_valuetype valuetype = napi_undefined; + NAPI_CALL(env, napi_typeof(env, args[argCallback], &valuetype)); + if (valuetype == napi_function) { + NAPI_CALL(env, napi_create_reference(env, args[argCallback], 1, &denormalizeuriCB->cbBase.cbInfo.callback)); + } + + NAPI_CALL(env, + napi_create_async_work(env, + nullptr, + resourceName, + DenormalizeUriExecuteCB, + DenormalizeUriAsyncCompleteCB, + (void *)denormalizeuriCB, + &denormalizeuriCB->cbBase.asyncWork)); + NAPI_CALL(env, napi_queue_async_work(env, denormalizeuriCB->cbBase.asyncWork)); + napi_value result = 0; + NAPI_CALL(env, napi_get_null(env, &result)); + HILOG_INFO("%{public}s, asyncCallback end.", __func__); + return result; +} + +napi_value DenormalizeUriPromise(napi_env env, DAHelperDenormalizeUriCB *denormalizeuriCB) +{ + HILOG_INFO("%{public}s, promise.", __func__); + if (denormalizeuriCB == nullptr) { + HILOG_ERROR("%{public}s, param == nullptr.", __func__); + return nullptr; + } + napi_value resourceName; + NAPI_CALL(env, napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName)); + napi_deferred deferred; + napi_value promise = 0; + NAPI_CALL(env, napi_create_promise(env, &deferred, &promise)); + denormalizeuriCB->cbBase.deferred = deferred; + + NAPI_CALL(env, + napi_create_async_work(env, + nullptr, + resourceName, + DenormalizeUriExecuteCB, + DenormalizeUriPromiseCompleteCB, + (void *)denormalizeuriCB, + &denormalizeuriCB->cbBase.asyncWork)); + NAPI_CALL(env, napi_queue_async_work(env, denormalizeuriCB->cbBase.asyncWork)); + HILOG_INFO("%{public}s, promise end.", __func__); + return promise; +} + +void DenormalizeUriExecuteCB(napi_env env, void *data) +{ + HILOG_INFO("NAPI_DenormalizeUri, worker pool thread execute."); + DAHelperDenormalizeUriCB *denormalizeuriCB = static_cast(data); + Uri uriValue(denormalizeuriCB->uri); + if (denormalizeuriCB->dataAbilityHelper != nullptr) { + OHOS::Uri uri(denormalizeuriCB->uri); + uriValue = denormalizeuriCB->dataAbilityHelper->DenormalizeUri(uri); + denormalizeuriCB->result = uriValue.ToString(); + } else { + HILOG_ERROR("NAPI_DenormalizeUri, dataAbilityHelper == nullptr"); + } + HILOG_INFO("NAPI_DenormalizeUri, worker pool thread execute end."); +} + +void DenormalizeUriAsyncCompleteCB(napi_env env, napi_status status, void *data) +{ + HILOG_INFO("NAPI_DenormalizeUri, main event thread complete."); + DAHelperDenormalizeUriCB *denormalizeuriCB = static_cast(data); + napi_value callback = nullptr; + napi_value undefined = nullptr; + napi_value result[ARGS_TWO] = {nullptr}; + napi_value callResult = nullptr; + NAPI_CALL_RETURN_VOID(env, napi_get_undefined(env, &undefined)); + NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, denormalizeuriCB->cbBase.cbInfo.callback, &callback)); + + result[PARAM0] = GetCallbackErrorValue(env, NO_ERROR); + NAPI_CALL_RETURN_VOID( + env, napi_create_string_utf8(env, denormalizeuriCB->result.c_str(), NAPI_AUTO_LENGTH, &result[PARAM1])); + + NAPI_CALL_RETURN_VOID(env, napi_call_function(env, undefined, callback, ARGS_TWO, &result[PARAM0], &callResult)); + + if (denormalizeuriCB->cbBase.cbInfo.callback != nullptr) { + NAPI_CALL_RETURN_VOID(env, napi_delete_reference(env, denormalizeuriCB->cbBase.cbInfo.callback)); + } + NAPI_CALL_RETURN_VOID(env, napi_delete_async_work(env, denormalizeuriCB->cbBase.asyncWork)); + delete denormalizeuriCB; + denormalizeuriCB = nullptr; + HILOG_INFO("NAPI_DenormalizeUri, main event thread complete end."); +} + +void DenormalizeUriPromiseCompleteCB(napi_env env, napi_status status, void *data) +{ + HILOG_INFO("NAPI_DenormalizeUri, main event thread complete."); + DAHelperDenormalizeUriCB *denormalizeuriCB = static_cast(data); + napi_value result = nullptr; + NAPI_CALL_RETURN_VOID( + env, napi_create_string_utf8(env, denormalizeuriCB->result.c_str(), NAPI_AUTO_LENGTH, &result)); + NAPI_CALL_RETURN_VOID(env, napi_resolve_deferred(env, denormalizeuriCB->cbBase.deferred, result)); + NAPI_CALL_RETURN_VOID(env, napi_delete_async_work(env, denormalizeuriCB->cbBase.asyncWork)); + delete denormalizeuriCB; + denormalizeuriCB = nullptr; + HILOG_INFO("NAPI_DenormalizeUri, main event thread complete end."); +} + +void UnwrapDataAbilityPredicates(NativeRdb::DataAbilityPredicates &predicates, napi_env env, napi_value value) +{ + auto tempPredicates = DataAbilityJsKit::DataAbilityPredicatesProxy::GetNativePredicates(env, value); + if (tempPredicates == nullptr) { + HILOG_ERROR("%{public}s, GetNativePredicates retval Marshalling failed.", __func__); + return; + } + predicates = *tempPredicates; +} + +/** + * @brief DataAbilityHelper NAPI method : insert. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_Delete(napi_env env, napi_callback_info info) +{ + HILOG_INFO("%{public}s,called", __func__); + DAHelperDeleteCB *deleteCB = new (std::nothrow) DAHelperDeleteCB; + if (deleteCB == nullptr) { + HILOG_ERROR("%{public}s, deleteCB == nullptr.", __func__); + return WrapVoidToJS(env); + } + deleteCB->cbBase.cbInfo.env = env; + deleteCB->cbBase.asyncWork = nullptr; + deleteCB->cbBase.deferred = nullptr; + deleteCB->cbBase.ability = nullptr; + + napi_value ret = DeleteWrap(env, info, deleteCB); + if (ret == nullptr) { + HILOG_ERROR("%{public}s,ret == nullptr", __func__); + if (deleteCB != nullptr) { + delete deleteCB; + deleteCB = nullptr; + } + ret = WrapVoidToJS(env); + } + HILOG_INFO("%{public}s,end", __func__); + return ret; +} + +/** + * @brief Insert processing function. + * + * @param env The environment that the Node-API call is invoked under. + * @param insertCB Process data asynchronously. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value DeleteWrap(napi_env env, napi_callback_info info, DAHelperDeleteCB *deleteCB) +{ + HILOG_INFO("%{public}s,called", __func__); + size_t argcAsync = ARGS_THREE; + const size_t argcPromise = ARGS_TWO; + const size_t argCountWithAsync = argcPromise + ARGS_ASYNC_COUNT; + napi_value args[ARGS_MAX_COUNT] = {nullptr}; + napi_value ret = 0; + napi_value thisVar = nullptr; + + NAPI_CALL(env, napi_get_cb_info(env, info, &argcAsync, args, &thisVar, nullptr)); + if (argcAsync > argCountWithAsync || argcAsync > ARGS_MAX_COUNT) { + HILOG_ERROR("%{public}s, Wrong argument count.", __func__); + return nullptr; + } + + napi_valuetype valuetype = napi_undefined; + NAPI_CALL(env, napi_typeof(env, args[PARAM0], &valuetype)); + if (valuetype == napi_string) { + deleteCB->uri = NapiValueToStringUtf8(env, args[PARAM0]); + HILOG_INFO("%{public}s,uri=%{public}s", __func__, deleteCB->uri.c_str()); + } + + UnwrapDataAbilityPredicates(deleteCB->predicates, env, args[PARAM1]); + DataAbilityHelper *objectInfo = nullptr; + napi_unwrap(env, thisVar, (void **)&objectInfo); + HILOG_INFO("%{public}s,DataAbilityHelper objectInfo = %{public}p", __func__, objectInfo); + deleteCB->dataAbilityHelper = objectInfo; + + if (argcAsync > argcPromise) { + ret = DeleteAsync(env, args, ARGS_TWO, deleteCB); + } else { + ret = DeletePromise(env, deleteCB); + } + HILOG_INFO("%{public}s,end", __func__); + return ret; +} + +napi_value DeleteAsync(napi_env env, napi_value *args, const size_t argCallback, DAHelperDeleteCB *deleteCB) +{ + HILOG_INFO("%{public}s, asyncCallback.", __func__); + if (args == nullptr || deleteCB == nullptr) { + HILOG_ERROR("%{public}s, param == nullptr.", __func__); + return nullptr; + } + napi_value resourceName = 0; + NAPI_CALL(env, napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName)); + + napi_valuetype valuetype = napi_undefined; + NAPI_CALL(env, napi_typeof(env, args[argCallback], &valuetype)); + if (valuetype == napi_function) { + NAPI_CALL(env, napi_create_reference(env, args[argCallback], 1, &deleteCB->cbBase.cbInfo.callback)); + } + + NAPI_CALL(env, + napi_create_async_work(env, + nullptr, + resourceName, + DeleteExecuteCB, + DeleteAsyncCompleteCB, + (void *)deleteCB, + &deleteCB->cbBase.asyncWork)); + NAPI_CALL(env, napi_queue_async_work(env, deleteCB->cbBase.asyncWork)); + napi_value result = 0; + NAPI_CALL(env, napi_get_null(env, &result)); + HILOG_INFO("%{public}s, asyncCallback end.", __func__); + return result; +} + +napi_value DeletePromise(napi_env env, DAHelperDeleteCB *deleteCB) +{ + HILOG_INFO("%{public}s, promise.", __func__); + if (deleteCB == nullptr) { + HILOG_ERROR("%{public}s, param == nullptr.", __func__); + return nullptr; + } + napi_value resourceName; + NAPI_CALL(env, napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName)); + napi_deferred deferred; + napi_value promise = 0; + NAPI_CALL(env, napi_create_promise(env, &deferred, &promise)); + deleteCB->cbBase.deferred = deferred; + + NAPI_CALL(env, + napi_create_async_work(env, + nullptr, + resourceName, + DeleteExecuteCB, + DeletePromiseCompleteCB, + (void *)deleteCB, + &deleteCB->cbBase.asyncWork)); + NAPI_CALL(env, napi_queue_async_work(env, deleteCB->cbBase.asyncWork)); + HILOG_INFO("%{public}s, promise end.", __func__); + return promise; +} + +void DeleteExecuteCB(napi_env env, void *data) +{ + HILOG_INFO("NAPI_Delete, worker pool thread execute."); + DAHelperDeleteCB *deleteCB = static_cast(data); + if (deleteCB->dataAbilityHelper != nullptr) { + OHOS::Uri uri(deleteCB->uri); + deleteCB->result = deleteCB->dataAbilityHelper->Delete(uri, deleteCB->predicates); + } else { + HILOG_ERROR("NAPI_Delete, dataAbilityHelper == nullptr"); + } + HILOG_INFO("NAPI_Delete, worker pool thread execute end."); +} + +void DeleteAsyncCompleteCB(napi_env env, napi_status status, void *data) +{ + HILOG_INFO("NAPI_Delete, main event thread complete."); + DAHelperDeleteCB *DeleteCB = static_cast(data); + napi_value callback = nullptr; + napi_value undefined = nullptr; + napi_value result[ARGS_TWO] = {nullptr}; + napi_value callResult = nullptr; + NAPI_CALL_RETURN_VOID(env, napi_get_undefined(env, &undefined)); + NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, DeleteCB->cbBase.cbInfo.callback, &callback)); + + result[PARAM0] = GetCallbackErrorValue(env, NO_ERROR); + napi_create_int32(env, DeleteCB->result, &result[PARAM1]); + NAPI_CALL_RETURN_VOID(env, napi_call_function(env, undefined, callback, ARGS_TWO, &result[PARAM0], &callResult)); + + if (DeleteCB->cbBase.cbInfo.callback != nullptr) { + NAPI_CALL_RETURN_VOID(env, napi_delete_reference(env, DeleteCB->cbBase.cbInfo.callback)); + } + NAPI_CALL_RETURN_VOID(env, napi_delete_async_work(env, DeleteCB->cbBase.asyncWork)); + delete DeleteCB; + DeleteCB = nullptr; + HILOG_INFO("NAPI_Delete, main event thread complete end."); +} + +void DeletePromiseCompleteCB(napi_env env, napi_status status, void *data) +{ + HILOG_INFO("NAPI_Delete, main event thread complete."); + DAHelperDeleteCB *DeleteCB = static_cast(data); + napi_value result = nullptr; + napi_create_int32(env, DeleteCB->result, &result); + NAPI_CALL_RETURN_VOID(env, napi_resolve_deferred(env, DeleteCB->cbBase.deferred, result)); + NAPI_CALL_RETURN_VOID(env, napi_delete_async_work(env, DeleteCB->cbBase.asyncWork)); + delete DeleteCB; + DeleteCB = nullptr; + HILOG_INFO("NAPI_Delete, main event thread complete end."); +} + +/** + * @brief DataAbilityHelper NAPI method : insert. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_Update(napi_env env, napi_callback_info info) +{ + HILOG_INFO("%{public}s,called", __func__); + DAHelperUpdateCB *updateCB = new (std::nothrow) DAHelperUpdateCB; + if (updateCB == nullptr) { + HILOG_ERROR("%{public}s, updateCB == nullptr.", __func__); + return WrapVoidToJS(env); + } + updateCB->cbBase.cbInfo.env = env; + updateCB->cbBase.asyncWork = nullptr; + updateCB->cbBase.deferred = nullptr; + updateCB->cbBase.ability = nullptr; + + napi_value ret = UpdateWrap(env, info, updateCB); + if (ret == nullptr) { + HILOG_ERROR("%{public}s,ret == nullptr", __func__); + if (updateCB != nullptr) { + delete updateCB; + updateCB = nullptr; + } + ret = WrapVoidToJS(env); + } + HILOG_INFO("%{public}s,end", __func__); + return ret; +} + +/** + * @brief Insert processing function. + * + * @param env The environment that the Node-API call is invoked under. + * @param insertCB Process data asynchronously. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value UpdateWrap(napi_env env, napi_callback_info info, DAHelperUpdateCB *updateCB) +{ + HILOG_INFO("%{public}s,called", __func__); + size_t argcAsync = ARGS_FOUR; + const size_t argcPromise = ARGS_THREE; + const size_t argCountWithAsync = argcPromise + ARGS_ASYNC_COUNT; + napi_value args[ARGS_MAX_COUNT] = {nullptr}; + napi_value ret = 0; + napi_value thisVar = nullptr; + + NAPI_CALL(env, napi_get_cb_info(env, info, &argcAsync, args, &thisVar, nullptr)); + if (argcAsync > argCountWithAsync || argcAsync > ARGS_MAX_COUNT) { + HILOG_ERROR("%{public}s, Wrong argument count.", __func__); + return nullptr; + } + + napi_valuetype valuetype = napi_undefined; + NAPI_CALL(env, napi_typeof(env, args[PARAM0], &valuetype)); + if (valuetype == napi_string) { + updateCB->uri = NapiValueToStringUtf8(env, args[PARAM0]); + HILOG_INFO("%{public}s,uri=%{public}s", __func__, updateCB->uri.c_str()); + } + + updateCB->valueBucket.Clear(); + AnalysisValuesBucket(updateCB->valueBucket, env, args[PARAM1]); + UnwrapDataAbilityPredicates(updateCB->predicates, env, args[PARAM2]); + DataAbilityHelper *objectInfo = nullptr; + napi_unwrap(env, thisVar, (void **)&objectInfo); + HILOG_INFO("%{public}s,DataAbilityHelper objectInfo = %{public}p", __func__, objectInfo); + updateCB->dataAbilityHelper = objectInfo; + + if (argcAsync > argcPromise) { + ret = UpdateAsync(env, args, ARGS_THREE, updateCB); + } else { + ret = UpdatePromise(env, updateCB); + } + HILOG_INFO("%{public}s,end", __func__); + return ret; +} + +napi_value UpdateAsync(napi_env env, napi_value *args, const size_t argCallback, DAHelperUpdateCB *updateCB) +{ + HILOG_INFO("%{public}s, asyncCallback.", __func__); + if (args == nullptr || updateCB == nullptr) { + HILOG_ERROR("%{public}s, param == nullptr.", __func__); + return nullptr; + } + napi_value resourceName = 0; + NAPI_CALL(env, napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName)); + + napi_valuetype valuetype = napi_undefined; + NAPI_CALL(env, napi_typeof(env, args[argCallback], &valuetype)); + if (valuetype == napi_function) { + NAPI_CALL(env, napi_create_reference(env, args[argCallback], 1, &updateCB->cbBase.cbInfo.callback)); + } + + NAPI_CALL(env, + napi_create_async_work(env, + nullptr, + resourceName, + UpdateExecuteCB, + UpdateAsyncCompleteCB, + (void *)updateCB, + &updateCB->cbBase.asyncWork)); + NAPI_CALL(env, napi_queue_async_work(env, updateCB->cbBase.asyncWork)); + napi_value result = 0; + NAPI_CALL(env, napi_get_null(env, &result)); + HILOG_INFO("%{public}s, asyncCallback end.", __func__); + return result; +} + +napi_value UpdatePromise(napi_env env, DAHelperUpdateCB *updateCB) +{ + HILOG_INFO("%{public}s, promise.", __func__); + if (updateCB == nullptr) { + HILOG_ERROR("%{public}s, param == nullptr.", __func__); + return nullptr; + } + napi_value resourceName; + NAPI_CALL(env, napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName)); + napi_deferred deferred; + napi_value promise = 0; + NAPI_CALL(env, napi_create_promise(env, &deferred, &promise)); + updateCB->cbBase.deferred = deferred; + + NAPI_CALL(env, + napi_create_async_work(env, + nullptr, + resourceName, + UpdateExecuteCB, + UpdatePromiseCompleteCB, + (void *)updateCB, + &updateCB->cbBase.asyncWork)); + NAPI_CALL(env, napi_queue_async_work(env, updateCB->cbBase.asyncWork)); + HILOG_INFO("%{public}s, promise end.", __func__); + return promise; +} + +void UpdateExecuteCB(napi_env env, void *data) +{ + HILOG_INFO("NAPI_Update, worker pool thread execute."); + DAHelperUpdateCB *updateCB = static_cast(data); + if (updateCB->dataAbilityHelper != nullptr) { + OHOS::Uri uri(updateCB->uri); + updateCB->result = updateCB->dataAbilityHelper->Update(uri, updateCB->valueBucket, updateCB->predicates); + } else { + HILOG_ERROR("NAPI_Update, dataAbilityHelper == nullptr"); + } + HILOG_INFO("NAPI_Update, worker pool thread execute end."); +} + +void UpdateAsyncCompleteCB(napi_env env, napi_status status, void *data) +{ + HILOG_INFO("NAPI_Update, main event thread complete."); + DAHelperUpdateCB *updateCB = static_cast(data); + napi_value callback = nullptr; + napi_value undefined = nullptr; + napi_value result[ARGS_TWO] = {nullptr}; + napi_value callResult = nullptr; + NAPI_CALL_RETURN_VOID(env, napi_get_undefined(env, &undefined)); + NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, updateCB->cbBase.cbInfo.callback, &callback)); + + result[PARAM0] = GetCallbackErrorValue(env, NO_ERROR); + napi_create_int32(env, updateCB->result, &result[PARAM1]); + NAPI_CALL_RETURN_VOID(env, napi_call_function(env, undefined, callback, ARGS_TWO, &result[PARAM0], &callResult)); + + if (updateCB->cbBase.cbInfo.callback != nullptr) { + NAPI_CALL_RETURN_VOID(env, napi_delete_reference(env, updateCB->cbBase.cbInfo.callback)); + } + NAPI_CALL_RETURN_VOID(env, napi_delete_async_work(env, updateCB->cbBase.asyncWork)); + delete updateCB; + updateCB = nullptr; + HILOG_INFO("NAPI_Update, main event thread complete end."); +} + +void UpdatePromiseCompleteCB(napi_env env, napi_status status, void *data) +{ + HILOG_INFO("NAPI_Update, main event thread complete."); + DAHelperUpdateCB *updateCB = static_cast(data); + napi_value result = nullptr; + napi_create_int32(env, updateCB->result, &result); + NAPI_CALL_RETURN_VOID(env, napi_resolve_deferred(env, updateCB->cbBase.deferred, result)); + NAPI_CALL_RETURN_VOID(env, napi_delete_async_work(env, updateCB->cbBase.asyncWork)); + delete updateCB; + updateCB = nullptr; + HILOG_INFO("NAPI_Update, main event thread complete end."); +} + +/** + * @brief DataAbilityHelper NAPI method : insert. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_OpenFile(napi_env env, napi_callback_info info) +{ + HILOG_INFO("%{public}s,called", __func__); + DAHelperOpenFileCB *openFileCB = new (std::nothrow) DAHelperOpenFileCB; + if (openFileCB == nullptr) { + HILOG_ERROR("%{public}s, openFileCB == nullptr.", __func__); + return WrapVoidToJS(env); + } + openFileCB->cbBase.cbInfo.env = env; + openFileCB->cbBase.asyncWork = nullptr; + openFileCB->cbBase.deferred = nullptr; + openFileCB->cbBase.ability = nullptr; + + napi_value ret = OpenFileWrap(env, info, openFileCB); + if (ret == nullptr) { + HILOG_ERROR("%{public}s,ret == nullptr", __func__); + if (openFileCB != nullptr) { + delete openFileCB; + openFileCB = nullptr; + } + ret = WrapVoidToJS(env); + } + HILOG_INFO("%{public}s,end", __func__); + return ret; +} + +/** + * @brief Insert processing function. + * + * @param env The environment that the Node-API call is invoked under. + * @param insertCB Process data asynchronously. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value OpenFileWrap(napi_env env, napi_callback_info info, DAHelperOpenFileCB *openFileCB) +{ + HILOG_INFO("%{public}s,called", __func__); + size_t argcAsync = ARGS_THREE; + const size_t argcPromise = ARGS_TWO; + const size_t argCountWithAsync = argcPromise + ARGS_ASYNC_COUNT; + napi_value args[ARGS_MAX_COUNT] = {nullptr}; + napi_value ret = 0; + napi_value thisVar = nullptr; + + NAPI_CALL(env, napi_get_cb_info(env, info, &argcAsync, args, &thisVar, nullptr)); + if (argcAsync > argCountWithAsync || argcAsync > ARGS_MAX_COUNT) { + HILOG_ERROR("%{public}s, Wrong argument count.", __func__); + return nullptr; + } + + napi_valuetype valuetype = napi_undefined; + NAPI_CALL(env, napi_typeof(env, args[PARAM0], &valuetype)); + if (valuetype == napi_string) { + openFileCB->uri = NapiValueToStringUtf8(env, args[PARAM0]); + HILOG_INFO("%{public}s,uri=%{public}s", __func__, openFileCB->uri.c_str()); + } + + NAPI_CALL(env, napi_typeof(env, args[PARAM1], &valuetype)); + if (valuetype == napi_string) { + openFileCB->mode = NapiValueToStringUtf8(env, args[PARAM1]); + HILOG_INFO("%{public}s,mode=%{public}s", __func__, openFileCB->mode.c_str()); + } + + DataAbilityHelper *objectInfo = nullptr; + napi_unwrap(env, thisVar, (void **)&objectInfo); + HILOG_INFO("%{public}s,DataAbilityHelper objectInfo = %{public}p", __func__, objectInfo); + openFileCB->dataAbilityHelper = objectInfo; + + if (argcAsync > argcPromise) { + ret = OpenFileAsync(env, args, ARGS_TWO, openFileCB); + } else { + ret = OpenFilePromise(env, openFileCB); + } + HILOG_INFO("%{public}s,end", __func__); + return ret; +} + +napi_value OpenFileAsync(napi_env env, napi_value *args, const size_t argCallback, DAHelperOpenFileCB *openFileCB) +{ + HILOG_INFO("%{public}s, asyncCallback.", __func__); + if (args == nullptr || openFileCB == nullptr) { + HILOG_ERROR("%{public}s, param == nullptr.", __func__); + return nullptr; + } + napi_value resourceName = 0; + NAPI_CALL(env, napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName)); + + napi_valuetype valuetype = napi_undefined; + NAPI_CALL(env, napi_typeof(env, args[argCallback], &valuetype)); + if (valuetype == napi_function) { + NAPI_CALL(env, napi_create_reference(env, args[argCallback], 1, &openFileCB->cbBase.cbInfo.callback)); + } + + NAPI_CALL(env, + napi_create_async_work(env, + nullptr, + resourceName, + OpenFileExecuteCB, + OpenFileAsyncCompleteCB, + (void *)openFileCB, + &openFileCB->cbBase.asyncWork)); + NAPI_CALL(env, napi_queue_async_work(env, openFileCB->cbBase.asyncWork)); + napi_value result = 0; + NAPI_CALL(env, napi_get_null(env, &result)); + HILOG_INFO("%{public}s, asyncCallback end.", __func__); + return result; +} + +napi_value OpenFilePromise(napi_env env, DAHelperOpenFileCB *openFileCB) +{ + HILOG_INFO("%{public}s, promise.", __func__); + if (openFileCB == nullptr) { + HILOG_ERROR("%{public}s, param == nullptr.", __func__); + return nullptr; + } + napi_value resourceName; + NAPI_CALL(env, napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName)); + napi_deferred deferred; + napi_value promise = 0; + NAPI_CALL(env, napi_create_promise(env, &deferred, &promise)); + openFileCB->cbBase.deferred = deferred; + + NAPI_CALL(env, + napi_create_async_work(env, + nullptr, + resourceName, + OpenFileExecuteCB, + OpenFilePromiseCompleteCB, + (void *)openFileCB, + &openFileCB->cbBase.asyncWork)); + NAPI_CALL(env, napi_queue_async_work(env, openFileCB->cbBase.asyncWork)); + HILOG_INFO("%{public}s, promise end.", __func__); + return promise; +} + +void OpenFileExecuteCB(napi_env env, void *data) +{ + HILOG_INFO("NAPI_OpenFile, worker pool thread execute."); + DAHelperOpenFileCB *OpenFileCB = static_cast(data); + if (OpenFileCB->dataAbilityHelper != nullptr) { + OHOS::Uri uri(OpenFileCB->uri); + OpenFileCB->result = OpenFileCB->dataAbilityHelper->OpenFile(uri, OpenFileCB->mode); + } else { + HILOG_ERROR("NAPI_OpenFile, dataAbilityHelper == nullptr"); + } + HILOG_INFO("NAPI_OpenFile, worker pool thread execute end."); +} + +void OpenFileAsyncCompleteCB(napi_env env, napi_status status, void *data) +{ + HILOG_INFO("NAPI_OpenFile, main event thread complete."); + DAHelperOpenFileCB *OpenFileCB = static_cast(data); + napi_value callback = nullptr; + napi_value undefined = nullptr; + napi_value result[ARGS_TWO] = {nullptr}; + napi_value callResult = nullptr; + NAPI_CALL_RETURN_VOID(env, napi_get_undefined(env, &undefined)); + NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, OpenFileCB->cbBase.cbInfo.callback, &callback)); + + result[PARAM0] = GetCallbackErrorValue(env, NO_ERROR); + napi_create_int32(env, OpenFileCB->result, &result[PARAM1]); + NAPI_CALL_RETURN_VOID(env, napi_call_function(env, undefined, callback, ARGS_TWO, &result[PARAM0], &callResult)); + + if (OpenFileCB->cbBase.cbInfo.callback != nullptr) { + NAPI_CALL_RETURN_VOID(env, napi_delete_reference(env, OpenFileCB->cbBase.cbInfo.callback)); + } + NAPI_CALL_RETURN_VOID(env, napi_delete_async_work(env, OpenFileCB->cbBase.asyncWork)); + delete OpenFileCB; + OpenFileCB = nullptr; + HILOG_INFO("NAPI_OpenFile, main event thread complete end."); +} + +void OpenFilePromiseCompleteCB(napi_env env, napi_status status, void *data) +{ + HILOG_INFO("NAPI_OpenFileCB, main event thread complete."); + DAHelperOpenFileCB *OpenFileCB = static_cast(data); + napi_value result = nullptr; + napi_create_int32(env, OpenFileCB->result, &result); + NAPI_CALL_RETURN_VOID(env, napi_resolve_deferred(env, OpenFileCB->cbBase.deferred, result)); + NAPI_CALL_RETURN_VOID(env, napi_delete_async_work(env, OpenFileCB->cbBase.asyncWork)); + delete OpenFileCB; + OpenFileCB = nullptr; + HILOG_INFO("NAPI_OpenFileCB, main event thread complete end."); +} + +/** + * @brief DataAbilityHelper NAPI method : insert. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_BatchInsert(napi_env env, napi_callback_info info) +{ + HILOG_INFO("%{public}s,called", __func__); + DAHelperBatchInsertCB *BatchInsertCB = new (std::nothrow) DAHelperBatchInsertCB; + if (BatchInsertCB == nullptr) { + HILOG_ERROR("%{public}s, BatchInsertCB == nullptr.", __func__); + return WrapVoidToJS(env); + } + BatchInsertCB->cbBase.cbInfo.env = env; + BatchInsertCB->cbBase.asyncWork = nullptr; + BatchInsertCB->cbBase.deferred = nullptr; + BatchInsertCB->cbBase.ability = nullptr; + + napi_value ret = BatchInsertWrap(env, info, BatchInsertCB); + if (ret == nullptr) { + HILOG_ERROR("%{public}s,ret == nullptr", __func__); + if (BatchInsertCB != nullptr) { + delete BatchInsertCB; + BatchInsertCB = nullptr; + } + ret = WrapVoidToJS(env); + } + HILOG_INFO("%{public}s,end", __func__); + return ret; +} + +std::vector NapiValueObject(napi_env env, napi_value param) +{ + HILOG_INFO("%{public}s,called", __func__); + std::vector result; + UnwrapArrayObjectFromJS(env, param, result); + return result; +} + +bool UnwrapArrayObjectFromJS(napi_env env, napi_value param, std::vector &value) +{ + HILOG_INFO("%{public}s,called", __func__); + uint32_t arraySize = 0; + napi_value jsValue = nullptr; + std::string strValue = ""; + + if (!IsArrayForNapiValue(env, param, arraySize)) { + HILOG_INFO("%{public}s, IsArrayForNapiValue is false", __func__); + return false; + } + + value.clear(); + for (uint32_t i = 0; i < arraySize; i++) { + jsValue = nullptr; + if (napi_get_element(env, param, i, &jsValue) != napi_ok) { + HILOG_INFO("%{public}s, napi_get_element is false", __func__); + return false; + } + + NativeRdb::ValuesBucket valueBucket; + valueBucket.Clear(); + AnalysisValuesBucket(valueBucket, env, jsValue); + + value.push_back(valueBucket); + } + HILOG_INFO("%{public}s,end", __func__); + return true; +} + +/** + * @brief Insert processing function. + * + * @param env The environment that the Node-API call is invoked under. + * @param insertCB Process data asynchronously. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value BatchInsertWrap(napi_env env, napi_callback_info info, DAHelperBatchInsertCB *batchInsertCB) +{ + HILOG_INFO("%{public}s,called", __func__); + size_t argcAsync = ARGS_THREE; + const size_t argcPromise = ARGS_TWO; + const size_t argCountWithAsync = argcPromise + ARGS_ASYNC_COUNT; + napi_value args[ARGS_MAX_COUNT] = {nullptr}; + napi_value ret = 0; + napi_value thisVar = nullptr; + + NAPI_CALL(env, napi_get_cb_info(env, info, &argcAsync, args, &thisVar, nullptr)); + if (argcAsync > argCountWithAsync || argcAsync > ARGS_MAX_COUNT) { + HILOG_ERROR("%{public}s, Wrong argument count.", __func__); + return nullptr; + } + + napi_valuetype valuetype = napi_undefined; + NAPI_CALL(env, napi_typeof(env, args[PARAM0], &valuetype)); + if (valuetype == napi_string) { + batchInsertCB->uri = NapiValueToStringUtf8(env, args[PARAM0]); + HILOG_INFO("%{public}s,uri=%{public}s", __func__, batchInsertCB->uri.c_str()); + } + + batchInsertCB->values = NapiValueObject(env, args[PARAM1]); + + DataAbilityHelper *objectInfo = nullptr; + napi_unwrap(env, thisVar, (void **)&objectInfo); + HILOG_INFO("%{public}s,DataAbilityHelper objectInfo = %{public}p", __func__, objectInfo); + batchInsertCB->dataAbilityHelper = objectInfo; + + if (argcAsync > argcPromise) { + ret = BatchInsertAsync(env, args, ARGS_TWO, batchInsertCB); + } else { + ret = BatchInsertPromise(env, batchInsertCB); + } + HILOG_INFO("%{public}s,end", __func__); + return ret; +} + +napi_value BatchInsertAsync( + napi_env env, napi_value *args, const size_t argCallback, DAHelperBatchInsertCB *batchInsertCB) +{ + HILOG_INFO("%{public}s, asyncCallback.", __func__); + if (args == nullptr || batchInsertCB == nullptr) { + HILOG_ERROR("%{public}s, param == nullptr.", __func__); + return nullptr; + } + napi_value resourceName = 0; + NAPI_CALL(env, napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName)); + + napi_valuetype valuetype = napi_undefined; + NAPI_CALL(env, napi_typeof(env, args[argCallback], &valuetype)); + if (valuetype == napi_function) { + NAPI_CALL(env, napi_create_reference(env, args[argCallback], 1, &batchInsertCB->cbBase.cbInfo.callback)); + } + + NAPI_CALL(env, + napi_create_async_work(env, + nullptr, + resourceName, + BatchInsertExecuteCB, + BatchInsertAsyncCompleteCB, + (void *)batchInsertCB, + &batchInsertCB->cbBase.asyncWork)); + NAPI_CALL(env, napi_queue_async_work(env, batchInsertCB->cbBase.asyncWork)); + napi_value result = 0; + NAPI_CALL(env, napi_get_null(env, &result)); + HILOG_INFO("%{public}s, asyncCallback end.", __func__); + return result; +} + +napi_value BatchInsertPromise(napi_env env, DAHelperBatchInsertCB *batchInsertCB) +{ + HILOG_INFO("%{public}s, promise.", __func__); + if (batchInsertCB == nullptr) { + HILOG_ERROR("%{public}s, param == nullptr.", __func__); + return nullptr; + } + napi_value resourceName; + NAPI_CALL(env, napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName)); + napi_deferred deferred; + napi_value promise = 0; + NAPI_CALL(env, napi_create_promise(env, &deferred, &promise)); + batchInsertCB->cbBase.deferred = deferred; + + NAPI_CALL(env, + napi_create_async_work(env, + nullptr, + resourceName, + BatchInsertExecuteCB, + BatchInsertPromiseCompleteCB, + (void *)batchInsertCB, + &batchInsertCB->cbBase.asyncWork)); + NAPI_CALL(env, napi_queue_async_work(env, batchInsertCB->cbBase.asyncWork)); + HILOG_INFO("%{public}s, promise end.", __func__); + return promise; +} + +void BatchInsertExecuteCB(napi_env env, void *data) +{ + HILOG_INFO("NAPI_BatchInsert, worker pool thread execute."); + DAHelperBatchInsertCB *batchInsertCB = static_cast(data); + if (batchInsertCB->dataAbilityHelper != nullptr) { + OHOS::Uri uri(batchInsertCB->uri); + batchInsertCB->result = batchInsertCB->dataAbilityHelper->BatchInsert(uri, batchInsertCB->values); + } else { + HILOG_ERROR("NAPI_BatchInsert, dataAbilityHelper == nullptr"); + } + HILOG_INFO("NAPI_BatchInsert, worker pool thread execute end."); +} + +void BatchInsertAsyncCompleteCB(napi_env env, napi_status status, void *data) +{ + HILOG_INFO("NAPI_BatchInsert, main event thread complete."); + DAHelperBatchInsertCB *BatchInsertCB = static_cast(data); + napi_value callback = nullptr; + napi_value undefined = nullptr; + napi_value result[ARGS_TWO] = {nullptr}; + napi_value callResult = nullptr; + NAPI_CALL_RETURN_VOID(env, napi_get_undefined(env, &undefined)); + NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, BatchInsertCB->cbBase.cbInfo.callback, &callback)); + + result[PARAM0] = GetCallbackErrorValue(env, NO_ERROR); + napi_create_int32(env, BatchInsertCB->result, &result[PARAM1]); + NAPI_CALL_RETURN_VOID(env, napi_call_function(env, undefined, callback, ARGS_TWO, &result[PARAM0], &callResult)); + + if (BatchInsertCB->cbBase.cbInfo.callback != nullptr) { + NAPI_CALL_RETURN_VOID(env, napi_delete_reference(env, BatchInsertCB->cbBase.cbInfo.callback)); + } + NAPI_CALL_RETURN_VOID(env, napi_delete_async_work(env, BatchInsertCB->cbBase.asyncWork)); + delete BatchInsertCB; + BatchInsertCB = nullptr; + HILOG_INFO("NAPI_BatchInsert, main event thread complete end."); +} + +void BatchInsertPromiseCompleteCB(napi_env env, napi_status status, void *data) +{ + HILOG_INFO("NAPI_BatchInsertCB, main event thread complete."); + DAHelperBatchInsertCB *BatchInsertCB = static_cast(data); + napi_value result = nullptr; + napi_create_int32(env, BatchInsertCB->result, &result); + NAPI_CALL_RETURN_VOID(env, napi_resolve_deferred(env, BatchInsertCB->cbBase.deferred, result)); + NAPI_CALL_RETURN_VOID(env, napi_delete_async_work(env, BatchInsertCB->cbBase.asyncWork)); + delete BatchInsertCB; + BatchInsertCB = nullptr; + HILOG_INFO("NAPI_BatchInsertCB, main event thread complete end."); +} + +/** + * @brief DataAbilityHelper NAPI method : insert. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_Query(napi_env env, napi_callback_info info) +{ + HILOG_INFO("%{public}s,called", __func__); + DAHelperQueryCB *QueryCB = new (std::nothrow) DAHelperQueryCB; + if (QueryCB == nullptr) { + HILOG_ERROR("%{public}s, QueryCB == nullptr.", __func__); + return WrapVoidToJS(env); + } + QueryCB->cbBase.cbInfo.env = env; + QueryCB->cbBase.asyncWork = nullptr; + QueryCB->cbBase.deferred = nullptr; + QueryCB->cbBase.ability = nullptr; + + napi_value ret = QueryWrap(env, info, QueryCB); + if (ret == nullptr) { + HILOG_ERROR("%{public}s,ret == nullptr", __func__); + if (QueryCB != nullptr) { + delete QueryCB; + QueryCB = nullptr; + } + ret = WrapVoidToJS(env); + } + HILOG_INFO("%{public}s,end", __func__); + return ret; +} + +/** + * @brief Insert processing function. + * + * @param env The environment that the Node-API call is invoked under. + * @param insertCB Process data asynchronously. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value QueryWrap(napi_env env, napi_callback_info info, DAHelperQueryCB *queryCB) +{ + HILOG_INFO("%{public}s,called", __func__); + size_t argcAsync = ARGS_FOUR; + const size_t argcPromise = ARGS_THREE; + const size_t argCountWithAsync = argcPromise + ARGS_ASYNC_COUNT; + napi_value args[ARGS_MAX_COUNT] = {nullptr}; + napi_value ret = 0; + napi_value thisVar = nullptr; + + NAPI_CALL(env, napi_get_cb_info(env, info, &argcAsync, args, &thisVar, nullptr)); + if (argcAsync > argCountWithAsync || argcAsync > ARGS_MAX_COUNT) { + HILOG_ERROR("%{public}s, Wrong argument count.", __func__); + return nullptr; + } + + napi_valuetype valuetype = napi_undefined; + NAPI_CALL(env, napi_typeof(env, args[PARAM0], &valuetype)); + if (valuetype == napi_string) { + queryCB->uri = NapiValueToStringUtf8(env, args[PARAM0]); + HILOG_INFO("%{public}s,uri=%{public}s", __func__, queryCB->uri.c_str()); + } + + std::vector result; + bool arrayStringbool = false; + arrayStringbool = NapiValueToArrayStringUtf8(env, args[PARAM1], result); + if (arrayStringbool == false) { + HILOG_ERROR("%{public}s, The return value of arraystringbool is false", __func__); + return nullptr; + } + queryCB->columns = result; + for (size_t i = 0; i < queryCB->columns.size(); i++) { + HILOG_INFO("%{public}s,columns=%{public}s", __func__, queryCB->columns.at(i).c_str()); + } + + UnwrapDataAbilityPredicates(queryCB->predicates, env, args[PARAM2]); + DataAbilityHelper *objectInfo = nullptr; + napi_unwrap(env, thisVar, (void **)&objectInfo); + HILOG_INFO("%{public}s,DataAbilityHelper objectInfo = %{public}p", __func__, objectInfo); + queryCB->dataAbilityHelper = objectInfo; + + if (argcAsync > argcPromise) { + ret = QueryAsync(env, args, ARGS_THREE, queryCB); + } else { + ret = QueryPromise(env, queryCB); + } + HILOG_INFO("%{public}s,end", __func__); + return ret; +} + +napi_value QueryAsync(napi_env env, napi_value *args, const size_t argCallback, DAHelperQueryCB *queryCB) +{ + HILOG_INFO("%{public}s, asyncCallback.", __func__); + if (args == nullptr || queryCB == nullptr) { + HILOG_ERROR("%{public}s, param == nullptr.", __func__); + return nullptr; + } + napi_value resourceName = 0; + NAPI_CALL(env, napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName)); + + napi_valuetype valuetype = napi_undefined; + NAPI_CALL(env, napi_typeof(env, args[argCallback], &valuetype)); + if (valuetype == napi_function) { + NAPI_CALL(env, napi_create_reference(env, args[argCallback], 1, &queryCB->cbBase.cbInfo.callback)); + } + + NAPI_CALL(env, + napi_create_async_work(env, + nullptr, + resourceName, + QueryExecuteCB, + QueryAsyncCompleteCB, + (void *)queryCB, + &queryCB->cbBase.asyncWork)); + NAPI_CALL(env, napi_queue_async_work(env, queryCB->cbBase.asyncWork)); + napi_value result = 0; + NAPI_CALL(env, napi_get_null(env, &result)); + HILOG_INFO("%{public}s, asyncCallback end.", __func__); + return result; +} + +napi_value QueryPromise(napi_env env, DAHelperQueryCB *queryCB) +{ + HILOG_INFO("%{public}s, promise.", __func__); + if (queryCB == nullptr) { + HILOG_ERROR("%{public}s, param == nullptr.", __func__); + return nullptr; + } + napi_value resourceName; + NAPI_CALL(env, napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName)); + napi_deferred deferred; + napi_value promise = 0; + NAPI_CALL(env, napi_create_promise(env, &deferred, &promise)); + queryCB->cbBase.deferred = deferred; + + NAPI_CALL(env, + napi_create_async_work(env, + nullptr, + resourceName, + QueryExecuteCB, + QueryPromiseCompleteCB, + (void *)queryCB, + &queryCB->cbBase.asyncWork)); + NAPI_CALL(env, napi_queue_async_work(env, queryCB->cbBase.asyncWork)); + HILOG_INFO("%{public}s, promise end.", __func__); + return promise; +} + +void QueryPromiseCompleteCB(napi_env env, napi_status status, void *data) +{ + HILOG_INFO("NAPI_DAHelperQueryCB, main event thread complete."); + DAHelperQueryCB *QueryCB = static_cast(data); + napi_value result = nullptr; + result = WrapResultSet(env, QueryCB->result); + NAPI_CALL_RETURN_VOID(env, napi_resolve_deferred(env, QueryCB->cbBase.deferred, result)); + NAPI_CALL_RETURN_VOID(env, napi_delete_async_work(env, QueryCB->cbBase.asyncWork)); + delete QueryCB; + QueryCB = nullptr; + HILOG_INFO("NAPI_DAHelperQueryCB, main event thread complete end."); +} + +void QueryExecuteCB(napi_env env, void *data) +{ + HILOG_INFO("NAPI_Query, worker pool thread execute."); + DAHelperQueryCB *queryCB = static_cast(data); + if (queryCB->dataAbilityHelper != nullptr) { + OHOS::Uri uri(queryCB->uri); + auto resultset = queryCB->dataAbilityHelper->Query(uri, queryCB->columns, queryCB->predicates); + if (resultset != nullptr) { + queryCB->result = resultset; + } else { + HILOG_INFO("NAPI_Query, resultset == nullptr."); + } + } else { + HILOG_ERROR("NAPI_Query, dataAbilityHelper == nullptr"); + } + HILOG_INFO("NAPI_Query, worker pool thread execute end."); +} + +void QueryAsyncCompleteCB(napi_env env, napi_status status, void *data) +{ + HILOG_INFO("NAPI_Query, main event thread complete."); + DAHelperQueryCB *queryCB = static_cast(data); + napi_value callback = nullptr; + napi_value undefined = nullptr; + napi_value result[ARGS_TWO] = {nullptr}; + napi_value callResult = nullptr; + NAPI_CALL_RETURN_VOID(env, napi_get_undefined(env, &undefined)); + NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, queryCB->cbBase.cbInfo.callback, &callback)); + + result[PARAM0] = GetCallbackErrorValue(env, NO_ERROR); + result[PARAM1] = WrapResultSet(env, queryCB->result); + + NAPI_CALL_RETURN_VOID(env, napi_call_function(env, undefined, callback, ARGS_TWO, &result[PARAM0], &callResult)); + + if (queryCB->cbBase.cbInfo.callback != nullptr) { + NAPI_CALL_RETURN_VOID(env, napi_delete_reference(env, queryCB->cbBase.cbInfo.callback)); + } + NAPI_CALL_RETURN_VOID(env, napi_delete_async_work(env, queryCB->cbBase.asyncWork)); + delete queryCB; + queryCB = nullptr; + HILOG_INFO("NAPI_Query, main event thread complete end."); +} + +napi_value WrapResultSet(napi_env env, const std::shared_ptr &resultSet) +{ + HILOG_INFO("%{public}s,called", __func__); + if (resultSet == nullptr) { + HILOG_ERROR("%{public}s, input parameter resultSet is nullptr", __func__); + return nullptr; + } + + return RdbJsKit::ResultSetProxy::NewInstance(env, resultSet); +} + +napi_value NAPI_Release(napi_env env, napi_callback_info info) +{ + HILOG_INFO("%{public}s,called", __func__); + DAHelperReleaseCB *releaseCB = new (std::nothrow) DAHelperReleaseCB; + if (releaseCB == nullptr) { + HILOG_ERROR("%{public}s, releaseCB == nullptr.", __func__); + return WrapVoidToJS(env); + } + releaseCB->cbBase.cbInfo.env = env; + releaseCB->cbBase.asyncWork = nullptr; + releaseCB->cbBase.deferred = nullptr; + + napi_value ret = ReleaseWrap(env, info, releaseCB); + if (ret == nullptr) { + HILOG_ERROR("%{public}s,ret == nullptr", __func__); + if (releaseCB != nullptr) { + delete releaseCB; + releaseCB = nullptr; + } + ret = WrapVoidToJS(env); + } + HILOG_INFO("%{public}s,end", __func__); + return ret; +} + +napi_value ReleaseWrap(napi_env env, napi_callback_info info, DAHelperReleaseCB *releaseCB) +{ + HILOG_INFO("%{public}s,called", __func__); + size_t argcAsync = ARGS_TWO; + const size_t argcPromise = ARGS_ONE; + const size_t argCountWithAsync = argcPromise + ARGS_ASYNC_COUNT; + napi_value args[ARGS_MAX_COUNT] = {nullptr}; + napi_value ret = nullptr; + napi_value thisVar = nullptr; + + NAPI_CALL(env, napi_get_cb_info(env, info, &argcAsync, args, &thisVar, nullptr)); + if (argcAsync > argCountWithAsync || argcAsync > ARGS_MAX_COUNT) { + HILOG_ERROR("%{public}s, Wrong argument count.", __func__); + return nullptr; + } + + DataAbilityHelper *objectInfo = nullptr; + napi_unwrap(env, thisVar, (void **)&objectInfo); + HILOG_INFO("DataAbilityHelper ReleaseWrap objectInfo = %{public}p", objectInfo); + releaseCB->dataAbilityHelper = objectInfo; + + if (argcAsync > argcPromise) { + ret = ReleaseAsync(env, args, ARGS_ONE, releaseCB); + } else { + ret = ReleasePromise(env, releaseCB); + } + HILOG_INFO("%{public}s,end", __func__); + return ret; +} + +napi_value ReleaseAsync(napi_env env, napi_value *args, const size_t argCallback, DAHelperReleaseCB *releaseCB) +{ + HILOG_INFO("%{public}s, asyncCallback.", __func__); + if (args == nullptr || releaseCB == nullptr) { + HILOG_ERROR("%{public}s, param == nullptr.", __func__); + return nullptr; + } + napi_value resourceName = 0; + NAPI_CALL(env, napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName)); + + napi_valuetype valuetype = napi_undefined; + NAPI_CALL(env, napi_typeof(env, args[argCallback], &valuetype)); + if (valuetype == napi_function) { + NAPI_CALL(env, napi_create_reference(env, args[argCallback], 1, &releaseCB->cbBase.cbInfo.callback)); + } + + NAPI_CALL(env, + napi_create_async_work(env, + nullptr, + resourceName, + ReleaseExecuteCB, + ReleaseAsyncCompleteCB, + (void *)releaseCB, + &releaseCB->cbBase.asyncWork)); + NAPI_CALL(env, napi_queue_async_work(env, releaseCB->cbBase.asyncWork)); + napi_value result = 0; + NAPI_CALL(env, napi_get_null(env, &result)); + HILOG_INFO("%{public}s, asyncCallback end.", __func__); + return result; +} + +napi_value ReleasePromise(napi_env env, DAHelperReleaseCB *releaseCB) +{ + HILOG_INFO("%{public}s, promise.", __func__); + if (releaseCB == nullptr) { + HILOG_ERROR("%{public}s, param == nullptr.", __func__); + return nullptr; + } + napi_value resourceName; + NAPI_CALL(env, napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName)); + napi_deferred deferred; + napi_value promise = 0; + NAPI_CALL(env, napi_create_promise(env, &deferred, &promise)); + releaseCB->cbBase.deferred = deferred; + + NAPI_CALL(env, + napi_create_async_work(env, + nullptr, + resourceName, + ReleaseExecuteCB, + ReleasePromiseCompleteCB, + (void *)releaseCB, + &releaseCB->cbBase.asyncWork)); + NAPI_CALL(env, napi_queue_async_work(env, releaseCB->cbBase.asyncWork)); + HILOG_INFO("%{public}s, promise end.", __func__); + return promise; +} + +void ReleaseExecuteCB(napi_env env, void *data) +{ + HILOG_INFO("NAPI_Release, worker pool thread execute."); + DAHelperReleaseCB *releaseCB = static_cast(data); + if (releaseCB->dataAbilityHelper != nullptr) { + releaseCB->result = releaseCB->dataAbilityHelper->Release(); + } else { + HILOG_ERROR("NAPI_Release, dataAbilityHelper == nullptr"); + } + HILOG_INFO("NAPI_Release, worker pool thread execute end."); +} + +void ReleaseAsyncCompleteCB(napi_env env, napi_status status, void *data) +{ + HILOG_INFO("NAPI_Release, main event thread complete."); + DAHelperReleaseCB *releaseCB = static_cast(data); + napi_value callback = nullptr; + napi_value undefined = nullptr; + napi_value result[ARGS_TWO] = {nullptr}; + napi_value callResult = nullptr; + NAPI_CALL_RETURN_VOID(env, napi_get_undefined(env, &undefined)); + NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, releaseCB->cbBase.cbInfo.callback, &callback)); + + result[PARAM0] = GetCallbackErrorValue(env, NO_ERROR); + napi_get_boolean(env, releaseCB->result, &result[PARAM1]); + NAPI_CALL_RETURN_VOID(env, napi_call_function(env, undefined, callback, ARGS_TWO, &result[PARAM0], &callResult)); + + if (releaseCB->cbBase.cbInfo.callback != nullptr) { + NAPI_CALL_RETURN_VOID(env, napi_delete_reference(env, releaseCB->cbBase.cbInfo.callback)); + } + NAPI_CALL_RETURN_VOID(env, napi_delete_async_work(env, releaseCB->cbBase.asyncWork)); + delete releaseCB; + releaseCB = nullptr; + HILOG_INFO("NAPI_Release, main event thread complete end."); +} + +void ReleasePromiseCompleteCB(napi_env env, napi_status status, void *data) +{ + HILOG_INFO("NAPI_Release, main event thread complete."); + DAHelperReleaseCB *releaseCB = static_cast(data); + napi_value result = nullptr; + napi_get_boolean(env, releaseCB->result, &result); + NAPI_CALL_RETURN_VOID(env, napi_resolve_deferred(env, releaseCB->cbBase.deferred, result)); + NAPI_CALL_RETURN_VOID(env, napi_delete_async_work(env, releaseCB->cbBase.asyncWork)); + delete releaseCB; + releaseCB = nullptr; + HILOG_INFO("NAPI_Release, main event thread complete end."); +} + +napi_value NAPI_ExecuteBatch(napi_env env, napi_callback_info info) +{ + HILOG_INFO("%{public}s,start", __func__); + DAHelperExecuteBatchCB *executeBatchCB = new (std::nothrow) DAHelperExecuteBatchCB; + if (executeBatchCB == nullptr) { + HILOG_ERROR("%{public}s, executeBatchCB == nullptr.", __func__); + return WrapVoidToJS(env); + } + executeBatchCB->cbBase.cbInfo.env = env; + executeBatchCB->cbBase.asyncWork = nullptr; + executeBatchCB->cbBase.deferred = nullptr; + executeBatchCB->cbBase.ability = nullptr; + + napi_value ret = ExecuteBatchWrap(env, info, executeBatchCB); + if (ret == nullptr) { + HILOG_ERROR("%{public}s, ret == nullptr.", __func__); + if (executeBatchCB != nullptr) { + delete executeBatchCB; + executeBatchCB = nullptr; + } + ret = WrapVoidToJS(env); + } + HILOG_INFO("%{public}s,end", __func__); + return ret; +} + +bool UnwrapArrayOperationFromJS( + napi_env env, napi_callback_info info, napi_value param, std::vector> &result) +{ + HILOG_INFO("%{public}s,called", __func__); + uint32_t arraySize = 0; + napi_value jsValue = nullptr; + std::string strValue = ""; + + if (!IsArrayForNapiValue(env, param, arraySize)) { + HILOG_ERROR("%{public}s, Wrong argument type ", __func__); + return false; + } + HILOG_INFO("%{public}s, param size:%{public}d ", __func__, arraySize); + result.clear(); + for (uint32_t i = 0; i < arraySize; i++) { + jsValue = nullptr; + if (napi_get_element(env, param, i, &jsValue) != napi_ok) { + HILOG_ERROR("%{public}s, get element failed, index:%{public}d ", __func__, i); + return false; + } + std::shared_ptr operation = nullptr; + UnwrapDataAbilityOperation(operation, env, jsValue); + HILOG_INFO("%{public}s, UnwrapDataAbilityOperation, index:%{public}d ", __func__, i); + result.push_back(operation); + } + return true; +} + +napi_value ExecuteBatchWrap(napi_env env, napi_callback_info info, DAHelperExecuteBatchCB *executeBatchCB) +{ + HILOG_INFO("%{public}s,start", __func__); + size_t argcAsync = ARGS_THREE; + const size_t argcPromise = ARGS_TWO; + const size_t argCountWithAsync = argcPromise + ARGS_ASYNC_COUNT; + napi_value args[ARGS_MAX_COUNT] = {nullptr}; + napi_value ret = 0; + napi_value thisVar = nullptr; + + NAPI_CALL(env, napi_get_cb_info(env, info, &argcAsync, args, &thisVar, nullptr)); + if (argcAsync > argCountWithAsync || argcAsync > ARGS_MAX_COUNT) { + HILOG_ERROR("%{public}s, Wrong argument count.", __func__); + return nullptr; + } + + napi_valuetype valuetype = napi_undefined; + NAPI_CALL(env, napi_typeof(env, args[PARAM0], &valuetype)); + if (valuetype == napi_string) { + executeBatchCB->uri = NapiValueToStringUtf8(env, args[PARAM0]); + HILOG_INFO("%{public}s,uri=%{public}s", __func__, executeBatchCB->uri.c_str()); + } else { + HILOG_ERROR("%{public}s, Wrong argument type.", __func__); + return nullptr; + } + + std::vector> operations; + UnwrapArrayOperationFromJS(env, info, args[PARAM1], operations); + HILOG_INFO("%{public}s,operations size=%{public}zu", __func__, operations.size()); + executeBatchCB->operations = operations; + + DataAbilityHelper *objectInfo = nullptr; + napi_unwrap(env, thisVar, (void **)&objectInfo); + HILOG_INFO("%{public}s,DataAbilityHelper objectInfo = %{public}p", __func__, objectInfo); + executeBatchCB->dataAbilityHelper = objectInfo; + + if (argcAsync > argcPromise) { + ret = ExecuteBatchAsync(env, args, argcAsync, argcPromise, executeBatchCB); + } else { + ret = ExecuteBatchPromise(env, executeBatchCB); + } + HILOG_INFO("%{public}s,end", __func__); + return ret; +} + +napi_value ExecuteBatchAsync( + napi_env env, napi_value *args, size_t argcAsync, const size_t argcPromise, DAHelperExecuteBatchCB *executeBatchCB) +{ + HILOG_INFO("%{public}s, asyncCallback start.", __func__); + if (args == nullptr || executeBatchCB == nullptr) { + HILOG_ERROR("%{public}s, param is nullptr.", __func__); + return nullptr; + } + napi_value resourceName = 0; + NAPI_CALL(env, napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName)); + + napi_valuetype valuetype = napi_undefined; + NAPI_CALL(env, napi_typeof(env, args[argcPromise], &valuetype)); + if (valuetype == napi_function) { + NAPI_CALL(env, napi_create_reference(env, args[argcPromise], 1, &executeBatchCB->cbBase.cbInfo.callback)); + } + + NAPI_CALL(env, + napi_create_async_work(env, + nullptr, + resourceName, + ExecuteBatchExecuteCB, + ExecuteBatchAsyncCompleteCB, + (void *)executeBatchCB, + &executeBatchCB->cbBase.asyncWork)); + NAPI_CALL(env, napi_queue_async_work(env, executeBatchCB->cbBase.asyncWork)); + napi_value result = 0; + NAPI_CALL(env, napi_get_null(env, &result)); + HILOG_INFO("%{public}s, asyncCallback end.", __func__); + return result; +} + +napi_value ExecuteBatchPromise(napi_env env, DAHelperExecuteBatchCB *executeBatchCB) +{ + HILOG_INFO("%{public}s, promise start.", __func__); + if (executeBatchCB == nullptr) { + HILOG_ERROR("%{public}s, param is nullptr.", __func__); + return nullptr; + } + napi_value resourceName; + NAPI_CALL(env, napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName)); + napi_deferred deferred; + napi_value promise = 0; + NAPI_CALL(env, napi_create_promise(env, &deferred, &promise)); + executeBatchCB->cbBase.deferred = deferred; + + NAPI_CALL(env, + napi_create_async_work(env, + nullptr, + resourceName, + ExecuteBatchExecuteCB, + ExecuteBatchPromiseCompleteCB, + (void *)executeBatchCB, + &executeBatchCB->cbBase.asyncWork)); + NAPI_CALL(env, napi_queue_async_work(env, executeBatchCB->cbBase.asyncWork)); + HILOG_INFO("%{public}s, promise end.", __func__); + return promise; +} + +void ExecuteBatchExecuteCB(napi_env env, void *data) +{ + HILOG_INFO("%{public}s,NAPI_ExecuteBatch, worker pool thread execute start.", __func__); + DAHelperExecuteBatchCB *executeBatchCB = static_cast(data); + if (executeBatchCB->dataAbilityHelper != nullptr) { + OHOS::Uri uri(executeBatchCB->uri); + executeBatchCB->result = executeBatchCB->dataAbilityHelper->ExecuteBatch(uri, executeBatchCB->operations); + HILOG_INFO("%{public}s, dataAbilityHelper is not nullptr.", __func__); + } + HILOG_INFO("%{public}s,NAPI_ExecuteBatch, worker pool thread execute end.", __func__); +} + +void ExecuteBatchAsyncCompleteCB(napi_env env, napi_status status, void *data) +{ + HILOG_INFO("%{public}s, NAPI_ExecuteBatch, main event thread complete start.", __func__); + DAHelperExecuteBatchCB *executeBatchCB = static_cast(data); + napi_value callback = nullptr; + napi_value undefined = nullptr; + napi_value result[ARGS_TWO] = {nullptr}; + napi_value callResult = nullptr; + NAPI_CALL_RETURN_VOID(env, napi_get_undefined(env, &undefined)); + NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, executeBatchCB->cbBase.cbInfo.callback, &callback)); + + result[PARAM0] = GetCallbackErrorValue(env, NO_ERROR); + napi_create_array(env, &result[PARAM1]); + GetDataAbilityResultForResult(env, executeBatchCB->result, result[PARAM1]); + NAPI_CALL_RETURN_VOID(env, napi_call_function(env, undefined, callback, ARGS_TWO, &result[PARAM0], &callResult)); + + if (executeBatchCB->cbBase.cbInfo.callback != nullptr) { + NAPI_CALL_RETURN_VOID(env, napi_delete_reference(env, executeBatchCB->cbBase.cbInfo.callback)); + } + NAPI_CALL_RETURN_VOID(env, napi_delete_async_work(env, executeBatchCB->cbBase.asyncWork)); + delete executeBatchCB; + executeBatchCB = nullptr; + HILOG_INFO("%{public}s, NAPI_ExecuteBatch, main event thread complete end.", __func__); +} + +void ExecuteBatchPromiseCompleteCB(napi_env env, napi_status status, void *data) +{ + HILOG_INFO("%{public}s, NAPI_ExecuteBatch, main event thread complete start.", __func__); + DAHelperExecuteBatchCB *executeBatchCB = static_cast(data); + napi_value result = nullptr; + napi_create_array(env, &result); + GetDataAbilityResultForResult(env, executeBatchCB->result, result); + NAPI_CALL_RETURN_VOID(env, napi_resolve_deferred(env, executeBatchCB->cbBase.deferred, result)); + NAPI_CALL_RETURN_VOID(env, napi_delete_async_work(env, executeBatchCB->cbBase.asyncWork)); + delete executeBatchCB; + executeBatchCB = nullptr; + HILOG_INFO("%{public}s, NAPI_ExecuteBatch, main event thread complete end.", __func__); +} + +void GetDataAbilityResultForResult( + napi_env env, const std::vector> dataAbilityResult, napi_value result) +{ + HILOG_INFO("%{public}s, NAPI_ExecuteBatch, getDataAbilityResultForResult start.", __func__); + int32_t index = 0; + std::vector> entities = dataAbilityResult; + for (const auto &item : entities) { + napi_value objDataAbilityResult; + NAPI_CALL_RETURN_VOID(env, napi_create_object(env, &objDataAbilityResult)); + + napi_value uri; + NAPI_CALL_RETURN_VOID( + env, napi_create_string_utf8(env, item->GetUri().ToString().c_str(), NAPI_AUTO_LENGTH, &uri)); + HILOG_INFO("%{public}s, NAPI_ExecuteBatch, uri = [%{public}s]", __func__, item->GetUri().ToString().c_str()); + NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, objDataAbilityResult, "uri", uri)); + + napi_value count; + NAPI_CALL_RETURN_VOID(env, napi_create_int32(env, item->GetCount(), &count)); + HILOG_INFO("%{public}s, NAPI_ExecuteBatch, count = [%{public}d]", __func__, item->GetCount()); + NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, objDataAbilityResult, "count", count)); + + NAPI_CALL_RETURN_VOID(env, napi_set_element(env, result, index, objDataAbilityResult)); + index++; + } + HILOG_INFO("%{public}s, NAPI_ExecuteBatch, getDataAbilityResultForResult end.", __func__); +} + +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/interfaces/kits/napi/aafwk/featureAbility/napi_data_ability_helper.h b/tools/interfaces/kits/napi/aafwk/featureAbility/napi_data_ability_helper.h new file mode 100644 index 00000000000..57230c2b78a --- /dev/null +++ b/tools/interfaces/kits/napi/aafwk/featureAbility/napi_data_ability_helper.h @@ -0,0 +1,478 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_APPEXECFWK_NAPI_DATA_ABILITY_HELPER_H +#define OHOS_APPEXECFWK_NAPI_DATA_ABILITY_HELPER_H +#include "feature_ability_common.h" +#include "data_ability_observer_stub.h" + +namespace OHOS { +namespace AppExecFwk { +class NAPIDataAbilityObserver : public AAFwk::DataAbilityObserverStub { +public: + void OnChange() override; + void SetEnv(const napi_env &env); + void SetCallbackRef(const napi_ref &ref); + +private: + napi_env env_ = nullptr; + napi_ref ref_ = nullptr; +}; + +/** + * @brief DataAbilityHelper NAPI module registration. + * + * @param env The environment that the Node-API call is invoked under. + * @param exports An empty object via the exports parameter as a convenience. + * + * @return The return value from Init is treated as the exports object for the module. + */ +napi_value DataAbilityHelperInit(napi_env env, napi_value exports); +napi_value DataAbilityHelperConstructor(napi_env env, napi_callback_info info); + +/** + * @brief DataAbilityHelper NAPI method : insert. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_Insert(napi_env env, napi_callback_info info); + +/** + * @brief Insert processing function. + * + * @param env The environment that the Node-API call is invoked under. + * @param insertCB Process data asynchronously. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value InsertWrap(napi_env env, napi_callback_info info, DAHelperInsertCB *insertCB); + +/** + * @brief Insert Async. + * + * @param env The environment that the Node-API call is invoked under. + * @param args Indicates the arguments passed into the callback. + * @param argcPromise Asynchronous data processing. + * @param insertCB Process data asynchronously. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value InsertAsync(napi_env env, napi_value *args, const size_t argCallback, DAHelperInsertCB *insertCB); + +/** + * @brief Insert Promise. + * + * @param env The environment that the Node-API call is invoked under. + * @param insertCB Process data asynchronously. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value InsertPromise(napi_env env, DAHelperInsertCB *insertCB); + +/** + * @brief Insert asynchronous processing function. + * + * @param env The environment that the Node-API call is invoked under. + * @param data Point to asynchronous processing of data. + */ +void InsertExecuteCB(napi_env env, void *data); + +/** + * @brief The callback at the end of the asynchronous callback. + * + * @param env The environment that the Node-API call is invoked under. + * @param data Point to asynchronous processing of data. + */ +void InsertAsyncCompleteCB(napi_env env, napi_status status, void *data); + +/** + * @brief The callback at the end of the Promise callback. + * + * @param env The environment that the Node-API call is invoked under. + * @param data Point to asynchronous processing of data. + */ +void InsertPromiseCompleteCB(napi_env env, napi_status status, void *data); + +/** + * @brief DataAbilityHelper NAPI method : notifyChange. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_NotifyChange(napi_env env, napi_callback_info info); + +/** + * @brief NotifyChange processing function. + * + * @param env The environment that the Node-API call is invoked under. + * @param notifyChangeCB Process data asynchronously. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value NotifyChangeWrap(napi_env env, napi_callback_info info, DAHelperNotifyChangeCB *notifyChangeCB); + +/** + * @brief NotifyChange Async. + * + * @param env The environment that the Node-API call is invoked under. + * @param args Indicates the arguments passed into the callback. + * @param argcPromise Asynchronous data processing. + * @param notifyChangeCB Process data asynchronously. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value NotifyChangeAsync( + napi_env env, napi_value *args, size_t argcAsync, const size_t argcPromise, DAHelperNotifyChangeCB *notifyChangeCB); + +/** + * @brief NotifyChange Promise. + * + * @param env The environment that the Node-API call is invoked under. + * @param notifyChangeCB Process data asynchronously. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value NotifyChangePromise(napi_env env, DAHelperNotifyChangeCB *notifyChangeCB); + +/** + * @brief NotifyChange asynchronous processing function. + * + * @param env The environment that the Node-API call is invoked under. + * @param data Point to asynchronous processing of data. + */ +void NotifyChangeExecuteCB(napi_env env, void *data); + +/** + * @brief The callback at the end of the asynchronous callback. + * + * @param env The environment that the Node-API call is invoked under. + * @param data Point to asynchronous processing of data. + */ +void NotifyChangeAsyncCompleteCB(napi_env env, napi_status status, void *data); + +/** + * @brief The callback at the end of the Promise callback. + * + * @param env The environment that the Node-API call is invoked under. + * @param data Point to asynchronous processing of data. + */ +void NotifyChangePromiseCompleteCB(napi_env env, napi_status status, void *data); + +/** + * @brief DataAbilityHelper NAPI method : on. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_Register(napi_env env, napi_callback_info info); + +/** + * @brief On processing function. + * + * @param env The environment that the Node-API call is invoked under. + * @param insertCB Process data asynchronously. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value RegisterWrap(napi_env env, napi_callback_info info, DAHelperOnOffCB *insertCB); + +/** + * @brief On Async. + * + * @param env The environment that the Node-API call is invoked under. + * @param args Indicates the arguments passed into the callback. + * @param argcPromise Asynchronous data processing. + * @param insertCB Process data asynchronously. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value RegisterAsync( + napi_env env, napi_value *args, size_t argcAsync, const size_t argcPromise, DAHelperOnOffCB *insertCB); + +/** + * @brief On asynchronous processing function. + * + * @param env The environment that the Node-API call is invoked under. + * @param data Point to asynchronous processing of data. + */ +void RegisterExecuteCB(napi_env env, void *data); + +/** + * @brief DataAbilityHelper NAPI method : off. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_UnRegister(napi_env env, napi_callback_info info); + +/** + * @brief Off processing function. + * + * @param env The environment that the Node-API call is invoked under. + * @param insertCB Process data asynchronously. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value UnRegisterWrap(napi_env env, napi_callback_info info, DAHelperOnOffCB *insertCB); + +/** + * @brief Off Async. + * + * @param env The environment that the Node-API call is invoked under. + * @param args Indicates the arguments passed into the callback. + * @param argcPromise Asynchronous data processing. + * @param insertCB Process data asynchronously. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value UnRegisterAsync( + napi_env env, napi_value *args, size_t argcAsync, const size_t argcPromise, DAHelperOnOffCB *insertCB); + +/** + * @brief Off asynchronous processing function. + * + * @param env The environment that the Node-API call is invoked under. + * @param data Point to asynchronous processing of data. + */ +void UnRegisterCompleteCB(napi_env env, napi_status status, void *data); +/** + * @brief Parse the ValuesBucket parameters. + * + * @param param Indicates the want parameters saved the parse result. + * @param env The environment that the Node-API call is invoked under. + * @param args Indicates the arguments passed into the callback. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value UnwrapValuesBucket(std::string &value, napi_env env, napi_value args); + +static std::vector registerInstances_; +napi_value NAPI_Release(napi_env env, napi_callback_info info); + +napi_value ReleaseWrap(napi_env env, napi_callback_info info, DAHelperReleaseCB *releaseCB); + +napi_value ReleaseAsync(napi_env env, napi_value *args, const size_t argCallback, DAHelperReleaseCB *releaseCB); + +napi_value ReleasePromise(napi_env env, DAHelperReleaseCB *releaseCB); + +void ReleaseExecuteCB(napi_env env, void *data); + +void ReleaseAsyncCompleteCB(napi_env env, napi_status status, void *data); + +void ReleasePromiseCompleteCB(napi_env env, napi_status status, void *data); + +napi_value NAPI_GetType(napi_env env, napi_callback_info info); +napi_value NAPI_GetType(napi_env env, napi_callback_info info); +napi_value GetTypeWrap(napi_env env, napi_callback_info info, DAHelperGetTypeCB *gettypeCB); +napi_value GetTypeAsync(napi_env env, napi_value *args, const size_t argCallback, DAHelperGetTypeCB *gettypeCB); +napi_value GetTypePromise(napi_env env, DAHelperGetTypeCB *gettypeCB); +void GetTypeExecuteCB(napi_env env, void *data); +void GetTypeAsyncCompleteCB(napi_env env, napi_status status, void *data); +void GetTypePromiseCompleteCB(napi_env env, napi_status status, void *data); + +napi_value NAPI_GetFileTypes(napi_env env, napi_callback_info info); +napi_value NAPI_GetFileTypes(napi_env env, napi_callback_info info); +napi_value GetFileTypesWrap(napi_env env, napi_callback_info info, DAHelperGetFileTypesCB *getfiletypesCB); +napi_value GetFileTypesAsync( + napi_env env, napi_value *args, const size_t argCallback, DAHelperGetFileTypesCB *getfiletypesCB); +napi_value GetFileTypesPromise(napi_env env, DAHelperGetFileTypesCB *getfiletypesCB); +void GetFileTypesExecuteCB(napi_env env, void *data); +void GetFileTypesAsyncCompleteCB(napi_env env, napi_status status, void *data); +void GetFileTypesPromiseCompleteCB(napi_env env, napi_status status, void *data); +napi_value WrapGetFileTypesCB(napi_env env, const DAHelperGetFileTypesCB &getfiletypesCB); + +napi_value NAPI_NormalizeUri(napi_env env, napi_callback_info info); +napi_value NAPI_NormalizeUri(napi_env env, napi_callback_info info); +napi_value NormalizeUriWrap(napi_env env, napi_callback_info info, DAHelperNormalizeUriCB *normalizeuriCB); +napi_value NormalizeUriAsync( + napi_env env, napi_value *args, const size_t argCallback, DAHelperNormalizeUriCB *normalizeuriCB); +napi_value NormalizeUriPromise(napi_env env, DAHelperNormalizeUriCB *normalizeuriCB); +void NormalizeUriExecuteCB(napi_env env, void *data); +void NormalizeUriAsyncCompleteCB(napi_env env, napi_status status, void *data); +void NormalizeUriPromiseCompleteCB(napi_env env, napi_status status, void *data); + +napi_value NAPI_DenormalizeUri(napi_env env, napi_callback_info info); +napi_value NAPI_DenormalizeUri(napi_env env, napi_callback_info info); +napi_value DenormalizeUriWrap(napi_env env, napi_callback_info info, DAHelperDenormalizeUriCB *denormalizeuriCB); +napi_value DenormalizeUriAsync( + napi_env env, napi_value *args, const size_t argCallback, DAHelperDenormalizeUriCB *denormalizeuriCB); +napi_value DenormalizeUriPromise(napi_env env, DAHelperDenormalizeUriCB *denormalizeuriCB); +void DenormalizeUriExecuteCB(napi_env env, void *data); +void DenormalizeUriAsyncCompleteCB(napi_env env, napi_status status, void *data); +void DenormalizeUriPromiseCompleteCB(napi_env env, napi_status status, void *data); + +napi_value NAPI_Delete(napi_env env, napi_callback_info info); + +napi_value DeleteWrap(napi_env env, napi_callback_info info, DAHelperDeleteCB *deleteCB); +napi_value DeleteAsync(napi_env env, napi_value *args, const size_t argCallback, DAHelperDeleteCB *deleteCB); + +napi_value DeletePromise(napi_env env, DAHelperDeleteCB *deleteCB); + +void DeleteExecuteCB(napi_env env, void *data); + +void DeleteAsyncCompleteCB(napi_env env, napi_status status, void *data); + +void DeletePromiseCompleteCB(napi_env env, napi_status status, void *data); + +napi_value NAPI_Update(napi_env env, napi_callback_info info); + +napi_value UpdateWrap(napi_env env, napi_callback_info info, DAHelperUpdateCB *updateCB); +napi_value UpdateAsync(napi_env env, napi_value *args, const size_t argCallback, DAHelperUpdateCB *updateCB); + +napi_value UpdatePromise(napi_env env, DAHelperUpdateCB *updateCB); + +void UpdateExecuteCB(napi_env env, void *data); + +void UpdateAsyncCompleteCB(napi_env env, napi_status status, void *data); + +void UpdatePromiseCompleteCB(napi_env env, napi_status status, void *data); + +napi_value NAPI_OpenFile(napi_env env, napi_callback_info info); + +napi_value OpenFileWrap(napi_env env, napi_callback_info info, DAHelperOpenFileCB *openFileCB); +napi_value OpenFileAsync(napi_env env, napi_value *args, const size_t argCallback, DAHelperOpenFileCB *openFileCB); + +napi_value OpenFilePromise(napi_env env, DAHelperOpenFileCB *openFileCB); + +void OpenFileExecuteCB(napi_env env, void *data); + +void OpenFileAsyncCompleteCB(napi_env env, napi_status status, void *data); + +void OpenFilePromiseCompleteCB(napi_env env, napi_status status, void *data); + +napi_value NAPI_BatchInsert(napi_env env, napi_callback_info info); + +napi_value BatchInsertWrap(napi_env env, napi_callback_info info, DAHelperBatchInsertCB *batchInsertCB); +napi_value BatchInsertAsync( + napi_env env, napi_value *args, const size_t argCallback, DAHelperBatchInsertCB *batchInsertCB); + +napi_value BatchInsertPromise(napi_env env, DAHelperBatchInsertCB *batchInsertCB); + +void BatchInsertExecuteCB(napi_env env, void *data); + +void BatchInsertAsyncCompleteCB(napi_env env, napi_status status, void *data); + +void BatchInsertPromiseCompleteCB(napi_env env, napi_status status, void *data); + +std::vector NapiValueObject(napi_env env, napi_value param); + +bool UnwrapArrayObjectFromJS(napi_env env, napi_value param, std::vector &value); + +napi_value NAPI_Query(napi_env env, napi_callback_info info); + +napi_value QueryWrap(napi_env env, napi_callback_info info, DAHelperQueryCB *queryCB); + +napi_value QueryAsync(napi_env env, napi_value *args, const size_t argCallback, DAHelperQueryCB *queryCB); + +napi_value QueryPromise(napi_env env, DAHelperQueryCB *queryCB); + +void QueryExecuteCB(napi_env env, void *data); + +void QueryAsyncCompleteCB(napi_env env, napi_status status, void *data); + +void QueryPromiseCompleteCB(napi_env env, napi_status status, void *data); + +napi_value WrapResultSet(napi_env env, const std::shared_ptr &resultSet); + +void AnalysisValuesBucket(NativeRdb::ValuesBucket &value, const napi_env &env, const napi_value &arg); +void SetValuesBucketObject( + NativeRdb::ValuesBucket &valuesBucket, const napi_env &env, std::string keyStr, napi_value value); + +void UnwrapDataAbilityPredicates(NativeRdb::DataAbilityPredicates &predicates, napi_env env, napi_value value); + +/** + * @brief DataAbilityHelper NAPI method : executeBatch. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_ExecuteBatch(napi_env env, napi_callback_info info); + +/** + * @brief ExecuteBatch processing function. + * + * @param env The environment that the Node-API call is invoked under. + * @param executeBatchCB Process data asynchronously. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value ExecuteBatchWrap(napi_env env, napi_callback_info info, DAHelperExecuteBatchCB *executeBatchCB); + +bool UnwrapArrayOperationFromJS( + napi_env env, napi_value param, std::vector> &result); +/** + * @brief ExecuteBatch Async. + * + * @param env The environment that the Node-API call is invoked under. + * @param args Indicates the arguments passed into the callback. + * @param argcPromise Asynchronous data processing. + * @param executeBatchCB Process data asynchronously. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value ExecuteBatchAsync( + napi_env env, napi_value *args, size_t argcAsync, const size_t argcPromise, DAHelperExecuteBatchCB *executeBatchCB); + +/** + * @brief ExecuteBatch Promise. + * + * @param env The environment that the Node-API call is invoked under. + * @param executeBatchCB Process data asynchronously. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value ExecuteBatchPromise(napi_env env, DAHelperExecuteBatchCB *executeBatchCB); + +/** + * @brief ExecuteBatch asynchronous processing function. + * + * @param env The environment that the Node-API call is invoked under. + * @param data Point to asynchronous processing of data. + */ +void ExecuteBatchExecuteCB(napi_env env, void *data); + +/** + * @brief The callback at the end of the asynchronous callback. + * + * @param env The environment that the Node-API call is invoked under. + * @param data Point to asynchronous processing of data. + */ +void ExecuteBatchAsyncCompleteCB(napi_env env, napi_status status, void *data); + +/** + * @brief The callback at the end of the Promise callback. + * + * @param env The environment that the Node-API call is invoked under. + * @param data Point to asynchronous processing of data. + */ +void ExecuteBatchPromiseCompleteCB(napi_env env, napi_status status, void *data); + +void GetDataAbilityResultForResult( + napi_env env, const std::vector> dataAbilityResult, napi_value result); + +} // namespace AppExecFwk +} // namespace OHOS +#endif /* OHOS_APPEXECFWK_NAPI_DATA_ABILITY_HELPER_H */ diff --git a/tools/interfaces/kits/napi/aafwk/featureAbility/napi_data_ability_operation.cpp b/tools/interfaces/kits/napi/aafwk/featureAbility/napi_data_ability_operation.cpp new file mode 100644 index 00000000000..e4f0188cda4 --- /dev/null +++ b/tools/interfaces/kits/napi/aafwk/featureAbility/napi_data_ability_operation.cpp @@ -0,0 +1,222 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "napi_data_ability_operation.h" +#include +#include +#include "hilog_wrapper.h" +#include "napi_common_want.h" +#include "data_ability_predicates.h" +#include "values_bucket.h" +#include "napi_data_ability_helper.h" + +namespace OHOS { +namespace AppExecFwk { +napi_value DataAbilityOperationInit(napi_env env, napi_value exports) +{ + const int INSERT = 1; + const int UPDATE = 2; + const int DELETE = 3; + const int ASSERT = 4; + HILOG_INFO("%{public}s called.", __func__); + + napi_value dataAbilityOperationType = nullptr; + napi_create_object(env, &dataAbilityOperationType); + SetNamedProperty(env, dataAbilityOperationType, "TYPE_INSERT", INSERT); + SetNamedProperty(env, dataAbilityOperationType, "TYPE_UPDATE", UPDATE); + SetNamedProperty(env, dataAbilityOperationType, "TYPE_DELETE", DELETE); + SetNamedProperty(env, dataAbilityOperationType, "TYPE_ASSERT", ASSERT); + + napi_property_descriptor properties[] = { + DECLARE_NAPI_PROPERTY("DataAbilityOperationType", dataAbilityOperationType), + }; + NAPI_CALL(env, napi_define_properties(env, exports, sizeof(properties) / sizeof(properties[0]), properties)); + + return exports; +} + +napi_value UnwrapDataAbilityOperation( + std::shared_ptr &dataAbilityOperation, napi_env env, napi_value param) +{ + HILOG_INFO("%{public}s called.", __func__); + if (!IsTypeForNapiValue(env, param, napi_object)) { + HILOG_ERROR("%{public}s, Params is invalid.", __func__); + return nullptr; + } + + napi_value result = BuildDataAbilityOperation(dataAbilityOperation, env, param); + return result; +} + +napi_value BuildDataAbilityOperation( + std::shared_ptr &dataAbilityOperation, napi_env env, napi_value param) +{ + HILOG_INFO("%{public}s start.", __func__); + + // get uri property + std::string uriStr(""); + if (!UnwrapStringByPropertyName(env, param, "uri", uriStr)) { + HILOG_ERROR("%{public}s, uri is not exist.", __func__); + return nullptr; + } + HILOG_INFO("%{public}s, uri:%{public}s", __func__, uriStr.c_str()); + std::shared_ptr uri = std::make_shared(uriStr); + + // get type property + int type = 0; + if (!UnwrapInt32ByPropertyName(env, param, "type", type)) { + HILOG_ERROR("%{public}s, type:%{public}d is not exist.", __func__, type); + return nullptr; + } + HILOG_INFO("%{public}s, type:%{public}d", __func__, type); + + std::shared_ptr builder = nullptr; + if (!GetDataAbilityOperationBuilder(builder, type, uri)) { + HILOG_ERROR("%{public}s, GetDataAbilityOperationBuilder failed.", __func__); + return nullptr; + } + + // get valuesBucket property + std::shared_ptr valuesBucket = std::make_shared(); + valuesBucket->Clear(); + napi_value jsValueBucket = GetPropertyValueByPropertyName(env, param, "valuesBucket", napi_object); + UnwrapValuesBucket(valuesBucket, env, jsValueBucket); + if (valuesBucket != nullptr) { + builder->WithValuesBucket(valuesBucket); + } + + // get dataAbilityPredicates property + std::shared_ptr predicates = std::make_shared(); + napi_value jsPredicates = GetPropertyValueByPropertyName(env, param, "predicates", napi_object); + UnwrapDataAbilityPredicates(*predicates, env, jsPredicates); + if (predicates != nullptr) { + builder->WithPredicates(predicates); + } + + // get expectedcount property + int expectedCount = 0; + UnwrapInt32ByPropertyName(env, param, "expectedCount", expectedCount); + HILOG_INFO("%{public}s, expectedCount:%{public}d", __func__, expectedCount); + if (expectedCount > 0) { + builder->WithExpectedCount(expectedCount); + } + + // get PredicatesBackReferences property + napi_value jsPredicatesBackReferences = + GetPropertyValueByPropertyName(env, param, "PredicatesBackReferences", napi_object); + UnwrapDataAbilityPredicatesBackReferences(builder, env, jsPredicatesBackReferences); + + // get interrupted property + bool interrupted = false; + UnwrapBooleanByPropertyName(env, param, "interrupted", interrupted); + builder->WithInterruptionAllowed(interrupted); + + if (builder != nullptr) { + HILOG_INFO("%{public}s, builder is not nullptr", __func__); + dataAbilityOperation = builder->Build(); + } + napi_value result; + NAPI_CALL(env, napi_create_int32(env, 1, &result)); + HILOG_INFO("%{public}s end.", __func__); + return result; +} + +bool GetDataAbilityOperationBuilder( + std::shared_ptr &builder, const int type, const std::shared_ptr &uri) +{ + HILOG_INFO("%{public}s called.", __func__); + switch (type) { + case DataAbilityOperation::TYPE_INSERT: + builder = DataAbilityOperation::NewInsertBuilder(uri); + break; + case DataAbilityOperation::TYPE_UPDATE: + builder = DataAbilityOperation::NewUpdateBuilder(uri); + break; + case DataAbilityOperation::TYPE_DELETE: + builder = DataAbilityOperation::NewDeleteBuilder(uri); + break; + case DataAbilityOperation::TYPE_ASSERT: + builder = DataAbilityOperation::NewAssertBuilder(uri); + break; + default: + HILOG_ERROR("%{public}s, type:%{public}d is invalid.", __func__, type); + return false; + } + return true; +} + +napi_value UnwrapValuesBucket( + std::shared_ptr ¶m, napi_env env, napi_value valueBucketParam) +{ + HILOG_INFO("%{public}s called.", __func__); + napi_value result; + + if (param == nullptr) { + HILOG_INFO("%{public}s input param is nullptr.", __func__); + NAPI_CALL(env, napi_create_int32(env, 0, &result)); + return result; + } + AnalysisValuesBucket(*param, env, valueBucketParam); + + NAPI_CALL(env, napi_create_int32(env, 1, &result)); + return result; +} + +napi_value UnwrapDataAbilityPredicatesBackReferences( + std::shared_ptr &builder, napi_env env, napi_value predicatesBackReferencesParam) +{ + HILOG_INFO("%{public}s called.", __func__); + + if (!IsTypeForNapiValue(env, predicatesBackReferencesParam, napi_object)) { + HILOG_ERROR("%{public}s, predicatesBackReferencesParam is invalid.", __func__); + return nullptr; + } + + napi_valuetype jsValueType = napi_undefined; + napi_value jsProNameList = nullptr; + uint32_t jsProCount = 0; + + NAPI_CALL(env, napi_get_property_names(env, predicatesBackReferencesParam, &jsProNameList)); + NAPI_CALL(env, napi_get_array_length(env, jsProNameList, &jsProCount)); + HILOG_INFO("%{public}s, Property size=%{public}d.", __func__, jsProCount); + + napi_value jsProName = nullptr; + napi_value jsProValue = nullptr; + for (uint32_t index = 0; index < jsProCount; index++) { + NAPI_CALL(env, napi_get_element(env, jsProNameList, index, &jsProName)); + std::string strProName = UnwrapStringFromJS(env, jsProName); + int intProName = std::atoi(strProName.c_str()); + HILOG_INFO("%{public}s, Property name=%{public}d.", __func__, intProName); + NAPI_CALL(env, napi_get_property(env, predicatesBackReferencesParam, jsProName, &jsProValue)); + NAPI_CALL(env, napi_typeof(env, jsProValue, &jsValueType)); + int32_t natValue32 = 0; + if (napi_get_value_int32(env, jsProValue, &natValue32) == napi_ok) { + HILOG_INFO("%{public}s, Property value=%{public}d.", __func__, natValue32); + builder->WithPredicatesBackReference(intProName, natValue32); + } + } + napi_value result; + NAPI_CALL(env, napi_create_int32(env, 1, &result)); + return result; +} + +void SetNamedProperty(napi_env env, napi_value obj, const char *propName, const int propValue) +{ + napi_value prop = nullptr; + napi_create_int32(env, propValue, &prop); + napi_set_named_property(env, obj, propName, prop); +} + +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/interfaces/kits/napi/aafwk/featureAbility/napi_data_ability_operation.h b/tools/interfaces/kits/napi/aafwk/featureAbility/napi_data_ability_operation.h new file mode 100644 index 00000000000..1a2626ee89c --- /dev/null +++ b/tools/interfaces/kits/napi/aafwk/featureAbility/napi_data_ability_operation.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef OHOS_APPEXECFWK_DATA_ABILITY_OPERATION_H +#define OHOS_APPEXECFWK_DATA_ABILITY_OPERATION_H + +#include "feature_ability_common.h" +#include "data_ability_operation.h" + +namespace OHOS { +namespace NativeRdb { +class DataAbilityPredicates; +class ValuesBucket; +} // namespace NativeRdb +namespace AppExecFwk { +/** + * @brief DataAbilityOperation NAPI module registration. + * + * @param env The environment that the Node-API call is invoked under. + * @param exports An empty object via the exports parameter as a convenience. + * + * @return The return value from Init is treated as the exports object for the module. + */ +napi_value DataAbilityOperationInit(napi_env env, napi_value exports); +void SetNamedProperty(napi_env env, napi_value obj, const char *propName, const int propValue); +/** + * @brief Parse the dataAbilityOperation parameters. + * + * @param param Indicates the dataAbilityOperation parameters saved the parse result. + * @param env The environment that the Node-API call is invoked under. + * @param args Indicates the arguments passed into the callback. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value UnwrapDataAbilityOperation(std::shared_ptr ¶m, napi_env env, napi_value args); +napi_value BuildDataAbilityOperation( + std::shared_ptr &dataAbilityOperation, napi_env env, napi_value param); +bool GetDataAbilityOperationBuilder( + std::shared_ptr &builder, const int type, const std::shared_ptr &uri); +/** + * @brief Parse the ValuesBucket parameters. + * + * @param param Indicates the valuesBucket parameters saved the parse result. + * @param env The environment that the Node-API call is invoked under. + * @param args Indicates the arguments passed into the callback. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value UnwrapValuesBucket(std::shared_ptr ¶m, napi_env env, napi_value args); +/** + * @brief Parse the DataAbilityPredicatesBackReferences parameters. + * + * @param builder Indicates the dataAbilityPredicatesBackReferences parameters saved the parse result. + * @param env The environment that the Node-API call is invoked under. + * @param args Indicates the arguments passed into the callback. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value UnwrapDataAbilityPredicatesBackReferences( + std::shared_ptr &builder, napi_env env, napi_value args); + +} // namespace AppExecFwk +} // namespace OHOS +#endif /* OHOS_APPEXECFWK_WANT_WRAPPER_H */ diff --git a/tools/interfaces/kits/napi/aafwk/featureAbility/native_module.cpp b/tools/interfaces/kits/napi/aafwk/featureAbility/native_module.cpp new file mode 100644 index 00000000000..831e817934e --- /dev/null +++ b/tools/interfaces/kits/napi/aafwk/featureAbility/native_module.cpp @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +#include "feature_ability.h" +#include "feature_ability_constant.h" +#include "napi_context.h" +#include "napi_data_ability_helper.h" +#include "napi_data_ability_operation.h" +#include "napi/native_api.h" +#include "napi/native_node_api.h" +namespace OHOS { +namespace AppExecFwk { +EXTERN_C_START +/* + * The module initialization. + */ +static napi_value Init(napi_env env, napi_value exports) +{ + FeatureAbilityInit(env, exports); + ContextPermissionInit(env, exports); + DataAbilityOperationInit(env, exports); + DataAbilityHelperInit(env, exports); + FAConstantInit(env, exports); + return exports; +} +EXTERN_C_END + +/* + * The module definition. + */ +static napi_module _module = { + .nm_version = 1, + .nm_flags = 0, + .nm_filename = nullptr, + .nm_register_func = Init, + .nm_modname = "ability.featureAbility", + .nm_priv = ((void *)0), + .reserved = {0} +}; + +/* + * The module registration. + */ +extern "C" __attribute__((constructor)) void RegisterModule(void) +{ + napi_module_register(&_module); +} +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/interfaces/kits/napi/aafwk/formManager/BUILD.gn b/tools/interfaces/kits/napi/aafwk/formManager/BUILD.gn new file mode 100644 index 00000000000..b8e50a0567c --- /dev/null +++ b/tools/interfaces/kits/napi/aafwk/formManager/BUILD.gn @@ -0,0 +1,47 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +#import("//build/config/ohos/rules.gni") +import("//build/ohos.gni") +ohos_shared_library("formmanager") { + include_dirs = [ + "//foundation/ace/napi/interfaces/kits", + "//foundation/aafwk/standard/frameworks/kits/ability/native/include", + "//foundation/aafwk/standard/interfaces/kits/napi/aafwk/formManager", + "//foundation/communication/ipc/interfaces/innerkits/ipc_core/include", + ] + + sources = [ + "napi_form_manager.cpp", + "native_module.cpp", + ] + + deps = [ + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/interfaces/innerkits/base:base", + "//foundation/ace/napi:ace_napi", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/kits:appkit_native", + ] + + external_deps = [ + "aafwk_standard:ability_manager", + "aafwk_standard:want", + "hiviewdfx_hilog_native:libhilog", + ] + + relative_install_dir = "module/ability" + + subsystem_name = "aafwk" + part_name = "aafwk_standard" +} diff --git a/tools/interfaces/kits/napi/aafwk/formManager/napi_form_manager.cpp b/tools/interfaces/kits/napi/aafwk/formManager/napi_form_manager.cpp new file mode 100644 index 00000000000..113a936f5ea --- /dev/null +++ b/tools/interfaces/kits/napi/aafwk/formManager/napi_form_manager.cpp @@ -0,0 +1,2657 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "napi_form_manager.h" +#include "napi/native_api.h" +#include "napi/native_node_api.h" +#include +#include +#include + +using namespace OHOS; +using namespace OHOS::AAFwk; +using namespace OHOS::AppExecFwk; + +namespace { + constexpr size_t ARGS_SIZE_ONE = 1; + constexpr size_t ARGS_SIZE_TWO = 2; + constexpr size_t ARGS_SIZE_THREE = 3; +} + +/** + * @brief Get a C++ string value from Node-API + * + * @param[in] env The environment that the Node-API call is invoked under + * @param[in] value This is an opaque pointer that is used to represent a JavaScript value + * + * @return Return a C++ string + */ +static std::string GetStringFromNAPI(napi_env env, napi_value value) +{ + std::string result; + size_t size = 0; + + if (napi_get_value_string_utf8(env, value, nullptr, 0, &size) != napi_ok) { + HILOG_ERROR("%{public}s, can not get string size", __func__); + return ""; + } + result.reserve(size + 1); + result.resize(size); + if (napi_get_value_string_utf8(env, value, result.data(), (size + 1), &size) != napi_ok) { + HILOG_ERROR("%{public}s, can not get string value", __func__); + return ""; + } + return result; +} + +/** + * @brief Parse form info into Node-API + * + * @param[in] env The environment that the Node-API call is invoked under + * @param[in] formInfo it is used for return forminfo to JavaScript + * @param[out] result This is an opaque pointer that is used to represent a JavaScript value + * + * @return void + */ +static void ParseFormInfoIntoNapi(napi_env env, const FormInfo &formInfo, napi_value &result) +{ + // bundleName + napi_value bundleName; + napi_create_string_utf8(env, formInfo.bundleName.c_str(), NAPI_AUTO_LENGTH, &bundleName); + HILOG_DEBUG("%{public}s, bundleName=%{public}s.", __func__, formInfo.bundleName.c_str()); + napi_set_named_property(env, result, "bundleName", bundleName); + + // moduleName + napi_value moduleName; + napi_create_string_utf8(env, formInfo.moduleName.c_str(), NAPI_AUTO_LENGTH, &moduleName); + HILOG_DEBUG("%{public}s, moduleName=%{public}s.", __func__, formInfo.moduleName.c_str()); + napi_set_named_property(env, result, "moduleName", moduleName); + + // abilityName + napi_value abilityName; + napi_create_string_utf8(env, formInfo.abilityName.c_str(), NAPI_AUTO_LENGTH, &abilityName); + HILOG_DEBUG("%{public}s, abilityName=%{public}s.", __func__, formInfo.abilityName.c_str()); + napi_set_named_property(env, result, "abilityName", abilityName); + + // name + napi_value name; + napi_create_string_utf8(env, formInfo.name.c_str(), NAPI_AUTO_LENGTH, &name); + HILOG_DEBUG("%{public}s, name=%{public}s.", __func__, formInfo.name.c_str()); + napi_set_named_property(env, result, "name", name); + + // description + napi_value description; + napi_create_string_utf8(env, formInfo.description.c_str(), NAPI_AUTO_LENGTH, &description); + HILOG_DEBUG("%{public}s, description=%{public}s.", __func__, formInfo.description.c_str()); + napi_set_named_property(env, result, "description", description); + + // descriptionId + napi_value descriptionId; + napi_create_int32(env, formInfo.descriptionId, &descriptionId); + HILOG_DEBUG("%{public}s, descriptionId=%{public}d.", __func__, formInfo.descriptionId); + napi_set_named_property(env, result, "descriptionId", descriptionId); + + // type + napi_value type; + FormType formType = formInfo.type; + napi_create_int32(env, (int32_t)formType, &type); + HILOG_DEBUG("%{public}s, formInfo_type=%{public}d.", __func__, (int32_t)formType); + napi_set_named_property(env, result, "type", type); + + // jsComponentName + napi_value jsComponentName; + napi_create_string_utf8(env, formInfo.jsComponentName.c_str(), NAPI_AUTO_LENGTH, &jsComponentName); + HILOG_DEBUG("%{public}s, jsComponentName=%{public}s.", __func__, formInfo.jsComponentName.c_str()); + napi_set_named_property(env, result, "jsComponentName", jsComponentName); + + // colorMode + napi_value colorMode; + FormsColorMode formsColorMode = formInfo.colorMode; + napi_create_int32(env, (int32_t)formsColorMode, &colorMode); + HILOG_DEBUG("%{public}s, formInfo_type=%{public}d.", __func__, (int32_t)formsColorMode); + napi_set_named_property(env, result, "colorMode", colorMode); + + // defaultFlag + napi_value defaultFlag; + napi_create_int32(env, (int32_t)formInfo.defaultFlag, &defaultFlag); + HILOG_DEBUG("%{public}s, defaultFlag=%{public}d.", __func__, formInfo.defaultFlag); + napi_set_named_property(env, result, "isDefault", defaultFlag); + + // formVisibleNotify + napi_value formVisibleNotify; + napi_create_int32(env, (int32_t)formInfo.formVisibleNotify, &formVisibleNotify); + HILOG_DEBUG("%{public}s, formVisibleNotify=%{public}d.", __func__, formInfo.formVisibleNotify); + napi_set_named_property(env, result, "formVisibleNotify", formVisibleNotify); + + // formConfigAbility + napi_value formConfigAbility; + napi_create_string_utf8(env, formInfo.formConfigAbility.c_str(), NAPI_AUTO_LENGTH, &formConfigAbility); + HILOG_DEBUG("%{public}s, formConfigAbility=%{public}s.", __func__, formInfo.formConfigAbility.c_str()); + napi_set_named_property(env, result, "formConfigAbility", formConfigAbility); + + // updateDuration + napi_value updateDuration; + napi_create_int32(env, formInfo.updateDuration, &updateDuration); + HILOG_DEBUG("%{public}s, updateDuration=%{public}d.", __func__, formInfo.updateDuration); + napi_set_named_property(env, result, "updateDuration", updateDuration); + + // defaultDimension + napi_value defaultDimension; + napi_create_int32(env, formInfo.defaultDimension, &defaultDimension); + HILOG_DEBUG("%{public}s, defaultDimension=%{public}d.", __func__, formInfo.defaultDimension); + napi_set_named_property(env, result, "defaultDimension", defaultDimension); + + // supportDimensions + napi_value supportDimensions; + napi_create_array(env, &supportDimensions); + int iDimensionsCount = 0; + for (auto dimension : formInfo.supportDimensions) { + HILOG_DEBUG("%{public}s, dimension=%{public}d.", __func__, dimension); + napi_value dimensionInfo; + napi_create_int32(env, (int32_t)dimension, &dimensionInfo); + napi_set_element(env, supportDimensions, iDimensionsCount, dimensionInfo); + ++iDimensionsCount; + } + HILOG_DEBUG("%{public}s, supportDimensions size=%{public}zu.", __func__, formInfo.supportDimensions.size()); + napi_set_named_property(env, result, "supportDimensions", supportDimensions); + + // customizeDatas + napi_value customizeDatas; + napi_create_array(env, &customizeDatas); + int iCustomizeDatasCount = 0; + for (auto customizeData : formInfo.customizeDatas) { + + napi_value customizeDataOnject = nullptr; + napi_create_object(env, &customizeDataOnject); + + // customizeData : name + napi_value customizeDataName; + napi_create_string_utf8(env, customizeData.name.c_str(), NAPI_AUTO_LENGTH, &customizeDataName); + HILOG_DEBUG("%{public}s, customizeData.name=%{public}s.", __func__, customizeData.name.c_str()); + napi_set_named_property(env, customizeDataOnject, "name", customizeDataName); + + // customizeData : value + napi_value customizeDataValue; + napi_create_string_utf8(env, customizeData.value.c_str(), NAPI_AUTO_LENGTH, &customizeDataValue); + HILOG_DEBUG("%{public}s, customizeData.value=%{public}s.", __func__, customizeData.value.c_str()); + napi_set_named_property(env, customizeDataOnject, "value", customizeDataValue); + + napi_set_element(env, customizeDatas, iCustomizeDatasCount, customizeDataOnject); + ++iDimensionsCount; + } + HILOG_DEBUG("%{public}s, customizeDatas size=%{public}zu.", __func__, formInfo.customizeDatas.size()); + napi_set_named_property(env, result, "customizeData", customizeDatas); + + // relatedBundleName + napi_value relatedBundleName; + napi_create_string_utf8(env, formInfo.relatedBundleName.c_str(), NAPI_AUTO_LENGTH, &relatedBundleName); + HILOG_DEBUG("%{public}s, relatedBundleName=%{public}s.", __func__, formInfo.relatedBundleName.c_str()); + napi_set_named_property(env, result, "relatedBundleName", relatedBundleName); + + return; +} + +/** + * @brief Call native kit function: DeleteForm + * + * @param[in] env The environment that the Node-API call is invoked under + * @param[out] asyncCallbackInfo Reference, callback info via Node-API + * + * @return void + */ +static void InnerDelForm(napi_env env, AsyncDelFormCallbackInfo* const asyncCallbackInfo) +{ + HILOG_DEBUG("%{public}s called.", __func__); + OHOS::AppExecFwk::Ability *ability = asyncCallbackInfo->ability; + bool ret = ability->DeleteForm(asyncCallbackInfo->formId); + if (ret) { + asyncCallbackInfo->result = 1; + } else { + asyncCallbackInfo->result = 0; + } + HILOG_DEBUG("%{public}s, end", __func__); +} + +/** + * @brief The implementation of Node-API interface: deleteForm + * + * @param[in] env The environment that the Node-API call is invoked under + * @param[out] info An opaque datatype that is passed to a callback function + * + * @return This is an opaque pointer that is used to represent a JavaScript value + */ +napi_value NAPI_DeleteForm(napi_env env, napi_callback_info info) +{ + HILOG_INFO("%{public}s called.", __func__); + + // Check the number of the arguments + size_t argc = ARGS_SIZE_TWO; + napi_value argv[ARGS_SIZE_TWO] = {nullptr}; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr)); + if (argc > ARGS_SIZE_TWO) { + HILOG_ERROR("%{public}s, wrong number of arguments.", __func__); + return nullptr; + } + HILOG_INFO("%{public}s, argc = [%{public}zu]", __func__, argc); + + // get global value + napi_value global = nullptr; + napi_get_global(env, &global); + + // get ability + napi_value abilityObj = nullptr; + napi_get_named_property(env, global, "ability", &abilityObj); + + // get ability pointer + OHOS::AppExecFwk::Ability* ability = nullptr; + napi_get_value_external(env, abilityObj, (void**)&ability); + HILOG_INFO("%{public}s, ability = [%{public}p]", __func__, ability); + + // Check the value type of the arguments + napi_valuetype valueType; + NAPI_CALL(env, napi_typeof(env, argv[0], &valueType)); + NAPI_ASSERT(env, valueType == napi_string, "The arguments[0] type of deleteForm is incorrect,\ + expected type is string."); + + std::string strFormId = GetStringFromNAPI(env, argv[0]); + int64_t formId = std::stoll(strFormId); + + AsyncDelFormCallbackInfo *asyncCallbackInfo = new + AsyncDelFormCallbackInfo { + .env = env, + .ability = ability, + .asyncWork = nullptr, + .deferred = nullptr, + .callback = nullptr, + .formId = 0, + .result = 0, + }; + asyncCallbackInfo->formId = formId; + + if (argc == ARGS_SIZE_TWO) { + HILOG_INFO("%{public}s, asyncCallback.", __func__); + + // Check the value type of the arguments + valueType = napi_undefined; + NAPI_CALL(env, napi_typeof(env, argv[1], &valueType)); + NAPI_ASSERT(env, valueType == napi_function, "The arguments[1] type of deleteForm is incorrect,\ + expected type is function."); + + napi_create_reference(env, argv[1], 1, &asyncCallbackInfo->callback); + + napi_value resourceName; + napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName); + napi_create_async_work( + env, + nullptr, + resourceName, + [](napi_env env, void *data) { + HILOG_INFO("%{public}s, napi_create_async_work running", __func__); + AsyncDelFormCallbackInfo *asyncCallbackInfo = (AsyncDelFormCallbackInfo *)data; + InnerDelForm(env, asyncCallbackInfo); + }, + [](napi_env env, napi_status status, void *data) { + AsyncDelFormCallbackInfo *asyncCallbackInfo = (AsyncDelFormCallbackInfo *)data; + HILOG_INFO("%{public}s, napi_create_async_work complete", __func__); + + if (asyncCallbackInfo->callback != nullptr) { + napi_value result; + napi_create_int32(env, asyncCallbackInfo->result, &result); + napi_value callback; + napi_value undefined; + napi_get_undefined(env, &undefined); + napi_get_reference_value(env, asyncCallbackInfo->callback, &callback); + napi_value callResult; + napi_call_function(env, undefined, callback, 1, &result, &callResult); + napi_delete_reference(env, asyncCallbackInfo->callback); + } + napi_delete_async_work(env, asyncCallbackInfo->asyncWork); + delete asyncCallbackInfo; + }, + (void *)asyncCallbackInfo, + &asyncCallbackInfo->asyncWork); + NAPI_CALL(env, napi_queue_async_work(env, asyncCallbackInfo->asyncWork)); + + napi_value result; + NAPI_CALL(env, napi_create_int32(env, 1, &result)); + return result; + } else { + HILOG_INFO("%{public}s, promise.", __func__); + napi_deferred deferred; + napi_value promise; + NAPI_CALL(env, napi_create_promise(env, &deferred, &promise)); + asyncCallbackInfo->deferred = deferred; + + napi_value resourceName; + napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName); + napi_create_async_work( + env, + nullptr, + resourceName, + [](napi_env env, void *data) { + HILOG_INFO("%{public}s, promise runnning", __func__); + AsyncDelFormCallbackInfo *asyncCallbackInfo = (AsyncDelFormCallbackInfo *)data; + InnerDelForm(env, asyncCallbackInfo); + }, + [](napi_env env, napi_status status, void *data) { + HILOG_INFO("%{public}s, promise complete", __func__); + AsyncDelFormCallbackInfo *asyncCallbackInfo = (AsyncDelFormCallbackInfo *)data; + + napi_value result; + napi_create_int32(env, asyncCallbackInfo->result, &result); + napi_resolve_deferred(asyncCallbackInfo->env, asyncCallbackInfo->deferred, result); + napi_delete_async_work(env, asyncCallbackInfo->asyncWork); + delete asyncCallbackInfo; + }, + (void *)asyncCallbackInfo, + &asyncCallbackInfo->asyncWork); + napi_queue_async_work(env, asyncCallbackInfo->asyncWork); + return promise; + } +} + +/** + * @brief Call native kit function: ReleaseForm + * + * @param[in] env The environment that the Node-API call is invoked under + * @param[out] asyncCallbackInfo Reference, callback info via Node-API + * + * @return void + */ +static void InnerReleaseForm(napi_env env, AsyncReleaseFormCallbackInfo* const asyncCallbackInfo) +{ + HILOG_DEBUG("%{public}s called.", __func__); + OHOS::AppExecFwk::Ability *ability = asyncCallbackInfo->ability; + bool ret = ability->ReleaseForm(asyncCallbackInfo->formId, asyncCallbackInfo->isReleaseCache); + if (ret) { + asyncCallbackInfo->result = 1; + } else { + asyncCallbackInfo->result = 0; + } + HILOG_DEBUG("%{public}s end", __func__); +} + +/** + * @brief The implementation of Node-API interface: releaseForm + * + * @param[in] env The environment that the Node-API call is invoked under + * @param[out] info An opaque datatype that is passed to a callback function + * + * @return This is an opaque pointer that is used to represent a JavaScript value + */ +napi_value NAPI_ReleaseForm(napi_env env, napi_callback_info info) +{ + HILOG_INFO("%{public}s called.", __func__); + + // Check the number of the arguments + size_t argc = ARGS_SIZE_THREE; + napi_value argv[ARGS_SIZE_THREE] = {nullptr}; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr)); + if (argc < ARGS_SIZE_TWO || argc > ARGS_SIZE_THREE) { + HILOG_ERROR("%{public}s, wrong number of arguments.", __func__); + return nullptr; + } + HILOG_INFO("%{public}s, argc = [%{public}zu]", __func__, argc); + + // Check the value type of the arguments + napi_valuetype valueType; + NAPI_CALL(env, napi_typeof(env, argv[0], &valueType)); + NAPI_ASSERT(env, valueType == napi_string, "The arguments[0] type of releaseForm is incorrect,\ + expected type is string."); + + std::string strFormId = GetStringFromNAPI(env, argv[0]); + int64_t formId = std::stoll(strFormId); + + valueType = napi_undefined; + NAPI_CALL(env, napi_typeof(env, argv[1], &valueType)); + NAPI_ASSERT(env, valueType == napi_boolean, "The arguments[1] type of releaseForm is incorrect,\ + expected type is boolean."); + + bool isReleaseCache = false; + napi_get_value_bool(env, argv[1], &isReleaseCache); + + // get global value + napi_value global = nullptr; + napi_get_global(env, &global); + + // get ability + napi_value abilityObj = nullptr; + napi_get_named_property(env, global, "ability", &abilityObj); + + // get ability pointer + OHOS::AppExecFwk::Ability* ability = nullptr; + napi_get_value_external(env, abilityObj, (void**)&ability); + HILOG_INFO("%{public}s, ability = [%{public}p]", __func__, ability); + + AsyncReleaseFormCallbackInfo *asyncCallbackInfo = new + AsyncReleaseFormCallbackInfo { + .env = env, + .ability = ability, + .asyncWork = nullptr, + .deferred = nullptr, + .callback = nullptr, + .formId = formId, + .isReleaseCache = isReleaseCache, + .result = 0, + }; + + if (argc == ARGS_SIZE_THREE) { + HILOG_INFO("%{public}s, asyncCallback.", __func__); + + // Check the value type of the arguments + valueType = napi_undefined; + NAPI_CALL(env, napi_typeof(env, argv[2], &valueType)); + NAPI_ASSERT(env, valueType == napi_function, "The arguments[2] type of releaseForm is incorrect,\ + expected type is function."); + + napi_create_reference(env, argv[2], 1, &asyncCallbackInfo->callback); + + napi_value resourceName; + napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName); + napi_create_async_work( + env, + nullptr, + resourceName, + [](napi_env env, void *data) { + HILOG_INFO("%{public}s, napi_create_async_work running", __func__); + AsyncReleaseFormCallbackInfo *asyncCallbackInfo = (AsyncReleaseFormCallbackInfo *)data; + InnerReleaseForm(env, asyncCallbackInfo); + }, + [](napi_env env, napi_status status, void *data) { + AsyncReleaseFormCallbackInfo *asyncCallbackInfo = (AsyncReleaseFormCallbackInfo *)data; + HILOG_INFO("%{public}s, napi_create_async_work complete", __func__); + + if (asyncCallbackInfo->callback != nullptr) { + napi_value result; + napi_create_int32(env, asyncCallbackInfo->result, &result); + napi_value callback; + napi_value undefined; + napi_get_undefined(env, &undefined); + napi_get_reference_value(env, asyncCallbackInfo->callback, &callback); + napi_value callResult; + napi_call_function(env, undefined, callback, 1, &result, &callResult); + napi_delete_reference(env, asyncCallbackInfo->callback); + } + napi_delete_async_work(env, asyncCallbackInfo->asyncWork); + delete asyncCallbackInfo; + }, + (void *)asyncCallbackInfo, + &asyncCallbackInfo->asyncWork); + NAPI_CALL(env, napi_queue_async_work(env, asyncCallbackInfo->asyncWork)); + + napi_value result; + NAPI_CALL(env, napi_create_int32(env, 1, &result)); + return result; + } else { + HILOG_INFO("%{public}s, promise.", __func__); + napi_deferred deferred; + napi_value promise; + NAPI_CALL(env, napi_create_promise(env, &deferred, &promise)); + asyncCallbackInfo->deferred = deferred; + + napi_value resourceName; + napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName); + napi_create_async_work( + env, + nullptr, + resourceName, + [](napi_env env, void *data) { + HILOG_INFO("%{public}s, promise running,", __func__); + AsyncReleaseFormCallbackInfo *asyncCallbackInfo = (AsyncReleaseFormCallbackInfo *)data; + InnerReleaseForm(env, asyncCallbackInfo); + }, + [](napi_env env, napi_status status, void *data) { + HILOG_INFO("%{public}s, promise complete", __func__); + AsyncReleaseFormCallbackInfo *asyncCallbackInfo = (AsyncReleaseFormCallbackInfo *)data; + + napi_value result; + napi_create_int32(env, asyncCallbackInfo->result, &result); + napi_resolve_deferred(asyncCallbackInfo->env, asyncCallbackInfo->deferred, result); + napi_delete_async_work(env, asyncCallbackInfo->asyncWork); + delete asyncCallbackInfo; + }, + (void *)asyncCallbackInfo, + &asyncCallbackInfo->asyncWork); + napi_queue_async_work(env, asyncCallbackInfo->asyncWork); + return promise; + } +} + +/** + * @brief Call native kit function: RequestForm + * + * @param[in] env The environment that the Node-API call is invoked under + * @param[out] asyncCallbackInfo Reference, callback info via Node-API + * + * @return void + */ +static void InnerRequestForm(napi_env env, AsyncRequestFormCallbackInfo* const asyncCallbackInfo) +{ + HILOG_DEBUG("%{public}s called.", __func__); + OHOS::AppExecFwk::Ability *ability = asyncCallbackInfo->ability; + bool ret = ability->RequestForm(asyncCallbackInfo->formId); + if (ret) { + asyncCallbackInfo->result = 1; + } else { + asyncCallbackInfo->result = 0; + } + HILOG_DEBUG("%{public}s, end", __func__); +} + +/** + * @brief The implementation of Node-API interface: requestForm + * + * @param[in] env The environment that the Node-API call is invoked under + * @param[out] info An opaque datatype that is passed to a callback function + * + * @return This is an opaque pointer that is used to represent a JavaScript value + */ +napi_value NAPI_RequestForm(napi_env env, napi_callback_info info) +{ + HILOG_INFO("%{public}s called.", __func__); + + // Check the number of the arguments + size_t argc = ARGS_SIZE_TWO; + napi_value argv[ARGS_SIZE_TWO] = {nullptr}; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr)); + if (argc > ARGS_SIZE_TWO) { + HILOG_ERROR("%{public}s, wrong number of arguments.", __func__); + return nullptr; + } + HILOG_INFO("%{public}s, argc = [%{public}zu]", __func__, argc); + + // Check the value type of the arguments + napi_valuetype valueType; + NAPI_CALL(env, napi_typeof(env, argv[0], &valueType)); + NAPI_ASSERT(env, valueType == napi_string, "The arguments[0] type of requestForm is incorrect,\ + expected type is string."); + + std::string strFormId = GetStringFromNAPI(env, argv[0]); + int64_t formId = std::stoll(strFormId); + + // get global value + napi_value global = nullptr; + napi_get_global(env, &global); + + // get ability + napi_value abilityObj = nullptr; + napi_get_named_property(env, global, "ability", &abilityObj); + + // get ability pointer + OHOS::AppExecFwk::Ability* ability = nullptr; + napi_get_value_external(env, abilityObj, (void**)&ability); + HILOG_INFO("%{public}s, ability = [%{public}p]", __func__, ability); + + AsyncRequestFormCallbackInfo *asyncCallbackInfo = new + AsyncRequestFormCallbackInfo { + .env = env, + .ability = ability, + .asyncWork = nullptr, + .deferred = nullptr, + .callback = nullptr, + .formId = formId, + .result = 0, + }; + + if (argc == ARGS_SIZE_TWO) { + HILOG_INFO("%{public}s, asyncCallback.", __func__); + + // Check the value type of the arguments + valueType = napi_undefined; + NAPI_CALL(env, napi_typeof(env, argv[1], &valueType)); + NAPI_ASSERT(env, valueType == napi_function, "The arguments[1] type of requestForm is incorrect,\ + expected type is function."); + + napi_create_reference(env, argv[1], 1, &asyncCallbackInfo->callback); + + napi_value resourceName; + napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName); + napi_create_async_work( + env, + nullptr, + resourceName, + [](napi_env env, void *data) { + HILOG_INFO("%{public}s, napi_create_async_work running", __func__); + AsyncRequestFormCallbackInfo *asyncCallbackInfo = (AsyncRequestFormCallbackInfo *)data; + InnerRequestForm(env, asyncCallbackInfo); + }, + [](napi_env env, napi_status status, void *data) { + AsyncRequestFormCallbackInfo *asyncCallbackInfo = (AsyncRequestFormCallbackInfo *)data; + HILOG_INFO("%{public}s, napi_create_async_work complete", __func__); + + if (asyncCallbackInfo->callback != nullptr) { + napi_value result; + napi_create_int32(env, asyncCallbackInfo->result, &result); + napi_value callback; + napi_value undefined; + napi_get_undefined(env, &undefined); + napi_get_reference_value(env, asyncCallbackInfo->callback, &callback); + napi_value callResult; + napi_call_function(env, undefined, callback, 1, &result, &callResult); + napi_delete_reference(env, asyncCallbackInfo->callback); + } + napi_delete_async_work(env, asyncCallbackInfo->asyncWork); + delete asyncCallbackInfo; + }, + (void *)asyncCallbackInfo, + &asyncCallbackInfo->asyncWork); + NAPI_CALL(env, napi_queue_async_work(env, asyncCallbackInfo->asyncWork)); + + napi_value result; + NAPI_CALL(env, napi_create_int32(env, 1, &result)); + return result; + } else { + HILOG_INFO("%{public}s, promise.", __func__); + napi_deferred deferred; + napi_value promise; + NAPI_CALL(env, napi_create_promise(env, &deferred, &promise)); + asyncCallbackInfo->deferred = deferred; + + napi_value resourceName; + napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName); + napi_create_async_work( + env, + nullptr, + resourceName, + [](napi_env env, void *data) { + HILOG_INFO("%{public}s, promise runnning", __func__); + AsyncRequestFormCallbackInfo *asyncCallbackInfo = (AsyncRequestFormCallbackInfo *)data; + InnerRequestForm(env, asyncCallbackInfo); + }, + [](napi_env env, napi_status status, void *data) { + HILOG_INFO("%{public}s, promise complete", __func__); + AsyncRequestFormCallbackInfo *asyncCallbackInfo = (AsyncRequestFormCallbackInfo *)data; + + napi_value result; + napi_create_int32(env, asyncCallbackInfo->result, &result); + napi_resolve_deferred(asyncCallbackInfo->env, asyncCallbackInfo->deferred, result); + napi_delete_async_work(env, asyncCallbackInfo->asyncWork); + delete asyncCallbackInfo; + }, + (void *)asyncCallbackInfo, + &asyncCallbackInfo->asyncWork); + napi_queue_async_work(env, asyncCallbackInfo->asyncWork); + return promise; + } +} + +/** + * @brief Call native kit function: SetFormNextRefreshTime + * + * @param[in] env The environment that the Node-API call is invoked under + * @param[out] asyncCallbackInfo Reference, callback info via Node-API + * + * @return void + */ +static void InnerSetFormNextRefreshTime(napi_env env, AsyncNextRefreshTimeFormCallbackInfo* const asyncCallbackInfo) +{ + HILOG_DEBUG("%{public}s called.", __func__); + OHOS::AppExecFwk::Ability *ability = asyncCallbackInfo->ability; + bool ret = ability->SetFormNextRefreshTime(asyncCallbackInfo->formId, asyncCallbackInfo->time); + if (ret) { + asyncCallbackInfo->result = 1; + } else { + asyncCallbackInfo->result = 0; + } + HILOG_DEBUG("%{public}s, end", __func__); +} + +/** + * @brief The implementation of Node-API interface: setFormNextRefreshTime + * + * @param[in] env The environment that the Node-API call is invoked under + * @param[out] info An opaque datatype that is passed to a callback function + * + * @return This is an opaque pointer that is used to represent a JavaScript value + */ +napi_value NAPI_SetFormNextRefreshTime(napi_env env, napi_callback_info info) +{ + HILOG_INFO("%{public}s called.", __func__); + + // Check the number of the arguments + size_t argc = ARGS_SIZE_THREE; + napi_value argv[ARGS_SIZE_THREE] = {nullptr}; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr)); + if (argc > ARGS_SIZE_THREE || argc < ARGS_SIZE_TWO) { + HILOG_ERROR("%{public}s, wrong number of arguments.", __func__); + return nullptr; + } + HILOG_INFO("%{public}s, argc = [%{public}zu]", __func__, argc); + + // Check the value type of the arguments + napi_valuetype valueType; + NAPI_CALL(env, napi_typeof(env, argv[0], &valueType)); + NAPI_ASSERT(env, valueType == napi_string, "The arguments[0] type of setFormNextRefreshTime is incorrect,\ + expected type is string."); + + std::string strFormId = GetStringFromNAPI(env, argv[0]); + int64_t formId = std::stoll(strFormId); + + valueType = napi_undefined; + NAPI_CALL(env, napi_typeof(env, argv[1], &valueType)); + NAPI_ASSERT(env, valueType == napi_number, "The arguments[1] type of setFormNextRefreshTime is incorrect,\ + expected type is number."); + + int32_t time; + napi_get_value_int32(env, argv[1], &time); + + // get global value + napi_value global = nullptr; + napi_get_global(env, &global); + + // get ability + napi_value abilityObj = nullptr; + napi_get_named_property(env, global, "ability", &abilityObj); + + // get ability pointer + OHOS::AppExecFwk::Ability* ability = nullptr; + napi_get_value_external(env, abilityObj, (void**)&ability); + HILOG_INFO("%{public}s, ability = [%{public}p]", __func__, ability); + + AsyncNextRefreshTimeFormCallbackInfo *asyncCallbackInfo = new + AsyncNextRefreshTimeFormCallbackInfo { + .env = env, + .ability = ability, + .asyncWork = nullptr, + .deferred = nullptr, + .callback = nullptr, + .formId = formId, + .time = time, + .result = 0, + }; + + if (argc == ARGS_SIZE_THREE) { + HILOG_INFO("%{public}s, asyncCallback.", __func__); + + // Check the value type of the arguments + valueType = napi_undefined; + NAPI_CALL(env, napi_typeof(env, argv[2], &valueType)); + NAPI_ASSERT(env, valueType == napi_function, "The arguments[2] type of setFormNextRefreshTime is incorrect,\ + expected type is function."); + + napi_create_reference(env, argv[1], 1, &asyncCallbackInfo->callback); + + napi_value resourceName; + napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName); + napi_create_async_work( + env, + nullptr, + resourceName, + [](napi_env env, void *data) { + HILOG_INFO("%{public}s, napi_create_async_work running", __func__); + + AsyncNextRefreshTimeFormCallbackInfo *asyncCallbackInfo = + (AsyncNextRefreshTimeFormCallbackInfo *)data; + + InnerSetFormNextRefreshTime(env, asyncCallbackInfo); + }, + [](napi_env env, napi_status status, void *data) { + AsyncNextRefreshTimeFormCallbackInfo *asyncCallbackInfo = + (AsyncNextRefreshTimeFormCallbackInfo *)data; + + HILOG_INFO("%{public}s, napi_create_async_work complete", __func__); + + if (asyncCallbackInfo->callback != nullptr) { + napi_value result; + napi_create_int32(env, asyncCallbackInfo->result, &result); + napi_value callback; + napi_value undefined; + napi_get_undefined(env, &undefined); + napi_get_reference_value(env, asyncCallbackInfo->callback, &callback); + napi_value callResult; + napi_call_function(env, undefined, callback, 1, &result, &callResult); + napi_delete_reference(env, asyncCallbackInfo->callback); + } + napi_delete_async_work(env, asyncCallbackInfo->asyncWork); + delete asyncCallbackInfo; + }, + (void *)asyncCallbackInfo, + &asyncCallbackInfo->asyncWork); + NAPI_CALL(env, napi_queue_async_work(env, asyncCallbackInfo->asyncWork)); + + napi_value result; + NAPI_CALL(env, napi_create_int32(env, 1, &result)); + return result; + } else { + HILOG_INFO("%{public}s, promise.", __func__); + napi_deferred deferred; + napi_value promise; + NAPI_CALL(env, napi_create_promise(env, &deferred, &promise)); + asyncCallbackInfo->deferred = deferred; + + napi_value resourceName; + napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName); + napi_create_async_work( + env, + nullptr, + resourceName, + [](napi_env env, void *data) { + HILOG_INFO("%{public}s, promise runnning", __func__); + AsyncNextRefreshTimeFormCallbackInfo *asyncCallbackInfo = + (AsyncNextRefreshTimeFormCallbackInfo *)data; + + InnerSetFormNextRefreshTime(env, asyncCallbackInfo); + }, + [](napi_env env, napi_status status, void *data) { + HILOG_INFO("%{public}s, promise complete", __func__); + AsyncNextRefreshTimeFormCallbackInfo *asyncCallbackInfo = + (AsyncNextRefreshTimeFormCallbackInfo *)data; + + napi_value result; + napi_create_int32(env, asyncCallbackInfo->result, &result); + napi_resolve_deferred(asyncCallbackInfo->env, asyncCallbackInfo->deferred, result); + napi_delete_async_work(env, asyncCallbackInfo->asyncWork); + delete asyncCallbackInfo; + }, + (void *)asyncCallbackInfo, + &asyncCallbackInfo->asyncWork); + napi_queue_async_work(env, asyncCallbackInfo->asyncWork); + return promise; + } +} + +/** + * @brief Call native kit function: UpdateForm + * + * @param[in] env The environment that the Node-API call is invoked under + * @param[out] asyncCallbackInfo Reference, callback info via Node-API + * + * @return void + */ +static void InnerUpdateForm(napi_env env, AsyncUpdateFormCallbackInfo* const asyncCallbackInfo) +{ + HILOG_DEBUG("%{public}s called.", __func__); + OHOS::AppExecFwk::Ability *ability = asyncCallbackInfo->ability; + bool ret = ability->UpdateForm(asyncCallbackInfo->formId, *asyncCallbackInfo->formProviderData); + if (ret) { + asyncCallbackInfo->result = 1; + } else { + asyncCallbackInfo->result = 0; + } + HILOG_DEBUG("%{public}s, end", __func__); +} + +/** + * @brief The implementation of Node-API interface: updateForm + * + * @param[in] env The environment that the Node-API call is invoked under + * @param[out] info An opaque datatype that is passed to a callback function + * + * @return This is an opaque pointer that is used to represent a JavaScript value + */ +napi_value NAPI_UpdateForm(napi_env env, napi_callback_info info) +{ + HILOG_INFO("%{public}s called.", __func__); + + // Check the number of the arguments + size_t argc = ARGS_SIZE_THREE; + napi_value argv[ARGS_SIZE_THREE] = {nullptr}; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr)); + if (argc > ARGS_SIZE_THREE || argc < ARGS_SIZE_TWO) { + HILOG_ERROR("%{public}s, wrong number of arguments.", __func__); + return nullptr; + } + HILOG_INFO("%{public}s, argc = [%{public}zu]", __func__, argc); + + // Check the value type of the arguments + napi_valuetype valueType; + NAPI_CALL(env, napi_typeof(env, argv[0], &valueType)); + NAPI_ASSERT(env, valueType == napi_string, "The arguments[0] type of updateForm is incorrect,\ + expected type is string."); + + std::string strFormId = GetStringFromNAPI(env, argv[0]); + int64_t formId = std::stoll(strFormId); + + NAPI_CALL(env, napi_typeof(env, argv[1], &valueType)); + NAPI_ASSERT(env, valueType == napi_string, "The arguments[1] type of updateForm is incorrect,\ + expected type is string."); + + OHOS::AppExecFwk::FormProviderData *formProviderData = nullptr; + napi_unwrap(env, argv[1], (void**)&formProviderData); + + // get global value + napi_value global = nullptr; + napi_get_global(env, &global); + + // get ability + napi_value abilityObj = nullptr; + napi_get_named_property(env, global, "ability", &abilityObj); + + // get ability pointer + OHOS::AppExecFwk::Ability* ability = nullptr; + napi_get_value_external(env, abilityObj, (void**)&ability); + HILOG_INFO("%{public}s, ability = [%{public}p]", __func__, ability); + + AsyncUpdateFormCallbackInfo *asyncCallbackInfo = new + AsyncUpdateFormCallbackInfo { + .env = env, + .ability = ability, + .asyncWork = nullptr, + .deferred = nullptr, + .callback = nullptr, + .formId = formId, + .formProviderData = std::shared_ptr(formProviderData), + .result = 0, + }; + + if (argc == ARGS_SIZE_THREE) { + HILOG_INFO("%{public}s, asyncCallback.", __func__); + + // Check the value type of the arguments + valueType = napi_undefined; + NAPI_CALL(env, napi_typeof(env, argv[2], &valueType)); + NAPI_ASSERT(env, valueType == napi_function, "The arguments[2] type of updateForm is incorrect,\ + expected type is function."); + + napi_create_reference(env, argv[1], 1, &asyncCallbackInfo->callback); + + napi_value resourceName; + napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName); + napi_create_async_work( + env, + nullptr, + resourceName, + [](napi_env env, void *data) { + HILOG_INFO("%{public}s, napi_create_async_work running", __func__); + AsyncUpdateFormCallbackInfo *asyncCallbackInfo = (AsyncUpdateFormCallbackInfo *)data; + InnerUpdateForm(env, asyncCallbackInfo); + }, + [](napi_env env, napi_status status, void *data) { + AsyncUpdateFormCallbackInfo *asyncCallbackInfo = (AsyncUpdateFormCallbackInfo *)data; + HILOG_INFO("%{public}s, napi_create_async_work complete", __func__); + + if (asyncCallbackInfo->callback != nullptr) { + napi_value result; + napi_create_int32(env, asyncCallbackInfo->result, &result); + napi_value callback; + napi_value undefined; + napi_get_undefined(env, &undefined); + napi_get_reference_value(env, asyncCallbackInfo->callback, &callback); + napi_value callResult; + napi_call_function(env, undefined, callback, 1, &result, &callResult); + napi_delete_reference(env, asyncCallbackInfo->callback); + } + napi_delete_async_work(env, asyncCallbackInfo->asyncWork); + delete asyncCallbackInfo; + }, + (void *)asyncCallbackInfo, + &asyncCallbackInfo->asyncWork); + NAPI_CALL(env, napi_queue_async_work(env, asyncCallbackInfo->asyncWork)); + + napi_value result; + NAPI_CALL(env, napi_create_int32(env, 1, &result)); + return result; + } else { + HILOG_INFO("%{public}s, promise.", __func__); + napi_deferred deferred; + napi_value promise; + NAPI_CALL(env, napi_create_promise(env, &deferred, &promise)); + asyncCallbackInfo->deferred = deferred; + + napi_value resourceName; + napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName); + napi_create_async_work( + env, + nullptr, + resourceName, + [](napi_env env, void *data) { + HILOG_INFO("%{public}s, promise runnning", __func__); + AsyncUpdateFormCallbackInfo *asyncCallbackInfo = (AsyncUpdateFormCallbackInfo *)data; + InnerUpdateForm(env, asyncCallbackInfo); + }, + [](napi_env env, napi_status status, void *data) { + HILOG_INFO("%{public}s, promise complete", __func__); + AsyncUpdateFormCallbackInfo *asyncCallbackInfo = (AsyncUpdateFormCallbackInfo *)data; + + napi_value result; + napi_create_int32(env, asyncCallbackInfo->result, &result); + napi_resolve_deferred(asyncCallbackInfo->env, asyncCallbackInfo->deferred, result); + napi_delete_async_work(env, asyncCallbackInfo->asyncWork); + delete asyncCallbackInfo; + }, + (void *)asyncCallbackInfo, + &asyncCallbackInfo->asyncWork); + napi_queue_async_work(env, asyncCallbackInfo->asyncWork); + return promise; + } +} + +/** + * @brief Call native kit function: CastTempForm + * + * @param[in] env The environment that the Node-API call is invoked under + * @param[out] asyncCallbackInfo Reference, callback info via Node-API + * + * @return void + */ +static void InnerCastTempForm(napi_env env, AsyncCastTempFormCallbackInfo* const asyncCallbackInfo) +{ + HILOG_DEBUG("%{public}s called.", __func__); + OHOS::AppExecFwk::Ability *ability = asyncCallbackInfo->ability; + bool ret = ability->CastTempForm(asyncCallbackInfo->formId); + if (ret) { + asyncCallbackInfo->result = 1; + } else { + asyncCallbackInfo->result = 0; + } + HILOG_DEBUG("%{public}s, end", __func__); +} + +/** + * @brief The implementation of Node-API interface: castTempForm + * + * @param[in] env The environment that the Node-API call is invoked under + * @param[out] info An opaque datatype that is passed to a callback function + * + * @return This is an opaque pointer that is used to represent a JavaScript value + */ +napi_value NAPI_CastTempForm(napi_env env, napi_callback_info info) +{ + HILOG_INFO("%{public}s called.", __func__); + + // Check the number of the arguments + size_t argc = ARGS_SIZE_TWO; + napi_value argv[ARGS_SIZE_TWO] = {nullptr}; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr)); + if (argc > ARGS_SIZE_TWO) { + HILOG_ERROR("%{public}s, wrong number of arguments.", __func__); + return nullptr; + } + HILOG_INFO("%{public}s, argc = [%{public}zu]", __func__, argc); + + // Check the value type of the arguments + napi_valuetype valueType; + NAPI_CALL(env, napi_typeof(env, argv[0], &valueType)); + NAPI_ASSERT(env, valueType == napi_string, "The arguments[0] type of castTempForm is incorrect,\ + expected type is string."); + + std::string strFormId = GetStringFromNAPI(env, argv[0]); + int64_t formId = std::stoll(strFormId); + + // get global value + napi_value global = nullptr; + napi_get_global(env, &global); + + // get ability + napi_value abilityObj = nullptr; + napi_get_named_property(env, global, "ability", &abilityObj); + + // get ability pointer + OHOS::AppExecFwk::Ability* ability = nullptr; + napi_get_value_external(env, abilityObj, (void**)&ability); + HILOG_INFO("%{public}s, ability = [%{public}p]", __func__, ability); + + AsyncCastTempFormCallbackInfo *asyncCallbackInfo = new + AsyncCastTempFormCallbackInfo { + .env = env, + .ability = ability, + .asyncWork = nullptr, + .deferred = nullptr, + .callback = nullptr, + .formId = formId, + .result = 0, + }; + + if (argc == ARGS_SIZE_TWO) { + HILOG_INFO("%{public}s, asyncCallback.", __func__); + + // Check the value type of the arguments + valueType = napi_undefined; + NAPI_CALL(env, napi_typeof(env, argv[1], &valueType)); + NAPI_ASSERT(env, valueType == napi_function, "The arguments[1] type of castTempForm is incorrect,\ + expected type is function."); + + napi_create_reference(env, argv[1], 1, &asyncCallbackInfo->callback); + + napi_value resourceName; + napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName); + napi_create_async_work( + env, + nullptr, + resourceName, + [](napi_env env, void *data) { + HILOG_INFO("%{public}s, napi_create_async_work running", __func__); + AsyncCastTempFormCallbackInfo *asyncCallbackInfo = (AsyncCastTempFormCallbackInfo *)data; + InnerCastTempForm(env, asyncCallbackInfo); + }, + [](napi_env env, napi_status status, void *data) { + AsyncCastTempFormCallbackInfo *asyncCallbackInfo = (AsyncCastTempFormCallbackInfo *)data; + HILOG_INFO("%{public}s, napi_create_async_work complete", __func__); + + if (asyncCallbackInfo->callback != nullptr) { + napi_value result; + napi_create_int32(env, asyncCallbackInfo->result, &result); + napi_value callback; + napi_value undefined; + napi_get_undefined(env, &undefined); + napi_get_reference_value(env, asyncCallbackInfo->callback, &callback); + napi_value callResult; + napi_call_function(env, undefined, callback, 1, &result, &callResult); + napi_delete_reference(env, asyncCallbackInfo->callback); + } + napi_delete_async_work(env, asyncCallbackInfo->asyncWork); + delete asyncCallbackInfo; + }, + (void *)asyncCallbackInfo, + &asyncCallbackInfo->asyncWork); + NAPI_CALL(env, napi_queue_async_work(env, asyncCallbackInfo->asyncWork)); + + napi_value result; + NAPI_CALL(env, napi_create_int32(env, 1, &result)); + return result; + } else { + HILOG_INFO("%{public}s, promise.", __func__); + napi_deferred deferred; + napi_value promise; + NAPI_CALL(env, napi_create_promise(env, &deferred, &promise)); + asyncCallbackInfo->deferred = deferred; + + napi_value resourceName; + napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName); + napi_create_async_work( + env, + nullptr, + resourceName, + [](napi_env env, void *data) { + HILOG_INFO("%{public}s, promise runnning", __func__); + AsyncCastTempFormCallbackInfo *asyncCallbackInfo = (AsyncCastTempFormCallbackInfo *)data; + InnerCastTempForm(env, asyncCallbackInfo); + }, + [](napi_env env, napi_status status, void *data) { + HILOG_INFO("%{public}s, promise complete", __func__); + AsyncCastTempFormCallbackInfo *asyncCallbackInfo = (AsyncCastTempFormCallbackInfo *)data; + + napi_value result; + napi_create_int32(env, asyncCallbackInfo->result, &result); + napi_resolve_deferred(asyncCallbackInfo->env, asyncCallbackInfo->deferred, result); + napi_delete_async_work(env, asyncCallbackInfo->asyncWork); + delete asyncCallbackInfo; + }, + (void *)asyncCallbackInfo, + &asyncCallbackInfo->asyncWork); + napi_queue_async_work(env, asyncCallbackInfo->asyncWork); + return promise; + } +} + +/** + * @brief Call native kit function: NotifyVisibleForms + * + * @param[in] env The environment that the Node-API call is invoked under + * @param[out] asyncCallbackInfo Reference, callback info via Node-API + * + * @return void + */ +static void InnerNotifyVisibleForms(napi_env env, AsyncNotifyVisibleFormsCallbackInfo* const asyncCallbackInfo) +{ + HILOG_DEBUG("%{public}s called.", __func__); + OHOS::AppExecFwk::Ability *ability = asyncCallbackInfo->ability; + bool ret = ability->NotifyVisibleForms(asyncCallbackInfo->formIds); + if (ret) { + asyncCallbackInfo->result = 1; + } else { + asyncCallbackInfo->result = 0; + } + HILOG_DEBUG("%{public}s, end", __func__); +} + +/** + * @brief The implementation of Node-API interface: notifyVisibleForms + * + * @param[in] env The environment that the Node-API call is invoked under + * @param[out] info An opaque datatype that is passed to a callback function + * + * @return This is an opaque pointer that is used to represent a JavaScript value + */ +napi_value NAPI_NotifyVisibleForms(napi_env env, napi_callback_info info) +{ + HILOG_INFO("%{public}s called.", __func__); + + // Check the number of the arguments + size_t argc = ARGS_SIZE_TWO; + napi_value argv[ARGS_SIZE_TWO] = {nullptr}; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr)); + if (argc > ARGS_SIZE_TWO) { + HILOG_ERROR("%{public}s, wrong number of arguments.", __func__); + return nullptr; + } + HILOG_INFO("%{public}s, argc = [%{public}zu]", __func__, argc); + + uint32_t arrayLength = 0; + NAPI_CALL(env, napi_get_array_length(env, argv[0], &arrayLength)); + NAPI_ASSERT(env, arrayLength > 0, "The arguments[0] value of notifyVisibleForms is incorrect,\ + this array is empty."); + + std::vector formIds; + formIds.clear(); + napi_valuetype valueType; + for (size_t i = 0; i < arrayLength; i++) { + napi_value napiFormId; + napi_get_element(env, argv[0], i, &napiFormId); + + // Check the value type of the arguments + valueType = napi_undefined; + NAPI_CALL(env, napi_typeof(env, napiFormId, &valueType)); + NAPI_ASSERT(env, valueType == napi_string, "The arguments[0] value type of notifyVisibleForms is incorrect,\ + expected type is string."); + + std::string strFormId = GetStringFromNAPI(env, napiFormId); + int64_t formIdValue = std::stoll(strFormId); + + formIds.push_back(formIdValue); + } + + // get global value + napi_value global = nullptr; + napi_get_global(env, &global); + + // get ability + napi_value abilityObj = nullptr; + napi_get_named_property(env, global, "ability", &abilityObj); + + // get ability pointer + OHOS::AppExecFwk::Ability* ability = nullptr; + napi_get_value_external(env, abilityObj, (void**)&ability); + HILOG_INFO("%{public}s, ability = [%{public}p]", __func__, ability); + + AsyncNotifyVisibleFormsCallbackInfo *asyncCallbackInfo = new + AsyncNotifyVisibleFormsCallbackInfo { + .env = env, + .ability = ability, + .asyncWork = nullptr, + .deferred = nullptr, + .callback = nullptr, + .formIds = formIds, + .result = 1, + }; + + if (argc == ARGS_SIZE_TWO) { + HILOG_INFO("%{public}s, asyncCallback.", __func__); + + // Check the value type of the arguments + valueType = napi_undefined; + NAPI_CALL(env, napi_typeof(env, argv[1], &valueType)); + NAPI_ASSERT(env, valueType == napi_function, "The arguments[1] type of notifyVisibleForms is incorrect,\ + expected type is function."); + + napi_create_reference(env, argv[1], 1, &asyncCallbackInfo->callback); + + napi_value resourceName; + napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName); + napi_create_async_work( + env, + nullptr, + resourceName, + [](napi_env env, void *data) { + HILOG_INFO("%{public}s, napi_create_async_work running", __func__); + + AsyncNotifyVisibleFormsCallbackInfo *asyncCallbackInfo = + (AsyncNotifyVisibleFormsCallbackInfo *)data; + + InnerNotifyVisibleForms(env, asyncCallbackInfo); + }, + [](napi_env env, napi_status status, void *data) { + AsyncNotifyVisibleFormsCallbackInfo *asyncCallbackInfo = + (AsyncNotifyVisibleFormsCallbackInfo *)data; + + HILOG_INFO("%{public}s, napi_create_async_work complete", __func__); + + if (asyncCallbackInfo->callback != nullptr) { + napi_value result; + napi_create_int32(env, asyncCallbackInfo->result, &result); + napi_value callback; + napi_value undefined; + napi_get_undefined(env, &undefined); + napi_get_reference_value(env, asyncCallbackInfo->callback, &callback); + napi_value callResult; + napi_call_function(env, undefined, callback, 1, &result, &callResult); + napi_delete_reference(env, asyncCallbackInfo->callback); + } + napi_delete_async_work(env, asyncCallbackInfo->asyncWork); + delete asyncCallbackInfo; + }, + (void *)asyncCallbackInfo, + &asyncCallbackInfo->asyncWork); + NAPI_CALL(env, napi_queue_async_work(env, asyncCallbackInfo->asyncWork)); + + napi_value result; + NAPI_CALL(env, napi_create_int32(env, 1, &result)); + return result; + } else { + HILOG_INFO("%{public}s, promise.", __func__); + napi_deferred deferred; + napi_value promise; + NAPI_CALL(env, napi_create_promise(env, &deferred, &promise)); + asyncCallbackInfo->deferred = deferred; + + napi_value resourceName; + napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName); + napi_create_async_work( + env, + nullptr, + resourceName, + [](napi_env env, void *data) { + HILOG_INFO("%{public}s, promise runnning", __func__); + + AsyncNotifyVisibleFormsCallbackInfo *asyncCallbackInfo = + (AsyncNotifyVisibleFormsCallbackInfo *)data; + + InnerNotifyVisibleForms(env, asyncCallbackInfo); + }, + [](napi_env env, napi_status status, void *data) { + HILOG_INFO("%{public}s, promise complete", __func__); + + AsyncNotifyVisibleFormsCallbackInfo *asyncCallbackInfo = + (AsyncNotifyVisibleFormsCallbackInfo *)data; + + napi_value result; + napi_create_int32(env, asyncCallbackInfo->result, &result); + napi_resolve_deferred(asyncCallbackInfo->env, asyncCallbackInfo->deferred, result); + napi_delete_async_work(env, asyncCallbackInfo->asyncWork); + delete asyncCallbackInfo; + }, + (void *)asyncCallbackInfo, + &asyncCallbackInfo->asyncWork); + napi_queue_async_work(env, asyncCallbackInfo->asyncWork); + return promise; + } +} + +/** + * @brief Call native kit function: NotifyInvisibleForms + * + * @param[in] env The environment that the Node-API call is invoked under + * @param[out] asyncCallbackInfo Reference, callback info via Node-API + * + * @return void + */ +static void InnerNotifyInvisibleForms(napi_env env, AsyncNotifyInvisibleFormsCallbackInfo* const asyncCallbackInfo) +{ + HILOG_DEBUG("%{public}s called.", __func__); + OHOS::AppExecFwk::Ability *ability = asyncCallbackInfo->ability; + bool ret = ability->NotifyInvisibleForms(asyncCallbackInfo->formIds); + if (ret) { + asyncCallbackInfo->result = 1; + } else { + asyncCallbackInfo->result = 0; + } + HILOG_DEBUG("%{public}s, end", __func__); +} + +/** + * @brief The implementation of Node-API interface: notifyInvisibleForms + * + * @param[in] env The environment that the Node-API call is invoked under + * @param[out] info An opaque datatype that is passed to a callback function + * + * @return This is an opaque pointer that is used to represent a JavaScript value + */ +napi_value NAPI_NotifyInvisibleForms(napi_env env, napi_callback_info info) +{ + HILOG_INFO("%{public}s called.", __func__); + + // Check the number of the arguments + size_t argc = ARGS_SIZE_TWO; + napi_value argv[ARGS_SIZE_TWO] = {nullptr}; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr)); + if (argc > ARGS_SIZE_TWO) { + HILOG_ERROR("%{public}s, wrong number of arguments.", __func__); + return nullptr; + } + HILOG_INFO("%{public}s, argc = [%{public}zu]", __func__, argc); + + uint32_t arrayLength = 0; + NAPI_CALL(env, napi_get_array_length(env, argv[0], &arrayLength)); + NAPI_ASSERT(env, arrayLength > 0, "The arguments[0] value of notifyInvisibleForms is incorrect,\ + this array is empty."); + + std::vector formIds; + formIds.clear(); + napi_valuetype valueType; + for (size_t i = 0; i < arrayLength; i++) { + napi_value napiFormId; + napi_get_element(env, argv[0], i, &napiFormId); + + // Check the value type of the arguments + valueType = napi_undefined; + NAPI_CALL(env, napi_typeof(env, napiFormId, &valueType)); + NAPI_ASSERT(env, valueType == napi_string, "The arguments[0] value type of notifyInvisibleForms \ + is incorrect, expected type is string."); + + std::string strFormId = GetStringFromNAPI(env, napiFormId); + int64_t formIdValue = std::stoll(strFormId); + + formIds.push_back(formIdValue); + } + + // get global value + napi_value global = nullptr; + napi_get_global(env, &global); + + // get ability + napi_value abilityObj = nullptr; + napi_get_named_property(env, global, "ability", &abilityObj); + + // get ability pointer + OHOS::AppExecFwk::Ability* ability = nullptr; + napi_get_value_external(env, abilityObj, (void**)&ability); + HILOG_INFO("%{public}s, ability = [%{public}p]", __func__, ability); + + AsyncNotifyInvisibleFormsCallbackInfo *asyncCallbackInfo = new + AsyncNotifyInvisibleFormsCallbackInfo { + .env = env, + .ability = ability, + .asyncWork = nullptr, + .deferred = nullptr, + .callback = nullptr, + .formIds = formIds, + .result = 1, + }; + + if (argc == ARGS_SIZE_TWO) { + HILOG_INFO("%{public}s, asyncCallback.", __func__); + + // Check the value type of the arguments + valueType = napi_undefined; + NAPI_CALL(env, napi_typeof(env, argv[1], &valueType)); + NAPI_ASSERT(env, valueType == napi_function, "The arguments[1] type of notifyInvisibleForms is incorrect,\ + expected type is function."); + + napi_create_reference(env, argv[1], 1, &asyncCallbackInfo->callback); + + napi_value resourceName; + napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName); + napi_create_async_work( + env, + nullptr, + resourceName, + [](napi_env env, void *data) { + HILOG_INFO("%{public}s, napi_create_async_work running", __func__); + + AsyncNotifyInvisibleFormsCallbackInfo *asyncCallbackInfo = + (AsyncNotifyInvisibleFormsCallbackInfo *)data; + + InnerNotifyInvisibleForms(env, asyncCallbackInfo); + }, + [](napi_env env, napi_status status, void *data) { + AsyncNotifyInvisibleFormsCallbackInfo *asyncCallbackInfo = + (AsyncNotifyInvisibleFormsCallbackInfo *)data; + + HILOG_INFO("%{public}s, napi_create_async_work complete", __func__); + + if (asyncCallbackInfo->callback != nullptr) { + napi_value result; + napi_create_int32(env, asyncCallbackInfo->result, &result); + napi_value callback; + napi_value undefined; + napi_get_undefined(env, &undefined); + napi_get_reference_value(env, asyncCallbackInfo->callback, &callback); + napi_value callResult; + napi_call_function(env, undefined, callback, 1, &result, &callResult); + napi_delete_reference(env, asyncCallbackInfo->callback); + } + napi_delete_async_work(env, asyncCallbackInfo->asyncWork); + delete asyncCallbackInfo; + }, + (void *)asyncCallbackInfo, + &asyncCallbackInfo->asyncWork); + NAPI_CALL(env, napi_queue_async_work(env, asyncCallbackInfo->asyncWork)); + + napi_value result; + NAPI_CALL(env, napi_create_int32(env, 1, &result)); + return result; + } else { + HILOG_INFO("%{public}s, promise.", __func__); + napi_deferred deferred; + napi_value promise; + NAPI_CALL(env, napi_create_promise(env, &deferred, &promise)); + asyncCallbackInfo->deferred = deferred; + + napi_value resourceName; + napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName); + napi_create_async_work( + env, + nullptr, + resourceName, + [](napi_env env, void *data) { + HILOG_INFO("%{public}s, promise runnning", __func__); + + AsyncNotifyInvisibleFormsCallbackInfo *asyncCallbackInfo = + (AsyncNotifyInvisibleFormsCallbackInfo *)data; + + InnerNotifyInvisibleForms(env, asyncCallbackInfo); + }, + [](napi_env env, napi_status status, void *data) { + HILOG_INFO("%{public}s, promise complete", __func__); + + AsyncNotifyInvisibleFormsCallbackInfo *asyncCallbackInfo = + (AsyncNotifyInvisibleFormsCallbackInfo *)data; + + napi_value result; + napi_create_int32(env, asyncCallbackInfo->result, &result); + napi_resolve_deferred(asyncCallbackInfo->env, asyncCallbackInfo->deferred, result); + napi_delete_async_work(env, asyncCallbackInfo->asyncWork); + delete asyncCallbackInfo; + }, + (void *)asyncCallbackInfo, + &asyncCallbackInfo->asyncWork); + napi_queue_async_work(env, asyncCallbackInfo->asyncWork); + return promise; + } +} + +/** + * @brief Call native kit function: EnableUpdateForm + * + * @param[in] env The environment that the Node-API call is invoked under + * @param[out] asyncCallbackInfo Reference, callback info via Node-API + * + * @return void + */ +static void InnerEnableFormsUpdate(napi_env env, AsyncEnableUpdateFormCallbackInfo* const asyncCallbackInfo) +{ + HILOG_DEBUG("%{public}s called.", __func__); + OHOS::AppExecFwk::Ability *ability = asyncCallbackInfo->ability; + bool ret = ability->EnableUpdateForm(asyncCallbackInfo->formIds); + if (ret) { + asyncCallbackInfo->result = 1; + } else { + asyncCallbackInfo->result = 0; + } + HILOG_DEBUG("%{public}s, end", __func__); +} + +/** + * @brief The implementation of Node-API interface: enableFormsUpdate + * + * @param[in] env The environment that the Node-API call is invoked under + * @param[out] info An opaque datatype that is passed to a callback function + * + * @return This is an opaque pointer that is used to represent a JavaScript value + */ +napi_value NAPI_EnableFormsUpdate(napi_env env, napi_callback_info info) +{ + HILOG_INFO("%{public}s called.", __func__); + + // Check the number of the arguments + size_t argc = ARGS_SIZE_TWO; + napi_value argv[ARGS_SIZE_TWO] = {nullptr}; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr)); + if (argc > ARGS_SIZE_TWO) { + HILOG_ERROR("%{public}s, wrong number of arguments.", __func__); + return nullptr; + } + HILOG_INFO("%{public}s, argc = [%{public}zu]", __func__, argc); + + uint32_t arrayLength = 0; + NAPI_CALL(env, napi_get_array_length(env, argv[0], &arrayLength)); + NAPI_ASSERT(env, arrayLength > 0, "The arguments[0] value of enableFormsUpdate \ + is incorrect, this array is empty."); + + std::vector formIds; + formIds.clear(); + napi_valuetype valueType; + for (size_t i = 0; i < arrayLength; i++) { + napi_value napiFormId; + napi_get_element(env, argv[0], i, &napiFormId); + + // Check the value type of the arguments + valueType = napi_undefined; + NAPI_CALL(env, napi_typeof(env, napiFormId, &valueType)); + NAPI_ASSERT(env, valueType == napi_string, "The arguments[0] value type of enableFormsUpdate \ + is incorrect, expected type is string."); + + std::string strFormId = GetStringFromNAPI(env, napiFormId); + int64_t formIdValue = std::stoll(strFormId); + + formIds.push_back(formIdValue); + } + + // get global value + napi_value global = nullptr; + napi_get_global(env, &global); + + // get ability + napi_value abilityObj = nullptr; + napi_get_named_property(env, global, "ability", &abilityObj); + + // get ability pointer + OHOS::AppExecFwk::Ability* ability = nullptr; + napi_get_value_external(env, abilityObj, (void**)&ability); + HILOG_INFO("%{public}s, ability = [%{public}p]", __func__, ability); + + AsyncEnableUpdateFormCallbackInfo *asyncCallbackInfo = new + AsyncEnableUpdateFormCallbackInfo { + .env = env, + .ability = ability, + .asyncWork = nullptr, + .deferred = nullptr, + .callback = nullptr, + .formIds = formIds, + .result = 0, + }; + + if (argc == ARGS_SIZE_TWO) { + HILOG_INFO("%{public}s, asyncCallback.", __func__); + + // Check the value type of the arguments + valueType = napi_undefined; + NAPI_CALL(env, napi_typeof(env, argv[1], &valueType)); + NAPI_ASSERT(env, valueType == napi_function, "The arguments[1] type of enableFormsUpdate \ + is incorrect, expected type is function."); + + napi_create_reference(env, argv[1], 1, &asyncCallbackInfo->callback); + + napi_value resourceName; + napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName); + napi_create_async_work( + env, + nullptr, + resourceName, + [](napi_env env, void *data) { + HILOG_INFO("%{public}s, napi_create_async_work running", __func__); + + AsyncEnableUpdateFormCallbackInfo *asyncCallbackInfo = + (AsyncEnableUpdateFormCallbackInfo *)data; + + InnerEnableFormsUpdate(env, asyncCallbackInfo); + }, + [](napi_env env, napi_status status, void *data) { + AsyncEnableUpdateFormCallbackInfo *asyncCallbackInfo = + (AsyncEnableUpdateFormCallbackInfo *)data; + + HILOG_INFO("%{public}s, napi_create_async_work complete", __func__); + + if (asyncCallbackInfo->callback != nullptr) { + napi_value result; + napi_create_int32(env, asyncCallbackInfo->result, &result); + napi_value callback; + napi_value undefined; + napi_get_undefined(env, &undefined); + napi_get_reference_value(env, asyncCallbackInfo->callback, &callback); + napi_value callResult; + napi_call_function(env, undefined, callback, 1, &result, &callResult); + napi_delete_reference(env, asyncCallbackInfo->callback); + } + napi_delete_async_work(env, asyncCallbackInfo->asyncWork); + delete asyncCallbackInfo; + }, + (void *)asyncCallbackInfo, + &asyncCallbackInfo->asyncWork); + NAPI_CALL(env, napi_queue_async_work(env, asyncCallbackInfo->asyncWork)); + + napi_value result; + NAPI_CALL(env, napi_create_int32(env, 1, &result)); + return result; + } else { + HILOG_INFO("%{public}s, promise.", __func__); + napi_deferred deferred; + napi_value promise; + NAPI_CALL(env, napi_create_promise(env, &deferred, &promise)); + asyncCallbackInfo->deferred = deferred; + + napi_value resourceName; + napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName); + napi_create_async_work( + env, + nullptr, + resourceName, + [](napi_env env, void *data) { + HILOG_INFO("%{public}s, promise runnning", __func__); + AsyncEnableUpdateFormCallbackInfo *asyncCallbackInfo = + (AsyncEnableUpdateFormCallbackInfo *)data; + + InnerEnableFormsUpdate(env, asyncCallbackInfo); + }, + [](napi_env env, napi_status status, void *data) { + HILOG_INFO("%{public}s, promise complete", __func__); + + AsyncEnableUpdateFormCallbackInfo *asyncCallbackInfo = + (AsyncEnableUpdateFormCallbackInfo *)data; + + napi_value result; + napi_create_int32(env, asyncCallbackInfo->result, &result); + napi_resolve_deferred(asyncCallbackInfo->env, asyncCallbackInfo->deferred, result); + napi_delete_async_work(env, asyncCallbackInfo->asyncWork); + delete asyncCallbackInfo; + }, + (void *)asyncCallbackInfo, + &asyncCallbackInfo->asyncWork); + napi_queue_async_work(env, asyncCallbackInfo->asyncWork); + return promise; + } +} + +/** + * @brief Call native kit function: DisableUpdateForm + * + * @param[in] env The environment that the Node-API call is invoked under + * @param[out] asyncCallbackInfo Reference, callback info via Node-API + * + * @return void + */ +static void InnerDisableFormsUpdate(napi_env env, AsyncDisableUpdateFormCallbackInfo* const asyncCallbackInfo) +{ + HILOG_DEBUG("%{public}s called.", __func__); + OHOS::AppExecFwk::Ability *ability = asyncCallbackInfo->ability; + bool ret = ability->DisableUpdateForm(asyncCallbackInfo->formIds); + if (ret) { + asyncCallbackInfo->result = 1; + } else { + asyncCallbackInfo->result = 0; + } + HILOG_DEBUG("%{public}s, end", __func__); +} + +/** + * @brief The implementation of Node-API interface: disableFormsUpdate + * + * @param[in] env The environment that the Node-API call is invoked under + * @param[out] info An opaque datatype that is passed to a callback function + * + * @return This is an opaque pointer that is used to represent a JavaScript value + */ +napi_value NAPI_DisableFormsUpdate(napi_env env, napi_callback_info info) +{ + HILOG_INFO("%{public}s called.", __func__); + + // Check the number of the arguments + size_t argc = ARGS_SIZE_TWO; + napi_value argv[ARGS_SIZE_TWO] = {nullptr}; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr)); + if (argc > ARGS_SIZE_TWO) { + HILOG_ERROR("%{public}s, wrong number of arguments.", __func__); + return nullptr; + } + HILOG_INFO("%{public}s, argc = [%{public}zu]", __func__, argc); + + uint32_t arrayLength = 0; + NAPI_CALL(env, napi_get_array_length(env, argv[0], &arrayLength)); + NAPI_ASSERT(env, arrayLength > 0, "The arguments[0] value of disableFormsUpdate \ + is incorrect, this array is empty."); + + std::vector formIds; + formIds.clear(); + napi_valuetype valueType; + for (size_t i = 0; i < arrayLength; i++) { + napi_value napiFormId; + napi_get_element(env, argv[0], i, &napiFormId); + + // Check the value type of the arguments + valueType = napi_undefined; + NAPI_CALL(env, napi_typeof(env, napiFormId, &valueType)); + NAPI_ASSERT(env, valueType == napi_string, "The arguments[0] value type of disableFormsUpdate \ + is incorrect, expected type is string."); + + std::string strFormId = GetStringFromNAPI(env, napiFormId); + int64_t formIdValue = std::stoll(strFormId); + + formIds.push_back(formIdValue); + } + + // get global value + napi_value global = nullptr; + napi_get_global(env, &global); + + // get ability + napi_value abilityObj = nullptr; + napi_get_named_property(env, global, "ability", &abilityObj); + + // get ability pointer + OHOS::AppExecFwk::Ability* ability = nullptr; + napi_get_value_external(env, abilityObj, (void**)&ability); + HILOG_INFO("%{public}s, ability = [%{public}p]", __func__, ability); + + AsyncDisableUpdateFormCallbackInfo *asyncCallbackInfo = new + AsyncDisableUpdateFormCallbackInfo { + .env = env, + .ability = ability, + .asyncWork = nullptr, + .deferred = nullptr, + .callback = nullptr, + .formIds = formIds, + .result = 0, + }; + + if (argc == ARGS_SIZE_TWO) { + HILOG_INFO("%{public}s, asyncCallback.", __func__); + + // Check the value type of the arguments + valueType = napi_undefined; + NAPI_CALL(env, napi_typeof(env, argv[1], &valueType)); + NAPI_ASSERT(env, valueType == napi_function, "The arguments[1] type of disableFormsUpdate \ + is incorrect, expected type is function."); + + napi_create_reference(env, argv[1], 1, &asyncCallbackInfo->callback); + + napi_value resourceName; + napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName); + napi_create_async_work( + env, + nullptr, + resourceName, + [](napi_env env, void *data) { + HILOG_INFO("%{public}s, napi_create_async_work running", __func__); + + AsyncDisableUpdateFormCallbackInfo *asyncCallbackInfo = + (AsyncDisableUpdateFormCallbackInfo *)data; + + InnerDisableFormsUpdate(env, asyncCallbackInfo); + }, + [](napi_env env, napi_status status, void *data) { + AsyncDisableUpdateFormCallbackInfo *asyncCallbackInfo = + (AsyncDisableUpdateFormCallbackInfo *)data; + + HILOG_INFO("%{public}s, napi_create_async_work complete", __func__); + + if (asyncCallbackInfo->callback != nullptr) { + napi_value result; + napi_create_int32(env, asyncCallbackInfo->result, &result); + napi_value callback; + napi_value undefined; + napi_get_undefined(env, &undefined); + napi_get_reference_value(env, asyncCallbackInfo->callback, &callback); + napi_value callResult; + napi_call_function(env, undefined, callback, 1, &result, &callResult); + napi_delete_reference(env, asyncCallbackInfo->callback); + } + napi_delete_async_work(env, asyncCallbackInfo->asyncWork); + delete asyncCallbackInfo; + }, + (void *)asyncCallbackInfo, + &asyncCallbackInfo->asyncWork); + NAPI_CALL(env, napi_queue_async_work(env, asyncCallbackInfo->asyncWork)); + + napi_value result; + NAPI_CALL(env, napi_create_int32(env, 1, &result)); + return result; + } else { + HILOG_INFO("%{public}s, promise.", __func__); + napi_deferred deferred; + napi_value promise; + NAPI_CALL(env, napi_create_promise(env, &deferred, &promise)); + asyncCallbackInfo->deferred = deferred; + + napi_value resourceName; + napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName); + napi_create_async_work( + env, + nullptr, + resourceName, + [](napi_env env, void *data) { + HILOG_INFO("%{public}s, promise runnning", __func__); + + AsyncDisableUpdateFormCallbackInfo *asyncCallbackInfo = + (AsyncDisableUpdateFormCallbackInfo *)data; + + InnerDisableFormsUpdate(env, asyncCallbackInfo); + }, + [](napi_env env, napi_status status, void *data) { + HILOG_INFO("%{public}s, promise complete", __func__); + + AsyncDisableUpdateFormCallbackInfo *asyncCallbackInfo = + (AsyncDisableUpdateFormCallbackInfo *)data; + + napi_value result; + napi_create_int32(env, asyncCallbackInfo->result, &result); + napi_resolve_deferred(asyncCallbackInfo->env, asyncCallbackInfo->deferred, result); + napi_delete_async_work(env, asyncCallbackInfo->asyncWork); + delete asyncCallbackInfo; + }, + (void *)asyncCallbackInfo, + &asyncCallbackInfo->asyncWork); + napi_queue_async_work(env, asyncCallbackInfo->asyncWork); + return promise; + } +} + +/** + * @brief Call native kit function: CheckFMSReady + * + * @param[in] env The environment that the Node-API call is invoked under + * @param[out] asyncCallbackInfo Reference, callback info via Node-API + * + * @return void + */ +static void InnerCheckFMSReady(napi_env env, AsyncCheckFMSReadyCallbackInfo* const asyncCallbackInfo) +{ + HILOG_DEBUG("%{public}s called.", __func__); + OHOS::AppExecFwk::Ability *ability = asyncCallbackInfo->ability; + asyncCallbackInfo->isFMSReady = ability->CheckFMSReady(); + HILOG_DEBUG("%{public}s, end", __func__); +} + +/** + * @brief The implementation of Node-API interface: checkFMSReady + * + * @param[in] env The environment that the Node-API call is invoked under + * @param[out] info An opaque datatype that is passed to a callback function + * + * @return This is an opaque pointer that is used to represent a JavaScript value + */ +napi_value NAPI_CheckFMSReady(napi_env env, napi_callback_info info) +{ + HILOG_INFO("%{public}s called.", __func__); + + // Check the number of the arguments + size_t argc = ARGS_SIZE_ONE; + napi_value argv[ARGS_SIZE_ONE] = {nullptr}; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr)); + if (argc > ARGS_SIZE_ONE) { + HILOG_ERROR("%{public}s, wrong number of arguments.", __func__); + return nullptr; + } + HILOG_INFO("%{public}s, argc = [%{public}zu]", __func__, argc); + + // get global value + napi_value global = nullptr; + napi_get_global(env, &global); + + // get ability + napi_value abilityObj = nullptr; + napi_get_named_property(env, global, "ability", &abilityObj); + + // get ability pointer + OHOS::AppExecFwk::Ability* ability = nullptr; + napi_get_value_external(env, abilityObj, (void**)&ability); + HILOG_INFO("%{public}s, ability = [%{public}p]", __func__, ability); + + AsyncCheckFMSReadyCallbackInfo *asyncCallbackInfo = new + AsyncCheckFMSReadyCallbackInfo { + .env = env, + .ability = ability, + .asyncWork = nullptr, + .deferred = nullptr, + .callback = nullptr, + .isFMSReady = false, + }; + + if (argc == ARGS_SIZE_ONE) { + HILOG_INFO("%{public}s, asyncCallback.", __func__); + + // Check the value type of the arguments + napi_valuetype valueType; + NAPI_CALL(env, napi_typeof(env, argv[0], &valueType)); + NAPI_ASSERT(env, valueType == napi_function, "The arguments[0] type of checkFMSReady is incorrect,\ + expected type is function."); + + napi_create_reference(env, argv[0], 1, &asyncCallbackInfo->callback); + napi_value resourceName; + napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName); + napi_create_async_work( + env, + nullptr, + resourceName, + [](napi_env env, void *data) { + HILOG_INFO("%{public}s, napi_create_async_work running", __func__); + + AsyncCheckFMSReadyCallbackInfo *asyncCallbackInfo = + (AsyncCheckFMSReadyCallbackInfo *)data; + + InnerCheckFMSReady(env, asyncCallbackInfo); + }, + [](napi_env env, napi_status status, void *data) { + HILOG_INFO("%{public}s, napi_create_async_work complete", __func__); + + AsyncCheckFMSReadyCallbackInfo *asyncCallbackInfo = + (AsyncCheckFMSReadyCallbackInfo *)data; + + if (asyncCallbackInfo->callback != nullptr) { + napi_value isFMSReadyResult; + napi_create_int32(env, asyncCallbackInfo->isFMSReady, &isFMSReadyResult); + napi_value callback; + napi_get_reference_value(env, asyncCallbackInfo->callback, &callback); + napi_value callResult; + napi_call_function(env, nullptr, callback, 1, &isFMSReadyResult, &callResult); + napi_delete_reference(env, asyncCallbackInfo->callback); + } + napi_delete_async_work(env, asyncCallbackInfo->asyncWork); + delete asyncCallbackInfo; + }, + (void *)asyncCallbackInfo, + &asyncCallbackInfo->asyncWork); + NAPI_CALL(env, napi_queue_async_work(env, asyncCallbackInfo->asyncWork)); + + napi_value result; + NAPI_CALL(env, napi_create_int32(env, 1, &result)); + return result; + } else { + HILOG_INFO("%{public}s, promise.", __func__); + napi_deferred deferred; + napi_value promise; + NAPI_CALL(env, napi_create_promise(env, &deferred, &promise)); + asyncCallbackInfo->deferred = deferred; + + napi_value resourceName; + napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName); + napi_create_async_work( + env, + nullptr, + resourceName, + [](napi_env env, void *data) { + HILOG_INFO("%{public}s, promise runnning", __func__); + + AsyncCheckFMSReadyCallbackInfo *asyncCallbackInfo = + (AsyncCheckFMSReadyCallbackInfo *)data; + + InnerCheckFMSReady(env, asyncCallbackInfo); + }, + [](napi_env env, napi_status status, void *data) { + HILOG_INFO("%{public}s, promise complete", __func__); + + AsyncCheckFMSReadyCallbackInfo *asyncCallbackInfo = + (AsyncCheckFMSReadyCallbackInfo *)data; + + napi_value result; + napi_create_int32(env, asyncCallbackInfo->isFMSReady, &result); + napi_resolve_deferred(asyncCallbackInfo->env, asyncCallbackInfo->deferred, result); + napi_delete_async_work(env, asyncCallbackInfo->asyncWork); + delete asyncCallbackInfo; + }, + (void *)asyncCallbackInfo, + &asyncCallbackInfo->asyncWork); + napi_queue_async_work(env, asyncCallbackInfo->asyncWork); + return promise; + } +} + +/** + * @brief Call native kit function: GetAllFormsInfo + * + * @param[in] env The environment that the Node-API call is invoked under + * @param[out] asyncCallbackInfo Reference, callback info via Node-API + * + * @return void + */ +static void InnerGetAllFormsInfo(napi_env env, AsyncGetAllFormsCallbackInfo* const asyncCallbackInfo) +{ + HILOG_DEBUG("%{public}s called.", __func__); + OHOS::AppExecFwk::Ability *ability = asyncCallbackInfo->ability; + bool ret = ability->GetAllFormsInfo(asyncCallbackInfo->formInfos); + if (ret) { + asyncCallbackInfo->result = 1; + } else { + asyncCallbackInfo->result = 0; + } + HILOG_DEBUG("%{public}s, end", __func__); +} + +/** + * @brief The implementation of Node-API interface: getAllFormsInfo + * + * @param[in] env The environment that the Node-API call is invoked under + * @param[out] info An opaque datatype that is passed to a callback function + * + * @return This is an opaque pointer that is used to represent a JavaScript value + */ +napi_value NAPI_GetAllFormsInfo(napi_env env, napi_callback_info info) +{ + HILOG_INFO("%{public}s called.", __func__); + + // Check the number of the arguments + size_t argc = ARGS_SIZE_ONE; + napi_value argv[ARGS_SIZE_ONE] = {nullptr}; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr)); + if (argc > ARGS_SIZE_ONE) { + HILOG_ERROR("%{public}s, wrong number of arguments.", __func__); + return nullptr; + } + HILOG_INFO("%{public}s, argc = [%{public}zu]", __func__, argc); + + std::vector formInfos; + formInfos.clear(); + + // get global value + napi_value global = nullptr; + napi_get_global(env, &global); + + // get ability + napi_value abilityObj = nullptr; + napi_get_named_property(env, global, "ability", &abilityObj); + + // get ability pointer + OHOS::AppExecFwk::Ability* ability = nullptr; + napi_get_value_external(env, abilityObj, (void**)&ability); + HILOG_INFO("%{public}s, ability = [%{public}p]", __func__, ability); + + AsyncGetAllFormsCallbackInfo *asyncCallbackInfo = new + AsyncGetAllFormsCallbackInfo { + .env = env, + .ability = ability, + .asyncWork = nullptr, + .deferred = nullptr, + .callback = nullptr, + .formInfos = formInfos, + .result = 0, + }; + + if (argc == ARGS_SIZE_ONE) { + HILOG_INFO("%{public}s, asyncCallback.", __func__); + + // Check the value type of the arguments + napi_valuetype valueType; + NAPI_CALL(env, napi_typeof(env, argv[0], &valueType)); + NAPI_ASSERT(env, valueType == napi_function, "The arguments[0] type of getAllFormsInfo is incorrect,\ + expected type is function."); + + napi_create_reference(env, argv[0], 1, &asyncCallbackInfo->callback); + napi_value resourceName; + napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName); + napi_create_async_work( + env, + nullptr, + resourceName, + [](napi_env env, void *data) { + HILOG_INFO("%{public}s, napi_create_async_work running", __func__); + + AsyncGetAllFormsCallbackInfo *asyncCallbackInfo = + (AsyncGetAllFormsCallbackInfo *)data; + + InnerGetAllFormsInfo(env, asyncCallbackInfo); + }, + [](napi_env env, napi_status status, void *data) { + HILOG_INFO("%{public}s, napi_create_async_work complete", __func__); + + AsyncGetAllFormsCallbackInfo *asyncCallbackInfo = + (AsyncGetAllFormsCallbackInfo *)data; + + napi_value arrayFormInfos; + napi_create_array(env, &arrayFormInfos); + if (asyncCallbackInfo->result) { + int iFormInfoCount = 0; + for (auto formInfo : asyncCallbackInfo->formInfos) { + napi_value formInfoObject = nullptr; + napi_create_object(env, &formInfoObject); + ParseFormInfoIntoNapi(env, formInfo, formInfoObject); + napi_set_element(env, arrayFormInfos, iFormInfoCount, formInfoObject); + ++iFormInfoCount; + } + } + + if (asyncCallbackInfo->callback != nullptr) { + napi_value callbackValues[2] = {0}; + napi_value callback; + napi_value resultCode; + napi_create_int32(env, asyncCallbackInfo->result, &resultCode); + callbackValues[0] = resultCode; + callbackValues[1] = arrayFormInfos; + napi_get_reference_value(env, asyncCallbackInfo->callback, &callback); + napi_value callResult; + napi_call_function(env, nullptr, callback, 2, callbackValues, &callResult); + napi_delete_reference(env, asyncCallbackInfo->callback); + } + napi_delete_async_work(env, asyncCallbackInfo->asyncWork); + delete asyncCallbackInfo; + }, + (void *)asyncCallbackInfo, + &asyncCallbackInfo->asyncWork); + NAPI_CALL(env, napi_queue_async_work(env, asyncCallbackInfo->asyncWork)); + napi_value result; + NAPI_CALL(env, napi_create_int32(env, 1, &result)); + return result; + } else { + HILOG_INFO("%{public}s, promise.", __func__); + napi_deferred deferred; + napi_value promise; + NAPI_CALL(env, napi_create_promise(env, &deferred, &promise)); + asyncCallbackInfo->deferred = deferred; + + napi_value resourceName; + napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName); + napi_create_async_work( + env, + nullptr, + resourceName, + [](napi_env env, void *data) { + HILOG_INFO("%{public}s, promise runnning", __func__); + + AsyncGetAllFormsCallbackInfo *asyncCallbackInfo = + (AsyncGetAllFormsCallbackInfo *)data; + + InnerGetAllFormsInfo(env, asyncCallbackInfo); + }, + [](napi_env env, napi_status status, void *data) { + HILOG_INFO("%{public}s, promise complete", __func__); + + AsyncGetAllFormsCallbackInfo *asyncCallbackInfo = + (AsyncGetAllFormsCallbackInfo *)data; + + napi_value arrayFormInfos; + napi_create_array(env, &arrayFormInfos); + if (asyncCallbackInfo->result) { + int iFormInfoCount = 0; + for (auto formInfo : asyncCallbackInfo->formInfos) { + napi_value formInfoObject = nullptr; + napi_create_object(env, &formInfoObject); + ParseFormInfoIntoNapi(env, formInfo, formInfoObject); + napi_set_element(env, arrayFormInfos, iFormInfoCount, formInfoObject); + ++iFormInfoCount; + } + } + napi_resolve_deferred(asyncCallbackInfo->env, asyncCallbackInfo->deferred, arrayFormInfos); + napi_delete_async_work(env, asyncCallbackInfo->asyncWork); + delete asyncCallbackInfo; + }, + (void *)asyncCallbackInfo, + &asyncCallbackInfo->asyncWork); + napi_queue_async_work(env, asyncCallbackInfo->asyncWork); + return promise; + } +} + +/** + * @brief Call native kit function: GetFormsInfoByApp + * + * @param[in] env The environment that the Node-API call is invoked under + * @param[out] asyncCallbackInfo Reference, callback info via Node-API + * + * @return void + */ +static void InnerGetFormsInfoByApp(napi_env env, AsyncGetFormsInfoByAppCallbackInfo* const asyncCallbackInfo) +{ + HILOG_DEBUG("%{public}s called.", __func__); + OHOS::AppExecFwk::Ability *ability = asyncCallbackInfo->ability; + bool ret = ability->GetFormsInfoByApp( + asyncCallbackInfo->bundleName, + asyncCallbackInfo->formInfos); + if (ret) { + asyncCallbackInfo->result = 1; + } else { + asyncCallbackInfo->result = 0; + } + HILOG_DEBUG("%{public}s, end", __func__); +} + +/** + * @brief The implementation of Node-API interface: getFormsInfoByApp + * + * @param[in] env The environment that the Node-API call is invoked under + * @param[out] info An opaque datatype that is passed to a callback function + * + * @return This is an opaque pointer that is used to represent a JavaScript value + */ +napi_value NAPI_GetFormsInfoByApp(napi_env env, napi_callback_info info) +{ + HILOG_INFO("%{public}s called.", __func__); + + // Check the number of the arguments + size_t argc = ARGS_SIZE_TWO; + napi_value argv[ARGS_SIZE_TWO] = {nullptr}; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr)); + if (argc > ARGS_SIZE_TWO) { + HILOG_ERROR("%{public}s, wrong number of arguments.", __func__); + return nullptr; + } + HILOG_INFO("%{public}s, argc = [%{public}zu]", __func__, argc); + + // Check the value type of the arguments + napi_valuetype valueType; + NAPI_CALL(env, napi_typeof(env, argv[0], &valueType)); + NAPI_ASSERT(env, valueType == napi_string, "The arguments[0] type of getFormsInfoByApp is incorrect,\ + expected type is string."); + + std::string bundleNameInfo = GetStringFromNAPI(env, argv[0]); + HILOG_INFO("%{public}s, bundleName=%{public}s.", __func__, bundleNameInfo.c_str()); + + std::vector formInfos; + formInfos.clear(); + + // get global value + napi_value global = nullptr; + napi_get_global(env, &global); + + // get ability + napi_value abilityObj = nullptr; + napi_get_named_property(env, global, "ability", &abilityObj); + + // get ability pointer + OHOS::AppExecFwk::Ability* ability = nullptr; + napi_get_value_external(env, abilityObj, (void**)&ability); + HILOG_INFO("%{public}s, ability = [%{public}p]", __func__, ability); + + AsyncGetFormsInfoByAppCallbackInfo *asyncCallbackInfo = new + AsyncGetFormsInfoByAppCallbackInfo { + .env = env, + .ability = ability, + .asyncWork = nullptr, + .deferred = nullptr, + .callback = nullptr, + .formInfos = formInfos, + .bundleName = bundleNameInfo, + .result = 0, + }; + + if (argc == ARGS_SIZE_TWO) { + HILOG_INFO("%{public}s, asyncCallback.", __func__); + + // Check the value type of the arguments + valueType = napi_undefined; + NAPI_CALL(env, napi_typeof(env, argv[1], &valueType)); + NAPI_ASSERT(env, valueType == napi_function, "The arguments[1] type of getFormsInfoByApp is incorrect,\ + expected type is function."); + + napi_create_reference(env, argv[1], 1, &asyncCallbackInfo->callback); + napi_value resourceName; + napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName); + napi_create_async_work( + env, + nullptr, + resourceName, + [](napi_env env, void *data) { + HILOG_INFO("%{public}s, napi_create_async_work running", __func__); + + AsyncGetFormsInfoByAppCallbackInfo *asyncCallbackInfo = + (AsyncGetFormsInfoByAppCallbackInfo *)data; + + InnerGetFormsInfoByApp(env, asyncCallbackInfo); + }, + [](napi_env env, napi_status status, void *data) { + HILOG_INFO("%{public}s, napi_create_async_work complete", __func__); + + AsyncGetFormsInfoByAppCallbackInfo *asyncCallbackInfo = + (AsyncGetFormsInfoByAppCallbackInfo *)data; + + napi_value arrayFormInfos; + napi_create_array(env, &arrayFormInfos); + if (asyncCallbackInfo->result) { + int iFormInfoCount = 0; + for (auto formInfo : asyncCallbackInfo->formInfos) { + napi_value formInfoObject = nullptr; + napi_create_object(env, &formInfoObject); + ParseFormInfoIntoNapi(env, formInfo, formInfoObject); + napi_set_element(env, arrayFormInfos, iFormInfoCount, formInfoObject); + ++iFormInfoCount; + } + } + if (asyncCallbackInfo->callback != nullptr) { + napi_value callbackValues[2] = {0}; + napi_value callback; + napi_value resultCode; + napi_create_int32(env, asyncCallbackInfo->result, &resultCode); + callbackValues[0] = resultCode; + callbackValues[1] = arrayFormInfos; + napi_get_reference_value(env, asyncCallbackInfo->callback, &callback); + napi_value callResult; + napi_call_function(env, nullptr, callback, 2, callbackValues, &callResult); + napi_delete_reference(env, asyncCallbackInfo->callback); + } + napi_delete_async_work(env, asyncCallbackInfo->asyncWork); + delete asyncCallbackInfo; + }, + (void *)asyncCallbackInfo, + &asyncCallbackInfo->asyncWork); + NAPI_CALL(env, napi_queue_async_work(env, asyncCallbackInfo->asyncWork)); + + napi_value result; + NAPI_CALL(env, napi_create_int32(env, 1, &result)); + return result; + } else { + HILOG_INFO("%{public}s, promise.", __func__); + napi_deferred deferred; + napi_value promise; + NAPI_CALL(env, napi_create_promise(env, &deferred, &promise)); + asyncCallbackInfo->deferred = deferred; + + napi_value resourceName; + napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName); + napi_create_async_work( + env, + nullptr, + resourceName, + [](napi_env env, void *data) { + HILOG_INFO("%{public}s, promise runnning", __func__); + + AsyncGetFormsInfoByAppCallbackInfo *asyncCallbackInfo = + (AsyncGetFormsInfoByAppCallbackInfo *)data; + + InnerGetFormsInfoByApp(env, asyncCallbackInfo); + }, + [](napi_env env, napi_status status, void *data) { + HILOG_INFO("%{public}s, promise complete", __func__); + + AsyncGetFormsInfoByAppCallbackInfo *asyncCallbackInfo = + (AsyncGetFormsInfoByAppCallbackInfo *)data; + + napi_value arrayFormInfos; + napi_create_array(env, &arrayFormInfos); + if (asyncCallbackInfo->result) { + int iFormInfoCount = 0; + for (auto formInfo : asyncCallbackInfo->formInfos) { + napi_value formInfoObject = nullptr; + napi_create_object(env, &formInfoObject); + ParseFormInfoIntoNapi(env, formInfo, formInfoObject); + napi_set_element(env, arrayFormInfos, iFormInfoCount, formInfoObject); + ++iFormInfoCount; + } + } + napi_resolve_deferred(asyncCallbackInfo->env, asyncCallbackInfo->deferred, arrayFormInfos); + napi_delete_async_work(env, asyncCallbackInfo->asyncWork); + delete asyncCallbackInfo; + }, + (void *)asyncCallbackInfo, + &asyncCallbackInfo->asyncWork); + napi_queue_async_work(env, asyncCallbackInfo->asyncWork); + return promise; + } +} + +/** + * @brief Call native kit function: GetFormsInfoByModule + * + * @param[in] env The environment that the Node-API call is invoked under + * @param[out] asyncCallbackInfo Reference, callback info via Node-API + * + * @return void + */ +static void InnerGetFormsInfoByModule(napi_env env, AsyncGetFormsInfoByModuleCallbackInfo* const asyncCallbackInfo) +{ + HILOG_DEBUG("%{public}s called.", __func__); + OHOS::AppExecFwk::Ability *ability = asyncCallbackInfo->ability; + + bool ret = ability->GetFormsInfoByModule( + asyncCallbackInfo->bundleName, + asyncCallbackInfo->moduleName, + asyncCallbackInfo->formInfos); + + if (ret) { + asyncCallbackInfo->result = 1; + } else { + asyncCallbackInfo->result = 0; + } + HILOG_DEBUG("%{public}s, end", __func__); +} + +/** + * @brief The implementation of Node-API interface: getFormsInfoByModule + * + * @param[in] env The environment that the Node-API call is invoked under + * @param[out] info An opaque datatype that is passed to a callback function + * + * @return This is an opaque pointer that is used to represent a JavaScript value + */ +napi_value NAPI_GetFormsInfoByModule(napi_env env, napi_callback_info info) +{ + HILOG_INFO("%{public}s called.", __func__); + + // Check the number of the arguments + size_t argc = ARGS_SIZE_THREE; + napi_value argv[ARGS_SIZE_THREE] = {nullptr}; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr)); + if (argc > ARGS_SIZE_THREE) { + HILOG_ERROR("%{public}s, wrong number of arguments.", __func__); + return nullptr; + } + HILOG_INFO("%{public}s, argc = [%{public}zu]", __func__, argc); + + // Check the value type of the arguments + napi_valuetype valueType; + NAPI_CALL(env, napi_typeof(env, argv[0], &valueType)); + NAPI_ASSERT(env, valueType == napi_string, "The arguments[0] type of getFormsInfoByModule is incorrect,\ + expected type is string."); + + std::string bundleNameInfo = GetStringFromNAPI(env, argv[0]); + HILOG_INFO("%{public}s, bundleName=%{public}s.", __func__, bundleNameInfo.c_str()); + + valueType = napi_undefined; + NAPI_CALL(env, napi_typeof(env, argv[1], &valueType)); + NAPI_ASSERT(env, valueType == napi_string, "The arguments[1] type of getFormsInfoByModule is incorrect,\ + expected type is string."); + + std::string moduleNameInfo = GetStringFromNAPI(env, argv[1]); + HILOG_INFO("%{public}s, moduleName=%{public}s.", __func__, moduleNameInfo.c_str()); + + std::vector formInfos; + formInfos.clear(); + + // get global value + napi_value global = nullptr; + napi_get_global(env, &global); + + // get ability + napi_value abilityObj = nullptr; + napi_get_named_property(env, global, "ability", &abilityObj); + + // get ability pointer + OHOS::AppExecFwk::Ability* ability = nullptr; + napi_get_value_external(env, abilityObj, (void**)&ability); + HILOG_INFO("%{public}s, ability = [%{public}p]", __func__, ability); + + AsyncGetFormsInfoByModuleCallbackInfo *asyncCallbackInfo = new + AsyncGetFormsInfoByModuleCallbackInfo { + .env = env, + .ability = ability, + .asyncWork = nullptr, + .deferred = nullptr, + .callback = nullptr, + .formInfos = formInfos, + .bundleName = bundleNameInfo, + .moduleName = moduleNameInfo, + .result = 0, + }; + + if (argc == ARGS_SIZE_THREE) { + HILOG_INFO("%{public}s, asyncCallback.", __func__); + + // Check the value type of the arguments + valueType = napi_undefined; + NAPI_CALL(env, napi_typeof(env, argv[2], &valueType)); + NAPI_ASSERT(env, valueType == napi_function, "The arguments[2] type of getFormsInfoByModule \ + is incorrect, expected type is function."); + + napi_create_reference(env, argv[2], 1, &asyncCallbackInfo->callback); + napi_value resourceName; + napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName); + napi_create_async_work( + env, + nullptr, + resourceName, + [](napi_env env, void *data) { + HILOG_INFO("%{public}s, napi_create_async_work running", __func__); + + AsyncGetFormsInfoByModuleCallbackInfo *asyncCallbackInfo = + (AsyncGetFormsInfoByModuleCallbackInfo *)data; + + InnerGetFormsInfoByModule(env, asyncCallbackInfo); + }, + [](napi_env env, napi_status status, void *data) { + HILOG_INFO("%{public}s, napi_create_async_work complete", __func__); + + AsyncGetFormsInfoByModuleCallbackInfo *asyncCallbackInfo = + (AsyncGetFormsInfoByModuleCallbackInfo *)data; + + napi_value arrayFormInfos; + napi_create_array(env, &arrayFormInfos); + if (asyncCallbackInfo->result) { + int iFormInfoCount = 0; + for (auto formInfo : asyncCallbackInfo->formInfos) { + napi_value formInfoObject = nullptr; + napi_create_object(env, &formInfoObject); + ParseFormInfoIntoNapi(env, formInfo, formInfoObject); + napi_set_element(env, arrayFormInfos, iFormInfoCount, formInfoObject); + ++iFormInfoCount; + } + } + if (asyncCallbackInfo->callback != nullptr) { + napi_value callbackValues[2] = {0}; + napi_value callback; + napi_value resultCode; + napi_create_int32(env, asyncCallbackInfo->result, &resultCode); + callbackValues[0] = resultCode; + callbackValues[1] = arrayFormInfos; + napi_get_reference_value(env, asyncCallbackInfo->callback, &callback); + napi_value callResult; + napi_call_function(env, nullptr, callback, 2, callbackValues, &callResult); + napi_delete_reference(env, asyncCallbackInfo->callback); + } + napi_delete_async_work(env, asyncCallbackInfo->asyncWork); + delete asyncCallbackInfo; + }, + (void *)asyncCallbackInfo, + &asyncCallbackInfo->asyncWork); + NAPI_CALL(env, napi_queue_async_work(env, asyncCallbackInfo->asyncWork)); + + napi_value result; + NAPI_CALL(env, napi_create_int32(env, 1, &result)); + return result; + } else { + HILOG_INFO("%{public}s, promise.", __func__); + napi_deferred deferred; + napi_value promise; + NAPI_CALL(env, napi_create_promise(env, &deferred, &promise)); + asyncCallbackInfo->deferred = deferred; + + napi_value resourceName; + napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName); + napi_create_async_work( + env, + nullptr, + resourceName, + [](napi_env env, void *data) { + HILOG_INFO("%{public}s, promise runnning", __func__); + + AsyncGetFormsInfoByModuleCallbackInfo *asyncCallbackInfo = + (AsyncGetFormsInfoByModuleCallbackInfo *)data; + + InnerGetFormsInfoByModule(env, asyncCallbackInfo); + }, + [](napi_env env, napi_status status, void *data) { + HILOG_INFO("%{public}s, promise complete", __func__); + + AsyncGetFormsInfoByModuleCallbackInfo *asyncCallbackInfo = + (AsyncGetFormsInfoByModuleCallbackInfo *)data; + + napi_value arrayFormInfos; + napi_create_array(env, &arrayFormInfos); + if (asyncCallbackInfo->result) { + int iFormInfoCount = 0; + for (auto formInfo : asyncCallbackInfo->formInfos) { + napi_value formInfoObject = nullptr; + napi_create_object(env, &formInfoObject); + ParseFormInfoIntoNapi(env, formInfo, formInfoObject); + napi_set_element(env, arrayFormInfos, iFormInfoCount, formInfoObject); + ++iFormInfoCount; + } + } + napi_resolve_deferred(asyncCallbackInfo->env, asyncCallbackInfo->deferred, arrayFormInfos); + napi_delete_async_work(env, asyncCallbackInfo->asyncWork); + delete asyncCallbackInfo; + }, + (void *)asyncCallbackInfo, + &asyncCallbackInfo->asyncWork); + napi_queue_async_work(env, asyncCallbackInfo->asyncWork); + return promise; + } +} diff --git a/tools/interfaces/kits/napi/aafwk/formManager/napi_form_manager.h b/tools/interfaces/kits/napi/aafwk/formManager/napi_form_manager.h new file mode 100755 index 00000000000..ff8333f697a --- /dev/null +++ b/tools/interfaces/kits/napi/aafwk/formManager/napi_form_manager.h @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FORM_ABILITY_H_ +#define FORM_ABILITY_H_ + +#include "ability.h" +#include "form_info.h" +#include "form_js_info.h" +#include "form_provider_info.h" +#include "hilog_wrapper.h" +#include "napi/native_common.h" +#include "napi/native_node_api.h" +#include "nlohmann/json.hpp" +#include "want.h" + +struct AsyncDelFormCallbackInfo { + napi_env env; + OHOS::AppExecFwk::Ability *ability; + napi_async_work asyncWork; + napi_deferred deferred; + napi_ref callback; + int64_t formId; + int result; +}; + +struct AsyncReleaseFormCallbackInfo { + napi_env env; + OHOS::AppExecFwk::Ability *ability; + napi_async_work asyncWork; + napi_deferred deferred; + napi_ref callback; + int64_t formId; + bool isReleaseCache; + int result; +}; + +struct AsyncRequestFormCallbackInfo { + napi_env env; + OHOS::AppExecFwk::Ability *ability; + napi_async_work asyncWork; + napi_deferred deferred; + napi_ref callback; + int64_t formId; + int result; +}; + +struct AsyncNextRefreshTimeFormCallbackInfo { + napi_env env; + OHOS::AppExecFwk::Ability *ability; + napi_async_work asyncWork; + napi_deferred deferred; + napi_ref callback; + int64_t formId; + int32_t time; + int result; +}; + +struct AsyncUpdateFormCallbackInfo { + napi_env env; + OHOS::AppExecFwk::Ability *ability; + napi_async_work asyncWork; + napi_deferred deferred; + napi_ref callback; + int64_t formId; + std::shared_ptr formProviderData; + int result; +}; + +struct AsyncCastTempFormCallbackInfo { + napi_env env; + OHOS::AppExecFwk::Ability *ability; + napi_async_work asyncWork; + napi_deferred deferred; + napi_ref callback; + int64_t formId; + int result; +}; + +struct AsyncNotifyVisibleFormsCallbackInfo { + napi_env env; + OHOS::AppExecFwk::Ability *ability; + napi_async_work asyncWork; + napi_deferred deferred; + napi_ref callback; + std::vector formIds; + int result; +}; + +struct AsyncNotifyInvisibleFormsCallbackInfo { + napi_env env; + OHOS::AppExecFwk::Ability *ability; + napi_async_work asyncWork; + napi_deferred deferred; + napi_ref callback; + std::vector formIds; + int result; +}; + +struct AsyncEnableUpdateFormCallbackInfo { + napi_env env; + OHOS::AppExecFwk::Ability *ability; + napi_async_work asyncWork; + napi_deferred deferred; + napi_ref callback; + std::vector formIds; + int result; +}; + +struct AsyncDisableUpdateFormCallbackInfo { + napi_env env; + OHOS::AppExecFwk::Ability *ability; + napi_async_work asyncWork; + napi_deferred deferred; + napi_ref callback; + std::vector formIds; + int result; +}; + +struct AsyncCheckFMSReadyCallbackInfo { + napi_env env; + OHOS::AppExecFwk::Ability *ability; + napi_async_work asyncWork; + napi_deferred deferred; + napi_ref callback; + bool isFMSReady; +}; + +struct AsyncGetAllFormsCallbackInfo { + napi_env env; + OHOS::AppExecFwk::Ability *ability; + napi_async_work asyncWork; + napi_deferred deferred; + napi_ref callback; + std::vector formInfos; + int result; +}; + +struct AsyncGetFormsInfoByAppCallbackInfo { + napi_env env; + OHOS::AppExecFwk::Ability *ability; + napi_async_work asyncWork; + napi_deferred deferred; + napi_ref callback; + std::vector formInfos; + std::string bundleName; + int result; +}; + +struct AsyncGetFormsInfoByModuleCallbackInfo { + napi_env env; + OHOS::AppExecFwk::Ability *ability; + napi_async_work asyncWork; + napi_deferred deferred; + napi_ref callback; + std::vector formInfos; + std::string bundleName; + std::string moduleName; + int result; +}; + +napi_value NAPI_DeleteForm(napi_env env, napi_callback_info info); +napi_value NAPI_ReleaseForm(napi_env env, napi_callback_info info); +napi_value NAPI_RequestForm(napi_env env, napi_callback_info info); +napi_value NAPI_SetFormNextRefreshTime(napi_env env, napi_callback_info info); +napi_value NAPI_UpdateForm(napi_env env, napi_callback_info info); +napi_value NAPI_CastTempForm(napi_env env, napi_callback_info info); +napi_value NAPI_NotifyVisibleForms(napi_env env, napi_callback_info info); +napi_value NAPI_NotifyInvisibleForms(napi_env env, napi_callback_info info); +napi_value NAPI_EnableFormsUpdate(napi_env env, napi_callback_info info); +napi_value NAPI_DisableFormsUpdate(napi_env env, napi_callback_info info); +napi_value NAPI_CheckFMSReady(napi_env env, napi_callback_info info); +napi_value NAPI_GetAllFormsInfo(napi_env env, napi_callback_info info); +napi_value NAPI_GetFormsInfoByApp(napi_env env, napi_callback_info info); +napi_value NAPI_GetFormsInfoByModule(napi_env env, napi_callback_info info); + +#endif /* FORM_ABILITY_H_ */ diff --git a/tools/interfaces/kits/napi/aafwk/formManager/native_module.cpp b/tools/interfaces/kits/napi/aafwk/formManager/native_module.cpp new file mode 100755 index 00000000000..664419ca19b --- /dev/null +++ b/tools/interfaces/kits/napi/aafwk/formManager/native_module.cpp @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include +#include +#include +#include "napi_form_manager.h" +#include "napi/native_api.h" +#include "napi/native_node_api.h" + +EXTERN_C_START + +/** + * @brief For N-API modules registration + * + * @param[in] env The environment that the Node-API call is invoked under + * @param[in] exports An empty object via the exports parameter as a convenience + * + * @return The return value from Init is treated as the exports object for the module + */ +static napi_value Init(napi_env env, napi_value exports) +{ + HILOG_INFO("napi_moudule Init start..."); + napi_property_descriptor properties[] = { + DECLARE_NAPI_FUNCTION("deleteForm", NAPI_DeleteForm), + DECLARE_NAPI_FUNCTION("releaseForm", NAPI_ReleaseForm), + DECLARE_NAPI_FUNCTION("requestForm", NAPI_RequestForm), + DECLARE_NAPI_FUNCTION("setFormNextRefreshTime", NAPI_SetFormNextRefreshTime), + DECLARE_NAPI_FUNCTION("updateForm", NAPI_UpdateForm), + DECLARE_NAPI_FUNCTION("castTempForm", NAPI_CastTempForm), + DECLARE_NAPI_FUNCTION("notifyVisibleForms", NAPI_NotifyVisibleForms), + DECLARE_NAPI_FUNCTION("notifyInvisibleForms", NAPI_NotifyInvisibleForms), + DECLARE_NAPI_FUNCTION("enableFormsUpdate", NAPI_EnableFormsUpdate), + DECLARE_NAPI_FUNCTION("disableFormsUpdate", NAPI_DisableFormsUpdate), + DECLARE_NAPI_FUNCTION("checkFMSReady", NAPI_CheckFMSReady), + DECLARE_NAPI_FUNCTION("getAllFormsInfo", NAPI_GetAllFormsInfo), + DECLARE_NAPI_FUNCTION("getFormsInfoByApp", NAPI_GetFormsInfoByApp), + DECLARE_NAPI_FUNCTION("getFormsInfoByModule", NAPI_GetFormsInfoByModule), + }; + NAPI_CALL(env, napi_define_properties(env, exports, sizeof(properties) / sizeof(properties[0]), properties)); + HILOG_INFO("napi_moudule Init end..."); + + return exports; +} + +EXTERN_C_END + +// Define a Node-API module. +static napi_module _module = { + .nm_version = 1, + .nm_flags = 0, + .nm_filename = nullptr, + .nm_register_func = Init, + .nm_modname = "ability.formmanager", + .nm_priv = ((void *)0), + .reserved = {0} +}; + +// Registers a Node-API module. +extern "C" __attribute__((constructor)) void RegisterModule(void) +{ + napi_module_register(&_module); +} \ No newline at end of file diff --git a/tools/interfaces/kits/napi/aafwk/inner/napi_common/BUILD.gn b/tools/interfaces/kits/napi/aafwk/inner/napi_common/BUILD.gn new file mode 100755 index 00000000000..484c7cb94f3 --- /dev/null +++ b/tools/interfaces/kits/napi/aafwk/inner/napi_common/BUILD.gn @@ -0,0 +1,56 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# import("//build/config/ohos/rules.gni") +import("//build/ohos.gni") +ohos_shared_library("napi_common") { + include_dirs = [ + "//foundation/ace/napi/interfaces/kits", + "//third_party/node/src", + "//third_party/libuv/include", + "//foundation/aafwk/standard/frameworks/kits/ability/native/include", + ] + + sources = [ + "napi_common_ability.cpp", + "napi_common_util.cpp", + "napi_common_want.cpp", + ] + + deps = [ + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/interfaces/innerkits/base:base", + "//foundation/ace/napi:ace_napi", + "//foundation/appexecfwk/standard/kits:appkit_native", + "//third_party/libuv:uv_static", + "//utils/native/base:utils", + ] + + external_deps = [ + "aafwk_standard:ability_manager", + "aafwk_standard:want", + "appexecfwk_standard:appexecfwk_base", + "appexecfwk_standard:appexecfwk_core", + "appexecfwk_standard:libeventhandler", + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + "ipc_js:rpc", + "native_appdatamgr:native_appdatafwk", + "native_appdatamgr:native_dataability", + "native_appdatamgr:native_rdb", + "samgr_L2:samgr_proxy", + ] + + subsystem_name = "aafwk" + part_name = "aafwk_standard" +} diff --git a/tools/interfaces/kits/napi/aafwk/inner/napi_common/feature_ability_common.h b/tools/interfaces/kits/napi/aafwk/inner/napi_common/feature_ability_common.h new file mode 100644 index 00000000000..a17344bbca0 --- /dev/null +++ b/tools/interfaces/kits/napi/aafwk/inner/napi_common/feature_ability_common.h @@ -0,0 +1,351 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_APPEXECFWK_FEATURE_ABILITY_COMMON_H +#define OHOS_APPEXECFWK_FEATURE_ABILITY_COMMON_H +#include "napi/native_common.h" +#include "napi/native_node_api.h" +#include "ability.h" +#include "want.h" +#include "napi_common.h" +#include "abs_shared_result_set.h" +#include "data_ability_predicates.h" +#include "values_bucket.h" +#include "napi_common_util.h" + +using Want = OHOS::AAFwk::Want; +using Ability = OHOS::AppExecFwk::Ability; +using AbilityStartSetting = OHOS::AppExecFwk::AbilityStartSetting; + +namespace OHOS { +namespace AppExecFwk { +class FeatureAbility; + +struct CallAbilityParam { + Want want; + int requestCode = 0; + bool forResultOption = false; + std::shared_ptr setting = nullptr; +}; + +struct OnAbilityCallback { + int requestCode = 0; + int resultCode = 0; + Want resultData; + CallbackInfo cb; +}; + +struct ContinueAbilityOptionsInfo { + bool reversible = false; + std::string deviceId; +}; + +struct AsyncCallbackInfo { + CallbackInfo cbInfo; + napi_async_work asyncWork = nullptr; + napi_deferred deferred = nullptr; + Ability *ability = nullptr; + CallAbilityParam param; + CallbackInfo aceCallback; + bool native_result; + AbilityType abilityType = AbilityType::UNKNOWN; + int errCode = 0; + ContinueAbilityOptionsInfo optionInfo; +}; + +struct CBBase { + CallbackInfo cbInfo; + napi_async_work asyncWork; + napi_deferred deferred; + Ability *ability = nullptr; + AbilityType abilityType = AbilityType::UNKNOWN; + int errCode = 0; +}; + +struct AppInfo_ { + std::string name; + std::string description; + int32_t descriptionId = 0; + bool systemApp = false; + bool enabled = true; // no data + std::string label; + std::string labelId; + std::string icon; + std::string iconId; + std::string process; + int32_t supportedModes = 0; + std::vector moduleSourceDirs; + std::vector permissions; + std::vector moduleInfos; + std::string entryDir; +}; + +struct AppInfoCB { + CBBase cbBase; + AppInfo_ appInfo; +}; + +struct AppTypeCB { + CBBase cbBase; + std::string name; +}; + +struct AbilityInfo_ { + std::string bundleName; + std::string name; + std::string label; + std::string description; + std::string icon; + int32_t labelId; + int32_t descriptionId; + int32_t iconId; + std::string moduleName; + std::string process; + std::string targetAbility; // no data + int32_t backgroundModes; // no data + bool isVisible = true; + bool formEnabled = false; // no data + int32_t type = 0; + int32_t subType = 0; // no data + int32_t orientation = 0; + int32_t launchMode = 0; + std::vector permissions; + std::vector deviceTypes; + std::vector deviceCapabilities; + std::string readPermission; // no data + std::string writePermission; // no data + AppInfo_ appInfo; + int32_t formEntity; // no data + int32_t minFormHeight; // no data + int32_t defaultFormHeight; // no data + int32_t minFormWidth; // no data + int32_t defaultFormWidth; // no data + std::string uri; +}; +struct AbilityInfoCB { + CBBase cbBase; + AbilityInfo_ abilityInfo; +}; + +struct AbilityNameCB { + CBBase cbBase; + std::string name; +}; + +struct ProcessInfoCB { + CBBase cbBase; + pid_t pid = 0; + std::string processName; +}; + +struct ProcessNameCB { + CBBase cbBase; + std::string processName; +}; + +struct CallingBundleCB { + CBBase cbBase; + std::string callingBundleName; +}; + +struct GetOrCreateLocalDirCB { + CBBase cbBase; + std::string rootDir; +}; + +struct DatabaseDirCB { + CBBase cbBase; + std::string dataBaseDir; +}; + +struct PreferencesDirCB { + CBBase cbBase; + std::string preferencesDir; +}; + +struct ElementNameCB { + CBBase cbBase; + std::string deviceId; + std::string bundleName; + std::string abilityName; + std::string uri; + std::string shortName; +}; + +struct HapModuleInfo_ { + std::string name; + std::string description; + int32_t descriptionId = 0; // no data + std::string icon; + std::string label; + int32_t labelId = 0; // no data + int32_t iconId = 0; // no data + std::string backgroundImg; + int32_t supportedModes = 0; + std::vector reqCapabilities; + std::vector deviceTypes; + std::vector abilityInfos; + std::string moduleName; + std::string mainAbilityName; // no data + bool installationFree; // no data +}; + +struct HapModuleInfoCB { + CBBase cbBase; + HapModuleInfo_ hapModuleInfo; +}; + +struct DataAbilityHelperCB { + CBBase cbBase; + napi_ref uri = nullptr; + napi_value result = nullptr; +}; + +struct DAHelperInsertCB { + CBBase cbBase; + DataAbilityHelper *dataAbilityHelper = nullptr; + std::string uri; + NativeRdb::ValuesBucket valueBucket; + int result = 0; +}; + +class NAPIAbilityConnection; +struct AbilityConnectionCB { + napi_env env; + napi_ref callback[3] = {0}; // onConnect/onDisconnect/onFailed + int resultCode = 0; + ElementName elementName; + sptr connection; +}; +struct ConnectAbilityCB { + CBBase cbBase; + Want want; + sptr abilityConnection; + AbilityConnectionCB abilityConnectionCB; + int64_t id; + bool result; + int errCode = 0; +}; + +struct DAHelperNotifyChangeCB { + CBBase cbBase; + DataAbilityHelper *dataAbilityHelper = nullptr; + std::string uri; +}; + +class NAPIDataAbilityObserver; +struct DAHelperOnOffCB { + CBBase cbBase; + DataAbilityHelper *dataAbilityHelper = nullptr; + sptr observer; + std::string uri; + int result = 0; +}; + +static inline std::string NapiValueToStringUtf8(napi_env env, napi_value value) +{ + std::string result = ""; + return UnwrapStringFromJS(env, value, result); +} + +static inline bool NapiValueToArrayStringUtf8(napi_env env, napi_value param, std::vector &result) +{ + return UnwrapArrayStringFromJS(env, param, result); +} + +struct DAHelperGetTypeCB { + CBBase cbBase; + DataAbilityHelper *dataAbilityHelper = nullptr; + std::string uri; + std::string result = ""; +}; + +struct DAHelperGetFileTypesCB { + CBBase cbBase; + DataAbilityHelper *dataAbilityHelper = nullptr; + std::string uri; + std::string mimeTypeFilter; + std::vector result; +}; + +struct DAHelperNormalizeUriCB { + CBBase cbBase; + DataAbilityHelper *dataAbilityHelper = nullptr; + std::string uri; + std::string result = ""; +}; +struct DAHelperDenormalizeUriCB { + CBBase cbBase; + DataAbilityHelper *dataAbilityHelper = nullptr; + std::string uri; + std::string result = ""; +}; + +struct DAHelperDeleteCB { + CBBase cbBase; + DataAbilityHelper *dataAbilityHelper = nullptr; + std::string uri; + NativeRdb::DataAbilityPredicates predicates; + int result = 0; +}; + +struct DAHelperQueryCB { + CBBase cbBase; + DataAbilityHelper *dataAbilityHelper = nullptr; + std::string uri; + std::vector columns; + NativeRdb::DataAbilityPredicates predicates; + std::shared_ptr result; +}; + +struct DAHelperUpdateCB { + CBBase cbBase; + DataAbilityHelper *dataAbilityHelper = nullptr; + std::string uri; + NativeRdb::ValuesBucket valueBucket; + NativeRdb::DataAbilityPredicates predicates; + int result = 0; +}; +struct DAHelperBatchInsertCB { + CBBase cbBase; + DataAbilityHelper *dataAbilityHelper = nullptr; + std::string uri; + std::vector values; + int result = 0; +}; +struct DAHelperOpenFileCB { + CBBase cbBase; + DataAbilityHelper *dataAbilityHelper = nullptr; + std::string uri; + std::string mode; + int result = 0; +}; + +struct DAHelperReleaseCB { + CBBase cbBase; + DataAbilityHelper *dataAbilityHelper = nullptr; + bool result = false; +}; + +struct DAHelperExecuteBatchCB { + CBBase cbBase; + std::string uri; + std::vector> operations; + DataAbilityHelper *dataAbilityHelper = nullptr; + std::vector> result; +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif /* OHOS_APPEXECFWK_FEATURE_ABILITY_COMMON_H */ diff --git a/tools/interfaces/kits/napi/aafwk/inner/napi_common/napi_common.h b/tools/interfaces/kits/napi/aafwk/inner/napi_common/napi_common.h new file mode 100755 index 00000000000..d3f624be95d --- /dev/null +++ b/tools/interfaces/kits/napi/aafwk/inner/napi_common/napi_common.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_APPEXECFWK_NAPI_COMMON_H +#define OHOS_APPEXECFWK_NAPI_COMMON_H + +#include "napi_common_error.h" +#include "napi_common_data.h" +#include "napi_common_util.h" +#include "napi_common_want.h" +#endif // OHOS_APPEXECFWK_NAPI_COMMON_H diff --git a/tools/interfaces/kits/napi/aafwk/inner/napi_common/napi_common_ability.cpp b/tools/interfaces/kits/napi/aafwk/inner/napi_common/napi_common_ability.cpp new file mode 100755 index 00000000000..d70985df33c --- /dev/null +++ b/tools/interfaces/kits/napi/aafwk/inner/napi_common/napi_common_ability.cpp @@ -0,0 +1,3443 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "napi_common_ability.h" +#include +#include +#include "napi_common_util.h" +#include "securec.h" +#include "hilog_wrapper.h" +#include "napi_remote_object.h" + +namespace OHOS { +namespace AppExecFwk { + +napi_value g_classContext; +napi_value g_dataAbilityHelper; +using NAPICreateJsRemoteObject = napi_value (*)(napi_env env, const sptr target); + +napi_value *GetGlobalClassContext(void) +{ + return &g_classContext; +} + +napi_value GetGlobalDataAbilityHelper(void) +{ + return g_dataAbilityHelper; +} + +bool CheckAbilityType(AbilityType typeInAbility, AbilityType typeWant) +{ + HILOG_INFO("%{public}s called.", __func__); + switch (typeWant) { + case AbilityType::PAGE: + return typeInAbility == AbilityType::PAGE; + default: + return typeInAbility != AbilityType::PAGE; + } + HILOG_INFO("%{public}s end.", __func__); + return false; +} + +bool CheckAbilityType(const CBBase *cbBase) +{ + HILOG_INFO("%{public}s called.", __func__); + if (cbBase == nullptr) { + HILOG_ERROR("%{public}s cbBase == nullptr", __func__); + return false; + } + + if (cbBase->ability == nullptr) { + HILOG_ERROR("%{public}s cbBase->ability == nullptr", __func__); + return false; + } + + const std::shared_ptr info = cbBase->ability->GetAbilityInfo(); + if (info == nullptr) { + HILOG_ERROR("%{public}s info == nullptr", __func__); + return false; + } + HILOG_INFO("%{public}s end.", __func__); + return CheckAbilityType((AbilityType)info->type, cbBase->abilityType); +} + +bool CheckAbilityType(const AsyncJSCallbackInfo *asyncCallbackInfo) +{ + HILOG_INFO("%{public}s called.", __func__); + if (asyncCallbackInfo == nullptr) { + HILOG_ERROR("%{public}s asyncCallbackInfo == nullptr", __func__); + return false; + } + + if (asyncCallbackInfo->ability == nullptr) { + HILOG_ERROR("%{public}s ability == nullptr", __func__); + return false; + } + + const std::shared_ptr info = asyncCallbackInfo->ability->GetAbilityInfo(); + if (info == nullptr) { + HILOG_ERROR("%{public}s info == nullptr", __func__); + return false; + } + HILOG_INFO("%{public}s end.", __func__); + return CheckAbilityType((AbilityType)info->type, asyncCallbackInfo->abilityType); +} + +bool CheckAbilityType(const AsyncCallbackInfo *asyncCallbackInfo) +{ + HILOG_INFO("%{public}s called.", __func__); + if (asyncCallbackInfo == nullptr) { + HILOG_ERROR("%{public}s asyncCallbackInfo == nullptr", __func__); + return false; + } + + if (asyncCallbackInfo->ability == nullptr) { + HILOG_ERROR("%{public}s ability == nullptr", __func__); + return false; + } + + const std::shared_ptr info = asyncCallbackInfo->ability->GetAbilityInfo(); + if (info == nullptr) { + HILOG_ERROR("%{public}s info == nullptr", __func__); + return false; + } + + HILOG_INFO("%{public}s end.", __func__); + return CheckAbilityType((AbilityType)info->type, asyncCallbackInfo->abilityType); +} + +void SaveAppInfo(AppInfo_ &appInfo, const ApplicationInfo &appInfoOrg) +{ + HILOG_INFO("%{public}s.", __func__); + appInfo.name = appInfoOrg.name; + appInfo.description = appInfoOrg.description; + appInfo.descriptionId = appInfoOrg.descriptionId; + appInfo.systemApp = appInfoOrg.isSystemApp; + appInfo.enabled = appInfoOrg.enabled; + appInfo.label = appInfoOrg.label; + appInfo.labelId = std::to_string(appInfoOrg.labelId); + appInfo.icon = appInfoOrg.iconPath; + appInfo.iconId = std::to_string(appInfoOrg.iconId); + appInfo.process = appInfoOrg.process; + appInfo.supportedModes = appInfoOrg.supportedModes; + for (size_t i = 0; i < appInfoOrg.moduleInfos.size(); i++) { + appInfo.moduleSourceDirs.emplace_back(appInfoOrg.moduleInfos.at(i).moduleSourceDir); + } + for (size_t i = 0; i < appInfoOrg.permissions.size(); i++) { + appInfo.permissions.emplace_back(appInfoOrg.permissions.at(i)); + } + for (size_t i = 0; i < appInfoOrg.moduleInfos.size(); i++) { + appInfo.moduleInfos.emplace_back(appInfoOrg.moduleInfos.at(i)); + } + appInfo.entryDir = appInfoOrg.entryDir; + HILOG_INFO("%{public}s end.", __func__); +} + +napi_value GetContinueAbilityOptionsInfoCommon( + const napi_env &env, const napi_value &value, ContinueAbilityOptionsInfo &info) +{ + HILOG_INFO("%{public}s.", __func__); + napi_value result = nullptr; + + // reversible?: boolean + if (GetContinueAbilityOptionsReversible(env, value, info) == nullptr) { + return nullptr; + } + + // deviceId?: string + if (GetContinueAbilityOptionsDeviceID(env, value, info) == nullptr) { + return nullptr; + } + + napi_get_null(env, &result); + HILOG_INFO("%{public}s.", __func__); + return result; +} + +napi_value GetContinueAbilityOptionsReversible( + const napi_env &env, const napi_value &value, ContinueAbilityOptionsInfo &info) +{ + HILOG_INFO("%{public}s.", __func__); + napi_valuetype valuetype = napi_undefined; + napi_value result = nullptr; + bool hasProperty = false; + bool reversible = false; + + NAPI_CALL(env, napi_has_named_property(env, value, "reversible", &hasProperty)); + if (hasProperty) { + napi_get_named_property(env, value, "reversible", &result); + NAPI_CALL(env, napi_typeof(env, result, &valuetype)); + NAPI_ASSERT(env, valuetype == napi_boolean, "Wrong argument type. Bool expected."); + napi_get_value_bool(env, result, &reversible); + info.reversible = reversible; + } + HILOG_INFO("%{public}s.", __func__); + return result; +} + +napi_value GetContinueAbilityOptionsDeviceID( + const napi_env &env, const napi_value &value, ContinueAbilityOptionsInfo &info) +{ + HILOG_INFO("%{public}s.", __func__); + napi_valuetype valuetype = napi_undefined; + napi_value result = nullptr; + bool hasProperty = false; + char str[STR_MAX_SIZE] = {0}; + size_t strLen = 0; + + NAPI_CALL(env, napi_has_named_property(env, value, "deviceId", &hasProperty)); + if (hasProperty) { + napi_get_named_property(env, value, "deviceId", &result); + NAPI_CALL(env, napi_typeof(env, result, &valuetype)); + NAPI_ASSERT(env, valuetype == napi_string, "Wrong argument type. String expected."); + NAPI_CALL(env, napi_get_value_string_utf8(env, result, str, STR_MAX_SIZE - 1, &strLen)); + info.deviceId = str; + } + HILOG_INFO("%{public}s.", __func__); + return result; +} + +napi_value WrapAppInfo(napi_env env, const AppInfo_ &appInfo) +{ + HILOG_INFO("%{public}s.", __func__); + napi_value result = nullptr; + napi_value proValue = nullptr; + NAPI_CALL(env, napi_create_object(env, &result)); + NAPI_CALL(env, napi_create_string_utf8(env, appInfo.name.c_str(), NAPI_AUTO_LENGTH, &proValue)); + NAPI_CALL(env, napi_set_named_property(env, result, "name", proValue)); + + NAPI_CALL(env, napi_create_string_utf8(env, appInfo.description.c_str(), NAPI_AUTO_LENGTH, &proValue)); + NAPI_CALL(env, napi_set_named_property(env, result, "description", proValue)); + + NAPI_CALL(env, napi_create_int32(env, appInfo.descriptionId, &proValue)); + NAPI_CALL(env, napi_set_named_property(env, result, "descriptionId", proValue)); + + NAPI_CALL(env, napi_get_boolean(env, appInfo.systemApp, &proValue)); + NAPI_CALL(env, napi_set_named_property(env, result, "systemApp", proValue)); + NAPI_CALL(env, napi_get_boolean(env, appInfo.enabled, &proValue)); + NAPI_CALL(env, napi_set_named_property(env, result, "enabled", proValue)); + NAPI_CALL(env, napi_create_string_utf8(env, appInfo.label.c_str(), NAPI_AUTO_LENGTH, &proValue)); + NAPI_CALL(env, napi_set_named_property(env, result, "label", proValue)); + NAPI_CALL(env, napi_create_string_utf8(env, appInfo.labelId.c_str(), NAPI_AUTO_LENGTH, &proValue)); + NAPI_CALL(env, napi_set_named_property(env, result, "labelId", proValue)); + NAPI_CALL(env, napi_create_string_utf8(env, appInfo.icon.c_str(), NAPI_AUTO_LENGTH, &proValue)); + NAPI_CALL(env, napi_set_named_property(env, result, "icon", proValue)); + NAPI_CALL(env, napi_create_string_utf8(env, appInfo.iconId.c_str(), NAPI_AUTO_LENGTH, &proValue)); + NAPI_CALL(env, napi_set_named_property(env, result, "iconId", proValue)); + NAPI_CALL(env, napi_create_string_utf8(env, appInfo.process.c_str(), NAPI_AUTO_LENGTH, &proValue)); + NAPI_CALL(env, napi_set_named_property(env, result, "process", proValue)); + NAPI_CALL(env, napi_create_int32(env, appInfo.supportedModes, &proValue)); + NAPI_CALL(env, napi_set_named_property(env, result, "supportedModes", proValue)); + napi_value jsArrayModDirs = nullptr; + NAPI_CALL(env, napi_create_array(env, &jsArrayModDirs)); + for (size_t i = 0; i < appInfo.moduleSourceDirs.size(); i++) { + proValue = nullptr; + NAPI_CALL( + env, napi_create_string_utf8(env, appInfo.moduleSourceDirs.at(i).c_str(), NAPI_AUTO_LENGTH, &proValue)); + NAPI_CALL(env, napi_set_element(env, jsArrayModDirs, i, proValue)); + } + NAPI_CALL(env, napi_set_named_property(env, result, "moduleSourceDirs", jsArrayModDirs)); + napi_value jsArrayPermissions = nullptr; + NAPI_CALL(env, napi_create_array(env, &jsArrayPermissions)); + for (size_t i = 0; i < appInfo.permissions.size(); i++) { + proValue = nullptr; + NAPI_CALL(env, napi_create_string_utf8(env, appInfo.permissions.at(i).c_str(), NAPI_AUTO_LENGTH, &proValue)); + NAPI_CALL(env, napi_set_element(env, jsArrayPermissions, i, proValue)); + } + NAPI_CALL(env, napi_set_named_property(env, result, "permissions", jsArrayPermissions)); + napi_value jsArrayModuleInfo = nullptr; + NAPI_CALL(env, napi_create_array(env, &jsArrayModuleInfo)); + for (size_t i = 0; i < appInfo.moduleInfos.size(); i++) { + napi_value jsModuleInfoObject = nullptr; + NAPI_CALL(env, napi_create_object(env, &jsModuleInfoObject)); + proValue = nullptr; + NAPI_CALL(env, + napi_create_string_utf8(env, appInfo.moduleInfos.at(i).moduleName.c_str(), NAPI_AUTO_LENGTH, &proValue)); + NAPI_CALL(env, napi_set_named_property(env, jsModuleInfoObject, "moduleName", proValue)); + proValue = nullptr; + NAPI_CALL(env, + napi_create_string_utf8( + env, appInfo.moduleInfos.at(i).moduleSourceDir.c_str(), NAPI_AUTO_LENGTH, &proValue)); + NAPI_CALL(env, napi_set_named_property(env, jsModuleInfoObject, "moduleSourceDir", proValue)); + NAPI_CALL(env, napi_set_element(env, jsArrayModuleInfo, i, jsModuleInfoObject)); + } + NAPI_CALL(env, napi_set_named_property(env, result, "moduleInfos", jsArrayModuleInfo)); + NAPI_CALL(env, napi_create_string_utf8(env, appInfo.entryDir.c_str(), NAPI_AUTO_LENGTH, &proValue)); + NAPI_CALL(env, napi_set_named_property(env, result, "entryDir", proValue)); + HILOG_INFO("%{public}s end.", __func__); + return result; +} + +/** + * @brief GetFilesDir asynchronous processing function. + * + * @param env The environment that the Node-API call is invoked under. + * @param data Point to asynchronous processing of data. + */ +void GetFilesDirExecuteCallback(napi_env env, void *data) +{ + HILOG_INFO("%{public}s called", __func__); + AsyncJSCallbackInfo *asyncCallbackInfo = static_cast(data); + if (asyncCallbackInfo == nullptr) { + HILOG_ERROR("%{public}s. asyncCallbackInfo is null", __func__); + return; + } + + asyncCallbackInfo->error_code = NAPI_ERR_NO_ERROR; + asyncCallbackInfo->native_data.data_type = NVT_NONE; + if (asyncCallbackInfo->ability == nullptr) { + HILOG_ERROR("%{public}s ability == nullptr", __func__); + asyncCallbackInfo->error_code = NAPI_ERR_ACE_ABILITY; + return; + } + + if (!CheckAbilityType(asyncCallbackInfo)) { + HILOG_ERROR("%{public}s wrong ability type", __func__); + asyncCallbackInfo->error_code = NAPI_ERR_ABILITY_TYPE_INVALID; + asyncCallbackInfo->native_data.data_type = NVT_UNDEFINED; + return; + } + + asyncCallbackInfo->native_data.data_type = NVT_STRING; + asyncCallbackInfo->native_data.str_value = asyncCallbackInfo->ability->GetFilesDir(); + HILOG_INFO("%{public}s end. filesDir=%{public}s", __func__, asyncCallbackInfo->native_data.str_value.c_str()); +} +/** + * @brief GetFilesDir processing function. + * + * @param env The environment that the Node-API call is invoked under. + * @param asyncCallbackInfo Process data asynchronously. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value NAPI_GetFilesDirWrap(napi_env env, napi_callback_info info, AsyncJSCallbackInfo *asyncCallbackInfo) +{ + HILOG_INFO("%{public}s called", __func__); + size_t argc = ARGS_MAX_COUNT; + napi_value args[ARGS_MAX_COUNT] = {nullptr}; + napi_value jsthis = 0; + void *data = nullptr; + + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, &jsthis, &data)); + + if (argc > ARGS_ONE) { + HILOG_INFO("%{public}s called, parameters is invalid.", __func__); + return nullptr; + } + + if (argc == ARGS_ONE) { + if (!CreateAsyncCallback(env, args[PARAM0], asyncCallbackInfo)) { + HILOG_INFO("%{public}s called, the first parameter is invalid.", __func__); + return nullptr; + } + } + + AsyncParamEx asyncParamEx; + if (asyncCallbackInfo->cbInfo.callback != nullptr) { + HILOG_INFO("%{public}s called. asyncCallback.", __func__); + asyncParamEx.resource = "NAPI_GetFilesDirCallback"; + asyncParamEx.execute = GetFilesDirExecuteCallback; + asyncParamEx.complete = CompleteAsyncCallbackWork; + + return ExecuteAsyncCallbackWork(env, asyncCallbackInfo, &asyncParamEx); + } else { + HILOG_INFO("%{public}s called. promise.", __func__); + asyncParamEx.resource = "NAPI_GetFilesDirPromise"; + asyncParamEx.execute = GetFilesDirExecuteCallback; + asyncParamEx.complete = CompletePromiseCallbackWork; + + return ExecutePromiseCallbackWork(env, asyncCallbackInfo, &asyncParamEx); + } +} +napi_value NAPI_GetFilesDirCommon(napi_env env, napi_callback_info info, AbilityType abilityType) +{ + HILOG_INFO("%{public}s called", __func__); + AsyncJSCallbackInfo *asyncCallbackInfo = CreateAsyncJSCallbackInfo(env); + if (asyncCallbackInfo == nullptr) { + HILOG_INFO("%{public}s called. Invoke CreateAsyncJSCallbackInfo failed.", __func__); + return WrapVoidToJS(env); + } + + asyncCallbackInfo->abilityType = abilityType; + napi_value ret = NAPI_GetFilesDirWrap(env, info, asyncCallbackInfo); + if (ret == nullptr) { + HILOG_ERROR("%{public}s ret == nullptr", __func__); + FreeAsyncJSCallbackInfo(&asyncCallbackInfo); + ret = WrapVoidToJS(env); + } + HILOG_INFO("%{public}s end", __func__); + return ret; +} + +/** + * @brief Create asynchronous data. + * + * @param env The environment that the Node-API call is invoked under. + * + * @return Return a pointer to AppTypeCB on success, nullptr on failure. + */ +AppTypeCB *CreateAppTypeCBInfo(napi_env env) +{ + HILOG_INFO("%{public}s, called.", __func__); + napi_value global = nullptr; + NAPI_CALL(env, napi_get_global(env, &global)); + + napi_value abilityObj = nullptr; + NAPI_CALL(env, napi_get_named_property(env, global, "ability", &abilityObj)); + + Ability *ability = nullptr; + NAPI_CALL(env, napi_get_value_external(env, abilityObj, (void **)&ability)); + + AppTypeCB *appTypeCB = new (std::nothrow) AppTypeCB; + if (appTypeCB == nullptr) { + HILOG_ERROR("%{public}s, appTypeCB == nullptr.", __func__); + return nullptr; + } + appTypeCB->cbBase.cbInfo.env = env; + appTypeCB->cbBase.asyncWork = nullptr; + appTypeCB->cbBase.deferred = nullptr; + appTypeCB->cbBase.ability = ability; + + HILOG_INFO("%{public}s, end.", __func__); + return appTypeCB; +} + +/** + * @brief GetAppType asynchronous processing function. + * + * @param env The environment that the Node-API call is invoked under. + * @param data Point to asynchronous processing of data. + */ +void GetAppTypeExecuteCB(napi_env env, void *data) +{ + HILOG_INFO("NAPI_GetApplicationInfo, worker pool thread execute."); + AppTypeCB *appTypeCB = static_cast(data); + if (appTypeCB == nullptr) { + HILOG_ERROR("NAPI_GetApplicationInfo,appTypeCB == nullptr"); + return; + } + + appTypeCB->cbBase.errCode = NAPI_ERR_NO_ERROR; + if (appTypeCB->cbBase.ability == nullptr) { + HILOG_ERROR("NAPI_GetApplicationInfo,ability == nullptr"); + appTypeCB->cbBase.errCode = NAPI_ERR_ACE_ABILITY; + return; + } + + if (!CheckAbilityType(&appTypeCB->cbBase)) { + HILOG_ERROR("NAPI_GetApplicationInfo,wrong ability type"); + appTypeCB->cbBase.errCode = NAPI_ERR_ABILITY_TYPE_INVALID; + return; + } + + appTypeCB->name = appTypeCB->cbBase.ability->GetAppType(); + HILOG_INFO("NAPI_GetApplicationInfo, worker pool thread execute end."); +} + +/** + * @brief The callback at the end of the asynchronous callback. + * + * @param env The environment that the Node-API call is invoked under. + * @param data Point to asynchronous processing of data. + */ +void GetAppTypeAsyncCompleteCB(napi_env env, napi_status status, void *data) +{ + HILOG_INFO("NAPI_GetApplicationInfo, main event thread complete."); + AppTypeCB *appTypeCB = static_cast(data); + napi_value callback = nullptr; + napi_value undefined = nullptr; + napi_value result[ARGS_TWO] = {nullptr}; + napi_value callResult = nullptr; + NAPI_CALL_RETURN_VOID(env, napi_get_undefined(env, &undefined)); + + result[PARAM0] = GetCallbackErrorValue(env, appTypeCB->cbBase.errCode); + if (appTypeCB->cbBase.errCode == NAPI_ERR_NO_ERROR) { + NAPI_CALL_RETURN_VOID(env, + napi_create_string_utf8( + env, appTypeCB->cbBase.ability->GetAppType().c_str(), NAPI_AUTO_LENGTH, &result[PARAM1])); + } else { + result[PARAM1] = WrapUndefinedToJS(env); + } + NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, appTypeCB->cbBase.cbInfo.callback, &callback)); + NAPI_CALL_RETURN_VOID(env, napi_call_function(env, undefined, callback, ARGS_TWO, &result[PARAM0], &callResult)); + + if (appTypeCB->cbBase.cbInfo.callback != nullptr) { + NAPI_CALL_RETURN_VOID(env, napi_delete_reference(env, appTypeCB->cbBase.cbInfo.callback)); + } + NAPI_CALL_RETURN_VOID(env, napi_delete_async_work(env, appTypeCB->cbBase.asyncWork)); + delete appTypeCB; + appTypeCB = nullptr; + HILOG_INFO("NAPI_GetApplicationInfo, main event thread complete end."); +} + +/** + * @brief The callback at the end of the Promise callback. + * + * @param env The environment that the Node-API call is invoked under. + * @param data Point to asynchronous processing of data. + */ +void GetAppTypePromiseCompleteCB(napi_env env, napi_status status, void *data) +{ + HILOG_INFO("GetAppTypePromiseCompleteCB, main event thread complete."); + AppTypeCB *appTypeCB = static_cast(data); + napi_value result = nullptr; + if (appTypeCB->cbBase.errCode == NAPI_ERR_NO_ERROR) { + napi_create_string_utf8(env, appTypeCB->cbBase.ability->GetAppType().c_str(), NAPI_AUTO_LENGTH, &result); + napi_resolve_deferred(env, appTypeCB->cbBase.deferred, result); + } else { + result = GetCallbackErrorValue(env, appTypeCB->cbBase.errCode); + napi_reject_deferred(env, appTypeCB->cbBase.deferred, result); + } + + napi_delete_async_work(env, appTypeCB->cbBase.asyncWork); + delete appTypeCB; + appTypeCB = nullptr; + HILOG_INFO("GetAppTypePromiseCompleteCB, main event thread complete end."); +} + +/** + * @brief GetAppType Async. + * + * @param env The environment that the Node-API call is invoked under. + * @param args Indicates the arguments passed into the callback. + * @param argcPromise Asynchronous data processing. + * @param appTypeCB Process data asynchronously. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value GetAppTypeAsync(napi_env env, napi_value *args, const size_t argCallback, AppTypeCB *appTypeCB) +{ + HILOG_INFO("%{public}s, asyncCallback.", __func__); + if (args == nullptr || appTypeCB == nullptr) { + HILOG_ERROR("%{public}s, param == nullptr.", __func__); + return nullptr; + } + napi_value resourceName = nullptr; + NAPI_CALL(env, napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName)); + + napi_valuetype valuetype = napi_undefined; + NAPI_CALL(env, napi_typeof(env, args[argCallback], &valuetype)); + if (valuetype == napi_function) { + NAPI_CALL(env, napi_create_reference(env, args[argCallback], 1, &appTypeCB->cbBase.cbInfo.callback)); + } + NAPI_CALL(env, + napi_create_async_work(env, + nullptr, + resourceName, + GetAppTypeExecuteCB, + GetAppTypeAsyncCompleteCB, + (void *)appTypeCB, + &appTypeCB->cbBase.asyncWork)); + NAPI_CALL(env, napi_queue_async_work(env, appTypeCB->cbBase.asyncWork)); + napi_value result = nullptr; + NAPI_CALL(env, napi_get_null(env, &result)); + HILOG_INFO("%{public}s, asyncCallback end.", __func__); + return result; +} + +/** + * @brief GetAppType Promise. + * + * @param env The environment that the Node-API call is invoked under. + * @param appTypeCB Process data asynchronously. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value GetAppTypePromise(napi_env env, AppTypeCB *appTypeCB) +{ + HILOG_INFO("%{public}s, promise.", __func__); + if (appTypeCB == nullptr) { + HILOG_ERROR("%{public}s, param == nullptr.", __func__); + return nullptr; + } + napi_value resourceName = nullptr; + NAPI_CALL(env, napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName)); + napi_deferred deferred; + napi_value promise = nullptr; + NAPI_CALL(env, napi_create_promise(env, &deferred, &promise)); + appTypeCB->cbBase.deferred = deferred; + + NAPI_CALL(env, + napi_create_async_work(env, + nullptr, + resourceName, + GetAppTypeExecuteCB, + GetAppTypePromiseCompleteCB, + (void *)appTypeCB, + &appTypeCB->cbBase.asyncWork)); + NAPI_CALL(env, napi_queue_async_work(env, appTypeCB->cbBase.asyncWork)); + HILOG_INFO("%{public}s, promise end.", __func__); + return promise; +} + +/** + * @brief GetAppType processing function. + * + * @param env The environment that the Node-API call is invoked under. + * @param appTypeCB Process data asynchronously. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value GetAppTypeWrap(napi_env env, napi_callback_info info, AppTypeCB *appTypeCB) +{ + HILOG_INFO("%{public}s, asyncCallback.", __func__); + if (appTypeCB == nullptr) { + HILOG_ERROR("%{public}s, appTypeCB == nullptr.", __func__); + return nullptr; + } + + size_t argcAsync = 1; + const size_t argcPromise = 0; + const size_t argCountWithAsync = argcPromise + ARGS_ASYNC_COUNT; + napi_value args[ARGS_MAX_COUNT] = {nullptr}; + napi_value ret = nullptr; + + NAPI_CALL(env, napi_get_cb_info(env, info, &argcAsync, args, nullptr, nullptr)); + if (argcAsync > argCountWithAsync || argcAsync > ARGS_MAX_COUNT) { + HILOG_ERROR("%{public}s, Wrong argument count.", __func__); + return nullptr; + } + + if (argcAsync > argcPromise) { + ret = GetAppTypeAsync(env, args, 0, appTypeCB); + } else { + ret = GetAppTypePromise(env, appTypeCB); + } + HILOG_INFO("%{public}s, asyncCallback end.", __func__); + return ret; +} + +/** + * @brief Obtains the type of this application. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_GetAppTypeCommon(napi_env env, napi_callback_info info, AbilityType abilityType) +{ + HILOG_INFO("%{public}s called.", __func__); + AppTypeCB *appTypeCB = CreateAppTypeCBInfo(env); + if (appTypeCB == nullptr) { + return WrapVoidToJS(env); + } + + appTypeCB->cbBase.errCode = NAPI_ERR_NO_ERROR; + appTypeCB->cbBase.abilityType = abilityType; + napi_value ret = GetAppTypeWrap(env, info, appTypeCB); + if (ret == nullptr) { + HILOG_ERROR("%{public}s, ret == nullptr.", __func__); + if (appTypeCB != nullptr) { + delete appTypeCB; + appTypeCB = nullptr; + } + ret = WrapVoidToJS(env); + } + HILOG_INFO("%{public}s, end.", __func__); + return ret; +} + +/** + * @brief Create asynchronous data. + * + * @param env The environment that the Node-API call is invoked under. + * + * @return Return a pointer to AbilityInfoCB on success, nullptr on failure. + */ +AbilityInfoCB *CreateAbilityInfoCBInfo(napi_env env) +{ + HILOG_INFO("%{public}s called.", __func__); + napi_value global = nullptr; + NAPI_CALL(env, napi_get_global(env, &global)); + + napi_value abilityObj = nullptr; + NAPI_CALL(env, napi_get_named_property(env, global, "ability", &abilityObj)); + + Ability *ability = nullptr; + NAPI_CALL(env, napi_get_value_external(env, abilityObj, (void **)&ability)); + + AbilityInfoCB *abilityInfoCB = new (std::nothrow) AbilityInfoCB; + if (abilityInfoCB == nullptr) { + HILOG_ERROR("%{public}s, abilityInfoCB == nullptr.", __func__); + return nullptr; + } + abilityInfoCB->cbBase.cbInfo.env = env; + abilityInfoCB->cbBase.asyncWork = nullptr; + abilityInfoCB->cbBase.deferred = nullptr; + abilityInfoCB->cbBase.ability = ability; + + HILOG_INFO("%{public}s end.", __func__); + return abilityInfoCB; +} + +void SaveAbilityInfo(AbilityInfo_ &abilityInfo, const AbilityInfo &abilityInfoOrg) +{ + HILOG_INFO("%{public}s called.", __func__); + abilityInfo.bundleName = abilityInfoOrg.bundleName; + abilityInfo.name = abilityInfoOrg.name; + abilityInfo.label = abilityInfoOrg.label; + abilityInfo.description = abilityInfoOrg.description; + abilityInfo.icon = abilityInfoOrg.iconPath; + abilityInfo.labelId = abilityInfoOrg.applicationInfo.labelId; + abilityInfo.descriptionId = abilityInfoOrg.applicationInfo.descriptionId; + abilityInfo.iconId = abilityInfoOrg.applicationInfo.iconId; + abilityInfo.moduleName = abilityInfoOrg.moduleName; + abilityInfo.process = abilityInfoOrg.process; + abilityInfo.isVisible = abilityInfoOrg.visible; + + abilityInfo.type = static_cast(abilityInfoOrg.type); + abilityInfo.orientation = static_cast(abilityInfoOrg.orientation); + abilityInfo.launchMode = static_cast(abilityInfoOrg.launchMode); + + abilityInfo.uri = abilityInfoOrg.uri; + abilityInfo.targetAbility = abilityInfoOrg.targetAbility; + + for (size_t i = 0; i < abilityInfoOrg.permissions.size(); i++) { + abilityInfo.permissions.emplace_back(abilityInfoOrg.permissions.at(i)); + } + for (size_t i = 0; i < abilityInfoOrg.deviceTypes.size(); i++) { + abilityInfo.deviceTypes.emplace_back(abilityInfoOrg.deviceTypes.at(i)); + } + for (size_t i = 0; i < abilityInfoOrg.deviceCapabilities.size(); i++) { + abilityInfo.deviceCapabilities.emplace_back(abilityInfoOrg.deviceCapabilities.at(i)); + } + + SaveAppInfo(abilityInfo.appInfo, abilityInfoOrg.applicationInfo); + + abilityInfo.readPermission = abilityInfoOrg.readPermission; + abilityInfo.writePermission = abilityInfoOrg.writePermission; + abilityInfo.formEntity = 0; // no data + abilityInfo.minFormHeight = 0; // no data + abilityInfo.defaultFormHeight = 0; // no data + abilityInfo.minFormWidth = 0; // no data + abilityInfo.defaultFormWidth = 0; // no data + abilityInfo.backgroundModes = 0; // no data + abilityInfo.subType = 0; // no data + abilityInfo.formEnabled = false; // no data + HILOG_INFO("%{public}s end.", __func__); +} + +napi_value WrapAbilityInfo(napi_env env, const AbilityInfo_ &abilityInfo) +{ + HILOG_INFO("%{public}s called.", __func__); + napi_value result = nullptr; + napi_value proValue = nullptr; + NAPI_CALL(env, napi_create_object(env, &result)); + NAPI_CALL(env, napi_create_string_utf8(env, abilityInfo.bundleName.c_str(), NAPI_AUTO_LENGTH, &proValue)); + NAPI_CALL(env, napi_set_named_property(env, result, "bundleName", proValue)); + + NAPI_CALL(env, napi_create_string_utf8(env, abilityInfo.name.c_str(), NAPI_AUTO_LENGTH, &proValue)); + NAPI_CALL(env, napi_set_named_property(env, result, "name", proValue)); + + NAPI_CALL(env, napi_create_string_utf8(env, abilityInfo.label.c_str(), NAPI_AUTO_LENGTH, &proValue)); + NAPI_CALL(env, napi_set_named_property(env, result, "label", proValue)); + + NAPI_CALL(env, napi_create_string_utf8(env, abilityInfo.description.c_str(), NAPI_AUTO_LENGTH, &proValue)); + NAPI_CALL(env, napi_set_named_property(env, result, "description", proValue)); + + NAPI_CALL(env, napi_create_string_utf8(env, abilityInfo.icon.c_str(), NAPI_AUTO_LENGTH, &proValue)); + NAPI_CALL(env, napi_set_named_property(env, result, "icon", proValue)); + + NAPI_CALL(env, napi_create_string_utf8(env, abilityInfo.moduleName.c_str(), NAPI_AUTO_LENGTH, &proValue)); + NAPI_CALL(env, napi_set_named_property(env, result, "moduleName", proValue)); + + NAPI_CALL(env, napi_create_string_utf8(env, abilityInfo.process.c_str(), NAPI_AUTO_LENGTH, &proValue)); + NAPI_CALL(env, napi_set_named_property(env, result, "process", proValue)); + + NAPI_CALL(env, napi_create_int32(env, static_cast(abilityInfo.type), &proValue)); + NAPI_CALL(env, napi_set_named_property(env, result, "type", proValue)); + + NAPI_CALL(env, napi_create_int32(env, static_cast(abilityInfo.orientation), &proValue)); + NAPI_CALL(env, napi_set_named_property(env, result, "orientation", proValue)); + + NAPI_CALL(env, napi_create_int32(env, static_cast(abilityInfo.launchMode), &proValue)); + NAPI_CALL(env, napi_set_named_property(env, result, "launchMode", proValue)); + + NAPI_CALL(env, napi_create_string_utf8(env, abilityInfo.uri.c_str(), NAPI_AUTO_LENGTH, &proValue)); + NAPI_CALL(env, napi_set_named_property(env, result, "uri", proValue)); + + NAPI_CALL(env, napi_create_string_utf8(env, abilityInfo.readPermission.c_str(), NAPI_AUTO_LENGTH, &proValue)); + NAPI_CALL(env, napi_set_named_property(env, result, "readPermission", proValue)); + + NAPI_CALL(env, napi_create_string_utf8(env, abilityInfo.writePermission.c_str(), NAPI_AUTO_LENGTH, &proValue)); + NAPI_CALL(env, napi_set_named_property(env, result, "writePermission", proValue)); + + NAPI_CALL(env, napi_create_string_utf8(env, abilityInfo.targetAbility.c_str(), NAPI_AUTO_LENGTH, &proValue)); + NAPI_CALL(env, napi_set_named_property(env, result, "targetAbility", proValue)); + + NAPI_CALL(env, napi_create_int32(env, abilityInfo.labelId, &proValue)); + NAPI_CALL(env, napi_set_named_property(env, result, "labelId", proValue)); + + NAPI_CALL(env, napi_create_int32(env, abilityInfo.descriptionId, &proValue)); + NAPI_CALL(env, napi_set_named_property(env, result, "descriptionId", proValue)); + + NAPI_CALL(env, napi_create_int32(env, abilityInfo.iconId, &proValue)); + NAPI_CALL(env, napi_set_named_property(env, result, "iconId", proValue)); + + NAPI_CALL(env, napi_create_int32(env, abilityInfo.formEntity, &proValue)); + NAPI_CALL(env, napi_set_named_property(env, result, "formEntity", proValue)); + + NAPI_CALL(env, napi_create_int32(env, abilityInfo.minFormHeight, &proValue)); + NAPI_CALL(env, napi_set_named_property(env, result, "minFormHeight", proValue)); + + NAPI_CALL(env, napi_create_int32(env, abilityInfo.defaultFormHeight, &proValue)); + NAPI_CALL(env, napi_set_named_property(env, result, "defaultFormHeight", proValue)); + + NAPI_CALL(env, napi_create_int32(env, abilityInfo.minFormWidth, &proValue)); + NAPI_CALL(env, napi_set_named_property(env, result, "minFormWidth", proValue)); + + NAPI_CALL(env, napi_create_int32(env, abilityInfo.defaultFormWidth, &proValue)); + NAPI_CALL(env, napi_set_named_property(env, result, "defaultFormWidth", proValue)); + + NAPI_CALL(env, napi_create_int32(env, abilityInfo.backgroundModes, &proValue)); + NAPI_CALL(env, napi_set_named_property(env, result, "backgroundModes", proValue)); + + NAPI_CALL(env, napi_create_int32(env, abilityInfo.subType, &proValue)); + NAPI_CALL(env, napi_set_named_property(env, result, "subType", proValue)); + + NAPI_CALL(env, napi_get_boolean(env, abilityInfo.isVisible, &proValue)); + NAPI_CALL(env, napi_set_named_property(env, result, "isVisible", proValue)); + + NAPI_CALL(env, napi_get_boolean(env, abilityInfo.formEnabled, &proValue)); + NAPI_CALL(env, napi_set_named_property(env, result, "formEnabled", proValue)); + + napi_value jsArrayPermissions = nullptr; + NAPI_CALL(env, napi_create_array(env, &jsArrayPermissions)); + for (size_t i = 0; i < abilityInfo.permissions.size(); i++) { + proValue = nullptr; + NAPI_CALL( + env, napi_create_string_utf8(env, abilityInfo.permissions.at(i).c_str(), NAPI_AUTO_LENGTH, &proValue)); + NAPI_CALL(env, napi_set_element(env, jsArrayPermissions, i, proValue)); + } + NAPI_CALL(env, napi_set_named_property(env, result, "permissions", jsArrayPermissions)); + + napi_value jsArrayDeviceCapabilities = nullptr; + NAPI_CALL(env, napi_create_array(env, &jsArrayDeviceCapabilities)); + for (size_t i = 0; i < abilityInfo.deviceCapabilities.size(); i++) { + proValue = nullptr; + NAPI_CALL(env, + napi_create_string_utf8(env, abilityInfo.deviceCapabilities.at(i).c_str(), NAPI_AUTO_LENGTH, &proValue)); + NAPI_CALL(env, napi_set_element(env, jsArrayDeviceCapabilities, i, proValue)); + } + NAPI_CALL(env, napi_set_named_property(env, result, "deviceCapabilities", jsArrayDeviceCapabilities)); + + napi_value jsArrayDeviceTypes = nullptr; + NAPI_CALL(env, napi_create_array(env, &jsArrayDeviceTypes)); + for (size_t i = 0; i < abilityInfo.deviceTypes.size(); i++) { + proValue = nullptr; + NAPI_CALL( + env, napi_create_string_utf8(env, abilityInfo.deviceTypes.at(i).c_str(), NAPI_AUTO_LENGTH, &proValue)); + NAPI_CALL(env, napi_set_element(env, jsArrayDeviceTypes, i, proValue)); + } + NAPI_CALL(env, napi_set_named_property(env, result, "deviceTypes", jsArrayDeviceTypes)); + + napi_value appInfo = nullptr; + appInfo = WrapAppInfo(env, abilityInfo.appInfo); + NAPI_CALL(env, napi_set_named_property(env, result, "applicationInfo", appInfo)); + HILOG_INFO("%{public}s end.", __func__); + return result; +} + +napi_value ConvertAbilityInfo(napi_env env, const AbilityInfo &abilityInfo) +{ + AbilityInfo_ temp; + SaveAbilityInfo(temp, abilityInfo); + return WrapAbilityInfo(env, temp); +} + +/** + * @brief GetAbilityInfo asynchronous processing function. + * + * @param env The environment that the Node-API call is invoked under. + * @param data Point to asynchronous processing of data. + */ +void GetAbilityInfoExecuteCB(napi_env env, void *data) +{ + HILOG_INFO("NAPI_GetApplicationInfo, worker pool thread execute."); + AbilityInfoCB *abilityInfoCB = static_cast(data); + if (abilityInfoCB == nullptr) { + HILOG_ERROR("NAPI_GetApplicationInfo, abilityInfoCB == nullptr"); + return; + } + + abilityInfoCB->cbBase.errCode = NAPI_ERR_NO_ERROR; + if (abilityInfoCB->cbBase.ability == nullptr) { + HILOG_ERROR("NAPI_GetApplicationInfo, ability == nullptr"); + abilityInfoCB->cbBase.errCode = NAPI_ERR_ACE_ABILITY; + return; + } + + if (!CheckAbilityType(&abilityInfoCB->cbBase)) { + HILOG_ERROR("NAPI_GetApplicationInfo,wrong ability type"); + abilityInfoCB->cbBase.errCode = NAPI_ERR_ABILITY_TYPE_INVALID; + return; + } + + std::shared_ptr abilityInfoPtr = abilityInfoCB->cbBase.ability->GetAbilityInfo(); + if (abilityInfoPtr != nullptr) { + SaveAbilityInfo(abilityInfoCB->abilityInfo, *abilityInfoPtr); + } else { + abilityInfoCB->cbBase.errCode = NAPI_ERR_ABILITY_CALL_INVALID; + } + HILOG_INFO("NAPI_GetApplicationInfo, worker pool thread execute end."); +} + +/** + * @brief The callback at the end of the asynchronous callback. + * + * @param env The environment that the Node-API call is invoked under. + * @param data Point to asynchronous processing of data. + */ +void GetAbilityInfoAsyncCompleteCB(napi_env env, napi_status status, void *data) +{ + HILOG_INFO("NAPI_GetApplicationInfo, main event thread complete."); + AbilityInfoCB *abilityInfoCB = static_cast(data); + napi_value callback = nullptr; + napi_value undefined = nullptr; + napi_value result[ARGS_TWO] = {nullptr}; + napi_value callResult = nullptr; + NAPI_CALL_RETURN_VOID(env, napi_get_undefined(env, &undefined)); + result[PARAM0] = GetCallbackErrorValue(env, abilityInfoCB->cbBase.errCode); + if (abilityInfoCB->cbBase.errCode == NAPI_ERR_NO_ERROR) { + result[PARAM1] = WrapAbilityInfo(env, abilityInfoCB->abilityInfo); + } else { + result[PARAM1] = WrapUndefinedToJS(env); + } + NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, abilityInfoCB->cbBase.cbInfo.callback, &callback)); + NAPI_CALL_RETURN_VOID(env, napi_call_function(env, undefined, callback, ARGS_TWO, &result[PARAM0], &callResult)); + + if (abilityInfoCB->cbBase.cbInfo.callback != nullptr) { + NAPI_CALL_RETURN_VOID(env, napi_delete_reference(env, abilityInfoCB->cbBase.cbInfo.callback)); + } + NAPI_CALL_RETURN_VOID(env, napi_delete_async_work(env, abilityInfoCB->cbBase.asyncWork)); + delete abilityInfoCB; + abilityInfoCB = nullptr; + HILOG_INFO("NAPI_GetApplicationInfo, main event thread complete end."); +} + +/** + * @brief The callback at the end of the Promise callback. + * + * @param env The environment that the Node-API call is invoked under. + * @param data Point to asynchronous processing of data. + */ +void GetAbilityInfoPromiseCompleteCB(napi_env env, napi_status status, void *data) +{ + HILOG_INFO("NAPI_GetApplicationInfo, main event thread complete."); + AbilityInfoCB *abilityInfoCB = static_cast(data); + napi_value result = nullptr; + if (abilityInfoCB->cbBase.errCode == NAPI_ERR_NO_ERROR) { + result = WrapAbilityInfo(env, abilityInfoCB->abilityInfo); + napi_resolve_deferred(env, abilityInfoCB->cbBase.deferred, result); + } else { + result = GetCallbackErrorValue(env, abilityInfoCB->cbBase.errCode); + napi_reject_deferred(env, abilityInfoCB->cbBase.deferred, result); + } + + napi_delete_async_work(env, abilityInfoCB->cbBase.asyncWork); + delete abilityInfoCB; + abilityInfoCB = nullptr; + HILOG_INFO("NAPI_GetApplicationInfo, main event thread complete end."); +} + +/** + * @brief GetAbilityInfo Async. + * + * @param env The environment that the Node-API call is invoked under. + * @param args Indicates the arguments passed into the callback. + * @param argcPromise Asynchronous data processing. + * @param abilityInfoCB Process data asynchronously. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value GetAbilityInfoAsync(napi_env env, napi_value *args, const size_t argCallback, AbilityInfoCB *abilityInfoCB) +{ + HILOG_INFO("%{public}s, asyncCallback.", __func__); + if (args == nullptr || abilityInfoCB == nullptr) { + HILOG_ERROR("%{public}s, param == nullptr.", __func__); + return nullptr; + } + napi_value resourceName = nullptr; + NAPI_CALL(env, napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName)); + + napi_valuetype valuetype = napi_undefined; + NAPI_CALL(env, napi_typeof(env, args[argCallback], &valuetype)); + if (valuetype == napi_function) { + NAPI_CALL(env, napi_create_reference(env, args[argCallback], 1, &abilityInfoCB->cbBase.cbInfo.callback)); + } + NAPI_CALL(env, + napi_create_async_work(env, + nullptr, + resourceName, + GetAbilityInfoExecuteCB, + GetAbilityInfoAsyncCompleteCB, + (void *)abilityInfoCB, + &abilityInfoCB->cbBase.asyncWork)); + NAPI_CALL(env, napi_queue_async_work(env, abilityInfoCB->cbBase.asyncWork)); + napi_value result = nullptr; + NAPI_CALL(env, napi_get_null(env, &result)); + HILOG_INFO("%{public}s, asyncCallback end.", __func__); + return result; +} + +/** + * @brief GetAbilityInfo Promise. + * + * @param env The environment that the Node-API call is invoked under. + * @param abilityInfoCB Process data asynchronously. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value GetAbilityInfoPromise(napi_env env, AbilityInfoCB *abilityInfoCB) +{ + HILOG_INFO("%{public}s, promise.", __func__); + if (abilityInfoCB == nullptr) { + HILOG_ERROR("%{public}s, param == nullptr.", __func__); + return nullptr; + } + napi_value resourceName = nullptr; + NAPI_CALL(env, napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName)); + napi_deferred deferred; + napi_value promise = nullptr; + NAPI_CALL(env, napi_create_promise(env, &deferred, &promise)); + abilityInfoCB->cbBase.deferred = deferred; + + NAPI_CALL(env, + napi_create_async_work(env, + nullptr, + resourceName, + GetAbilityInfoExecuteCB, + GetAbilityInfoPromiseCompleteCB, + (void *)abilityInfoCB, + &abilityInfoCB->cbBase.asyncWork)); + NAPI_CALL(env, napi_queue_async_work(env, abilityInfoCB->cbBase.asyncWork)); + HILOG_INFO("%{public}s, promise end.", __func__); + return promise; +} + +/** + * @brief GetAbilityInfo processing function. + * + * @param env The environment that the Node-API call is invoked under. + * @param abilityInfoCB Process data asynchronously. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value GetAbilityInfoWrap(napi_env env, napi_callback_info info, AbilityInfoCB *abilityInfoCB) +{ + HILOG_INFO("%{public}s, asyncCallback.", __func__); + if (abilityInfoCB == nullptr) { + HILOG_ERROR("%{public}s, abilityInfoCB == nullptr.", __func__); + return nullptr; + } + + size_t argcAsync = 1; + const size_t argcPromise = 0; + const size_t argCountWithAsync = argcPromise + ARGS_ASYNC_COUNT; + napi_value args[ARGS_MAX_COUNT] = {nullptr}; + napi_value ret = nullptr; + + NAPI_CALL(env, napi_get_cb_info(env, info, &argcAsync, args, nullptr, nullptr)); + if (argcAsync > argCountWithAsync || argcAsync > ARGS_MAX_COUNT) { + HILOG_ERROR("%{public}s, Wrong argument count.", __func__); + return nullptr; + } + + if (argcAsync > argcPromise) { + ret = GetAbilityInfoAsync(env, args, 0, abilityInfoCB); + } else { + ret = GetAbilityInfoPromise(env, abilityInfoCB); + } + HILOG_INFO("%{public}s, asyncCallback end.", __func__); + return ret; +} + +/** + * @brief Obtains information about the current ability. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_GetAbilityInfoCommon(napi_env env, napi_callback_info info, AbilityType abilityType) +{ + HILOG_INFO("%{public}s called.", __func__); + AbilityInfoCB *abilityInfoCB = CreateAbilityInfoCBInfo(env); + if (abilityInfoCB == nullptr) { + return WrapVoidToJS(env); + } + + abilityInfoCB->cbBase.errCode = NAPI_ERR_NO_ERROR; + abilityInfoCB->cbBase.abilityType = abilityType; + napi_value ret = GetAbilityInfoWrap(env, info, abilityInfoCB); + if (ret == nullptr) { + HILOG_ERROR("%{public}s ret == nullptr", __func__); + if (abilityInfoCB != nullptr) { + delete abilityInfoCB; + abilityInfoCB = nullptr; + } + ret = WrapVoidToJS(env); + } + HILOG_INFO("%{public}s end.", __func__); + return ret; +} + +/** + * @brief Create asynchronous data. + * + * @param env The environment that the Node-API call is invoked under. + * + * @return Return a pointer to HapModuleInfoCB on success, nullptr on failure. + */ +HapModuleInfoCB *CreateHapModuleInfoCBInfo(napi_env env) +{ + HILOG_INFO("%{public}s called.", __func__); + napi_value global = nullptr; + NAPI_CALL(env, napi_get_global(env, &global)); + + napi_value abilityObj = nullptr; + NAPI_CALL(env, napi_get_named_property(env, global, "ability", &abilityObj)); + + Ability *ability = nullptr; + NAPI_CALL(env, napi_get_value_external(env, abilityObj, (void **)&ability)); + + HapModuleInfoCB *hapModuleInfoCB = new (std::nothrow) HapModuleInfoCB; + if (hapModuleInfoCB == nullptr) { + HILOG_ERROR("%{public}s, hapModuleInfoCB == nullptr.", __func__); + return nullptr; + } + hapModuleInfoCB->cbBase.cbInfo.env = env; + hapModuleInfoCB->cbBase.asyncWork = nullptr; + hapModuleInfoCB->cbBase.deferred = nullptr; + hapModuleInfoCB->cbBase.ability = ability; + + HILOG_INFO("%{public}s end.", __func__); + return hapModuleInfoCB; +} + +void SaveHapModuleInfo(HapModuleInfo_ &hapModuleInfo, const HapModuleInfo &hapModuleInfoOrg) +{ + HILOG_INFO("%{public}s called.", __func__); + hapModuleInfo.name = hapModuleInfoOrg.name; + hapModuleInfo.description = hapModuleInfoOrg.description; + hapModuleInfo.icon = hapModuleInfoOrg.iconPath; + hapModuleInfo.label = hapModuleInfoOrg.label; + hapModuleInfo.backgroundImg = hapModuleInfoOrg.backgroundImg; + hapModuleInfo.moduleName = hapModuleInfoOrg.moduleName; + hapModuleInfo.supportedModes = hapModuleInfoOrg.supportedModes; + hapModuleInfo.descriptionId = 0; // no data + hapModuleInfo.labelId = 0; // no data + hapModuleInfo.iconId = 0; // no data + hapModuleInfo.mainAbilityName = ""; // no data + hapModuleInfo.installationFree = false; // no data + + for (size_t i = 0; i < hapModuleInfoOrg.reqCapabilities.size(); i++) { + hapModuleInfo.reqCapabilities.emplace_back(hapModuleInfoOrg.reqCapabilities.at(i)); + } + + for (size_t i = 0; i < hapModuleInfoOrg.deviceTypes.size(); i++) { + hapModuleInfo.deviceTypes.emplace_back(hapModuleInfoOrg.deviceTypes.at(i)); + } + + for (size_t i = 0; i < hapModuleInfoOrg.abilityInfos.size(); i++) { + AbilityInfo_ abilityInfo; + SaveAbilityInfo(abilityInfo, hapModuleInfoOrg.abilityInfos.at(i)); + hapModuleInfo.abilityInfos.emplace_back(abilityInfo); + } + HILOG_INFO("%{public}s end.", __func__); +} + +napi_value WrapHapModuleInfo(napi_env env, const HapModuleInfoCB &hapModuleInfoCB) +{ + HILOG_INFO("%{public}s called.", __func__); + napi_value result = nullptr; + napi_value proValue = nullptr; + NAPI_CALL(env, napi_create_object(env, &result)); + NAPI_CALL( + env, napi_create_string_utf8(env, hapModuleInfoCB.hapModuleInfo.name.c_str(), NAPI_AUTO_LENGTH, &proValue)); + NAPI_CALL(env, napi_set_named_property(env, result, "name", proValue)); + + NAPI_CALL(env, + napi_create_string_utf8(env, hapModuleInfoCB.hapModuleInfo.description.c_str(), NAPI_AUTO_LENGTH, &proValue)); + NAPI_CALL(env, napi_set_named_property(env, result, "description", proValue)); + + NAPI_CALL( + env, napi_create_string_utf8(env, hapModuleInfoCB.hapModuleInfo.icon.c_str(), NAPI_AUTO_LENGTH, &proValue)); + NAPI_CALL(env, napi_set_named_property(env, result, "icon", proValue)); + + NAPI_CALL( + env, napi_create_string_utf8(env, hapModuleInfoCB.hapModuleInfo.label.c_str(), NAPI_AUTO_LENGTH, &proValue)); + NAPI_CALL(env, napi_set_named_property(env, result, "label", proValue)); + + NAPI_CALL(env, + napi_create_string_utf8(env, hapModuleInfoCB.hapModuleInfo.backgroundImg.c_str(), NAPI_AUTO_LENGTH, &proValue)); + NAPI_CALL(env, napi_set_named_property(env, result, "backgroundImg", proValue)); + + NAPI_CALL(env, + napi_create_string_utf8(env, hapModuleInfoCB.hapModuleInfo.moduleName.c_str(), NAPI_AUTO_LENGTH, &proValue)); + NAPI_CALL(env, napi_set_named_property(env, result, "moduleName", proValue)); + + NAPI_CALL(env, napi_create_int32(env, hapModuleInfoCB.hapModuleInfo.supportedModes, &proValue)); + NAPI_CALL(env, napi_set_named_property(env, result, "supportedModes", proValue)); + + NAPI_CALL(env, napi_create_int32(env, hapModuleInfoCB.hapModuleInfo.descriptionId, &proValue)); + NAPI_CALL(env, napi_set_named_property(env, result, "descriptionId", proValue)); + + NAPI_CALL(env, napi_create_int32(env, hapModuleInfoCB.hapModuleInfo.labelId, &proValue)); + NAPI_CALL(env, napi_set_named_property(env, result, "labelId", proValue)); + + NAPI_CALL(env, napi_create_int32(env, hapModuleInfoCB.hapModuleInfo.iconId, &proValue)); + NAPI_CALL(env, napi_set_named_property(env, result, "iconId", proValue)); + + NAPI_CALL(env, + napi_create_string_utf8( + env, hapModuleInfoCB.hapModuleInfo.mainAbilityName.c_str(), NAPI_AUTO_LENGTH, &proValue)); + NAPI_CALL(env, napi_set_named_property(env, result, "mainAbilityName", proValue)); + + NAPI_CALL(env, napi_get_boolean(env, hapModuleInfoCB.hapModuleInfo.installationFree, &proValue)); + NAPI_CALL(env, napi_set_named_property(env, result, "installationFree", proValue)); + + napi_value jsArrayreqCapabilities = nullptr; + NAPI_CALL(env, napi_create_array(env, &jsArrayreqCapabilities)); + for (size_t i = 0; i < hapModuleInfoCB.hapModuleInfo.reqCapabilities.size(); i++) { + proValue = nullptr; + NAPI_CALL(env, + napi_create_string_utf8( + env, hapModuleInfoCB.hapModuleInfo.reqCapabilities.at(i).c_str(), NAPI_AUTO_LENGTH, &proValue)); + NAPI_CALL(env, napi_set_element(env, jsArrayreqCapabilities, i, proValue)); + } + NAPI_CALL(env, napi_set_named_property(env, result, "reqCapabilities", jsArrayreqCapabilities)); + + napi_value jsArraydeviceTypes = nullptr; + NAPI_CALL(env, napi_create_array(env, &jsArraydeviceTypes)); + for (size_t i = 0; i < hapModuleInfoCB.hapModuleInfo.deviceTypes.size(); i++) { + proValue = nullptr; + NAPI_CALL(env, + napi_create_string_utf8( + env, hapModuleInfoCB.hapModuleInfo.deviceTypes.at(i).c_str(), NAPI_AUTO_LENGTH, &proValue)); + NAPI_CALL(env, napi_set_element(env, jsArraydeviceTypes, i, proValue)); + } + NAPI_CALL(env, napi_set_named_property(env, result, "deviceTypes", jsArraydeviceTypes)); + + napi_value abilityInfos = nullptr; + NAPI_CALL(env, napi_create_array(env, &abilityInfos)); + for (size_t i = 0; i < hapModuleInfoCB.hapModuleInfo.abilityInfos.size(); i++) { + napi_value abilityInfo = nullptr; + abilityInfo = WrapAbilityInfo(env, hapModuleInfoCB.hapModuleInfo.abilityInfos.at(i)); + NAPI_CALL(env, napi_set_element(env, abilityInfos, i, abilityInfo)); + } + NAPI_CALL(env, napi_set_named_property(env, result, "abilityInfos", abilityInfos)); + HILOG_INFO("%{public}s end.", __func__); + return result; +} + +void GetHapModuleInfoExecuteCB(napi_env env, void *data) +{ + HILOG_INFO("NAPI_GetHapModuleInfo, worker pool thread execute."); + HapModuleInfoCB *hapModuleInfoCB = static_cast(data); + if (hapModuleInfoCB == nullptr) { + HILOG_ERROR("NAPI_GetHapModuleInfo, hapModuleInfoCB == nullptr"); + return; + } + + hapModuleInfoCB->cbBase.errCode = NAPI_ERR_NO_ERROR; + if (hapModuleInfoCB->cbBase.ability == nullptr) { + HILOG_ERROR("NAPI_GetHapModuleInfo, ability == nullptr"); + hapModuleInfoCB->cbBase.errCode = NAPI_ERR_ACE_ABILITY; + return; + } + + if (!CheckAbilityType(&hapModuleInfoCB->cbBase)) { + HILOG_ERROR("NAPI_GetHapModuleInfo,wrong ability type"); + hapModuleInfoCB->cbBase.errCode = NAPI_ERR_ABILITY_TYPE_INVALID; + return; + } + + std::shared_ptr hapModuleInfoPtr = hapModuleInfoCB->cbBase.ability->GetHapModuleInfo(); + if (hapModuleInfoPtr != nullptr) { + SaveHapModuleInfo(hapModuleInfoCB->hapModuleInfo, *hapModuleInfoPtr); + } else { + hapModuleInfoCB->cbBase.errCode = NAPI_ERR_ABILITY_CALL_INVALID; + } + HILOG_INFO("NAPI_GetHapModuleInfo, worker pool thread execute end."); +} + +void GetHapModuleInfoAsyncCompleteCB(napi_env env, napi_status status, void *data) +{ + HILOG_INFO("NAPI_GetHapModuleInfo, main event thread complete."); + HapModuleInfoCB *hapModuleInfoCB = static_cast(data); + napi_value callback = nullptr; + napi_value undefined = nullptr; + napi_value result[ARGS_TWO] = {nullptr}; + napi_value callResult = nullptr; + NAPI_CALL_RETURN_VOID(env, napi_get_undefined(env, &undefined)); + result[PARAM0] = GetCallbackErrorValue(env, hapModuleInfoCB->cbBase.errCode); + if (hapModuleInfoCB->cbBase.errCode == NAPI_ERR_NO_ERROR) { + result[PARAM1] = WrapHapModuleInfo(env, *hapModuleInfoCB); + } else { + result[PARAM1] = WrapUndefinedToJS(env); + } + NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, hapModuleInfoCB->cbBase.cbInfo.callback, &callback)); + NAPI_CALL_RETURN_VOID(env, napi_call_function(env, undefined, callback, ARGS_TWO, &result[PARAM0], &callResult)); + + if (hapModuleInfoCB->cbBase.cbInfo.callback != nullptr) { + NAPI_CALL_RETURN_VOID(env, napi_delete_reference(env, hapModuleInfoCB->cbBase.cbInfo.callback)); + } + NAPI_CALL_RETURN_VOID(env, napi_delete_async_work(env, hapModuleInfoCB->cbBase.asyncWork)); + delete hapModuleInfoCB; + hapModuleInfoCB = nullptr; + HILOG_INFO("NAPI_GetHapModuleInfo, main event thread complete end."); +} + +void GetHapModuleInfoPromiseCompleteCB(napi_env env, napi_status status, void *data) +{ + HILOG_INFO("NAPI_GetHapModuleInfo, main event thread complete."); + HapModuleInfoCB *hapModuleInfoCB = static_cast(data); + napi_value result = nullptr; + if (hapModuleInfoCB->cbBase.errCode == NAPI_ERR_NO_ERROR) { + result = WrapHapModuleInfo(env, *hapModuleInfoCB); + napi_resolve_deferred(env, hapModuleInfoCB->cbBase.deferred, result); + } else { + result = GetCallbackErrorValue(env, hapModuleInfoCB->cbBase.errCode); + napi_reject_deferred(env, hapModuleInfoCB->cbBase.deferred, result); + } + + napi_delete_async_work(env, hapModuleInfoCB->cbBase.asyncWork); + delete hapModuleInfoCB; + hapModuleInfoCB = nullptr; + HILOG_INFO("NAPI_GetHapModuleInfo, main event thread complete end."); +} + +/** + * @brief GetHapModuleInfo Async. + * + * @param env The environment that the Node-API call is invoked under. + * @param args Indicates the arguments passed into the callback. + * @param argcPromise Asynchronous data processing. + * @param hapModuleInfoCB Process data asynchronously. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value GetHapModuleInfoAsync( + napi_env env, napi_value *args, const size_t argCallback, HapModuleInfoCB *hapModuleInfoCB) +{ + HILOG_INFO("%{public}s, asyncCallback.", __func__); + if (args == nullptr || hapModuleInfoCB == nullptr) { + HILOG_ERROR("%{public}s, param == nullptr.", __func__); + return nullptr; + } + napi_value resourceName = nullptr; + NAPI_CALL(env, napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName)); + + napi_valuetype valuetype = napi_undefined; + NAPI_CALL(env, napi_typeof(env, args[argCallback], &valuetype)); + if (valuetype == napi_function) { + NAPI_CALL(env, napi_create_reference(env, args[argCallback], 1, &hapModuleInfoCB->cbBase.cbInfo.callback)); + } + NAPI_CALL(env, + napi_create_async_work(env, + nullptr, + resourceName, + GetHapModuleInfoExecuteCB, + GetHapModuleInfoAsyncCompleteCB, + (void *)hapModuleInfoCB, + &hapModuleInfoCB->cbBase.asyncWork)); + NAPI_CALL(env, napi_queue_async_work(env, hapModuleInfoCB->cbBase.asyncWork)); + napi_value result = nullptr; + NAPI_CALL(env, napi_get_null(env, &result)); + HILOG_INFO("%{public}s, asyncCallback end.", __func__); + return result; +} + +/** + * @brief GetHapModuleInfo Promise. + * + * @param env The environment that the Node-API call is invoked under. + * @param hapModuleInfoCB Process data asynchronously. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value GetHapModuleInfoPromise(napi_env env, HapModuleInfoCB *hapModuleInfoCB) +{ + HILOG_INFO("%{public}s, promise.", __func__); + if (hapModuleInfoCB == nullptr) { + HILOG_ERROR("%{public}s, param == nullptr.", __func__); + return nullptr; + } + napi_value resourceName = nullptr; + NAPI_CALL(env, napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName)); + napi_deferred deferred; + napi_value promise = nullptr; + NAPI_CALL(env, napi_create_promise(env, &deferred, &promise)); + hapModuleInfoCB->cbBase.deferred = deferred; + + NAPI_CALL(env, + napi_create_async_work(env, + nullptr, + resourceName, + GetHapModuleInfoExecuteCB, + GetHapModuleInfoPromiseCompleteCB, + (void *)hapModuleInfoCB, + &hapModuleInfoCB->cbBase.asyncWork)); + NAPI_CALL(env, napi_queue_async_work(env, hapModuleInfoCB->cbBase.asyncWork)); + HILOG_INFO("%{public}s, promise end.", __func__); + return promise; +} + +napi_value GetHapModuleInfoWrap(napi_env env, napi_callback_info info, HapModuleInfoCB *hapModuleInfoCB) +{ + HILOG_INFO("%{public}s, asyncCallback.", __func__); + if (hapModuleInfoCB == nullptr) { + HILOG_ERROR("%{public}s, hapModuleInfoCB == nullptr.", __func__); + return nullptr; + } + + size_t argcAsync = 1; + const size_t argcPromise = 0; + const size_t argCountWithAsync = argcPromise + ARGS_ASYNC_COUNT; + napi_value args[ARGS_MAX_COUNT] = {nullptr}; + napi_value ret = nullptr; + + NAPI_CALL(env, napi_get_cb_info(env, info, &argcAsync, args, nullptr, nullptr)); + if (argcAsync > argCountWithAsync || argcAsync > ARGS_MAX_COUNT) { + HILOG_ERROR("%{public}s, Wrong argument count.", __func__); + return nullptr; + } + + if (argcAsync > argcPromise) { + ret = GetHapModuleInfoAsync(env, args, 0, hapModuleInfoCB); + } else { + ret = GetHapModuleInfoPromise(env, hapModuleInfoCB); + } + HILOG_INFO("%{public}s, asyncCallback end.", __func__); + return ret; +} + +/** + * @brief Obtains the HapModuleInfo object of the application. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_GetHapModuleInfoCommon(napi_env env, napi_callback_info info, AbilityType abilityType) +{ + HILOG_INFO("%{public}s called.", __func__); + HapModuleInfoCB *hapModuleInfoCB = CreateHapModuleInfoCBInfo(env); + if (hapModuleInfoCB == nullptr) { + return WrapVoidToJS(env); + } + + hapModuleInfoCB->cbBase.errCode = NAPI_ERR_NO_ERROR; + hapModuleInfoCB->cbBase.abilityType = abilityType; + napi_value ret = GetHapModuleInfoWrap(env, info, hapModuleInfoCB); + if (ret == nullptr) { + HILOG_ERROR("%{public}s ret == nullptr", __func__); + if (hapModuleInfoCB != nullptr) { + delete hapModuleInfoCB; + hapModuleInfoCB = nullptr; + } + ret = WrapVoidToJS(env); + } + HILOG_INFO("%{public}s end.", __func__); + return ret; +} + +/** + * @brief Create asynchronous data. + * + * @param env The environment that the Node-API call is invoked under. + * + * @return Return a pointer to AsyncCallbackInfo on success, nullptr on failure + */ +AsyncCallbackInfo *CreateAsyncCallbackInfo(napi_env env) +{ + HILOG_INFO("%{public}s called.", __func__); + if (env == nullptr) { + HILOG_INFO("%{public}s env == nullptr.", __func__); + return nullptr; + } + + napi_status ret; + napi_value global = 0; + const napi_extended_error_info *errorInfo = nullptr; + ret = napi_get_global(env, &global); + if (ret != napi_ok) { + napi_get_last_error_info(env, &errorInfo); + HILOG_ERROR("%{public}s get_global=%{public}d err:%{public}s", __func__, ret, errorInfo->error_message); + } + + napi_value abilityObj = 0; + ret = napi_get_named_property(env, global, "ability", &abilityObj); + if (ret != napi_ok) { + napi_get_last_error_info(env, &errorInfo); + HILOG_ERROR("%{public}s get_named_property=%{public}d err:%{public}s", __func__, ret, errorInfo->error_message); + } + + Ability *ability = nullptr; + ret = napi_get_value_external(env, abilityObj, (void **)&ability); + if (ret != napi_ok) { + napi_get_last_error_info(env, &errorInfo); + HILOG_ERROR("%{public}s get_value_external=%{public}d err:%{public}s", __func__, ret, errorInfo->error_message); + } + + AsyncCallbackInfo *asyncCallbackInfo = new (std::nothrow) AsyncCallbackInfo; + if (asyncCallbackInfo == nullptr) { + HILOG_ERROR("%{public}s asyncCallbackInfo == nullptr", __func__); + return nullptr; + } + asyncCallbackInfo->cbInfo.env = env; + asyncCallbackInfo->asyncWork = nullptr; + asyncCallbackInfo->deferred = nullptr; + asyncCallbackInfo->ability = ability; + asyncCallbackInfo->native_result = false; + asyncCallbackInfo->errCode = NAPI_ERR_NO_ERROR; + asyncCallbackInfo->abilityType = AbilityType::UNKNOWN; + + HILOG_INFO("%{public}s end.", __func__); + return asyncCallbackInfo; +} + +void GetContextAsyncExecuteCB(napi_env env, void *data) +{ + HILOG_INFO("GetContextAsync, worker pool thread execute."); + AsyncCallbackInfo *asyncCallbackInfo = static_cast(data); + if (asyncCallbackInfo == nullptr) { + HILOG_ERROR("GetContextAsync, asyncCallbackInfo == nullptr"); + return; + } + asyncCallbackInfo->errCode = NAPI_ERR_NO_ERROR; + if (asyncCallbackInfo->ability == nullptr) { + HILOG_ERROR("GetContextAsync, ability == nullptr"); + asyncCallbackInfo->errCode = NAPI_ERR_ACE_ABILITY; + return; + } + + if (!CheckAbilityType(asyncCallbackInfo)) { + HILOG_ERROR("GetContextAsync,wrong ability type"); + asyncCallbackInfo->errCode = NAPI_ERR_ABILITY_TYPE_INVALID; + return; + } + HILOG_INFO("GetContextAsync, worker pool thread execute end."); +} + +napi_value GetContextAsync( + napi_env env, napi_value *args, const size_t argCallback, AsyncCallbackInfo *asyncCallbackInfo) +{ + HILOG_INFO("%{public}s, asyncCallback.", __func__); + if (args == nullptr || asyncCallbackInfo == nullptr) { + HILOG_ERROR("%{public}s, param == nullptr.", __func__); + return nullptr; + } + napi_value resourceName = 0; + napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName); + + napi_valuetype valuetype = napi_undefined; + napi_typeof(env, args[argCallback], &valuetype); + if (valuetype == napi_function) { + napi_create_reference(env, args[argCallback], 1, &asyncCallbackInfo->cbInfo.callback); + } + napi_create_async_work( + env, + nullptr, + resourceName, + GetContextAsyncExecuteCB, + [](napi_env env, napi_status status, void *data) { + HILOG_INFO("GetContextAsync, main event thread complete."); + AsyncCallbackInfo *asyncCallbackInfo = static_cast(data); + napi_value callback = 0; + napi_value undefined = 0; + napi_value result[ARGS_TWO] = {0}; + napi_value callResult = 0; + napi_get_undefined(env, &undefined); + result[PARAM0] = GetCallbackErrorValue(env, asyncCallbackInfo->errCode); + if (asyncCallbackInfo->errCode == NAPI_ERR_NO_ERROR) { + napi_new_instance(env, g_classContext, 0, nullptr, &result[PARAM1]); + } else { + result[PARAM1] = WrapUndefinedToJS(env); + } + napi_get_reference_value(env, asyncCallbackInfo->cbInfo.callback, &callback); + napi_call_function(env, undefined, callback, ARGS_TWO, &result[PARAM0], &callResult); + + if (asyncCallbackInfo->cbInfo.callback != nullptr) { + napi_delete_reference(env, asyncCallbackInfo->cbInfo.callback); + } + napi_delete_async_work(env, asyncCallbackInfo->asyncWork); + delete asyncCallbackInfo; + asyncCallbackInfo = nullptr; + HILOG_INFO("GetContextAsync, main event thread complete end."); + }, + (void *)asyncCallbackInfo, + &asyncCallbackInfo->asyncWork); + napi_queue_async_work(env, asyncCallbackInfo->asyncWork); + napi_value result = 0; + napi_get_null(env, &result); + HILOG_INFO("%{public}s, asyncCallback end.", __func__); + return result; +} + +napi_value GetContextPromise(napi_env env, AsyncCallbackInfo *asyncCallbackInfo) +{ + HILOG_INFO("%{public}s, promise.", __func__); + if (asyncCallbackInfo == nullptr) { + HILOG_ERROR("%{public}s, param == nullptr.", __func__); + return nullptr; + } + napi_value resourceName = 0; + napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName); + napi_deferred deferred; + napi_value promise = 0; + napi_create_promise(env, &deferred, &promise); + asyncCallbackInfo->deferred = deferred; + + napi_create_async_work( + env, + nullptr, + resourceName, + GetContextAsyncExecuteCB, + [](napi_env env, napi_status status, void *data) { + HILOG_INFO("GetContextPromise, main event thread complete."); + AsyncCallbackInfo *asyncCallbackInfo = static_cast(data); + napi_value result = nullptr; + if (asyncCallbackInfo->errCode == NAPI_ERR_NO_ERROR) { + napi_new_instance(env, g_classContext, 0, nullptr, &result); + napi_resolve_deferred(env, asyncCallbackInfo->deferred, result); + } else { + result = GetCallbackErrorValue(env, asyncCallbackInfo->errCode); + napi_reject_deferred(env, asyncCallbackInfo->deferred, result); + } + + napi_delete_async_work(env, asyncCallbackInfo->asyncWork); + delete asyncCallbackInfo; + asyncCallbackInfo = nullptr; + HILOG_INFO("GetContextPromise, main event thread complete end."); + }, + (void *)asyncCallbackInfo, + &asyncCallbackInfo->asyncWork); + napi_queue_async_work(env, asyncCallbackInfo->asyncWork); + HILOG_INFO("%{public}s, promise end.", __func__); + return promise; +} + +/** + * @brief GetContext processing function. + * + * @param env The environment that the Node-API call is invoked under. + * @param asyncCallbackInfo Process data asynchronously. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value GetContextWrap(napi_env env, napi_callback_info info, AsyncCallbackInfo *asyncCallbackInfo) +{ + HILOG_INFO("%{public}s, called.", __func__); + if (asyncCallbackInfo == nullptr) { + HILOG_ERROR("%{public}s, asyncCallbackInfo == nullptr.", __func__); + return nullptr; + } + + asyncCallbackInfo->errCode = NAPI_ERR_NO_ERROR; + if (!CheckAbilityType(asyncCallbackInfo)) { + HILOG_ERROR("%{public}s,wrong ability type", __func__); + asyncCallbackInfo->errCode = NAPI_ERR_ABILITY_TYPE_INVALID; + return nullptr; + } + + napi_value result = nullptr; + napi_new_instance(env, g_classContext, 0, nullptr, &result); + HILOG_INFO("%{public}s, end.", __func__); + return result; +} + +/** + * @brief Get context. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_GetContextCommon(napi_env env, napi_callback_info info, AbilityType abilityType) +{ + HILOG_INFO("%{public}s, called.", __func__); + AsyncCallbackInfo *asyncCallbackInfo = CreateAsyncCallbackInfo(env); + if (asyncCallbackInfo == nullptr) { + HILOG_ERROR("%{public}s asyncCallbackInfo == nullptr", __func__); + return WrapVoidToJS(env); + } + + asyncCallbackInfo->errCode = NAPI_ERR_NO_ERROR; + asyncCallbackInfo->abilityType = abilityType; + napi_value ret = GetContextWrap(env, info, asyncCallbackInfo); + + delete asyncCallbackInfo; + asyncCallbackInfo = nullptr; + + if (ret == nullptr) { + ret = WrapVoidToJS(env); + HILOG_ERROR("%{public}s ret == nullptr", __func__); + } else { + HILOG_INFO("%{public}s, end.", __func__); + } + return ret; +} + +void GetWantExecuteCB(napi_env env, void *data) +{ + HILOG_INFO("%{public}s, called.", __func__); + AsyncCallbackInfo *asyncCallbackInfo = static_cast(data); + if (asyncCallbackInfo == nullptr) { + HILOG_ERROR("%{public}s, asyncCallbackInfo == nullptr", __func__); + return; + } + asyncCallbackInfo->errCode = NAPI_ERR_NO_ERROR; + if (asyncCallbackInfo->ability == nullptr) { + HILOG_ERROR("%{public}s, ability == nullptr", __func__); + asyncCallbackInfo->errCode = NAPI_ERR_ACE_ABILITY; + return; + } + + if (!CheckAbilityType(asyncCallbackInfo)) { + HILOG_ERROR("%{public}s, wrong ability type", __func__); + asyncCallbackInfo->errCode = NAPI_ERR_ABILITY_TYPE_INVALID; + return; + } + + std::shared_ptr ptrWant = asyncCallbackInfo->ability->GetWant(); + if (ptrWant != nullptr) { + asyncCallbackInfo->param.want = *ptrWant; + } else { + asyncCallbackInfo->errCode = NAPI_ERR_ABILITY_CALL_INVALID; + } + HILOG_INFO("%{public}s, end.", __func__); +} + +napi_value GetWantAsync(napi_env env, napi_value *args, const size_t argCallback, AsyncCallbackInfo *asyncCallbackInfo) +{ + HILOG_INFO("%{public}s, asyncCallback.", __func__); + if (args == nullptr || asyncCallbackInfo == nullptr) { + HILOG_ERROR("%{public}s, param == nullptr.", __func__); + return nullptr; + } + napi_value resourceName = 0; + napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName); + + napi_valuetype valuetype = napi_undefined; + napi_typeof(env, args[argCallback], &valuetype); + if (valuetype == napi_function) { + napi_create_reference(env, args[argCallback], 1, &asyncCallbackInfo->cbInfo.callback); + } + napi_create_async_work( + env, + nullptr, + resourceName, + GetWantExecuteCB, + [](napi_env env, napi_status status, void *data) { + HILOG_INFO("GetWantAsync, main event thread complete."); + AsyncCallbackInfo *asyncCallbackInfo = static_cast(data); + napi_value callback = 0; + napi_value undefined = 0; + napi_value result[ARGS_TWO] = {0}; + napi_value callResult = 0; + napi_get_undefined(env, &undefined); + result[PARAM0] = GetCallbackErrorValue(env, asyncCallbackInfo->errCode); + if (asyncCallbackInfo->errCode == NAPI_ERR_NO_ERROR) { + result[PARAM1] = WrapWant(env, asyncCallbackInfo->param.want); + } else { + result[PARAM1] = WrapUndefinedToJS(env); + } + napi_get_reference_value(env, asyncCallbackInfo->cbInfo.callback, &callback); + napi_call_function(env, undefined, callback, ARGS_TWO, &result[PARAM0], &callResult); + + if (asyncCallbackInfo->cbInfo.callback != nullptr) { + napi_delete_reference(env, asyncCallbackInfo->cbInfo.callback); + } + napi_delete_async_work(env, asyncCallbackInfo->asyncWork); + delete asyncCallbackInfo; + asyncCallbackInfo = nullptr; + HILOG_INFO("GetWantAsync, main event thread complete end."); + }, + (void *)asyncCallbackInfo, + &asyncCallbackInfo->asyncWork); + napi_queue_async_work(env, asyncCallbackInfo->asyncWork); + napi_value result = 0; + napi_get_null(env, &result); + HILOG_INFO("%{public}s, asyncCallback end.", __func__); + return result; +} + +napi_value GetWantPromise(napi_env env, AsyncCallbackInfo *asyncCallbackInfo) +{ + HILOG_INFO("%{public}s, promise.", __func__); + if (asyncCallbackInfo == nullptr) { + HILOG_ERROR("%{public}s, param == nullptr.", __func__); + return nullptr; + } + napi_value resourceName = 0; + napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName); + napi_deferred deferred; + napi_value promise = 0; + napi_create_promise(env, &deferred, &promise); + asyncCallbackInfo->deferred = deferred; + + napi_create_async_work( + env, + nullptr, + resourceName, + GetWantExecuteCB, + [](napi_env env, napi_status status, void *data) { + HILOG_INFO("GetWantPromise, main event thread complete."); + AsyncCallbackInfo *asyncCallbackInfo = static_cast(data); + napi_value result = nullptr; + if (asyncCallbackInfo->errCode == NAPI_ERR_NO_ERROR) { + result = WrapWant(env, asyncCallbackInfo->param.want); + napi_resolve_deferred(env, asyncCallbackInfo->deferred, result); + } else { + result = GetCallbackErrorValue(env, asyncCallbackInfo->errCode); + napi_reject_deferred(env, asyncCallbackInfo->deferred, result); + } + + napi_delete_async_work(env, asyncCallbackInfo->asyncWork); + delete asyncCallbackInfo; + asyncCallbackInfo = nullptr; + HILOG_INFO("GetWantPromise, main event thread complete end."); + }, + (void *)asyncCallbackInfo, + &asyncCallbackInfo->asyncWork); + napi_queue_async_work(env, asyncCallbackInfo->asyncWork); + HILOG_INFO("%{public}s, promise end.", __func__); + return promise; +} + +/** + * @brief GetWantWrap processing function. + * + * @param env The environment that the Node-API call is invoked under. + * @param asyncCallbackInfo Process data asynchronously. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value GetWantWrap(napi_env env, napi_callback_info info, AsyncCallbackInfo *asyncCallbackInfo) +{ + HILOG_INFO("%{public}s, asyncCallback.", __func__); + if (asyncCallbackInfo == nullptr) { + HILOG_ERROR("%{public}s, asyncCallbackInfo == nullptr.", __func__); + return nullptr; + } + + size_t argcAsync = 1; + const size_t argcPromise = 0; + const size_t argCountWithAsync = argcPromise + ARGS_ASYNC_COUNT; + napi_value args[ARGS_MAX_COUNT] = {nullptr}; + napi_value ret = 0; + + NAPI_CALL(env, napi_get_cb_info(env, info, &argcAsync, args, nullptr, nullptr)); + if (argcAsync > argCountWithAsync || argcAsync > ARGS_MAX_COUNT) { + HILOG_ERROR("%{public}s, Wrong argument count.", __func__); + return nullptr; + } + + if (argcAsync > argcPromise) { + ret = GetWantAsync(env, args, 0, asyncCallbackInfo); + } else { + ret = GetWantPromise(env, asyncCallbackInfo); + } + HILOG_INFO("%{public}s, asyncCallback end.", __func__); + return ret; +} + +/** + * @brief Get want. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_GetWantCommon(napi_env env, napi_callback_info info, AbilityType abilityType) +{ + HILOG_INFO("%{public}s, called.", __func__); + AsyncCallbackInfo *asyncCallbackInfo = CreateAsyncCallbackInfo(env); + if (asyncCallbackInfo == nullptr) { + HILOG_ERROR("%{public}s, asyncCallbackInfo == nullptr", __func__); + return WrapVoidToJS(env); + } + + asyncCallbackInfo->errCode = NAPI_ERR_NO_ERROR; + asyncCallbackInfo->abilityType = abilityType; + napi_value ret = GetWantWrap(env, info, asyncCallbackInfo); + if (ret == nullptr) { + HILOG_ERROR("%{public}s, ret == nullptr", __func__); + if (asyncCallbackInfo != nullptr) { + delete asyncCallbackInfo; + asyncCallbackInfo = nullptr; + } + ret = WrapVoidToJS(env); + } + HILOG_INFO("%{public}s, end.", __func__); + return ret; +} + +/** + * @brief Create asynchronous data. + * + * @param env The environment that the Node-API call is invoked under. + * + * @return Return a pointer to AbilityNameCB on success, nullptr on failure. + */ +AbilityNameCB *CreateAbilityNameCBInfo(napi_env env) +{ + HILOG_INFO("%{public}s, called.", __func__); + napi_value global = nullptr; + NAPI_CALL(env, napi_get_global(env, &global)); + + napi_value abilityObj = nullptr; + NAPI_CALL(env, napi_get_named_property(env, global, "ability", &abilityObj)); + + Ability *ability = nullptr; + NAPI_CALL(env, napi_get_value_external(env, abilityObj, (void **)&ability)); + + AbilityNameCB *abilityNameCB = new (std::nothrow) AbilityNameCB; + if (abilityNameCB == nullptr) { + HILOG_ERROR("%{public}s, abilityNameCB == nullptr.", __func__); + return nullptr; + } + abilityNameCB->cbBase.cbInfo.env = env; + abilityNameCB->cbBase.asyncWork = nullptr; + abilityNameCB->cbBase.deferred = nullptr; + abilityNameCB->cbBase.ability = ability; + + HILOG_INFO("%{public}s, end.", __func__); + return abilityNameCB; +} + +napi_value WrapAbilityName(napi_env env, AbilityNameCB *abilityNameCB) +{ + HILOG_INFO("%{public}s, called.", __func__); + if (abilityNameCB == nullptr) { + HILOG_ERROR("%{public}s, Invalid param(abilityNameCB == nullptr)", __func__); + return nullptr; + } + napi_value result = nullptr; + NAPI_CALL(env, napi_create_string_utf8(env, abilityNameCB->name.c_str(), NAPI_AUTO_LENGTH, &result)); + HILOG_INFO("%{public}s, end.", __func__); + return result; +} + +/** + * @brief GetAbilityName asynchronous processing function. + * + * @param env The environment that the Node-API call is invoked under. + * @param data Point to asynchronous processing of data. + */ +void GetAbilityNameExecuteCB(napi_env env, void *data) +{ + HILOG_INFO("%{public}s, called.", __func__); + AbilityNameCB *abilityNameCB = static_cast(data); + if (abilityNameCB == nullptr) { + HILOG_ERROR("%{public}s, abilityNameCB == nullptr", __func__); + return; + } + abilityNameCB->cbBase.errCode = NAPI_ERR_NO_ERROR; + if (abilityNameCB->cbBase.ability == nullptr) { + HILOG_ERROR("%{public}s, ability == nullptr", __func__); + abilityNameCB->cbBase.errCode = NAPI_ERR_ACE_ABILITY; + return; + } + + if (!CheckAbilityType(&abilityNameCB->cbBase)) { + HILOG_ERROR("%{public}s, wrong ability type", __func__); + abilityNameCB->cbBase.errCode = NAPI_ERR_ABILITY_TYPE_INVALID; + return; + } + + abilityNameCB->name = abilityNameCB->cbBase.ability->GetAbilityName(); + HILOG_INFO("%{public}s, end.", __func__); +} + +/** + * @brief The callback at the end of the asynchronous callback. + * + * @param env The environment that the Node-API call is invoked under. + * @param data Point to asynchronous processing of data. + */ +void GetAbilityNameAsyncCompleteCB(napi_env env, napi_status status, void *data) +{ + HILOG_INFO("%{public}s, called.", __func__); + AbilityNameCB *abilityNameCB = static_cast(data); + napi_value callback = nullptr; + napi_value undefined = nullptr; + napi_value result[ARGS_TWO] = {nullptr}; + napi_value callResult = nullptr; + NAPI_CALL_RETURN_VOID(env, napi_get_undefined(env, &undefined)); + result[PARAM0] = GetCallbackErrorValue(env, abilityNameCB->cbBase.errCode); + if (abilityNameCB->cbBase.errCode == NAPI_ERR_NO_ERROR) { + result[PARAM1] = WrapAbilityName(env, abilityNameCB); + } else { + result[PARAM1] = WrapUndefinedToJS(env); + } + NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, abilityNameCB->cbBase.cbInfo.callback, &callback)); + NAPI_CALL_RETURN_VOID(env, napi_call_function(env, undefined, callback, ARGS_TWO, &result[PARAM0], &callResult)); + if (abilityNameCB->cbBase.cbInfo.callback != nullptr) { + NAPI_CALL_RETURN_VOID(env, napi_delete_reference(env, abilityNameCB->cbBase.cbInfo.callback)); + } + NAPI_CALL_RETURN_VOID(env, napi_delete_async_work(env, abilityNameCB->cbBase.asyncWork)); + delete abilityNameCB; + abilityNameCB = nullptr; + HILOG_INFO("%{public}s, end.", __func__); +} + +/** + * @brief The callback at the end of the Promise callback. + * + * @param env The environment that the Node-API call is invoked under. + * @param data Point to asynchronous processing of data. + */ +void GetAbilityNamePromiseCompleteCB(napi_env env, napi_status status, void *data) +{ + HILOG_INFO("NAPI_GetAbilityName, main event thread complete."); + AbilityNameCB *abilityNameCB = static_cast(data); + napi_value result = nullptr; + if (abilityNameCB->cbBase.errCode == NAPI_ERR_NO_ERROR) { + result = WrapAbilityName(env, abilityNameCB); + napi_resolve_deferred(env, abilityNameCB->cbBase.deferred, result); + } else { + result = GetCallbackErrorValue(env, abilityNameCB->cbBase.errCode); + napi_reject_deferred(env, abilityNameCB->cbBase.deferred, result); + } + + napi_delete_async_work(env, abilityNameCB->cbBase.asyncWork); + delete abilityNameCB; + abilityNameCB = nullptr; + HILOG_INFO("NAPI_GetAbilityName, main event thread complete end."); +} + +/** + * @brief GetAbilityName Async. + * + * @param env The environment that the Node-API call is invoked under. + * @param args Indicates the arguments passed into the callback. + * @param argcPromise Asynchronous data processing. + * @param abilityNameCB Process data asynchronously. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value GetAbilityNameAsync(napi_env env, napi_value *args, const size_t argCallback, AbilityNameCB *abilityNameCB) +{ + HILOG_INFO("%{public}s, asyncCallback.", __func__); + if (args == nullptr || abilityNameCB == nullptr) { + HILOG_ERROR("%{public}s, param == nullptr.", __func__); + return nullptr; + } + napi_value resourceName = nullptr; + NAPI_CALL(env, napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName)); + + napi_valuetype valuetype = napi_undefined; + NAPI_CALL(env, napi_typeof(env, args[argCallback], &valuetype)); + if (valuetype == napi_function) { + NAPI_CALL(env, napi_create_reference(env, args[argCallback], 1, &abilityNameCB->cbBase.cbInfo.callback)); + } + NAPI_CALL(env, + napi_create_async_work(env, + nullptr, + resourceName, + GetAbilityNameExecuteCB, + GetAbilityNameAsyncCompleteCB, + (void *)abilityNameCB, + &abilityNameCB->cbBase.asyncWork)); + NAPI_CALL(env, napi_queue_async_work(env, abilityNameCB->cbBase.asyncWork)); + napi_value result = nullptr; + NAPI_CALL(env, napi_get_null(env, &result)); + HILOG_INFO("%{public}s, asyncCallback end.", __func__); + return result; +} + +/** + * @brief GetAbilityName Promise. + * + * @param env The environment that the Node-API call is invoked under. + * @param abilityNameCB Process data asynchronously. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value GetAbilityNamePromise(napi_env env, AbilityNameCB *abilityNameCB) +{ + HILOG_INFO("%{public}s, promise.", __func__); + if (abilityNameCB == nullptr) { + HILOG_ERROR("%{public}s, param == nullptr.", __func__); + return nullptr; + } + napi_value resourceName = nullptr; + NAPI_CALL(env, napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName)); + napi_deferred deferred; + napi_value promise = nullptr; + NAPI_CALL(env, napi_create_promise(env, &deferred, &promise)); + abilityNameCB->cbBase.deferred = deferred; + + NAPI_CALL(env, + napi_create_async_work(env, + nullptr, + resourceName, + GetAbilityNameExecuteCB, + GetAbilityNamePromiseCompleteCB, + (void *)abilityNameCB, + &abilityNameCB->cbBase.asyncWork)); + NAPI_CALL(env, napi_queue_async_work(env, abilityNameCB->cbBase.asyncWork)); + HILOG_INFO("%{public}s, promise end.", __func__); + return promise; +} + +/** + * @brief GetAbilityName processing function. + * + * @param env The environment that the Node-API call is invoked under. + * @param abilityNameCB Process data asynchronously. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value GetAbilityNameWrap(napi_env env, napi_callback_info info, AbilityNameCB *abilityNameCB) +{ + HILOG_INFO("%{public}s, asyncCallback.", __func__); + if (abilityNameCB == nullptr) { + HILOG_ERROR("%{public}s, abilityNameCB == nullptr.", __func__); + return nullptr; + } + + size_t argcAsync = 1; + const size_t argcPromise = 0; + const size_t argCountWithAsync = argcPromise + ARGS_ASYNC_COUNT; + napi_value args[ARGS_MAX_COUNT] = {nullptr}; + napi_value ret = nullptr; + + NAPI_CALL(env, napi_get_cb_info(env, info, &argcAsync, args, nullptr, nullptr)); + if (argcAsync > argCountWithAsync || argcAsync > ARGS_MAX_COUNT) { + HILOG_ERROR("%{public}s, Wrong argument count.", __func__); + return nullptr; + } + + if (argcAsync > argcPromise) { + ret = GetAbilityNameAsync(env, args, 0, abilityNameCB); + } else { + ret = GetAbilityNamePromise(env, abilityNameCB); + } + HILOG_INFO("%{public}s, asyncCallback end.", __func__); + return ret; +} + +/** + * @brief Obtains the class name in this ability name, without the prefixed bundle name. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_GetAbilityNameCommon(napi_env env, napi_callback_info info, AbilityType abilityType) +{ + HILOG_INFO("%{public}s called.", __func__); + AbilityNameCB *ablityNameCB = CreateAbilityNameCBInfo(env); + if (ablityNameCB == nullptr) { + HILOG_ERROR("%{public}s ablityNameCB == nullptr", __func__); + return WrapVoidToJS(env); + } + + ablityNameCB->cbBase.errCode = NAPI_ERR_NO_ERROR; + ablityNameCB->cbBase.abilityType = abilityType; + napi_value ret = GetAbilityNameWrap(env, info, ablityNameCB); + if (ret == nullptr) { + HILOG_ERROR("%{public}s ret == nullptr", __func__); + if (ablityNameCB != nullptr) { + delete ablityNameCB; + ablityNameCB = nullptr; + } + ret = WrapVoidToJS(env); + } + HILOG_INFO("%{public}s end.", __func__); + return ret; +} + +void UnwrapAbilityStartSettingForNumber( + napi_env env, const std::string key, napi_value param, AAFwk::AbilityStartSetting &setting) +{ + int32_t natValue32 = 0; + double natValueDouble = 0.0; + bool isReadValue32 = false; + bool isReadDouble = false; + if (napi_get_value_int32(env, param, &natValue32) == napi_ok) { + HILOG_INFO("%{public}s called. Property value=%{public}d.", __func__, natValue32); + isReadValue32 = true; + } + + if (napi_get_value_double(env, param, &natValueDouble) == napi_ok) { + HILOG_INFO("%{public}s called. Property value=%{public}lf.", __func__, natValueDouble); + isReadDouble = true; + } + + if (isReadValue32 && isReadDouble) { + if (abs(natValueDouble - natValue32 * 1.0) > 0.0) { + setting.AddProperty(key, std::to_string(natValueDouble)); + } else { + setting.AddProperty(key, std::to_string(natValue32)); + } + } else if (isReadValue32) { + setting.AddProperty(key, std::to_string(natValue32)); + } else if (isReadDouble) { + setting.AddProperty(key, std::to_string(natValueDouble)); + } +} + +bool UnwrapAbilityStartSetting(napi_env env, napi_value param, AAFwk::AbilityStartSetting &setting) +{ + HILOG_INFO("%{public}s called.", __func__); + + if (!IsTypeForNapiValue(env, param, napi_object)) { + return false; + } + + napi_valuetype jsValueType = napi_undefined; + napi_value jsProNameList = nullptr; + uint32_t jsProCount = 0; + + NAPI_CALL_BASE(env, napi_get_property_names(env, param, &jsProNameList), false); + NAPI_CALL_BASE(env, napi_get_array_length(env, jsProNameList, &jsProCount), false); + HILOG_INFO("%{public}s called. Property size=%{public}d.", __func__, jsProCount); + + napi_value jsProName = nullptr; + napi_value jsProValue = nullptr; + for (uint32_t index = 0; index < jsProCount; index++) { + NAPI_CALL_BASE(env, napi_get_element(env, jsProNameList, index, &jsProName), false); + + std::string strProName = UnwrapStringFromJS(env, jsProName); + HILOG_INFO("%{public}s called. Property name=%{public}s.", __func__, strProName.c_str()); + NAPI_CALL_BASE(env, napi_get_named_property(env, param, strProName.c_str(), &jsProValue), false); + NAPI_CALL_BASE(env, napi_typeof(env, jsProValue, &jsValueType), false); + + switch (jsValueType) { + case napi_string: { + std::string natValue = UnwrapStringFromJS(env, jsProValue); + HILOG_INFO("%{public}s called. Property value=%{public}s.", __func__, natValue.c_str()); + setting.AddProperty(strProName, natValue); + break; + } + case napi_boolean: { + bool natValue = false; + NAPI_CALL_BASE(env, napi_get_value_bool(env, jsProValue, &natValue), false); + HILOG_INFO("%{public}s called. Property value=%{public}s.", __func__, natValue ? "true" : "false"); + setting.AddProperty(strProName, std::to_string(natValue)); + break; + } + case napi_number: + UnwrapAbilityStartSettingForNumber(env, strProName, jsProValue, setting); + break; + default: + break; + } + } + + return true; +} + +/** + * @brief Parse the parameters. + * + * @param param Indicates the parameters saved the parse result. + * @param env The environment that the Node-API call is invoked under. + * @param args Indicates the arguments passed into the callback. + * + * @return The return value from NAPI C++ to JS for the module. + */ +bool UnwrapParamForWant(napi_env env, napi_value args, AbilityType abilityType, CallAbilityParam ¶m) +{ + HILOG_INFO("%{public}s called.", __func__); + bool ret = false; + napi_valuetype valueType = napi_undefined; + param.setting = nullptr; + NAPI_CALL_BASE(env, napi_typeof(env, args, &valueType), false); + if (valueType != napi_object) { + HILOG_ERROR("%{public}s, Wrong argument type.", __func__); + return false; + } + + napi_value jsWant = GetPropertyValueByPropertyName(env, args, "want", napi_object); + if (jsWant == nullptr) { + HILOG_ERROR("%{public}s, jsWant == nullptr", __func__); + return false; + } + + ret = UnwrapWant(env, jsWant, param.want); + + napi_value jsSettingObj = GetPropertyValueByPropertyName(env, args, "abilityStartSetting", napi_object); + if (jsSettingObj != nullptr) { + param.setting = AbilityStartSetting::GetEmptySetting(); + if (!UnwrapAbilityStartSetting(env, jsSettingObj, *(param.setting))) { + HILOG_ERROR("%{public}s, unwrap abilityStartSetting falied.", __func__); + } + HILOG_INFO("%{public}s abilityStartSetting = %{public}p.", __func__, param.setting.get()); + } + + HILOG_INFO("%{public}s end.", __func__); + return ret; +} + +void StartAbilityExecuteCB(napi_env env, void *data) +{ + HILOG_INFO("%{public}s called.", __func__); + AsyncCallbackInfo *asyncCallbackInfo = (AsyncCallbackInfo *)data; + if (asyncCallbackInfo == nullptr) { + HILOG_ERROR("%{public}s asyncCallbackInfo == nullptr", __func__); + return; + } + asyncCallbackInfo->errCode = NAPI_ERR_NO_ERROR; + if (asyncCallbackInfo->ability == nullptr) { + asyncCallbackInfo->errCode = NAPI_ERR_ACE_ABILITY; + HILOG_ERROR("%{public}s ability == nullptr", __func__); + return; + } + + if (!CheckAbilityType(asyncCallbackInfo)) { + HILOG_ERROR("%{public}s wrong ability type", __func__); + asyncCallbackInfo->errCode = NAPI_ERR_ABILITY_TYPE_INVALID; + return; + } + + if (asyncCallbackInfo->param.setting == nullptr) { + HILOG_INFO("%{public}s param.setting == nullptr call StartAbility.", __func__); + asyncCallbackInfo->ability->StartAbility(asyncCallbackInfo->param.want); + } else { + HILOG_INFO("%{public}s param.setting != nullptr call StartAbility.", __func__); + asyncCallbackInfo->ability->StartAbility(asyncCallbackInfo->param.want, *(asyncCallbackInfo->param.setting)); + } + HILOG_INFO("%{public}s end.", __func__); +} + +void StartAbilityCallbackCompletedCB(napi_env env, napi_status status, void *data) +{ + HILOG_INFO("%{public}s called.", __func__); + AsyncCallbackInfo *asyncCallbackInfo = static_cast(data); + napi_value callback = 0; + napi_value undefined = 0; + napi_value result[ARGS_TWO] = {0}; + napi_value callResult = 0; + napi_get_undefined(env, &undefined); + result[PARAM0] = GetCallbackErrorValue(env, asyncCallbackInfo->errCode); + if (asyncCallbackInfo->errCode == NAPI_ERR_NO_ERROR) { + napi_create_int32(env, 0, &result[PARAM1]); + } else { + result[PARAM1] = WrapUndefinedToJS(env); + } + + napi_get_reference_value(env, asyncCallbackInfo->cbInfo.callback, &callback); + napi_call_function(env, undefined, callback, ARGS_TWO, &result[PARAM0], &callResult); + + if (asyncCallbackInfo->cbInfo.callback != nullptr) { + napi_delete_reference(env, asyncCallbackInfo->cbInfo.callback); + } + napi_delete_async_work(env, asyncCallbackInfo->asyncWork); + delete asyncCallbackInfo; + asyncCallbackInfo = nullptr; + HILOG_INFO("%{public}s end.", __func__); +} + +void StartAbilityPromiseCompletedCB(napi_env env, napi_status status, void *data) +{ + HILOG_INFO("%{public}s called.", __func__); + AsyncCallbackInfo *asyncCallbackInfo = static_cast(data); + napi_value result = 0; + if (asyncCallbackInfo->errCode == NAPI_ERR_NO_ERROR) { + napi_create_int32(env, 0, &result); + napi_resolve_deferred(env, asyncCallbackInfo->deferred, result); + } else { + result = GetCallbackErrorValue(env, asyncCallbackInfo->errCode); + napi_reject_deferred(env, asyncCallbackInfo->deferred, result); + } + + napi_delete_async_work(env, asyncCallbackInfo->asyncWork); + HILOG_INFO("%{public}s, end.", __func__); + delete asyncCallbackInfo; +} + +napi_value StartAbilityAsync( + napi_env env, napi_value *args, const size_t argCallback, AsyncCallbackInfo *asyncCallbackInfo) +{ + HILOG_INFO("%{public}s asyncCallback.", __func__); + if (args == nullptr || asyncCallbackInfo == nullptr) { + HILOG_ERROR("%{public}s, param == nullptr.", __func__); + return nullptr; + } + napi_value resourceName = 0; + NAPI_CALL(env, napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName)); + + napi_valuetype valuetype = napi_undefined; + NAPI_CALL(env, napi_typeof(env, args[argCallback], &valuetype)); + if (valuetype == napi_function) { + NAPI_CALL(env, napi_create_reference(env, args[argCallback], 1, &asyncCallbackInfo->cbInfo.callback)); + } + + NAPI_CALL(env, + napi_create_async_work(env, + nullptr, + resourceName, + StartAbilityExecuteCB, + StartAbilityCallbackCompletedCB, + (void *)asyncCallbackInfo, + &asyncCallbackInfo->asyncWork)); + NAPI_CALL(env, napi_queue_async_work(env, asyncCallbackInfo->asyncWork)); + + HILOG_INFO("%{public}s asyncCallback end.", __func__); + return WrapVoidToJS(env); +} + +napi_value StartAbilityPromise(napi_env env, AsyncCallbackInfo *asyncCallbackInfo) +{ + HILOG_INFO("%{public}s, promise.", __func__); + if (asyncCallbackInfo == nullptr) { + HILOG_ERROR("%{public}s, param == nullptr.", __func__); + return nullptr; + } + napi_value resourceName; + NAPI_CALL(env, napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName)); + napi_deferred deferred; + napi_value promise = 0; + NAPI_CALL(env, napi_create_promise(env, &deferred, &promise)); + asyncCallbackInfo->deferred = deferred; + + NAPI_CALL(env, + napi_create_async_work(env, + nullptr, + resourceName, + StartAbilityExecuteCB, + StartAbilityPromiseCompletedCB, + (void *)asyncCallbackInfo, + &asyncCallbackInfo->asyncWork)); + NAPI_CALL(env, napi_queue_async_work(env, asyncCallbackInfo->asyncWork)); + HILOG_INFO("%{public}s, end.", __func__); + return promise; +} + +/** + * @brief StartAbility processing function. + * + * @param env The environment that the Node-API call is invoked under. + * @param asyncCallbackInfo Process data asynchronously. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value StartAbilityWrap(napi_env env, napi_callback_info info, AsyncCallbackInfo *asyncCallbackInfo) +{ + HILOG_INFO("%{public}s called.", __func__); + size_t argcAsync = 2; + const size_t argcPromise = 1; + const size_t argCountWithAsync = argcPromise + ARGS_ASYNC_COUNT; + napi_value args[ARGS_MAX_COUNT] = {nullptr}; + napi_value ret = 0; + + NAPI_CALL(env, napi_get_cb_info(env, info, &argcAsync, args, nullptr, nullptr)); + if (argcAsync > argCountWithAsync || argcAsync > ARGS_MAX_COUNT) { + HILOG_ERROR("%{public}s, Wrong argument count.", __func__); + return nullptr; + } + + CallAbilityParam param; + if (UnwrapParamForWant(env, args[PARAM0], asyncCallbackInfo->abilityType, param) == false) { + HILOG_ERROR("%{public}s, call UnwrapParamForWant failed.", __func__); + return nullptr; + } + + asyncCallbackInfo->param = param; + if (argcAsync > argcPromise) { + ret = StartAbilityAsync(env, args, 1, asyncCallbackInfo); + } else { + ret = StartAbilityPromise(env, asyncCallbackInfo); + } + + HILOG_INFO("%{public}s end.", __func__); + return ret; +} + +/** + * @brief startAbility. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_StartAbilityCommon(napi_env env, napi_callback_info info, AbilityType abilityType) +{ + HILOG_INFO("%{public}s called.", __func__); + AsyncCallbackInfo *asyncCallbackInfo = CreateAsyncCallbackInfo(env); + if (asyncCallbackInfo == nullptr) { + HILOG_ERROR("%{public}s asyncCallbackInfo == nullpter", __func__); + return WrapVoidToJS(env); + } + + asyncCallbackInfo->errCode = NAPI_ERR_NO_ERROR; + asyncCallbackInfo->abilityType = abilityType; + napi_value ret = StartAbilityWrap(env, info, asyncCallbackInfo); + if (ret == nullptr) { + HILOG_ERROR("%{public}s ret == nullpter", __func__); + if (asyncCallbackInfo != nullptr) { + delete asyncCallbackInfo; + asyncCallbackInfo = nullptr; + } + ret = WrapVoidToJS(env); + } + HILOG_INFO("%{public}s end.", __func__); + return ret; +} + +bool UnwrapParamStopAbilityWrap(napi_env env, size_t argc, napi_value *argv, AsyncJSCallbackInfo *asyncCallbackInfo) +{ + HILOG_INFO("%{public}s called, argc=%{public}zu", __func__, argc); + const size_t argcMax = 2; + if (argc > argcMax || argc < argcMax - 1) { + HILOG_ERROR("%{public}s, Params is invalid.", __func__); + return false; + } + + if (argc == argcMax) { + if (!CreateAsyncCallback(env, argv[PARAM1], asyncCallbackInfo)) { + HILOG_INFO("%{public}s, the second parameter is invalid.", __func__); + return false; + } + } + + return UnwrapWant(env, argv[PARAM0], asyncCallbackInfo->param.want); +} + +void StopAbilityExecuteCallback(napi_env env, void *data) +{ + HILOG_INFO("%{public}s called.", __func__); + AsyncJSCallbackInfo *asyncCallbackInfo = static_cast(data); + if (asyncCallbackInfo == nullptr) { + HILOG_ERROR("%{public}s asyncCallbackInfo is null", __func__); + return; + } + + asyncCallbackInfo->error_code = NAPI_ERR_NO_ERROR; + asyncCallbackInfo->native_data.data_type = NVT_NONE; + + if (asyncCallbackInfo->ability == nullptr) { + HILOG_ERROR("%{public}s ability is null", __func__); + asyncCallbackInfo->error_code = NAPI_ERR_ACE_ABILITY; + return; + } + + if (!CheckAbilityType(asyncCallbackInfo)) { + HILOG_ERROR("%{public}s wrong ability type", __func__); + asyncCallbackInfo->error_code = NAPI_ERR_ABILITY_TYPE_INVALID; + asyncCallbackInfo->native_data.data_type = NVT_UNDEFINED; + return; + } + + asyncCallbackInfo->native_data.data_type = NVT_BOOL; + asyncCallbackInfo->native_data.bool_value = asyncCallbackInfo->ability->StopAbility(asyncCallbackInfo->param.want); + HILOG_INFO("%{public}s end.", __func__); +} + +napi_value StopAbilityWrap(napi_env env, napi_callback_info info, AsyncJSCallbackInfo *asyncCallbackInfo) +{ + HILOG_INFO("%{public}s called.", __func__); + size_t argc = ARGS_MAX_COUNT; + napi_value args[ARGS_MAX_COUNT] = {nullptr}; + napi_value jsthis = 0; + void *data = nullptr; + + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, &jsthis, &data)); + + if (!UnwrapParamStopAbilityWrap(env, argc, args, asyncCallbackInfo)) { + HILOG_INFO("%{public}s called. Invoke UnwrapParamStopAbility fail", __func__); + return nullptr; + } + + AsyncParamEx asyncParamEx; + if (asyncCallbackInfo->cbInfo.callback != nullptr) { + HILOG_INFO("%{public}s called. asyncCallback.", __func__); + asyncParamEx.resource = "NAPI_StopAbilityWrapCallback"; + asyncParamEx.execute = StopAbilityExecuteCallback; + asyncParamEx.complete = CompleteAsyncCallbackWork; + + return ExecuteAsyncCallbackWork(env, asyncCallbackInfo, &asyncParamEx); + } else { + HILOG_INFO("%{public}s called. promise.", __func__); + asyncParamEx.resource = "NAPI_StopAbilityWrapPromise"; + asyncParamEx.execute = StopAbilityExecuteCallback; + asyncParamEx.complete = CompletePromiseCallbackWork; + + return ExecutePromiseCallbackWork(env, asyncCallbackInfo, &asyncParamEx); + } +} + +/** + * @brief stopAbility. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_StopAbilityCommon(napi_env env, napi_callback_info info, AbilityType abilityType) +{ + HILOG_INFO("%{public}s called.", __func__); + AsyncJSCallbackInfo *asyncCallbackInfo = CreateAsyncJSCallbackInfo(env); + if (asyncCallbackInfo == nullptr) { + HILOG_ERROR("%{public}s. Invoke CreateAsyncJSCallbackInfo failed.", __func__); + return WrapVoidToJS(env); + } + + asyncCallbackInfo->error_code = NAPI_ERR_NO_ERROR; + asyncCallbackInfo->abilityType = abilityType; + napi_value ret = StopAbilityWrap(env, info, asyncCallbackInfo); + if (ret == nullptr) { + HILOG_ERROR("%{public}s. ret == nullptr", __func__); + FreeAsyncJSCallbackInfo(&asyncCallbackInfo); + ret = WrapVoidToJS(env); + } + HILOG_INFO("%{public}s end.", __func__); + return ret; +} + +/** + * @brief Create asynchronous data. + * + * @param env The environment that the Node-API call is invoked under. + * + * @return Return a pointer to AbilityNameCB on success, nullptr on failure. + */ +ConnectAbilityCB *CreateConnectAbilityCBInfo(napi_env env) +{ + HILOG_INFO("%{public}s called.", __func__); + napi_value global = nullptr; + NAPI_CALL(env, napi_get_global(env, &global)); + + napi_value abilityObj = nullptr; + NAPI_CALL(env, napi_get_named_property(env, global, "ability", &abilityObj)); + + Ability *ability = nullptr; + NAPI_CALL(env, napi_get_value_external(env, abilityObj, (void **)&ability)); + + ConnectAbilityCB *connectAbilityCB = new (std::nothrow) ConnectAbilityCB; + if (connectAbilityCB == nullptr) { + HILOG_ERROR("%{public}s connectAbilityCB == nullptr", __func__); + return nullptr; + } + connectAbilityCB->cbBase.cbInfo.env = env; + connectAbilityCB->cbBase.asyncWork = nullptr; + connectAbilityCB->cbBase.deferred = nullptr; + connectAbilityCB->cbBase.ability = ability; + + HILOG_INFO("%{public}s end.", __func__); + return connectAbilityCB; +} + +void ConnectAbilityExecuteCB(napi_env env, void *data) +{ + HILOG_INFO("%{public}s called.", __func__); + ConnectAbilityCB *connectAbilityCB = static_cast(data); + if (connectAbilityCB == nullptr) { + HILOG_ERROR("%{public}s connectAbilityCB == nullptr.", __func__); + return; + } + connectAbilityCB->errCode = NAPI_ERR_NO_ERROR; + if (connectAbilityCB->cbBase.ability == nullptr) { + connectAbilityCB->errCode = NAPI_ERR_ACE_ABILITY; + HILOG_ERROR("%{public}s ability == nullptr.", __func__); + return; + } + + if (!CheckAbilityType(&connectAbilityCB->cbBase)) { + connectAbilityCB->errCode = NAPI_ERR_ABILITY_TYPE_INVALID; + HILOG_ERROR("%{public}s ability type invalid.", __func__); + return; + } + + connectAbilityCB->abilityConnection->SetEnv(env); + connectAbilityCB->abilityConnection->SetConnectCBRef(connectAbilityCB->abilityConnectionCB.callback[0]); + connectAbilityCB->abilityConnection->SetDisconnectCBRef(connectAbilityCB->abilityConnectionCB.callback[1]); + connectAbilityCB->result = + connectAbilityCB->cbBase.ability->ConnectAbility(connectAbilityCB->want, connectAbilityCB->abilityConnection); + HILOG_INFO("%{public}s end.bundlename:%{public}s abilityname:%{public}s result:%{public}d", + __func__, + connectAbilityCB->want.GetBundle().c_str(), + connectAbilityCB->want.GetElement().GetAbilityName().c_str(), + connectAbilityCB->result); +} + +void ConnectAbilityCallbackCompletedCB(napi_env env, napi_status status, void *data) +{ + HILOG_INFO("%{public}s called.", __func__); + ConnectAbilityCB *connectAbilityCB = static_cast(data); + napi_value callback = 0; + napi_value undefined = 0; + napi_value result = 0; + napi_value callResult = 0; + napi_get_undefined(env, &undefined); + HILOG_INFO("%{public}s errCode=%{public}d result=%{public}d id=%{public}" PRId64, + __func__, + connectAbilityCB->errCode, + connectAbilityCB->result, + connectAbilityCB->id); + if (connectAbilityCB->errCode != NAPI_ERR_NO_ERROR || connectAbilityCB->result == false) { + HILOG_INFO("%{public}s connectAbility failed.", __func__); + // return error code in onFailed asynccallback + int errorCode = NO_ERROR; + switch (connectAbilityCB->errCode) { + case NAPI_ERR_ACE_ABILITY: + errorCode = ABILITY_NOT_FOUND; + break; + case NAPI_ERR_PARAM_INVALID: + errorCode = INVALID_PARAMETER; + break; + default: + break; + } + NAPI_CALL_RETURN_VOID(env, napi_create_int32(env, errorCode, &result)); + NAPI_CALL_RETURN_VOID( + env, napi_get_reference_value(env, connectAbilityCB->abilityConnectionCB.callback[PARAM2], &callback)); + NAPI_CALL_RETURN_VOID(env, napi_call_function(env, undefined, callback, ARGS_ONE, &result, &callResult)); + } + if (connectAbilityCB->cbBase.cbInfo.callback != nullptr) { + NAPI_CALL_RETURN_VOID(env, napi_delete_reference(env, connectAbilityCB->cbBase.cbInfo.callback)); + } + if (connectAbilityCB->abilityConnectionCB.callback[PARAM2] != nullptr) { + NAPI_CALL_RETURN_VOID(env, napi_delete_reference(env, connectAbilityCB->abilityConnectionCB.callback[PARAM2])); + } + NAPI_CALL_RETURN_VOID(env, napi_delete_async_work(env, connectAbilityCB->cbBase.asyncWork)); + delete connectAbilityCB; + connectAbilityCB = nullptr; + HILOG_INFO("%{public}s end.", __func__); +} + +napi_value ConnectAbilityAsync(napi_env env, napi_value *args, ConnectAbilityCB *connectAbilityCB) +{ + HILOG_INFO("%{public}s asyncCallback.", __func__); + if (args == nullptr || connectAbilityCB == nullptr) { + HILOG_ERROR("%{public}s, param == nullptr.", __func__); + return nullptr; + } + napi_value resourceName = 0; + NAPI_CALL(env, napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName)); + + NAPI_CALL(env, + napi_create_async_work(env, + nullptr, + resourceName, + ConnectAbilityExecuteCB, + ConnectAbilityCallbackCompletedCB, + (void *)connectAbilityCB, + &connectAbilityCB->cbBase.asyncWork)); + NAPI_CALL(env, napi_queue_async_work(env, connectAbilityCB->cbBase.asyncWork)); + HILOG_INFO("%{public}s asyncCallback end.", __func__); + return WrapVoidToJS(env); +} + +/** + * @brief ConnectAbility processing function. + * + * @param env The environment that the Node-API call is invoked under. + * @param connectAbilityCB Process data asynchronously. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value ConnectAbilityWrap(napi_env env, napi_callback_info info, ConnectAbilityCB *connectAbilityCB) +{ + HILOG_INFO("%{public}s called.", __func__); + size_t argcAsync = ARGS_TWO; + napi_value args[ARGS_MAX_COUNT] = {nullptr}; + napi_value ret = 0; + + NAPI_CALL(env, napi_get_cb_info(env, info, &argcAsync, args, nullptr, nullptr)); + if (argcAsync != ARGS_TWO) { + HILOG_ERROR("%{public}s, Wrong argument count.", __func__); + connectAbilityCB->errCode = NAPI_ERR_PARAM_INVALID; + return nullptr; + } + + if (!UnwrapWant(env, args[PARAM0], connectAbilityCB->want)) { + HILOG_INFO("%{public}s called. Invoke UnwrapWant fail", __func__); + return nullptr; + } + + HILOG_INFO("%{public}s bundlename:%{public}s abilityname:%{public}s", + __func__, + connectAbilityCB->want.GetBundle().c_str(), + connectAbilityCB->want.GetElement().GetAbilityName().c_str()); + + std::string bundleName = connectAbilityCB->want.GetBundle(); + std::string abilityName = connectAbilityCB->want.GetElement().GetAbilityName(); + auto item = std::find_if(connects_.begin(), + connects_.end(), + [&bundleName, &abilityName](const std::map>::value_type &obj) { + return (bundleName == obj.first.want.GetBundle()) && + (abilityName == obj.first.want.GetElement().GetAbilityName()); + }); + if (item != connects_.end()) { + // match bundlename && abilityname + connectAbilityCB->id = item->first.id; + connectAbilityCB->abilityConnection = item->second; + HILOG_INFO("%{public}s find connection:%{public}p exist", __func__, item->second.GetRefPtr()); + } else { + sptr conn(new (std::nothrow) NAPIAbilityConnection()); + connectAbilityCB->id = serialNumber_; + connectAbilityCB->abilityConnection = conn; + ConnecttionKey key; + key.id = connectAbilityCB->id; + key.want = connectAbilityCB->want; + connects_.emplace(key, conn); + if (serialNumber_ < INT64_MAX) { + serialNumber_++; + } else { + serialNumber_ = 0; + } + HILOG_INFO("%{public}s not find connection, make new one:%{public}p.", __func__, conn.GetRefPtr()); + } + HILOG_INFO("%{public}s id:%{public}" PRId64, __func__, connectAbilityCB->id); + + if (argcAsync > PARAM1) { + napi_value jsMethod = nullptr; + napi_valuetype valuetype = napi_undefined; + napi_typeof(env, args[PARAM1], &valuetype); + if (valuetype == napi_object) { + NAPI_CALL(env, napi_get_named_property(env, args[PARAM1], "onConnect", &jsMethod)); + NAPI_CALL(env, napi_typeof(env, jsMethod, &valuetype)); + HILOG_INFO("%{public}s, function onConnect valuetype=%{public}d.", __func__, valuetype); + NAPI_CALL( + env, napi_create_reference(env, jsMethod, 1, &connectAbilityCB->abilityConnectionCB.callback[PARAM0])); + + NAPI_CALL(env, napi_get_named_property(env, args[PARAM1], "onDisconnect", &jsMethod)); + NAPI_CALL(env, napi_typeof(env, jsMethod, &valuetype)); + HILOG_INFO("%{public}s, function onDisconnect valuetype=%{public}d.", __func__, valuetype); + NAPI_CALL( + env, napi_create_reference(env, jsMethod, 1, &connectAbilityCB->abilityConnectionCB.callback[PARAM1])); + + NAPI_CALL(env, napi_get_named_property(env, args[PARAM1], "onFailed", &jsMethod)); + NAPI_CALL(env, napi_typeof(env, jsMethod, &valuetype)); + HILOG_INFO("%{public}s, function onFailed valuetype=%{public}d.", __func__, valuetype); + NAPI_CALL( + env, napi_create_reference(env, jsMethod, 1, &connectAbilityCB->abilityConnectionCB.callback[PARAM2])); + } else { + HILOG_ERROR("%{public}s, Wrong argument type.", __func__); + return nullptr; + } + } + + ret = ConnectAbilityAsync(env, args, connectAbilityCB); + if (ret != nullptr) { + // return number to js + NAPI_CALL(env, napi_create_int64(env, connectAbilityCB->id, &ret)); + HILOG_INFO("%{public}s id=%{public}" PRId64, __func__, connectAbilityCB->id); + } + HILOG_INFO("%{public}s called end.", __func__); + return ret; +} + +/** + * @brief ConnectAbility. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_ConnectAbilityCommon(napi_env env, napi_callback_info info, AbilityType abilityType) +{ + HILOG_INFO("%{public}s called.", __func__); + ConnectAbilityCB *connectAbilityCB = CreateConnectAbilityCBInfo(env); + if (connectAbilityCB == nullptr) { + HILOG_ERROR("%{public}s connectAbilityCB == nullptr", __func__); + return WrapVoidToJS(env); + } + + connectAbilityCB->errCode = NAPI_ERR_NO_ERROR; + connectAbilityCB->cbBase.abilityType = abilityType; + napi_value ret = ConnectAbilityWrap(env, info, connectAbilityCB); + if (ret == nullptr) { + HILOG_ERROR("%{public}s ret == nullptr", __func__); + if (connectAbilityCB != nullptr) { + delete connectAbilityCB; + connectAbilityCB = nullptr; + } + ret = WrapVoidToJS(env); + } + HILOG_INFO("%{public}s end.", __func__); + return ret; +} + +/** + * @brief Create asynchronous data. + * + * @param env The environment that the Node-API call is invoked under. + * + * @return Return a pointer to AbilityNameCB on success, nullptr on failure. + */ +ConnectAbilityCB *CreateDisConnectAbilityCBInfo(napi_env env) +{ + HILOG_INFO("%{public}s called.", __func__); + napi_value global = nullptr; + NAPI_CALL(env, napi_get_global(env, &global)); + + napi_value abilityObj = nullptr; + NAPI_CALL(env, napi_get_named_property(env, global, "ability", &abilityObj)); + + Ability *ability = nullptr; + NAPI_CALL(env, napi_get_value_external(env, abilityObj, (void **)&ability)); + + ConnectAbilityCB *connectAbilityCB = new (std::nothrow) ConnectAbilityCB; + if (connectAbilityCB == nullptr) { + HILOG_ERROR("%{public}s connectAbilityCB == nullptr", __func__); + return nullptr; + } + connectAbilityCB->cbBase.cbInfo.env = env; + connectAbilityCB->cbBase.asyncWork = nullptr; + connectAbilityCB->cbBase.deferred = nullptr; + connectAbilityCB->cbBase.ability = ability; + + HILOG_INFO("%{public}s end.", __func__); + return connectAbilityCB; +} + +void DisConnectAbilityExecuteCB(napi_env env, void *data) +{ + HILOG_INFO("%{public}s called.", __func__); + ConnectAbilityCB *connectAbilityCB = static_cast(data); + if (connectAbilityCB == nullptr) { + HILOG_ERROR("%{public}s connectAbilityCB == nullptr.", __func__); + return; + } + connectAbilityCB->errCode = NAPI_ERR_NO_ERROR; + if (connectAbilityCB->cbBase.ability == nullptr) { + connectAbilityCB->errCode = NAPI_ERR_ACE_ABILITY; + HILOG_ERROR("%{public}s ability == nullptr.", __func__); + return; + } + + if (!CheckAbilityType(&connectAbilityCB->cbBase)) { + connectAbilityCB->errCode = NAPI_ERR_ABILITY_TYPE_INVALID; + HILOG_ERROR("%{public}s ability type invalid.", __func__); + return; + } + + HILOG_INFO("%{public}s DisconnectAbility called.", __func__); + connectAbilityCB->cbBase.ability->DisconnectAbility(connectAbilityCB->abilityConnection); + HILOG_INFO("%{public}s end. bundlename:%{public}s abilityname:%{public}s", + __func__, + connectAbilityCB->want.GetBundle().c_str(), + connectAbilityCB->want.GetElement().GetAbilityName().c_str()); +} + +void DisConnectAbilityCallbackCompletedCB(napi_env env, napi_status status, void *data) +{ + HILOG_INFO("%{public}s called.", __func__); + ConnectAbilityCB *connectAbilityCB = static_cast(data); + napi_value callback = 0; + napi_value undefined = 0; + napi_value result[ARGS_TWO] = {0}; + napi_value callResult = 0; + napi_get_undefined(env, &undefined); + result[PARAM0] = GetCallbackErrorValue(env, connectAbilityCB->errCode); + if (connectAbilityCB->errCode == NAPI_ERR_NO_ERROR) { + result[PARAM1] = WrapVoidToJS(env); + } else { + result[PARAM1] = WrapUndefinedToJS(env); + } + + NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, connectAbilityCB->cbBase.cbInfo.callback, &callback)); + NAPI_CALL_RETURN_VOID(env, napi_call_function(env, undefined, callback, ARGS_TWO, &result[PARAM0], &callResult)); + + if (connectAbilityCB->cbBase.cbInfo.callback != nullptr) { + NAPI_CALL_RETURN_VOID(env, napi_delete_reference(env, connectAbilityCB->cbBase.cbInfo.callback)); + } + NAPI_CALL_RETURN_VOID(env, napi_delete_async_work(env, connectAbilityCB->cbBase.asyncWork)); + delete connectAbilityCB; + connectAbilityCB = nullptr; + HILOG_INFO("%{public}s end.", __func__); +} + +void DisConnectAbilityPromiseCompletedCB(napi_env env, napi_status status, void *data) +{ + HILOG_INFO("%{public}s called.", __func__); + ConnectAbilityCB *connectAbilityCB = static_cast(data); + napi_value result = 0; + if (connectAbilityCB->errCode == NAPI_ERR_NO_ERROR) { + result = WrapVoidToJS(env); + napi_resolve_deferred(env, connectAbilityCB->cbBase.deferred, result); + } else { + result = GetCallbackErrorValue(env, connectAbilityCB->errCode); + napi_reject_deferred(env, connectAbilityCB->cbBase.deferred, result); + } + + napi_delete_async_work(env, connectAbilityCB->cbBase.asyncWork); + delete connectAbilityCB; + HILOG_INFO("%{public}s end.", __func__); +} + +napi_value DisConnectAbilityAsync( + napi_env env, napi_value *args, const size_t argCallback, ConnectAbilityCB *connectAbilityCB) +{ + HILOG_INFO("%{public}s asyncCallback.", __func__); + if (args == nullptr || connectAbilityCB == nullptr) { + HILOG_ERROR("%{public}s, param == nullptr.", __func__); + return nullptr; + } + napi_value resourceName = 0; + NAPI_CALL(env, napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName)); + + napi_valuetype valuetype = napi_undefined; + NAPI_CALL(env, napi_typeof(env, args[argCallback], &valuetype)); + if (valuetype == napi_function) { + NAPI_CALL(env, napi_create_reference(env, args[argCallback], 1, &connectAbilityCB->cbBase.cbInfo.callback)); + } + + NAPI_CALL(env, + napi_create_async_work(env, + nullptr, + resourceName, + DisConnectAbilityExecuteCB, + DisConnectAbilityCallbackCompletedCB, + (void *)connectAbilityCB, + &connectAbilityCB->cbBase.asyncWork)); + NAPI_CALL(env, napi_queue_async_work(env, connectAbilityCB->cbBase.asyncWork)); + HILOG_INFO("%{public}s asyncCallback end.", __func__); + return WrapVoidToJS(env); +} + +napi_value DisConnectAbilityPromise(napi_env env, ConnectAbilityCB *connectAbilityCB) +{ + HILOG_INFO("%{public}s, promise.", __func__); + if (connectAbilityCB == nullptr) { + HILOG_ERROR("%{public}s, param == nullptr.", __func__); + return nullptr; + } + napi_value resourceName; + NAPI_CALL(env, napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName)); + napi_deferred deferred; + napi_value promise = 0; + NAPI_CALL(env, napi_create_promise(env, &deferred, &promise)); + connectAbilityCB->cbBase.deferred = deferred; + + NAPI_CALL(env, + napi_create_async_work(env, + nullptr, + resourceName, + DisConnectAbilityExecuteCB, + DisConnectAbilityPromiseCompletedCB, + (void *)connectAbilityCB, + &connectAbilityCB->cbBase.asyncWork)); + NAPI_CALL(env, napi_queue_async_work(env, connectAbilityCB->cbBase.asyncWork)); + HILOG_INFO("%{public}s, promise end.", __func__); + return promise; +} + +/** + * @brief DisConnectAbility processing function. + * + * @param env The environment that the Node-API call is invoked under. + * @param connectAbilityCB Process data asynchronously. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value DisConnectAbilityWrap(napi_env env, napi_callback_info info, ConnectAbilityCB *connectAbilityCB) +{ + HILOG_INFO("%{public}s called.", __func__); + size_t argcAsync = ARGS_TWO; + const size_t argcPromise = ARGS_ONE; + const size_t argCountWithAsync = argcPromise + ARGS_ASYNC_COUNT; + napi_value args[ARGS_MAX_COUNT] = {nullptr}; + napi_value ret = 0; + + NAPI_CALL(env, napi_get_cb_info(env, info, &argcAsync, args, nullptr, nullptr)); + if (argcAsync > argCountWithAsync || argcAsync > ARGS_MAX_COUNT) { + HILOG_ERROR("%{public}s, Wrong argument count.", __func__); + return nullptr; + } + + napi_valuetype valuetype = napi_undefined; + napi_typeof(env, args[PARAM0], &valuetype); + if (valuetype == napi_number) { + NAPI_CALL(env, napi_get_value_int64(env, args[PARAM0], &connectAbilityCB->id)); + } + + HILOG_INFO("%{public}s id:%{public}" PRId64, __func__, connectAbilityCB->id); + int64_t id = connectAbilityCB->id; + auto item = std::find_if(connects_.begin(), + connects_.end(), + [&id](const std::map>::value_type &obj) { + return id == obj.first.id; + }); + if (item != connects_.end()) { + // match id + connectAbilityCB->want = item->first.want; + connectAbilityCB->abilityConnection = item->second; + HILOG_INFO("%{public}s find conn ability:%{public}p exist", __func__, item->second.GetRefPtr()); + } else { + HILOG_INFO("%{public}s not find conn ability exist.", __func__); + HILOG_INFO("%{public}s there is no ability to disconnect.", __func__); + return nullptr; + } + + if (argcAsync > argcPromise) { + ret = DisConnectAbilityAsync(env, args, ARGS_ONE, connectAbilityCB); + } else { + ret = DisConnectAbilityPromise(env, connectAbilityCB); + } + HILOG_INFO("%{public}s end.", __func__); + return ret; +} + +/** + * @brief DisConnectAbility. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_DisConnectAbilityCommon(napi_env env, napi_callback_info info, AbilityType abilityType) +{ + HILOG_INFO("%{public}s called.", __func__); + ConnectAbilityCB *connectAbilityCB = CreateConnectAbilityCBInfo(env); + if (connectAbilityCB == nullptr) { + HILOG_ERROR("%{public}s connectAbilityCB == nullptr", __func__); + return WrapVoidToJS(env); + } + + connectAbilityCB->errCode = NAPI_ERR_NO_ERROR; + connectAbilityCB->cbBase.abilityType = abilityType; + napi_value ret = DisConnectAbilityWrap(env, info, connectAbilityCB); + if (ret == nullptr) { + HILOG_ERROR("%{public}s ret == nullptr", __func__); + if (connectAbilityCB != nullptr) { + delete connectAbilityCB; + connectAbilityCB = nullptr; + } + ret = WrapVoidToJS(env); + } + HILOG_INFO("%{public}s end.", __func__); + return ret; +} + +void NAPIAbilityConnection::SetEnv(const napi_env &env) +{ + env_ = env; +} + +void NAPIAbilityConnection::SetConnectCBRef(const napi_ref &ref) +{ + connectRef_ = ref; +} + +void NAPIAbilityConnection::SetDisconnectCBRef(const napi_ref &ref) +{ + disconnectRef_ = ref; +} + +void UvWorkOnAbilityConnectDone(uv_work_t *work, int status) +{ + HILOG_INFO("UvWorkOnAbilityConnectDone, uv_queue_work"); + if (work == nullptr) { + HILOG_ERROR("UvWorkOnAbilityConnectDone, work is null"); + return; + } + // JS Thread + ConnectAbilityCB *connectAbilityCB = static_cast(work->data); + if (connectAbilityCB == nullptr) { + HILOG_ERROR("UvWorkOnAbilityConnectDone, connectAbilityCB is null"); + return; + } + napi_value result[ARGS_TWO] = {0}; + result[PARAM0] = + WrapElementName(connectAbilityCB->cbBase.cbInfo.env, connectAbilityCB->abilityConnectionCB.elementName); + napi_value jsRemoteObject = NAPI_ohos_rpc_CreateJsRemoteObject( + connectAbilityCB->cbBase.cbInfo.env, connectAbilityCB->abilityConnectionCB.connection); + result[PARAM1] = jsRemoteObject; + + napi_value callback = 0; + napi_value undefined = 0; + napi_get_undefined(connectAbilityCB->cbBase.cbInfo.env, &undefined); + napi_value callResult = 0; + napi_get_reference_value(connectAbilityCB->cbBase.cbInfo.env, connectAbilityCB->cbBase.cbInfo.callback, &callback); + + napi_call_function( + connectAbilityCB->cbBase.cbInfo.env, undefined, callback, ARGS_TWO, &result[PARAM0], &callResult); + if (connectAbilityCB->cbBase.cbInfo.callback != nullptr) { + napi_delete_reference(connectAbilityCB->cbBase.cbInfo.env, connectAbilityCB->cbBase.cbInfo.callback); + } + if (connectAbilityCB != nullptr) { + delete connectAbilityCB; + connectAbilityCB = nullptr; + } + if (work != nullptr) { + delete work; + work = nullptr; + } + HILOG_INFO("UvWorkOnAbilityConnectDone, uv_queue_work end"); +} + +void NAPIAbilityConnection::OnAbilityConnectDone( + const AppExecFwk::ElementName &element, const sptr &remoteObject, int resultCode) +{ + HILOG_INFO("%{public}s, called.", __func__); + if (remoteObject == nullptr) { + HILOG_ERROR("%{public}s, remoteObject == nullptr.", __func__); + return; + } + uv_loop_s *loop = nullptr; + + napi_get_uv_event_loop(env_, &loop); + if (loop == nullptr) { + HILOG_ERROR("%{public}s, loop == nullptr.", __func__); + return; + } + + uv_work_t *work = new uv_work_t; + if (work == nullptr) { + HILOG_ERROR("%{public}s, work==nullptr.", __func__); + return; + } + + ConnectAbilityCB *connectAbilityCB = new (std::nothrow) ConnectAbilityCB; + if (connectAbilityCB == nullptr) { + HILOG_ERROR("%{public}s, connectAbilityCB == nullptr.", __func__); + if (work != nullptr) { + delete work; + work = nullptr; + } + return; + } + connectAbilityCB->cbBase.cbInfo.env = env_; + connectAbilityCB->cbBase.cbInfo.callback = connectRef_; + connectAbilityCB->abilityConnectionCB.elementName = element; + connectAbilityCB->abilityConnectionCB.resultCode = resultCode; + connectAbilityCB->abilityConnectionCB.connection = remoteObject; + work->data = (void *)connectAbilityCB; + + int rev = uv_queue_work( + loop, work, [](uv_work_t *work) {}, UvWorkOnAbilityConnectDone); + if (rev != 0) { + if (connectAbilityCB != nullptr) { + delete connectAbilityCB; + connectAbilityCB = nullptr; + } + if (work != nullptr) { + delete work; + work = nullptr; + } + } + HILOG_INFO("%{public}s, end.", __func__); +} + +void UvWorkOnAbilityDisconnectDone(uv_work_t *work, int status) +{ + HILOG_INFO("UvWorkOnAbilityDisconnectDone, uv_queue_work"); + if (work == nullptr) { + HILOG_ERROR("UvWorkOnAbilityDisconnectDone, work is null"); + return; + } + // JS Thread + ConnectAbilityCB *connectAbilityCB = static_cast(work->data); + if (connectAbilityCB == nullptr) { + HILOG_ERROR("UvWorkOnAbilityDisconnectDone, connectAbilityCB is null"); + return; + } + napi_value result = nullptr; + result = WrapElementName(connectAbilityCB->cbBase.cbInfo.env, connectAbilityCB->abilityConnectionCB.elementName); + + napi_value callback = 0; + napi_value undefined = 0; + napi_get_undefined(connectAbilityCB->cbBase.cbInfo.env, &undefined); + napi_value callResult = 0; + napi_get_reference_value(connectAbilityCB->cbBase.cbInfo.env, connectAbilityCB->cbBase.cbInfo.callback, &callback); + + napi_call_function(connectAbilityCB->cbBase.cbInfo.env, undefined, callback, ARGS_ONE, &result, &callResult); + if (connectAbilityCB->cbBase.cbInfo.callback != nullptr) { + napi_delete_reference(connectAbilityCB->cbBase.cbInfo.env, connectAbilityCB->cbBase.cbInfo.callback); + } + + // release connect + HILOG_INFO("UvWorkOnAbilityDisconnectDone connects_.size:%{public}zu", connects_.size()); + std::string bundleName = connectAbilityCB->abilityConnectionCB.elementName.GetBundleName(); + std::string abilityName = connectAbilityCB->abilityConnectionCB.elementName.GetAbilityName(); + auto item = std::find_if(connects_.begin(), + connects_.end(), + [bundleName, abilityName](const std::map>::value_type &obj) { + return (bundleName == obj.first.want.GetBundle()) && + (abilityName == obj.first.want.GetElement().GetAbilityName()); + }); + if (item != connects_.end()) { + // match bundlename && abilityname + connects_.erase(item); + HILOG_INFO("UvWorkOnAbilityDisconnectDone erase connects_.size:%{public}zu", connects_.size()); + } + + if (connectAbilityCB != nullptr) { + delete connectAbilityCB; + connectAbilityCB = nullptr; + } + if (work != nullptr) { + delete work; + work = nullptr; + } + HILOG_INFO("UvWorkOnAbilityDisconnectDone, uv_queue_work end"); +} + +void NAPIAbilityConnection::OnAbilityDisconnectDone(const AppExecFwk::ElementName &element, int resultCode) +{ + HILOG_INFO("%{public}s, called.", __func__); + + uv_loop_s *loop = nullptr; + napi_get_uv_event_loop(env_, &loop); + if (loop == nullptr) { + HILOG_ERROR("%{public}s, loop == nullptr.", __func__); + return; + } + + HILOG_INFO("OnAbilityDisconnectDone bundleName:%{public}s abilityName:%{public}s resultCode:%{public}d", + element.GetBundleName().c_str(), + element.GetAbilityName().c_str(), + resultCode); + uv_work_t *work = new uv_work_t; + if (work == nullptr) { + HILOG_ERROR("%{public}s, work == nullptr.", __func__); + return; + } + + ConnectAbilityCB *connectAbilityCB = new (std::nothrow) ConnectAbilityCB; + if (connectAbilityCB == nullptr) { + HILOG_ERROR("%{public}s, connectAbilityCB == nullptr.", __func__); + if (work != nullptr) { + delete work; + work = nullptr; + } + return; + } + connectAbilityCB->cbBase.cbInfo.env = env_; + connectAbilityCB->cbBase.cbInfo.callback = disconnectRef_; + connectAbilityCB->abilityConnectionCB.elementName = element; + connectAbilityCB->abilityConnectionCB.resultCode = resultCode; + work->data = (void *)connectAbilityCB; + + int rev = uv_queue_work( + loop, work, [](uv_work_t *work) {}, UvWorkOnAbilityDisconnectDone); + if (rev != 0) { + if (connectAbilityCB != nullptr) { + delete connectAbilityCB; + connectAbilityCB = nullptr; + } + if (work != nullptr) { + delete work; + work = nullptr; + } + } + HILOG_INFO("%{public}s, end.", __func__); +} + +/** + * @brief AcquireDataAbilityHelper. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_AcquireDataAbilityHelperCommon(napi_env env, napi_callback_info info, AbilityType abilityType) +{ + HILOG_INFO("%{public}s,called", __func__); + DataAbilityHelperCB *dataAbilityHelperCB = new (std::nothrow) DataAbilityHelperCB; + if (dataAbilityHelperCB == nullptr) { + HILOG_ERROR("%{public}s, dataAbilityHelperCB == nullptr", __func__); + return WrapVoidToJS(env); + } + + napi_value global = nullptr; + napi_get_global(env, &global); + napi_value abilityObj = nullptr; + napi_get_named_property(env, global, "ability", &abilityObj); + Ability *ability = nullptr; + napi_get_value_external(env, abilityObj, (void **)&ability); + if (ability == nullptr) { + HILOG_ERROR("%{public}s, ability == nullptr", __func__); + if (dataAbilityHelperCB != nullptr) { + delete dataAbilityHelperCB; + dataAbilityHelperCB = nullptr; + } + return WrapVoidToJS(env); + } + + dataAbilityHelperCB->cbBase.cbInfo.env = env; + dataAbilityHelperCB->cbBase.ability = ability; + dataAbilityHelperCB->cbBase.errCode = NAPI_ERR_NO_ERROR; + dataAbilityHelperCB->cbBase.abilityType = abilityType; + napi_value ret = AcquireDataAbilityHelperWrap(env, info, dataAbilityHelperCB); + if (ret == nullptr) { + HILOG_ERROR("%{public}s, ret == nullptr", __func__); + if (dataAbilityHelperCB != nullptr) { + delete dataAbilityHelperCB; + dataAbilityHelperCB = nullptr; + } + ret = WrapVoidToJS(env); + } + HILOG_INFO("%{public}s,end", __func__); + return ret; +} + +/** + * @brief acquireDataAbilityHelper processing function. + * + * @param env The environment that the Node-API call is invoked under. + * @param dataAbilityHelperCB Process data asynchronously. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value AcquireDataAbilityHelperWrap(napi_env env, napi_callback_info info, DataAbilityHelperCB *dataAbilityHelperCB) +{ + HILOG_INFO("%{public}s,called", __func__); + if (dataAbilityHelperCB == nullptr) { + HILOG_ERROR("%{public}s,dataAbilityHelperCB == nullptr", __func__); + return nullptr; + } + + size_t requireArgc = ARGS_ONE; + size_t argc = ARGS_ONE; + napi_value args[ARGS_ONE] = {nullptr}; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, nullptr, nullptr)); + if (argc > requireArgc) { + HILOG_ERROR("%{public}s, Wrong argument count.", __func__); + return nullptr; + } + + napi_valuetype valuetype = napi_undefined; + NAPI_CALL(env, napi_typeof(env, args[PARAM0], &valuetype)); + if (valuetype != napi_string) { + HILOG_ERROR("%{public}s, Wrong argument type.", __func__); + return nullptr; + } + + if (!CheckAbilityType(&dataAbilityHelperCB->cbBase)) { + dataAbilityHelperCB->cbBase.errCode = NAPI_ERR_ABILITY_TYPE_INVALID; + HILOG_ERROR("%{public}s ability type invalid.", __func__); + return nullptr; + } + + napi_value result = nullptr; + NAPI_CALL(env, napi_new_instance(env, g_dataAbilityHelper, 1, &args[PARAM0], &result)); + delete dataAbilityHelperCB; + dataAbilityHelperCB = nullptr; + HILOG_INFO("%{public}s,end", __func__); + return result; +} +} // namespace AppExecFwk +} // namespace OHOS diff --git a/tools/interfaces/kits/napi/aafwk/inner/napi_common/napi_common_ability.h b/tools/interfaces/kits/napi/aafwk/inner/napi_common/napi_common_ability.h new file mode 100755 index 00000000000..eb2b4b7268f --- /dev/null +++ b/tools/interfaces/kits/napi/aafwk/inner/napi_common/napi_common_ability.h @@ -0,0 +1,249 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_APPEXECFWK_NAPI_COMMON_ABILITY_H +#define OHOS_APPEXECFWK_NAPI_COMMON_ABILITY_H +#include "feature_ability_common.h" +#include "ability_info.h" +#include "ability_connect_callback_stub.h" + +namespace OHOS { +namespace AppExecFwk { + +const std::int32_t STR_MAX_SIZE = 128; + +napi_value *GetGlobalClassContext(void); +napi_value GetGlobalDataAbilityHelper(void); +void SaveAppInfo(AppInfo_ &appInfo, const ApplicationInfo &appInfoOrg); +napi_value WrapAppInfo(napi_env env, const AppInfo_ &appInfo); + +/** + * @brief Get Files Dir. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_GetFilesDirCommon(napi_env env, napi_callback_info info, AbilityType abilityType); + +/** + * @brief Obtains the type of this application. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_GetAppTypeCommon(napi_env env, napi_callback_info info, AbilityType abilityType); + +/** + * @brief Obtains information about the current ability. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_GetAbilityInfoCommon(napi_env env, napi_callback_info info, AbilityType abilityType); + +/** + * @brief Obtains the HapModuleInfo object of the application. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_GetHapModuleInfoCommon(napi_env env, napi_callback_info info, AbilityType abilityType); + +/** + * @brief Create asynchronous data. + * + * @param env The environment that the Node-API call is invoked under. + * + * @return Return a pointer to AsyncCallbackInfo on success, nullptr on failure + */ +AsyncCallbackInfo *CreateAsyncCallbackInfo(napi_env env); +/** + * @brief Get context. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_GetContextCommon(napi_env env, napi_callback_info info, AbilityType abilityType); + +/** + * @brief Get want. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_GetWantCommon(napi_env env, napi_callback_info info, AbilityType abilityType); + +/** + * @brief Obtains the class name in this ability name, without the prefixed bundle name. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_GetAbilityNameCommon(napi_env env, napi_callback_info info, AbilityType abilityType); + +/** + * @brief startAbility. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_StartAbilityCommon(napi_env env, napi_callback_info info, AbilityType abilityType); + +/** + * @brief stopAbility. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_StopAbilityCommon(napi_env env, napi_callback_info info, AbilityType abilityType); + +/** + * @brief Obtains the continue ability Info this application. + * + * @param env The environment that the Node-API call is invoked under. + * @param value The value passed into the info. + * @param info The continue ability options info + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value GetContinueAbilityOptionsInfoCommon( + const napi_env &env, const napi_value &value, ContinueAbilityOptionsInfo &info); + +/** + * @brief Obtains the continue ability can reversible or not + * + * @param env The environment that the Node-API call is invoked under. + * @param value The value passed into the info. + * @param info The continue ability options info + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value GetContinueAbilityOptionsReversible( + const napi_env &env, const napi_value &value, ContinueAbilityOptionsInfo &info); + +/** + * @brief Obtains the continue ability Info this application. + * + * @param env The environment that the Node-API call is invoked under. + * @param value The value passed into the info. + * @param info The continue ability options info + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value GetContinueAbilityOptionsDeviceID( + const napi_env &env, const napi_value &value, ContinueAbilityOptionsInfo &info); + +bool UnwrapAbilityStartSetting(napi_env env, napi_value param, AAFwk::AbilityStartSetting &setting); + +class NAPIAbilityConnection : public AAFwk::AbilityConnectionStub { +public: + void OnAbilityConnectDone( + const AppExecFwk::ElementName &element, const sptr &remoteObject, int resultCode) override; + void OnAbilityDisconnectDone(const AppExecFwk::ElementName &element, int resultCode) override; + void SetEnv(const napi_env &env); + void SetConnectCBRef(const napi_ref &ref); + void SetDisconnectCBRef(const napi_ref &ref); + +private: + napi_env env_; + napi_ref connectRef_; + napi_ref disconnectRef_; +}; + +/** + * @brief connectAbility. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_ConnectAbilityCommon(napi_env env, napi_callback_info info, AbilityType abilityType); + +/** + * @brief disconnectAbility. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_DisConnectAbilityCommon(napi_env env, napi_callback_info info, AbilityType abilityType); + +/** + * @brief acquireDataAbilityHelper processing function. + * + * @param env The environment that the Node-API call is invoked under. + * @param dataAbilityHelperCB Process data asynchronously. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value AcquireDataAbilityHelperWrap( + napi_env env, napi_callback_info info, DataAbilityHelperCB *dataAbilityHelperCB); + +/** + * @brief AcquireDataAbilityHelper. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_AcquireDataAbilityHelperCommon(napi_env env, napi_callback_info info, AbilityType abilityType); + +napi_value ConvertAbilityInfo(napi_env env, const AbilityInfo &abilityInfo); + +struct ConnecttionKey { + Want want; + int64_t id; +}; +struct key_compare { + bool operator()(const ConnecttionKey &key1, const ConnecttionKey &key2) const + { + if (key1.id < key2.id) { + return true; + } + return false; + } +}; +static std::map, key_compare> connects_; +static int64_t serialNumber_ = 0; +enum ErrorCode { + NO_ERROR = 0, + INVALID_PARAMETER = -1, + ABILITY_NOT_FOUND = -2, + PERMISSION_DENY = -3, +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif // OHOS_APPEXECFWK_NAPI_COMMON_ABILITY_H diff --git a/tools/interfaces/kits/napi/aafwk/inner/napi_common/napi_common_data.h b/tools/interfaces/kits/napi/aafwk/inner/napi_common/napi_common_data.h new file mode 100755 index 00000000000..ce44f196dc0 --- /dev/null +++ b/tools/interfaces/kits/napi/aafwk/inner/napi_common/napi_common_data.h @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_APPEXECFWK_NAPI_COMMON_DATA_H +#define OHOS_APPEXECFWK_NAPI_COMMON_DATA_H + +#include +#include +#include +#include "napi/native_common.h" +#include "napi/native_node_api.h" +#include "pac_map.h" +#include "ability.h" + +using Ability = OHOS::AppExecFwk::Ability; +namespace OHOS { +namespace AppExecFwk { + +#define NATIVE_C_BUFFER_SIZE 1024 /* Converted to C-style string buffer size */ +#define ARGS_MAX_COUNT 10 +#define ARGS_ASYNC_COUNT 1 + +#define ARGS_ONE 1 +#define ARGS_TWO 2 +#define ARGS_THREE 3 +#define ARGS_FOUR 4 +#define ARGS_FIVE 5 +#define ARGS_SIX 6 +#define ARGS_SEVEN 7 +#define ARGS_EIGHT 8 +#define ARGS_NINE 9 +#define ARGS_TEN 10 + +#define PARAM0 0 +#define PARAM1 1 +#define PARAM2 2 +#define PARAM3 3 +#define PARAM4 4 +#define PARAM5 5 +#define PARAM6 6 +#define PARAM7 7 +#define PARAM8 8 +#define PARAM9 9 +#define PARAM10 10 + +struct CallbackInfo { + napi_env env; + napi_ref callback = 0; + napi_deferred deferred; +}; + +struct CallAbilityParamData { + PacMap paramArgs; + Want want; +}; + +typedef enum { + NVT_NONE = 0, + NVT_UNDEFINED, + NVT_INT32, + NVT_BOOL, + NVT_STRING, + NVT_DOUBLE, + NVT_PACMAP, +} TNativeValueType; + +typedef struct __ThreadReturnData { + TNativeValueType data_type; + int32_t int32_value; + bool bool_value; + std::string str_value; + double double_value; + PacMap pac_value; +} ThreadReturnData; + +typedef struct __AsyncJSCallbackInfo { + CallbackInfo cbInfo; + napi_async_work asyncWork; + napi_deferred deferred; + Ability *ability; + AbilityType abilityType; + CallAbilityParamData param; + ThreadReturnData native_data; + napi_value result; + int error_code; + CallbackInfo *aceCallback; +} AsyncJSCallbackInfo; + +typedef struct __AsyncParamEx { + std::string resource; + size_t argc; + napi_async_execute_callback execute; + napi_async_complete_callback complete; +} AsyncParamEx; + +typedef struct __ComplexArrayData { + std::vector intList; + std::vector longList; + std::vector boolList; + std::vector doubleList; + std::vector stringList; +} ComplexArrayData; + +} // namespace AppExecFwk +} // namespace OHOS +#endif // OHOS_APPEXECFWK_NAPI_COMMON_DATA_H diff --git a/tools/interfaces/kits/napi/aafwk/inner/napi_common/napi_common_error.h b/tools/interfaces/kits/napi/aafwk/inner/napi_common/napi_common_error.h new file mode 100755 index 00000000000..07f660d0b7b --- /dev/null +++ b/tools/interfaces/kits/napi/aafwk/inner/napi_common/napi_common_error.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_APPEXECFWK_NAPI_COMMON_ERROR_H +#define OHOS_APPEXECFWK_NAPI_COMMON_ERROR_H + +namespace OHOS { +namespace AppExecFwk { + +#define NAPI_ERR_NO_ERROR 0 +#define NAPI_ERR_NO_PERMISSION -100 +#define NAPI_ERR_INNER_DATA -101 // Internal data error, data allocation fail +#define NAPI_ERR_ACE_ABILITY -102 // Failed to acquire ability object +#define NAPI_ERR_LONG_CALLBACK -103 // Failed to acquire long callack object +#define NAPI_ERR_PARAM_INVALID -104 // Parameter is invalid +#define NAPI_ERR_ABILITY_TYPE_INVALID -105 // Type of ability is invalid +#define NAPI_ERR_ABILITY_CALL_INVALID -106 // Call the ability interface, the return value is wrong +} // namespace AppExecFwk +} // namespace OHOS +#endif // OHOS_APPEXECFWK_NAPI_COMMON_ERROR_H diff --git a/tools/interfaces/kits/napi/aafwk/inner/napi_common/napi_common_util.cpp b/tools/interfaces/kits/napi/aafwk/inner/napi_common/napi_common_util.cpp new file mode 100755 index 00000000000..d3166b17b16 --- /dev/null +++ b/tools/interfaces/kits/napi/aafwk/inner/napi_common/napi_common_util.cpp @@ -0,0 +1,1116 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "napi_common_util.h" +#include "napi_common_data.h" +#include "napi_common_error.h" +#include "hilog_wrapper.h" +#include "securec.h" + +namespace OHOS { +namespace AppExecFwk { + +bool IsTypeForNapiValue(napi_env env, napi_value param, napi_valuetype expectType) +{ + napi_valuetype valueType = napi_undefined; + + if (napi_typeof(env, param, &valueType) != napi_ok) { + return false; + } + + return valueType == expectType; +} + +bool IsArrayForNapiValue(napi_env env, napi_value param, uint32_t &arraySize) +{ + bool isArray = false; + arraySize = 0; + + if (napi_is_array(env, param, &isArray) != napi_ok || isArray == false) { + return false; + } + + if (napi_get_array_length(env, param, &arraySize) != napi_ok) { + return false; + } + return true; +} + +napi_value WrapVoidToJS(napi_env env) +{ + napi_value result = nullptr; + NAPI_CALL(env, napi_get_null(env, &result)); + return result; +} + +napi_value WrapUndefinedToJS(napi_env env) +{ + napi_value result = nullptr; + NAPI_CALL(env, napi_get_undefined(env, &result)); + return result; +} + +napi_value CreateJSObject(napi_env env) +{ + napi_value result = nullptr; + NAPI_CALL(env, napi_create_object(env, &result)); + return result; +} + +napi_value WrapInt32ToJS(napi_env env, int32_t value) +{ + napi_value result = nullptr; + NAPI_CALL(env, napi_create_int32(env, value, &result)); + return result; +} + +int UnwrapInt32FromJS(napi_env env, napi_value param, int defaultValue) +{ + int value = defaultValue; + if (napi_get_value_int32(env, param, &value) == napi_ok) { + return value; + } else { + return defaultValue; + } +} + +bool UnwrapInt32FromJS2(napi_env env, napi_value param, int &value) +{ + bool result = false; + if (napi_get_value_int32(env, param, &value) == napi_ok) { + result = true; + } + return result; +} + +napi_value WrapLongToJS(napi_env env, long value) +{ + napi_value result = nullptr; + NAPI_CALL(env, napi_create_int32(env, value, &result)); + return result; +} + +long UnwrapLongFromJS(napi_env env, napi_value param, long defaultValue) +{ + int value = 0; + if (napi_get_value_int32(env, param, &value) == napi_ok) { + return value; + } else { + return defaultValue; + } +} + +bool UnwrapLongFromJS2(napi_env env, napi_value param, long &value) +{ + bool result = false; + int natValue = 0; + if (napi_get_value_int32(env, param, &natValue) == napi_ok) { + value = natValue; + result = true; + } + return result; +} + +napi_value WrapInt64ToJS(napi_env env, int64_t value) +{ + napi_value result = nullptr; + NAPI_CALL(env, napi_create_int64(env, value, &result)); + return result; +} + +int64_t UnwrapInt64FromJS(napi_env env, napi_value param, int64_t defaultValue) +{ + int64_t value = defaultValue; + if (napi_get_value_int64(env, param, &value) == napi_ok) { + return value; + } else { + return defaultValue; + } +} + +bool UnwrapInt64FromJS2(napi_env env, napi_value param, int64_t &value) +{ + bool result = false; + if (napi_get_value_int64(env, param, &value) == napi_ok) { + result = true; + } + return result; +} + +napi_value WrapBoolToJS(napi_env env, bool value) +{ + napi_value result = nullptr; + NAPI_CALL(env, napi_get_boolean(env, value, &result)); + return result; +} + +bool UnwrapBoolFromJS(napi_env env, napi_value param, bool defaultValue) +{ + bool value = defaultValue; + if (napi_get_value_bool(env, param, &value) == napi_ok) { + return value; + } else { + return defaultValue; + } +} + +bool UnwrapBoolFromJS2(napi_env env, napi_value param, bool &value) +{ + bool result = false; + if (napi_get_value_bool(env, param, &value) == napi_ok) { + result = true; + } + return result; +} + +napi_value WrapDoubleToJS(napi_env env, double value) +{ + napi_value result = nullptr; + NAPI_CALL(env, napi_create_double(env, value, &result)); + return result; +} + +double UnwrapDoubleFromJS(napi_env env, napi_value param, double defaultValue) +{ + double value = defaultValue; + if (napi_get_value_double(env, param, &value) == napi_ok) { + return value; + } else { + return defaultValue; + } +} + +bool UnwrapDoubleFromJS2(napi_env env, napi_value param, double &value) +{ + bool result = false; + if (napi_get_value_double(env, param, &value) == napi_ok) { + result = true; + } + return result; +} + +napi_value WrapStringToJS(napi_env env, const std::string &value) +{ + napi_value result = nullptr; + NAPI_CALL(env, napi_create_string_utf8(env, value.c_str(), NAPI_AUTO_LENGTH, &result)); + return result; +} + +std::string UnwrapStringFromJS(napi_env env, napi_value param, const std::string &defaultValue) +{ + size_t size = 0; + if (napi_get_value_string_utf8(env, param, nullptr, 0, &size) != napi_ok) { + return defaultValue; + } + + std::string value(""); + if (size == 0) { + return defaultValue; + } + + char *buf = new (std::nothrow) char[size + 1]; + if (buf == nullptr) { + return value; + } + memset_s(buf, size + 1, 0, size + 1); + + bool rev = napi_get_value_string_utf8(env, param, buf, size + 1, &size) == napi_ok; + if (rev) { + value = buf; + } else { + value = defaultValue; + } + + delete[] buf; + buf = nullptr; + return value; +} + +bool UnwrapStringFromJS2(napi_env env, napi_value param, std::string &value) +{ + value = ""; + size_t size = 0; + if (napi_get_value_string_utf8(env, param, nullptr, 0, &size) != napi_ok) { + return false; + } + + if (size == 0) { + return true; + } + + char *buf = new (std::nothrow) char[size + 1]; + if (buf == nullptr) { + return false; + } + memset_s(buf, (size + 1), 0, (size + 1)); + + bool rev = napi_get_value_string_utf8(env, param, buf, size + 1, &size) == napi_ok; + if (rev) { + value = buf; + } + delete[] buf; + buf = nullptr; + return rev; +} + +napi_value WrapArrayInt32ToJS(napi_env env, const std::vector &value) +{ + napi_value jsArray = nullptr; + napi_value jsValue = nullptr; + uint32_t index = 0; + + NAPI_CALL(env, napi_create_array(env, &jsArray)); + for (uint32_t i = 0; i < value.size(); i++) { + jsValue = nullptr; + if (napi_create_int32(env, value[i], &jsValue) == napi_ok) { + if (napi_set_element(env, jsArray, index, jsValue) == napi_ok) { + index++; + } + } + } + return jsArray; +} + +bool UnwrapArrayInt32FromJS(napi_env env, napi_value param, std::vector &value) +{ + uint32_t arraySize = 0; + napi_value jsValue = nullptr; + int natValue = 0; + + if (!IsArrayForNapiValue(env, param, arraySize)) { + return false; + } + + value.clear(); + for (uint32_t i = 0; i < arraySize; i++) { + jsValue = nullptr; + natValue = 0; + if (napi_get_element(env, param, i, &jsValue) != napi_ok) { + return false; + } + + if (!UnwrapInt32FromJS2(env, jsValue, natValue)) { + return false; + } + + value.push_back(natValue); + } + return true; +} + +napi_value WrapArrayLongToJS(napi_env env, const std::vector &value) +{ + napi_value jsArray = nullptr; + napi_value jsValue = nullptr; + uint32_t index = 0; + + NAPI_CALL(env, napi_create_array(env, &jsArray)); + for (uint32_t i = 0; i < value.size(); i++) { + jsValue = nullptr; + if (napi_create_int32(env, (int)(value[i]), &jsValue) == napi_ok) { + if (napi_set_element(env, jsArray, index, jsValue) == napi_ok) { + index++; + } + } + } + return jsArray; +} + +bool UnwrapArrayLongFromJS(napi_env env, napi_value param, std::vector &value) +{ + uint32_t arraySize = 0; + napi_value jsValue = nullptr; + long natValue = 0; + + if (!IsArrayForNapiValue(env, param, arraySize)) { + return false; + } + + value.clear(); + for (uint32_t i = 0; i < arraySize; i++) { + jsValue = nullptr; + natValue = 0; + if (napi_get_element(env, param, i, &jsValue) != napi_ok) { + return false; + } + + if (!UnwrapLongFromJS2(env, jsValue, natValue)) { + return false; + } + + value.push_back(natValue); + } + return true; +} + +napi_value WrapArrayInt64ToJS(napi_env env, const std::vector &value) +{ + napi_value jsArray = nullptr; + napi_value jsValue = nullptr; + uint32_t index = 0; + + NAPI_CALL(env, napi_create_array(env, &jsArray)); + for (uint32_t i = 0; i < value.size(); i++) { + jsValue = nullptr; + if (napi_create_int64(env, value[i], &jsValue) == napi_ok) { + if (napi_set_element(env, jsArray, index, jsValue) == napi_ok) { + index++; + } + } + } + return jsArray; +} + +bool UnwrapArrayInt64FromJS(napi_env env, napi_value param, std::vector &value) +{ + uint32_t arraySize = 0; + napi_value jsValue = nullptr; + int64_t natValue = 0; + + if (!IsArrayForNapiValue(env, param, arraySize)) { + return false; + } + + value.clear(); + for (uint32_t i = 0; i < arraySize; i++) { + jsValue = nullptr; + natValue = 0; + if (napi_get_element(env, param, i, &jsValue) != napi_ok) { + return false; + } + + if (!UnwrapInt64FromJS2(env, jsValue, natValue)) { + return false; + } + + value.push_back(natValue); + } + return true; +} + +napi_value WrapArrayDoubleToJS(napi_env env, const std::vector &value) +{ + napi_value jsArray = nullptr; + napi_value jsValue = nullptr; + uint32_t index = 0; + + NAPI_CALL(env, napi_create_array(env, &jsArray)); + for (uint32_t i = 0; i < value.size(); i++) { + jsValue = nullptr; + if (napi_create_double(env, value[i], &jsValue) == napi_ok) { + if (napi_set_element(env, jsArray, index, jsValue) == napi_ok) { + index++; + } + } + } + return jsArray; +} + +bool UnwrapArrayDoubleFromJS(napi_env env, napi_value param, std::vector &value) +{ + uint32_t arraySize = 0; + napi_value jsValue = nullptr; + double natValue = 0; + + if (!IsArrayForNapiValue(env, param, arraySize)) { + return false; + } + + value.clear(); + for (uint32_t i = 0; i < arraySize; i++) { + jsValue = nullptr; + natValue = 0; + if (napi_get_element(env, param, i, &jsValue) != napi_ok) { + return false; + } + + if (!UnwrapDoubleFromJS2(env, jsValue, natValue)) { + return false; + } + + value.push_back(natValue); + } + return true; +} + +napi_value WrapArrayBoolToJS(napi_env env, const std::vector &value) +{ + napi_value jsArray = nullptr; + napi_value jsValue = nullptr; + uint32_t index = 0; + + NAPI_CALL(env, napi_create_array(env, &jsArray)); + for (uint32_t i = 0; i < value.size(); i++) { + jsValue = nullptr; + if (napi_get_boolean(env, value[i], &jsValue) == napi_ok) { + if (napi_set_element(env, jsArray, index, jsValue) == napi_ok) { + index++; + } + } + } + return jsArray; +} + +bool UnwrapArrayBoolFromJS(napi_env env, napi_value param, std::vector &value) +{ + uint32_t arraySize = 0; + napi_value jsValue = nullptr; + bool natValue = 0; + + if (!IsArrayForNapiValue(env, param, arraySize)) { + return false; + } + + value.clear(); + for (uint32_t i = 0; i < arraySize; i++) { + jsValue = nullptr; + natValue = 0; + if (napi_get_element(env, param, i, &jsValue) != napi_ok) { + return false; + } + + if (!UnwrapBoolFromJS2(env, jsValue, natValue)) { + return false; + } + + value.push_back(natValue); + } + return true; +} + +napi_value WrapArrayStringToJS(napi_env env, const std::vector &value) +{ + napi_value jsArray = nullptr; + napi_value jsValue = nullptr; + uint32_t index = 0; + + NAPI_CALL(env, napi_create_array(env, &jsArray)); + for (uint32_t i = 0; i < value.size(); i++) { + jsValue = nullptr; + if (napi_create_string_utf8(env, value[i].c_str(), NAPI_AUTO_LENGTH, &jsValue) == napi_ok) { + if (napi_set_element(env, jsArray, index, jsValue) == napi_ok) { + index++; + } + } + } + return jsArray; +} + +bool UnwrapArrayStringFromJS(napi_env env, napi_value param, std::vector &value) +{ + uint32_t arraySize = 0; + napi_value jsValue = nullptr; + std::string natValue(""); + + if (!IsArrayForNapiValue(env, param, arraySize)) { + return false; + } + + value.clear(); + for (uint32_t i = 0; i < arraySize; i++) { + jsValue = nullptr; + natValue = ""; + if (napi_get_element(env, param, i, &jsValue) != napi_ok) { + return false; + } + + if (!UnwrapStringFromJS2(env, jsValue, natValue)) { + return false; + } + + value.push_back(natValue); + } + return true; +} + +bool UnwrapArrayComplexFromJS(napi_env env, napi_value param, ComplexArrayData &value) +{ + uint32_t arraySize = 0; + if (!IsArrayForNapiValue(env, param, arraySize)) { + return false; + } + + napi_valuetype valueType = napi_undefined; + napi_value jsValue = nullptr; + bool isDouble = false; + + value.intList.clear(); + value.longList.clear(); + value.boolList.clear(); + value.doubleList.clear(); + value.stringList.clear(); + + for (uint32_t i = 0; i < arraySize; i++) { + jsValue = nullptr; + valueType = napi_undefined; + NAPI_CALL_BASE(env, napi_get_element(env, param, i, &jsValue), false); + NAPI_CALL_BASE(env, napi_typeof(env, jsValue, &valueType), false); + switch (valueType) { + case napi_string: { + std::string elementValue(""); + if (UnwrapStringFromJS2(env, jsValue, elementValue)) { + value.stringList.push_back(elementValue); + } else { + return false; + } + break; + } + case napi_boolean: { + bool elementValue = false; + NAPI_CALL_BASE(env, napi_get_value_bool(env, jsValue, &elementValue), false); + value.boolList.push_back(elementValue); + break; + } + case napi_number: { + int32_t elementInt32 = 0; + double elementDouble = 0.0; + if (isDouble) { + if (napi_get_value_double(env, jsValue, &elementDouble) == napi_ok) { + value.doubleList.push_back(elementDouble); + } + break; + } else { + bool isReadValue32 = napi_get_value_int32(env, jsValue, &elementInt32) == napi_ok; + bool isReadDouble = napi_get_value_double(env, jsValue, &elementDouble) == napi_ok; + if (isReadValue32 && isReadDouble) { + if (abs(elementDouble - elementInt32 * 1.0) > 0.0) { + isDouble = true; + if (value.intList.size() > 0) { + for (size_t j = 0; j < value.intList.size(); j++) { + value.doubleList.push_back(value.intList[j]); + } + value.intList.clear(); + } + value.doubleList.push_back(elementDouble); + } else { + value.intList.push_back(elementInt32); + } + } else if (isReadValue32) { + value.intList.push_back(elementInt32); + } else if (isReadDouble) { + isDouble = true; + if (value.intList.size() > 0) { + for (size_t j = 0; j < value.intList.size(); j++) { + value.doubleList.push_back(value.intList[j]); + } + value.intList.clear(); + } + value.doubleList.push_back(elementDouble); + } + } + break; + } + default: + break; + } + } + return true; +} + +/** + * @brief Indicates the specified attribute exists in the object passed by JS. + * + * @param env The environment that the Node-API call is invoked under. + * @param jsObject Indicates object passed by JS. + * @param propertyName Indicates the name of the property. + * + * @return Returns true if the attribute exists, else returns false. + */ +bool IsExistsByPropertyName(napi_env env, napi_value jsObject, const char *propertyName) +{ + bool result = false; + if (napi_has_named_property(env, jsObject, propertyName, &result) == napi_ok) { + return result; + } else { + return false; + } +} + +/** + * @brief Get the JSValue of the specified name from the JS object. + * + * @param env The environment that the Node-API call is invoked under. + * @param jsObject Indicates object passed by JS. + * @param propertyName Indicates the name of the property. + * @param expectType Indicates expected JS data type. + * + * @return Return the property value of the specified property name int jsObject on success, otherwise return nullptr. + */ +napi_value GetPropertyValueByPropertyName( + napi_env env, napi_value jsObject, const char *propertyName, napi_valuetype expectType) +{ + napi_value value = nullptr; + if (IsExistsByPropertyName(env, jsObject, propertyName) == false) { + return nullptr; + } + + if (napi_get_named_property(env, jsObject, propertyName, &value) != napi_ok) { + return nullptr; + } + + if (!IsTypeForNapiValue(env, value, expectType)) { + return nullptr; + } + + return value; +} + +bool SetPropertyValueByPropertyName(napi_env env, napi_value jsObject, const char *propertyName, napi_value value) +{ + if (value != nullptr && propertyName != nullptr) { + NAPI_CALL_BASE(env, napi_set_named_property(env, jsObject, propertyName, value), false); + return true; + } + return false; +} + +/** + * @brief Get the native number(int32) from the JSObject of the given property name. + * + * @param env The environment that the Node-API call is invoked under. + * @param jsObject Indicates object passed by JS. + * @param propertyName Indicates the name of the property. + * @param value Indicates the returned native value. + * + * @return Return true if successful, else return false. + */ +bool UnwrapInt32ByPropertyName(napi_env env, napi_value jsObject, const char *propertyName, int32_t &value) +{ + napi_value jsValue = GetPropertyValueByPropertyName(env, jsObject, propertyName, napi_number); + if (jsValue != nullptr) { + return UnwrapInt32FromJS2(env, jsValue, value); + } else { + return false; + } +} + +/** + * @brief Get the native number(double) from the JSObject of the given property name. + * + * @param env The environment that the Node-API call is invoked under. + * @param jsObject Indicates object passed by JS. + * @param propertyName Indicates the name of the property. + * @param value Indicates the returned native value. + * + * @return Return true if successful, else return false. + */ +bool UnwrapDoubleByPropertyName(napi_env env, napi_value jsObject, const char *propertyName, double &value) +{ + napi_value jsValue = GetPropertyValueByPropertyName(env, jsObject, propertyName, napi_number); + if (jsValue != nullptr) { + return UnwrapDoubleFromJS2(env, jsValue, value); + } else { + return false; + } +} + +/** + * @brief Get the native boolean from the JSObject of the given property name. + * + * @param env The environment that the Node-API call is invoked under. + * @param jsObject Indicates object passed by JS. + * @param propertyName Indicates the name of the property. + * @param value Indicates the returned native value. + * + * @return Return true if successful, else return false. + */ +bool UnwrapBooleanByPropertyName(napi_env env, napi_value jsObject, const char *propertyName, bool &value) +{ + napi_value jsValue = GetPropertyValueByPropertyName(env, jsObject, propertyName, napi_boolean); + if (jsValue != nullptr) { + return UnwrapBoolFromJS2(env, jsValue, value); + } else { + return false; + } +} + +bool UnwrapBooleanArrayByPropertyName( + napi_env env, napi_value jsObject, const char *propertyName, std::vector &value) +{ + napi_value jsArray = GetPropertyValueByPropertyName(env, jsObject, propertyName, napi_object); + if (jsArray == nullptr) { + return false; + } + + return UnwrapArrayBoolFromJS(env, jsArray, value); +} + +/** + * @brief Get the native string from the JSObject of the given property name. + * + * @param env The environment that the Node-API call is invoked under. + * @param jsObject Indicates object passed by JS. + * @param propertyName Indicates the name of the property. + * @param value Indicates the returned native value. + * + * @return Return true if successful, else return false. + */ +bool UnwrapStringByPropertyName(napi_env env, napi_value jsObject, const char *propertyName, std::string &value) +{ + napi_value jsValue = GetPropertyValueByPropertyName(env, jsObject, propertyName, napi_string); + if (jsValue != nullptr) { + return UnwrapStringFromJS2(env, jsValue, value); + } else { + return false; + } +} + +bool UnwrapStringArrayByPropertyName( + napi_env env, napi_value jsObject, const char *propertyName, std::vector &value) +{ + napi_value jsArray = GetPropertyValueByPropertyName(env, jsObject, propertyName, napi_object); + if (jsArray == nullptr) { + return false; + } + + return UnwrapArrayStringFromJS(env, jsArray, value); +} + +bool UnwrapComplexArrayByPropertyName( + napi_env env, napi_value jsObject, const char *propertyName, ComplexArrayData &value) +{ + napi_value jsArray = GetPropertyValueByPropertyName(env, jsObject, propertyName, napi_object); + if (jsArray == nullptr) { + return false; + } + + return UnwrapArrayComplexFromJS(env, jsArray, value); +} + +void ClearThreadReturnData(ThreadReturnData *data) +{ + if (data != nullptr) { + data->data_type = NVT_NONE; + data->int32_value = 0; + data->bool_value = false; + data->str_value = ""; + data->double_value = 0.0; + } +} + +napi_value GetCallbackErrorValue(napi_env env, int errCode) +{ + napi_value jsObject = nullptr; + napi_value jsValue = nullptr; + NAPI_CALL(env, napi_create_int32(env, errCode, &jsValue)); + NAPI_CALL(env, napi_create_object(env, &jsObject)); + NAPI_CALL(env, napi_set_named_property(env, jsObject, "code", jsValue)); + return jsObject; +} + +/** + * @brief Create asynchronous data. + * + * @param env The environment that the Node-API call is invoked under. + * + * @return Return a pointer to AsyncPermissionCallbackInfo on success, nullptr on failure + */ +AsyncJSCallbackInfo *CreateAsyncJSCallbackInfo(napi_env env) +{ + HILOG_INFO("%{public}s called.", __func__); + + napi_value global = 0; + NAPI_CALL(env, napi_get_global(env, &global)); + + napi_value abilityObj = 0; + NAPI_CALL(env, napi_get_named_property(env, global, "ability", &abilityObj)); + + Ability *ability = nullptr; + NAPI_CALL(env, napi_get_value_external(env, abilityObj, (void **)&ability)); + + AsyncJSCallbackInfo *asyncCallbackInfo = new (std::nothrow) AsyncJSCallbackInfo; + if (asyncCallbackInfo == nullptr) { + HILOG_ERROR("%{public}s, asyncCallbackInfo == nullptr.", __func__); + return nullptr; + } + asyncCallbackInfo->cbInfo.env = env; + asyncCallbackInfo->cbInfo.callback = nullptr; + asyncCallbackInfo->asyncWork = nullptr; + asyncCallbackInfo->deferred = nullptr; + asyncCallbackInfo->ability = ability; + asyncCallbackInfo->abilityType = AbilityType::UNKNOWN; + asyncCallbackInfo->aceCallback = nullptr; + + if (asyncCallbackInfo != nullptr) { + ClearThreadReturnData(&asyncCallbackInfo->native_data); + } + return asyncCallbackInfo; +} + +void FreeAsyncJSCallbackInfo(AsyncJSCallbackInfo **asyncCallbackInfo) +{ + if (asyncCallbackInfo == nullptr) { + return; + } + if (*asyncCallbackInfo == nullptr) { + return; + } + + if ((*asyncCallbackInfo)->cbInfo.callback != nullptr && (*asyncCallbackInfo)->cbInfo.env != nullptr) { + napi_delete_reference((*asyncCallbackInfo)->cbInfo.env, (*asyncCallbackInfo)->cbInfo.callback); + (*asyncCallbackInfo)->cbInfo.callback = nullptr; + (*asyncCallbackInfo)->cbInfo.env = nullptr; + } + + delete (*asyncCallbackInfo); + *asyncCallbackInfo = nullptr; +} + +/** + * @brief Convert local data to JS data. + * + * @param env The environment that the Node-API call is invoked under. + * @param data The local data. + * @param value the JS data. + * + * @return The return value from NAPI C++ to JS for the module. + */ +bool WrapThreadReturnData(napi_env env, const ThreadReturnData *data, napi_value *value) +{ + if (data == nullptr || value == nullptr) { + return false; + } + + switch (data->data_type) { + case NVT_UNDEFINED: + NAPI_CALL_BASE(env, napi_get_undefined(env, value), false); + break; + case NVT_INT32: + NAPI_CALL_BASE(env, napi_create_int32(env, data->int32_value, value), false); + break; + case NVT_BOOL: + NAPI_CALL_BASE(env, napi_get_boolean(env, data->bool_value, value), false); + break; + case NVT_STRING: + NAPI_CALL_BASE(env, napi_create_string_utf8(env, data->str_value.c_str(), NAPI_AUTO_LENGTH, value), false); + break; + default: + NAPI_CALL_BASE(env, napi_get_null(env, value), false); + break; + } + return true; +} + +/** + * @brief Create asynchronous data. + * + * @param env The environment that the Node-API call is invoked under. + * @param param Parameter list. + * @param callback Point to asynchronous processing of data. + * + * @return Return true successfully, otherwise return false. + */ +bool CreateAsyncCallback(napi_env env, napi_value param, AsyncJSCallbackInfo *callback) +{ + HILOG_INFO("%{public}s called.", __func__); + + if (param == nullptr || callback == nullptr) { + HILOG_INFO("%{public}s called, param or callback is null.", __func__); + return false; + } + + callback->cbInfo.callback = CreateCallbackRefFromJS(env, param); + if (callback->cbInfo.callback == nullptr) { + HILOG_INFO("%{public}s, create ref failed.", __func__); + return false; + } + + return true; +} + +napi_ref CreateCallbackRefFromJS(napi_env env, napi_value param) +{ + if (env == nullptr || param == nullptr) { + HILOG_INFO("%{public}s called, env or param is null ", __func__); + return nullptr; + } + + napi_valuetype valueType = napi_undefined; + NAPI_CALL(env, napi_typeof(env, param, &valueType)); + + if (valueType != napi_function) { + HILOG_INFO("%{public}s called, Param is invalid.", __func__); + return nullptr; + } + + napi_ref callbackRef = nullptr; + NAPI_CALL(env, napi_create_reference(env, param, 1, &callbackRef)); + return callbackRef; +} + +/** + * @brief Asynchronous callback processing. + * + * @param env The environment that the Node-API call is invoked under. + * @param asyncCallbackInfo Process data asynchronously. + * @param param other param. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value ExecuteAsyncCallbackWork(napi_env env, AsyncJSCallbackInfo *asyncCallbackInfo, const AsyncParamEx *param) +{ + HILOG_INFO("%{public}s called.", __func__); + if (asyncCallbackInfo == nullptr || param == nullptr) { + HILOG_INFO("%{public}s called, asyncCallbackInfo or param is null", __func__); + return nullptr; + } + + napi_value resourceName = nullptr; + NAPI_CALL(env, napi_create_string_latin1(env, param->resource.c_str(), NAPI_AUTO_LENGTH, &resourceName)); + + NAPI_CALL(env, + napi_create_async_work(env, + nullptr, + resourceName, + param->execute, + param->complete, + (void *)asyncCallbackInfo, + &asyncCallbackInfo->asyncWork)); + + NAPI_CALL(env, napi_queue_async_work(env, asyncCallbackInfo->asyncWork)); + + return WrapVoidToJS(env); +} + +/** + * @brief Asynchronous promise processing. + * + * @param env The environment that the Node-API call is invoked under. + * @param asyncCallbackInfo Process data asynchronously. + * @param param other param. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value ExecutePromiseCallbackWork(napi_env env, AsyncJSCallbackInfo *asyncCallbackInfo, const AsyncParamEx *param) +{ + HILOG_INFO("%{public}s called.", __func__); + if (asyncCallbackInfo == nullptr || param == nullptr) { + HILOG_INFO("%{public}s called, asyncCallbackInfo or param is null", __func__); + return nullptr; + } + + napi_value resourceName = 0; + NAPI_CALL(env, napi_create_string_latin1(env, param->resource.c_str(), NAPI_AUTO_LENGTH, &resourceName)); + + napi_deferred deferred = 0; + napi_value promise = 0; + NAPI_CALL(env, napi_create_promise(env, &deferred, &promise)); + + asyncCallbackInfo->deferred = deferred; + NAPI_CALL(env, + napi_create_async_work(env, + nullptr, + resourceName, + param->execute, + param->complete, + (void *)asyncCallbackInfo, + &asyncCallbackInfo->asyncWork)); + + NAPI_CALL(env, napi_queue_async_work(env, asyncCallbackInfo->asyncWork)); + return promise; +} + +/** + * @brief The callback at the end of the asynchronous callback. + * + * @param env The environment that the Node-API call is invoked under. + * @param data Point to asynchronous processing of data. + */ +void CompleteAsyncCallbackWork(napi_env env, napi_status status, void *data) +{ + HILOG_INFO("%{public}s called.", __func__); + + AsyncJSCallbackInfo *asyncCallbackInfo = (AsyncJSCallbackInfo *)data; + if (asyncCallbackInfo == nullptr) { + HILOG_INFO("%{public}s called, asyncCallbackInfo is null", __func__); + return; + } + + napi_value callback = 0; + napi_value undefined = 0; + napi_get_undefined(env, &undefined); + napi_value callResult = 0; + napi_value revParam[ARGS_TWO] = {nullptr}; + + revParam[PARAM0] = GetCallbackErrorValue(env, asyncCallbackInfo->error_code); + WrapThreadReturnData(env, &asyncCallbackInfo->native_data, &revParam[PARAM1]); + + if (asyncCallbackInfo->cbInfo.callback != nullptr) { + napi_get_reference_value(env, asyncCallbackInfo->cbInfo.callback, &callback); + napi_call_function(env, undefined, callback, ARGS_TWO, revParam, &callResult); + napi_delete_reference(env, asyncCallbackInfo->cbInfo.callback); + } + + napi_delete_async_work(env, asyncCallbackInfo->asyncWork); + delete asyncCallbackInfo; + asyncCallbackInfo = nullptr; +} + +/** + * @brief The callback at the end of the Promise callback. + * + * @param env The environment that the Node-API call is invoked under. + * @param data Point to asynchronous processing of data. + */ +void CompletePromiseCallbackWork(napi_env env, napi_status status, void *data) +{ + HILOG_INFO("%{public}s called.", __func__); + + AsyncJSCallbackInfo *asyncCallbackInfo = (AsyncJSCallbackInfo *)data; + if (asyncCallbackInfo == nullptr) { + HILOG_INFO("%{public}s called, asyncCallbackInfo is null", __func__); + return; + } + + napi_value result = 0; + if (asyncCallbackInfo->error_code == NAPI_ERR_NO_ERROR) { + WrapThreadReturnData(env, &asyncCallbackInfo->native_data, &result); + napi_resolve_deferred(env, asyncCallbackInfo->deferred, result); + } else { + result = GetCallbackErrorValue(env, asyncCallbackInfo->error_code); + napi_reject_deferred(env, asyncCallbackInfo->deferred, result); + } + napi_delete_async_work(env, asyncCallbackInfo->asyncWork); + delete asyncCallbackInfo; + asyncCallbackInfo = nullptr; +} + +std::vector ConvertU8Vector(napi_env env, napi_value jsValue) +{ + bool isTypedArray = false; + if (napi_is_typedarray(env, jsValue, &isTypedArray) != napi_ok || !isTypedArray) { + return {}; + } + + napi_typedarray_type type; + size_t length = 0; + napi_value buffer = nullptr; + size_t offset = 0; + NAPI_CALL_BASE(env, napi_get_typedarray_info(env, jsValue, &type, &length, nullptr, &buffer, &offset), {}); + if (type != napi_uint8_array) { + return {}; + } + uint8_t *data = nullptr; + size_t total = 0; + NAPI_CALL_BASE(env, napi_get_arraybuffer_info(env, buffer, reinterpret_cast(&data), &total), {}); + length = std::min(length, total - offset); + std::vector result(sizeof(uint8_t) + length); + memcpy_s(result.data(), result.size(), &data[offset], length); + return result; +} + +} // namespace AppExecFwk +} // namespace OHOS diff --git a/tools/interfaces/kits/napi/aafwk/inner/napi_common/napi_common_util.h b/tools/interfaces/kits/napi/aafwk/inner/napi_common/napi_common_util.h new file mode 100755 index 00000000000..3844f23d4e3 --- /dev/null +++ b/tools/interfaces/kits/napi/aafwk/inner/napi_common/napi_common_util.h @@ -0,0 +1,242 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_APPEXECFWK_NAPI_COMMON_UTIL_H +#define OHOS_APPEXECFWK_NAPI_COMMON_UTIL_H + +#include "napi/native_common.h" +#include "napi/native_node_api.h" +#include "napi_common_data.h" + +namespace OHOS { +namespace AppExecFwk { + +static constexpr int32_t DEFAULT_BUF_SIZE = 1024; +static constexpr int32_t ASYNC_RST_SIZE = 2; + +bool IsTypeForNapiValue(napi_env env, napi_value param, napi_valuetype expectType); +bool IsArrayForNapiValue(napi_env env, napi_value param, uint32_t &arraySize); + +napi_value WrapVoidToJS(napi_env env); +napi_value WrapUndefinedToJS(napi_env env); + +napi_value CreateJSObject(napi_env env); + +napi_value WrapInt32ToJS(napi_env env, int32_t value); +int UnwrapInt32FromJS(napi_env env, napi_value param, int defaultValue = 0); +bool UnwrapInt32FromJS2(napi_env env, napi_value param, int &value); + +napi_value WrapLongToJS(napi_env env, long value); +long UnwrapLongFromJS(napi_env env, napi_value param, long defaultValue = 0); +bool UnwrapLongFromJS2(napi_env env, napi_value param, long &value); + +napi_value WrapInt64ToJS(napi_env env, int64_t value); +int64_t UnwrapInt64FromJS(napi_env env, napi_value param, int64_t defaultValue = 0); +bool UnwrapInt64FromJS2(napi_env env, napi_value param, int64_t &value); + +napi_value WrapBoolToJS(napi_env env, bool value); +bool UnWrapBoolFromJS(napi_env env, napi_value param, bool defaultValue = false); +bool UnwrapBoolFromJS2(napi_env env, napi_value param, bool &value); + +napi_value WrapDoubleToJS(napi_env env, double value); +double UnWrapDoubleFromJS(napi_env env, napi_value param, double defaultValue = 0.0); +bool UnWrapDoubleFromJS2(napi_env env, napi_value param, double &value); + +napi_value WrapStringToJS(napi_env env, const std::string &value); +std::string UnwrapStringFromJS(napi_env env, napi_value param, const std::string &defaultValue = ""); +bool UnwrapStringFromJS2(napi_env env, napi_value param, std::string &value); + +napi_value WrapArrayInt32ToJS(napi_env env, const std::vector &value); +bool UnwrapArrayInt32FromJS(napi_env env, napi_value param, std::vector &value); + +napi_value WrapArrayLongToJS(napi_env env, const std::vector &value); +bool UnwrapArrayLongFromJS(napi_env env, napi_value param, std::vector &value); + +napi_value WrapArrayInt64ToJS(napi_env env, const std::vector &value); +bool UnwrapArrayInt64FromJS(napi_env env, napi_value param, std::vector &value); + +napi_value WrapArrayDoubleToJS(napi_env env, const std::vector &value); +bool UnwrapArrayDoubleFromJS(napi_env env, napi_value param, std::vector &value); + +napi_value WrapArrayBoolToJS(napi_env env, const std::vector &value); +bool UnwrapArrayBoolFromJS(napi_env env, napi_value param, std::vector &value); + +napi_value WrapArrayStringToJS(napi_env env, const std::vector &value); +bool UnwrapArrayStringFromJS(napi_env env, napi_value param, std::vector &value); + +bool UnwrapArrayComplexFromJS(napi_env env, napi_value param, ComplexArrayData &value); + +/** + * @brief Indicates the specified attribute exists in the object passed by JS. + * + * @param env The environment that the Node-API call is invoked under. + * @param jsObject Indicates object passed by JS. + * @param propertyName Indicates the name of the property. + * + * @return Returns true if the attribute exists, else returns false. + */ +bool IsExistsByPropertyName(napi_env env, napi_value jsObject, const char *propertyName); + +/** + * @brief Get the JSValue of the specified name from the JS object. + * + * @param env The environment that the Node-API call is invoked under. + * @param jsObject Indicates object passed by JS. + * @param propertyName Indicates the name of the property. + * @param expectType Indicates expected JS data type. + * + * @return Return the property value of the specified property name int jsObject on success, otherwise return nullptr. + */ +napi_value GetPropertyValueByPropertyName( + napi_env env, napi_value jsObject, const char *propertyName, napi_valuetype expectType); + +bool SetPropertyValueByPropertyName(napi_env env, napi_value jsObject, const char *propertyName, napi_value value); + +/** + * @brief Get the native number(int32) from the JSObject of the given property name. + * + * @param env The environment that the Node-API call is invoked under. + * @param jsObject Indicates object passed by JS. + * @param propertyName Indicates the name of the property. + * @param value Indicates the returned native value. + * + * @return Return true if successful, else return false. + */ +bool UnwrapInt32ByPropertyName(napi_env env, napi_value jsObject, const char *propertyName, int32_t &value); + +/** + * @brief Get the native number(double) from the JSObject of the given property name. + * + * @param env The environment that the Node-API call is invoked under. + * @param jsObject Indicates object passed by JS. + * @param propertyName Indicates the name of the property. + * @param value Indicates the returned native value. + * + * @return Return true if successful, else return false. + */ +bool UnwrapDoubleByPropertyName(napi_env env, napi_value jsObject, const char *propertyName, double &value); + +/** + * @brief Get the native boolean from the JSObject of the given property name. + * + * @param env The environment that the Node-API call is invoked under. + * @param jsObject Indicates object passed by JS. + * @param propertyName Indicates the name of the property. + * @param value Indicates the returned native value. + * + * @return Return true if successful, else return false. + */ +bool UnwrapBooleanByPropertyName(napi_env env, napi_value jsObject, const char *propertyName, bool &value); +bool UnwrapBooleanArrayByPropertyName( + napi_env env, napi_value jsObject, const char *propertyName, std::vector &value); + +/** + * @brief Get the native string from the JSObject of the given property name. + * + * @param env The environment that the Node-API call is invoked under. + * @param jsObject Indicates object passed by JS. + * @param propertyName Indicates the name of the property. + * @param value Indicates the returned native value. + * + * @return Return true if successful, else return false. + */ +bool UnwrapStringByPropertyName(napi_env env, napi_value jsObject, const char *propertyName, std::string &value); +bool UnwrapStringArrayByPropertyName( + napi_env env, napi_value jsObject, const char *propertyName, std::vector &value); + +bool UnwrapComplexArrayByPropertyName( + napi_env env, napi_value jsObject, const char *propertyName, ComplexArrayData &value); + +void ClearThreadReturnData(ThreadReturnData *data); + +napi_value GetCallbackErrorValue(napi_env env, int errCode); + +/** + * @brief Create asynchronous data. + * + * @param env The environment that the Node-API call is invoked under. + * + * @return Return a pointer to AsyncJSCallbackInfo on success, nullptr on failure + */ +AsyncJSCallbackInfo *CreateAsyncJSCallbackInfo(napi_env env); +void FreeAsyncJSCallbackInfo(AsyncJSCallbackInfo **asyncCallbackInfo); + +/** + * @brief Convert local data to JS data. + * + * @param env The environment that the Node-API call is invoked under. + * @param data The local data. + * @param value the JS data. + * + * @return The return value from NAPI C++ to JS for the module. + */ +bool WrapThreadReturnData(napi_env env, const ThreadReturnData *data, napi_value *value); + +/** + * @brief Create asynchronous data. + * + * @param env The environment that the Node-API call is invoked under. + * @param param Parameter list. + * @param callback Point to asynchronous processing of data. + * + * @return Return true successfully, otherwise return false. + */ +bool CreateAsyncCallback(napi_env env, napi_value param, AsyncJSCallbackInfo *callback); + +napi_ref CreateCallbackRefFromJS(napi_env env, napi_value param); + +/** + * @brief Asynchronous callback processing. + * + * @param env The environment that the Node-API call is invoked under. + * @param asyncCallbackInfo Process data asynchronously. + * @param param other param. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value ExecuteAsyncCallbackWork(napi_env env, AsyncJSCallbackInfo *asyncCallbackInfo, const AsyncParamEx *param); + +/** + * @brief Asynchronous promise processing. + * + * @param env The environment that the Node-API call is invoked under. + * @param asyncCallbackInfo Process data asynchronously. + * @param param other param. + * + * @return Return JS data successfully, otherwise return nullptr. + */ +napi_value ExecutePromiseCallbackWork(napi_env env, AsyncJSCallbackInfo *asyncCallbackInfo, const AsyncParamEx *param); + +/** + * @brief The callback at the end of the asynchronous callback. + * + * @param env The environment that the Node-API call is invoked under. + * @param data Point to asynchronous processing of data. + */ +void CompleteAsyncCallbackWork(napi_env env, napi_status status, void *data); + +/** + * @brief The callback at the end of the Promise callback. + * + * @param env The environment that the Node-API call is invoked under. + * @param data Point to asynchronous processing of data. + */ +void CompletePromiseCallbackWork(napi_env env, napi_status status, void *data); + +std::vector ConvertU8Vector(napi_env env, napi_value jsValue); + +} // namespace AppExecFwk +} // namespace OHOS +#endif // OHOS_APPEXECFWK_NAPI_COMMON_UTIL_H diff --git a/tools/interfaces/kits/napi/aafwk/inner/napi_common/napi_common_want.cpp b/tools/interfaces/kits/napi/aafwk/inner/napi_common/napi_common_want.cpp new file mode 100755 index 00000000000..b177bd45f82 --- /dev/null +++ b/tools/interfaces/kits/napi/aafwk/inner/napi_common/napi_common_want.cpp @@ -0,0 +1,925 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "napi_common_want.h" +#include "napi_common_util.h" +#include "hilog_wrapper.h" +#include "ohos/aafwk/content/want_params_wrapper.h" +#include "ohos/aafwk/base/array_wrapper.h" +#include "ohos/aafwk/base/bool_wrapper.h" +#include "ohos/aafwk/base/byte_wrapper.h" +#include "ohos/aafwk/base/double_wrapper.h" +#include "ohos/aafwk/base/float_wrapper.h" +#include "ohos/aafwk/base/int_wrapper.h" +#include "ohos/aafwk/base/long_wrapper.h" +#include "ohos/aafwk/base/short_wrapper.h" +#include "ohos/aafwk/base/string_wrapper.h" +#include "ohos/aafwk/base/zchar_wrapper.h" + +namespace OHOS { +namespace AppExecFwk { +EXTERN_C_START +/** + * @brief Init param of wantOptions. + * + * @param flagMap Indicates flag of list in Want . + */ +void InnerInitWantOptionsData(std::map &flagMap) +{ + flagMap.emplace("authReadUriPermission", Want::FLAG_AUTH_READ_URI_PERMISSION); + flagMap.emplace("authWriteUriPermission", Want::FLAG_AUTH_WRITE_URI_PERMISSION); + flagMap.emplace("abilityForwardResult", Want::FLAG_ABILITY_FORWARD_RESULT); + flagMap.emplace("abilityContinuation", Want::FLAG_ABILITY_CONTINUATION); + flagMap.emplace("notOhosComponent", Want::FLAG_NOT_OHOS_COMPONENT); + flagMap.emplace("abilityFormEnabled", Want::FLAG_ABILITY_FORM_ENABLED); + flagMap.emplace("authPersistableUriPermission", Want::FLAG_AUTH_PERSISTABLE_URI_PERMISSION); + flagMap.emplace("authPrefixUriPermission", Want::FLAG_AUTH_PREFIX_URI_PERMISSION); + flagMap.emplace("abilitySliceMultiDevice", Want::FLAG_ABILITYSLICE_MULTI_DEVICE); + flagMap.emplace("startForegroundAbility", Want::FLAG_START_FOREGROUND_ABILITY); + flagMap.emplace("installOnDemand", Want::FLAG_INSTALL_ON_DEMAND); + flagMap.emplace("abilitySliceForwardResult", Want::FLAG_ABILITYSLICE_FORWARD_RESULT); + flagMap.emplace("installWithBackgroundMode", Want::FLAG_INSTALL_WITH_BACKGROUND_MODE); +} + +napi_value WrapElementName(napi_env env, const ElementName &elementName) +{ + HILOG_INFO("%{public}s called.", __func__); + + napi_value jsObject = nullptr; + NAPI_CALL(env, napi_create_object(env, &jsObject)); + + napi_value jsValue = nullptr; + HILOG_INFO("%{public}s called. deviceID=%{public}s", __func__, elementName.GetDeviceID().c_str()); + NAPI_CALL(env, napi_create_string_utf8(env, elementName.GetDeviceID().c_str(), NAPI_AUTO_LENGTH, &jsValue)); + NAPI_CALL(env, napi_set_named_property(env, jsObject, "deviceId", jsValue)); + + jsValue = nullptr; + HILOG_INFO("%{public}s called. GetBundleName=%{public}s", __func__, elementName.GetBundleName().c_str()); + NAPI_CALL(env, napi_create_string_utf8(env, elementName.GetBundleName().c_str(), NAPI_AUTO_LENGTH, &jsValue)); + NAPI_CALL(env, napi_set_named_property(env, jsObject, "bundleName", jsValue)); + + jsValue = nullptr; + HILOG_INFO("%{public}s called. GetAbilityName=%{public}s", __func__, elementName.GetAbilityName().c_str()); + NAPI_CALL(env, napi_create_string_utf8(env, elementName.GetAbilityName().c_str(), NAPI_AUTO_LENGTH, &jsValue)); + NAPI_CALL(env, napi_set_named_property(env, jsObject, "abilityName", jsValue)); + + return jsObject; +} + +bool UnwrapElementName(napi_env env, napi_value param, ElementName &elementName) +{ + HILOG_INFO("%{public}s called.", __func__); + + std::string natValue(""); + if (UnwrapStringByPropertyName(env, param, "deviceId", natValue)) { + elementName.SetDeviceID(natValue); + } + + natValue = ""; + if (UnwrapStringByPropertyName(env, param, "bundleName", natValue)) { + elementName.SetBundleName(natValue); + } + + natValue = ""; + if (UnwrapStringByPropertyName(env, param, "abilityName", natValue)) { + elementName.SetAbilityName(natValue); + } + return true; +} +bool InnerWrapWantParamsChar( + napi_env env, napi_value jsObject, const std::string &key, const AAFwk::WantParams &wantParams) +{ + auto value = wantParams.GetParam(key); + AAFwk::IChar *ao = AAFwk::IChar::Query(value); + if (ao != nullptr) { + std::string natValue(static_cast(ao)->ToString()); + HILOG_INFO("%{public}s called. key=%{public}s, natValue=%{public}s", __func__, key.c_str(), natValue.c_str()); + napi_value jsValue = WrapStringToJS(env, natValue); + if (jsValue != nullptr) { + NAPI_CALL_BASE(env, napi_set_named_property(env, jsObject, key.c_str(), jsValue), false); + return true; + } + } + return false; +} + +bool InnerWrapWantParamsString( + napi_env env, napi_value jsObject, const std::string &key, const AAFwk::WantParams &wantParams) +{ + auto value = wantParams.GetParam(key); + AAFwk::IString *ao = AAFwk::IString::Query(value); + if (ao != nullptr) { + std::string natValue = AAFwk::String::Unbox(ao); + HILOG_INFO("%{public}s called. key=%{public}s, natValue=%{public}s", __func__, key.c_str(), natValue.c_str()); + napi_value jsValue = WrapStringToJS(env, natValue); + if (jsValue != nullptr) { + NAPI_CALL_BASE(env, napi_set_named_property(env, jsObject, key.c_str(), jsValue), false); + return true; + } + } + return false; +} + +bool InnerWrapWantParamsBool( + napi_env env, napi_value jsObject, const std::string &key, const AAFwk::WantParams &wantParams) +{ + auto value = wantParams.GetParam(key); + AAFwk::IBoolean *bo = AAFwk::IBoolean::Query(value); + if (bo != nullptr) { + bool natValue = AAFwk::Boolean::Unbox(bo); + napi_value jsValue = WrapBoolToJS(env, natValue); + if (jsValue != nullptr) { + NAPI_CALL_BASE(env, napi_set_named_property(env, jsObject, key.c_str(), jsValue), false); + return true; + } + } + return false; +} + +bool InnerWrapWantParamsByte( + napi_env env, napi_value jsObject, const std::string &key, const AAFwk::WantParams &wantParams) +{ + auto value = wantParams.GetParam(key); + AAFwk::IByte *bo = AAFwk::IByte::Query(value); + if (bo != nullptr) { + int intValue = AAFwk::Byte::Unbox(bo); + napi_value jsValue = WrapInt32ToJS(env, intValue); + if (jsValue != nullptr) { + NAPI_CALL_BASE(env, napi_set_named_property(env, jsObject, key.c_str(), jsValue), false); + return true; + } + } + return false; +} + +bool InnerWrapWantParamsShort( + napi_env env, napi_value jsObject, const std::string &key, const AAFwk::WantParams &wantParams) +{ + auto value = wantParams.GetParam(key); + AAFwk::IShort *ao = AAFwk::IShort::Query(value); + if (ao != nullptr) { + short natValue = AAFwk::Short::Unbox(ao); + napi_value jsValue = WrapInt32ToJS(env, natValue); + if (jsValue != nullptr) { + NAPI_CALL_BASE(env, napi_set_named_property(env, jsObject, key.c_str(), jsValue), false); + return true; + } + } + return false; +} + +bool InnerWrapWantParamsInt32( + napi_env env, napi_value jsObject, const std::string &key, const AAFwk::WantParams &wantParams) +{ + auto value = wantParams.GetParam(key); + AAFwk::IInteger *ao = AAFwk::IInteger::Query(value); + if (ao != nullptr) { + int natValue = AAFwk::Integer::Unbox(ao); + HILOG_INFO("%{public}s called. key=%{public}s, natValue=%{public}d", __func__, key.c_str(), natValue); + napi_value jsValue = WrapInt32ToJS(env, natValue); + if (jsValue != nullptr) { + NAPI_CALL_BASE(env, napi_set_named_property(env, jsObject, key.c_str(), jsValue), false); + return true; + } + } + return false; +} + +bool InnerWrapWantParamsInt64( + napi_env env, napi_value jsObject, const std::string &key, const AAFwk::WantParams &wantParams) +{ + auto value = wantParams.GetParam(key); + AAFwk::ILong *ao = AAFwk::ILong::Query(value); + if (ao != nullptr) { + int64_t natValue = AAFwk::Long::Unbox(ao); + napi_value jsValue = WrapInt64ToJS(env, natValue); + if (jsValue != nullptr) { + NAPI_CALL_BASE(env, napi_set_named_property(env, jsObject, key.c_str(), jsValue), false); + return true; + } + } + return false; +} + +bool InnerWrapWantParamsFloat( + napi_env env, napi_value jsObject, const std::string &key, const AAFwk::WantParams &wantParams) +{ + auto value = wantParams.GetParam(key); + AAFwk::IFloat *ao = AAFwk::IFloat::Query(value); + if (ao != nullptr) { + float natValue = AAFwk::Float::Unbox(ao); + napi_value jsValue = WrapDoubleToJS(env, natValue); + if (jsValue != nullptr) { + NAPI_CALL_BASE(env, napi_set_named_property(env, jsObject, key.c_str(), jsValue), false); + return true; + } + } + return false; +} + +bool InnerWrapWantParamsDouble( + napi_env env, napi_value jsObject, const std::string &key, const AAFwk::WantParams &wantParams) +{ + auto value = wantParams.GetParam(key); + AAFwk::IDouble *ao = AAFwk::IDouble::Query(value); + if (ao != nullptr) { + double natValue = AAFwk::Double::Unbox(ao); + napi_value jsValue = WrapDoubleToJS(env, natValue); + if (jsValue != nullptr) { + NAPI_CALL_BASE(env, napi_set_named_property(env, jsObject, key.c_str(), jsValue), false); + return true; + } + } + return false; +} + +bool InnerWrapWantParamsWantParams( + napi_env env, napi_value jsObject, const std::string &key, const AAFwk::WantParams &wantParams) +{ + HILOG_INFO("%{public}s called. key=%{public}s", __func__, key.c_str()); + auto value = wantParams.GetParam(key); + AAFwk::IWantParams *o = AAFwk::IWantParams::Query(value); + if (o != nullptr) { + AAFwk::WantParams wp = AAFwk::WantParamWrapper::Unbox(o); + napi_value jsValue = WrapWantParams(env, wp); + if (jsValue != nullptr) { + NAPI_CALL_BASE(env, napi_set_named_property(env, jsObject, key.c_str(), jsValue), false); + return true; + } + } + return false; +} +bool InnerWrapWantParamsArrayChar(napi_env env, napi_value jsObject, const std::string &key, sptr &ao) +{ + HILOG_INFO("%{public}s called.", __func__); + long size = 0; + if (ao->GetLength(size) != ERR_OK) { + return false; + } + + std::vector natArray; + for (long i = 0; i < size; i++) { + sptr iface = nullptr; + if (ao->Get(i, iface) == ERR_OK) { + AAFwk::IChar *iValue = AAFwk::IChar::Query(iface); + if (iValue != nullptr) { + std::string str(static_cast(iValue)->ToString()); + HILOG_INFO("%{public}s called. str=%{public}s", __func__, str.c_str()); + natArray.push_back(str); + } + } + } + + napi_value jsValue = WrapArrayStringToJS(env, natArray); + if (jsValue != nullptr) { + NAPI_CALL_BASE(env, napi_set_named_property(env, jsObject, key.c_str(), jsValue), false); + return true; + } + return false; +} + +bool InnerWrapWantParamsArrayString(napi_env env, napi_value jsObject, const std::string &key, sptr &ao) +{ + long size = 0; + if (ao->GetLength(size) != ERR_OK) { + return false; + } + + std::vector natArray; + for (long i = 0; i < size; i++) { + sptr iface = nullptr; + if (ao->Get(i, iface) == ERR_OK) { + AAFwk::IString *iValue = AAFwk::IString::Query(iface); + if (iValue != nullptr) { + natArray.push_back(AAFwk::String::Unbox(iValue)); + } + } + } + + napi_value jsValue = WrapArrayStringToJS(env, natArray); + if (jsValue != nullptr) { + NAPI_CALL_BASE(env, napi_set_named_property(env, jsObject, key.c_str(), jsValue), false); + return true; + } + return false; +} + +bool InnerWrapWantParamsArrayBool(napi_env env, napi_value jsObject, const std::string &key, sptr &ao) +{ + long size = 0; + if (ao->GetLength(size) != ERR_OK) { + return false; + } + + std::vector natArray; + for (long i = 0; i < size; i++) { + sptr iface = nullptr; + if (ao->Get(i, iface) == ERR_OK) { + AAFwk::IBoolean *iValue = AAFwk::IBoolean::Query(iface); + if (iValue != nullptr) { + natArray.push_back(AAFwk::Boolean::Unbox(iValue)); + } + } + } + + napi_value jsValue = WrapArrayBoolToJS(env, natArray); + if (jsValue != nullptr) { + NAPI_CALL_BASE(env, napi_set_named_property(env, jsObject, key.c_str(), jsValue), false); + return true; + } + return false; +} + +bool InnerWrapWantParamsArrayShort(napi_env env, napi_value jsObject, const std::string &key, sptr &ao) +{ + long size = 0; + if (ao->GetLength(size) != ERR_OK) { + return false; + } + + std::vector natArray; + for (long i = 0; i < size; i++) { + sptr iface = nullptr; + if (ao->Get(i, iface) == ERR_OK) { + AAFwk::IShort *iValue = AAFwk::IShort::Query(iface); + if (iValue != nullptr) { + natArray.push_back(AAFwk::Short::Unbox(iValue)); + } + } + } + + napi_value jsValue = WrapArrayInt32ToJS(env, natArray); + if (jsValue != nullptr) { + NAPI_CALL_BASE(env, napi_set_named_property(env, jsObject, key.c_str(), jsValue), false); + return true; + } + return false; +} +bool InnerWrapWantParamsArrayByte(napi_env env, napi_value jsObject, const std::string &key, sptr &ao) +{ + long size = 0; + if (ao->GetLength(size) != ERR_OK) { + return false; + } + + std::vector natArray; + for (long i = 0; i < size; i++) { + sptr iface = nullptr; + if (ao->Get(i, iface) == ERR_OK) { + AAFwk::IByte *iValue = AAFwk::IByte::Query(iface); + if (iValue != nullptr) { + int intValue = AAFwk::Byte::Unbox(iValue); + natArray.push_back(intValue); + } + } + } + + napi_value jsValue = WrapArrayInt32ToJS(env, natArray); + if (jsValue != nullptr) { + NAPI_CALL_BASE(env, napi_set_named_property(env, jsObject, key.c_str(), jsValue), false); + return true; + } + return false; +} + +bool InnerWrapWantParamsArrayInt32(napi_env env, napi_value jsObject, const std::string &key, sptr &ao) +{ + long size = 0; + if (ao->GetLength(size) != ERR_OK) { + return false; + } + + std::vector natArray; + for (long i = 0; i < size; i++) { + sptr iface = nullptr; + if (ao->Get(i, iface) == ERR_OK) { + AAFwk::IInteger *iValue = AAFwk::IInteger::Query(iface); + if (iValue != nullptr) { + natArray.push_back(AAFwk::Integer::Unbox(iValue)); + } + } + } + + napi_value jsValue = WrapArrayInt32ToJS(env, natArray); + if (jsValue != nullptr) { + NAPI_CALL_BASE(env, napi_set_named_property(env, jsObject, key.c_str(), jsValue), false); + return true; + } + return false; +} + +bool InnerWrapWantParamsArrayInt64(napi_env env, napi_value jsObject, const std::string &key, sptr &ao) +{ + long size = 0; + if (ao->GetLength(size) != ERR_OK) { + return false; + } + + std::vector natArray; + for (long i = 0; i < size; i++) { + sptr iface = nullptr; + if (ao->Get(i, iface) == ERR_OK) { + AAFwk::ILong *iValue = AAFwk::ILong::Query(iface); + if (iValue != nullptr) { + natArray.push_back(AAFwk::Long::Unbox(iValue)); + } + } + } + + napi_value jsValue = WrapArrayInt64ToJS(env, natArray); + if (jsValue != nullptr) { + NAPI_CALL_BASE(env, napi_set_named_property(env, jsObject, key.c_str(), jsValue), false); + return true; + } + return false; +} + +bool InnerWrapWantParamsArrayFloat(napi_env env, napi_value jsObject, const std::string &key, sptr &ao) +{ + long size = 0; + if (ao->GetLength(size) != ERR_OK) { + return false; + } + + std::vector natArray; + for (long i = 0; i < size; i++) { + sptr iface = nullptr; + if (ao->Get(i, iface) == ERR_OK) { + AAFwk::IFloat *iValue = AAFwk::IFloat::Query(iface); + if (iValue != nullptr) { + natArray.push_back(AAFwk::Float::Unbox(iValue)); + } + } + } + + napi_value jsValue = WrapArrayDoubleToJS(env, natArray); + if (jsValue != nullptr) { + NAPI_CALL_BASE(env, napi_set_named_property(env, jsObject, key.c_str(), jsValue), false); + return true; + } + return false; +} + +bool InnerWrapWantParamsArrayDouble(napi_env env, napi_value jsObject, const std::string &key, sptr &ao) +{ + long size = 0; + if (ao->GetLength(size) != ERR_OK) { + return false; + } + + std::vector natArray; + for (long i = 0; i < size; i++) { + sptr iface = nullptr; + if (ao->Get(i, iface) == ERR_OK) { + AAFwk::IDouble *iValue = AAFwk::IDouble::Query(iface); + if (iValue != nullptr) { + natArray.push_back(AAFwk::Double::Unbox(iValue)); + } + } + } + + napi_value jsValue = WrapArrayDoubleToJS(env, natArray); + if (jsValue != nullptr) { + NAPI_CALL_BASE(env, napi_set_named_property(env, jsObject, key.c_str(), jsValue), false); + return true; + } + return false; +} + +bool InnerWrapWantParamsArray(napi_env env, napi_value jsObject, const std::string &key, sptr &ao) +{ + HILOG_INFO("%{public}s called. key=%{public}s", __func__, key.c_str()); + if (AAFwk::Array::IsStringArray(ao)) { + return InnerWrapWantParamsArrayString(env, jsObject, key, ao); + } else if (AAFwk::Array::IsBooleanArray(ao)) { + return InnerWrapWantParamsArrayBool(env, jsObject, key, ao); + } else if (AAFwk::Array::IsShortArray(ao)) { + return InnerWrapWantParamsArrayShort(env, jsObject, key, ao); + } else if (AAFwk::Array::IsIntegerArray(ao)) { + return InnerWrapWantParamsArrayInt32(env, jsObject, key, ao); + } else if (AAFwk::Array::IsLongArray(ao)) { + return InnerWrapWantParamsArrayInt64(env, jsObject, key, ao); + } else if (AAFwk::Array::IsFloatArray(ao)) { + return InnerWrapWantParamsArrayFloat(env, jsObject, key, ao); + } else if (AAFwk::Array::IsByteArray(ao)) { + return InnerWrapWantParamsArrayByte(env, jsObject, key, ao); + } else if (AAFwk::Array::IsCharArray(ao)) { + return InnerWrapWantParamsArrayChar(env, jsObject, key, ao); + } else { + return false; + } +} + +napi_value WrapWantParams(napi_env env, const AAFwk::WantParams &wantParams) +{ + HILOG_INFO("%{public}s called.", __func__); + napi_value jsObject = nullptr; + NAPI_CALL(env, napi_create_object(env, &jsObject)); + + napi_value jsValue = nullptr; + const std::map> paramList = wantParams.GetParams(); + for (auto iter = paramList.begin(); iter != paramList.end(); iter++) { + jsValue = nullptr; + if (AAFwk::IString::Query(iter->second) != nullptr) { + InnerWrapWantParamsString(env, jsObject, iter->first, wantParams); + } else if (AAFwk::IBoolean::Query(iter->second) != nullptr) { + InnerWrapWantParamsBool(env, jsObject, iter->first, wantParams); + } else if (AAFwk::IShort::Query(iter->second) != nullptr) { + InnerWrapWantParamsShort(env, jsObject, iter->first, wantParams); + } else if (AAFwk::IInteger::Query(iter->second) != nullptr) { + InnerWrapWantParamsInt32(env, jsObject, iter->first, wantParams); + } else if (AAFwk::ILong::Query(iter->second) != nullptr) { + InnerWrapWantParamsInt64(env, jsObject, iter->first, wantParams); + } else if (AAFwk::IFloat::Query(iter->second) != nullptr) { + InnerWrapWantParamsFloat(env, jsObject, iter->first, wantParams); + } else if (AAFwk::IDouble::Query(iter->second) != nullptr) { + InnerWrapWantParamsDouble(env, jsObject, iter->first, wantParams); + } else if (AAFwk::IChar::Query(iter->second) != nullptr) { + InnerWrapWantParamsChar(env, jsObject, iter->first, wantParams); + } else if (AAFwk::IByte::Query(iter->second) != nullptr) { + InnerWrapWantParamsByte(env, jsObject, iter->first, wantParams); + } else if (AAFwk::IArray::Query(iter->second) != nullptr) { + AAFwk::IArray *ao = AAFwk::IArray::Query(iter->second); + if (ao != nullptr) { + sptr array(ao); + InnerWrapWantParamsArray(env, jsObject, iter->first, array); + } + } else if (AAFwk::IWantParams::Query(iter->second) != nullptr) { + InnerWrapWantParamsWantParams(env, jsObject, iter->first, wantParams); + } + } + return jsObject; +} + +bool InnerSetWantParamsArrayString( + const std::string &key, const std::vector &value, AAFwk::WantParams &wantParams) +{ + long size = value.size(); + sptr ao = new (std::nothrow) AAFwk::Array(size, AAFwk::g_IID_IString); + if (ao != nullptr) { + for (long i = 0; i < size; i++) { + ao->Set(i, AAFwk::String::Box(value[i])); + } + wantParams.SetParam(key, ao); + return true; + } else { + return false; + } +} + +bool InnerSetWantParamsArrayInt(const std::string &key, const std::vector &value, AAFwk::WantParams &wantParams) +{ + long size = value.size(); + sptr ao = new (std::nothrow) AAFwk::Array(size, AAFwk::g_IID_IInteger); + if (ao != nullptr) { + for (long i = 0; i < size; i++) { + ao->Set(i, AAFwk::Integer::Box(value[i])); + } + wantParams.SetParam(key, ao); + return true; + } else { + return false; + } +} + +bool InnerSetWantParamsArrayLong(const std::string &key, const std::vector &value, AAFwk::WantParams &wantParams) +{ + long size = value.size(); + sptr ao = new (std::nothrow) AAFwk::Array(size, AAFwk::g_IID_ILong); + if (ao != nullptr) { + for (long i = 0; i < size; i++) { + ao->Set(i, AAFwk::Long::Box(value[i])); + } + wantParams.SetParam(key, ao); + return true; + } else { + return false; + } +} + +bool InnerSetWantParamsArrayBool(const std::string &key, const std::vector &value, AAFwk::WantParams &wantParams) +{ + long size = value.size(); + sptr ao = new (std::nothrow) AAFwk::Array(size, AAFwk::g_IID_IBoolean); + if (ao != nullptr) { + for (long i = 0; i < size; i++) { + ao->Set(i, AAFwk::Boolean::Box(value[i])); + } + wantParams.SetParam(key, ao); + return true; + } else { + return false; + } +} + +bool InnerSetWantParamsArrayDouble( + const std::string &key, const std::vector &value, AAFwk::WantParams &wantParams) +{ + long size = value.size(); + sptr ao = new (std::nothrow) AAFwk::Array(size, AAFwk::g_IID_IDouble); + if (ao != nullptr) { + for (long i = 0; i < size; i++) { + ao->Set(i, AAFwk::Double::Box(value[i])); + } + wantParams.SetParam(key, ao); + return true; + } else { + return false; + } +} + +bool InnerUnwrapWantParamsArray(napi_env env, const std::string &key, napi_value param, AAFwk::WantParams &wantParams) +{ + HILOG_INFO("%{public}s called.", __func__); + + ComplexArrayData natArrayValue; + if (!UnwrapArrayComplexFromJS(env, param, natArrayValue)) { + return false; + } + + if (natArrayValue.stringList.size() > 0) { + return InnerSetWantParamsArrayString(key, natArrayValue.stringList, wantParams); + } + if (natArrayValue.intList.size() > 0) { + return InnerSetWantParamsArrayInt(key, natArrayValue.intList, wantParams); + } + if (natArrayValue.longList.size() > 0) { + return InnerSetWantParamsArrayLong(key, natArrayValue.longList, wantParams); + } + if (natArrayValue.boolList.size() > 0) { + return InnerSetWantParamsArrayBool(key, natArrayValue.boolList, wantParams); + } + if (natArrayValue.doubleList.size() > 0) { + return InnerSetWantParamsArrayDouble(key, natArrayValue.doubleList, wantParams); + } + + return false; +} + +bool InnerUnwrapWantParams(napi_env env, const std::string &key, napi_value param, AAFwk::WantParams &wantParams) +{ + HILOG_INFO("%{public}s called.", __func__); + AAFwk::WantParams wp; + + if (UnwrapWantParams(env, param, wp)) { + sptr pWantParams = AAFwk::WantParamWrapper::Box(wp); + if (pWantParams != nullptr) { + wantParams.SetParam(key, pWantParams); + return true; + } + } + return false; +} + +bool UnwrapWantParams(napi_env env, napi_value param, AAFwk::WantParams &wantParams) +{ + HILOG_INFO("%{public}s called.", __func__); + + if (!IsTypeForNapiValue(env, param, napi_object)) { + return false; + } + + napi_valuetype jsValueType = napi_undefined; + napi_value jsProNameList = nullptr; + uint32_t jsProCount = 0; + + NAPI_CALL_BASE(env, napi_get_property_names(env, param, &jsProNameList), false); + NAPI_CALL_BASE(env, napi_get_array_length(env, jsProNameList, &jsProCount), false); + HILOG_INFO("%{public}s called. Property size=%{public}d.", __func__, jsProCount); + + napi_value jsProName = nullptr; + napi_value jsProValue = nullptr; + for (uint32_t index = 0; index < jsProCount; index++) { + NAPI_CALL_BASE(env, napi_get_element(env, jsProNameList, index, &jsProName), false); + + std::string strProName = UnwrapStringFromJS(env, jsProName); + HILOG_INFO("%{public}s called. Property name=%{public}s.", __func__, strProName.c_str()); + NAPI_CALL_BASE(env, napi_get_named_property(env, param, strProName.c_str(), &jsProValue), false); + NAPI_CALL_BASE(env, napi_typeof(env, jsProValue, &jsValueType), false); + + switch (jsValueType) { + case napi_string: { + std::string natValue = UnwrapStringFromJS(env, jsProValue); + HILOG_INFO("%{public}s called. Property value=%{public}s.", __func__, natValue.c_str()); + wantParams.SetParam(strProName, AAFwk::String::Box(natValue)); + break; + } + case napi_boolean: { + bool natValue = false; + NAPI_CALL_BASE(env, napi_get_value_bool(env, jsProValue, &natValue), false); + HILOG_INFO("%{public}s called. Property value=%{public}s.", __func__, natValue ? "true" : "false"); + wantParams.SetParam(strProName, AAFwk::Boolean::Box(natValue)); + break; + } + case napi_number: { + int32_t natValue32 = 0; + double natValueDouble = 0.0; + bool isReadValue32 = false; + bool isReadDouble = false; + if (napi_get_value_int32(env, jsProValue, &natValue32) == napi_ok) { + HILOG_INFO("%{public}s called. Property value=%{public}d.", __func__, natValue32); + isReadValue32 = true; + } + + if (napi_get_value_double(env, jsProValue, &natValueDouble) == napi_ok) { + HILOG_INFO("%{public}s called. Property value=%{public}lf.", __func__, natValueDouble); + isReadDouble = true; + } + + if (isReadValue32 && isReadDouble) { + if (abs(natValueDouble - natValue32 * 1.0) > 0.0) { + wantParams.SetParam(strProName, AAFwk::Double::Box(natValueDouble)); + } else { + wantParams.SetParam(strProName, AAFwk::Integer::Box(natValue32)); + } + } else if (isReadValue32) { + wantParams.SetParam(strProName, AAFwk::Integer::Box(natValue32)); + } else if (isReadDouble) { + wantParams.SetParam(strProName, AAFwk::Double::Box(natValueDouble)); + } + break; + } + case napi_object: { + bool isArray = false; + if (napi_is_array(env, jsProValue, &isArray) == napi_ok) { + if (isArray) { + HILOG_INFO("%{public}s called. %{public}s is array.", __func__, strProName.c_str()); + InnerUnwrapWantParamsArray(env, strProName, jsProValue, wantParams); + } else { + HILOG_INFO("%{public}s called. %{public}s is wantparams.", __func__, strProName.c_str()); + InnerUnwrapWantParams(env, strProName, jsProValue, wantParams); + } + } + break; + } + default: + break; + } + } + + return true; +} + +napi_value InnerWrapWantOptions(napi_env env, const Want &want) +{ + HILOG_INFO("%{public}s called.", __func__); + napi_value jsObject = nullptr; + std::map flagMap; + InnerInitWantOptionsData(flagMap); + unsigned int flags = want.GetFlags(); + bool natValue = false; + napi_value jsValue = nullptr; + + NAPI_CALL(env, napi_create_object(env, &jsObject)); + for (auto iter = flagMap.begin(); iter != flagMap.end(); iter++) { + jsValue = nullptr; + natValue = ((flags & iter->second) == iter->second); + if (napi_get_boolean(env, natValue, &jsValue) == napi_ok) { + SetPropertyValueByPropertyName(env, jsObject, iter->first.c_str(), jsValue); + } + } + + return jsObject; +} + +bool InnerUnwrapWantOptions(napi_env env, napi_value param, const char *propertyName, Want &want) +{ + napi_value jsValue = GetPropertyValueByPropertyName(env, param, propertyName, napi_object); + if (jsValue == nullptr) { + return false; + } + + bool natValue = false; + unsigned int flags = 0; + std::map flagMap; + InnerInitWantOptionsData(flagMap); + for (auto iter = flagMap.begin(); iter != flagMap.end(); iter++) { + natValue = false; + if (UnwrapBooleanByPropertyName(env, jsValue, iter->first.c_str(), natValue)) { + if (natValue) { + flags |= iter->second; + } + } + } + + want.SetFlags(flags); + return true; +} + +napi_value WrapWant(napi_env env, const Want &want) +{ + HILOG_INFO("%{public}s called.", __func__); + napi_value jsObject = nullptr; + napi_value jsValue = nullptr; + + NAPI_CALL(env, napi_create_object(env, &jsObject)); + + napi_value jsElementName = WrapElementName(env, want.GetElement()); + if (jsElementName == nullptr) { + HILOG_INFO("%{public}s called. Invoke WrapElementName failed.", __func__); + return nullptr; + } + + jsValue = GetPropertyValueByPropertyName(env, jsElementName, "deviceId", napi_string); + SetPropertyValueByPropertyName(env, jsObject, "deviceId", jsValue); + + jsValue = nullptr; + jsValue = GetPropertyValueByPropertyName(env, jsElementName, "bundleName", napi_string); + SetPropertyValueByPropertyName(env, jsObject, "bundleName", jsValue); + + jsValue = nullptr; + jsValue = GetPropertyValueByPropertyName(env, jsElementName, "abilityName", napi_string); + SetPropertyValueByPropertyName(env, jsObject, "abilityName", jsValue); + + jsValue = nullptr; + jsValue = WrapStringToJS(env, want.GetUriString()); + SetPropertyValueByPropertyName(env, jsObject, "uri", jsValue); + + jsValue = nullptr; + jsValue = WrapStringToJS(env, want.GetType()); + SetPropertyValueByPropertyName(env, jsObject, "type", jsValue); + + jsValue = nullptr; + jsValue = WrapInt32ToJS(env, want.GetFlags()); + SetPropertyValueByPropertyName(env, jsObject, "flags", jsValue); + + jsValue = nullptr; + jsValue = WrapStringToJS(env, want.GetAction()); + SetPropertyValueByPropertyName(env, jsObject, "action", jsValue); + + jsValue = nullptr; + jsValue = WrapWantParams(env, want.GetParams()); + SetPropertyValueByPropertyName(env, jsObject, "parameters", jsValue); + + jsValue = nullptr; + jsValue = WrapArrayStringToJS(env, want.GetEntities()); + SetPropertyValueByPropertyName(env, jsObject, "entities", jsValue); + + return jsObject; +} + +bool UnwrapWant(napi_env env, napi_value param, Want &want) +{ + HILOG_INFO("%{public}s called.", __func__); + + if (!IsTypeForNapiValue(env, param, napi_object)) { + HILOG_INFO("%{public}s called. Params is invalid.", __func__); + return false; + } + + napi_value jsValue = GetPropertyValueByPropertyName(env, param, "parameters", napi_object); + if (jsValue != nullptr) { + AAFwk::WantParams wantParams; + if (UnwrapWantParams(env, jsValue, wantParams)) { + want.SetParams(wantParams); + } + } + + std::string natValueString(""); + if (UnwrapStringByPropertyName(env, param, "action", natValueString)) { + want.SetAction(natValueString); + } + + std::vector natValueStringList; + if (UnwrapStringArrayByPropertyName(env, param, "entities", natValueStringList)) { + for (size_t i = 0; i < natValueStringList.size(); i++) { + want.AddEntity(natValueStringList[i]); + } + } + + natValueString = ""; + if (UnwrapStringByPropertyName(env, param, "uri", natValueString)) { + want.SetUri(natValueString); + } + + int32_t flags = 0; + if (UnwrapInt32ByPropertyName(env, param, "flags", flags)) { + want.SetFlags(flags); + } + + ElementName natElementName; + UnwrapElementName(env, param, natElementName); + want.SetElementName(natElementName.GetDeviceID(), natElementName.GetBundleName(), natElementName.GetAbilityName()); + + natValueString = ""; + if (UnwrapStringByPropertyName(env, param, "type", natValueString)) { + want.SetType(natValueString); + } + + return true; +} +EXTERN_C_END +} // namespace AppExecFwk +} // namespace OHOS diff --git a/tools/interfaces/kits/napi/aafwk/inner/napi_common/napi_common_want.h b/tools/interfaces/kits/napi/aafwk/inner/napi_common/napi_common_want.h new file mode 100755 index 00000000000..66e06f310fa --- /dev/null +++ b/tools/interfaces/kits/napi/aafwk/inner/napi_common/napi_common_want.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_APPEXECFWK_NAPI_COMMON_WANT_H +#define OHOS_APPEXECFWK_NAPI_COMMON_WANT_H + +#include +#include +#include +#include "want.h" +#include "napi_common_data.h" +#include "want_params.h" + +namespace OHOS { +namespace AppExecFwk { +EXTERN_C_START + +napi_value WrapElementName(napi_env env, const ElementName &elementName); +bool UnwrapElementName(napi_env env, napi_value param, ElementName &elementName); + +napi_value WrapWantParams(napi_env env, const AAFwk::WantParams &wantParams); +bool UnwrapWantParams(napi_env env, napi_value param, AAFwk::WantParams &wantParams); + +napi_value WrapWant(napi_env env, const Want &want); +bool UnwrapWant(napi_env env, napi_value param, Want &want); + +EXTERN_C_END +} // namespace AppExecFwk +} // namespace OHOS +#endif // OHOS_APPEXECFWK_NAPI_COMMON_WANT_H diff --git a/tools/interfaces/kits/napi/aafwk/particleAbility/BUILD.gn b/tools/interfaces/kits/napi/aafwk/particleAbility/BUILD.gn new file mode 100755 index 00000000000..db9864702e1 --- /dev/null +++ b/tools/interfaces/kits/napi/aafwk/particleAbility/BUILD.gn @@ -0,0 +1,57 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# import("//build/config/ohos/rules.gni") +import("//build/ohos.gni") +ohos_shared_library("particleability") { + include_dirs = [ + "//foundation/ace/napi/interfaces/kits", + "//third_party/node/src", + "//third_party/libuv/include", + "//foundation/aafwk/standard/frameworks/kits/ability/native/include", + "//foundation/aafwk/standard/interfaces/kits/napi/aafwk/inner/napi_common", + "//foundation/aafwk/standard/services/common/include", + "//foundation/aafwk/standard/interfaces/innerkits/ability_manager/include", + ] + + sources = [ + "native_module.cpp", + "particle_ability.cpp", + ] + + deps = [ + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/interfaces/innerkits/base:base", + "//foundation/aafwk/standard/interfaces/kits/napi/aafwk/inner/napi_common:napi_common", + "//foundation/ace/napi:ace_napi", + "//foundation/appexecfwk/standard/kits:appkit_native", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//third_party/libuv:uv_static", + "//utils/native/base:utils", + ] + + external_deps = [ + "aafwk_standard:ability_manager", + "aafwk_standard:want", + "appexecfwk_standard:appexecfwk_base", + "appexecfwk_standard:appexecfwk_core", + "appexecfwk_standard:libeventhandler", + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] + + relative_install_dir = "module/ability" + + subsystem_name = "aafwk" + part_name = "aafwk_standard" +} diff --git a/tools/interfaces/kits/napi/aafwk/particleAbility/native_module.cpp b/tools/interfaces/kits/napi/aafwk/particleAbility/native_module.cpp new file mode 100755 index 00000000000..fd1578e82d0 --- /dev/null +++ b/tools/interfaces/kits/napi/aafwk/particleAbility/native_module.cpp @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include "napi/native_api.h" +#include "napi/native_node_api.h" +#include "particle_ability.h" +namespace OHOS { +namespace AppExecFwk { +EXTERN_C_START +/* + * The module initialization. + */ +static napi_value ParticleInit(napi_env env, napi_value exports) +{ + ParticleAbilityInit(env, exports); + return exports; +} +EXTERN_C_END + +/* + * The module definition. + */ +static napi_module _module = { + .nm_version = 1, + .nm_flags = 0, + .nm_filename = nullptr, + .nm_register_func = ParticleInit, + .nm_modname = "ability.particleAbility", + .nm_priv = ((void *)0), + .reserved = {0} +}; + +/* + * The module registration. + */ +extern "C" __attribute__((constructor)) void RegisterModule(void) +{ + napi_module_register(&_module); +} +} // namespace AppExecFwk +} // namespace OHOS diff --git a/tools/interfaces/kits/napi/aafwk/particleAbility/particle_ability.cpp b/tools/interfaces/kits/napi/aafwk/particleAbility/particle_ability.cpp new file mode 100755 index 00000000000..2de3dd1ea82 --- /dev/null +++ b/tools/interfaces/kits/napi/aafwk/particleAbility/particle_ability.cpp @@ -0,0 +1,213 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "particle_ability.h" +#include +#include +#include +#include "securec.h" +#include "hilog_wrapper.h" +#include "../inner/napi_common/napi_common_ability.h" + +using namespace OHOS::AAFwk; +using namespace OHOS::AppExecFwk; + +namespace OHOS { +namespace AppExecFwk { + +/** + * @brief Obtains the type of this application. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_PAGetAppType(napi_env env, napi_callback_info info) +{ + HILOG_INFO("%{public}s called.", __func__); + return NAPI_GetAppTypeCommon(env, info, AbilityType::UNKNOWN); +} + +/** + * @brief Obtains information about the current ability. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_PAGetAbilityInfo(napi_env env, napi_callback_info info) +{ + HILOG_INFO("%{public}s called.", __func__); + return NAPI_GetAbilityInfoCommon(env, info, AbilityType::UNKNOWN); +} + +/** + * @brief Obtains the HapModuleInfo object of the application. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_PAGetHapModuleInfo(napi_env env, napi_callback_info info) +{ + HILOG_INFO("%{public}s called.", __func__); + return NAPI_GetHapModuleInfoCommon(env, info, AbilityType::UNKNOWN); +} + +/** + * @brief Get context. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_PAGetContext(napi_env env, napi_callback_info info) +{ + HILOG_INFO("%{public}s called.", __func__); + return NAPI_GetContextCommon(env, info, AbilityType::UNKNOWN); +} + +/** + * @brief Get want. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_PAGetWant(napi_env env, napi_callback_info info) +{ + HILOG_INFO("%{public}s called.", __func__); + return NAPI_GetWantCommon(env, info, AbilityType::UNKNOWN); +} + +/** + * @brief Obtains the class name in this ability name, without the prefixed bundle name. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_PAGetAbilityName(napi_env env, napi_callback_info info) +{ + HILOG_INFO("%{public}s called.", __func__); + return NAPI_GetAbilityNameCommon(env, info, AbilityType::UNKNOWN); +} + +/** + * @brief ParticleAbility NAPI method : startAbility. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_PAStartAbility(napi_env env, napi_callback_info info) +{ + HILOG_INFO("%{public}s called.", __func__); + return NAPI_StartAbilityCommon(env, info, AbilityType::UNKNOWN); +} + +/** + * @brief ParticleAbility NAPI method : stopAbility. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_PAStopAbility(napi_env env, napi_callback_info info) +{ + HILOG_INFO("%{public}s called.", __func__); + return NAPI_StopAbilityCommon(env, info, AbilityType::UNKNOWN); +} + +/** + * @brief ParticleAbility NAPI method : connectAbility. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_PAConnectAbility(napi_env env, napi_callback_info info) +{ + HILOG_INFO("%{public}s called.", __func__); + return NAPI_ConnectAbilityCommon(env, info, AbilityType::UNKNOWN); +} + +/** + * @brief ParticleAbility NAPI method : disconnectAbility. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_PADisConnectAbility(napi_env env, napi_callback_info info) +{ + HILOG_INFO("%{public}s called.", __func__); + return NAPI_DisConnectAbilityCommon(env, info, AbilityType::UNKNOWN); +} + +/** + * @brief FeatureAbility NAPI method : acquireDataAbilityHelper. + * + * @param env The environment that the Node-API call is invoked under. + * @param info The callback info passed into the callback function. + * + * @return The return value from NAPI C++ to JS for the module. + */ +napi_value NAPI_PAAcquireDataAbilityHelper(napi_env env, napi_callback_info info) +{ + HILOG_INFO("%{public}s,called", __func__); + return NAPI_AcquireDataAbilityHelperCommon(env, info, AbilityType::UNKNOWN); +} + +/** + * @brief ParticleAbility NAPI module registration. + * + * @param env The environment that the Node-API call is invoked under. + * @param exports An empty object via the exports parameter as a convenience. + * + * @return The return value from Init is treated as the exports object for the module. + */ +napi_value ParticleAbilityInit(napi_env env, napi_value exports) +{ + HILOG_INFO("%{public}s called.", __func__); + napi_property_descriptor properties[] = { + DECLARE_NAPI_FUNCTION("getAppType", NAPI_PAGetAppType), + DECLARE_NAPI_FUNCTION("getAbilityInfo", NAPI_PAGetAbilityInfo), + DECLARE_NAPI_FUNCTION("getHapModuleInfo", NAPI_PAGetHapModuleInfo), + DECLARE_NAPI_FUNCTION("getContext", NAPI_PAGetContext), + DECLARE_NAPI_FUNCTION("getWant", NAPI_PAGetWant), + DECLARE_NAPI_FUNCTION("getAbilityName", NAPI_PAGetAbilityName), + DECLARE_NAPI_FUNCTION("startAbility", NAPI_PAStartAbility), + DECLARE_NAPI_FUNCTION("stopAbility", NAPI_PAStopAbility), + DECLARE_NAPI_FUNCTION("connectAbility", NAPI_PAConnectAbility), + DECLARE_NAPI_FUNCTION("disconnectAbility", NAPI_PADisConnectAbility), + DECLARE_NAPI_FUNCTION("acquireDataAbilityHelper", NAPI_PAAcquireDataAbilityHelper), + }; + napi_define_properties(env, exports, sizeof(properties) / sizeof(properties[0]), properties); + + return exports; +} + +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/interfaces/kits/napi/aafwk/particleAbility/particle_ability.h b/tools/interfaces/kits/napi/aafwk/particleAbility/particle_ability.h new file mode 100755 index 00000000000..0ee568145ac --- /dev/null +++ b/tools/interfaces/kits/napi/aafwk/particleAbility/particle_ability.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_APPEXECFWK_PARTICLE_ABILITY_H +#define OHOS_APPEXECFWK_PARTICLE_ABILITY_H + +#include "napi/native_common.h" +#include "napi/native_node_api.h" + +namespace OHOS { +namespace AppExecFwk { +/** + * @brief ParticleAbility NAPI module registration. + * + * @param env The environment that the Node-API call is invoked under. + * @param exports An empty object via the exports parameter as a convenience. + * + * @return The return value from Init is treated as the exports object for the module. + */ +napi_value ParticleAbilityInit(napi_env env, napi_value exports); + +} // namespace AppExecFwk +} // namespace OHOS +#endif /* OHOS_APPEXECFWK_PARTICLE_ABILITY_H */ diff --git a/tools/interfaces/kits/napi/aafwk/wantConstant/BUILD.gn b/tools/interfaces/kits/napi/aafwk/wantConstant/BUILD.gn new file mode 100644 index 00000000000..c05883224b6 --- /dev/null +++ b/tools/interfaces/kits/napi/aafwk/wantConstant/BUILD.gn @@ -0,0 +1,52 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# import("//build/config/ohos/rules.gni") +import("//build/ohos.gni") +ohos_shared_library("wantconstant") { + include_dirs = [ + "//foundation/ace/napi/interfaces/kits", + "//third_party/node/src", + "//third_party/libuv/include", + "//foundation/aafwk/standard/frameworks/kits/ability/native/include", + "//foundation/aafwk/standard/interfaces/kits/napi/aafwk/wantConstant", + ] + + sources = [ + "native_module.cpp", + "want_constant.cpp", + ] + + deps = [ + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/interfaces/innerkits/base:base", + "//foundation/ace/napi:ace_napi", + "//foundation/appexecfwk/standard/kits:appkit_native", + "//third_party/libuv:uv_static", + "//utils/native/base:utils", + ] + + external_deps = [ + "aafwk_standard:ability_manager", + "aafwk_standard:want", + "appexecfwk_standard:appexecfwk_base", + "appexecfwk_standard:appexecfwk_core", + "appexecfwk_standard:libeventhandler", + "hiviewdfx_hilog_native:libhilog", + ] + + relative_install_dir = "module/ability" + + subsystem_name = "aafwk" + part_name = "aafwk_standard" +} diff --git a/tools/interfaces/kits/napi/aafwk/wantConstant/native_module.cpp b/tools/interfaces/kits/napi/aafwk/wantConstant/native_module.cpp new file mode 100644 index 00000000000..b739218a78d --- /dev/null +++ b/tools/interfaces/kits/napi/aafwk/wantConstant/native_module.cpp @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +#include "want_constant.h" +#include "napi/native_api.h" +#include "napi/native_node_api.h" +namespace OHOS { +namespace AppExecFwk { +EXTERN_C_START +/* + * The module initialization. + */ +static napi_value Init(napi_env env, napi_value exports) +{ + WantConstantInit(env, exports); + return exports; +} +EXTERN_C_END + +/* + * The module definition. + */ +static napi_module _module = { + .nm_version = 1, + .nm_flags = 0, + .nm_filename = nullptr, + .nm_register_func = Init, + .nm_modname = "ability.wantConstant", + .nm_priv = ((void *)0), + .reserved = {0} +}; + +/* + * The module registration. + */ +extern "C" __attribute__((constructor)) void RegisterModule(void) +{ + napi_module_register(&_module); +} +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/interfaces/kits/napi/aafwk/wantConstant/want_constant.cpp b/tools/interfaces/kits/napi/aafwk/wantConstant/want_constant.cpp new file mode 100644 index 00000000000..9ae73ac4a97 --- /dev/null +++ b/tools/interfaces/kits/napi/aafwk/wantConstant/want_constant.cpp @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "want_constant.h" +#include +#include +#include +#include "securec.h" +#include "hilog_wrapper.h" + +namespace OHOS { +namespace AppExecFwk { +/** + * @brief WantConstantInit NAPI module registration. + * + * @param env The environment that the Node-API call is invoked under. + * @param exports An empty object via the exports parameter as a convenience. + * + * @return The return value from Init is treated as the exports object for the module. + */ +napi_value WantConstantInit(napi_env env, napi_value exports) +{ + HILOG_INFO("%{public}s,called1", __func__); + napi_value action = nullptr; + napi_value entity = nullptr; + napi_value Flags = nullptr; + napi_create_object(env, &action); + napi_create_object(env, &entity); + napi_create_object(env, &Flags); + + SetNamedProperty(env, action, "ohos.want.action.home", "ACTION_HOME"); + SetNamedProperty(env, action, "ohos.want.action.dial", "ACTION_DIAL"); + SetNamedProperty(env, action, "ohos.want.action.search", "ACTION_SEARCH"); + SetNamedProperty(env, action, "ohos.settings.wireless", "ACTION_WIRELESS_SETTINGS"); + SetNamedProperty(env, action, "ohos.settings.manage.applications", "ACTION_MANAGE_APPLICATIONS_SETTINGS"); + SetNamedProperty(env, action, "ohos.settings.application.details", "ACTION_APPLICATION_DETAILS_SETTINGS"); + SetNamedProperty(env, action, "ohos.want.action.setAlarm", "ACTION_SET_ALARM"); + SetNamedProperty(env, action, "ohos.want.action.showAlarms", "ACTION_SHOW_ALARMS"); + SetNamedProperty(env, action, "ohos.want.action.snoozeAlarm", "ACTION_SNOOZE_ALARM"); + SetNamedProperty(env, action, "ohos.want.action.dismissAlarm", "ACTION_DISMISS_ALARM"); + SetNamedProperty(env, action, "ohos.want.action.dismissTimer", "ACTION_DISMISS_TIMER"); + SetNamedProperty(env, action, "ohos.want.action.sendSms", "ACTION_SEND_SMS"); + SetNamedProperty(env, action, "ohos.want.action.choose", "ACTION_CHOOSE"); + SetNamedProperty(env, action, "ohos.want.action.select", "ACTION_SELECT"); + SetNamedProperty(env, action, "ohos.want.action.sendData", "ACTION_SEND_DATA"); + SetNamedProperty(env, action, "ohos.want.action.sendMultipleData", "ACTION_SEND_MULTIPLE_DATA"); + SetNamedProperty(env, action, "ohos.want.action.scanMediaFile", "ACTION_SCAN_MEDIA_FILE"); + SetNamedProperty(env, action, "ohos.want.action.viewData", "ACTION_VIEW_DATA"); + SetNamedProperty(env, action, "ohos.want.action.editData", "ACTION_EDIT_DATA"); + SetNamedProperty(env, action, "ability.want.params.INTENT", "INTENT_PARAMS_INTENT"); + SetNamedProperty(env, action, "ability.want.params.TITLE", "INTENT_PARAMS_TITLE"); + SetNamedProperty(env, action, "ohos.action.fileSelect", "ACTION_FILE_SELECT"); + SetNamedProperty(env, action, "ability.params.stream", "PARAMS_STREAM"); + + SetNamedProperty(env, entity, "entity.system.default", "ENTITY_DEFAULT"); + SetNamedProperty(env, entity, "entity.system.home", "ENTITY_HOME"); + SetNamedProperty(env, entity, "entity.system.voice", "ENTITY_VOICE"); + SetNamedProperty(env, entity, "entity.system.browsable", "ENTITY_BROWSABLE"); + SetNamedProperty(env, entity, "entity.system.video", "ENTITY_VIDEO"); + + SetNamedProperty(env, Flags, 0x00000001, "FLAG_AUTH_READ_URI_PERMISSION"); + SetNamedProperty(env, Flags, 0x00000002, "FLAG_AUTH_WRITE_URI_PERMISSION"); + SetNamedProperty(env, Flags, 0x00000004, "FLAG_ABILITY_FORWARD_RESULT"); + SetNamedProperty(env, Flags, 0x00000008, "FLAG_ABILITY_CONTINUATION"); + SetNamedProperty(env, Flags, 0x00000010, "FLAG_NOT_OHOS_COMPONENT"); + SetNamedProperty(env, Flags, 0x00000020, "FLAG_ABILITY_FORM_ENABLED"); + SetNamedProperty(env, Flags, 0x00000040, "FLAG_AUTH_PERSISTABLE_URI_PERMISSION"); + SetNamedProperty(env, Flags, 0x00000080, "FLAG_AUTH_PREFIX_URI_PERMISSION"); + SetNamedProperty(env, Flags, 0x00000100, "FLAG_ABILITYSLICE_MULTI_DEVICE"); + SetNamedProperty(env, Flags, 0x00000200, "FLAG_START_FOREGROUND_ABILITY"); + SetNamedProperty(env, Flags, 0x00000400, "FLAG_ABILITY_CONTINUATION_REVERSIBLE"); + SetNamedProperty(env, Flags, 0x00000800, "FLAG_INSTALL_ON_DEMAND"); + SetNamedProperty(env, Flags, 0x80000000, "FLAG_INSTALL_WITH_BACKGROUND_MODE"); + SetNamedProperty(env, Flags, 0x00008000, "FLAG_ABILITY_CLEAR_MISSION"); + SetNamedProperty(env, Flags, 0x10000000, "FLAG_ABILITY_NEW_MISSION"); + SetNamedProperty(env, Flags, 0x20000000, "FLAG_ABILITY_MISSION_TOP"); + + napi_property_descriptor exportFuncs[] = { + DECLARE_NAPI_PROPERTY("Action", action), + DECLARE_NAPI_PROPERTY("Entity", entity), + DECLARE_NAPI_PROPERTY("Flags", Flags), + }; + napi_define_properties(env, exports, sizeof(exportFuncs) / sizeof(*exportFuncs), exportFuncs); + + return exports; +} + +void SetNamedProperty(napi_env env, napi_value dstObj, const char *objName, const char *propName) +{ + napi_value prop = nullptr; + napi_create_string_utf8(env, objName, NAPI_AUTO_LENGTH, &prop); + napi_set_named_property(env, dstObj, propName, prop); +} + +void SetNamedProperty(napi_env env, napi_value dstObj, const int32_t objValue, const char *propName) +{ + napi_value prop = nullptr; + napi_create_int32(env, objValue, &prop); + napi_set_named_property(env, dstObj, propName, prop); +} + +napi_value ActionConstructor(napi_env env, napi_callback_info info) +{ + napi_value jsthis = nullptr; + napi_get_cb_info(env, info, nullptr, nullptr, &jsthis, nullptr); + return jsthis; +} +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/interfaces/kits/napi/aafwk/wantConstant/want_constant.h b/tools/interfaces/kits/napi/aafwk/wantConstant/want_constant.h new file mode 100644 index 00000000000..5a44ae771f3 --- /dev/null +++ b/tools/interfaces/kits/napi/aafwk/wantConstant/want_constant.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_APPEXECFWK_WANT_CONSTANT_H +#define OHOS_APPEXECFWK_WANT_CONSTANT_H +#include "napi/native_common.h" +#include "napi/native_node_api.h" + +namespace OHOS { +namespace AppExecFwk { +/** + * @brief WantConstantInit NAPI module registration. + * + * @param env The environment that the Node-API call is invoked under. + * @param exports An empty object via the exports parameter as a convenience. + * + * @return The return value from Init is treated as the exports object for the module. + */ +napi_value WantConstantInit(napi_env env, napi_value exports); +napi_value ActionConstructor(napi_env env, napi_callback_info info); +void SetNamedProperty(napi_env env, napi_value dstObj, const char *objName, const char *propName); +void SetNamedProperty(napi_env env, napi_value dstObj, const int32_t objValue, const char *propName); +} // namespace AppExecFwk +} // namespace OHOS +#endif /* OHOS_APPEXECFWK_WANT_CONSTANT_H */ diff --git a/tools/ohos.build b/tools/ohos.build new file mode 100755 index 00000000000..0f802dabcd7 --- /dev/null +++ b/tools/ohos.build @@ -0,0 +1,90 @@ +{ + "parts": { + "aafwk_standard": { + "module_list": [ + "//foundation/aafwk/standard/services:services_target", + "//foundation/aafwk/standard/tools:tools_target", + "//foundation/aafwk/standard/interfaces/innerkits:innerkits_target", + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/sa_profile:aafwk_sa_profile", + "//foundation/aafwk/standard/interfaces/kits/napi:napi_packages" + ], + "inner_kits": [ + { + "header": { + "header_base": "//foundation/aafwk/standard/interfaces/innerkits/base/include/", + "header_files": [ + "ohos/aafwk/base/array_wrapper.h", + "ohos/aafwk/base/base_def.h", + "ohos/aafwk/base/base_interfaces.h", + "ohos/aafwk/base/base_object.h", + "ohos/aafwk/base/base_types.h", + "ohos/aafwk/base/bool_wrapper.h", + "ohos/aafwk/base/byte_wrapper.h", + "ohos/aafwk/base/double_wrapper.h", + "ohos/aafwk/base/float_wrapper.h", + "ohos/aafwk/base/int_wrapper.h", + "ohos/aafwk/base/light_refbase.h", + "ohos/aafwk/base/long_wrapper.h", + "ohos/aafwk/base/short_wrapper.h", + "ohos/aafwk/base/string_wrapper.h" + ] + }, + "name": "//foundation/aafwk/standard/interfaces/innerkits/base:base" + }, + { + "header": { + "header_base": "//foundation/aafwk/standard/interfaces/innerkits/want/include/", + "header_files": [ + "ohos/aafwk/content/want.h", + "ohos/aafwk/content/skills.h", + "ohos/aafwk/content/want_params.h", + "ohos/aafwk/content/match_type.h", + "ohos/aafwk/content/operation.h", + "ohos/aafwk/content/patterns_matcher.h", + "ohos/aafwk/content/pac_map.h" + ] + }, + "name": "//foundation/aafwk/standard/interfaces/innerkits/want:want" + }, + { + "header": { + "header_base": "//foundation/aafwk/standard/interfaces/innerkits/intent/include/", + "header_files": [ + "ohos/aafwk/content/intent.h", + "ohos/aafwk/content/intent_filter.h", + "ohos/aafwk/content/intent_params.h" + ] + }, + "name": "//foundation/aafwk/standard/interfaces/innerkits/intent:intent" + }, + { + "header": { + "header_base": "//foundation/aafwk/standard/interfaces/innerkits/ability_manager/include", + "header_files": [ + "ability_connect_callback_interface.h", + "ability_connect_callback_stub.h", + "ability_manager_client.h", + "ability_manager_errors.h", + "ability_manager_interface.h", + "ability_scheduler_interface.h" + ] + }, + "name": "//foundation/aafwk/standard/interfaces/innerkits/ability_manager:ability_manager" + } + ], + "test_list": [ + "//foundation/aafwk/standard/frameworks/kits/content/cpp/test:unittest", + "//foundation/aafwk/standard/frameworks/kits/ability/native/test:unittest", + "//foundation/aafwk/standard/frameworks/kits/test:moduletest", + "//foundation/aafwk/standard/services/test:moduletest", + "//foundation/aafwk/standard/services:unittest", + "//foundation/aafwk/standard/tools/test:systemtest", + "//foundation/aafwk/standard/tools/test:moduletest", + "//foundation/aafwk/standard/tools/test:unittest", + "//foundation/aafwk/standard/tools/zip/test:unittest" + ] + } + }, + "subsystem": "aafwk" +} diff --git a/tools/sa_profile/180.xml b/tools/sa_profile/180.xml new file mode 100644 index 00000000000..f383c870b01 --- /dev/null +++ b/tools/sa_profile/180.xml @@ -0,0 +1,27 @@ + + + + foundation + + 180 + /system/lib64/libabilityms.z.so + + + true + false + 1 + + diff --git a/tools/sa_profile/182.xml b/tools/sa_profile/182.xml new file mode 100644 index 00000000000..fe3de304b92 --- /dev/null +++ b/tools/sa_profile/182.xml @@ -0,0 +1,27 @@ + + + + foundation + + 182 + /system/lib64/libdataobsms.z.so + + + true + false + 1 + + diff --git a/tools/sa_profile/BUILD.gn b/tools/sa_profile/BUILD.gn new file mode 100644 index 00000000000..c87ec0a7a01 --- /dev/null +++ b/tools/sa_profile/BUILD.gn @@ -0,0 +1,20 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos/sa_profile/sa_profile.gni") + +ohos_sa_profile("aafwk_sa_profile") { + sources = [ "180.xml","182.xml" ] + + part_name = "aafwk_standard" +} diff --git a/tools/services/BUILD.gn b/tools/services/BUILD.gn new file mode 100644 index 00000000000..f3d58e1151e --- /dev/null +++ b/tools/services/BUILD.gn @@ -0,0 +1,28 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +group("services_target") { + deps = [ + "abilitymgr:abilityms_target", + "dataobsmgr:dataobsms", + ] +} + +group("unittest") { + testonly = true + + deps = [ + "abilitymgr:unittest", + "dataobsmgr:unittest", + ] +} diff --git a/tools/services/abilitymgr/BUILD.gn b/tools/services/abilitymgr/BUILD.gn new file mode 100644 index 00000000000..5b47dccaee9 --- /dev/null +++ b/tools/services/abilitymgr/BUILD.gn @@ -0,0 +1,102 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") +import("//foundation/aafwk/standard/aafwk.gni") +import("//foundation/aafwk/standard/services/abilitymgr/abilitymgr.gni") +EVENT_DIR = "//base/notification/ces_standard/" + +group("abilityms_target") { + deps = [ + ":abilityms", + ":ams_service_config", + ] +} + +group("unittest") { + testonly = true + + deps = [ "test:unittest" ] +} + +config("abilityms_config") { + include_dirs = [ + "include/", + "${EVENT_DIR}/frameworks/core/include", + "${EVENT_DIR}/interfaces/innerkits/native/include", + "${innerkits_path}/ability_manager/include", + "${innerkits_path}/base/include", + "${innerkits_path}/want/include", + "${innerkits_path}/want/include/ohos/aafwk/content", + "${innerkits_path}/intent/include/ohos/aafwk/content", + "${innerkits_path}/want/include/ohos/aafwk/content", + "${services_path}/common/include", + "//utils/native/base/include", + "//utils/system/safwk/native/include", + "//prebuilts/jdk/jdk8/linux-x86/include", + "//prebuilts/jdk/jdk8/linux-x86/include/linux", + "//third_party/json/include", + "//foundation/aafwk/standard/frameworks/kits/ability/native/include", + "//foundation/distributeddatamgr/appdatamgr/interfaces/innerkits/native_rdb/include", + "//foundation/distributeddatamgr/appdatamgr/interfaces/innerkits/native_appdatafwk/include", + "//foundation/distributeddatamgr/appdatamgr/interfaces/innerkits/native_dataability/include", + "//foundation/aafwk/standard/interfaces/innerkits/dataobs_manager/include", + ] + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } +} + +ohos_shared_library("abilityms") { + sources = abilityms_files + sources += [ "${services_path}/abilitymgr/src/sa_mgr_client.cpp" ] + + configs = [ ":abilityms_config" ] + + deps = [ + "${innerkits_path}/want:want", + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/frameworks/kits/ability/native:dummy_classes", + "//foundation/aafwk/standard/interfaces/innerkits/base:base", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_core:appexecfwk_core", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/distributeddatamgr/appdatamgr/interfaces/innerkits/native_dataability:native_dataability", + "//foundation/distributeddatamgr/appdatamgr/interfaces/innerkits/native_rdb:native_rdb", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//foundation/distributedschedule/safwk/interfaces/innerkits/safwk:system_ability_fwk", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy:samgr_proxy", + "//utils/native/base:utils", + ] + + external_deps = [ + "ces_standard:cesfwk_core", + "ces_standard:cesfwk_innerkits", + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] + + subsystem_name = "aafwk" + part_name = "aafwk_standard" +} + +ohos_prebuilt_etc("ams_service_config.json") { + source = "//foundation/aafwk/standard/services/abilitymgr/resource/ams_service_config.json" + subsystem_name = "aafwk" + part_name = "aafwk_standard" +} + +group("ams_service_config") { + deps = [ ":ams_service_config.json" ] +} diff --git a/tools/services/abilitymgr/abilitymgr.gni b/tools/services/abilitymgr/abilitymgr.gni new file mode 100644 index 00000000000..fe5beb7822a --- /dev/null +++ b/tools/services/abilitymgr/abilitymgr.gni @@ -0,0 +1,67 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//foundation/aafwk/standard/aafwk.gni") + +abilityms_files = [ + "${services_path}/abilitymgr/src/ability_connect_manager.cpp", + "${services_path}/abilitymgr/src/ability_connect_callback_stub.cpp", + "${services_path}/abilitymgr/src/ability_event_handler.cpp", + "${services_path}/abilitymgr/src/ability_manager_service.cpp", + "${services_path}/abilitymgr/src/ability_manager_stub.cpp", + "${services_path}/abilitymgr/src/ability_manager_proxy.cpp", + "${services_path}/abilitymgr/src/ability_record.cpp", + "${services_path}/abilitymgr/src/ability_scheduler_stub.cpp", + "${services_path}/abilitymgr/src/ability_scheduler_proxy.cpp", + "${services_path}/abilitymgr/src/ability_stack_manager.cpp", + "${services_path}/abilitymgr/src/ability_token_stub.cpp", + "${services_path}/abilitymgr/src/app_scheduler.cpp", + "${services_path}/abilitymgr/src/connection_record.cpp", + "${services_path}/abilitymgr/src/data_ability_caller_recipient.cpp", + "${services_path}/abilitymgr/src/data_ability_manager.cpp", + "${services_path}/abilitymgr/src/data_ability_record.cpp", + "${services_path}/abilitymgr/src/lifecycle_deal.cpp", + "${services_path}/abilitymgr/src/mission_record.cpp", + "${services_path}/abilitymgr/src/mission_stack.cpp", + "${services_path}/abilitymgr/src/power_storage.cpp", + "${services_path}/abilitymgr/src/lifecycle_state_info.cpp", + "${services_path}/abilitymgr/src/stack_info.cpp", + "${services_path}/abilitymgr/src/mission_stack_info.cpp", + "${services_path}/abilitymgr/src/mission_record_info.cpp", + "${services_path}/abilitymgr/src/ability_record_info.cpp", + "${services_path}/abilitymgr/src/ability_mission_info.cpp", + "${services_path}/abilitymgr/src/mission_description_info.cpp", + "${services_path}/abilitymgr/src/image_info.cpp", + "${services_path}/abilitymgr/src/mission_snapshot_info.cpp", + "${services_path}/abilitymgr/src/kernal_system_app_manager.cpp", + "${services_path}/abilitymgr/src/caller_info.cpp", + "${services_path}/abilitymgr/src/sender_info.cpp", + "${services_path}/abilitymgr/src/wants_info.cpp", + "${services_path}/abilitymgr/src/want_sender_info.cpp", + "${services_path}/abilitymgr/src/pending_want_record.cpp", + "${services_path}/abilitymgr/src/want_receiver_proxy.cpp", + "${services_path}/abilitymgr/src/want_receiver_stub.cpp", + "${services_path}/abilitymgr/src/want_sender_proxy.cpp", + "${services_path}/abilitymgr/src/want_sender_stub.cpp", + "${services_path}/abilitymgr/src/pending_want_key.cpp", + "${services_path}/abilitymgr/src/pending_want_manager.cpp", + "${services_path}/abilitymgr/src/pending_want_common_event.cpp", + "${services_path}/abilitymgr/src/lock_mission_container.cpp", + "${services_path}/abilitymgr/src/ability_start_setting.cpp", + "${services_path}/abilitymgr/src/mission_option.cpp", + "${services_path}/abilitymgr/src/stack_setting.cpp", + "${services_path}/abilitymgr/src/aafwk_dummy_configuration.cpp", + "${services_path}/abilitymgr/src/configuration_holder.cpp", + "${services_path}/abilitymgr/src/resume_mission_container.cpp", + "${services_path}/abilitymgr/src/ams_configuration_parameter.cpp", +] diff --git a/tools/services/abilitymgr/include/ability_config.h b/tools/services/abilitymgr/include/ability_config.h new file mode 100644 index 00000000000..58cd30018be --- /dev/null +++ b/tools/services/abilitymgr/include/ability_config.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_ABILITY_CONFIG_H +#define OHOS_AAFWK_ABILITY_CONFIG_H + +#include + +namespace OHOS { +namespace AAFwk { +namespace AbilityConfig { +const std::string NAME_ABILITY_MGR_SERVICE = "AbilityManagerService"; +const std::string NAME_BUNDLE_MGR_SERVICE = "BundleMgrService"; +const std::string SCHEME_DATA_ABILITY = "dataability"; +const std::string SYSTEM_UI_BUNDLE_NAME = "com.ohos.systemui"; +const std::string SYSTEM_UI_STATUS_BAR = "com.ohos.systemui.statusbar.MainAbility"; +const std::string SYSTEM_UI_NAVIGATION_BAR = "com.ohos.systemui.navigationbar.MainAbility"; +const std::string SYSTEM_DIALOG_NAME = "com.ohos.systemui.systemdialog.MainAbility"; + +const std::string SYSTEM_DIALOG_REQUEST_PERMISSIONS = "OHOS_RESULT_PERMISSIONS_LIST_YES"; +const std::string SYSTEM_DIALOG_CALLER_BUNDLENAME = "OHOS_RESULT_CALLER_BUNDLERNAME"; +const std::string SYSTEM_DIALOG_KEY = "OHOS_RESULT_PERMISSION_KEY"; + +const std::string DEVICE_MANAGER_BUNDLE_NAME = "com.ohos.devicemanagerui"; +const std::string DEVICE_MANAGER_NAME = "com.ohos.devicemanagerui.MainAbility"; + +const std::string EVENT_SYSTEM_WINDOW_MODE_CHANGED = "common.event.SYSTEM_WINDOW_MODE_CHANGED"; +const int EVENT_CODE_SYSTEM_WINDOW_MODE_CHANGED = 1; + +const std::string MISSION_NAME_MARK_HEAD = "#"; +const std::string MISSION_NAME_SEPARATOR = ":"; + +const std::string FLOATING_WINDOW_PERMISSION = "ohos.permission.SYSTEM_FLOAT_WINDOW"; + +const std::string LAUNCHER_ABILITY_NAME = "com.ohos.launcher.MainAbility"; +const std::string LAUNCHER_BUNDLE_NAME = "com.ohos.launcher"; +} // namespace AbilityConfig +} // namespace AAFwk +} // namespace OHOS + +#endif // OHOS_AAFWK_ABILITY_CONFIG_H diff --git a/tools/services/abilitymgr/include/ability_connect_callback_proxy.h b/tools/services/abilitymgr/include/ability_connect_callback_proxy.h new file mode 100644 index 00000000000..e3dac04b3c5 --- /dev/null +++ b/tools/services/abilitymgr/include/ability_connect_callback_proxy.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_ABILITY_CONNECT_CALLBACK_PROXY_H +#define OHOS_AAFWK_ABILITY_CONNECT_CALLBACK_PROXY_H + +#include "ability_connect_callback_interface.h" +#include "iremote_proxy.h" + +namespace OHOS { +namespace AAFwk { +/** + * @class AbilityConnectProxy + * AbilityConnect proxy. + */ +class AbilityConnectionProxy : public IRemoteProxy { +public: + explicit AbilityConnectionProxy(const sptr &impl) : IRemoteProxy(impl) + {} + + virtual ~AbilityConnectionProxy() + {} + + /** + * OnAbilityConnectDone, AbilityMs notify caller ability the result of connect. + * + * @param element,.service ability's ElementName. + * @param remoteObject,.the session proxy of service ability. + * @param resultCode, ERR_OK on success, others on failure. + */ + virtual void OnAbilityConnectDone( + const AppExecFwk::ElementName &element, const sptr &remoteObject, int resultCode) override; + + /** + * OnAbilityDisconnectDone, AbilityMs notify caller ability the result of disconnect. + * + * @param element,.service ability's ElementName. + * @param resultCode, ERR_OK on success, others on failure. + */ + virtual void OnAbilityDisconnectDone(const AppExecFwk::ElementName &element, int resultCode) override; + +private: + bool WriteInterfaceToken(MessageParcel &data); + +private: + static inline BrokerDelegator delegator_; +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_ABILITY_CONNECT_CALLBACK_PROXY_H \ No newline at end of file diff --git a/tools/services/abilitymgr/include/ability_connect_manager.h b/tools/services/abilitymgr/include/ability_connect_manager.h new file mode 100644 index 00000000000..e5f8ceb6b40 --- /dev/null +++ b/tools/services/abilitymgr/include/ability_connect_manager.h @@ -0,0 +1,417 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_ABILITY_CONNECT_MANAGER_H +#define OHOS_AAFWK_ABILITY_CONNECT_MANAGER_H + +#include +#include +#include + +#include "ability_connect_callback_interface.h" +#include "ability_event_handler.h" +#include "ability_record.h" +#include "connection_record.h" +#include "element_name.h" +#include "ohos/aafwk/content/want.h" +#include "iremote_object.h" +#include "nocopyable.h" + +namespace OHOS { +namespace AAFwk { +using OHOS::AppExecFwk::AbilityType; +/** + * @class AbilityConnectManager + * AbilityConnectManager provides a facility for managing service ability connection. + */ +class AbilityConnectManager : public std::enable_shared_from_this { +public: + using ConnectMapType = std::map, std::list>>; + using ServiceMapType = std::map>; + using ConnectListType = std::list>; + using RecipientMapType = std::map, sptr>; + + AbilityConnectManager(); + virtual ~AbilityConnectManager(); + + /** + * StartAbility with request. + * + * @param abilityRequest, the request of the service ability to start. + * @return Returns ERR_OK on success, others on failure. + */ + int StartAbility(const AbilityRequest &abilityRequest); + + /** + * TerminateAbility with token and result want. + * + * @param token, the token of service type's ability to terminate. + * @return Returns ERR_OK on success, others on failure. + */ + int TerminateAbility(const sptr &token); + + /** + * TerminateAbility, terminate the special ability. + * + * @param caller, caller ability record. + * @param requestCode, abililty request code + * @return Returns ERR_OK on success, others on failure. + */ + int TerminateAbility(const std::shared_ptr &caller, int requestCode); + + /** + * StopServiceAbility with request. + * + * @param abilityRequest, request. + * @return Returns ERR_OK on success, others on failure. + */ + int StopServiceAbility(const AbilityRequest &abilityRequest); + + /** + * Destroys this Service ability if the number of times it + * has been started equals the number represented by + * the given startId. + * + * @param token ability's token. + * @param startId is incremented by 1 every time this ability is started. + * @return Returns true if the startId matches the number of startup times + * and this Service ability will be destroyed; returns false otherwise. + */ + int TerminateAbilityResult(const sptr &token, int startId); + + /** + * ConnectAbilityLocked, connect session with service ability. + * + * @param abilityRequest, Special want for service type's ability. + * @param connect, Callback used to notify caller the result of connecting or disconnecting. + * @param callerToken, caller ability token. + * @return Returns ERR_OK on success, others on failure. + */ + int ConnectAbilityLocked(const AbilityRequest &abilityRequest, const sptr &connect, + const sptr &callerToken); + + /** + * DisconnectAbilityLocked, disconnect session with callback. + * + * @param connect, Callback used to notify caller the result of connecting or disconnecting. + * @return Returns ERR_OK on success, others on failure. + */ + int DisconnectAbilityLocked(const sptr &connect); + + /** + * AttachAbilityThreadLocked, ability call this interface after loaded. + * + * @param scheduler, the interface handler of kit ability. + * @param token, ability's token. + * @return Returns ERR_OK on success, others on failure. + */ + int AttachAbilityThreadLocked(const sptr &scheduler, const sptr &token); + + /** + * OnAbilityRequestDone, app manager service call this interface after ability request done. + * + * @param token, ability's token. + * @param state, the state of ability lift cycle. + */ + void OnAbilityRequestDone(const sptr &token, const int32_t state); + + void OnAppStateChanged(const AppInfo &info); + + /** + * AbilityTransitionDone, ability call this interface after lift cycle was changed. + * + * @param token, ability's token. + * @param state, the state of ability lift cycle. + * @return Returns ERR_OK on success, others on failure. + */ + int AbilityTransitionDone(const sptr &token, int state); + + /** + * ScheduleConnectAbilityDoneLocked, service ability call this interface while session was connected. + * + * @param token, service ability's token. + * @param remoteObject, the session proxy of service ability. + * @return Returns ERR_OK on success, others on failure. + */ + int ScheduleConnectAbilityDoneLocked(const sptr &token, const sptr &remoteObject); + + /** + * ScheduleDisconnectAbilityDone, service ability call this interface while session was disconnected. + * + * @param token,service ability's token. + * @return Returns ERR_OK on success, others on failure. + */ + int ScheduleDisconnectAbilityDoneLocked(const sptr &token); + + /** + * ScheduleCommandAbilityDoneLocked, service ability call this interface while session was onCommanded. + * + * @param token,service ability's token. + * @return Returns ERR_OK on success, others on failure. + */ + int ScheduleCommandAbilityDoneLocked(const sptr &token); + + /** + * GetServiceRecordByElementName. + * + * @param element, service ability's element. + * @return Returns AbilityRecord shared_ptr. + */ + std::shared_ptr GetServiceRecordByElementName(const std::string &element); + + /** + * GetServiceRecordByToken. + * + * @param token, service ability's token. + * @return Returns AbilityRecord shared_ptr. + */ + std::shared_ptr GetServiceRecordByToken(const sptr &token); + ConnectListType GetConnectRecordListByCallback(sptr callback); + void RemoveAll(); + + /** + * SetEventHandler. + * + * @param handler,EventHandler + */ + inline void SetEventHandler(const std::shared_ptr &handler) + { + eventHandler_ = handler; + } + + /** + * GetConnectMap. + * + * @return Returns connection record list. + */ + inline const ConnectMapType &GetConnectMap() const + { + return connectMap_; + } + + /** + * GetServiceMap. + * + * @return Returns service ability record map. + */ + inline const ServiceMapType &GetServiceMap() const + { + return serviceMap_; + } + + /** + * OnAbilityDied. + * + * @param abilityRecord, service ability record. + */ + void OnAbilityDied(const std::shared_ptr &abilityRecord); + + void DumpState(std::vector &info, const std::string &args = "") const; + + // MSG 0 - 20 represents timeout message + static constexpr uint32_t LOAD_TIMEOUT_MSG = 0; + static constexpr uint32_t CONNECT_TIMEOUT_MSG = 1; + +private: + /** + * StartAbilityLocked with request. + * + * @param abilityRequest, the request of the service ability to start. + * @return Returns ERR_OK on success, others on failure. + */ + int StartAbilityLocked(const AbilityRequest &abilityRequest); + + /** + * TerminateAbilityLocked with token and result want. + * + * @param token, the token of service type's ability to terminate. + * @param resultCode, the result code of service type's ability to terminate. + * @param resultWant, the result want for service type's ability to terminate. + * @return Returns ERR_OK on success, others on failure. + */ + int TerminateAbilityLocked(const sptr &token); + + /** + * Destroys this Service ability if the number of times it + * has been started equals the number represented by + * the given startId. + * + * @param token ability's token. + * @param startId is incremented by 1 every time this ability is started. + * @return Returns true if the startId matches the number of startup times + * and this Service ability will be destroyed; returns false otherwise. + */ + int TerminateAbilityResultLocked(const sptr &token, int startId); + + /** + * StopAbilityLocked with request. + * + * @param abilityRequest, the request of the service ability to start. + * @return Returns ERR_OK on success, others on failure. + */ + int StopServiceAbilityLocked(const AbilityRequest &abilityRequest); + + /** + * LoadAbility. + * + * @param abilityRecord, the ptr of the ability to load. + */ + void LoadAbility(const std::shared_ptr &abilityRecord); + + /** + * ConnectAbility.Schedule connect ability + * + * @param abilityRecord, the ptr of the ability to connect. + */ + void ConnectAbility(const std::shared_ptr &abilityRecord); + + /** + * CommandAbility. Schedule command ability + * + * @param abilityRecord, the ptr of the ability to command. + */ + void CommandAbility(const std::shared_ptr &abilityRecord); + + /** + * CompleteCommandAbility. complete command ability + * + * @param abilityRecord, the ptr of the ability to command. + */ + void CompleteCommandAbility(std::shared_ptr abilityRecord); + + /** + * TerminateDone. + * + * @param abilityRecord, the ptr of the ability to terminate. + */ + void TerminateDone(const std::shared_ptr &abilityRecord); + + /** + * dispatch service ability life cycle . + * + * @param abilityRecord. + * @param state. + */ + int DispatchInactive(const std::shared_ptr &abilityRecord, int state); + int DispatchTerminate(const std::shared_ptr &abilityRecord); + + void HandleStartTimeoutTask(const std::shared_ptr &abilityRecord, int resultCode); + void HandleStopTimeoutTask(const std::shared_ptr &abilityRecord); + void HandleDisconnectTask(const ConnectListType &connectlist); + + /** + * IsAbilityConnected. + * + * @param abilityRecord, the ptr of the connected ability. + * @param connectRecordList, connect record list. + * @return true: ability is connected, false: ability is not connected + */ + bool IsAbilityConnected(const std::shared_ptr &abilityRecord, + const std::list> &connectRecordList); + + /** + * RemoveConnectionRecordFromMap. + * + * @param connect, the ptr of the connect record. + */ + void RemoveConnectionRecordFromMap(const std::shared_ptr &connect); + + /** + * RemoveServiceAbility. + * + * @param service, the ptr of the ability record. + */ + void RemoveServiceAbility(const std::shared_ptr &service); + + /** + * GetOrCreateServiceRecord. + * + * @param abilityRequest, Special want for service type's ability. + * @param isCreatedByConnect, whether is created by connect ability mode. + * @param targetAbilityRecord, the target service ability record. + * @param isLoadedAbility, whether the target ability has been loaded. + */ + void GetOrCreateServiceRecord(const AbilityRequest &abilityRequest, const bool isCreatedByConnect, + std::shared_ptr &targetAbilityRecord, bool &isLoadedAbility); + + /** + * GetConnectRecordListFromMap. + * + * @param connect, callback object. + * @param isCreatedByConnect, whether is created by connect ability mode. + * @param connectRecordList, the target connectRecordList. + * @param isCallbackConnected, whether the callback has been connected. + */ + void GetConnectRecordListFromMap( + const sptr &connect, std::list> &connectRecordList); + + /** + * AddConnectDeathRecipient. + * + * @param connect, callback object. + */ + void AddConnectDeathRecipient(const sptr &connect); + + /** + * RemoteConnectDeathRecipient. + * + * @param connect, callback object. + */ + void RemoveConnectDeathRecipient(const sptr &connect); + + /** + * RemoteConnectDeathRecipient. + * + * @param remote, callback object. + */ + void OnCallBackDied(const wptr &remote); + + /** + * HandleOnCallBackDied. + * + * @param connect, callback object. + */ + void HandleCallBackDiedTask(const sptr &connect); + + /** + * HandleOnCallBackDied. + * + * @param abilityRecord, died ability. + */ + void HandleAbilityDiedTask(const std::shared_ptr &abilityRecord); + + /** + * PostTimeOutTask. + * + * @param abilityRecord, ability. + * @param messageId, message id. + */ + void PostTimeOutTask(const std::shared_ptr &abilityRecord, uint32_t messageId); + +private: + const std::string TASK_ON_CALLBACK_DIED = "OnCallbackDiedTask"; + const std::string TASK_ON_ABILITY_DIED = "OnAbilityDiedTask"; + + std::recursive_mutex Lock_; + ConnectMapType connectMap_; + ServiceMapType serviceMap_; + RecipientMapType recipientMap_; + std::shared_ptr eventHandler_; + + DISALLOW_COPY_AND_MOVE(AbilityConnectManager); +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_ABILITY_CONNECT_MANAGER_H diff --git a/tools/services/abilitymgr/include/ability_event_handler.h b/tools/services/abilitymgr/include/ability_event_handler.h new file mode 100644 index 00000000000..7942db03618 --- /dev/null +++ b/tools/services/abilitymgr/include/ability_event_handler.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_ABILITY_EVENT_HANDLER_H +#define OHOS_AAFWK_ABILITY_EVENT_HANDLER_H + +#include + +#include "event_handler.h" +#include "event_runner.h" + +namespace OHOS { +namespace AAFwk { +class AbilityManagerService; +/** + * @class AbilityEventHandler + * AbilityEventHandler handling the ability event. + */ +class AbilityEventHandler : public AppExecFwk::EventHandler { +public: + AbilityEventHandler( + const std::shared_ptr &runner, const std::weak_ptr &server); + virtual ~AbilityEventHandler() = default; + + /** + * ProcessEvent with request. + * + * @param event, inner event loop. + */ + void ProcessEvent(const AppExecFwk::InnerEvent::Pointer &event) override; + +private: + void ProcessLoadTimeOut(int64_t eventId); + void ProcessActiveTimeOut(int64_t eventId); + void ProcessInactiveTimeOut(int64_t eventId); + +private: + std::weak_ptr server_; +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_ABILITY_EVENT_HANDLER_H \ No newline at end of file diff --git a/tools/services/abilitymgr/include/ability_manager_proxy.h b/tools/services/abilitymgr/include/ability_manager_proxy.h new file mode 100644 index 00000000000..1d583ffc6d6 --- /dev/null +++ b/tools/services/abilitymgr/include/ability_manager_proxy.h @@ -0,0 +1,454 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_ABILITY_MANAGER_PROXY_H +#define OHOS_AAFWK_ABILITY_MANAGER_PROXY_H + +#include "ability_manager_interface.h" +#include "hilog_wrapper.h" +#include "iremote_proxy.h" + +namespace OHOS { +namespace AAFwk { +/** + * @class AbilityManagerProxy + * AbilityManagerProxy. + */ +class AbilityManagerProxy : public IRemoteProxy { +public: + explicit AbilityManagerProxy(const sptr &impl) : IRemoteProxy(impl) + {} + + virtual ~AbilityManagerProxy() + {} + + /** + * StartAbility with want, send want to ability manager service. + * + * @param want, the want of the ability to start. + * @param requestCode, Ability request code. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int StartAbility(const Want &want, int requestCode = DEFAULT_INVAL_VALUE) override; + + /** + * StartAbility with want, send want to ability manager service. + * + * @param want, the want of the ability to start. + * @param callerToken, caller ability token. + * @param requestCode the resultCode of the ability to start. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int StartAbility( + const Want &want, const sptr &callerToken, int requestCode = DEFAULT_INVAL_VALUE) override; + + /** + * Starts a new ability with specific start settings. + * + * @param want Indicates the ability to start. + * @param requestCode the resultCode of the ability to start. + * @param abilityStartSetting Indicates the setting ability used to start. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int StartAbility(const Want &want, const AbilityStartSetting &abilityStartSetting, + const sptr &callerToken, int requestCode = DEFAULT_INVAL_VALUE) override; + + /** + * TerminateAbility, terminate the special ability. + * + * @param token, the token of the ability to terminate. + * @param resultCode, the resultCode of the ability to terminate. + * @param resultWant, the Want of the ability to return. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int TerminateAbility( + const sptr &token, int resultCode, const Want *resultWant = nullptr) override; + + /** + * TerminateAbility, terminate the special ability. + * + * @param callerToken, caller ability token. + * @param requestCode, Ability request code. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int TerminateAbilityByCaller(const sptr &callerToken, int requestCode) override; + + /** + * ConnectAbility, connect session with service ability. + * + * @param want, Special want for service type's ability. + * @param connect, Callback used to notify caller the result of connecting or disconnecting. + * @param callerToken, caller ability token. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int ConnectAbility( + const Want &want, const sptr &connect, const sptr &callerToken) override; + + /** + * DisconnectAbility, connect session with service ability. + * + * @param connect, Callback used to notify caller the result of connecting or disconnecting. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int DisconnectAbility(const sptr &connect) override; + + /** + * AcquireDataAbility, acquire a data ability by its authority, if it not existed, + * AMS loads it synchronously. + * + * @param uri, data ability uri. + * @param isKill, true: when a data ability is died, ams will kill this client, or do nothing. + * @param callerToken, specifies the caller ability token. + * @return returns the data ability ipc object, or nullptr for failed. + */ + virtual sptr AcquireDataAbility( + const Uri &uri, bool isKill, const sptr &callerToken) override; + + /** + * ReleaseDataAbility, release the data ability that referenced by 'dataAbilityToken'. + * + * @param dataAbilityScheduler, specifies the data ability that will be released. + * @param callerToken, specifies the caller ability token. + * @return returns ERR_OK if succeeded, or error codes for failed. + */ + virtual int ReleaseDataAbility( + sptr dataAbilityScheduler, const sptr &callerToken) override; + + /** + * AddWindowInfo, add windowToken to AbilityRecord. + * + * @param token, the token of the ability. + * @param windowToken, window id of the ability. + */ + virtual void AddWindowInfo(const sptr &token, int32_t windowToken) override; + + /** + * AttachAbilityThread, ability call this interface after loaded. + * + * @param scheduler,.the interface handler of kit ability. + * @param token,.ability's token. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int AttachAbilityThread( + const sptr &scheduler, const sptr &token) override; + + /** + * AbilityTransitionDone, ability call this interface after lift cycle was changed. + * + * @param token,.ability's token. + * @param state,.the state of ability lift cycle. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int AbilityTransitionDone(const sptr &token, int state) override; + + /** + * ScheduleConnectAbilityDone, service ability call this interface while session was connected. + * + * @param token,.service ability's token. + * @param remoteObject,.the session proxy of service ability. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int ScheduleConnectAbilityDone( + const sptr &token, const sptr &remoteObject) override; + + /** + * ScheduleDisconnectAbilityDone, service ability call this interface while session was disconnected. + * + * @param token,.service ability's token. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int ScheduleDisconnectAbilityDone(const sptr &token) override; + + /** + * ScheduleCommandAbilityDone, service ability call this interface while session was commanded. + * + * @param token,.service ability's token. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int ScheduleCommandAbilityDone(const sptr &token) override; + + /** + * dump ability stack info, about userID, mission stack info, + * mission record info and ability info. + * + * @param state Ability stack info. + * @return Returns ERR_OK on success, others on failure. + */ + virtual void DumpState(const std::string &args, std::vector &state) override; + + /** + * Destroys this Service ability if the number of times it + * has been started equals the number represented by + * the given startId. + * + * @param token ability's token. + * @param startId is incremented by 1 every time this ability is started. + * @return Returns true if the startId matches the number of startup times + * and this Service ability will be destroyed; returns false otherwise. + */ + virtual int TerminateAbilityResult(const sptr &token, int startId) override; + + /** + * Destroys this Service ability by Want. + * + * @param want, Special want for service type's ability. + * @return Returns true if this Service ability will be destroyed; returns false otherwise. + */ + virtual int StopServiceAbility(const Want &want) override; + + /** + * Obtains information about ability stack that are running on the device. + * + * @param stackInfo Ability stack info. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int GetAllStackInfo(StackInfo &stackInfo) override; + + /** + * Get the list of the missions that the user has recently launched, + * with the most recent being first and older ones after in order. + * + * @param recentList recent mission info + * @param numMax The maximum number of entries to return in the list. The + * actual number returned may be smaller, depending on how many tasks the + * user has started and the maximum number the system can remember. + * @param falgs Information about what to return. May be any combination + * of {@link #RECENT_WITH_EXCLUDED} and {@link #RECENT_IGNORE_UNAVAILABLE}. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int GetRecentMissions( + const int32_t numMax, const int32_t flags, std::vector &recentList) override; + + /** + * Get mission snapshot by mission id + * + * @param missionId the id of the mission to retrieve the sAutoapshots + * @return Returns ERR_OK on success, others on failure. + */ + virtual int GetMissionSnapshot(const int32_t missionId, MissionSnapshotInfo &snapshot) override; + + /** + * Ask that the mission associated with a given mission ID be moved to the + * front of the stack, so it is now visible to the user. + * + * @param missionId. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int MoveMissionToTop(int32_t missionId) override; + + /** + * Requires that tasks associated with a given capability token be moved to the background + * + * @param token ability token + * @param nonFirst If nonfirst is false and not the lowest ability of the mission, you cannot move mission to end + * @return Returns ERR_OK on success, others on failure. + */ + virtual int MoveMissionToEnd(const sptr &token, bool nonFirst) override; + + /** + * Remove the specified mission from the stack by missionid + * + * @param id. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int RemoveMission(int id) override; + + /** + * Remove the specified mission stack by stack id + * + * @param id. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int RemoveStack(int id) override; + + /** + * Kill the process immediately. + * + * @param bundleName. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int KillProcess(const std::string &bundleName) override; + + /** + * Uninstall app + * + * @param bundleName. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int UninstallApp(const std::string &bundleName) override; + + /** + * Moving mission to the specified stack by mission option(Enter floating window mode). + * @param missionOption, target mission option + * @return Returns ERR_OK on success, others on failure. + */ + virtual int MoveMissionToFloatingStack(const MissionOption &missionOption) override; + + /** + * Moving mission to the specified stack by mission option(Enter floating window mode). + * @param missionOption, target mission option + * @return Returns ERR_OK on success, others on failure. + */ + virtual int MoveMissionToSplitScreenStack(const MissionOption &missionOption) override; + + /** + * Change the focus of ability in the mission stack. + * @param lostToken, the token of lost focus ability + * @param getToken, the token of get focus ability + * @return Returns ERR_OK on success, others on failure. + */ + virtual int ChangeFocusAbility( + const sptr &lostFocusToken, const sptr &getFocusToken) override; + + /** + * minimize multiwindow by mission id. + * @param missionId, the id of target mission + * @return Returns ERR_OK on success, others on failure. + */ + virtual int MinimizeMultiWindow(int missionId) override; + + /** + * maximize multiwindow by mission id. + * @param missionId, the id of target mission + * @return Returns ERR_OK on success, others on failure. + */ + virtual int MaximizeMultiWindow(int missionId) override; + + /** + * get missions info of floating mission stack. + * @param list, mission info. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int GetFloatingMissions(std::vector &list) override; + + /** + * close multiwindow by mission id. + * @param missionId, the id of target mission. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int CloseMultiWindow(int missionId) override; + + /** + * set special mission stack default settings. + * @param stackSetting, mission stack default settings. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int SetMissionStackSetting(const StackSetting &stackSetting) override; + + /** + * @brief Checks whether this ability is the first ability in a mission. + * + * @return Returns true is first in Mission. + */ + virtual bool IsFirstInMission(const sptr &token) override; + + /** + * Checks whether a specified permission has been granted to the process identified by pid and uid + * + * @param permission Indicates the permission to check. + * @param pid Indicates the ID of the process to check. + * @param uid Indicates the UID of the process to check. + * @param message Describe success or failure + * + * @return Returns ERR_OK on success, others on failure. + */ + virtual int CompelVerifyPermission(const std::string &permission, int pid, int uid, std::string &message) override; + + /** + * Save the top ability States and move them to the background + * @return Returns ERR_OK on success, others on failure. + */ + virtual int PowerOff() override; + + /** + * Restore the state before top ability poweroff + * @return Returns ERR_OK on success, others on failure. + */ + virtual int PowerOn() override; + + /** + * Sets the application to start its ability in lock mission mode. + * @param missionId luck mission id + * @return Returns ERR_OK on success, others on failure. + */ + virtual int LockMission(int missionId) override; + + /** + * Unlocks this ability by exiting the lock mission mode. + * @param missionId unluck mission id + * @return Returns ERR_OK on success, others on failure. + */ + virtual int UnlockMission(int missionId) override; + + /** + * Sets description information about the mission containing this ability. + * + * @param description Indicates the object containing information about the + * mission. This parameter cannot be null. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int SetMissionDescriptionInfo( + const sptr &token, const MissionDescriptionInfo &description) override; + + /** + * get current system mission lock mode state. + * + * @return Returns 0: LOCK_MISSION_STATE_NONE, 1: LOCK_MISSION_STATE_LOCKED + */ + virtual int GetMissionLockModeState() override; + + /** + * Updates the configuration by modifying the configuration. + * + * @param config Indicates the new configuration + * @return Returns ERR_OK on success, others on failure. + */ + virtual int UpdateConfiguration(const DummyConfiguration &config) override; + + virtual sptr GetWantSender( + const WantSenderInfo &wantSenderInfo, const sptr &callerToken) override; + + virtual int SendWantSender(const sptr &target, const SenderInfo &senderInfo) override; + + virtual void CancelWantSender(const sptr &sender) override; + + virtual int GetPendingWantUid(const sptr &target) override; + + virtual int GetPendingWantUserId(const sptr &target) override; + + virtual std::string GetPendingWantBundleName(const sptr &target) override; + + virtual int GetPendingWantCode(const sptr &target) override; + + virtual int GetPendingWantType(const sptr &target) override; + + virtual void RegisterCancelListener(const sptr &sender, const sptr &receiver) override; + + virtual void UnregisterCancelListener( + const sptr &sender, const sptr &receiver) override; + + virtual int GetPendingRequestWant(const sptr &target, std::shared_ptr &want) override; + +private: + template + int GetParcelableInfos(MessageParcel &reply, std::vector &parcelableInfos); + bool WriteInterfaceToken(MessageParcel &data); + +private: + static inline BrokerDelegator delegator_; +}; +} // namespace AAFwk +} // namespace OHOS +#endif diff --git a/tools/services/abilitymgr/include/ability_manager_service.h b/tools/services/abilitymgr/include/ability_manager_service.h new file mode 100644 index 00000000000..38a3803ff91 --- /dev/null +++ b/tools/services/abilitymgr/include/ability_manager_service.h @@ -0,0 +1,649 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_ABILITY_MANAGER_SERVICE_H +#define OHOS_AAFWK_ABILITY_MANAGER_SERVICE_H + +#include +#include +#include +#include + +#include "ability_connect_manager.h" +#include "ability_event_handler.h" +#include "ability_manager_stub.h" +#include "ability_stack_manager.h" +#include "app_scheduler.h" +#include "bundlemgr/bundle_mgr_interface.h" +#include "data_ability_manager.h" +#include "hilog_wrapper.h" +#include "iremote_object.h" +#include "kernal_system_app_manager.h" +#include "system_ability.h" +#include "uri.h" +#include "ability_config.h" +#include "pending_want_manager.h" +#include "ams_configuration_parameter.h" + +namespace OHOS { +namespace AAFwk { +enum class ServiceRunningState { STATE_NOT_START, STATE_RUNNING }; + +class PendingWantManager; +/** + * @class AbilityManagerService + * AbilityManagerService provides a facility for managing ability life cycle. + */ +class AbilityManagerService : public SystemAbility, + public AbilityManagerStub, + public AppStateCallback, + public std::enable_shared_from_this { + DECLARE_DELAYED_SINGLETON(AbilityManagerService) + DECLEAR_SYSTEM_ABILITY(AbilityManagerService) +public: + void OnStart() override; + void OnStop() override; + ServiceRunningState QueryServiceState() const; + + /** + * StartAbility with want, send want to ability manager service. + * + * @param want, the want of the ability to start. + * @param requestCode, Ability request code. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int StartAbility(const Want &want, int requestCode = DEFAULT_INVAL_VALUE) override; + + /** + * StartAbility with want, send want to ability manager service. + * + * @param want, the want of the ability to start. + * @param callerToken, caller ability token. + * @param requestCode the resultCode of the ability to start. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int StartAbility( + const Want &want, const sptr &callerToken, int requestCode = DEFAULT_INVAL_VALUE) override; + + /** + * Starts a new ability with specific start settings. + * + * @param want Indicates the ability to start. + * @param abilityStartSetting Indicates the setting ability used to start. + * @param callerToken, caller ability token. + * @param requestCode the resultCode of the ability to start. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int StartAbility(const Want &want, const AbilityStartSetting &abilityStartSetting, + const sptr &callerToken, int requestCode = DEFAULT_INVAL_VALUE) override; + + /** + * TerminateAbility, terminate the special ability. + * + * @param token, the token of the ability to terminate. + * @param resultCode, the resultCode of the ability to terminate. + * @param resultWant, the Want of the ability to return. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int TerminateAbility(const sptr &token, int resultCode = DEFAULT_INVAL_VALUE, + const Want *resultWant = nullptr) override; + + /** + * TerminateAbility, terminate the special ability. + * + * @param callerToken, caller ability token. + * @param requestCode, Ability request code. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int TerminateAbilityByCaller(const sptr &callerToken, int requestCode) override; + + /** + * ConnectAbility, connect session with service ability. + * + * @param want, Special want for service type's ability. + * @param connect, Callback used to notify caller the result of connecting or disconnecting. + * @param callerToken, caller ability token. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int ConnectAbility( + const Want &want, const sptr &connect, const sptr &callerToken) override; + + virtual int DisconnectAbility(const sptr &connect) override; + + /** + * AcquireDataAbility, acquire a data ability by its authority, if it not existed, + * AMS loads it synchronously. + * + * @param uri, data ability uri. + * @param tryBind, true: when a data ability is died, ams will kill this client, or do nothing. + * @param callerToken, specifies the caller ability token. + * @return returns the data ability ipc object, or nullptr for failed. + */ + virtual sptr AcquireDataAbility( + const Uri &uri, bool tryBind, const sptr &callerToken) override; + + /** + * ReleaseDataAbility, release the data ability that referenced by 'dataAbilityToken'. + * + * @param dataAbilityToken, specifies the data ability that will be released. + * @param callerToken, specifies the caller ability token. + * @return returns ERR_OK if succeeded, or error codes for failed. + */ + virtual int ReleaseDataAbility( + sptr dataAbilityScheduler, const sptr &callerToken) override; + + /** + * AddWindowInfo, add windowToken to AbilityRecord. + * + * @param token, the token of the ability. + * @param windowToken, window id of the ability. + */ + virtual void AddWindowInfo(const sptr &token, int32_t windowToken) override; + + /** + * AttachAbilityThread, ability call this interface after loaded. + * + * @param scheduler,.the interface handler of kit ability. + * @param token,.ability's token. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int AttachAbilityThread( + const sptr &scheduler, const sptr &token) override; + + /** + * AbilityTransitionDone, ability call this interface after lift cycle was changed. + * + * @param token,.ability's token. + * @param state,.the state of ability lift cycle. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int AbilityTransitionDone(const sptr &token, int state) override; + + /** + * ScheduleConnectAbilityDone, service ability call this interface while session was connected. + * + * @param token,.service ability's token. + * @param remoteObject,.the session proxy of service ability. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int ScheduleConnectAbilityDone( + const sptr &token, const sptr &remoteObject) override; + + /** + * ScheduleDisconnectAbilityDone, service ability call this interface while session was disconnected. + * + * @param token,.service ability's token. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int ScheduleDisconnectAbilityDone(const sptr &token) override; + + /** + * ScheduleCommandAbilityDone, service ability call this interface while session was commanded. + * + * @param token,.service ability's token. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int ScheduleCommandAbilityDone(const sptr &token) override; + + /** + * GetEventHandler, get the ability manager service's handler. + * + * @return Returns AbilityEventHandler ptr. + */ + std::shared_ptr GetEventHandler(); + + /** + * SetStackManager, set the user id of stack manager. + * + * @param userId, user id. + */ + void SetStackManager(int userId); + + /** + * GetStackManager, get the current stack manager. + * + * @return Returns AbilityStackManager ptr. + */ + std::shared_ptr GetStackManager(); + + /** + * DumpWaittingAbilityQueue. + * + * @param result, result. + */ + void DumpWaittingAbilityQueue(std::string &result); + + /** + * dump ability stack info, about userID, mission stack info, + * mission record info and ability info. + * + * @param state Ability stack info. + * @return Returns ERR_OK on success, others on failure. + */ + virtual void DumpState(const std::string &args, std::vector &info) override; + + /** + * Obtains information about ability stack that are running on the device. + * + * @param stackInfo Ability stack info. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int GetAllStackInfo(StackInfo &stackInfo) override; + + /** + * Destroys this Service ability if the number of times it + * has been started equals the number represented by + * the given startId. + * + * @param token ability's token. + * @param startId is incremented by 1 every time this ability is started. + * @return Returns true if the startId matches the number of startup times + * and this Service ability will be destroyed; returns false otherwise. + */ + virtual int TerminateAbilityResult(const sptr &token, int startId) override; + + /** + * Destroys this Service ability by Want. + * + * @param want, Special want for service type's ability. + * @return Returns true if this Service ability will be destroyed; returns false otherwise. + */ + virtual int StopServiceAbility(const Want &want) override; + + /** + * Get the list of the missions that the user has recently launched, + * with the most recent being first and older ones after in order. + * + * @param recentList recent mission info + * @param numMax The maximum number of entries to return in the list. The + * actual number returned may be smaller, depending on how many tasks the + * user has started and the maximum number the system can remember. + * @param falgs Information about what to return. May be any combination + * of {@link #RECENT_WITH_EXCLUDED} and {@link #RECENT_IGNORE_UNAVAILABLE}. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int GetRecentMissions( + const int32_t numMax, const int32_t flags, std::vector &recentList) override; + + /** + * Get mission snapshot by mission id + * + * @param missionId the id of the mission to retrieve the sAutoapshots + * @return Returns ERR_OK on success, others on failure. + */ + virtual int GetMissionSnapshot(const int32_t missionId, MissionSnapshotInfo &snapshot) override; + + /** + * Ask that the mission associated with a given mission ID be moved to the + * front of the stack, so it is now visible to the user. + * + * @param missionId. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int MoveMissionToTop(int32_t missionId) override; + + /** + * Requires that tasks associated with a given capability token be moved to the background + * + * @param token ability token + * @param nonFirst If nonfirst is false and not the lowest ability of the mission, you cannot move mission to end + * @return Returns ERR_OK on success, others on failure. + */ + virtual int MoveMissionToEnd(const sptr &token, const bool nonFirst) override; + + /** + * Remove the specified mission from the stack by mission id + * + * @param missionId. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int RemoveMission(int id) override; + + /** + * Remove the specified mission stack by stack id + * + * @param id. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int RemoveStack(int id) override; + + /** + * Kill the process immediately. + * + * @param bundleName. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int KillProcess(const std::string &bundleName) override; + + /** + * Uninstall app + * + * @param bundleName. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int UninstallApp(const std::string &bundleName) override; + + /** + * Moving mission to the specified stack by mission option(Enter floating window mode). + * @param missionOption, target mission option + * @return Returns ERR_OK on success, others on failure. + */ + virtual int MoveMissionToFloatingStack(const MissionOption &missionOption) override; + + /** + * Moving mission to the specified stack by mission option(Enter floating window mode). + * @param missionOption, target mission option + * @return Returns ERR_OK on success, others on failure. + */ + virtual int MoveMissionToSplitScreenStack(const MissionOption &missionOption) override; + + /** + * Change the focus of ability in the mission stack. + * @param lostToken, the token of lost focus ability + * @param getToken, the token of get focus ability + * @return Returns ERR_OK on success, others on failure. + */ + virtual int ChangeFocusAbility( + const sptr &lostFocusToken, const sptr &getFocusToken) override; + + /** + * minimize multiwindow by mission id. + * @param missionId, the id of target mission + * @return Returns ERR_OK on success, others on failure. + */ + virtual int MinimizeMultiWindow(int missionId) override; + + /** + * maximize multiwindow by mission id. + * @param missionId, the id of target mission + * @return Returns ERR_OK on success, others on failure. + */ + virtual int MaximizeMultiWindow(int missionId) override; + + /** + * get missions info of floating mission stack. + * @param list, mission info. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int GetFloatingMissions(std::vector &list) override; + + /** + * close multiwindow by mission id. + * @param missionId, the id of target mission. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int CloseMultiWindow(int missionId) override; + + /** + * set special mission stack default settings. + * @param stackSetting, mission stack default settings. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int SetMissionStackSetting(const StackSetting &stackSetting) override; + + /** + * @brief Checks whether this ability is the first ability in a mission. + * + * @return Returns true is first in Mission. + */ + virtual bool IsFirstInMission(const sptr &token) override; + + /** + * Checks whether a specified permission has been granted to the process identified by pid and uid + * + * @param permission Indicates the permission to check. + * @param pid Indicates the ID of the process to check. + * @param uid Indicates the UID of the process to check. + * @param message Describe success or failure + * + * @return Returns ERR_OK on success, others on failure. + */ + virtual int CompelVerifyPermission(const std::string &permission, int pid, int uid, std::string &message) override; + + /** + * Save the top ability States and move them to the background + * @return Returns ERR_OK on success, others on failure. + */ + virtual int PowerOff() override; + + /** + * Restore the state before top ability poweroff + * @return Returns ERR_OK on success, others on failure. + */ + virtual int PowerOn() override; + + /** + * Sets the application to start its ability in lock mission mode. + * @param missionId luck mission id + * @return Returns ERR_OK on success, others on failure. + */ + virtual int LockMission(int missionId) override; + + /** + * Unlocks this ability by exiting the lock mission mode. + * @param missionId unluck mission id + * @return Returns ERR_OK on success, others on failure. + */ + virtual int UnlockMission(int missionId) override; + + /** + * Sets description information about the mission containing this ability. + * + * @param description Indicates the object containing information about the + * mission. This parameter cannot be null. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int SetMissionDescriptionInfo( + const sptr &token, const MissionDescriptionInfo &description) override; + + /** + * get current system mission lock mode state. + * + * @return Returns 0: LOCK_MISSION_STATE_NONE, 1: LOCK_MISSION_STATE_LOCKED + */ + virtual int GetMissionLockModeState() override; + + /** + * Updates the configuration by modifying the configuration. + * + * @param config Indicates the new configuration + * @return Returns ERR_OK on success, others on failure. + */ + virtual int UpdateConfiguration(const DummyConfiguration &config) override; + + /** + * remove all service record. + * + */ + void RemoveAllServiceRecord(); + + virtual sptr GetWantSender( + const WantSenderInfo &wantSenderInfo, const sptr &callerToken) override; + + virtual int SendWantSender(const sptr &target, const SenderInfo &senderInfo) override; + + virtual void CancelWantSender(const sptr &sender) override; + + virtual int GetPendingWantUid(const sptr &target) override; + + virtual int GetPendingWantUserId(const sptr &target) override; + + virtual std::string GetPendingWantBundleName(const sptr &target) override; + + virtual int GetPendingWantCode(const sptr &target) override; + + virtual int GetPendingWantType(const sptr &target) override; + + virtual void RegisterCancelListener(const sptr &sender, const sptr &receiver) override; + + virtual void UnregisterCancelListener( + const sptr &sender, const sptr &receiver) override; + + virtual int GetPendingRequestWant(const sptr &target, std::shared_ptr &want) override; + + /** + * get service record by element name. + * + */ + std::shared_ptr GetServiceRecordByElementName(const std::string &element); + std::list> GetConnectRecordListByCallback(sptr callback); + + void OnAbilityDied(std::shared_ptr abilityRecord); + + /** + * wait for starting system ui. + * + */ + void StartSystemUi(const std::string name); + + void HandleLoadTimeOut(int64_t eventId); + void HandleActiveTimeOut(int64_t eventId); + void HandleInactiveTimeOut(int64_t eventId); + + void RestartAbility(const sptr &token); + void NotifyBmsAbilityLifeStatus( + const std::string &bundleName, const std::string &abilityName, const int64_t launchTime); + + int StartAbility(const Want &want, const sptr &callerToken, int requestCode, int callerUid = -1); + + int CheckPermission(const std::string &bundleName, const std::string &permission); + + // MSG 0 - 20 represents timeout message + static constexpr uint32_t LOAD_TIMEOUT_MSG = 0; + static constexpr uint32_t ACTIVE_TIMEOUT_MSG = 1; + static constexpr uint32_t INACTIVE_TIMEOUT_MSG = 2; + static constexpr uint32_t BACKGROUND_TIMEOUT_MSG = 3; + static constexpr uint32_t TERMINATE_TIMEOUT_MSG = 4; + + static constexpr uint32_t LOAD_TIMEOUT = 3000; // ms + static constexpr uint32_t ACTIVE_TIMEOUT = 5000; // ms + static constexpr uint32_t INACTIVE_TIMEOUT = 500; // ms + static constexpr uint32_t BACKGROUND_TIMEOUT = 10000; // ms + static constexpr uint32_t TERMINATE_TIMEOUT = 10000; // ms + static constexpr uint32_t CONNECT_TIMEOUT = 500; // ms + static constexpr uint32_t DISCONNECT_TIMEOUT = 500; // ms + static constexpr uint32_t COMMAND_TIMEOUT = 5000; // ms + static constexpr uint32_t SYSTEM_UI_TIMEOUT = 5000; // ms + static constexpr uint32_t RESTART_TIMEOUT = 5000; // ms + static constexpr uint32_t RESTART_ABILITY_TIMEOUT = 500; // ms + + static constexpr uint32_t MIN_DUMP_ARGUMENT_NUM = 2; + static constexpr uint32_t MAX_WAIT_SYSTEM_UI_NUM = 600; + + enum DumpKey { + KEY_DUMP_ALL = 0, + KEY_DUMP_STACK_LIST, + KEY_DUMP_STACK, + KEY_DUMP_MISSION, + KEY_DUMP_TOP_ABILITY, + KEY_DUMP_WAIT_QUEUE, + KEY_DUMP_SERVICE, + KEY_DUMP_DATA, + KEY_DUMP_SYSTEM_UI, + KEY_DUMP_FOCUS_ABILITY, + }; + + friend class AbilityStackManager; + +protected: + void OnAbilityRequestDone(const sptr &token, const int32_t state) override; + int GetUidByBundleName(std::string bundleName); + + void OnAppStateChanged(const AppInfo &info) override; + +private: + /** + * initialization of ability manager service. + * + */ + bool Init(); + /** + * starting lanucher ability. + * + */ + void StartingLauncherAbility(); + + /** + * starting system ui abilites. + * + */ + void StartingSystemUiAbility(const SatrtUiMode &mode); + + /** + * connet bms. + * + */ + void ConnectBmsService(); + /** + * get the user id. + * + */ + int GetUserId(); + bool IsSystemUiApp(const AppExecFwk::AbilityInfo &info) const; + + /** + * generate ability request. + * + */ + int GenerateAbilityRequest( + const Want &want, int requestCode, AbilityRequest &request, const sptr &callerToken); + /** + * Select to start the application according to the configuration file of AMS + * + */ + void StartSystemApplication(); + + sptr GetBundleManager(); + int PreLoadAppDataAbilities(const std::string &bundleName); + + bool VerificationToken(const sptr &token); + void RequestPermission(const Want *resultWant); + + void DumpInner(const std::string &args, std::vector &info); + void DumpStackListInner(const std::string &args, std::vector &info); + void DumpStackInner(const std::string &args, std::vector &info); + void DumpMissionInner(const std::string &args, std::vector &info); + void DumpTopAbilityInner(const std::string &args, std::vector &info); + void DumpWaittingAbilityQueueInner(const std::string &args, std::vector &info); + void DumpStateInner(const std::string &args, std::vector &info); + void DataDumpStateInner(const std::string &args, std::vector &info); + void SystemDumpStateInner(const std::string &args, std::vector &info); + void DumpFocusMapInner(const std::string &args, std::vector &info); + void DumpFuncInit(); + bool CheckCallerIsSystemAppByIpc(); + using DumpFuncType = void (AbilityManagerService::*)(const std::string &args, std::vector &info); + std::map dumpFuncMap_; + + constexpr static int REPOLL_TIME_MICRO_SECONDS = 1000000; + constexpr static int WAITING_BOOT_ANIMATION_TIMER = 5; + + std::shared_ptr eventLoop_; + std::shared_ptr handler_; + ServiceRunningState state_; + std::unordered_map> stackManagers_; + std::shared_ptr currentStackManager_; + std::shared_ptr connectManager_; + sptr iBundleManager_; + std::shared_ptr appScheduler_; + std::shared_ptr dataAbilityManager_; + std::shared_ptr pendingWantManager_; + std::shared_ptr systemAppManager_; + std::shared_ptr amsConfigResolver_; + const static std::map dumpMap; +}; + +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_ABILITY_MANAGER_SERVICE_H diff --git a/tools/services/abilitymgr/include/ability_manager_stub.h b/tools/services/abilitymgr/include/ability_manager_stub.h new file mode 100644 index 00000000000..e2bd2be6212 --- /dev/null +++ b/tools/services/abilitymgr/include/ability_manager_stub.h @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_ABILITY_MANAGER_STUB_H +#define OHOS_AAFWK_ABILITY_MANAGER_STUB_H + +#include "ability_manager_interface.h" + +#include +#include + +#include "hilog_wrapper.h" + +namespace OHOS { +namespace AAFwk { +/** + * @class AbilityManagerStub + * AbilityManagerStub. + */ +class AbilityManagerStub : public IRemoteStub { +public: + AbilityManagerStub(); + ~AbilityManagerStub(); + virtual int OnRemoteRequest( + uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override; + +private: + void FirstStepInit(); + void SecondStepInit(); + int TerminateAbilityInner(MessageParcel &data, MessageParcel &reply); + int TerminateAbilityByCallerInner(MessageParcel &data, MessageParcel &reply); + int AttachAbilityThreadInner(MessageParcel &data, MessageParcel &reply); + int AbilityTransitionDoneInner(MessageParcel &data, MessageParcel &reply); + int ScheduleConnectAbilityDoneInner(MessageParcel &data, MessageParcel &reply); + int ScheduleDisconnectAbilityDoneInner(MessageParcel &data, MessageParcel &reply); + int AddWindowInfoInner(MessageParcel &data, MessageParcel &reply); + int TerminateAbilityResultInner(MessageParcel &data, MessageParcel &reply); + int GetAllStackInfoInner(MessageParcel &data, MessageParcel &reply); + int GetRecentMissionsInner(MessageParcel &data, MessageParcel &reply); + int RemoveMissionInner(MessageParcel &data, MessageParcel &reply); + int RemoveStackInner(MessageParcel &data, MessageParcel &reply); + int ScheduleCommandAbilityDoneInner(MessageParcel &data, MessageParcel &reply); + int GetMissionSnapshotInner(MessageParcel &data, MessageParcel &reply); + int AcquireDataAbilityInner(MessageParcel &data, MessageParcel &reply); + int ReleaseDataAbilityInner(MessageParcel &data, MessageParcel &reply); + int MoveMissionToTopInner(MessageParcel &data, MessageParcel &reply); + int MoveMissionToEndInner(MessageParcel &data, MessageParcel &reply); + int KillProcessInner(MessageParcel &data, MessageParcel &reply); + int UninstallAppInner(MessageParcel &data, MessageParcel &reply); + int StartAbilityInner(MessageParcel &data, MessageParcel &reply); + int StartAbilityAddCallerInner(MessageParcel &data, MessageParcel &reply); + int ConnectAbilityInner(MessageParcel &data, MessageParcel &reply); + int DisconnectAbilityInner(MessageParcel &data, MessageParcel &reply); + int StopServiceAbilityInner(MessageParcel &data, MessageParcel &reply); + int DumpStateInner(MessageParcel &data, MessageParcel &reply); + int StartAbilityForSettingsInner(MessageParcel &data, MessageParcel &reply); + int MoveMissionToFloatingStackInner(MessageParcel &data, MessageParcel &reply); + int MoveMissionToSplitScreenStackInner(MessageParcel &data, MessageParcel &reply); + int ChangeFocusAbilityInner(MessageParcel &data, MessageParcel &reply); + int MinimizeMultiWindowInner(MessageParcel &data, MessageParcel &reply); + int MaximizeMultiWindowInner(MessageParcel &data, MessageParcel &reply); + int GetFloatingMissionsInner(MessageParcel &data, MessageParcel &reply); + int CloseMultiWindowInner(MessageParcel &data, MessageParcel &reply); + int SetMissionStackSettingInner(MessageParcel &data, MessageParcel &reply); + int IsFirstInMissionInner(MessageParcel &data, MessageParcel &reply); + int CompelVerifyPermissionInner(MessageParcel &data, MessageParcel &reply); + int PowerOffInner(MessageParcel &data, MessageParcel &reply); + int PowerOnInner(MessageParcel &data, MessageParcel &reply); + int LockMissionInner(MessageParcel &data, MessageParcel &reply); + int UnlockMissionInner(MessageParcel &data, MessageParcel &reply); + int SetMissionDescriptionInfoInner(MessageParcel &data, MessageParcel &reply); + int GetMissionLockModeStateInner(MessageParcel &data, MessageParcel &reply); + int UpdateConfigurationInner(MessageParcel &data, MessageParcel &reply); + + int GetWantSenderInner(MessageParcel &data, MessageParcel &reply); + int SendWantSenderInner(MessageParcel &data, MessageParcel &reply); + int CancelWantSenderInner(MessageParcel &data, MessageParcel &reply); + + int GetPendingWantUidInner(MessageParcel &data, MessageParcel &reply); + int GetPendingWantUserIdInner(MessageParcel &data, MessageParcel &reply); + int GetPendingWantBundleNameInner(MessageParcel &data, MessageParcel &reply); + int GetPendingWantCodeInner(MessageParcel &data, MessageParcel &reply); + int GetPendingWantTypeInner(MessageParcel &data, MessageParcel &reply); + + int RegisterCancelListenerInner(MessageParcel &data, MessageParcel &reply); + int UnregisterCancelListenerInner(MessageParcel &data, MessageParcel &reply); + + int GetPendingRequestWantInner(MessageParcel &data, MessageParcel &reply); + int MoveMissionToEndTestInner(MessageParcel &data, MessageParcel &reply); + + using RequestFuncType = int (AbilityManagerStub::*)(MessageParcel &data, MessageParcel &reply); + std::map requestFuncMap_; +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_ABILITY_MANAGER_STUB_H diff --git a/tools/services/abilitymgr/include/ability_record.h b/tools/services/abilitymgr/include/ability_record.h new file mode 100644 index 00000000000..cfb89faeb60 --- /dev/null +++ b/tools/services/abilitymgr/include/ability_record.h @@ -0,0 +1,747 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_ABILITY_RECORD_H +#define OHOS_AAFWK_ABILITY_RECORD_H + +#include +#include +#include +#include +#include + +#include "ability_info.h" +#include "ability_start_setting.h" +#include "ability_token_stub.h" +#include "ability_window_configuration.h" +#include "app_scheduler.h" +#include "application_info.h" +#include "ability_record_info.h" +#include "configuration_holder.h" +#include "lifecycle_deal.h" +#include "lifecycle_state_info.h" +#include "want.h" +#include "window_info.h" + +namespace OHOS { +namespace AAFwk { +using Closure = std::function; + +class AbilityRecord; +class MissionRecord; +class ConnectionRecord; + +const std::string ABILITY_TOKEN_NAME = "AbilityToken"; +const std::string LINE_SEPARATOR = "\n"; + +/** + * @class Token + * Token is identification of ability and used to interact with kit and wms. + */ +class Token : public AbilityTokenStub { +public: + explicit Token(std::weak_ptr abilityRecord); + virtual ~Token(); + + std::shared_ptr GetAbilityRecord() const; + static std::shared_ptr GetAbilityRecordByToken(const sptr &token); + +private: + std::weak_ptr abilityRecord_; // ability of this token +}; + +/** + * @class AbilityResult + * Record requestCode of for-result start mode and result. + */ +class AbilityResult { +public: + AbilityResult() = default; + AbilityResult(int requestCode, int resultCode, const Want &resultWant) + : requestCode_(requestCode), resultCode_(resultCode), resultWant_(resultWant) + {} + virtual ~AbilityResult() + {} + + int requestCode_ = -1; // requestCode of for-result start mode + int resultCode_ = -1; // resultCode of for-result start mode + Want resultWant_; // for-result start mode ability will send the result to caller +}; + +/** + * @class CallerRecord + * Record caller ability of for-result start mode and result. + */ +class CallerRecord { +public: + CallerRecord() = default; + CallerRecord(int requestCode, std::weak_ptr caller) : requestCode_(requestCode), caller_(caller) + {} + virtual ~CallerRecord() + {} + + int GetRequestCode() + { + return requestCode_; + } + std::shared_ptr GetCaller() + { + return caller_.lock(); + } + +private: + int requestCode_ = -1; // requestCode of for-result start mode + std::weak_ptr caller_; +}; + +/** + * @class AbilityRequest + * Wrap parameters of starting ability. + */ +struct AbilityRequest { + Want want; + AppExecFwk::AbilityInfo abilityInfo; + AppExecFwk::ApplicationInfo appInfo; + int requestCode = -1; + bool restart = false; + sptr callerToken; + std::shared_ptr startSetting = nullptr; + void Dump(std::vector &state) + { + std::string dumpInfo = " want [" + want.ToUri() + "]"; + state.push_back(dumpInfo); + dumpInfo = " app name [" + abilityInfo.applicationName + "]"; + state.push_back(dumpInfo); + dumpInfo = " main name [" + abilityInfo.name + "]"; + state.push_back(dumpInfo); + dumpInfo = " request code [" + std::to_string(requestCode) + "]"; + state.push_back(dumpInfo); + } +}; + +/** + * @class AbilityRecord + * AbilityRecord records ability info and states and used to schedule ability life. + */ +class AbilityRecord : public ConfigurationHolder, public std::enable_shared_from_this { +public: + AbilityRecord(const Want &want, const AppExecFwk::AbilityInfo &abilityInfo, + const AppExecFwk::ApplicationInfo &applicationInfo, int requestCode = -1); + + virtual ~AbilityRecord(); + + /** + * CreateAbilityRecord. + * + * @param abilityRequest,create ability record. + * @return Returns ability record ptr. + */ + static std::shared_ptr CreateAbilityRecord(const AbilityRequest &abilityRequest); + + /** + * Init ability record. + * + * @return Returns true on success, others on failure. + */ + bool Init(); + + /** + * load ability. + * + * @return Returns ERR_OK on success, others on failure. + */ + int LoadAbility(); + + /** + * terminate ability. + * + * @return Returns ERR_OK on success, others on failure. + */ + int TerminateAbility(); + + /** + * set ability's mission record. + * + * @param missionRecord, mission record. + */ + void SetMissionRecord(const std::shared_ptr &missionRecord); + + /** + * set ability's mission stack. + * + * @param missionStack, mission stack. + */ + void SetMissionStackId(const int stackId); + + /** + * Get ability's mission stack id. + */ + int GetMissionStackId() const; + + /** + * get ability's mission record. + * + * @return missionRecord, mission record. + */ + std::shared_ptr GetMissionRecord() const; + + int GetMissionRecordId() const; + + /** + * get ability's info. + * + * @return ability info. + */ + const AppExecFwk::AbilityInfo &GetAbilityInfo() const; + + /** + * get application's info. + * + * @return application info. + */ + const AppExecFwk::ApplicationInfo &GetApplicationInfo() const; + + /** + * set ability's state. + * + * @param state, ability's state. + */ + void SetAbilityState(AbilityState state); + + /** + * get ability's state. + * + * @return ability state. + */ + AbilityState GetAbilityState() const; + + /** + * set ability scheduler for accessing ability thread. + * + * @param scheduler , ability scheduler. + */ + void SetScheduler(const sptr &scheduler); + + /** + * get ability's token. + * + * @return ability's token. + */ + sptr GetToken() const; + + /** + * set ability's previous ability record. + * + * @param abilityRecord , previous ability record + */ + void SetPreAbilityRecord(const std::shared_ptr &abilityRecord); + + /** + * get ability's previous ability record. + * + * @return previous ability record + */ + std::shared_ptr GetPreAbilityRecord() const; + + /** + * set ability's next ability record. + * + * @param abilityRecord , next ability record + */ + void SetNextAbilityRecord(const std::shared_ptr &abilityRecord); + + /** + * get ability's previous ability record. + * + * @return previous ability record + */ + std::shared_ptr GetNextAbilityRecord() const; + + /** + * set ability's back ability record. + * + * @param abilityRecord , back ability record + */ + void SetBackAbilityRecord(const std::shared_ptr &abilityRecord); + + /** + * get ability's back ability record. + * + * @return back ability record + */ + std::shared_ptr GetBackAbilityRecord() const; + + /** + * set event id. + * + * @param eventId + */ + void SetEventId(int64_t eventId); + + /** + * get event id. + * + * @return eventId + */ + int64_t GetEventId() const; + + /** + * check whether the ability is ready. + * + * @return true : ready ,false: not ready + */ + bool IsReady() const; + + /** + * check whether the ability 's window is attached. + * + * @return true : attached ,false: not attached + */ + bool IsWindowAttached() const; + + /** + * check whether the ability is launcher. + * + * @return true : lanucher ,false: not lanucher + */ + bool IsLauncherAbility() const; + + /** + * check whether the ability is terminating. + * + * @return true : yes ,false: not + */ + bool IsTerminating() const; + + /** + * check whether the ability force to terminate. + * + * @return true : yes ,false: not + */ + bool IsForceTerminate() const; + void SetForceTerminate(bool flag); + + /** + * set the ability is terminating. + * + */ + void SetTerminatingState(); + + /** + * set the ability is new want flag. + * + * @return isNewWant + */ + void SetIsNewWant(bool isNewWant); + + /** + * check whether the ability is new want flag. + * + * @return true : yes ,false: not + */ + bool IsNewWant() const; + + /** + * check whether the ability is created by connect ability mode. + * + * @return true : yes ,false: not + */ + bool IsCreateByConnect() const; + + /** + * set the ability is created by connect ability mode. + * + */ + void SetCreateByConnectMode(); + + /** + * active the ability. + * + */ + void Activate(); + + /** + * process request of activing the ability. + * + */ + void ProcessActivate(); + + /** + * process request of activing the ability in moving. + * + */ + void ProcessActivateInMoving(); + + /** + * process request of inactiving the ability. + * + */ + void ProcessInactivate(); + + /** + * process request of inactiving the ability in moving. + * + */ + void ProcessInactivateInMoving(); + + /** + * inactive the ability. + * + */ + void Inactivate(); + + /** + * move the ability to back ground. + * + */ + void MoveToBackground(const Closure &task); + + /** + * terminate the ability. + * + */ + void Terminate(const Closure &task); + + /** + * connect the ability. + * + */ + void ConnectAbility(); + + /** + * disconnect the ability. + * + */ + void DisconnectAbility(); + + /** + * Command the ability. + * + */ + void CommandAbility(); + + /** + * save ability state. + * + */ + void SaveAbilityState(); + + /** + * restore ability state. + * + */ + void RestoreAbilityState(); + + /** + * notify top active ability updated. + * + */ + void TopActiveAbilityChanged(bool flag); + + /** + * set the want for start ability. + * + */ + void SetWant(const Want &want); + + /** + * get the want for start ability. + * + */ + const Want &GetWant() const; + + /** + * get request code of the ability to start. + * + */ + int GetRequestCode() const; + + /** + * set the result object of the ability which one need to be terminated. + * + */ + void SetResult(const std::shared_ptr &result); + + /** + * get the result object of the ability which one need to be terminated. + * + */ + std::shared_ptr GetResult() const; + + /** + * send result object to caller ability thread. + * + */ + void SendResult(); + + /** + * send result object to caller ability. + * + */ + void SendResultToCallers(); + + /** + * save result object to caller ability. + * + */ + void SaveResultToCallers(const int resultCode, const Want *resultWant); + + /** + * add connect record to the list. + * + */ + void AddConnectRecordToList(const std::shared_ptr &connRecord); + + /** + * get the list of connect record. + * + */ + std::list> GetConnectRecordList() const; + + /** + * get the list of connect record. + * + */ + std::list> GetConnectingRecordList(); + + /** + * remove the connect record from list. + * + */ + void RemoveConnectRecordFromList(const std::shared_ptr &connRecord); + + /** + * check whether connect list is empty. + * + */ + bool IsConnectListEmpty(); + + /** + * add ability's window info to record. + * + */ + void AddWindowInfo(int windowToken); + + /** + * remove ability's window info from record. + * + */ + void RemoveWindowInfo(); + + /** + * get ability's window info from record. + * + */ + std::shared_ptr GetWindowInfo() const; + + /** + * add caller record + * + */ + void AddCallerRecord(const sptr &callerToken, int requestCode); + + /** + * get caller record to list. + * + */ + std::list> GetCallerRecordList() const; + + /** + * get connecting record from list. + * + */ + std::shared_ptr GetConnectingRecord() const; + + /** + * get disconnecting record from list. + * + */ + std::shared_ptr GetDisconnectingRecord() const; + + /** + * convert ability state (enum type to string type). + * + */ + static std::string ConvertAbilityState(const AbilityState &state); + + static std::string ConvertAppState(const AppState &state); + + /** + * convert life cycle state to ability state . + * + */ + static int ConvertLifeCycleToAbilityState(const AbilityLifeCycleState &state); + + /** + * get the ability record id. + * + */ + inline int GetRecordId() const + { + return recordId_; + } + + /** + * dump ability info. + * + */ + void Dump(std::vector &info); + + void SetStartTime(); + + int64_t GetStartTime() const; + + /** + * dump service info. + * + */ + void DumpService(std::vector &info) const; + + /** + * get ability record info. + * + */ + void GetAbilityRecordInfo(AbilityRecordInfo &recordInfo); + + /** + * set aconnect remote object. + * + */ + void SetConnRemoteObject(const sptr &remoteObject); + + /** + * get connect remote object. + * + */ + sptr GetConnRemoteObject() const; + + void AddStartId(); + int GetStartId() const; + + void SetIsUninstallAbility(); + /** + * Determine whether ability is uninstalled + * + * @return true: uninstalled false: installed + */ + bool IsUninstallAbility() const; + + void SetKernalSystemAbility(); + bool IsKernalSystemAbility() const; + + void SetLauncherRoot(); + bool IsLauncherRoot() const; + + bool IsAbilityState(const AbilityState &state) const; + + bool SupportMultWindow() const; + void NotifyMultiWinModeChanged(const AbilityWindowConfiguration &winModeKey, bool flag); + void SetInMovingState(bool isMoving); + bool GetInMovingState() const; + + bool IsToEnd() const; + void SetToEnd(bool isToEnd); + + void SetStartSetting(const std::shared_ptr &setting); + std::shared_ptr GetStartSetting() const; + + void SetPowerState(const bool isPower); + bool GetPowerState() const; + + void SetRestarting(const bool isRestart); + bool IsRestarting() const; + void SetAppState(const AppState &state); + AppState GetAppState() const; + + unsigned int GetIntConfigChanges(); + void ClearFlag(); + +protected: + virtual bool OnConfigurationChanged(const DummyConfiguration &config, unsigned int configChanges) override; + virtual std::shared_ptr GetParent() override; + virtual unsigned int GetChildSize() override; + virtual std::shared_ptr FindChild(unsigned int index) override; + +private: + /** + * get the type of ability. + * + */ + void GetAbilityTypeString(std::string &typeStr); + void OnSchedulerDied(const wptr &remote); + void SendEvent(uint32_t msg, uint32_t timeOut); + + static int64_t abilityRecordId; + int recordId_ = 0; // record id + Want want_ = {}; // want to start this ability + AppExecFwk::AbilityInfo abilityInfo_ = {}; // the ability info get from BMS + AppExecFwk::ApplicationInfo applicationInfo_ = {}; // the ability info get from BMS + sptr token_ = {}; // used to interact with kit and wms + std::weak_ptr missionRecord_ = {}; // mission of this ability + std::weak_ptr preAbilityRecord_ = {}; // who starts this ability record + std::weak_ptr nextAbilityRecord_ = {}; // ability that started by this ability + std::weak_ptr backAbilityRecord_ = {}; // who back to this ability record + std::unique_ptr lifecycleDeal_ = {}; // life manager used to schedule life + int64_t startTime_ = 0; // records first time of ability start + bool isReady_ = false; // is ability thread attached? + bool isWindowAttached_ = false; // Is window of this ability attached? + bool isLauncherAbility_ = false; // is launcher? + int64_t eventId_ = 0; // post event id + static int64_t g_abilityRecordEventId_; + sptr scheduler_ = {}; // kit scheduler + bool isTerminating_ = false; // is terminating ? + LifeCycleStateInfo lifeCycleStateInfo_; // target life state info + AbilityState currentState_ = AbilityState::INITIAL; // current life state + std::shared_ptr windowInfo_; // add window info + bool isCreateByConnect_ = false; // is created by connect ability mode? + bool isToEnd_ = false; // is to end ? + + int requestCode_ = -1; // requestCode_: >= 0 for-result start mode; <0 for normal start mode in default. + sptr schedulerDeathRecipient_ = {}; // scheduler binderDied Recipient + + /** + * result_: ability starts with for-result mode will send result before being terminated. + * Its caller will receive results before active. + * Now we assume only one result generate when terminate. + */ + std::shared_ptr result_ = {}; + + // service(ability) can be connected by multi-pages(abilites), so need to store this service's connections + std::list> connRecordList_ = {}; + // service(ability) onConnect() return proxy of service ability + sptr connRemoteObject_ = {}; + int startId_ = 0; // service(ability) start id + + // page(ability) can be started by multi-pages(abilites), so need to store this ability's caller + std::list> callerList_ = {}; + + bool isUninstall_ = false; + bool isForceTerminate_ = false; + const static std::map stateToStrMap; + const static std::map convertStateMap; + const static std::map appStateToStrMap_; + + bool isKernalSystemAbility_ = false; + bool isLauncherRoot_ = false; + bool isPowerState_ = false; // ability to change state when poweroff and poweron. + + PacMap stateDatas_; // ability saved ability state data + bool isRestarting_ = false; // is restarting ? + bool isInMovingState_ = false; // whether complete multi window moving state. + AppState appState_ = AppState::BEGIN; +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_ABILITY_RECORD_H diff --git a/tools/services/abilitymgr/include/ability_scheduler_proxy.h b/tools/services/abilitymgr/include/ability_scheduler_proxy.h new file mode 100644 index 00000000000..156dc0f06bd --- /dev/null +++ b/tools/services/abilitymgr/include/ability_scheduler_proxy.h @@ -0,0 +1,289 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_ABILITY_SCHEDULE_PROXY_H +#define OHOS_AAFWK_ABILITY_SCHEDULE_PROXY_H + +#include "ability_scheduler_interface.h" + +#include + +namespace OHOS { +namespace NativeRdb { +class AbsSharedResultSet; +class DataAbilityPredicates; +class ValuesBucket; +} // namespace NativeRdb +namespace AAFwk { +/** + * @class AbilitySchedulerProxy + * AbilityScheduler proxy. + */ +class AbilitySchedulerProxy : public IRemoteProxy { +public: + explicit AbilitySchedulerProxy(const sptr &impl) : IRemoteProxy(impl) + {} + + virtual ~AbilitySchedulerProxy() + {} + + /* + * ScheduleAbilityTransaction, schedule ability to transform life state. + * + * @param Want, Special Want for service type's ability. + * @param targetState, The lifecycle state to be transformed + */ + void ScheduleAbilityTransaction(const Want &want, const LifeCycleStateInfo &targetState) override; + + /* + * SendResult, Send result to app when ability is terminated with result want. + * + * @param requestCode, the requestCode of the ability to start. + * @param resultCode, the resultCode of the ability to terminate. + * @param resultWant, the want of the ability to terminate. + */ + void SendResult(int requestCode, int resultCode, const Want &resultWant) override; + + /* + * ScheduleConnectAbility, schedule service ability to connect. + * + * @param Want, Special Want for service type's ability. + */ + void ScheduleConnectAbility(const Want &want) override; + + /* + * ScheduleDisconnectAbility, schedule service ability to disconnect. + */ + void ScheduleDisconnectAbility(const Want &want) override; + + /* + * ScheduleCommandAbility, schedule service ability to command. + */ + void ScheduleCommandAbility(const Want &want, bool restart, int startId) override; + + /* + * ScheduleSaveAbilityState, scheduling save ability state. + */ + void ScheduleSaveAbilityState(PacMap &outState) override; + + /* + * ScheduleRestoreAbilityState, scheduling restore ability state. + */ + void ScheduleRestoreAbilityState(const PacMap &inState) override; + + void ScheduleUpdateConfiguration(const DummyConfiguration &config) override; + + /** + * @brief Obtains the MIME types of files supported. + * + * @param uri Indicates the path of the files to obtain. + * @param mimeTypeFilter Indicates the MIME types of the files to obtain. This parameter cannot be null. + * + * @return Returns the matched MIME types. If there is no match, null is returned. + */ + virtual std::vector GetFileTypes(const Uri &uri, const std::string &mimeTypeFilter) override; + + /** + * @brief Opens a file in a specified remote path. + * + * @param uri Indicates the path of the file to open. + * @param mode Indicates the file open mode, which can be "r" for read-only access, "w" for write-only access + * (erasing whatever data is currently in the file), "wt" for write access that truncates any existing file, + * "wa" for write-only access to append to any existing data, "rw" for read and write access on any existing data, + * or "rwt" for read and write access that truncates any existing file. + * + * @return Returns the file descriptor. + */ + virtual int OpenFile(const Uri &uri, const std::string &mode) override; + + /** + * @brief This is like openFile, open a file that need to be able to return sub-sections of files,often assets + * inside of their .hap. + * + * @param uri Indicates the path of the file to open. + * @param mode Indicates the file open mode, which can be "r" for read-only access, "w" for write-only access + * (erasing whatever data is currently in the file), "wt" for write access that truncates any existing file, + * "wa" for write-only access to append to any existing data, "rw" for read and write access on any existing + * data, or "rwt" for read and write access that truncates any existing file. + * + * @return Returns the RawFileDescriptor object containing file descriptor. + */ + virtual int OpenRawFile(const Uri &uri, const std::string &mode) override; + + /** + * @brief Inserts a single data record into the database. + * + * @param uri Indicates the path of the data to operate. + * @param value Indicates the data record to insert. If this parameter is null, a blank row will be inserted. + * + * @return Returns the index of the inserted data record. + */ + virtual int Insert(const Uri &uri, const NativeRdb::ValuesBucket &value) override; + + /** + * @brief Updates data records in the database. + * + * @param uri Indicates the path of data to update. + * @param value Indicates the data to update. This parameter can be null. + * @param predicates Indicates filter criteria. You should define the processing logic when this parameter is null. + * + * @return Returns the number of data records updated. + */ + virtual int Update(const Uri &uri, const NativeRdb::ValuesBucket &value, + const NativeRdb::DataAbilityPredicates &predicates) override; + + /** + * @brief Deletes one or more data records from the database. + * + * @param uri Indicates the path of the data to operate. + * @param predicates Indicates filter criteria. You should define the processing logic when this parameter is null. + * + * @return Returns the number of data records deleted. + */ + virtual int Delete(const Uri &uri, const NativeRdb::DataAbilityPredicates &predicates) override; + + /** + * @brief Deletes one or more data records from the database. + * + * @param uri Indicates the path of data to query. + * @param columns Indicates the columns to query. If this parameter is null, all columns are queried. + * @param predicates Indicates filter criteria. You should define the processing logic when this parameter is null. + * + * @return Returns the query result. + */ + virtual std::shared_ptr Query( + const Uri &uri, std::vector &columns, const NativeRdb::DataAbilityPredicates &predicates) override; + + /** + * @brief Obtains the MIME type matching the data specified by the URI of the Data ability. This method should be + * implemented by a Data ability. Data abilities supports general data types, including text, HTML, and JPEG. + * + * @param uri Indicates the URI of the data. + * + * @return Returns the MIME type that matches the data specified by uri. + */ + std::string GetType(const Uri &uri) override; + + /** + * @brief Reloads data in the database. + * + * @param uri Indicates the position where the data is to reload. This parameter is mandatory. + * @param extras Indicates the PacMap object containing the additional parameters to be passed in this call. This + * parameter can be null. If a custom Sequenceable object is put in the PacMap object and will be transferred across + * processes, you must call BasePacMap.setClassLoader(ClassLoader) to set a class loader for the custom object. + * + * @return Returns true if the data is successfully reloaded; returns false otherwise. + */ + bool Reload(const Uri &uri, const PacMap &extras) override; + + /** + * @brief Inserts multiple data records into the database. + * + * @param uri Indicates the path of the data to operate. + * @param values Indicates the data records to insert. + * + * @return Returns the number of data records inserted. + */ + int BatchInsert(const Uri &uri, const std::vector &values) override; + + /** + * @brief notify multi window mode changed. + * + * @param winModeKey Indicates ability Window display mode. + * @param flag Indicates this ability has been enter this mode. + */ + void NotifyMultiWinModeChanged(int32_t winModeKey, bool flag) override; + + /** + * @brief Registers an observer to DataObsMgr specified by the given Uri. + * + * @param uri, Indicates the path of the data to operate. + * @param dataObserver, Indicates the IDataAbilityObserver object. + * + * @return Return true if success. otherwise return false. + */ + bool ScheduleRegisterObserver(const Uri &uri, const sptr &dataObserver) override; + + /** + * @brief Deregisters an observer used for DataObsMgr specified by the given Uri. + * + * @param uri, Indicates the path of the data to operate. + * @param dataObserver, Indicates the IDataAbilityObserver object. + * + * @return Return true if success. otherwise return false. + */ + bool ScheduleUnregisterObserver(const Uri &uri, const sptr &dataObserver) override; + + /** + * @brief notify this ability is top active ability. + * + * @param flag true: Indicates this ability is top active ability + */ + void NotifyTopActiveAbilityChanged(bool flag) override; + + /** + * @brief Notifies the registered observers of a change to the data resource specified by Uri. + * + * @param uri, Indicates the path of the data to operate. + * + * @return Return true if success. otherwise return false. + */ + bool ScheduleNotifyChange(const Uri &uri) override; + + /** + * @brief Converts the given uri that refer to the Data ability into a normalized URI. A normalized URI can be used + * across devices, persisted, backed up, and restored. It can refer to the same item in the Data ability even if the + * context has changed. If you implement URI normalization for a Data ability, you must also implement + * denormalizeUri(ohos.utils.net.Uri) to enable URI denormalization. After this feature is enabled, URIs passed to + * any method that is called on the Data ability must require normalization verification and denormalization. The + * default implementation of this method returns null, indicating that this Data ability does not support URI + * normalization. + * + * @param uri Indicates the Uri object to normalize. + * + * @return Returns the normalized Uri object if the Data ability supports URI normalization; returns null otherwise. + */ + Uri NormalizeUri(const Uri &uri) override; + + /** + * @brief Converts the given normalized uri generated by normalizeUri(ohos.utils.net.Uri) into a denormalized one. + * The default implementation of this method returns the original URI passed to it. + * + * @param uri uri Indicates the Uri object to denormalize. + * + * @return Returns the denormalized Uri object if the denormalization is successful; returns the original Uri passed + * to this method if there is nothing to do; returns null if the data identified by the original Uri cannot be found + * in the current environment. + */ + Uri DenormalizeUri(const Uri &uri) override; + + /** + * @brief Performs batch operations on the database. + * + * @param operations Indicates a list of database operations on the database. + * @return Returns the result of each operation, in array. + */ + std::vector> ExecuteBatch( + const std::vector> &operations) override; + +private: + bool WriteInterfaceToken(MessageParcel &data); + +private: + static inline BrokerDelegator delegator_; +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_ABILITY_SCHEDULE_PROXY_H diff --git a/tools/services/abilitymgr/include/ability_scheduler_stub.h b/tools/services/abilitymgr/include/ability_scheduler_stub.h new file mode 100644 index 00000000000..88cdc87d70a --- /dev/null +++ b/tools/services/abilitymgr/include/ability_scheduler_stub.h @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_OS_AAFWK_ABILITY_SCHEDULE_STUB_H +#define OHOS_OS_AAFWK_ABILITY_SCHEDULE_STUB_H + +#include + +#include "ability_scheduler_interface.h" + +#include +#include + +namespace OHOS { +namespace AAFwk { +/** + * @class AbilitySchedulerStub + * AbilityScheduler Stub. + */ +class AbilitySchedulerStub : public IRemoteStub { +public: + AbilitySchedulerStub(); + ~AbilitySchedulerStub(); + virtual int OnRemoteRequest( + uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override; + +private: + int AbilityTransactionInner(MessageParcel &data, MessageParcel &reply); + int SendResultInner(MessageParcel &data, MessageParcel &reply); + int ConnectAbilityInner(MessageParcel &data, MessageParcel &reply); + int DisconnectAbilityInner(MessageParcel &data, MessageParcel &reply); + int CommandAbilityInner(MessageParcel &data, MessageParcel &reply); + int SaveAbilityStateInner(MessageParcel &data, MessageParcel &reply); + int RestoreAbilityStateInner(MessageParcel &data, MessageParcel &reply); + int GetFileTypesInner(MessageParcel &data, MessageParcel &reply); + int OpenFileInner(MessageParcel &data, MessageParcel &reply); + int OpenRawFileInner(MessageParcel &data, MessageParcel &reply); + int InsertInner(MessageParcel &data, MessageParcel &reply); + int UpdatetInner(MessageParcel &data, MessageParcel &reply); + int DeleteInner(MessageParcel &data, MessageParcel &reply); + int QueryInner(MessageParcel &data, MessageParcel &reply); + int GetTypeInner(MessageParcel &data, MessageParcel &reply); + int ReloadInner(MessageParcel &data, MessageParcel &reply); + int BatchInsertInner(MessageParcel &data, MessageParcel &reply); + int RegisterObserverInner(MessageParcel &data, MessageParcel &reply); + int UnregisterObserverInner(MessageParcel &data, MessageParcel &reply); + int NotifyChangeInner(MessageParcel &data, MessageParcel &reply); + int NormalizeUriInner(MessageParcel &data, MessageParcel &reply); + int DenormalizeUriInner(MessageParcel &data, MessageParcel &reply); + int UpdateConfigurationInner(MessageParcel &data, MessageParcel &reply); + int ExecuteBatchInner(MessageParcel &data, MessageParcel &reply); + int MutiWinModeChangedInner(MessageParcel &data, MessageParcel &reply); + int TopActiveAbilityChangedInner(MessageParcel &data, MessageParcel &reply); + using RequestFuncType = int (AbilitySchedulerStub::*)(MessageParcel &data, MessageParcel &reply); + std::map requestFuncMap_; +}; + +/** + * @class AbilitySchedulerRecipient + * AbilitySchedulerRecipient notices IRemoteBroker died. + */ +class AbilitySchedulerRecipient : public IRemoteObject::DeathRecipient { +public: + using RemoteDiedHandler = std::function &)>; + + explicit AbilitySchedulerRecipient(RemoteDiedHandler handler); + + virtual ~AbilitySchedulerRecipient(); + + virtual void OnRemoteDied(const wptr &remote); + +private: + RemoteDiedHandler handler_; +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_ABILITY_SCHEDULE_STUB_H diff --git a/tools/services/abilitymgr/include/ability_stack_manager.h b/tools/services/abilitymgr/include/ability_stack_manager.h new file mode 100644 index 00000000000..84bab5fdcb4 --- /dev/null +++ b/tools/services/abilitymgr/include/ability_stack_manager.h @@ -0,0 +1,699 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_ABILITY_STACK_MANAGER_H +#define OHOS_AAFWK_ABILITY_STACK_MANAGER_H + +#include +#include +#include +#include +#include + +#include "ability_info.h" +#include "ability_record.h" +#include "application_info.h" +#include "aafwk_dummy_configuration.h" +#include "mission_record.h" +#include "mission_stack.h" +#include "mission_option.h" +#include "ability_mission_info.h" +#include "lock_mission_container.h" +#include "resume_mission_container.h" +#include "stack_info.h" +#include "power_storage.h" +#include "want.h" + +namespace OHOS { +namespace AAFwk { +enum class SystemWindowMode { + DEFAULT_WINDOW_MODE = 0, + SPLITSCREEN_WINDOW_MODE, + FLOATING_WINDOW_MODE, + FLOATING_AND_SPLITSCREEN_WINDOW_MODE, +}; +/** + * @class AbilityStackManager + * AbilityStackManager provides a facility for managing page ability life cycle. + */ +class AbilityStackManager : public std::enable_shared_from_this { +public: + explicit AbilityStackManager(int userId); + ~AbilityStackManager(); + + /** + * init ability stack manager. + * + */ + void Init(); + + /** + * StartAbility with request. + * + * @param abilityRequest, the request of the service ability to start. + * @return Returns ERR_OK on success, others on failure. + */ + int StartAbility(const AbilityRequest &abilityRequest); + + /** + * TerminateAbility with token and result want. + * + * @param token, the token of service type's ability to terminate. + * @param resultCode, the result code of service type's ability to terminate. + * @param resultWant, the result want for service type's ability to terminate. + * @return Returns ERR_OK on success, others on failure. + */ + int TerminateAbility(const sptr &token, int resultCode, const Want *resultWant); + + /** + * TerminateAbility, terminate the special ability. + * + * @param caller, caller ability record. + * @param requestCode, abililty request code + * @return Returns ERR_OK on success, others on failure. + */ + int TerminateAbility(const std::shared_ptr &caller, int requestCode); + + /** + * get ability stack manager's user id. + * + * @return Returns userId. + */ + int GetAbilityStackManagerUserId() const; + + /** + * get current working mission stack. + * + * @return current mission stack. + */ + std::shared_ptr GetCurrentMissionStack() const + { + return currentMissionStack_; + } + + /** + * get current top ability's token of stack. + * + * @return top ability record's token. + */ + sptr GetCurrentTopAbilityToken(); + + /** + * get the ability record by token. + * + * @param recordId, ability record id. + * @return ability record. + */ + std::shared_ptr GetAbilityRecordById(const int64_t recordId); + + /** + * get the stack by id. + * + * @param recordId, stack id. + * @return MissionStack. + */ + std::shared_ptr GetStackById(int stackId); + + /** + * get current top mission of stack. + * + * @return top mission record. + */ + std::shared_ptr GetTopMissionRecord() const; + + /** + * get the ability record by token. + * + * @param token, the token of ability. + * @return ability record. + */ + std::shared_ptr GetAbilityRecordByToken(const sptr &token); + + /** + * get terminating ability from terminate list. + * + * @param token, the token of ability. + */ + std::shared_ptr GetAbilityFromTerminateList(const sptr &token); + + /** + * get the mission record by record id. + * + * @param id, the record id of mission. + * @return mission record. + */ + std::shared_ptr GetMissionRecordById(int id) const; + + /** + * get the mission record by record name. + * + * @param name, the record name of mission. + * @return mission record. + */ + std::shared_ptr GetMissionRecordByName(std::string name) const; + + /** + * get the mission record by record id from all stacks. + * + * @param id, the record id of mission. + * @return mission record. + */ + std::shared_ptr GetMissionRecordFromAllStacks(int id) const; + + /** + * remove the mission record by record id. + * + * @param id, the record id of mission. + * @return Returns true on success, false on failure. + */ + bool RemoveMissionRecordById(int id); + + /** + * attach ability thread ipc object. + * + * @param scheduler, ability thread ipc object. + * @param token, the token of ability. + * @return Returns ERR_OK on success, others on failure. + */ + int AttachAbilityThread(const sptr &scheduler, const sptr &token); + + /** + * AbilityTransitionDone, ability call this interface after lift cycle was changed. + * + * @param token,.ability's token. + * @param state,.the state of ability lift cycle. + * @return Returns ERR_OK on success, others on failure. + */ + int AbilityTransitionDone(const sptr &token, int state); + + /** + * AddWindowInfo, add windowToken to AbilityRecord. + * + * @param token, the token of the ability. + * @param windowToken, window id of the ability. + */ + void AddWindowInfo(const sptr &token, int32_t windowToken); + + /** + * OnAbilityRequestDone, app manager service call this interface after ability request done. + * + * @param token,ability's token. + * @param state,the state of ability lift cycle. + */ + void OnAbilityRequestDone(const sptr &token, const int32_t state); + + void OnAppStateChanged(const AppInfo &info); + + /** + * Remove the specified mission from the stack by mission id. + * + * @param missionId, target mission id. + * @return Returns ERR_OK on success, others on failure. + */ + int RemoveMissionById(int missionId); + + /** + * Remove the specified mission stack by stack id + * + * @param id. + * @return Returns ERR_OK on success, others on failure. + */ + int RemoveStack(int stackId); + + /** + * move the mission stack to the top. + * + * @param stack, target mission stack. + */ + void MoveMissionStackToTop(const std::shared_ptr &stack); + + int GetMaxHoldMissionsByStackId(int stackId) const; + bool SupportSyncVisualByStackId(int stackId) const; + + void SetMissionStackSetting(const StackSetting &stackSetting); + + /** + * complete ability life cycle . + * + * @param abilityRecord. + */ + void CompleteActive(const std::shared_ptr &abilityRecord); + void CompleteInactive(const std::shared_ptr &abilityRecord); + void CompleteBackground(const std::shared_ptr &abilityRecord); + void CompleteTerminate(const std::shared_ptr &abilityRecord); + + void MoveToBackgroundTask(const std::shared_ptr &abilityRecord); + + /** + * dump ability stack info, about userID, mission stack info, + * mission record info and ability info. + * + * @param info Ability stack info. + * @return Returns ERR_OK on success, others on failure. + */ + void Dump(std::vector &info); + void DumpWaittingAbilityQueue(std::string &result); + void DumpTopAbility(std::vector &info); + void DumpMission(int missionId, std::vector &info); + void DumpStack(int missionStackId, std::vector &info); + void DumpStackList(std::vector &info); + void DumpFocusMap(std::vector &info); + + /** + * get the target mission stack by want info. + * + * @param want , the want for starting ability. + */ + std::shared_ptr GetTargetMissionStack(const AbilityRequest &abilityRequest); + std::shared_ptr GetTargetMissionStackByDefault(const AbilityRequest &abilityRequest); + std::shared_ptr GetTargetMissionStackBySetting(const AbilityRequest &abilityRequest); + + /** + * Obtains information about ability stack that are running on the device. + * + * @param stackInfo Ability stack info. + * @return Returns ERR_OK on success, others on failure. + */ + void GetAllStackInfo(StackInfo &stackInfo); + + /** + * Get the list of the missions that the user has recently launched, + * with the most recent being first and older ones after in order. + * + * @param recentList recent mission info + * @param numMax The maximum number of entries to return in the list. The + * actual number returned may be smaller, depending on how many tasks the + * user has started and the maximum number the system can remember. + * @param falgs Information about what to return. May be any combination + * of {@link #RECENT_WITH_EXCLUDED} and {@link #RECENT_IGNORE_UNAVAILABLE}. + * @return Returns ERR_OK on success, others on failure. + */ + int GetRecentMissions(const int32_t numMax, const int32_t flags, std::vector &recentList); + + /** + * Ask that the mission associated with a given mission ID be moved to the + * front of the stack, so it is now visible to the user. + * + * @param missionId. + * @return Returns ERR_OK on success, others on failure. + */ + int MoveMissionToTop(int32_t missionId); + + /** + * Requires that tasks associated with a given capability token be moved to the background + * + * @param token ability token + * @param nonFirst If nonfirst is false and not the lowest ability of the mission, you cannot move mission to end + * @return Returns ERR_OK on success, others on failure. + */ + int MoveMissionToEnd(const sptr &token, const bool nonFirst); + + int MoveMissionToEndLocked(int missionId); + + /** + * Ability detects death + * + * @param abilityRecord + */ + void OnAbilityDied(std::shared_ptr abilityRecord); + + /** + * Uninstall app + * + * @param bundleName. + */ + void UninstallApp(const std::string &bundleName); + + void OnTimeOut(uint32_t msgId, int64_t eventId); + bool IsFirstInMission(const sptr &token); + bool IsFrontInAllStack(const std::shared_ptr &stack) const; + bool IsTopInMission(const std::shared_ptr &abilityRecord) const; + + /** + * Moving some missions to the specified stack by mission option(Enter splitscreen or floating window mode). + * @param missionOption, target mission option + * @return Returns ERR_OK on success, others on failure. + */ + int MoveMissionToFloatingStack(const MissionOption &missionOption); + int MoveMissionToSplitScreenStack(const MissionOption &missionOption); + + /** + * minimize multiwindow by mission id. + * @param missionId, the id of target mission + * @return Returns ERR_OK on success, others on failure. + */ + int MinimizeMultiWindow(int missionId); + /** + * maximize multiwindow by mission id. + * @param missionId, the id of target mission + * @return Returns ERR_OK on success, others on failure. + */ + int MaximizeMultiWindow(int missionId); + + /** + * Change the focus of ability in the mission stack. + * @param lostToken, the token of lost focus ability + * @param getToken, the token of get focus ability + * @return Returns ERR_OK on success, others on failure. + */ + int ChangeFocusAbility(const sptr &lostFocusToken, const sptr &getFocusToken); + + /** + * get missions info of floating mission stack. + * @param list, mission info. + * @return Returns ERR_OK on success, others on failure. + */ + int GetFloatingMissions(std::vector &list); + + /** + * close multiwindow by mission id. + * @param missionId, the id of target mission. + * @return Returns ERR_OK on success, others on failure. + */ + int CloseMultiWindow(int missionId); + + void JudgingIsRemoveMultiScreenStack(std::shared_ptr &stack); + + /** + * Save the top ability States and move them to the background + * @return Returns ERR_OK on success, others on failure. + */ + int PowerOff(); + + /** + * Restore the state before top ability poweroff + * @return Returns ERR_OK on success, others on failure. + */ + int PowerOn(); + + int StartLockMission(int uid, int missionId, bool isSystemApp, int isLock); + int SetMissionDescriptionInfo( + const std::shared_ptr &abilityRecord, const MissionDescriptionInfo &description); + int GetMissionLockModeState(); + + /** + * update configuration to ability + * @return Returns ERR_OK on success, others on failure. + */ + int UpdateConfiguration(const DummyConfiguration &config); + + void RestartAbility(const std::shared_ptr abilityRecord); + +private: + /** + * dispatch ability life cycle . + * + * @param abilityRecord. + * @param state. + */ + int DispatchState(const std::shared_ptr &abilityRecord, int state); + int DispatchActive(const std::shared_ptr &abilityRecord, int state); + int DispatchInactive(const std::shared_ptr &abilityRecord, int state); + int DispatchBackground(const std::shared_ptr &abilityRecord, int state); + int DispatchTerminate(const std::shared_ptr &abilityRecord, int state); + int DispatchLifecycle(const std::shared_ptr &lastTopAbility, + const std::shared_ptr ¤tTopAbility, bool isTopFullScreen = false); + void ContinueLifecycle(); + + /** + * get current top ability of stack. + * + * @return top ability record. + */ + std::shared_ptr GetCurrentTopAbility() const; + + /** + * StartAbilityLocked. + * + * @param currentTopAbilityRecord, current top ability. + * @param abilityRequest the request of the ability to start. + * @return Returns ERR_OK on success, others on failure. + */ + int StartAbilityLocked( + const std::shared_ptr ¤tTopAbility, const AbilityRequest &abilityRequest); + + int StartAbilityAsSpecialLocked( + const std::shared_ptr ¤tTopAbility, const AbilityRequest &abilityRequest); + + /** + * TerminateAbilityLocked. + * + * @param abilityRecord, target ability. + * @param resultCode the result code of the ability to terminate. + * @param resultWant the result Want of the ability to terminate. + * @return Returns ERR_OK on success, others on failure. + */ + int TerminateAbilityLocked( + const std::shared_ptr &abilityRecord, int resultCode, const Want *resultWant); + + /** + * Remove the specified mission from the stack by mission id. + * + * @param missionId, target mission id. + * @return Returns ERR_OK on success, others on failure. + */ + int RemoveMissionByIdLocked(int missionId); + + /** + * remove terminating ability from stack. + * + * @param abilityRecord, target ability. + */ + void RemoveTerminatingAbility(const std::shared_ptr &abilityRecord); + + /** + * push waitting ability to queue. + * + * @param abilityRequest, the request of ability. + */ + void EnqueueWaittingAbility(const AbilityRequest &abilityRequest); + + /** + * start waitting ability. + */ + void StartWaittingAbility(); + + /** + * get tartget ability and mission by request and top ability. + * + * @param abilityRequest, the request of ability. + * @param currentTopAbility, top ability. + * @param tragetAbilityRecord, out param. + * @param targetMissionRecord, out param. + */ + void GetMissionRecordAndAbilityRecord(const AbilityRequest &abilityRequest, + const std::shared_ptr ¤tTopAbility, std::shared_ptr &tragetAbilityRecord, + std::shared_ptr &targetMissionRecord); + + /** + * check wheather the ability is launcher. + * + * @param abilityRequest, the abilityRequest fot starting ability. + * @return Returns true on success, false on failure. + */ + bool IsLauncherAbility(const AbilityRequest &abilityRequest) const; + + /** + * check wheather the mission has launcher ability. + * + * @param id, mission id. + * @return Returns true on success, false on failure. + */ + bool IsLauncherMission(int id); + + /** + * Get the list of the missions that the user has recently launched, + * with the most recent being first and older ones after in order. + * + * @param recentList recent mission info + * @param numMax The maximum number of entries to return in the list. The + * actual number returned may be smaller, depending on how many tasks the + * user has started and the maximum number the system can remember. + * @param falgs Information about what to return. May be any combination + * of {@link #RECENT_WITH_EXCLUDED} and {@link #RECENT_IGNORE_UNAVAILABLE}. + * @return Returns ERR_OK on success, others on failure. + */ + int GetRecentMissionsLocked(const int32_t numMax, const int32_t flags, std::vector &recentList); + + void CreateRecentMissionInfo(const MissionRecordInfo &mission, AbilityMissionInfo &recentMissionInfo); + + /** + * Ask that the mission associated with a given mission ID be moved to the + * front of the stack, so it is now visible to the user. + * + * @param missionId. + * @return Returns ERR_OK on success, others on failure. + */ + int MoveMissionToTopLocked(int32_t missionId); + + /** + * Requires that tasks associated with a given capability token be moved to the background + * + * @param token ability token + * @param nonFirst If nonfirst is false and not the lowest ability of the mission, you cannot move mission to end + * @return Returns ERR_OK on success, others on failure. + */ + int MoveMissionToEndLocked(const sptr &token, const bool nonFirst); + + /** + * Remove the specified mission stack by stack id + * + * @param id. + * @return Returns ERR_OK on success, others on failure. + */ + int RemoveStackLocked(int stackId); + + /** + * Force return to launcher + */ + void BackToLauncher(); + void DelayedStartLauncher(); + + /** + * Ability from launcher stack detects death + * + * @param abilityRecord + */ + void OnAbilityDiedByLauncher(std::shared_ptr abilityRecord); + + /** + * Ability from default stack detects death + * + * @param abilityRecord + */ + void OnAbilityDiedByDefault(std::shared_ptr abilityRecord); + + /** + * Add uninstall tags to ability + * + * @param bundleName + */ + void AddUninstallTags(const std::string &bundleName); + + /** + * Get target record by start mode. + */ + void GetRecordBySingleton(const AbilityRequest &abilityRequest, + const std::shared_ptr ¤tTopAbility, std::shared_ptr &targetAbilityRecord, + std::shared_ptr &targetMissionRecord); + + void GetRecordByStandard(const AbilityRequest &abilityRequest, + const std::shared_ptr ¤tTopAbility, std::shared_ptr &targetAbilityRecord, + std::shared_ptr &targetMissionRecord); + + /** + * Get root ability from launcher mission stack. + */ + std::shared_ptr GetLauncherRootAbility() const; + + /** + * Get ability record by event id. + * @param eventId + * @return Returns target record. + */ + std::shared_ptr GetAbilityRecordByEventId(int64_t eventId) const; + + /** + * Get or Create mission stack by stack id, + * @param stackId, target stack id + * @param isCreateFlag, if the stack is not exist, decide whether or not to create a new mission stack, + * default is fasle. + * @return Returns target missionStack. + */ + std::shared_ptr GetOrCreateMissionStack(int stackId, bool isCreateFlag = false); + + /** + * Moving some missions to the specified stack by mission option(Enter splitscreen or floating window mode). + * @param missionOption, target mission option + * @return Returns ERR_OK on success, others on failure. + */ + int MoveMissionsToStackLocked(const std::list &missionOptions); + int CheckMultiWindowCondition(const std::list &missionOptions) const; + int CheckMultiWindowCondition( + const std::shared_ptr ¤tTopAbility, const AbilityRequest &abilityRequest) const; + bool CheckMissionStackWillOverflow(const std::list &missionOptions) const; + int CompleteMoveMissionToStack( + const std::shared_ptr &missionRecord, const std::shared_ptr &stack); + int CompleteMissionMoving(std::shared_ptr &missionRecord, int stackId); + SystemWindowMode JudgingTargetSystemWindowMode(AbilityWindowConfiguration config) const; + SystemWindowMode GetTargetSystemWindowMode(const SystemWindowMode &willWinMode); + int JudgingTargetStackId(AbilityWindowConfiguration config) const; + int StartAbilityLifeCycle(std::shared_ptr lastTopAbility, + std::shared_ptr currentTopAbility, std::shared_ptr targetAbility); + + void ActiveTopAbility(const std::shared_ptr &abilityRecord); + void MoveMissionAndAbility(const std::shared_ptr ¤tTopAbility, + std::shared_ptr &targetAbilityRecord, std::shared_ptr &targetMissionRecord); + int PowerOffLocked(); + int PowerOnLocked(); + + bool CheckLockMissionCondition( + int uid, int missionId, int isLock, bool isSystemApp, std::shared_ptr &mission, int &lockUid); + bool CanStartInLockMissionState( + const AbilityRequest &abilityRequest, const std::shared_ptr ¤tTopAbility) const; + bool CanStopInLockMissionState(const std::shared_ptr &terminateAbility) const; + void SendUnlockMissionMessage(); + std::shared_ptr GetTopFullScreenStack(); + bool IsFullScreenStack(int stackId) const; + + /** + * minimize multiwindow by mission id. + * @param missionId, the id of target mission + * @return Returns ERR_OK on success, others on failure. + */ + int MinimizeMultiWindowLocked(int missionId); + int ChangeFocusAbilityLocked(const std::shared_ptr &targetAbility); + + void NotifyWindowModeChanged(const SystemWindowMode &windowMode); + + int ProcessConfigurationChange(); + + void UpdateFocusAbilityRecord( + int displayId, const std::shared_ptr &focusAbility, bool isNotify = false); + void UpdateFocusAbilityRecord(const std::shared_ptr &abilityRecord, bool isNotify = false); + void CheckMissionRecordIsResume(const std::shared_ptr &mission); + int ChangedPowerStorageAbilityToActive(std::shared_ptr &powerStorage); + +private: + static constexpr int MIN_MISSION_STACK_ID = LAUNCHER_MISSION_STACK_ID; + static constexpr int MAX_MISSION_STACK_ID = FLOATING_MISSION_STACK_ID; + static constexpr int MAX_CAN_MOVE_MISSIONS = 2; + + int userId_; + bool powerOffing_ = false; + std::recursive_mutex stackLock_; + std::shared_ptr launcherMissionStack_; + std::shared_ptr defaultMissionStack_; + std::shared_ptr currentMissionStack_; + std::shared_ptr lastMissionStack_; + std::list> missionStackList_; + std::list> terminateAbilityRecordList_; // abilities on terminating put in this + // list. + std::queue waittingAbilityQueue_; + std::list> focusWaitingList_; + std::shared_ptr powerStorage_; + // find AbilityRecord by windowToken. one windowToken has one and only one AbilityRecord. + std::unordered_map> windowTokenToAbilityMap_; + std::shared_ptr lockMissionContainer_ = nullptr; + SystemWindowMode curSysWindowMode_ = SystemWindowMode::DEFAULT_WINDOW_MODE; + bool isMultiWinMoving_ = false; + std::vector stackSettings_; + std::map> focusAbilityRecordMap_; // abilities has been focused , + // key : display id, value: focused ability + std::shared_ptr resumeMissionContainer_; +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_ABILITY_STACK_MANAGER_H diff --git a/tools/services/abilitymgr/include/ability_token_interface.h b/tools/services/abilitymgr/include/ability_token_interface.h new file mode 100644 index 00000000000..b329d481b25 --- /dev/null +++ b/tools/services/abilitymgr/include/ability_token_interface.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_ABILITY_TOKEN_INTERFACE_H +#define OHOS_AAFWK_ABILITY_TOKEN_INTERFACE_H + +#include + +namespace OHOS { +namespace AAFwk { +/** + * @class IAbilityToken + * IAbilityToken is identification of ability and used to interact with kit and wms. + */ +class IAbilityToken : public OHOS::IRemoteBroker { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"ohos.aafwk.AbilityToken"); +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_ABILITY_TOKEN_INTERFACE_H diff --git a/tools/services/abilitymgr/include/ability_token_proxy.h b/tools/services/abilitymgr/include/ability_token_proxy.h new file mode 100644 index 00000000000..0cb4d73b8a8 --- /dev/null +++ b/tools/services/abilitymgr/include/ability_token_proxy.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_ABILITY_TOKEN_PROXY_H +#define OHOS_AAFWK_ABILITY_TOKEN_PROXY_H + +#include "ability_token_interface.h" + +#include "iremote_proxy.h" + +namespace OHOS { +namespace AAFwk { +/** + * @class AbilityTokenProxy + * AbilityToken proxy. + */ +class AbilityTokenProxy : public IRemoteProxy { +public: + explicit AbilityTokenProxy(const sptr &impl) : IRemoteProxy(impl) + {} + virtual ~AbilityTokenProxy() + {} + +private: + static inline BrokerDelegator delegator_; +}; +} // namespace AAFwk +} // namespace OHOS + +#endif // OHOS_AAFWK_ABILITY_TOKEN_PROXY_H diff --git a/tools/services/abilitymgr/include/ability_token_stub.h b/tools/services/abilitymgr/include/ability_token_stub.h new file mode 100644 index 00000000000..b2f4ef0a7cc --- /dev/null +++ b/tools/services/abilitymgr/include/ability_token_stub.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_ABILITY_TOKEN_STUB_H +#define OHOS_AAFWK_ABILITY_TOKEN_STUB_H + +#include "ability_token_interface.h" + +#include +#include + +namespace OHOS { +namespace AAFwk { +/** + * @class AbilityTokenStub + * AbilityToken stub. + */ +class AbilityTokenStub : public IRemoteStub { +public: + DECLARE_INTERFACE_DESCRIPTOR(u""); + AbilityTokenStub(); + + virtual ~AbilityTokenStub(); +}; + +/** + * @class AbilityTokenRecipient + * AbilityTokenRecipient notice IRemoteBroker died. + */ +class AbilityTokenRecipient : public IRemoteObject::DeathRecipient { +public: + AbilityTokenRecipient() + {} + + virtual ~AbilityTokenRecipient() + {} + + virtual void OnRemoteDied(const wptr &remote); +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_ABILITY_TOKEN_STUB_H diff --git a/tools/services/abilitymgr/include/ability_util.h b/tools/services/abilitymgr/include/ability_util.h new file mode 100644 index 00000000000..a090a1eb267 --- /dev/null +++ b/tools/services/abilitymgr/include/ability_util.h @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_ABILITY_UTIL_H +#define OHOS_AAFWK_ABILITY_UTIL_H + +#include +#include "hilog_wrapper.h" +#include "ability_config.h" +#include "ipc_skeleton.h" +#include "sa_mgr_client.h" +#include "bundlemgr/bundle_mgr_interface.h" +#include "system_ability_definition.h" +#include "ability_manager_errors.h" + +namespace OHOS { +namespace AAFwk { +namespace AbilityUtil { +constexpr int32_t SYSTEM_UID = 1000; +constexpr int32_t ROOT_UID = 0; + +#define CHECK_POINTER_CONTINUE(object) \ + if (!object) { \ + HILOG_ERROR("pointer is nullptr, %{public}s, %{public}d", __func__, __LINE__); \ + continue; \ + } + +#define CHECK_POINTER_IS_NULLPTR(object) \ + if (object == nullptr) { \ + HILOG_ERROR("pointer is nullptr."); \ + return; \ + } + +#define CHECK_POINTER(object) \ + if (!object) { \ + HILOG_ERROR("pointer is nullptr."); \ + return; \ + } + +#define CHECK_POINTER_LOG(object, log) \ + if (!object) { \ + HILOG_ERROR("%{public}s:", log); \ + return; \ + } + +#define CHECK_POINTER_AND_RETURN(object, value) \ + if (!object) { \ + HILOG_ERROR("pointer is nullptr."); \ + return value; \ + } + +#define CHECK_POINTER_AND_RETURN_LOG(object, value, log) \ + if (!object) { \ + HILOG_ERROR("%{public}s:", log); \ + return value; \ + } + +#define CHECK_POINTER_RETURN_BOOL(object) \ + if (!object) { \ + HILOG_ERROR("pointer is nullptr."); \ + return false; \ + } + +#define CHECK_RET_RETURN_RET(object, log) \ + if (object != ERR_OK) { \ + HILOG_ERROR("%{public}s, ret : %{public}d", log, object); \ + return object; \ + } + +#define CHECK_TRUE_RETURN_RET(object, value, log) \ + if (object) { \ + HILOG_WARN("%{public}s", log); \ + return value; \ + } + +[[maybe_unused]] static bool IsSystemDialogAbility(const std::string &bundleName, const std::string &abilityName) +{ + if (abilityName == AbilityConfig::SYSTEM_DIALOG_NAME && bundleName == AbilityConfig::SYSTEM_UI_BUNDLE_NAME) { + return true; + } + + if (abilityName == AbilityConfig::DEVICE_MANAGER_NAME && bundleName == AbilityConfig::DEVICE_MANAGER_BUNDLE_NAME) { + return true; + } + + return false; +} + +[[maybe_unused]] static std::string ConvertBundleNameSingleton(const std::string &bundleName, const std::string &name) +{ + std::string strName = + AbilityConfig::MISSION_NAME_MARK_HEAD + bundleName + AbilityConfig::MISSION_NAME_SEPARATOR + name; + return strName; +} + +static constexpr int64_t NANOSECONDS = 1000000000; // NANOSECONDS mean 10^9 nano second +static constexpr int64_t MICROSECONDS = 1000000; // MICROSECONDS mean 10^6 millias second +[[maybe_unused]] static int64_t SystemTimeMillis() +{ + struct timespec t; + t.tv_sec = 0; + t.tv_nsec = 0; + clock_gettime(CLOCK_MONOTONIC, &t); + return (int64_t)((t.tv_sec) * NANOSECONDS + t.tv_nsec) / MICROSECONDS; +} + +[[maybe_unused]] static int64_t UTCTimeSeconds() +{ + struct timespec t; + t.tv_sec = 0; + t.tv_nsec = 0; + clock_gettime(CLOCK_REALTIME, &t); + return (int64_t)(t.tv_sec); +} + +static sptr GetBundleManager() +{ + auto bundleObj = + OHOS::DelayedSingleton::GetInstance()->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID); + if (bundleObj == nullptr) { + HILOG_ERROR("failed to get bundle manager service"); + return nullptr; + } + return iface_cast(bundleObj); +} + +[[maybe_unused]] static int JudgeAbilityVisibleControl(const AppExecFwk::AbilityInfo &abilityInfo, int callerUid = -1) +{ + HILOG_DEBUG("%{public}s begin", __func__); + if (!abilityInfo.visible) { + HILOG_DEBUG("ability visible is false"); + if (callerUid == -1) { + callerUid = IPCSkeleton::GetCallingUid(); + } + if (ROOT_UID == callerUid) { + HILOG_ERROR("uid is root,ability cannot be start when the visible is false"); + return ABILITY_VISIBLE_FALSE_DENY_REQUEST; + } + auto bms = GetBundleManager(); + CHECK_POINTER_AND_RETURN(bms, GET_ABILITY_SERVICE_FAILED); + auto isSystemApp = bms->CheckIsSystemAppByUid(callerUid); + if (callerUid != SYSTEM_UID && !isSystemApp) { + HILOG_DEBUG("caller is not systemApp or system"); + std::string bundleName; + bool result = bms->GetBundleNameForUid(callerUid, bundleName); + if (!result) { + HILOG_ERROR("GetBundleNameForUid fail"); + return ABILITY_VISIBLE_FALSE_DENY_REQUEST; + } + if (bundleName != abilityInfo.bundleName) { + HILOG_ERROR("caller ability bundlename not equal abilityInfo.bundleName bundleName: %{public}s " + "abilityInfo.bundleName: %{public}s", + bundleName.c_str(), + abilityInfo.bundleName.c_str()); + return ABILITY_VISIBLE_FALSE_DENY_REQUEST; + } + } + } + HILOG_DEBUG("%{public}s end", __func__); + return ERR_OK; +} +} // namespace AbilityUtil +} // namespace AAFwk +} // namespace OHOS + +#endif // OHOS_AAFWK_ABILITY_UTIL_H diff --git a/tools/services/abilitymgr/include/ams_configuration_parameter.h b/tools/services/abilitymgr/include/ams_configuration_parameter.h new file mode 100644 index 00000000000..b3c48716802 --- /dev/null +++ b/tools/services/abilitymgr/include/ams_configuration_parameter.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_AMS_CONFIGURATION_PARAMETER_H +#define OHOS_AAFWK_AMS_CONFIGURATION_PARAMETER_H + +#include +#include + +namespace OHOS { +namespace AAFwk { +namespace AmsConfig { +const std::string AMS_CONFIG_FILE_PATH {"/system/etc/ams_service_config.json"}; +const std::string SERVICE_ITEM_AMS {"service_startup_config"}; +const std::string STARTUP_LAUNCHER {"startup_launcher"}; +const std::string STARTUP_STATUS_BAR {"startup_system_ui_status_bar"}; +const std::string STARTUP_NAVIGATION_BAR {"startup_system_ui_navigation_bar"}; +} // namespace AmsConfig + +enum class SatrtUiMode { STATUSBAR = 1, NAVIGATIONBAR = 2, STARTUIBOTH = 3 }; + +class AmsConfigurationParameter final { +public: + AmsConfigurationParameter() = default; + ~AmsConfigurationParameter() = default; + /** + * return true : ams no config file + * return false : ams have config file + */ + bool NonConfigFile() const; + /** + * return true : ams can start launcher + * return false : ams do not start launcher + */ + bool GetStartLauncherState() const; + /** + * return true : ams can start system ui status bar + * return false : ams do not start system ui status bar + */ + bool GetStatusBarState() const; + /** + * return true : ams can start system ui navigation bar + * return false : ams do not start system ui navigation bar + */ + bool GetNavigationBarState() const; + /** + * Get profile information + */ + void Parse(); + + enum { READ_OK = 0, READ_FAIL = 1, READ_JSON_FAIL = 2 }; + +private: + /** + * Read the configuration file of ams + * + */ + int LoadAmsConfiguration(const std::string &filePath); + +private: + bool nonConfigFile {false}; + bool canStartLauncher {false}; + bool canStartUiStatusBar {false}; + bool canStartUiNavigationBar {false}; +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_AMS_CONFIGURATION_PARAMETER_H diff --git a/tools/services/abilitymgr/include/app_scheduler.h b/tools/services/abilitymgr/include/app_scheduler.h new file mode 100644 index 00000000000..e3e01140edf --- /dev/null +++ b/tools/services/abilitymgr/include/app_scheduler.h @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_APP_SCHEDULER_H +#define OHOS_AAFWK_APP_SCHEDULER_H + +#include +#include + +#include "ability_info.h" +// #include "app_process_data.h" +#include "appmgr/app_mgr_client.h" +#include "appmgr/app_state_callback_host.h" +#include "application_info.h" +#include "iremote_object.h" +#include "refbase.h" +#include "singleton.h" + +namespace OHOS { +namespace AAFwk { +/** + * @enum AppAbilityState + * AppAbilityState defines the life cycle state of app ability. + */ +enum class AppAbilityState { + ABILITY_STATE_UNDEFINED = 0, + ABILITY_STATE_FOREGROUND, + ABILITY_STATE_BACKGROUND, + ABILITY_STATE_END, +}; + +enum class AppState { + BEGIN = 0, + READY, + FOREGROUND, + BACKGROUND, + SUSPENDED, + TERMINATED, + END, +}; + +struct AppInfo { + std::string appName; + std::string processName; + int32_t uid; + AppState state; +}; +/** + * @class AppStateCallback + * AppStateCallback. + */ +class AppStateCallback { +public: + AppStateCallback() + {} + virtual ~AppStateCallback() + {} + + virtual void OnAbilityRequestDone(const sptr &token, const int32_t state) = 0; + + virtual void OnAppStateChanged(const AppInfo &info) = 0; +}; + +/** + * @class AppScheduler + * AppScheduler , access app manager service. + */ +class AppScheduler : virtual RefBase, public AppExecFwk::AppStateCallbackHost { + + DECLARE_DELAYED_SINGLETON(AppScheduler) +public: + /** + * init app scheduler. + * @param callback, app state call back. + * @return true on success ,false on failure. + */ + bool Init(const std::weak_ptr &callback); + + /** + * load ability with token, ability info and application info. + * + * @param token, the token of ability. + * @param preToken, the token of ability's caller. + * @param abilityinfo, ability info. + * @param application, application info. + * @return true on success ,false on failure. + */ + int LoadAbility(const sptr &token, const sptr &preToken, + const AppExecFwk::AbilityInfo &abilityinfo, const AppExecFwk::ApplicationInfo &application); + + /** + * terminate ability with token. + * + * @param token, the token of ability. + * @return true on success ,false on failure. + */ + int TerminateAbility(const sptr &token); + + /** + * move ability to forground. + * + * @param token, the token of ability. + */ + void MoveToForground(const sptr &token); + + /** + * move ability to background. + * + * @param token, the token of ability. + */ + void MoveToBackground(const sptr &token); + + /** + * AbilityBehaviorAnalysis, ability behavior analysis assistant process optimization. + * + * @param token, the unique identification to start the ability. + * @param preToken, the unique identification to call the ability. + * @param visibility, the visibility information about windows info. + * @param perceptibility, the Perceptibility information about windows info. + * @param connectionState, the service ability connection state. + * @return Returns RESULT_OK on success, others on failure. + */ + void AbilityBehaviorAnalysis(const sptr &token, const sptr &preToken, + const int32_t visibility, const int32_t perceptibility, const int32_t connectionState); + + /** + * KillProcessByAbilityToken, call KillProcessByAbilityToken() through proxy object, + * kill the process by ability token. + * + * @param token, the unique identification to the ability. + */ + void KillProcessByAbilityToken(const sptr &token); + + /** + * convert ability state to app ability state. + * + * @param state, the state of ability. + */ + AppAbilityState ConvertToAppAbilityState(const int32_t state); + + /** + * get ability state. + * + * @return state, the state of app ability. + */ + AppAbilityState GetAbilityState() const; + + /** + * kill the application + * + * @param bundleName. + */ + int KillApplication(const std::string &bundleName); + + void AttachTimeOut(const sptr &token); + + /** + * Checks whether a specified permission has been granted to the process identified by pid and uid + * + * @param permission Indicates the permission to check. + * @param pid Indicates the ID of the process to check. + * @param uid Indicates the UID of the process to check. + * @param message Describe success or failure + * + * @return Returns ERR_OK on success, others on failure. + */ + int CompelVerifyPermission(const std::string &permission, int pid, int uid, std::string &message); + +protected: + /** + * OnAbilityRequestDone, app manager service call this interface after ability request done. + * + * @param token,ability's token. + * @param state,the state of ability lift cycle. + */ + virtual void OnAbilityRequestDone(const sptr &token, const AppExecFwk::AbilityState state) override; + + /** + * Application state changed callback. + * + * @param appProcessData Process data + */ + virtual void OnAppStateChanged(const AppExecFwk::AppProcessData &appData) override; + +private: + std::weak_ptr callback_; + std::unique_ptr appMgrClient_; + AppAbilityState appAbilityState_ = AppAbilityState::ABILITY_STATE_UNDEFINED; +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_APP_SCHEDULER_H diff --git a/tools/services/abilitymgr/include/configuration_holder.h b/tools/services/abilitymgr/include/configuration_holder.h new file mode 100644 index 00000000000..35aed5e3726 --- /dev/null +++ b/tools/services/abilitymgr/include/configuration_holder.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef OHOS_AAFWK_CONFIGURATION_HOLDER_H +#define OHOS_AAFWK_CONFIGURATION_HOLDER_H + +#include "aafwk_dummy_configuration.h" + +#include + +namespace OHOS { +namespace AAFwk { +/** + * @class AbilityRecord + * AbilityRecord records ability info and states and used to schedule ability life. + */ +class ConfigurationHolder { +public: + ConfigurationHolder() = default; + virtual ~ConfigurationHolder() = default; + + void UpdateConfiguration(const std::shared_ptr config); + std::shared_ptr GetConfiguration() const; + bool ProcessConfigurationChange(); + bool ForceProcessConfigurationChange(const std::shared_ptr &config); + +protected: + virtual bool OnConfigurationChanged(const DummyConfiguration &config, unsigned int configChanges); + virtual std::shared_ptr GetParent() = 0; + virtual unsigned int GetChildSize() = 0; + virtual std::shared_ptr FindChild(unsigned int index) = 0; + + static constexpr unsigned int CHANGE_CONFIG_ALL_CHANGED = 0xFFFFFFFF; + static constexpr unsigned int CHANGE_CONFIG_NONE = 0x00000000; + static constexpr unsigned int CHANGE_CONFIG_LOCALE = 0x00000001; + static constexpr unsigned int CHANGE_CONFIG_LAYOUT = 0x00000002; + static constexpr unsigned int CHANGE_CONFIG_FONTSIZE = 0x00000004; + static constexpr unsigned int CHANGE_CONFIG_ORIENTATION = 0x00000008; + static constexpr unsigned int CHANGE_CONFIG_DENSITY = 0x00000010; + +private: + void DealUpdateConfiguration(); + bool ProcessConfigurationChangeInner(const std::shared_ptr &config); + +private: + std::shared_ptr baseConfiguration_ = nullptr; +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_CONFIGURATION_HOLDER_H \ No newline at end of file diff --git a/tools/services/abilitymgr/include/connection_record.h b/tools/services/abilitymgr/include/connection_record.h new file mode 100644 index 00000000000..78894354ecc --- /dev/null +++ b/tools/services/abilitymgr/include/connection_record.h @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_CONNECTION_RECORD_H +#define OHOS_AAFWK_CONNECTION_RECORD_H + +#include "ability_connect_callback_interface.h" +#include "ability_record.h" +#include "nocopyable.h" + +namespace OHOS { +namespace AAFwk { +/** + * @enum ConnectionState + * ConnectionState defines the state of connect ability. + */ +enum class ConnectionState { INIT, CONNECTING, CONNECTED, DISCONNECTING, DISCONNECTED }; +/** + * @class ConnectionRecord + * ConnectionRecord,This class is used to record information about a connection. + */ +class ConnectionRecord : public std::enable_shared_from_this { +public: + ConnectionRecord(const sptr &callerToken, const std::shared_ptr &targetService, + const sptr &connCallback); + virtual ~ConnectionRecord(); + + /** + * create a connection record by caller token , service ability and call back ipc object. + * + * @param callerToken, the token of caller ability. + * @param targetService, target service ability. + * @param callback, call back (ipc object). + * @return Return the connect record. + */ + static std::shared_ptr CreateConnectionRecord(const sptr &callerToken, + const std::shared_ptr &targetService, const sptr &connCallback); + + /** + * set the connect state. + * + * @param state, target connection state. + */ + void SetConnectState(const ConnectionState &state); + + /** + * get the connect state. + * + * @return state, target connection state. + */ + ConnectionState GetConnectState() const; + + /** + * get the token of the ability. + * + * @return token. + */ + sptr GetToken() const; + + /** + * get the ability record from connection record. + * + * @return AbilityRecord. + */ + std::shared_ptr GetAbilityRecord() const; + + sptr GetAbilityConnectCallback() const; + + /** + * disconnect the service ability. + * + * @return Returns ERR_OK on success, others on failure. + */ + int DisconnectAbility(); + + /** + * force to disconnect time out event. + * + */ + void DisconnectTimeout(); + + /** + * complete connect ability and invoke callback. + * + */ + void CompleteConnect(int resultCode); + + /** + * complete disconnect ability and invoke callback. + * + */ + void CompleteDisconnect(int resultCode); + + /** + * scheduler target service disconnect done. + * + */ + void ScheduleDisconnectAbilityDone(); + + /** + * scheduler target service Connect done. + * + */ + void ScheduleConnectAbilityDone(); + + /** + * get connection record id. + * + */ + inline int GetRecordId() const + { + return recordId_; + } + + void ClearConnCallBack(); + + std::string ConvertConnectionState(const ConnectionState &state) const; + + void Dump(std::vector &info) const; + +private: + static int64_t connectRecordId; + int recordId_; // record id + ConnectionState state_; // service connection state + sptr callerToken_; // from:caller token + std::shared_ptr targetService_; // target:service need to be connected + sptr connCallback_; // service connect callback + + DISALLOW_COPY_AND_MOVE(ConnectionRecord); +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_CONNECTION_RECORD_H \ No newline at end of file diff --git a/tools/services/abilitymgr/include/data_ability_caller_recipient.h b/tools/services/abilitymgr/include/data_ability_caller_recipient.h new file mode 100644 index 00000000000..5a7768a2534 --- /dev/null +++ b/tools/services/abilitymgr/include/data_ability_caller_recipient.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_OS_AAFWK_DATAABILITY_CALLER_RECIPIENT_H +#define OHOS_OS_AAFWK_DATAABILITY_CALLER_RECIPIENT_H + +#include +#include +#include + +namespace OHOS { +namespace AAFwk { +class DataAbilityCallerRecipient : public IRemoteObject::DeathRecipient { +public: + using RemoteDiedHandler = std::function &)>; + + explicit DataAbilityCallerRecipient(RemoteDiedHandler handler); + + virtual ~DataAbilityCallerRecipient(); + + virtual void OnRemoteDied(const wptr &remote); + +private: + RemoteDiedHandler handler_; +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_OS_AAFWK_DATAABILITY_CALLER_RECIPIENT_H \ No newline at end of file diff --git a/tools/services/abilitymgr/include/data_ability_manager.h b/tools/services/abilitymgr/include/data_ability_manager.h new file mode 100644 index 00000000000..b3286f03df1 --- /dev/null +++ b/tools/services/abilitymgr/include/data_ability_manager.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_DATA_ABILITY_MANAGER_H +#define OHOS_AAFWK_DATA_ABILITY_MANAGER_H + +#include +#include +#include +#include + +#include "ability_record.h" +#include "data_ability_record.h" +#include "nocopyable.h" + +namespace OHOS { +namespace AAFwk { +class DataAbilityManager : public NoCopyable { +public: + DataAbilityManager(); + virtual ~DataAbilityManager(); + +public: + sptr Acquire( + const AbilityRequest &abilityRequest, bool tryBind, const sptr &client, bool isSystem); + int Release(const sptr &scheduler, const sptr &client, bool isSystem); + int AttachAbilityThread(const sptr &scheduler, const sptr &token); + int AbilityTransitionDone(const sptr &token, int state); + void OnAbilityRequestDone(const sptr &token, const int32_t state); + void OnAppStateChanged(const AppInfo &info); + void OnAbilityDied(const std::shared_ptr &abilityRecord); + std::shared_ptr GetAbilityRecordById(int64_t id); + std::shared_ptr GetAbilityRecordByToken(const sptr &token); + std::shared_ptr GetAbilityRecordByScheduler(const sptr &scheduler); + void Dump(const char *func, int line); + void DumpState(std::vector &info, const std::string &args = "") const; + +private: + using DataAbilityRecordPtr = std::shared_ptr; + using DataAbilityRecordPtrMap = std::map; + +private: + DataAbilityRecordPtr LoadLocked(const std::string &name, const AbilityRequest &req); + void DumpLocked(const char *func, int line); + +private: + std::mutex mutex_; + DataAbilityRecordPtrMap dataAbilityRecordsLoaded_; + DataAbilityRecordPtrMap dataAbilityRecordsLoading_; +}; +} // namespace AAFwk +} // namespace OHOS + +#endif // OHOS_AAFWK_DATA_ABILITY_MANAGER_H diff --git a/tools/services/abilitymgr/include/data_ability_record.h b/tools/services/abilitymgr/include/data_ability_record.h new file mode 100644 index 00000000000..76673d73d64 --- /dev/null +++ b/tools/services/abilitymgr/include/data_ability_record.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_DATA_ABILITY_RECORD_H +#define OHOS_AAFWK_DATA_ABILITY_RECORD_H + +#include +#include +#include +#include +#include +#include + +#include "ability_record.h" +#include "data_ability_caller_recipient.h" + +namespace OHOS { +namespace AAFwk { +class DataAbilityRecord { +public: + explicit DataAbilityRecord(const AbilityRequest &req); + virtual ~DataAbilityRecord(); + +public: + int StartLoading(); + int WaitForLoaded(std::mutex &mutex, const std::chrono::system_clock::duration &timeout); + sptr GetScheduler(); + int Attach(const sptr &scheduler); + int OnTransitionDone(int state); + int AddClient(const sptr &client, bool tryBind, bool isSystem); + int RemoveClient(const sptr &client, bool isSystem); + int RemoveClients(const std::shared_ptr &client = nullptr); + size_t GetClientCount(const sptr &client = nullptr) const; + int KillBoundClientProcesses(); + const AbilityRequest &GetRequest() const; + std::shared_ptr GetAbilityRecord(); + sptr GetToken(); + void Dump() const; + void Dump(std::vector &info) const; + +private: + using IRemoteObjectPtr = sptr; + using AbilityRecordPtr = std::shared_ptr; + + struct ClientInfo { + IRemoteObjectPtr client; + bool tryBind; + bool isSystem; + }; + void OnSchedulerDied(const wptr &remote); + +private: + std::condition_variable_any loadedCond_{}; + AbilityRequest request_{}; + AbilityRecordPtr ability_{}; + sptr scheduler_{}; + std::list clients_{}; + sptr callerDeathRecipient_; // caller binderDied Recipient +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_DATA_ABILITY_RECORD_H diff --git a/tools/services/abilitymgr/include/kernal_system_app_manager.h b/tools/services/abilitymgr/include/kernal_system_app_manager.h new file mode 100644 index 00000000000..fac62154f33 --- /dev/null +++ b/tools/services/abilitymgr/include/kernal_system_app_manager.h @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_KERNAL_SYSTEM_APP_MANAGER_H +#define OHOS_AAFWK_KERNAL_SYSTEM_APP_MANAGER_H + +#include +#include + +#include "mission_record.h" +#include "mission_stack.h" +#include "want.h" + +namespace OHOS { +namespace AAFwk { +/** + * @class KernalSystemAppManager + * KernalSystemAppManager provides a facility for managing systerm ability life cycle. + */ +class KernalSystemAppManager : public std::enable_shared_from_this { +public: + explicit KernalSystemAppManager(int userId); + ~KernalSystemAppManager(); + + /** + * init kernal system app manager. + * + */ + void Init(); + /** + * StartAbility with request. + * + * @param abilityRequest, the request of the ability to start. + * @return Returns ERR_OK on success, others on failure. + */ + int StartAbility(const AbilityRequest &abilityRequest); + /** + * attach ability thread ipc object. + * + * @param scheduler, ability thread ipc object. + * @param token, the token of ability. + * @return Returns ERR_OK on success, others on failure. + */ + int AttachAbilityThread(const sptr &scheduler, const sptr &token); + /** + * AbilityTransitionDone, ability call this interface after lift cycle was changed. + * + * @param token,.ability's token. + * @param state,.the state of ability lift cycle. + * @return Returns ERR_OK on success, others on failure. + */ + int AbilityTransitionDone(const sptr &token, int state); + /** + * OnAbilityRequestDone, app manager service call this interface after ability request done. + * + * @param token,ability's token. + * @param state,the state of ability lift cycle. + */ + void OnAbilityRequestDone(const sptr &token, const int32_t state); + + void OnAppStateChanged(const AppInfo &info); + + /** + * get manager's user id. + */ + int GetManagerUserId() const; + + void DumpState(std::vector &info); + + void OnAbilityDied(std::shared_ptr abilityRecord); + + void OnTimeOut(uint32_t msgId, int64_t eventId); + + /** + * get the ability record by token. + * + * @return abilityRecord, target ability. + */ + std::shared_ptr GetAbilityRecordByToken(const sptr &token); + + int UpdateConfiguration(const DummyConfiguration &config); + void RestartAbility(const std::shared_ptr abilityRecord); + +private: + /** + * StartAbilityLocked. + * + * @param abilityRequest the request of the ability to start. + * @return Returns ERR_OK on success, others on failure. + */ + int StartAbilityLocked(const AbilityRequest &abilityRequest); + /** + * push waitting ability to queue. + * + * @param abilityRequest, the request of ability. + */ + void EnqueueWaittingAbility(const AbilityRequest &abilityRequest); + /** + * pop waitting ability. + * + */ + void DequeueWaittingAbility(); + /** + * get current top ability of stack. + * + * @return top ability record. + */ + std::shared_ptr GetCurrentTopAbility() const; + /** + * get or create the target ability record of system app. + * + * @param abilityRequest, the request of ability. + * @param targetAbility, target ability record. + */ + void GetOrCreateAbilityRecord(const AbilityRequest &abilityRequest, std::shared_ptr &targetAbility); + /** + * get the flag of the target ability record. + * + * @param bundleName, target bundleName. + * @param abilityName, target ability name. + */ + static std::string GetFlagOfAbility(const std::string &bundleName, const std::string &abilityName); + /** + * get the ability record by eventId. + * + * @return abilityRecord, target ability. + */ + std::shared_ptr GetAbilityRecordByEventId(const int64_t eventId) const; + /** + * dispatch ability life cycle . + * + * @param abilityRecord. + * @param state. + */ + int DispatchActive(const std::shared_ptr &abilityRecord, int state); + int DispatchInactive(const std::shared_ptr &abilityRecord, int state); + /** + * complete ability life cycle . + * + * @param abilityRecord. + */ + void CompleteActive(const std::shared_ptr &abilityRecord); + void CompleteInactive(const std::shared_ptr &abilityRecord); + + bool RemoveAbilityRecord(std::shared_ptr ability); + +private: + std::recursive_mutex stackLock_; + std::list> abilities_; + std::queue waittingAbilityQueue_; + int userId_; +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_KERNAL_SYSTEM_APP_MANAGER_H diff --git a/tools/services/abilitymgr/include/lifecycle_deal.h b/tools/services/abilitymgr/include/lifecycle_deal.h new file mode 100644 index 00000000000..3113640d4bd --- /dev/null +++ b/tools/services/abilitymgr/include/lifecycle_deal.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_LIFECYCLE_DEAL_H +#define OHOS_AAFWK_LIFECYCLE_DEAL_H + +#include + +#include "ability_scheduler_interface.h" +#include "want.h" +#include "nocopyable.h" + +namespace OHOS { +namespace AAFwk { +/** + * @class LifecycleDeal + * LifecycleDeal schedule ability life. + */ +class LifecycleDeal { +public: + LifecycleDeal(); + virtual ~LifecycleDeal(); + + /** + * set scheduler for accessing ability + * + * @param scheduler, ability thread ipc proxy. + */ + void SetScheduler(const sptr &scheduler); + + /** + * schedule ability life + * + */ + void Activate(const Want &want, LifeCycleStateInfo &stateInfo); + void Inactivate(const Want &want, LifeCycleStateInfo &stateInfo); + void MoveToBackground(const Want &want, LifeCycleStateInfo &stateInfo); + void ConnectAbility(const Want &want); + void DisconnectAbility(const Want &want); + void Terminate(const Want &want, LifeCycleStateInfo &stateInfo); + void CommandAbility(const Want &want, bool reStart, int startId); + void SaveAbilityState(PacMap &outState); + void RestoreAbilityState(const PacMap &inState); + void UpdateConfiguration(const DummyConfiguration &config); + +private: + sptr abilityScheduler_; // kit interface used to schedule ability life + + DISALLOW_COPY_AND_MOVE(LifecycleDeal); +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_LIFECYCLE_DEAL_H \ No newline at end of file diff --git a/tools/services/abilitymgr/include/lock_mission_container.h b/tools/services/abilitymgr/include/lock_mission_container.h new file mode 100644 index 00000000000..1b553f0b7b7 --- /dev/null +++ b/tools/services/abilitymgr/include/lock_mission_container.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_LOCK_MISSION_CONTAINER_H +#define OHOS_AAFWK_LOCK_MISSION_CONTAINER_H + +#include + +#include "mission_record.h" + +namespace OHOS { +namespace AAFwk { +/** + * @class LockMissionContainer + * LockMissionContainer records locked mission record. + */ +class LockMissionContainer { +public: + LockMissionContainer() = default; + virtual ~LockMissionContainer() = default; + + enum LockMissionState { LOCK_MISSION_STATE_NONE = 0, LOCK_MISSION_STATE_LOCKED, LOCK_MISSION_STATE_PINNED }; + + bool IsLockedMissionState() const; + bool SetLockedMission(const std::shared_ptr &mission, int lockUid, bool isSystemApp); + bool ReleaseLockedMission(const std::shared_ptr &mission, int callerUid, bool isForce); + bool IsSameLockedMission(std::string bundleName) const; + std::shared_ptr GetLockMission(); + int GetLockedMissionState() const; + +private: + void Clear(); + +private: + int lockerUid_ = -1; + LockMissionState lockState_ = LOCK_MISSION_STATE_NONE; + std::weak_ptr lockMission_; +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_LOCK_MISSION_CONTAINER_H \ No newline at end of file diff --git a/tools/services/abilitymgr/include/mission_record.h b/tools/services/abilitymgr/include/mission_record.h new file mode 100644 index 00000000000..67f5ef83157 --- /dev/null +++ b/tools/services/abilitymgr/include/mission_record.h @@ -0,0 +1,244 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_MISSION_RECORD_H +#define OHOS_AAFWK_MISSION_RECORD_H + +#include + +#include "ability_record.h" +#include "mission_stack.h" +#include "mission_description_info.h" +#include "mission_option.h" + +namespace OHOS { +namespace AAFwk { +class MissionStack; +/** + * @class MissionRecord + * MissionRecord records mission info and ability records. + */ +class MissionRecord : public ConfigurationHolder { +public: + MissionRecord(const std::string &bundleName = ""); + MissionRecord(const std::shared_ptr &mission); + virtual ~MissionRecord(); + + /** + * calculate next mission id + * + * @return mission id. + */ + static int GetNextMissionId(); + + /** + * get this mission record id + * + * @return mission record id. + */ + int GetMissionRecordId() const; + + /** + * get the number of abilities owned by this mission + * + * @return count. + */ + int GetAbilityRecordCount() const; + + /** + * get the bottom ability of this mission + * + * @return AbilityRecord. + */ + std::shared_ptr GetBottomAbilityRecord() const; + + /** + * get the top ability of this mission + * + * @return AbilityRecord. + */ + std::shared_ptr GetTopAbilityRecord() const; + + /** + * get the last top ability of this mission + * + * @return AbilityRecord. + */ + std::shared_ptr GetLastTopAbility() const; + + /** + * get the ability by token + * + * @return AbilityRecord. + */ + std::shared_ptr GetAbilityRecordByToken(const sptr &token) const; + + /** + * get the ability by id + * + * @return AbilityRecord. + */ + std::shared_ptr GetAbilityRecordById(const int64_t recordId) const; + + /** + * get the ability record by caller token and request code + * + * @return AbilityRecord. + */ + std::shared_ptr GetAbilityRecordByCaller( + const std::shared_ptr &caller, int requestCode); + + /** + * put the ability at the top of the stack + * + * @param AbilityRecord. + */ + void AddAbilityRecordToTop(std::shared_ptr ability); + + /** + * remove the ability from the stack + * + * @param AbilityRecord. + */ + bool RemoveAbilityRecord(std::shared_ptr ability); + + /** + * remove the ability at the top of the stack + * + * @param AbilityRecord. + */ + bool RemoveTopAbilityRecord(); + + /** + * remove all ability record from stack + * + * @param AbilityRecord. + */ + void RemoveAll(); + + /** + * dump the mission and ability stack information + * + * @param info + */ + void Dump(std::vector &info); + + /** + * check whether it is the same mission by bundleName + * + * @param bundleName + */ + bool IsSameMissionRecord(const std::string &bundleName) const; + + /** + * Get all the ability information in this mission + * + * @param abilityInfos + */ + void GetAllAbilityInfo(std::vector &abilityInfos); + + /** + * check whether it is the top ability by abilityName + * + * @param abilityName + */ + bool IsTopAbilityRecordByName(const std::string &abilityName); + + /** + * set whether it is created by luncher + * + * @param isCreate + */ + void SetIsLauncherCreate(); + + /** + * is luncher create + * + * @return is create + */ + bool IsLauncherCreate() const; + + /** + * set mission's previous mission record. + * + * @param record , previous mission record + */ + void SetPreMissionRecord(const std::shared_ptr &record); + + /** + * get mission's previous mission record. + * + * @return previous mission record + */ + std::shared_ptr GetPreMissionRecord() const; + + /** + * Check whether it exists through record ID + * + * @param id: ability record id + */ + bool IsExistAbilityRecord(int32_t id); + + /** + * set parent mission stack. + * + * @param missionStack: the parent mission stack + */ + void SetMissionStack(const std::shared_ptr &missionStack, int stackId); + std::shared_ptr GetMissionStack() const; + + std::string GetName() const + { + return bundleName_; + }; + + void SetMissionDescriptionInfo(std::shared_ptr &description) + { + missionDescriptionInfo_ = description; + }; + + std::shared_ptr GetMissionDescriptionInfo() const + { + return missionDescriptionInfo_; + }; + + bool SupportMultWindow() const; + + void SetMissionOption(const MissionOption &option); + const MissionOption &GetMissionOption() const; + + bool IsEmpty(); + void Resume(const std::shared_ptr &backup); + +protected: + virtual std::shared_ptr GetParent() override; + virtual unsigned int GetChildSize() override; + virtual std::shared_ptr FindChild(unsigned int index) override; + +private: + static int nextMissionId_; + int missionId_; + std::string bundleName_; + std::list> abilities_; + bool isLauncherCreate_ = false; + std::weak_ptr preMissionRecord_; + std::weak_ptr parentMissionStack_; + + std::shared_ptr missionDescriptionInfo_ = nullptr; + MissionOption option_; +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_MISSION_RECORD_H \ No newline at end of file diff --git a/tools/services/abilitymgr/include/mission_stack.h b/tools/services/abilitymgr/include/mission_stack.h new file mode 100644 index 00000000000..1d402bc4243 --- /dev/null +++ b/tools/services/abilitymgr/include/mission_stack.h @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_MISSION_STACK_H +#define OHOS_AAFWK_MISSION_STACK_H + +#include +#include + +#include "ability_info.h" +#include "application_info.h" +#include "mission_record.h" +#include "mission_record_info.h" +#include "want.h" +#include "stack_setting.h" + +namespace OHOS { +namespace AAFwk { +/** + * @class MissionStack + * MissionStack records mission info. + */ +class MissionStack : public ConfigurationHolder { +public: + MissionStack(int id, int userId); + virtual ~MissionStack(); + + /** + * get target mission record by app name + * + * @return mission record. + */ + std::shared_ptr GetTargetMissionRecord(const std::string &appName); + + /** + * get mission stack id + * + * @return id. + */ + int GetMissionStackId() const; + + /** + * get mission stack user id + * + * @return user id. + */ + int GetMissionStackUserId() const; + + /** + * get the number of missions owned by this mission stack + * + * @return count. + */ + int GetMissionRecordCount() const; + + /** + * get the top ability of this mission stack + * + * @return AbilityRecord. + */ + std::shared_ptr GetTopAbilityRecord() const; + + /** + * get the top mission of this mission stack + * + * @return MissionRecord. + */ + std::shared_ptr GetTopMissionRecord(); + + /** + * get the bottom mission of this mission stack + * + * @return MissionRecord. + */ + std::shared_ptr GetBottomMissionRecord(); + + /** + * get the mission by id + * + * @return MissionRecord. + */ + std::shared_ptr GetMissionRecordById(int id); + + /** + * get the mission by token + * + * @return AbilityRecord. + */ + std::shared_ptr GetAbilityRecordByToken(const sptr &token); + + /** + * get the ability record by caller token and request code + * + * @return AbilityRecord. + */ + std::shared_ptr GetAbilityRecordByCaller( + const std::shared_ptr &caller, int requestCode); + + /** + * get the mission by id + * + * @return AbilityRecord. + */ + std::shared_ptr GetAbilityRecordById(const int64_t recordId); + + /** + * remove the ability record from stack by token + */ + bool RemoveAbilityRecordByToken(const Token &token); + + /** + * remove the mission record from stack by id + */ + bool RemoveMissionRecord(int id); + + /** + * remove all mission from stack + */ + void RemoveAll(); + + /** + * add the mission at the top of the stack + */ + void AddMissionRecordToTop(std::shared_ptr mission); + + /** + * put the mission at the top of the stack + */ + void MoveMissionRecordToTop(std::shared_ptr mission); + + void MoveMissionRecordToBottom(const std::shared_ptr &mission); + + /** + * dump the mission stack information + */ + void Dump(std::vector &info); + void DumpStackList(std::vector &info); + + /** + * get all mission info about this stack + */ + void GetAllMissionInfo(std::vector &missionInfos); + + /** + * Check whether there is a mission record in the mission stack + */ + bool IsExistMissionRecord(int missionId); + + bool IsTopMissionRecord(std::shared_ptr &missionRecord) const; + + bool IsEqualStackId(int stackId); + + bool IsEmpty(); + +protected: + virtual std::shared_ptr GetParent() override; + virtual unsigned int GetChildSize() override; + virtual std::shared_ptr FindChild(unsigned int index) override; + +private: + int missionStackId_; + int userId_; + std::list> missions_; +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_MISSION_STACK_H diff --git a/tools/services/abilitymgr/include/pending_want_common_event.h b/tools/services/abilitymgr/include/pending_want_common_event.h new file mode 100644 index 00000000000..2941a696c5b --- /dev/null +++ b/tools/services/abilitymgr/include/pending_want_common_event.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PENDING_WANT_COMMON_EVENT_H +#define PENDING_WANT_COMMON_EVENT_H + +#include "common_event_data.h" +#include "common_event_subscriber.h" +#include "want.h" +#include "want_params.h" +#include "want_receiver_interface.h" + +namespace OHOS { +namespace AAFwk { +using namespace OHOS::EventFwk; + +class PendingWantCommonEvent : public CommonEventSubscriber { +public: + PendingWantCommonEvent(); + virtual ~PendingWantCommonEvent() = default; + + virtual void OnReceiveEvent(const EventFwk::CommonEventData &data) override; + + void SetWantParams(const WantParams &wantParams); + void SetFinishedReceiver(const sptr &finishedReceiver); + +private: + Want want_; + WantParams wantParams_; + sptr finishedReceiver_; +}; +} // namespace AAFwk +} // namespace OHOS +#endif // PENDING_WANT_COMMON_EVENT_H \ No newline at end of file diff --git a/tools/services/abilitymgr/include/pending_want_key.h b/tools/services/abilitymgr/include/pending_want_key.h new file mode 100644 index 00000000000..4dce896efd6 --- /dev/null +++ b/tools/services/abilitymgr/include/pending_want_key.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_PENDING_WANT_KEY_H +#define OHOS_AAFWK_PENDING_WANT_KEY_H + +#include +#include + +#include "want.h" +#include "ability_record.h" +#include "wants_info.h" + +namespace OHOS { +namespace AAFwk { +#define ODD_PRIME_NUMBER (37) + +class PendingWantKey { +public: + PendingWantKey() = default; + virtual ~PendingWantKey() = default; + void SetType(const int32_t type); + void SetBundleName(const std::string &bundleName); + void SetRequestWho(const std::string &requestWho); + void SetRequestCode(int32_t requestCode); + void SetRequestWant(const Want &requestWant); + void SetRequestResolvedType(const std::string &requestResolvedType); + void SetAllWantsInfos(const std::vector &allWantsInfos); + void SetFlags(int32_t flags); + void SetCode(int32_t code); + void SetUserId(int32_t userId); + + int32_t GetType(); + std::string GetBundleName(); + std::string GetRequestWho(); + int32_t GetRequestCode(); + Want GetRequestWant(); + std::string GetRequestResolvedType(); + std::vector GetAllWantsInfos(); + int32_t GetFlags(); + int32_t GetCode(); + int32_t GetUserId(); + +private: + int32_t type_ = {}; + std::string bundleName_ = {}; + std::string requestWho_ = {}; + int32_t requestCode_ = {}; + Want requestWant_ = {}; + std::string requestResolvedType_ = {}; + std::vector allWantsInfos_ = {}; + int32_t flags_ = {}; + int32_t code_ = {}; + int32_t userId_ = {}; +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_PENDING_WANT_KEY_H \ No newline at end of file diff --git a/tools/services/abilitymgr/include/pending_want_manager.h b/tools/services/abilitymgr/include/pending_want_manager.h new file mode 100644 index 00000000000..8bb097dc038 --- /dev/null +++ b/tools/services/abilitymgr/include/pending_want_manager.h @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_PENDING_WANT_MANAGER_H +#define OHOS_AAFWK_PENDING_WANT_MANAGER_H + +#include +#include +#include +#include +#include + +#include "ability_manager_errors.h" +#include "ability_record.h" +#include "common_event.h" +#include "nocopyable.h" +#include "pending_want_key.h" +#include "pending_want_record.h" +#include "pending_want_common_event.h" +#include "sender_info.h" +#include "want_sender_info.h" + +namespace OHOS { +namespace AAFwk { +enum class OperationType { + /** + * Unknown operation. + */ + UNKNOWN_TYPE, + + /** + * Starts an ability with a UI. + */ + START_ABILITY, + + /** + * Starts multiple abilities. + */ + START_ABILITIES, + + /** + * Starts an ability without a UI. + */ + START_SERVICE, + + /** + * Sends a common event. + */ + SEND_COMMON_EVENT, + + /** + * Starts a foreground ability without a UI. + */ + START_FOREGROUND_SERVICE +}; + +enum class Flags { + /** + * Indicates that the {@link WantAgent} can be used only once. + */ + ONE_TIME_FLAG = 1 << 30, + + /** + * Indicates that {@code null} is returned if the {@link WantAgent} does not exist. + */ + NO_BUILD_FLAG = 1 << 29, + + /** + * Indicates that the existing {@link WantAgent} should be canceled before the new object is generated. + */ + CANCEL_PRESENT_FLAG = 1 << 28, + + /** + * Indicates that the system only replaces the extra data of the existing {@link WantAgent} + * with that of the new object. + */ + UPDATE_PRESENT_FLAG = 1 << 27, + + /** + * Indicates that the created {@link WantAgent} should be immutable. + */ + CONSTANT_FLAG = 1 << 26, + + /** + * Indicates that the current value of {@code element} can be replaced + * when the {@link WantAgent} is triggered. + */ + REPLACE_ELEMENT, + + /** + * Indicates that the current value of {@code action} can be replaced + * when the {@link WantAgent} is triggered. + */ + REPLACE_ACTION, + + /** + * Indicates that the current value of {@code uri} can be replaced when the {@link WantAgent} is triggered. + */ + REPLACE_URI, + + /** + * Indicates that the current value of {@code entities} can be replaced + * when the {@link WantAgent} is triggered. + */ + REPLACE_ENTITIES, + + /** + * Indicates that the current value of {@code bundleName} can be replaced + * when the {@link WantAgent} is triggered. + */ + REPLACE_BUNDLE +}; + +constexpr int32_t SYSTEM_UID = 1000; + +class PendingWantManager : public std::enable_shared_from_this, public NoCopyable { +public: + PendingWantManager(); + explicit PendingWantManager(const std::shared_ptr &manager){}; + virtual ~PendingWantManager(); + +public: + sptr GetWantSender(const int32_t callingUid, const int32_t uid, const bool isSystemApp, + const WantSenderInfo &wantSenderInfo, const sptr &callerToken); + int32_t SendWantSender(const sptr &target, const SenderInfo &senderInfo); + void CancelWantSender( + const int32_t callingUid, const int32_t uid, const bool isSystemApp, const sptr &sender); + + int32_t GetPendingWantUid(const sptr &target); + int32_t GetPendingWantUserId(const sptr &target); + std::string GetPendingWantBundleName(const sptr &target); + int32_t GetPendingWantCode(const sptr &target); + int32_t GetPendingWantType(const sptr &target); + void RegisterCancelListener(const sptr &sender, const sptr &recevier); + void UnregisterCancelListener(const sptr &sender, const sptr &recevier); + int32_t GetPendingRequestWant(const sptr &target, std::shared_ptr &want); + + void CancelWantSenderLocked(PendingWantRecord &record, bool cleanAbility); + int32_t PendingWantStartAbility( + const Want &want, const sptr &callerToken, int32_t requestCode, int32_t callerUid); + int32_t PendingWantStartAbilitys(const std::vector wnatsInfo, const sptr &callerToken, + int32_t requestCode, int32_t callerUid); + int32_t PendingWantPublishCommonEvent(const Want &want, const SenderInfo &senderInfo, int32_t callerUid); + +private: + sptr GetWantSenderLocked(const int32_t callingUid, const int32_t uid, const int32_t userId, + WantSenderInfo &wantSenderInfo, const sptr &callerToken); + void MakeWantSenderCanceledLocked(PendingWantRecord &record); + + sptr GetPendingWantRecordByKey(const std::shared_ptr &key); + bool CheckPendingWantRecordByKey( + const std::shared_ptr &inputKey, const std::shared_ptr &key); + + sptr GetPendingWantRecordByCode(int32_t code); + static int32_t PendingRecordIdCreate(); + +private: + std::map, sptr> wantRecords_; + std::recursive_mutex mutex_; +}; +} // namespace AAFwk +} // namespace OHOS + +#endif // OHOS_AAFWK_PENDING_WANT_MANAGER_H diff --git a/tools/services/abilitymgr/include/pending_want_record.h b/tools/services/abilitymgr/include/pending_want_record.h new file mode 100644 index 00000000000..297b6f5992f --- /dev/null +++ b/tools/services/abilitymgr/include/pending_want_record.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_PENDING_WANT_RECORD_H +#define OHOS_AAFWK_PENDING_WANT_RECORD_H + +#include +#include + +#include "iremote_object.h" +#include "refbase.h" + +#include "ability_record.h" +#include "want_sender_stub.h" +#include "sender_info.h" +#include "pending_want_key.h" + +namespace OHOS { +namespace AAFwk { +class PendingWantManager; +class PendingWantRecord : public WantSenderStub { +public: + static const int START_CANCELED = -96; + + PendingWantRecord(); + PendingWantRecord(const std::shared_ptr &pendingWantManager, int32_t uid, + const sptr &callerToken, std::shared_ptr key); + virtual ~PendingWantRecord(); + + virtual void Send(SenderInfo &senderInfo); + virtual void RegisterCancelListener(const sptr &receiver); + virtual void UnregisterCancelListener(const sptr &receiver); + + virtual int32_t SenderInner(SenderInfo &senderInfo); + +public: + std::shared_ptr GetKey(); + int32_t GetUid() const; + void SetCallerUid(const int32_t callerUid); + void SetCanceled(); + bool GetCanceled(); + std::list> GetCancelCallbacks(); + +private: + std::weak_ptr pendingWantManager_ = {}; + int32_t uid_ = 0; + int32_t callerUid_ = 0; + sptr callerToken_ = {}; + bool canceled_ = false; + std::shared_ptr key_ = {}; + std::list> mCancelCallbacks_ = {}; + std::recursive_mutex lock_ = {}; +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_PENDING_WANT_RECORD_H \ No newline at end of file diff --git a/tools/services/abilitymgr/include/power_storage.h b/tools/services/abilitymgr/include/power_storage.h new file mode 100644 index 00000000000..3130bc027c4 --- /dev/null +++ b/tools/services/abilitymgr/include/power_storage.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_POWER_STORAGE_H +#define OHOS_AAFWK_POWER_STORAGE_H + +#include "ability_record.h" + +namespace OHOS { +namespace AAFwk { +struct PowerOffRecord { + std::weak_ptr ability; + int32_t missionId; + int32_t StackId; + AbilityState state; +}; + +class PowerStorage { +public: + PowerStorage() = default; + virtual ~PowerStorage() = default; + + void SetPowerOffInActiveRecord(const std::shared_ptr &ability); + std::vector GetPowerOffInActiveRecord() const; + void SetPowerOffActiveRecord(const std::shared_ptr &ability); + std::vector GetPowerOffActiveRecord() const; + +private: + std::vector inActiveRecord_; + std::vector activeRecord_; +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_POWER_STORAGE_H diff --git a/tools/services/abilitymgr/include/resume_mission_container.h b/tools/services/abilitymgr/include/resume_mission_container.h new file mode 100644 index 00000000000..e414f0e864e --- /dev/null +++ b/tools/services/abilitymgr/include/resume_mission_container.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_RESUME_MISSION_CONTAINER_H +#define OHOS_AAFWK_RESUME_MISSION_CONTAINER_H + +#include "mission_record.h" +#include "ability_event_handler.h" + +namespace OHOS { +namespace AAFwk { +class ResumeMissionContainer { +public: + explicit ResumeMissionContainer(const std::shared_ptr &handler); + virtual ~ResumeMissionContainer() = default; + + void Save(const std::shared_ptr &mission); + void Resume(const std::shared_ptr &mission); + bool IsResume(int missionId); + void Remove(int missionId); + +private: + const std::string taskName_ = "ResumeMission#"; + static constexpr int64_t recordSaveTime_ = 24 * 60 * 60 * 1000; + std::map> missionMaps_; + std::shared_ptr handler_; +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_RESUME_MISSION_CONTAINER_H \ No newline at end of file diff --git a/tools/services/abilitymgr/include/sa_mgr_client.h b/tools/services/abilitymgr/include/sa_mgr_client.h new file mode 100644 index 00000000000..8e52432c4dd --- /dev/null +++ b/tools/services/abilitymgr/include/sa_mgr_client.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_SA_MGR_CLIENT_H +#define OHOS_AAFWK_SA_MGR_CLIENT_H + +#include +#include +#include +#include + +#include "if_system_ability_manager.h" +#include "iremote_object.h" +#include "singleton.h" + +namespace OHOS { +namespace AAFwk { +/** + * @class SaMgrClient + * SaMgrClient. + */ +class SaMgrClient { + DECLARE_DELAYED_SINGLETON(SaMgrClient) +public: + sptr GetSystemAbility(const int32_t systemAbilityId); + void RegisterSystemAbility(const int32_t systemAbilityId, sptr broker); + +private: + OHOS::sptr saMgr_; + std::mutex saMutex_; + std::unordered_map> servicesMap_; +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_SA_MGR_CLIENT_H diff --git a/tools/services/abilitymgr/include/want_receiver_proxy.h b/tools/services/abilitymgr/include/want_receiver_proxy.h new file mode 100644 index 00000000000..281d3c0d3d0 --- /dev/null +++ b/tools/services/abilitymgr/include/want_receiver_proxy.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_WANT_RECEIVER_PROXY_H +#define OHOS_AAFWK_WANT_RECEIVER_PROXY_H + +#include "want_receiver_interface.h" +#include + +namespace OHOS { +namespace AAFwk { +class WantReceiverProxy : public IRemoteProxy { +public: + explicit WantReceiverProxy(const sptr &impl) : IRemoteProxy(impl) + {} + + virtual ~WantReceiverProxy() + {} + + virtual void Send(const int32_t resultCode) override; + virtual void PerformReceive(const Want &want, int resultCode, const std::string &data, const WantParams &extras, + bool serialized, bool sticky, int sendingUser) override; + +private: + bool WriteInterfaceToken(MessageParcel &data); + static inline BrokerDelegator delegator_; +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_WANT_RECEIVER_PROXY_H diff --git a/tools/services/abilitymgr/include/want_receiver_stub.h b/tools/services/abilitymgr/include/want_receiver_stub.h new file mode 100644 index 00000000000..0ac73f217af --- /dev/null +++ b/tools/services/abilitymgr/include/want_receiver_stub.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_OS_AAFWK_WANT_RECEIVER_STUB_H +#define OHOS_OS_AAFWK_WANT_RECEIVER_STUB_H + +#include "want_receiver_interface.h" + +#include +#include +#include + +namespace OHOS { +namespace AAFwk { +class WantReceiverStub : public IRemoteStub { +public: + WantReceiverStub(); + virtual ~WantReceiverStub(); + + virtual int OnRemoteRequest( + uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override; + +private: + int SendInner(MessageParcel &data, MessageParcel &reply); + int PerformReceiveInner(MessageParcel &data, MessageParcel &reply); + using RequestFuncType = int (WantReceiverStub::*)(MessageParcel &data, MessageParcel &reply); + std::map requestFuncMap_; +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_OS_AAFWK_WANT_RECEIVER_STUB_H \ No newline at end of file diff --git a/tools/services/abilitymgr/include/want_sender_proxy.h b/tools/services/abilitymgr/include/want_sender_proxy.h new file mode 100644 index 00000000000..bb7077f5ecd --- /dev/null +++ b/tools/services/abilitymgr/include/want_sender_proxy.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_WANT_SENDER_PROXY_H +#define OHOS_AAFWK_WANT_SENDER_PROXY_H + +#include "want_sender_interface.h" +#include + +namespace OHOS { +namespace AAFwk { +class WantSenderProxy : public IRemoteProxy { +public: + explicit WantSenderProxy(const sptr &impl) : IRemoteProxy(impl) + {} + + virtual ~WantSenderProxy() + {} + + virtual void Send(SenderInfo &senderInfo) override; + +private: + bool WriteInterfaceToken(MessageParcel &data); + +private: + static inline BrokerDelegator delegator_; +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_WANT_SENDER_PROXY_H diff --git a/tools/services/abilitymgr/include/want_sender_stub.h b/tools/services/abilitymgr/include/want_sender_stub.h new file mode 100644 index 00000000000..8cfce8619fc --- /dev/null +++ b/tools/services/abilitymgr/include/want_sender_stub.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_OS_AAFWK_WANT_SENDER_STUB_H +#define OHOS_OS_AAFWK_WANT_SENDER_STUB_H + +#include +#include "want_sender_interface.h" + +#include +#include + +namespace OHOS { +namespace AAFwk { +class WantSenderStub : public IRemoteStub { +public: + WantSenderStub(); + virtual ~WantSenderStub(); + + virtual int OnRemoteRequest( + uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override; + +private: + int SendInner(MessageParcel &data, MessageParcel &reply); + using RequestFuncType = int (WantSenderStub::*)(MessageParcel &data, MessageParcel &reply); + std::map requestFuncMap_; +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_OS_AAFWK_WANT_SENDER_STUB_H \ No newline at end of file diff --git a/tools/services/abilitymgr/include/window_info.h b/tools/services/abilitymgr/include/window_info.h new file mode 100644 index 00000000000..1ccf7cdd652 --- /dev/null +++ b/tools/services/abilitymgr/include/window_info.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_WINDOW_INFO_H +#define OHOS_AAFWK_WINDOW_INFO_H + +#include + +namespace OHOS { +namespace AAFwk { +/** + * @class WindowInfo + * Record window info include window id and window state. + */ +class WindowInfo { +public: + WindowInfo() = default; + explicit WindowInfo(int windowToken) : windowToken_(windowToken) + {} + virtual ~WindowInfo() + {} + + int32_t windowToken_ = -1; // window id + bool isVisible_ = false; +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_WINDOW_INFO_H \ No newline at end of file diff --git a/tools/services/abilitymgr/resource/ams_service_config.json b/tools/services/abilitymgr/resource/ams_service_config.json new file mode 100644 index 00000000000..0dd3ebfb965 --- /dev/null +++ b/tools/services/abilitymgr/resource/ams_service_config.json @@ -0,0 +1,8 @@ +{ + "service_startup_config":{ + "startup_launcher":true, + "startup_system_ui_status_bar" : true, + "startup_system_ui_navigation_bar" : true + } + +} diff --git a/tools/services/abilitymgr/src/aafwk_dummy_configuration.cpp b/tools/services/abilitymgr/src/aafwk_dummy_configuration.cpp new file mode 100644 index 00000000000..3d6c420bc48 --- /dev/null +++ b/tools/services/abilitymgr/src/aafwk_dummy_configuration.cpp @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "aafwk_dummy_configuration.h" + +#include "string_ex.h" + +#include "hilog_wrapper.h" + +namespace OHOS { +namespace AAFwk { + +DummyConfiguration::DummyConfiguration(const std::string &name) : testInfostr_(name) +{} + +bool DummyConfiguration::ReadFromParcel(Parcel &parcel) +{ + testInfostr_ = Str16ToStr8(parcel.ReadString16()); + return true; +} + +DummyConfiguration *DummyConfiguration::Unmarshalling(Parcel &parcel) +{ + DummyConfiguration *dummyConfiguration = new (std::nothrow) DummyConfiguration(); + if (dummyConfiguration && !dummyConfiguration->ReadFromParcel(parcel)) { + delete dummyConfiguration; + dummyConfiguration = nullptr; + } + return dummyConfiguration; +} + +bool DummyConfiguration::Marshalling(Parcel &parcel) const +{ + if (!parcel.WriteString16(Str8ToStr16(testInfostr_))) { + return false; + } + return true; +} + +unsigned int DummyConfiguration::Differ(const std::shared_ptr config) const +{ + // temp test code + if (config == nullptr || config->GetName() == "none") { + return 0x00000000; + } + + std::vector changes; + std::string name = config->GetName(); + std::string::size_type nbegin = 0; + std::string::size_type nend = 0; + while (true) { + nend = name.find_first_of("#", nbegin); + if (nend == std::string::npos) { + changes.push_back(name.substr(nbegin, name.length())); + break; + } + changes.push_back(name.substr(nbegin, nend - nbegin)); + nbegin = nend + 1; + } + + HILOG_ERROR("fail to get AbilityEventHandler"); + + unsigned int flag = 0x00000000; + for (auto item : changes) { + if (item == "locale") { + flag |= 0x00000001; + } else if (item == "layout") { + flag |= 0x00000002; + } else if (item == "fontSize") { + flag |= 0x00000004; + } else if (item == "orientation") { + flag |= 0x00000008; + } else if (item == "density") { + flag |= 0x00000010; + } else { + continue; + } + } + return flag; +} + +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/abilitymgr/src/ability_connect_callback_stub.cpp b/tools/services/abilitymgr/src/ability_connect_callback_stub.cpp new file mode 100644 index 00000000000..546007f44a0 --- /dev/null +++ b/tools/services/abilitymgr/src/ability_connect_callback_stub.cpp @@ -0,0 +1,154 @@ + +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ability_connect_callback_stub.h" + +#include "ability_connect_callback_proxy.h" +#include "hilog_wrapper.h" +#include "ipc_types.h" +#include "message_parcel.h" +#include "want.h" + +namespace OHOS { +namespace AAFwk { +bool AbilityConnectionProxy::WriteInterfaceToken(MessageParcel &data) +{ + if (!data.WriteInterfaceToken(AbilityConnectionProxy::GetDescriptor())) { + HILOG_ERROR("Write interface token failed."); + return false; + } + return true; +} + +void AbilityConnectionProxy::OnAbilityConnectDone( + const AppExecFwk::ElementName &element, const sptr &remoteObject, int resultCode) +{ + int error; + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!WriteInterfaceToken(data)) { + return; + } + + if (!data.WriteParcelable(&element)) { + HILOG_ERROR("Connect done element error."); + return; + } + + if (!data.WriteParcelable(remoteObject)) { + HILOG_ERROR("Connect done remote object error."); + return; + } + + if (!data.WriteInt32(resultCode)) { + HILOG_ERROR("Connect done result code error."); + return; + } + + error = Remote()->SendRequest(IAbilityConnection::ON_ABILITY_CONNECT_DONE, data, reply, option); + if (error != NO_ERROR) { + HILOG_ERROR("Connect done fail, error: %{public}d", error); + return; + } +} + +void AbilityConnectionProxy::OnAbilityDisconnectDone(const AppExecFwk::ElementName &element, int resultCode) +{ + int error; + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!WriteInterfaceToken(data)) { + return; + } + if (!data.WriteParcelable(&element) || !data.WriteInt32(resultCode)) { + HILOG_ERROR("Disconnect done data write error."); + return; + } + + error = Remote()->SendRequest(IAbilityConnection::ON_ABILITY_DISCONNECT_DONE, data, reply, option); + if (error != NO_ERROR) { + HILOG_ERROR("Disconnect done fail, error: %d", error); + return; + } +} + +AbilityConnectionStub::AbilityConnectionStub() +{} + +AbilityConnectionStub::~AbilityConnectionStub() +{} + +int AbilityConnectionStub::OnRemoteRequest( + uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) +{ + std::u16string descriptor = AbilityConnectionStub::GetDescriptor(); + std::u16string remoteDescriptor = data.ReadInterfaceToken(); + if (descriptor != remoteDescriptor) { + HILOG_INFO("Local descriptor is not equal to remote"); + return ERR_INVALID_STATE; + } + + auto element = data.ReadParcelable(); + switch (code) { + case IAbilityConnection::ON_ABILITY_CONNECT_DONE: { + if (element == nullptr) { + HILOG_ERROR("callback stub receive element is nullptr"); + return ERR_INVALID_VALUE; + } + auto remoteObject = data.ReadParcelable(); + auto resultCode = data.ReadInt32(); + OnAbilityConnectDone(*element, remoteObject, resultCode); + delete element; + return NO_ERROR; + } + case IAbilityConnection::ON_ABILITY_DISCONNECT_DONE: { + if (element == nullptr) { + HILOG_ERROR("callback stub receive element is nullptr"); + return ERR_INVALID_VALUE; + } + auto resultCode = data.ReadInt32(); + OnAbilityDisconnectDone(*element, resultCode); + delete element; + return NO_ERROR; + } + default: { + if (element != nullptr) { + delete element; + } + return IPCObjectStub::OnRemoteRequest(code, data, reply, option); + } + } +} + +void AbilityConnectCallbackRecipient::OnRemoteDied(const wptr &__attribute__((unused)) remote) +{ + HILOG_ERROR("On remote died."); + if (handler_) { + handler_(remote); + } +} + +AbilityConnectCallbackRecipient::AbilityConnectCallbackRecipient(RemoteDiedHandler handler) : handler_(handler) +{} + +AbilityConnectCallbackRecipient::~AbilityConnectCallbackRecipient() +{} +} // namespace AAFwk +} // namespace OHOS diff --git a/tools/services/abilitymgr/src/ability_connect_manager.cpp b/tools/services/abilitymgr/src/ability_connect_manager.cpp new file mode 100644 index 00000000000..47ded621884 --- /dev/null +++ b/tools/services/abilitymgr/src/ability_connect_manager.cpp @@ -0,0 +1,876 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ability_connect_manager.h" + +#include + +#include "ability_util.h" +#include "hilog_wrapper.h" +#include "ability_manager_errors.h" +#include "ability_manager_service.h" +#include "ability_connect_callback_stub.h" + +namespace OHOS { +namespace AAFwk { + +AbilityConnectManager::AbilityConnectManager() +{} + +AbilityConnectManager::~AbilityConnectManager() +{} + +int AbilityConnectManager::StartAbility(const AbilityRequest &abilityRequest) +{ + std::lock_guard guard(Lock_); + return StartAbilityLocked(abilityRequest); +} + +int AbilityConnectManager::TerminateAbility(const sptr &token) +{ + std::lock_guard guard(Lock_); + return TerminateAbilityLocked(token); +} + +int AbilityConnectManager::TerminateAbility(const std::shared_ptr &caller, int requestCode) +{ + HILOG_INFO("Terminate ability."); + std::lock_guard guard(Lock_); + + std::shared_ptr targetAbility = nullptr; + int result = static_cast(ABILITY_VISIBLE_FALSE_DENY_REQUEST); + std::for_each(serviceMap_.begin(), + serviceMap_.end(), + [&targetAbility, &caller, requestCode, &result](ServiceMapType::reference service) { + auto callerList = service.second->GetCallerRecordList(); + for (auto &it : callerList) { + if (it->GetCaller() == caller && it->GetRequestCode() == requestCode) { + targetAbility = service.second; + if (targetAbility) { + result = AbilityUtil::JudgeAbilityVisibleControl(targetAbility->GetAbilityInfo()); + } + break; + } + } + }); + + if (!targetAbility) { + return NO_FOUND_ABILITY_BY_CALLER; + } + if (result != ERR_OK) { + HILOG_ERROR("%{public}s JudgeAbilityVisibleControl error.", __func__); + return result; + } + + return TerminateAbilityLocked(targetAbility->GetToken()); +} + +int AbilityConnectManager::StopServiceAbility(const AbilityRequest &abilityRequest) +{ + HILOG_INFO("Stop Service ability."); + std::lock_guard guard(Lock_); + return StopServiceAbilityLocked(abilityRequest); +} + +int AbilityConnectManager::TerminateAbilityResult(const sptr &token, int startId) +{ + HILOG_INFO("Terminate ability result."); + std::lock_guard guard(Lock_); + return TerminateAbilityResultLocked(token, startId); +} + +int AbilityConnectManager::StartAbilityLocked(const AbilityRequest &abilityRequest) +{ + HILOG_INFO("Start ability locked, ability_name: %{public}s", abilityRequest.want.GetElement().GetURI().c_str()); + + std::shared_ptr targetService; + bool isLoadedAbility = false; + GetOrCreateServiceRecord(abilityRequest, false, targetService, isLoadedAbility); + CHECK_POINTER_AND_RETURN(targetService, ERR_INVALID_VALUE); + + targetService->AddCallerRecord(abilityRequest.callerToken, abilityRequest.requestCode); + + if (!isLoadedAbility) { + LoadAbility(targetService); + } else if (targetService->IsAbilityState(AbilityState::ACTIVE)) { + // It may have been started through connect + CommandAbility(targetService); + } else { + HILOG_ERROR("Target service is already activing."); + return START_SERVICE_ABILITY_ACTIVING; + } + + sptr token = targetService->GetToken(); + sptr preToken = nullptr; + if (targetService->GetPreAbilityRecord()) { + preToken = targetService->GetPreAbilityRecord()->GetToken(); + } + DelayedSingleton::GetInstance()->AbilityBehaviorAnalysis(token, preToken, 0, 1, 1); + return ERR_OK; +} + +int AbilityConnectManager::TerminateAbilityLocked(const sptr &token) +{ + HILOG_INFO("Terminate ability locked."); + auto abilityRecord = GetServiceRecordByToken(token); + CHECK_POINTER_AND_RETURN(abilityRecord, ERR_INVALID_VALUE); + + if (abilityRecord->IsTerminating()) { + HILOG_INFO("Ability is on terminating."); + return ERR_OK; + } + + if (abilityRecord->GetConnectRecordList().empty()) { + HILOG_INFO("Service ability has no any connection, and not started , need terminate."); + auto timeoutTask = [abilityRecord, connectManager = shared_from_this()]() { + HILOG_WARN("Disconnect ability terminate timeout."); + connectManager->HandleStopTimeoutTask(abilityRecord); + }; + abilityRecord->Terminate(timeoutTask); + } else { + HILOG_WARN("Target service has been connected. It cannot be stopped."); + return TERMINATE_SERVICE_IS_CONNECTED; + } + + return ERR_OK; +} + +int AbilityConnectManager::TerminateAbilityResultLocked(const sptr &token, int startId) +{ + HILOG_INFO("Terminate ability result locked, startId: %{public}d", startId); + CHECK_POINTER_AND_RETURN(token, ERR_INVALID_VALUE); + + auto abilityRecord = Token::GetAbilityRecordByToken(token); + CHECK_POINTER_AND_RETURN(abilityRecord, ERR_INVALID_VALUE); + + if (abilityRecord->GetStartId() != startId) { + HILOG_ERROR("Start id not equal."); + return TERMINATE_ABILITY_RESULT_FAILED; + } + + return TerminateAbilityLocked(token); +} + +int AbilityConnectManager::StopServiceAbilityLocked(const AbilityRequest &abilityRequest) +{ + HILOG_INFO("Stop service ability locked."); + AppExecFwk::ElementName element( + abilityRequest.abilityInfo.deviceId, abilityRequest.abilityInfo.bundleName, abilityRequest.abilityInfo.name); + auto abilityRecord = GetServiceRecordByElementName(element.GetURI()); + CHECK_POINTER_AND_RETURN(abilityRecord, ERR_INVALID_VALUE); + + if (abilityRecord->IsTerminating()) { + HILOG_INFO("Ability is on terminating."); + return ERR_OK; + } + + if (abilityRecord->GetConnectRecordList().empty()) { + HILOG_INFO("Service ability has no any connection, and no started , need terminate."); + auto timeoutTask = [abilityRecord, connectManager = shared_from_this()]() { + HILOG_WARN("Disconnect ability terminate timeout."); + connectManager->HandleStopTimeoutTask(abilityRecord); + }; + abilityRecord->Terminate(timeoutTask); + } else { + HILOG_WARN("Target service has been connected. It cannot be stopped."); + return TERMINATE_SERVICE_IS_CONNECTED; + } + + return ERR_OK; +} + +void AbilityConnectManager::GetOrCreateServiceRecord(const AbilityRequest &abilityRequest, + const bool isCreatedByConnect, std::shared_ptr &targetService, bool &isLoadedAbility) +{ + AppExecFwk::ElementName element( + abilityRequest.abilityInfo.deviceId, abilityRequest.abilityInfo.bundleName, abilityRequest.abilityInfo.name); + auto serviceMapIter = serviceMap_.find(element.GetURI()); + if (serviceMapIter == serviceMap_.end()) { + targetService = AbilityRecord::CreateAbilityRecord(abilityRequest); + if (isCreatedByConnect && targetService != nullptr) { + targetService->SetCreateByConnectMode(); + } + serviceMap_.emplace(element.GetURI(), targetService); + isLoadedAbility = false; + } else { + targetService = serviceMapIter->second; + if (targetService != nullptr) { + // want may be changed for the same ability. + targetService->SetWant(abilityRequest.want); + } + isLoadedAbility = true; + } +} + +void AbilityConnectManager::GetConnectRecordListFromMap( + const sptr &connect, std::list> &connectRecordList) +{ + auto connectMapIter = connectMap_.find(connect->AsObject()); + if (connectMapIter != connectMap_.end()) { + connectRecordList = connectMapIter->second; + } +} + +int AbilityConnectManager::ConnectAbilityLocked(const AbilityRequest &abilityRequest, + const sptr &connect, const sptr &callerToken) +{ + HILOG_INFO("%{public}s, ability_name:%{public}s", __func__, abilityRequest.want.GetElement().GetURI().c_str()); + std::lock_guard guard(Lock_); + + // 1. get target service ability record, and check whether it has been loaded. + std::shared_ptr targetService; + bool isLoadedAbility = false; + GetOrCreateServiceRecord(abilityRequest, true, targetService, isLoadedAbility); + CHECK_POINTER_AND_RETURN(targetService, ERR_INVALID_VALUE); + // 2. get target connectRecordList, and check whether this callback has been connected. + ConnectListType connectRecordList; + GetConnectRecordListFromMap(connect, connectRecordList); + bool isCallbackConnected = !connectRecordList.empty(); + // 3. If this service ability and callback has been connected, There is no need to connect repeatedly + if (isLoadedAbility && (isCallbackConnected) && IsAbilityConnected(targetService, connectRecordList)) { + HILOG_ERROR("Service and callback was connected."); + return ERR_OK; + } + + // 4. Other cases , need to connect the service ability + auto connectRecord = ConnectionRecord::CreateConnectionRecord(callerToken, targetService, connect); + CHECK_POINTER_AND_RETURN(connectRecord, ERR_INVALID_VALUE); + connectRecord->SetConnectState(ConnectionState::CONNECTING); + targetService->AddConnectRecordToList(connectRecord); + connectRecordList.push_back(connectRecord); + if (isCallbackConnected) { + RemoveConnectDeathRecipient(connect); + connectMap_.erase(connectMap_.find(connect->AsObject())); + } + AddConnectDeathRecipient(connect); + connectMap_.emplace(connect->AsObject(), connectRecordList); + + // 5. load or connect ability + if (!isLoadedAbility) { + LoadAbility(targetService); + } else if (targetService->IsAbilityState(AbilityState::ACTIVE)) { + // this service ability has not first connect + if (targetService->GetConnectRecordList().size() > 1) { + if (eventHandler_ != nullptr) { + auto task = [connectRecord]() { connectRecord->CompleteConnect(ERR_OK); }; + eventHandler_->PostTask(task); + } + } else { + ConnectAbility(targetService); + } + } else { + HILOG_ERROR("Target service is already activing."); + } + + auto token = targetService->GetToken(); + auto preToken = iface_cast(connectRecord->GetToken()); + DelayedSingleton::GetInstance()->AbilityBehaviorAnalysis(token, preToken, 0, 1, 1); + return ERR_OK; +} + +int AbilityConnectManager::DisconnectAbilityLocked(const sptr &connect) +{ + HILOG_INFO("Disconnect ability locked."); + std::lock_guard guard(Lock_); + + // 1. check whether callback was connected. + ConnectListType connectRecordList; + GetConnectRecordListFromMap(connect, connectRecordList); + if (connectRecordList.empty()) { + HILOG_ERROR("Can't find the connect list from connect map by callback."); + return CONNECTION_NOT_EXIST; + } + + // 2. schedule disconnect to target service + for (auto &connectRecord : connectRecordList) { + if (connectRecord) { + auto abilityRecord = connectRecord->GetAbilityRecord(); + CHECK_POINTER_AND_RETURN(abilityRecord, ERR_INVALID_VALUE); + int result = AbilityUtil::JudgeAbilityVisibleControl(abilityRecord->GetAbilityInfo()); + if (result != ERR_OK) { + HILOG_ERROR("%{public}s JudgeAbilityVisibleControl error.", __func__); + return result; + } + int ret = connectRecord->DisconnectAbility(); + if (ret != ERR_OK) { + HILOG_ERROR("Disconnect ability fail , ret = %{public}d.", ret); + return ret; + } + HILOG_INFO("Disconnect ability ,connect record id %{public}d", connectRecord->GetRecordId()); + } + } + + // 3. target servie has another connection, this record callback disconnected directly. + if (eventHandler_ != nullptr) { + auto task = [connectRecordList, connectManager = shared_from_this()]() { + connectManager->HandleDisconnectTask(connectRecordList); + }; + eventHandler_->PostTask(task); + } + + return ERR_OK; +} + +int AbilityConnectManager::AttachAbilityThreadLocked( + const sptr &scheduler, const sptr &token) +{ + std::lock_guard guard(Lock_); + auto abilityRecord = GetServiceRecordByToken(token); + CHECK_POINTER_AND_RETURN(abilityRecord, ERR_INVALID_VALUE); + if (eventHandler_ != nullptr) { + int recordId = abilityRecord->GetRecordId(); + std::string taskName = std::string("LoadTimeout_") + std::to_string(recordId); + eventHandler_->RemoveTask(taskName); + eventHandler_->RemoveEvent(AbilityManagerService::LOAD_TIMEOUT_MSG, abilityRecord->GetEventId()); + } + std::string element = abilityRecord->GetWant().GetElement().GetURI(); + HILOG_INFO("Ability: %{public}s", element.c_str()); + abilityRecord->SetScheduler(scheduler); + + DelayedSingleton::GetInstance()->MoveToForground(token); + return ERR_OK; +} + +void AbilityConnectManager::OnAbilityRequestDone(const sptr &token, const int32_t state) +{ + std::lock_guard guard(Lock_); + auto abilitState = DelayedSingleton::GetInstance()->ConvertToAppAbilityState(state); + auto abilityRecord = GetServiceRecordByToken(token); + CHECK_POINTER(abilityRecord); + std::string element = abilityRecord->GetWant().GetElement().GetURI(); + HILOG_INFO("Ability: %{public}s", element.c_str()); + + if (abilitState == AppAbilityState::ABILITY_STATE_FOREGROUND) { + abilityRecord->Inactivate(); + } else if (abilitState == AppAbilityState::ABILITY_STATE_BACKGROUND) { + DelayedSingleton::GetInstance()->TerminateAbility(token); + RemoveServiceAbility(abilityRecord); + } +} + +void AbilityConnectManager::OnAppStateChanged(const AppInfo &info) +{ + std::lock_guard guard(Lock_); + std::for_each(serviceMap_.begin(), serviceMap_.end(), [&info](ServiceMapType::reference service) { + if (service.second && service.second->GetApplicationInfo().name == info.appName && + (info.processName == service.second->GetAbilityInfo().process || + info.processName == service.second->GetApplicationInfo().bundleName)) { + service.second->SetAppState(info.state); + } + }); +} + +int AbilityConnectManager::AbilityTransitionDone(const sptr &token, int state) +{ + std::lock_guard guard(Lock_); + auto abilityRecord = GetServiceRecordByToken(token); + CHECK_POINTER_AND_RETURN(abilityRecord, ERR_INVALID_VALUE); + + std::string element = abilityRecord->GetWant().GetElement().GetURI(); + int targetState = AbilityRecord::ConvertLifeCycleToAbilityState(static_cast(state)); + std::string abilityState = AbilityRecord::ConvertAbilityState(static_cast(targetState)); + HILOG_INFO("Ability: %{public}s, state: %{public}s", element.c_str(), abilityState.c_str()); + + switch (state) { + case AbilityState::INACTIVE: { + return DispatchInactive(abilityRecord, state); + } + case AbilityState::INITIAL: { + return DispatchTerminate(abilityRecord); + } + default: { + HILOG_WARN("Don't support transiting state: %{public}d", state); + return ERR_INVALID_VALUE; + } + } +} + +int AbilityConnectManager::ScheduleConnectAbilityDoneLocked( + const sptr &token, const sptr &remoteObject) +{ + std::lock_guard guard(Lock_); + CHECK_POINTER_AND_RETURN(token, ERR_INVALID_VALUE); + + auto abilityRecord = Token::GetAbilityRecordByToken(token); + CHECK_POINTER_AND_RETURN(abilityRecord, ERR_INVALID_VALUE); + + std::string element = abilityRecord->GetWant().GetElement().GetURI(); + HILOG_DEBUG("Ability: %{public}s", element.c_str()); + + if ((!abilityRecord->IsAbilityState(AbilityState::INACTIVE)) && + (!abilityRecord->IsAbilityState(AbilityState::ACTIVE))) { + HILOG_ERROR("Ability record state is not inactive ,state:%{public}d", abilityRecord->GetAbilityState()); + return INVALID_CONNECTION_STATE; + } + + abilityRecord->SetConnRemoteObject(remoteObject); + // There may be multiple callers waiting for the connection result + auto connectRecordList = abilityRecord->GetConnectRecordList(); + for (auto &connectRecord : connectRecordList) { + connectRecord->ScheduleConnectAbilityDone(); + } + + return ERR_OK; +} + +int AbilityConnectManager::ScheduleDisconnectAbilityDoneLocked(const sptr &token) +{ + std::lock_guard guard(Lock_); + auto abilityRecord = GetServiceRecordByToken(token); + CHECK_POINTER_AND_RETURN(abilityRecord, CONNECTION_NOT_EXIST); + + auto connect = abilityRecord->GetDisconnectingRecord(); + CHECK_POINTER_AND_RETURN(connect, CONNECTION_NOT_EXIST); + + if (!abilityRecord->IsAbilityState(AbilityState::ACTIVE)) { + HILOG_ERROR("The service ability state is not active ,state:%{public}d", abilityRecord->GetAbilityState()); + return INVALID_CONNECTION_STATE; + } + + std::string element = abilityRecord->GetWant().GetElement().GetURI(); + HILOG_INFO("disconnect ability done with service %{public}s", element.c_str()); + + // complete disconnect and remove record from conn map + connect->ScheduleDisconnectAbilityDone(); + abilityRecord->RemoveConnectRecordFromList(connect); + if (abilityRecord->IsConnectListEmpty() && abilityRecord->GetStartId() == 0) { + HILOG_INFO("Service ability has no any connection, and not started , need terminate."); + auto timeoutTask = [abilityRecord, connectManager = shared_from_this()]() { + HILOG_WARN("Disconnect ability terminate timeout."); + connectManager->HandleStopTimeoutTask(abilityRecord); + }; + abilityRecord->Terminate(timeoutTask); + } + RemoveConnectionRecordFromMap(connect); + + return ERR_OK; +} + +int AbilityConnectManager::ScheduleCommandAbilityDoneLocked(const sptr &token) +{ + std::lock_guard guard(Lock_); + CHECK_POINTER_AND_RETURN(token, ERR_INVALID_VALUE); + auto abilityRecord = Token::GetAbilityRecordByToken(token); + CHECK_POINTER_AND_RETURN(abilityRecord, ERR_INVALID_VALUE); + std::string element = abilityRecord->GetWant().GetElement().GetURI(); + HILOG_DEBUG("Ability: %{public}s", element.c_str()); + + if ((!abilityRecord->IsAbilityState(AbilityState::INACTIVE)) && + (!abilityRecord->IsAbilityState(AbilityState::ACTIVE))) { + HILOG_ERROR("Ability record state is not inactive ,state:%{public}d", abilityRecord->GetAbilityState()); + return INVALID_CONNECTION_STATE; + } + // complete command and pop waiting start ability from queue. + CompleteCommandAbility(abilityRecord); + + return ERR_OK; +} + +void AbilityConnectManager::CompleteCommandAbility(std::shared_ptr abilityRecord) +{ + CHECK_POINTER(abilityRecord); + + if (eventHandler_) { + int recordId = abilityRecord->GetRecordId(); + std::string taskName = std::string("CommandTimeout_") + std::to_string(recordId) + std::string("_") + + std::to_string(abilityRecord->GetStartId()); + eventHandler_->RemoveTask(taskName); + } + + abilityRecord->SetAbilityState(AbilityState::ACTIVE); +} + +std::shared_ptr AbilityConnectManager::GetServiceRecordByElementName(const std::string &element) +{ + std::lock_guard guard(Lock_); + auto mapIter = serviceMap_.find(element); + if (mapIter != serviceMap_.end()) { + return mapIter->second; + } + return nullptr; +} + +std::shared_ptr AbilityConnectManager::GetServiceRecordByToken(const sptr &token) +{ + std::lock_guard guard(Lock_); + auto IsMatch = [token](auto service) { + sptr srcToken = service.second->GetToken(); + return srcToken == token; + }; + auto serviceRecord = std::find_if(serviceMap_.begin(), serviceMap_.end(), IsMatch); + if (serviceRecord != serviceMap_.end()) { + return serviceRecord->second; + } + return nullptr; +} + +std::list> AbilityConnectManager::GetConnectRecordListByCallback( + sptr callback) +{ + std::lock_guard guard(Lock_); + std::list> connectList; + auto connectMapIter = connectMap_.find(callback->AsObject()); + if (connectMapIter != connectMap_.end()) { + connectList = connectMapIter->second; + } + return connectList; +} + +void AbilityConnectManager::RemoveAll() +{ + serviceMap_.clear(); + connectMap_.clear(); +} + +void AbilityConnectManager::LoadAbility(const std::shared_ptr &abilityRecord) +{ + CHECK_POINTER(abilityRecord); + + PostTimeOutTask(abilityRecord, AbilityManagerService::LOAD_TIMEOUT_MSG); + + sptr token = abilityRecord->GetToken(); + sptr perToken = nullptr; + if (abilityRecord->IsCreateByConnect()) { + perToken = iface_cast(abilityRecord->GetConnectingRecord()->GetToken()); + } else { + auto callerList = abilityRecord->GetCallerRecordList(); + if (!callerList.empty()) { + perToken = callerList.back()->GetCaller()->GetToken(); + } + } + DelayedSingleton::GetInstance()->LoadAbility( + token, perToken, abilityRecord->GetAbilityInfo(), abilityRecord->GetApplicationInfo()); + + abilityRecord->SetStartTime(); +} + +void AbilityConnectManager::PostTimeOutTask(const std::shared_ptr &abilityRecord, uint32_t messageId) +{ + CHECK_POINTER(abilityRecord); + CHECK_POINTER(eventHandler_); + if (messageId != AbilityConnectManager::LOAD_TIMEOUT_MSG && + messageId != AbilityConnectManager::CONNECT_TIMEOUT_MSG) { + HILOG_ERROR("Timeout task messageId is error."); + return; + } + + int recordId; + std::string taskName; + int resultCode; + uint32_t delayTime; + if (messageId == AbilityManagerService::LOAD_TIMEOUT_MSG) { + // first load ability, There is at most one connect record. + recordId = abilityRecord->GetRecordId(); + taskName = std::string("LoadTimeout_") + std::to_string(recordId); + resultCode = LOAD_ABILITY_TIMEOUT; + delayTime = AbilityManagerService::LOAD_TIMEOUT; + } else { + auto connectRecord = abilityRecord->GetConnectingRecord(); + CHECK_POINTER(connectRecord); + recordId = connectRecord->GetRecordId(); + taskName = std::string("ConnectTimeout_") + std::to_string(recordId); + resultCode = CONNECTION_TIMEOUT; + delayTime = AbilityManagerService::CONNECT_TIMEOUT; + } + + auto timeoutTask = [abilityRecord, connectManager = shared_from_this(), resultCode]() { + HILOG_WARN("Connect or load ability timeout."); + connectManager->HandleStartTimeoutTask(abilityRecord, resultCode); + }; + + eventHandler_->PostTask(timeoutTask, taskName, delayTime); +} + +void AbilityConnectManager::HandleStartTimeoutTask(const std::shared_ptr &abilityRecord, int resultCode) +{ + HILOG_DEBUG("Complete connect or load ability timeout."); + std::lock_guard guard(Lock_); + CHECK_POINTER(abilityRecord); + auto connectingList = abilityRecord->GetConnectingRecordList(); + for (auto &connectRecord : connectingList) { + if (connectRecord == nullptr) { + HILOG_WARN("ConnectRecord is nullptr."); + continue; + } + connectRecord->CompleteConnect(resultCode); + abilityRecord->RemoveConnectRecordFromList(connectRecord); + RemoveConnectionRecordFromMap(connectRecord); + } + if (resultCode == LOAD_ABILITY_TIMEOUT) { + HILOG_DEBUG("Load time out , remove target service record from services map."); + RemoveServiceAbility(abilityRecord); + } +} + +void AbilityConnectManager::HandleStopTimeoutTask(const std::shared_ptr &abilityRecord) +{ + HILOG_DEBUG("Complete stop ability timeout start."); + std::lock_guard guard(Lock_); + CHECK_POINTER(abilityRecord); + TerminateDone(abilityRecord); +} + +void AbilityConnectManager::HandleDisconnectTask(const ConnectListType &connectlist) +{ + HILOG_DEBUG("Complete disconnect ability."); + std::lock_guard guard(Lock_); + for (auto &connectRecord : connectlist) { + if (!connectRecord) { + continue; + } + auto targetService = connectRecord->GetAbilityRecord(); + if (targetService && connectRecord->GetConnectState() == ConnectionState::DISCONNECTED && + targetService->GetConnectRecordList().size() > 1) { + HILOG_WARN("This record complete disconnect directly. recordId:%{public}d", connectRecord->GetRecordId()); + connectRecord->CompleteDisconnect(ERR_OK); + targetService->RemoveConnectRecordFromList(connectRecord); + RemoveConnectionRecordFromMap(connectRecord); + }; + } +} + +int AbilityConnectManager::DispatchInactive(const std::shared_ptr &abilityRecord, int state) +{ + CHECK_POINTER_AND_RETURN(eventHandler_, ERR_INVALID_VALUE); + if (!abilityRecord->IsAbilityState(AbilityState::INACTIVATING)) { + HILOG_ERROR("Ability transition life state error. expect %{public}d, actual %{public}d callback %{public}d", + AbilityState::INACTIVATING, + abilityRecord->GetAbilityState(), + state); + return ERR_INVALID_VALUE; + } + eventHandler_->RemoveEvent(AbilityManagerService::INACTIVE_TIMEOUT_MSG, abilityRecord->GetEventId()); + + // complete inactive + abilityRecord->SetAbilityState(AbilityState::INACTIVE); + if (abilityRecord->IsCreateByConnect()) { + ConnectAbility(abilityRecord); + } else { + CommandAbility(abilityRecord); + } + + return ERR_OK; +} + +int AbilityConnectManager::DispatchTerminate(const std::shared_ptr &abilityRecord) +{ + // remove terminate timeout task + if (eventHandler_ != nullptr) { + eventHandler_->RemoveTask(std::to_string(abilityRecord->GetEventId())); + } + // complete terminate + TerminateDone(abilityRecord); + return ERR_OK; +} + +void AbilityConnectManager::ConnectAbility(const std::shared_ptr &abilityRecord) +{ + CHECK_POINTER(abilityRecord); + PostTimeOutTask(abilityRecord, AbilityConnectManager::CONNECT_TIMEOUT_MSG); + abilityRecord->ConnectAbility(); +} + +void AbilityConnectManager::CommandAbility(const std::shared_ptr &abilityRecord) +{ + if (eventHandler_ != nullptr) { + // first connect ability, There is at most one connect record. + int recordId = abilityRecord->GetRecordId(); + abilityRecord->AddStartId(); + std::string taskName = std::string("CommandTimeout_") + std::to_string(recordId) + std::string("_") + + std::to_string(abilityRecord->GetStartId()); + auto timeoutTask = [abilityRecord, connectManager = shared_from_this()]() { + HILOG_ERROR("Command ability timeout. %{public}s", abilityRecord->GetAbilityInfo().name.c_str()); + }; + eventHandler_->PostTask(timeoutTask, taskName, AbilityManagerService::COMMAND_TIMEOUT); + // scheduling command ability + abilityRecord->CommandAbility(); + } +} + +void AbilityConnectManager::TerminateDone(const std::shared_ptr &abilityRecord) +{ + if (!abilityRecord->IsAbilityState(AbilityState::TERMINATING)) { + std::string expect = AbilityRecord::ConvertAbilityState(AbilityState::TERMINATING); + std::string actual = AbilityRecord::ConvertAbilityState(abilityRecord->GetAbilityState()); + HILOG_ERROR( + "Transition life state error. expect %{public}s, actual %{public}s", expect.c_str(), actual.c_str()); + return; + } + DelayedSingleton::GetInstance()->MoveToBackground(abilityRecord->GetToken()); +} + +bool AbilityConnectManager::IsAbilityConnected(const std::shared_ptr &abilityRecord, + const std::list> &connectRecordList) +{ + auto isMatch = [abilityRecord](auto connectRecord) -> bool { + if (abilityRecord == nullptr || connectRecord == nullptr) { + return false; + } + if (abilityRecord != connectRecord->GetAbilityRecord()) { + return false; + } + return true; + }; + return std::any_of(connectRecordList.begin(), connectRecordList.end(), isMatch); +} + +void AbilityConnectManager::RemoveConnectionRecordFromMap(const std::shared_ptr &connection) +{ + for (auto &connectCallback : connectMap_) { + auto &connectList = connectCallback.second; + auto connectRecord = std::find(connectList.begin(), connectList.end(), connection); + if (connectRecord != connectList.end()) { + HILOG_INFO("Remove connrecord(%{public}d) from maplist.", (*connectRecord)->GetRecordId()); + connectList.remove(connection); + if (connectList.empty()) { + HILOG_INFO("Remove connlist from map."); + sptr connect = iface_cast(connectCallback.first); + RemoveConnectDeathRecipient(connect); + connectMap_.erase(connectCallback.first); + } + return; + } + } +} + +void AbilityConnectManager::RemoveServiceAbility(const std::shared_ptr &abilityRecord) +{ + CHECK_POINTER(abilityRecord); + const AppExecFwk::AbilityInfo &abilityInfo = abilityRecord->GetAbilityInfo(); + std::string element = abilityInfo.deviceId + "/" + abilityInfo.bundleName + "/" + abilityInfo.name; + HILOG_INFO("Remove service(%{public}s) from map.", element.c_str()); + auto it = serviceMap_.find(element); + if (it != serviceMap_.end()) { + HILOG_INFO("Remove service(%{public}s) from map.", element.c_str()); + serviceMap_.erase(it); + } +} + +void AbilityConnectManager::AddConnectDeathRecipient(const sptr &connect) +{ + CHECK_POINTER(connect); + CHECK_POINTER(connect->AsObject()); + auto it = recipientMap_.find(connect->AsObject()); + if (it != recipientMap_.end()) { + HILOG_ERROR("This death recipient has been added."); + return; + } else { + sptr deathRecipient = new AbilityConnectCallbackRecipient( + std::bind(&AbilityConnectManager::OnCallBackDied, this, std::placeholders::_1)); + connect->AsObject()->AddDeathRecipient(deathRecipient); + recipientMap_.emplace(connect->AsObject(), deathRecipient); + } +} + +void AbilityConnectManager::RemoveConnectDeathRecipient(const sptr &connect) +{ + CHECK_POINTER(connect); + CHECK_POINTER(connect->AsObject()); + auto it = recipientMap_.find(connect->AsObject()); + if (it != recipientMap_.end()) { + it->first->RemoveDeathRecipient(it->second); + recipientMap_.erase(it); + return; + } +} + +void AbilityConnectManager::OnCallBackDied(const wptr &remote) +{ + auto object = remote.promote(); + CHECK_POINTER(object); + if (eventHandler_) { + auto task = [object, connectManager = shared_from_this()]() { connectManager->HandleCallBackDiedTask(object); }; + eventHandler_->PostTask(task, TASK_ON_CALLBACK_DIED); + } +} + +void AbilityConnectManager::HandleCallBackDiedTask(const sptr &connect) +{ + HILOG_INFO("Handle call back died task."); + std::lock_guard guard(Lock_); + CHECK_POINTER(connect); + auto it = connectMap_.find(connect); + if (it != connectMap_.end()) { + ConnectListType connectRecordList = it->second; + for (auto &connRecord : connectRecordList) { + connRecord->ClearConnCallBack(); + } + } else { + HILOG_INFO("Died object can't find from conn map."); + return; + } + sptr object = iface_cast(connect); + DisconnectAbilityLocked(object); +} + +void AbilityConnectManager::OnAbilityDied(const std::shared_ptr &abilityRecord) +{ + HILOG_INFO("On ability died."); + CHECK_POINTER(abilityRecord); + if (abilityRecord->GetAbilityInfo().type != AbilityType::SERVICE) { + HILOG_DEBUG("Ability type is not service."); + return; + } + if (eventHandler_) { + auto task = [abilityRecord, connectManager = shared_from_this()]() { + connectManager->HandleAbilityDiedTask(abilityRecord); + }; + eventHandler_->PostTask(task, TASK_ON_ABILITY_DIED); + } +} + +void AbilityConnectManager::HandleAbilityDiedTask(const std::shared_ptr &abilityRecord) +{ + HILOG_INFO("Handle ability died task."); + std::lock_guard guard(Lock_); + CHECK_POINTER(abilityRecord); + if (!GetServiceRecordByToken(abilityRecord->GetToken())) { + HILOG_ERROR("Died ability record is not exist in service map."); + return; + } + + ConnectListType connlist = abilityRecord->GetConnectRecordList(); + for (auto &connectRecord : connlist) { + HILOG_WARN("This record complete disconnect directly. recordId:%{public}d", connectRecord->GetRecordId()); + connectRecord->CompleteDisconnect(ERR_OK); + abilityRecord->RemoveConnectRecordFromList(connectRecord); + RemoveConnectionRecordFromMap(connectRecord); + } + + RemoveServiceAbility(abilityRecord); +} + +void AbilityConnectManager::DumpState(std::vector &info, const std::string &args) const +{ + if (!args.empty()) { + auto it = std::find_if(serviceMap_.begin(), serviceMap_.end(), [&args](const auto &service) { + return service.first.compare(args) == 0; + }); + if (it != serviceMap_.end()) { + info.emplace_back("uri [ " + it->first + " ]"); + it->second->DumpService(info); + } else { + info.emplace_back(args + ": Nothing to dump."); + } + } else { + info.emplace_back("serviceAbilityRecords:"); + for (auto &&service : serviceMap_) { + info.emplace_back(" uri [" + service.first + "]"); + service.second->DumpService(info); + } + } +} +} // namespace AAFwk +} // namespace OHOS diff --git a/tools/services/abilitymgr/src/ability_event_handler.cpp b/tools/services/abilitymgr/src/ability_event_handler.cpp new file mode 100644 index 00000000000..aa259478921 --- /dev/null +++ b/tools/services/abilitymgr/src/ability_event_handler.cpp @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ability_event_handler.h" + +#include "hilog_wrapper.h" +#include "ability_util.h" +#include "ability_manager_service.h" + +namespace OHOS { +namespace AAFwk { +AbilityEventHandler::AbilityEventHandler( + const std::shared_ptr &runner, const std::weak_ptr &server) + : AppExecFwk::EventHandler(runner), server_(server) +{ + HILOG_INFO("Constructors."); +} + +void AbilityEventHandler::ProcessEvent(const AppExecFwk::InnerEvent::Pointer &event) +{ + CHECK_POINTER(event); + HILOG_DEBUG("Event id obtained: %{public}u.", event->GetInnerEventId()); + switch (event->GetInnerEventId()) { + case AbilityManagerService::LOAD_TIMEOUT_MSG: { + ProcessLoadTimeOut(event->GetParam()); + break; + } + case AbilityManagerService::ACTIVE_TIMEOUT_MSG: { + ProcessActiveTimeOut(event->GetParam()); + break; + } + case AbilityManagerService::INACTIVE_TIMEOUT_MSG: { + HILOG_INFO("Inactive timeout."); + // inactivate pre ability immediately in case blocking next ability start + ProcessInactiveTimeOut(event->GetParam()); + break; + } + default: { + HILOG_WARN("Unsupported timeout message."); + break; + } + } +} + +void AbilityEventHandler::ProcessLoadTimeOut(int64_t eventId) +{ + HILOG_INFO("Attach timeout."); + auto server = server_.lock(); + CHECK_POINTER(server); + server->HandleLoadTimeOut(eventId); +} + +void AbilityEventHandler::ProcessActiveTimeOut(int64_t eventId) +{ + HILOG_INFO("Active timeout."); + auto server = server_.lock(); + CHECK_POINTER(server); + server->HandleActiveTimeOut(eventId); +} +void AbilityEventHandler::ProcessInactiveTimeOut(int64_t eventId) +{ + HILOG_INFO("Inactive timeout."); + auto server = server_.lock(); + CHECK_POINTER(server); + server->HandleInactiveTimeOut(eventId); +} +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/abilitymgr/src/ability_manager_client.cpp b/tools/services/abilitymgr/src/ability_manager_client.cpp new file mode 100644 index 00000000000..683fce6cdc3 --- /dev/null +++ b/tools/services/abilitymgr/src/ability_manager_client.cpp @@ -0,0 +1,542 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ability_manager_client.h" + +#include "string_ex.h" + +#include "ability_manager_interface.h" +#include "hilog_wrapper.h" +#include "ipc_skeleton.h" +#include "iservice_registry.h" +#include "if_system_ability_manager.h" +#include "system_ability_definition.h" + +namespace OHOS { +namespace AAFwk { +std::shared_ptr AbilityManagerClient::instance_ = nullptr; +std::mutex AbilityManagerClient::mutex_; + +#define CHECK_REMOTE_OBJECT(object) \ + if (!object) { \ + if (ERR_OK != Connect()) { \ + HILOG_ERROR("ability service can't connect."); \ + return; \ + } \ + } + +#define CHECK_REMOTE_OBJECT_AND_RETURN(object, value) \ + if (!object) { \ + if (ERR_OK != Connect()) { \ + HILOG_ERROR("ability service can't connect."); \ + return value; \ + } \ + } + +std::shared_ptr AbilityManagerClient::GetInstance() +{ + if (instance_ == nullptr) { + std::lock_guard lock_l(mutex_); + if (instance_ == nullptr) { + instance_ = std::make_shared(); + } + } + return instance_; +} + +AbilityManagerClient::AbilityManagerClient() +{} + +AbilityManagerClient::~AbilityManagerClient() +{} + +ErrCode AbilityManagerClient::AttachAbilityThread( + const sptr &scheduler, const sptr &token) +{ + CHECK_REMOTE_OBJECT_AND_RETURN(remoteObject_, ABILITY_SERVICE_NOT_CONNECTED); + sptr abms = iface_cast(remoteObject_); + return abms->AttachAbilityThread(scheduler, token); +} + +ErrCode AbilityManagerClient::AbilityTransitionDone(const sptr &token, int state) +{ + CHECK_REMOTE_OBJECT_AND_RETURN(remoteObject_, ABILITY_SERVICE_NOT_CONNECTED); + sptr abms = iface_cast(remoteObject_); + return abms->AbilityTransitionDone(token, state); +} + +ErrCode AbilityManagerClient::ScheduleConnectAbilityDone( + const sptr &token, const sptr &remoteObject) +{ + CHECK_REMOTE_OBJECT_AND_RETURN(remoteObject_, ABILITY_SERVICE_NOT_CONNECTED); + sptr abms = iface_cast(remoteObject_); + return abms->ScheduleConnectAbilityDone(token, remoteObject); +} + +ErrCode AbilityManagerClient::ScheduleDisconnectAbilityDone(const sptr &token) +{ + CHECK_REMOTE_OBJECT_AND_RETURN(remoteObject_, ABILITY_SERVICE_NOT_CONNECTED); + sptr abms = iface_cast(remoteObject_); + return abms->ScheduleDisconnectAbilityDone(token); +} + +ErrCode AbilityManagerClient::ScheduleCommandAbilityDone(const sptr &token) +{ + CHECK_REMOTE_OBJECT_AND_RETURN(remoteObject_, ABILITY_SERVICE_NOT_CONNECTED); + sptr abms = iface_cast(remoteObject_); + return abms->ScheduleCommandAbilityDone(token); +} + +void AbilityManagerClient::AddWindowInfo(const sptr &token, int32_t windowToken) +{ + CHECK_REMOTE_OBJECT(remoteObject_); + sptr abms = iface_cast(remoteObject_); + abms->AddWindowInfo(token, windowToken); +} + +ErrCode AbilityManagerClient::StartAbility(const Want &want, int requestCode) +{ + CHECK_REMOTE_OBJECT_AND_RETURN(remoteObject_, ABILITY_SERVICE_NOT_CONNECTED); + sptr abms = iface_cast(remoteObject_); + return abms->StartAbility(want, requestCode); +} + +ErrCode AbilityManagerClient::StartAbility(const Want &want, const sptr &callerToken, int requestCode) +{ + CHECK_REMOTE_OBJECT_AND_RETURN(remoteObject_, ABILITY_SERVICE_NOT_CONNECTED); + sptr abms = iface_cast(remoteObject_); + return abms->StartAbility(want, callerToken, requestCode); +} + +ErrCode AbilityManagerClient::StartAbility(const Want &want, const AbilityStartSetting &abilityStartSetting, + const sptr &callerToken, int requestCode) +{ + CHECK_REMOTE_OBJECT_AND_RETURN(remoteObject_, ABILITY_SERVICE_NOT_CONNECTED); + sptr abms = iface_cast(remoteObject_); + return abms->StartAbility(want, abilityStartSetting, callerToken, requestCode); +} + +ErrCode AbilityManagerClient::TerminateAbility(const sptr &token, int resultCode, const Want *resultWant) +{ + CHECK_REMOTE_OBJECT_AND_RETURN(remoteObject_, ABILITY_SERVICE_NOT_CONNECTED); + sptr abms = iface_cast(remoteObject_); + return abms->TerminateAbility(token, resultCode, resultWant); +} + +ErrCode AbilityManagerClient::TerminateAbility(const sptr &callerToken, int requestCode) +{ + CHECK_REMOTE_OBJECT_AND_RETURN(remoteObject_, ABILITY_SERVICE_NOT_CONNECTED); + sptr abms = iface_cast(remoteObject_); + return abms->TerminateAbilityByCaller(callerToken, requestCode); +} + +ErrCode AbilityManagerClient::TerminateAbilityResult(const sptr &token, int startId) +{ + CHECK_REMOTE_OBJECT_AND_RETURN(remoteObject_, ABILITY_SERVICE_NOT_CONNECTED); + sptr abms = iface_cast(remoteObject_); + return abms->TerminateAbilityResult(token, startId); +} + +ErrCode AbilityManagerClient::ConnectAbility( + const Want &want, const sptr &connect, const sptr &callerToken) +{ + CHECK_REMOTE_OBJECT_AND_RETURN(remoteObject_, ABILITY_SERVICE_NOT_CONNECTED); + sptr abms = iface_cast(remoteObject_); + return abms->ConnectAbility(want, connect, callerToken); +} + +ErrCode AbilityManagerClient::DisconnectAbility(const sptr &connect) +{ + CHECK_REMOTE_OBJECT_AND_RETURN(remoteObject_, ABILITY_SERVICE_NOT_CONNECTED); + sptr abms = iface_cast(remoteObject_); + return abms->DisconnectAbility(connect); +} + +sptr AbilityManagerClient::AcquireDataAbility( + const Uri &uri, bool tryBind, const sptr &callerToken) +{ + CHECK_REMOTE_OBJECT_AND_RETURN(remoteObject_, nullptr); + sptr abms = iface_cast(remoteObject_); + return abms->AcquireDataAbility(uri, tryBind, callerToken); +} + +ErrCode AbilityManagerClient::ReleaseDataAbility( + sptr dataAbilityScheduler, const sptr &callerToken) +{ + CHECK_REMOTE_OBJECT_AND_RETURN(remoteObject_, ABILITY_SERVICE_NOT_CONNECTED); + sptr abms = iface_cast(remoteObject_); + return abms->ReleaseDataAbility(dataAbilityScheduler, callerToken); +} + +ErrCode AbilityManagerClient::DumpState(const std::string &args, std::vector &state) +{ + CHECK_REMOTE_OBJECT_AND_RETURN(remoteObject_, ABILITY_SERVICE_NOT_CONNECTED); + sptr abms = iface_cast(remoteObject_); + abms->DumpState(args, state); + return ERR_OK; +} + +ErrCode AbilityManagerClient::Connect() +{ + std::lock_guard lock(mutex_); + if (remoteObject_ != nullptr) { + return ERR_OK; + } + sptr systemManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + if (systemManager == nullptr) { + HILOG_ERROR("Fail to get registry."); + return GET_ABILITY_SERVICE_FAILED; + } + remoteObject_ = systemManager->GetSystemAbility(ABILITY_MGR_SERVICE_ID); + if (remoteObject_ == nullptr) { + HILOG_ERROR("Fail to connect ability manager service."); + return GET_ABILITY_SERVICE_FAILED; + } + HILOG_DEBUG("Connect ability manager service success."); + return ERR_OK; +} + +ErrCode AbilityManagerClient::GetAllStackInfo(StackInfo &stackInfo) +{ + CHECK_REMOTE_OBJECT_AND_RETURN(remoteObject_, ABILITY_SERVICE_NOT_CONNECTED); + sptr abms = iface_cast(remoteObject_); + return abms->GetAllStackInfo(stackInfo); +} + +ErrCode AbilityManagerClient::StopServiceAbility(const Want &want) +{ + CHECK_REMOTE_OBJECT_AND_RETURN(remoteObject_, ABILITY_SERVICE_NOT_CONNECTED); + sptr abms = iface_cast(remoteObject_); + return abms->StopServiceAbility(want); +} + +ErrCode AbilityManagerClient::GetRecentMissions( + const int32_t numMax, const int32_t flags, std::vector &recentList) +{ + CHECK_REMOTE_OBJECT_AND_RETURN(remoteObject_, ABILITY_SERVICE_NOT_CONNECTED); + sptr abms = iface_cast(remoteObject_); + return abms->GetRecentMissions(numMax, flags, recentList); +} + +ErrCode AbilityManagerClient::GetMissionSnapshot(const int32_t missionId, MissionSnapshotInfo &snapshot) +{ + CHECK_REMOTE_OBJECT_AND_RETURN(remoteObject_, ABILITY_SERVICE_NOT_CONNECTED); + sptr abms = iface_cast(remoteObject_); + return abms->GetMissionSnapshot(missionId, snapshot); +} + +ErrCode AbilityManagerClient::MoveMissionToTop(int32_t missionId) +{ + CHECK_REMOTE_OBJECT_AND_RETURN(remoteObject_, ABILITY_SERVICE_NOT_CONNECTED); + sptr abms = iface_cast(remoteObject_); + return abms->MoveMissionToTop(missionId); +} + +ErrCode AbilityManagerClient::MoveMissionToEnd(const sptr &token, const bool nonFirst) +{ + CHECK_REMOTE_OBJECT_AND_RETURN(remoteObject_, ABILITY_SERVICE_NOT_CONNECTED); + sptr abms = iface_cast(remoteObject_); + return abms->MoveMissionToEnd(token, nonFirst); +} + +ErrCode AbilityManagerClient::RemoveMissions(std::vector missionId) +{ + CHECK_REMOTE_OBJECT_AND_RETURN(remoteObject_, ABILITY_SERVICE_NOT_CONNECTED); + sptr abms = iface_cast(remoteObject_); + int error = ERR_OK; + for (auto it : missionId) { + error = abms->RemoveMission(it); + if (error != ERR_OK) { + HILOG_ERROR("Failed, error:%{private}d", error); + break; + } + } + + return error; +} + +ErrCode AbilityManagerClient::RemoveStack(int id) +{ + CHECK_REMOTE_OBJECT_AND_RETURN(remoteObject_, ABILITY_SERVICE_NOT_CONNECTED); + sptr abms = iface_cast(remoteObject_); + return abms->RemoveStack(id); +} + +ErrCode AbilityManagerClient::KillProcess(const std::string &bundleName) +{ + CHECK_REMOTE_OBJECT_AND_RETURN(remoteObject_, ABILITY_SERVICE_NOT_CONNECTED); + sptr abms = iface_cast(remoteObject_); + return abms->KillProcess(bundleName); +} + +ErrCode AbilityManagerClient::IsFirstInMission(const sptr &token) +{ + if (token == nullptr) { + HILOG_ERROR("token is nullptr"); + return ERR_NULL_OBJECT; + } + CHECK_REMOTE_OBJECT_AND_RETURN(remoteObject_, ABILITY_SERVICE_NOT_CONNECTED); + sptr abms = iface_cast(remoteObject_); + if (!(abms->IsFirstInMission(token))) { + return NO_FIRST_IN_MISSION; + } + return ERR_OK; +} + +ErrCode AbilityManagerClient::CompelVerifyPermission( + const std::string &permission, int pid, int uid, std::string &message) +{ + CHECK_REMOTE_OBJECT_AND_RETURN(remoteObject_, ABILITY_SERVICE_NOT_CONNECTED); + sptr abms = iface_cast(remoteObject_); + return abms->CompelVerifyPermission(permission, pid, uid, message); +} + +ErrCode AbilityManagerClient::MoveMissionToFloatingStack(const MissionOption &missionOption) +{ + CHECK_REMOTE_OBJECT_AND_RETURN(remoteObject_, ABILITY_SERVICE_NOT_CONNECTED); + sptr abms = iface_cast(remoteObject_); + return abms->MoveMissionToFloatingStack(missionOption); +} + +ErrCode AbilityManagerClient::MoveMissionToSplitScreenStack(const MissionOption &missionOption) +{ + CHECK_REMOTE_OBJECT_AND_RETURN(remoteObject_, ABILITY_SERVICE_NOT_CONNECTED); + sptr abms = iface_cast(remoteObject_); + return abms->MoveMissionToSplitScreenStack(missionOption); +} + +ErrCode AbilityManagerClient::MinimizeMultiWindow(int missionId) +{ + CHECK_REMOTE_OBJECT_AND_RETURN(remoteObject_, ABILITY_SERVICE_NOT_CONNECTED); + sptr abms = iface_cast(remoteObject_); + return abms->MinimizeMultiWindow(missionId); +} + +ErrCode AbilityManagerClient::MaximizeMultiWindow(int missionId) +{ + CHECK_REMOTE_OBJECT_AND_RETURN(remoteObject_, ABILITY_SERVICE_NOT_CONNECTED); + sptr abms = iface_cast(remoteObject_); + return abms->MaximizeMultiWindow(missionId); +} + +ErrCode AbilityManagerClient::ChangeFocusAbility( + const sptr &lostFocusToken, const sptr &getFocusToken) +{ + CHECK_REMOTE_OBJECT_AND_RETURN(remoteObject_, ABILITY_SERVICE_NOT_CONNECTED); + sptr abms = iface_cast(remoteObject_); + return abms->ChangeFocusAbility(lostFocusToken, getFocusToken); +} + +ErrCode AbilityManagerClient::GetFloatingMissions(std::vector &list) +{ + CHECK_REMOTE_OBJECT_AND_RETURN(remoteObject_, ABILITY_SERVICE_NOT_CONNECTED); + sptr abms = iface_cast(remoteObject_); + return abms->GetFloatingMissions(list); +} + +ErrCode AbilityManagerClient::CloseMultiWindow(int missionId) +{ + CHECK_REMOTE_OBJECT_AND_RETURN(remoteObject_, ABILITY_SERVICE_NOT_CONNECTED); + sptr abms = iface_cast(remoteObject_); + return abms->CloseMultiWindow(missionId); +} + +ErrCode AbilityManagerClient::SetMissionStackSetting(const StackSetting &stackSetting) +{ + CHECK_REMOTE_OBJECT_AND_RETURN(remoteObject_, ABILITY_SERVICE_NOT_CONNECTED); + sptr abms = iface_cast(remoteObject_); + return abms->SetMissionStackSetting(stackSetting); +} + +ErrCode AbilityManagerClient::PowerOff() +{ + CHECK_REMOTE_OBJECT_AND_RETURN(remoteObject_, ABILITY_SERVICE_NOT_CONNECTED); + sptr abms = iface_cast(remoteObject_); + return abms->PowerOff(); +} + +ErrCode AbilityManagerClient::PowerOn() +{ + CHECK_REMOTE_OBJECT_AND_RETURN(remoteObject_, ABILITY_SERVICE_NOT_CONNECTED); + sptr abms = iface_cast(remoteObject_); + return abms->PowerOn(); +} + +ErrCode AbilityManagerClient::LockMission(int missionId) +{ + CHECK_REMOTE_OBJECT_AND_RETURN(remoteObject_, ABILITY_SERVICE_NOT_CONNECTED); + sptr abms = iface_cast(remoteObject_); + return abms->LockMission(missionId); +} + +ErrCode AbilityManagerClient::UnlockMission(int missionId) +{ + CHECK_REMOTE_OBJECT_AND_RETURN(remoteObject_, ABILITY_SERVICE_NOT_CONNECTED); + sptr abms = iface_cast(remoteObject_); + return abms->UnlockMission(missionId); +} + +ErrCode AbilityManagerClient::SetMissionDescriptionInfo( + const sptr &token, const MissionDescriptionInfo &description) +{ + CHECK_REMOTE_OBJECT_AND_RETURN(remoteObject_, ABILITY_SERVICE_NOT_CONNECTED); + sptr abms = iface_cast(remoteObject_); + return abms->SetMissionDescriptionInfo(token, description); +} + +ErrCode AbilityManagerClient::GetMissionLockModeState() +{ + CHECK_REMOTE_OBJECT_AND_RETURN(remoteObject_, ABILITY_SERVICE_NOT_CONNECTED); + sptr abms = iface_cast(remoteObject_); + return abms->GetMissionLockModeState(); +} + +ErrCode AbilityManagerClient::UpdateConfiguration(const DummyConfiguration &config) +{ + CHECK_REMOTE_OBJECT_AND_RETURN(remoteObject_, ABILITY_SERVICE_NOT_CONNECTED); + sptr abms = iface_cast(remoteObject_); + return abms->UpdateConfiguration(config); +} + +sptr AbilityManagerClient::GetWantSender( + const WantSenderInfo &wantSenderInfo, const sptr &callerToken) +{ + CHECK_REMOTE_OBJECT_AND_RETURN(remoteObject_, nullptr); + sptr abms = iface_cast(remoteObject_); + return abms->GetWantSender(wantSenderInfo, callerToken); +} + +ErrCode AbilityManagerClient::SendWantSender(const sptr &target, const SenderInfo &senderInfo) +{ + CHECK_REMOTE_OBJECT_AND_RETURN(remoteObject_, ABILITY_SERVICE_NOT_CONNECTED); + sptr abms = iface_cast(remoteObject_); + return abms->SendWantSender(target, senderInfo); +} + +void AbilityManagerClient::CancelWantSender(const sptr &sender) +{ + CHECK_REMOTE_OBJECT(remoteObject_); + sptr abms = iface_cast(remoteObject_); + abms->CancelWantSender(sender); +} + +ErrCode AbilityManagerClient::GetPendingWantUid(const sptr &target, int32_t &uid) +{ + CHECK_REMOTE_OBJECT_AND_RETURN(remoteObject_, ABILITY_SERVICE_NOT_CONNECTED); + if (target == nullptr) { + HILOG_ERROR("target is nullptr."); + return ABILITY_SERVICE_NOT_CONNECTED; + } + sptr abms = iface_cast(remoteObject_); + uid = abms->GetPendingWantUid(target); + return ERR_OK; +} + +ErrCode AbilityManagerClient::GetPendingWantUserId(const sptr &target, int32_t &userId) +{ + CHECK_REMOTE_OBJECT_AND_RETURN(remoteObject_, ABILITY_SERVICE_NOT_CONNECTED); + if (target == nullptr) { + HILOG_ERROR("target is nullptr."); + return ABILITY_SERVICE_NOT_CONNECTED; + } + sptr abms = iface_cast(remoteObject_); + userId = abms->GetPendingWantUserId(target); + return ERR_OK; +} + +ErrCode AbilityManagerClient::GetPendingWantBundleName(const sptr &target, std::string &bundleName) +{ + CHECK_REMOTE_OBJECT_AND_RETURN(remoteObject_, ABILITY_SERVICE_NOT_CONNECTED); + if (target == nullptr) { + HILOG_ERROR("target is nullptr."); + return ABILITY_SERVICE_NOT_CONNECTED; + } + sptr abms = iface_cast(remoteObject_); + bundleName = abms->GetPendingWantBundleName(target); + return ERR_OK; +} + +ErrCode AbilityManagerClient::GetPendingWantCode(const sptr &target, int32_t &code) +{ + CHECK_REMOTE_OBJECT_AND_RETURN(remoteObject_, ABILITY_SERVICE_NOT_CONNECTED); + if (target == nullptr) { + HILOG_ERROR("target is nullptr."); + return ABILITY_SERVICE_NOT_CONNECTED; + } + sptr abms = iface_cast(remoteObject_); + code = abms->GetPendingWantCode(target); + return ERR_OK; +} + +ErrCode AbilityManagerClient::GetPendingWantType(const sptr &target, int32_t &type) +{ + CHECK_REMOTE_OBJECT_AND_RETURN(remoteObject_, ABILITY_SERVICE_NOT_CONNECTED); + if (target == nullptr) { + HILOG_ERROR("target is nullptr."); + return ABILITY_SERVICE_NOT_CONNECTED; + } + sptr abms = iface_cast(remoteObject_); + type = abms->GetPendingWantType(target); + type < 0 ? type = 0 : type; + return ERR_OK; +} + +void AbilityManagerClient::RegisterCancelListener(const sptr &sender, const sptr &recevier) +{ + CHECK_REMOTE_OBJECT(remoteObject_); + if (sender == nullptr) { + HILOG_ERROR("sender is nullptr."); + return; + } + if (recevier == nullptr) { + HILOG_ERROR("recevier is nullptr."); + return; + } + sptr abms = iface_cast(remoteObject_); + abms->RegisterCancelListener(sender, recevier); +} + +void AbilityManagerClient::UnregisterCancelListener( + const sptr &sender, const sptr &recevier) +{ + CHECK_REMOTE_OBJECT(remoteObject_); + if (sender == nullptr) { + HILOG_ERROR("sender is nullptr."); + return; + } + if (recevier == nullptr) { + HILOG_ERROR("recevier is nullptr."); + return; + } + sptr abms = iface_cast(remoteObject_); + abms->UnregisterCancelListener(sender, recevier); +} + +ErrCode AbilityManagerClient::GetPendingRequestWant(const sptr &target, std::shared_ptr &want) +{ + CHECK_REMOTE_OBJECT_AND_RETURN(remoteObject_, ABILITY_SERVICE_NOT_CONNECTED); + if (target == nullptr) { + HILOG_ERROR("target is nullptr."); + return ABILITY_SERVICE_NOT_CONNECTED; + } + if (want == nullptr) { + HILOG_ERROR("want is nullptr."); + return ABILITY_SERVICE_NOT_CONNECTED; + } + sptr abms = iface_cast(remoteObject_); + return abms->GetPendingRequestWant(target, want); +} +} // namespace AAFwk +} // namespace OHOS diff --git a/tools/services/abilitymgr/src/ability_manager_proxy.cpp b/tools/services/abilitymgr/src/ability_manager_proxy.cpp new file mode 100644 index 00000000000..23e742003d3 --- /dev/null +++ b/tools/services/abilitymgr/src/ability_manager_proxy.cpp @@ -0,0 +1,1338 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ability_manager_proxy.h" + +#include "errors.h" +#include "string_ex.h" + +#include "ability_connect_callback_proxy.h" +#include "ability_connect_callback_stub.h" +#include "ability_manager_errors.h" +#include "ability_scheduler_proxy.h" +#include "ability_scheduler_stub.h" + +namespace OHOS { +namespace AAFwk { +bool AbilityManagerProxy::WriteInterfaceToken(MessageParcel &data) +{ + if (!data.WriteInterfaceToken(AbilityManagerProxy::GetDescriptor())) { + HILOG_ERROR("write interface token failed."); + return false; + } + return true; +} + +int AbilityManagerProxy::StartAbility(const Want &want, int requestCode) +{ + int error; + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!WriteInterfaceToken(data)) { + return INNER_ERR; + } + if (!data.WriteParcelable(&want)) { + HILOG_ERROR("want write failed."); + return INNER_ERR; + } + if (!data.WriteInt32(requestCode)) { + HILOG_ERROR("requestCode write failed."); + return INNER_ERR; + } + + error = Remote()->SendRequest(IAbilityManager::START_ABILITY, data, reply, option); + if (error != NO_ERROR) { + HILOG_ERROR("Send request error: %{public}d", error); + return error; + } + return reply.ReadInt32(); +} + +int AbilityManagerProxy::StartAbility(const Want &want, const AbilityStartSetting &abilityStartSetting, + const sptr &callerToken, int requestCode) +{ + int error; + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!WriteInterfaceToken(data)) { + return INNER_ERR; + } + if (!data.WriteParcelable(&want)) { + HILOG_ERROR("want write failed."); + return INNER_ERR; + } + if (!data.WriteParcelable(&abilityStartSetting)) { + HILOG_ERROR("abilityStartSetting write failed."); + return INNER_ERR; + } + if (!data.WriteParcelable(callerToken)) { + HILOG_ERROR("callerToken write failed."); + return INNER_ERR; + } + if (!data.WriteInt32(requestCode)) { + HILOG_ERROR("requestCode write failed."); + return INNER_ERR; + } + error = Remote()->SendRequest(IAbilityManager::START_ABILITY_FOR_SETTINGS, data, reply, option); + if (error != NO_ERROR) { + HILOG_ERROR("Send request error: %{public}d", error); + return error; + } + return reply.ReadInt32(); +} + +int AbilityManagerProxy::StartAbility(const Want &want, const sptr &callerToken, int requestCode) +{ + int error; + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!WriteInterfaceToken(data)) { + return INNER_ERR; + } + if (!data.WriteParcelable(&want)) { + HILOG_ERROR("want write failed."); + return INNER_ERR; + } + if (!data.WriteParcelable(callerToken)) { + HILOG_ERROR("callerToken write failed."); + return INNER_ERR; + } + if (!data.WriteInt32(requestCode)) { + HILOG_ERROR("requestCode write failed."); + return INNER_ERR; + } + + error = Remote()->SendRequest(IAbilityManager::START_ABILITY_ADD_CALLER, data, reply, option); + if (error != NO_ERROR) { + HILOG_ERROR("Send request error: %{public}d", error); + return error; + } + return reply.ReadInt32(); +} + +int AbilityManagerProxy::TerminateAbility(const sptr &token, int resultCode, const Want *resultWant) +{ + int error; + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!WriteInterfaceToken(data)) { + return INNER_ERR; + } + if (!data.WriteParcelable(token) || !data.WriteInt32(resultCode) || !data.WriteParcelable(resultWant)) { + HILOG_ERROR("data write failed."); + return INNER_ERR; + } + error = Remote()->SendRequest(IAbilityManager::TERMINATE_ABILITY, data, reply, option); + if (error != NO_ERROR) { + HILOG_ERROR("Send request error: %{public}d", error); + return error; + } + return reply.ReadInt32(); +} + +int AbilityManagerProxy::TerminateAbilityByCaller(const sptr &callerToken, int requestCode) +{ + int error; + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!WriteInterfaceToken(data)) { + return INNER_ERR; + } + if (!data.WriteParcelable(callerToken) || !data.WriteInt32(requestCode)) { + HILOG_ERROR("data write failed."); + return INNER_ERR; + } + error = Remote()->SendRequest(IAbilityManager::TERMINATE_ABILITY_BY_CALLER, data, reply, option); + if (error != NO_ERROR) { + HILOG_ERROR("Send request error: %{public}d", error); + return error; + } + return reply.ReadInt32(); +} + +int AbilityManagerProxy::ConnectAbility( + const Want &want, const sptr &connect, const sptr &callerToken) +{ + int error; + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!WriteInterfaceToken(data)) { + return INNER_ERR; + } + if (!data.WriteParcelable(&want)) { + HILOG_ERROR("want write failed."); + return ERR_INVALID_VALUE; + } + if (connect == nullptr) { + HILOG_ERROR("connect ability fail, connect is nullptr"); + return ERR_INVALID_VALUE; + } + if (!data.WriteParcelable(connect->AsObject())) { + HILOG_ERROR("connect write failed."); + return ERR_INVALID_VALUE; + } + if (!data.WriteParcelable(callerToken)) { + HILOG_ERROR("callerToken write failed."); + return ERR_INVALID_VALUE; + } + + error = Remote()->SendRequest(IAbilityManager::CONNECT_ABILITY, data, reply, option); + if (error != NO_ERROR) { + HILOG_ERROR("Send request error: %{public}d", error); + return error; + } + return reply.ReadInt32(); +} + +int AbilityManagerProxy::DisconnectAbility(const sptr &connect) +{ + int error; + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (connect == nullptr) { + HILOG_ERROR("disconnect ability fail, connect is nullptr"); + return ERR_INVALID_VALUE; + } + if (!WriteInterfaceToken(data)) { + return INNER_ERR; + } + if (!data.WriteParcelable(connect->AsObject())) { + HILOG_ERROR("connect write failed."); + return ERR_INVALID_VALUE; + } + + error = Remote()->SendRequest(IAbilityManager::DISCONNECT_ABILITY, data, reply, option); + if (error != NO_ERROR) { + HILOG_ERROR("Send request error: %{public}d", error); + return error; + } + return reply.ReadInt32(); +} + +sptr AbilityManagerProxy::AcquireDataAbility( + const Uri &uri, bool tryBind, const sptr &callerToken) +{ + int error; + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!callerToken) { + HILOG_ERROR("invalid parameters for acquire data ability."); + return nullptr; + } + if (!WriteInterfaceToken(data)) { + return nullptr; + } + if (!data.WriteString(uri.ToString()) || !data.WriteBool(tryBind) || !data.WriteParcelable(callerToken)) { + HILOG_ERROR("data write failed."); + return nullptr; + } + error = Remote()->SendRequest(IAbilityManager::ACQUIRE_DATA_ABILITY, data, reply, option); + if (error != NO_ERROR) { + HILOG_ERROR("Send request error: %{public}d", error); + return nullptr; + } + + return iface_cast(reply.ReadParcelable()); +} + +int AbilityManagerProxy::ReleaseDataAbility( + sptr dataAbilityScheduler, const sptr &callerToken) +{ + int error; + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!dataAbilityScheduler || !callerToken) { + return ERR_INVALID_VALUE; + } + if (!WriteInterfaceToken(data)) { + return INNER_ERR; + } + if (!data.WriteParcelable(dataAbilityScheduler->AsObject()) || !data.WriteParcelable(callerToken)) { + HILOG_ERROR("data write failed."); + return INNER_ERR; + } + error = Remote()->SendRequest(IAbilityManager::RELEASE_DATA_ABILITY, data, reply, option); + if (error != NO_ERROR) { + HILOG_ERROR("Send request error: %{public}d", error); + return error; + } + return reply.ReadInt32(); +} + +int AbilityManagerProxy::AttachAbilityThread(const sptr &scheduler, const sptr &token) +{ + int error; + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (scheduler == nullptr) { + return ERR_INVALID_VALUE; + } + if (!WriteInterfaceToken(data)) { + return INNER_ERR; + } + if (!data.WriteParcelable(scheduler->AsObject()) || !data.WriteParcelable(token)) { + HILOG_ERROR("data write failed."); + return INNER_ERR; + } + error = Remote()->SendRequest(IAbilityManager::ATTACH_ABILITY_THREAD, data, reply, option); + if (error != NO_ERROR) { + HILOG_ERROR("Send request error: %{public}d", error); + return error; + } + return reply.ReadInt32(); +} + +int AbilityManagerProxy::AbilityTransitionDone(const sptr &token, int state) +{ + int error; + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!WriteInterfaceToken(data)) { + return INNER_ERR; + } + if (!data.WriteParcelable(token) || !data.WriteInt32(state)) { + HILOG_ERROR("data write failed."); + return INNER_ERR; + } + error = Remote()->SendRequest(IAbilityManager::ABILITY_TRANSITION_DONE, data, reply, option); + if (error != NO_ERROR) { + HILOG_ERROR("Send request error: %{public}d", error); + return error; + } + return reply.ReadInt32(); +} + +int AbilityManagerProxy::ScheduleConnectAbilityDone( + const sptr &token, const sptr &remoteObject) +{ + int error; + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!WriteInterfaceToken(data)) { + return INNER_ERR; + } + if (!data.WriteParcelable(token)) { + HILOG_ERROR("token write failed."); + return ERR_INVALID_VALUE; + } + if (!data.WriteParcelable(remoteObject)) { + HILOG_ERROR("remoteObject write failed."); + return ERR_INVALID_VALUE; + } + + error = Remote()->SendRequest(IAbilityManager::CONNECT_ABILITY_DONE, data, reply, option); + if (error != NO_ERROR) { + HILOG_ERROR("Send request error: %{public}d", error); + return error; + } + return reply.ReadInt32(); +} + +int AbilityManagerProxy::ScheduleDisconnectAbilityDone(const sptr &token) +{ + int error; + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!WriteInterfaceToken(data)) { + return INNER_ERR; + } + if (!data.WriteParcelable(token)) { + HILOG_ERROR("token write failed."); + return ERR_INVALID_VALUE; + } + + error = Remote()->SendRequest(IAbilityManager::DISCONNECT_ABILITY_DONE, data, reply, option); + if (error != NO_ERROR) { + HILOG_ERROR("Send request error: %{public}d", error); + return error; + } + return reply.ReadInt32(); +} + +int AbilityManagerProxy::ScheduleCommandAbilityDone(const sptr &token) +{ + int error; + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!WriteInterfaceToken(data)) { + return INNER_ERR; + } + if (!data.WriteParcelable(token)) { + HILOG_ERROR("token write failed."); + return ERR_INVALID_VALUE; + } + + error = Remote()->SendRequest(IAbilityManager::COMMAND_ABILITY_DONE, data, reply, option); + if (error != NO_ERROR) { + HILOG_ERROR("Send request error: %{public}d", error); + return error; + } + return reply.ReadInt32(); +} + +void AbilityManagerProxy::AddWindowInfo(const sptr &token, int32_t windowToken) +{ + int error; + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!WriteInterfaceToken(data)) { + return; + } + if (!data.WriteParcelable(token) || !data.WriteInt32(windowToken)) { + HILOG_ERROR("data write failed."); + return; + } + error = Remote()->SendRequest(ADD_WINDOW_INFO, data, reply, option); + if (error != NO_ERROR) { + HILOG_ERROR("Send request error: %{public}d", error); + } +} + +void AbilityManagerProxy::DumpState(const std::string &args, std::vector &state) +{ + int error; + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!WriteInterfaceToken(data)) { + return; + } + data.WriteString16(Str8ToStr16(args)); + error = Remote()->SendRequest(IAbilityManager::DUMP_STATE, data, reply, option); + if (error != NO_ERROR) { + HILOG_ERROR("AbilityManagerProxy: SendRequest err %{public}d", error); + return; + } + int32_t stackNum = reply.ReadInt32(); + for (int i = 0; i < stackNum; i++) { + std::string stac = Str16ToStr8(reply.ReadString16()); + state.emplace_back(stac); + } +} + +int AbilityManagerProxy::TerminateAbilityResult(const sptr &token, int startId) +{ + int error; + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!WriteInterfaceToken(data)) { + return INNER_ERR; + } + if (!data.WriteParcelable(token) || !data.WriteInt32(startId)) { + HILOG_ERROR("data write failed."); + return ERR_INVALID_VALUE; + } + error = Remote()->SendRequest(IAbilityManager::TERMINATE_ABILITY_RESULT, data, reply, option); + if (error != NO_ERROR) { + HILOG_ERROR("Send request error: %{public}d", error); + return error; + } + return reply.ReadInt32(); +} + +int AbilityManagerProxy::StopServiceAbility(const Want &want) +{ + int error; + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!WriteInterfaceToken(data)) { + return INNER_ERR; + } + if (!data.WriteParcelable(&want)) { + HILOG_ERROR("want write failed."); + return INNER_ERR; + } + error = Remote()->SendRequest(IAbilityManager::STOP_SERVICE_ABILITY, data, reply, option); + if (error != NO_ERROR) { + HILOG_ERROR("Send request error: %{public}d", error); + return error; + } + return reply.ReadInt32(); +} + +int AbilityManagerProxy::GetAllStackInfo(StackInfo &stackInfo) +{ + int error; + MessageParcel data; + MessageParcel reply; + MessageOption option(MessageOption::TF_SYNC); + + if (!WriteInterfaceToken(data)) { + return INNER_ERR; + } + sptr remote = Remote(); + if (remote == nullptr) { + HILOG_ERROR("remote is nullptr."); + return ERR_UNKNOWN_OBJECT; + } + error = remote->SendRequest(IAbilityManager::LIST_STACK_INFO, data, reply, option); + if (error != NO_ERROR) { + HILOG_ERROR("Send request error: %{public}d", error); + return error; + } + int32_t result = reply.ReadInt32(); + if (result != ERR_OK) { + HILOG_ERROR("Read info failed, err %{public}d", result); + return result; + } + std::unique_ptr info(reply.ReadParcelable()); + if (!info) { + HILOG_ERROR("Read info failed."); + return ERR_UNKNOWN_OBJECT; + } + stackInfo = *info; + return result; +} + +template +int AbilityManagerProxy::GetParcelableInfos(MessageParcel &reply, std::vector &parcelableInfos) +{ + int32_t infoSize = reply.ReadInt32(); + for (int32_t i = 0; i < infoSize; i++) { + std::unique_ptr info(reply.ReadParcelable()); + if (!info) { + HILOG_ERROR("Read Parcelable infos failed."); + return ERR_INVALID_VALUE; + } + parcelableInfos.emplace_back(*info); + } + return NO_ERROR; +} + +int AbilityManagerProxy::GetRecentMissions( + const int32_t numMax, const int32_t flags, std::vector &recentList) +{ + int error; + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!WriteInterfaceToken(data)) { + return INNER_ERR; + } + if (!data.WriteInt32(numMax)) { + HILOG_ERROR("numMax write failed."); + return ERR_INVALID_VALUE; + } + if (!data.WriteInt32(flags)) { + HILOG_ERROR("flags write failed."); + return ERR_INVALID_VALUE; + } + error = Remote()->SendRequest(IAbilityManager::GET_RECENT_MISSION, data, reply, option); + if (error != NO_ERROR) { + HILOG_ERROR("Send request error: %{public}d", error); + return error; + } + error = GetParcelableInfos(reply, recentList); + if (error != NO_ERROR) { + HILOG_ERROR("Get info error: %{public}d", error); + return error; + } + return reply.ReadInt32(); +} + +int AbilityManagerProxy::GetMissionSnapshot(const int32_t missionId, MissionSnapshotInfo &snapshot) +{ + int error; + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!WriteInterfaceToken(data)) { + return INNER_ERR; + } + if (!data.WriteInt32(missionId)) { + HILOG_ERROR("missionId write failed."); + return ERR_INVALID_VALUE; + } + error = Remote()->SendRequest(IAbilityManager::GET_MISSION_SNAPSHOT, data, reply, option); + if (error != NO_ERROR) { + HILOG_ERROR("Send request error: %{public}d", error); + return error; + } + std::unique_ptr info(reply.ReadParcelable()); + if (!info) { + HILOG_ERROR("readParcelableInfo failed."); + return ERR_UNKNOWN_OBJECT; + } + snapshot = *info; + return reply.ReadInt32(); +} + +int AbilityManagerProxy::MoveMissionToTop(int32_t missionId) +{ + int error; + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!WriteInterfaceToken(data)) { + return INNER_ERR; + } + if (!data.WriteInt32(missionId)) { + HILOG_ERROR("missionId write failed."); + return ERR_INVALID_VALUE; + } + error = Remote()->SendRequest(IAbilityManager::MOVE_MISSION_TO_TOP, data, reply, option); + if (error != NO_ERROR) { + HILOG_ERROR("Send request error: %{public}d", error); + return error; + } + return reply.ReadInt32(); +} + +int AbilityManagerProxy::MoveMissionToEnd(const sptr &token, const bool nonFirst) +{ + int error; + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!WriteInterfaceToken(data)) { + return INNER_ERR; + } + if (!data.WriteParcelable(token) || !data.WriteBool(nonFirst)) { + HILOG_ERROR("data write failed."); + return ERR_INVALID_VALUE; + } + error = Remote()->SendRequest(IAbilityManager::MOVE_MISSION_TO_END, data, reply, option); + if (error != NO_ERROR) { + HILOG_ERROR("Send request error: %{public}d", error); + return error; + } + return reply.ReadInt32(); +} + +int AbilityManagerProxy::RemoveMission(int id) +{ + int error; + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!WriteInterfaceToken(data)) { + return INNER_ERR; + } + if (!data.WriteInt32(id)) { + HILOG_ERROR("id write failed."); + return ERR_INVALID_VALUE; + } + error = Remote()->SendRequest(IAbilityManager::REMOVE_MISSION, data, reply, option); + if (error != NO_ERROR) { + HILOG_ERROR("Send request error: %{public}d", error); + return error; + } + return reply.ReadInt32(); +} + +int AbilityManagerProxy::RemoveStack(int id) +{ + int error; + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!WriteInterfaceToken(data)) { + return INNER_ERR; + } + if (!data.WriteInt32(id)) { + HILOG_ERROR("id write failed."); + return ERR_INVALID_VALUE; + } + error = Remote()->SendRequest(IAbilityManager::REMOVE_STACK, data, reply, option); + if (error != NO_ERROR) { + HILOG_ERROR("Send request error: %{public}d", error); + return error; + } + return reply.ReadInt32(); +} + +int AbilityManagerProxy::KillProcess(const std::string &bundleName) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!WriteInterfaceToken(data)) { + return INNER_ERR; + } + if (!data.WriteString16(Str8ToStr16(bundleName))) { + HILOG_ERROR("bundleName write failed."); + return ERR_INVALID_VALUE; + } + int error = Remote()->SendRequest(IAbilityManager::KILL_PROCESS, data, reply, option); + if (error != NO_ERROR) { + HILOG_ERROR("Send request error: %{public}d", error); + return error; + } + return reply.ReadInt32(); +} + +int AbilityManagerProxy::UninstallApp(const std::string &bundleName) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!WriteInterfaceToken(data)) { + return INNER_ERR; + } + if (!data.WriteString16(Str8ToStr16(bundleName))) { + HILOG_ERROR("bundleName write failed."); + return ERR_INVALID_VALUE; + } + int error = Remote()->SendRequest(IAbilityManager::UNINSTALL_APP, data, reply, option); + if (error != NO_ERROR) { + HILOG_ERROR("Send request error: %{public}d", error); + return error; + } + return reply.ReadInt32(); +} + +int AbilityManagerProxy::MoveMissionToFloatingStack(const MissionOption &missionOption) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!WriteInterfaceToken(data)) { + return INNER_ERR; + } + if (!data.WriteParcelable(&missionOption)) { + HILOG_ERROR("fail to write to parcel."); + return INNER_ERR; + } + int error = Remote()->SendRequest(IAbilityManager::MOVE_MISSION_TO_FLOATING_STACK, data, reply, option); + if (error != NO_ERROR) { + HILOG_ERROR("%s, error: %d", __func__, error); + return error; + } + return reply.ReadInt32(); +} + +int AbilityManagerProxy::MoveMissionToSplitScreenStack(const MissionOption &missionOption) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!WriteInterfaceToken(data)) { + return INNER_ERR; + } + if (!data.WriteParcelable(&missionOption)) { + HILOG_ERROR("fail to write to parcel."); + return INNER_ERR; + } + int error = Remote()->SendRequest(IAbilityManager::MOVE_MISSION_TO_SPLITSCREEN_STACK, data, reply, option); + if (error != NO_ERROR) { + HILOG_ERROR("%s, error: %d", __func__, error); + return error; + } + return reply.ReadInt32(); +} + +int AbilityManagerProxy::ChangeFocusAbility( + const sptr &lostFocusToken, const sptr &getFocusToken) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!WriteInterfaceToken(data)) { + return INNER_ERR; + } + if (!data.WriteParcelable(lostFocusToken) || !data.WriteParcelable(getFocusToken)) { + HILOG_ERROR("change focus ability failed"); + return ERR_INVALID_VALUE; + } + auto error = Remote()->SendRequest(IAbilityManager::CHANGE_FOCUS_ABILITY, data, reply, option); + if (error != NO_ERROR) { + HILOG_ERROR("change focus ability error: %d", error); + return error; + } + return reply.ReadInt32(); +} + +int AbilityManagerProxy::MinimizeMultiWindow(int missionId) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!WriteInterfaceToken(data)) { + return INNER_ERR; + } + if (!data.WriteInt32(missionId)) { + HILOG_ERROR("WriteInt32 fail."); + return ERR_INVALID_VALUE; + } + auto error = Remote()->SendRequest(IAbilityManager::MINIMIZE_MULTI_WINDOW, data, reply, option); + if (error != NO_ERROR) { + HILOG_ERROR("minimize multi window error: %d", error); + return error; + } + return reply.ReadInt32(); +} + +int AbilityManagerProxy::MaximizeMultiWindow(int missionId) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!WriteInterfaceToken(data)) { + return INNER_ERR; + } + if (!data.WriteInt32(missionId)) { + HILOG_ERROR("WriteInt32 fail."); + return ERR_INVALID_VALUE; + } + auto error = Remote()->SendRequest(IAbilityManager::MAXIMIZE_MULTI_WINDOW, data, reply, option); + if (error != NO_ERROR) { + HILOG_ERROR("maximize multi window error: %d", error); + return error; + } + return reply.ReadInt32(); +} + +int AbilityManagerProxy::GetFloatingMissions(std::vector &list) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!WriteInterfaceToken(data)) { + return INNER_ERR; + } + auto error = Remote()->SendRequest(IAbilityManager::GET_FLOATING_MISSIONS, data, reply, option); + if (error != NO_ERROR) { + HILOG_ERROR("get floating mission fail, error: %{public}d", error); + return error; + } + error = GetParcelableInfos(reply, list); + if (error != NO_ERROR) { + HILOG_ERROR("GetParcelableInfos fail, error: %{public}d", error); + return error; + } + return reply.ReadInt32(); +} + +int AbilityManagerProxy::CloseMultiWindow(int missionId) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!WriteInterfaceToken(data)) { + return INNER_ERR; + } + if (!data.WriteInt32(missionId)) { + HILOG_ERROR("WriteInt32 fail."); + return ERR_INVALID_VALUE; + } + auto error = Remote()->SendRequest(IAbilityManager::CLOSE_MULTI_WINDOW, data, reply, option); + if (error != NO_ERROR) { + HILOG_ERROR("close multi window error: %d", error); + return error; + } + return reply.ReadInt32(); +} + +int AbilityManagerProxy::SetMissionStackSetting(const StackSetting &stackSetting) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!WriteInterfaceToken(data)) { + return INNER_ERR; + } + if (!data.WriteParcelable(&stackSetting)) { + HILOG_ERROR("%{public}s WriteParcelable", __func__); + return INNER_ERR; + } + auto error = Remote()->SendRequest(IAbilityManager::SET_STACK_SETTING, data, reply, option); + if (error != NO_ERROR) { + HILOG_ERROR("%{public}s for result fail, error: %d", __func__, error); + return error; + } + return reply.ReadInt32(); +} + +bool AbilityManagerProxy::IsFirstInMission(const sptr &token) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!WriteInterfaceToken(data)) { + return INNER_ERR; + } + if (!data.WriteParcelable(token)) { + HILOG_ERROR("token write failed."); + return false; + } + auto error = Remote()->SendRequest(IAbilityManager::IS_FIRST_IN_MISSION, data, reply, option); + if (error != NO_ERROR) { + HILOG_ERROR("Send request error: %{public}d", error); + return false; + } + return reply.ReadBool(); +} + +int AbilityManagerProxy::CompelVerifyPermission(const std::string &permission, int pid, int uid, std::string &message) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!WriteInterfaceToken(data)) { + return INNER_ERR; + } + if (!data.WriteString16(Str8ToStr16(permission)) || !data.WriteInt32(pid) || !data.WriteInt32(uid)) { + HILOG_ERROR("data write failed."); + return INNER_ERR; + } + auto error = Remote()->SendRequest(IAbilityManager::COMPEL_VERIFY_PERMISSION, data, reply, option); + if (error != NO_ERROR) { + HILOG_ERROR("Send request error: %{public}d", error); + return error; + } + message = Str16ToStr8(reply.ReadString16()); + return reply.ReadInt32(); +} + +int AbilityManagerProxy::PowerOff() +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!WriteInterfaceToken(data)) { + return INNER_ERR; + } + auto error = Remote()->SendRequest(IAbilityManager::POWER_OFF, data, reply, option); + if (error != NO_ERROR) { + HILOG_ERROR("Send request error: %{public}d", error); + return error; + } + return reply.ReadInt32(); +} + +int AbilityManagerProxy::PowerOn() +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!WriteInterfaceToken(data)) { + return INNER_ERR; + } + auto error = Remote()->SendRequest(IAbilityManager::POWER_ON, data, reply, option); + if (error != NO_ERROR) { + HILOG_ERROR("Send request error: %{public}d", error); + return error; + } + return reply.ReadInt32(); +} + +int AbilityManagerProxy::LockMission(int missionId) +{ + int error; + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!WriteInterfaceToken(data)) { + return INNER_ERR; + } + if (!data.WriteInt32(missionId)) { + HILOG_ERROR("lock mission by id , WriteInt32 fail."); + return ERR_INVALID_VALUE; + } + error = Remote()->SendRequest(IAbilityManager::LUCK_MISSION, data, reply, option); + if (error != NO_ERROR) { + HILOG_ERROR("lock mission by id , error: %d", error); + return error; + } + return reply.ReadInt32(); +} + +int AbilityManagerProxy::UnlockMission(int missionId) +{ + int error; + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!WriteInterfaceToken(data)) { + return INNER_ERR; + } + if (!data.WriteInt32(missionId)) { + HILOG_ERROR("unlock mission by id , WriteInt32 fail."); + return ERR_INVALID_VALUE; + } + error = Remote()->SendRequest(IAbilityManager::UNLUCK_MISSION, data, reply, option); + if (error != NO_ERROR) { + HILOG_ERROR("unlock mission by id , error: %d", error); + return error; + } + return reply.ReadInt32(); +} + +int AbilityManagerProxy::SetMissionDescriptionInfo( + const sptr &token, const MissionDescriptionInfo &description) +{ + int error; + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!WriteInterfaceToken(data)) { + return INNER_ERR; + } + if (!data.WriteParcelable(token)) { + HILOG_ERROR("%{public}s for result fail", __func__); + return false; + } + if (!data.WriteParcelable(&description)) { + HILOG_ERROR("%{public}s for result fail", __func__); + return false; + } + error = Remote()->SendRequest(IAbilityManager::SET_MISSION_INFO, data, reply, option); + if (error != NO_ERROR) { + HILOG_ERROR("unlock mission by id , error: %d", error); + return error; + } + return reply.ReadInt32(); +} + +int AbilityManagerProxy::GetMissionLockModeState() +{ + int error; + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!WriteInterfaceToken(data)) { + return INNER_ERR; + } + error = Remote()->SendRequest(IAbilityManager::GET_MISSION_LOCK_MODE_STATE, data, reply, option); + if (error != NO_ERROR) { + HILOG_ERROR("get mission luck mode state , error: %d", error); + return error; + } + return reply.ReadInt32(); +} + +int AbilityManagerProxy::UpdateConfiguration(const DummyConfiguration &config) +{ + int error; + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!WriteInterfaceToken(data)) { + return INNER_ERR; + } + if (!data.WriteParcelable(&config)) { + return INNER_ERR; + } + error = Remote()->SendRequest(IAbilityManager::UPDATE_CONFIGURATION, data, reply, option); + if (error != NO_ERROR) { + HILOG_ERROR("update configuration, error: %d", error); + return error; + } + return reply.ReadInt32(); +} + +sptr AbilityManagerProxy::GetWantSender( + const WantSenderInfo &wantSenderInfo, const sptr &callerToken) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!WriteInterfaceToken(data)) { + return nullptr; + } + if (!data.WriteParcelable(&wantSenderInfo)) { + HILOG_ERROR("wantSenderInfo write failed."); + return nullptr; + } + if (!data.WriteParcelable(callerToken)) { + HILOG_ERROR("callerToken write failed."); + return nullptr; + } + auto error = Remote()->SendRequest(IAbilityManager::GET_PENDING_WANT_SENDER, data, reply, option); + if (error != NO_ERROR) { + HILOG_ERROR("Send request error: %{public}d", error); + return nullptr; + } + sptr wantSender = iface_cast(reply.ReadParcelable()); + if (!wantSender) { + return nullptr; + } + return wantSender; +} + +int AbilityManagerProxy::SendWantSender(const sptr &target, const SenderInfo &senderInfo) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!WriteInterfaceToken(data)) { + return INNER_ERR; + } + if (target == nullptr || !data.WriteParcelable(target->AsObject())) { + HILOG_ERROR("target write failed."); + return INNER_ERR; + } + if (!data.WriteParcelable(&senderInfo)) { + HILOG_ERROR("senderInfo write failed."); + return INNER_ERR; + } + + auto error = Remote()->SendRequest(IAbilityManager::SEND_PENDING_WANT_SENDER, data, reply, option); + if (error != NO_ERROR) { + HILOG_ERROR("Send request error: %{public}d", error); + return error; + } + return reply.ReadInt32(); +} + +void AbilityManagerProxy::CancelWantSender(const sptr &sender) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!WriteInterfaceToken(data)) { + return; + } + if (sender == nullptr || !data.WriteParcelable(sender->AsObject())) { + HILOG_ERROR("sender write failed."); + return; + } + auto error = Remote()->SendRequest(IAbilityManager::CANCEL_PENDING_WANT_SENDER, data, reply, option); + if (error != NO_ERROR) { + HILOG_ERROR("Send request error: %{public}d", error); + return; + } +} + +int AbilityManagerProxy::GetPendingWantUid(const sptr &target) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!WriteInterfaceToken(data)) { + return INNER_ERR; + } + if (target == nullptr || !data.WriteParcelable(target->AsObject())) { + HILOG_ERROR("target write failed."); + return ERR_INVALID_VALUE; + } + auto error = Remote()->SendRequest(IAbilityManager::GET_PENDING_WANT_UID, data, reply, option); + if (error != NO_ERROR) { + HILOG_ERROR("Send request error: %{public}d", error); + return INNER_ERR; + } + return reply.ReadInt32(); +} + +int AbilityManagerProxy::GetPendingWantUserId(const sptr &target) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!WriteInterfaceToken(data)) { + return INNER_ERR; + } + if (target == nullptr || !data.WriteParcelable(target->AsObject())) { + HILOG_ERROR("target write failed."); + return ERR_INVALID_VALUE; + } + auto error = Remote()->SendRequest(IAbilityManager::GET_PENDING_WANT_USERID, data, reply, option); + if (error != NO_ERROR) { + HILOG_ERROR("Send request error: %{public}d", error); + return INNER_ERR; + } + return reply.ReadInt32(); +} + +std::string AbilityManagerProxy::GetPendingWantBundleName(const sptr &target) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!WriteInterfaceToken(data)) { + return ""; + } + if (target == nullptr || !data.WriteParcelable(target->AsObject())) { + HILOG_ERROR("target write failed."); + return ""; + } + auto error = Remote()->SendRequest(IAbilityManager::GET_PENDING_WANT_BUNDLENAME, data, reply, option); + if (error != NO_ERROR) { + HILOG_ERROR("Send request error: %{public}d", error); + return ""; + } + return Str16ToStr8(reply.ReadString16()); +} + +int AbilityManagerProxy::GetPendingWantCode(const sptr &target) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!WriteInterfaceToken(data)) { + return INNER_ERR; + } + if (target == nullptr || !data.WriteParcelable(target->AsObject())) { + HILOG_ERROR("target write failed."); + return ERR_INVALID_VALUE; + } + auto error = Remote()->SendRequest(IAbilityManager::GET_PENDING_WANT_CODE, data, reply, option); + if (error != NO_ERROR) { + HILOG_ERROR("Send request error: %{public}d", error); + return INNER_ERR; + } + return reply.ReadInt32(); +} + +int AbilityManagerProxy::GetPendingWantType(const sptr &target) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!WriteInterfaceToken(data)) { + return INNER_ERR; + } + if (target == nullptr || !data.WriteParcelable(target->AsObject())) { + HILOG_ERROR("target write failed."); + return ERR_INVALID_VALUE; + } + auto error = Remote()->SendRequest(IAbilityManager::GET_PENDING_WANT_TYPE, data, reply, option); + if (error != NO_ERROR) { + HILOG_ERROR("Send request error: %{public}d", error); + return INNER_ERR; + } + return reply.ReadInt32(); +} + +void AbilityManagerProxy::RegisterCancelListener(const sptr &sender, const sptr &receiver) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!WriteInterfaceToken(data)) { + return; + } + if (sender == nullptr || !data.WriteParcelable(sender->AsObject())) { + HILOG_ERROR("sender write failed."); + return; + } + if (receiver == nullptr || !data.WriteParcelable(receiver->AsObject())) { + HILOG_ERROR("receiver write failed."); + return; + } + auto error = Remote()->SendRequest(IAbilityManager::REGISTER_CANCEL_LISTENER, data, reply, option); + if (error != NO_ERROR) { + HILOG_ERROR("Send request error: %{public}d", error); + return; + } +} + +void AbilityManagerProxy::UnregisterCancelListener(const sptr &sender, const sptr &receiver) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!WriteInterfaceToken(data)) { + return; + } + if (sender == nullptr || !data.WriteParcelable(sender->AsObject())) { + HILOG_ERROR("sender write failed."); + return; + } + if (receiver == nullptr || !data.WriteParcelable(receiver->AsObject())) { + HILOG_ERROR("receiver write failed."); + return; + } + auto error = Remote()->SendRequest(IAbilityManager::UNREGISTER_CANCEL_LISTENER, data, reply, option); + if (error != NO_ERROR) { + HILOG_ERROR("Send request error: %{public}d", error); + return; + } +} + +int AbilityManagerProxy::GetPendingRequestWant(const sptr &target, std::shared_ptr &want) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!WriteInterfaceToken(data)) { + return INNER_ERR; + } + if (target == nullptr || !data.WriteParcelable(target->AsObject())) { + HILOG_ERROR("target write failed."); + return INNER_ERR; + } + if (want == nullptr || !data.WriteParcelable(want.get())) { + HILOG_ERROR("want write failed."); + return INNER_ERR; + } + auto error = Remote()->SendRequest(IAbilityManager::GET_PENDING_REQUEST_WANT, data, reply, option); + if (error != NO_ERROR) { + HILOG_ERROR("Send request error: %{public}d", error); + return error; + } + std::unique_ptr wantInfo(reply.ReadParcelable()); + if (!wantInfo) { + HILOG_ERROR("readParcelableInfo failed"); + return INNER_ERR; + } + want = std::move(wantInfo); + + return NO_ERROR; +} +} // namespace AAFwk +} // namespace OHOS diff --git a/tools/services/abilitymgr/src/ability_manager_service.cpp b/tools/services/abilitymgr/src/ability_manager_service.cpp new file mode 100644 index 00000000000..0921f701a43 --- /dev/null +++ b/tools/services/abilitymgr/src/ability_manager_service.cpp @@ -0,0 +1,1605 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ability_manager_service.h" + +#include +#include +#include +#include +#include "string_ex.h" + +#include "ability_util.h" +#include "ability_info.h" +#include "ability_manager_errors.h" +#include "hilog_wrapper.h" +#include "if_system_ability_manager.h" +#include "ipc_skeleton.h" +#include "sa_mgr_client.h" +#include "system_ability_definition.h" + +using OHOS::AppExecFwk::ElementName; + +namespace OHOS { +namespace AAFwk { +using namespace std::chrono; +constexpr auto DATA_ABILITY_START_TIMEOUT = 5s; +const std::map AbilityManagerService::dumpMap = { + std::map::value_type("--all", KEY_DUMP_ALL), + std::map::value_type("-a", KEY_DUMP_ALL), + std::map::value_type("--stack-list", KEY_DUMP_STACK_LIST), + std::map::value_type("-l", KEY_DUMP_STACK_LIST), + std::map::value_type("--stack", KEY_DUMP_STACK), + std::map::value_type("-s", KEY_DUMP_STACK), + std::map::value_type("--mission", KEY_DUMP_MISSION), + std::map::value_type("-m", KEY_DUMP_MISSION), + std::map::value_type("--top", KEY_DUMP_TOP_ABILITY), + std::map::value_type("-t", KEY_DUMP_TOP_ABILITY), + std::map::value_type("--waitting-queue", KEY_DUMP_WAIT_QUEUE), + std::map::value_type("-w", KEY_DUMP_WAIT_QUEUE), + std::map::value_type("--serv", KEY_DUMP_SERVICE), + std::map::value_type("-e", KEY_DUMP_SERVICE), + std::map::value_type("--data", KEY_DUMP_DATA), + std::map::value_type("-d", KEY_DUMP_DATA), + std::map::value_type("--ui", KEY_DUMP_SYSTEM_UI), + std::map::value_type("-u", KEY_DUMP_SYSTEM_UI), + std::map::value_type("-focus", KEY_DUMP_FOCUS_ABILITY), + std::map::value_type("-f", KEY_DUMP_FOCUS_ABILITY), +}; +const bool REGISTER_RESULT = + SystemAbility::MakeAndRegisterAbility(DelayedSingleton::GetInstance().get()); + +AbilityManagerService::AbilityManagerService() + : SystemAbility(ABILITY_MGR_SERVICE_ID, true), + eventLoop_(nullptr), + handler_(nullptr), + state_(ServiceRunningState::STATE_NOT_START), + connectManager_(std::make_shared()), + iBundleManager_(nullptr) +{ + std::shared_ptr appScheduler( + DelayedSingleton::GetInstance().get(), [](AppScheduler *x) { x->DecStrongRef(x); }); + appScheduler_ = appScheduler; + DumpFuncInit(); +} + +AbilityManagerService::~AbilityManagerService() +{} + +void AbilityManagerService::OnStart() +{ + if (state_ == ServiceRunningState::STATE_RUNNING) { + HILOG_INFO("Ability manager service has already started."); + return; + } + HILOG_INFO("Ability manager service started."); + if (!Init()) { + HILOG_ERROR("Failed to init service."); + return; + } + state_ = ServiceRunningState::STATE_RUNNING; + eventLoop_->Run(); + /* Publish service maybe failed, so we need call this function at the last, + * so it can't affect the TDD test program */ + bool ret = Publish(DelayedSingleton::GetInstance().get()); + if (!ret) { + HILOG_ERROR("Init publish failed!"); + return; + } + + HILOG_INFO("Ability manager service start success."); +} + +bool AbilityManagerService::Init() +{ + eventLoop_ = AppExecFwk::EventRunner::Create(AbilityConfig::NAME_ABILITY_MGR_SERVICE); + CHECK_POINTER_RETURN_BOOL(eventLoop_); + + handler_ = std::make_shared(eventLoop_, weak_from_this()); + CHECK_POINTER_RETURN_BOOL(handler_); + CHECK_POINTER_RETURN_BOOL(connectManager_); + connectManager_->SetEventHandler(handler_); + + auto dataAbilityManager = std::make_shared(); + CHECK_POINTER_RETURN_BOOL(dataAbilityManager); + + amsConfigResolver_ = std::make_shared(); + if (amsConfigResolver_) { + amsConfigResolver_->Parse(); + HILOG_INFO("ams config parse"); + } + + auto pendingWantManager = std::make_shared(); + if (!pendingWantManager) { + HILOG_ERROR("Failed to init pending want ability manager."); + return false; + } + + int userId = GetUserId(); + SetStackManager(userId); + systemAppManager_ = std::make_shared(userId); + CHECK_POINTER_RETURN_BOOL(systemAppManager_); + + auto startLauncherAbilityTask = [aams = shared_from_this()]() { aams->StartSystemApplication(); }; + handler_->PostTask(startLauncherAbilityTask, "startLauncherAbility"); + dataAbilityManager_ = dataAbilityManager; + pendingWantManager_ = pendingWantManager; + HILOG_INFO("Init success."); + return true; +} + +void AbilityManagerService::OnStop() +{ + HILOG_INFO("Stop service."); + eventLoop_.reset(); + handler_.reset(); + state_ = ServiceRunningState::STATE_NOT_START; +} + +ServiceRunningState AbilityManagerService::QueryServiceState() const +{ + return state_; +} + +int AbilityManagerService::StartAbility(const Want &want, int requestCode) +{ + HILOG_INFO("%{public}s", __func__); + return StartAbility(want, nullptr, requestCode, -1); +} + +int AbilityManagerService::StartAbility(const Want &want, const sptr &callerToken, int requestCode) +{ + HILOG_INFO("%{public}s", __func__); + return StartAbility(want, callerToken, requestCode, -1); +} + +int AbilityManagerService::StartAbility( + const Want &want, const sptr &callerToken, int requestCode, int callerUid) +{ + HILOG_INFO("%{public}s", __func__); + if (callerToken != nullptr && !VerificationToken(callerToken)) { + return ERR_INVALID_VALUE; + } + + AbilityRequest abilityRequest; + int result = GenerateAbilityRequest(want, requestCode, abilityRequest, callerToken); + if (result != ERR_OK) { + HILOG_ERROR("Generate ability request error."); + return result; + } + auto abilityInfo = abilityRequest.abilityInfo; + result = AbilityUtil::JudgeAbilityVisibleControl(abilityInfo, callerUid); + if (result != ERR_OK) { + HILOG_ERROR("%{public}s JudgeAbilityVisibleControl error.", __func__); + return result; + } + auto type = abilityInfo.type; + if (type == AppExecFwk::AbilityType::DATA) { + HILOG_ERROR("Cannot start data ability, use 'AcquireDataAbility()' instead."); + return ERR_INVALID_VALUE; + } + + if (!AbilityUtil::IsSystemDialogAbility(abilityInfo.bundleName, abilityInfo.name)) { + result = PreLoadAppDataAbilities(abilityInfo.bundleName); + if (result != ERR_OK) { + HILOG_ERROR("StartAbility: App data ability preloading failed, '%{public}s', %{public}d", + abilityInfo.bundleName.c_str(), + result); + return result; + } + } + + if (type == AppExecFwk::AbilityType::SERVICE) { + return connectManager_->StartAbility(abilityRequest); + } + + if (IsSystemUiApp(abilityRequest.abilityInfo)) { + return systemAppManager_->StartAbility(abilityRequest); + } + + return currentStackManager_->StartAbility(abilityRequest); +} + +int AbilityManagerService::StartAbility(const Want &want, const AbilityStartSetting &abilityStartSetting, + const sptr &callerToken, int requestCode) +{ + HILOG_INFO("Start ability setting."); + if (callerToken != nullptr && !VerificationToken(callerToken)) { + return ERR_INVALID_VALUE; + } + + AbilityRequest abilityRequest; + int result = GenerateAbilityRequest(want, requestCode, abilityRequest, callerToken); + if (result != ERR_OK) { + HILOG_ERROR("Generate ability request error."); + return result; + } + + abilityRequest.startSetting = std::make_shared(abilityStartSetting); + + auto abilityInfo = abilityRequest.abilityInfo; + if (abilityInfo.type == AppExecFwk::AbilityType::DATA) { + HILOG_ERROR("Cannot start data ability, use 'AcquireDataAbility()' instead."); + return ERR_INVALID_VALUE; + } + + if (!AbilityUtil::IsSystemDialogAbility(abilityInfo.bundleName, abilityInfo.name)) { + result = PreLoadAppDataAbilities(abilityInfo.bundleName); + if (result != ERR_OK) { + HILOG_ERROR("StartAbility: App data ability preloading failed, '%{public}s', %{public}d", + abilityInfo.bundleName.c_str(), + result); + return result; + } + } + + if (abilityInfo.type != AppExecFwk::AbilityType::PAGE) { + HILOG_ERROR("Only support for page type ability."); + return ERR_INVALID_VALUE; + } + if (IsSystemUiApp(abilityRequest.abilityInfo)) { + return systemAppManager_->StartAbility(abilityRequest); + } + return currentStackManager_->StartAbility(abilityRequest); +} + +int AbilityManagerService::TerminateAbility(const sptr &token, int resultCode, const Want *resultWant) +{ + HILOG_INFO("Terminate ability for result: %{public}d", (resultWant != nullptr)); + if (!VerificationToken(token)) { + return ERR_INVALID_VALUE; + } + + auto abilityRecord = Token::GetAbilityRecordByToken(token); + CHECK_POINTER_AND_RETURN(abilityRecord, ERR_INVALID_VALUE); + int result = AbilityUtil::JudgeAbilityVisibleControl(abilityRecord->GetAbilityInfo()); + if (result != ERR_OK) { + HILOG_ERROR("%{public}s JudgeAbilityVisibleControl error.", __func__); + return result; + } + + if (IsSystemUiApp(abilityRecord->GetAbilityInfo())) { + HILOG_ERROR("System ui not allow terminate."); + return ERR_INVALID_VALUE; + } + + auto type = abilityRecord->GetAbilityInfo().type; + if (type == AppExecFwk::AbilityType::SERVICE) { + return connectManager_->TerminateAbility(token); + } + + if (type == AppExecFwk::AbilityType::DATA) { + HILOG_ERROR("Cannot terminate data ability, use 'ReleaseDataAbility()' instead."); + return ERR_INVALID_VALUE; + } + + if ((resultWant != nullptr) && + AbilityUtil::IsSystemDialogAbility( + abilityRecord->GetAbilityInfo().bundleName, abilityRecord->GetAbilityInfo().name) && + resultWant->HasParameter(AbilityConfig::SYSTEM_DIALOG_KEY) && + resultWant->HasParameter(AbilityConfig::SYSTEM_DIALOG_CALLER_BUNDLENAME) && + resultWant->HasParameter(AbilityConfig::SYSTEM_DIALOG_REQUEST_PERMISSIONS)) { + RequestPermission(resultWant); + } + + return currentStackManager_->TerminateAbility(token, resultCode, resultWant); +} + +void AbilityManagerService::RequestPermission(const Want *resultWant) +{ + HILOG_INFO("Request permission."); + CHECK_POINTER(iBundleManager_); + CHECK_POINTER_IS_NULLPTR(resultWant); + + auto callerBundleName = resultWant->GetStringParam(AbilityConfig::SYSTEM_DIALOG_CALLER_BUNDLENAME); + auto permissions = resultWant->GetStringArrayParam(AbilityConfig::SYSTEM_DIALOG_REQUEST_PERMISSIONS); + + for (auto &it : permissions) { + auto ret = iBundleManager_->RequestPermissionFromUser(callerBundleName, it, GetUserId()); + HILOG_INFO("Request permission from user result :%{public}d, permission:%{public}s.", ret, it.c_str()); + } +} + +int AbilityManagerService::TerminateAbilityByCaller(const sptr &callerToken, int requestCode) +{ + HILOG_INFO("Terminate ability by caller."); + if (!VerificationToken(callerToken)) { + return ERR_INVALID_VALUE; + } + + auto abilityRecord = Token::GetAbilityRecordByToken(callerToken); + CHECK_POINTER_AND_RETURN(abilityRecord, ERR_INVALID_VALUE); + + if (IsSystemUiApp(abilityRecord->GetAbilityInfo())) { + HILOG_ERROR("System ui not allow terminate."); + return ERR_INVALID_VALUE; + } + + auto type = abilityRecord->GetAbilityInfo().type; + switch (type) { + case AppExecFwk::AbilityType::SERVICE: { + auto result = connectManager_->TerminateAbility(abilityRecord, requestCode); + if (result == NO_FOUND_ABILITY_BY_CALLER) { + return currentStackManager_->TerminateAbility(abilityRecord, requestCode); + } + return result; + } + case AppExecFwk::AbilityType::PAGE: { + auto result = currentStackManager_->TerminateAbility(abilityRecord, requestCode); + if (result == NO_FOUND_ABILITY_BY_CALLER) { + return connectManager_->TerminateAbility(abilityRecord, requestCode); + } + return result; + } + default: + return ERR_INVALID_VALUE; + } +} + +int AbilityManagerService::GetRecentMissions( + const int32_t numMax, const int32_t flags, std::vector &recentList) +{ + HILOG_INFO("numMax: %{public}d, flags: %{public}d", numMax, flags); + if (numMax < 0 || flags < 0) { + HILOG_ERROR("numMax or flags is invalid."); + return ERR_INVALID_VALUE; + } + if (!CheckCallerIsSystemAppByIpc()) { + HILOG_ERROR("caller is not systemApp"); + return CALLER_ISNOT_SYSTEMAPP; + } + + return currentStackManager_->GetRecentMissions(numMax, flags, recentList); +} + +int AbilityManagerService::GetMissionSnapshot(const int32_t missionId, MissionSnapshotInfo &snapshot) +{ + return 0; +} + +int AbilityManagerService::SetMissionDescriptionInfo( + const sptr &token, const MissionDescriptionInfo &description) +{ + HILOG_INFO("%{public}s called", __func__); + CHECK_POINTER_AND_RETURN(token, ERR_INVALID_VALUE); + CHECK_POINTER_AND_RETURN(currentStackManager_, INNER_ERR); + + auto abilityRecord = Token::GetAbilityRecordByToken(token); + CHECK_POINTER_AND_RETURN(abilityRecord, ERR_INVALID_VALUE); + + return currentStackManager_->SetMissionDescriptionInfo(abilityRecord, description); +} + +int AbilityManagerService::GetMissionLockModeState() +{ + HILOG_INFO("%{public}s called", __func__); + CHECK_POINTER_AND_RETURN(currentStackManager_, ERR_INVALID_VALUE); + return currentStackManager_->GetMissionLockModeState(); +} + +int AbilityManagerService::UpdateConfiguration(const DummyConfiguration &config) +{ + HILOG_INFO("%{public}s called", __func__); + CHECK_POINTER_AND_RETURN(currentStackManager_, ERR_INVALID_VALUE); + CHECK_POINTER_AND_RETURN(systemAppManager_, ERR_INVALID_VALUE); + + systemAppManager_->UpdateConfiguration(config); + + return currentStackManager_->UpdateConfiguration(config); +} + +int AbilityManagerService::MoveMissionToTop(int32_t missionId) +{ + HILOG_INFO("Move mission to top."); + if (missionId < 0) { + HILOG_ERROR("Mission id is invalid."); + return ERR_INVALID_VALUE; + } + + return currentStackManager_->MoveMissionToTop(missionId); +} + +int AbilityManagerService::MoveMissionToEnd(const sptr &token, const bool nonFirst) +{ + HILOG_INFO("Move mission to end."); + CHECK_POINTER_AND_RETURN(token, ERR_INVALID_VALUE); + if (!VerificationToken(token)) { + return ERR_INVALID_VALUE; + } + return currentStackManager_->MoveMissionToEnd(token, nonFirst); +} + +int AbilityManagerService::RemoveMission(int id) +{ + HILOG_INFO("Remove mission."); + if (id < 0) { + HILOG_ERROR("Mission id is invalid."); + return ERR_INVALID_VALUE; + } + if (!CheckCallerIsSystemAppByIpc()) { + HILOG_ERROR("caller is not systemApp"); + return CALLER_ISNOT_SYSTEMAPP; + } + return currentStackManager_->RemoveMissionById(id); +} + +int AbilityManagerService::RemoveStack(int id) +{ + HILOG_INFO("Remove stack."); + if (id < 0) { + HILOG_ERROR("Stack id is invalid."); + return ERR_INVALID_VALUE; + } + return currentStackManager_->RemoveStack(id); +} + +int AbilityManagerService::ConnectAbility( + const Want &want, const sptr &connect, const sptr &callerToken) +{ + HILOG_INFO("Connect ability."); + CHECK_POINTER_AND_RETURN(connect, ERR_INVALID_VALUE); + CHECK_POINTER_AND_RETURN(connect->AsObject(), ERR_INVALID_VALUE); + AbilityRequest abilityRequest; + int result = GenerateAbilityRequest(want, DEFAULT_INVAL_VALUE, abilityRequest, callerToken); + if (result != ERR_OK) { + HILOG_ERROR("Generate ability request error."); + return result; + } + auto abilityInfo = abilityRequest.abilityInfo; + result = AbilityUtil::JudgeAbilityVisibleControl(abilityInfo); + if (result != ERR_OK) { + HILOG_ERROR("%{public}s JudgeAbilityVisibleControl error.", __func__); + return result; + } + auto type = abilityInfo.type; + if (type != AppExecFwk::AbilityType::SERVICE) { + HILOG_ERROR("Connect Ability failed, target Ability is not Service."); + return TARGET_ABILITY_NOT_SERVICE; + } + result = PreLoadAppDataAbilities(abilityInfo.bundleName); + if (result != ERR_OK) { + HILOG_ERROR("ConnectAbility: App data ability preloading failed, '%{public}s', %{public}d", + abilityInfo.bundleName.c_str(), + result); + return result; + } + return connectManager_->ConnectAbilityLocked(abilityRequest, connect, callerToken); +} + +int AbilityManagerService::DisconnectAbility(const sptr &connect) +{ + HILOG_DEBUG("Disconnect ability."); + CHECK_POINTER_AND_RETURN(connect, ERR_INVALID_VALUE); + CHECK_POINTER_AND_RETURN(connect->AsObject(), ERR_INVALID_VALUE); + return connectManager_->DisconnectAbilityLocked(connect); +} + +void AbilityManagerService::RemoveAllServiceRecord() +{ + connectManager_->RemoveAll(); +} + +sptr AbilityManagerService::GetWantSender( + const WantSenderInfo &wantSenderInfo, const sptr &callerToken) +{ + HILOG_INFO("Get want Sender."); + CHECK_POINTER_AND_RETURN(pendingWantManager_, nullptr); + + auto bms = GetBundleManager(); + CHECK_POINTER_AND_RETURN(bms, nullptr); + + int32_t callerUid = IPCSkeleton::GetCallingUid(); + AppExecFwk::BundleInfo bundleInfo; + bool bundleMgrResult = + bms->GetBundleInfo(wantSenderInfo.bundleName, AppExecFwk::BundleFlag::GET_BUNDLE_DEFAULT, bundleInfo); + if (!bundleMgrResult) { + HILOG_ERROR("GetBundleInfo is fail."); + return nullptr; + } + + HILOG_INFO("AbilityManagerService::GetWantSender: bundleName = %{public}s", wantSenderInfo.bundleName.c_str()); + return pendingWantManager_->GetWantSender( + callerUid, bundleInfo.uid, bms->CheckIsSystemAppByUid(callerUid), wantSenderInfo, callerToken); +} + +int AbilityManagerService::SendWantSender(const sptr &target, const SenderInfo &senderInfo) +{ + HILOG_INFO("Send want sender."); + CHECK_POINTER_AND_RETURN(pendingWantManager_, ERR_INVALID_VALUE); + CHECK_POINTER_AND_RETURN(target, ERR_INVALID_VALUE); + return pendingWantManager_->SendWantSender(target, senderInfo); +} + +void AbilityManagerService::CancelWantSender(const sptr &sender) +{ + HILOG_INFO("Cancel want sender."); + CHECK_POINTER(pendingWantManager_); + CHECK_POINTER(sender); + + auto bms = GetBundleManager(); + CHECK_POINTER(bms); + + int32_t callerUid = IPCSkeleton::GetCallingUid(); + sptr record = iface_cast(sender->AsObject()); + + AppExecFwk::BundleInfo bundleInfo; + bool bundleMgrResult = + bms->GetBundleInfo(record->GetKey()->GetBundleName(), AppExecFwk::BundleFlag::GET_BUNDLE_DEFAULT, bundleInfo); + if (!bundleMgrResult) { + HILOG_ERROR("GetBundleInfo is fail."); + return; + } + + pendingWantManager_->CancelWantSender(callerUid, bundleInfo.uid, bms->CheckIsSystemAppByUid(callerUid), sender); +} + +int AbilityManagerService::GetPendingWantUid(const sptr &target) +{ + HILOG_INFO("%{public}s:begin.", __func__); + + if (pendingWantManager_ == nullptr) { + HILOG_ERROR("%s, pendingWantManager_ is nullptr", __func__); + return -1; + } + if (target == nullptr) { + HILOG_ERROR("%s, target is nullptr", __func__); + return -1; + } + return pendingWantManager_->GetPendingWantUid(target); +} + +int AbilityManagerService::GetPendingWantUserId(const sptr &target) +{ + HILOG_INFO("%{public}s:begin.", __func__); + + if (pendingWantManager_ == nullptr) { + HILOG_ERROR("%s, pendingWantManager_ is nullptr", __func__); + return -1; + } + if (target == nullptr) { + HILOG_ERROR("%s, target is nullptr", __func__); + return -1; + } + return pendingWantManager_->GetPendingWantUserId(target); +} + +std::string AbilityManagerService::GetPendingWantBundleName(const sptr &target) +{ + HILOG_INFO("Get pending want bundle name."); + CHECK_POINTER_AND_RETURN(pendingWantManager_, ""); + CHECK_POINTER_AND_RETURN(target, ""); + return pendingWantManager_->GetPendingWantBundleName(target); +} + +int AbilityManagerService::GetPendingWantCode(const sptr &target) +{ + HILOG_INFO("%{public}s:begin.", __func__); + + if (pendingWantManager_ == nullptr) { + HILOG_ERROR("%s, pendingWantManager_ is nullptr", __func__); + return -1; + } + if (target == nullptr) { + HILOG_ERROR("%s, target is nullptr", __func__); + return -1; + } + return pendingWantManager_->GetPendingWantCode(target); +} + +int AbilityManagerService::GetPendingWantType(const sptr &target) +{ + HILOG_INFO("%{public}s:begin.", __func__); + + if (pendingWantManager_ == nullptr) { + HILOG_ERROR("%s, pendingWantManager_ is nullptr", __func__); + return -1; + } + if (target == nullptr) { + HILOG_ERROR("%s, target is nullptr", __func__); + return -1; + } + return pendingWantManager_->GetPendingWantType(target); +} + +void AbilityManagerService::RegisterCancelListener(const sptr &sender, const sptr &receiver) +{ + HILOG_INFO("Register cancel listener."); + CHECK_POINTER(pendingWantManager_); + CHECK_POINTER(sender); + CHECK_POINTER(receiver); + pendingWantManager_->RegisterCancelListener(sender, receiver); +} + +void AbilityManagerService::UnregisterCancelListener( + const sptr &sender, const sptr &receiver) +{ + HILOG_INFO("Unregister cancel listener."); + CHECK_POINTER(pendingWantManager_); + CHECK_POINTER(sender); + CHECK_POINTER(receiver); + pendingWantManager_->UnregisterCancelListener(sender, receiver); +} + +int AbilityManagerService::GetPendingRequestWant(const sptr &target, std::shared_ptr &want) +{ + HILOG_INFO("Get pending request want."); + CHECK_POINTER_AND_RETURN(pendingWantManager_, ERR_INVALID_VALUE); + CHECK_POINTER_AND_RETURN(target, ERR_INVALID_VALUE); + CHECK_POINTER_AND_RETURN(want, ERR_INVALID_VALUE); + return pendingWantManager_->GetPendingRequestWant(target, want); +} + +std::shared_ptr AbilityManagerService::GetServiceRecordByElementName(const std::string &element) +{ + return connectManager_->GetServiceRecordByElementName(element); +} + +std::list> AbilityManagerService::GetConnectRecordListByCallback( + sptr callback) +{ + return connectManager_->GetConnectRecordListByCallback(callback); +} + +sptr AbilityManagerService::AcquireDataAbility( + const Uri &uri, bool tryBind, const sptr &callerToken) +{ + HILOG_INFO("%{public}s, called. uid %{public}d", __func__, IPCSkeleton::GetCallingUid()); + bool isSystem = (IPCSkeleton::GetCallingUid() == AbilityUtil::SYSTEM_UID); + if (!isSystem) { + HILOG_INFO("callerToken not system %{public}s", __func__); + if (!VerificationToken(callerToken)) { + HILOG_INFO("VerificationToken fail"); + return nullptr; + } + } + + auto bms = GetBundleManager(); + CHECK_POINTER_AND_RETURN(bms, nullptr); + + auto localUri(uri); + if (localUri.GetScheme() != AbilityConfig::SCHEME_DATA_ABILITY) { + HILOG_ERROR("Acquire data ability with invalid uri scheme."); + return nullptr; + } + std::vector pathSegments; + localUri.GetPathSegments(pathSegments); + if (pathSegments.empty()) { + HILOG_ERROR("Acquire data ability with invalid uri path."); + return nullptr; + } + + AbilityRequest abilityRequest; + std::string dataAbilityUri = localUri.ToString(); + bool queryResult = iBundleManager_->QueryAbilityInfoByUri(dataAbilityUri, abilityRequest.abilityInfo); + if (!queryResult || abilityRequest.abilityInfo.name.empty() || abilityRequest.abilityInfo.bundleName.empty()) { + HILOG_ERROR("Invalid ability info for data ability acquiring."); + return nullptr; + } + int result = AbilityUtil::JudgeAbilityVisibleControl(abilityRequest.abilityInfo); + if (result != ERR_OK) { + HILOG_ERROR("%{public}s JudgeAbilityVisibleControl error.", __func__); + return nullptr; + } + abilityRequest.appInfo = abilityRequest.abilityInfo.applicationInfo; + if (abilityRequest.appInfo.name.empty() || abilityRequest.appInfo.bundleName.empty()) { + HILOG_ERROR("Invalid app info for data ability acquiring."); + return nullptr; + } + if (abilityRequest.abilityInfo.type != AppExecFwk::AbilityType::DATA) { + HILOG_ERROR("BMS query result is not a data ability."); + return nullptr; + } + HILOG_DEBUG("Query data ability info: %{public}s|%{public}s|%{public}s", + abilityRequest.appInfo.name.c_str(), + abilityRequest.appInfo.bundleName.c_str(), + abilityRequest.abilityInfo.name.c_str()); + + return dataAbilityManager_->Acquire(abilityRequest, tryBind, callerToken, isSystem); +} + +int AbilityManagerService::ReleaseDataAbility( + sptr dataAbilityScheduler, const sptr &callerToken) +{ + HILOG_INFO("%{public}s, called.", __func__); + bool isSystem = (IPCSkeleton::GetCallingUid() == AbilityUtil::SYSTEM_UID); + if (!isSystem) { + HILOG_INFO("callerToken not system %{public}s", __func__); + if (!VerificationToken(callerToken)) { + HILOG_INFO("VerificationToken fail"); + return ERR_INVALID_STATE; + } + } + + return dataAbilityManager_->Release(dataAbilityScheduler, callerToken, isSystem); +} + +int AbilityManagerService::AttachAbilityThread( + const sptr &scheduler, const sptr &token) +{ + HILOG_INFO("Attach ability thread."); + CHECK_POINTER_AND_RETURN(scheduler, ERR_INVALID_VALUE); + + if (!VerificationToken(token)) { + return ERR_INVALID_VALUE; + } + + auto abilityRecord = Token::GetAbilityRecordByToken(token); + CHECK_POINTER_AND_RETURN(abilityRecord, ERR_INVALID_VALUE); + + auto abilityInfo = abilityRecord->GetAbilityInfo(); + auto type = abilityInfo.type; + if (type == AppExecFwk::AbilityType::SERVICE) { + return connectManager_->AttachAbilityThreadLocked(scheduler, token); + } + if (type == AppExecFwk::AbilityType::DATA) { + return dataAbilityManager_->AttachAbilityThread(scheduler, token); + } + if (IsSystemUiApp(abilityInfo)) { + return systemAppManager_->AttachAbilityThread(scheduler, token); + } + return currentStackManager_->AttachAbilityThread(scheduler, token); +} + +void AbilityManagerService::DumpFuncInit() +{ + dumpFuncMap_[KEY_DUMP_ALL] = &AbilityManagerService::DumpInner; + dumpFuncMap_[KEY_DUMP_STACK_LIST] = &AbilityManagerService::DumpStackListInner; + dumpFuncMap_[KEY_DUMP_STACK] = &AbilityManagerService::DumpStackInner; + dumpFuncMap_[KEY_DUMP_MISSION] = &AbilityManagerService::DumpMissionInner; + dumpFuncMap_[KEY_DUMP_TOP_ABILITY] = &AbilityManagerService::DumpTopAbilityInner; + dumpFuncMap_[KEY_DUMP_WAIT_QUEUE] = &AbilityManagerService::DumpWaittingAbilityQueueInner; + dumpFuncMap_[KEY_DUMP_SERVICE] = &AbilityManagerService::DumpStateInner; + dumpFuncMap_[KEY_DUMP_DATA] = &AbilityManagerService::DataDumpStateInner; + dumpFuncMap_[KEY_DUMP_SYSTEM_UI] = &AbilityManagerService::SystemDumpStateInner; + dumpFuncMap_[KEY_DUMP_FOCUS_ABILITY] = &AbilityManagerService::DumpFocusMapInner; +} + +void AbilityManagerService::DumpInner(const std::string &args, std::vector &info) +{ + currentStackManager_->Dump(info); +} + +void AbilityManagerService::DumpStackListInner(const std::string &args, std::vector &info) +{ + currentStackManager_->DumpStackList(info); +} + +void AbilityManagerService::DumpFocusMapInner(const std::string &args, std::vector &info) +{ + currentStackManager_->DumpFocusMap(info); +} + +void AbilityManagerService::DumpStackInner(const std::string &args, std::vector &info) +{ + std::vector argList; + SplitStr(args, " ", argList); + if (argList.empty()) { + return; + } + if (argList.size() < MIN_DUMP_ARGUMENT_NUM) { + info.push_back("error: invalid argument, please see 'ability dump -h'."); + return; + } + int stackId = DEFAULT_INVAL_VALUE; + (void)StrToInt(argList[1], stackId); + currentStackManager_->DumpStack(stackId, info); +} + +void AbilityManagerService::DumpMissionInner(const std::string &args, std::vector &info) +{ + std::vector argList; + SplitStr(args, " ", argList); + if (argList.empty()) { + return; + } + if (argList.size() < MIN_DUMP_ARGUMENT_NUM) { + info.push_back("error: invalid argument, please see 'ability dump -h'."); + return; + } + int missionId = DEFAULT_INVAL_VALUE; + (void)StrToInt(argList[1], missionId); + currentStackManager_->DumpMission(missionId, info); +} + +void AbilityManagerService::DumpTopAbilityInner(const std::string &args, std::vector &info) +{ + currentStackManager_->DumpTopAbility(info); +} + +void AbilityManagerService::DumpWaittingAbilityQueueInner(const std::string &args, std::vector &info) +{ + std::string result; + DumpWaittingAbilityQueue(result); + info.push_back(result); +} + +void AbilityManagerService::DumpStateInner(const std::string &args, std::vector &info) +{ + std::vector argList; + SplitStr(args, " ", argList); + if (argList.empty()) { + return; + } + if (argList.size() == MIN_DUMP_ARGUMENT_NUM) { + connectManager_->DumpState(info, argList[1]); + } else if (argList.size() < MIN_DUMP_ARGUMENT_NUM) { + connectManager_->DumpState(info); + } else { + info.emplace_back("error: invalid argument, please see 'ability dump -h'."); + } +} + +void AbilityManagerService::DataDumpStateInner(const std::string &args, std::vector &info) +{ + std::vector argList; + SplitStr(args, " ", argList); + if (argList.empty()) { + return; + } + if (argList.size() == MIN_DUMP_ARGUMENT_NUM) { + dataAbilityManager_->DumpState(info, argList[1]); + } else if (argList.size() < MIN_DUMP_ARGUMENT_NUM) { + dataAbilityManager_->DumpState(info); + } else { + info.emplace_back("error: invalid argument, please see 'ability dump -h'."); + } +} + +void AbilityManagerService::SystemDumpStateInner(const std::string &args, std::vector &info) +{ + systemAppManager_->DumpState(info); +} + +void AbilityManagerService::DumpState(const std::string &args, std::vector &info) +{ + std::vector argList; + SplitStr(args, " ", argList); + if (argList.empty()) { + return; + } + auto it = dumpMap.find(argList[0]); + if (it == dumpMap.end()) { + return; + } + DumpKey key = it->second; + auto itFunc = dumpFuncMap_.find(key); + if (itFunc != dumpFuncMap_.end()) { + auto dumpFunc = itFunc->second; + if (dumpFunc != nullptr) { + (this->*dumpFunc)(args, info); + return; + } + } + info.push_back("error: invalid argument, please see 'ability dump -h'."); +} + +int AbilityManagerService::AbilityTransitionDone(const sptr &token, int state) +{ + HILOG_INFO("Ability transition done, state:%{public}d", state); + if (!VerificationToken(token)) { + return ERR_INVALID_VALUE; + } + + auto abilityRecord = Token::GetAbilityRecordByToken(token); + CHECK_POINTER_AND_RETURN_LOG(abilityRecord, ERR_INVALID_VALUE, "Ability record is nullptr."); + + auto abilityInfo = abilityRecord->GetAbilityInfo(); + HILOG_DEBUG("state:%{public}d name:%{public}s", state, abilityInfo.name.c_str()); + auto type = abilityInfo.type; + if (type == AppExecFwk::AbilityType::SERVICE) { + return connectManager_->AbilityTransitionDone(token, state); + } + if (type == AppExecFwk::AbilityType::DATA) { + return dataAbilityManager_->AbilityTransitionDone(token, state); + } + if (IsSystemUiApp(abilityInfo)) { + return systemAppManager_->AbilityTransitionDone(token, state); + } + + return currentStackManager_->AbilityTransitionDone(token, state); +} + +int AbilityManagerService::ScheduleConnectAbilityDone( + const sptr &token, const sptr &remoteObject) +{ + HILOG_INFO("Schedule connect ability done."); + if (!VerificationToken(token)) { + return ERR_INVALID_VALUE; + } + + auto abilityRecord = Token::GetAbilityRecordByToken(token); + CHECK_POINTER_AND_RETURN(abilityRecord, ERR_INVALID_VALUE); + + auto type = abilityRecord->GetAbilityInfo().type; + if (type != AppExecFwk::AbilityType::SERVICE) { + HILOG_ERROR("Connect ability failed, target ability is not service."); + return TARGET_ABILITY_NOT_SERVICE; + } + + return connectManager_->ScheduleConnectAbilityDoneLocked(token, remoteObject); +} + +int AbilityManagerService::ScheduleDisconnectAbilityDone(const sptr &token) +{ + HILOG_INFO("Schedule disconnect ability done."); + if (!VerificationToken(token)) { + return ERR_INVALID_VALUE; + } + + auto abilityRecord = Token::GetAbilityRecordByToken(token); + CHECK_POINTER_AND_RETURN(abilityRecord, ERR_INVALID_VALUE); + + auto type = abilityRecord->GetAbilityInfo().type; + if (type != AppExecFwk::AbilityType::SERVICE) { + HILOG_ERROR("Connect ability failed, target ability is not service."); + return TARGET_ABILITY_NOT_SERVICE; + } + + return connectManager_->ScheduleDisconnectAbilityDoneLocked(token); +} + +int AbilityManagerService::ScheduleCommandAbilityDone(const sptr &token) +{ + HILOG_INFO("Schedule command ability done."); + if (!VerificationToken(token)) { + return ERR_INVALID_VALUE; + } + + auto abilityRecord = Token::GetAbilityRecordByToken(token); + CHECK_POINTER_AND_RETURN(abilityRecord, ERR_INVALID_VALUE); + + auto type = abilityRecord->GetAbilityInfo().type; + if (type != AppExecFwk::AbilityType::SERVICE) { + HILOG_ERROR("Connect ability failed, target ability is not service."); + return TARGET_ABILITY_NOT_SERVICE; + } + + return connectManager_->ScheduleCommandAbilityDoneLocked(token); +} + +void AbilityManagerService::AddWindowInfo(const sptr &token, int32_t windowToken) +{ + HILOG_DEBUG("Add window id."); + if (!VerificationToken(token)) { + return; + } + currentStackManager_->AddWindowInfo(token, windowToken); +} + +void AbilityManagerService::OnAbilityRequestDone(const sptr &token, const int32_t state) +{ + HILOG_INFO("On ability request done."); + if (!VerificationToken(token)) { + return; + } + + auto abilityRecord = Token::GetAbilityRecordByToken(token); + CHECK_POINTER(abilityRecord); + + auto type = abilityRecord->GetAbilityInfo().type; + switch (type) { + case AppExecFwk::AbilityType::SERVICE: + connectManager_->OnAbilityRequestDone(token, state); + break; + case AppExecFwk::AbilityType::DATA: + dataAbilityManager_->OnAbilityRequestDone(token, state); + break; + default: { + if (IsSystemUiApp(abilityRecord->GetAbilityInfo())) { + systemAppManager_->OnAbilityRequestDone(token, state); + break; + } + currentStackManager_->OnAbilityRequestDone(token, state); + break; + } + } +} + +void AbilityManagerService::OnAppStateChanged(const AppInfo &info) +{ + HILOG_INFO("On app state changed."); + currentStackManager_->OnAppStateChanged(info); + connectManager_->OnAppStateChanged(info); + systemAppManager_->OnAppStateChanged(info); + dataAbilityManager_->OnAppStateChanged(info); +} + +std::shared_ptr AbilityManagerService::GetEventHandler() +{ + return handler_; +} + +void AbilityManagerService::SetStackManager(int userId) +{ + auto iterator = stackManagers_.find(userId); + if (iterator != stackManagers_.end()) { + currentStackManager_ = iterator->second; + } else { + currentStackManager_ = std::make_shared(userId); + currentStackManager_->Init(); + stackManagers_.emplace(userId, currentStackManager_); + } +} + +std::shared_ptr AbilityManagerService::GetStackManager() +{ + return currentStackManager_; +} + +void AbilityManagerService::DumpWaittingAbilityQueue(std::string &result) +{ + currentStackManager_->DumpWaittingAbilityQueue(result); + return; +} + +// multi user scene +int AbilityManagerService::GetUserId() +{ + return DEFAULT_USER_ID; +} + +void AbilityManagerService::StartingLauncherAbility() +{ + HILOG_DEBUG("%{public}s", __func__); + if (!iBundleManager_) { + HILOG_INFO("bms service is null"); + } + + /* query if launcher ability has installed */ + AppExecFwk::AbilityInfo abilityInfo; + /* First stage, hardcoding for the first launcher App */ + Want want; + want.SetElementName(AbilityConfig::LAUNCHER_BUNDLE_NAME, AbilityConfig::LAUNCHER_ABILITY_NAME); + while (!(iBundleManager_->QueryAbilityInfo(want, abilityInfo))) { + HILOG_INFO("Waiting query launcher ability info completed."); + usleep(REPOLL_TIME_MICRO_SECONDS); + } + + HILOG_INFO("waiting boot animation for 5 seconds."); + usleep(REPOLL_TIME_MICRO_SECONDS * WAITING_BOOT_ANIMATION_TIMER); + HILOG_INFO("Start Home Launcher Ability."); + /* start launch ability */ + (void)StartAbility(want, DEFAULT_INVAL_VALUE); + return; +} + +void AbilityManagerService::StartSystemUi(const std::string abilityName) +{ + HILOG_INFO("Starting system ui app."); + Want want; + want.SetElementName(AbilityConfig::SYSTEM_UI_BUNDLE_NAME, abilityName); + HILOG_INFO("Ability name: %{public}s.", abilityName.c_str()); + (void)StartAbility(want, DEFAULT_INVAL_VALUE); + return; +} + +int AbilityManagerService::GenerateAbilityRequest( + const Want &want, int requestCode, AbilityRequest &request, const sptr &callerToken) +{ + request.want = want; + request.requestCode = requestCode; + request.callerToken = callerToken; + request.startSetting = nullptr; + + auto bms = GetBundleManager(); + CHECK_POINTER_AND_RETURN(bms, GET_ABILITY_SERVICE_FAILED); + + bms->QueryAbilityInfo(want, request.abilityInfo); + if (request.abilityInfo.name.empty() || request.abilityInfo.bundleName.empty()) { + HILOG_ERROR("Get ability info failed."); + return RESOLVE_ABILITY_ERR; + } + HILOG_DEBUG("Query ability name: %{public}s,", request.abilityInfo.name.c_str()); + + request.appInfo = request.abilityInfo.applicationInfo; + if (request.appInfo.name.empty() || request.appInfo.bundleName.empty()) { + HILOG_ERROR("Get app info failed."); + return RESOLVE_APP_ERR; + } + HILOG_DEBUG("Query app name: %{public}s,", request.appInfo.name.c_str()); + return ERR_OK; +} + +int AbilityManagerService::GetAllStackInfo(StackInfo &stackInfo) +{ + HILOG_DEBUG("Get all stack info."); + CHECK_POINTER_AND_RETURN(currentStackManager_, ERR_NO_INIT); + currentStackManager_->GetAllStackInfo(stackInfo); + return ERR_OK; +} + +int AbilityManagerService::TerminateAbilityResult(const sptr &token, int startId) +{ + HILOG_INFO("Terminate ability result, startId: %{public}d", startId); + if (!VerificationToken(token)) { + return ERR_INVALID_VALUE; + } + + auto abilityRecord = Token::GetAbilityRecordByToken(token); + CHECK_POINTER_AND_RETURN(abilityRecord, ERR_INVALID_VALUE); + int result = AbilityUtil::JudgeAbilityVisibleControl(abilityRecord->GetAbilityInfo()); + if (result != ERR_OK) { + HILOG_ERROR("%{public}s JudgeAbilityVisibleControl error.", __func__); + return result; + } + + auto type = abilityRecord->GetAbilityInfo().type; + if (type != AppExecFwk::AbilityType::SERVICE) { + HILOG_ERROR("target ability is not service."); + return TARGET_ABILITY_NOT_SERVICE; + } + + return connectManager_->TerminateAbilityResult(token, startId); +} + +int AbilityManagerService::StopServiceAbility(const Want &want) +{ + HILOG_DEBUG("Stop service ability."); + AbilityRequest abilityRequest; + int result = GenerateAbilityRequest(want, DEFAULT_INVAL_VALUE, abilityRequest, nullptr); + if (result != ERR_OK) { + HILOG_ERROR("Generate ability request error."); + return result; + } + auto abilityInfo = abilityRequest.abilityInfo; + auto type = abilityInfo.type; + if (type != AppExecFwk::AbilityType::SERVICE) { + HILOG_ERROR("Target ability is not service type."); + return TARGET_ABILITY_NOT_SERVICE; + } + return connectManager_->StopServiceAbility(abilityRequest); +} + +void AbilityManagerService::OnAbilityDied(std::shared_ptr abilityRecord) +{ + CHECK_POINTER(abilityRecord); + + if (systemAppManager_ && abilityRecord->IsKernalSystemAbility()) { + systemAppManager_->OnAbilityDied(abilityRecord); + return; + } + + if (currentStackManager_) { + currentStackManager_->OnAbilityDied(abilityRecord); + } + + if (connectManager_) { + connectManager_->OnAbilityDied(abilityRecord); + } + + if (dataAbilityManager_) { + dataAbilityManager_->OnAbilityDied(abilityRecord); + } +} + +int AbilityManagerService::KillProcess(const std::string &bundleName) +{ + HILOG_DEBUG("Kill process, bundleName: %{public}s", bundleName.c_str()); + int ret = DelayedSingleton::GetInstance()->KillApplication(bundleName); + if (ret != ERR_OK) { + return KILL_PROCESS_FAILED; + } + return ERR_OK; +} + +int AbilityManagerService::UninstallApp(const std::string &bundleName) +{ + HILOG_DEBUG("Uninstall app, bundleName: %{public}s", bundleName.c_str()); + CHECK_POINTER_AND_RETURN(currentStackManager_, ERR_NO_INIT); + currentStackManager_->UninstallApp(bundleName); + int ret = DelayedSingleton::GetInstance()->KillApplication(bundleName); + if (ret != ERR_OK) { + return UNINSTALL_APP_FAILED; + } + return ERR_OK; +} + +sptr AbilityManagerService::GetBundleManager() +{ + if (iBundleManager_ == nullptr) { + auto bundleObj = + OHOS::DelayedSingleton::GetInstance()->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID); + if (bundleObj == nullptr) { + HILOG_ERROR("Failed to get bundle manager service."); + return nullptr; + } + iBundleManager_ = iface_cast(bundleObj); + } + + return iBundleManager_; +} + +int AbilityManagerService::PreLoadAppDataAbilities(const std::string &bundleName) +{ + if (bundleName.empty()) { + HILOG_ERROR("Invalid bundle name when app data abilities preloading."); + return ERR_INVALID_VALUE; + } + + if (dataAbilityManager_ == nullptr) { + HILOG_ERROR("Invalid data ability manager when app data abilities preloading."); + return ERR_INVALID_STATE; + } + + auto bms = GetBundleManager(); + CHECK_POINTER_AND_RETURN(bms, GET_ABILITY_SERVICE_FAILED); + + AppExecFwk::BundleInfo bundleInfo; + bool ret = bms->GetBundleInfo(bundleName, AppExecFwk::BundleFlag::GET_BUNDLE_WITH_ABILITIES, bundleInfo); + if (!ret) { + HILOG_ERROR("Failed to get bundle info when app data abilities preloading."); + return RESOLVE_APP_ERR; + } + + HILOG_INFO("App data abilities preloading for bundle '%{public}s'...", bundleName.data()); + + auto begin = system_clock::now(); + AbilityRequest dataAbilityRequest; + dataAbilityRequest.appInfo = bundleInfo.applicationInfo; + for (auto it = bundleInfo.abilityInfos.begin(); it != bundleInfo.abilityInfos.end(); ++it) { + if (it->type != AppExecFwk::AbilityType::DATA) { + continue; + } + if ((system_clock::now() - begin) >= DATA_ABILITY_START_TIMEOUT) { + HILOG_ERROR("App data ability preloading for '%{public}s' timeout.", bundleName.c_str()); + return ERR_TIMED_OUT; + } + dataAbilityRequest.abilityInfo = *it; + HILOG_INFO("App data ability preloading: '%{public}s.%{public}s'...", it->bundleName.c_str(), it->name.c_str()); + + auto dataAbility = dataAbilityManager_->Acquire(dataAbilityRequest, false, nullptr, false); + if (dataAbility == nullptr) { + HILOG_ERROR( + "Failed to preload data ability '%{public}s.%{public}s'.", it->bundleName.c_str(), it->name.c_str()); + return ERR_NULL_OBJECT; + } + } + + HILOG_INFO("App data abilities preloading done."); + + return ERR_OK; +} + +bool AbilityManagerService::IsSystemUiApp(const AppExecFwk::AbilityInfo &info) const +{ + if (info.bundleName != AbilityConfig::SYSTEM_UI_BUNDLE_NAME) { + return false; + } + return (info.name == AbilityConfig::SYSTEM_UI_NAVIGATION_BAR || info.name == AbilityConfig::SYSTEM_UI_STATUS_BAR); +} + +void AbilityManagerService::HandleLoadTimeOut(int64_t eventId) +{ + HILOG_DEBUG("Handle load timeout."); + if (systemAppManager_) { + systemAppManager_->OnTimeOut(AbilityManagerService::LOAD_TIMEOUT_MSG, eventId); + } + if (currentStackManager_) { + currentStackManager_->OnTimeOut(AbilityManagerService::LOAD_TIMEOUT_MSG, eventId); + } +} + +void AbilityManagerService::HandleActiveTimeOut(int64_t eventId) +{ + HILOG_DEBUG("Handle active timeout."); + if (systemAppManager_) { + systemAppManager_->OnTimeOut(AbilityManagerService::ACTIVE_TIMEOUT_MSG, eventId); + } + if (currentStackManager_) { + currentStackManager_->OnTimeOut(AbilityManagerService::ACTIVE_TIMEOUT_MSG, eventId); + } +} + +void AbilityManagerService::HandleInactiveTimeOut(int64_t eventId) +{ + HILOG_DEBUG("Handle inactive timeout."); + if (currentStackManager_) { + currentStackManager_->OnTimeOut(AbilityManagerService::INACTIVE_TIMEOUT_MSG, eventId); + } +} + +bool AbilityManagerService::VerificationToken(const sptr &token) +{ + HILOG_INFO("Verification token."); + CHECK_POINTER_RETURN_BOOL(currentStackManager_); + CHECK_POINTER_RETURN_BOOL(dataAbilityManager_); + CHECK_POINTER_RETURN_BOOL(connectManager_); + + if (currentStackManager_->GetAbilityRecordByToken(token)) { + return true; + } + + if (currentStackManager_->GetAbilityFromTerminateList(token)) { + return true; + } + + if (dataAbilityManager_->GetAbilityRecordByToken(token)) { + return true; + } + + if (connectManager_->GetServiceRecordByToken(token)) { + return true; + } + + if (systemAppManager_->GetAbilityRecordByToken(token)) { + return true; + } + + HILOG_ERROR("Failed to verify token."); + return false; +} + +int AbilityManagerService::MoveMissionToFloatingStack(const MissionOption &missionOption) +{ + HILOG_INFO("Move mission to floating stack."); + return currentStackManager_->MoveMissionToFloatingStack(missionOption); +} + +int AbilityManagerService::MoveMissionToSplitScreenStack(const MissionOption &missionOption) +{ + HILOG_INFO("Move mission to split screen stack."); + return currentStackManager_->MoveMissionToSplitScreenStack(missionOption); +} + +int AbilityManagerService::ChangeFocusAbility( + const sptr &lostFocusToken, const sptr &getFocusToken) +{ + HILOG_INFO("Change focus ability."); + CHECK_POINTER_AND_RETURN(lostFocusToken, ERR_INVALID_VALUE); + CHECK_POINTER_AND_RETURN(getFocusToken, ERR_INVALID_VALUE); + CHECK_POINTER_AND_RETURN(currentStackManager_, ERR_INVALID_VALUE); + + if (!VerificationToken(lostFocusToken)) { + return ERR_INVALID_VALUE; + } + + if (!VerificationToken(getFocusToken)) { + return ERR_INVALID_VALUE; + } + + return currentStackManager_->ChangeFocusAbility(lostFocusToken, getFocusToken); +} + +int AbilityManagerService::MinimizeMultiWindow(int missionId) +{ + HILOG_INFO("Minimize multi window."); + return currentStackManager_->MinimizeMultiWindow(missionId); +} + +int AbilityManagerService::MaximizeMultiWindow(int missionId) +{ + HILOG_INFO("Maximize multi window."); + return currentStackManager_->MaximizeMultiWindow(missionId); +} + +int AbilityManagerService::GetFloatingMissions(std::vector &list) +{ + HILOG_INFO("Get floating missions."); + return currentStackManager_->GetFloatingMissions(list); +} + +int AbilityManagerService::CloseMultiWindow(int missionId) +{ + HILOG_INFO("Close multi window."); + CHECK_POINTER_AND_RETURN(currentStackManager_, ERR_INVALID_VALUE); + return currentStackManager_->CloseMultiWindow(missionId); +} + +int AbilityManagerService::SetMissionStackSetting(const StackSetting &stackSetting) +{ + HILOG_INFO("Set mission stack setting."); + currentStackManager_->SetMissionStackSetting(stackSetting); + return ERR_OK; +} + +bool AbilityManagerService::IsFirstInMission(const sptr &token) +{ + HILOG_INFO("Is first in mission."); + CHECK_POINTER_RETURN_BOOL(token); + CHECK_POINTER_RETURN_BOOL(currentStackManager_); + + if (!VerificationToken(token)) { + return false; + } + + return currentStackManager_->IsFirstInMission(token); +} + +int AbilityManagerService::CompelVerifyPermission(const std::string &permission, int pid, int uid, std::string &message) +{ + HILOG_INFO("Compel verify permission."); + return DelayedSingleton::GetInstance()->CompelVerifyPermission(permission, pid, uid, message); +} + +int AbilityManagerService::PowerOff() +{ + HILOG_INFO("Power off."); + CHECK_POINTER_AND_RETURN(currentStackManager_, ERR_NO_INIT); + return currentStackManager_->PowerOff(); +} + +int AbilityManagerService::PowerOn() +{ + HILOG_INFO("Power on."); + CHECK_POINTER_AND_RETURN(currentStackManager_, ERR_NO_INIT); + return currentStackManager_->PowerOn(); +} + +int AbilityManagerService::LockMission(int missionId) +{ + HILOG_INFO("request lock mission id :%{public}d", missionId); + CHECK_POINTER_AND_RETURN(currentStackManager_, ERR_NO_INIT); + CHECK_POINTER_AND_RETURN(iBundleManager_, ERR_NO_INIT); + + int callerUid = IPCSkeleton::GetCallingUid(); + int callerPid = IPCSkeleton::GetCallingPid(); + bool isSystemApp = iBundleManager_->CheckIsSystemAppByUid(callerUid); + HILOG_DEBUG("locker uid :%{public}d, pid :%{public}d. isSystemApp: %{public}d", callerUid, callerPid, isSystemApp); + return currentStackManager_->StartLockMission(callerUid, missionId, isSystemApp, true); +} + +int AbilityManagerService::UnlockMission(int missionId) +{ + HILOG_INFO("request unlock mission id :%{public}d", missionId); + CHECK_POINTER_AND_RETURN(currentStackManager_, ERR_NO_INIT); + CHECK_POINTER_AND_RETURN(iBundleManager_, ERR_NO_INIT); + + int callerUid = IPCSkeleton::GetCallingUid(); + int callerPid = IPCSkeleton::GetCallingPid(); + bool isSystemApp = iBundleManager_->CheckIsSystemAppByUid(callerUid); + HILOG_DEBUG("locker uid :%{public}d, pid :%{public}d. isSystemApp: %{public}d", callerUid, callerPid, isSystemApp); + return currentStackManager_->StartLockMission(callerUid, missionId, isSystemApp, false); +} + +int AbilityManagerService::GetUidByBundleName(std::string bundleName) +{ + CHECK_POINTER_AND_RETURN(iBundleManager_, -1); + return iBundleManager_->GetUidByBundleName(bundleName, GetUserId()); +} + +void AbilityManagerService::RestartAbility(const sptr &token) +{ + HILOG_INFO("%{public}s called", __func__); + CHECK_POINTER(currentStackManager_); + CHECK_POINTER(systemAppManager_); + if (!VerificationToken(token)) { + return; + } + + auto abilityRecord = Token::GetAbilityRecordByToken(token); + CHECK_POINTER(abilityRecord); + + if (IsSystemUiApp(abilityRecord->GetAbilityInfo())) { + systemAppManager_->RestartAbility(abilityRecord); + return; + } + + currentStackManager_->RestartAbility(abilityRecord); +} + +void AbilityManagerService::NotifyBmsAbilityLifeStatus( + const std::string &bundleName, const std::string &abilityName, const int64_t launchTime) +{ + auto bundleManager = GetBundleManager(); + CHECK_POINTER(bundleManager); + bundleManager->NotifyActivityLifeStatus(bundleName, abilityName, launchTime); +} + +void AbilityManagerService::StartSystemApplication() +{ + HILOG_DEBUG("%{public}s", __func__); + + ConnectBmsService(); + + if (!amsConfigResolver_ || amsConfigResolver_->NonConfigFile()) { + HILOG_INFO("start all"); + StartingLauncherAbility(); + StartingSystemUiAbility(SatrtUiMode::STARTUIBOTH); + return; + } + + if (amsConfigResolver_->GetStartLauncherState()) { + HILOG_INFO("start launcher"); + StartingLauncherAbility(); + } + + if (amsConfigResolver_->GetStatusBarState()) { + HILOG_INFO("start status bar"); + StartingSystemUiAbility(SatrtUiMode::STATUSBAR); + } + + if (amsConfigResolver_->GetNavigationBarState()) { + HILOG_INFO("start navigation bar"); + StartingSystemUiAbility(SatrtUiMode::NAVIGATIONBAR); + } +} + +void AbilityManagerService::ConnectBmsService() +{ + HILOG_DEBUG("%{public}s", __func__); + HILOG_INFO("Waiting AppMgr Service run completed."); + while (!appScheduler_->Init(shared_from_this())) { + HILOG_ERROR("failed to init appScheduler_"); + usleep(REPOLL_TIME_MICRO_SECONDS); + } + + HILOG_INFO("Waiting BundleMgr Service run completed."); + /* wait until connected to bundle manager service */ + while (iBundleManager_ == nullptr) { + sptr bundle_obj = + OHOS::DelayedSingleton::GetInstance()->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID); + if (bundle_obj == nullptr) { + HILOG_ERROR("failed to get bundle manager service"); + usleep(REPOLL_TIME_MICRO_SECONDS); + continue; + } + iBundleManager_ = iface_cast(bundle_obj); + } + + HILOG_INFO("Connect bms success!"); +} + +void AbilityManagerService::StartingSystemUiAbility(const SatrtUiMode &mode) +{ + HILOG_DEBUG("%{public}s", __func__); + if (!iBundleManager_) { + HILOG_INFO("bms service is null"); + } + + AppExecFwk::AbilityInfo statusBarInfo; + AppExecFwk::AbilityInfo navigationBarInfo; + Want statusBarWant; + Want navigationBarWant; + statusBarWant.SetElementName(AbilityConfig::SYSTEM_UI_BUNDLE_NAME, AbilityConfig::SYSTEM_UI_STATUS_BAR); + navigationBarWant.SetElementName(AbilityConfig::SYSTEM_UI_BUNDLE_NAME, AbilityConfig::SYSTEM_UI_NAVIGATION_BAR); + uint32_t waitCnt = 0; + // Wait 10 minutes for the installation to complete. + while ((!(iBundleManager_->QueryAbilityInfo(statusBarWant, statusBarInfo)) || + !(iBundleManager_->QueryAbilityInfo(navigationBarWant, navigationBarInfo))) && + waitCnt < MAX_WAIT_SYSTEM_UI_NUM) { + HILOG_INFO("Waiting query system ui info completed."); + usleep(REPOLL_TIME_MICRO_SECONDS); + waitCnt++; + } + + HILOG_INFO("start ui mode : %{public}d", mode); + switch (mode) { + case SatrtUiMode::STATUSBAR: + StartSystemUi(AbilityConfig::SYSTEM_UI_STATUS_BAR); + break; + case SatrtUiMode::NAVIGATIONBAR: + StartSystemUi(AbilityConfig::SYSTEM_UI_NAVIGATION_BAR); + break; + case SatrtUiMode::STARTUIBOTH: + StartSystemUi(AbilityConfig::SYSTEM_UI_STATUS_BAR); + StartSystemUi(AbilityConfig::SYSTEM_UI_NAVIGATION_BAR); + break; + default: + HILOG_INFO("Input mode error ..."); + break; + } +} + +bool AbilityManagerService::CheckCallerIsSystemAppByIpc() +{ + HILOG_DEBUG("%{public}s begin", __func__); + auto bms = GetBundleManager(); + CHECK_POINTER_RETURN_BOOL(bms); + int32_t callerUid = IPCSkeleton::GetCallingUid(); + HILOG_ERROR("callerUid %{public}d", callerUid); + return bms->CheckIsSystemAppByUid(callerUid); +} +} // namespace AAFwk +} // namespace OHOS diff --git a/tools/services/abilitymgr/src/ability_manager_stub.cpp b/tools/services/abilitymgr/src/ability_manager_stub.cpp new file mode 100644 index 00000000000..15fce299245 --- /dev/null +++ b/tools/services/abilitymgr/src/ability_manager_stub.cpp @@ -0,0 +1,793 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ability_manager_stub.h" + +#include "errors.h" +#include "string_ex.h" + +#include "ability_connect_callback_proxy.h" +#include "ability_connect_callback_stub.h" +#include "ability_manager_errors.h" +#include "ability_scheduler_proxy.h" +#include "ability_scheduler_stub.h" + +namespace OHOS { +namespace AAFwk { + +AbilityManagerStub::AbilityManagerStub() +{ + FirstStepInit(); + SecondStepInit(); +} + +AbilityManagerStub::~AbilityManagerStub() +{ + requestFuncMap_.clear(); +} + +void AbilityManagerStub::FirstStepInit() +{ + requestFuncMap_[TERMINATE_ABILITY] = &AbilityManagerStub::TerminateAbilityInner; + requestFuncMap_[TERMINATE_ABILITY_BY_CALLER] = &AbilityManagerStub::TerminateAbilityByCallerInner; + requestFuncMap_[ATTACH_ABILITY_THREAD] = &AbilityManagerStub::AttachAbilityThreadInner; + requestFuncMap_[ABILITY_TRANSITION_DONE] = &AbilityManagerStub::AbilityTransitionDoneInner; + requestFuncMap_[CONNECT_ABILITY_DONE] = &AbilityManagerStub::ScheduleConnectAbilityDoneInner; + requestFuncMap_[DISCONNECT_ABILITY_DONE] = &AbilityManagerStub::ScheduleDisconnectAbilityDoneInner; + requestFuncMap_[ADD_WINDOW_INFO] = &AbilityManagerStub::AddWindowInfoInner; + requestFuncMap_[TERMINATE_ABILITY_RESULT] = &AbilityManagerStub::TerminateAbilityResultInner; + requestFuncMap_[LIST_STACK_INFO] = &AbilityManagerStub::GetAllStackInfoInner; + requestFuncMap_[GET_RECENT_MISSION] = &AbilityManagerStub::GetRecentMissionsInner; + requestFuncMap_[REMOVE_MISSION] = &AbilityManagerStub::RemoveMissionInner; + requestFuncMap_[REMOVE_STACK] = &AbilityManagerStub::RemoveStackInner; + requestFuncMap_[COMMAND_ABILITY_DONE] = &AbilityManagerStub::ScheduleCommandAbilityDoneInner; + requestFuncMap_[GET_MISSION_SNAPSHOT] = &AbilityManagerStub::GetMissionSnapshotInner; + requestFuncMap_[ACQUIRE_DATA_ABILITY] = &AbilityManagerStub::AcquireDataAbilityInner; + requestFuncMap_[RELEASE_DATA_ABILITY] = &AbilityManagerStub::ReleaseDataAbilityInner; + requestFuncMap_[MOVE_MISSION_TO_TOP] = &AbilityManagerStub::MoveMissionToTopInner; + requestFuncMap_[MOVE_MISSION_TO_END] = &AbilityManagerStub::MoveMissionToEndInner; + requestFuncMap_[KILL_PROCESS] = &AbilityManagerStub::KillProcessInner; + requestFuncMap_[UNINSTALL_APP] = &AbilityManagerStub::UninstallAppInner; + requestFuncMap_[START_ABILITY] = &AbilityManagerStub::StartAbilityInner; + requestFuncMap_[START_ABILITY_ADD_CALLER] = &AbilityManagerStub::StartAbilityAddCallerInner; + requestFuncMap_[CONNECT_ABILITY] = &AbilityManagerStub::ConnectAbilityInner; + requestFuncMap_[DISCONNECT_ABILITY] = &AbilityManagerStub::DisconnectAbilityInner; + requestFuncMap_[STOP_SERVICE_ABILITY] = &AbilityManagerStub::StopServiceAbilityInner; + requestFuncMap_[DUMP_STATE] = &AbilityManagerStub::DumpStateInner; + requestFuncMap_[START_ABILITY_FOR_SETTINGS] = &AbilityManagerStub::StartAbilityForSettingsInner; + requestFuncMap_[MOVE_MISSION_TO_FLOATING_STACK] = &AbilityManagerStub::MoveMissionToFloatingStackInner; + requestFuncMap_[MOVE_MISSION_TO_SPLITSCREEN_STACK] = &AbilityManagerStub::MoveMissionToSplitScreenStackInner; + requestFuncMap_[CHANGE_FOCUS_ABILITY] = &AbilityManagerStub::ChangeFocusAbilityInner; + requestFuncMap_[MINIMIZE_MULTI_WINDOW] = &AbilityManagerStub::MinimizeMultiWindowInner; +} + +void AbilityManagerStub::SecondStepInit() +{ + requestFuncMap_[MAXIMIZE_MULTI_WINDOW] = &AbilityManagerStub::MaximizeMultiWindowInner; + requestFuncMap_[GET_FLOATING_MISSIONS] = &AbilityManagerStub::GetFloatingMissionsInner; + requestFuncMap_[CLOSE_MULTI_WINDOW] = &AbilityManagerStub::CloseMultiWindowInner; + requestFuncMap_[SET_STACK_SETTING] = &AbilityManagerStub::SetMissionStackSettingInner; + requestFuncMap_[IS_FIRST_IN_MISSION] = &AbilityManagerStub::IsFirstInMissionInner; + requestFuncMap_[COMPEL_VERIFY_PERMISSION] = &AbilityManagerStub::CompelVerifyPermissionInner; + requestFuncMap_[POWER_OFF] = &AbilityManagerStub::PowerOffInner; + requestFuncMap_[POWER_ON] = &AbilityManagerStub::PowerOnInner; + requestFuncMap_[LUCK_MISSION] = &AbilityManagerStub::LockMissionInner; + requestFuncMap_[UNLUCK_MISSION] = &AbilityManagerStub::UnlockMissionInner; + requestFuncMap_[GET_PENDING_WANT_SENDER] = &AbilityManagerStub::GetWantSenderInner; + requestFuncMap_[SEND_PENDING_WANT_SENDER] = &AbilityManagerStub::SendWantSenderInner; + requestFuncMap_[CANCEL_PENDING_WANT_SENDER] = &AbilityManagerStub::CancelWantSenderInner; + requestFuncMap_[GET_PENDING_WANT_UID] = &AbilityManagerStub::GetPendingWantUidInner; + requestFuncMap_[GET_PENDING_WANT_USERID] = &AbilityManagerStub::GetPendingWantUserIdInner; + requestFuncMap_[GET_PENDING_WANT_BUNDLENAME] = &AbilityManagerStub::GetPendingWantBundleNameInner; + requestFuncMap_[GET_PENDING_WANT_CODE] = &AbilityManagerStub::GetPendingWantCodeInner; + requestFuncMap_[GET_PENDING_WANT_TYPE] = &AbilityManagerStub::GetPendingWantTypeInner; + requestFuncMap_[REGISTER_CANCEL_LISTENER] = &AbilityManagerStub::RegisterCancelListenerInner; + requestFuncMap_[UNREGISTER_CANCEL_LISTENER] = &AbilityManagerStub::UnregisterCancelListenerInner; + requestFuncMap_[GET_PENDING_REQUEST_WANT] = &AbilityManagerStub::GetPendingRequestWantInner; + requestFuncMap_[SET_MISSION_INFO] = &AbilityManagerStub::SetMissionDescriptionInfoInner; + requestFuncMap_[GET_MISSION_LOCK_MODE_STATE] = &AbilityManagerStub::GetMissionLockModeStateInner; + requestFuncMap_[UPDATE_CONFIGURATION] = &AbilityManagerStub::UpdateConfigurationInner; +} + +int AbilityManagerStub::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) +{ + HILOG_DEBUG("cmd = %{public}d, flags= %{public}d", code, option.GetFlags()); + std::u16string descriptor = AbilityManagerStub::GetDescriptor(); + std::u16string remoteDescriptor = data.ReadInterfaceToken(); + if (descriptor != remoteDescriptor) { + HILOG_INFO("local descriptor is not equal to remote"); + return ERR_INVALID_STATE; + } + + auto itFunc = requestFuncMap_.find(code); + if (itFunc != requestFuncMap_.end()) { + auto requestFunc = itFunc->second; + if (requestFunc != nullptr) { + return (this->*requestFunc)(data, reply); + } + } + HILOG_WARN("default case, need check."); + return IPCObjectStub::OnRemoteRequest(code, data, reply, option); +} + +int AbilityManagerStub::TerminateAbilityInner(MessageParcel &data, MessageParcel &reply) +{ + sptr token = data.ReadParcelable(); + int resultCode = data.ReadInt32(); + Want *resultWant = data.ReadParcelable(); + int32_t result = TerminateAbility(token, resultCode, resultWant); + reply.WriteInt32(result); + if (resultWant != nullptr) { + delete resultWant; + } + return NO_ERROR; +} + +int AbilityManagerStub::TerminateAbilityByCallerInner(MessageParcel &data, MessageParcel &reply) +{ + auto callerToken = data.ReadParcelable(); + int requestCode = data.ReadInt32(); + int32_t result = TerminateAbilityByCaller(callerToken, requestCode); + reply.WriteInt32(result); + return NO_ERROR; +} + +int AbilityManagerStub::AttachAbilityThreadInner(MessageParcel &data, MessageParcel &reply) +{ + auto scheduler = iface_cast(data.ReadParcelable()); + auto token = data.ReadParcelable(); + int32_t result = AttachAbilityThread(scheduler, token); + reply.WriteInt32(result); + return NO_ERROR; +} + +int AbilityManagerStub::AbilityTransitionDoneInner(MessageParcel &data, MessageParcel &reply) +{ + auto token = data.ReadParcelable(); + int targetState = data.ReadInt32(); + int32_t result = AbilityTransitionDone(token, targetState); + reply.WriteInt32(result); + return NO_ERROR; +} + +int AbilityManagerStub::ScheduleConnectAbilityDoneInner(MessageParcel &data, MessageParcel &reply) +{ + auto token = data.ReadParcelable(); + auto remoteObject = data.ReadParcelable(); + int32_t result = ScheduleConnectAbilityDone(token, remoteObject); + reply.WriteInt32(result); + return NO_ERROR; +} + +int AbilityManagerStub::ScheduleDisconnectAbilityDoneInner(MessageParcel &data, MessageParcel &reply) +{ + auto token = data.ReadParcelable(); + int32_t result = ScheduleDisconnectAbilityDone(token); + reply.WriteInt32(result); + return NO_ERROR; +} + +int AbilityManagerStub::AddWindowInfoInner(MessageParcel &data, MessageParcel &reply) +{ + sptr token = data.ReadParcelable(); + int windowToken = data.ReadInt32(); + AddWindowInfo(token, windowToken); + return NO_ERROR; +} + +int AbilityManagerStub::TerminateAbilityResultInner(MessageParcel &data, MessageParcel &reply) +{ + sptr token = data.ReadParcelable(); + int startId = data.ReadInt32(); + int32_t result = TerminateAbilityResult(token, startId); + reply.WriteInt32(result); + return NO_ERROR; +} + +int AbilityManagerStub::GetAllStackInfoInner(MessageParcel &data, MessageParcel &reply) +{ + StackInfo stackInfo; + int32_t result = GetAllStackInfo(stackInfo); + if (!reply.WriteInt32(result)) { + HILOG_ERROR("GetAllStackInfo result error"); + return ERR_INVALID_VALUE; + } + if (!reply.WriteParcelable(&stackInfo)) { + HILOG_ERROR("GetAllStackInfo error"); + return ERR_INVALID_VALUE; + } + return NO_ERROR; +} + +int AbilityManagerStub::GetRecentMissionsInner(MessageParcel &data, MessageParcel &reply) +{ + int numMax = data.ReadInt32(); + int flags = data.ReadInt32(); + std::vector missionInfos; + int32_t result = GetRecentMissions(numMax, flags, missionInfos); + reply.WriteInt32(missionInfos.size()); + for (auto &it : missionInfos) { + if (!reply.WriteParcelable(&it)) { + return ERR_INVALID_VALUE; + } + } + if (!reply.WriteInt32(result)) { + return ERR_INVALID_VALUE; + } + return result; +} + +int AbilityManagerStub::RemoveMissionInner(MessageParcel &data, MessageParcel &reply) +{ + int id = data.ReadInt32(); + int32_t result = RemoveMission(id); + if (!reply.WriteInt32(result)) { + HILOG_ERROR("remove mission error."); + return ERR_INVALID_VALUE; + } + return NO_ERROR; +} + +int AbilityManagerStub::RemoveStackInner(MessageParcel &data, MessageParcel &reply) +{ + int id = data.ReadInt32(); + int32_t result = RemoveStack(id); + if (!reply.WriteInt32(result)) { + HILOG_ERROR("remove stack error"); + return ERR_INVALID_VALUE; + } + return NO_ERROR; +} + +int AbilityManagerStub::ScheduleCommandAbilityDoneInner(MessageParcel &data, MessageParcel &reply) +{ + auto token = data.ReadParcelable(); + int32_t result = ScheduleCommandAbilityDone(token); + reply.WriteInt32(result); + return NO_ERROR; +} + +int AbilityManagerStub::GetMissionSnapshotInner(MessageParcel &data, MessageParcel &reply) +{ + MissionSnapshotInfo snapshot; + int32_t missionId = data.ReadInt32(); + int32_t result = GetMissionSnapshot(missionId, snapshot); + if (!reply.WriteParcelable(&snapshot)) { + HILOG_ERROR("GetMissionSnapshot error"); + return ERR_INVALID_VALUE; + } + + if (!reply.WriteInt32(result)) { + HILOG_ERROR("GetMissionSnapshot result error"); + return ERR_INVALID_VALUE; + } + return NO_ERROR; +} + +int AbilityManagerStub::AcquireDataAbilityInner(MessageParcel &data, MessageParcel &reply) +{ + std::unique_ptr uri(new Uri(data.ReadString())); + bool tryBind = data.ReadBool(); + sptr callerToken = data.ReadParcelable(); + sptr result = AcquireDataAbility(*uri, tryBind, callerToken); + HILOG_DEBUG("acquire data ability %{public}s", result ? "ok" : "failed"); + if (result) { + reply.WriteParcelable(result->AsObject()); + } else { + reply.WriteParcelable(nullptr); + } + return NO_ERROR; +} + +int AbilityManagerStub::ReleaseDataAbilityInner(MessageParcel &data, MessageParcel &reply) +{ + auto scheduler = iface_cast(data.ReadParcelable()); + auto callerToken = data.ReadParcelable(); + int32_t result = ReleaseDataAbility(scheduler, callerToken); + HILOG_DEBUG("release data ability ret = %d", result); + reply.WriteInt32(result); + return NO_ERROR; +} + +int AbilityManagerStub::MoveMissionToTopInner(MessageParcel &data, MessageParcel &reply) +{ + int32_t id = data.ReadInt32(); + int result = MoveMissionToTop(id); + if (!reply.WriteInt32(result)) { + HILOG_ERROR("move mission to top error"); + return ERR_INVALID_VALUE; + } + return NO_ERROR; +} + +int AbilityManagerStub::MoveMissionToEndInner(MessageParcel &data, MessageParcel &reply) +{ + auto token = data.ReadParcelable(); + auto nonFirst = data.ReadBool(); + int result = MoveMissionToEnd(token, nonFirst); + if (!reply.WriteInt32(result)) { + HILOG_ERROR("move mission to top error"); + return ERR_INVALID_VALUE; + } + return NO_ERROR; +} + +int AbilityManagerStub::KillProcessInner(MessageParcel &data, MessageParcel &reply) +{ + std::string bundleName = Str16ToStr8(data.ReadString16()); + int result = KillProcess(bundleName); + if (!reply.WriteInt32(result)) { + HILOG_ERROR("remove stack error"); + return ERR_INVALID_VALUE; + } + return NO_ERROR; +} + +int AbilityManagerStub::UninstallAppInner(MessageParcel &data, MessageParcel &reply) +{ + std::string bundleName = Str16ToStr8(data.ReadString16()); + int result = UninstallApp(bundleName); + if (!reply.WriteInt32(result)) { + HILOG_ERROR("remove stack error"); + return ERR_INVALID_VALUE; + } + return NO_ERROR; +} + +int AbilityManagerStub::StartAbilityInner(MessageParcel &data, MessageParcel &reply) +{ + Want *want = data.ReadParcelable(); + if (want == nullptr) { + HILOG_ERROR("want is nullptr"); + return ERR_INVALID_VALUE; + } + int requestCode = data.ReadInt32(); + int32_t result = StartAbility(*want, requestCode); + reply.WriteInt32(result); + delete want; + return NO_ERROR; +} + +int AbilityManagerStub::StartAbilityAddCallerInner(MessageParcel &data, MessageParcel &reply) +{ + Want *want = data.ReadParcelable(); + if (want == nullptr) { + HILOG_ERROR("want is nullptr"); + return ERR_INVALID_VALUE; + } + auto callerToken = data.ReadParcelable(); + int requestCode = data.ReadInt32(); + int32_t result = StartAbility(*want, callerToken, requestCode); + reply.WriteInt32(result); + delete want; + return NO_ERROR; +} + +int AbilityManagerStub::ConnectAbilityInner(MessageParcel &data, MessageParcel &reply) +{ + Want *want = data.ReadParcelable(); + if (want == nullptr) { + HILOG_ERROR("want is nullptr"); + return ERR_INVALID_VALUE; + } + auto callback = iface_cast(data.ReadParcelable()); + auto token = data.ReadParcelable(); + int32_t result = ConnectAbility(*want, callback, token); + reply.WriteInt32(result); + delete want; + return NO_ERROR; +} + +int AbilityManagerStub::DisconnectAbilityInner(MessageParcel &data, MessageParcel &reply) +{ + auto callback = iface_cast(data.ReadParcelable()); + int32_t result = DisconnectAbility(callback); + HILOG_DEBUG("disconnect ability ret = %d", result); + reply.WriteInt32(result); + return NO_ERROR; +} + +int AbilityManagerStub::StopServiceAbilityInner(MessageParcel &data, MessageParcel &reply) +{ + Want *want = data.ReadParcelable(); + if (want == nullptr) { + HILOG_ERROR("want is nullptr"); + return ERR_INVALID_VALUE; + } + int32_t result = StopServiceAbility(*want); + reply.WriteInt32(result); + delete want; + return NO_ERROR; +} + +int AbilityManagerStub::DumpStateInner(MessageParcel &data, MessageParcel &reply) +{ + std::vector result; + std::string args = Str16ToStr8(data.ReadString16()); + std::vector argList; + SplitStr(args, " ", argList); + if (argList.empty()) { + return ERR_INVALID_VALUE; + } + DumpState(args, result); + reply.WriteInt32(result.size()); + for (auto stack : result) { + reply.WriteString16(Str8ToStr16(stack)); + } + return NO_ERROR; +} + +int AbilityManagerStub::StartAbilityForSettingsInner(MessageParcel &data, MessageParcel &reply) +{ + Want *want = data.ReadParcelable(); + if (want == nullptr) { + HILOG_ERROR("want is nullptr"); + return ERR_INVALID_VALUE; + } + AbilityStartSetting *abilityStartSetting = data.ReadParcelable(); + auto callerToken = data.ReadParcelable(); + int requestCode = data.ReadInt32(); + int32_t result = StartAbility(*want, *abilityStartSetting, callerToken, requestCode); + reply.WriteInt32(result); + delete want; + delete abilityStartSetting; + return NO_ERROR; +} + +int AbilityManagerStub::MoveMissionToFloatingStackInner(MessageParcel &data, MessageParcel &reply) +{ + MissionOption *missionOption = data.ReadParcelable(); + if (missionOption == nullptr) { + HILOG_ERROR("missionOption is nullptr"); + return ERR_INVALID_VALUE; + } + + auto result = MoveMissionToFloatingStack(*missionOption); + reply.WriteInt32(result); + delete missionOption; + return NO_ERROR; +} + +int AbilityManagerStub::MoveMissionToSplitScreenStackInner(MessageParcel &data, MessageParcel &reply) +{ + MissionOption *missionOption = data.ReadParcelable(); + if (missionOption == nullptr) { + HILOG_ERROR("missionOption is nullptr"); + return ERR_INVALID_VALUE; + } + auto result = MoveMissionToSplitScreenStack(*missionOption); + reply.WriteInt32(result); + delete missionOption; + return NO_ERROR; +} + +int AbilityManagerStub::ChangeFocusAbilityInner(MessageParcel &data, MessageParcel &reply) +{ + auto loseToken = data.ReadParcelable(); + auto getToken = data.ReadParcelable(); + auto result = ChangeFocusAbility(loseToken, getToken); + reply.WriteInt32(result); + return NO_ERROR; +} + +int AbilityManagerStub::MinimizeMultiWindowInner(MessageParcel &data, MessageParcel &reply) +{ + auto missionId = data.ReadInt32(); + auto result = MinimizeMultiWindow(missionId); + reply.WriteInt32(result); + return NO_ERROR; +} + +int AbilityManagerStub::MaximizeMultiWindowInner(MessageParcel &data, MessageParcel &reply) +{ + auto missionId = data.ReadInt32(); + auto result = MaximizeMultiWindow(missionId); + reply.WriteInt32(result); + return NO_ERROR; +} + +int AbilityManagerStub::GetFloatingMissionsInner(MessageParcel &data, MessageParcel &reply) +{ + std::vector missionInfos; + auto result = GetFloatingMissions(missionInfos); + reply.WriteInt32(missionInfos.size()); + for (auto &it : missionInfos) { + if (!reply.WriteParcelable(&it)) { + return ERR_INVALID_VALUE; + } + } + if (!reply.WriteInt32(result)) { + return ERR_INVALID_VALUE; + } + return NO_ERROR; +} + +int AbilityManagerStub::CloseMultiWindowInner(MessageParcel &data, MessageParcel &reply) +{ + auto missionId = data.ReadInt32(); + auto result = CloseMultiWindow(missionId); + reply.WriteInt32(result); + return NO_ERROR; +} + +int AbilityManagerStub::SetMissionStackSettingInner(MessageParcel &data, MessageParcel &reply) +{ + StackSetting *stackSetting = data.ReadParcelable(); + if (stackSetting == nullptr) { + HILOG_ERROR("stackSetting is nullptr"); + return ERR_INVALID_VALUE; + } + auto result = SetMissionStackSetting(*stackSetting); + reply.WriteInt32(result); + delete stackSetting; + return NO_ERROR; +} + +int AbilityManagerStub::IsFirstInMissionInner(MessageParcel &data, MessageParcel &reply) +{ + auto token = data.ReadParcelable(); + auto result = IsFirstInMission(token); + if (!reply.WriteBool(result)) { + HILOG_ERROR("reply write failed."); + return ERR_INVALID_VALUE; + } + return NO_ERROR; +} + +int AbilityManagerStub::CompelVerifyPermissionInner(MessageParcel &data, MessageParcel &reply) +{ + auto permission = Str16ToStr8(data.ReadString16()); + auto pid = data.ReadInt32(); + auto uid = data.ReadInt32(); + std::string message; + auto result = CompelVerifyPermission(permission, pid, uid, message); + reply.WriteString16(Str8ToStr16(message)); + reply.WriteInt32(result); + return NO_ERROR; +} + +int AbilityManagerStub::PowerOffInner(MessageParcel &data, MessageParcel &reply) +{ + auto result = PowerOff(); + reply.WriteInt32(result); + return NO_ERROR; +} + +int AbilityManagerStub::PowerOnInner(MessageParcel &data, MessageParcel &reply) +{ + auto result = PowerOn(); + reply.WriteInt32(result); + return NO_ERROR; +} + +int AbilityManagerStub::LockMissionInner(MessageParcel &data, MessageParcel &reply) +{ + int32_t id = data.ReadInt32(); + int result = LockMission(id); + if (!reply.WriteInt32(result)) { + HILOG_ERROR("AbilityManagerStub: lock mission failed."); + return ERR_INVALID_VALUE; + } + return NO_ERROR; +} + +int AbilityManagerStub::UnlockMissionInner(MessageParcel &data, MessageParcel &reply) +{ + int32_t id = data.ReadInt32(); + int result = UnlockMission(id); + if (!reply.WriteInt32(result)) { + HILOG_ERROR("AbilityManagerStub: lock mission failed."); + return ERR_INVALID_VALUE; + } + return NO_ERROR; +} + +int AbilityManagerStub::SetMissionDescriptionInfoInner(MessageParcel &data, MessageParcel &reply) +{ + auto token = data.ReadParcelable(); + std::unique_ptr missionInfo(data.ReadParcelable()); + int result = SetMissionDescriptionInfo(token, *missionInfo); + if (!reply.WriteInt32(result)) { + HILOG_ERROR("AbilityManagerStub: set mission info failed."); + return ERR_INVALID_VALUE; + } + return NO_ERROR; +} + +int AbilityManagerStub::GetMissionLockModeStateInner(MessageParcel &data, MessageParcel &reply) +{ + int result = GetMissionLockModeState(); + if (!reply.WriteInt32(result)) { + HILOG_ERROR("AbilityManagerStub: get mission lock mode state failed."); + return ERR_INVALID_VALUE; + } + return NO_ERROR; +} + +int AbilityManagerStub::UpdateConfigurationInner(MessageParcel &data, MessageParcel &reply) +{ + std::unique_ptr config(data.ReadParcelable()); + if (config == nullptr) { + HILOG_ERROR("AbilityManagerStub: config is nullptr"); + return ERR_INVALID_VALUE; + } + int result = UpdateConfiguration(*config); + if (!reply.WriteInt32(result)) { + HILOG_ERROR("AbilityManagerStub: update configuration failed."); + return ERR_INVALID_VALUE; + } + return NO_ERROR; +} + +int AbilityManagerStub::GetWantSenderInner(MessageParcel &data, MessageParcel &reply) +{ + WantSenderInfo *wantSenderInfo = data.ReadParcelable(); + if (wantSenderInfo == nullptr) { + HILOG_ERROR("wantSenderInfo is nullptr"); + return ERR_INVALID_VALUE; + } + sptr callerToken = data.ReadParcelable(); + sptr wantSender = GetWantSender(*wantSenderInfo, callerToken); + if (!reply.WriteParcelable(wantSender->AsObject())) { + HILOG_ERROR("failed to reply wantSender instance to client, for write parcel error"); + return ERR_INVALID_VALUE; + } + return NO_ERROR; +} + +int AbilityManagerStub::SendWantSenderInner(MessageParcel &data, MessageParcel &reply) +{ + sptr wantSender = iface_cast(data.ReadParcelable()); + if (wantSender == nullptr) { + HILOG_ERROR("wantSender is nullptr"); + return ERR_INVALID_VALUE; + } + SenderInfo *senderInfo = data.ReadParcelable(); + if (senderInfo == nullptr) { + HILOG_ERROR("senderInfo is nullptr"); + return ERR_INVALID_VALUE; + } + int32_t result = SendWantSender(wantSender, *senderInfo); + reply.WriteInt32(result); + return NO_ERROR; +} + +int AbilityManagerStub::CancelWantSenderInner(MessageParcel &data, MessageParcel &reply) +{ + sptr wantSender = iface_cast(data.ReadParcelable()); + if (wantSender == nullptr) { + HILOG_ERROR("wantSender is nullptr"); + return ERR_INVALID_VALUE; + } + CancelWantSender(wantSender); + return NO_ERROR; +} + +int AbilityManagerStub::GetPendingWantUidInner(MessageParcel &data, MessageParcel &reply) +{ + sptr wantSender = iface_cast(data.ReadParcelable()); + if (wantSender == nullptr) { + HILOG_ERROR("wantSender is nullptr"); + return ERR_INVALID_VALUE; + } + + int32_t uid = GetPendingWantUid(wantSender); + reply.WriteInt32(uid); + return NO_ERROR; +} + +int AbilityManagerStub::GetPendingWantUserIdInner(MessageParcel &data, MessageParcel &reply) +{ + sptr wantSender = iface_cast(data.ReadParcelable()); + if (wantSender == nullptr) { + HILOG_ERROR("wantSender is nullptr"); + return ERR_INVALID_VALUE; + } + + int32_t userId = GetPendingWantUserId(wantSender); + reply.WriteInt32(userId); + return NO_ERROR; +} + +int AbilityManagerStub::GetPendingWantBundleNameInner(MessageParcel &data, MessageParcel &reply) +{ + sptr wantSender = iface_cast(data.ReadParcelable()); + if (wantSender == nullptr) { + HILOG_ERROR("wantSender is nullptr"); + return ERR_INVALID_VALUE; + } + + std::string bundleName = GetPendingWantBundleName(wantSender); + reply.WriteString16(Str8ToStr16(bundleName)); + return NO_ERROR; +} + +int AbilityManagerStub::GetPendingWantCodeInner(MessageParcel &data, MessageParcel &reply) +{ + sptr wantSender = iface_cast(data.ReadParcelable()); + if (wantSender == nullptr) { + HILOG_ERROR("wantSender is nullptr"); + return ERR_INVALID_VALUE; + } + + int32_t code = GetPendingWantCode(wantSender); + reply.WriteInt32(code); + return NO_ERROR; +} + +int AbilityManagerStub::GetPendingWantTypeInner(MessageParcel &data, MessageParcel &reply) +{ + sptr wantSender = iface_cast(data.ReadParcelable()); + if (wantSender == nullptr) { + HILOG_ERROR("wantSender is nullptr"); + return ERR_INVALID_VALUE; + } + + int32_t type = GetPendingWantType(wantSender); + reply.WriteInt32(type); + return NO_ERROR; +} + +int AbilityManagerStub::RegisterCancelListenerInner(MessageParcel &data, MessageParcel &reply) +{ + sptr sender = iface_cast(data.ReadParcelable()); + if (sender == nullptr) { + HILOG_ERROR("sender is nullptr"); + return ERR_INVALID_VALUE; + } + sptr receiver = iface_cast(data.ReadParcelable()); + if (receiver == nullptr) { + HILOG_ERROR("receiver is nullptr"); + return ERR_INVALID_VALUE; + } + RegisterCancelListener(sender, receiver); + return NO_ERROR; +} + +int AbilityManagerStub::UnregisterCancelListenerInner(MessageParcel &data, MessageParcel &reply) +{ + sptr sender = iface_cast(data.ReadParcelable()); + if (sender == nullptr) { + HILOG_ERROR("sender is nullptr"); + return ERR_INVALID_VALUE; + } + sptr receiver = iface_cast(data.ReadParcelable()); + if (receiver == nullptr) { + HILOG_ERROR("receiver is nullptr"); + return ERR_INVALID_VALUE; + } + UnregisterCancelListener(sender, receiver); + return NO_ERROR; +} + +int AbilityManagerStub::GetPendingRequestWantInner(MessageParcel &data, MessageParcel &reply) +{ + sptr wantSender = iface_cast(data.ReadParcelable()); + if (wantSender == nullptr) { + HILOG_ERROR("wantSender is nullptr"); + return ERR_INVALID_VALUE; + } + + std::shared_ptr want(data.ReadParcelable()); + int32_t result = GetPendingRequestWant(wantSender, want); + if (result != NO_ERROR) { + HILOG_ERROR("GetPendingRequestWant is failed"); + return ERR_INVALID_VALUE; + } + reply.WriteParcelable(want.get()); + return NO_ERROR; +} +} // namespace AAFwk +} // namespace OHOS diff --git a/tools/services/abilitymgr/src/ability_mission_info.cpp b/tools/services/abilitymgr/src/ability_mission_info.cpp new file mode 100644 index 00000000000..307ccd80c9f --- /dev/null +++ b/tools/services/abilitymgr/src/ability_mission_info.cpp @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ability_mission_info.h" + +#include "hilog_wrapper.h" +#include "nlohmann/json.hpp" +#include "string_ex.h" + +namespace OHOS { +namespace AAFwk { +bool AbilityMissionInfo::ReadFromParcel(Parcel &parcel) +{ + id = parcel.ReadInt32(); + runingState = parcel.ReadInt32(); + missionStackId = parcel.ReadInt32(); + + auto want = parcel.ReadParcelable(); + if (want == nullptr) { + return false; + } + baseWant = *want; + + auto bAbility = parcel.ReadParcelable(); + if (bAbility == nullptr) { + return false; + } + baseAbility = *bAbility; + + auto tAbility = parcel.ReadParcelable(); + if (tAbility == nullptr) { + return false; + } + topAbility = *tAbility; + + size = parcel.ReadInt32(); + + auto mDescription = parcel.ReadParcelable(); + if (mDescription == nullptr) { + return false; + } + missionDescription = *mDescription; + + return true; +} + +AbilityMissionInfo *AbilityMissionInfo::Unmarshalling(Parcel &parcel) +{ + AbilityMissionInfo *info = new (std::nothrow) AbilityMissionInfo(); + if (info == nullptr) { + return nullptr; + } + + if (!info->ReadFromParcel(parcel)) { + delete info; + info = nullptr; + } + return info; +} + +bool AbilityMissionInfo::Marshalling(Parcel &parcel) const +{ + parcel.WriteInt32(id); + parcel.WriteInt32(runingState); + parcel.WriteInt32(missionStackId); + parcel.WriteParcelable(&baseWant); + parcel.WriteParcelable(&baseAbility); + parcel.WriteParcelable(&topAbility); + parcel.WriteInt32(size); + parcel.WriteParcelable(&missionDescription); + + return true; +} +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/abilitymgr/src/ability_record.cpp b/tools/services/abilitymgr/src/ability_record.cpp new file mode 100644 index 00000000000..3ab940549b2 --- /dev/null +++ b/tools/services/abilitymgr/src/ability_record.cpp @@ -0,0 +1,1109 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ability_record.h" + +#include +#include + +#include "errors.h" +#include "hilog_wrapper.h" +#include "ability_util.h" +#include "ability_event_handler.h" +#include "ability_manager_service.h" +#include "ability_scheduler_stub.h" + +namespace OHOS { +namespace AAFwk { +int64_t AbilityRecord::abilityRecordId = 0; +int64_t AbilityRecord::g_abilityRecordEventId_ = 0; +const std::map AbilityRecord::stateToStrMap = { + std::map::value_type(INITIAL, "INITIAL"), + std::map::value_type(INACTIVE, "INACTIVE"), + std::map::value_type(ACTIVE, "ACTIVE"), + std::map::value_type(BACKGROUND, "BACKGROUND"), + std::map::value_type(SUSPENDED, "SUSPENDED"), + std::map::value_type(INACTIVATING, "INACTIVATING"), + std::map::value_type(ACTIVATING, "ACTIVATING"), + std::map::value_type(MOVING_BACKGROUND, "MOVING_BACKGROUND"), + std::map::value_type(TERMINATING, "TERMINATING"), +}; +const std::map AbilityRecord::appStateToStrMap_ = { + std::map::value_type(AppState::BEGIN, "BEGIN"), + std::map::value_type(AppState::READY, "READY"), + std::map::value_type(AppState::FOREGROUND, "FOREGROUND"), + std::map::value_type(AppState::BACKGROUND, "BACKGROUND"), + std::map::value_type(AppState::SUSPENDED, "SUSPENDED"), + std::map::value_type(AppState::TERMINATED, "TERMINATED"), + std::map::value_type(AppState::END, "END"), +}; +const std::map AbilityRecord::convertStateMap = { + std::map::value_type(ABILITY_STATE_INITIAL, INITIAL), + std::map::value_type(ABILITY_STATE_INACTIVE, INACTIVE), + std::map::value_type(ABILITY_STATE_ACTIVE, ACTIVE), + std::map::value_type(ABILITY_STATE_BACKGROUND, BACKGROUND), + std::map::value_type(ABILITY_STATE_SUSPENDED, SUSPENDED), +}; + +Token::Token(std::weak_ptr abilityRecord) : abilityRecord_(abilityRecord) +{} + +Token::~Token() +{} + +std::shared_ptr Token::GetAbilityRecordByToken(const sptr &token) +{ + CHECK_POINTER_AND_RETURN(token, nullptr); + return (static_cast(token.GetRefPtr()))->GetAbilityRecord(); +} + +std::shared_ptr Token::GetAbilityRecord() const +{ + return abilityRecord_.lock(); +} + +AbilityRecord::AbilityRecord(const Want &want, const AppExecFwk::AbilityInfo &abilityInfo, + const AppExecFwk::ApplicationInfo &applicationInfo, int requestCode) + : want_(want), abilityInfo_(abilityInfo), applicationInfo_(applicationInfo), requestCode_(requestCode) +{ + recordId_ = abilityRecordId++; +} + +AbilityRecord::~AbilityRecord() +{ + if (scheduler_ != nullptr && schedulerDeathRecipient_ != nullptr) { + auto object = scheduler_->AsObject(); + if (object != nullptr) { + object->RemoveDeathRecipient(schedulerDeathRecipient_); + } + } +} + +std::shared_ptr AbilityRecord::CreateAbilityRecord(const AbilityRequest &abilityRequest) +{ + std::shared_ptr abilityRecord = std::make_shared( + abilityRequest.want, abilityRequest.abilityInfo, abilityRequest.appInfo, abilityRequest.requestCode); + CHECK_POINTER_AND_RETURN(abilityRecord, nullptr); + if (!abilityRecord->Init()) { + HILOG_ERROR("failed to init new ability record"); + return nullptr; + } + if (abilityRequest.startSetting != nullptr) { + HILOG_INFO("abilityRequest.startSetting..."); + abilityRecord->SetStartSetting(abilityRequest.startSetting); + } + return abilityRecord; +} + +bool AbilityRecord::Init() +{ + lifecycleDeal_ = std::make_unique(); + CHECK_POINTER_RETURN_BOOL(lifecycleDeal_); + + token_ = new (std::nothrow) Token(weak_from_this()); + CHECK_POINTER_RETURN_BOOL(token_); + + if (applicationInfo_.isLauncherApp) { + isLauncherAbility_ = true; + } + return true; +} + +int AbilityRecord::LoadAbility() +{ + HILOG_INFO("%s", __func__); + startTime_ = AbilityUtil::SystemTimeMillis(); + CHECK_POINTER_AND_RETURN(token_, ERR_INVALID_VALUE); + std::string appName = applicationInfo_.name; + if (appName.empty()) { + HILOG_ERROR("app name is empty"); + return ERR_INVALID_VALUE; + } + + if (abilityInfo_.type != AppExecFwk::AbilityType::DATA) { + if (isKernalSystemAbility_) { + SendEvent(AbilityManagerService::LOAD_TIMEOUT_MSG, AbilityManagerService::SYSTEM_UI_TIMEOUT); + } else { + SendEvent(AbilityManagerService::LOAD_TIMEOUT_MSG, AbilityManagerService::LOAD_TIMEOUT); + } + } + sptr callerToken_ = nullptr; + if (!callerList_.empty()) { + callerToken_ = callerList_.back()->GetCaller()->GetToken(); + } + return DelayedSingleton::GetInstance()->LoadAbility( + token_, callerToken_, abilityInfo_, applicationInfo_); +} + +int AbilityRecord::TerminateAbility() +{ + HILOG_INFO("%{public}s", __func__); + return DelayedSingleton::GetInstance()->TerminateAbility(token_); +} + +void AbilityRecord::SetMissionRecord(const std::shared_ptr &missionRecord) +{ + missionRecord_ = missionRecord; + if (missionRecord) { + lifeCycleStateInfo_.missionId = missionRecord->GetMissionRecordId(); + } +} + +void AbilityRecord::SetMissionStackId(const int stackId) +{ + lifeCycleStateInfo_.stackId = stackId; +} + +int AbilityRecord::GetMissionStackId() const +{ + return lifeCycleStateInfo_.stackId; +} + +std::shared_ptr AbilityRecord::GetMissionRecord() const +{ + return missionRecord_.lock(); +} + +int AbilityRecord::GetMissionRecordId() const +{ + if (missionRecord_.lock()) { + return missionRecord_.lock()->GetMissionRecordId(); + } + return DEFAULT_INVAL_VALUE; +} + +const AppExecFwk::AbilityInfo &AbilityRecord::GetAbilityInfo() const +{ + return abilityInfo_; +} + +const AppExecFwk::ApplicationInfo &AbilityRecord::GetApplicationInfo() const +{ + return applicationInfo_; +} + +AbilityState AbilityRecord::GetAbilityState() const +{ + return currentState_; +} + +void AbilityRecord::SetAbilityState(AbilityState state) +{ + currentState_ = state; +} + +void AbilityRecord::SetScheduler(const sptr &scheduler) +{ + HILOG_INFO("%{public}s", __func__); + CHECK_POINTER(lifecycleDeal_); + if (scheduler != nullptr) { + if (scheduler_ != nullptr && schedulerDeathRecipient_ != nullptr) { + auto schedulerObject = scheduler_->AsObject(); + if (schedulerObject != nullptr) { + schedulerObject->RemoveDeathRecipient(schedulerDeathRecipient_); + } + } + if (schedulerDeathRecipient_ == nullptr) { + schedulerDeathRecipient_ = + new AbilitySchedulerRecipient(std::bind(&AbilityRecord::OnSchedulerDied, this, std::placeholders::_1)); + } + isReady_ = true; + scheduler_ = scheduler; + lifecycleDeal_->SetScheduler(scheduler); + auto schedulerObject = scheduler_->AsObject(); + if (schedulerObject != nullptr) { + schedulerObject->AddDeathRecipient(schedulerDeathRecipient_); + } + } else { + HILOG_ERROR("scheduler is nullptr"); + isReady_ = false; + isWindowAttached_ = false; + SetIsNewWant(false); + if (scheduler_ != nullptr && schedulerDeathRecipient_ != nullptr) { + auto schedulerObject = scheduler_->AsObject(); + if (schedulerObject != nullptr) { + schedulerObject->RemoveDeathRecipient(schedulerDeathRecipient_); + } + } + scheduler_ = scheduler; + } +} + +sptr AbilityRecord::GetToken() const +{ + return token_; +} + +void AbilityRecord::SetPreAbilityRecord(const std::shared_ptr &abilityRecord) +{ + preAbilityRecord_ = abilityRecord; +} + +std::shared_ptr AbilityRecord::GetPreAbilityRecord() const +{ + return preAbilityRecord_.lock(); +} + +void AbilityRecord::SetNextAbilityRecord(const std::shared_ptr &abilityRecord) +{ + nextAbilityRecord_ = abilityRecord; +} + +std::shared_ptr AbilityRecord::GetNextAbilityRecord() const +{ + return nextAbilityRecord_.lock(); +} + +void AbilityRecord::SetBackAbilityRecord(const std::shared_ptr &abilityRecord) +{ + backAbilityRecord_ = abilityRecord; +} + +std::shared_ptr AbilityRecord::GetBackAbilityRecord() const +{ + return backAbilityRecord_.lock(); +} + +void AbilityRecord::SetEventId(int64_t eventId) +{ + eventId_ = eventId; +} + +int64_t AbilityRecord::GetEventId() const +{ + return eventId_; +} + +bool AbilityRecord::IsReady() const +{ + return isReady_; +} + +bool AbilityRecord::IsWindowAttached() const +{ + return isWindowAttached_; +} + +bool AbilityRecord::IsLauncherAbility() const +{ + return isLauncherAbility_; +} + +bool AbilityRecord::IsTerminating() const +{ + return isTerminating_; +} + +bool AbilityRecord::IsForceTerminate() const +{ + return isForceTerminate_; +} + +void AbilityRecord::SetForceTerminate(bool flag) +{ + isForceTerminate_ = flag; +} + +void AbilityRecord::SetTerminatingState() +{ + isTerminating_ = true; +} + +bool AbilityRecord::IsNewWant() const +{ + return lifeCycleStateInfo_.isNewWant; +} + +void AbilityRecord::SetIsNewWant(bool isNewWant) +{ + lifeCycleStateInfo_.isNewWant = isNewWant; +} + +bool AbilityRecord::IsCreateByConnect() const +{ + return isCreateByConnect_; +} + +void AbilityRecord::SetCreateByConnectMode() +{ + isCreateByConnect_ = true; +} + +void AbilityRecord::Activate() +{ + HILOG_INFO("Activate."); + CHECK_POINTER(lifecycleDeal_); + + SendEvent(AbilityManagerService::ACTIVE_TIMEOUT_MSG, AbilityManagerService::ACTIVE_TIMEOUT); + + // schedule active after updating AbilityState and sending timeout message to avoid ability async callback + // earlier than above actions. + currentState_ = AbilityState::ACTIVATING; + lifecycleDeal_->Activate(want_, lifeCycleStateInfo_); + + // update ability state to appMgr service when restart + if (IsNewWant()) { + sptr preToken = nullptr; + if (GetPreAbilityRecord()) { + preToken = GetPreAbilityRecord()->GetToken(); + } + DelayedSingleton::GetInstance()->AbilityBehaviorAnalysis(token_, preToken, 1, 1, 1); + } +} + +void AbilityRecord::ProcessActivateInMoving() +{ + HILOG_DEBUG("ProcessActivateInMovingState."); + if (!IsAbilityState(AbilityState::ACTIVE) && !IsAbilityState(AbilityState::ACTIVATING)) { + SetInMovingState(true); + ProcessActivate(); + } +} + +void AbilityRecord::ProcessInactivateInMoving() +{ + HILOG_DEBUG("ProcessActivateInMovingState."); + if (IsAbilityState(AbilityState::ACTIVE) || IsAbilityState(AbilityState::ACTIVATING)) { + SetInMovingState(true); + ProcessInactivate(); + } +} + +void AbilityRecord::ProcessActivate() +{ + std::string element = GetWant().GetElement().GetURI(); + HILOG_DEBUG("ability record: %{public}s", element.c_str()); + + if (isReady_) { + if (IsAbilityState(AbilityState::BACKGROUND)) { + // background to activte state + if (!ProcessConfigurationChange()) { + // true: restartability, false: continue activate + HILOG_DEBUG("MoveToForground, %{public}s", element.c_str()); + DelayedSingleton::GetInstance()->MoveToForground(token_); + } + } else { + HILOG_DEBUG("Activate %{public}s", element.c_str()); + Activate(); + } + } else { + LoadAbility(); + } +} + +void AbilityRecord::ProcessInactivate() +{ + std::string element = GetWant().GetElement().GetURI(); + HILOG_DEBUG("ability record: %{public}s", element.c_str()); + + if (isReady_) { + if (IsAbilityState(AbilityState::BACKGROUND)) { + // background to activte state + if (!ProcessConfigurationChange()) { + // true: restartability, false: continue activate + HILOG_DEBUG("MoveToForground, %{public}s", element.c_str()); + DelayedSingleton::GetInstance()->MoveToForground(token_); + } + } else if (!IsAbilityState(AbilityState::INACTIVE) && !IsAbilityState(AbilityState::INACTIVATING)) { + HILOG_DEBUG("Inactivate %{public}s", element.c_str()); + Inactivate(); + } + } else { + LoadAbility(); + } +} + +void AbilityRecord::Inactivate() +{ + HILOG_INFO("Inactivate."); + CHECK_POINTER(lifecycleDeal_); + + SendEvent(AbilityManagerService::INACTIVE_TIMEOUT_MSG, AbilityManagerService::INACTIVE_TIMEOUT); + + // schedule inactive after updating AbilityState and sending timeout message to avoid ability async callback + // earlier than above actions. + currentState_ = AbilityState::INACTIVATING; + lifecycleDeal_->Inactivate(want_, lifeCycleStateInfo_); +} + +void AbilityRecord::MoveToBackground(const Closure &task) +{ + HILOG_INFO("Move to background."); + CHECK_POINTER(lifecycleDeal_); + auto handler = DelayedSingleton::GetInstance()->GetEventHandler(); + if (handler == nullptr || task == nullptr) { + // handler is nullptr means couldn't send timeout message. But still need to notify ability to inactive. + // so don't return here. + HILOG_ERROR("handler is nullptr or task is nullptr."); + } else { + g_abilityRecordEventId_++; + eventId_ = g_abilityRecordEventId_; + // eventId_ is a unique id of the task. + handler->PostTask(task, std::to_string(eventId_), AbilityManagerService::BACKGROUND_TIMEOUT); + } + + if (!IsTerminating() || IsRestarting()) { + // schedule save ability state before moving to background. + SaveAbilityState(); + } + + // schedule background after updating AbilityState and sending timeout message to avoid ability async callback + // earlier than above actions. + currentState_ = AbilityState::MOVING_BACKGROUND; + lifecycleDeal_->MoveToBackground(want_, lifeCycleStateInfo_); +} + +void AbilityRecord::Terminate(const Closure &task) +{ + HILOG_INFO("Terminate ability."); + CHECK_POINTER(lifecycleDeal_); + auto handler = DelayedSingleton::GetInstance()->GetEventHandler(); + if (handler == nullptr || task == nullptr) { + // handler is nullptr means couldn't send timeout message. But still need to notify ability to inactive. + // so don't return here. + HILOG_ERROR("handler is nullptr or task is nullptr."); + } else { + g_abilityRecordEventId_++; + eventId_ = g_abilityRecordEventId_; + // eventId_ is a unique id of the task. + handler->PostTask(task, std::to_string(eventId_), AbilityManagerService::TERMINATE_TIMEOUT); + } + // schedule background after updating AbilityState and sending timeout message to avoid ability async callback + // earlier than above actions. + currentState_ = AbilityState::TERMINATING; + lifecycleDeal_->Terminate(want_, lifeCycleStateInfo_); +} + +void AbilityRecord::ConnectAbility() +{ + HILOG_INFO("Connect ability."); + CHECK_POINTER(lifecycleDeal_); + lifecycleDeal_->ConnectAbility(want_); +} + +void AbilityRecord::DisconnectAbility() +{ + HILOG_INFO("Disconnect ability."); + CHECK_POINTER(lifecycleDeal_); + lifecycleDeal_->DisconnectAbility(want_); +} + +void AbilityRecord::CommandAbility() +{ + HILOG_INFO("Command ability."); + CHECK_POINTER(lifecycleDeal_); + lifecycleDeal_->CommandAbility(want_, false, startId_); +} + +void AbilityRecord::SaveAbilityState() +{ + HILOG_INFO("%{public}s", __func__); + CHECK_POINTER(lifecycleDeal_); + lifecycleDeal_->SaveAbilityState(stateDatas_); +} + +void AbilityRecord::RestoreAbilityState() +{ + HILOG_INFO("%{public}s", __func__); + CHECK_POINTER(lifecycleDeal_); + lifecycleDeal_->RestoreAbilityState(stateDatas_); + stateDatas_.Clear(); + isRestarting_ = false; +} + +void AbilityRecord::TopActiveAbilityChanged(bool flag) +{ + HILOG_INFO("%{public}s called, isTop: %{public}d", __func__, flag); + CHECK_POINTER(scheduler_); + scheduler_->NotifyTopActiveAbilityChanged(flag); +} + +void AbilityRecord::SetWant(const Want &want) +{ + want_ = want; +} + +const Want &AbilityRecord::GetWant() const +{ + return want_; +} + +int AbilityRecord::GetRequestCode() const +{ + return requestCode_; +} + +void AbilityRecord::SetResult(const std::shared_ptr &result) +{ + result_ = result; +} + +std::shared_ptr AbilityRecord::GetResult() const +{ + return result_; +} + +void AbilityRecord::SendResult() +{ + HILOG_INFO("Send result."); + CHECK_POINTER(scheduler_); + CHECK_POINTER(result_); + scheduler_->SendResult(result_->requestCode_, result_->resultCode_, result_->resultWant_); + // reset result to avoid send result next time + result_.reset(); +} + +void AbilityRecord::SendResultToCallers() +{ + for (auto caller : GetCallerRecordList()) { + std::shared_ptr callerAbilityRecord = caller->GetCaller(); + if (callerAbilityRecord != nullptr && callerAbilityRecord->GetResult() != nullptr) { + callerAbilityRecord->SendResult(); + } + } +} + +void AbilityRecord::SaveResultToCallers(const int resultCode, const Want *resultWant) +{ + for (auto caller : GetCallerRecordList()) { + std::shared_ptr callerAbilityRecord = caller->GetCaller(); + if (callerAbilityRecord != nullptr) { + callerAbilityRecord->SetResult( + std::make_shared(caller->GetRequestCode(), resultCode, *resultWant)); + } + } +} + +void AbilityRecord::AddConnectRecordToList(const std::shared_ptr &connRecord) +{ + CHECK_POINTER(connRecord); + auto it = std::find(connRecordList_.begin(), connRecordList_.end(), connRecord); + // found it + if (it != connRecordList_.end()) { + HILOG_DEBUG("Found it in list, so no need to add same connection(%{public}p)", connRecord.get()); + return; + } + // no found then add new connection to list + HILOG_DEBUG("No found in list, so add new connection(%{public}p) to list", connRecord.get()); + connRecordList_.push_back(connRecord); +} + +std::list> AbilityRecord::GetConnectRecordList() const +{ + return connRecordList_; +} + +void AbilityRecord::RemoveConnectRecordFromList(const std::shared_ptr &connRecord) +{ + CHECK_POINTER(connRecord); + connRecordList_.remove(connRecord); +} + +void AbilityRecord::AddCallerRecord(const sptr &callerToken, int requestCode) +{ + HILOG_INFO("Add caller record."); + auto abilityRecord = Token::GetAbilityRecordByToken(callerToken); + CHECK_POINTER(abilityRecord); + + auto isExist = [&abilityRecord](const std::shared_ptr &callerRecord) { + return (callerRecord->GetCaller() == abilityRecord); + }; + + auto record = std::find_if(callerList_.begin(), callerList_.end(), isExist); + if (record != callerList_.end()) { + callerList_.erase(record); + } + + callerList_.emplace_back(std::make_shared(requestCode, abilityRecord)); + + lifeCycleStateInfo_.caller.requestCode = requestCode; + lifeCycleStateInfo_.caller.deviceId = abilityRecord->GetAbilityInfo().deviceId; + lifeCycleStateInfo_.caller.bundleName = abilityRecord->GetAbilityInfo().bundleName; + lifeCycleStateInfo_.caller.abilityName = abilityRecord->GetAbilityInfo().name; + HILOG_INFO("caller %{public}s, %{public}s, %{public}s", + abilityRecord->GetAbilityInfo().deviceId.c_str(), + abilityRecord->GetAbilityInfo().bundleName.c_str(), + abilityRecord->GetAbilityInfo().name.c_str()); +} + +std::list> AbilityRecord::GetCallerRecordList() const +{ + return callerList_; +} + +void AbilityRecord::AddWindowInfo(int windowToken) +{ + windowInfo_ = std::make_shared(windowToken); + isWindowAttached_ = true; +} + +void AbilityRecord::RemoveWindowInfo() +{ + windowInfo_.reset(); +} + +bool AbilityRecord::IsConnectListEmpty() +{ + return connRecordList_.empty(); +} + +std::shared_ptr AbilityRecord::GetWindowInfo() const +{ + return windowInfo_; +} + +std::shared_ptr AbilityRecord::GetConnectingRecord() const +{ + auto connect = + std::find_if(connRecordList_.begin(), connRecordList_.end(), [](std::shared_ptr record) { + return record->GetConnectState() == ConnectionState::CONNECTING; + }); + return (connect != connRecordList_.end()) ? *connect : nullptr; +} + +std::list> AbilityRecord::GetConnectingRecordList() +{ + std::list> connectingList; + for (auto record : connRecordList_) { + if (record && record->GetConnectState() == ConnectionState::CONNECTING) { + connectingList.push_back(record); + } + } + return connectingList; +} + +std::shared_ptr AbilityRecord::GetDisconnectingRecord() const +{ + auto connect = + std::find_if(connRecordList_.begin(), connRecordList_.end(), [](std::shared_ptr record) { + return record->GetConnectState() == ConnectionState::DISCONNECTING; + }); + return (connect != connRecordList_.end()) ? *connect : nullptr; +} + +void AbilityRecord::GetAbilityTypeString(std::string &typeStr) +{ + AppExecFwk::AbilityType type = GetAbilityInfo().type; + switch (type) { + case AppExecFwk::AbilityType::PAGE: { + typeStr = "PAGE"; + break; + } + case AppExecFwk::AbilityType::SERVICE: { + typeStr = "SERVICE"; + break; + } + // for config.json type + case AppExecFwk::AbilityType::DATA: { + typeStr = "DATA"; + break; + } + default: { + typeStr = "UNKNOWN"; + break; + } + } +} + +std::string AbilityRecord::ConvertAbilityState(const AbilityState &state) +{ + auto it = stateToStrMap.find(state); + if (it != stateToStrMap.end()) { + return it->second; + } + return "INVALIDSTATE"; +} + +std::string AbilityRecord::ConvertAppState(const AppState &state) +{ + auto it = appStateToStrMap_.find(state); + if (it != appStateToStrMap_.end()) { + return it->second; + } + return "INVALIDSTATE"; +} + +int AbilityRecord::ConvertLifeCycleToAbilityState(const AbilityLifeCycleState &state) +{ + auto it = convertStateMap.find(state); + if (it != convertStateMap.end()) { + return it->second; + } + return DEFAULT_INVAL_VALUE; +} + +void AbilityRecord::Dump(std::vector &info) +{ + std::string dumpInfo = " AbilityRecord ID #" + std::to_string(recordId_); + info.push_back(dumpInfo); + dumpInfo = " app name [" + GetAbilityInfo().applicationName + "]"; + info.push_back(dumpInfo); + dumpInfo = " main name [" + GetAbilityInfo().name + "]"; + info.push_back(dumpInfo); + dumpInfo = " bundle name [" + GetAbilityInfo().bundleName + "]"; + info.push_back(dumpInfo); + // get ability type(unknown/page/service/provider) + std::string typeStr; + GetAbilityTypeString(typeStr); + dumpInfo = " ability type [" + typeStr + "]"; + info.push_back(dumpInfo); + std::shared_ptr preAbility = GetPreAbilityRecord(); + if (preAbility == nullptr) { + dumpInfo = " previous ability app name [NULL]" + LINE_SEPARATOR; + dumpInfo += " previous ability file name [NULL]"; + } else { + dumpInfo = + " previous ability app name [" + preAbility->GetAbilityInfo().applicationName + "]" + LINE_SEPARATOR; + dumpInfo += " previous ability file name [" + preAbility->GetAbilityInfo().name + "]"; + } + info.push_back(dumpInfo); + std::shared_ptr nextAbility = GetNextAbilityRecord(); + if (nextAbility == nullptr) { + dumpInfo = " next ability app name [NULL]" + LINE_SEPARATOR; + dumpInfo += " next ability file name [NULL]"; + } else { + dumpInfo = + " next ability app name [" + nextAbility->GetAbilityInfo().applicationName + "]" + LINE_SEPARATOR; + dumpInfo += " next ability main name [" + nextAbility->GetAbilityInfo().name + "]"; + } + info.push_back(dumpInfo); + dumpInfo = " state #" + AbilityRecord::ConvertAbilityState(GetAbilityState()) + " start time [" + + std::to_string(startTime_) + "]"; + info.push_back(dumpInfo); + dumpInfo = " app state #" + AbilityRecord::ConvertAppState(appState_); + info.push_back(dumpInfo); + dumpInfo = " ready #" + std::to_string(isReady_) + " window attached #" + + std::to_string(isWindowAttached_) + " launcher #" + std::to_string(isLauncherAbility_); + info.push_back(dumpInfo); +} + +void AbilityRecord::SetStartTime() +{ + if (startTime_ == 0) { + startTime_ = AbilityUtil::SystemTimeMillis(); + } +} + +int64_t AbilityRecord::GetStartTime() const +{ + return startTime_; +} + +void AbilityRecord::DumpService(std::vector &info) const +{ + info.emplace_back(" AbilityRecord ID #" + std::to_string(GetRecordId()) + " state #" + + AbilityRecord::ConvertAbilityState(GetAbilityState()) + " start time [" + + std::to_string(GetStartTime()) + "]"); + info.emplace_back(" main name [" + GetAbilityInfo().name + "]"); + info.emplace_back(" bundle name [" + GetAbilityInfo().bundleName + "]"); + info.emplace_back(" ability type [SERVICE]"); + info.emplace_back(" app state #" + AbilityRecord::ConvertAppState(appState_)); + info.emplace_back(" Connections: " + std::to_string(connRecordList_.size())); + + for (auto &&conn : connRecordList_) { + if (conn) { + conn->Dump(info); + } + } +} + +void AbilityRecord::GetAbilityRecordInfo(AbilityRecordInfo &recordInfo) +{ + recordInfo.elementName = want_.GetElement().GetURI(); + recordInfo.id = recordId_; + recordInfo.appName = abilityInfo_.applicationName; + recordInfo.mainName = abilityInfo_.name; + recordInfo.abilityType = static_cast(abilityInfo_.type); + + std::shared_ptr preAbility = GetPreAbilityRecord(); + if (preAbility) { + recordInfo.previousAppName = preAbility->GetAbilityInfo().applicationName; + recordInfo.previousMainName = preAbility->GetAbilityInfo().name; + } + + std::shared_ptr nextAbility = GetNextAbilityRecord(); + if (nextAbility) { + recordInfo.nextAppName = nextAbility->GetAbilityInfo().applicationName; + recordInfo.nextMainName = nextAbility->GetAbilityInfo().name; + } + + recordInfo.state = static_cast(currentState_); + recordInfo.startTime = std::to_string(startTime_); + recordInfo.ready = isReady_; + recordInfo.windowAttached = isWindowAttached_; + recordInfo.lanucher = isLauncherAbility_; +} + +void AbilityRecord::OnSchedulerDied(const wptr &remote) +{ + HILOG_DEBUG("On scheduler died."); + CHECK_POINTER(scheduler_); + + auto object = remote.promote(); + CHECK_POINTER(object); + + if (object != scheduler_->AsObject()) { + HILOG_ERROR("Ability on scheduler died: scheduler is not matches with remote."); + return; + } + + isReady_ = false; + if (scheduler_ != nullptr && schedulerDeathRecipient_ != nullptr) { + auto schedulerObject = scheduler_->AsObject(); + if (schedulerObject != nullptr) { + schedulerObject->RemoveDeathRecipient(schedulerDeathRecipient_); + } + } + scheduler_.clear(); + CHECK_POINTER(lifecycleDeal_); + lifecycleDeal_->SetScheduler(nullptr); + isWindowAttached_ = false; + + auto abilityManagerService = DelayedSingleton::GetInstance(); + CHECK_POINTER(abilityManagerService); + + auto handler = abilityManagerService->GetEventHandler(); + CHECK_POINTER(handler); + + HILOG_INFO("Ability on scheduler died: '%{public}s'", abilityInfo_.name.c_str()); + auto task = [abilityManagerService, ability = shared_from_this()]() { + abilityManagerService->OnAbilityDied(ability); + }; + handler->PostTask(task); +} + +void AbilityRecord::SetConnRemoteObject(const sptr &remoteObject) +{ + connRemoteObject_ = remoteObject; +} + +sptr AbilityRecord::GetConnRemoteObject() const +{ + return connRemoteObject_; +} + +void AbilityRecord::AddStartId() +{ + startId_++; +} +int AbilityRecord::GetStartId() const +{ + return startId_; +} + +void AbilityRecord::SetIsUninstallAbility() +{ + isUninstall_ = true; +} + +bool AbilityRecord::IsUninstallAbility() const +{ + return isUninstall_; +} + +void AbilityRecord::SetKernalSystemAbility() +{ + isKernalSystemAbility_ = true; +} + +bool AbilityRecord::IsKernalSystemAbility() const +{ + return isKernalSystemAbility_; +} + +void AbilityRecord::SetLauncherRoot() +{ + isLauncherRoot_ = true; +} +bool AbilityRecord::IsLauncherRoot() const +{ + return isLauncherRoot_; +} + +bool AbilityRecord::IsAbilityState(const AbilityState &state) const +{ + return (currentState_ == state); +} + +void AbilityRecord::SendEvent(uint32_t msg, uint32_t timeOut) +{ + auto handler = DelayedSingleton::GetInstance()->GetEventHandler(); + CHECK_POINTER(handler); + + g_abilityRecordEventId_++; + eventId_ = g_abilityRecordEventId_; + handler->SendEvent(msg, eventId_, timeOut); +} + +bool AbilityRecord::SupportMultWindow() const +{ + // LauncherAbility don't support multi window display. + if (isLauncherAbility_) { + return false; + } + + return true; +} + +void AbilityRecord::NotifyMultiWinModeChanged(const AbilityWindowConfiguration &winModeKey, bool flag) +{ + HILOG_INFO("Notify multi window mode changed."); + CHECK_POINTER(scheduler_); + scheduler_->NotifyMultiWinModeChanged(static_cast(winModeKey), flag); +} + +void AbilityRecord::SetInMovingState(bool isMoving) +{ + isInMovingState_ = isMoving; +} + +bool AbilityRecord::GetInMovingState() const +{ + return isInMovingState_; +} + +bool AbilityRecord::IsToEnd() const +{ + return isToEnd_; +} +void AbilityRecord::SetToEnd(bool isToEnd) +{ + isToEnd_ = isToEnd; +} + +void AbilityRecord::SetStartSetting(const std::shared_ptr &setting) +{ + lifeCycleStateInfo_.setting = setting; +} + +std::shared_ptr AbilityRecord::GetStartSetting() const +{ + return lifeCycleStateInfo_.setting; +} + +void AbilityRecord::SetPowerState(const bool isPower) +{ + isPowerState_ = isPower; +} + +bool AbilityRecord::GetPowerState() const +{ + return isPowerState_; +} + +void AbilityRecord::SetRestarting(const bool isRestart) +{ + isRestarting_ = isRestart; +} + +bool AbilityRecord::IsRestarting() const +{ + return isRestarting_; +} + +void AbilityRecord::SetAppState(const AppState &state) +{ + appState_ = state; +} + +AppState AbilityRecord::GetAppState() const +{ + return appState_; +} + +bool AbilityRecord::OnConfigurationChanged(const DummyConfiguration &config, unsigned int configChanges) +{ + HILOG_INFO("%{public}s called", __FUNCTION__); + + HILOG_INFO("targetConfig: %{public}s, changeTypes:%{public}d", config.GetName().c_str(), configChanges); + + unsigned int focusChanges = GetIntConfigChanges(); + bool isFocused = ((focusChanges & configChanges) > 0); + if (isFocused) { + CHECK_POINTER_RETURN_BOOL(lifecycleDeal_); + if (isReady_) { + lifecycleDeal_->UpdateConfiguration(config); + return false; + } + } + + auto abilityManagerService = DelayedSingleton::GetInstance(); + CHECK_POINTER_RETURN_BOOL(abilityManagerService); + auto handler = abilityManagerService->GetEventHandler(); + g_abilityRecordEventId_++; + eventId_ = g_abilityRecordEventId_; + + CHECK_POINTER_RETURN_BOOL(handler); + auto task = [abilityManagerService, token = token_]() { abilityManagerService->RestartAbility(token); }; + // eventId_ is a unique id of the task. + handler->PostTask(task, std::to_string(eventId_), AbilityManagerService::RESTART_ABILITY_TIMEOUT); + return true; +} + +std::shared_ptr AbilityRecord::GetParent() +{ + return missionRecord_.lock(); +} + +unsigned int AbilityRecord::GetChildSize() +{ + return 0; +} + +std::shared_ptr AbilityRecord::FindChild(unsigned int index) +{ + return nullptr; +} + +unsigned int AbilityRecord::GetIntConfigChanges() +{ + auto changes = abilityInfo_.configChanges; + unsigned int intChangs = CHANGE_CONFIG_NONE; + + for (auto item : changes) { + HILOG_INFO("configChange: %{public}s", item.c_str()); + if (item == "locale") { + intChangs |= CHANGE_CONFIG_LOCALE; + } else if (item == "layout") { + intChangs |= CHANGE_CONFIG_LAYOUT; + } else if (item == "fontSize") { + intChangs |= CHANGE_CONFIG_FONTSIZE; + } else if (item == "orientation") { + intChangs |= CHANGE_CONFIG_ORIENTATION; + } else if (item == "density") { + intChangs |= CHANGE_CONFIG_DENSITY; + } else { + continue; + } + } + return intChangs; +} + +void AbilityRecord::ClearFlag() +{ + isRestarting_ = false; + isPowerState_ = false; + isForceTerminate_ = false; + isUninstall_ = false; + isTerminating_ = false; + isInMovingState_ = false; + preAbilityRecord_.reset(); + nextAbilityRecord_.reset(); + backAbilityRecord_.reset(); + startTime_ = 0; + appState_ = AppState::END; +} +} // namespace AAFwk +} // namespace OHOS diff --git a/tools/services/abilitymgr/src/ability_record_info.cpp b/tools/services/abilitymgr/src/ability_record_info.cpp new file mode 100644 index 00000000000..f5ac2c9918a --- /dev/null +++ b/tools/services/abilitymgr/src/ability_record_info.cpp @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "mission_record_info.h" + +#include "hilog_wrapper.h" +#include "nlohmann/json.hpp" +#include "string_ex.h" + +namespace OHOS { +namespace AAFwk { +bool AbilityRecordInfo::ReadFromParcel(Parcel &parcel) +{ + id = parcel.ReadInt32(); + elementName = Str16ToStr8(parcel.ReadString16()); + appName = Str16ToStr8(parcel.ReadString16()); + mainName = Str16ToStr8(parcel.ReadString16()); + abilityType = parcel.ReadInt32(); + previousAppName = Str16ToStr8(parcel.ReadString16()); + previousMainName = Str16ToStr8(parcel.ReadString16()); + nextAppName = Str16ToStr8(parcel.ReadString16()); + nextMainName = Str16ToStr8(parcel.ReadString16()); + int32_t abilityState = parcel.ReadInt32(); + state = static_cast(abilityState); + startTime = Str16ToStr8(parcel.ReadString16()); + ready = parcel.ReadBool(); + windowAttached = parcel.ReadBool(); + lanucher = parcel.ReadBool(); + + return true; +} + +AbilityRecordInfo *AbilityRecordInfo::Unmarshalling(Parcel &parcel) +{ + AbilityRecordInfo *info = new (std::nothrow) AbilityRecordInfo(); + if (info == nullptr) { + return nullptr; + } + + if (!info->ReadFromParcel(parcel)) { + delete info; + info = nullptr; + } + return info; +} + +bool AbilityRecordInfo::Marshalling(Parcel &parcel) const +{ + parcel.WriteInt32(id); + parcel.WriteString16(Str8ToStr16(elementName)); + parcel.WriteString16(Str8ToStr16(appName)); + parcel.WriteString16(Str8ToStr16(mainName)); + parcel.WriteInt32(abilityType); + parcel.WriteString16(Str8ToStr16(previousAppName)); + parcel.WriteString16(Str8ToStr16(previousMainName)); + parcel.WriteString16(Str8ToStr16(nextAppName)); + parcel.WriteString16(Str8ToStr16(nextMainName)); + parcel.WriteInt32(static_cast(state)); + parcel.WriteString16(Str8ToStr16(startTime)); + parcel.WriteBool(ready); + parcel.WriteBool(windowAttached); + parcel.WriteBool(lanucher); + + return true; +} +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/abilitymgr/src/ability_scheduler_proxy.cpp b/tools/services/abilitymgr/src/ability_scheduler_proxy.cpp new file mode 100644 index 00000000000..533c0545777 --- /dev/null +++ b/tools/services/abilitymgr/src/ability_scheduler_proxy.cpp @@ -0,0 +1,953 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "ability_scheduler_proxy.h" +#include "abs_shared_result_set.h" +#include "data_ability_predicates.h" +#include "values_bucket.h" + +#include "hilog_wrapper.h" +#include "ipc_types.h" +#include "ishared_result_set.h" +#include "pac_map.h" +#include "want.h" +#include "data_ability_observer_interface.h" +#include "data_ability_result.h" +#include "data_ability_operation.h" + +namespace OHOS { +namespace AAFwk { +bool AbilitySchedulerProxy::WriteInterfaceToken(MessageParcel &data) +{ + if (!data.WriteInterfaceToken(AbilitySchedulerProxy::GetDescriptor())) { + HILOG_ERROR("write interface token failed"); + return false; + } + return true; +} + +void AbilitySchedulerProxy::ScheduleAbilityTransaction(const Want &want, const LifeCycleStateInfo &stateInfo) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!WriteInterfaceToken(data)) { + return; + } + data.WriteParcelable(&want); + data.WriteParcelable(&stateInfo); + int32_t err = Remote()->SendRequest(IAbilityScheduler::SCHEDULE_ABILITY_TRANSACTION, data, reply, option); + if (err != NO_ERROR) { + HILOG_ERROR("ScheduleAbilityTransaction fail to SendRequest. err: %d", err); + } +} + +void AbilitySchedulerProxy::SendResult(int requestCode, int resultCode, const Want &resultWant) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!WriteInterfaceToken(data)) { + return; + } + data.WriteInt32(requestCode); + data.WriteInt32(resultCode); + if (!data.WriteParcelable(&resultWant)) { + HILOG_ERROR("fail to WriteParcelable"); + return; + } + int32_t err = Remote()->SendRequest(IAbilityScheduler::SEND_RESULT, data, reply, option); + if (err != NO_ERROR) { + HILOG_ERROR("SendResult fail to SendRequest. err: %d", err); + } +} + +void AbilitySchedulerProxy::ScheduleConnectAbility(const Want &want) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!WriteInterfaceToken(data)) { + return; + } + if (!data.WriteParcelable(&want)) { + HILOG_ERROR("fail to WriteParcelable"); + return; + } + int32_t err = Remote()->SendRequest(IAbilityScheduler::SCHEDULE_ABILITY_CONNECT, data, reply, option); + if (err != NO_ERROR) { + HILOG_ERROR("ScheduleConnectAbility fail to SendRequest. err: %d", err); + } +} + +void AbilitySchedulerProxy::ScheduleDisconnectAbility(const Want &want) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!WriteInterfaceToken(data)) { + return; + } + if (!data.WriteParcelable(&want)) { + HILOG_ERROR("fail to WriteParcelable"); + return; + } + + int32_t err = Remote()->SendRequest(IAbilityScheduler::SCHEDULE_ABILITY_DISCONNECT, data, reply, option); + if (err != NO_ERROR) { + HILOG_ERROR("ScheduleDisconnectAbility fail to SendRequest. err: %d", err); + } +} + +void AbilitySchedulerProxy::ScheduleCommandAbility(const Want &want, bool restart, int startId) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!WriteInterfaceToken(data)) { + return; + } + if (!data.WriteParcelable(&want) && !data.WriteBool(restart) && !data.WriteInt32(startId)) { + HILOG_ERROR("fail to WriteParcelable"); + return; + } + + int32_t err = Remote()->SendRequest(IAbilityScheduler::SCHEDULE_ABILITY_COMMAND, data, reply, option); + if (err != NO_ERROR) { + HILOG_ERROR("ScheduleCommandAbility fail to SendRequest. err: %d", err); + } +} + +void AbilitySchedulerProxy::ScheduleSaveAbilityState(PacMap &outState) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!WriteInterfaceToken(data)) { + return; + } + int32_t err = Remote()->SendRequest(IAbilityScheduler::SCHEDULE_SAVE_ABILITY_STATE, data, reply, option); + if (err != NO_ERROR) { + HILOG_ERROR("ScheduleSaveAbilityState fail to SendRequest. err: %d", err); + } + std::unique_ptr pacMap(reply.ReadParcelable()); + if (!pacMap) { + HILOG_ERROR("readParcelableInfo failed"); + return; + } + outState = *pacMap; +} + +void AbilitySchedulerProxy::ScheduleRestoreAbilityState(const PacMap &inState) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!WriteInterfaceToken(data)) { + return; + } + if (!data.WriteParcelable(&inState)) { + HILOG_ERROR("WriteParcelable error"); + return; + } + int32_t err = Remote()->SendRequest(IAbilityScheduler::SCHEDULE_RESTORE_ABILITY_STATE, data, reply, option); + if (err != NO_ERROR) { + HILOG_ERROR("ScheduleRestoreAbilityState fail to SendRequest. err: %d", err); + } +} + +void AbilitySchedulerProxy::ScheduleUpdateConfiguration(const DummyConfiguration &config) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!WriteInterfaceToken(data)) { + return; + } + if (!data.WriteParcelable(&config)) { + HILOG_ERROR("fail to WriteParcelable"); + return; + } + int32_t err = Remote()->SendRequest(IAbilityScheduler::SCHEDULE_UPDATE_CONFIGURATION, data, reply, option); + if (err != NO_ERROR) { + HILOG_ERROR("ScheduleRestoreAbilityState fail to SendRequest. err: %d", err); + } +} + +/** + * @brief Obtains the MIME types of files supported. + * + * @param uri Indicates the path of the files to obtain. + * @param mimeTypeFilter Indicates the MIME types of the files to obtain. This parameter cannot be null. + * + * @return Returns the matched MIME types. If there is no match, null is returned. + */ +std::vector AbilitySchedulerProxy::GetFileTypes(const Uri &uri, const std::string &mimeTypeFilter) +{ + std::vector types; + + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!WriteInterfaceToken(data)) { + return types; + } + + if (!data.WriteParcelable(&uri)) { + HILOG_ERROR("fail to WriteParcelable uri"); + return types; + } + + if (!data.WriteString(mimeTypeFilter)) { + HILOG_ERROR("fail to WriteString mimeTypeFilter"); + return types; + } + + int32_t err = Remote()->SendRequest(IAbilityScheduler::SCHEDULE_GETFILETYPES, data, reply, option); + if (err != NO_ERROR) { + HILOG_ERROR("GetFileTypes fail to SendRequest. err: %d", err); + } + + if (!reply.ReadStringVector(&types)) { + HILOG_ERROR("fail to ReadStringVector types"); + } + + return types; +} + +/** + * @brief Opens a file in a specified remote path. + * + * @param uri Indicates the path of the file to open. + * @param mode Indicates the file open mode, which can be "r" for read-only access, "w" for write-only access + * (erasing whatever data is currently in the file), "wt" for write access that truncates any existing file, + * "wa" for write-only access to append to any existing data, "rw" for read and write access on any existing data, + * or "rwt" for read and write access that truncates any existing file. + * + * @return Returns the file descriptor. + */ +int AbilitySchedulerProxy::OpenFile(const Uri &uri, const std::string &mode) +{ + int fd = -1; + + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!WriteInterfaceToken(data)) { + return fd; + } + + if (!data.WriteParcelable(&uri)) { + HILOG_ERROR("fail to WriteParcelable uri"); + return fd; + } + + if (!data.WriteString(mode)) { + HILOG_ERROR("fail to WriteString mode"); + return fd; + } + + int32_t err = Remote()->SendRequest(IAbilityScheduler::SCHEDULE_OPENFILE, data, reply, option); + if (err != NO_ERROR) { + HILOG_ERROR("OpenFile fail to SendRequest. err: %d", err); + return err; + } + + fd = reply.ReadFileDescriptor(); + if (fd == -1) { + HILOG_ERROR("fail to ReadInt32 fd"); + return fd; + } + + return fd; +} + +/** + * @brief This is like openFile, open a file that need to be able to return sub-sections of files,often assets + * inside of their .hap. + * + * @param uri Indicates the path of the file to open. + * @param mode Indicates the file open mode, which can be "r" for read-only access, "w" for write-only access + * (erasing whatever data is currently in the file), "wt" for write access that truncates any existing file, + * "wa" for write-only access to append to any existing data, "rw" for read and write access on any existing + * data, or "rwt" for read and write access that truncates any existing file. + * + * @return Returns the RawFileDescriptor object containing file descriptor. + */ +int AbilitySchedulerProxy::OpenRawFile(const Uri &uri, const std::string &mode) +{ + int fd = -1; + + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!WriteInterfaceToken(data)) { + return fd; + } + + if (!data.WriteParcelable(&uri)) { + HILOG_ERROR("fail to WriteParcelable uri"); + return fd; + } + + if (!data.WriteString(mode)) { + HILOG_ERROR("fail to WriteString mode"); + return fd; + } + + int32_t err = Remote()->SendRequest(IAbilityScheduler::SCHEDULE_OPENRAWFILE, data, reply, option); + if (err != NO_ERROR) { + HILOG_ERROR("OpenFile fail to SendRequest. err: %d", err); + } + + if (!reply.ReadInt32(fd)) { + HILOG_ERROR("fail to ReadInt32 fd"); + return fd; + } + + return fd; +} + +/** + * @brief Inserts a single data record into the database. + * + * @param uri Indicates the path of the data to operate. + * @param value Indicates the data record to insert. If this parameter is null, a blank row will be inserted. + * + * @return Returns the index of the inserted data record. + */ +int AbilitySchedulerProxy::Insert(const Uri &uri, const NativeRdb::ValuesBucket &value) +{ + int index = -1; + + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!WriteInterfaceToken(data)) { + return index; + } + + if (!data.WriteParcelable(&uri)) { + HILOG_ERROR("fail to WriteParcelable uri"); + return index; + } + + if (!data.WriteParcelable(&value)) { + HILOG_ERROR("fail to WriteParcelable value"); + return index; + } + + int32_t err = Remote()->SendRequest(IAbilityScheduler::SCHEDULE_INSERT, data, reply, option); + if (err != NO_ERROR) { + HILOG_ERROR("Insert fail to SendRequest. err: %d", err); + return err; + } + + if (!reply.ReadInt32(index)) { + HILOG_ERROR("fail to ReadInt32 index"); + return index; + } + + return index; +} + +/** + * @brief Updates data records in the database. + * + * @param uri Indicates the path of data to update. + * @param value Indicates the data to update. This parameter can be null. + * @param predicates Indicates filter criteria. You should define the processing logic when this parameter is null. + * + * @return Returns the number of data records updated. + */ +int AbilitySchedulerProxy::Update(const Uri &uri, const NativeRdb::ValuesBucket &value, const NativeRdb::DataAbilityPredicates &predicates) +{ + int index = -1; + + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!WriteInterfaceToken(data)) { + return index; + } + + if (!data.WriteParcelable(&uri)) { + HILOG_ERROR("fail to WriteParcelable uri"); + return index; + } + + if (!data.WriteParcelable(&value)) { + HILOG_ERROR("fail to WriteParcelable value"); + return index; + } + + if (!data.WriteParcelable(&predicates)) { + HILOG_ERROR("fail to WriteParcelable predicates"); + return index; + } + + int32_t err = Remote()->SendRequest(IAbilityScheduler::SCHEDULE_UPDATE, data, reply, option); + if (err != NO_ERROR) { + HILOG_ERROR("Update fail to SendRequest. err: %d", err); + return err; + } + + if (!reply.ReadInt32(index)) { + HILOG_ERROR("fail to ReadInt32 index"); + return index; + } + + return index; +} + +/** + * @brief Deletes one or more data records from the database. + * + * @param uri Indicates the path of the data to operate. + * @param predicates Indicates filter criteria. You should define the processing logic when this parameter is null. + * + * @return Returns the number of data records deleted. + */ +int AbilitySchedulerProxy::Delete(const Uri &uri, const NativeRdb::DataAbilityPredicates &predicates) +{ + int index = -1; + + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!WriteInterfaceToken(data)) { + return index; + } + + if (!data.WriteParcelable(&uri)) { + HILOG_ERROR("fail to WriteParcelable uri"); + return index; + } + + if (!data.WriteParcelable(&predicates)) { + HILOG_ERROR("fail to WriteParcelable predicates"); + return index; + } + + int32_t err = Remote()->SendRequest(IAbilityScheduler::SCHEDULE_DELETE, data, reply, option); + if (err != NO_ERROR) { + HILOG_ERROR("Delete fail to SendRequest. err: %d", err); + } + + if (!reply.ReadInt32(index)) { + HILOG_ERROR("fail to ReadInt32 index"); + return index; + } + + return index; +} + +/** + * @brief Deletes one or more data records from the database. + * + * @param uri Indicates the path of data to query. + * @param columns Indicates the columns to query. If this parameter is null, all columns are queried. + * @param predicates Indicates filter criteria. You should define the processing logic when this parameter is null. + * + * @return Returns the query result. + */ +std::shared_ptr AbilitySchedulerProxy::Query( + const Uri &uri, std::vector &columns, const NativeRdb::DataAbilityPredicates &predicates) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!WriteInterfaceToken(data)) { + return nullptr; + } + + if (!data.WriteParcelable(&uri)) { + HILOG_ERROR("fail to WriteParcelable uri"); + return nullptr; + } + + if (!data.WriteStringVector(columns)) { + HILOG_ERROR("fail to WriteStringVector columns"); + return nullptr; + } + + if (!data.WriteParcelable(&predicates)) { + HILOG_ERROR("fail to WriteParcelable predicates"); + return nullptr; + } + + int32_t err = Remote()->SendRequest(IAbilityScheduler::SCHEDULE_QUERY, data, reply, option); + if (err != NO_ERROR) { + HILOG_ERROR("Query fail to SendRequest. err: %d", err); + return nullptr; + } + return OHOS::NativeRdb::ISharedResultSet::ReadFromParcel(reply); +} + +/** + * @brief Obtains the MIME type matching the data specified by the URI of the Data ability. This method should be + * implemented by a Data ability. Data abilities supports general data types, including text, HTML, and JPEG. + * + * @param uri Indicates the URI of the data. + * + * @return Returns the MIME type that matches the data specified by uri. + */ +std::string AbilitySchedulerProxy::GetType(const Uri &uri) +{ + std::string type; + + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!WriteInterfaceToken(data)) { + return type; + } + + if (!data.WriteParcelable(&uri)) { + HILOG_ERROR("fail to WriteParcelable uri"); + return type; + } + + int32_t err = Remote()->SendRequest(IAbilityScheduler::SCHEDULE_GETTYPE, data, reply, option); + if (err != NO_ERROR) { + HILOG_ERROR("GetFileTypes fail to SendRequest. err: %d", err); + } + + type = reply.ReadString(); + if (type.empty()) { + HILOG_ERROR("fail to ReadString type"); + return type; + } + + return type; +} + +/** + * @brief Reloads data in the database. + * + * @param uri Indicates the position where the data is to reload. This parameter is mandatory. + * @param extras Indicates the PacMap object containing the additional parameters to be passed in this call. This + * parameter can be null. If a custom Sequenceable object is put in the PacMap object and will be transferred across + * processes, you must call BasePacMap.setClassLoader(ClassLoader) to set a class loader for the custom object. + * + * @return Returns true if the data is successfully reloaded; returns false otherwise. + */ +bool AbilitySchedulerProxy::Reload(const Uri &uri, const PacMap &extras) +{ + bool ret = false; + + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!WriteInterfaceToken(data)) { + return ret; + } + + if (!data.WriteParcelable(&uri)) { + HILOG_ERROR("fail to WriteParcelable uri"); + return ret; + } + + if (!data.WriteParcelable(&extras)) { + HILOG_ERROR("fail to WriteParcelable extras"); + return ret; + } + + int32_t err = Remote()->SendRequest(IAbilityScheduler::SCHEDULE_RELOAD, data, reply, option); + if (err != NO_ERROR) { + HILOG_ERROR("GetFileTypes fail to SendRequest. err: %d", err); + } + + ret = reply.ReadBool(); + if (!ret) { + HILOG_ERROR("fail to ReadBool ret"); + return ret; + } + + return ret; +} + +/** + * @brief Inserts multiple data records into the database. + * + * @param uri Indicates the path of the data to operate. + * @param values Indicates the data records to insert. + * + * @return Returns the number of data records inserted. + */ +int AbilitySchedulerProxy::BatchInsert(const Uri &uri, const std::vector &values) +{ + int ret = -1; + + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!WriteInterfaceToken(data)) { + return ret; + } + + if (!data.WriteParcelable(&uri)) { + HILOG_ERROR("fail to WriteParcelable uri"); + return ret; + } + + int count = values.size(); + if (!data.WriteInt32(count)) { + HILOG_ERROR("fail to WriteInt32 ret"); + return ret; + } + + for (int i = 0; i < count; i++) { + if (!data.WriteParcelable(&values[i])) { + HILOG_ERROR("fail to WriteParcelable ret, index = %{public}d", i); + return ret; + } + } + + int32_t err = Remote()->SendRequest(IAbilityScheduler::SCHEDULE_BATCHINSERT, data, reply, option); + if (err != NO_ERROR) { + HILOG_ERROR("GetFileTypes fail to SendRequest. err: %d", err); + } + + if (!reply.ReadInt32(ret)) { + HILOG_ERROR("fail to ReadInt32 index"); + return ret; + } + + return ret; +} + +/** + * @brief notify multi window mode changed. + * + * @param winModeKey Indicates ability Window display mode. + * @param flag Indicates this ability has been enter this mode. + */ +void AbilitySchedulerProxy::NotifyMultiWinModeChanged(int32_t winModeKey, bool flag) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!WriteInterfaceToken(data)) { + return; + } + if (!data.WriteInt32(winModeKey)) { + HILOG_ERROR("fail to WriteParcelable"); + return; + } + if (!data.WriteBool(flag)) { + HILOG_ERROR("fail to WriteBool"); + return; + } + int32_t err = Remote()->SendRequest(IAbilityScheduler::MULTI_WIN_CHANGED, data, reply, option); + if (err != NO_ERROR) { + HILOG_ERROR("NotifyMultiWinModeChanged fail to SendRequest. err: %d", err); + } +} + +/** + * @brief Registers an observer to DataObsMgr specified by the given Uri. + * + * @param uri, Indicates the path of the data to operate. + * @param dataObserver, Indicates the IDataAbilityObserver object. + */ +bool AbilitySchedulerProxy::ScheduleRegisterObserver(const Uri &uri, const sptr &dataObserver) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!WriteInterfaceToken(data)) { + HILOG_ERROR("%{public}s WriteInterfaceToken(data) return false", __func__); + return false; + } + + if (!data.WriteParcelable(&uri)) { + HILOG_ERROR("%{public}s failed to WriteParcelable uri ", __func__); + return false; + } + + if (!data.WriteParcelable(dataObserver->AsObject())) { + HILOG_ERROR("%{public}s failed to WriteParcelable dataObserver ", __func__); + return false; + } + + int32_t result = Remote()->SendRequest(IAbilityScheduler::SCHEDULE_REGISTEROBSERVER, data, reply, option); + if (result == ERR_NONE) { + HILOG_INFO("%{public}s SendRequest ok, retval is %{public}d", __func__, reply.ReadInt32()); + return true; + } else { + HILOG_ERROR("%{public}s SendRequest error, result=%{public}d", __func__, result); + return false; + } +} + +/** + * @brief Deregisters an observer used for DataObsMgr specified by the given Uri. + * + * @param uri, Indicates the path of the data to operate. + * @param dataObserver, Indicates the IDataAbilityObserver object. + */ +bool AbilitySchedulerProxy::ScheduleUnregisterObserver(const Uri &uri, const sptr &dataObserver) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!WriteInterfaceToken(data)) { + HILOG_ERROR("%{public}s WriteInterfaceToken(data) return false", __func__); + return false; + } + + if (!data.WriteParcelable(&uri)) { + HILOG_ERROR("%{public}s failed to WriteParcelable uri ", __func__); + return false; + } + + if (!data.WriteParcelable(dataObserver->AsObject())) { + HILOG_ERROR("%{public}s failed to WriteParcelable dataObserver ", __func__); + return false; + } + + int32_t result = Remote()->SendRequest(IAbilityScheduler::SCHEDULE_UNREGISTEROBSERVER, data, reply, option); + if (result == ERR_NONE) { + HILOG_INFO("%{public}s SendRequest ok, retval is %{public}d", __func__, reply.ReadInt32()); + return true; + } else { + HILOG_ERROR("%{public}s SendRequest error, result=%{public}d", __func__, result); + return false; + } +} + +/** + * @brief Notifies the registered observers of a change to the data resource specified by Uri. + * + * @param uri, Indicates the path of the data to operate. + */ +bool AbilitySchedulerProxy::ScheduleNotifyChange(const Uri &uri) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!WriteInterfaceToken(data)) { + HILOG_ERROR("%{public}s WriteInterfaceToken(data) return false", __func__); + return false; + } + + if (!data.WriteParcelable(&uri)) { + HILOG_ERROR("%{public}s failed to WriteParcelable uri ", __func__); + return false; + } + + int32_t result = Remote()->SendRequest(IAbilityScheduler::SCHEDULE_NOTIFYCHANGE, data, reply, option); + if (result == ERR_NONE) { + HILOG_INFO("%{public}s SendRequest ok, retval is %{public}d", __func__, reply.ReadInt32()); + return true; + } else { + HILOG_ERROR("%{public}s SendRequest error, result=%{public}d", __func__, result); + return false; + } +} + +/** + * @brief notify this ability is top active ability. + * + * @param flag true: Indicates this ability is top active ability + */ +void AbilitySchedulerProxy::NotifyTopActiveAbilityChanged(bool flag) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!WriteInterfaceToken(data)) { + return; + } + if (!data.WriteBool(flag)) { + HILOG_ERROR("fail to WriteBool"); + return; + } + int32_t err = Remote()->SendRequest(IAbilityScheduler::TOP_ACTIVE_ABILITY_CHANGED, data, reply, option); + if (err != NO_ERROR) { + HILOG_ERROR("NotifyTopActiveAbilityChanged fail to SendRequest. err: %d", err); + } +} + +/** + * @brief Converts the given uri that refer to the Data ability into a normalized URI. A normalized URI can be used + * across devices, persisted, backed up, and restored. It can refer to the same item in the Data ability even if the + * context has changed. If you implement URI normalization for a Data ability, you must also implement + * denormalizeUri(ohos.utils.net.Uri) to enable URI denormalization. After this feature is enabled, URIs passed to + * any method that is called on the Data ability must require normalization verification and denormalization. The + * default implementation of this method returns null, indicating that this Data ability does not support URI + * normalization. + * + * @param uri Indicates the Uri object to normalize. + * + * @return Returns the normalized Uri object if the Data ability supports URI normalization; returns null otherwise. + */ +Uri AbilitySchedulerProxy::NormalizeUri(const Uri &uri) +{ + Uri urivalue(""); + + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!WriteInterfaceToken(data)) { + return urivalue; + } + + if (!data.WriteParcelable(&uri)) { + HILOG_ERROR("fail to WriteParcelable uri"); + return urivalue; + } + + int32_t err = Remote()->SendRequest(IAbilityScheduler::SCHEDULE_NORMALIZEURI, data, reply, option); + if (err != NO_ERROR) { + HILOG_ERROR("NormalizeUri fail to SendRequest. err: %d", err); + } + + std::unique_ptr info(reply.ReadParcelable()); + if (!info) { + HILOG_ERROR("ReadParcelable value is nullptr."); + return Uri(""); + } + return *info; +} + +/** + * @brief Converts the given normalized uri generated by normalizeUri(ohos.utils.net.Uri) into a denormalized one. + * The default implementation of this method returns the original URI passed to it. + * + * @param uri uri Indicates the Uri object to denormalize. + * + * @return Returns the denormalized Uri object if the denormalization is successful; returns the original Uri passed + * to this method if there is nothing to do; returns null if the data identified by the original Uri cannot be found + * in the current environment. + */ +Uri AbilitySchedulerProxy::DenormalizeUri(const Uri &uri) +{ + Uri urivalue(""); + + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!WriteInterfaceToken(data)) { + return urivalue; + } + + if (!data.WriteParcelable(&uri)) { + HILOG_ERROR("fail to WriteParcelable uri"); + return urivalue; + } + + int32_t err = Remote()->SendRequest(IAbilityScheduler::SCHEDULE_DENORMALIZEURI, data, reply, option); + if (err != NO_ERROR) { + HILOG_ERROR("DenormalizeUri fail to SendRequest. err: %d", err); + } + + std::unique_ptr info(reply.ReadParcelable()); + if (!info) { + HILOG_ERROR("ReadParcelable value is nullptr."); + return Uri(""); + } + return *info; +} + +std::vector> AbilitySchedulerProxy::ExecuteBatch( + const std::vector> &operations) +{ + HILOG_INFO("AbilitySchedulerProxy::ExecuteBatch start"); + MessageParcel data; + MessageParcel reply; + MessageOption option; + + MessageParcel datatemp; + + std::vector> results; + results.clear(); + + if (!WriteInterfaceToken(data)) { + HILOG_ERROR("AbilitySchedulerProxy::ExecuteBatch fail to Writer token"); + return results; + } + + int count = operations.size(); + if (!data.WriteInt32(count)) { + HILOG_ERROR("AbilitySchedulerProxy::ExecuteBatch fail to WriteInt32 ret"); + return results; + } + datatemp.WriteInt32(count); + + for (int i = 0; i < count; i++) { + if (!data.WriteParcelable(operations[i].get())) { + HILOG_ERROR("AbilitySchedulerProxy::ExecuteBatch fail to WriteParcelable ret, index = %{public}d", i); + return results; + } + datatemp.WriteParcelable(operations[i].get()); + } + + int32_t err = Remote()->SendRequest(IAbilityScheduler::SCHEDULE_EXECUTEBATCH, data, reply, option); + if (err != NO_ERROR) { + HILOG_ERROR("AbilitySchedulerProxy::ExecuteBatch fail to SendRequest. err: %{public}d", err); + } + + int tempCount = 0; + if (!datatemp.ReadInt32(tempCount)) { + HILOG_ERROR("AbilitySchedulerProxy::ExecuteBatchInner fail to ReadInt32 count"); + return results; + } + HILOG_ERROR("AbilitySchedulerProxy::ExecuteBatchInner datatemp.ReadInt32(tempCount) to %{public}d", tempCount); + + for (int i = 0; i < tempCount; ++i) { + AppExecFwk::DataAbilityOperation *operation = datatemp.ReadParcelable(); + if (operation == nullptr) { + HILOG_ERROR("AbilitySchedulerProxy::ExecuteBatchInner operation is nullptr, index = %{public}d", i); + return results; + } + } + HILOG_INFO("AbilitySchedulerProxy::ExecuteBatchInner operation->testShow done "); + + int total = 0; + if (!reply.ReadInt32(total)) { + HILOG_ERROR("AbilitySchedulerProxy::ExecuteBatch fail to ReadInt32 count %{public}d", total); + return results; + } + + for (int i = 0; i < total; i++) { + AppExecFwk::DataAbilityResult *result = reply.ReadParcelable(); + if (result == nullptr) { + HILOG_ERROR("AbilitySchedulerProxy::ExecuteBatch result is nullptr, index = %{public}d", i); + return results; + } + std::shared_ptr dataAbilityResult(result); + results.push_back(dataAbilityResult); + } + HILOG_INFO("AbilitySchedulerProxy::ExecuteBatch end"); + return results; +} +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/abilitymgr/src/ability_scheduler_stub.cpp b/tools/services/abilitymgr/src/ability_scheduler_stub.cpp new file mode 100644 index 00000000000..cddd0940eca --- /dev/null +++ b/tools/services/abilitymgr/src/ability_scheduler_stub.cpp @@ -0,0 +1,579 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ability_scheduler_stub.h" +#include "abs_shared_result_set.h" +#include "data_ability_predicates.h" +#include "values_bucket.h" + +#include "hilog_wrapper.h" +#include "ipc_types.h" +#include "ishared_result_set.h" +#include "pac_map.h" +#include "want.h" +#include "data_ability_observer_interface.h" +#include "data_ability_result.h" +#include "data_ability_operation.h" + +namespace OHOS { +namespace AAFwk { +AbilitySchedulerStub::AbilitySchedulerStub() +{ + requestFuncMap_[SCHEDULE_ABILITY_TRANSACTION] = &AbilitySchedulerStub::AbilityTransactionInner; + requestFuncMap_[SEND_RESULT] = &AbilitySchedulerStub::SendResultInner; + requestFuncMap_[SCHEDULE_ABILITY_CONNECT] = &AbilitySchedulerStub::ConnectAbilityInner; + requestFuncMap_[SCHEDULE_ABILITY_DISCONNECT] = &AbilitySchedulerStub::DisconnectAbilityInner; + requestFuncMap_[SCHEDULE_ABILITY_COMMAND] = &AbilitySchedulerStub::CommandAbilityInner; + requestFuncMap_[SCHEDULE_SAVE_ABILITY_STATE] = &AbilitySchedulerStub::SaveAbilityStateInner; + requestFuncMap_[SCHEDULE_RESTORE_ABILITY_STATE] = &AbilitySchedulerStub::RestoreAbilityStateInner; + requestFuncMap_[SCHEDULE_GETFILETYPES] = &AbilitySchedulerStub::GetFileTypesInner; + requestFuncMap_[SCHEDULE_OPENFILE] = &AbilitySchedulerStub::OpenFileInner; + requestFuncMap_[SCHEDULE_OPENRAWFILE] = &AbilitySchedulerStub::OpenRawFileInner; + requestFuncMap_[SCHEDULE_INSERT] = &AbilitySchedulerStub::InsertInner; + requestFuncMap_[SCHEDULE_UPDATE] = &AbilitySchedulerStub::UpdatetInner; + requestFuncMap_[SCHEDULE_DELETE] = &AbilitySchedulerStub::DeleteInner; + requestFuncMap_[SCHEDULE_QUERY] = &AbilitySchedulerStub::QueryInner; + requestFuncMap_[SCHEDULE_GETTYPE] = &AbilitySchedulerStub::GetTypeInner; + requestFuncMap_[SCHEDULE_RELOAD] = &AbilitySchedulerStub::ReloadInner; + requestFuncMap_[SCHEDULE_BATCHINSERT] = &AbilitySchedulerStub::BatchInsertInner; + requestFuncMap_[SCHEDULE_REGISTEROBSERVER] = &AbilitySchedulerStub::RegisterObserverInner; + requestFuncMap_[SCHEDULE_UNREGISTEROBSERVER] = &AbilitySchedulerStub::UnregisterObserverInner; + requestFuncMap_[SCHEDULE_NOTIFYCHANGE] = &AbilitySchedulerStub::NotifyChangeInner; + requestFuncMap_[MULTI_WIN_CHANGED] = &AbilitySchedulerStub::MutiWinModeChangedInner; + requestFuncMap_[SCHEDULE_NORMALIZEURI] = &AbilitySchedulerStub::NormalizeUriInner; + requestFuncMap_[SCHEDULE_DENORMALIZEURI] = &AbilitySchedulerStub::DenormalizeUriInner; + requestFuncMap_[SCHEDULE_UPDATE_CONFIGURATION] = &AbilitySchedulerStub::UpdateConfigurationInner; + requestFuncMap_[SCHEDULE_EXECUTEBATCH] = &AbilitySchedulerStub::ExecuteBatchInner; + requestFuncMap_[TOP_ACTIVE_ABILITY_CHANGED] = &AbilitySchedulerStub::TopActiveAbilityChangedInner; +} + +AbilitySchedulerStub::~AbilitySchedulerStub() +{ + requestFuncMap_.clear(); +} + +int AbilitySchedulerStub::OnRemoteRequest( + uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) +{ + HILOG_DEBUG("AbilitySchedulerStub::OnRemoteRequest, cmd = %d, flags= %d", code, option.GetFlags()); + std::u16string descriptor = AbilitySchedulerStub::GetDescriptor(); + std::u16string remoteDescriptor = data.ReadInterfaceToken(); + if (descriptor != remoteDescriptor) { + HILOG_INFO("local descriptor is not equal to remote"); + return ERR_INVALID_STATE; + } + + auto itFunc = requestFuncMap_.find(code); + if (itFunc != requestFuncMap_.end()) { + auto requestFunc = itFunc->second; + if (requestFunc != nullptr) { + return (this->*requestFunc)(data, reply); + } + } + HILOG_WARN("AbilitySchedulerStub::OnRemoteRequest, default case, need check."); + return IPCObjectStub::OnRemoteRequest(code, data, reply, option); +} + +int AbilitySchedulerStub::AbilityTransactionInner(MessageParcel &data, MessageParcel &reply) +{ + std::shared_ptr want(data.ReadParcelable()); + if (want == nullptr) { + HILOG_ERROR("AbilitySchedulerStub want is nullptr"); + return ERR_INVALID_VALUE; + } + std::unique_ptr stateInfo(data.ReadParcelable()); + if (!stateInfo) { + HILOG_ERROR("ReadParcelable failed"); + return ERR_INVALID_VALUE; + } + ScheduleAbilityTransaction(*want, *stateInfo); + return NO_ERROR; +} + +int AbilitySchedulerStub::SendResultInner(MessageParcel &data, MessageParcel &reply) +{ + int requestCode = data.ReadInt32(); + int resultCode = data.ReadInt32(); + std::shared_ptr want(data.ReadParcelable()); + if (want == nullptr) { + HILOG_ERROR("AbilitySchedulerStub want is nullptr"); + return ERR_INVALID_VALUE; + } + SendResult(requestCode, resultCode, *want); + return NO_ERROR; +} + +int AbilitySchedulerStub::ConnectAbilityInner(MessageParcel &data, MessageParcel &reply) +{ + std::shared_ptr want(data.ReadParcelable()); + if (want == nullptr) { + HILOG_ERROR("AbilitySchedulerStub want is nullptr"); + return ERR_INVALID_VALUE; + } + ScheduleConnectAbility(*want); + return NO_ERROR; +} + +int AbilitySchedulerStub::DisconnectAbilityInner(MessageParcel &data, MessageParcel &reply) +{ + std::shared_ptr want(data.ReadParcelable()); + if (want == nullptr) { + HILOG_ERROR("AbilitySchedulerStub want is nullptr"); + return ERR_INVALID_VALUE; + } + ScheduleDisconnectAbility(*want); + return NO_ERROR; +} + +int AbilitySchedulerStub::CommandAbilityInner(MessageParcel &data, MessageParcel &reply) +{ + std::shared_ptr want(data.ReadParcelable()); + if (want == nullptr) { + HILOG_ERROR("AbilitySchedulerStub want is nullptr"); + return ERR_INVALID_VALUE; + } + bool reStart = data.ReadBool(); + int startId = data.ReadInt32(); + ScheduleCommandAbility(*want, reStart, startId); + return NO_ERROR; +} + +int AbilitySchedulerStub::SaveAbilityStateInner(MessageParcel &data, MessageParcel &reply) +{ + PacMap pacMap; + ScheduleSaveAbilityState(pacMap); + if (!reply.WriteParcelable(&pacMap)) { + HILOG_ERROR("AbilityManagerStub: SaveAbilityState error"); + return ERR_INVALID_VALUE; + } + return NO_ERROR; +} + +int AbilitySchedulerStub::RestoreAbilityStateInner(MessageParcel &data, MessageParcel &reply) +{ + std::shared_ptr pacMap(data.ReadParcelable()); + if (pacMap == nullptr) { + HILOG_ERROR("AbilitySchedulerStub RestoreAbilityState is nullptr"); + return ERR_INVALID_VALUE; + } + ScheduleRestoreAbilityState(*pacMap); + return NO_ERROR; +} + +int AbilitySchedulerStub::GetFileTypesInner(MessageParcel &data, MessageParcel &reply) +{ + std::shared_ptr uri(data.ReadParcelable()); + if (uri == nullptr) { + HILOG_ERROR("AbilitySchedulerStub uri is nullptr"); + return ERR_INVALID_VALUE; + } + std::string mimeTypeFilter = data.ReadString(); + if (mimeTypeFilter.empty()) { + HILOG_ERROR("AbilitySchedulerStub mimeTypeFilter is nullptr"); + return ERR_INVALID_VALUE; + } + std::vector types = GetFileTypes(*uri, mimeTypeFilter); + if (!reply.WriteStringVector(types)) { + HILOG_ERROR("fail to WriteStringVector types"); + return ERR_INVALID_VALUE; + } + return NO_ERROR; +} + +int AbilitySchedulerStub::OpenFileInner(MessageParcel &data, MessageParcel &reply) +{ + std::shared_ptr uri(data.ReadParcelable()); + if (uri == nullptr) { + HILOG_ERROR("AbilitySchedulerStub uri is nullptr"); + return ERR_INVALID_VALUE; + } + std::string mode = data.ReadString(); + if (mode.empty()) { + HILOG_ERROR("AbilitySchedulerStub mode is nullptr"); + return ERR_INVALID_VALUE; + } + int fd = OpenFile(*uri, mode); + if (!reply.WriteFileDescriptor(fd)) { + HILOG_ERROR("fail to WriteFileDescriptor fd"); + return ERR_INVALID_VALUE; + } + return NO_ERROR; +} + +int AbilitySchedulerStub::OpenRawFileInner(MessageParcel &data, MessageParcel &reply) +{ + std::shared_ptr uri(data.ReadParcelable()); + if (uri == nullptr) { + HILOG_ERROR("AbilitySchedulerStub uri is nullptr"); + return ERR_INVALID_VALUE; + } + std::string mode = data.ReadString(); + if (mode.empty()) { + HILOG_ERROR("AbilitySchedulerStub mode is nullptr"); + return ERR_INVALID_VALUE; + } + int fd = OpenRawFile(*uri, mode); + if (!reply.WriteInt32(fd)) { + HILOG_ERROR("fail to WriteInt32 fd"); + return ERR_INVALID_VALUE; + } + return NO_ERROR; +} + +int AbilitySchedulerStub::InsertInner(MessageParcel &data, MessageParcel &reply) +{ + std::shared_ptr uri(data.ReadParcelable()); + if (uri == nullptr) { + HILOG_ERROR("AbilitySchedulerStub uri is nullptr"); + return ERR_INVALID_VALUE; + } + std::shared_ptr value(data.ReadParcelable()); + if (value == nullptr) { + HILOG_ERROR("ReadParcelable value is nullptr"); + return ERR_INVALID_VALUE; + } + int index = Insert(*uri, *value); + if (!reply.WriteInt32(index)) { + HILOG_ERROR("fail to WriteInt32 index"); + return ERR_INVALID_VALUE; + } + HILOG_INFO("AbilitySchedulerStub::InsertInner end"); + return NO_ERROR; +} + +int AbilitySchedulerStub::UpdatetInner(MessageParcel &data, MessageParcel &reply) +{ + std::shared_ptr uri(data.ReadParcelable()); + if (uri == nullptr) { + HILOG_ERROR("AbilitySchedulerStub uri is nullptr"); + return ERR_INVALID_VALUE; + } + std::shared_ptr value(data.ReadParcelable()); + if (value == nullptr) { + HILOG_ERROR("ReadParcelable value is nullptr"); + return ERR_INVALID_VALUE; + } + std::shared_ptr predicates( + data.ReadParcelable()); + if (predicates == nullptr) { + HILOG_ERROR("ReadParcelable predicates is nullptr"); + return ERR_INVALID_VALUE; + } + int index = Update(*uri, *value, *predicates); + if (!reply.WriteInt32(index)) { + HILOG_ERROR("fail to WriteInt32 index"); + return ERR_INVALID_VALUE; + } + return NO_ERROR; +} + +int AbilitySchedulerStub::DeleteInner(MessageParcel &data, MessageParcel &reply) +{ + std::shared_ptr uri(data.ReadParcelable()); + if (uri == nullptr) { + HILOG_ERROR("AbilitySchedulerStub uri is nullptr"); + return ERR_INVALID_VALUE; + } + std::shared_ptr predicates( + data.ReadParcelable()); + if (predicates == nullptr) { + HILOG_ERROR("ReadParcelable predicates is nullptr"); + return ERR_INVALID_VALUE; + } + int index = Delete(*uri, *predicates); + if (!reply.WriteInt32(index)) { + HILOG_ERROR("fail to WriteInt32 index"); + return ERR_INVALID_VALUE; + } + return NO_ERROR; +} + +int AbilitySchedulerStub::QueryInner(MessageParcel &data, MessageParcel &reply) +{ + std::shared_ptr uri(data.ReadParcelable()); + if (uri == nullptr) { + HILOG_ERROR("AbilitySchedulerStub uri is nullptr"); + return ERR_INVALID_VALUE; + } + std::vector columns; + if (!data.ReadStringVector(&columns)) { + HILOG_ERROR("fail to ReadStringVector columns"); + return ERR_INVALID_VALUE; + } + std::shared_ptr predicates( + data.ReadParcelable()); + if (predicates == nullptr) { + HILOG_ERROR("ReadParcelable predicates is nullptr"); + return ERR_INVALID_VALUE; + } + auto resultSet = Query(*uri, columns, *predicates); + if (resultSet == nullptr) { + HILOG_ERROR("fail to WriteParcelable resultSet"); + return ERR_INVALID_VALUE; + } + auto result = NativeRdb::ISharedResultSet::WriteToParcel(std::move(resultSet), reply); + if (result == nullptr) { + HILOG_ERROR("!resultSet->Marshalling(reply)"); + return ERR_INVALID_VALUE; + } + HILOG_INFO("AbilitySchedulerStub::QueryInner end"); + return NO_ERROR; +} + +int AbilitySchedulerStub::GetTypeInner(MessageParcel &data, MessageParcel &reply) +{ + std::shared_ptr uri(data.ReadParcelable()); + if (uri == nullptr) { + HILOG_ERROR("AbilitySchedulerStub uri is nullptr"); + return ERR_INVALID_VALUE; + } + std::string type = GetType(*uri); + if (!reply.WriteString(type)) { + HILOG_ERROR("fail to WriteString type"); + return ERR_INVALID_VALUE; + } + return NO_ERROR; +} + +int AbilitySchedulerStub::ReloadInner(MessageParcel &data, MessageParcel &reply) +{ + std::shared_ptr uri(data.ReadParcelable()); + if (uri == nullptr) { + HILOG_ERROR("AbilitySchedulerStub uri is nullptr"); + return ERR_INVALID_VALUE; + } + + std::shared_ptr extras(data.ReadParcelable()); + if (extras == nullptr) { + HILOG_ERROR("AbilitySchedulerStub extras is nullptr"); + return ERR_INVALID_VALUE; + } + bool ret = Reload(*uri, *extras); + if (!reply.WriteBool(ret)) { + HILOG_ERROR("fail to writeBool ret"); + return ERR_INVALID_VALUE; + } + return NO_ERROR; +} + +int AbilitySchedulerStub::BatchInsertInner(MessageParcel &data, MessageParcel &reply) +{ + std::shared_ptr uri(data.ReadParcelable()); + if (uri == nullptr) { + HILOG_ERROR("AbilitySchedulerStub uri is nullptr"); + return ERR_INVALID_VALUE; + } + + int count = 0; + if (!data.ReadInt32(count)) { + HILOG_ERROR("fail to ReadInt32 index"); + return ERR_INVALID_VALUE; + } + + std::vector values; + for (int i = 0; i < count; i++) { + NativeRdb::ValuesBucket *value = data.ReadParcelable(); + if (value == nullptr) { + HILOG_ERROR("AbilitySchedulerStub value is nullptr, index = %{public}d", i); + return ERR_INVALID_VALUE; + } + values.emplace_back(*value); + } + + int ret = BatchInsert(*uri, values); + if (!reply.WriteInt32(ret)) { + HILOG_ERROR("fail to WriteInt32 ret"); + return ERR_INVALID_VALUE; + } + return NO_ERROR; +} + +int AbilitySchedulerStub::RegisterObserverInner(MessageParcel &data, MessageParcel &reply) +{ + std::shared_ptr uri(data.ReadParcelable()); + if (uri == nullptr) { + HILOG_ERROR("AbilitySchedulerStub uri is nullptr"); + return ERR_INVALID_VALUE; + } + auto obServer = iface_cast(data.ReadParcelable()); + if (obServer == nullptr) { + HILOG_ERROR("AbilitySchedulerStub obServer is nullptr"); + return ERR_INVALID_VALUE; + } + + bool ret = ScheduleRegisterObserver(*uri, obServer); + if (!reply.WriteInt32(ret)) { + HILOG_ERROR("fail to WriteInt32 ret"); + return ERR_INVALID_VALUE; + } + return NO_ERROR; +} + +int AbilitySchedulerStub::UnregisterObserverInner(MessageParcel &data, MessageParcel &reply) +{ + std::shared_ptr uri(data.ReadParcelable()); + if (uri == nullptr) { + HILOG_ERROR("AbilitySchedulerStub uri is nullptr"); + return ERR_INVALID_VALUE; + } + auto obServer = iface_cast(data.ReadParcelable()); + if (obServer == nullptr) { + HILOG_ERROR("AbilitySchedulerStub obServer is nullptr"); + return ERR_INVALID_VALUE; + } + + bool ret = ScheduleUnregisterObserver(*uri, obServer); + if (!reply.WriteInt32(ret)) { + HILOG_ERROR("fail to WriteInt32 ret"); + return ERR_INVALID_VALUE; + } + return NO_ERROR; +} + +int AbilitySchedulerStub::NotifyChangeInner(MessageParcel &data, MessageParcel &reply) +{ + std::shared_ptr uri(data.ReadParcelable()); + if (uri == nullptr) { + HILOG_ERROR("AbilitySchedulerStub uri is nullptr"); + return ERR_INVALID_VALUE; + } + + bool ret = ScheduleNotifyChange(*uri); + if (!reply.WriteInt32(ret)) { + HILOG_ERROR("fail to WriteInt32 ret"); + return ERR_INVALID_VALUE; + } + return NO_ERROR; +} + +int AbilitySchedulerStub::NormalizeUriInner(MessageParcel &data, MessageParcel &reply) +{ + std::shared_ptr uri(data.ReadParcelable()); + if (uri == nullptr) { + HILOG_ERROR("AbilitySchedulerStub uri is nullptr"); + return ERR_INVALID_VALUE; + } + + Uri ret(""); + ret = NormalizeUri(*uri); + if (!reply.WriteParcelable(&ret)) { + HILOG_ERROR("fail to WriteParcelable type"); + return ERR_INVALID_VALUE; + } + return NO_ERROR; +} + +int AbilitySchedulerStub::DenormalizeUriInner(MessageParcel &data, MessageParcel &reply) +{ + std::shared_ptr uri(data.ReadParcelable()); + if (uri == nullptr) { + HILOG_ERROR("AbilitySchedulerStub uri is nullptr"); + return ERR_INVALID_VALUE; + } + + Uri ret(""); + ret = DenormalizeUri(*uri); + if (!reply.WriteParcelable(&ret)) { + HILOG_ERROR("fail to WriteParcelable type"); + return ERR_INVALID_VALUE; + } + return NO_ERROR; +} + +int AbilitySchedulerStub::UpdateConfigurationInner(MessageParcel &data, MessageParcel &reply) +{ + std::shared_ptr globalConfiguration(data.ReadParcelable()); + if (globalConfiguration == nullptr) { + HILOG_ERROR("AbilitySchedulerStub globalConfiguration is nullptr"); + return ERR_INVALID_VALUE; + } + ScheduleUpdateConfiguration(*globalConfiguration); + return NO_ERROR; +} + +int AbilitySchedulerStub::MutiWinModeChangedInner(MessageParcel &data, MessageParcel &reply) +{ + int32_t winModeKey = data.ReadInt32(); + bool flag = data.ReadBool(); + NotifyMultiWinModeChanged(winModeKey, flag); + return NO_ERROR; +} + +int AbilitySchedulerStub::TopActiveAbilityChangedInner(MessageParcel &data, MessageParcel &reply) +{ + bool flag = data.ReadBool(); + NotifyTopActiveAbilityChanged(flag); + return NO_ERROR; +} + +int AbilitySchedulerStub::ExecuteBatchInner(MessageParcel &data, MessageParcel &reply) +{ + HILOG_INFO("AbilitySchedulerStub::ExecuteBatchInner start"); + int count = 0; + if (!data.ReadInt32(count)) { + HILOG_ERROR("AbilitySchedulerStub::ExecuteBatchInner fail to ReadInt32 count"); + return ERR_INVALID_VALUE; + } + HILOG_INFO("AbilitySchedulerStub::ExecuteBatchInner count:%{public}d", count); + std::vector> operations; + for (int i = 0; i < count; i++) { + AppExecFwk::DataAbilityOperation *operation = data.ReadParcelable(); + if (operation == nullptr) { + HILOG_ERROR("AbilitySchedulerStub::ExecuteBatchInner operation is nullptr, index = %{public}d", i); + return ERR_INVALID_VALUE; + } + std::shared_ptr dataAbilityOperation(operation); + operations.push_back(dataAbilityOperation); + } + + std::vector> results = ExecuteBatch(operations); + int total = results.size(); + if (!reply.WriteInt32(total)) { + HILOG_ERROR("AbilitySchedulerStub::ExecuteBatchInner fail to WriteInt32 ret"); + return ERR_INVALID_VALUE; + } + HILOG_INFO("AbilitySchedulerStub::ExecuteBatchInner total:%{public}d", total); + for (int i = 0; i < total; i++) { + if (results[i] == nullptr) { + HILOG_ERROR("AbilitySchedulerStub::ExecuteBatchInner results[i] is nullptr, index = %{public}d", i); + return ERR_INVALID_VALUE; + } + if (!reply.WriteParcelable(results[i].get())) { + HILOG_ERROR( + "AbilitySchedulerStub::ExecuteBatchInner fail to WriteParcelable operation, index = %{public}d", i); + return ERR_INVALID_VALUE; + } + } + HILOG_INFO("AbilitySchedulerStub::ExecuteBatchInner end"); + return NO_ERROR; +} + +void AbilitySchedulerRecipient::OnRemoteDied(const wptr &remote) +{ + HILOG_ERROR("recv AbilitySchedulerRecipient death notice"); + + if (handler_) { + handler_(remote); + } +} + +AbilitySchedulerRecipient::AbilitySchedulerRecipient(RemoteDiedHandler handler) : handler_(handler) +{} + +AbilitySchedulerRecipient::~AbilitySchedulerRecipient() +{} + +} // namespace AAFwk +} // namespace OHOS diff --git a/tools/services/abilitymgr/src/ability_stack_manager.cpp b/tools/services/abilitymgr/src/ability_stack_manager.cpp new file mode 100644 index 00000000000..2653933312a --- /dev/null +++ b/tools/services/abilitymgr/src/ability_stack_manager.cpp @@ -0,0 +1,3454 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ability_stack_manager.h" + +#include +#include + +#include "hilog_wrapper.h" +#include "ability_util.h" +#include "ability_manager_errors.h" +#include "ability_manager_service.h" +#include "app_scheduler.h" +#include "common_event.h" +#include "common_event_manager.h" + +namespace OHOS { +namespace AAFwk { +AbilityStackManager::AbilityStackManager(int userId) : userId_(userId) +{} + +void AbilityStackManager::Init() +{ + launcherMissionStack_ = std::make_shared(LAUNCHER_MISSION_STACK_ID, userId_); + missionStackList_.push_back(launcherMissionStack_); + defaultMissionStack_ = std::make_shared(DEFAULT_MISSION_STACK_ID, userId_); + missionStackList_.push_back(defaultMissionStack_); + currentMissionStack_ = launcherMissionStack_; + + resumeMissionContainer_ = std::make_shared( + DelayedSingleton::GetInstance()->GetEventHandler()); +} + +AbilityStackManager::~AbilityStackManager() +{} + +int AbilityStackManager::StartAbility(const AbilityRequest &abilityRequest) +{ + HILOG_DEBUG("Start ability."); + std::lock_guard guard(stackLock_); + + auto currentTopAbilityRecord = GetCurrentTopAbility(); + if (!CanStartInLockMissionState(abilityRequest, currentTopAbilityRecord)) { + SendUnlockMissionMessage(); + return LOCK_MISSION_STATE_DENY_REQUEST; + } + + auto abilityInfo = abilityRequest.abilityInfo; + auto type = abilityInfo.type; + if (abilityInfo.applicationInfo.isLauncherApp && type == AppExecFwk::AbilityType::PAGE && currentTopAbilityRecord && + AbilityUtil::IsSystemDialogAbility( + currentTopAbilityRecord->GetAbilityInfo().bundleName, currentTopAbilityRecord->GetAbilityInfo().name)) { + HILOG_ERROR("Page ability is dialog type, cannot return to luncher."); + return ERR_INVALID_VALUE; + } + + if (!waittingAbilityQueue_.empty()) { + HILOG_INFO("Waiting queue is not empty, so enqueue ability for waiting."); + EnqueueWaittingAbility(abilityRequest); + return START_ABILITY_WAITING; + } + + if (currentTopAbilityRecord != nullptr) { + std::string element = currentTopAbilityRecord->GetWant().GetElement().GetURI(); + HILOG_DEBUG("current top: %{public}s", element.c_str()); + if (currentTopAbilityRecord->GetAbilityState() != ACTIVE) { + HILOG_INFO("Top ability is not active, so enqueue ability for waiting."); + EnqueueWaittingAbility(abilityRequest); + return START_ABILITY_WAITING; + } + } + + // need to start ability as special + if (abilityRequest.startSetting && !abilityRequest.abilityInfo.applicationInfo.isLauncherApp) { + auto windowkey = static_cast( + std::atoi(abilityRequest.startSetting->GetProperty(AbilityStartSetting::WINDOW_MODE_KEY).c_str())); + HILOG_DEBUG("Start ability with settings ..."); + if (windowkey == AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_FLOATING || + windowkey == AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_PRIMARY) { + return StartAbilityAsSpecialLocked(currentTopAbilityRecord, abilityRequest); + } + } + + return StartAbilityLocked(currentTopAbilityRecord, abilityRequest); +} + +int AbilityStackManager::StartAbilityLocked( + const std::shared_ptr ¤tTopAbility, const AbilityRequest &abilityRequest) +{ + HILOG_DEBUG("Start ability locked."); + CHECK_POINTER_AND_RETURN(currentMissionStack_, INNER_ERR); + // 1. choose target mission stack + std::shared_ptr targetStack = GetTargetMissionStack(abilityRequest); + CHECK_POINTER_AND_RETURN(targetStack, CREATE_MISSION_STACK_FAILED); + auto lastTopAbility = targetStack->GetTopAbilityRecord(); + + // 2. move target mission stack to top, currentMissionStack will be changed. + MoveMissionStackToTop(targetStack); + + // 3. get mission record and ability recode + std::shared_ptr targetAbilityRecord; + std::shared_ptr targetMissionRecord; + GetMissionRecordAndAbilityRecord(abilityRequest, currentTopAbility, targetAbilityRecord, targetMissionRecord); + if (targetAbilityRecord == nullptr || targetMissionRecord == nullptr) { + HILOG_ERROR("Failed to get ability record or mission record."); + MoveMissionStackToTop(lastMissionStack_); + return ERR_INVALID_VALUE; + } + targetAbilityRecord->AddCallerRecord(abilityRequest.callerToken, abilityRequest.requestCode); + MoveMissionAndAbility(currentTopAbility, targetAbilityRecord, targetMissionRecord); + + // 4. start processing ability lifecycle + if (currentTopAbility == nullptr) { + // top ability is null, then launch the first Ability. + targetAbilityRecord->SetLauncherRoot(); + return targetAbilityRecord->LoadAbility(); + } else { + // complete ability background if needed. + return StartAbilityLifeCycle(lastTopAbility, currentTopAbility, targetAbilityRecord); + } +} + +int AbilityStackManager::StartAbilityLifeCycle(std::shared_ptr lastTopAbility, + std::shared_ptr currentTopAbility, std::shared_ptr targetAbility) +{ + CHECK_POINTER_AND_RETURN(targetAbility, ERR_INVALID_VALUE); + CHECK_POINTER_AND_RETURN(currentTopAbility, ERR_INVALID_VALUE); + enum ChangeType { T_ACTIVE, T_CHANGE, T_DEFAULT } changeType; + + bool isMissionChanged = currentTopAbility->GetMissionRecordId() != targetAbility->GetMissionRecordId(); + bool isStackChanged = currentTopAbility->GetMissionStackId() != targetAbility->GetMissionStackId(); + bool isCurrentFull = IsFullScreenStack(currentTopAbility->GetMissionStackId()); + bool isTargetFull = IsFullScreenStack(targetAbility->GetMissionStackId()); + + std::shared_ptr needBackgroundAbility; + + // set target changeType + if (isMissionChanged) { + if (isStackChanged) { + if (isCurrentFull && isTargetFull) { + changeType = T_DEFAULT; + } else if (!isCurrentFull && isTargetFull) { + auto needAbility = (targetAbility->GetMissionStackId() == DEFAULT_MISSION_STACK_ID) + ? launcherMissionStack_->GetTopAbilityRecord() + : defaultMissionStack_->GetTopAbilityRecord(); + changeType = T_CHANGE; + needBackgroundAbility = + (needAbility && needAbility->IsAbilityState(AbilityState::ACTIVE)) ? needAbility : lastTopAbility; + } else { + auto self(shared_from_this()); + auto IsChanged = [&lastTopAbility, &targetAbility, self]() { + bool isSameMission = lastTopAbility->GetMissionRecordId() == targetAbility->GetMissionRecordId(); + bool isSyncVisual = self->SupportSyncVisualByStackId(targetAbility->GetMissionStackId()); + return (isSameMission || (!isSameMission && !isSyncVisual)) && + lastTopAbility->IsAbilityState(AbilityState::ACTIVE) + ? T_CHANGE + : T_ACTIVE; + }; + changeType = lastTopAbility ? IsChanged() : T_ACTIVE; + needBackgroundAbility = (changeType == T_CHANGE) ? lastTopAbility : nullptr; + } + } else { + if (SupportSyncVisualByStackId(targetAbility->GetMissionStackId())) { + auto targetMission = targetAbility->GetMissionRecord(); + auto secondAbility = targetMission ? targetMission->GetLastTopAbility() : nullptr; + if (secondAbility && secondAbility->IsAbilityState(AbilityState::ACTIVE)) { + needBackgroundAbility = secondAbility; + changeType = T_CHANGE; + } else { + changeType = T_ACTIVE; + } + } else { + changeType = T_DEFAULT; + } + } + } else { + changeType = T_DEFAULT; + } + + needBackgroundAbility = (changeType == T_DEFAULT) ? currentTopAbility : needBackgroundAbility; + + changeType = needBackgroundAbility ? changeType : T_ACTIVE; + + HILOG_DEBUG("ChangeType: %{public}d, needBackAbility : %{public}s", + changeType, + needBackgroundAbility ? needBackgroundAbility->GetAbilityInfo().name.c_str() : "none"); + + // deal ability lifecycle. + switch (changeType) { + // 1. last top ability don't need inactive , target ability active directly. + case T_ACTIVE: { + targetAbility->ProcessActivate(); + break; + } + // 2. change inactive ability, add pre and next flag. + case T_CHANGE: { + targetAbility->SetPreAbilityRecord(needBackgroundAbility); + needBackgroundAbility->SetNextAbilityRecord(targetAbility); + needBackgroundAbility->Inactivate(); + break; + } + // 3. usually, last top ability need inactive, target ability need active. + case T_DEFAULT: + default: { + needBackgroundAbility->Inactivate(); + break; + } + } + return ERR_OK; +} + +int AbilityStackManager::StartAbilityAsSpecialLocked( + const std::shared_ptr ¤tTopAbility, const AbilityRequest &abilityRequest) +{ + HILOG_DEBUG("Start ability as special locked."); + CHECK_POINTER_AND_RETURN(currentTopAbility, INNER_ERR); + CHECK_RET_RETURN_RET( + CheckMultiWindowCondition(currentTopAbility, abilityRequest), "Check multiwindow condition is failed."); + + // 1. choose target mission stack + auto targetStack = GetTargetMissionStack(abilityRequest); + CHECK_POINTER_AND_RETURN(targetStack, CREATE_MISSION_STACK_FAILED); + auto lastTopAbility = targetStack->GetTopAbilityRecord(); + + // 2. get mission record and ability recode + std::shared_ptr targetAbilityRecord; + std::shared_ptr targetMissionRecord; + GetMissionRecordAndAbilityRecord(abilityRequest, currentTopAbility, targetAbilityRecord, targetMissionRecord); + if (targetAbilityRecord == nullptr || targetMissionRecord == nullptr) { + HILOG_ERROR("Failed to get ability record or mission record."); + return ERR_INVALID_VALUE; + } + targetAbilityRecord->AddCallerRecord(abilityRequest.callerToken, abilityRequest.requestCode); + + MissionOption option; + option.userId = userId_; + option.missionId = targetMissionRecord->GetMissionRecordId(); + option.winModeKey = static_cast( + std::atoi(abilityRequest.startSetting->GetProperty(AbilityStartSetting::WINDOW_MODE_KEY).c_str())); + targetMissionRecord->SetMissionOption(option); + + // 3. first create mission record or stack is not changed, + // just load target ability and inactive the current top ability. + if (targetMissionRecord->GetMissionStack() == nullptr || + targetMissionRecord->GetMissionStack()->GetMissionStackId() == targetStack->GetMissionStackId()) { + MoveMissionStackToTop(targetStack); + MoveMissionAndAbility(currentTopAbility, targetAbilityRecord, targetMissionRecord); + HILOG_DEBUG("First create mission record ,missionId:%{public}d", targetMissionRecord->GetMissionRecordId()); + return StartAbilityLifeCycle(lastTopAbility, currentTopAbility, targetAbilityRecord); + } + + // 4. mission stack is changed, move mission to target stack. + isMultiWinMoving_ = true; + CompleteMoveMissionToStack(targetMissionRecord, targetStack); + MoveMissionAndAbility(currentTopAbility, targetAbilityRecord, targetMissionRecord); + HILOG_DEBUG("Mission stack is changed, move mission to target stack ,missionId:%{public}d", + targetMissionRecord->GetMissionRecordId()); + CHECK_RET_RETURN_RET(DispatchLifecycle(currentTopAbility, targetAbilityRecord, false), "Dispatch lifecycle error."); + // Judging target system window mode, and notify event. + auto willWinMode = JudgingTargetSystemWindowMode(option.winModeKey); + auto targetWinMode = GetTargetSystemWindowMode(willWinMode); + NotifyWindowModeChanged(targetWinMode); + return ERR_OK; +} + +void AbilityStackManager::MoveMissionAndAbility(const std::shared_ptr ¤tTopAbility, + std::shared_ptr &targetAbilityRecord, std::shared_ptr &targetMissionRecord) +{ + HILOG_INFO("Move mission and ability."); + CHECK_POINTER(targetAbilityRecord); + CHECK_POINTER(targetMissionRecord); + + // set relationship of mission record and ability record + if (currentTopAbility != nullptr) { + targetAbilityRecord->SetPreAbilityRecord(currentTopAbility); + currentTopAbility->SetNextAbilityRecord(targetAbilityRecord); + // move mission to end, don't set pre mission + auto targetPreMission = targetMissionRecord->GetPreMissionRecord(); + if (targetPreMission) { + currentTopAbility->GetMissionRecord()->SetPreMissionRecord(targetPreMission); + } + targetMissionRecord->SetPreMissionRecord(currentTopAbility->GetMissionRecord()); + if (currentTopAbility->IsLauncherAbility()) { + targetMissionRecord->SetIsLauncherCreate(); + } + } + // check mission window mode. + if (targetAbilityRecord->GetMissionRecord() == nullptr) { + auto option = targetMissionRecord->GetMissionOption(); + if (option.winModeKey == AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_FLOATING || + option.winModeKey == AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_PRIMARY || + option.winModeKey == AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_SECONDARY) { + auto setting = AbilityStartSetting::GetEmptySetting(); + setting->AddProperty(AbilityStartSetting::WINDOW_MODE_KEY, std::to_string(option.winModeKey)); + targetAbilityRecord->SetStartSetting(setting); + } + } + + // add caller record + targetAbilityRecord->SetMissionRecord(targetMissionRecord); + // add ability record to mission record. + // if this ability record exist this mission record, do not add. + targetMissionRecord->AddAbilityRecordToTop(targetAbilityRecord); + // reparent mission record, currentMissionStack is the target mission stack. + targetMissionRecord->SetMissionStack(currentMissionStack_, currentMissionStack_->GetMissionStackId()); + // add mission record to mission stack. + // if this mission record exist this mission stack, do not add. + currentMissionStack_->AddMissionRecordToTop(targetMissionRecord); + // move mission record to top + // if this mission exist at top, do not move. + currentMissionStack_->MoveMissionRecordToTop(targetMissionRecord); +} + +int AbilityStackManager::TerminateAbility(const sptr &token, int resultCode, const Want *resultWant) +{ + HILOG_INFO("Terminate ability."); + std::lock_guard guard(stackLock_); + auto abilityRecord = Token::GetAbilityRecordByToken(token); + CHECK_POINTER_AND_RETURN(abilityRecord, ERR_INVALID_VALUE); + // if ability was already in terminate list, don't do anything but wait. + CHECK_TRUE_RETURN_RET(abilityRecord->IsTerminating(), ERR_OK, "Ability is on terminating."); + // check if ability is in stack to avoid user create fake token. + CHECK_POINTER_AND_RETURN_LOG( + GetAbilityRecordByToken(token), INNER_ERR, "Ability is not in stack, nor in terminating list."); + + auto missionRecord = abilityRecord->GetMissionRecord(); + CHECK_POINTER_AND_RETURN(missionRecord, INNER_ERR); + if (abilityRecord->IsLauncherAbility() && abilityRecord->IsLauncherRoot()) { + HILOG_WARN("Don't allow terminate root launcher"); + return TERMINATE_LAUNCHER_DENIED; + } + + if (!CanStopInLockMissionState(abilityRecord)) { + SendUnlockMissionMessage(); + return LOCK_MISSION_STATE_DENY_REQUEST; + } + + // if ability is in multiwindow stack, and is bottom ability of this mission, + // just background, don't schedule terminate + if (!IsFullScreenStack(abilityRecord->GetMissionStackId()) && + missionRecord->GetBottomAbilityRecord() == abilityRecord) { + HILOG_INFO("Mulitwindow stack , bottom ability of mission .just background, don't schedule terminate."); + return MoveMissionToEndLocked(missionRecord->GetMissionRecordId()); + } + + HILOG_INFO("Schedule normal terminate process."); + abilityRecord->SetTerminatingState(); + return TerminateAbilityLocked(abilityRecord, resultCode, resultWant); +} + +int AbilityStackManager::TerminateAbility(const std::shared_ptr &caller, int requestCode) +{ + HILOG_INFO("Terminate ability."); + std::lock_guard guard(stackLock_); + + std::shared_ptr targetAbility = nullptr; + int result = static_cast(ABILITY_VISIBLE_FALSE_DENY_REQUEST); + for (auto &stack : missionStackList_) { + targetAbility = stack->GetAbilityRecordByCaller(caller, requestCode); + if (targetAbility) { + result = AbilityUtil::JudgeAbilityVisibleControl(targetAbility->GetAbilityInfo()); + break; + } + } + + if (!targetAbility) { + HILOG_ERROR("%{public}s, Can't find target ability", __func__); + return NO_FOUND_ABILITY_BY_CALLER; + } + if (result != ERR_OK) { + HILOG_ERROR("%{public}s JudgeAbilityVisibleControl error.", __func__); + return result; + } + + if (!CanStopInLockMissionState(targetAbility)) { + SendUnlockMissionMessage(); + return LOCK_MISSION_STATE_DENY_REQUEST; + } + + return TerminateAbility(targetAbility->GetToken(), DEFAULT_INVAL_VALUE, nullptr); +} + +int AbilityStackManager::TerminateAbilityLocked( + const std::shared_ptr &abilityRecord, int resultCode, const Want *resultWant) +{ + HILOG_INFO("%{public}s, called", __func__); + if (abilityRecord == nullptr) { + HILOG_ERROR("abilityRecord is invalid"); + return ERR_INVALID_VALUE; + } + + if (abilityRecord->IsRestarting()) { + HILOG_ERROR("abilityRecord is restarting, deny terminate."); + return ERR_INVALID_VALUE; + } + // save result to caller AbilityRecord + if (resultWant != nullptr) { + abilityRecord->SaveResultToCallers(resultCode, resultWant); + } + // common case, ability terminate at active and at top position + if (abilityRecord->IsAbilityState(AbilityState::ACTIVE) || + abilityRecord->IsAbilityState(AbilityState::ACTIVATING) || + abilityRecord->IsAbilityState(AbilityState::INITIAL)) { + RemoveTerminatingAbility(abilityRecord); + abilityRecord->Inactivate(); + return ERR_OK; + } + // it's not common case when ability terminate at non-active state and non-top position. + if (abilityRecord->IsAbilityState(AbilityState::INACTIVE)) { + // ability on inactive, remove AbilityRecord out of stack and then schedule to background. + RemoveTerminatingAbility(abilityRecord); + abilityRecord->SendResultToCallers(); + MoveToBackgroundTask(abilityRecord); + } else if (abilityRecord->IsAbilityState(AbilityState::BACKGROUND)) { + // ability on background, remove AbilityRecord out of stack and then schedule to terminate. + RemoveTerminatingAbility(abilityRecord); + abilityRecord->SendResultToCallers(); + auto self(shared_from_this()); + auto task = [abilityRecord, self]() { + HILOG_WARN("Disconnect ability terminate timeout."); + self->CompleteTerminate(abilityRecord); + }; + abilityRecord->Terminate(task); + } else if (abilityRecord->IsAbilityState(AbilityState::INACTIVATING) || + abilityRecord->IsAbilityState(AbilityState::MOVING_BACKGROUND)) { + // ability on inactivating or moving to background. + // remove AbilityRecord out of stack and waiting for ability(kit) AbilityTransitionDone. + RemoveTerminatingAbility(abilityRecord); + abilityRecord->SendResultToCallers(); + } else { + HILOG_WARN("Ability state is invalid."); + } + return ERR_OK; +} + +int AbilityStackManager::RemoveMissionById(int missionId) +{ + std::lock_guard guard(stackLock_); + if (missionId < 0) { + HILOG_ERROR("Mission id is invalid."); + return ERR_INVALID_VALUE; + } + if (lockMissionContainer_ && lockMissionContainer_->IsLockedMissionState()) { + HILOG_ERROR("current is lock mission state, refusing to operate other mission."); + return ERR_INVALID_VALUE; + } + return RemoveMissionByIdLocked(missionId); +} + +int AbilityStackManager::RemoveMissionByIdLocked(int missionId) +{ + CHECK_POINTER_AND_RETURN_LOG(defaultMissionStack_, ERR_NO_INIT, "defaultMissionStack_ is invalid."); + + auto missionRecord = GetMissionRecordFromAllStacks(missionId); + CHECK_POINTER_AND_RETURN_LOG(missionRecord, REMOVE_MISSION_ID_NOT_EXIST, "Mission id is invalid."); + CHECK_TRUE_RETURN_RET(IsLauncherMission(missionId), + REMOVE_MISSION_LAUNCHER_DENIED, + "Don't allow to terminate mission which has launcher ability."); + + auto currentStack = missionRecord->GetMissionStack(); + CHECK_POINTER_AND_RETURN_LOG(currentStack, REMOVE_MISSION_FAILED, "Current stack is nullptr."); + + auto topAbility = missionRecord->GetTopAbilityRecord(); + CHECK_POINTER_AND_RETURN(topAbility, REMOVE_MISSION_FAILED); + + std::shared_ptr activeAbility; + if (topAbility->IsAbilityState(ACTIVE) || topAbility->IsAbilityState(ACTIVATING)) { + activeAbility = topAbility; + } + + std::vector abilityInfos; + missionRecord->GetAllAbilityInfo(abilityInfos); + for (auto &ability : abilityInfos) { + auto abilityRecord = missionRecord->GetAbilityRecordById(ability.id); + if (abilityRecord == nullptr || abilityRecord->IsTerminating()) { + HILOG_WARN("Ability record is not exist or is on terminating."); + continue; + } + + if (abilityRecord == activeAbility) { + continue; + } + + if (abilityRecord->IsAbilityState(AbilityState::INITIAL)) { + HILOG_INFO("Ability record state is INITIAL, remove ability, continue."); + missionRecord->RemoveAbilityRecord(abilityRecord); + if (missionRecord->IsEmpty()) { + RemoveMissionRecordById(missionRecord->GetMissionRecordId()); + JudgingIsRemoveMultiScreenStack(currentStack); + } + continue; + } + + abilityRecord->SetTerminatingState(); + auto ret = TerminateAbilityLocked(abilityRecord, DEFAULT_INVAL_VALUE, nullptr); + if (ret != ERR_OK) { + HILOG_ERROR("Remove mission error: %{public}d.", ret); + return REMOVE_MISSION_FAILED; + } + } + + if (activeAbility) { + activeAbility->SetTerminatingState(); + auto ret = TerminateAbilityLocked(activeAbility, DEFAULT_INVAL_VALUE, nullptr); + if (ret != ERR_OK) { + HILOG_ERROR("Remove mission error: %{public}d.", ret); + return REMOVE_MISSION_FAILED; + } + } + + return ERR_OK; +} + +int AbilityStackManager::RemoveStack(int stackId) +{ + HILOG_DEBUG("stackId : %{public}d", stackId); + std::lock_guard guard(stackLock_); + if (stackId > MAX_MISSION_STACK_ID || stackId < MIN_MISSION_STACK_ID) { + HILOG_ERROR("stackId:%{public}d is invalid.", stackId); + return ERR_INVALID_VALUE; + } + + if (lockMissionContainer_ && lockMissionContainer_->IsLockedMissionState()) { + HILOG_ERROR("current is lock mission state, refusing to operate other mission."); + return ERR_INVALID_VALUE; + } + + return RemoveStackLocked(stackId); +} + +int AbilityStackManager::RemoveStackLocked(int stackId) +{ + HILOG_DEBUG("stackId : %{public}d", stackId); + CHECK_TRUE_RETURN_RET(missionStackList_.empty(), MISSION_STACK_LIST_IS_EMPTY, "Mission stack list is empty."); + + // don't allow remove launcher mission stack. + CHECK_TRUE_RETURN_RET(stackId == LAUNCHER_MISSION_STACK_ID, + REMOVE_STACK_LAUNCHER_DENIED, + "Don't allow remove launcher mission stack."); + + auto isExist = [stackId]( + const std::shared_ptr &stack) { return stackId == stack->GetMissionStackId(); }; + auto iter = std::find_if(missionStackList_.begin(), missionStackList_.end(), isExist); + CHECK_TRUE_RETURN_RET(iter == missionStackList_.end(), REMOVE_STACK_ID_NOT_EXIST, "Remove stack id is not exist."); + // remove mission record from mission stack. + if (*iter != nullptr) { + std::vector missionInfos; + (*iter)->GetAllMissionInfo(missionInfos); + for (auto &mission : missionInfos) { + int result = RemoveMissionByIdLocked(mission.id); + if (result != ERR_OK) { + HILOG_ERROR("Remove mission failed, mission id : %{public}d", mission.id); + return result; + } + } + } + + return ERR_OK; +} + +void AbilityStackManager::SetMissionStackSetting(const StackSetting &stackSetting) +{ + HILOG_DEBUG("Set mission stack setting, stackId : %{public}d", stackSetting.stackId); + std::lock_guard guard(stackLock_); + if (lockMissionContainer_ && lockMissionContainer_->IsLockedMissionState()) { + HILOG_ERROR("current is lock mission state, refusing to operate other mission."); + return; + } + auto isExist = [stackId = stackSetting.stackId](const StackSetting &it) { return stackId == it.stackId; }; + auto iter = std::find_if(stackSettings_.begin(), stackSettings_.end(), isExist); + if (iter != stackSettings_.end()) { + stackSettings_.erase(iter); + } + StackSetting settings = stackSetting; + stackSettings_.emplace_back(settings); +} + +/** + * remove AbilityRecord from stack to terminate list. + * update MissionStack to prepare next top ability. + */ +void AbilityStackManager::RemoveTerminatingAbility(const std::shared_ptr &abilityRecord) +{ + CHECK_POINTER(abilityRecord); + auto missionRecord = abilityRecord->GetMissionRecord(); + CHECK_POINTER(missionRecord); + auto currentStack = missionRecord->GetMissionStack(); + CHECK_POINTER(currentStack); + + auto isActive = (abilityRecord->IsAbilityState(AbilityState::ACTIVE) || + abilityRecord->IsAbilityState(AbilityState::ACTIVATING) || + abilityRecord->IsAbilityState(AbilityState::INITIAL)); + + missionRecord->RemoveAbilityRecord(abilityRecord); + terminateAbilityRecordList_.push_back(abilityRecord); + + std::shared_ptr needTopAbility; + + if (!missionRecord->IsEmpty()) { + needTopAbility = missionRecord->GetTopAbilityRecord(); + CHECK_POINTER(needTopAbility); + abilityRecord->SetNextAbilityRecord(needTopAbility); + return; + } + + if (!isActive) { + RemoveMissionRecordById(missionRecord->GetMissionRecordId()); + JudgingIsRemoveMultiScreenStack(currentStack); + return; + } + + if (currentStack->IsEqualStackId(FLOATING_MISSION_STACK_ID)) { + RemoveMissionRecordById(missionRecord->GetMissionRecordId()); + JudgingIsRemoveMultiScreenStack(currentStack); + MoveMissionStackToTop(GetTopFullScreenStack()); + needTopAbility = GetCurrentTopAbility(); + abilityRecord->SetNextAbilityRecord(needTopAbility); + return; + } + + if (IsFullScreenStack(currentStack->GetMissionStackId())) { + auto isExist = (!missionRecord->IsLauncherCreate() && missionRecord->GetPreMissionRecord() != nullptr && + launcherMissionStack_->IsExistMissionRecord( + missionRecord->GetPreMissionRecord()->GetMissionRecordId())); + if ((missionRecord->IsLauncherCreate()) || (missionRecord == missionStackList_.back()->GetTopMissionRecord()) || + isExist || (missionRecord == missionStackList_.front()->GetBottomMissionRecord())) { + RemoveMissionRecordById(missionRecord->GetMissionRecordId()); + MoveMissionStackToTop(launcherMissionStack_); + } else { + RemoveMissionRecordById(missionRecord->GetMissionRecordId()); + } + auto fullScreenStack = GetTopFullScreenStack(); + CHECK_POINTER(fullScreenStack); + needTopAbility = fullScreenStack->GetTopAbilityRecord(); + CHECK_POINTER(needTopAbility); + abilityRecord->SetNextAbilityRecord(needTopAbility); + } +} + +int AbilityStackManager::GetAbilityStackManagerUserId() const +{ + return userId_; +} + +std::shared_ptr AbilityStackManager::GetCurrentTopAbility() const +{ + std::shared_ptr topMissionStack = missionStackList_.front(); + HILOG_DEBUG("Top mission stack id is %{public}d", topMissionStack->GetMissionStackId()); + return topMissionStack->GetTopAbilityRecord(); +} + +sptr AbilityStackManager::GetCurrentTopAbilityToken() +{ + std::lock_guard guard(stackLock_); + sptr token = nullptr; + std::shared_ptr topMissionStack = missionStackList_.front(); + std::shared_ptr abilityRecord = topMissionStack->GetTopAbilityRecord(); + if (abilityRecord != nullptr) { + token = abilityRecord->GetToken(); + } + return token; +} + +std::shared_ptr AbilityStackManager::GetAbilityRecordById(const int64_t recordId) +{ + std::lock_guard guard(stackLock_); + for (auto missionStack : missionStackList_) { + std::shared_ptr abilityRecord = missionStack->GetAbilityRecordById(recordId); + if (abilityRecord != nullptr) { + return abilityRecord; + } + } + return nullptr; +} + +std::shared_ptr AbilityStackManager::GetStackById(int stackId) +{ + std::lock_guard guard(stackLock_); + for (auto missionStack : missionStackList_) { + if (missionStack->GetMissionStackId() == stackId) { + return missionStack; + } + } + return nullptr; +} + +std::shared_ptr AbilityStackManager::GetTopMissionRecord() const +{ + if (currentMissionStack_ == nullptr) { + HILOG_ERROR("currentMissionStack_ is nullptr."); + return nullptr; + } + return currentMissionStack_->GetTopMissionRecord(); +} + +std::shared_ptr AbilityStackManager::GetMissionRecordById(int id) const +{ + if (currentMissionStack_ == nullptr) { + HILOG_ERROR("currentMissionStack_ is nullptr."); + return nullptr; + } + return currentMissionStack_->GetMissionRecordById(id); +} + +std::shared_ptr AbilityStackManager::GetMissionRecordFromAllStacks(int id) const +{ + for (auto missionStack : missionStackList_) { + std::shared_ptr missionRecord = missionStack->GetMissionRecordById(id); + if (missionRecord != nullptr) { + return missionRecord; + } + } + return nullptr; +} + +std::shared_ptr AbilityStackManager::GetMissionRecordByName(std::string name) const +{ + for (auto missionStack : missionStackList_) { + std::shared_ptr missionRecord = missionStack->GetTargetMissionRecord(name); + if (missionRecord != nullptr) { + return missionRecord; + } + } + return nullptr; +} + +std::shared_ptr AbilityStackManager::GetAbilityRecordByToken(const sptr &token) +{ + std::lock_guard guard(stackLock_); + for (auto missionStack : missionStackList_) { + std::shared_ptr abilityRecord = missionStack->GetAbilityRecordByToken(token); + if (abilityRecord != nullptr) { + return abilityRecord; + } + } + return nullptr; +} + +std::shared_ptr AbilityStackManager::GetAbilityFromTerminateList(const sptr &token) +{ + std::lock_guard guard(stackLock_); + for (auto abilityRecord : terminateAbilityRecordList_) { + // token is type of IRemoteObject, abilityRecord->GetToken() is type of Token extending from IRemoteObject. + if (abilityRecord && token == abilityRecord->GetToken()->AsObject()) { + return abilityRecord; + } + } + return nullptr; +} + +bool AbilityStackManager::RemoveMissionRecordById(int id) +{ + for (auto missionstack : missionStackList_) { + if (missionstack->RemoveMissionRecord(id)) { + return true; + } + } + return false; +} + +void AbilityStackManager::MoveMissionStackToTop(const std::shared_ptr &stack) +{ + if (stack == nullptr) { + HILOG_ERROR("Stack is nullptr."); + return; + } + if (missionStackList_.front() == stack) { + HILOG_DEBUG("Stack is at the top of list, mission id: %d", stack->GetMissionStackId()); + return; + } + lastMissionStack_ = currentMissionStack_; + missionStackList_.remove(stack); + missionStackList_.push_front(stack); + currentMissionStack_ = stack; +} + +std::shared_ptr AbilityStackManager::GetTargetMissionStack(const AbilityRequest &abilityRequest) +{ + // priority : starting launcher ability . + if (abilityRequest.abilityInfo.applicationInfo.isLauncherApp) { + return launcherMissionStack_; + } + + // next: start ability for settings(multiwindow) + if (abilityRequest.startSetting != nullptr) { + return GetTargetMissionStackBySetting(abilityRequest); + } + + // other: refer to the stack of the caller ability. + return GetTargetMissionStackByDefault(abilityRequest); +} + +std::shared_ptr AbilityStackManager::GetTargetMissionStackByDefault(const AbilityRequest &abilityRequest) +{ + bool isSingleton = abilityRequest.abilityInfo.launchMode == AppExecFwk::LaunchMode::SINGLETON; + std::shared_ptr requestMission = nullptr; + if (isSingleton) { + std::string bundleName = AbilityUtil::ConvertBundleNameSingleton( + abilityRequest.abilityInfo.bundleName, abilityRequest.abilityInfo.name); + requestMission = GetMissionRecordByName(bundleName); + } else { + requestMission = GetMissionRecordByName(abilityRequest.abilityInfo.bundleName); + } + + bool isExist = requestMission != nullptr; + auto currentTop = GetCurrentTopAbility(); + if (currentTop) { + // caller is launcher , request is not launcher, exist ability just restart. + if (isExist && (currentTop->IsLauncherAbility() || (!currentTop->IsLauncherAbility() && isSingleton) || + (!currentTop->IsLauncherAbility() && + currentTop->GetAbilityInfo().launchMode == AppExecFwk::LaunchMode::SINGLETON))) { + return requestMission->GetMissionStack(); + } + // caller and request is not launcher, start ability at current mission stack. + if (!currentTop->IsLauncherAbility() && !isSingleton && + currentTop->GetAbilityInfo().launchMode != AppExecFwk::LaunchMode::SINGLETON) { + auto callerParent = currentTop->GetMissionRecord(); + return callerParent->GetMissionStack(); + } + } + + return defaultMissionStack_; +} + +std::shared_ptr AbilityStackManager::GetTargetMissionStackBySetting(const AbilityRequest &abilityRequest) +{ + if (abilityRequest.startSetting != nullptr) { + AbilityWindowConfiguration windowMode = static_cast( + std::atoi(abilityRequest.startSetting->GetProperty(AbilityStartSetting::WINDOW_MODE_KEY).c_str())); + switch (windowMode) { + case AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_FLOATING: + return GetOrCreateMissionStack(FLOATING_MISSION_STACK_ID, true); + case AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_PRIMARY: + return GetOrCreateMissionStack(SPLIT_SCREEN_MISSION_STACK_ID, true); + default: + break; + } + } + + return defaultMissionStack_; +} + +int AbilityStackManager::AttachAbilityThread(const sptr &scheduler, const sptr &token) +{ + std::lock_guard guard(stackLock_); + auto abilityRecord = GetAbilityRecordByToken(token); + CHECK_POINTER_AND_RETURN(abilityRecord, ERR_INVALID_VALUE); + + std::string element = abilityRecord->GetWant().GetElement().GetURI(); + HILOG_DEBUG("Ability: %{public}s", element.c_str()); + + std::shared_ptr handler = + DelayedSingleton::GetInstance()->GetEventHandler(); + CHECK_POINTER_AND_RETURN_LOG(handler, ERR_INVALID_VALUE, "Fail to get AbilityEventHandler."); + handler->RemoveEvent(AbilityManagerService::LOAD_TIMEOUT_MSG, abilityRecord->GetEventId()); + + abilityRecord->SetScheduler(scheduler); + if (abilityRecord->IsRestarting()) { + abilityRecord->RestoreAbilityState(); + } + DelayedSingleton::GetInstance()->MoveToForground(token); + + return ERR_OK; +} + +int AbilityStackManager::AbilityTransitionDone(const sptr &token, int state) +{ + std::lock_guard guard(stackLock_); + auto abilityRecord = GetAbilityRecordByToken(token); + if (abilityRecord == nullptr) { + HILOG_INFO("Ability record may in terminate list."); + abilityRecord = GetAbilityFromTerminateList(token); + CHECK_POINTER_AND_RETURN(abilityRecord, ERR_INVALID_VALUE); + } + + std::string element = abilityRecord->GetWant().GetElement().GetURI(); + int targetState = AbilityRecord::ConvertLifeCycleToAbilityState(static_cast(state)); + std::string abilityState = AbilityRecord::ConvertAbilityState(static_cast(targetState)); + HILOG_INFO("ability: %{public}s, state: %{public}s", element.c_str(), abilityState.c_str()); + + return DispatchState(abilityRecord, targetState); +} + +int AbilityStackManager::DispatchState(const std::shared_ptr &abilityRecord, int state) +{ + HILOG_DEBUG("Dispatch state."); + switch (state) { + case AbilityState::ACTIVE: { + return DispatchActive(abilityRecord, state); + } + case AbilityState::INACTIVE: { + return DispatchInactive(abilityRecord, state); + } + case AbilityState::BACKGROUND: { + return DispatchBackground(abilityRecord, state); + } + case AbilityState::INITIAL: { + return DispatchTerminate(abilityRecord, state); + } + default: { + HILOG_WARN("Don't support transiting state: %d", state); + return ERR_INVALID_VALUE; + } + } +} + +int AbilityStackManager::DispatchActive(const std::shared_ptr &abilityRecord, int state) +{ + auto handler = DelayedSingleton::GetInstance()->GetEventHandler(); + CHECK_POINTER_AND_RETURN_LOG(handler, ERR_INVALID_VALUE, "Fail to get AbilityEventHandler."); + CHECK_POINTER_AND_RETURN(abilityRecord, ERR_INVALID_VALUE); + + if (!abilityRecord->IsAbilityState(AbilityState::ACTIVATING)) { + HILOG_ERROR("Ability transition life state error. expect %{public}d, actual %{public}d callback %{public}d", + AbilityState::ACTIVATING, + abilityRecord->GetAbilityState(), + state); + return ERR_INVALID_VALUE; + } + + handler->RemoveEvent(AbilityManagerService::ACTIVE_TIMEOUT_MSG, abilityRecord->GetEventId()); + auto self(shared_from_this()); + auto task = [self, abilityRecord]() { self->CompleteActive(abilityRecord); }; + handler->PostTask(task); + + return ERR_OK; +} + +int AbilityStackManager::DispatchInactive(const std::shared_ptr &abilityRecord, int state) +{ + auto handler = DelayedSingleton::GetInstance()->GetEventHandler(); + CHECK_POINTER_AND_RETURN_LOG(handler, ERR_INVALID_VALUE, "Fail to get AbilityEventHandler."); + CHECK_POINTER_AND_RETURN(abilityRecord, ERR_INVALID_VALUE); + + if (!abilityRecord->IsAbilityState(AbilityState::INACTIVATING)) { + HILOG_ERROR("Ability transition life state error. expect %{public}d, actual %{public}d callback %{public}d", + AbilityState::INACTIVATING, + abilityRecord->GetAbilityState(), + state); + return ERR_INVALID_VALUE; + } + + handler->RemoveEvent(AbilityManagerService::INACTIVE_TIMEOUT_MSG, abilityRecord->GetEventId()); + auto self(shared_from_this()); + auto task = [self, abilityRecord]() { self->CompleteInactive(abilityRecord); }; + handler->PostTask(task); + + return ERR_OK; +} + +int AbilityStackManager::DispatchBackground(const std::shared_ptr &abilityRecord, int state) +{ + auto handler = DelayedSingleton::GetInstance()->GetEventHandler(); + CHECK_POINTER_AND_RETURN_LOG(handler, ERR_INVALID_VALUE, "Fail to get AbilityEventHandler."); + CHECK_POINTER_AND_RETURN(abilityRecord, ERR_INVALID_VALUE); + + if (!abilityRecord->IsAbilityState(AbilityState::MOVING_BACKGROUND)) { + HILOG_ERROR("Ability transition life state error. expect %{public}d, actual %{public}d callback %{public}d", + AbilityState::MOVING_BACKGROUND, + abilityRecord->GetAbilityState(), + state); + return ERR_INVALID_VALUE; + } + + // remove background timeout task. + handler->RemoveTask(std::to_string(abilityRecord->GetEventId())); + auto self(shared_from_this()); + auto task = [self, abilityRecord]() { self->CompleteBackground(abilityRecord); }; + handler->PostTask(task); + + return ERR_OK; +} + +int AbilityStackManager::DispatchTerminate(const std::shared_ptr &abilityRecord, int state) +{ + auto handler = DelayedSingleton::GetInstance()->GetEventHandler(); + CHECK_POINTER_AND_RETURN_LOG(handler, ERR_INVALID_VALUE, "Fail to get AbilityEventHandler."); + CHECK_POINTER_AND_RETURN(abilityRecord, ERR_INVALID_VALUE); + + if (!abilityRecord->IsAbilityState(AbilityState::TERMINATING)) { + HILOG_ERROR("Ability transition life state error. expect %{public}d, actual %{public}d callback %{public}d", + AbilityState::TERMINATING, + abilityRecord->GetAbilityState(), + state); + return INNER_ERR; + } + + // remove terminate timeout task. + handler->RemoveTask(std::to_string(abilityRecord->GetEventId())); + auto self(shared_from_this()); + auto task = [self, abilityRecord]() { self->CompleteTerminate(abilityRecord); }; + handler->PostTask(task); + + return ERR_OK; +} + +void AbilityStackManager::AddWindowInfo(const sptr &token, int32_t windowToken) +{ + HILOG_DEBUG("Add window id."); + std::lock_guard guard(stackLock_); + // create WindowInfo and add to its AbilityRecord + auto abilityRecord = GetAbilityRecordByToken(token); + CHECK_POINTER(abilityRecord); + if (abilityRecord->GetWindowInfo()) { + HILOG_DEBUG("WindowInfo is already added. Can't add again."); + return; + } + + if (!abilityRecord->IsAbilityState(ACTIVATING)) { + HILOG_INFO("Add windowInfo at state: %{public}d.", abilityRecord->GetAbilityState()); + } + if (windowTokenToAbilityMap_[windowToken] != nullptr) { + // It shouldn't happen. Possible reasons for this case: + // 1. windowmanager generates same window token. + // 2. abilityms doesn't destroy ability in terminate process. + HILOG_ERROR("Window token has been added to other AbilityRecord. ability name: %{private}s", + abilityRecord->GetAbilityInfo().name.c_str()); + } else { + abilityRecord->AddWindowInfo(windowToken); + windowTokenToAbilityMap_[windowToken] = abilityRecord; + HILOG_INFO("Add windowInfo complete, ability:%{public}s", abilityRecord->GetAbilityInfo().name.c_str()); + } +} + +void AbilityStackManager::OnAbilityRequestDone(const sptr &token, const int32_t state) +{ + HILOG_DEBUG("Ability request app state %{public}d done.", state); + std::lock_guard guard(stackLock_); + AppAbilityState abilitState = DelayedSingleton::GetInstance()->ConvertToAppAbilityState(state); + if (abilitState == AppAbilityState::ABILITY_STATE_FOREGROUND) { + auto abilityRecord = GetAbilityRecordByToken(token); + CHECK_POINTER(abilityRecord); + std::string element = abilityRecord->GetWant().GetElement().GetURI(); + HILOG_DEBUG("ability: %{public}s", element.c_str()); + abilityRecord->Activate(); + } +} + +void AbilityStackManager::OnAppStateChanged(const AppInfo &info) +{ + std::lock_guard guard(stackLock_); + + for (auto &stack : missionStackList_) { + std::vector missions; + stack->GetAllMissionInfo(missions); + for (auto &missionInfo : missions) { + auto mission = stack->GetMissionRecordById(missionInfo.id); + if (!mission) { + HILOG_ERROR("Mission is nullptr."); + continue; + } + std::vector abilitys; + mission->GetAllAbilityInfo(abilitys); + for (auto &abilityInfo : abilitys) { + auto ability = mission->GetAbilityRecordById(abilityInfo.id); + if (!ability) { + HILOG_ERROR("Ability is nullptr."); + continue; + } + + if (ability->GetApplicationInfo().name == info.appName && + (info.processName == ability->GetAbilityInfo().process || + info.processName == ability->GetApplicationInfo().bundleName)) { + ability->SetAppState(info.state); + } + } + } + } +} + +void AbilityStackManager::CompleteActive(const std::shared_ptr &abilityRecord) +{ + std::lock_guard guard(stackLock_); + + CHECK_POINTER(abilityRecord); + std::string element = abilityRecord->GetWant().GetElement().GetURI(); + HILOG_INFO("ability: %{public}s", element.c_str()); + + abilityRecord->SetAbilityState(AbilityState::ACTIVE); + // update top active ability + UpdateFocusAbilityRecord(abilityRecord); + + // multi window moving, complete state. + if (abilityRecord->GetInMovingState()) { + // top ability active at last, finish moving. + if (abilityRecord == GetCurrentTopAbility()) { + HILOG_DEBUG("Complete multi window moving,target state is active."); + abilityRecord->SetInMovingState(false); + isMultiWinMoving_ = false; + return; + } + // background to active state. + abilityRecord->SetInMovingState(false); + ContinueLifecycle(); + return; + } + + DelayedSingleton::GetInstance()->NotifyBmsAbilityLifeStatus( + abilityRecord->GetAbilityInfo().bundleName, + abilityRecord->GetAbilityInfo().name, + AbilityUtil::UTCTimeSeconds()); +#if BINDER_IPC_32BIT + HILOG_INFO("notify bms ability life status, bundle name:%{public}s, ability name:%{public}s, time:%{public}lld", + abilityRecord->GetAbilityInfo().bundleName.c_str(), + abilityRecord->GetAbilityInfo().name.c_str(), + AbilityUtil::UTCTimeSeconds()); +#else + HILOG_INFO("notify bms ability life status, bundle name:%{public}s, ability name:%{public}s, time:%{public}ld", + abilityRecord->GetAbilityInfo().bundleName.c_str(), + abilityRecord->GetAbilityInfo().name.c_str(), + AbilityUtil::UTCTimeSeconds()); +#endif + + auto self(shared_from_this()); + auto startWaittingAbilityTask = [self]() { self->StartWaittingAbility(); }; + + auto handler = DelayedSingleton::GetInstance()->GetEventHandler(); + CHECK_POINTER_LOG(handler, "Fail to get AbilityEventHandler."); + if (abilityRecord->GetPowerState()) { + CHECK_POINTER(powerStorage_); + bool isActiveAbility = false; + auto powerActiveStorages = powerStorage_->GetPowerOffActiveRecord(); + for (auto &powerActiveStorage : powerActiveStorages) { + auto storageActiveAbility = powerActiveStorage.ability.lock(); + if (abilityRecord == storageActiveAbility) { + isActiveAbility = true; + } + } + HILOG_DEBUG("isActiveAbility value %{public}d", static_cast(isActiveAbility)); + if (isActiveAbility && abilityRecord == GetCurrentTopAbility()) { + HILOG_DEBUG("Top ability, complete active."); + abilityRecord->SetPowerState(false); + handler->PostTask(startWaittingAbilityTask, "startWaittingAbility"); + powerStorage_.reset(); + return; + } + if (isActiveAbility) { + return; + } + HILOG_DEBUG("Not top ability, need complete inactive."); + abilityRecord->ProcessInactivate(); + return; + } + + if (abilityRecord->IsToEnd()) { + abilityRecord->SetToEnd(false); + } + + /* PostTask to trigger start Ability from waiting queue */ + handler->PostTask(startWaittingAbilityTask, "startWaittingAbility"); + + auto preAbilityRecord = abilityRecord->GetPreAbilityRecord(); + // 1. preAbility must be inactive when start ability. + // move preAbility to background only if it was inactive. + if (preAbilityRecord) { + auto preStackId = preAbilityRecord->GetMissionStackId(); + auto currentStackId = abilityRecord->GetMissionStackId(); + auto preMissionId = preAbilityRecord->GetMissionRecordId(); + auto currentMissionId = abilityRecord->GetMissionRecordId(); + auto isBackground = + (!IsTopInMission(preAbilityRecord)) || preAbilityRecord->IsToEnd() || + ((IsFullScreenStack(preStackId) && IsFullScreenStack(currentStackId)) || + ((preStackId == FLOATING_MISSION_STACK_ID) && (currentStackId == FLOATING_MISSION_STACK_ID) && + preMissionId == currentMissionId) || + ((preStackId == FLOATING_MISSION_STACK_ID) && (currentStackId == FLOATING_MISSION_STACK_ID) && + !SupportSyncVisualByStackId(FLOATING_MISSION_STACK_ID) && preMissionId != currentMissionId)); + + if (isBackground && preAbilityRecord->IsAbilityState(AbilityState::INACTIVE) && + !AbilityUtil::IsSystemDialogAbility( + abilityRecord->GetAbilityInfo().bundleName, abilityRecord->GetAbilityInfo().name)) { + std::string preElement = preAbilityRecord->GetWant().GetElement().GetURI(); + HILOG_INFO("Pre ability record: %{public}s", preElement.c_str()); + // preAbility was inactive ,resume new want flag to false + MoveToBackgroundTask(preAbilityRecord); + // Flag completed move to end. + if (preAbilityRecord->IsToEnd()) { + preAbilityRecord->SetToEnd(false); + } + } + } + + // 2. nextAbility was in terminate list when terminate ability. + // should move to background and then terminate. + std::shared_ptr nextAbilityRecord = abilityRecord->GetNextAbilityRecord(); + if (nextAbilityRecord != nullptr && nextAbilityRecord->IsAbilityState(AbilityState::INACTIVE) && + nextAbilityRecord->IsTerminating()) { + std::string nextElement = nextAbilityRecord->GetWant().GetElement().GetURI(); + HILOG_INFO("Next ability record : %{public}s", nextElement.c_str()); + MoveToBackgroundTask(nextAbilityRecord); + } + + // 3. when the mission ends and returns to lanucher directly, the next and back are inconsistent. + // shoukd move back ability to background and then terminate. + std::shared_ptr backAbilityRecord = abilityRecord->GetBackAbilityRecord(); + if (backAbilityRecord != nullptr && backAbilityRecord->IsAbilityState(AbilityState::INACTIVE) && + backAbilityRecord->IsTerminating() && + (nextAbilityRecord == nullptr || nextAbilityRecord->GetRecordId() != backAbilityRecord->GetRecordId())) { + std::string backElement = backAbilityRecord->GetWant().GetElement().GetURI(); + HILOG_INFO("Back ability record: %{public}s", backElement.c_str()); + MoveToBackgroundTask(backAbilityRecord); + } + if (powerOffing_ && waittingAbilityQueue_.empty()) { + HILOG_INFO("Wait for the ability life cycle to complete and execute poweroff."); + PowerOffLocked(); + } +} + +void AbilityStackManager::MoveToBackgroundTask(const std::shared_ptr &abilityRecord) +{ + CHECK_POINTER(abilityRecord); + abilityRecord->SetIsNewWant(false); + std::string backElement = abilityRecord->GetWant().GetElement().GetURI(); + HILOG_INFO("Ability record: %{public}s", backElement.c_str()); + auto self(shared_from_this()); + auto task = [abilityRecord, self]() { + HILOG_WARN("Stack manager move to background timeout."); + self->CompleteBackground(abilityRecord); + }; + abilityRecord->MoveToBackground(task); +} + +void AbilityStackManager::CompleteInactive(const std::shared_ptr &abilityRecord) +{ + std::lock_guard guard(stackLock_); + std::string element = abilityRecord->GetWant().GetElement().GetURI(); + HILOG_INFO("ability: %{public}s", element.c_str()); + abilityRecord->SetAbilityState(AbilityState::INACTIVE); + + // 0. multi window moving , complete lifecycle. + if (abilityRecord->GetInMovingState()) { + if (abilityRecord == GetCurrentTopAbility()) { + ContinueLifecycle(); + return; + } + MoveToBackgroundTask(abilityRecord); + abilityRecord->SetInMovingState(false); + // to process next active ability + ContinueLifecycle(); + return; + } + + if (abilityRecord->IsToEnd()) { + auto nextAbility = abilityRecord->GetNextAbilityRecord(); + if (!nextAbility || (nextAbility && !nextAbility->IsToEnd())) { + abilityRecord->SetToEnd(false); + MoveToBackgroundTask(abilityRecord); + return; + } + } + + // ability state is inactive + if (abilityRecord->GetPowerState()) { + CHECK_POINTER(powerStorage_); + auto powerActiveStorages = powerStorage_->GetPowerOffActiveRecord(); + for (auto &powerActiveStorage : powerActiveStorages) { + auto storageActiveAbility = powerActiveStorage.ability.lock(); + if (abilityRecord == storageActiveAbility) { + abilityRecord->SetPowerState(false); + MoveToBackgroundTask(abilityRecord); + return; + } + } + + HILOG_DEBUG("Complete ,target state is inactive."); + abilityRecord->SetPowerState(false); + auto powerInActiveStorages = powerStorage_->GetPowerOffInActiveRecord(); + for (auto &powerInActiveStorage : powerInActiveStorages) { + auto storageInActiveAbility = powerInActiveStorage.ability.lock(); + CHECK_POINTER_CONTINUE(storageInActiveAbility); + if (storageInActiveAbility->GetPowerState()) { + HILOG_DEBUG("Wait other ability to complete lifecycle. Ability: %{public}s.", + storageInActiveAbility->GetAbilityInfo().name.c_str()); + return; + } + } + if (ChangedPowerStorageAbilityToActive(powerStorage_) != ERR_OK) { + HILOG_ERROR("ChangedPowerStorageAbilityToActive Fail"); + return; + } + return; + } + // 1. it may be inactive callback of terminate ability. + if (abilityRecord->IsTerminating()) { + abilityRecord->SendResultToCallers(); + if (abilityRecord->IsForceTerminate()) { + HILOG_WARN("Ability is forced to terminate."); + MoveToBackgroundTask(abilityRecord); + return; + } + auto nextActiveAbility = abilityRecord->GetNextAbilityRecord(); + CHECK_POINTER_LOG(nextActiveAbility, "No top ability! Jump to launcher."); + if (nextActiveAbility->IsAbilityState(ACTIVE)) { + MoveToBackgroundTask(abilityRecord); + UpdateFocusAbilityRecord(nextActiveAbility, true); + return; + } + // need to specify the back ability as the current ability + nextActiveAbility->SetBackAbilityRecord(abilityRecord); + // top ability.has been pushed into stack, but haven't load. + // so we need load it first + nextActiveAbility->ProcessActivate(); + return; + } + + // 2. it may be callback of restart ability. + if (abilityRecord->IsRestarting()) { + HILOG_INFO("%{public}s, back ability record: %{public}s", __func__, element.c_str()); + MoveToBackgroundTask(abilityRecord); + return; + } + // 3. it may be callback of start ability. + // if next ability has been launched and is in bottom of mission, just resume other than loading ability. + auto nextAbilityRecord = abilityRecord->GetNextAbilityRecord(); + CHECK_POINTER_LOG(nextAbilityRecord, "Failed to get next ability record."); + + std::string nextElement = nextAbilityRecord->GetWant().GetElement().GetURI(); + HILOG_DEBUG("Next ability record: %{public}s", nextElement.c_str()); + nextAbilityRecord->ProcessActivate(); +} + +void AbilityStackManager::CompleteBackground(const std::shared_ptr &abilityRecord) +{ + std::lock_guard guard(stackLock_); + std::string element = abilityRecord->GetWant().GetElement().GetURI(); + sptr token = abilityRecord->GetToken(); + HILOG_INFO("ability: %{public}s", element.c_str()); + + if (abilityRecord->GetAbilityState() == ACTIVATING || abilityRecord->GetAbilityState() == ACTIVE || + abilityRecord->GetAbilityState() == INITIAL) { + HILOG_ERROR("Ability may be activing or active, it can't complete background."); + return; + } + + abilityRecord->SetAbilityState(AbilityState::BACKGROUND); + // send application state to AppMS. + // notify AppMS to update application state. + DelayedSingleton::GetInstance()->MoveToBackground(token); + // Abilities ahead of the one started with SingleTask mode were put in terminate list, we need to terminate + // them. + auto self(shared_from_this()); + for (auto terminateAbility : terminateAbilityRecordList_) { + if (terminateAbility->IsAbilityState(AbilityState::BACKGROUND)) { + auto timeoutTask = [terminateAbility, self]() { + HILOG_WARN("Disconnect ability terminate timeout."); + self->CompleteTerminate(terminateAbility); + }; + terminateAbility->Terminate(timeoutTask); + } + } + + if (abilityRecord->IsRestarting() && abilityRecord->IsAbilityState(AbilityState::BACKGROUND)) { + auto timeoutTask = [abilityRecord, self]() { + HILOG_WARN("disconnect ability terminate timeout."); + self->CompleteTerminate(abilityRecord); + }; + abilityRecord->Terminate(timeoutTask); + } +} + +void AbilityStackManager::CompleteTerminate(const std::shared_ptr &abilityRecord) +{ + std::lock_guard guard(stackLock_); + + CHECK_POINTER(abilityRecord); + std::string element = abilityRecord->GetWant().GetElement().GetURI(); + HILOG_INFO("ability: %{public}s", element.c_str()); + + if (!abilityRecord->IsAbilityState(AbilityState::TERMINATING)) { + HILOG_ERROR("%{public}s, ability is not terminating.", __func__); + return; + } + + // notify AppMS terminate + if (abilityRecord->TerminateAbility() != ERR_OK) { + // Don't return here + HILOG_ERROR("AppMS fail to terminate ability."); + } + // destroy abilityRecord + auto windowInfo = abilityRecord->GetWindowInfo(); + if (windowInfo != nullptr) { + windowTokenToAbilityMap_.erase(windowInfo->windowToken_); + } + + if (abilityRecord->IsRestarting()) { + abilityRecord->SetAbilityState(AbilityState::INITIAL); + abilityRecord->SetScheduler(nullptr); + abilityRecord->LoadAbility(); + } + for (auto it : terminateAbilityRecordList_) { + if (it == abilityRecord) { + terminateAbilityRecordList_.remove(it); + HILOG_DEBUG("Destroy ability record count %ld", abilityRecord.use_count()); + break; + } + HILOG_WARN("Can't find ability in terminate list."); + } +} + +void AbilityStackManager::Dump(std::vector &info) +{ + std::lock_guard guard(stackLock_); + std::string dumpInfo = "User ID #" + std::to_string(userId_); + info.push_back(dumpInfo); + for (auto missionStack : missionStackList_) { + missionStack->Dump(info); + } +} + +void AbilityStackManager::DumpStack(int missionStackId, std::vector &info) +{ + std::lock_guard guard(stackLock_); + std::string dumpInfo = "User ID #" + std::to_string(userId_); + info.push_back(dumpInfo); + for (auto missionStack : missionStackList_) { + if (missionStackId == missionStack->GetMissionStackId()) { + missionStack->Dump(info); + return; + } + } + info.push_back("Invalid stack number, please see ability dump stack-list."); + return; +} + +void AbilityStackManager::DumpStackList(std::vector &info) +{ + std::lock_guard guard(stackLock_); + std::string dumpInfo = "User ID #" + std::to_string(userId_); + info.push_back(dumpInfo); + for (auto missionStack : missionStackList_) { + missionStack->DumpStackList(info); + } +} + +void AbilityStackManager::DumpFocusMap(std::vector &info) +{ + std::lock_guard guard(stackLock_); + std::string dumpInfo = "User ID #" + std::to_string(userId_); + info.push_back(dumpInfo); + for (auto iter : focusAbilityRecordMap_) { + std::string displayInfo = " Display ID #" + std::to_string(iter.first); + info.push_back(displayInfo); + auto ability = iter.second; + if (ability.lock()) { + ability.lock()->Dump(info); + } + } +} + +void AbilityStackManager::GetAllStackInfo(StackInfo &stackInfo) +{ + std::lock_guard guard(stackLock_); + for (auto missionStack : missionStackList_) { + MissionStackInfo missionStackInfo; + missionStackInfo.id = missionStack->GetMissionStackId(); + missionStack->GetAllMissionInfo(missionStackInfo.missionRecords); + stackInfo.missionStackInfos.emplace_back(missionStackInfo); + } +} + +void AbilityStackManager::DumpMission(int missionId, std::vector &info) +{ + std::lock_guard guard(stackLock_); + std::string dumpInfo = "User ID #" + std::to_string(userId_); + info.push_back(dumpInfo); + for (auto missionStack : missionStackList_) { + auto mission = missionStack->GetMissionRecordById(missionId); + if (mission != nullptr) { + mission->Dump(info); + return; + } + } + info.push_back("error: invalid mission number, please see 'ability dump --stack-list'."); + return; +} + +void AbilityStackManager::DumpTopAbility(std::vector &info) +{ + std::lock_guard guard(stackLock_); + std::string dumpInfo = "User ID #" + std::to_string(userId_); + auto topAbility = GetCurrentTopAbility(); + if (topAbility) { + topAbility->Dump(info); + } + return; +} + +void AbilityStackManager::DumpWaittingAbilityQueue(std::string &result) +{ + std::queue copyQueue; + { + std::lock_guard guard(stackLock_); + if (waittingAbilityQueue_.empty()) { + result = "The waitting ability queue is empty."; + return; + } + copyQueue = waittingAbilityQueue_; + } + + result = "User ID #" + std::to_string(userId_) + LINE_SEPARATOR; + while (!copyQueue.empty()) { + auto ability = copyQueue.front(); + std::vector state; + ability.Dump(state); + + for (auto it : state) { + result += it; + result += LINE_SEPARATOR; + } + copyQueue.pop(); + } + return; +} + +void AbilityStackManager::EnqueueWaittingAbility(const AbilityRequest &abilityRequest) +{ + waittingAbilityQueue_.push(abilityRequest); + return; +} + +void AbilityStackManager::StartWaittingAbility() +{ + std::lock_guard guard(stackLock_); + auto topAbility = GetCurrentTopAbility(); + CHECK_POINTER(topAbility); + + if (!topAbility->IsAbilityState(ACTIVE)) { + HILOG_INFO("Top ability is not active, must return for start waiting again."); + return; + } + + if (!waittingAbilityQueue_.empty()) { + AbilityRequest abilityRequest = waittingAbilityQueue_.front(); + waittingAbilityQueue_.pop(); + StartAbilityLocked(topAbility, abilityRequest); + return; + } +} + +void AbilityStackManager::GetMissionRecordAndAbilityRecord(const AbilityRequest &abilityRequest, + const std::shared_ptr ¤tTopAbility, std::shared_ptr &targetAbilityRecord, + std::shared_ptr &targetMissionRecord) +{ + HILOG_DEBUG("Get mission record and ability record."); + CHECK_POINTER(currentMissionStack_); + + // The singleInstance start mode, mission name is #bundleName:abilityName. + if (abilityRequest.abilityInfo.launchMode == AppExecFwk::LaunchMode::SINGLETON) { + GetRecordBySingleton(abilityRequest, currentTopAbility, targetAbilityRecord, targetMissionRecord); + // The standard start mode, mission name is bundle name by default. + } else { + GetRecordByStandard(abilityRequest, currentTopAbility, targetAbilityRecord, targetMissionRecord); + } +} + +void AbilityStackManager::GetRecordBySingleton(const AbilityRequest &abilityRequest, + const std::shared_ptr ¤tTopAbility, std::shared_ptr &targetAbilityRecord, + std::shared_ptr &targetMissionRecord) +{ + std::string bundleName = + AbilityUtil::ConvertBundleNameSingleton(abilityRequest.abilityInfo.bundleName, abilityRequest.abilityInfo.name); + auto missionRecord = GetMissionRecordByName(bundleName); + if (missionRecord == nullptr) { + targetAbilityRecord = AbilityRecord::CreateAbilityRecord(abilityRequest); + targetMissionRecord = std::make_shared(bundleName); + } else { + targetAbilityRecord = missionRecord->GetTopAbilityRecord(); + if (targetAbilityRecord != nullptr) { + targetAbilityRecord->SetWant(abilityRequest.want); + targetAbilityRecord->SetIsNewWant(true); + CheckMissionRecordIsResume(missionRecord); + } + targetMissionRecord = missionRecord; + } +} + +void AbilityStackManager::GetRecordByStandard(const AbilityRequest &abilityRequest, + const std::shared_ptr ¤tTopAbility, std::shared_ptr &targetAbilityRecord, + std::shared_ptr &targetMissionRecord) +{ + bool isStackChanged = false; + if (currentTopAbility) { + isStackChanged = (currentTopAbility->IsLauncherAbility() && !IsLauncherAbility(abilityRequest)) || + (!currentTopAbility->IsLauncherAbility() && IsLauncherAbility(abilityRequest)); + } + + if (currentTopAbility == nullptr || (currentTopAbility && isStackChanged) || + (currentTopAbility && currentTopAbility->GetAbilityInfo().launchMode == AppExecFwk::LaunchMode::SINGLETON)) { + // first get target mission record by bundleName + auto missionRecord = GetMissionRecordByName(abilityRequest.abilityInfo.bundleName); + if (missionRecord == nullptr) { + targetAbilityRecord = AbilityRecord::CreateAbilityRecord(abilityRequest); + targetMissionRecord = std::make_shared(abilityRequest.abilityInfo.bundleName); + } else { + /* If current top ability is singleton mode, target mission record will be changed. + * Check whether the requested ability is not at the top of the stack of the target mission, + * True: Need to create a new one . Other: Restart the top ability of this mission. + */ + CheckMissionRecordIsResume(missionRecord); + + if (currentTopAbility && (!isStackChanged) && + (currentTopAbility->GetAbilityInfo().launchMode == AppExecFwk::LaunchMode::SINGLETON) && + ((!missionRecord->IsTopAbilityRecordByName(abilityRequest.abilityInfo.name)) || + (missionRecord->IsTopAbilityRecordByName(abilityRequest.abilityInfo.name) && + abilityRequest.abilityInfo.launchMode == AppExecFwk::LaunchMode::STANDARD))) { + targetAbilityRecord = AbilityRecord::CreateAbilityRecord(abilityRequest); + } else { + targetAbilityRecord = missionRecord->GetTopAbilityRecord(); + if (targetAbilityRecord != nullptr) { + // The third-party app is called back from the desktop, + // and the specified slice route does not take effect. + targetAbilityRecord->SetWant(abilityRequest.want); + targetAbilityRecord->SetIsNewWant(true); + } + } + targetMissionRecord = missionRecord; + } + } else if (currentTopAbility && (!isStackChanged)) { + // The requested ability is already top ability. Reuse top ability. + targetMissionRecord = currentTopAbility->GetMissionRecord(); + CheckMissionRecordIsResume(targetMissionRecord); + if (abilityRequest.abilityInfo.launchMode == AppExecFwk::LaunchMode::SINGLETOP && + currentTopAbility->GetMissionRecord()->IsTopAbilityRecordByName(abilityRequest.abilityInfo.name)) { + targetAbilityRecord = currentTopAbility; + targetAbilityRecord->SetWant(abilityRequest.want); + targetAbilityRecord->SetIsNewWant(true); + } else { + targetAbilityRecord = AbilityRecord::CreateAbilityRecord(abilityRequest); + } + } +} + +bool AbilityStackManager::IsLauncherAbility(const AbilityRequest &abilityRequest) const +{ + return abilityRequest.abilityInfo.applicationInfo.isLauncherApp; +} + +bool AbilityStackManager::IsLauncherMission(int id) +{ + if (launcherMissionStack_ == nullptr || launcherMissionStack_->GetMissionRecordById(id) == nullptr) { + return false; + } + return true; +} + +int AbilityStackManager::GetRecentMissions( + const int32_t numMax, const int32_t flags, std::vector &recentList) +{ + HILOG_INFO("Get recent missions."); + std::lock_guard guard(stackLock_); + if (numMax < 0) { + HILOG_ERROR("numMax is invalid"); + return ERR_INVALID_VALUE; + } + if (flags < RECENT_WITH_EXCLUDED || flags > RECENT_IGNORE_UNAVAILABLE) { + HILOG_ERROR("flags is invalid"); + return ERR_INVALID_VALUE; + } + + return GetRecentMissionsLocked(numMax, flags, recentList); +} + +int AbilityStackManager::GetRecentMissionsLocked( + const int32_t numMax, const int32_t flags, std::vector &recentList) +{ + HILOG_INFO("Get recent missions locked."); + CHECK_POINTER_AND_RETURN(defaultMissionStack_, ERR_NO_INIT); + + bool withExcluded = (static_cast(flags) & RECENT_WITH_EXCLUDED) != 0; + std::vector missionInfos; + defaultMissionStack_->GetAllMissionInfo(missionInfos); + for (auto &mission : missionInfos) { + if (static_cast(recentList.size()) >= numMax) { + break; + } + // flags is RECENT_IGNORE_UNAVAILABLE, + // You need to determine the mission optimized by the process + // Then continue + if (!withExcluded) { + auto missionRecord = defaultMissionStack_->GetMissionRecordById(mission.id); + if (!missionRecord) { + HILOG_ERROR("Mission is nullptr, continue."); + continue; + } + auto ability = missionRecord->GetTopAbilityRecord(); + if (!ability) { + HILOG_ERROR("Ability is nullptr, continue."); + continue; + } + if (ability->IsAbilityState(AbilityState::INITIAL)) { + HILOG_INFO("Flag is RECENT_IGNORE_UNAVAILABLE, ability state: INITIAL, continue."); + continue; + } + } + AbilityMissionInfo recentMissionInfo; + CreateRecentMissionInfo(mission, recentMissionInfo); + recentList.emplace_back(recentMissionInfo); + } + + return ERR_OK; +} + +void AbilityStackManager::CreateRecentMissionInfo( + const MissionRecordInfo &mission, AbilityMissionInfo &recentMissionInfo) +{ + HILOG_INFO("Create recent mission info."); + recentMissionInfo.id = mission.id; + recentMissionInfo.runingState = DEFAULT_INVAL_VALUE; + + auto missionRecord = GetMissionRecordFromAllStacks(mission.id); + CHECK_POINTER_LOG(missionRecord, "Mission record is not exist."); + auto parentStack = missionRecord->GetMissionStack(); + recentMissionInfo.missionStackId = parentStack->GetMissionStackId(); + auto baseAbility = missionRecord->GetBottomAbilityRecord(); + if (baseAbility != nullptr) { + recentMissionInfo.baseWant = baseAbility->GetWant(); + OHOS::AppExecFwk::ElementName baseElement(baseAbility->GetAbilityInfo().deviceId, + baseAbility->GetAbilityInfo().bundleName, + baseAbility->GetAbilityInfo().name); + recentMissionInfo.baseAbility = baseElement; + } + + auto topAbility = missionRecord->GetTopAbilityRecord(); + if (topAbility != nullptr) { + OHOS::AppExecFwk::ElementName topElement(topAbility->GetAbilityInfo().deviceId, + topAbility->GetAbilityInfo().bundleName, + topAbility->GetAbilityInfo().name); + recentMissionInfo.topAbility = topElement; + + MissionDescriptionInfo missionDescription; + missionDescription.label = topAbility->GetApplicationInfo().label; + missionDescription.iconPath = topAbility->GetApplicationInfo().iconPath; + recentMissionInfo.missionDescription = missionDescription; + } + + if (auto desc = missionRecord->GetMissionDescriptionInfo()) { + recentMissionInfo.missionDescription = *desc; + } + + recentMissionInfo.size = missionRecord->GetAbilityRecordCount(); +} + +int AbilityStackManager::SetMissionDescriptionInfo( + const std::shared_ptr &abilityRecord, const MissionDescriptionInfo &description) +{ + HILOG_DEBUG("%{public}s called", __FUNCTION__); + CHECK_POINTER_AND_RETURN(abilityRecord, SET_MISSION_INFO_FAILED); + + auto mission = abilityRecord->GetMissionRecord(); + CHECK_POINTER_AND_RETURN(mission, SET_MISSION_INFO_FAILED); + auto ptr = std::make_shared(description); + mission->SetMissionDescriptionInfo(ptr); + + return ERR_OK; +} + +int AbilityStackManager::GetMissionLockModeState() +{ + HILOG_DEBUG("%{public}s called", __FUNCTION__); + if (!lockMissionContainer_) { + return LockMissionContainer::LockMissionState::LOCK_MISSION_STATE_NONE; + } + + return lockMissionContainer_->GetLockedMissionState(); +} + +int AbilityStackManager::UpdateConfiguration(const DummyConfiguration &config) +{ + HILOG_INFO("%{public}s called", __FUNCTION__); + std::lock_guard guard(stackLock_); + + // update all stack configuration. + for (auto &stack : missionStackList_) { + CHECK_POINTER_AND_RETURN(stack, ERR_INVALID_VALUE); + HILOG_DEBUG("stack id : %{public}d", stack->GetMissionStackId()); + std::shared_ptr configSptr = std::make_shared(config); + stack->UpdateConfiguration(configSptr); + } + + return ProcessConfigurationChange(); +} + +int AbilityStackManager::ProcessConfigurationChange() +{ + HILOG_INFO("%{public}s called.", __FUNCTION__); + + // all active ability check whether process onconfigurationchanged + for (auto &stack : missionStackList_) { + CHECK_POINTER_AND_RETURN(stack, ERR_INVALID_VALUE); + HILOG_DEBUG("stack id : %{public}d", stack->GetMissionStackId()); + std::vector missionInfos; + stack->GetAllMissionInfo(missionInfos); + for (auto &mission : missionInfos) { + auto missionRecord = stack->GetMissionRecordById(mission.id); + if (!missionRecord) { + continue; + } + for (auto &it : mission.abilityRecordInfos) { + auto abilityRecord = missionRecord->GetAbilityRecordById(it.id); + if (abilityRecord && abilityRecord->IsAbilityState(AbilityState::ACTIVE)) { + abilityRecord->ProcessConfigurationChange(); + } + } + } + } + + return ERR_OK; +} + +void AbilityStackManager::RestartAbility(const std::shared_ptr abilityRecord) +{ + HILOG_INFO("%{public}s called", __FUNCTION__); + CHECK_POINTER(abilityRecord); + abilityRecord->SetRestarting(true); + if (abilityRecord->IsAbilityState(AbilityState::ACTIVE) || + abilityRecord->IsAbilityState(AbilityState::ACTIVATING)) { + abilityRecord->Inactivate(); + } else if (abilityRecord->IsAbilityState(AbilityState::INACTIVE) || + abilityRecord->IsAbilityState(AbilityState::INACTIVATING)) { + MoveToBackgroundTask(abilityRecord); + } else if (abilityRecord->IsAbilityState(AbilityState::BACKGROUND) || + abilityRecord->IsAbilityState(AbilityState::MOVING_BACKGROUND)) { + auto self(shared_from_this()); + auto timeoutTask = [abilityRecord, self]() { + HILOG_WARN("disconnect ability terminate timeout."); + self->CompleteTerminate(abilityRecord); + }; + abilityRecord->Terminate(timeoutTask); + } else { + HILOG_WARN("target ability can't be restarted."); + } +} + +int AbilityStackManager::MoveMissionToTop(int32_t missionId) +{ + HILOG_INFO("Move mission to top."); + std::lock_guard guard(stackLock_); + if (missionId < 0) { + HILOG_ERROR("Mission id is invalid."); + return ERR_INVALID_VALUE; + } + + if (lockMissionContainer_ && lockMissionContainer_->IsLockedMissionState()) { + HILOG_ERROR("current is lock mission state, refusing to operate other mission."); + return ERR_INVALID_VALUE; + } + + return MoveMissionToTopLocked(missionId); +} + +int AbilityStackManager::MoveMissionToTopLocked(int32_t missionId) +{ + HILOG_INFO("Move mission to top locked."); + + if (isMultiWinMoving_) { + HILOG_ERROR("System is moving multi window state, request deny."); + return MOVE_MISSION_TO_STACK_MOVING_DENIED; + } + + CHECK_TRUE_RETURN_RET((!defaultMissionStack_ || !launcherMissionStack_), ERR_NO_INIT, "Mission stack is invalid."); + auto currentTopAbility = GetCurrentTopAbility(); + CHECK_POINTER_AND_RETURN(currentTopAbility, MOVE_MISSION_FAILED); + + auto currentStack = currentTopAbility->GetMissionRecord()->GetMissionStack(); + CHECK_POINTER_AND_RETURN(currentStack, MOVE_MISSION_FAILED); + + auto requestMissionRecord = GetMissionRecordFromAllStacks(missionId); + CHECK_POINTER_AND_RETURN(requestMissionRecord, MOVE_MISSION_FAILED); + + CheckMissionRecordIsResume(requestMissionRecord); + + auto requestAbilityRecord = requestMissionRecord->GetTopAbilityRecord(); + CHECK_POINTER_AND_RETURN(requestAbilityRecord, MOVE_MISSION_FAILED); + + auto requestStack = requestMissionRecord->GetMissionStack(); + CHECK_POINTER_AND_RETURN(requestStack, MOVE_MISSION_FAILED); + + // request ability active, current ability active, change focus + if (requestAbilityRecord->IsAbilityState(ACTIVE)) { + MoveMissionStackToTop(requestStack); + requestStack->MoveMissionRecordToTop(requestMissionRecord); + UpdateFocusAbilityRecord(requestAbilityRecord, true); + return ERR_OK; + } + + if (currentStack->IsEqualStackId(FLOATING_MISSION_STACK_ID) && + IsFullScreenStack(requestStack->GetMissionStackId())) { + auto fullScreenStack = GetTopFullScreenStack(); + CHECK_POINTER_AND_RETURN(fullScreenStack, MOVE_MISSION_FAILED); + currentTopAbility = fullScreenStack->GetTopAbilityRecord(); + } + + if (IsFullScreenStack(currentStack->GetMissionStackId()) && + requestStack->IsEqualStackId(FLOATING_MISSION_STACK_ID)) { + auto floatingStack = GetOrCreateMissionStack(FLOATING_MISSION_STACK_ID, false); + auto topAbility = floatingStack->GetTopAbilityRecord(); + if (SupportSyncVisualByStackId(FLOATING_MISSION_STACK_ID) || + (!SupportSyncVisualByStackId(FLOATING_MISSION_STACK_ID) && requestAbilityRecord == topAbility)) { + MoveMissionStackToTop(requestStack); + requestAbilityRecord->ProcessActivate(); + return ERR_OK; + } + currentTopAbility = topAbility; + } + + MoveMissionStackToTop(requestStack); + MoveMissionAndAbility(currentTopAbility, requestAbilityRecord, requestMissionRecord); + + currentTopAbility->Inactivate(); + return ERR_OK; +} + +int AbilityStackManager::MoveMissionToEnd(const sptr &token, const bool nonFirst) +{ + std::lock_guard guard(stackLock_); + + if (lockMissionContainer_ && lockMissionContainer_->IsLockedMissionState()) { + HILOG_ERROR("current is lock mission state, refusing to operate other mission."); + return ERR_INVALID_VALUE; + } + + if (isMultiWinMoving_) { + HILOG_ERROR("System is moving multi window state, request deny."); + return MOVE_MISSION_TO_STACK_MOVING_DENIED; + } + + return MoveMissionToEndLocked(token, nonFirst); +} + +int AbilityStackManager::MoveMissionToEndLocked(const sptr &token, const bool nonFirst) +{ + HILOG_INFO("Move mission to end locked."); + + CHECK_POINTER_AND_RETURN(token, MOVE_MISSION_FAILED); + + auto abilityRecord = GetAbilityRecordByToken(token); + CHECK_POINTER_AND_RETURN(abilityRecord, MOVE_MISSION_FAILED); + + auto missionRecord = abilityRecord->GetMissionRecord(); + CHECK_POINTER_AND_RETURN(missionRecord, MOVE_MISSION_FAILED); + + if (!nonFirst) { + if (missionRecord->GetBottomAbilityRecord() != abilityRecord) { + HILOG_ERROR("nonFirst is false, it's not the bottom of the mission, can't move mission to end."); + return MOVE_MISSION_FAILED; + } + } + + return MoveMissionToEndLocked(missionRecord->GetMissionRecordId()); +} + +int AbilityStackManager::MoveMissionToEndLocked(int missionId) +{ + HILOG_INFO("Move mission to end locked by mission id."); + + if (isMultiWinMoving_) { + HILOG_ERROR("System is moving multi window state, request deny."); + return MOVE_MISSION_TO_STACK_MOVING_DENIED; + } + + if (lockMissionContainer_ && lockMissionContainer_->IsLockedMissionState()) { + HILOG_ERROR("current is lock mission state, refusing to operate other mission."); + return ERR_INVALID_VALUE; + } + auto requestMission = GetMissionRecordFromAllStacks(missionId); + CHECK_POINTER_AND_RETURN(requestMission, MOVE_MISSION_FAILED); + auto requestAbility = requestMission->GetTopAbilityRecord(); + CHECK_POINTER_AND_RETURN(requestAbility, MOVE_MISSION_FAILED); + auto requestStack = requestMission->GetMissionStack(); + CHECK_POINTER_AND_RETURN(requestStack, MOVE_MISSION_FAILED); + + if (!requestAbility->IsAbilityState(AbilityState::ACTIVE) || + requestAbility->GetAbilityInfo().applicationInfo.isLauncherApp) { + HILOG_ERROR("Ability is not active, or ability is launcher, can't move mission to end."); + return MOVE_MISSION_FAILED; + } + // current top ability hold focus + auto currentTopAbility = GetCurrentTopAbility(); + CHECK_POINTER_AND_RETURN(currentTopAbility, MOVE_MISSION_FAILED); + auto currentMission = currentTopAbility->GetMissionRecord(); + CHECK_POINTER_AND_RETURN(currentMission, MOVE_MISSION_FAILED); + auto currentStack = currentMission->GetMissionStack(); + CHECK_POINTER_AND_RETURN(currentStack, MOVE_MISSION_FAILED); + + std::shared_ptr targetAbilityRecord; + std::shared_ptr targetMissionRecord; + std::shared_ptr targetMissionStack; + + if (IsFullScreenStack(currentStack->GetMissionStackId()) && + requestStack->GetMissionStackId() == FLOATING_MISSION_STACK_ID) { + requestStack->MoveMissionRecordToBottom(requestMission); + requestAbility->SetToEnd(true); + requestAbility->Inactivate(); + return ERR_OK; + } + + if (currentStack->GetMissionStackId() == FLOATING_MISSION_STACK_ID && + requestStack->GetMissionStackId() == FLOATING_MISSION_STACK_ID) { + requestStack->MoveMissionRecordToBottom(requestMission); + requestAbility->SetToEnd(true); + requestAbility->Inactivate(); + // floating hold focus, shift focus to full screen stack + if (currentTopAbility == requestAbility) { + auto fullScreenStack = GetTopFullScreenStack(); + CHECK_POINTER_AND_RETURN(fullScreenStack, MOVE_MISSION_FAILED); + MoveMissionStackToTop(fullScreenStack); + auto fullScreenTopAbility = fullScreenStack->GetTopAbilityRecord(); + CHECK_POINTER_AND_RETURN(fullScreenTopAbility, MOVE_MISSION_FAILED); + UpdateFocusAbilityRecord(fullScreenTopAbility, true); + } + return ERR_OK; + } + + auto isActiveLauncher = (requestMission->IsLauncherCreate() || + requestMission->GetMissionStack()->GetBottomMissionRecord() == requestMission); + requestStack->MoveMissionRecordToBottom(requestMission); + requestMission->SetIsLauncherCreate(); + + if (isActiveLauncher) { + MoveMissionStackToTop(launcherMissionStack_); + targetMissionStack = launcherMissionStack_; + targetMissionRecord = launcherMissionStack_->GetTopMissionRecord(); + targetAbilityRecord = targetMissionRecord->GetTopAbilityRecord(); + } else { + targetMissionStack = requestStack; + targetMissionRecord = targetMissionStack->GetTopMissionRecord(); + targetAbilityRecord = targetMissionRecord->GetTopAbilityRecord(); + } + + targetAbilityRecord->SetPreAbilityRecord(requestAbility); + requestAbility->SetNextAbilityRecord(targetAbilityRecord); + + targetAbilityRecord->SetToEnd(true); + requestAbility->SetToEnd(true); + requestAbility->Inactivate(); + return ERR_OK; +} + +void AbilityStackManager::OnAbilityDied(std::shared_ptr abilityRecord) +{ + HILOG_INFO("On ability died."); + std::lock_guard guard(stackLock_); + CHECK_POINTER(abilityRecord); + CHECK_POINTER(launcherMissionStack_); + CHECK_POINTER(defaultMissionStack_); + + if (abilityRecord->GetAbilityInfo().type != AbilityType::PAGE) { + HILOG_ERROR("Ability type is not page."); + return; + } + // release mission when locked. + auto mission = abilityRecord->GetMissionRecord(); + if (mission && lockMissionContainer_ && lockMissionContainer_->IsLockedMissionState()) { + if (lockMissionContainer_->IsSameLockedMission(mission->GetName())) { + lockMissionContainer_->ReleaseLockedMission(mission, -1, true); + } + } + + // If the launcher ability is dead, delete the record + if (abilityRecord->IsLauncherAbility()) { + OnAbilityDiedByLauncher(abilityRecord); + return; + } + + OnAbilityDiedByDefault(abilityRecord); +} + +void AbilityStackManager::OnAbilityDiedByLauncher(std::shared_ptr abilityRecord) +{ + HILOG_INFO("On ability died by launcher."); + CHECK_POINTER(abilityRecord); + CHECK_POINTER(launcherMissionStack_); + auto mission = abilityRecord->GetMissionRecord(); + if (!mission || !launcherMissionStack_->IsExistMissionRecord(mission->GetMissionRecordId()) || + !mission->IsExistAbilityRecord(abilityRecord->GetRecordId())) { + HILOG_ERROR("Mission or ability record is not in launcher stack."); + return; + } + + if (!abilityRecord->IsUninstallAbility()) { + HILOG_INFO("Save mission"); + resumeMissionContainer_->Save(mission); + } else { + resumeMissionContainer_->Remove(mission->GetMissionRecordId()); + } + + // Terminate launcher ability on the top of dead ability + std::vector abilityInfos; + mission->GetAllAbilityInfo(abilityInfos); + for (auto &it : abilityInfos) { + auto ability = mission->GetAbilityRecordById(it.id); + if (!ability) { + HILOG_WARN("Ability is nullptr."); + continue; + } + if (ability == abilityRecord) { + break; + } + if (ability->IsTerminating()) { + HILOG_ERROR("Ability is terminating."); + continue; + } + HILOG_DEBUG("Terminate launcher ability."); + ability->SetTerminatingState(); + TerminateAbilityLocked(ability, DEFAULT_INVAL_VALUE, nullptr); + } + + // Process the dead ability record + if (mission->GetBottomAbilityRecord() == abilityRecord && abilityRecord->IsLauncherRoot()) { + HILOG_DEBUG("Root launcher ability died, set state: INITIAL."); + abilityRecord->ClearFlag(); + abilityRecord->SetAbilityState(AbilityState::INITIAL); + } else { + mission->RemoveAbilityRecord(abilityRecord); + if (mission->IsEmpty()) { + launcherMissionStack_->RemoveMissionRecord(mission->GetMissionRecordId()); + } + } + + DelayedStartLauncher(); +} + +void AbilityStackManager::DelayedStartLauncher() +{ + auto abilityManagerService = DelayedSingleton::GetInstance(); + CHECK_POINTER(abilityManagerService); + auto handler = abilityManagerService->GetEventHandler(); + CHECK_POINTER(handler); + auto timeoutTask = [stackManager = shared_from_this()]() { + HILOG_DEBUG("The launcher needs to be restarted."); + stackManager->BackToLauncher(); + }; + handler->PostTask(timeoutTask, "Launcher_Restart", AbilityManagerService::RESTART_TIMEOUT); +} + +void AbilityStackManager::OnAbilityDiedByDefault(std::shared_ptr abilityRecord) +{ + HILOG_INFO("On ability died by default."); + CHECK_POINTER(abilityRecord); + auto mission = abilityRecord->GetMissionRecord(); + CHECK_POINTER(mission); + if (!mission->IsExistAbilityRecord(abilityRecord->GetRecordId())) { + HILOG_ERROR("Mission is nullptr or not exist."); + return; + } + + if (abilityRecord->IsAbilityState(AbilityState::ACTIVATING) || + abilityRecord->IsAbilityState(AbilityState::INITIAL)) { + auto preAbility = abilityRecord->GetPreAbilityRecord(); + if (preAbility && preAbility->IsAbilityState(AbilityState::INACTIVE)) { + MoveToBackgroundTask(preAbility); + } + } + + if (!abilityRecord->IsUninstallAbility()) { + HILOG_INFO("Save mission"); + resumeMissionContainer_->Save(mission); + } else { + resumeMissionContainer_->Remove(mission->GetMissionRecordId()); + } + + auto topAbility = mission->GetTopAbilityRecord(); + CHECK_POINTER(topAbility); + auto stack = mission->GetMissionStack(); + CHECK_POINTER(stack); + auto isFloatingFocusDied = + ((topAbility == GetCurrentTopAbility()) && stack->IsEqualStackId(FLOATING_MISSION_STACK_ID) && + (topAbility->IsAbilityState(ACTIVE) || topAbility->IsAbilityState(ACTIVATING))); + + auto isFullStackActiveDied = (IsFullScreenStack(stack->GetMissionStackId()) && + (topAbility->IsAbilityState(ACTIVE) || topAbility->IsAbilityState(ACTIVATING))); + + std::vector abilityInfos; + mission->GetAllAbilityInfo(abilityInfos); + for (auto &it : abilityInfos) { + auto ability = mission->GetAbilityRecordById(it.id); + if (!ability) { + HILOG_ERROR("ability is nullptr,%{public}d", __LINE__); + continue; + } + if (ability == abilityRecord) { + break; + } + if (ability->IsTerminating()) { + HILOG_ERROR("ability is terminating, %{public}d", __LINE__); + continue; + } + HILOG_INFO("Terminate ability, %{public}d", __LINE__); + ability->SetForceTerminate(true); + ability->SetTerminatingState(); + TerminateAbilityLocked(ability, DEFAULT_INVAL_VALUE, nullptr); + } + + if (abilityRecord->IsUninstallAbility()) { + HILOG_INFO("Ability uninstall,%{public}d", __LINE__); + mission->RemoveAbilityRecord(abilityRecord); + if (mission->IsEmpty()) { + RemoveMissionRecordById(mission->GetMissionRecordId()); + JudgingIsRemoveMultiScreenStack(stack); + } + } else { + if (mission->GetBottomAbilityRecord() == abilityRecord) { + HILOG_INFO("Ability died, state: INITIAL, %{public}d", __LINE__); + abilityRecord->ClearFlag(); + abilityRecord->SetAbilityState(AbilityState::INITIAL); + } else { + HILOG_INFO("Ability died, remove record, %{public}d", __LINE__); + mission->RemoveAbilityRecord(abilityRecord); + } + } + + if (isFloatingFocusDied) { + HILOG_INFO("floating focus ability died, back to full stack"); + auto fullScreenStack = GetTopFullScreenStack(); + CHECK_POINTER(fullScreenStack); + auto topFullScreenAbility = fullScreenStack->GetTopAbilityRecord(); + CHECK_POINTER(fullScreenStack); + MoveMissionStackToTop(fullScreenStack); + if (topFullScreenAbility->IsAbilityState(AbilityState::ACTIVE)) { + UpdateFocusAbilityRecord(topFullScreenAbility, true); + } else { + topFullScreenAbility->ProcessActivate(); + } + return; + } + + if (isFullStackActiveDied) { + HILOG_INFO("full stack active ability died, back to launcher."); + DelayedStartLauncher(); + } +} + +void AbilityStackManager::BackToLauncher() +{ + HILOG_INFO("Back to launcher."); + std::lock_guard guard(stackLock_); + CHECK_POINTER(defaultMissionStack_); + CHECK_POINTER(launcherMissionStack_); + + auto fullScreenStack = GetTopFullScreenStack(); + CHECK_POINTER(fullScreenStack); + auto currentTopAbility = fullScreenStack->GetTopAbilityRecord(); + if (currentTopAbility && (currentTopAbility->IsAbilityState(AbilityState::ACTIVE) || + currentTopAbility->IsAbilityState(AbilityState::ACTIVATING))) { + HILOG_WARN("Current top ability is active, no need to start launcher."); + return; + } + auto launcherAbility = GetLauncherRootAbility(); + CHECK_POINTER_LOG(launcherAbility, "There is no root launcher ability record, back to launcher failed."); + + MoveMissionStackToTop(launcherMissionStack_); + + auto missionRecord = launcherAbility->GetMissionRecord(); + CHECK_POINTER_LOG(missionRecord, "Can't get root launcher ability record's mission, back to launcher failed."); + + CheckMissionRecordIsResume(missionRecord); + + if (currentTopAbility) { + launcherAbility->SetPreAbilityRecord(currentTopAbility); + currentTopAbility->SetNextAbilityRecord(launcherAbility); + + missionRecord->SetPreMissionRecord(currentTopAbility->GetMissionRecord()); + if (currentTopAbility->IsLauncherAbility()) { + missionRecord->SetIsLauncherCreate(); + } + } + launcherMissionStack_->MoveMissionRecordToTop(missionRecord); + launcherAbility->ProcessActivate(); +} + +std::shared_ptr AbilityStackManager::GetLauncherRootAbility() const +{ + if (!launcherMissionStack_) { + HILOG_ERROR("Mission stack is invalid."); + return nullptr; + } + std::vector missionInfos; + launcherMissionStack_->GetAllMissionInfo(missionInfos); + for (auto &mission : missionInfos) { + auto missionRecord = launcherMissionStack_->GetMissionRecordById(mission.id); + if (!missionRecord) { + continue; + } + for (auto &it : mission.abilityRecordInfos) { + auto abilityRecord = missionRecord->GetAbilityRecordById(it.id); + if (abilityRecord && abilityRecord->IsLauncherRoot()) { + return abilityRecord; + } + } + } + return nullptr; +} + +void AbilityStackManager::UninstallApp(const std::string &bundleName) +{ + HILOG_INFO("Uninstall app, bundleName: %{public}s", bundleName.c_str()); + auto abilityManagerService = DelayedSingleton::GetInstance(); + CHECK_POINTER(abilityManagerService); + auto handler = abilityManagerService->GetEventHandler(); + CHECK_POINTER(handler); + auto task = [bundleName, this]() { AddUninstallTags(bundleName); }; + handler->PostTask(task); +} + +void AbilityStackManager::AddUninstallTags(const std::string &bundleName) +{ + HILOG_INFO("Add uninstall tags, bundleName: %{public}s", bundleName.c_str()); + std::lock_guard guard(stackLock_); + for (auto &stack : missionStackList_) { + std::vector missions; + stack->GetAllMissionInfo(missions); + for (auto &missionInfo : missions) { + auto mission = stack->GetMissionRecordById(missionInfo.id); + if (!mission) { + HILOG_ERROR("Mission is nullptr."); + continue; + } + std::vector abilitys; + mission->GetAllAbilityInfo(abilitys); + for (auto &abilityInfo : abilitys) { + auto ability = mission->GetAbilityRecordById(abilityInfo.id); + if (!ability) { + HILOG_ERROR("Ability is nullptr."); + continue; + } + + if (ability->GetAbilityInfo().bundleName == bundleName) { + if (ability->IsAbilityState(AbilityState::INITIAL)) { + mission->RemoveAbilityRecord(ability); + stack->RemoveMissionRecord(mission->GetMissionRecordId()); + CHECK_POINTER(resumeMissionContainer_); + resumeMissionContainer_->Remove(mission->GetMissionRecordId()); + if (lockMissionContainer_ && lockMissionContainer_->IsLockedMissionState()) { + if (lockMissionContainer_->IsSameLockedMission(mission->GetName())) { + lockMissionContainer_->ReleaseLockedMission(mission, -1, true); + } + } + continue; + } + ability->SetIsUninstallAbility(); + } + } + } + } + // Multi screen stack may be empty + auto floatingStack = GetOrCreateMissionStack(FLOATING_MISSION_STACK_ID, false); + JudgingIsRemoveMultiScreenStack(floatingStack); + auto splitScreenStack = GetOrCreateMissionStack(SPLIT_SCREEN_MISSION_STACK_ID, false); + JudgingIsRemoveMultiScreenStack(splitScreenStack); +} + +std::shared_ptr AbilityStackManager::GetAbilityRecordByEventId(int64_t eventId) const +{ + HILOG_DEBUG("Get ability record by eventId."); + for (auto &stack : missionStackList_) { + std::vector missionInfos; + stack->GetAllMissionInfo(missionInfos); + for (auto &mission : missionInfos) { + auto missionRecord = stack->GetMissionRecordById(mission.id); + if (!missionRecord) { + continue; + } + for (auto &it : mission.abilityRecordInfos) { + auto abilityRecord = missionRecord->GetAbilityRecordById(it.id); + if (abilityRecord && abilityRecord->GetEventId() == eventId) { + return abilityRecord; + } + } + } + } + return nullptr; +} + +void AbilityStackManager::OnTimeOut(uint32_t msgId, int64_t eventId) +{ + HILOG_DEBUG("On timeout."); + std::lock_guard guard(stackLock_); + auto abilityRecord = GetAbilityRecordByEventId(eventId); + if (abilityRecord == nullptr) { + HILOG_ERROR("stack manager on time out event: ability record is nullptr."); + return; + } + + // release mission when locked. + auto mission = abilityRecord->GetMissionRecord(); + if (mission && lockMissionContainer_ && lockMissionContainer_->IsLockedMissionState()) { + if (lockMissionContainer_->IsSameLockedMission(mission->GetName())) { + lockMissionContainer_->ReleaseLockedMission(mission, -1, true); + } + } + CHECK_POINTER_LOG(abilityRecord, "stack manager on time out event: ability record is nullptr."); + + HILOG_DEBUG("Ability timeout ,msg:%{public}d,name:%{public}s", msgId, abilityRecord->GetAbilityInfo().name.c_str()); + + switch (msgId) { + case AbilityManagerService::LOAD_TIMEOUT_MSG: + ActiveTopAbility(abilityRecord); + break; + case AbilityManagerService::ACTIVE_TIMEOUT_MSG: + case AbilityManagerService::INACTIVE_TIMEOUT_MSG: + DelayedStartLauncher(); + break; + default: + break; + } +} + +int AbilityStackManager::MoveMissionToFloatingStack(const MissionOption &missionOption) +{ + HILOG_DEBUG("Move mission to floating stack, missionId: %{public}d", missionOption.missionId); + std::lock_guard guard(stackLock_); + if (lockMissionContainer_ && lockMissionContainer_->IsLockedMissionState()) { + HILOG_ERROR("current is lock mission state, refusing to operate other mission."); + return ERR_INVALID_VALUE; + } + if (missionOption.missionId == DEFAULT_INVAL_VALUE) { + HILOG_ERROR("Mission id is invalid."); + return ERR_INVALID_DATA; + } + if (JudgingTargetSystemWindowMode(missionOption.winModeKey) != SystemWindowMode::FLOATING_WINDOW_MODE) { + HILOG_ERROR("The requested mode is error."); + return ERR_INVALID_DATA; + } + std::list missionOptions; + MissionOption option = missionOption; + missionOptions.push_back(option); + + return MoveMissionsToStackLocked(missionOptions); +} + +int AbilityStackManager::MoveMissionToSplitScreenStack(const MissionOption &missionOption) +{ + HILOG_DEBUG("Move mission to split screen stack, missionId:%{public}d", missionOption.missionId); + std::lock_guard guard(stackLock_); + if (lockMissionContainer_ && lockMissionContainer_->IsLockedMissionState()) { + HILOG_ERROR("current is lock mission state, refusing to operate other mission."); + return ERR_INVALID_VALUE; + } + if (missionOption.missionId == DEFAULT_INVAL_VALUE) { + HILOG_ERROR("mission id is invalid."); + return ERR_INVALID_DATA; + } + if (JudgingTargetSystemWindowMode(missionOption.winModeKey) != SystemWindowMode::SPLITSCREEN_WINDOW_MODE) { + HILOG_ERROR("The requested mode is error."); + return ERR_INVALID_DATA; + } + std::list missionOptions; + MissionOption option = missionOption; + missionOptions.push_back(option); + + return MoveMissionsToStackLocked(missionOptions); +} + +int AbilityStackManager::MoveMissionsToStackLocked(const std::list &missionOptions) +{ +#if BINDER_IPC_32BIT + HILOG_DEBUG("Request mission option size :%{public}u", missionOptions.size()); +#else + HILOG_DEBUG("Request mission option size :%{public}lu", missionOptions.size()); +#endif + + // check condition whether can enter or exit multiwindow mode. + CHECK_RET_RETURN_RET(CheckMultiWindowCondition(missionOptions), "check multiwindow condition is failed."); + + // complete mission stack moving and notify ability window mode has changed. + auto lastTopAbility = GetCurrentTopAbility(); + isMultiWinMoving_ = true; + for (auto &it : missionOptions) { + auto sourceMission = GetMissionRecordFromAllStacks(it.missionId); + CheckMissionRecordIsResume(sourceMission); + CHECK_POINTER_AND_RETURN(sourceMission, MOVE_MISSION_TO_STACK_NOT_EXIST_MISSION); + CHECK_RET_RETURN_RET(CompleteMissionMoving(sourceMission, JudgingTargetStackId(it.winModeKey)), + "complete mission moving failed."); + sourceMission->SetMissionOption(it); + } + + // to do ,split srceen mode ,change second screen missionoption. + + // schulde ability lifescycle (all stack) + auto currentTopAbility = GetCurrentTopAbility(); + bool isFullScreen = + missionOptions.front().winModeKey == AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_FULLSCREEN; + // top ability active and display fullscreen, others background state. + CHECK_RET_RETURN_RET( + DispatchLifecycle(lastTopAbility, currentTopAbility, isFullScreen), "Dispatch lifecycle error."); + + // Judging target system window mode, and notify event. + auto willWinMode = JudgingTargetSystemWindowMode(missionOptions.front().winModeKey); + auto targetWinMode = GetTargetSystemWindowMode(willWinMode); + NotifyWindowModeChanged(targetWinMode); + + return ERR_OK; +} + +int AbilityStackManager::MaximizeMultiWindow(int missionId) +{ + HILOG_DEBUG("Maximize multi window, missionId:%{public}d", missionId); + std::lock_guard guard(stackLock_); + if (lockMissionContainer_ && lockMissionContainer_->IsLockedMissionState()) { + HILOG_ERROR("current is lock mission state, refusing to operate other mission."); + return ERR_INVALID_VALUE; + } + + auto missionRecord = GetMissionRecordFromAllStacks(missionId); + CHECK_POINTER_AND_RETURN(missionRecord, MAXIMIZE_MULTIWINDOW_NOT_EXIST); + auto parentStack = missionRecord->GetMissionStack(); + CHECK_POINTER_AND_RETURN(parentStack, ERR_INVALID_DATA); + if (!parentStack->IsEqualStackId(FLOATING_MISSION_STACK_ID)) { + HILOG_ERROR("This mission is not exist in multiwindow stack."); + return MAXIMIZE_MULTIWINDOW_NOT_EXIST; + } + auto topAbility = missionRecord->GetTopAbilityRecord(); + CHECK_POINTER_AND_RETURN(topAbility, ERR_INVALID_DATA); + if (!topAbility->IsAbilityState(AbilityState::INACTIVE) && !topAbility->IsAbilityState(AbilityState::ACTIVE)) { + HILOG_ERROR("This mission is not visible, maximize failed."); + return MAXIMIZE_MULTIWINDOW_FAILED; + } + // construct mission option, request to move mission to default stack. + MissionOption option; + option.missionId = missionId; + option.winModeKey = AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_FULLSCREEN; + std::list missionOptions; + missionOptions.push_back(option); + + return MoveMissionsToStackLocked(missionOptions); +} + +void AbilityStackManager::ContinueLifecycle() +{ + HILOG_INFO("Continue lifecycle."); + for (auto &stack : missionStackList_) { + CHECK_POINTER(stack); + std::vector missionInfos; + stack->GetAllMissionInfo(missionInfos); + for (auto &it : missionInfos) { + std::shared_ptr missionRecord = stack->GetMissionRecordById(it.id); + CHECK_POINTER(missionRecord); + auto topAbility = missionRecord->GetTopAbilityRecord(); + CHECK_POINTER(topAbility); + if (topAbility->GetInMovingState() && topAbility != GetCurrentTopAbility()) { + HILOG_DEBUG("Wait other ability to complete lifecycle. Ability: %{public}s.", + topAbility->GetAbilityInfo().name.c_str()); + return; + } + } + } + + auto currentTopAbility = GetCurrentTopAbility(); + CHECK_POINTER(currentTopAbility); + HILOG_DEBUG("At last, complete top ability lifecycle, target state is active."); + if (currentTopAbility->IsAbilityState(AbilityState::ACTIVE)) { + UpdateFocusAbilityRecord(currentTopAbility, true); + currentTopAbility->SetInMovingState(false); + isMultiWinMoving_ = false; + } else { + currentTopAbility->ProcessActivate(); + } +} + +int AbilityStackManager::DispatchLifecycle(const std::shared_ptr &lastTopAbility, + const std::shared_ptr ¤tTopAbility, bool isTopFullScreen) +{ + CHECK_POINTER_AND_RETURN(lastTopAbility, ERR_INVALID_DATA); + CHECK_POINTER_AND_RETURN(currentTopAbility, ERR_INVALID_DATA); + + auto lastMission = lastTopAbility->GetMissionRecord(); + CHECK_POINTER_AND_RETURN(lastMission, ERR_INVALID_DATA); + auto lastMissionStack = lastMission->GetMissionStack(); + CHECK_POINTER_AND_RETURN(lastMissionStack, ERR_INVALID_DATA); + + auto topFullStack = GetTopFullScreenStack(); + CHECK_POINTER_AND_RETURN(topFullStack, ERR_INVALID_DATA); + + for (auto &stack : missionStackList_) { + CHECK_POINTER_AND_RETURN(stack, ERR_INVALID_DATA); + bool isSyncVisual = SupportSyncVisualByStackId(stack->GetMissionStackId()); + + HILOG_DEBUG("Processing stack lifescycle: stack id: %{public}d, isSyncVisual: %{public}d", + stack->GetMissionStackId(), + isSyncVisual); + + std::vector missionInfos; + stack->GetAllMissionInfo(missionInfos); + for (auto &it : missionInfos) { + std::shared_ptr missionRecord = stack->GetMissionRecordById(it.id); + CHECK_POINTER_AND_RETURN(missionRecord, ERR_INVALID_DATA); + auto topAbility = missionRecord->GetTopAbilityRecord(); + CHECK_POINTER_AND_RETURN(topAbility, ERR_INVALID_DATA); + // last top active ability , need to inactive. + if (topAbility == lastTopAbility || topAbility == currentTopAbility) { + HILOG_DEBUG("Last top active ability or Current top ability, lifecycle at last."); + topAbility->SetInMovingState(true); + continue; + } + // top ability active , others need to background state. + if (isTopFullScreen) { + HILOG_DEBUG("Top ability will full screen, others need to background."); + topAbility->ProcessInactivateInMoving(); + continue; + } + // Except the top mission of the stack, all the others are in the background state, + // When this mission stack not support sync visual. + if (!stack->IsTopMissionRecord(missionRecord)) { + if (!isSyncVisual) { + HILOG_DEBUG("This mission stack not support sync visual. need to background."); + topAbility->ProcessInactivateInMoving(); + } + continue; + } + // process top mission. + // fullscreen stack, only the top ability is active state, others keep background state. + if (stack == topFullStack) { + HILOG_DEBUG("Fullscreen stack ,top abiltiy need to active."); + topAbility->ProcessActivateInMoving(); + continue; + } + // others force background state. + HILOG_DEBUG("Others keep background state."); + topAbility->ProcessInactivateInMoving(); + } + } + + bool isNotTopInFullScreen = + IsFullScreenStack(lastTopAbility->GetMissionStackId()) && + (!lastMissionStack->IsTopMissionRecord(lastMission) || lastMissionStack != topFullStack); + bool isNotTopInMultiWin = !IsFullScreenStack(lastTopAbility->GetMissionStackId()) && + !SupportSyncVisualByStackId(lastTopAbility->GetMissionStackId()) && + (!lastMissionStack->IsTopMissionRecord(lastMission) || + (lastMission->GetMissionRecordId() == (currentTopAbility->GetMissionRecordId()))); + if (lastTopAbility == currentTopAbility) { + HILOG_DEBUG("Lasttopability is equal to currenttopability."); + } else if (isNotTopInFullScreen || isNotTopInMultiWin || isTopFullScreen) { + HILOG_DEBUG("Last top active ability , need to inactive."); + lastTopAbility->ProcessInactivateInMoving(); + } else { + lastTopAbility->SetInMovingState(false); + } + + // if there is no ability to wait for processing active, just active top ability immediately + ContinueLifecycle(); + + return ERR_OK; +} + +SystemWindowMode AbilityStackManager::GetTargetSystemWindowMode(const SystemWindowMode &willWinMode) +{ + if (curSysWindowMode_ == willWinMode) { + return curSysWindowMode_; + } + + bool isCrossFlag = curSysWindowMode_ == SystemWindowMode::FLOATING_AND_SPLITSCREEN_WINDOW_MODE; + switch (willWinMode) { + case SystemWindowMode::SPLITSCREEN_WINDOW_MODE: + case SystemWindowMode::FLOATING_WINDOW_MODE: + return (isCrossFlag || curSysWindowMode_ != SystemWindowMode::DEFAULT_WINDOW_MODE) ? curSysWindowMode_ + : willWinMode; + default: + break; + } + + // will win mode is default mode ,need to check current mission stack list. + bool isFloating = GetOrCreateMissionStack(FLOATING_MISSION_STACK_ID, false) != nullptr; + bool isSplitScreen = GetOrCreateMissionStack(SPLIT_SCREEN_MISSION_STACK_ID, false) != nullptr; + + if (isFloating && isSplitScreen) { + return SystemWindowMode::FLOATING_AND_SPLITSCREEN_WINDOW_MODE; + } else if (isFloating) { + return SystemWindowMode::FLOATING_WINDOW_MODE; + } else if (isSplitScreen) { + return SystemWindowMode::SPLITSCREEN_WINDOW_MODE; + } else { + return willWinMode; + } +} + +int AbilityStackManager::CheckMultiWindowCondition(const std::list &missionOptions) const +{ + HILOG_DEBUG("Check multi window condition."); + if (isMultiWinMoving_) { + HILOG_ERROR("System is moving multi window state, request deny."); + return MOVE_MISSION_TO_STACK_MOVING_DENIED; + } + + auto currentTopAbilityRecord = GetCurrentTopAbility(); + if (currentTopAbilityRecord && + AbilityUtil::IsSystemDialogAbility( + currentTopAbilityRecord->GetAbilityInfo().bundleName, currentTopAbilityRecord->GetAbilityInfo().name)) { + HILOG_ERROR("Top page ability is dialog type, cannot return to launcher"); + return MOVE_MISSION_TO_STACK_MOVING_DENIED; + } + + if (missionOptions.empty() || missionOptions.size() > MAX_CAN_MOVE_MISSIONS) { + HILOG_ERROR("Moving missions has been out of size, Maximum:%{public}d.", MAX_CAN_MOVE_MISSIONS); + return MOVE_MISSION_TO_STACK_OUT_OF_SIZE; + } + // check request missions exist, and has same window mode. + auto lastOption = missionOptions.front(); + for (auto &it : missionOptions) { + if (!it.IsSameWindowMode(lastOption.winModeKey)) { + HILOG_ERROR("Mission options are not in same win mode."); + return MOVE_MISSION_TO_STACK_NOT_SAME_WIN_MODE; + } + auto targetMission = GetMissionRecordFromAllStacks(it.missionId); + if (!targetMission) { + HILOG_ERROR("Moving mission record is not exist."); + return MOVE_MISSION_TO_STACK_NOT_EXIST_MISSION; + } + auto parentStack = targetMission->GetMissionStack(); + if (parentStack && parentStack->GetMissionStackId() == JudgingTargetStackId(it.winModeKey)) { + HILOG_ERROR("Refuse moving mission to its own stack."); + return MOVE_MISSION_TO_STACK_NOT_EXIST_MISSION; + } + if (!targetMission->SupportMultWindow()) { + HILOG_ERROR("Moving mission record is not support multi window."); + return MOVE_MISSION_TO_STACK_NOT_SUPPORT_MULTI_WIN; + } + } + + // check whether target mission stack will be overflow. + if (!CheckMissionStackWillOverflow(missionOptions)) { + HILOG_ERROR("Mission stack will overflow, refuse to move mission."); + return MOVE_MISSION_TO_STACK_TARGET_STACK_OVERFLOW; + } + + return ERR_OK; +} + +int AbilityStackManager::CheckMultiWindowCondition( + const std::shared_ptr ¤tTopAbility, const AbilityRequest &abilityRequest) const +{ + HILOG_DEBUG("Check multi window condition."); + CHECK_POINTER_AND_RETURN_LOG(abilityRequest.startSetting, START_ABILITY_SETTING_FAILED, "startsetting is nullptr."); + + if (isMultiWinMoving_) { + HILOG_ERROR("System is moving multi window state, request deny."); + return START_ABILITY_SETTING_FAILED; + } + + if (currentTopAbility && + AbilityUtil::IsSystemDialogAbility( + currentTopAbility->GetAbilityInfo().bundleName, currentTopAbility->GetAbilityInfo().name)) { + HILOG_ERROR("Top page ability is dialog type, cannot return to launcher."); + return START_ABILITY_SETTING_FAILED; + } + // check whether target mission stack will be overflow. + MissionOption option; + option.winModeKey = static_cast( + std::atoi(abilityRequest.startSetting->GetProperty(AbilityStartSetting::WINDOW_MODE_KEY).c_str())); + std::list list; + list.push_back(option); + if (!CheckMissionStackWillOverflow(list)) { + HILOG_ERROR("Mission stack will overflow."); + return START_ABILITY_SETTING_NOT_SUPPORT_MULTI_WIN; + } + + return ERR_OK; +} + +bool AbilityStackManager::CheckMissionStackWillOverflow(const std::list &missionOptions) const +{ + std::map calcMap; + for (auto &it : missionStackList_) { + calcMap.emplace(it->GetMissionStackId(), it->GetMissionRecordCount()); + } + + auto isOverFlow = [&](int stackId, std::map &calcMap) { + calcMap[stackId]++; + if (GetMaxHoldMissionsByStackId(stackId) > 0 && calcMap[stackId] > GetMaxHoldMissionsByStackId(stackId)) { + HILOG_ERROR( + "Over limit of holding mission, stackId:%{public}d , size:%{public}d", stackId, calcMap[stackId]); + return false; + } + return true; + }; + + // check whether splitscreen and floating stack will overflow. + for (auto &option : missionOptions) { + auto stackId = JudgingTargetStackId(option.winModeKey); + if (!isOverFlow(stackId, calcMap)) { + return false; + } + } + + return true; +} + +int AbilityStackManager::CompleteMissionMoving(std::shared_ptr &sourceMission, int stackId) +{ + CHECK_POINTER_AND_RETURN(sourceMission, MOVE_MISSION_TO_STACK_NOT_EXIST_MISSION); + auto targetStack = GetOrCreateMissionStack(stackId, true); + CHECK_POINTER_AND_RETURN(targetStack, ERR_INVALID_DATA); + + CHECK_RET_RETURN_RET(CompleteMoveMissionToStack(sourceMission, targetStack), "Moving mission record failed."); + + return ERR_OK; +} + +std::shared_ptr AbilityStackManager::GetOrCreateMissionStack(int stackId, bool isCreateFlag) +{ + HILOG_DEBUG("Target stack id:%{public}d", stackId); + if (stackId > MAX_MISSION_STACK_ID || stackId < MIN_MISSION_STACK_ID) { + HILOG_ERROR("stack id:%{public}d is not defined.", stackId); + return nullptr; + } + auto isExist = [stackId]( + const std::shared_ptr &stack) { return stackId == stack->GetMissionStackId(); }; + auto iter = std::find_if(missionStackList_.begin(), missionStackList_.end(), isExist); + if (iter != missionStackList_.end()) { + HILOG_DEBUG("Get target mission stack success."); + return *iter; + } + + if (isCreateFlag) { + HILOG_DEBUG("Target mission stack is not exist, need to create."); + std::shared_ptr missionStack = std::make_shared(stackId, userId_); + missionStackList_.push_back(missionStack); +#if BINDER_IPC_32BIT + HILOG_DEBUG("Add stackId(%{public}d) to missionStackList, mission stack size:%{public}u", + stackId, + missionStackList_.size()); +#else + HILOG_DEBUG("Add stackId(%{public}d) to missionStackList, mission stack size:%{public}lu", + stackId, + missionStackList_.size()); +#endif + return missionStack; + } + + HILOG_DEBUG("Target mission stack is not exist."); + return nullptr; +} + +int AbilityStackManager::CompleteMoveMissionToStack( + const std::shared_ptr &sourceMission, const std::shared_ptr &targetStack) +{ + CHECK_POINTER_AND_RETURN(sourceMission, ERR_INVALID_DATA); + CHECK_POINTER_AND_RETURN(targetStack, ERR_INVALID_DATA); + auto sourceStack = sourceMission->GetMissionStack(); + CHECK_POINTER_AND_RETURN(sourceStack, ERR_INVALID_DATA); + + bool isTop = sourceMission->IsLauncherCreate() && sourceMission == GetTopMissionRecord(); + + HILOG_DEBUG("Mission reparent : src stack id:%{public}d, target stack id:%{public}d, isTop:%{public}d", + sourceStack->GetMissionStackId(), + targetStack->GetMissionStackId(), + isTop); + + // remove mission record from source stack. + sourceStack->RemoveMissionRecord(sourceMission->GetMissionRecordId()); + // add mission to target mission stack top. + targetStack->AddMissionRecordToTop(sourceMission); + targetStack->MoveMissionRecordToTop(sourceMission); + sourceMission->SetMissionStack(targetStack, targetStack->GetMissionStackId()); + if ((sourceStack->IsEmpty() || isTop) && targetStack != defaultMissionStack_) { + MoveMissionStackToTop(launcherMissionStack_); + } + if (sourceStack->IsEmpty() && (!IsFullScreenStack(sourceStack->GetMissionStackId()))) { + HILOG_DEBUG("Remove stack when mission count is zero. stack:%{public}d.", sourceStack->GetMissionStackId()); + missionStackList_.remove(sourceStack); + } + // move target mission stack to top. + MoveMissionStackToTop(targetStack); + + return ERR_OK; +} + +void AbilityStackManager::ActiveTopAbility(const std::shared_ptr &abilityRecord) +{ + HILOG_INFO("Active top ability."); + CHECK_POINTER(abilityRecord); + + DelayedSingleton::GetInstance()->AttachTimeOut(abilityRecord->GetToken()); + + if (abilityRecord->IsLauncherRoot()) { + HILOG_INFO("Launcher root load timeout, restart."); + DelayedStartLauncher(); + return; + } + + // Pre ability does not need to judge null + auto preAbility = abilityRecord->GetPreAbilityRecord(); + auto missionRecord = abilityRecord->GetMissionRecord(); + CHECK_POINTER(missionRecord); + auto stack = missionRecord->GetMissionStack(); + CHECK_POINTER(stack); + + // remove ability and mission and stack + missionRecord->RemoveAbilityRecord(abilityRecord); + if (missionRecord->IsEmpty()) { + RemoveMissionRecordById(missionRecord->GetMissionRecordId()); + JudgingIsRemoveMultiScreenStack(stack); + } + + if (preAbility && preAbility->IsAbilityState(INACTIVE)) { + HILOG_INFO("Load timeout, restart pre ability."); + MoveMissionStackToTop(preAbility->GetMissionRecord()->GetMissionStack()); + preAbility->ProcessActivate(); + } else { + auto topFullScreenStack = GetTopFullScreenStack(); + CHECK_POINTER(topFullScreenStack); + auto topFullScreenAbility = topFullScreenStack->GetTopAbilityRecord(); + if (topFullScreenAbility && topFullScreenAbility->IsAbilityState(INACTIVE)) { + HILOG_INFO("Load timeout, top full screen ability restart."); + MoveMissionStackToTop(topFullScreenStack); + topFullScreenAbility->ProcessActivate(); + } else { + HILOG_INFO("Load timeout, back to launcher."); + BackToLauncher(); + } + } +} + +int AbilityStackManager::GetMaxHoldMissionsByStackId(int stackId) const +{ + for (auto &it : stackSettings_) { + if (it.stackId == stackId) { + return it.maxHoldMission; + } + } + return DEFAULT_INVAL_VALUE; +} + +bool AbilityStackManager::SupportSyncVisualByStackId(int stackId) const +{ + for (auto &it : stackSettings_) { + if (it.stackId == stackId && (!IsFullScreenStack(stackId))) { + return it.isSyncVisual; + } + } + return false; +} + +SystemWindowMode AbilityStackManager::JudgingTargetSystemWindowMode(AbilityWindowConfiguration config) const +{ + switch (config) { + // to do, split multi screen ,add key + case AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_PRIMARY: + case AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_SECONDARY: + return SystemWindowMode::SPLITSCREEN_WINDOW_MODE; + case AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_FLOATING: + return SystemWindowMode::FLOATING_WINDOW_MODE; + default: + return SystemWindowMode::DEFAULT_WINDOW_MODE; + } +} + +int AbilityStackManager::JudgingTargetStackId(AbilityWindowConfiguration config) const +{ + switch (config) { + // to do, split multi screen ,add key + case AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_PRIMARY: + return SPLIT_SCREEN_MISSION_STACK_ID; + case AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_FLOATING: + return FLOATING_MISSION_STACK_ID; + default: + return DEFAULT_MISSION_STACK_ID; + } +} + +bool AbilityStackManager::IsFirstInMission(const sptr &token) +{ + HILOG_INFO("Is first in mission."); + std::lock_guard guard(stackLock_); + + CHECK_POINTER_RETURN_BOOL(token); + auto abilityRecord = GetAbilityRecordByToken(token); + CHECK_POINTER_RETURN_BOOL(abilityRecord); + + auto missionRecord = abilityRecord->GetMissionRecord(); + CHECK_POINTER_RETURN_BOOL(missionRecord); + + return (missionRecord->GetBottomAbilityRecord() == abilityRecord); +} + +int AbilityStackManager::PowerOff() +{ + HILOG_INFO("Power off."); + std::lock_guard guard(stackLock_); + return PowerOffLocked(); +} + +int AbilityStackManager::PowerOffLocked() +{ + HILOG_INFO("Power off locked."); + auto currentTopAbility = GetCurrentTopAbility(); + if ((currentTopAbility && !currentTopAbility->IsAbilityState(AbilityState::ACTIVE)) || + !waittingAbilityQueue_.empty()) { + HILOG_WARN("Current top ability is not active, waiting ability lifecycle complete"); + // In CompleteActive,waiting ability lifecycle complete,execute PowerOffLocked again + powerOffing_ = true; + return POWER_OFF_WAITING; + } + + powerStorage_ = std::make_shared(); + CHECK_POINTER_AND_RETURN(powerStorage_, POWER_OFF_FAILED); + for (auto &stack : missionStackList_) { + std::vector missionInfos; + stack->GetAllMissionInfo(missionInfos); + auto checkAbility = [&](const MissionRecordInfo &missionInfo) { + auto missionRecord = stack->GetMissionRecordById(missionInfo.id); + CHECK_POINTER(missionRecord); + auto abilityRecord = missionRecord->GetTopAbilityRecord(); + CHECK_POINTER(abilityRecord); + if (abilityRecord->IsAbilityState(AbilityState::ACTIVE)) { + powerStorage_->SetPowerOffActiveRecord(abilityRecord); + abilityRecord->SetPowerState(true); + abilityRecord->ProcessInactivate(); + } + if (abilityRecord->IsAbilityState(AbilityState::INACTIVE)) { + powerStorage_->SetPowerOffInActiveRecord(abilityRecord); + MoveToBackgroundTask(abilityRecord); + } + }; + for_each(missionInfos.begin(), missionInfos.end(), checkAbility); + } + return ERR_OK; +} + +int AbilityStackManager::PowerOn() +{ + HILOG_INFO("Power on."); + std::lock_guard guard(stackLock_); + return PowerOnLocked(); +} + +int AbilityStackManager::PowerOnLocked() +{ + HILOG_INFO("Power on locked."); + powerOffing_ = false; + + CHECK_POINTER_AND_RETURN(powerStorage_, POWER_ON_FAILED); + auto powerInActiveStorages = powerStorage_->GetPowerOffInActiveRecord(); + if (powerInActiveStorages.empty()) { + if (ChangedPowerStorageAbilityToActive(powerStorage_) != ERR_OK) { + HILOG_ERROR("ChangedPowerStorageAbilityToActive Fail"); + return POWER_ON_FAILED; + } + return ERR_OK; + } + + for (auto &powerInActiveStorage : powerInActiveStorages) { + auto storageInActiveAbility = powerInActiveStorage.ability.lock(); + CHECK_POINTER_CONTINUE(storageInActiveAbility); + storageInActiveAbility->SetPowerState(true); + storageInActiveAbility->ProcessActivate(); + } + return ERR_OK; +} + +int AbilityStackManager::ChangedPowerStorageAbilityToActive(std::shared_ptr &powerStorage) +{ + HILOG_INFO("%{public}s", __func__); + CHECK_POINTER_AND_RETURN(powerStorage, ERR_INVALID_VALUE); + auto powerActiveStorages = powerStorage->GetPowerOffActiveRecord(); + // Start the ability except the top of the stack + for (auto &powerActiveStorage : powerActiveStorages) { + auto storageActiveAbility = powerActiveStorage.ability.lock(); + CHECK_POINTER_CONTINUE(storageActiveAbility); + storageActiveAbility->SetPowerState(true); + if (storageActiveAbility == GetCurrentTopAbility()) { + HILOG_DEBUG("There is no ability in active state except the top of the stack"); + continue; + } + storageActiveAbility->ProcessActivate(); + } + // Finally,Start stack top ability + auto currentTopAbility = GetCurrentTopAbility(); + CHECK_POINTER_AND_RETURN(currentTopAbility, ERR_INVALID_VALUE); + currentTopAbility->ProcessActivate(); + HILOG_DEBUG("start the ability at the top of the stack"); + return ERR_OK; +} + +int AbilityStackManager::StartLockMission(int uid, int missionId, bool isSystemApp, int isLock) +{ + HILOG_INFO("%{public}s", __func__); + std::lock_guard guard(stackLock_); + + if (lockMissionContainer_ == nullptr) { + lockMissionContainer_ = std::make_shared(); + CHECK_POINTER_AND_RETURN(lockMissionContainer_, INNER_ERR); + } + + std::shared_ptr missionRecord; + int lockUid = -1; + if (!CheckLockMissionCondition(uid, missionId, isLock, isSystemApp, missionRecord, lockUid)) { + HILOG_ERROR("check lock mission condition failed."); + return LOCK_MISSION_DENY_FAILED; + } + + // lock mission + if (isLock) { + if (!lockMissionContainer_->SetLockedMission(missionRecord, lockUid, isSystemApp)) { + HILOG_ERROR("lock mission error."); + return LOCK_MISSION_DENY_FAILED; + } + // notify wms mission locked state. + + // move lock mission to top + return MoveMissionToTopLocked(missionRecord->GetMissionRecordId()); + } + + // unlock mission + if (!lockMissionContainer_->ReleaseLockedMission(missionRecord, uid, isSystemApp)) { + HILOG_ERROR("unlock mission error."); + return UNLOCK_MISSION_DENY_FAILED; + } + return ERR_OK; +} + +bool AbilityStackManager::CheckLockMissionCondition( + int uid, int missionId, int isLock, bool isSystemApp, std::shared_ptr &mission, int &lockUid) +{ + CHECK_POINTER_RETURN_BOOL(lockMissionContainer_); + // lock or unlock mission by uid and missionId. + if ((isLock && lockMissionContainer_->IsLockedMissionState()) || + (!isLock && !lockMissionContainer_->IsLockedMissionState())) { + return false; + } + + mission = GetMissionRecordFromAllStacks(missionId); + if (missionId < 0 || mission == nullptr) { + HILOG_ERROR("target mission is not exist."); + return false; + } + + auto fullScreenStack = IsFullScreenStack(mission->GetMissionStack()->GetMissionStackId()); + if (!fullScreenStack) { + HILOG_ERROR("Multi-window active,lock mission failed."); + return false; + } + + auto topability = mission->GetTopAbilityRecord(); + auto bottomability = mission->GetBottomAbilityRecord(); + auto abilityManagerService = DelayedSingleton::GetInstance(); + CHECK_POINTER_RETURN_BOOL(topability); + CHECK_POINTER_RETURN_BOOL(bottomability); + CHECK_POINTER_RETURN_BOOL(abilityManagerService); + lockUid = abilityManagerService->GetUidByBundleName(bottomability->GetAbilityInfo().bundleName); + HILOG_INFO("target mission uid :%{public}d", lockUid); + + if (isLock && !isSystemApp) { + // caller and locking ability must be same uid, and forground state. + return (lockUid == uid) && + (topability->IsAbilityState(AbilityState::ACTIVE) || topability->IsAbilityState(AbilityState::INACTIVE)); + } + + return true; +} + +bool AbilityStackManager::CanStartInLockMissionState( + const AbilityRequest &abilityRequest, const std::shared_ptr ¤tTopAbility) const +{ + if (currentTopAbility == nullptr || lockMissionContainer_ == nullptr) { + return true; + } + + if (!lockMissionContainer_->IsLockedMissionState()) { + return true; + } + + // current ability singeton mode + if (currentTopAbility->GetAbilityInfo().launchMode == AppExecFwk::LaunchMode::SINGLETON) { + if (abilityRequest.abilityInfo.launchMode == AppExecFwk::LaunchMode::SINGLETON) { + std::string bundleName = AbilityConfig::MISSION_NAME_MARK_HEAD + abilityRequest.abilityInfo.bundleName + + AbilityConfig::MISSION_NAME_SEPARATOR + abilityRequest.abilityInfo.name; + return lockMissionContainer_->IsSameLockedMission(bundleName); + } + return false; + } + // current ability standard mode + if (abilityRequest.abilityInfo.launchMode != AppExecFwk::LaunchMode::SINGLETON) { + bool isStackNotChanged = (currentTopAbility->IsLauncherAbility() && IsLauncherAbility(abilityRequest)) || + (!currentTopAbility->IsLauncherAbility() && !IsLauncherAbility(abilityRequest)); + // ability request will add to same mission. + return isStackNotChanged; + } + + return false; +} + +bool AbilityStackManager::CanStopInLockMissionState(const std::shared_ptr &terminateAbility) const +{ + if (lockMissionContainer_ == nullptr) { + return true; + } + + if (!lockMissionContainer_->IsLockedMissionState()) { + return true; + } + + auto mission = terminateAbility->GetMissionRecord(); + auto bottom = mission->GetBottomAbilityRecord(); + CHECK_POINTER_RETURN_BOOL(mission); + CHECK_POINTER_RETURN_BOOL(bottom); + return (lockMissionContainer_->IsSameLockedMission(mission->GetName()) && terminateAbility != bottom); +} + +void AbilityStackManager::SendUnlockMissionMessage() +{ + HILOG_ERROR("current is lock mission state, refusing to operate other mission."); +} + +bool AbilityStackManager::IsTopInMission(const std::shared_ptr &abilityRecord) const +{ + CHECK_POINTER_RETURN_BOOL(abilityRecord); + auto missionRecord = abilityRecord->GetMissionRecord(); + CHECK_POINTER_RETURN_BOOL(missionRecord); + + return (missionRecord->GetTopAbilityRecord() == abilityRecord); +} + +bool AbilityStackManager::IsFrontInAllStack(const std::shared_ptr &stack) const +{ + return stack == missionStackList_.front(); +} + +bool AbilityStackManager::IsFullScreenStack(int stackId) const +{ + return (stackId == DEFAULT_MISSION_STACK_ID || stackId == LAUNCHER_MISSION_STACK_ID); +} + +std::shared_ptr AbilityStackManager::GetTopFullScreenStack() +{ + auto isExist = [&](const std::shared_ptr &stack) { + return IsFullScreenStack(stack->GetMissionStackId()); + }; + auto iter = std::find_if(missionStackList_.begin(), missionStackList_.end(), isExist); + if (iter != missionStackList_.end()) { + return (*iter); + } + return nullptr; +} + +int AbilityStackManager::MinimizeMultiWindow(int missionId) +{ + std::lock_guard guard(stackLock_); + if (lockMissionContainer_ && lockMissionContainer_->IsLockedMissionState()) { + HILOG_ERROR("current is lock mission state, refusing to operate other mission."); + return ERR_INVALID_VALUE; + } + return MinimizeMultiWindowLocked(missionId); +} + +int AbilityStackManager::MinimizeMultiWindowLocked(int missionId) +{ + HILOG_INFO("Minimize multi window locked."); + auto missionRecord = GetMissionRecordFromAllStacks(missionId); + CHECK_POINTER_AND_RETURN(missionRecord, MINIMIZE_MULTI_WINDOW_FAILED); + + auto stack = missionRecord->GetMissionStack(); + CHECK_POINTER_AND_RETURN(stack, MINIMIZE_MULTI_WINDOW_FAILED); + + if (!stack->IsEqualStackId(FLOATING_MISSION_STACK_ID)) { + HILOG_ERROR("Mission is not in the float stack, can't be minimized."); + return MINIMIZE_MULTI_WINDOW_FAILED; + } + + return MoveMissionToEndLocked(missionRecord->GetMissionRecordId()); +} + +int AbilityStackManager::ChangeFocusAbility( + const sptr &lostFocusToken, const sptr &getFocusToken) +{ + HILOG_INFO("Change focus ability."); + std::lock_guard guard(stackLock_); + CHECK_POINTER_AND_RETURN(lostFocusToken, ERR_INVALID_VALUE); + CHECK_POINTER_AND_RETURN(getFocusToken, ERR_INVALID_VALUE); + if (getFocusToken == lostFocusToken) { + HILOG_WARN("get token is equal to lost token."); + return CHANGE_FOCUS_ABILITY_FAILED; + } + + auto currentAbility = GetCurrentTopAbility(); + CHECK_POINTER_AND_RETURN(currentAbility, CHANGE_FOCUS_ABILITY_FAILED); + if (!currentAbility->IsAbilityState(AbilityState::ACTIVE) || !waittingAbilityQueue_.empty()) { + HILOG_WARN("Top ability is not active or waiting queue is not empty, change focus failed"); + return CHANGE_FOCUS_ABILITY_FAILED; + } + + auto targetAbility = Token::GetAbilityRecordByToken(getFocusToken); + CHECK_POINTER_AND_RETURN(targetAbility, CHANGE_FOCUS_ABILITY_FAILED); + return ChangeFocusAbilityLocked(targetAbility); +} + +int AbilityStackManager::ChangeFocusAbilityLocked(const std::shared_ptr &targetAbility) +{ + HILOG_INFO("Change focus ability locked."); + CHECK_POINTER_AND_RETURN(targetAbility, ERR_INVALID_VALUE); + + auto currentAbility = GetCurrentTopAbility(); + CHECK_POINTER_AND_RETURN(currentAbility, CHANGE_FOCUS_ABILITY_FAILED); + + if (targetAbility == currentAbility || !targetAbility->IsAbilityState(ACTIVE)) { + HILOG_ERROR("Target ability is current ability, or target ability is not active, can't change focus."); + return CHANGE_FOCUS_ABILITY_FAILED; + } + + auto targetMission = targetAbility->GetMissionRecord(); + CHECK_POINTER_AND_RETURN_LOG( + targetMission, CHANGE_FOCUS_ABILITY_FAILED, " TargetMission is nullptr, change focus failed."); + + return MoveMissionToTop(targetMission->GetMissionRecordId()); +} + +int AbilityStackManager::GetFloatingMissions(std::vector &list) +{ + HILOG_INFO("Get floating missions."); + std::lock_guard guard(stackLock_); + + auto floatingStack = GetOrCreateMissionStack(FLOATING_MISSION_STACK_ID, false); + CHECK_POINTER_AND_RETURN_LOG( + floatingStack, GET_FLOATING_STACK_FAILED, "Floating stack is not exist, get floating missions failed."); + + std::vector missionInfos; + floatingStack->GetAllMissionInfo(missionInfos); + for (auto &mission : missionInfos) { + AbilityMissionInfo recentMissionInfo; + CreateRecentMissionInfo(mission, recentMissionInfo); + list.emplace_back(recentMissionInfo); + } + + return ERR_OK; +} + +int AbilityStackManager::CloseMultiWindow(int missionId) +{ + HILOG_INFO("Close multi window."); + std::lock_guard guard(stackLock_); + if (lockMissionContainer_ && lockMissionContainer_->IsLockedMissionState()) { + HILOG_ERROR("current is lock mission state, refusing to operate other mission."); + return ERR_INVALID_VALUE; + } + + auto mission = GetMissionRecordFromAllStacks(missionId); + CHECK_POINTER_AND_RETURN(mission, CLOSE_MULTI_WINDOW_FAILED); + + auto stack = mission->GetMissionStack(); + CHECK_POINTER_AND_RETURN(stack, CLOSE_MULTI_WINDOW_FAILED); + + if (IsFullScreenStack(stack->GetMissionStackId())) { + HILOG_ERROR("Full screen stack is not close."); + return CLOSE_MULTI_WINDOW_FAILED; + } + + return RemoveMissionByIdLocked(missionId); +} + +void AbilityStackManager::JudgingIsRemoveMultiScreenStack(std::shared_ptr &stack) +{ + HILOG_INFO("Judging is remove multi screen stack."); + + if (stack && !IsFullScreenStack(stack->GetMissionStackId()) && stack->IsEmpty()) { + HILOG_DEBUG("Current stack is empty, remove."); + missionStackList_.remove(stack); + + auto targetWinMode = GetTargetSystemWindowMode(SystemWindowMode::DEFAULT_WINDOW_MODE); + NotifyWindowModeChanged(targetWinMode); + } +} + +void AbilityStackManager::NotifyWindowModeChanged(const SystemWindowMode &windowMode) +{ + HILOG_INFO("Notify window mode changed, will window mode: %{public}d", windowMode); + if (curSysWindowMode_ == windowMode) { + HILOG_ERROR("change mode is current mode"); + return; + } + + HILOG_INFO("current mode : %{public}d , target window mode : %{public}d", curSysWindowMode_, windowMode); + + curSysWindowMode_ = windowMode; + + std::string data; + switch (windowMode) { + case SystemWindowMode::SPLITSCREEN_WINDOW_MODE: + data = "SPLITSCREEN_WINDOW_MODE"; + break; + case SystemWindowMode::FLOATING_WINDOW_MODE: + data = "FLOATING_WINDOW_MODE"; + break; + case SystemWindowMode::FLOATING_AND_SPLITSCREEN_WINDOW_MODE: + data = "FLOATING_AND_SPLITSCREEN_WINDOW_MODE"; + break; + default: + data = "DEFAULT_WINDOW_MODE"; + break; + } + + HILOG_INFO("Publish common event : system window mode changed"); + EventFwk::CommonEventData commonData; + Want want; + want.SetAction(AbilityConfig::EVENT_SYSTEM_WINDOW_MODE_CHANGED); + commonData.SetWant(want); + commonData.SetCode(AbilityConfig::EVENT_CODE_SYSTEM_WINDOW_MODE_CHANGED); + commonData.SetData(data); + EventFwk::CommonEventManager::PublishCommonEvent(commonData); +} + +void AbilityStackManager::UpdateFocusAbilityRecord(const std::shared_ptr &abilityRecord, bool isNotify) +{ + CHECK_POINTER(abilityRecord); + auto getMissionOptionDisplayId = [target = abilityRecord]() { + auto missionRecord = target->GetMissionRecord(); + return missionRecord ? missionRecord->GetMissionOption().displayKey : DISPLAY_DEFAULT_ID; + }; + auto setting = abilityRecord->GetStartSetting(); + int displayId = setting ? std::atoi(setting->GetProperty(AbilityStartSetting::WINDOW_DISPLAY_ID_KEY).c_str()) + : getMissionOptionDisplayId(); + UpdateFocusAbilityRecord(displayId, abilityRecord, isNotify); +} + +void AbilityStackManager::UpdateFocusAbilityRecord( + int displayId, const std::shared_ptr &focusAbility, bool isNotify) +{ + CHECK_POINTER(focusAbility); + auto iter = focusAbilityRecordMap_.find(displayId); + if (iter != focusAbilityRecordMap_.end()) { + auto loseFocusAbility = iter->second.lock(); + if (loseFocusAbility && isNotify) { + loseFocusAbility->TopActiveAbilityChanged(false); + } + focusAbilityRecordMap_.erase(iter); + } + + HILOG_INFO("top active ability changed, displayId:%{public}d, name:%{public}s", + displayId, + focusAbility->GetAbilityInfo().name.c_str()); + + if (isNotify) { + focusAbility->TopActiveAbilityChanged(true); + } + focusAbilityRecordMap_.emplace(displayId, focusAbility); +} + +void AbilityStackManager::CheckMissionRecordIsResume(const std::shared_ptr &mission) +{ + if (resumeMissionContainer_ && resumeMissionContainer_->IsResume(mission->GetMissionRecordId())) { + resumeMissionContainer_->Resume(mission); + } +} +} // namespace AAFwk +} // namespace OHOS diff --git a/tools/services/abilitymgr/src/ability_start_setting.cpp b/tools/services/abilitymgr/src/ability_start_setting.cpp new file mode 100644 index 00000000000..a429fcd2b58 --- /dev/null +++ b/tools/services/abilitymgr/src/ability_start_setting.cpp @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ability_start_setting.h" +#include +#include "string_ex.h" + +using namespace OHOS; + +namespace OHOS { +namespace AAFwk { + +const std::string AbilityStartSetting::BOUNDS_KEY = "bounds"; +const std::string AbilityStartSetting::WINDOW_DISPLAY_ID_KEY = "windowId"; +const std::string AbilityStartSetting::WINDOW_MODE_KEY = "windowMode"; + +/** + * @brief Construct copy function. + * @param other indicates instance of abilitystartsetting object + * @return none. + */ +AbilityStartSetting::AbilityStartSetting(const AbilityStartSetting &other) +{ + abilityStarKey_.clear(); + abilityStarKey_ = other.abilityStarKey_; +} +/** + * @brief Overload assignment operation. + * @param other indicates instance of abilitystartsetting object. + * @return Returns current instance of abilitystartsetting object. + */ +AbilityStartSetting &AbilityStartSetting::operator=(const AbilityStartSetting &other) +{ + if (this != &other) { + abilityStarKey_.clear(); + abilityStarKey_ = other.abilityStarKey_; + } + return *this; +} +/** + * @brief Inner function to create AbilityStartSetting + * + * @return Returns the shared_ptr of AbilityStartSetting object. + */ +std::shared_ptr AbilityStartSettingCreator() +{ + std::shared_ptr abilityStartSetting {new (std::nothrow) AbilityStartSetting()}; + return abilityStartSetting; +} + +/** + * @brief Obtains an empty AbilityStartSetting object. + * + * @return Returns the btains an empty AbilityStartSetting object. + */ +std::shared_ptr AbilityStartSetting::GetEmptySetting() +{ + return AbilityStartSettingCreator(); +} + +/** + * @brief Obtains the names of all the attributes that have been added to this AbilityStartSetting object. + * + * @return Returns the set of attribute names included in this AbilityStartSetting object. + */ +std::set AbilityStartSetting::GetPropertiesKey() +{ + std::set abilityStartSet; + abilityStartSet.clear(); + + for (auto it : abilityStarKey_) { + abilityStartSet.emplace(it.first); + } + return abilityStartSet; +} + +/** + * @brief Checks whether this AbilityStartSetting object is empty. + * + * @return Returns true if this AbilityStartSetting object is empty and animatorOption is null; returns false otherwise. + */ +bool AbilityStartSetting::IsEmpty() +{ + return (abilityStarKey_.size() == 0); +} + +/** + * @brief Sets the names of all the attributes of the AbilityStartSetting object. + * + * @param key Indicates the name of the key. + * @param value The window display mode of the values. + */ +void AbilityStartSetting::AddProperty(const std::string &key, const std::string &value) +{ + abilityStarKey_[key] = value; +} + +/** + * @brief Gets the name of the attributes of the AbilityStartSetting object. + * + * @param key Indicates the name of the key. + * @return Returns value Indicates the value of the attributes of the AbilityStartSetting object + */ +std::string AbilityStartSetting::GetProperty(const std::string &key) +{ + auto it = abilityStarKey_.find(key); + if (it == abilityStarKey_.end()) { + return std::string(); + } + return abilityStarKey_[key]; +} + +/** + * @brief Write the data of AbilityStartSetting to the file stream + * @param parcel indicates write the data of AbilityStartSetting to the file stream through parcel + * @return bool + */ +bool AbilityStartSetting::Marshalling(Parcel &parcel) const +{ + size_t size = abilityStarKey_.size(); + + // 1. Number of key value pairs written + parcel.WriteUint32((uint32_t)size); + + std::map::const_iterator it; + + // 2. Write the key and value strings + for (auto pair : abilityStarKey_) { + // 1.key + parcel.WriteString16(Str8ToStr16(pair.first)); + // 2.data content + parcel.WriteString16(Str8ToStr16(pair.second)); + } + + return true; +} + +/** + * @brief Reading file stream through parcel to generate AbilityStartSetting instance + * @param parcel indicates reading file stream through parcel to generate AbilityStartSetting instance + * @return AbilityStartSetting shared_ptr + */ +AbilityStartSetting *AbilityStartSetting::Unmarshalling(Parcel &parcel) +{ + AbilityStartSetting *abilityStartSetting = new (std::nothrow) AbilityStartSetting(); + if (abilityStartSetting == nullptr) { + return nullptr; + } + // 1. Number of key value pairs read + uint32_t size = 0; + parcel.ReadUint32(size); + std::u16string keyReadString16; + std::u16string dataReadString16; + for (size_t i = 0; (i < size) && abilityStartSetting; i++) { + // 1.key + keyReadString16 = parcel.ReadString16(); + // 2.data content + dataReadString16 = parcel.ReadString16(); + abilityStartSetting->abilityStarKey_[Str16ToStr8(keyReadString16)] = Str16ToStr8(dataReadString16); + keyReadString16.clear(); + dataReadString16.clear(); + } + + return abilityStartSetting; +} +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/abilitymgr/src/ability_token_stub.cpp b/tools/services/abilitymgr/src/ability_token_stub.cpp new file mode 100644 index 00000000000..88e9c9ae88e --- /dev/null +++ b/tools/services/abilitymgr/src/ability_token_stub.cpp @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ability_token_stub.h" + +#include "ability_token_proxy.h" +#include "hilog_wrapper.h" + +namespace OHOS { +namespace AAFwk { +AbilityTokenStub::AbilityTokenStub() +{} + +AbilityTokenStub::~AbilityTokenStub() +{} + +void AbilityTokenRecipient::OnRemoteDied(const wptr &__attribute__((unused)) remote) +{ + HILOG_ERROR("recv AbilityTokenRecipient death notice"); +} +} // namespace AAFwk +} // namespace OHOS diff --git a/tools/services/abilitymgr/src/ams_configuration_parameter.cpp b/tools/services/abilitymgr/src/ams_configuration_parameter.cpp new file mode 100644 index 00000000000..9f6c383cf6a --- /dev/null +++ b/tools/services/abilitymgr/src/ams_configuration_parameter.cpp @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ams_configuration_parameter.h" +#include "hilog_wrapper.h" + +namespace OHOS { +namespace AAFwk { +using json = nlohmann::json; + +void AmsConfigurationParameter::Parse() +{ + auto ref = LoadAmsConfiguration(AmsConfig::AMS_CONFIG_FILE_PATH); + HILOG_INFO("load config ref : %{public}d", ref); +} + +bool AmsConfigurationParameter::GetStartLauncherState() const +{ + return canStartLauncher; +} + +bool AmsConfigurationParameter::GetStatusBarState() const +{ + return canStartUiStatusBar; +} + +bool AmsConfigurationParameter::GetNavigationBarState() const +{ + return canStartUiNavigationBar; +} + +bool AmsConfigurationParameter::NonConfigFile() const +{ + return nonConfigFile; +} + +int AmsConfigurationParameter::LoadAmsConfiguration(const std::string &filePath) +{ + HILOG_DEBUG("%{public}s", __func__); + + std::ifstream inFile; + inFile.open(filePath, std::ios::in); + if (!inFile.is_open()) { + HILOG_INFO("read ams config error ..."); + nonConfigFile = true; + return READ_FAIL; + } + + json amsJson; + inFile >> amsJson; + if (amsJson.is_discarded()) { + HILOG_INFO("json discarded error ..."); + nonConfigFile = true; + inFile.close(); + return READ_JSON_FAIL; + } + + if (amsJson.contains(AmsConfig::SERVICE_ITEM_AMS)) { + canStartLauncher = amsJson.at(AmsConfig::SERVICE_ITEM_AMS).at(AmsConfig::STARTUP_LAUNCHER).get(); + canStartUiStatusBar = amsJson.at(AmsConfig::SERVICE_ITEM_AMS).at(AmsConfig::STARTUP_STATUS_BAR).get(); + canStartUiNavigationBar = + amsJson.at(AmsConfig::SERVICE_ITEM_AMS).at(AmsConfig::STARTUP_NAVIGATION_BAR).get(); + HILOG_INFO("get ams service config succes!"); + } else { + HILOG_INFO("json no have service item ..."); + nonConfigFile = true; + amsJson.clear(); + inFile.close(); + return READ_JSON_FAIL; + } + + amsJson.clear(); + inFile.close(); + HILOG_INFO("read ams config succes!"); + return READ_OK; +} + +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/abilitymgr/src/app_scheduler.cpp b/tools/services/abilitymgr/src/app_scheduler.cpp new file mode 100644 index 00000000000..3836273affc --- /dev/null +++ b/tools/services/abilitymgr/src/app_scheduler.cpp @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "app_scheduler.h" + +#include "hilog_wrapper.h" +#include "ability_util.h" +#include "ability_manager_errors.h" +#include "ability_record.h" +#include "appmgr/app_mgr_constants.h" + +namespace OHOS { +namespace AAFwk { +AppScheduler::AppScheduler() : appMgrClient_(std::make_unique()) +{} + +AppScheduler::~AppScheduler() +{} + +bool AppScheduler::Init(const std::weak_ptr &callback) +{ + CHECK_POINTER_RETURN_BOOL(callback.lock()); + CHECK_POINTER_RETURN_BOOL(appMgrClient_); + + callback_ = callback; + /* because the errcode type of AppMgr Client API will be changed to int, + * so must to covert the return result */ + int result = static_cast(appMgrClient_->ConnectAppMgrService()); + if (result != ERR_OK) { + HILOG_ERROR("failed to ConnectAppMgrService"); + return false; + } + this->IncStrongRef(this); + result = static_cast(appMgrClient_->RegisterAppStateCallback(sptr(this))); + if (result != ERR_OK) { + HILOG_ERROR("failed to RegisterAppStateCallback"); + return false; + } + HILOG_INFO("success to ConnectAppMgrService"); + return true; +} + +int AppScheduler::LoadAbility(const sptr &token, const sptr &preToken, + const AppExecFwk::AbilityInfo &abilityInfo, const AppExecFwk::ApplicationInfo &applicationInfo) +{ + HILOG_DEBUG("Load ability."); + CHECK_POINTER_AND_RETURN(appMgrClient_, INNER_ERR); + /* because the errcode type of AppMgr Client API will be changed to int, + * so must to covert the return result */ + int ret = static_cast(appMgrClient_->LoadAbility(token, preToken, abilityInfo, applicationInfo)); + if (ret != ERR_OK) { + HILOG_ERROR("AppScheduler fail to LoadAbility. ret %d", ret); + return INNER_ERR; + } + return ERR_OK; +} + +int AppScheduler::TerminateAbility(const sptr &token) +{ + HILOG_DEBUG("Terminate ability."); + CHECK_POINTER_AND_RETURN(appMgrClient_, INNER_ERR); + /* because the errcode type of AppMgr Client API will be changed to int, + * so must to covert the return result */ + int ret = static_cast(appMgrClient_->TerminateAbility(token)); + if (ret != ERR_OK) { + HILOG_ERROR("AppScheduler fail to TerminateAbility. ret %d", ret); + return INNER_ERR; + } + return ERR_OK; +} + +void AppScheduler::MoveToForground(const sptr &token) +{ + HILOG_DEBUG("Move to forground."); + CHECK_POINTER(appMgrClient_); + appMgrClient_->UpdateAbilityState(token, AppExecFwk::AbilityState::ABILITY_STATE_FOREGROUND); +} + +void AppScheduler::MoveToBackground(const sptr &token) +{ + HILOG_DEBUG("Move to background."); + CHECK_POINTER(appMgrClient_); + appMgrClient_->UpdateAbilityState(token, AppExecFwk::AbilityState::ABILITY_STATE_BACKGROUND); +} + +void AppScheduler::AbilityBehaviorAnalysis(const sptr &token, const sptr &preToken, + const int32_t visibility, const int32_t perceptibility, const int32_t connectionState) +{ + HILOG_DEBUG("Ability behavior analysis."); + CHECK_POINTER(appMgrClient_); + appMgrClient_->AbilityBehaviorAnalysis(token, preToken, visibility, perceptibility, connectionState); +} + +void AppScheduler::KillProcessByAbilityToken(const sptr &token) +{ + HILOG_DEBUG("Kill process by ability token."); + CHECK_POINTER(appMgrClient_); + appMgrClient_->KillProcessByAbilityToken(token); +} + +AppAbilityState AppScheduler::ConvertToAppAbilityState(const int32_t state) +{ + AppExecFwk::AbilityState abilityState = static_cast(state); + switch (abilityState) { + case AppExecFwk::AbilityState::ABILITY_STATE_FOREGROUND: { + return AppAbilityState::ABILITY_STATE_FOREGROUND; + } + case AppExecFwk::AbilityState::ABILITY_STATE_BACKGROUND: { + return AppAbilityState::ABILITY_STATE_BACKGROUND; + } + default: + return AppAbilityState::ABILITY_STATE_UNDEFINED; + } +} + +AppAbilityState AppScheduler::GetAbilityState() const +{ + return appAbilityState_; +} + +void AppScheduler::OnAbilityRequestDone(const sptr &token, const AppExecFwk::AbilityState state) +{ + HILOG_INFO("On ability request done, state:%{public}d", static_cast(state)); + auto callback = callback_.lock(); + CHECK_POINTER(callback); + appAbilityState_ = ConvertToAppAbilityState(static_cast(state)); + callback->OnAbilityRequestDone(token, static_cast(state)); +} + +int AppScheduler::KillApplication(const std::string &bundleName) +{ + CHECK_POINTER_AND_RETURN(appMgrClient_, INNER_ERR); + int ret = (int)appMgrClient_->KillApplication(bundleName); + if (ret != ERR_OK) { + HILOG_ERROR("Fail to kill application."); + return INNER_ERR; + } + + return ERR_OK; +} + +void AppScheduler::AttachTimeOut(const sptr &token) +{ + CHECK_POINTER(appMgrClient_); + appMgrClient_->AbilityAttachTimeOut(token); +} + +int AppScheduler::CompelVerifyPermission(const std::string &permission, int pid, int uid, std::string &message) +{ + CHECK_POINTER_AND_RETURN(appMgrClient_, INNER_ERR); + auto ret = static_cast(appMgrClient_->CompelVerifyPermission(permission, pid, uid, message)); + if (ret != ERR_OK) { + HILOG_ERROR("Compel verify permission failed."); + return INNER_ERR; + } + + return ERR_OK; +} + +void AppScheduler::OnAppStateChanged(const AppExecFwk::AppProcessData &appData) +{ + auto callback = callback_.lock(); + CHECK_POINTER(callback); + AppInfo info; + info.appName = appData.appName; + info.processName = appData.processName; + info.uid = appData.uid; + info.state = static_cast(appData.appState); + callback->OnAppStateChanged(info); +} +} // namespace AAFwk +} // namespace OHOS diff --git a/tools/services/abilitymgr/src/caller_info.cpp b/tools/services/abilitymgr/src/caller_info.cpp new file mode 100644 index 00000000000..73db4bd5c44 --- /dev/null +++ b/tools/services/abilitymgr/src/caller_info.cpp @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "caller_info.h" + +#include "string_ex.h" +#include "nlohmann/json.hpp" +#include "hilog_wrapper.h" + +namespace OHOS { +namespace AAFwk { + +bool CallerInfo::ReadFromParcel(Parcel &parcel) +{ + requestCode = parcel.ReadInt32(); + deviceId = Str16ToStr8(parcel.ReadString16()); + bundleName = Str16ToStr8(parcel.ReadString16()); + abilityName = Str16ToStr8(parcel.ReadString16()); + return true; +} + +CallerInfo *CallerInfo::Unmarshalling(Parcel &parcel) +{ + CallerInfo *info = new (std::nothrow) CallerInfo(); + if (info && !info->ReadFromParcel(parcel)) { + delete info; + info = nullptr; + } + return info; +} + +bool CallerInfo::Marshalling(Parcel &parcel) const +{ + // write requestCode + if (!parcel.WriteInt32(requestCode)) { + return false; + } + // write deviceId + if (!parcel.WriteString16(Str8ToStr16(deviceId))) { + return false; + } + // write bundleName + if (!parcel.WriteString16(Str8ToStr16(bundleName))) { + return false; + } + // write abilityName + if (!parcel.WriteString16(Str8ToStr16(abilityName))) { + return false; + } + return true; +} + +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/abilitymgr/src/configuration_holder.cpp b/tools/services/abilitymgr/src/configuration_holder.cpp new file mode 100644 index 00000000000..72e3f6b6699 --- /dev/null +++ b/tools/services/abilitymgr/src/configuration_holder.cpp @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "configuration_holder.h" +#include "hilog_wrapper.h" + +namespace OHOS { +namespace AAFwk { + +void ConfigurationHolder::UpdateConfiguration(const std::shared_ptr config) +{ + if (GetChildSize() == 0 && GetParent()) { + HILOG_INFO("%{public}s child update configuration at the time of activing.", __func__); + return; + } + auto configChanges = baseConfiguration_ ? baseConfiguration_->Differ(config) : CHANGE_CONFIG_ALL_CHANGED; + if (configChanges > 0) { + // update base configuration immediately + baseConfiguration_ = config; + } + + DealUpdateConfiguration(); +} + +std::shared_ptr ConfigurationHolder::GetConfiguration() const +{ + return baseConfiguration_; +} + +void ConfigurationHolder::DealUpdateConfiguration() +{ + for (unsigned int index = 0; index < GetChildSize(); index++) { + auto child = FindChild(index); + if (child) { + child->UpdateConfiguration(baseConfiguration_); + } + } +} + +bool ConfigurationHolder::ProcessConfigurationChange() +{ + HILOG_INFO("%{public}s", __func__); + auto parent = GetParent(); + auto targetConfig = parent ? parent->GetConfiguration() : baseConfiguration_; + if (targetConfig == nullptr && baseConfiguration_ == nullptr) { + HILOG_DEBUG("targetConfig and baseConfiguration_ is nullptr, no change."); + return false; + } + + return ProcessConfigurationChangeInner(targetConfig); +} + +bool ConfigurationHolder::ForceProcessConfigurationChange(const std::shared_ptr &config) +{ + return ProcessConfigurationChangeInner(config); +} + +bool ConfigurationHolder::ProcessConfigurationChangeInner(const std::shared_ptr &config) +{ + auto configChanges = baseConfiguration_ ? baseConfiguration_->Differ(config) : CHANGE_CONFIG_ALL_CHANGED; + if (configChanges > 0) { + // update base configuration immediately + baseConfiguration_ = config; + HILOG_DEBUG("have changes."); + if (baseConfiguration_) { + return OnConfigurationChanged(*(baseConfiguration_.get()), configChanges); + } + } + HILOG_DEBUG("there is no change."); + return false; +} + +bool ConfigurationHolder::OnConfigurationChanged(const DummyConfiguration &config, unsigned int configChanges) +{ + return false; +} +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/abilitymgr/src/connection_record.cpp b/tools/services/abilitymgr/src/connection_record.cpp new file mode 100644 index 00000000000..9ac21d41ba9 --- /dev/null +++ b/tools/services/abilitymgr/src/connection_record.cpp @@ -0,0 +1,213 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "connection_record.h" + +#include "hilog_wrapper.h" +#include "ability_util.h" +#include "ability_manager_errors.h" +#include "ability_manager_service.h" + +namespace OHOS { +namespace AAFwk { +int64_t ConnectionRecord::connectRecordId = 0; + +ConnectionRecord::ConnectionRecord(const sptr &callerToken, + const std::shared_ptr &targetService, const sptr &connCallback) + : state_(ConnectionState::INIT), + callerToken_(callerToken), + targetService_(targetService), + connCallback_(connCallback) +{ + recordId_ = connectRecordId++; +} + +ConnectionRecord::~ConnectionRecord() +{} + +std::shared_ptr ConnectionRecord::CreateConnectionRecord(const sptr &callerToken, + const std::shared_ptr &targetService, const sptr &connCallback) +{ + auto connRecord = std::make_shared(callerToken, targetService, connCallback); + CHECK_POINTER_AND_RETURN(connRecord, nullptr); + connRecord->SetConnectState(ConnectionState::INIT); + return connRecord; +} + +void ConnectionRecord::SetConnectState(const ConnectionState &state) +{ + state_ = state; +} + +ConnectionState ConnectionRecord::GetConnectState() const +{ + return state_; +} + +sptr ConnectionRecord::GetToken() const +{ + return callerToken_; +} + +std::shared_ptr ConnectionRecord::GetAbilityRecord() const +{ + return targetService_; +} + +sptr ConnectionRecord::GetAbilityConnectCallback() const +{ + return connCallback_; +} + +void ConnectionRecord::ClearConnCallBack() +{ + if (connCallback_) { + connCallback_.clear(); + } +} + +int ConnectionRecord::DisconnectAbility() +{ + if (state_ != ConnectionState::CONNECTED) { + HILOG_INFO("The connection has not established."); + return INVALID_CONNECTION_STATE; + } + + /* set state to Disconnecting */ + SetConnectState(ConnectionState::DISCONNECTING); + CHECK_POINTER_AND_RETURN(targetService_, ERR_INVALID_VALUE); + int connectNums = targetService_->GetConnectRecordList().size(); + if (connectNums == 1) { + /* post timeout task to eventhandler */ + auto handler = DelayedSingleton::GetInstance()->GetEventHandler(); + if (handler == nullptr) { + HILOG_ERROR("fail to get AbilityEventHandler"); + } else { + std::string taskName("DisconnectTimeout_"); + taskName += std::to_string(recordId_); + auto disconnectTask = [connectionRecord = shared_from_this()]() { + HILOG_ERROR("Disconnect ability timeout"); + connectionRecord->DisconnectTimeout(); + }; + handler->PostTask(disconnectTask, taskName, AbilityManagerService::DISCONNECT_TIMEOUT); + } + /* schedule disconnect to target ability */ + targetService_->DisconnectAbility(); + } else { + SetConnectState(ConnectionState::DISCONNECTED); + } + + return ERR_OK; +} + +void ConnectionRecord::CompleteConnect(int resultCode) +{ + CHECK_POINTER(targetService_); + if (resultCode == ERR_OK) { + SetConnectState(ConnectionState::CONNECTED); + targetService_->SetAbilityState(AbilityState::ACTIVE); + } + const AppExecFwk::AbilityInfo &abilityInfo = targetService_->GetAbilityInfo(); + AppExecFwk::ElementName element(abilityInfo.deviceId, abilityInfo.bundleName, abilityInfo.name); + auto remoteObject = targetService_->GetConnRemoteObject(); + if (connCallback_) { + connCallback_->OnAbilityConnectDone(element, remoteObject, resultCode); + } + HILOG_INFO("result: %{public}d. connectstate:%{public}d.", resultCode, state_); +} + +void ConnectionRecord::CompleteDisconnect(int resultCode) +{ + if (resultCode == ERR_OK) { + SetConnectState(ConnectionState::DISCONNECTED); + } + CHECK_POINTER(targetService_); + const AppExecFwk::AbilityInfo &abilityInfo = targetService_->GetAbilityInfo(); + AppExecFwk::ElementName element(abilityInfo.deviceId, abilityInfo.bundleName, abilityInfo.name); + if (connCallback_) { + connCallback_->OnAbilityDisconnectDone(element, resultCode); + } + HILOG_INFO("result: %{public}d. connectstate:%{public}d.", resultCode, state_); +} + +void ConnectionRecord::ScheduleDisconnectAbilityDone() +{ + if (state_ != ConnectionState::DISCONNECTING) { + HILOG_ERROR("fail to schedule disconnect ability done, current state is not disconnecting."); + return; + } + + auto handler = DelayedSingleton::GetInstance()->GetEventHandler(); + if (handler == nullptr) { + HILOG_ERROR("fail to get AbilityEventHandler"); + } else { + std::string taskName = std::string("DisconnectTimeout_") + std::to_string(recordId_); + handler->RemoveTask(taskName); + } + + CompleteDisconnect(ERR_OK); +} + +void ConnectionRecord::ScheduleConnectAbilityDone() +{ + if (state_ != ConnectionState::CONNECTING) { + HILOG_ERROR("fail to schedule connect ability done, current state is not connecting."); + return; + } + auto handler = DelayedSingleton::GetInstance()->GetEventHandler(); + if (handler == nullptr) { + HILOG_ERROR("fail to get AbilityEventHandler"); + } else { + std::string taskName = std::string("ConnectTimeout_") + std::to_string(recordId_); + handler->RemoveTask(taskName); + } + + CompleteConnect(ERR_OK); +} + +void ConnectionRecord::DisconnectTimeout() +{ + CHECK_POINTER(targetService_); + /* force to disconnect */ + /* so scheduler target service disconnect done */ + DelayedSingleton::GetInstance()->ScheduleDisconnectAbilityDone(targetService_->GetToken()); +} + +std::string ConnectionRecord::ConvertConnectionState(const ConnectionState &state) const +{ + switch (state) { + case ConnectionState::INIT: + return "INIT"; + case ConnectionState::CONNECTING: + return "CONNECTING"; + case ConnectionState::CONNECTED: + return "CONNECTED"; + case ConnectionState::DISCONNECTING: + return "DISCONNECTING"; + case ConnectionState::DISCONNECTED: + return "DISCONNECTED"; + default: + return "INVALIDSTATE"; + } +} + +void ConnectionRecord::Dump(std::vector &info) const +{ + info.emplace_back(" > " + GetAbilityRecord()->GetAbilityInfo().bundleName + "/" + + GetAbilityRecord()->GetAbilityInfo().name + " connectionState #" + + ConvertConnectionState(GetConnectState())); +} +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/abilitymgr/src/data_ability_caller_recipient.cpp b/tools/services/abilitymgr/src/data_ability_caller_recipient.cpp new file mode 100644 index 00000000000..e0639f57e7d --- /dev/null +++ b/tools/services/abilitymgr/src/data_ability_caller_recipient.cpp @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "data_ability_caller_recipient.h" +#include "hilog_wrapper.h" + +namespace OHOS { +namespace AAFwk { +void DataAbilityCallerRecipient::OnRemoteDied(const wptr &remote) +{ + HILOG_ERROR("recv DataAbilityCallerRecipient death notice"); + + if (handler_) { + handler_(remote); + } +} + +DataAbilityCallerRecipient::DataAbilityCallerRecipient(RemoteDiedHandler handler) : handler_(handler) +{ + HILOG_ERROR("%{public}s", __func__); +} + +DataAbilityCallerRecipient::~DataAbilityCallerRecipient() +{ + HILOG_ERROR("%{public}s", __func__); +} +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/abilitymgr/src/data_ability_manager.cpp b/tools/services/abilitymgr/src/data_ability_manager.cpp new file mode 100644 index 00000000000..21c15566070 --- /dev/null +++ b/tools/services/abilitymgr/src/data_ability_manager.cpp @@ -0,0 +1,491 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "data_ability_manager.h" + +#include +#include + +#include "hilog_wrapper.h" +#include "ability_util.h" + +namespace OHOS { +namespace AAFwk { +using namespace std::chrono; +using namespace std::placeholders; + +namespace { +constexpr bool DEBUG_ENABLED = false; +constexpr system_clock::duration DATA_ABILITY_LOAD_TIMEOUT = 11000ms; +} // namespace + +DataAbilityManager::DataAbilityManager() +{ + HILOG_DEBUG("%{public}s(%{public}d)", __PRETTY_FUNCTION__, __LINE__); +} + +DataAbilityManager::~DataAbilityManager() +{ + HILOG_DEBUG("%{public}s(%{public}d)", __PRETTY_FUNCTION__, __LINE__); +} + +sptr DataAbilityManager::Acquire( + const AbilityRequest &abilityRequest, bool tryBind, const sptr &client, bool isSystem) +{ + HILOG_DEBUG("%{public}s(%{public}d)", __PRETTY_FUNCTION__, __LINE__); + + if (abilityRequest.abilityInfo.type != AppExecFwk::AbilityType::DATA) { + HILOG_ERROR("Data ability manager acquire: not a data ability."); + return nullptr; + } + + if (abilityRequest.abilityInfo.bundleName.empty() || abilityRequest.abilityInfo.name.empty()) { + HILOG_ERROR("Data ability manager acquire: invalid name."); + return nullptr; + } + + std::shared_ptr clientAbilityRecord; + const std::string dataAbilityName(abilityRequest.abilityInfo.bundleName + '.' + abilityRequest.abilityInfo.name); + + if (client && !isSystem) { + clientAbilityRecord = Token::GetAbilityRecordByToken(client); + if (!clientAbilityRecord) { + HILOG_ERROR("Data ability manager acquire: invalid client token."); + return nullptr; + } + if (abilityRequest.abilityInfo.bundleName == clientAbilityRecord->GetAbilityInfo().bundleName && + abilityRequest.abilityInfo.name == clientAbilityRecord->GetAbilityInfo().name) { + HILOG_ERROR("Data ability '%{public}s' cannot acquires itself.", dataAbilityName.c_str()); + return nullptr; + } + HILOG_INFO("Ability '%{public}s' acquiring data ability '%{public}s'...", + clientAbilityRecord->GetAbilityInfo().name.c_str(), + dataAbilityName.c_str()); + } else { + HILOG_INFO("Loading data ability '%{public}s'...", dataAbilityName.c_str()); + } + + std::lock_guard locker(mutex_); + + if (DEBUG_ENABLED) { + DumpLocked(__func__, __LINE__); + } + + DataAbilityRecordPtr dataAbilityRecord; + + auto it = dataAbilityRecordsLoaded_.find(dataAbilityName); + if (it == dataAbilityRecordsLoaded_.end()) { + HILOG_DEBUG("Acquiring data ability is not existed, loading..."); + dataAbilityRecord = LoadLocked(dataAbilityName, abilityRequest); + if (!dataAbilityRecord) { + HILOG_ERROR("Failed to load data ability '%{public}s'.", dataAbilityName.c_str()); + return nullptr; + } + } else { + HILOG_DEBUG("Acquiring data ability is existed ."); + dataAbilityRecord = it->second; + } + + auto scheduler = dataAbilityRecord->GetScheduler(); + if (!scheduler) { + if (DEBUG_ENABLED) { + HILOG_ERROR("BUG: data ability '%{public}s' is not loaded, removing it...", dataAbilityName.c_str()); + } + auto it = dataAbilityRecordsLoaded_.find(dataAbilityName); + if (it != dataAbilityRecordsLoaded_.end()) { + dataAbilityRecordsLoaded_.erase(it); + } + return nullptr; + } + + if (client) { + dataAbilityRecord->AddClient(client, tryBind, isSystem); + } + + if (DEBUG_ENABLED) { + DumpLocked(__func__, __LINE__); + } + + return scheduler; +} + +int DataAbilityManager::Release( + const sptr &scheduler, const sptr &client, bool isSystem) +{ + HILOG_DEBUG("%{public}s(%{public}d)", __PRETTY_FUNCTION__, __LINE__); + + CHECK_POINTER_AND_RETURN(scheduler, ERR_NULL_OBJECT); + CHECK_POINTER_AND_RETURN(client, ERR_NULL_OBJECT); + + std::lock_guard locker(mutex_); + + if (DEBUG_ENABLED) { + DumpLocked(__func__, __LINE__); + } + + DataAbilityRecordPtrMap::iterator it; + DataAbilityRecordPtr dataAbilityRecord; + + for (it = dataAbilityRecordsLoaded_.begin(); it != dataAbilityRecordsLoaded_.end(); ++it) { + if (it->second->GetScheduler() != nullptr && it->second->GetScheduler()->AsObject() == scheduler->AsObject()) { + dataAbilityRecord = it->second; + break; + } + } + + if (!dataAbilityRecord) { + HILOG_ERROR("Releasing not existed data ability."); + return ERR_UNKNOWN_OBJECT; + } + + auto abilityRecord = dataAbilityRecord->GetAbilityRecord(); + CHECK_POINTER_AND_RETURN(abilityRecord, ERR_UNKNOWN_OBJECT); + int result = AbilityUtil::JudgeAbilityVisibleControl(abilityRecord->GetAbilityInfo()); + if (result != ERR_OK) { + HILOG_ERROR("%{public}s JudgeAbilityVisibleControl error.", __func__); + return result; + } + + if (dataAbilityRecord->GetClientCount(client) == 0) { + HILOG_ERROR("Release data ability with wrong client."); + return ERR_UNKNOWN_OBJECT; + } + + HILOG_INFO("Releasing data ability '%{public}s'...", it->first.c_str()); + dataAbilityRecord->RemoveClient(client, isSystem); + + if (DEBUG_ENABLED) { + DumpLocked(__func__, __LINE__); + } + + return ERR_OK; +} + +int DataAbilityManager::AttachAbilityThread(const sptr &scheduler, const sptr &token) +{ + HILOG_DEBUG("%{public}s(%{public}d)", __PRETTY_FUNCTION__, __LINE__); + + CHECK_POINTER_AND_RETURN(scheduler, ERR_NULL_OBJECT); + CHECK_POINTER_AND_RETURN(token, ERR_NULL_OBJECT); + + std::lock_guard locker(mutex_); + + if (DEBUG_ENABLED) { + DumpLocked(__func__, __LINE__); + } + + HILOG_INFO("Attaching data ability..."); + + DataAbilityRecordPtrMap::iterator it = dataAbilityRecordsLoading_.begin(); + DataAbilityRecordPtr dataAbilityRecord; + auto record = Token::GetAbilityRecordByToken(token); + std::string abilityName = ""; + if (record != nullptr) { + abilityName = record->GetAbilityInfo().name; + } + for (it = dataAbilityRecordsLoading_.begin(); it != dataAbilityRecordsLoading_.end(); ++it) { + if (it->second->GetToken() == token) { + dataAbilityRecord = it->second; + break; + } + } + + if (!dataAbilityRecord) { + HILOG_ERROR("Attaching data ability '%{public}s' is not in loading state.", abilityName.c_str()); + return ERR_UNKNOWN_OBJECT; + } + + if (DEBUG_ENABLED && dataAbilityRecord->GetClientCount() > 0) { + HILOG_ERROR("BUG: Attaching data ability '%{public}s' has clients.", abilityName.c_str()); + } + + if (DEBUG_ENABLED && dataAbilityRecord->GetScheduler()) { + HILOG_ERROR("BUG: Attaching data ability '%{public}s' has ready.", abilityName.c_str()); + } + + if (DEBUG_ENABLED && dataAbilityRecordsLoaded_.count(it->first) != 0) { + HILOG_ERROR("BUG: The attaching data ability '%{public}s' has already existed.", abilityName.c_str()); + } + + return dataAbilityRecord->Attach(scheduler); +} + +int DataAbilityManager::AbilityTransitionDone(const sptr &token, int state) +{ + HILOG_DEBUG("%{public}s(%{public}d)", __PRETTY_FUNCTION__, __LINE__); + + CHECK_POINTER_AND_RETURN(token, ERR_NULL_OBJECT); + + std::lock_guard locker(mutex_); + + if (DEBUG_ENABLED) { + DumpLocked(__func__, __LINE__); + } + + HILOG_INFO("Handling data ability transition done %{public}d...", state); + + DataAbilityRecordPtrMap::iterator it; + DataAbilityRecordPtr dataAbilityRecord; + auto record = Token::GetAbilityRecordByToken(token); + std::string abilityName = ""; + if (record != nullptr) { + abilityName = record->GetAbilityInfo().name; + } + for (it = dataAbilityRecordsLoading_.begin(); it != dataAbilityRecordsLoading_.end(); ++it) { + if (it->second->GetToken() == token) { + dataAbilityRecord = it->second; + break; + } + } + if (!dataAbilityRecord) { + HILOG_ERROR("Attaching data ability '%{public}s' is not existed.", abilityName.c_str()); + return ERR_UNKNOWN_OBJECT; + } + + int ret = dataAbilityRecord->OnTransitionDone(state); + if (ret == ERR_OK) { + dataAbilityRecordsLoaded_[it->first] = dataAbilityRecord; + dataAbilityRecordsLoading_.erase(it); + } + + return ret; +} + +void DataAbilityManager::OnAbilityRequestDone(const sptr &token, const int32_t state) +{ + /* Do nothing now. */ +} + +void DataAbilityManager::OnAbilityDied(const std::shared_ptr &abilityRecord) +{ + HILOG_DEBUG("%{public}s(%{public}d)", __PRETTY_FUNCTION__, __LINE__); + + CHECK_POINTER(abilityRecord); + + std::lock_guard locker(mutex_); + + if (DEBUG_ENABLED) { + DumpLocked(__func__, __LINE__); + } + + if (abilityRecord->GetAbilityInfo().type == AppExecFwk::AbilityType::DATA) { + // If 'abilityRecord' is a data ability server, trying to remove it from 'dataAbilityRecords_'. + for (auto it = dataAbilityRecordsLoaded_.begin(); it != dataAbilityRecordsLoaded_.end(); ++it) { + if (it->second->GetAbilityRecord() == abilityRecord) { + it->second->KillBoundClientProcesses(); + HILOG_DEBUG("Removing died data ability record..."); + dataAbilityRecordsLoaded_.erase(it); + break; + } + } + } + + if (DEBUG_ENABLED) { + DumpLocked(__func__, __LINE__); + } + + // If 'abilityRecord' is a data ability client, tring to remove it from all servers. + for (auto it = dataAbilityRecordsLoaded_.begin(); it != dataAbilityRecordsLoaded_.end(); ++it) { + it->second->RemoveClients(abilityRecord); + } + + if (DEBUG_ENABLED) { + DumpLocked(__func__, __LINE__); + } +} + +void DataAbilityManager::OnAppStateChanged(const AppInfo &info) +{ + std::lock_guard locker(mutex_); + + for (auto it = dataAbilityRecordsLoaded_.begin(); it != dataAbilityRecordsLoaded_.end(); ++it) { + auto abilityRecord = it->second->GetAbilityRecord(); + if (abilityRecord && abilityRecord->GetApplicationInfo().name == info.appName && + (info.processName == abilityRecord->GetAbilityInfo().process || + info.processName == abilityRecord->GetApplicationInfo().bundleName)) { + abilityRecord->SetAppState(info.state); + } + } + + for (auto it = dataAbilityRecordsLoading_.begin(); it != dataAbilityRecordsLoading_.end(); ++it) { + auto abilityRecord = it->second->GetAbilityRecord(); + if (abilityRecord && abilityRecord->GetApplicationInfo().name == info.appName && + (info.processName == abilityRecord->GetAbilityInfo().process || + info.processName == abilityRecord->GetApplicationInfo().bundleName)) { + abilityRecord->SetAppState(info.state); + } + } +} + +std::shared_ptr DataAbilityManager::GetAbilityRecordById(int64_t id) +{ + HILOG_DEBUG("%{public}s(%{public}d)", __PRETTY_FUNCTION__, __LINE__); + + std::lock_guard locker(mutex_); + + for (auto it = dataAbilityRecordsLoaded_.begin(); it != dataAbilityRecordsLoaded_.end(); ++it) { + auto abilityRecord = it->second->GetAbilityRecord(); + if (abilityRecord->GetRecordId() == id) { + return abilityRecord; + } + } + + return nullptr; +} + +std::shared_ptr DataAbilityManager::GetAbilityRecordByToken(const sptr &token) +{ + HILOG_INFO("%{public}s(%{public}d)", __PRETTY_FUNCTION__, __LINE__); + + CHECK_POINTER_AND_RETURN(token, nullptr); + + std::lock_guard locker(mutex_); + for (auto it = dataAbilityRecordsLoaded_.begin(); it != dataAbilityRecordsLoaded_.end(); ++it) { + auto abilityRecord = it->second->GetAbilityRecord(); + if (abilityRecord == Token::GetAbilityRecordByToken(token)) { + return abilityRecord; + } + } + for (auto it = dataAbilityRecordsLoading_.begin(); it != dataAbilityRecordsLoading_.end(); ++it) { + auto abilityRecord = it->second->GetAbilityRecord(); + if (abilityRecord == Token::GetAbilityRecordByToken(token)) { + return abilityRecord; + } + } + return nullptr; +} + +std::shared_ptr DataAbilityManager::GetAbilityRecordByScheduler(const sptr &scheduler) +{ + HILOG_DEBUG("%{public}s(%{public}d)", __PRETTY_FUNCTION__, __LINE__); + + CHECK_POINTER_AND_RETURN(scheduler, nullptr); + + std::lock_guard locker(mutex_); + + for (auto it = dataAbilityRecordsLoaded_.begin(); it != dataAbilityRecordsLoaded_.end(); ++it) { + if (it->second->GetScheduler() != nullptr && it->second->GetScheduler()->AsObject() == scheduler->AsObject()) { + return it->second->GetAbilityRecord(); + } + } + + return nullptr; +} + +void DataAbilityManager::Dump(const char *func, int line) +{ + HILOG_DEBUG("%{public}s(%{public}d)", __PRETTY_FUNCTION__, __LINE__); + + std::lock_guard locker(mutex_); + + DumpLocked(func, line); +} + +DataAbilityManager::DataAbilityRecordPtr DataAbilityManager::LoadLocked( + const std::string &name, const AbilityRequest &req) +{ + HILOG_DEBUG("%{public}s(%{public}d) name '%{public}s'", __PRETTY_FUNCTION__, __LINE__, name.c_str()); + + DataAbilityRecordPtr dataAbilityRecord; + + auto it = dataAbilityRecordsLoading_.find(name); + if (it == dataAbilityRecordsLoading_.end()) { + HILOG_INFO("Acquiring data ability is not in loading, trying to load it..."); + + dataAbilityRecord = std::make_shared(req); + if (!dataAbilityRecord) { + HILOG_ERROR("Failed to allocate data ability record."); + return nullptr; + } + + // Start data ability loading process asynchronously. + int startResult = dataAbilityRecord->StartLoading(); + if (startResult != ERR_OK) { + HILOG_ERROR("Failed to load data ability %{public}d", startResult); + return nullptr; + } + + auto insertResult = dataAbilityRecordsLoading_.insert( {name, dataAbilityRecord} ); + if (!insertResult.second) { + HILOG_ERROR("Failed to insert data ability to loading map."); + return nullptr; + } + } else { + HILOG_INFO("Acquired data ability is loading..."); + dataAbilityRecord = it->second; + } + + HILOG_INFO("Waiting for data ability loaded..."); + + // Waiting for data ability loaded. + int ret = dataAbilityRecord->WaitForLoaded(mutex_, DATA_ABILITY_LOAD_TIMEOUT); + if (ret != ERR_OK) { + HILOG_ERROR("Wait for data ability failed %{public}d.", ret); + it = dataAbilityRecordsLoading_.find(name); + if (it != dataAbilityRecordsLoading_.end()) { + dataAbilityRecordsLoading_.erase(it); + } + return nullptr; + } + + return dataAbilityRecord; +} + +void DataAbilityManager::DumpLocked(const char *func, int line) +{ + if (func && line >= 0) { + HILOG_INFO("Data ability manager dump at %{public}s(%{public}d)", func, line); + } else { + HILOG_INFO("Data ability manager dump"); + } + + HILOG_INFO("Available data ability count: %{public}zu", dataAbilityRecordsLoaded_.size()); + + for (auto it = dataAbilityRecordsLoaded_.begin(); it != dataAbilityRecordsLoaded_.end(); ++it) { + HILOG_INFO("'%{public}s':", it->first.c_str()); + it->second->Dump(); + } + + HILOG_INFO("Loading data ability count: %{public}zu", dataAbilityRecordsLoading_.size()); + + for (auto it = dataAbilityRecordsLoading_.begin(); it != dataAbilityRecordsLoading_.end(); ++it) { + HILOG_INFO("'%{public}s':", it->first.c_str()); + it->second->Dump(); + } +} + +void DataAbilityManager::DumpState(std::vector &info, const std::string &args) const +{ + if (!args.empty()) { + auto it = std::find_if(dataAbilityRecordsLoaded_.begin(), + dataAbilityRecordsLoaded_.end(), + [&args](const auto &dataAbilityRecord) { return dataAbilityRecord.first.compare(args) == 0; }); + if (it != dataAbilityRecordsLoaded_.end()) { + info.emplace_back("AbilityName [ " + it->first + " ]"); + it->second->Dump(info); + } else { + info.emplace_back(args + ": Nothing to dump."); + } + } else { + info.emplace_back("dataAbilityRecords:"); + for (auto &&dataAbilityRecord : dataAbilityRecordsLoaded_) { + info.emplace_back(" uri [" + dataAbilityRecord.first + "]"); + dataAbilityRecord.second->Dump(info); + } + } + return; +} +} // namespace AAFwk +} // namespace OHOS diff --git a/tools/services/abilitymgr/src/data_ability_record.cpp b/tools/services/abilitymgr/src/data_ability_record.cpp new file mode 100644 index 00000000000..91b3cd27327 --- /dev/null +++ b/tools/services/abilitymgr/src/data_ability_record.cpp @@ -0,0 +1,560 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "data_ability_record.h" + +#include +#include "hilog_wrapper.h" +#include "ability_util.h" +#include "app_scheduler.h" + +namespace OHOS { +namespace AAFwk { +DataAbilityRecord::DataAbilityRecord(const AbilityRequest &req) : request_(req) +{ + HILOG_DEBUG("%{public}s(%{public}d)", __PRETTY_FUNCTION__, __LINE__); + + if (request_.abilityInfo.type != AppExecFwk::AbilityType::DATA) { + HILOG_ERROR("BUG: Construct a data ability with wrong ability type."); + } +} + +DataAbilityRecord::~DataAbilityRecord() +{ + HILOG_DEBUG("%{public}s(%{public}d)", __PRETTY_FUNCTION__, __LINE__); +} + +int DataAbilityRecord::StartLoading() +{ + HILOG_INFO("Start data ability loading..."); + + if (ability_ || scheduler_) { + HILOG_ERROR("Data ability already started."); + return ERR_ALREADY_EXISTS; + } + + if (request_.abilityInfo.type != AppExecFwk::AbilityType::DATA) { + HILOG_ERROR("Start a data ability with wrong ability type."); + return ERR_INVALID_VALUE; + } + + auto ability = AbilityRecord::CreateAbilityRecord(request_); + if (!ability) { + HILOG_ERROR("Failed to allocate ability for DataAbilityRecord."); + return ERR_NO_MEMORY; + } + + int ret = ability->LoadAbility(); + if (ret != ERR_OK) { + HILOG_ERROR("Failed to start data ability loading."); + return ret; + } + + ability_ = ability; + + // Ability state is 'INITIAL' now. + + return ERR_OK; +} + +int DataAbilityRecord::WaitForLoaded(std::mutex &mutex, const std::chrono::system_clock::duration &timeout) +{ + CHECK_POINTER_AND_RETURN(ability_, ERR_INVALID_STATE); + + // Data ability uses 'ACTIVATE' as loaded state. + if (ability_->GetAbilityState() == ACTIVE) { + return ERR_OK; + } + + auto ret = loadedCond_.wait_for(mutex, timeout, [this] { return ability_->GetAbilityState() == ACTIVE; }); + + if (!ret) { + return ERR_TIMED_OUT; + } + + if (!scheduler_ || ability_->GetAbilityState() != ACTIVE) { + return ERR_INVALID_STATE; + } + + return ERR_OK; +} + +sptr DataAbilityRecord::GetScheduler() +{ + // Check if data ability is attached. + CHECK_POINTER_AND_RETURN(ability_, nullptr); + CHECK_POINTER_AND_RETURN(scheduler_, nullptr); + + // Check if data ability is loaded. + if (ability_->GetAbilityState() != ACTIVE) { + return nullptr; + } + + return scheduler_; +} + +int DataAbilityRecord::Attach(const sptr &scheduler) +{ + HILOG_DEBUG("%{public}s(%{public}d)", __PRETTY_FUNCTION__, __LINE__); + + if (!scheduler) { + HILOG_ERROR("Attach data ability: invalid scheduler."); + return ERR_INVALID_DATA; + } + + if (!ability_) { + HILOG_ERROR("Data ability attach: not startloading."); + return ERR_INVALID_STATE; + } + + if (scheduler_) { + HILOG_ERROR("Attach data ability: already attached."); + return ERR_INVALID_STATE; + } + + // INITIAL => ACTIVATING + + if (ability_->GetAbilityState() != INITIAL) { + HILOG_ERROR("Attaching data ability: not in 'INITIAL' state."); + return ERR_INVALID_STATE; + } + + HILOG_DEBUG("Attaching data ability..."); + ability_->SetScheduler(scheduler); + scheduler_ = scheduler; + + HILOG_INFO("Scheduling 'OnStart' for data ability '%{public}s|%{public}s'...", + ability_->GetApplicationInfo().bundleName.c_str(), + ability_->GetAbilityInfo().name.c_str()); + + ability_->SetAbilityState(ACTIVATING); + + LifeCycleStateInfo state; + state.state = AbilityLifeCycleState::ABILITY_STATE_ACTIVE; + + scheduler->ScheduleAbilityTransaction(ability_->GetWant(), state); + + return ERR_OK; +} + +int DataAbilityRecord::OnTransitionDone(int state) +{ + CHECK_POINTER_AND_RETURN(ability_, ERR_INVALID_STATE); + CHECK_POINTER_AND_RETURN(scheduler_, ERR_INVALID_STATE); + + if (ability_->GetAbilityState() != ACTIVATING) { + HILOG_ERROR("Data ability on transition done: not in 'ACTIVATING' state."); + return ERR_INVALID_STATE; + } + + if (state != AbilityLifeCycleState::ABILITY_STATE_ACTIVE) { + HILOG_ERROR("Data ability on transition done: not ACTIVE."); + ability_->SetAbilityState(INITIAL); + loadedCond_.notify_all(); + return ERR_INVALID_STATE; + } + + // ACTIVATING => ACTIVE(loaded): + // Set loaded state, data ability uses 'ACTIVE' as loaded state. + + ability_->SetAbilityState(ACTIVE); + loadedCond_.notify_all(); + + HILOG_INFO("Data ability '%{public}s|%{public}s' is loaded.", + ability_->GetApplicationInfo().bundleName.c_str(), + ability_->GetAbilityInfo().name.c_str()); + + return ERR_OK; +} + +int DataAbilityRecord::AddClient(const sptr &client, bool tryBind, bool isSystem) +{ + HILOG_INFO("Adding data ability client..."); + + if (!client) { + HILOG_ERROR("Data ability add client: invalid param."); + return ERR_INVALID_STATE; + } + + if (!ability_ || !scheduler_) { + HILOG_ERROR("Data ability add client: not attached."); + return ERR_INVALID_STATE; + } + + if (ability_->GetAbilityState() != ACTIVE) { + HILOG_ERROR("Data ability add client: not loaded."); + return ERR_INVALID_STATE; + } + + auto appScheduler = DelayedSingleton::GetInstance(); + if (!appScheduler) { + HILOG_ERROR("Data ability add client: failed to get app scheduler."); + return ERR_NULL_OBJECT; + } + + if (isSystem) { + HILOG_ERROR("When the caller is system,add death monitoring"); + if (client != nullptr && callerDeathRecipient_ != nullptr) { + client->RemoveDeathRecipient(callerDeathRecipient_); + } + if (callerDeathRecipient_ == nullptr) { + callerDeathRecipient_ = new DataAbilityCallerRecipient( + std::bind(&DataAbilityRecord::OnSchedulerDied, this, std::placeholders::_1)); + } + if (client != nullptr) { + client->AddDeathRecipient(callerDeathRecipient_); + } + } + + // One client can be added multi-times, so 'RemoveClient()' must be called in corresponding times. + auto &clientInfo = clients_.emplace_back(); + clientInfo.client = client; + clientInfo.tryBind = tryBind; + clientInfo.isSystem = isSystem; + if (!isSystem) { + auto clientAbilityRecord = Token::GetAbilityRecordByToken(client); + CHECK_POINTER_AND_RETURN(clientAbilityRecord, ERR_UNKNOWN_OBJECT); + appScheduler->AbilityBehaviorAnalysis(ability_->GetToken(), clientAbilityRecord->GetToken(), 0, 0, 1); + HILOG_INFO("Ability ability '%{public}s|%{public}s'.", + clientAbilityRecord->GetApplicationInfo().bundleName.c_str(), + clientAbilityRecord->GetAbilityInfo().name.c_str()); + } + + if (clients_.size() == 1) { + HILOG_INFO("Moving data ability app to foreground..."); + appScheduler->MoveToForground(ability_->GetToken()); + } + + HILOG_INFO("Data ability '%{public}s|%{public}s'.", + ability_->GetApplicationInfo().bundleName.c_str(), + ability_->GetAbilityInfo().name.c_str()); + + return ERR_OK; +} + +int DataAbilityRecord::RemoveClient(const sptr &client, bool isSystem) +{ + HILOG_INFO("Removing data ability client..."); + + if (!client) { + HILOG_ERROR("Data ability remove client: invalid client."); + return ERR_INVALID_STATE; + } + + if (!ability_ || !scheduler_) { + HILOG_ERROR("Data ability remove clients: not attached."); + return ERR_INVALID_STATE; + } + + if (ability_->GetAbilityState() != ACTIVE) { + HILOG_ERROR("Data ability remove client: not loaded."); + return ERR_INVALID_STATE; + } + + if (clients_.empty()) { + HILOG_DEBUG("BUG: Data ability record has no clients."); + return ERR_OK; + } + + auto appScheduler = DelayedSingleton::GetInstance(); + if (!appScheduler) { + HILOG_ERROR("Data ability record remove client: invalid app scheduler."); + return ERR_NULL_OBJECT; + } + + for (auto it(clients_.begin()); it != clients_.end(); ++it) { + if (it->client == client) { + if (!isSystem) { + auto clientAbilityRecord = Token::GetAbilityRecordByToken(client); + CHECK_POINTER_AND_RETURN(clientAbilityRecord, ERR_UNKNOWN_OBJECT); + appScheduler->AbilityBehaviorAnalysis(ability_->GetToken(), clientAbilityRecord->GetToken(), 0, 0, 0); + HILOG_INFO("Ability ability '%{public}s|%{public}s'.", + clientAbilityRecord->GetApplicationInfo().bundleName.c_str(), + clientAbilityRecord->GetAbilityInfo().name.c_str()); + } + clients_.erase(it); + HILOG_INFO("Data ability '%{public}s|%{public}s'.", + ability_->GetApplicationInfo().bundleName.c_str(), + ability_->GetAbilityInfo().name.c_str()); + break; + } + } + + if (clients_.empty()) { + HILOG_INFO("Moving data ability to background..."); + appScheduler->MoveToBackground(ability_->GetToken()); + } + + return ERR_OK; +} + +int DataAbilityRecord::RemoveClients(const std::shared_ptr &client) +{ + HILOG_DEBUG("%{public}s(%{public}d)", __PRETTY_FUNCTION__, __LINE__); + + if (!ability_ || !scheduler_) { + HILOG_ERROR("Data ability remove clients: not attached."); + return ERR_INVALID_STATE; + } + + if (ability_->GetAbilityState() != ACTIVE) { + HILOG_ERROR("Data ability remove clients: not loaded."); + return ERR_INVALID_STATE; + } + + if (clients_.empty()) { + HILOG_DEBUG("Data ability remove clients: no clients."); + return ERR_OK; + } + + auto appScheduler = DelayedSingleton::GetInstance(); + if (!appScheduler) { + HILOG_ERROR("Data ability remove clients: invalid app scheduler."); + return ERR_NULL_OBJECT; + } + + if (client) { + HILOG_DEBUG("Removing data ability clients with filter..."); + auto it = clients_.begin(); + while (it != clients_.end()) { + if (!it->isSystem) { + auto clientAbilityRecord = Token::GetAbilityRecordByToken(it->client); + CHECK_POINTER_CONTINUE(clientAbilityRecord); + if (clientAbilityRecord == client) { + appScheduler->AbilityBehaviorAnalysis( + ability_->GetToken(), clientAbilityRecord->GetToken(), 0, 0, 0); + it = clients_.erase(it); + HILOG_INFO("Ability '%{public}s|%{public}s' --X-> Data ability '%{public}s|%{public}s'.", + client->GetApplicationInfo().bundleName.c_str(), + client->GetAbilityInfo().name.c_str(), + ability_->GetApplicationInfo().bundleName.c_str(), + ability_->GetAbilityInfo().name.c_str()); + } else { + ++it; + } + } else { + ++it; + } + } + } else { + HILOG_DEBUG("Removing data ability clients..."); + auto it = clients_.begin(); + while (it != clients_.end()) { + if (!it->isSystem) { + auto clientAbilityRecord = Token::GetAbilityRecordByToken(it->client); + if (!clientAbilityRecord) { + HILOG_DEBUG("clientAbilityRecord is null,clear record"); + it = clients_.erase(it); + continue; + } + appScheduler->AbilityBehaviorAnalysis(ability_->GetToken(), clientAbilityRecord->GetToken(), 0, 0, 0); + it = clients_.erase(it); + HILOG_INFO("Ability '%{public}s|%{public}s' --X-> Data ability '%{public}s|%{public}s'.", + client->GetApplicationInfo().bundleName.c_str(), + client->GetAbilityInfo().name.c_str(), + ability_->GetApplicationInfo().bundleName.c_str(), + ability_->GetAbilityInfo().name.c_str()); + } else { + ++it; + } + } + } + + if (clients_.empty()) { + HILOG_INFO("Moving data ability to background..."); + appScheduler->MoveToBackground(ability_->GetToken()); + } + + return ERR_OK; +} + +size_t DataAbilityRecord::GetClientCount(const sptr &client) const +{ + CHECK_POINTER_AND_RETURN(ability_, 0); + CHECK_POINTER_AND_RETURN(scheduler_, 0); + + if (ability_->GetAbilityState() != ACTIVE) { + HILOG_ERROR("Data ability get client count: not loaded."); + return 0; + } + + if (client) { + return std::count_if( + clients_.begin(), clients_.end(), [client](const ClientInfo &ci) { return ci.client == client; }); + } + + return clients_.size(); +} + +int DataAbilityRecord::KillBoundClientProcesses() +{ + CHECK_POINTER_AND_RETURN(ability_, ERR_INVALID_STATE); + CHECK_POINTER_AND_RETURN(scheduler_, ERR_INVALID_STATE); + + if (ability_->GetAbilityState() != ACTIVE) { + HILOG_ERROR("Data ability kill bound clients: not loaded."); + return ERR_INVALID_STATE; + } + + auto appScheduler = DelayedSingleton::GetInstance(); + if (!appScheduler) { + HILOG_ERROR("Data ability kill bound clients: invalid app scheduler."); + return ERR_INVALID_STATE; + } + + for (auto it = clients_.begin(); it != clients_.end(); ++it) { + if (it->tryBind && false == it->isSystem) { + auto clientAbilityRecord = Token::GetAbilityRecordByToken(it->client); + CHECK_POINTER_CONTINUE(clientAbilityRecord); + HILOG_INFO("Killing bound client '%{public}s|%{public}s' of data ability '%{public}s|%{public}s'...", + clientAbilityRecord->GetApplicationInfo().bundleName.c_str(), + clientAbilityRecord->GetAbilityInfo().name.c_str(), + ability_->GetApplicationInfo().bundleName.c_str(), + ability_->GetAbilityInfo().name.c_str()); + appScheduler->KillProcessByAbilityToken(clientAbilityRecord->GetToken()); + } + } + + return ERR_OK; +} + +const AbilityRequest &DataAbilityRecord::GetRequest() const +{ + return request_; +} + +std::shared_ptr DataAbilityRecord::GetAbilityRecord() +{ + return ability_; +} + +sptr DataAbilityRecord::GetToken() +{ + if (!ability_) { + return nullptr; + } + + return ability_->GetToken(); +} + +void DataAbilityRecord::Dump() const +{ + CHECK_POINTER(ability_); + + HILOG_INFO("attached: %{public}s, clients: %{public}zu, refcnt: %{public}d, state: %{public}s", + scheduler_ ? "true" : "false", + clients_.size(), + scheduler_ ? scheduler_->GetSptrRefCount() : 0, + AbilityRecord::ConvertAbilityState(ability_->GetAbilityState()).c_str()); + + int i = 0; + + for (auto it = clients_.begin(); it != clients_.end(); ++it) { + if (false == it->isSystem) { + auto clientAbilityRecord = Token::GetAbilityRecordByToken(it->client); + CHECK_POINTER_CONTINUE(clientAbilityRecord); + HILOG_INFO(" %{public}2d '%{public}s|%{public}s' - tryBind: %{public}s", + i++, + clientAbilityRecord->GetApplicationInfo().bundleName.c_str(), + clientAbilityRecord->GetAbilityInfo().name.c_str(), + it->tryBind ? "true" : "false"); + } else { + HILOG_INFO(" %{public}2d '%{public}s' - tryBind: %{public}s", + i++, + "caller is system", + it->tryBind ? "true" : "false"); + } + } +} + +void DataAbilityRecord::Dump(std::vector &info) const +{ + CHECK_POINTER(ability_); + info.emplace_back(" AbilityRecord ID #" + std::to_string(ability_->GetRecordId()) + " state #" + + AbilityRecord::ConvertAbilityState(ability_->GetAbilityState()) + " start time [" + + std::to_string(ability_->GetStartTime()) + "]"); + info.emplace_back(" main name [" + ability_->GetAbilityInfo().name + "]"); + info.emplace_back(" bundle name [" + ability_->GetAbilityInfo().bundleName + "]"); + info.emplace_back(" ability type [DATA]"); + info.emplace_back(" app state #" + AbilityRecord::ConvertAppState(ability_->GetAppState())); + info.emplace_back(" Clients: " + std::to_string(clients_.size())); + + for (auto &&client : clients_) { + if (false == client.isSystem) { + auto clientAbilityRecord = Token::GetAbilityRecordByToken(client.client); + CHECK_POINTER_CONTINUE(clientAbilityRecord); + info.emplace_back(" > " + clientAbilityRecord->GetAbilityInfo().bundleName + "/" + + clientAbilityRecord->GetAbilityInfo().name + " tryBind #" + + (client.tryBind ? "true" : "false") + " isSystem # " + + (client.isSystem ? "true" : "false")); + } else { + info.emplace_back(std::string(" > Caller is System / tryBind # ") + + (client.tryBind ? "true" : "false") + " isSystem # " + + (client.isSystem ? "true" : "false")); + } + } +} + +void DataAbilityRecord::OnSchedulerDied(const wptr &remote) +{ + HILOG_INFO("'%{public}s':", __func__); + auto object = remote.promote(); + + if (clients_.empty()) { + HILOG_DEBUG("BUG: Data ability record has no clients."); + return; + } + + auto appScheduler = DelayedSingleton::GetInstance(); + if (!appScheduler) { + HILOG_ERROR("Data ability remove clients: invalid app scheduler."); + return; + } + + if (object) { + auto it = clients_.begin(); + while (it != clients_.end()) { + if (it->client == object) { + HILOG_DEBUG("remove system caller record with filter..."); + it = clients_.erase(it); + HILOG_INFO("Data ability '%{public}s|%{public}s'.", + ability_->GetApplicationInfo().bundleName.c_str(), + ability_->GetAbilityInfo().name.c_str()); + } else { + ++it; + } + } + } else { + auto it = clients_.begin(); + while (it != clients_.end()) { + if (it->isSystem) { + HILOG_DEBUG("remove system caller record..."); + it = clients_.erase(it); + HILOG_INFO("Data ability '%{public}s|%{public}s'.", + ability_->GetApplicationInfo().bundleName.c_str(), + ability_->GetAbilityInfo().name.c_str()); + } else { + ++it; + } + } + } + + if (clients_.empty()) { + HILOG_INFO("Moving data ability to background..."); + appScheduler->MoveToBackground(ability_->GetToken()); + } +} +} // namespace AAFwk +} // namespace OHOS diff --git a/tools/services/abilitymgr/src/image_info.cpp b/tools/services/abilitymgr/src/image_info.cpp new file mode 100644 index 00000000000..ce17e36c506 --- /dev/null +++ b/tools/services/abilitymgr/src/image_info.cpp @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "image_info.h" + +#include "string_ex.h" +#include "nlohmann/json.hpp" +#include "hilog_wrapper.h" + +namespace OHOS { +namespace AAFwk { +bool ImageHeader::ReadFromParcel(Parcel &parcel) +{ + colorMode = parcel.ReadUint32(); + reserved = parcel.ReadUint32(); + width = parcel.ReadUint16(); + height = parcel.ReadUint16(); + return true; +} + +ImageHeader *ImageHeader::Unmarshalling(Parcel &parcel) +{ + ImageHeader *info = new (std::nothrow) ImageHeader(); + if (info == nullptr) { + return nullptr; + } + + if (!info->ReadFromParcel(parcel)) { + delete info; + info = nullptr; + } + return info; +} + +bool ImageHeader::Marshalling(Parcel &parcel) const +{ + parcel.WriteUint32(colorMode); + parcel.WriteUint32(reserved); + parcel.WriteUint16(width); + parcel.WriteUint16(height); + return true; +} + +bool ImageInfo::ReadFromParcel(Parcel &parcel) +{ + return false; +} + +ImageInfo *ImageInfo::Unmarshalling(Parcel &parcel) +{ + ImageInfo *info = new (std::nothrow) ImageInfo(); + if (info == nullptr) { + return nullptr; + } + + if (!info->ReadFromParcel(parcel)) { + delete info; + info = nullptr; + } + return info; +} + +bool ImageInfo::Marshalling(Parcel &parcel) const +{ + return false; +} +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/abilitymgr/src/kernal_system_app_manager.cpp b/tools/services/abilitymgr/src/kernal_system_app_manager.cpp new file mode 100644 index 00000000000..a609d93a4f3 --- /dev/null +++ b/tools/services/abilitymgr/src/kernal_system_app_manager.cpp @@ -0,0 +1,393 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "kernal_system_app_manager.h" +#include "hilog_wrapper.h" +#include "ability_util.h" +#include "ability_manager_errors.h" +#include "ability_manager_service.h" +#include "app_scheduler.h" + +namespace OHOS { +namespace AAFwk { +KernalSystemAppManager::KernalSystemAppManager(int userId) : userId_(userId) +{} + +KernalSystemAppManager::~KernalSystemAppManager() +{} + +int KernalSystemAppManager::StartAbility(const AbilityRequest &abilityRequest) +{ + HILOG_INFO("start kernal systerm ability."); + std::lock_guard guard(stackLock_); + if (!waittingAbilityQueue_.empty()) { + HILOG_INFO("waiting queue is not empty, so enqueue systerm ui ability for waiting."); + EnqueueWaittingAbility(abilityRequest); + return START_ABILITY_WAITING; + } + + std::shared_ptr topAbilityRecord = GetCurrentTopAbility(); + auto requestFlag = GetFlagOfAbility(abilityRequest.abilityInfo.bundleName, abilityRequest.abilityInfo.name); + if (topAbilityRecord != nullptr) { + auto topFlag = + GetFlagOfAbility(topAbilityRecord->GetAbilityInfo().bundleName, topAbilityRecord->GetAbilityInfo().name); + if (topFlag == requestFlag && topAbilityRecord->GetAbilityState() == INITIAL) { + HILOG_INFO("top systerm ui ability need to restart."); + } + if (topAbilityRecord->GetAbilityState() == ACTIVATING) { + HILOG_INFO("top systerm ui ability is not active, so enqueue ability for waiting."); + EnqueueWaittingAbility(abilityRequest); + return START_ABILITY_WAITING; + } + } + + return StartAbilityLocked(abilityRequest); +} + +int KernalSystemAppManager::StartAbilityLocked(const AbilityRequest &abilityRequest) +{ + std::shared_ptr targetAbility; + GetOrCreateAbilityRecord(abilityRequest, targetAbility); + CHECK_POINTER_AND_RETURN(targetAbility, ERR_INVALID_VALUE); + targetAbility->SetKernalSystemAbility(); + + HILOG_INFO("Load kernal system ability, bundleName:%{public}s , abilityName:%{public}s", + abilityRequest.abilityInfo.bundleName.c_str(), + abilityRequest.abilityInfo.name.c_str()); + + if (targetAbility->IsAbilityState(AbilityState::ACTIVE) || + targetAbility->IsAbilityState(AbilityState::ACTIVATING)) { + HILOG_INFO("kernal system ability is already activing or activated."); + targetAbility->Activate(); + return ERR_OK; + } + return targetAbility->LoadAbility(); +} + +int KernalSystemAppManager::AttachAbilityThread( + const sptr &scheduler, const sptr &token) +{ + HILOG_INFO("Attach ability thread."); + std::lock_guard guard(stackLock_); + auto abilityRecord = GetAbilityRecordByToken(token); + CHECK_POINTER_AND_RETURN(abilityRecord, ERR_INVALID_VALUE); + + std::string flag = KernalSystemAppManager::GetFlagOfAbility( + abilityRecord->GetAbilityInfo().bundleName, abilityRecord->GetAbilityInfo().name); + HILOG_INFO("ability: %{public}s", flag.c_str()); + + auto handler = DelayedSingleton::GetInstance()->GetEventHandler(); + CHECK_POINTER_AND_RETURN(handler, ERR_INVALID_VALUE); + + handler->RemoveEvent(AbilityManagerService::LOAD_TIMEOUT_MSG, abilityRecord->GetEventId()); + + abilityRecord->SetScheduler(scheduler); + DelayedSingleton::GetInstance()->MoveToForground(token); + + return ERR_OK; +} + +void KernalSystemAppManager::OnAbilityRequestDone(const sptr &token, const int32_t state) +{ + HILOG_INFO("On ability request done."); + std::lock_guard guard(stackLock_); + AppAbilityState abilitState = DelayedSingleton::GetInstance()->ConvertToAppAbilityState(state); + if (abilitState == AppAbilityState::ABILITY_STATE_FOREGROUND) { + auto abilityRecord = GetAbilityRecordByToken(token); + CHECK_POINTER(abilityRecord); + abilityRecord->Activate(); + } +} + +void KernalSystemAppManager::OnAppStateChanged(const AppInfo &info) +{ + std::lock_guard guard(stackLock_); + for (auto ability : abilities_) { + if (ability && ability->GetApplicationInfo().name == info.appName && + (info.processName == ability->GetAbilityInfo().process || + info.processName == ability->GetApplicationInfo().bundleName)) { + ability->SetAppState(info.state); + } + } +} + +int KernalSystemAppManager::AbilityTransitionDone(const sptr &token, int state) +{ + HILOG_INFO("Ability transition done."); + std::lock_guard guard(stackLock_); + auto abilityRecord = GetAbilityRecordByToken(token); + CHECK_POINTER_AND_RETURN(abilityRecord, ERR_INVALID_VALUE); + + std::string flag = KernalSystemAppManager::GetFlagOfAbility( + abilityRecord->GetAbilityInfo().bundleName, abilityRecord->GetAbilityInfo().name); + int targetState = AbilityRecord::ConvertLifeCycleToAbilityState(static_cast(state)); + std::string abilityState = AbilityRecord::ConvertAbilityState(static_cast(targetState)); + HILOG_INFO("ability: %{public}s, state: %{public}s", flag.c_str(), abilityState.c_str()); + + switch (targetState) { + case AbilityState::ACTIVE: { + return DispatchActive(abilityRecord, targetState); + } + default: { + HILOG_WARN("don't support transiting state: %d", targetState); + return ERR_INVALID_VALUE; + } + } +} + +int KernalSystemAppManager::DispatchActive(const std::shared_ptr &abilityRecord, int state) +{ + auto handler = DelayedSingleton::GetInstance()->GetEventHandler(); + CHECK_POINTER_AND_RETURN(handler, ERR_INVALID_VALUE); + CHECK_POINTER_AND_RETURN(abilityRecord, ERR_INVALID_VALUE); + + if (!abilityRecord->IsAbilityState(AbilityState::ACTIVATING)) { + HILOG_ERROR("kernal ability transition life state error. start:%{public}d", state); + return ERR_INVALID_VALUE; + } + handler->RemoveEvent(AbilityManagerService::ACTIVE_TIMEOUT_MSG, abilityRecord->GetEventId()); + + auto task = [kernalManager = shared_from_this(), abilityRecord]() { kernalManager->CompleteActive(abilityRecord); }; + handler->PostTask(task); + return ERR_OK; +} + +void KernalSystemAppManager::CompleteActive(const std::shared_ptr &abilityRecord) +{ + HILOG_INFO("Complete active."); + std::lock_guard guard(stackLock_); + abilityRecord->SetAbilityState(AbilityState::ACTIVE); + + auto handler = DelayedSingleton::GetInstance()->GetEventHandler(); + CHECK_POINTER(handler); + + auto task = [kernalManager = shared_from_this()]() { kernalManager->DequeueWaittingAbility(); }; + handler->PostTask(task, "DequeueWaittingAbility"); +} + +void KernalSystemAppManager::GetOrCreateAbilityRecord( + const AbilityRequest &abilityRequest, std::shared_ptr &targetAbility) +{ + std::string abilityFlag = KernalSystemAppManager::GetFlagOfAbility( + abilityRequest.abilityInfo.bundleName, abilityRequest.abilityInfo.name); + auto isExist = [targetFlag = abilityFlag](const std::shared_ptr &ability) { + if (ability == nullptr) { + return false; + } + return KernalSystemAppManager::GetFlagOfAbility( + ability->GetAbilityInfo().bundleName, + ability->GetAbilityInfo().name) == targetFlag; + }; + auto iter = std::find_if(abilities_.begin(), abilities_.end(), isExist); + if (iter != abilities_.end()) { + targetAbility = *iter; + targetAbility->SetWant(abilityRequest.want); + targetAbility->SetIsNewWant(true); + return; + } + targetAbility = AbilityRecord::CreateAbilityRecord(abilityRequest); + abilities_.push_front(targetAbility); +} + +std::string KernalSystemAppManager::GetFlagOfAbility(const std::string &bundleName, const std::string &abilityName) +{ + return bundleName + ":" + abilityName; +} + +int KernalSystemAppManager::GetManagerUserId() const +{ + return userId_; +} + +std::shared_ptr KernalSystemAppManager::GetCurrentTopAbility() const +{ + if (abilities_.empty()) { + return nullptr; + } + return abilities_.front(); +} + +std::shared_ptr KernalSystemAppManager::GetAbilityRecordByToken(const sptr &token) +{ + std::lock_guard guard(stackLock_); + auto abilityToFind = Token::GetAbilityRecordByToken(token); + CHECK_POINTER_AND_RETURN(abilityToFind, nullptr); + + auto isExist = [targetAbility = abilityToFind](const std::shared_ptr &ability) { + if (ability == nullptr) { + return false; + } + return targetAbility == ability; + }; + auto iter = std::find_if(abilities_.begin(), abilities_.end(), isExist); + if (iter != abilities_.end()) { + return *iter; + } + + return nullptr; +} + +std::shared_ptr KernalSystemAppManager::GetAbilityRecordByEventId(const int64_t eventId) const +{ + auto isExist = [targetEventId = eventId](const std::shared_ptr &ability) { + if (ability == nullptr) { + return false; + } + return (ability->GetEventId() == targetEventId); + }; + auto iter = std::find_if(abilities_.begin(), abilities_.end(), isExist); + if (iter != abilities_.end()) { + return *iter; + } + return nullptr; +} + +bool KernalSystemAppManager::RemoveAbilityRecord(std::shared_ptr ability) +{ + CHECK_POINTER_RETURN_BOOL(ability); + for (auto iter = abilities_.begin(); iter != abilities_.end(); iter++) { + if ((*iter) == ability) { + abilities_.erase(iter); + return true; + } + } + HILOG_ERROR("can not find ability"); + return false; +} + +void KernalSystemAppManager::EnqueueWaittingAbility(const AbilityRequest &abilityRequest) +{ + waittingAbilityQueue_.push(abilityRequest); + return; +} + +void KernalSystemAppManager::DequeueWaittingAbility() +{ + std::lock_guard guard(stackLock_); + std::shared_ptr topAbility = GetCurrentTopAbility(); + if (topAbility != nullptr && topAbility->GetAbilityState() != ACTIVE) { + HILOG_INFO("top ability is not active, must return for waiting again"); + return; + } + if (!waittingAbilityQueue_.empty()) { + AbilityRequest abilityRequest = waittingAbilityQueue_.front(); + waittingAbilityQueue_.pop(); + HILOG_INFO("bundleName: %{public}s, abilityName: %{public}s", + abilityRequest.abilityInfo.bundleName.c_str(), + abilityRequest.abilityInfo.name.c_str()); + + StartAbilityLocked(abilityRequest); + } +} +void KernalSystemAppManager::DumpState(std::vector &info) +{ + info.emplace_back("SystemUIRecords:"); + for (auto &ability : abilities_) { + ability->Dump(info); + } +} + +void KernalSystemAppManager::OnAbilityDied(std::shared_ptr abilityRecord) +{ + std::lock_guard guard(stackLock_); + CHECK_POINTER(abilityRecord); + if (!abilityRecord->IsKernalSystemAbility()) { + HILOG_ERROR("System UI on scheduler died, ability type is not system ui"); + return; + } + + if (GetAbilityRecordByToken(abilityRecord->GetToken()) == nullptr) { + HILOG_ERROR("System UI on scheduler died, record is not exist."); + return; + } + auto ams = DelayedSingleton::GetInstance(); + CHECK_POINTER(ams); + + auto handler = ams->GetEventHandler(); + CHECK_POINTER(handler); + + HILOG_INFO("System UI on scheduler died: '%{public}s'", abilityRecord->GetAbilityInfo().name.c_str()); + std::string name = abilityRecord->GetAbilityInfo().name; + abilityRecord->SetAbilityState(AbilityState::INITIAL); + auto timeoutTask = [ams, abilityRecord]() { + if (abilityRecord) { + ams->StartSystemUi(abilityRecord->GetAbilityInfo().name); + } + }; + handler->PostTask(timeoutTask, "SystemUi_Die_" + name, AbilityManagerService::RESTART_TIMEOUT); +} +void KernalSystemAppManager::OnTimeOut(uint32_t msgId, int64_t eventId) +{ + std::lock_guard guard(stackLock_); + if (abilities_.empty()) { + HILOG_ERROR("System UI on time out event: ability stack is empty."); + return; + } + + auto abilityRecord = GetAbilityRecordByEventId(eventId); + CHECK_POINTER(abilityRecord); + + auto ams = DelayedSingleton::GetInstance(); + CHECK_POINTER(ams); + + auto handler = ams->GetEventHandler(); + CHECK_POINTER(handler); + + switch (msgId) { + case AbilityManagerService::LOAD_TIMEOUT_MSG: + case AbilityManagerService::ACTIVE_TIMEOUT_MSG: { + std::string bundleName = abilityRecord->GetAbilityInfo().bundleName; + std::string name = abilityRecord->GetAbilityInfo().name; + RemoveAbilityRecord(abilityRecord); + auto task = [ams, bundleName]() { + ams->KillProcess(bundleName); + HILOG_ERROR("System UI on time out event: KillProcess:%{public}s", bundleName.c_str()); + }; + handler->PostTask(task); + auto timeoutTask = [ams, name]() { + ams->StartSystemUi(name); + HILOG_ERROR("System UI on time out event: restart:%{public}s", name.c_str()); + }; + handler->PostTask(timeoutTask, "SystemUi_Timeout_" + name, AbilityManagerService::RESTART_TIMEOUT); + break; + } + default: + break; + } +} + +int KernalSystemAppManager::UpdateConfiguration(const DummyConfiguration &config) +{ + std::lock_guard guard(stackLock_); + std::shared_ptr configPtr = std::make_shared(config); + for (auto &ability : abilities_) { + if (ability) { + if (ability->IsAbilityState(AbilityState::ACTIVE)) { + HILOG_DEBUG("system ui update configuration."); + ability->ForceProcessConfigurationChange(configPtr); + } + } + } + return ERR_OK; +} + +void KernalSystemAppManager::RestartAbility(const std::shared_ptr abilityRecord) +{ + CHECK_POINTER(abilityRecord); + HILOG_DEBUG("Restart ability system ui. %{public}s", abilityRecord->GetAbilityInfo().name.c_str()); + return; +} +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/abilitymgr/src/lifecycle_deal.cpp b/tools/services/abilitymgr/src/lifecycle_deal.cpp new file mode 100644 index 00000000000..25befa3056a --- /dev/null +++ b/tools/services/abilitymgr/src/lifecycle_deal.cpp @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "lifecycle_deal.h" +#include "hilog_wrapper.h" +#include "ability_util.h" +#include "ability_record.h" + +namespace OHOS { +namespace AAFwk { +LifecycleDeal::LifecycleDeal() +{} + +LifecycleDeal::~LifecycleDeal() +{} + +void LifecycleDeal::SetScheduler(const sptr &scheduler) +{ + abilityScheduler_ = scheduler; +} + +void LifecycleDeal::Activate(const Want &want, LifeCycleStateInfo &stateInfo) +{ + HILOG_INFO("Activate."); + CHECK_POINTER(abilityScheduler_); + HILOG_INFO("caller %{public}s, %{public}s, %{public}s", + stateInfo.caller.deviceId.c_str(), + stateInfo.caller.bundleName.c_str(), + stateInfo.caller.abilityName.c_str()); + stateInfo.state = AbilityLifeCycleState::ABILITY_STATE_ACTIVE; + abilityScheduler_->ScheduleAbilityTransaction(want, stateInfo); +} + +void LifecycleDeal::Inactivate(const Want &want, LifeCycleStateInfo &stateInfo) +{ + HILOG_INFO("Inactivate."); + CHECK_POINTER(abilityScheduler_); + stateInfo.state = AbilityLifeCycleState::ABILITY_STATE_INACTIVE; + abilityScheduler_->ScheduleAbilityTransaction(want, stateInfo); +} + +void LifecycleDeal::MoveToBackground(const Want &want, LifeCycleStateInfo &stateInfo) +{ + HILOG_INFO("Move to background."); + CHECK_POINTER(abilityScheduler_); + stateInfo.state = AbilityLifeCycleState::ABILITY_STATE_BACKGROUND; + abilityScheduler_->ScheduleAbilityTransaction(want, stateInfo); +} + +void LifecycleDeal::ConnectAbility(const Want &want) +{ + HILOG_INFO("Connect ability."); + CHECK_POINTER(abilityScheduler_); + abilityScheduler_->ScheduleConnectAbility(want); +} + +void LifecycleDeal::DisconnectAbility(const Want &want) +{ + HILOG_INFO("Disconnect ability."); + CHECK_POINTER(abilityScheduler_); + abilityScheduler_->ScheduleDisconnectAbility(want); +} + +void LifecycleDeal::Terminate(const Want &want, LifeCycleStateInfo &stateInfo) +{ + HILOG_INFO("Terminate."); + CHECK_POINTER(abilityScheduler_); + stateInfo.state = AbilityLifeCycleState::ABILITY_STATE_INITIAL; + abilityScheduler_->ScheduleAbilityTransaction(want, stateInfo); +} + +void LifecycleDeal::CommandAbility(const Want &want, bool reStart, int startId) +{ + HILOG_INFO("Command ability."); + CHECK_POINTER(abilityScheduler_); + abilityScheduler_->ScheduleCommandAbility(want, reStart, startId); +} + +void LifecycleDeal::SaveAbilityState(PacMap &outState) +{ + HILOG_INFO("%{public}s, %{public}d", __func__, __LINE__); + CHECK_POINTER(abilityScheduler_); + abilityScheduler_->ScheduleSaveAbilityState(outState); +} + +void LifecycleDeal::RestoreAbilityState(const PacMap &inState) +{ + HILOG_INFO("%{public}s, %{public}d", __func__, __LINE__); + CHECK_POINTER(abilityScheduler_); + abilityScheduler_->ScheduleRestoreAbilityState(inState); +} + +void LifecycleDeal::UpdateConfiguration(const DummyConfiguration &config) +{ + HILOG_INFO("%{public}s, %{public}d", __func__, __LINE__); + CHECK_POINTER(abilityScheduler_); + abilityScheduler_->ScheduleUpdateConfiguration(config); +} +} // namespace AAFwk +} // namespace OHOS diff --git a/tools/services/abilitymgr/src/lifecycle_state_info.cpp b/tools/services/abilitymgr/src/lifecycle_state_info.cpp new file mode 100644 index 00000000000..0c24ec6b1c6 --- /dev/null +++ b/tools/services/abilitymgr/src/lifecycle_state_info.cpp @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "lifecycle_state_info.h" + +#include "nlohmann/json.hpp" +#include "string_ex.h" + +namespace OHOS { +namespace AAFwk { +bool LifeCycleStateInfo::ReadFromParcel(Parcel &parcel) +{ + isNewWant = parcel.ReadBool(); + int32_t stateData = parcel.ReadInt32(); + state = static_cast(stateData); + missionId = parcel.ReadInt32(); + stackId = parcel.ReadInt32(); + std::unique_ptr callerInfo(parcel.ReadParcelable()); + if (callerInfo == nullptr) { + return false; + } + caller = *callerInfo; + AbilityStartSetting *pSetting = parcel.ReadParcelable(); + if (pSetting != nullptr) { + setting = std::shared_ptr(pSetting); + } else { + setting = nullptr; + } + return true; +} + +LifeCycleStateInfo *LifeCycleStateInfo::Unmarshalling(Parcel &parcel) +{ + LifeCycleStateInfo *info = new (std::nothrow) LifeCycleStateInfo(); + if (info == nullptr) { + return nullptr; + } + + if (!info->ReadFromParcel(parcel)) { + delete info; + info = nullptr; + } + return info; +} + +bool LifeCycleStateInfo::Marshalling(Parcel &parcel) const +{ + // write isNewWant + if (!parcel.WriteBool(isNewWant)) { + return false; + } + // write state + if (!parcel.WriteInt32(static_cast(state))) { + return false; + } + // write missionId + if (!parcel.WriteInt32(missionId)) { + return false; + } + // write stackId + if (!parcel.WriteInt32(stackId)) { + return false; + } + // write caller + if (!parcel.WriteParcelable(&caller)) { + return false; + } + // write setting + if (!parcel.WriteParcelable(setting.get())) { + return false; + } + return true; +} +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/abilitymgr/src/lock_mission_container.cpp b/tools/services/abilitymgr/src/lock_mission_container.cpp new file mode 100644 index 00000000000..e4f1cc9acbd --- /dev/null +++ b/tools/services/abilitymgr/src/lock_mission_container.cpp @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "lock_mission_container.h" + +#include "hilog_wrapper.h" + +namespace OHOS { +namespace AAFwk { +bool LockMissionContainer::IsLockedMissionState() const +{ + return lockState_ != LockMissionState::LOCK_MISSION_STATE_NONE; +} + +int LockMissionContainer::GetLockedMissionState() const +{ + return lockState_; +} + +bool LockMissionContainer::SetLockedMission( + const std::shared_ptr &mission, int lockerUid, bool isSystemApp) +{ + auto lockMission = lockMission_.lock(); + if (lockMission) { + HILOG_WARN("It already exists lock mission , deny lock request. locked mission id :%{public}d, name : " + "%{public}s ,request mission id :%{public}d, name : %{public}s", + lockMission->GetMissionRecordId(), + lockMission->GetName().c_str(), + mission->GetMissionRecordId(), + mission->GetName().c_str()); + return false; + } + + HILOG_INFO("lock mission ID: %{public}d , name : %{public}s lockerUid : %{public}d", + mission->GetMissionRecordId(), + mission->GetName().c_str(), + lockerUid); + lockMission_ = mission; + lockerUid_ = lockerUid; + lockState_ = + isSystemApp ? LockMissionState::LOCK_MISSION_STATE_PINNED : LockMissionState::LOCK_MISSION_STATE_LOCKED; + return true; +} + +bool LockMissionContainer::ReleaseLockedMission( + const std::shared_ptr &mission, int callerUid, bool isForce) +{ + auto lockMission = lockMission_.lock(); + if (lockMission == nullptr) { + HILOG_WARN("There is no locked mission. release locked mission fail."); + return false; + } + + if (isForce && lockMission == mission) { + HILOG_INFO("release lock mission ID: %{public}d , name : %{public}s lockerUid : %{public}d", + lockMission->GetMissionRecordId(), + lockMission->GetName().c_str(), + lockerUid_); + Clear(); + return true; + } + + if (callerUid != lockerUid_) { + HILOG_WARN("caller uid not equal to locker uid. release locked mission fail."); + return false; + } + + if (mission != lockMission) { + HILOG_WARN("unlock mission not equal to locked mission. release locked mission fail."); + return false; + } + + HILOG_INFO("Normal release lock mission ID: %{public}d , name : %{public}s lockerUid : %{public}d", + lockMission->GetMissionRecordId(), + lockMission->GetName().c_str(), + lockerUid_); + + Clear(); + return true; +} + +bool LockMissionContainer::IsSameLockedMission(std::string bundleName) const +{ + auto lockMission = lockMission_.lock(); + if (lockMission == nullptr) { + HILOG_WARN("There is no locked mission. release locked mission fail."); + return false; + } + return lockMission->GetName() == bundleName; +} + +void LockMissionContainer::Clear() +{ + lockMission_.reset(); + lockerUid_ = -1; + lockState_ = LockMissionState::LOCK_MISSION_STATE_NONE; +} + +std::shared_ptr LockMissionContainer::GetLockMission() +{ + return lockMission_.lock(); +} +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/abilitymgr/src/mission_description_info.cpp b/tools/services/abilitymgr/src/mission_description_info.cpp new file mode 100644 index 00000000000..ae2bbe3903a --- /dev/null +++ b/tools/services/abilitymgr/src/mission_description_info.cpp @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "mission_description_info.h" + +#include "hilog_wrapper.h" +#include "nlohmann/json.hpp" +#include "string_ex.h" + +namespace OHOS { +namespace AAFwk { +bool MissionDescriptionInfo::ReadFromParcel(Parcel &parcel) +{ + label = Str16ToStr8(parcel.ReadString16()); + iconPath = Str16ToStr8(parcel.ReadString16()); + + return true; +} + +MissionDescriptionInfo *MissionDescriptionInfo::Unmarshalling(Parcel &parcel) +{ + MissionDescriptionInfo *info = new (std::nothrow) MissionDescriptionInfo(); + if (info == nullptr) { + return nullptr; + } + + if (!info->ReadFromParcel(parcel)) { + delete info; + info = nullptr; + } + return info; +} + +bool MissionDescriptionInfo::Marshalling(Parcel &parcel) const +{ + parcel.WriteString16(Str8ToStr16(label)); + parcel.WriteString16(Str8ToStr16(iconPath)); + + return true; +} +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/abilitymgr/src/mission_option.cpp b/tools/services/abilitymgr/src/mission_option.cpp new file mode 100644 index 00000000000..68aa6f260e2 --- /dev/null +++ b/tools/services/abilitymgr/src/mission_option.cpp @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "mission_option.h" +#include "string_ex.h" + +namespace OHOS { +namespace AAFwk { +bool MissionOption::IsSameWindowMode(const AbilityWindowConfiguration &key) const +{ + return ((winModeKey == key) || + (winModeKey == AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_PRIMARY && + key == AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_SECONDARY) || + (key == AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_PRIMARY && + winModeKey == AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_SECONDARY)); +} + +bool MissionOption::ReadFromParcel(Parcel &parcel) +{ + userId = parcel.ReadInt32(); + missionId = parcel.ReadInt32(); + winModeKey = static_cast(parcel.ReadInt32()); + displayKey = parcel.ReadInt32(); + + int32_t size = parcel.ReadInt32(); + for (int32_t i = 0; i < size; i++) { + std::string key = Str16ToStr8(parcel.ReadString16()); + std::string data = Str16ToStr8(parcel.ReadString16()); + properties_[key] = data; + } + + return true; +} + +MissionOption *MissionOption::Unmarshalling(Parcel &parcel) +{ + MissionOption *option = new (std::nothrow) MissionOption(); + if (option == nullptr) { + return nullptr; + } + + if (!option->ReadFromParcel(parcel)) { + delete option; + option = nullptr; + } + + return option; +} + +bool MissionOption::Marshalling(Parcel &parcel) const +{ + parcel.WriteInt32(userId); + parcel.WriteInt32(missionId); + parcel.WriteInt32(static_cast(winModeKey)); + parcel.WriteInt32(displayKey); + + parcel.WriteInt32(properties_.size()); + for (auto pair : properties_) { + parcel.WriteString16(Str8ToStr16(pair.first)); + parcel.WriteString16(Str8ToStr16(pair.second)); + } + + return true; +} + +void MissionOption::AddProperty(const std::string &key, const std::string &value) +{ + properties_[key] = value; +} + +void MissionOption::GetProperty(const std::string &key, std::string &value) +{ + auto it = properties_.find(key); + if (it == properties_.end()) { + value = std::string(); + return; + } + value = properties_[key]; +} + +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/abilitymgr/src/mission_record.cpp b/tools/services/abilitymgr/src/mission_record.cpp new file mode 100644 index 00000000000..5f324ba9869 --- /dev/null +++ b/tools/services/abilitymgr/src/mission_record.cpp @@ -0,0 +1,349 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "mission_record.h" + +#include "hilog_wrapper.h" +#include "ability_util.h" + +namespace OHOS { +namespace AAFwk { +int MissionRecord::nextMissionId_ = 0; + +MissionRecord::MissionRecord(const std::string &bundleName) : bundleName_(bundleName) +{ + missionId_ = GetNextMissionId(); + option_.missionId = missionId_; +} + +MissionRecord::MissionRecord(const std::shared_ptr &mission) +{ + bundleName_ = mission->bundleName_; + missionId_ = mission->missionId_; + abilities_.insert(abilities_.begin(), mission->abilities_.begin(), mission->abilities_.end()); + isLauncherCreate_ = mission->isLauncherCreate_; + preMissionRecord_ = mission->preMissionRecord_; + parentMissionStack_ = mission->parentMissionStack_; + missionDescriptionInfo_ = mission->missionDescriptionInfo_; +} + +MissionRecord::~MissionRecord() +{} + +int MissionRecord::GetNextMissionId() +{ + return nextMissionId_++; +} + +int MissionRecord::GetMissionRecordId() const +{ + return missionId_; +} + +int MissionRecord::GetAbilityRecordCount() const +{ + return abilities_.size(); +} + +std::shared_ptr MissionRecord::GetBottomAbilityRecord() const +{ + if (abilities_.empty()) { + HILOG_ERROR("abilities is empty"); + return nullptr; + } + return abilities_.back(); +} + +std::shared_ptr MissionRecord::GetTopAbilityRecord() const +{ + if (abilities_.empty()) { + HILOG_ERROR("abilities is empty"); + return nullptr; + } + return abilities_.front(); +} + +std::shared_ptr MissionRecord::GetLastTopAbility() const +{ + if (abilities_.empty() || abilities_.size() == 1) { + HILOG_WARN("no last top ability."); + return nullptr; + } + auto iter = abilities_.begin(); + return (*(++iter)); +} + +std::shared_ptr MissionRecord::GetAbilityRecordByToken(const sptr &token) const +{ + auto abilityToFind = Token::GetAbilityRecordByToken(token); + CHECK_POINTER_AND_RETURN(abilityToFind, nullptr); + + auto isExist = [targetAbility = abilityToFind](const std::shared_ptr &ability) { + if (ability == nullptr) { + return false; + } + return targetAbility == ability; + }; + + auto iter = std::find_if(abilities_.begin(), abilities_.end(), isExist); + if (iter != abilities_.end()) { + return *iter; + } + + return nullptr; +} + +std::shared_ptr MissionRecord::GetAbilityRecordById(const int64_t recordId) const +{ + for (std::shared_ptr ability : abilities_) { + if (ability != nullptr && ability->GetRecordId() == recordId) { + return ability; + } + } + return nullptr; +} + +std::shared_ptr MissionRecord::GetAbilityRecordByCaller( + const std::shared_ptr &caller, int requestCode) +{ + for (auto &ability : abilities_) { + auto callerList = ability->GetCallerRecordList(); + for (auto callerAbility : callerList) { + if (callerAbility->GetCaller() == caller && callerAbility->GetRequestCode() == requestCode) { + return ability; + } + } + } + return nullptr; +} + +void MissionRecord::AddAbilityRecordToTop(std::shared_ptr ability) +{ + CHECK_POINTER(ability); + auto isExist = [targetAbility = ability](const std::shared_ptr &ability) { + if (ability == nullptr) { + return false; + } + return targetAbility == ability; + }; + auto iter = std::find_if(abilities_.begin(), abilities_.end(), isExist); + if (iter == abilities_.end()) { + abilities_.push_front(ability); + ability->ForceProcessConfigurationChange(GetConfiguration()); + } +} + +bool MissionRecord::RemoveAbilityRecord(std::shared_ptr ability) +{ + CHECK_POINTER_RETURN_BOOL(ability); + for (auto iter = abilities_.begin(); iter != abilities_.end(); iter++) { + if ((*iter) == ability) { + abilities_.erase(iter); + return true; + } + } + HILOG_ERROR("can not find ability"); + return false; +} + +bool MissionRecord::RemoveTopAbilityRecord() +{ + if (abilities_.empty()) { + HILOG_ERROR("abilities is empty"); + return false; + } + abilities_.pop_front(); + return true; +} + +void MissionRecord::RemoveAll() +{ + abilities_.clear(); +} + +void MissionRecord::Dump(std::vector &info) +{ + std::string dumpInfo = " MissionRecord ID #" + std::to_string(missionId_); + std::shared_ptr bottomAbility = GetBottomAbilityRecord(); + if (bottomAbility) { + dumpInfo += " bottom app [" + bottomAbility->GetAbilityInfo().name + "]"; + info.push_back(dumpInfo); + for (auto abilityRecord : abilities_) { + abilityRecord->Dump(info); + } + } +} + +bool MissionRecord::IsSameMissionRecord(const std::string &bundleName) const +{ + if (bundleName.empty() || bundleName_.empty()) { + return false; + } + return (bundleName == bundleName_); +} + +void MissionRecord::GetAllAbilityInfo(std::vector &abilityInfos) +{ + for (auto ability : abilities_) { + AbilityRecordInfo abilityInfo; + ability->GetAbilityRecordInfo(abilityInfo); + abilityInfos.emplace_back(abilityInfo); + } +} + +bool MissionRecord::IsTopAbilityRecordByName(const std::string &abilityName) +{ + std::shared_ptr topAbility = GetTopAbilityRecord(); + if (topAbility == nullptr) { + return false; + } + + return (topAbility->GetAbilityInfo().name.compare(abilityName) == 0); +} + +void MissionRecord::SetIsLauncherCreate() +{ + isLauncherCreate_ = true; +} + +bool MissionRecord::IsLauncherCreate() const +{ + return isLauncherCreate_; +} + +void MissionRecord::SetPreMissionRecord(const std::shared_ptr &record) +{ + preMissionRecord_ = record; +} + +std::shared_ptr MissionRecord::GetPreMissionRecord() const +{ + return preMissionRecord_.lock(); +} + +bool MissionRecord::IsExistAbilityRecord(int32_t id) +{ + for (auto &it : abilities_) { + if (it->GetRecordId() == id) { + return true; + } + } + return false; +} + +bool MissionRecord::SupportMultWindow() const +{ + auto bottom = GetBottomAbilityRecord(); + if (bottom != nullptr) { + return bottom->SupportMultWindow(); + } + return false; +} + +void MissionRecord::SetMissionStack(const std::shared_ptr &missionStack, int stackId) +{ + CHECK_POINTER(missionStack); + parentMissionStack_ = missionStack; + UpdateConfiguration(missionStack->GetConfiguration()); + for (auto &it : abilities_) { + it->SetMissionStackId(stackId); + } +} + +std::shared_ptr MissionRecord::GetMissionStack() const +{ + return parentMissionStack_.lock(); +} + +void MissionRecord::SetMissionOption(const MissionOption &option) +{ + if (option.winModeKey != option_.winModeKey) { + HILOG_ERROR("Batch processing notify multi window mode changed."); + for (auto &it : abilities_) { + CHECK_POINTER(it); + bool flag = option.winModeKey == AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_PRIMARY || + option.winModeKey == AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_SECONDARY || + option.winModeKey == AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_FLOATING; + // true : old is multi win, target is fullscreen. + // false : old is fullscreen, target is multi win. + auto key = flag ? option.winModeKey : option_.winModeKey; + if (it->IsReady()) { + it->NotifyMultiWinModeChanged(key, flag); + } + } + } + + option_ = option; +} + +const MissionOption &MissionRecord::GetMissionOption() const +{ + return option_; +} + +bool MissionRecord::IsEmpty() +{ + return abilities_.empty(); +} + +std::shared_ptr MissionRecord::GetParent() +{ + return parentMissionStack_.lock(); +} + +unsigned int MissionRecord::GetChildSize() +{ + return abilities_.size(); +} + +std::shared_ptr MissionRecord::FindChild(unsigned int index) +{ + if (index < abilities_.size() && index >= 0) { + auto iter = abilities_.begin(); + std::advance(iter, index); + return (*iter); + } + return nullptr; +} + +void MissionRecord::Resume(const std::shared_ptr &backup) +{ + HILOG_INFO("mission resume."); + // backup abilities_ size = 1, singleton ability need resume + if (std::equal(abilities_.begin(), abilities_.end(), backup->abilities_.begin()) && backup->abilities_.size() > 1) { + HILOG_ERROR("List equality, no resume"); + return; + } + + std::list> diffAbilitys; + for (auto &ability : backup->abilities_) { + if (abilities_.front() == ability) { + break; + } + + ability->SetAbilityState(AbilityState::INITIAL); + diffAbilitys.emplace_back(ability); + } + + abilities_.insert(abilities_.begin(), diffAbilitys.begin(), diffAbilitys.end()); + + for (auto &ability : abilities_) { + if (ability->IsAbilityState(AbilityState::INITIAL)) { + ability->SetRestarting(true); + } + } +} +} // namespace AAFwk +} // namespace OHOS diff --git a/tools/services/abilitymgr/src/mission_record_info.cpp b/tools/services/abilitymgr/src/mission_record_info.cpp new file mode 100644 index 00000000000..32f318b3e06 --- /dev/null +++ b/tools/services/abilitymgr/src/mission_record_info.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "mission_record_info.h" + +#include "hilog_wrapper.h" +#include "nlohmann/json.hpp" +#include "string_ex.h" + +namespace OHOS { +namespace AAFwk { +bool MissionRecordInfo::ReadFromParcel(Parcel &parcel) +{ + parcel.ReadInt32(id); + int32_t abilityRecordInfosSize = parcel.ReadInt32(); + for (int32_t i = 0; i < abilityRecordInfosSize; i++) { + std::unique_ptr abilityRecordInfo(parcel.ReadParcelable()); + if (!abilityRecordInfo) { + HILOG_ERROR("ReadParcelable failed"); + return false; + } + abilityRecordInfos.emplace_back(*abilityRecordInfo); + } + return true; +} + +MissionRecordInfo *MissionRecordInfo::Unmarshalling(Parcel &parcel) +{ + MissionRecordInfo *info = new (std::nothrow) MissionRecordInfo(); + if (info == nullptr) { + return nullptr; + } + + if (!info->ReadFromParcel(parcel)) { + delete info; + info = nullptr; + } + return info; +} + +bool MissionRecordInfo::Marshalling(Parcel &parcel) const +{ + parcel.WriteInt32(id); + parcel.WriteInt32(abilityRecordInfos.size()); + for (auto &abilityRecordInfo : abilityRecordInfos) { + parcel.WriteParcelable(&abilityRecordInfo); + } + + return true; +} + +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/abilitymgr/src/mission_snapshot_info.cpp b/tools/services/abilitymgr/src/mission_snapshot_info.cpp new file mode 100644 index 00000000000..872885b973f --- /dev/null +++ b/tools/services/abilitymgr/src/mission_snapshot_info.cpp @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "mission_snapshot_info.h" + +#include "hilog_wrapper.h" +#include "nlohmann/json.hpp" +#include "string_ex.h" + +namespace OHOS { +namespace AAFwk { +bool MissionSnapshotInfo::ReadFromParcel(Parcel &parcel) +{ + std::unique_ptr image(parcel.ReadParcelable()); + if (image == nullptr) { + return false; + } + snapshot = *image; + return true; +} + +MissionSnapshotInfo *MissionSnapshotInfo::Unmarshalling(Parcel &parcel) +{ + MissionSnapshotInfo *info = new (std::nothrow) MissionSnapshotInfo(); + if (info == nullptr) { + return nullptr; + } + + if (!info->ReadFromParcel(parcel)) { + delete info; + info = nullptr; + } + return info; +} + +bool MissionSnapshotInfo::Marshalling(Parcel &parcel) const +{ + parcel.WriteParcelable(&snapshot); + return true; +} +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/abilitymgr/src/mission_stack.cpp b/tools/services/abilitymgr/src/mission_stack.cpp new file mode 100644 index 00000000000..884505d5907 --- /dev/null +++ b/tools/services/abilitymgr/src/mission_stack.cpp @@ -0,0 +1,302 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "mission_stack.h" +#include "hilog_wrapper.h" +#include "ability_util.h" + +namespace OHOS { +namespace AAFwk { +MissionStack::MissionStack(int id, int userId) : missionStackId_(id), userId_(userId) +{} + +MissionStack::~MissionStack() +{} + +std::shared_ptr MissionStack::GetTargetMissionRecord(const std::string &bundleName) +{ + /* We need choose which misson the target ability insert from misson list. + * The first ability in the misson is the entrance of this misson. + * Normally, + * one applicaiton's abilites are in the same misson in misson stack. + * So, the choose method is that the target ability's bundle name + * whether matches to which misson's entrance. + * Check the first ability record in mission record. + * if the first ability bundle name in mission record + * equal to the target ability name, then choose this mission record. + */ + auto checkAbility = [&bundleName](const std::shared_ptr &missionRecord) { + if (missionRecord == nullptr) { + return false; + } + return missionRecord->IsSameMissionRecord(bundleName); + }; + auto iter = std::find_if(missions_.begin(), missions_.end(), checkAbility); + if (iter == missions_.end()) { + return nullptr; + } + return *iter; +} + +int MissionStack::GetMissionStackId() const +{ + return missionStackId_; +} + +int MissionStack::GetMissionStackUserId() const +{ + return userId_; +} + +int MissionStack::GetMissionRecordCount() const +{ + return missions_.size(); +} + +std::shared_ptr MissionStack::GetTopAbilityRecord() const +{ + if (missions_.empty()) { + HILOG_ERROR("missions_ is empty"); + return nullptr; + } + std::shared_ptr topMission = missions_.front(); + if (topMission) { + return topMission->GetTopAbilityRecord(); + } + return nullptr; +} + +std::shared_ptr MissionStack::GetAbilityRecordById(const int64_t recordId) +{ + std::shared_ptr abilityRecord = nullptr; + for (std::shared_ptr mission : missions_) { + abilityRecord = mission->GetAbilityRecordById(recordId); + if (abilityRecord != nullptr) { + return abilityRecord; + } + } + return nullptr; +} +std::shared_ptr MissionStack::GetTopMissionRecord() +{ + if (missions_.empty()) { + HILOG_ERROR("missions_ is empty"); + return nullptr; + } + return missions_.front(); +} + +bool MissionStack::IsTopMissionRecord(std::shared_ptr &missionRecord) const +{ + return missions_.front() == missionRecord; +} + +std::shared_ptr MissionStack::GetBottomMissionRecord() +{ + if (missions_.empty()) { + HILOG_ERROR("missions_ is empty"); + return nullptr; + } + return missions_.back(); +} + +std::shared_ptr MissionStack::GetMissionRecordById(int id) +{ + if (missions_.empty()) { + HILOG_ERROR("missions_ is empty"); + return nullptr; + } + for (auto iter = missions_.begin(); iter != missions_.end(); iter++) { + if ((*iter) != nullptr && (*iter)->GetMissionRecordId() == id) { + return *iter; + } + } + return nullptr; +} + +std::shared_ptr MissionStack::GetAbilityRecordByToken(const sptr &token) +{ + std::shared_ptr abilityRecord = nullptr; + for (std::shared_ptr mission : missions_) { + abilityRecord = mission->GetAbilityRecordByToken(token); + if (abilityRecord != nullptr) { + return abilityRecord; + } + } + return nullptr; +} + +std::shared_ptr MissionStack::GetAbilityRecordByCaller( + const std::shared_ptr &caller, int requestCode) +{ + for (auto mission : missions_) { + auto abilityRecord = mission->GetAbilityRecordByCaller(caller, requestCode); + if (abilityRecord) { + return abilityRecord; + } + } + return nullptr; +} + +bool MissionStack::RemoveAbilityRecordByToken(const Token &token) +{ + std::shared_ptr abilityRecord = token.GetAbilityRecord(); + for (std::shared_ptr mission : missions_) { + if (mission->RemoveAbilityRecord(abilityRecord)) { + return true; + } + } + HILOG_INFO("RemoveAbilityRecordByToken can not find AbilityRecord"); + return false; +} + +bool MissionStack::RemoveMissionRecord(int id) +{ + if (missions_.empty()) { + return false; + } + for (auto iter = missions_.begin(); iter != missions_.end(); iter++) { + if ((*iter)->GetMissionRecordId() == id) { + missions_.erase(iter); + return true; + } + } + return false; +} + +void MissionStack::RemoveAll() +{ + missions_.clear(); +} + +void MissionStack::AddMissionRecordToTop(std::shared_ptr mission) +{ + CHECK_POINTER(mission); + auto isExist = [targetMission = mission](const std::shared_ptr &mission) { + if (mission == nullptr) { + return false; + } + return targetMission == mission; + }; + auto iter = std::find_if(missions_.begin(), missions_.end(), isExist); + if (iter == missions_.end()) { + missions_.push_front(mission); + } +} + +void MissionStack::MoveMissionRecordToTop(std::shared_ptr mission) +{ + CHECK_POINTER(mission); + if (missions_.front() == mission) { + HILOG_ERROR("missions is at the top of list"); + return; + } + for (auto iter = missions_.begin(); iter != missions_.end(); iter++) { + if ((*iter) == mission) { + missions_.erase(iter); + break; + } + } + missions_.emplace_front(mission); +} + +void MissionStack::MoveMissionRecordToBottom(const std::shared_ptr &mission) +{ + CHECK_POINTER(mission); + if (missions_.back() == mission) { + HILOG_ERROR("missions is at the bottom of list"); + return; + } + for (auto iter = missions_.begin(); iter != missions_.end(); iter++) { + if ((*iter) == mission) { + missions_.erase(iter); + break; + } + } + missions_.emplace_back(mission); +} + +void MissionStack::Dump(std::vector &info) +{ + std::string dumpInfo = " MissionStack ID #" + std::to_string(missionStackId_); + info.push_back(dumpInfo); + for (auto missionRecord : missions_) { + missionRecord->Dump(info); + } +} + +void MissionStack::DumpStackList(std::vector &info) +{ + std::string dumpInfo = " MissionStack ID #" + std::to_string(missionStackId_) + " ["; + for (auto missionRecord : missions_) { + dumpInfo += " "; + dumpInfo += "#"; + dumpInfo += std::to_string(missionRecord->GetMissionRecordId()); + } + dumpInfo += " ]"; + info.push_back(dumpInfo); +} + +void MissionStack::GetAllMissionInfo(std::vector &missionInfos) +{ + for (auto mission : missions_) { + MissionRecordInfo missionRecordInfo; + missionRecordInfo.id = mission->GetMissionRecordId(); + mission->GetAllAbilityInfo(missionRecordInfo.abilityRecordInfos); + missionInfos.emplace_back(missionRecordInfo); + } +} + +bool MissionStack::IsExistMissionRecord(int missionId) +{ + for (auto &iter : missions_) { + if (iter->GetMissionRecordId() == missionId) { + return true; + } + } + return false; +} + +bool MissionStack::IsEqualStackId(int stackId) +{ + return (stackId == missionStackId_); +} + +bool MissionStack::IsEmpty() +{ + return missions_.empty(); +} + +std::shared_ptr MissionStack::GetParent() +{ + return nullptr; +} + +unsigned int MissionStack::GetChildSize() +{ + return missions_.size(); +} + +std::shared_ptr MissionStack::FindChild(unsigned int index) +{ + if (index < missions_.size() && index >= 0) { + auto iter = missions_.begin(); + std::advance(iter, index); + return (*iter); + } + return nullptr; +} +} // namespace AAFwk +} // namespace OHOS diff --git a/tools/services/abilitymgr/src/mission_stack_info.cpp b/tools/services/abilitymgr/src/mission_stack_info.cpp new file mode 100644 index 00000000000..561c9e24ceb --- /dev/null +++ b/tools/services/abilitymgr/src/mission_stack_info.cpp @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "mission_stack_info.h" + +#include "hilog_wrapper.h" +#include "nlohmann/json.hpp" +#include "string_ex.h" + +namespace OHOS { +namespace AAFwk { +bool MissionStackInfo::ReadFromParcel(Parcel &parcel) +{ + parcel.ReadInt32(id); + int32_t missionStackInfosSize = parcel.ReadInt32(); + for (int32_t i = 0; i < missionStackInfosSize; i++) { + std::unique_ptr missionRecordInfo(parcel.ReadParcelable()); + if (!missionRecordInfo) { + HILOG_ERROR("ReadParcelable failed"); + return false; + } + missionRecords.emplace_back(*missionRecordInfo); + } + return true; +} + +MissionStackInfo *MissionStackInfo::Unmarshalling(Parcel &parcel) +{ + MissionStackInfo *info = new (std::nothrow) MissionStackInfo(); + if (info == nullptr) { + return nullptr; + } + + if (!info->ReadFromParcel(parcel)) { + delete info; + info = nullptr; + } + return info; +} + +bool MissionStackInfo::Marshalling(Parcel &parcel) const +{ + parcel.WriteInt32(id); + parcel.WriteInt32(missionRecords.size()); + for (auto &missionRecordInfo : missionRecords) { + parcel.WriteParcelable(&missionRecordInfo); + } + + return true; +} +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/abilitymgr/src/pending_want_common_event.cpp b/tools/services/abilitymgr/src/pending_want_common_event.cpp new file mode 100644 index 00000000000..a5eb09d48b8 --- /dev/null +++ b/tools/services/abilitymgr/src/pending_want_common_event.cpp @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "pending_want_common_event.h" +#include "hilog_wrapper.h" + +namespace OHOS { +namespace AAFwk { +PendingWantCommonEvent::PendingWantCommonEvent() +{} + +void PendingWantCommonEvent::SetWantParams(const WantParams &wantParams) +{ + wantParams_ = wantParams; +} + +void PendingWantCommonEvent::SetFinishedReceiver(const sptr &finishedReceiver) +{ + finishedReceiver_ = finishedReceiver; +} + +void PendingWantCommonEvent::OnReceiveEvent(const EventFwk::CommonEventData &data) +{ + HILOG_INFO("Receive common event callback."); + if (finishedReceiver_ != nullptr) { + HILOG_INFO("PendingWantCommonEvent::OnReceiveEvent begin."); + finishedReceiver_->PerformReceive(data.GetWant(), data.GetCode(), "", wantParams_, false, false, 0); + HILOG_INFO("PendingWantCommonEvent::OnReceiveEvent end."); + } +} +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/abilitymgr/src/pending_want_key.cpp b/tools/services/abilitymgr/src/pending_want_key.cpp new file mode 100644 index 00000000000..f67cade3669 --- /dev/null +++ b/tools/services/abilitymgr/src/pending_want_key.cpp @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "pending_want_key.h" +#include "iremote_object.h" + +namespace OHOS { +namespace AAFwk { +void PendingWantKey::SetType(const int32_t type) +{ + type_ = type; +} + +void PendingWantKey::SetBundleName(const std::string &bundleName) +{ + bundleName_ = bundleName; +} + +void PendingWantKey::SetRequestWho(const std::string &requestWho) +{ + requestWho_ = requestWho; +} + +void PendingWantKey::SetRequestCode(int32_t requestCode) +{ + requestCode_ = requestCode; +} + +void PendingWantKey::SetRequestWant(const Want &requestWant) +{ + requestWant_ = requestWant; +} + +void PendingWantKey::SetRequestResolvedType(const std::string &requestResolvedType) +{ + requestResolvedType_ = requestResolvedType; +} + +void PendingWantKey::SetAllWantsInfos(const std::vector &allWantsInfos) +{ + allWantsInfos_ = allWantsInfos; +} + +void PendingWantKey::SetFlags(int32_t flags) +{ + flags_ = flags; +} + +void PendingWantKey::SetCode(int32_t code) +{ + code_ = code; +} + +void PendingWantKey::SetUserId(int32_t userId) +{ + userId_ = userId; +} + +int32_t PendingWantKey::GetType() +{ + return type_; +} + +std::string PendingWantKey::GetBundleName() +{ + return bundleName_; +} + +std::string PendingWantKey::GetRequestWho() +{ + return requestWho_; +} + +int32_t PendingWantKey::GetRequestCode() +{ + return requestCode_; +} + +Want PendingWantKey::GetRequestWant() +{ + return requestWant_; +} + +std::string PendingWantKey::GetRequestResolvedType() +{ + return requestResolvedType_; +} + +std::vector PendingWantKey::GetAllWantsInfos() +{ + return allWantsInfos_; +} + +int32_t PendingWantKey::GetFlags() +{ + return flags_; +} + +int32_t PendingWantKey::GetCode() +{ + return code_; +} + +int32_t PendingWantKey::GetUserId() +{ + return userId_; +} +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/abilitymgr/src/pending_want_manager.cpp b/tools/services/abilitymgr/src/pending_want_manager.cpp new file mode 100644 index 00000000000..488822694a4 --- /dev/null +++ b/tools/services/abilitymgr/src/pending_want_manager.cpp @@ -0,0 +1,425 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "pending_want_manager.h" + +#include +#include +#include + +#include "ability_manager_service.h" +#include "hilog_wrapper.h" + +namespace OHOS { +namespace AAFwk { +using namespace OHOS::EventFwk; +using namespace std::chrono; +using namespace std::placeholders; + +PendingWantManager::PendingWantManager() +{ + HILOG_DEBUG("%{public}s(%{public}d)", __PRETTY_FUNCTION__, __LINE__); +} + +PendingWantManager::~PendingWantManager() +{ + HILOG_DEBUG("%{public}s(%{public}d)", __PRETTY_FUNCTION__, __LINE__); +} + +sptr PendingWantManager::GetWantSender(const int32_t callingUid, const int32_t uid, const bool isSystemApp, + const WantSenderInfo &wantSenderInfo, const sptr &callerToken) +{ + HILOG_INFO("PendingWantManager::GetWantSender begin."); + + std::lock_guard locker(mutex_); + if (callingUid != 0 && callingUid != SYSTEM_UID && !isSystemApp) { + if (callingUid != uid) { + HILOG_INFO("is not allowed to send"); + return nullptr; + } + } + WantSenderInfo info = wantSenderInfo; + return GetWantSenderLocked(callingUid, uid, wantSenderInfo.userId, info, callerToken); +} + +sptr PendingWantManager::GetWantSenderLocked(const int32_t callingUid, const int32_t uid, + const int32_t userId, WantSenderInfo &wantSenderInfo, const sptr &callerToken) +{ + HILOG_INFO("%{public}s:begin.", __func__); + + bool needCreate = ((uint32_t)wantSenderInfo.flags & (uint32_t)Flags::NO_BUILD_FLAG) != 0; + bool needCancel = ((uint32_t)wantSenderInfo.flags & (uint32_t)Flags::CANCEL_PRESENT_FLAG) != 0; + bool needUpdate = ((uint32_t)wantSenderInfo.flags & (uint32_t)Flags::UPDATE_PRESENT_FLAG) != 0; + + wantSenderInfo.flags = + ((uint32_t)wantSenderInfo.flags & (~((uint32_t)Flags::NO_BUILD_FLAG | (uint32_t)Flags::CANCEL_PRESENT_FLAG | + (uint32_t)Flags::UPDATE_PRESENT_FLAG))); + + std::lock_guard locker(mutex_); + std::shared_ptr pendingKey = std::make_shared(); + pendingKey->SetBundleName(wantSenderInfo.bundleName); + pendingKey->SetRequestWho(wantSenderInfo.resultWho); + pendingKey->SetRequestCode(wantSenderInfo.requestCode); + pendingKey->SetFlags(wantSenderInfo.flags); + pendingKey->SetUserId(wantSenderInfo.userId); + pendingKey->SetType(wantSenderInfo.type); + if (wantSenderInfo.allWants.size() > 0) { + pendingKey->SetRequestWant(wantSenderInfo.allWants.back().want); + pendingKey->SetRequestResolvedType(wantSenderInfo.allWants.back().resolvedTypes); + pendingKey->SetAllWantsInfos(wantSenderInfo.allWants); + } + auto ref = GetPendingWantRecordByKey(pendingKey); + if (ref != nullptr) { + if (!needCancel) { + if (needUpdate && wantSenderInfo.allWants.size() > 0) { + ref->GetKey()->SetRequestWant(wantSenderInfo.allWants.back().want); + ref->GetKey()->SetRequestResolvedType(wantSenderInfo.allWants.back().resolvedTypes); + wantSenderInfo.allWants.back().want = ref->GetKey()->GetRequestWant(); + wantSenderInfo.allWants.back().resolvedTypes = ref->GetKey()->GetRequestResolvedType(); + ref->GetKey()->SetAllWantsInfos(wantSenderInfo.allWants); + ref->SetCallerUid(callingUid); + } + return ref; + } + MakeWantSenderCanceledLocked(*ref); + wantRecords_.erase(ref->GetKey()); + return nullptr; + } + + if (needCreate) { + return (ref != nullptr) ? ref : nullptr; + } + + sptr rec = + new (std::nothrow) PendingWantRecord(shared_from_this(), uid, callerToken, pendingKey); + if (rec != nullptr) { + rec->SetCallerUid(callingUid); + pendingKey->SetCode(PendingRecordIdCreate()); + wantRecords_.insert(std::make_pair(pendingKey, rec)); + return rec; + } + return nullptr; +} + +void PendingWantManager::MakeWantSenderCanceledLocked(PendingWantRecord &record) +{ + HILOG_INFO("%{public}s:begin.", __func__); + + record.SetCanceled(); + for (auto &callback : record.GetCancelCallbacks()) { + callback->Send(record.GetKey()->GetRequestCode()); + } +} + +sptr PendingWantManager::GetPendingWantRecordByKey(const std::shared_ptr &key) +{ + HILOG_INFO("%{public}s:begin.", __func__); + + std::lock_guard locker(mutex_); + for (const auto &item : wantRecords_) { + const auto &pendingKey = item.first; + const auto &pendingRecord = item.second; + if ((pendingRecord != nullptr) && CheckPendingWantRecordByKey(pendingKey, key)) { + return pendingRecord; + } + } + return nullptr; +} + +bool PendingWantManager::CheckPendingWantRecordByKey( + const std::shared_ptr &inputKey, const std::shared_ptr &key) +{ + if (inputKey->GetBundleName().compare(key->GetBundleName()) != 0) { + return false; + } + if (inputKey->GetType() != key->GetType()) { + return false; + } + if (inputKey->GetRequestWho().compare(key->GetRequestWho()) != 0) { + return false; + } + if (inputKey->GetRequestCode() != key->GetRequestCode()) { + return false; + } + if (!inputKey->GetRequestWant().OperationEquals(key->GetRequestWant())) { + return false; + } + if (inputKey->GetRequestResolvedType().compare(key->GetRequestResolvedType()) != 0) { + return false; + } + if (inputKey->GetFlags() != key->GetFlags()) { + return false; + } + if (inputKey->GetUserId() != key->GetUserId()) { + return false; + } + return true; +} + +int32_t PendingWantManager::SendWantSender(const sptr &target, const SenderInfo &senderInfo) +{ + HILOG_INFO("%{public}s:begin.", __func__); + + if (target == nullptr) { + HILOG_ERROR("%{public}s:sender is nullptr.", __func__); + return ERR_INVALID_VALUE; + } + SenderInfo info = senderInfo; + sptr record = iface_cast(target->AsObject()); + return record->SenderInner(info); +} + +void PendingWantManager::CancelWantSender( + const int32_t callingUid, const int32_t uid, const bool isSystemApp, const sptr &sender) +{ + HILOG_INFO("%{public}s:begin.", __func__); + + if (sender == nullptr) { + HILOG_ERROR("%{public}s:sender is nullptr.", __func__); + return; + } + + std::lock_guard locker(mutex_); + if (callingUid != 0 && callingUid != SYSTEM_UID && !isSystemApp) { + if (callingUid != uid) { + HILOG_INFO("is not allowed to send"); + return; + } + } + sptr record = iface_cast(sender->AsObject()); + CancelWantSenderLocked(*record, true); +} + +void PendingWantManager::CancelWantSenderLocked(PendingWantRecord &record, bool cleanAbility) +{ + HILOG_INFO("%{public}s:begin.", __func__); + + MakeWantSenderCanceledLocked(record); + if (cleanAbility) { + wantRecords_.erase(record.GetKey()); + } +} + +int32_t PendingWantManager::PendingWantStartAbility( + const Want &want, const sptr &callerToken, int32_t requestCode, int32_t callerUid) +{ + HILOG_INFO("%{public}s:begin.", __func__); + return DelayedSingleton::GetInstance()->StartAbility( + want, callerToken, requestCode, callerUid); +} + +int32_t PendingWantManager::PendingWantStartAbilitys(const std::vector wantsInfo, + const sptr &callerToken, int32_t requestCode, int32_t callerUid) +{ + HILOG_INFO("%{public}s:begin.", __func__); + + int32_t result = ERR_OK; + for (const auto &item : wantsInfo) { + const auto &want = item.want; + result = DelayedSingleton::GetInstance()->StartAbility( + want, callerToken, requestCode, callerUid); + if (result != ERR_OK && result != START_ABILITY_WAITING) { + HILOG_ERROR("%{public}s:result != ERR_OK && result != START_ABILITY_WAITING.", __func__); + return result; + } + } + return result; +} + +int32_t PendingWantManager::PendingWantPublishCommonEvent( + const Want &want, const SenderInfo &senderInfo, int32_t callerUid) +{ + HILOG_INFO("%{public}s:begin.", __func__); + + CommonEventData eventData; + eventData.SetWant(want); + eventData.SetCode(senderInfo.code); + + CommonEventPublishInfo eventPublishData; + if (!senderInfo.requiredPermission.empty()) { + std::vector permissions; + permissions.emplace_back(senderInfo.requiredPermission); + eventPublishData.SetSubscriberPermissions(permissions); + } + + std::shared_ptr pendingWantCommonEvent = nullptr; + if (senderInfo.finishedReceiver != nullptr) { + eventPublishData.SetOrdered(true); + pendingWantCommonEvent = std::make_shared(); + pendingWantCommonEvent->SetFinishedReceiver(senderInfo.finishedReceiver); + WantParams wantParams = {}; + pendingWantCommonEvent->SetWantParams(wantParams); + } + bool result = DelayedSingleton::GetInstance()->PublishCommonEvent( + eventData, eventPublishData, pendingWantCommonEvent, callerUid); + return ((result == true) ? ERR_OK : (-1)); +} + +int32_t PendingWantManager::PendingRecordIdCreate() +{ + HILOG_INFO("%{public}s:begin.", __func__); + + static std::atomic_int id(0); + return ++id; +} + +sptr PendingWantManager::GetPendingWantRecordByCode(int32_t code) +{ + HILOG_INFO("%{public}s:begin. wantRecords_ size = %{public}zu", __func__, wantRecords_.size()); + + std::lock_guard locker(mutex_); + auto iter = std::find_if(wantRecords_.begin(), wantRecords_.end(), [&code](const auto &pair) { + return pair.second->GetKey()->GetCode() == code; + }); + return ((iter == wantRecords_.end()) ? nullptr : iter->second); +} + +int32_t PendingWantManager::GetPendingWantUid(const sptr &target) +{ + HILOG_INFO("%{public}s:begin.", __func__); + + if (target == nullptr) { + HILOG_ERROR("%{public}s:target is nullptr.", __func__); + return -1; + } + + sptr targetRecord = iface_cast(target->AsObject()); + auto record = GetPendingWantRecordByCode(targetRecord->GetKey()->GetCode()); + return ((record != nullptr) ? (record->GetUid()) : (-1)); +} + +int32_t PendingWantManager::GetPendingWantUserId(const sptr &target) +{ + HILOG_INFO("%{public}s:begin.", __func__); + + if (target == nullptr) { + HILOG_ERROR("%{public}s:target is nullptr.", __func__); + return -1; + } + + sptr targetRecord = iface_cast(target->AsObject()); + auto record = GetPendingWantRecordByCode(targetRecord->GetKey()->GetCode()); + return ((record != nullptr) ? (record->GetKey()->GetUserId()) : (-1)); +} + +std::string PendingWantManager::GetPendingWantBundleName(const sptr &target) +{ + HILOG_INFO("%{public}s:begin.", __func__); + + if (target == nullptr) { + HILOG_ERROR("%{public}s:target is nullptr.", __func__); + return ""; + } + + sptr targetRecord = iface_cast(target->AsObject()); + auto record = GetPendingWantRecordByCode(targetRecord->GetKey()->GetCode()); + if (record != nullptr) { + return record->GetKey()->GetBundleName(); + } + return ""; +} + +int32_t PendingWantManager::GetPendingWantCode(const sptr &target) +{ + HILOG_INFO("%{public}s:begin.", __func__); + + if (target == nullptr) { + HILOG_ERROR("%{public}s:target is nullptr.", __func__); + return -1; + } + + sptr targetRecord = iface_cast(target->AsObject()); + auto record = GetPendingWantRecordByCode(targetRecord->GetKey()->GetCode()); + return ((record != nullptr) ? (record->GetKey()->GetCode()) : (-1)); +} + +int32_t PendingWantManager::GetPendingWantType(const sptr &target) +{ + HILOG_INFO("%{public}s:begin.", __func__); + + if (target == nullptr) { + HILOG_ERROR("%{public}s:target is nullptr.", __func__); + return -1; + } + + sptr targetRecord = iface_cast(target->AsObject()); + auto record = GetPendingWantRecordByCode(targetRecord->GetKey()->GetCode()); + return ((record != nullptr) ? (record->GetKey()->GetType()) : (-1)); +} + +void PendingWantManager::RegisterCancelListener(const sptr &sender, const sptr &recevier) +{ + HILOG_INFO("%{public}s:begin.", __func__); + + if ((sender == nullptr) || (recevier == nullptr)) { + HILOG_ERROR("%{public}s:sender is nullptr or recevier is nullptr.", __func__); + return; + } + + sptr targetRecord = iface_cast(sender->AsObject()); + auto record = GetPendingWantRecordByCode(targetRecord->GetKey()->GetCode()); + if (record == nullptr) { + HILOG_ERROR("%{public}s:record is nullptr. code = %{public}d", __func__, targetRecord->GetKey()->GetCode()); + return; + } + bool cancel = record->GetCanceled(); + std::lock_guard locker(mutex_); + if (!cancel) { + record->RegisterCancelListener(recevier); + } +} + +void PendingWantManager::UnregisterCancelListener(const sptr &sender, const sptr &recevier) +{ + HILOG_INFO("%{public}s:begin.", __func__); + + if (sender == nullptr || recevier == nullptr) { + HILOG_ERROR("%{public}s:sender is nullptr or recevier is nullptr.", __func__); + return; + } + + sptr targetRecord = iface_cast(sender->AsObject()); + auto record = GetPendingWantRecordByCode(targetRecord->GetKey()->GetCode()); + if (record == nullptr) { + HILOG_ERROR("%{public}s:record is nullptr.", __func__); + return; + } + std::lock_guard locker(mutex_); + record->UnregisterCancelListener(recevier); +} + +int32_t PendingWantManager::GetPendingRequestWant(const sptr &target, std::shared_ptr &want) +{ + HILOG_INFO("%{public}s:begin.", __func__); + if (target == nullptr) { + HILOG_ERROR("%{public}s:target is nullptr.", __func__); + return ERR_INVALID_VALUE; + } + if (want == nullptr) { + HILOG_ERROR("%{public}s:want is nullptr.", __func__); + return ERR_INVALID_VALUE; + } + sptr targetRecord = iface_cast(target->AsObject()); + auto record = GetPendingWantRecordByCode(targetRecord->GetKey()->GetCode()); + if (record == nullptr) { + HILOG_ERROR("%{public}s:record is nullptr.", __func__); + return ERR_INVALID_VALUE; + } + want.reset(new (std::nothrow) Want(record->GetKey()->GetRequestWant())); + HILOG_ERROR("%{public}s:want is ok.", __func__); + return NO_ERROR; +} +} // namespace AAFwk +} // namespace OHOS diff --git a/tools/services/abilitymgr/src/pending_want_record.cpp b/tools/services/abilitymgr/src/pending_want_record.cpp new file mode 100644 index 00000000000..c782fb0e54a --- /dev/null +++ b/tools/services/abilitymgr/src/pending_want_record.cpp @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "pending_want_record.h" + +#include "hilog_wrapper.h" +#include "iremote_object.h" +#include "pending_want_manager.h" + +namespace OHOS { +namespace AAFwk { +PendingWantRecord::PendingWantRecord() +{} + +PendingWantRecord::PendingWantRecord(const std::shared_ptr &pendingWantManager, int32_t uid, + const sptr &callerToken, std::shared_ptr key) + : pendingWantManager_(pendingWantManager), uid_(uid), callerToken_(callerToken), key_(key) +{} + +PendingWantRecord::~PendingWantRecord() +{} + +void PendingWantRecord::Send(SenderInfo &senderInfo) +{ + SenderInner(senderInfo); +} + +void PendingWantRecord::RegisterCancelListener(const sptr &receiver) +{ + if (receiver == nullptr) { + return; + } + mCancelCallbacks_.emplace_back(receiver); +} + +void PendingWantRecord::UnregisterCancelListener(const sptr &receiver) +{ + if (receiver == nullptr) { + return; + } + if (mCancelCallbacks_.size()) { + auto it = std::find(mCancelCallbacks_.cbegin(), mCancelCallbacks_.cend(), receiver); + if (it != mCancelCallbacks_.cend()) { + mCancelCallbacks_.erase(it); + } + } +} + +int32_t PendingWantRecord::SenderInner(SenderInfo &senderInfo) +{ + HILOG_INFO("%{public}s:begin.", __func__); + std::lock_guard locker(lock_); + if (canceled_) { + return START_CANCELED; + } + + auto pendingWantManager = pendingWantManager_.lock(); + if (pendingWantManager == nullptr) { + HILOG_ERROR("%{public}s:pendingWantManager is nullptr.", __func__); + return ERR_INVALID_VALUE; + } + + if (((uint32_t)key_->GetFlags() & (uint32_t)Flags::ONE_TIME_FLAG) != 0) { + pendingWantManager->CancelWantSenderLocked(*this, true); + } + + Want want; + if (key_->GetAllWantsInfos().size() != 0) { + want = key_->GetRequestWant(); + } + bool immutable = ((uint32_t)key_->GetFlags() & (uint32_t)Flags::CONSTANT_FLAG) != 0; + senderInfo.resolvedType = key_->GetRequestResolvedType(); + if (!immutable) { + want.AddFlags(key_->GetFlags()); + } + + bool sendFinish = (senderInfo.finishedReceiver != nullptr); + int res = NO_ERROR; + switch (key_->GetType()) { + case (int32_t)OperationType::START_ABILITY: + res = pendingWantManager->PendingWantStartAbility(want, callerToken_, -1, callerUid_); + break; + case (int32_t)OperationType::START_ABILITIES: { + std::vector allWantsInfos = key_->GetAllWantsInfos(); + allWantsInfos.back().want = want; + res = pendingWantManager->PendingWantStartAbilitys(allWantsInfos, callerToken_, -1, callerUid_); + break; + } + case (int32_t)OperationType::START_SERVICE: + case (int32_t)OperationType::START_FOREGROUND_SERVICE: + res = pendingWantManager->PendingWantStartAbility(want, callerToken_, -1, callerUid_); + break; + case (int32_t)OperationType::SEND_COMMON_EVENT: + res = pendingWantManager->PendingWantPublishCommonEvent(want, senderInfo, callerUid_); + (res == ERR_OK) ? (sendFinish = false) : (sendFinish = (senderInfo.finishedReceiver != nullptr)); + break; + default: + break; + } + + if (sendFinish && res != START_CANCELED) { + WantParams wantParams = {}; + senderInfo.finishedReceiver->PerformReceive(want, senderInfo.code, "", wantParams, false, false, 0); + } + + return res; +} + +std::shared_ptr PendingWantRecord::GetKey() +{ + return key_; +} + +int32_t PendingWantRecord::GetUid() const +{ + return uid_; +} + +void PendingWantRecord::SetCanceled() +{ + canceled_ = true; +} +bool PendingWantRecord::GetCanceled() +{ + return canceled_; +} + +void PendingWantRecord::SetCallerUid(const int32_t callerUid) +{ + callerUid_ = callerUid; +} + +std::list> PendingWantRecord::GetCancelCallbacks() +{ + return mCancelCallbacks_; +} +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/abilitymgr/src/power_storage.cpp b/tools/services/abilitymgr/src/power_storage.cpp new file mode 100644 index 00000000000..8dc9ef8616b --- /dev/null +++ b/tools/services/abilitymgr/src/power_storage.cpp @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "power_storage.h" +#include "ability_util.h" +#include "mission_record.h" + +namespace OHOS { +namespace AAFwk { +void PowerStorage::SetPowerOffInActiveRecord(const std::shared_ptr &ability) +{ + CHECK_POINTER(ability); + PowerOffRecord record; + record.ability = ability; + record.StackId = ability->GetMissionRecord()->GetMissionStack()->GetMissionStackId(); + record.missionId = ability->GetMissionRecord()->GetMissionRecordId(); + record.state = ability->GetAbilityState(); + inActiveRecord_.emplace_back(record); +} + +std::vector PowerStorage::GetPowerOffInActiveRecord() const +{ + return inActiveRecord_; +} + +void PowerStorage::SetPowerOffActiveRecord(const std::shared_ptr &ability) +{ + CHECK_POINTER(ability); + PowerOffRecord record; + record.ability = ability; + record.StackId = ability->GetMissionRecord()->GetMissionStack()->GetMissionStackId(); + record.missionId = ability->GetMissionRecord()->GetMissionRecordId(); + record.state = ability->GetAbilityState(); + activeRecord_.emplace_back(record); +} + +std::vector PowerStorage::GetPowerOffActiveRecord() const +{ + return activeRecord_; +} +} // namespace AAFwk +} // namespace OHOS diff --git a/tools/services/abilitymgr/src/resume_mission_container.cpp b/tools/services/abilitymgr/src/resume_mission_container.cpp new file mode 100644 index 00000000000..2c449f949df --- /dev/null +++ b/tools/services/abilitymgr/src/resume_mission_container.cpp @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "resume_mission_container.h" +#include "hilog_wrapper.h" +#include "ability_util.h" + +namespace OHOS { +namespace AAFwk { +ResumeMissionContainer::ResumeMissionContainer(const std::shared_ptr &handler) : handler_(handler) +{} + +void ResumeMissionContainer::Save(const std::shared_ptr &mission) +{ + HILOG_INFO("Save."); + CHECK_POINTER(mission); + + auto missionId = mission->GetMissionRecordId(); + auto finder = missionMaps_.find(missionId); + std::shared_ptr backup; + if (finder == missionMaps_.end()) { + HILOG_INFO("Backup"); + backup = std::make_shared(mission); + missionMaps_.emplace(missionId, backup); + } + + if (backup) { + HILOG_INFO("start save time..."); + handler_->PostTask( + [this, missionId]() { Remove(missionId); }, taskName_ + std::to_string(missionId), recordSaveTime_); + } +} + +void ResumeMissionContainer::Resume(const std::shared_ptr &mission) +{ + HILOG_INFO("Resume."); + CHECK_POINTER(mission); + + auto backup = missionMaps_.find(mission->GetMissionRecordId()); + mission->Resume(backup->second); + missionMaps_.erase(mission->GetMissionRecordId()); +} + +void ResumeMissionContainer::Remove(int missionId) +{ + HILOG_INFO("Remove."); + missionMaps_.erase(missionId); + handler_->RemoveTask(taskName_ + std::to_string(missionId)); +} + +bool ResumeMissionContainer::IsResume(int missionId) +{ + return (missionMaps_.find(missionId) != missionMaps_.end()); +} +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/abilitymgr/src/sa_mgr_client.cpp b/tools/services/abilitymgr/src/sa_mgr_client.cpp new file mode 100644 index 00000000000..e8798f65e0d --- /dev/null +++ b/tools/services/abilitymgr/src/sa_mgr_client.cpp @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "sa_mgr_client.h" + +#include "hilog_wrapper.h" +#include "if_system_ability_manager.h" +#include "ipc_skeleton.h" +#include "iservice_registry.h" +#include "string_ex.h" + +namespace OHOS { +namespace AAFwk { +SaMgrClient::SaMgrClient() : saMgr_(nullptr) +{} + +SaMgrClient::~SaMgrClient() +{} + +sptr SaMgrClient::GetSystemAbility(const int32_t systemAbilityId) +{ + // use single instance of saMgr_ + if (saMgr_ == nullptr) { + std::lock_guard lock(saMutex_); + if (saMgr_ == nullptr) { + saMgr_ = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + if (saMgr_ == nullptr) { + HILOG_ERROR("Fail to get registry."); + return nullptr; + } + } + } + return saMgr_->GetSystemAbility(systemAbilityId); +} + +void SaMgrClient::RegisterSystemAbility( + const int32_t __attribute__((unused)) systemAbilityId, sptr __attribute__((unused)) broker) +{ + (void)servicesMap_; +} +} // namespace AAFwk +} // namespace OHOS diff --git a/tools/services/abilitymgr/src/sender_info.cpp b/tools/services/abilitymgr/src/sender_info.cpp new file mode 100644 index 00000000000..1c405be08df --- /dev/null +++ b/tools/services/abilitymgr/src/sender_info.cpp @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "sender_info.h" + +#include "hilog_wrapper.h" +#include "nlohmann/json.hpp" +#include "string_ex.h" + +#include "ipc_types.h" +#include "iremote_object.h" + +namespace OHOS { +namespace AAFwk { +bool SenderInfo::ReadFromParcel(Parcel &parcel) +{ + HILOG_INFO("%{public}s:begin.", __func__); + + code = parcel.ReadInt32(); + auto wantResquest = parcel.ReadParcelable(); + if (wantResquest == nullptr) { + HILOG_ERROR("%{public}s:wantResquest is nullptr.", __func__); + return false; + } + want = *wantResquest; + resolvedType = Str16ToStr8(parcel.ReadString16()); + sptr finishedReceiverResquest = parcel.ReadParcelable(); + if (finishedReceiverResquest != nullptr) { + finishedReceiver = iface_cast(finishedReceiverResquest); + if (!finishedReceiver) { + return false; + } + } else { + HILOG_ERROR("%{public}s:finishedReceiverResquest is nullptr.", __func__); + } + + requiredPermission = Str16ToStr8(parcel.ReadString16()); + return true; +} + +SenderInfo *SenderInfo::Unmarshalling(Parcel &parcel) +{ + HILOG_INFO("%{public}s:begin.", __func__); + + SenderInfo *info = new (std::nothrow) SenderInfo(); + if (info == nullptr) { + HILOG_ERROR("%{public}s:senderInfo is nullptr.", __func__); + return nullptr; + } + + if (!info->ReadFromParcel(parcel)) { + HILOG_ERROR("%{public}s:ReadFromParcel failed.", __func__); + delete info; + info = nullptr; + } + return info; +} + +bool SenderInfo::Marshalling(Parcel &parcel) const +{ + HILOG_INFO("%{public}s:begin.", __func__); + + parcel.WriteInt32(code); + parcel.WriteParcelable(&want); + parcel.WriteString16(Str8ToStr16(resolvedType)); + if (finishedReceiver != nullptr) { + parcel.WriteParcelable(finishedReceiver->AsObject()); + } else { + parcel.WriteParcelable(nullptr); + } + parcel.WriteString16(Str8ToStr16(requiredPermission)); + return true; +} +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/abilitymgr/src/stack_info.cpp b/tools/services/abilitymgr/src/stack_info.cpp new file mode 100644 index 00000000000..0ca1e673fa0 --- /dev/null +++ b/tools/services/abilitymgr/src/stack_info.cpp @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "stack_info.h" + +#include "hilog_wrapper.h" +#include "nlohmann/json.hpp" +#include "string_ex.h" + +namespace OHOS { +namespace AAFwk { +bool StackInfo::ReadFromParcel(Parcel &parcel) +{ + int32_t missionStackInfosSize = parcel.ReadInt32(); + for (int32_t i = 0; i < missionStackInfosSize; i++) { + std::unique_ptr missionStackInfo(parcel.ReadParcelable()); + if (!missionStackInfo) { + HILOG_ERROR("ReadParcelable failed"); + return false; + } + missionStackInfos.emplace_back(*missionStackInfo); + } + return true; +} + +StackInfo *StackInfo::Unmarshalling(Parcel &parcel) +{ + StackInfo *info = new (std::nothrow) StackInfo(); + if (info == nullptr) { + return nullptr; + } + + if (!info->ReadFromParcel(parcel)) { + delete info; + info = nullptr; + } + return info; +} + +bool StackInfo::Marshalling(Parcel &parcel) const +{ + parcel.WriteInt32(missionStackInfos.size()); + for (auto &missionStackInfo : missionStackInfos) { + parcel.WriteParcelable(&missionStackInfo); + } + + return true; +} +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/abilitymgr/src/stack_setting.cpp b/tools/services/abilitymgr/src/stack_setting.cpp new file mode 100644 index 00000000000..994800206ea --- /dev/null +++ b/tools/services/abilitymgr/src/stack_setting.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "stack_setting.h" + +#include "hilog_wrapper.h" +#include "string_ex.h" + +namespace OHOS { +namespace AAFwk { +bool StackSetting::ReadFromParcel(Parcel &parcel) +{ + userId = parcel.ReadInt32(); + stackId = static_cast(parcel.ReadInt32()); + maxHoldMission = parcel.ReadInt32(); + isSyncVisual = parcel.ReadBool(); + return true; +} + +StackSetting *StackSetting::Unmarshalling(Parcel &parcel) +{ + StackSetting *setiing = new (std::nothrow) StackSetting(); + if (setiing == nullptr) { + return nullptr; + } + + if (!setiing->ReadFromParcel(parcel)) { + delete setiing; + setiing = nullptr; + } + return setiing; +} + +bool StackSetting::Marshalling(Parcel &parcel) const +{ + parcel.WriteInt32(userId); + parcel.WriteInt32(static_cast(stackId)); + parcel.WriteInt32(maxHoldMission); + parcel.WriteBool(isSyncVisual); + return true; +} +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/abilitymgr/src/want_receiver_proxy.cpp b/tools/services/abilitymgr/src/want_receiver_proxy.cpp new file mode 100644 index 00000000000..13ccb7d54e7 --- /dev/null +++ b/tools/services/abilitymgr/src/want_receiver_proxy.cpp @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "want_receiver_proxy.h" + +#include "hilog_wrapper.h" +#include "ipc_types.h" + +namespace OHOS { +namespace AAFwk { +bool WantReceiverProxy::WriteInterfaceToken(MessageParcel &data) +{ + if (!data.WriteInterfaceToken(WantReceiverProxy::GetDescriptor())) { + HILOG_ERROR("write interface token failed"); + return false; + } + return true; +} + +void WantReceiverProxy::Send(const int32_t resultCode) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option(MessageOption::TF_SYNC); + if (!WriteInterfaceToken(data)) { + return; + } + data.WriteInt32(resultCode); + sptr remote = Remote(); + if (remote == nullptr) { + HILOG_ERROR("Remote() is NULL"); + return; + } + int32_t ret = remote->SendRequest(static_cast(IWantReceiver::WANT_RECEIVER_SEND), data, reply, option); + if (ret != NO_ERROR) { + HILOG_ERROR("SendRequest is failed, error code: %{public}d", ret); + } +} + +void WantReceiverProxy::PerformReceive(const Want &want, int resultCode, const std::string &data, + const WantParams &extras, bool serialized, bool sticky, int sendingUser) +{ + MessageParcel msgData; + MessageParcel reply; + MessageOption option(MessageOption::TF_SYNC); + if (!WriteInterfaceToken(msgData)) { + return; + } + msgData.WriteParcelable(&want); + msgData.WriteInt32(resultCode); + msgData.WriteString16(Str8ToStr16(data)); + msgData.WriteParcelable(&extras); + msgData.WriteBool(serialized); + msgData.WriteBool(sticky); + msgData.WriteInt32(sendingUser); + sptr remote = Remote(); + if (remote == nullptr) { + HILOG_ERROR("Remote() is NULL"); + return; + } + int32_t ret = remote->SendRequest( + static_cast(IWantReceiver::WANT_RECEIVER_PERFORM_RECEIVE), msgData, reply, option); + if (ret != NO_ERROR) { + HILOG_ERROR("SendRequest is failed, error code: %{public}d", ret); + } +} +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/abilitymgr/src/want_receiver_stub.cpp b/tools/services/abilitymgr/src/want_receiver_stub.cpp new file mode 100644 index 00000000000..f0461bdc12d --- /dev/null +++ b/tools/services/abilitymgr/src/want_receiver_stub.cpp @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "want_receiver_stub.h" + +#include "hilog_wrapper.h" +#include "ipc_types.h" + +#include "pac_map.h" + +namespace OHOS { +namespace AAFwk { +WantReceiverStub::WantReceiverStub() +{ + requestFuncMap_[WANT_RECEIVER_SEND] = &WantReceiverStub::SendInner; + requestFuncMap_[WANT_RECEIVER_PERFORM_RECEIVE] = &WantReceiverStub::PerformReceiveInner; +} + +WantReceiverStub::~WantReceiverStub() +{ + requestFuncMap_.clear(); +} + +int WantReceiverStub::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) +{ + HILOG_DEBUG("WantReceiverStub::OnRemoteRequest, cmd = %d, flags= %d", code, option.GetFlags()); + std::u16string descriptor = WantReceiverStub::GetDescriptor(); + std::u16string remoteDescriptor = data.ReadInterfaceToken(); + if (descriptor != remoteDescriptor) { + HILOG_INFO("local descriptor is not equal to remote"); + return ERR_INVALID_STATE; + } + + auto itFunc = requestFuncMap_.find(code); + if (itFunc != requestFuncMap_.end()) { + auto requestFunc = itFunc->second; + if (requestFunc != nullptr) { + return (this->*requestFunc)(data, reply); + } + } + HILOG_WARN("WantReceiverStub::OnRemoteRequest, default case, need check."); + return IPCObjectStub::OnRemoteRequest(code, data, reply, option); +} + +int WantReceiverStub::SendInner(MessageParcel &data, MessageParcel &reply) +{ + int32_t resultCode = data.ReadInt32(); + Send(resultCode); + return NO_ERROR; +} + +int WantReceiverStub::PerformReceiveInner(MessageParcel &data, MessageParcel &reply) +{ + Want *want = data.ReadParcelable(); + if (want == nullptr) { + HILOG_ERROR("AbilityManagerStub: want is nullptr"); + return ERR_INVALID_VALUE; + } + + int resultCode = data.ReadInt32(); + std::string bundleName = Str16ToStr8(data.ReadString16()); + + WantParams *wantParams = data.ReadParcelable(); + if (wantParams == nullptr) { + HILOG_ERROR("AbilityManagerStub: wantParams is nullptr"); + return ERR_INVALID_VALUE; + } + + bool serialized = data.ReadBool(); + bool sticky = data.ReadBool(); + int sendingUser = data.ReadInt32(); + + PerformReceive(*want, resultCode, bundleName, *wantParams, serialized, sticky, sendingUser); + return NO_ERROR; +} +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/abilitymgr/src/want_sender_info.cpp b/tools/services/abilitymgr/src/want_sender_info.cpp new file mode 100644 index 00000000000..a0756a66a2b --- /dev/null +++ b/tools/services/abilitymgr/src/want_sender_info.cpp @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "want_sender_info.h" + +#include "hilog_wrapper.h" +#include "nlohmann/json.hpp" +#include "string_ex.h" + +namespace OHOS { +namespace AAFwk { +bool WantSenderInfo::ReadFromParcel(Parcel &parcel) +{ + type = parcel.ReadInt32(); + bundleName = Str16ToStr8(parcel.ReadString16()); + resultWho = Str16ToStr8(parcel.ReadString16()); + requestCode = parcel.ReadInt32(); + int32_t wantsInfoSize = parcel.ReadInt32(); + for (int32_t i = 0; i < wantsInfoSize; i++) { + std::unique_ptr wantsInfo(parcel.ReadParcelable()); + if (!wantsInfo) { + HILOG_ERROR("ReadParcelable failed"); + return false; + } + allWants.emplace_back(*wantsInfo); + } + flags = parcel.ReadInt32(); + userId = parcel.ReadInt32(); + return true; +} + +WantSenderInfo *WantSenderInfo::Unmarshalling(Parcel &parcel) +{ + WantSenderInfo *info = new (std::nothrow) WantSenderInfo(); + if (info == nullptr) { + return nullptr; + } + + if (!info->ReadFromParcel(parcel)) { + delete info; + info = nullptr; + } + return info; +} + +bool WantSenderInfo::Marshalling(Parcel &parcel) const +{ + parcel.WriteInt32(type); + parcel.WriteString16(Str8ToStr16(bundleName)); + parcel.WriteString16(Str8ToStr16(resultWho)); + parcel.WriteInt32(requestCode); + size_t wantsInfoSize = allWants.size(); + if (!parcel.WriteInt32(wantsInfoSize)) { + return false; + } + for (size_t i = 0; i < wantsInfoSize; i++) { + if (!parcel.WriteParcelable(&allWants[i])) { + return false; + } + } + parcel.WriteInt32(flags); + parcel.WriteInt32(userId); + return true; +} +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/abilitymgr/src/want_sender_proxy.cpp b/tools/services/abilitymgr/src/want_sender_proxy.cpp new file mode 100644 index 00000000000..4f828d2d0d1 --- /dev/null +++ b/tools/services/abilitymgr/src/want_sender_proxy.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "want_sender_proxy.h" + +#include "hilog_wrapper.h" +#include "ipc_types.h" + +namespace OHOS { +namespace AAFwk { +bool WantSenderProxy::WriteInterfaceToken(MessageParcel &data) +{ + if (!data.WriteInterfaceToken(WantSenderProxy::GetDescriptor())) { + HILOG_ERROR("write interface token failed"); + return false; + } + return true; +} + +void WantSenderProxy::Send(SenderInfo &senderInfo) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option(MessageOption::TF_SYNC); + if (!WriteInterfaceToken(data)) { + return; + } + if (!data.WriteParcelable(&senderInfo)) { + HILOG_ERROR("fail to WriteParcelable value"); + return; + } + sptr remote = Remote(); + if (remote == nullptr) { + HILOG_ERROR("Remote() is NULL"); + return; + } + int32_t ret = remote->SendRequest(static_cast(IWantSender::WANT_SENDER_SEND), data, reply, option); + if (ret != NO_ERROR) { + HILOG_ERROR("SendRequest is failed, error code: %{public}d", ret); + } +} +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/abilitymgr/src/want_sender_stub.cpp b/tools/services/abilitymgr/src/want_sender_stub.cpp new file mode 100644 index 00000000000..479502360e4 --- /dev/null +++ b/tools/services/abilitymgr/src/want_sender_stub.cpp @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "want_sender_stub.h" + +#include "hilog_wrapper.h" +#include "ipc_types.h" + +namespace OHOS { +namespace AAFwk { +WantSenderStub::WantSenderStub() +{ + requestFuncMap_[WANT_SENDER_SEND] = &WantSenderStub::SendInner; +} + +WantSenderStub::~WantSenderStub() +{ + requestFuncMap_.clear(); +} + +int WantSenderStub::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) +{ + HILOG_DEBUG("WantSendStub::OnRemoteRequest, cmd = %d, flags= %d", code, option.GetFlags()); + std::u16string descriptor = WantSenderStub::GetDescriptor(); + std::u16string remoteDescriptor = data.ReadInterfaceToken(); + if (descriptor != remoteDescriptor) { + HILOG_INFO("local descriptor is not equal to remote"); + return ERR_INVALID_STATE; + } + + auto itFunc = requestFuncMap_.find(code); + if (itFunc != requestFuncMap_.end()) { + auto requestFunc = itFunc->second; + if (requestFunc != nullptr) { + return (this->*requestFunc)(data, reply); + } + } + HILOG_WARN("WantSenderStub::OnRemoteRequest, default case, need check."); + return IPCObjectStub::OnRemoteRequest(code, data, reply, option); +} + +int WantSenderStub::SendInner(MessageParcel &data, MessageParcel &reply) +{ + SenderInfo *senderInfo = data.ReadParcelable(); + if (senderInfo == nullptr) { + HILOG_ERROR("WantSenderStub: senderInfo is nullptr"); + return ERR_INVALID_VALUE; + } + Send(*senderInfo); + delete senderInfo; + return NO_ERROR; +} +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/abilitymgr/src/wants_info.cpp b/tools/services/abilitymgr/src/wants_info.cpp new file mode 100644 index 00000000000..81a16b872ad --- /dev/null +++ b/tools/services/abilitymgr/src/wants_info.cpp @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "wants_info.h" + +#include "hilog_wrapper.h" +#include "nlohmann/json.hpp" +#include "string_ex.h" + +namespace OHOS { +namespace AAFwk { +bool WantsInfo::ReadFromParcel(Parcel &parcel) +{ + auto wantResquest = parcel.ReadParcelable(); + if (wantResquest == nullptr) { + return false; + } + want = *wantResquest; + + resolvedTypes = Str16ToStr8(parcel.ReadString16()); + return true; +} + +WantsInfo *WantsInfo::Unmarshalling(Parcel &parcel) +{ + WantsInfo *info = new (std::nothrow) WantsInfo(); + if (info == nullptr) { + return nullptr; + } + + if (!info->ReadFromParcel(parcel)) { + delete info; + info = nullptr; + } + return info; +} + +bool WantsInfo::Marshalling(Parcel &parcel) const +{ + parcel.WriteParcelable(&want); + parcel.WriteString16(Str8ToStr16(resolvedTypes)); + return true; +} +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/abilitymgr/test/BUILD.gn b/tools/services/abilitymgr/test/BUILD.gn new file mode 100644 index 00000000000..93ed8273f5f --- /dev/null +++ b/tools/services/abilitymgr/test/BUILD.gn @@ -0,0 +1,166 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/test.gni") +import("//foundation/aafwk/standard/aafwk.gni") +import("//foundation/aafwk/standard/services/abilitymgr/abilitymgr.gni") + +EVENT_DIR = "//base/notification/ces_standard/" + +ohos_source_set("abilityms_test_source") { + sources = [ + "${services_path}/abilitymgr/src/aafwk_dummy_configuration.cpp", + "${services_path}/abilitymgr/src/ability_connect_callback_stub.cpp", + "${services_path}/abilitymgr/src/ability_connect_manager.cpp", + "${services_path}/abilitymgr/src/ability_event_handler.cpp", + "${services_path}/abilitymgr/src/ability_manager_proxy.cpp", + "${services_path}/abilitymgr/src/ability_manager_service.cpp", + "${services_path}/abilitymgr/src/ability_manager_stub.cpp", + "${services_path}/abilitymgr/src/ability_mission_info.cpp", + "${services_path}/abilitymgr/src/ability_record.cpp", + "${services_path}/abilitymgr/src/ability_record_info.cpp", + "${services_path}/abilitymgr/src/ability_scheduler_proxy.cpp", + "${services_path}/abilitymgr/src/ability_scheduler_stub.cpp", + "${services_path}/abilitymgr/src/ability_stack_manager.cpp", + "${services_path}/abilitymgr/src/ability_start_setting.cpp", + "${services_path}/abilitymgr/src/ability_token_stub.cpp", + "${services_path}/abilitymgr/src/ams_configuration_parameter.cpp", + "${services_path}/abilitymgr/src/caller_info.cpp", + "${services_path}/abilitymgr/src/configuration_holder.cpp", + "${services_path}/abilitymgr/src/connection_record.cpp", + "${services_path}/abilitymgr/src/data_ability_caller_recipient.cpp", + "${services_path}/abilitymgr/src/data_ability_manager.cpp", + "${services_path}/abilitymgr/src/data_ability_record.cpp", + "${services_path}/abilitymgr/src/image_info.cpp", + "${services_path}/abilitymgr/src/kernal_system_app_manager.cpp", + "${services_path}/abilitymgr/src/lifecycle_deal.cpp", + "${services_path}/abilitymgr/src/lifecycle_state_info.cpp", + "${services_path}/abilitymgr/src/lock_mission_container.cpp", + "${services_path}/abilitymgr/src/mission_description_info.cpp", + "${services_path}/abilitymgr/src/mission_option.cpp", + "${services_path}/abilitymgr/src/mission_record.cpp", + "${services_path}/abilitymgr/src/mission_record_info.cpp", + "${services_path}/abilitymgr/src/mission_snapshot_info.cpp", + "${services_path}/abilitymgr/src/mission_stack.cpp", + "${services_path}/abilitymgr/src/mission_stack_info.cpp", + "${services_path}/abilitymgr/src/pending_want_common_event.cpp", + "${services_path}/abilitymgr/src/pending_want_key.cpp", + "${services_path}/abilitymgr/src/pending_want_manager.cpp", + "${services_path}/abilitymgr/src/pending_want_record.cpp", + "${services_path}/abilitymgr/src/power_storage.cpp", + "${services_path}/abilitymgr/src/resume_mission_container.cpp", + "${services_path}/abilitymgr/src/sender_info.cpp", + "${services_path}/abilitymgr/src/stack_info.cpp", + "${services_path}/abilitymgr/src/stack_setting.cpp", + "${services_path}/abilitymgr/src/want_receiver_proxy.cpp", + "${services_path}/abilitymgr/src/want_receiver_stub.cpp", + "${services_path}/abilitymgr/src/want_sender_info.cpp", + "${services_path}/abilitymgr/src/want_sender_proxy.cpp", + "${services_path}/abilitymgr/src/want_sender_stub.cpp", + "${services_path}/abilitymgr/src/wants_info.cpp", + ] + + include_dirs = [ + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_core/include/", + "${EVENT_DIR}/frameworks/core/include", + "${EVENT_DIR}/interfaces/innerkits/native/include", + "${services_path}/abilitymgr/test/mock/libs/system_ability_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy/include", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_core/include/appmgr", + "//foundation/aafwk/standard/interfaces/innerkits/dataobs_manager/include", + ] + + external_dependent_files = [ + "//foundation/aafwk/standard/services/abilitymgr/test/mock/libs/appexecfwk_core/src/appmgr/app_state_callback_host.cpp", + "//foundation/aafwk/standard/services/abilitymgr/test/mock/libs/appexecfwk_core/src/appmgr/app_mgr_client.cpp", + "//foundation/appexecfwk/standard/common/log/src/app_log_wrapper.cpp", + "//foundation/aafwk/standard/services/abilitymgr/test/mock/libs/appexecfwk_core/src/appmgr/app_state_callback_proxy.cpp", + ] + + sources += external_dependent_files + + public_configs = [ + "${services_path}/abilitymgr:abilityms_config", + "${services_path}/abilitymgr/test/mock:aafwk_mock_config", + ] + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + deps = [ + "${innerkits_path}/want:want", + "${services_path}/abilitymgr/test/mock/libs/sa_mgr:sa_mgr_mock", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//utils/native/base:utils", + ] + + external_deps = [ + "ces_standard:cesfwk_core", + "ces_standard:cesfwk_innerkits", + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + "native_appdatamgr:native_appdatafwk", + "native_appdatamgr:native_dataability", + "native_appdatamgr:native_rdb", + ] +} + +group("unittest") { + testonly = true + + deps = [ + "unittest/phone/ability_connect_callback_proxy_test:unittest", + "unittest/phone/ability_connect_callback_stub_test:unittest", + "unittest/phone/ability_connect_manage_test:unittest", + "unittest/phone/ability_dump_test:unittest", + "unittest/phone/ability_manager_proxy_test:unittest", + "unittest/phone/ability_manager_service_test:unittest", + "unittest/phone/ability_manager_stub_test:unittest", + "unittest/phone/ability_manager_test:unittest", + "unittest/phone/ability_record_test:unittest", + "unittest/phone/ability_scheduler_proxy_test:unittest", + "unittest/phone/ability_scheduler_stub_test:unittest", + "unittest/phone/ability_service_start_test:unittest", + "unittest/phone/ability_stack_manager_test:unittest", + "unittest/phone/ability_token_proxy_test:unittest", + "unittest/phone/ability_token_stub_test:unittest", + "unittest/phone/ability_with_applications_test:unittest", + "unittest/phone/abilityms_appms_test:unittest", + "unittest/phone/app_scheduler_test:unittest", + "unittest/phone/configuration_holder_test:unittest", + "unittest/phone/connection_record_test:unittest", + "unittest/phone/data_ability_manager_test:unittest", + "unittest/phone/data_ability_record_test:unittest", + "unittest/phone/info_test:unittest", + "unittest/phone/kernal_system_app_manager_test:unittest", + "unittest/phone/lifecycle_deal_test:unittest", + "unittest/phone/lifecycle_test:unittest", + "unittest/phone/mission_record_test:unittest", + "unittest/phone/mission_stack_test:unittest", + "unittest/phone/pending_want_key_test:unittest", + "unittest/phone/pending_want_manager_test:unittest", + "unittest/phone/pending_want_record_test:unittest", + "unittest/phone/resume_mission_container_test:unittest", + "unittest/phone/sender_info_test:unittest", + "unittest/phone/terminate_ability_test:unittest", + "unittest/phone/want_receiver_proxy_test:unittest", + "unittest/phone/want_receiver_stub_test:unittest", + "unittest/phone/want_sender_info_test:unittest", + "unittest/phone/want_sender_proxy_test:unittest", + "unittest/phone/want_sender_stub_test:unittest", + "unittest/phone/wants_info_test:unittest", + "unittest/phone/window_info_test:unittest", + ] +} diff --git a/tools/services/abilitymgr/test/mock/BUILD.gn b/tools/services/abilitymgr/test/mock/BUILD.gn new file mode 100644 index 00000000000..462fb2834eb --- /dev/null +++ b/tools/services/abilitymgr/test/mock/BUILD.gn @@ -0,0 +1,35 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") +import("//foundation/aafwk/standard/aafwk.gni") + +group("mock_target") { + testonly = true + deps = [ + "appmgr_test_service:appmgr_test_service", + "libs/aakit:aakit_mock", + "libs/appexecfwk_core:appexecfwk_appmgr_mock", + "libs/appexecfwk_core:appexecfwk_bundlemgr_mock", + "libs/sa_mgr:sa_mgr_mock", + ] +} + +config("aafwk_mock_config") { + configs = [ + "libs/aakit:aakit_mock_config", + "libs/appexecfwk_core:appexecfwk_core_mock_config", + "libs/sa_mgr:sa_mgr_mock_config", + "appmgr_test_service:appmgr_test_service_config", + ] +} diff --git a/tools/services/abilitymgr/test/mock/appmgr_test_service/BUILD.gn b/tools/services/abilitymgr/test/mock/appmgr_test_service/BUILD.gn new file mode 100755 index 00000000000..2dc9a664957 --- /dev/null +++ b/tools/services/abilitymgr/test/mock/appmgr_test_service/BUILD.gn @@ -0,0 +1,57 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") +import("//foundation/aafwk/standard/aafwk.gni") + +config("appmgr_test_service_config") { + include_dirs = [ + "//foundation/aafwk/standard/services/abilitymgr/test/mock/appmgr_test_service/include/", + "//foundation/aafwk/standard/services/abilitymgr/include", + "//foundation/aafwk/standard/interfaces/innerkits/ability_manager/include", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_core/include", + "//foundation/aafwk/standard/frameworks/kits/ability/native/include", + "//foundation/aafwk/standard/services/common/include", + "//base/notification/ces_standard/frameworks/core/include", + "//base/notification/ces_standard/interfaces/innerkits/native/include", + ] +} + +ohos_source_set("appmgr_test_service") { + include_dirs = [ + "${services_path}/abilitymgr/test/mock/libs/system_ability_mock", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy/include", + "//foundation/aafwk/standard/services/abilitymgr/test/mock/libs/aakit/include", + "//third_party/jsoncpp/include", + ] + + sources = [ "src/appmgr_test_service.cpp" ] + + configs = [ ":appmgr_test_service_config" ] + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + deps = [ + "${innerkits_path}/want:want", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//third_party/jsoncpp:jsoncpp", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] +} diff --git a/tools/services/abilitymgr/test/mock/appmgr_test_service/include/appmgr_test_service.h b/tools/services/abilitymgr/test/mock/appmgr_test_service/include/appmgr_test_service.h new file mode 100644 index 00000000000..d2ec874ce0f --- /dev/null +++ b/tools/services/abilitymgr/test/mock/appmgr_test_service/include/appmgr_test_service.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_APPMGR_TEST_SERVICE_H +#define OHOS_AAFWK_APPMGR_TEST_SERVICE_H + +#include "ability_manager_service.h" +#include "event_handler.h" +#include "event_runner.h" +#include + +namespace OHOS { +namespace AAFwk { +class AppMgrEventHandler : public AppExecFwk::EventHandler { +public: + AppMgrEventHandler( + const std::shared_ptr &runner, const std::shared_ptr &server); + virtual ~AppMgrEventHandler() + {} + + void ProcessEvent(const AppExecFwk::InnerEvent::Pointer &event) override; + +private: + static constexpr int BLOCK_TEST_TIME = 500000; /* Blocked test time is 500ms */ + void ProcessLoadAbility(const AppExecFwk::InnerEvent::Pointer &event); + + void ProcessUpdateAppState(const AppExecFwk::InnerEvent::Pointer &event); + + void ScheduleAbilityTransaction(const AppExecFwk::InnerEvent::Pointer &event); + + void ScheduleConnectAbilityTransaction(const AppExecFwk::InnerEvent::Pointer &event); + void ScheduleDisconnectAbilityTransaction(const AppExecFwk::InnerEvent::Pointer &event); + + std::shared_ptr server_; + std::map, sptr> tokenMap_; +}; + +class AppManagerTestService : public std::enable_shared_from_this { + DECLARE_DELAYED_SINGLETON(AppManagerTestService) +public: + void Start(); + std::shared_ptr GetEventHandler() const + { + return handler_; + } + // MSG 0 - 20 simulate appmgr service message + static constexpr uint32_t LOAD_ABILITY_MSG = 0; + static constexpr uint32_t UPDATE_APP_STATE_MSG = 1; + // MSG 20 - 100 simulate app kit message + static constexpr uint32_t SCHEDULE_ABILITY_MSG = 20; + static constexpr uint32_t SCHEDULE_CONNECT_MSG = 21; + static constexpr uint32_t SCHEDULE_DISCONNECT_MSG = 22; + static constexpr uint32_t SCHEDULE_COMMAND_MSG = 23; + +private: + std::shared_ptr eventLoop_; + std::shared_ptr handler_; +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_APPMGR_TEST_SERVICE_H \ No newline at end of file diff --git a/tools/services/abilitymgr/test/mock/appmgr_test_service/src/appmgr_test_service.cpp b/tools/services/abilitymgr/test/mock/appmgr_test_service/src/appmgr_test_service.cpp new file mode 100644 index 00000000000..539e147ba3d --- /dev/null +++ b/tools/services/abilitymgr/test/mock/appmgr_test_service/src/appmgr_test_service.cpp @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "appmgr_test_service.h" + +#include +#include + +#include "ability_scheduler.h" +#include "hilog_wrapper.h" + +namespace OHOS { +namespace AAFwk { + +AppMgrEventHandler::AppMgrEventHandler( + const std::shared_ptr &runner, const std::shared_ptr &server) + : AppExecFwk::EventHandler(runner), server_(server) +{ + HILOG_INFO("AbilityEventHandler::AbilityEventHandler::instance created."); +} + +void AppMgrEventHandler::ProcessEvent(const AppExecFwk::InnerEvent::Pointer &event) +{ + if (event == nullptr) { + HILOG_ERROR("AMSEventHandler::ProcessEvent::parameter error"); + return; + } + HILOG_DEBUG("AMSEventHandler::ProcessEvent::inner event id obtained: %u.", event->GetInnerEventId()); + switch (event->GetInnerEventId()) { + case AppManagerTestService::LOAD_ABILITY_MSG: { + HILOG_DEBUG("Load Ability msg."); + ProcessLoadAbility(event); + break; + } + case AppManagerTestService::SCHEDULE_ABILITY_MSG: { + HILOG_DEBUG("scheduler ability msg."); + ScheduleAbilityTransaction(event); + break; + } + case AppManagerTestService::SCHEDULE_CONNECT_MSG: { + HILOG_DEBUG("scheduler connect msg."); + ScheduleConnectAbilityTransaction(event); + break; + } + case AppManagerTestService::SCHEDULE_DISCONNECT_MSG: { + HILOG_DEBUG("scheduler disconnect msg."); + ScheduleDisconnectAbilityTransaction(event); + break; + } + default: { + HILOG_DEBUG("unknown message."); + break; + } + } +} + +void AppMgrEventHandler::ProcessLoadAbility(const AppExecFwk::InnerEvent::Pointer &event) +{ + HILOG_DEBUG("process load ability."); + auto tokenPtr = event->GetUniqueObject>().get(); + if (tokenPtr == nullptr) { + HILOG_ERROR("abilityToken unavailable."); + } else { + OHOS::sptr token = *tokenPtr; + std::shared_ptr ability = Token::GetAbilityRecordByToken(token); + if (ability == nullptr) { + HILOG_ERROR("ability unavailable."); + return; + } + HILOG_DEBUG("attach ability %s thread.", ability->GetAbilityInfo().name.c_str()); + sptr abilitySched = new AbilityScheduler(); + tokenMap_[abilitySched] = token; + server_->AttachAbilityThread(abilitySched, token); + static int32_t windowToken = 0; + server_->AddWindowInfo(token, ++windowToken); + } +} + +void AppMgrEventHandler::ScheduleAbilityTransaction(const AppExecFwk::InnerEvent::Pointer &event) +{ + auto object = event->GetUniqueObject, int>>(); + auto abilitySched = object.get()->first; + auto targetState = object.get()->second; + auto abilityToken = tokenMap_[abilitySched]; + + if (abilityToken == nullptr) { + HILOG_ERROR("abilityToken unavailable. object: %p", object.get()); + return; + } + + std::shared_ptr ability = Token::GetAbilityRecordByToken(abilityToken); + if (ability == nullptr) { + HILOG_ERROR("ability unavailable."); + return; + } + AppExecFwk::AbilityInfo abilityinfo = ability->GetAbilityInfo(); + + if (targetState == ACTIVE) { + HILOG_DEBUG("process schedule ability %s active.", abilityinfo.name.c_str()); + if (std::string::npos != abilityinfo.name.find("BlockActive")) { + usleep(BLOCK_TEST_TIME); + } + } else if (targetState == INACTIVE) { + HILOG_DEBUG("process schedule ability %s inactive.", abilityinfo.name.c_str()); + if (std::string::npos != abilityinfo.name.find("BlockInActive")) { + usleep(BLOCK_TEST_TIME); + } + } + server_->AbilityTransitionDone(ability->GetToken(), targetState); + return; +} + +void AppMgrEventHandler::ScheduleConnectAbilityTransaction(const AppExecFwk::InnerEvent::Pointer &event) +{ + auto object = event->GetUniqueObject, Want>>(); + auto abilitySched = object.get()->first; + auto abilityToken = tokenMap_[abilitySched]; + server_->ScheduleConnectAbilityDone(abilityToken, abilityToken); +} + +void AppMgrEventHandler::ScheduleDisconnectAbilityTransaction(const AppExecFwk::InnerEvent::Pointer &event) +{ + auto object = event->GetUniqueObject>(); + auto abilitySchedPtr = object.get(); + sptr abilitySched = *abilitySchedPtr; + auto abilityToken = tokenMap_[abilitySched]; + + if (abilityToken == nullptr) { + HILOG_ERROR("abilityToken unavailable. object: %p", object.get()); + return; + } + + std::shared_ptr ability = Token::GetAbilityRecordByToken(abilityToken); + if (ability == nullptr) { + HILOG_ERROR("ability unavailable."); + return; + } + AppExecFwk::AbilityInfo abilityinfo = ability->GetAbilityInfo(); + if (std::string::npos == abilityinfo.name.find("Block")) { + HILOG_INFO("no block, so call disconnect done"); + server_->ScheduleDisconnectAbilityDone(abilityToken); + } + return; +} + +AppManagerTestService::AppManagerTestService() : eventLoop_(nullptr), handler_(nullptr) +{} + +AppManagerTestService::~AppManagerTestService() +{} + +void AppManagerTestService::Start() +{ + eventLoop_ = AppExecFwk::EventRunner::Create("AppManagerTestService"); + if (eventLoop_.get() == nullptr) { + HILOG_ERROR("failed to create EventRunner"); + return; + } + handler_ = std::make_shared(eventLoop_, DelayedSingleton::GetInstance()); + eventLoop_->Run(); + return; +} + +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/abilitymgr/test/mock/include/mock_app_manager_client.h b/tools/services/abilitymgr/test/mock/include/mock_app_manager_client.h new file mode 100644 index 00000000000..b05c3802034 --- /dev/null +++ b/tools/services/abilitymgr/test/mock/include/mock_app_manager_client.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_AAFWK_SERVICES_TEST_MT_MOCK_APP_MANAGER_CLIENT_H +#define FOUNDATION_AAFWK_SERVICES_TEST_MT_MOCK_APP_MANAGER_CLIENT_H + +#include + +#include "app_mgr_client.h" + +namespace OHOS { +namespace AppExecFwk { +class MockAppMgrClient : public AppMgrClient { +public: + MockAppMgrClient() + {} + ~MockAppMgrClient() + {} + MOCK_METHOD4(LoadAbility, AppMgrResultCode(const sptr &token, const sptr &preToken, + const AbilityInfo &abilityInfo, const ApplicationInfo &appInfo)); + + MOCK_METHOD1(TerminateAbility, AppMgrResultCode(const sptr &)); + MOCK_METHOD2(UpdateAbilityState, AppMgrResultCode(const sptr &token, const AbilityState state)); + MOCK_METHOD1(RegisterAppStateCallback, AppMgrResultCode(const sptr &callback)); + MOCK_METHOD0(ConnectAppMgrService, AppMgrResultCode()); + MOCK_METHOD1(KillApplication, AppMgrResultCode(const std::string &)); + MOCK_METHOD5(AbilityBehaviorAnalysis, + AppMgrResultCode(const sptr &token, const sptr &preToken, + const int32_t visibility, const int32_t perceptibility, const int32_t connectionState)); + MOCK_METHOD1(KillProcessByAbilityToken, AppMgrResultCode(const sptr &token)); + MOCK_METHOD4(CompelVerifyPermission, int(const std::string &permission, int pid, int uid, std::string &message)); +}; +} // namespace AppExecFwk +} // namespace OHOS + +#endif // FOUNDATION_AAFWK_SERVICES_TEST_MT_MOCK_APP_MGR_CLIENT_H diff --git a/tools/services/abilitymgr/test/mock/include/mock_app_mgr_client.h b/tools/services/abilitymgr/test/mock/include/mock_app_mgr_client.h new file mode 100644 index 00000000000..605bc5058ab --- /dev/null +++ b/tools/services/abilitymgr/test/mock/include/mock_app_mgr_client.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_AAFWK_SERVICES_ABILITY_TEST_MOCK_APP_MGR_CLIENT_H +#define FOUNDATION_AAFWK_SERVICES_ABILITY_TEST_MOCK_APP_MGR_CLIENT_H + +#include "gmock/gmock.h" +#include "app_mgr_client.h" +#include "hilog_wrapper.h" + +namespace OHOS { +namespace AAFwk { +using namespace OHOS::AppExecFwk; +class MockAppMgrClient : public AppMgrClient { +public: + MockAppMgrClient(){}; + virtual ~MockAppMgrClient(){}; + + virtual AppMgrResultCode LoadAbility(const sptr &token, const sptr &preToken, + const AbilityInfo &abilityInfo, const ApplicationInfo &appInfo) + { + HILOG_INFO("MockAppMgrClient LoadAbility enter."); + token_ = token; + return AppMgrResultCode::RESULT_OK; + } + + sptr GetToken() + { + return token_; + }; + +private: + sptr token_; +}; +} // namespace AAFwk +} // namespace OHOS +#endif // FOUNDATION_AAFWK_SERVICES_ABILITY_TEST_MOCK_APP_MGR_CLIENT_H diff --git a/tools/services/abilitymgr/test/mock/include/mock_configuration_holder.h b/tools/services/abilitymgr/test/mock/include/mock_configuration_holder.h new file mode 100644 index 00000000000..efd4cd09a84 --- /dev/null +++ b/tools/services/abilitymgr/test/mock/include/mock_configuration_holder.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_AAFWK_SERVICES_TEST_MT_MOCK_APP_MANAGER_CLIENT_H +#define FOUNDATION_AAFWK_SERVICES_TEST_MT_MOCK_APP_MANAGER_CLIENT_H + +#include + +#include "configuration_holder.h" + +namespace OHOS { +namespace AppExecFwk { + +class MockConfigurationHolder : public AAFwk::ConfigurationHolder { +public: + MockConfigurationHolder() + {} + ~MockConfigurationHolder() + {} + + std::shared_ptr GetParent() + { + return nullptr; + } + + unsigned int GetChildSize() + { + return 1; + } + + std::shared_ptr FindChild(unsigned int index) + { + return nullptr; + } +}; + +} // namespace AppExecFwk +} // namespace OHOS + +#endif // FOUNDATION_AAFWK_SERVICES_TEST_MT_MOCK_APP_MGR_CLIENT_H diff --git a/tools/services/abilitymgr/test/mock/libs/aakit/BUILD.gn b/tools/services/abilitymgr/test/mock/libs/aakit/BUILD.gn new file mode 100755 index 00000000000..20ab44215e2 --- /dev/null +++ b/tools/services/abilitymgr/test/mock/libs/aakit/BUILD.gn @@ -0,0 +1,56 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") +import("//foundation/aafwk/standard/aafwk.gni") + +config("aakit_mock_config") { + include_dirs = [ + "//foundation/aafwk/standard/services/abilitymgr/test/mock/libs/aakit/include", + "//foundation/aafwk/standard/interfaces/innerkits/ability_manager/include", + "//foundation/aafwk/standard/services/abilitymgr/include", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base/include", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_core/include", + "//foundation/aafwk/standard/frameworks/kits/ability/native/include/", + "include/", + "//third_party/jsoncpp/include", + "//foundation/distributedschedule/dmsfwk/services/dtbschedmgr/include/", + "//foundation/aafwk/standard/services/common/include/", + ] +} + +ohos_source_set("aakit_mock") { + sources = [ + "src/ability_scheduler.cpp", + "src/mock_ability_connect_callback.cpp", + ] + + configs = [ ":aakit_mock_config" ] + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + deps = [ + "${innerkits_path}/want:want", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/distributedschedule/safwk/interfaces/innerkits/safwk:system_ability_fwk", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy:samgr_proxy", + "//third_party/jsoncpp:jsoncpp", + "//utils/native/base:utils", + ] + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] +} diff --git a/tools/services/abilitymgr/test/mock/libs/aakit/include/ability_scheduler.h b/tools/services/abilitymgr/test/mock/libs/aakit/include/ability_scheduler.h new file mode 100644 index 00000000000..9163532c74a --- /dev/null +++ b/tools/services/abilitymgr/test/mock/libs/aakit/include/ability_scheduler.h @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_ABILITY_SCHEDULER_H +#define OHOS_AAFWK_ABILITY_SCHEDULER_H + +#include "ability_scheduler_stub.h" +#include "ability_record.h" +#include "dummy_values_bucket.h" +#include "dummy_data_ability_predicates.h" +#include "dummy_result_set.h" + +namespace OHOS { +namespace AAFwk { +/** + * @class AbilityScheduler + * AbilityScheduler is used to schedule ability kit lifecycle. + */ +class AbilityScheduler : public AbilitySchedulerStub, virtual RefBase { +public: + AbilityScheduler(); + virtual ~AbilityScheduler(); + + void ScheduleAbilityTransaction(const Want &want, const LifeCycleStateInfo &targetState) override; + + void SendResult(int requestCode, int resultCode, const Want &resultWant) override; + + const AbilityResult &GetResult() const; + + void ScheduleConnectAbility(const Want &want) override; + + void ScheduleDisconnectAbility(const Want &want) override; + + void ScheduleCommandAbility(const Want &want, bool restart, int startId) override; + + void ScheduleSaveAbilityState(PacMap &outState) override; + + void ScheduleRestoreAbilityState(const PacMap &inState) override; + + void ScheduleUpdateConfiguration(const DummyConfiguration &config) override; + + std::vector GetFileTypes(const Uri &uri, const std::string &mimeTypeFilter) override; + + int OpenFile(const Uri &uri, const std::string &mode) override; + + int Insert(const Uri &uri, const NativeRdb::ValuesBucket &value) override; + + int Update(const Uri &uri, const NativeRdb::ValuesBucket &value, + const NativeRdb::DataAbilityPredicates &predicates) override; + + int Delete(const Uri &uri, const NativeRdb::DataAbilityPredicates &predicates) override; + + std::shared_ptr Query( + const Uri &uri, std::vector &columns, const NativeRdb::DataAbilityPredicates &predicates) override; + + std::string GetType(const Uri &uri) override; + + int OpenRawFile(const Uri &uri, const std::string &mode) override; + + bool Reload(const Uri &uri, const PacMap &extras) override; + + int BatchInsert(const Uri &uri, const std::vector &values) override; + + void NotifyMultiWinModeChanged(int32_t winModeKey, bool flag) override; + Uri NormalizeUri(const Uri &uri) override; + Uri DenormalizeUri(const Uri &uri) override; + + void NotifyTopActiveAbilityChanged(bool flag) override + { + }; + virtual bool ScheduleRegisterObserver(const Uri &uri, const sptr &dataObserver) override + { + return true; + }; + virtual bool ScheduleUnregisterObserver(const Uri &uri, const sptr &dataObserver) override + { + return true; + }; + virtual bool ScheduleNotifyChange(const Uri &uri) override + { + return true; + }; + virtual std::vector> ExecuteBatch( + const std::vector> &operations) override + { + return std::vector>(); + }; + +private: + AbilityResult result_; +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_ABILITY_SCHEDULER_H diff --git a/tools/services/abilitymgr/test/mock/libs/aakit/include/mock_ability_connect_callback.h b/tools/services/abilitymgr/test/mock/libs/aakit/include/mock_ability_connect_callback.h new file mode 100644 index 00000000000..8eeba878aff --- /dev/null +++ b/tools/services/abilitymgr/test/mock/libs/aakit/include/mock_ability_connect_callback.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_AAAFWK_INTERFACES_INNERKITS_ABILITY_CONNECT_CALLBACK_H +#define FOUNDATION_AAAFWK_INTERFACES_INNERKITS_ABILITY_CONNECT_CALLBACK_H + +#include "ability_connect_callback_interface.h" +#include "ability_connect_callback_stub.h" + +namespace OHOS { +namespace AAFwk { +class AbilityConnectCallback : public AbilityConnectionStub { +public: + AbilityConnectCallback(){}; + virtual ~AbilityConnectCallback(){}; + virtual void OnAbilityConnectDone( + const AppExecFwk::ElementName &element, const sptr &remoteObject, int resultCode) override; + virtual void OnAbilityDisconnectDone(const AppExecFwk::ElementName &element, int resultCode) override; + static int onAbilityConnectDoneCount; + static int onAbilityDisconnectDoneCount; +}; +} // namespace AAFwk +} // namespace OHOS + +#endif // FOUNDATION_AAAFWK_INTERFACES_INNERKITS_ABILITY_CONNECT_CALLBACK_H \ No newline at end of file diff --git a/tools/services/abilitymgr/test/mock/libs/aakit/src/ability_scheduler.cpp b/tools/services/abilitymgr/test/mock/libs/aakit/src/ability_scheduler.cpp new file mode 100644 index 00000000000..be56d35a9b2 --- /dev/null +++ b/tools/services/abilitymgr/test/mock/libs/aakit/src/ability_scheduler.cpp @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ability_scheduler.h" + +#include "hilog_wrapper.h" + +namespace OHOS { +namespace AAFwk { + +AbilityScheduler::AbilityScheduler() +{} + +AbilityScheduler::~AbilityScheduler() +{} + +void AbilityScheduler::ScheduleAbilityTransaction(const Want &want, const LifeCycleStateInfo &targetState) +{ + HILOG_INFO("AbilityScheduler ScheduleAbilityTransaction %d", targetState.state); + (void)want; +} + +void AbilityScheduler::SendResult(int requestCode, int resultCode, const Want &resultWant) +{ + HILOG_INFO("AbilityScheduler SendResult %d resultCode %d", requestCode, resultCode); + result_ = AbilityResult(requestCode, resultCode, resultWant); +} + +const AbilityResult &AbilityScheduler::GetResult() const +{ + return result_; +} + +void AbilityScheduler::ScheduleConnectAbility(const Want &want) +{ + (void)want; +} + +void AbilityScheduler::ScheduleDisconnectAbility(const Want &want) +{} + +void AbilityScheduler::ScheduleCommandAbility(const Want &want, bool restart, int startId) +{} + +void AbilityScheduler::ScheduleSaveAbilityState(PacMap &outState) +{} + +void AbilityScheduler::ScheduleRestoreAbilityState(const PacMap &inState) +{} + +void AbilityScheduler::ScheduleUpdateConfiguration(const DummyConfiguration &config) +{} + +std::vector AbilityScheduler::GetFileTypes(const Uri &uri, const std::string &mimeTypeFilter) +{ + std::vector values; + return values; +} + +int AbilityScheduler::OpenFile(const Uri &uri, const std::string &mode) +{ + return -1; +} + +int AbilityScheduler::Insert(const Uri &uri, const NativeRdb::ValuesBucket &value) +{ + return -1; +} + +int AbilityScheduler::Update(const Uri &uri, const NativeRdb::ValuesBucket &value, const NativeRdb::DataAbilityPredicates &predicates) +{ + return -1; +} + +int AbilityScheduler::Delete(const Uri &uri, const NativeRdb::DataAbilityPredicates &predicates) +{ + return -1; +} + +std::shared_ptr AbilityScheduler::Query( + const Uri &uri, std::vector &columns, const NativeRdb::DataAbilityPredicates &predicates) +{ + return nullptr; +} + +std::string AbilityScheduler::GetType(const Uri &uri) +{ + return result_.resultWant_.GetType(); +} + +int AbilityScheduler::OpenRawFile(const Uri &uri, const std::string &mode) +{ + return -1; +} + +bool AbilityScheduler::Reload(const Uri &uri, const PacMap &extras) +{ + return false; +} + +int AbilityScheduler::BatchInsert(const Uri &uri, const std::vector &values) +{ + return -1; +} + +void AbilityScheduler::NotifyMultiWinModeChanged(int32_t winModeKey, bool flag) +{} +Uri AbilityScheduler::NormalizeUri(const Uri &uri) +{ + Uri urivalue(""); + return urivalue; +} + +Uri AbilityScheduler::DenormalizeUri(const Uri &uri) +{ + Uri urivalue(""); + return urivalue; +} + +// void AbilityScheduler::NotifyTopActiveAbilityChanged(bool flag) +// {} + +} // namespace AAFwk +} // namespace OHOS diff --git a/tools/services/abilitymgr/test/mock/libs/aakit/src/mock_ability_connect_callback.cpp b/tools/services/abilitymgr/test/mock/libs/aakit/src/mock_ability_connect_callback.cpp new file mode 100644 index 00000000000..1857392bb0c --- /dev/null +++ b/tools/services/abilitymgr/test/mock/libs/aakit/src/mock_ability_connect_callback.cpp @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "mock_ability_connect_callback.h" +#include "hilog_wrapper.h" + +namespace OHOS { +namespace AAFwk { + +int AbilityConnectCallback::onAbilityConnectDoneCount = 0; +int AbilityConnectCallback::onAbilityDisconnectDoneCount = 0; + +void AbilityConnectCallback::OnAbilityConnectDone(const AppExecFwk::ElementName &__attribute__((unused)) element, + const sptr &__attribute__((unused)) remoteObject, int __attribute__((unused)) resultCode) +{ + HILOG_DEBUG("mock AbilityConnectCallback::OnAbilityConnectDone"); + onAbilityConnectDoneCount++; +} + +void AbilityConnectCallback::OnAbilityDisconnectDone( + const AppExecFwk::ElementName &__attribute__((unused)) element, int __attribute__((unused)) resultCode) +{ + HILOG_DEBUG("mock AbilityConnectCallback::OnAbilityDisConnectDone"); + onAbilityDisconnectDoneCount++; +} + +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/abilitymgr/test/mock/libs/ability_scheduler_mock/ability_scheduler_mock.h b/tools/services/abilitymgr/test/mock/libs/ability_scheduler_mock/ability_scheduler_mock.h new file mode 100755 index 00000000000..aa698acecaa --- /dev/null +++ b/tools/services/abilitymgr/test/mock/libs/ability_scheduler_mock/ability_scheduler_mock.h @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once +#include "ability_scheduler_interface.h" +#include +#include +#include "hilog_wrapper.h" +#include + +namespace OHOS { +namespace AAFwk { +class AbilitySchedulerMock : public IRemoteStub { +public: + AbilitySchedulerMock() : code_(0) + {} + virtual ~AbilitySchedulerMock() + {} + + MOCK_METHOD2(ScheduleAbilityTransaction, void(const Want &, const LifeCycleStateInfo &)); + MOCK_METHOD3(SendResult, void(int, int, const Want &)); + MOCK_METHOD1(ScheduleConnectAbility, void(const Want &)); + MOCK_METHOD1(ScheduleDisconnectAbility, void(const Want &)); + MOCK_METHOD1(ScheduleSaveAbilityState, void(PacMap &)); + MOCK_METHOD1(ScheduleRestoreAbilityState, void(const PacMap &)); + MOCK_METHOD1(ScheduleUpdateConfiguration, void(const DummyConfiguration &)); + MOCK_METHOD1(ScheduleNewWant, void(const Want &)); + MOCK_METHOD4(SendRequest, int(uint32_t, MessageParcel &, MessageParcel &, MessageOption &)); + MOCK_METHOD3(ScheduleCommandAbility, void(const Want &, bool, int)); + MOCK_METHOD1(NotifyTopActiveAbilityChanged, void(bool flag)); + MOCK_METHOD2(NotifyMultiWinModeChanged, void(int32_t winModeKey, bool flag)); + + int InvokeSendRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) + { + code_ = code; + return 0; + } + + int InvokeErrorSendRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) + { + code_ = code; + return UNKNOWN_ERROR; + } + + std::vector GetFileTypes(const Uri &uri, const std::string &mimeTypeFilter) + { + std::vector types; + return types; + } + + int OpenFile(const Uri &uri, const std::string &mode) + { + return -1; + } + + int Insert(const Uri &uri, const NativeRdb::ValuesBucket &value) + { + return -1; + } + + int Update(const Uri &uri, const NativeRdb::ValuesBucket &value, const NativeRdb::DataAbilityPredicates &predicates) + { + return -1; + } + + int Delete(const Uri &uri, const NativeRdb::DataAbilityPredicates &predicates) + { + return -1; + } + + std::shared_ptr Query( + const Uri &uri, std::vector &columns, const NativeRdb::DataAbilityPredicates &predicates) + { + return nullptr; + } + + virtual std::string GetType(const Uri &uri) override + { + return " "; + } + + int OpenRawFile(const Uri &uri, const std::string &mode) + { + return -1; + } + + bool Reload(const Uri &uri, const PacMap &extras) + { + return false; + } + + int BatchInsert(const Uri &uri, const std::vector &values) + { + return -1; + } + + Uri NormalizeUri(const Uri &uri) + { + Uri urivalue(""); + return urivalue; + } + + Uri DenormalizeUri(const Uri &uri) + { + Uri urivalue(""); + return urivalue; + } + + virtual bool ScheduleRegisterObserver(const Uri &uri, const sptr &dataObserver) + { + return true; + } + + virtual bool ScheduleUnregisterObserver(const Uri &uri, const sptr &dataObserver) + { + return true; + } + + virtual bool ScheduleNotifyChange(const Uri &uri) + { + return true; + } + + virtual std::vector> ExecuteBatch( + const std::vector> &operations) + { + return std::vector>(); + } + + int code_ = 0; +}; +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/abilitymgr/test/mock/libs/appexecfwk_core/BUILD.gn b/tools/services/abilitymgr/test/mock/libs/appexecfwk_core/BUILD.gn new file mode 100644 index 00000000000..e8c19894c2a --- /dev/null +++ b/tools/services/abilitymgr/test/mock/libs/appexecfwk_core/BUILD.gn @@ -0,0 +1,85 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") +import("//foundation/aafwk/standard/aafwk.gni") + +config("appexecfwk_core_mock_config") { + include_dirs = [ + "//foundation/aafwk/standard/services/abilitymgr/test/mock/libs/appexecfwk_core/include/", + "//foundation/aafwk/standard/services/abilitymgr/test/mock/libs/appexecfwk_core/include/appmgr", + "//foundation/aafwk/standard/services/abilitymgr/test/mock/libs/appexecfwk_core/include/bundlemgr", + "//foundation/aafwk/standard/interfaces/innerkits/ability_manager/include", + "//foundation/aafwk/standard/services/abilitymgr/include", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base/include", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_core/include/appmgr/", + "//foundation/aafwk/standard/frameworks/kits/ability/native/include/", + "//base/telephony/core_service/sim/include/", + "//base/notification/ces_standard/frameworks/core/include/", + "//base/notification/ces_standard/interfaces/innerkits/native/include/", + "//foundation/aafwk/standard/services/abilitymgr/test/mock/libs/aakit/include/", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base/include", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_core/include/bundlemgr/", + ] +} + +ohos_source_set("appexecfwk_appmgr_mock") { + # sources = [ "src/appmgr/mock_app_manager.cpp" ] + + configs = [ ":appexecfwk_core_mock_config" ] + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + deps = [ + "${innerkits_path}/want:want", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/distributedschedule/safwk/interfaces/innerkits/safwk:system_ability_fwk", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy:samgr_proxy", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] +} + +ohos_source_set("appexecfwk_bundlemgr_mock") { + sources = [ "src/bundlemgr/mock_bundle_manager.cpp" ] + testonly = true + configs = [ + ":appexecfwk_core_mock_config", + "${services_path}/common:common_config", + ] + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + deps = [ + "${innerkits_path}/want:want", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/distributedschedule/safwk/interfaces/innerkits/safwk:system_ability_fwk", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy:samgr_proxy", + "//third_party/googletest:gmock_main", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] +} diff --git a/tools/services/abilitymgr/test/mock/libs/appexecfwk_core/include/appmgr/app_mgr_client.h b/tools/services/abilitymgr/test/mock/libs/appexecfwk_core/include/appmgr/app_mgr_client.h new file mode 100644 index 00000000000..5dc03a6f8e9 --- /dev/null +++ b/tools/services/abilitymgr/test/mock/libs/appexecfwk_core/include/appmgr/app_mgr_client.h @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_APPEXECFWK_INTERFACES_INNERKITS_APPEXECFWK_CORE_INCLUDE_APP_MGR_CLIENT_H +#define FOUNDATION_APPEXECFWK_INTERFACES_INNERKITS_APPEXECFWK_CORE_INCLUDE_APP_MGR_CLIENT_H + +#include "iremote_object.h" +#include "refbase.h" + +#include "ability_info.h" +#include "application_info.h" +// #include "app_mgr_constants.h" +#include "iapp_state_callback.h" +#include "running_process_info.h" + +namespace OHOS { +namespace AppExecFwk { +class AppServiceManager; +class AppMgrClient { +public: + AppMgrClient(); + virtual ~AppMgrClient(); + + /** + * Load ability. + * + * @param token, Ability identify. + * @param abilityInfo, Ability information. + * @param appInfo, Application information. + * @return Returns RESULT_OK on success, others on failure. + */ + virtual AppMgrResultCode LoadAbility(const sptr &token, const sptr &preToken, + const AbilityInfo &abilityInfo, const ApplicationInfo &appInfo); + + /** + * Terminate ability. + * + * @param token Ability identify. + * + * @return Returns RESULT_OK on success, others on failure. + */ + virtual AppMgrResultCode TerminateAbility(const sptr &token); + + /** + * Update ability state. + * + * @param token Ability identify. + * @param state Ability running state. + * @return Returns RESULT_OK on success, others on failure. + */ + virtual AppMgrResultCode UpdateAbilityState(const sptr &token, const AbilityState state); + + /** + * Register Application state callback. + * + * @param callback IAppStateCallback + * @return Returns RESULT_OK on success, others on failure. + */ + virtual AppMgrResultCode RegisterAppStateCallback(const sptr &callback); + + /** + * Connect service. + * + * @return Returns RESULT_OK on success, others on failure. + */ + virtual AppMgrResultCode ConnectAppMgrService(); + + /** + * Ability manager resst. + * + * @return Returns RESULT_OK on success, others on failure. + */ + virtual AppMgrResultCode Reset(); + + /** + * AbilityBehaviorAnalysis, ability behavior analysis assistant process optimization. + * + * @param token, the unique identification to start the ability. + * @param preToken, the unique identification to call the ability. + * @param visibility, the visibility information about windows info. + * @param perceptibility, the Perceptibility information about windows info. + * @param connectionState, the service ability connection state. + * @return Returns RESULT_OK on success, others on failure. + */ + virtual AppMgrResultCode AbilityBehaviorAnalysis(const sptr &token, + const sptr &preToken, const int32_t visibility, const int32_t perceptibility, + const int32_t connectionState); + + /** + * KillProcessByAbilityToken, call KillProcessByAbilityToken() through proxy object, + * kill the process by ability token. + * + * @param token, the unique identification to the ability. + * @return Returns RESULT_OK on success, others on failure. + */ + virtual AppMgrResultCode KillProcessByAbilityToken(const sptr &token); + + /** + * KillApplication, call KillApplication() through proxy object, kill the application. + * + * @param bundleName, bundle name in Application record. + * @return ERR_OK, return back success, others fail. + */ + virtual AppMgrResultCode KillApplication(const std::string &bundleName); + + /** + * ClearUpApplicationData, call ClearUpApplicationData() through proxy project, + * clear the application data. + * + * @param bundleName, bundle name in Application record. + * @return + */ + virtual AppMgrResultCode ClearUpApplicationData(const std::string &bundleName); + + /** + * GetAllRunningProcesses, call GetAllRunningProcesses() through proxy project. + * Obtains information about application processes that are running on the device. + * + * @param info, app name in Application record. + * @return ERR_OK ,return back success��others fail. + */ + virtual AppMgrResultCode GetAllRunningProcesses(std::vector &info); + + /** + * SetAppSuspendTimes, Setting the Freezing Time of APP Background. + * + * @param time, The timeout recorded when the application enters the background . + * + * @return Success or Failure . + */ + virtual AppMgrResultCode SetAppFreezingTime(int time); + + /** + * GetAppFreezingTime, Getting the Freezing Time of APP Background. + * + * @param time, The timeout recorded when the application enters the background . + * + * @return Success or Failure . + */ + virtual AppMgrResultCode GetAppFreezingTime(int &time); + virtual void AbilityAttachTimeOut(const sptr &token); + + /** + * Checks whether a specified permission has been granted to the process identified by pid and uid + * + * @param permission Indicates the permission to check. + * @param pid Indicates the ID of the process to check. + * @param uid Indicates the UID of the process to check. + * @param message Describe success or failure + * + * @return Returns ERR_OK on success, others on failure. + */ + virtual int CompelVerifyPermission(const std::string &permission, int pid, int uid, std::string &message); + +private: + void SetServiceManager(std::unique_ptr serviceMgr); + +private: + std::unique_ptr serviceManager_; + sptr remote_; + sptr callback_; +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_APPEXECFWK_INTERFACES_INNERKITS_APPEXECFWK_CORE_INCLUDE_APP_MGR_CLIENT_H diff --git a/tools/services/abilitymgr/test/mock/libs/appexecfwk_core/include/appmgr/app_mgr_interface.h b/tools/services/abilitymgr/test/mock/libs/appexecfwk_core/include/appmgr/app_mgr_interface.h new file mode 100644 index 00000000000..766e8d23f2b --- /dev/null +++ b/tools/services/abilitymgr/test/mock/libs/appexecfwk_core/include/appmgr/app_mgr_interface.h @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_APPEXECFWK_INTERFACES_INNERKITS_APPEXECFWK_CORE_INCLUDE_APPMGR_APP_MGR_INTERFACE_H +#define FOUNDATION_APPEXECFWK_INTERFACES_INNERKITS_APPEXECFWK_CORE_INCLUDE_APPMGR_APP_MGR_INTERFACE_H + +#include "iremote_broker.h" +#include "iremote_object.h" + +#include "ability_info.h" +#include "application_info.h" +#include "app_record_id.h" +#include "iapp_state_callback.h" +#include "ams_mgr_interface.h" +#include "running_process_info.h" + +namespace OHOS { +namespace AppExecFwk { + +class IAppMgr : public IRemoteBroker { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"ohos.appexecfwk.AppMgr"); + + /** + * AttachApplication, call AttachApplication() through proxy object, + * get all the information needed to start the Application (data related to the Application ). + * + * @param app, information needed to start the Application. + * @return + */ + virtual void AttachApplication(const sptr &app) = 0; + + /** + * ApplicationForegrounded, call ApplicationForegrounded() through proxy object, + * set the application to Foreground State. + * + * @param recordId, a unique record that identifies this Application from others. + * @return + */ + virtual void ApplicationForegrounded(const int32_t recordId) = 0; + + /** + * ApplicationBackgrounded, call ApplicationBackgrounded() through proxy object, + * set the application to Backgrounded State. + * + * @param recordId, a unique record that identifies this Application from others. + * @return + */ + virtual void ApplicationBackgrounded(const int32_t recordId) = 0; + + /** + * ApplicationTerminated, call ApplicationTerminated() through proxy object, + * terminate the application. + * + * @param recordId, a unique record that identifies this Application from others. + * @return + */ + virtual void ApplicationTerminated(const int32_t recordId) = 0; + + /** + * CheckPermission, call CheckPermission() through proxy object, check the permission. + * + * @param recordId, a unique record that identifies this Application from others. + * @param permission, check the permissions. + * @return ERR_OK, return back success, others fail. + */ + virtual int CheckPermission(const int32_t recordId, const std::string &permission) = 0; + + /** + * AbilityCleaned,call through AbilityCleaned() proxy project, clean Ability record. + * + * @param token, a unique record that identifies AbilityCleaned from others. + * @return + */ + virtual void AbilityCleaned(const sptr &token) = 0; + + /** + * GetAmsMgr, call GetAmsMgr() through proxy object, get AMS interface instance. + * + * @return sptr, return to AMS interface instance. + */ + virtual sptr GetAmsMgr() = 0; + + /** + * ClearUpApplicationData, call ClearUpApplicationData() through proxy project, + * clear the application data. + * + * @param bundleName, bundle name in Application record. + * @return + */ + virtual int32_t ClearUpApplicationData(const std::string &bundleName) = 0; + + /** + * IsBackgroundRunningRestricted, call IsBackgroundRunningRestricted() through proxy project, + * Checks whether the process of this application is forbidden to run in the background. + * + * @param bundleName, bundle name in Application record. + * @return ERR_OK, return back success, others fail. + */ + virtual int IsBackgroundRunningRestricted(const std::string &bundleName) = 0; + + /** + * GetAllRunningProcesses, call GetAllRunningProcesses() through proxy project. + * Obtains information about application processes that are running on the device. + * + * @param info, app name in Application record. + * @return ERR_OK ,return back success,others fail. + */ + virtual int GetAllRunningProcesses(std::vector &info) = 0; + + /** + * SetAppSuspendTimes, Setting the Freezing Time of APP Background. + * + * @param time, The timeout recorded when the application enters the background . + * + * @return Success or Failure . + */ + virtual void SetAppFreezingTime(int time) = 0; + + /** + * GetAppFreezingTime, Getting the Freezing Time of APP Background. + * + * @param time, The timeout recorded when the application enters the background . + * + * @return Success or Failure . + */ + virtual void GetAppFreezingTime(int &time) = 0; + + enum class Message { + AMS_APP_ATTACH_APPLICATION = 0, + AMS_APP_APPLICATION_FOREGROUNDED, + AMS_APP_APPLICATION_BACKGROUNDED, + AMS_APP_APPLICATION_TERMINATED, + AMS_APP_CHECK_PERMISSION, + AMS_APP_ABILITY_CLEANED, + AMS_APP_GET_MGR_INSTANCE, + AMS_APP_CLEAR_UP_APPLICATION_DATA, + AMS_APP_IS_BACKGROUND_RUNNING_RESTRICTED, + AMS_APP_GET_ALL_RUNNING_PROCESSES, + AMS_APP_SET_APP_FREEZING_TIME, + AMS_APP_GET_APP_FREEZING_TIME, + }; +}; + +} // namespace AppExecFwk +} // namespace OHOS + +#endif // FOUNDATION_APPEXECFWK_INTERFACES_INNERKITS_APPEXECFWK_CORE_INCLUDE_APPMGR_APP_MGR_INTERFACE_H diff --git a/tools/services/abilitymgr/test/mock/libs/appexecfwk_core/include/appmgr/app_process_data.h b/tools/services/abilitymgr/test/mock/libs/appexecfwk_core/include/appmgr/app_process_data.h new file mode 100644 index 00000000000..aae4d474947 --- /dev/null +++ b/tools/services/abilitymgr/test/mock/libs/appexecfwk_core/include/appmgr/app_process_data.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_APPEXECFWK_INTERFACES_INNERKITS_APPEXECFWK_CORE_INCLUDE_APPMGR_APP_PROCESS_DATA_H +#define FOUNDATION_APPEXECFWK_INTERFACES_INNERKITS_APPEXECFWK_CORE_INCLUDE_APPMGR_APP_PROCESS_DATA_H + +#include + +#include "parcel.h" + +#include "app_mgr_constants.h" + +namespace OHOS { +namespace AppExecFwk { + +struct AppProcessData : public Parcelable { + /** + * @brief read this Sequenceable object from a Parcel. + * + * @param inParcel Indicates the Parcel object into which the Sequenceable object has been marshaled. + * @return Returns true if read successed; returns false otherwise. + */ + bool ReadFromParcel(Parcel &parcel); + + /** + * @brief Marshals this Sequenceable object into a Parcel. + * + * @param outParcel Indicates the Parcel object to which the Sequenceable object will be marshaled. + */ + virtual bool Marshalling(Parcel &parcel) const override; + + /** + * @brief Unmarshals this Sequenceable object from a Parcel. + * + * @param inParcel Indicates the Parcel object into which the Sequenceable object has been marshaled. + */ + static AppProcessData *Unmarshalling(Parcel &parcel); + + std::string appName; + std::string processName; + ApplicationState appState = ApplicationState::APP_STATE_CREATE; + pid_t pid = 0; + int32_t uid = 0; +}; + +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_APPEXECFWK_INTERFACES_INNERKITS_APPEXECFWK_CORE_INCLUDE_APPMGR_APP_PROCESS_DATA_H diff --git a/tools/services/abilitymgr/test/mock/libs/appexecfwk_core/include/appmgr/app_state_callback_host.h b/tools/services/abilitymgr/test/mock/libs/appexecfwk_core/include/appmgr/app_state_callback_host.h new file mode 100644 index 00000000000..eae36ceccf4 --- /dev/null +++ b/tools/services/abilitymgr/test/mock/libs/appexecfwk_core/include/appmgr/app_state_callback_host.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AppExecFwk_APP_STATE_CALLBACK_HOST_H +#define OHOS_AppExecFwk_APP_STATE_CALLBACK_HOST_H + +#include +#include "iremote_stub.h" +#include "nocopyable.h" +#include "string_ex.h" +#include "app_mgr_constants.h" +#include "appmgr/iapp_state_callback.h" +#include "iremote_object.h" + +namespace OHOS { +namespace AppExecFwk { +class AppStateCallbackHost : public IRemoteStub { +public: + AppStateCallbackHost(); + virtual ~AppStateCallbackHost(); + + virtual int OnRemoteRequest( + uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override; + + /** + * AbilityMgr's request is done. + * + * @param token Ability token. + * @param state Application state. + */ + virtual void OnAbilityRequestDone(const sptr &, const AbilityState) override; + + /** + * Application state changed callback. + * + * @param appProcessData Process data + */ + virtual void OnAppStateChanged(const AppProcessData &) override; + +private: + int32_t HandleOnAppStateChanged(MessageParcel &data, MessageParcel &reply); + int32_t HandleOnAbilityRequestDone(MessageParcel &data, MessageParcel &reply); + + using AppStateCallbackFunc = int32_t (AppStateCallbackHost::*)(MessageParcel &data, MessageParcel &reply); + std::map memberFuncMap_; + + DISALLOW_COPY_AND_MOVE(AppStateCallbackHost); +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_APPEXECFWK_INTERFACES_INNERKITS_APPMGR_INCLUDE_APP_STATE_CALLBACK_HOST_H diff --git a/tools/services/abilitymgr/test/mock/libs/appexecfwk_core/include/appmgr/iapp_state_callback.h b/tools/services/abilitymgr/test/mock/libs/appexecfwk_core/include/appmgr/iapp_state_callback.h new file mode 100644 index 00000000000..5abbef37c64 --- /dev/null +++ b/tools/services/abilitymgr/test/mock/libs/appexecfwk_core/include/appmgr/iapp_state_callback.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_APPEXECFWK_INTERFACES_INNERKITS_APPEXECFWK_CORE_INCLUDE_APPMGR_IAPP_STATE_CALLBACK_H +#define FOUNDATION_APPEXECFWK_INTERFACES_INNERKITS_APPEXECFWK_CORE_INCLUDE_APPMGR_IAPP_STATE_CALLBACK_H + +#include "iremote_broker.h" +#include "iremote_object.h" + +#include "app_mgr_constants.h" +#include "app_process_data.h" + +namespace OHOS { +namespace AppExecFwk { +class IAppStateCallback : public IRemoteBroker { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"ohos.appexecfwk.AppStateCallback"); + + /** + * Application state changed callback. + * + * @param appProcessData Process data + */ + virtual void OnAppStateChanged(const AppProcessData &appProcessData) = 0; + + /** + * AbilityMgr's request is done. + * + * @param token Ability token. + * @param state Application state. + */ + virtual void OnAbilityRequestDone(const sptr &token, const AbilityState state) = 0; + + enum class Message { + TRANSACT_ON_APP_STATE_CHANGED = 0, + TRANSACT_ON_ABILITY_REQUEST_DONE, + }; +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_APPEXECFWK_INTERFACES_INNERKITS_APPEXECFWK_CORE_INCLUDE_APPMGR_IAPP_STATE_CALLBACK_H diff --git a/tools/services/abilitymgr/test/mock/libs/appexecfwk_core/include/bundlemgr/bundle_mgr_interface.h b/tools/services/abilitymgr/test/mock/libs/appexecfwk_core/include/bundlemgr/bundle_mgr_interface.h new file mode 100644 index 00000000000..32985d2bcb9 --- /dev/null +++ b/tools/services/abilitymgr/test/mock/libs/appexecfwk_core/include/bundlemgr/bundle_mgr_interface.h @@ -0,0 +1,263 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_APPEXECFWK_INTERFACES_INNERKITS_BUNDLEMGR_INCLUDE_MOCK_BUNDLE_MGR_INTERFACE_H +#define FOUNDATION_APPEXECFWK_INTERFACES_INNERKITS_BUNDLEMGR_INCLUDE_MOCK_BUNDLE_MGR_INTERFACE_H + +#include "ability_info.h" +#include "application_info.h" +#include "iremote_broker.h" +#include "iremote_object.h" + +#include "bundle_info.h" +#include "hap_module_info.h" +#include "ohos/aafwk/content/want.h" +#include "permission_def.h" + +#include "module_usage_record.h" + +using OHOS::AAFwk::Want; +namespace OHOS { +namespace AppExecFwk { +enum class DumpFlag { + DUMP_BUNDLE_LIST = 1, + DUMP_ALL_BUNDLE_INFO, + DUMP_BUNDLE_INFO, +}; + +enum class InstallFlag { + NORMAL = 0, + // Allow to replace the existing bundle when the new version isn't lower than the old one. + // If the bundle does not exist, just like normal flag. + REPLACE_EXISTING = 1, +}; + +enum class InstallLocation { + INTERNAL_ONLY = 1, + PREFER_EXTERNAL = 2, +}; + +struct InstallParam : public Parcelable { + InstallFlag installFlag = InstallFlag::NORMAL; + InstallLocation installLocation = InstallLocation::INTERNAL_ONLY; + int userId = -1; + // Is keep user data while uninstall. + bool isKeepData = false; + bool noCheckSignature = false; + + // the parcel object function is not const. + bool ReadFromParcel(Parcel &parcel); + virtual bool Marshalling(Parcel &parcel) const override; + static InstallParam *Unmarshalling(Parcel &parcel); +}; +class IBundleStatusCallback : public IRemoteBroker { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"ohos.appexecfwk.BundleStatusCallback"); + + virtual void OnBundleStateChanged(const uint8_t installType, const int32_t resultCode, const std::string &resultMsg, + const std::string &bundleName) = 0; + + enum class Message { + ON_BUNDLE_STATE_CHANGED, + }; +}; + +class ICleanCacheCallback : public IRemoteBroker { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"ohos.appexecfwk.CleanCacheCallback"); + + virtual void OnCleanCacheFinished(bool succeeded) = 0; + + enum class Message { + ON_CLEAN_CACHE_CALLBACK, + }; +}; + +class OnPermissionChangedCallback : public IRemoteBroker { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"ohos.appexecfwk.OnPermissionChangedCallback"); + /** + * @brief Called when an application's permission changed. + * @param uid Indicates the uid of the application which permission changed. + */ + virtual void OnChanged(const int32_t uid) = 0; + + enum class Message { + ON_CHANGED, + }; +}; + +class IStatusReceiver : public IRemoteBroker { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"ohos.appexecfwk.StatusReceiver"); + + virtual void OnStatusNotify(const int progress) = 0; + virtual void OnFinished(const int32_t resultCode, const std::string &resultMsg) = 0; + + enum class Message { + ON_STATUS_NOTIFY, + ON_FINISHED, + }; + + enum { + SUCCESS = 0, + ERR_INSTALL_INTERNAL_ERROR, + ERR_INSTALL_PARSE_FAILED, + ERR_INSTALL_VERSION_DOWNGRADE, + ERR_INSTALL_VERIFICATION_FAILED, + ERR_INSTALL_NO_SIGNATURE_INFO, + ERR_INSTALL_UPDATE_INCOMPATIBLE, + ERR_INSTALL_INVALID_BUNDLE_FILE, + ERR_INSTALL_MISSING_INSTALLED_BUNDLE, + ERR_INSTALL_ALREADY_EXIST, + ERR_INSTALL_PARSE_UNEXPECTED, + ERR_INSTALL_PARSE_MISSING_BUNDLE, + ERR_INSTALL_PARSE_MISSING_ABILITY, + ERR_INSTALL_PARSE_NO_PROFILE, + ERR_INSTALL_PARSE_BAD_PROFILE, + ERR_INSTALL_PARSE_PROFILE_PROP_TYPE_ERROR, + ERR_INSTALL_PARSE_PROFILE_MISSING_PROP, + ERR_UNINSTALL_INVALID_NAME, + ERR_UNKNOW, + }; +}; + +class IBundleInstaller : public IRemoteBroker { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"ohos.appexecfwk.BundleInstaller"); + + virtual bool Install(const std::string &bundleFilePath, const InstallParam &installParam, + const sptr &statusReceiver) = 0; + virtual bool Uninstall(const std::string &bundleName, const InstallParam &installParam, + const sptr &statusReceiver) = 0; + + enum class Message { + INSTALL, + UNINSTALL, + }; +}; + +class IBundleMgr : public IRemoteBroker { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"ohos.aafwk.BundleMgr"); + virtual bool GetApplicationInfo( + const std::string &appName, const ApplicationFlag flag, const int userId, ApplicationInfo &appInfo) = 0; + virtual bool GetApplicationInfos( + const ApplicationFlag flag, const int userId, std::vector &appInfos) = 0; + virtual bool GetBundleInfo(const std::string &bundleName, const BundleFlag flag, BundleInfo &bundleInfo) = 0; + virtual bool GetBundleInfos(const BundleFlag flag, std::vector &bundleInfos) = 0; + virtual int GetUidByBundleName(const std::string &bundleName, const int userId) = 0; + virtual std::string GetAppIdByBundleName(const std::string &bundleName, const int userId) = 0; + virtual bool GetBundleNameForUid(const int uid, std::string &bundleName) = 0; + virtual bool GetBundlesForUid(const int uid, std::vector &bundleNames) = 0; + virtual bool GetNameForUid(const int uid, std::string &name) = 0; + virtual bool GetBundleGids(const std::string &bundleName, std::vector &gids) = 0; + virtual std::string GetAppType(const std::string &bundleName) = 0; + virtual bool CheckIsSystemAppByUid(const int uid) = 0; + virtual bool GetBundleInfosByMetaData(const std::string &metaData, std::vector &bundleInfos) = 0; + virtual bool QueryAbilityInfo(const Want &want, AbilityInfo &abilityInfo) = 0; + virtual bool QueryAbilityInfos(const Want &want, std::vector &abilityInfos) = 0; + virtual bool QueryAbilityInfoByUri(const std::string &abilityUri, AbilityInfo &abilityInfo) = 0; + virtual bool QueryKeepAliveBundleInfos(std::vector &bundleInfos) = 0; + virtual std::string GetAbilityLabel(const std::string &bundleName, const std::string &className) = 0; + virtual bool GetBundleArchiveInfo( + const std::string &hapFilePath, const BundleFlag flag, BundleInfo &bundleInfo) = 0; + virtual bool GetHapModuleInfo(const AbilityInfo &abilityInfo, HapModuleInfo &hapModuleInfo) = 0; + virtual bool GetLaunchWantForBundle(const std::string &bundleName, Want &want) = 0; + virtual int CheckPublicKeys(const std::string &firstBundleName, const std::string &secondBundleName) = 0; + virtual int CheckPermission(const std::string &bundleName, const std::string &permission) = 0; + virtual bool GetPermissionDef(const std::string &permissionName, PermissionDef &permissionDef) = 0; + virtual bool GetAllPermissionGroupDefs(std::vector &permissionDefs) = 0; + virtual bool GetAppsGrantedPermissions( + const std::vector &permissions, std::vector &appNames) = 0; + virtual bool HasSystemCapability(const std::string &capName) = 0; + virtual bool GetSystemAvailableCapabilities(std::vector &systemCaps) = 0; + virtual bool IsSafeMode() = 0; + virtual bool CleanBundleCacheFiles( + const std::string &bundleName, const sptr &cleanCacheCallback) = 0; + virtual bool CleanBundleDataFiles(const std::string &bundleName) = 0; + virtual bool RegisterBundleStatusCallback(const sptr &bundleStatusCallback) = 0; + virtual bool ClearBundleStatusCallback(const sptr &bundleStatusCallback) = 0; + virtual bool UnregisterBundleStatusCallback() = 0; + virtual bool DumpInfos(const DumpFlag flag, const std::string &bundleName, std::string &result) = 0; + virtual bool IsApplicationEnabled(const std::string &bundleName) = 0; + virtual bool SetApplicationEnabled(const std::string &bundleName, bool isEnable) = 0; + virtual bool IsAbilityEnabled(const AbilityInfo &abilityInfo) = 0; + virtual bool SetAbilityEnabled(const AbilityInfo &abilityInfo, bool isEnabled) = 0; + virtual std::string GetAbilityIcon(const std::string &bundleName, const std::string &className) = 0; + virtual bool CanRequestPermission( + const std::string &bundleName, const std::string &permissionName, const int userId) = 0; + virtual bool RequestPermissionFromUser( + const std::string &bundleName, const std::string &permission, const int userId) = 0; + virtual bool RegisterAllPermissionsChanged(const sptr &callback) = 0; + virtual bool RegisterPermissionsChanged( + const std::vector &uids, const sptr &callback) = 0; + virtual bool UnregisterPermissionsChanged(const sptr &callback) = 0; + virtual sptr GetBundleInstaller() = 0; + virtual bool GetModuleUsageRecords( + const int32_t number, std::vector &moduleUsageRecords) = 0; + virtual bool NotifyActivityLifeStatus( + const std::string &bundleName, const std::string &abilityName, const int64_t launchTime) = 0; + enum class Message { + GET_APPLICATION_INFO, + GET_APPLICATION_INFOS, + GET_BUNDLE_INFO, + GET_BUNDLE_INFOS, + GET_UID_BY_BUNDLE_NAME, + GET_APPID_BY_BUNDLE_NAME, + GET_BUNDLE_NAME_FOR_UID, + GET_BUNDLES_FOR_UID, + GET_NAME_FOR_UID, + GET_BUNDLE_GIDS, + GET_APP_TYPE, + CHECK_IS_SYSTEM_APP_BY_UID, + GET_BUNDLE_INFOS_BY_METADATA, + QUERY_ABILITY_INFO, + QUERY_ABILITY_INFO_BY_URI, + QUERY_KEEPALIVE_BUNDLE_INFOS, + GET_ABILITY_LABEL, + GET_BUNDLE_ARCHIVE_INFO, + GET_HAP_MODULE_INFO, + GET_LAUNCH_WANT_FOR_BUNDLE, + CHECK_PUBLICKEYS, + CHECK_PERMISSION, + GET_PERMISSION_DEF, + GET_ALL_PERMISSION_GROUP_DEFS, + GET_APPS_GRANTED_PERMISSIONS, + HAS_SYSTEM_CAPABILITY, + GET_SYSTEM_AVAILABLE_CAPABILITIES, + IS_SAFE_MODE, + CLEAN_BUNDLE_CACHE_FILES, + CLEAN_BUNDLE_DATA_FILES, + REGISTER_BUNDLE_STATUS_CALLBACK, + CLEAR_BUNDLE_STATUS_CALLBACK, + UNREGISTER_BUNDLE_STATUS_CALLBACK, + DUMP_INFOS, + IS_APPLICATION_ENABLED, + SET_APPLICATION_ENABLED, + IS_ABILITY_ENABLED, + SET_ABILITY_ENABLED, + GET_ABILITY_ICON, + CAN_REQUEST_PERMISSION, + REQUEST_PERMISSION_FROM_USER, + REGISTER_ALL_PERMISSIONS_CHANGED, + REGISTER_PERMISSIONS_CHANGED, + UNREGISTER_PERMISSIONS_CHANGED, + GET_BUNDLE_INSTALLER, + }; +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_APPEXECFWK_INTERFACES_INNERKITS_BUNDLEMGR_INCLUDE_MOCK_BUNDLE_MGR_INTERFACE_H \ No newline at end of file diff --git a/tools/services/abilitymgr/test/mock/libs/appexecfwk_core/include/bundlemgr/mock_bundle_manager.h b/tools/services/abilitymgr/test/mock/libs/appexecfwk_core/include/bundlemgr/mock_bundle_manager.h new file mode 100755 index 00000000000..664a3eb1686 --- /dev/null +++ b/tools/services/abilitymgr/test/mock/libs/appexecfwk_core/include/bundlemgr/mock_bundle_manager.h @@ -0,0 +1,289 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_ABILITY_MOCK_BUNDLE_MANAGER_H +#define OHOS_AAFWK_ABILITY_MOCK_BUNDLE_MANAGER_H + +#include +#include +#include "ability_info.h" +#include "application_info.h" +#include "bundlemgr/bundle_mgr_interface.h" +#include "ohos/aafwk/content/want.h" +#include "iremote_proxy.h" +#include "iremote_stub.h" +#include "form_info.h" +#include "shortcut_info.h" + +namespace OHOS { +namespace AppExecFwk { +namespace { +const std::string COM_IX_HIWORLD = "com.ix.hiworld"; +const std::string COM_IX_HIMUSIC = "com.ix.hiMusic"; +const std::string COM_IX_HIRADIO = "com.ix.hiRadio"; +const std::string COM_IX_HISERVICE = "com.ix.hiService"; +const std::string COM_IX_MUSICSERVICE = "com.ix.musicService"; +const std::string COM_IX_HIDATA = "com.ix.hiData"; +constexpr int32_t MAX_SYS_UID = 2899; +constexpr int32_t ROOT_UID = 0; + +auto HiWordInfo = [](std::string bundleName, AbilityInfo &abilityInfo, ElementName &elementTemp) { + abilityInfo.name = elementTemp.GetAbilityName(); + abilityInfo.bundleName = elementTemp.GetBundleName(); + abilityInfo.applicationInfo.bundleName = elementTemp.GetBundleName(); + abilityInfo.applicationName = "Helloworld"; + abilityInfo.applicationInfo.name = "Helloworld"; + abilityInfo.type = AbilityType::PAGE; + abilityInfo.applicationInfo.isLauncherApp = true; + return true; +}; + +auto HiMusicInfo = [](std::string bundleName, AbilityInfo &abilityInfo, ElementName &elementTemp) { + abilityInfo.name = elementTemp.GetAbilityName(); + abilityInfo.bundleName = elementTemp.GetBundleName(); + abilityInfo.applicationInfo.bundleName = elementTemp.GetBundleName(); + abilityInfo.applicationName = "hiMusic"; + abilityInfo.applicationInfo.name = "hiMusic"; + abilityInfo.type = AbilityType::PAGE; + abilityInfo.applicationInfo.isLauncherApp = false; + + if (elementTemp.GetAbilityName() == "MusicAbility") { + abilityInfo.process = "p1"; + abilityInfo.launchMode = LaunchMode::STANDARD; + } + if (elementTemp.GetAbilityName() == "MusicTopAbility") { + abilityInfo.process = "p1"; + abilityInfo.launchMode = LaunchMode::SINGLETOP; + } + if (elementTemp.GetAbilityName() == "MusicSAbility") { + abilityInfo.process = "p2"; + abilityInfo.launchMode = LaunchMode::SINGLETON; + } + return true; +}; + +auto HiRadioInfo = [](std::string bundleName, AbilityInfo &abilityInfo, ElementName &elementTemp) { + abilityInfo.name = elementTemp.GetAbilityName(); + abilityInfo.bundleName = elementTemp.GetBundleName(); + abilityInfo.applicationInfo.bundleName = elementTemp.GetBundleName(); + abilityInfo.applicationName = "hiRadio"; + abilityInfo.applicationInfo.name = "hiRadio"; + abilityInfo.type = AbilityType::PAGE; + abilityInfo.process = "p3"; + if (elementTemp.GetAbilityName() == "RadioAbility") { + abilityInfo.launchMode = LaunchMode::STANDARD; + } + if (elementTemp.GetAbilityName() == "RadioTopAbility") { + abilityInfo.launchMode = LaunchMode::SINGLETON; + } + return true; +}; + +auto HiServiceInfo = [](std::string bundleName, AbilityInfo &abilityInfo, ElementName &elementTemp) { + abilityInfo.name = elementTemp.GetAbilityName(); + abilityInfo.bundleName = elementTemp.GetBundleName(); + abilityInfo.applicationInfo.bundleName = elementTemp.GetBundleName(); + abilityInfo.applicationName = "hiService"; + abilityInfo.applicationInfo.name = "hiService"; + abilityInfo.type = AbilityType::SERVICE; + abilityInfo.process = "p4"; + return true; +}; + +auto MusicServiceInfo = [](std::string bundleName, AbilityInfo &abilityInfo, ElementName &elementTemp) { + abilityInfo.name = elementTemp.GetAbilityName(); + abilityInfo.bundleName = elementTemp.GetBundleName(); + abilityInfo.applicationInfo.bundleName = elementTemp.GetBundleName(); + abilityInfo.applicationName = "musicService"; + abilityInfo.applicationInfo.name = "musicService"; + abilityInfo.type = AbilityType::SERVICE; + abilityInfo.process = "p5"; + return true; +}; + +auto HiDataInfo = [](std::string bundleName, AbilityInfo &abilityInfo, ElementName &elementTemp) { + abilityInfo.name = elementTemp.GetAbilityName(); + abilityInfo.bundleName = elementTemp.GetBundleName(); + abilityInfo.applicationInfo.bundleName = elementTemp.GetBundleName(); + abilityInfo.applicationName = "hiData"; + abilityInfo.applicationInfo.name = "hiData"; + abilityInfo.type = AbilityType::DATA; + abilityInfo.process = "p6"; + return true; +}; +} // namespace +class BundleMgrProxy : public IRemoteProxy { +public: + explicit BundleMgrProxy(const sptr &impl) : IRemoteProxy(impl) + {} + virtual ~BundleMgrProxy() + {} + int QueryWantAbility(const AAFwk::Want &want, std::vector &abilityInfos); + + bool QueryAbilityInfo(const AAFwk::Want &want, AbilityInfo &abilityInfo) override; + + bool QueryAbilityInfoByUri(const std::string &uri, AbilityInfo &abilityInfo) override; + + bool GetApplicationInfo( + const std::string &appName, const ApplicationFlag flag, const int userId, ApplicationInfo &appInfo) override; + + bool GetBundleInfo(const std::string &bundleName, const BundleFlag flag, BundleInfo &bundleInfo) override; + + virtual bool NotifyActivityLifeStatus( + const std::string &bundleName, const std::string &abilityName, const int64_t launchTime) override; + virtual bool CheckIsSystemAppByUid(const int uid) override; + MOCK_METHOD3(GetApplicationInfos, + bool(const ApplicationFlag flag, const int userId, std::vector &appInfos)); + MOCK_METHOD2(GetBundleInfos, bool(const BundleFlag flag, std::vector &bundleInfos)); + MOCK_METHOD2(GetUidByBundleName, int(const std::string &bundleName, const int userId)); + MOCK_METHOD2(GetBundleNameForUid, bool(const int uid, std::string &bundleName)); + MOCK_METHOD2(GetBundleGids, bool(const std::string &bundleName, std::vector &gids)); + MOCK_METHOD1(GetAppType, std::string(const std::string &bundleName)); + MOCK_METHOD2(GetBundleInfosByMetaData, bool(const std::string &metaData, std::vector &bundleInfos)); + MOCK_METHOD1(QueryKeepAliveBundleInfos, bool(std::vector &bundleInfos)); + MOCK_METHOD2(GetAbilityLabel, std::string(const std::string &bundleName, const std::string &className)); + MOCK_METHOD3( + GetBundleArchiveInfo, bool(const std::string &hapFilePath, const BundleFlag flag, BundleInfo &bundleInfo)); + MOCK_METHOD2(GetHapModuleInfo, bool(const AbilityInfo &abilityInfo, HapModuleInfo &hapModuleInfo)); + MOCK_METHOD2(GetLaunchWantForBundle, bool(const std::string &bundleName, Want &want)); + MOCK_METHOD2(CheckPublicKeys, int(const std::string &firstBundleName, const std::string &secondBundleName)); + MOCK_METHOD2(CheckPermission, int(const std::string &bundleName, const std::string &permission)); + MOCK_METHOD2(GetPermissionDef, bool(const std::string &permissionName, PermissionDef &permissionDef)); + MOCK_METHOD1(GetAllPermissionGroupDefs, bool(std::vector &permissionDefs)); + MOCK_METHOD2(GetAppsGrantedPermissions, + bool(const std::vector &permissions, std::vector &appNames)); + MOCK_METHOD1(HasSystemCapability, bool(const std::string &capName)); + MOCK_METHOD1(GetSystemAvailableCapabilities, bool(std::vector &systemCaps)); + MOCK_METHOD0(IsSafeMode, bool()); + MOCK_METHOD2(CleanBundleCacheFiles, + bool(const std::string &bundleName, const sptr &cleanCacheCallback)); + MOCK_METHOD1(CleanBundleDataFiles, bool(const std::string &bundleName)); + MOCK_METHOD3(RequestPermissionFromUser, + bool(const std::string &bundleName, const std::string &permission, const int userId)); + MOCK_METHOD1(RegisterBundleStatusCallback, bool(const sptr &bundleStatusCallback)); + MOCK_METHOD1(ClearBundleStatusCallback, bool(const sptr &bundleStatusCallback)); + MOCK_METHOD0(UnregisterBundleStatusCallback, bool()); + MOCK_METHOD3(DumpInfos, bool(const DumpFlag flag, const std::string &bundleName, std::string &result)); + MOCK_METHOD1(IsApplicationEnabled, bool(const std::string &bundleName)); + MOCK_METHOD2(SetApplicationEnabled, bool(const std::string &bundleName, bool isEnable)); + MOCK_METHOD0(GetBundleInstaller, sptr()); + MOCK_METHOD2(GetAppIdByBundleName, std::string(const std::string &bundleName, const int userId)); + MOCK_METHOD2(GetBundlesForUid, bool(const int uid, std::vector &bundleNames)); + MOCK_METHOD2(GetNameForUid, bool(const int uid, std::string &name)); + MOCK_METHOD2(QueryAbilityInfos, bool(const Want &want, std::vector &abilityInfos)); + MOCK_METHOD1(IsAbilityEnabled, bool(const AbilityInfo &abilityInfo)); + MOCK_METHOD2(SetAbilityEnabled, bool(const AbilityInfo &abilityInfo, bool isEnabled)); + MOCK_METHOD2(GetAbilityIcon, std::string(const std::string &bundleName, const std::string &className)); + MOCK_METHOD3( + CanRequestPermission, bool(const std::string &bundleName, const std::string &permissionName, const int userId)); + MOCK_METHOD1(RegisterAllPermissionsChanged, bool(const sptr &callback)); + MOCK_METHOD2(RegisterPermissionsChanged, + bool(const std::vector &uids, const sptr &callback)); + MOCK_METHOD1(UnregisterPermissionsChanged, bool(const sptr &callback)); + MOCK_METHOD1(GetAllFormsInfo, bool(std::vector &formInfos)); + MOCK_METHOD2(GetFormsInfoByApp, bool(const std::string &bundleName, std::vector &formInfos)); + MOCK_METHOD3(GetFormsInfoByModule, + bool(const std::string &bundleName, const std::string &moduleName, std::vector &formInfos)); + MOCK_METHOD2(GetShortcutInfos, bool(const std::string &bundleName, std::vector &shortcutInfos)); +}; + +class BundleMgrStub : public IRemoteStub { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"IBundleMgr"); + virtual int OnRemoteRequest( + uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override; +}; + +class BundleMgrService : public BundleMgrStub { +public: + BundleMgrService(); + ~BundleMgrService(); + + bool QueryAbilityInfo(const AAFwk::Want &want, AbilityInfo &abilityInfo) override; + bool QueryAbilityInfoByUri(const std::string &uri, AbilityInfo &abilityInfo) override; + bool GetApplicationInfo( + const std::string &appName, const ApplicationFlag flag, const int userId, ApplicationInfo &appInfo) override; + bool GetBundleInfo(const std::string &bundleName, const BundleFlag flag, BundleInfo &bundleInfo) override; + int GetUidByBundleName(const std::string &bundleName, const int userId) override; + virtual bool CheckIsSystemAppByUid(const int uid) override; + + bool CheckWantEntity(const AAFwk::Want &, AbilityInfo &); + + virtual bool NotifyActivityLifeStatus( + const std::string &bundleName, const std::string &abilityName, const int64_t launchTime) override; + MOCK_METHOD2(QueryWantAbility, int(const AAFwk::Want &want, std::vector &abilityInfos)); + MOCK_METHOD3(GetApplicationInfos, + bool(const ApplicationFlag flag, const int userId, std::vector &appInfos)); + MOCK_METHOD2(GetBundleInfos, bool(const BundleFlag flag, std::vector &bundleInfos)); + MOCK_METHOD2(GetBundleNameForUid, bool(const int uid, std::string &bundleName)); + MOCK_METHOD2(GetBundleGids, bool(const std::string &bundleName, std::vector &gids)); + MOCK_METHOD1(GetAppType, std::string(const std::string &bundleName)); + MOCK_METHOD2(GetBundleInfosByMetaData, bool(const std::string &metaData, std::vector &bundleInfos)); + MOCK_METHOD1(QueryKeepAliveBundleInfos, bool(std::vector &bundleInfos)); + MOCK_METHOD2(GetAbilityLabel, std::string(const std::string &bundleName, const std::string &className)); + MOCK_METHOD3( + GetBundleArchiveInfo, bool(const std::string &hapFilePath, const BundleFlag flag, BundleInfo &bundleInfo)); + MOCK_METHOD2(GetHapModuleInfo, bool(const AbilityInfo &abilityInfo, HapModuleInfo &hapModuleInfo)); + MOCK_METHOD2(GetLaunchWantForBundle, bool(const std::string &bundleName, Want &want)); + MOCK_METHOD2(CheckPublicKeys, int(const std::string &firstBundleName, const std::string &secondBundleName)); + MOCK_METHOD2(CheckPermission, int(const std::string &bundleName, const std::string &permission)); + MOCK_METHOD2(GetPermissionDef, bool(const std::string &permissionName, PermissionDef &permissionDef)); + MOCK_METHOD1(GetAllPermissionGroupDefs, bool(std::vector &permissionDefs)); + MOCK_METHOD2(GetAppsGrantedPermissions, + bool(const std::vector &permissions, std::vector &appNames)); + MOCK_METHOD1(HasSystemCapability, bool(const std::string &capName)); + MOCK_METHOD1(GetSystemAvailableCapabilities, bool(std::vector &systemCaps)); + MOCK_METHOD0(IsSafeMode, bool()); + MOCK_METHOD2(CleanBundleCacheFiles, + bool(const std::string &bundleName, const sptr &cleanCacheCallback)); + MOCK_METHOD1(CleanBundleDataFiles, bool(const std::string &bundleName)); + MOCK_METHOD3(RequestPermissionFromUser, + bool(const std::string &bundleName, const std::string &permission, const int userId)); + MOCK_METHOD1(RegisterBundleStatusCallback, bool(const sptr &bundleStatusCallback)); + MOCK_METHOD1(ClearBundleStatusCallback, bool(const sptr &)); + MOCK_METHOD2(SetApplicationEnabled, bool(const std::string &bundleName, bool isEnable)); + MOCK_METHOD0(GetBundleInstaller, sptr()); + MOCK_METHOD2(GetAppIdByBundleName, std::string(const std::string &bundleName, const int userId)); + MOCK_METHOD2(GetBundlesForUid, bool(const int uid, std::vector &bundleNames)); + MOCK_METHOD2(GetNameForUid, bool(const int uid, std::string &name)); + MOCK_METHOD2(QueryAbilityInfos, bool(const Want &want, std::vector &abilityInfos)); + MOCK_METHOD1(IsAbilityEnabled, bool(const AbilityInfo &abilityInfo)); + MOCK_METHOD2(SetAbilityEnabled, bool(const AbilityInfo &abilityInfo, bool isEnabled)); + MOCK_METHOD2(GetAbilityIcon, std::string(const std::string &bundleName, const std::string &className)); + MOCK_METHOD3( + CanRequestPermission, bool(const std::string &bundleName, const std::string &permissionName, const int userId)); + MOCK_METHOD1(RegisterAllPermissionsChanged, bool(const sptr &callback)); + MOCK_METHOD2(RegisterPermissionsChanged, + bool(const std::vector &uids, const sptr &callback)); + MOCK_METHOD1(UnregisterPermissionsChanged, bool(const sptr &callback)); + MOCK_METHOD2(GetModuleUsageRecords, bool(const int32_t number, std::vector &moduleUsageRecords)); + MOCK_METHOD1(GetAllFormsInfo, bool(std::vector &formInfos)); + MOCK_METHOD2(GetFormsInfoByApp, bool(const std::string &bundleName, std::vector &formInfos)); + MOCK_METHOD3(GetFormsInfoByModule, + bool(const std::string &bundleName, const std::string &moduleName, std::vector &formInfos)); + MOCK_METHOD2(GetShortcutInfos, bool(const std::string &bundleName, std::vector &shortcutInfos)); + MOCK_METHOD0(UnregisterBundleStatusCallback, bool()); + MOCK_METHOD3(DumpInfos, bool(const DumpFlag flag, const std::string &bundleName, std::string &result)); + MOCK_METHOD1(IsApplicationEnabled, bool(const std::string &bundleName)); + +public: + using QueryAbilityInfoFunType = + std::function; + std::map abilityInfoMap_; +}; +} // namespace AppExecFwk +} // namespace OHOS + +#endif // OHOS_AAFWK_ABILITY_MOCK_BUNDLE_MANAGER_H diff --git a/tools/services/abilitymgr/test/mock/libs/appexecfwk_core/src/appmgr/app_mgr_client.cpp b/tools/services/abilitymgr/test/mock/libs/appexecfwk_core/src/appmgr/app_mgr_client.cpp new file mode 100644 index 00000000000..39d6f63bf14 --- /dev/null +++ b/tools/services/abilitymgr/test/mock/libs/appexecfwk_core/src/appmgr/app_mgr_client.cpp @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "app_mgr_client.h" + +#include +#include +#include + +#include "if_system_ability_manager.h" +#include "ipc_skeleton.h" + +#include "app_mgr_interface.h" +#include "app_service_manager.h" + +namespace OHOS { +namespace AppExecFwk { + +AppMgrClient::AppMgrClient() +{} + +AppMgrClient::~AppMgrClient() +{} + +AppMgrResultCode AppMgrClient::LoadAbility(const sptr &token, const sptr &preToken, + const AbilityInfo &abilityInfo, const ApplicationInfo &appInfo) +{ + return AppMgrResultCode::RESULT_OK; +} + +AppMgrResultCode AppMgrClient::TerminateAbility(const sptr &token) +{ + return AppMgrResultCode::RESULT_OK; +} + +AppMgrResultCode AppMgrClient::UpdateAbilityState(const sptr &token, const AbilityState state) +{ + return AppMgrResultCode::RESULT_OK; +} + +AppMgrResultCode AppMgrClient::RegisterAppStateCallback(const sptr &callback) +{ + return AppMgrResultCode::RESULT_OK; +} + +AppMgrResultCode AppMgrClient::Reset() +{ + return AppMgrResultCode::RESULT_OK; +} + +AppMgrResultCode AppMgrClient::AbilityBehaviorAnalysis(const sptr &token, + const sptr &preToken, const int32_t visibility, const int32_t perceptibility, + const int32_t connectionState) +{ + return AppMgrResultCode::RESULT_OK; +} + +AppMgrResultCode AppMgrClient::KillProcessByAbilityToken(const sptr &token) +{ + return AppMgrResultCode::RESULT_OK; +} + +AppMgrResultCode AppMgrClient::KillApplication(const std::string &bundleName) +{ + return AppMgrResultCode::RESULT_OK; +} + +AppMgrResultCode AppMgrClient::ClearUpApplicationData(const std::string &bundleName) +{ + return AppMgrResultCode::RESULT_OK; +} + +AppMgrResultCode AppMgrClient::GetAllRunningProcesses(std::vector &info) +{ + return AppMgrResultCode::RESULT_OK; +} + +AppMgrResultCode AppMgrClient::SetAppFreezingTime(int time) +{ + return AppMgrResultCode::RESULT_OK; +} + +AppMgrResultCode AppMgrClient::GetAppFreezingTime(int &time) +{ + return AppMgrResultCode::RESULT_OK; +} + +AppMgrResultCode AppMgrClient::ConnectAppMgrService() +{ + return AppMgrResultCode::RESULT_OK; +} + +// void AppMgrClient::SetServiceManager(std::unique_ptr serviceMgr) +// {} + +void AppMgrClient::AbilityAttachTimeOut(const sptr &token) +{} + +int AppMgrClient::CompelVerifyPermission(const std::string &permission, int pid, int uid, std::string &message) +{ + return AppMgrResultCode::RESULT_OK; +} + +} // namespace AppExecFwk +} // namespace OHOS diff --git a/tools/services/abilitymgr/test/mock/libs/appexecfwk_core/src/appmgr/app_state_callback_host.cpp b/tools/services/abilitymgr/test/mock/libs/appexecfwk_core/src/appmgr/app_state_callback_host.cpp new file mode 100644 index 00000000000..f79e2397e6a --- /dev/null +++ b/tools/services/abilitymgr/test/mock/libs/appexecfwk_core/src/appmgr/app_state_callback_host.cpp @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "app_state_callback_host.h" +#include "appexecfwk_errors.h" +#include "app_log_wrapper.h" +#include "ipc_types.h" +#include "iremote_object.h" +#include "app_state_callback_proxy.h" + +namespace OHOS { +namespace AppExecFwk { + +AppStateCallbackHost::AppStateCallbackHost() +{} + +AppStateCallbackHost::~AppStateCallbackHost() +{} + +int AppStateCallbackHost::OnRemoteRequest( + uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) +{ + return 0; +} + +void AppStateCallbackHost::OnAbilityRequestDone(const sptr &, const AbilityState) +{ + APP_LOGD("OnAbilityRequestDone called"); +} + +void AppStateCallbackHost::OnAppStateChanged(const AppProcessData &) +{ + APP_LOGD("OnAppStateChanged called"); +} + +int32_t AppStateCallbackHost::HandleOnAppStateChanged(MessageParcel &data, MessageParcel &reply) +{ + return NO_ERROR; +} + +int32_t AppStateCallbackHost::HandleOnAbilityRequestDone(MessageParcel &data, MessageParcel &reply) +{ + return NO_ERROR; +} + +} // namespace AppExecFwk +} // namespace OHOS diff --git a/tools/services/abilitymgr/test/mock/libs/appexecfwk_core/src/appmgr/app_state_callback_proxy.cpp b/tools/services/abilitymgr/test/mock/libs/appexecfwk_core/src/appmgr/app_state_callback_proxy.cpp new file mode 100644 index 00000000000..82033a61b96 --- /dev/null +++ b/tools/services/abilitymgr/test/mock/libs/appexecfwk_core/src/appmgr/app_state_callback_proxy.cpp @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "app_state_callback_proxy.h" + +#include "ipc_types.h" + +#include "app_log_wrapper.h" + +namespace OHOS { +namespace AppExecFwk { + +AppStateCallbackProxy::AppStateCallbackProxy(const sptr &impl) : IRemoteProxy(impl) +{} + +bool AppStateCallbackProxy::WriteInterfaceToken(MessageParcel &data) +{ + return true; +} + +void AppStateCallbackProxy::OnAbilityRequestDone(const sptr &token, const AbilityState state) +{} + +void AppStateCallbackProxy::OnAppStateChanged(const AppProcessData &appProcessData) +{} + +} // namespace AppExecFwk +} // namespace OHOS diff --git a/tools/services/abilitymgr/test/mock/libs/appexecfwk_core/src/appmgr/mock_app_scheduler.cpp b/tools/services/abilitymgr/test/mock/libs/appexecfwk_core/src/appmgr/mock_app_scheduler.cpp new file mode 100644 index 00000000000..ce8df131d7e --- /dev/null +++ b/tools/services/abilitymgr/test/mock/libs/appexecfwk_core/src/appmgr/mock_app_scheduler.cpp @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "app_scheduler.h" + +#include "hilog_wrapper.h" +#include "ability_util.h" +#include "ability_manager_errors.h" +#include "ability_record.h" +#include "appmgr/app_mgr_constants.h" + +namespace OHOS { +namespace AAFwk { +AppScheduler::AppScheduler() +{ + HILOG_INFO(" Test AppScheduler::AppScheduler()"); +} + +AppScheduler::~AppScheduler() +{ + HILOG_INFO("Test AppScheduler::~AppScheduler()"); +} + +bool AppScheduler::Init(const std::weak_ptr &callback) +{ + HILOG_INFO("Test AppScheduler::Init()"); + if (!callback.lock()) { + return false; + } + return true; +} + +int AppScheduler::LoadAbility(const sptr &token, const sptr &preToken, + const AppExecFwk::AbilityInfo &abilityInfo, const AppExecFwk::ApplicationInfo &applicationInfo) +{ + HILOG_INFO("Test AppScheduler::LoadAbility()"); + if (applicationInfo.bundleName.find("com.ix.First.Test") != std::string::npos) { + return INNER_ERR; + } + return ERR_OK; +} + +int AppScheduler::TerminateAbility(const sptr &token) +{ + HILOG_INFO("Test AppScheduler::TerminateAbility()"); + return ERR_OK; +} + +void AppScheduler::MoveToForground(const sptr &token) +{ + HILOG_INFO("Test AppScheduler::MoveToForground()"); +} + +void AppScheduler::MoveToBackground(const sptr &token) +{ + HILOG_INFO("Test AppScheduler::MoveToBackground()"); +} + +void AppScheduler::AbilityBehaviorAnalysis(const sptr &token, const sptr &preToken, + const int32_t visibility, const int32_t perceptibility, const int32_t connectionState) +{ + HILOG_INFO("Test AppScheduler::AbilityBehaviorAnalysis()"); +} + +void AppScheduler::KillProcessByAbilityToken(const sptr &token) +{ + HILOG_INFO("Test AppScheduler::KillProcessByAbilityToken()"); +} + +AppAbilityState AppScheduler::ConvertToAppAbilityState(const int32_t state) +{ + AppExecFwk::AbilityState abilityState = static_cast(state); + switch (abilityState) { + case AppExecFwk::AbilityState::ABILITY_STATE_FOREGROUND: { + return AppAbilityState::ABILITY_STATE_FOREGROUND; + } + case AppExecFwk::AbilityState::ABILITY_STATE_BACKGROUND: { + return AppAbilityState::ABILITY_STATE_BACKGROUND; + } + default: + return AppAbilityState::ABILITY_STATE_UNDEFINED; + } +} + +AppAbilityState AppScheduler::GetAbilityState() const +{ + return appAbilityState_; +} + +void AppScheduler::OnAbilityRequestDone(const sptr &token, const AppExecFwk::AbilityState state) +{ + HILOG_INFO("Test AppScheduler::OnAbilityRequestDone()"); +} + +int AppScheduler::KillApplication(const std::string &bundleName) +{ + HILOG_INFO("Test AppScheduler::KillApplication()"); + return ERR_OK; +} + +void AppScheduler::AttachTimeOut(const sptr &token) +{ + HILOG_INFO("Test AppScheduler::AttachTimeOut()"); +} + +int AppScheduler::CompelVerifyPermission(const std::string &permission, int pid, int uid, std::string &message) +{ + HILOG_INFO("Test AppScheduler::CompelVerifyPermission()"); + return ERR_OK; +} + +void AppScheduler::OnAppStateChanged(const AppExecFwk::AppProcessData &appData) +{ + HILOG_INFO("Test AppScheduler::OnAppStateChanged()"); +} +} // namespace AAFwk +} // namespace OHOS diff --git a/tools/services/abilitymgr/test/mock/libs/appexecfwk_core/src/bundlemgr/mock_bundle_manager.cpp b/tools/services/abilitymgr/test/mock/libs/appexecfwk_core/src/bundlemgr/mock_bundle_manager.cpp new file mode 100644 index 00000000000..2b7e1827e88 --- /dev/null +++ b/tools/services/abilitymgr/test/mock/libs/appexecfwk_core/src/bundlemgr/mock_bundle_manager.cpp @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "mock_bundle_manager.h" +#include "ability_info.h" +#include "application_info.h" +#include "hilog_wrapper.h" +#include "ability_config.h" + +namespace OHOS { +namespace AppExecFwk { +using namespace OHOS::AAFwk; + +int BundleMgrProxy::QueryWantAbility( + const AAFwk::Want &__attribute__((unused)) want, std::vector &__attribute__((unused)) abilityInfos) +{ + return 0; +} + +bool BundleMgrProxy::QueryAbilityInfo(const AAFwk::Want &want, AbilityInfo &abilityInfo) +{ + ElementName eleName = want.GetElement(); + if (eleName.GetBundleName().empty()) { + return false; + } + abilityInfo.name = eleName.GetAbilityName(); + abilityInfo.bundleName = eleName.GetBundleName(); + abilityInfo.applicationName = eleName.GetAbilityName() + "App"; + abilityInfo.visible = true; + if (abilityInfo.bundleName != "com.ix.hiworld") { + abilityInfo.applicationInfo.isLauncherApp = false; + } + return true; +} + +bool BundleMgrProxy::GetBundleInfo(const std::string &bundleName, const BundleFlag flag, BundleInfo &bundleInfo) +{ + return true; +} + +bool BundleMgrProxy::QueryAbilityInfoByUri(const std::string &uri, AbilityInfo &abilityInfo) +{ + return false; +} + +bool BundleMgrProxy::GetApplicationInfo( + const std::string &appName, const ApplicationFlag flag, const int userId, ApplicationInfo &appInfo) +{ + if (appName.empty()) { + return false; + } + appInfo.name = "Helloworld"; + appInfo.bundleName = "com.ix.hiworld"; + return true; +} + +bool BundleMgrProxy::NotifyActivityLifeStatus( + const std::string &bundleName, const std::string &abilityName, const int64_t launchTime) +{ + GTEST_LOG_(INFO) << "BundleMgrProxy::NotifyActivityLifeStatus()"; + return true; +} + +int BundleMgrStub::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) +{ + return 0; +} + +BundleMgrService::BundleMgrService() +{ + abilityInfoMap_.emplace(COM_IX_HIWORLD, HiWordInfo); + abilityInfoMap_.emplace(COM_IX_HIMUSIC, HiMusicInfo); + abilityInfoMap_.emplace(COM_IX_HIRADIO, HiRadioInfo); + abilityInfoMap_.emplace(COM_IX_HISERVICE, HiServiceInfo); + abilityInfoMap_.emplace(COM_IX_MUSICSERVICE, MusicServiceInfo); + abilityInfoMap_.emplace(COM_IX_HIDATA, HiDataInfo); + GTEST_LOG_(INFO) << "BundleMgrService()"; +} + +BundleMgrService::~BundleMgrService() +{ + GTEST_LOG_(INFO) << "~BundleMgrService()"; +} + +bool BundleMgrService::GetBundleInfo(const std::string &bundleName, const BundleFlag flag, BundleInfo &bundleInfo) +{ + return true; +} + +bool BundleMgrService::QueryAbilityInfo(const AAFwk::Want &want, AbilityInfo &abilityInfo) +{ + if (CheckWantEntity(want, abilityInfo)) { + return true; + } + + ElementName elementTemp = want.GetElement(); + std::string abilityNameTemp = elementTemp.GetAbilityName(); + std::string bundleNameTemp = elementTemp.GetBundleName(); + abilityInfo.deviceId = elementTemp.GetDeviceID(); + abilityInfo.visible = true; + + if (bundleNameTemp.empty() || abilityNameTemp.empty()) { + return false; + } + + auto fun = abilityInfoMap_.find(bundleNameTemp); + if (fun != abilityInfoMap_.end()) { + auto call = fun->second; + if (call) { + call(bundleNameTemp, abilityInfo, elementTemp); + return true; + } + } + if (std::string::npos != elementTemp.GetBundleName().find("service")) { + abilityInfo.type = AppExecFwk::AbilityType::SERVICE; + } + abilityInfo.name = elementTemp.GetAbilityName(); + abilityInfo.bundleName = elementTemp.GetBundleName(); + abilityInfo.applicationName = elementTemp.GetBundleName(); + abilityInfo.deviceId = elementTemp.GetDeviceID(); + abilityInfo.applicationInfo.bundleName = elementTemp.GetBundleName(); + abilityInfo.applicationInfo.name = "hello"; + if (want.HasEntity(Want::ENTITY_HOME) && want.GetAction() == Want::ACTION_HOME) { + abilityInfo.applicationInfo.isLauncherApp = true; + } else { + abilityInfo.applicationInfo.isLauncherApp = false; + abilityInfo.applicationInfo.iconPath = "icon path"; + abilityInfo.applicationInfo.label = "app label"; + } + return true; +} + +bool BundleMgrService::QueryAbilityInfoByUri(const std::string &uri, AbilityInfo &abilityInfo) +{ + return false; +} + +bool BundleMgrService::GetApplicationInfo( + const std::string &appName, const ApplicationFlag flag, const int userId, ApplicationInfo &appInfo) +{ + if (appName.empty()) { + return false; + } + return true; +} + +bool BundleMgrService::CheckIsSystemAppByUid(const int uid) +{ + int maxSysUid{MAX_SYS_UID}; + int baseSysUid{ROOT_UID}; + if (uid >= baseSysUid && uid <= maxSysUid) { + return true; + } + return false; +} + +bool BundleMgrService::CheckWantEntity(const AAFwk::Want &want, AbilityInfo &abilityInfo) +{ + auto entityVector = want.GetEntities(); + ElementName element = want.GetElement(); + if (entityVector.empty()) { + return false; + } + + auto find = false; + // filter ams onstart + for (const auto &entity : entityVector) { + if (entity == Want::FLAG_HOME_INTENT_FROM_SYSTEM && element.GetAbilityName().empty() && + element.GetBundleName().empty()) { + find = true; + break; + } + } + + auto bundleName = element.GetBundleName(); + auto abilityName = element.GetAbilityName(); + if (find || (bundleName == AbilityConfig::SYSTEM_UI_BUNDLE_NAME && + (abilityName == AbilityConfig::SYSTEM_UI_STATUS_BAR || + abilityName == AbilityConfig::SYSTEM_UI_NAVIGATION_BAR))) { + return true; + } + + return false; +} + +int BundleMgrService::GetUidByBundleName(const std::string &bundleName, const int userId) +{ + return 1000; +} + +bool BundleMgrService::NotifyActivityLifeStatus( + const std::string &bundleName, const std::string &abilityName, const int64_t launchTime) +{ + GTEST_LOG_(INFO) << "BundleMgrService::NotifyActivityLifeStatus()"; + return true; +} + +} // namespace AppExecFwk +} // namespace OHOS diff --git a/tools/services/abilitymgr/test/mock/libs/sa_mgr/BUILD.gn b/tools/services/abilitymgr/test/mock/libs/sa_mgr/BUILD.gn new file mode 100644 index 00000000000..2c074f41bf4 --- /dev/null +++ b/tools/services/abilitymgr/test/mock/libs/sa_mgr/BUILD.gn @@ -0,0 +1,44 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") +import("//foundation/aafwk/standard/aafwk.gni") + +config("sa_mgr_mock_config") { + include_dirs = [ + "${services_path}/abilitymgr/include", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy/include", + ] + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } +} + +ohos_source_set("sa_mgr_mock") { + sources = [ "src/sa_mgr_client_mock.cpp" ] + configs = [ + ":sa_mgr_mock_config", + "${services_path}/common:common_config", + ] + + deps = [ + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy:samgr_proxy", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] +} diff --git a/tools/services/abilitymgr/test/mock/libs/sa_mgr/src/sa_mgr_client_mock.cpp b/tools/services/abilitymgr/test/mock/libs/sa_mgr/src/sa_mgr_client_mock.cpp new file mode 100644 index 00000000000..a8852163300 --- /dev/null +++ b/tools/services/abilitymgr/test/mock/libs/sa_mgr/src/sa_mgr_client_mock.cpp @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "sa_mgr_client.h" +#include "hilog_wrapper.h" + +#include "ipc_skeleton.h" +#include "string_ex.h" + +#include "if_system_ability_manager.h" +#include "iservice_registry.h" + +namespace OHOS { +namespace AAFwk { + +SaMgrClient::SaMgrClient() +{} + +SaMgrClient::~SaMgrClient() +{} + +sptr SaMgrClient::GetSystemAbility(const int32_t systemAbilityId) +{ + HILOG_INFO("Test GetSystemAbility id : %{public}d", systemAbilityId); + return servicesMap_[systemAbilityId]; +} + +void SaMgrClient::RegisterSystemAbility(const int32_t systemAbilityId, sptr broker) +{ + HILOG_INFO("Test RegisterSystemAbility id : %{public}d", systemAbilityId); + servicesMap_[systemAbilityId] = broker; +} + +} // namespace AAFwk +} // namespace OHOS diff --git a/tools/services/abilitymgr/test/mock/libs/system_ability_mock/system_ability.h b/tools/services/abilitymgr/test/mock/libs/system_ability_mock/system_ability.h new file mode 100644 index 00000000000..85bfdde3062 --- /dev/null +++ b/tools/services/abilitymgr/test/mock/libs/system_ability_mock/system_ability.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_AAFWK_SERVICES_TEST_MOCK_SYSTEM_ABILITY_H +#define FOUNDATION_AAFWK_SERVICES_TEST_MOCK_SYSTEM_ABILITY_H + +#include "hilog/log.h" +#include "iremote_object.h" + +namespace OHOS { +#define REGISTER_SYSTEM_ABILITY_BY_ID(a, b, c) +#define REGISTER_SYSTEM_ABILITY(abilityClassName, abilityId, runOnCreate) +#define DECLEAR_SYSTEM_ABILITY(className) + +static constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, 0xD001100, "MockSystemAbility"}; + +class SystemAbility { +public: + static bool MakeAndRegisterAbility(SystemAbility *) + { + return true; + } + +protected: + virtual void OnStart() + { + HiviewDFX::HiLog::Debug(LABEL, "Mock SystemAbility OnStart called"); + } + + virtual void OnStop() + { + HiviewDFX::HiLog::Debug(LABEL, "Mock SystemAbility OnStop called"); + } + + bool Publish(sptr systemAbility) + { + HiviewDFX::HiLog::Debug(LABEL, "Mock SystemAbility Publish called"); + systemAbility.ForceSetRefPtr(nullptr); + // For test just mock to return true + return true; + } + + SystemAbility(bool runOnCreate = false) + { + HiviewDFX::HiLog::Debug(LABEL, "Mock SystemAbility default Creator called %d", runOnCreate); + } + + SystemAbility(const int32_t serviceId, bool runOnCreate = false) + { + HiviewDFX::HiLog::Debug(LABEL, "Mock SystemAbility Creator called %d", runOnCreate); + } + + virtual ~SystemAbility() + { + HiviewDFX::HiLog::Debug(LABEL, "Mock SystemAbility Destructor called"); + } +}; +} // namespace OHOS +#endif // FOUNDATION_AAFWK_SERVICES_TEST_MOCK_SYSTEM_ABILITY_H diff --git a/tools/services/abilitymgr/test/unittest/phone/ability_connect_callback_proxy_test/BUILD.gn b/tools/services/abilitymgr/test/unittest/phone/ability_connect_callback_proxy_test/BUILD.gn new file mode 100644 index 00000000000..99c1afcc495 --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/ability_connect_callback_proxy_test/BUILD.gn @@ -0,0 +1,69 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/test.gni") +import("//foundation/aafwk/standard/aafwk.gni") + +module_output_path = "aafwk_standard/abilitymgr" + +ohos_unittest("ability_connect_callback_proxy_test") { + module_out_path = module_output_path + + include_dirs = [ + "${services_path}/abilitymgr/test/mock/libs/system_ability_mock", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy/include", + ] + + sources = [ + "//foundation/aafwk/standard/services/abilitymgr/test/mock/libs/appexecfwk_core/src/appmgr/mock_app_scheduler.cpp", + "ability_connect_callback_proxy_test.cpp", # add mock file + ] + + configs = [ + "${services_path}/abilitymgr:abilityms_config", + "${services_path}/abilitymgr/test/mock:aafwk_mock_config", + ] + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + deps = [ + "${innerkits_path}/want:want", + "${services_path}/abilitymgr/test:abilityms_test_source", + "${services_path}/abilitymgr/test/mock/libs/aakit:aakit_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_appmgr_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_bundlemgr_mock", + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/frameworks/kits/ability/native:dummy_classes", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//third_party/googletest:gmock_main", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + "native_appdatamgr:native_appdatafwk", + "native_appdatamgr:native_dataability", + "native_appdatamgr:native_rdb", + ] +} + +group("unittest") { + testonly = true + + deps = [ ":ability_connect_callback_proxy_test" ] +} diff --git a/tools/services/abilitymgr/test/unittest/phone/ability_connect_callback_proxy_test/ability_connect_callback_proxy_test.cpp b/tools/services/abilitymgr/test/unittest/phone/ability_connect_callback_proxy_test/ability_connect_callback_proxy_test.cpp new file mode 100644 index 00000000000..df8600e45de --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/ability_connect_callback_proxy_test/ability_connect_callback_proxy_test.cpp @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "ability_connect_callback_proxy.h" +#include "mock_ability_connect_callback_stub.h" + +using namespace testing::ext; +using namespace testing; +namespace OHOS { +namespace AAFwk { + +class AbilityConnectCallBackProxyTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + + std::shared_ptr proxy_{nullptr}; +}; + +void AbilityConnectCallBackProxyTest::SetUpTestCase(void) +{} +void AbilityConnectCallBackProxyTest::TearDownTestCase(void) +{} +void AbilityConnectCallBackProxyTest::SetUp() +{} +void AbilityConnectCallBackProxyTest::TearDown() +{} + +/* + * Feature: AAFwk + * Function: AbilityConnectionProxy + * SubFunction: IPC of client and server + * FunctionPoints: OnAbilityConnectDone + * EnvConditions: NA + * CaseDescription: verify OnAbilityConnectDone IPC between client and server. + */ +HWTEST_F(AbilityConnectCallBackProxyTest, AbilityConnectionCallBack_IPC_001, TestSize.Level1) +{ + sptr mockAbilityConnectStub(new MockAbilityConnectCallback()); + sptr callback(new AbilityConnectionProxy(mockAbilityConnectStub)); + AppExecFwk::ElementName element; + sptr remoteObject; + EXPECT_CALL(*mockAbilityConnectStub, OnAbilityConnectDone(_, _, _)) + .Times(1) + .WillOnce(InvokeWithoutArgs(mockAbilityConnectStub.GetRefPtr(), &MockAbilityConnectCallback::PostVoid)); + callback->OnAbilityConnectDone(element, remoteObject, 0); + mockAbilityConnectStub->Wait(); +} + +/* + * Feature: AAFwk + * Function: AbilityConnectionProxy + * SubFunction: IPC of client and server + * FunctionPoints: OnAbilityDisconnectDone + * EnvConditions: NA + * CaseDescription: verify OnAbilityDisconnectDone IPC between client and server. + */ +HWTEST_F(AbilityConnectCallBackProxyTest, AbilityConnectionCallBack_IPC_002, TestSize.Level1) +{ + sptr mockAbilityConnectStub(new MockAbilityConnectCallback()); + sptr callback(new AbilityConnectionProxy(mockAbilityConnectStub)); + AppExecFwk::ElementName element; + EXPECT_CALL(*mockAbilityConnectStub, OnAbilityDisconnectDone(_, _)) + .Times(1) + .WillOnce(InvokeWithoutArgs(mockAbilityConnectStub.GetRefPtr(), &MockAbilityConnectCallback::PostVoid)); + callback->OnAbilityDisconnectDone(element, 0); + mockAbilityConnectStub->Wait(); +} + +/* + * Feature: AAFwk + * Function: AbilityConnectionProxy + * SubFunction: IPC of client and server + * FunctionPoints: instance + * EnvConditions: NA + * CaseDescription: instance is success. + */ +HWTEST_F(AbilityConnectCallBackProxyTest, AbilityConnectionCallBack_IPC_003, TestSize.Level1) +{ + sptr mockAbilityConnectStub(new MockAbilityConnectCallback()); + sptr callback(new AbilityConnectionProxy(mockAbilityConnectStub)); + EXPECT_NE(callback, nullptr); +} +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/abilitymgr/test/unittest/phone/ability_connect_callback_proxy_test/mock_ability_connect_callback_stub.h b/tools/services/abilitymgr/test/unittest/phone/ability_connect_callback_proxy_test/mock_ability_connect_callback_stub.h new file mode 100644 index 00000000000..848dc69007f --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/ability_connect_callback_proxy_test/mock_ability_connect_callback_stub.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MOCK_FOUNDATION_AAAFWK_INTERFACES_INNERKITS_ABILITY_CONNECT_CALLBACK_STUB_H +#define MOCK_FOUNDATION_AAAFWK_INTERFACES_INNERKITS_ABILITY_CONNECT_CALLBACK_STUB_H + +#include +#include "ability_connect_callback_stub.h" +#include "semaphore_ex.h" + +namespace OHOS { +namespace AAFwk { +class MockAbilityConnectCallback : public AbilityConnectionStub { +public: + MOCK_METHOD3(OnAbilityConnectDone, + void(const AppExecFwk::ElementName &element, const sptr &remoteObject, int resultCode)); + MOCK_METHOD2(OnAbilityDisconnectDone, void(const AppExecFwk::ElementName &element, int resultCode)); + + void Wait() + { + sem_.Wait(); + } + + int Post() + { + sem_.Post(); + return 0; + } + + void PostVoid() + { + sem_.Post(); + } + +private: + Semaphore sem_; +}; +} // namespace AAFwk +} // namespace OHOS + +#endif // MOCK_FOUNDATION_AAAFWK_INTERFACES_INNERKITS_ABILITY_CONNECT_CALLBACK_STUB_H \ No newline at end of file diff --git a/tools/services/abilitymgr/test/unittest/phone/ability_connect_callback_stub_test/BUILD.gn b/tools/services/abilitymgr/test/unittest/phone/ability_connect_callback_stub_test/BUILD.gn new file mode 100644 index 00000000000..f1c14e1b147 --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/ability_connect_callback_stub_test/BUILD.gn @@ -0,0 +1,70 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/test.gni") +import("//foundation/aafwk/standard/aafwk.gni") + +module_output_path = "aafwk_standard/abilitymgr" + +ohos_unittest("ability_connect_callback_stub_test") { + module_out_path = module_output_path + + include_dirs = [ + "${services_path}/abilitymgr/test/mock/libs/system_ability_mock", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy/include", + ] + + sources = [ + "//foundation/aafwk/standard/services/abilitymgr/test/mock/libs/appexecfwk_core/src/appmgr/mock_app_scheduler.cpp", + "ability_connect_callback_stub_test.cpp", # add mock file + ] + + configs = [ + "${services_path}/abilitymgr:abilityms_config", + "${services_path}/abilitymgr/test/mock:aafwk_mock_config", + ] + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + deps = [ + "${innerkits_path}/want:want", + "${services_path}/abilitymgr/test:abilityms_test_source", + "${services_path}/abilitymgr/test/mock/libs/aakit:aakit_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_appmgr_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_bundlemgr_mock", + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/frameworks/kits/ability/native:dummy_classes", + + # "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//third_party/googletest:gmock_main", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + "native_appdatamgr:native_appdatafwk", + "native_appdatamgr:native_dataability", + "native_appdatamgr:native_rdb", + ] +} + +group("unittest") { + testonly = true + + deps = [ ":ability_connect_callback_stub_test" ] +} diff --git a/tools/services/abilitymgr/test/unittest/phone/ability_connect_callback_stub_test/ability_connect_callback_stub_test.cpp b/tools/services/abilitymgr/test/unittest/phone/ability_connect_callback_stub_test/ability_connect_callback_stub_test.cpp new file mode 100644 index 00000000000..8c901c98532 --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/ability_connect_callback_stub_test/ability_connect_callback_stub_test.cpp @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "iremote_proxy.h" +#include "mock_ability_connect_callback_stub.h" +#include "ability_connect_callback_proxy.h" + +using namespace testing::ext; +using namespace OHOS::AAFwk; +using namespace OHOS; +using namespace testing; + +class AbilityConnectCallBackStubTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + + void WriteInterfaceToken(MessageParcel &data); +}; + +void AbilityConnectCallBackStubTest::SetUpTestCase(void) +{} +void AbilityConnectCallBackStubTest::TearDownTestCase(void) +{} +void AbilityConnectCallBackStubTest::SetUp() +{} +void AbilityConnectCallBackStubTest::TearDown() +{} + +void AbilityConnectCallBackStubTest::WriteInterfaceToken(MessageParcel &data) +{ + data.WriteInterfaceToken(AbilityConnectionProxy::GetDescriptor()); +} + +/* + * Feature: AbilityConnectionStub + * Function: OnRemoteRequest + * SubFunction: NA + * FunctionPoints: AbilityConnectionStub OnRemoteRequest + * EnvConditions: ElementName is nullptr + * CaseDescription: Verify that on remote request is normal and abnormal + */ +HWTEST_F(AbilityConnectCallBackStubTest, AbilityConnectionCallBack_IPC_001, TestSize.Level0) +{ + sptr mockAbilityConnectStub(new MockAbilityConnectCallback()); + + MessageParcel data; + MessageParcel reply; + MessageOption option; + + sptr remoteObject; + int32_t reqCode = 10; + + WriteInterfaceToken(data); + data.WriteParcelable(nullptr); + data.WriteParcelable(remoteObject); + data.WriteInt32(reqCode); + + int res = mockAbilityConnectStub->OnRemoteRequest(IAbilityConnection::ON_ABILITY_CONNECT_DONE, data, reply, option); + EXPECT_EQ(res, ERR_INVALID_VALUE); +} + +/* + * Feature: AbilityConnectionStub + * Function: OnRemoteRequest + * SubFunction: NA + * FunctionPoints: AbilityConnectionStub OnRemoteRequest + * EnvConditions: ElementName is not nullptr + * CaseDescription: Verify that on remote request is normal and abnormal + */ +HWTEST_F(AbilityConnectCallBackStubTest, AbilityConnectionCallBack_IPC_002, TestSize.Level0) +{ + sptr mockAbilityConnectStub(new MockAbilityConnectCallback()); + + MessageParcel data; + MessageParcel reply; + MessageOption option; + + auto element = std::make_shared("bundlename", "appname", "abilityname"); + sptr remoteObject; + int32_t reqCode = 10; + + WriteInterfaceToken(data); + data.WriteParcelable(element.get()); + data.WriteParcelable(remoteObject); + data.WriteInt32(reqCode); + + EXPECT_CALL(*mockAbilityConnectStub, OnAbilityConnectDone(_, _, _)).Times(1); + int res = mockAbilityConnectStub->OnRemoteRequest(IAbilityConnection::ON_ABILITY_CONNECT_DONE, data, reply, option); + EXPECT_EQ(res, ERR_OK); +} + +/* + * Feature: AbilityConnectionStub + * Function: OnRemoteRequest + * SubFunction: NA + * FunctionPoints: AbilityConnectionStub OnRemoteRequest + * EnvConditions: ElementName is nullptr + * CaseDescription: Verify that on remote request is normal and abnormal + */ +HWTEST_F(AbilityConnectCallBackStubTest, AbilityConnectionCallBack_IPC_003, TestSize.Level0) +{ + sptr mockAbilityConnectStub(new MockAbilityConnectCallback()); + + MessageParcel data; + MessageParcel reply; + MessageOption option; + + sptr remoteObject; + int32_t reqCode = 10; + + WriteInterfaceToken(data); + data.WriteParcelable(nullptr); + data.WriteInt32(reqCode); + + int res = + mockAbilityConnectStub->OnRemoteRequest(IAbilityConnection::ON_ABILITY_DISCONNECT_DONE, data, reply, option); + EXPECT_EQ(res, ERR_INVALID_VALUE); +} + +/* + * Feature: AbilityConnectionStub + * Function: OnRemoteRequest + * SubFunction: NA + * FunctionPoints: AbilityConnectionStub OnRemoteRequest + * EnvConditions: ElementName is not nullptr + * CaseDescription: Verify that on remote request is normal and abnormal + */ +HWTEST_F(AbilityConnectCallBackStubTest, AbilityConnectionCallBack_IPC_004, TestSize.Level0) +{ + sptr mockAbilityConnectStub(new MockAbilityConnectCallback()); + + MessageParcel data; + MessageParcel reply; + MessageOption option; + + auto element = std::make_shared("bundlename", "appname", "abilityname"); + sptr remoteObject; + int32_t reqCode = 10; + + WriteInterfaceToken(data); + data.WriteParcelable(element.get()); + data.WriteInt32(reqCode); + + EXPECT_CALL(*mockAbilityConnectStub, OnAbilityDisconnectDone(_, _)).Times(1); + int res = + mockAbilityConnectStub->OnRemoteRequest(IAbilityConnection::ON_ABILITY_DISCONNECT_DONE, data, reply, option); + EXPECT_EQ(res, ERR_OK); +} \ No newline at end of file diff --git a/tools/services/abilitymgr/test/unittest/phone/ability_connect_callback_stub_test/mock_ability_connect_callback_stub.h b/tools/services/abilitymgr/test/unittest/phone/ability_connect_callback_stub_test/mock_ability_connect_callback_stub.h new file mode 100644 index 00000000000..848dc69007f --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/ability_connect_callback_stub_test/mock_ability_connect_callback_stub.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MOCK_FOUNDATION_AAAFWK_INTERFACES_INNERKITS_ABILITY_CONNECT_CALLBACK_STUB_H +#define MOCK_FOUNDATION_AAAFWK_INTERFACES_INNERKITS_ABILITY_CONNECT_CALLBACK_STUB_H + +#include +#include "ability_connect_callback_stub.h" +#include "semaphore_ex.h" + +namespace OHOS { +namespace AAFwk { +class MockAbilityConnectCallback : public AbilityConnectionStub { +public: + MOCK_METHOD3(OnAbilityConnectDone, + void(const AppExecFwk::ElementName &element, const sptr &remoteObject, int resultCode)); + MOCK_METHOD2(OnAbilityDisconnectDone, void(const AppExecFwk::ElementName &element, int resultCode)); + + void Wait() + { + sem_.Wait(); + } + + int Post() + { + sem_.Post(); + return 0; + } + + void PostVoid() + { + sem_.Post(); + } + +private: + Semaphore sem_; +}; +} // namespace AAFwk +} // namespace OHOS + +#endif // MOCK_FOUNDATION_AAAFWK_INTERFACES_INNERKITS_ABILITY_CONNECT_CALLBACK_STUB_H \ No newline at end of file diff --git a/tools/services/abilitymgr/test/unittest/phone/ability_connect_manage_test/BUILD.gn b/tools/services/abilitymgr/test/unittest/phone/ability_connect_manage_test/BUILD.gn new file mode 100644 index 00000000000..0fbe0ec84b4 --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/ability_connect_manage_test/BUILD.gn @@ -0,0 +1,65 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/test.gni") +import("//foundation/aafwk/standard/aafwk.gni") + +module_output_path = "aafwk_standard/abilitymgr" + +ohos_unittest("ability_connect_manage_test") { + module_out_path = module_output_path + + sources = [ + # add mock file + "//foundation/aafwk/standard/frameworks/kits/ability/native/src/dummy_data_ability_predicates.cpp", + "//foundation/aafwk/standard/frameworks/kits/ability/native/src/dummy_result_set.cpp", + "//foundation/aafwk/standard/frameworks/kits/ability/native/src/dummy_values_bucket.cpp", + "//foundation/aafwk/standard/services/abilitymgr/test/mock/libs/appexecfwk_core/src/appmgr/mock_app_scheduler.cpp", + "ability_connect_manage_test.cpp", + ] + + configs = [ + "${services_path}/abilitymgr:abilityms_config", + "${services_path}/abilitymgr/test/mock:aafwk_mock_config", + ] + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + deps = [ + "${innerkits_path}/want:want", + "${services_path}/abilitymgr/test:abilityms_test_source", + "${services_path}/abilitymgr/test/mock/libs/aakit:aakit_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_appmgr_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_bundlemgr_mock", + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//foundation/distributedschedule/safwk/interfaces/innerkits/safwk:system_ability_fwk", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy:samgr_proxy", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] +} + +group("unittest") { + testonly = true + + deps = [ ":ability_connect_manage_test" ] +} diff --git a/tools/services/abilitymgr/test/unittest/phone/ability_connect_manage_test/ability_connect_manage_test.cpp b/tools/services/abilitymgr/test/unittest/phone/ability_connect_manage_test/ability_connect_manage_test.cpp new file mode 100644 index 00000000000..e0b64b04de9 --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/ability_connect_manage_test/ability_connect_manage_test.cpp @@ -0,0 +1,1382 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#define private public +#define protected public +#include "ability_connect_manager.h" +#undef private +#undef protected + +#include "ability_manager_errors.h" +#include "ability_scheduler.h" +#include "event_handler.h" +#include "mock_ability_connect_callback.h" + +using namespace testing::ext; +using namespace OHOS::AppExecFwk; + +namespace OHOS { +namespace AAFwk { +template +static void WaitUntilTaskCalled(const F &f, const std::shared_ptr &handler, std::atomic &taskCalled) +{ + const uint32_t maxRetryCount = 1000; + const uint32_t sleepTime = 1000; + uint32_t count = 0; + if (handler->PostTask(f)) { + while (!taskCalled.load()) { + ++count; + // if delay more than 1 second, break + if (count >= maxRetryCount) { + break; + } + usleep(sleepTime); + } + } +} + +static void WaitUntilTaskDone(const std::shared_ptr &handler) +{ + std::atomic taskCalled(false); + auto f = [&taskCalled]() { taskCalled.store(true); }; + WaitUntilTaskCalled(f, handler, taskCalled); +} + +class AbilityConnectManageTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + + AbilityConnectManager *ConnectManager() const; + + AbilityRequest GenerateAbilityRequest(const std::string &deviceName, const std::string &abilityName, + const std::string &appName, const std::string &bundleName); + + static constexpr int TEST_WAIT_TIME = 1000000; + +protected: + AbilityRequest abilityRequest_{}; + AbilityRequest abilityRequest1_{}; + std::shared_ptr serviceRecord_{nullptr}; + std::shared_ptr serviceRecord1_{nullptr}; + OHOS::sptr serviceToken_{nullptr}; + OHOS::sptr serviceToken1_{nullptr}; + OHOS::sptr callbackA_{nullptr}; + OHOS::sptr callbackB_{nullptr}; + +private: + std::shared_ptr connectManager_; +}; + +AbilityRequest AbilityConnectManageTest::GenerateAbilityRequest(const std::string &deviceName, + const std::string &abilityName, const std::string &appName, const std::string &bundleName) +{ + ElementName element(deviceName, bundleName, abilityName); + Want want; + want.SetElement(element); + + AbilityInfo abilityInfo; + abilityInfo.visible = true; + abilityInfo.applicationName = appName; + abilityInfo.type = AbilityType::SERVICE; + abilityInfo.name = abilityName; + abilityInfo.bundleName = bundleName; + abilityInfo.deviceId = deviceName; + ApplicationInfo appinfo; + appinfo.name = appName; + abilityInfo.applicationInfo = appinfo; + AbilityRequest abilityRequest; + abilityRequest.want = want; + abilityRequest.abilityInfo = abilityInfo; + abilityRequest.appInfo = appinfo; + + return abilityRequest; +} + +void AbilityConnectManageTest::SetUpTestCase(void) +{} +void AbilityConnectManageTest::TearDownTestCase(void) +{} + +void AbilityConnectManageTest::SetUp(void) +{ + connectManager_ = std::make_unique(); + // generate ability request + std::string deviceName = "device"; + std::string abilityName = "ServiceAbility"; + std::string appName = "hiservcie"; + std::string bundleName = "com.ix.hiservcie"; + abilityRequest_ = GenerateAbilityRequest(deviceName, abilityName, appName, bundleName); + serviceRecord_ = AbilityRecord::CreateAbilityRecord(abilityRequest_); + serviceToken_ = serviceRecord_->GetToken(); + std::string deviceName1 = "device"; + std::string abilityName1 = "musicServiceAbility"; + std::string appName1 = "musicservcie"; + std::string bundleName1 = "com.ix.musicservcie"; + abilityRequest1_ = GenerateAbilityRequest(deviceName1, abilityName1, appName1, bundleName1); + serviceRecord1_ = AbilityRecord::CreateAbilityRecord(abilityRequest1_); + serviceToken1_ = serviceRecord_->GetToken(); + callbackA_ = new AbilityConnectCallback(); + callbackB_ = new AbilityConnectCallback(); +} + +void AbilityConnectManageTest::TearDown(void) +{ + // reset the callback count + AbilityConnectCallback::onAbilityConnectDoneCount = 0; + AbilityConnectCallback::onAbilityDisconnectDoneCount = 0; + serviceRecord_ = nullptr; +} + +AbilityConnectManager *AbilityConnectManageTest::ConnectManager() const +{ + return connectManager_.get(); +} + +/* + * Feature: AbilityConnectManager + * Function: StartAbility + * SubFunction: NA + * FunctionPoints: StartAbility + * EnvConditions:NA + * CaseDescription: Verify the normal process of startability + */ +HWTEST_F(AbilityConnectManageTest, AAFWK_Connect_Service_001, TestSize.Level1) +{ + auto handler = std::make_shared(EventRunner::Create()); + ConnectManager()->SetEventHandler(handler); + + auto result = ConnectManager()->StartAbility(abilityRequest_); + EXPECT_EQ(OHOS::ERR_OK, result); + WaitUntilTaskDone(handler); + + auto elementName = abilityRequest_.want.GetElement().GetURI(); + auto service = ConnectManager()->GetServiceRecordByElementName(elementName); + EXPECT_NE(service, nullptr); + EXPECT_EQ(static_cast(ConnectManager()->GetServiceMap().size()), 1); + + service->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + + auto result1 = ConnectManager()->StartAbility(abilityRequest_); + WaitUntilTaskDone(handler); + EXPECT_EQ(OHOS::ERR_OK, result1); + EXPECT_EQ(static_cast(ConnectManager()->GetServiceMap().size()), 1); + + service->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVATING); + auto result2 = ConnectManager()->StartAbility(abilityRequest_); + WaitUntilTaskDone(handler); + EXPECT_EQ(OHOS::AAFwk::START_SERVICE_ABILITY_ACTIVING, result2); + EXPECT_EQ(static_cast(ConnectManager()->GetServiceMap().size()), 1); +} + +/* + * Feature: AbilityConnectManager + * Function: TerminateAbility + * SubFunction: NA + * FunctionPoints: StartAbility and TerminateAbility + * EnvConditions:NA + * CaseDescription: Verify the following: + * 1.token is nullptr, terminate ability failed + * 2.token is not nullptr, terminate ability success, and verify the status + */ +HWTEST_F(AbilityConnectManageTest, AAFWK_Connect_Service_002, TestSize.Level1) +{ + auto handler = std::make_shared(EventRunner::Create()); + ConnectManager()->SetEventHandler(handler); + + auto result = ConnectManager()->StartAbility(abilityRequest_); + EXPECT_EQ(OHOS::ERR_OK, result); + WaitUntilTaskDone(handler); + + OHOS::sptr nullToken = nullptr; + auto result1 = ConnectManager()->TerminateAbility(nullToken); + EXPECT_EQ(OHOS::ERR_INVALID_VALUE, result1); + + auto elementName = abilityRequest_.want.GetElement().GetURI(); + auto service = ConnectManager()->GetServiceRecordByElementName(elementName); + EXPECT_NE(service, nullptr); + + auto result2 = ConnectManager()->TerminateAbility(service->GetToken()); + WaitUntilTaskDone(handler); + EXPECT_EQ(OHOS::ERR_OK, result2); + EXPECT_EQ(service->GetAbilityState(), TERMINATING); +} + +/* + * Feature: AbilityConnectManager + * Function: TerminateAbility + * SubFunction: NA + * FunctionPoints: StartAbility and TerminateAbility + * EnvConditions:NA + * CaseDescription: Verify ability is terminating, terminate ability success + */ +HWTEST_F(AbilityConnectManageTest, AAFWK_Connect_Service_003, TestSize.Level1) +{ + auto handler = std::make_shared(EventRunner::Create()); + ConnectManager()->SetEventHandler(handler); + + auto result = ConnectManager()->StartAbility(abilityRequest_); + EXPECT_EQ(OHOS::ERR_OK, result); + WaitUntilTaskDone(handler); + + auto elementName = abilityRequest_.want.GetElement().GetURI(); + auto service = ConnectManager()->GetServiceRecordByElementName(elementName); + EXPECT_NE(service, nullptr); + + service->SetTerminatingState(); + auto result1 = ConnectManager()->TerminateAbility(service->GetToken()); + WaitUntilTaskDone(handler); + EXPECT_EQ(OHOS::ERR_OK, result1); + EXPECT_NE(service->GetAbilityState(), TERMINATING); +} + +/* + * Feature: AbilityConnectManager + * Function: TerminateAbility + * SubFunction: NA + * FunctionPoints: StartAbility and TerminateAbility + * EnvConditions: NA + * CaseDescription: Verify service is connected, terminate ability failed + */ +HWTEST_F(AbilityConnectManageTest, AAFWK_Connect_Service_004, TestSize.Level1) +{ + auto handler = std::make_shared(EventRunner::Create()); + ConnectManager()->SetEventHandler(handler); + + auto result = ConnectManager()->StartAbility(abilityRequest_); + EXPECT_EQ(OHOS::ERR_OK, result); + WaitUntilTaskDone(handler); + + auto result1 = ConnectManager()->ConnectAbilityLocked(abilityRequest_, callbackA_, nullptr); + EXPECT_EQ(0, result1); + + auto elementName = abilityRequest_.want.GetElement().GetURI(); + auto service = ConnectManager()->GetServiceRecordByElementName(elementName); + EXPECT_NE(service, nullptr); + + auto result2 = ConnectManager()->TerminateAbility(service->GetToken()); + WaitUntilTaskDone(handler); + EXPECT_EQ(OHOS::AAFwk::TERMINATE_SERVICE_IS_CONNECTED, result2); + EXPECT_NE(service->GetAbilityState(), TERMINATING); +} + +/* + * Feature: AbilityConnectManager + * Function: StopServiceAbility + * SubFunction: NA + * FunctionPoints: StartAbility and StopServiceAbility + * EnvConditions: NA + * CaseDescription: Verify the following: + * 1.token is nullptr, stop service ability failed + * 2.token is not nullptr, stop service ability success, and verify the status + */ +HWTEST_F(AbilityConnectManageTest, AAFWK_Connect_Service_005, TestSize.Level1) +{ + auto handler = std::make_shared(EventRunner::Create()); + ConnectManager()->SetEventHandler(handler); + + auto result = ConnectManager()->StartAbility(abilityRequest_); + EXPECT_EQ(OHOS::ERR_OK, result); + WaitUntilTaskDone(handler); + + auto elementName = abilityRequest_.want.GetElement().GetURI(); + auto service = ConnectManager()->GetServiceRecordByElementName(elementName); + EXPECT_NE(service, nullptr); + + AbilityRequest otherRequest; + auto result1 = ConnectManager()->StopServiceAbility(otherRequest); + WaitUntilTaskDone(handler); + EXPECT_EQ(OHOS::ERR_INVALID_VALUE, result1); + + auto result2 = ConnectManager()->StopServiceAbility(abilityRequest_); + WaitUntilTaskDone(handler); + EXPECT_EQ(OHOS::ERR_OK, result2); + EXPECT_EQ(service->GetAbilityState(), TERMINATING); +} + +/* + * Feature: AbilityConnectManager + * Function: StopServiceAbility + * SubFunction: NA + * FunctionPoints: StartAbility and StopServiceAbility + * EnvConditions:NA + * CaseDescription: Verify ability is terminating, stop service ability success + */ +HWTEST_F(AbilityConnectManageTest, AAFWK_Connect_Service_006, TestSize.Level1) +{ + auto handler = std::make_shared(EventRunner::Create()); + ConnectManager()->SetEventHandler(handler); + + auto result = ConnectManager()->StartAbility(abilityRequest_); + EXPECT_EQ(OHOS::ERR_OK, result); + WaitUntilTaskDone(handler); + + auto elementName = abilityRequest_.want.GetElement().GetURI(); + auto service = ConnectManager()->GetServiceRecordByElementName(elementName); + EXPECT_NE(service, nullptr); + + service->SetTerminatingState(); + auto result1 = ConnectManager()->StopServiceAbility(abilityRequest_); + WaitUntilTaskDone(handler); + EXPECT_EQ(OHOS::ERR_OK, result1); + EXPECT_NE(service->GetAbilityState(), TERMINATING); +} + +/* + * Feature: AbilityConnectManager + * Function: StopServiceAbility + * SubFunction: NA + * FunctionPoints: StartAbility and StopServiceAbility + * EnvConditions: NA + * CaseDescription: Verify service is connected, stop service ability failed + */ +HWTEST_F(AbilityConnectManageTest, AAFWK_Connect_Service_007, TestSize.Level1) +{ + auto handler = std::make_shared(EventRunner::Create()); + ConnectManager()->SetEventHandler(handler); + + auto result = ConnectManager()->StartAbility(abilityRequest_); + EXPECT_EQ(OHOS::ERR_OK, result); + WaitUntilTaskDone(handler); + + auto result1 = ConnectManager()->ConnectAbilityLocked(abilityRequest_, callbackA_, nullptr); + EXPECT_EQ(0, result1); + + auto elementName = abilityRequest_.want.GetElement().GetURI(); + auto service = ConnectManager()->GetServiceRecordByElementName(elementName); + EXPECT_NE(service, nullptr); + + auto result2 = ConnectManager()->StopServiceAbility(abilityRequest_); + WaitUntilTaskDone(handler); + EXPECT_EQ(OHOS::AAFwk::TERMINATE_SERVICE_IS_CONNECTED, result2); + EXPECT_NE(service->GetAbilityState(), TERMINATING); +} + +/* + * Feature: AbilityConnectManager + * Function: ConnectAbilityLocked + * SubFunction: NA + * FunctionPoints: NA + * EnvConditions:NA + * CaseDescription: verify the scene of service not loaded and callback not bound. + */ +HWTEST_F(AbilityConnectManageTest, AAFWK_Connect_Service_008, TestSize.Level1) +{ + int result = ConnectManager()->ConnectAbilityLocked(abilityRequest_, callbackA_, nullptr); + EXPECT_EQ(0, result); + + auto connectMap = ConnectManager()->GetConnectMap(); + auto connectRecordList = connectMap.at(callbackA_->AsObject()); + EXPECT_EQ(1, static_cast(connectRecordList.size())); + + auto elementName = abilityRequest_.want.GetElement(); + auto elementNameUri = elementName.GetURI(); + auto serviceMap = ConnectManager()->GetServiceMap(); + auto abilityRecord = serviceMap.at(elementNameUri); + connectRecordList = abilityRecord->GetConnectRecordList(); + EXPECT_EQ(1, static_cast(connectRecordList.size())); +} + +/* + * Feature: AbilityConnectManager + * Function: ConnectAbilityLocked + * SubFunction: NA + * FunctionPoints: NA + * EnvConditions:NA + * CaseDescription: verify the scene of service load ability's timeout. + */ +HWTEST_F(AbilityConnectManageTest, AAFWK_Connect_Service_009, TestSize.Level1) +{ + auto handler = std::make_shared(EventRunner::Create()); + ConnectManager()->SetEventHandler(handler); + int result = ConnectManager()->ConnectAbilityLocked(abilityRequest_, callbackA_, nullptr); + EXPECT_EQ(0, result); + + auto connectMap = ConnectManager()->GetConnectMap(); + EXPECT_EQ(1, static_cast(connectMap.size())); + WaitUntilTaskDone(handler); + usleep(TEST_WAIT_TIME); + + connectMap = ConnectManager()->GetConnectMap(); + EXPECT_EQ(1, static_cast(connectMap.size())); +} + +/* + * Feature: AbilityConnectManager + * Function: ConnectAbilityLocked + * SubFunction: NA + * FunctionPoints: NA + * EnvConditions:NA + * CaseDescription: verify the scene of service loaded and callback not bound. + */ +HWTEST_F(AbilityConnectManageTest, AAFWK_Connect_Service_010, TestSize.Level1) +{ + auto result = ConnectManager()->ConnectAbilityLocked(abilityRequest_, callbackA_, nullptr); + EXPECT_EQ(0, result); + + result = ConnectManager()->ConnectAbilityLocked(abilityRequest_, callbackB_, nullptr); + EXPECT_EQ(0, result); + + auto connectMap = ConnectManager()->GetConnectMap(); + auto connectRecordList = connectMap.at(callbackA_->AsObject()); + EXPECT_EQ(1, static_cast(connectRecordList.size())); + + connectRecordList = connectMap.at(callbackB_->AsObject()); + EXPECT_EQ(1, static_cast(connectRecordList.size())); + + auto elementName = abilityRequest_.want.GetElement(); + std::string elementNameUri = elementName.GetURI(); + auto serviceMap = ConnectManager()->GetServiceMap(); + auto abilityRecord = serviceMap.at(elementNameUri); + connectRecordList = abilityRecord->GetConnectRecordList(); + EXPECT_EQ(2, static_cast(connectRecordList.size())); +} + +/* + * Feature: AbilityConnectManager + * Function: ConnectAbilityLocked + * SubFunction: NA + * FunctionPoints: NA + * EnvConditions:NA + * CaseDescription: verify the scene of service connect ability's timeout. + */ +HWTEST_F(AbilityConnectManageTest, AAFWK_Connect_Service_011, TestSize.Level1) +{ + auto handler = std::make_shared(EventRunner::Create()); + ConnectManager()->SetEventHandler(handler); + + int result = ConnectManager()->ConnectAbilityLocked(abilityRequest_, callbackA_, nullptr); + auto elementName = abilityRequest_.want.GetElement(); + std::string elementNameUri = elementName.GetURI(); + auto serviceMap = ConnectManager()->GetServiceMap(); + auto abilityRecord = serviceMap.at(elementNameUri); + auto token = abilityRecord->GetToken(); + + auto connectMap = ConnectManager()->GetConnectMap(); + EXPECT_EQ(1, static_cast(connectMap.size())); + + auto scheduler = new AbilityScheduler(); + ConnectManager()->AttachAbilityThreadLocked(scheduler, token->AsObject()); + ConnectManager()->OnAbilityRequestDone( + token->AsObject(), static_cast(AppAbilityState::ABILITY_STATE_FOREGROUND)); + ConnectManager()->AbilityTransitionDone(token->AsObject(), OHOS::AAFwk::AbilityState::INACTIVE); + + WaitUntilTaskDone(handler); + usleep(TEST_WAIT_TIME); + connectMap = ConnectManager()->GetConnectMap(); + EXPECT_EQ(0, result); + EXPECT_EQ(1, static_cast(connectMap.size())); +} + +/* + * Feature: AbilityConnectManager + * Function: ConnectAbilityLocked + * SubFunction: NA + * FunctionPoints: NA + * EnvConditions:NA + * CaseDescription: verify the scene of service loaded and callback bound. + */ +HWTEST_F(AbilityConnectManageTest, AAFWK_Connect_Service_012, TestSize.Level1) +{ + auto result = ConnectManager()->ConnectAbilityLocked(abilityRequest_, callbackA_, nullptr); + EXPECT_EQ(0, result); + + result = ConnectManager()->ConnectAbilityLocked(abilityRequest_, callbackA_, nullptr); + EXPECT_EQ(0, result); + + auto connectMap = ConnectManager()->GetConnectMap(); + auto connectRecordList = connectMap.at(callbackA_->AsObject()); + EXPECT_EQ(1, static_cast(connectRecordList.size())); + + auto elementName = abilityRequest_.want.GetElement(); + std::string elementNameUri = elementName.GetURI(); + auto serviceMap = ConnectManager()->GetServiceMap(); + auto abilityRecord = serviceMap.at(elementNameUri); + connectRecordList = abilityRecord->GetConnectRecordList(); + EXPECT_EQ(1, static_cast(connectRecordList.size())); +} + +/* + * Feature: AbilityConnectManager + * Function: ConnectAbilityLocked + * SubFunction: NA + * FunctionPoints: NA + * EnvConditions:NA + * CaseDescription: verify the scene of service not loaded and callback bound. + */ +HWTEST_F(AbilityConnectManageTest, AAFWK_Connect_Service_013, TestSize.Level1) +{ + int result = ConnectManager()->ConnectAbilityLocked(abilityRequest_, callbackA_, nullptr); + EXPECT_EQ(0, result); + + std::string deviceNameB = "device"; + std::string abilityNameB = "ServiceAbilityB"; + std::string appNameB = "hiservcieB"; + std::string bundleNameB = "com.ix.hiservcieB"; + auto abilityRequestB = GenerateAbilityRequest(deviceNameB, abilityNameB, appNameB, bundleNameB); + result = ConnectManager()->ConnectAbilityLocked(abilityRequestB, callbackA_, nullptr); + EXPECT_EQ(0, result); + + auto connectMap = ConnectManager()->GetConnectMap(); + auto connectRecordList = connectMap.at(callbackA_->AsObject()); + EXPECT_EQ(2, static_cast(connectRecordList.size())); + + auto elementName = abilityRequest_.want.GetElement(); + std::string elementNameUri = elementName.GetURI(); + auto serviceMap = ConnectManager()->GetServiceMap(); + auto abilityRecord = serviceMap.at(elementNameUri); + connectRecordList = abilityRecord->GetConnectRecordList(); + EXPECT_EQ(1, static_cast(connectRecordList.size())); + + auto elementNameB = abilityRequest_.want.GetElement(); + std::string elementNameUriB = elementNameB.GetURI(); + abilityRecord = serviceMap.at(elementNameUriB); + connectRecordList = abilityRecord->GetConnectRecordList(); + EXPECT_EQ(1, static_cast(connectRecordList.size())); +} + +/* + * Feature: AbilityConnectManager + * Function: ConnectAbilityLocked + * SubFunction: NA + * FunctionPoints: NA + * EnvConditions:NA + * CaseDescription: verify the scene of service loaded and callback bound, but service and callback was not associated. + */ +HWTEST_F(AbilityConnectManageTest, AAFWK_Connect_Service_014, TestSize.Level1) +{ + auto result = ConnectManager()->ConnectAbilityLocked(abilityRequest_, callbackA_, nullptr); + EXPECT_EQ(0, result); + + std::string deviceNameB = "device"; + std::string abilityNameB = "ServiceAbilityB"; + std::string appNameB = "hiservcieB"; + std::string bundleNameB = "com.ix.hiservcieB"; + auto abilityRequestB = GenerateAbilityRequest(deviceNameB, abilityNameB, appNameB, bundleNameB); + result = ConnectManager()->ConnectAbilityLocked(abilityRequestB, callbackB_, nullptr); + EXPECT_EQ(0, result); + + ConnectManager()->ConnectAbilityLocked(abilityRequest_, callbackB_, nullptr); + auto connectMap = ConnectManager()->GetConnectMap(); + auto connectRecordList = connectMap.at(callbackB_->AsObject()); + EXPECT_EQ(2, static_cast(connectRecordList.size())); + + connectRecordList = connectMap.at(callbackA_->AsObject()); + EXPECT_EQ(1, static_cast(connectRecordList.size())); + + auto elementName = abilityRequest_.want.GetElement(); + std::string elementNameUri = elementName.GetURI(); + auto serviceMap = ConnectManager()->GetServiceMap(); + auto abilityRecord = serviceMap.at(elementNameUri); + connectRecordList = abilityRecord->GetConnectRecordList(); + EXPECT_EQ(2, static_cast(connectRecordList.size())); +} + +/* + * Feature: AbilityConnectManager + * Function: AttachAbilityThreadLocked + * SubFunction: NA + * FunctionPoints: NA + * EnvConditions:NA + * CaseDescription: verify the AttachAbilityThreadLocked function when the parameter is null. + */ +HWTEST_F(AbilityConnectManageTest, AAFWK_Connect_Service_015, TestSize.Level1) +{ + auto result = ConnectManager()->AttachAbilityThreadLocked(nullptr, nullptr); + EXPECT_EQ(OHOS::ERR_INVALID_VALUE, result); +} + +/* + * Feature: AbilityConnectManager + * Function: ScheduleConnectAbilityDoneLocked + * SubFunction: NA + * FunctionPoints: NA + * EnvConditions:NA + * CaseDescription: verify the ScheduleConnectAbilityDoneLocked function when the parameter is null. + */ +HWTEST_F(AbilityConnectManageTest, AAFWK_Connect_Service_016, TestSize.Level1) +{ + auto callback = new AbilityConnectCallback(); + auto result = ConnectManager()->ScheduleConnectAbilityDoneLocked(nullptr, callback); + EXPECT_EQ(OHOS::ERR_INVALID_VALUE, result); +} + +/* + * Feature: AbilityConnectManager + * Function: ScheduleConnectAbilityDoneLocked + * SubFunction: NA + * FunctionPoints: NA + * EnvConditions:NA + * CaseDescription: verify the ScheduleConnectAbilityDoneLocked function when the state is CONNECTED. + */ +HWTEST_F(AbilityConnectManageTest, AAFWK_Connect_Service_017, TestSize.Level1) +{ + auto callback = new AbilityConnectCallback(); + ConnectManager()->ConnectAbilityLocked(abilityRequest_, callback, nullptr); + + auto elementName = abilityRequest_.want.GetElement(); + std::string elementNameUri = elementName.GetURI(); + auto serviceMap = ConnectManager()->GetServiceMap(); + auto abilityRecord = serviceMap.at(elementNameUri); + auto token = abilityRecord->GetToken(); + + abilityRecord->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + ConnectManager()->ScheduleConnectAbilityDoneLocked(token, callback); + auto abilityRecordB = Token::GetAbilityRecordByToken(token); + EXPECT_TRUE(abilityRecordB); + auto connectRecordList = abilityRecordB->GetConnectRecordList(); + int size = connectRecordList.size(); + EXPECT_EQ(1, size); + if (size != 0) { + auto connState = (*(connectRecordList.begin()))->GetConnectState(); + EXPECT_EQ(ConnectionState::CONNECTED, connState); + } +} + +/* + * Feature: AbilityConnectManager + * Function: ScheduleConnectAbilityDoneLocked + * SubFunction: NA + * FunctionPoints: NA + * EnvConditions:NA + * CaseDescription: verify the input parameters. + */ +HWTEST_F(AbilityConnectManageTest, AAFWK_Kit_Connect_001, TestSize.Level1) +{ + // start test + // test1 for serviceToken is null but remoteObject is valid + OHOS::sptr object = new AbilityConnectCallback(); + int ret = ConnectManager()->ScheduleConnectAbilityDoneLocked(nullptr, object); + EXPECT_EQ(OHOS::ERR_INVALID_VALUE, ret); + + // test2 for both of serviceToken and remoteObject are null + ret = ConnectManager()->ScheduleConnectAbilityDoneLocked(nullptr, nullptr); + EXPECT_EQ(OHOS::ERR_INVALID_VALUE, ret); +} + +/* + * Feature: AbilityConnectManager + * Function: ScheduleConnectAbilityDoneLocked + * SubFunction: NA + * FunctionPoints: NA + * EnvConditions:NA + * CaseDescription: verify the input serviceToken which corresponding ability record doesn't exist. + */ +HWTEST_F(AbilityConnectManageTest, AAFWK_Kit_Connect_002, TestSize.Level1) +{ + // test for serviceToken's abilityRecord is null + serviceRecord_ = nullptr; + int ret = ConnectManager()->ScheduleConnectAbilityDoneLocked(serviceToken_, nullptr); + EXPECT_EQ(OHOS::ERR_INVALID_VALUE, ret); +} + +/* + * Feature: AbilityConnectManager + * Function: ScheduleConnectAbilityDoneLocked + * SubFunction: OnAbilityConnectDone + * FunctionPoints: NA + * EnvConditions:NA + * CaseDescription: verify the input serviceToken which corresponding connection list is empty. + */ +HWTEST_F(AbilityConnectManageTest, AAFWK_Kit_Connect_003, TestSize.Level1) +{ + // test for serviceToken's connection list is null + // start test + auto callback = new AbilityConnectCallback(); + int ret = ConnectManager()->ScheduleConnectAbilityDoneLocked(serviceToken_, callback); + EXPECT_EQ(OHOS::AAFwk::INVALID_CONNECTION_STATE, ret); + auto connList = serviceRecord_->GetConnectRecordList(); + EXPECT_EQ(true, connList.empty()); // the connection list size should be empty +} + +/* + * Feature: AbilityConnectManager + * Function: ScheduleConnectAbilityDoneLocked + * SubFunction: OnAbilityConnectDone + * FunctionPoints: NA + * EnvConditions:NA + * CaseDescription: verify the input serviceToken which corresponding connection list members' state + * is not CONNECTING or CONNECTED. + */ +HWTEST_F(AbilityConnectManageTest, AAFWK_Kit_Connect_004, TestSize.Level1) +{ + // test for schedule the service connected done but the corresponding connection state is not CONNECTING + // generate the first connection record of callbackA_ + auto newConnRecord1 = ConnectionRecord::CreateConnectionRecord( + serviceToken_, serviceRecord_, callbackA_); // newConnRecord1's default state is INIT + serviceRecord_->AddConnectRecordToList(newConnRecord1); + // generate the second connection record of callbackB_ + auto newConnRecord2 = ConnectionRecord::CreateConnectionRecord(serviceToken_, serviceRecord_, callbackB_); + newConnRecord2->SetConnectState(ConnectionState::DISCONNECTING); // newConnRecord2's state is DISCONNECTING + serviceRecord_->AddConnectRecordToList(newConnRecord2); + auto connList = serviceRecord_->GetConnectRecordList(); + EXPECT_EQ(2, static_cast(connList.size())); // the connection list members should be two + // start test + auto callback = new AbilityConnectCallback(); + serviceRecord_->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + int ret = ConnectManager()->ScheduleConnectAbilityDoneLocked(serviceToken_, callback); + EXPECT_EQ(OHOS::ERR_OK, ret); // the result should be OK + // connection callback should not be called, so check the count + EXPECT_EQ(0, AbilityConnectCallback::onAbilityConnectDoneCount); + EXPECT_EQ(0, AbilityConnectCallback::onAbilityDisconnectDoneCount); +} + +/* + * Feature: AbilityConnectManager + * Function: ScheduleConnectAbilityDoneLocked + * SubFunction: OnAbilityConnectDone + * FunctionPoints: NA + * EnvConditions:NA + * CaseDescription: verify the scene : 1.serviceToken's corresponding connection list member's state is CONNECTING. + * 2.But the connection callback is null. + */ +HWTEST_F(AbilityConnectManageTest, AAFWK_Kit_Connect_005, TestSize.Level1) +{ + // test for schedule the service connected done but the corresponding connection state is not CONNECTING + // generate the first connection record of null + auto newConnRecord1 = ConnectionRecord::CreateConnectionRecord( + serviceToken_, serviceRecord_, nullptr); // newConnRecord1's default state is INIT + serviceRecord_->AddConnectRecordToList(newConnRecord1); + newConnRecord1->SetConnectState(ConnectionState::CONNECTING); // newConnRecord1's state is CONNECTING + auto connList = serviceRecord_->GetConnectRecordList(); + EXPECT_EQ(1, static_cast(connList.size())); // the connection list members should be zero + // start test + auto callback = new AbilityConnectCallback(); + serviceRecord_->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + int ret = ConnectManager()->ScheduleConnectAbilityDoneLocked(serviceToken_, callback); + EXPECT_EQ(OHOS::ERR_OK, ret); // the result should be OK + // connection callback should not be called, so check the count + EXPECT_EQ(0, AbilityConnectCallback::onAbilityConnectDoneCount); +} + +/* + * Feature: AbilityConnectManager + * Function: ScheduleConnectAbilityDoneLocked + * SubFunction: OnAbilityConnectDone + * FunctionPoints: NA + * EnvConditions:NA + * CaseDescription: verify the scene : 1.serviceToken's corresponding connection list member's state is CONNECTED. + * 2.But the connection callback is null. + */ +HWTEST_F(AbilityConnectManageTest, AAFWK_Kit_Connect_006, TestSize.Level1) +{ + // test for schedule the service connected done but the corresponding connection state is not CONNECTING + // generate the first connection record of null + auto newConnRecord1 = ConnectionRecord::CreateConnectionRecord( + serviceToken_, serviceRecord_, nullptr); // newConnRecord1's default state is INIT + serviceRecord_->AddConnectRecordToList(newConnRecord1); + newConnRecord1->SetConnectState(ConnectionState::CONNECTED); // newConnRecord1's state is CONNECTED + auto connList = serviceRecord_->GetConnectRecordList(); + EXPECT_EQ(1, static_cast(connList.size())); // the connection list members should be zero + // start test + auto callback = new AbilityConnectCallback(); + serviceRecord_->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + int ret = ConnectManager()->ScheduleConnectAbilityDoneLocked(serviceToken_, callback); + EXPECT_EQ(OHOS::ERR_OK, ret); // the result should be OK + // connection callback should not be called, so check the count + EXPECT_EQ(0, AbilityConnectCallback::onAbilityConnectDoneCount); +} + +/* + * Feature: AbilityConnectManager + * Function: ScheduleConnectAbilityDoneLocked + * SubFunction: OnAbilityConnectDone + * FunctionPoints: NA + * EnvConditions:NA + * CaseDescription: verify the scene : 1.serviceToken's corresponding connection list member's state is CONNECTING. + * 2.But the connection callback is valid. + */ +HWTEST_F(AbilityConnectManageTest, AAFWK_Kit_Connect_007, TestSize.Level1) +{ + // test for schedule the service connected done but the corresponding connection state is not CONNECTING + // generate the first connection record of callbackA_ + auto newConnRecord1 = ConnectionRecord::CreateConnectionRecord( + serviceToken_, serviceRecord_, callbackA_); // newConnRecord1's default state is INIT + serviceRecord_->AddConnectRecordToList(newConnRecord1); + // generate the second connection record of callbackB_ + auto newConnRecord2 = ConnectionRecord::CreateConnectionRecord(serviceToken_, serviceRecord_, callbackB_); + newConnRecord2->SetConnectState(ConnectionState::CONNECTING); // newConnRecord2's state is CONNECTING + serviceRecord_->AddConnectRecordToList(newConnRecord2); + auto connList = serviceRecord_->GetConnectRecordList(); + EXPECT_EQ(2, static_cast(connList.size())); // the connection list members should be two + // start test + auto callback = new AbilityConnectCallback(); + serviceRecord_->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + int ret = ConnectManager()->ScheduleConnectAbilityDoneLocked(serviceToken_, callback); + EXPECT_EQ(OHOS::ERR_OK, ret); // the result should be OK + // connection callback should not be called, so check the count + EXPECT_EQ(1, AbilityConnectCallback::onAbilityConnectDoneCount); + EXPECT_EQ(0, AbilityConnectCallback::onAbilityDisconnectDoneCount); +} + +/* + * Feature: AbilityConnectManager + * Function: ScheduleConnectAbilityDoneLocked + * SubFunction: OnAbilityConnectDone + * FunctionPoints: NA + * EnvConditions:NA + * CaseDescription: verify the scene : 1.serviceToken's corresponding connection list member's state is CONNECTED. + * 2.But the connection callback is valid. + */ +HWTEST_F(AbilityConnectManageTest, AAFWK_Kit_Connect_008, TestSize.Level1) +{ + // test for schedule the service connected done but the corresponding connection state is not CONNECTING + // generate the first connection record of callbackA_ + auto newConnRecord1 = ConnectionRecord::CreateConnectionRecord( + serviceToken_, serviceRecord_, callbackA_); // newConnRecord1's default state is INIT + newConnRecord1->SetConnectState(ConnectionState::CONNECTED); // newConnRecord1's state is CONNECTED + serviceRecord_->AddConnectRecordToList(newConnRecord1); + // generate the second connection record of callbackB_ + auto newConnRecord2 = ConnectionRecord::CreateConnectionRecord(serviceToken_, serviceRecord_, callbackB_); + newConnRecord2->SetConnectState(ConnectionState::CONNECTING); // newConnRecord2's state is CONNECTING + serviceRecord_->AddConnectRecordToList(newConnRecord2); + // generate the third connection record of callbackC + auto callbackC = new AbilityConnectCallback(); + auto newConnRecord3 = ConnectionRecord::CreateConnectionRecord(serviceToken_, serviceRecord_, callbackC); + newConnRecord3->SetConnectState(ConnectionState::CONNECTING); // newConnRecord3's state is CONNECTING + serviceRecord_->AddConnectRecordToList(newConnRecord3); + auto connList = serviceRecord_->GetConnectRecordList(); + EXPECT_EQ(3, static_cast(connList.size())); // the connection list members should be three + // start test + auto callback = new AbilityConnectCallback(); + serviceRecord_->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + int ret = ConnectManager()->ScheduleConnectAbilityDoneLocked(serviceToken_, callback); + EXPECT_EQ(OHOS::ERR_OK, ret); // the result should be OK + // connection callback should not be called, so check the count + EXPECT_EQ(2, AbilityConnectCallback::onAbilityConnectDoneCount); + EXPECT_EQ(0, AbilityConnectCallback::onAbilityDisconnectDoneCount); +} + +/* + * Feature: AbilityConnectManager + * Function: DisconnectAbilityLocked + * SubFunction: + * FunctionPoints: DisconnectAbilityLocked and ConnectAbilityLocked + * EnvConditions:NA + * CaseDescription:Verify the following: + * 1. Disconnect ability a nonexistent connect, disconnect failed + * 2. If the current connect ability state is not connected, disconnect fails + * 3. Verify the success of disconnect ability + */ +HWTEST_F(AbilityConnectManageTest, AAFWK_Kit_Disconnect_001, TestSize.Level1) +{ + auto handler = std::make_shared(EventRunner::Create()); + ConnectManager()->SetEventHandler(handler); + + auto callback = new AbilityConnectCallback(); + auto result = ConnectManager()->DisconnectAbilityLocked(callback); + EXPECT_EQ(result, OHOS::AAFwk::CONNECTION_NOT_EXIST); + + auto result1 = ConnectManager()->ConnectAbilityLocked(abilityRequest_, callbackA_, nullptr); + EXPECT_EQ(0, result1); + + auto result2 = ConnectManager()->DisconnectAbilityLocked(callbackA_); + EXPECT_EQ(result2, OHOS::AAFwk::INVALID_CONNECTION_STATE); + + auto list = ConnectManager()->GetConnectRecordListByCallback(callbackA_); + EXPECT_EQ(static_cast(list.size()), 1); + + for (auto &it : list) { + it->SetConnectState(ConnectionState::CONNECTED); + } + + auto result3 = ConnectManager()->DisconnectAbilityLocked(callbackA_); + EXPECT_EQ(result3, OHOS::ERR_OK); +} + +/* + * Feature: AbilityConnectManager + * Function: DisconnectAbilityLocked + * SubFunction: + * FunctionPoints: DisconnectAbilityLocked and ConnectAbilityLocked + * EnvConditions:NA + * CaseDescription: Results after verifying the disconnect ability + */ +HWTEST_F(AbilityConnectManageTest, AAFWK_Kit_Disconnect_002, TestSize.Level1) +{ + auto handler = std::make_shared(EventRunner::Create()); + ConnectManager()->SetEventHandler(handler); + + auto result = ConnectManager()->ConnectAbilityLocked(abilityRequest_, callbackA_, nullptr); + EXPECT_EQ(0, result); + + auto result1 = ConnectManager()->ConnectAbilityLocked(abilityRequest_, callbackB_, nullptr); + EXPECT_EQ(0, result1); + + auto result2 = ConnectManager()->ConnectAbilityLocked(abilityRequest1_, callbackA_, nullptr); + EXPECT_EQ(0, result2); + + auto result3 = ConnectManager()->ConnectAbilityLocked(abilityRequest1_, callbackB_, nullptr); + EXPECT_EQ(0, result3); + + auto listA = ConnectManager()->GetConnectRecordListByCallback(callbackA_); + EXPECT_EQ(static_cast(listA.size()), 2); + + for (auto &it : listA) { + it->SetConnectState(ConnectionState::CONNECTED); + } + + auto listB = ConnectManager()->GetConnectRecordListByCallback(callbackB_); + EXPECT_EQ(static_cast(listB.size()), 2); + + for (auto &it : listB) { + it->SetConnectState(ConnectionState::CONNECTED); + } + + auto result5 = ConnectManager()->DisconnectAbilityLocked(callbackA_); + WaitUntilTaskDone(handler); + EXPECT_EQ(result5, OHOS::ERR_OK); + auto serviceMap = ConnectManager()->GetServiceMap(); + EXPECT_EQ(static_cast(serviceMap.size()), 2); + + auto connectMap = ConnectManager()->GetConnectMap(); + EXPECT_EQ(static_cast(connectMap.size()), 1); + for (auto &it : connectMap) { + EXPECT_EQ(static_cast(it.second.size()), 2); + } +} + +/* + * Feature: AbilityConnectManager + * Function: OnAbilityRequestDone + * SubFunction: NA + * FunctionPoints: OnAbilityRequestDone + * EnvConditions:NA + * CaseDescription: Verify the ability status, right + */ +HWTEST_F(AbilityConnectManageTest, AAFWK_Connect_Service_018, TestSize.Level1) +{ + auto handler = std::make_shared(EventRunner::Create()); + ConnectManager()->SetEventHandler(handler); + + ConnectManager()->ConnectAbilityLocked(abilityRequest_, callbackA_, nullptr); + auto elementName = abilityRequest_.want.GetElement(); + std::string elementNameUri = elementName.GetURI(); + auto serviceMap = ConnectManager()->GetServiceMap(); + auto abilityRecord = serviceMap.at(elementNameUri); + auto token = abilityRecord->GetToken(); + + auto connectMap = ConnectManager()->GetConnectMap(); + EXPECT_EQ(1, static_cast(connectMap.size())); + + auto scheduler = new AbilityScheduler(); + ConnectManager()->AttachAbilityThreadLocked(scheduler, token->AsObject()); + + // invalid parameter, direct return + OHOS::sptr nullToken = nullptr; + ConnectManager()->OnAbilityRequestDone( + nullToken, static_cast(OHOS::AppExecFwk::AbilityState::ABILITY_STATE_FOREGROUND)); + + ConnectManager()->OnAbilityRequestDone( + token->AsObject(), static_cast(OHOS::AppExecFwk::AbilityState::ABILITY_STATE_FOREGROUND)); + WaitUntilTaskDone(handler); + EXPECT_EQ(abilityRecord->GetAbilityState(), OHOS::AAFwk::AbilityState::INACTIVATING); + + ConnectManager()->OnAbilityRequestDone( + token->AsObject(), static_cast(OHOS::AppExecFwk::AbilityState::ABILITY_STATE_BACKGROUND)); + WaitUntilTaskDone(handler); + EXPECT_EQ(0, static_cast(ConnectManager()->GetServiceMap().size())); +} + +/* + * Feature: AbilityConnectManager + * Function: AbilityTransitionDone + * SubFunction: NA + * FunctionPoints: AbilityTransitionDone + * EnvConditions:NA + * CaseDescription: Verify the abilitytransitiondone process + */ +HWTEST_F(AbilityConnectManageTest, AAFWK_Connect_Service_019, TestSize.Level1) +{ + OHOS::sptr nullToken = nullptr; + auto result = ConnectManager()->AbilityTransitionDone(nullToken, OHOS::AAFwk::AbilityState::INACTIVE); + EXPECT_EQ(result, OHOS::ERR_INVALID_VALUE); + + ConnectManager()->ConnectAbilityLocked(abilityRequest_, callbackA_, nullptr); + auto elementName = abilityRequest_.want.GetElement(); + std::string elementNameUri = elementName.GetURI(); + auto serviceMap = ConnectManager()->GetServiceMap(); + auto abilityRecord = serviceMap.at(elementNameUri); + auto token = abilityRecord->GetToken(); + + auto result1 = ConnectManager()->AbilityTransitionDone(token, OHOS::AAFwk::AbilityState::INACTIVE); + EXPECT_EQ(result1, OHOS::ERR_INVALID_VALUE); + + auto result2 = ConnectManager()->AbilityTransitionDone(token, OHOS::AAFwk::AbilityState::INITIAL); + EXPECT_EQ(result2, OHOS::ERR_OK); + + auto result3 = ConnectManager()->AbilityTransitionDone(token, OHOS::AAFwk::AbilityState::TERMINATING); + EXPECT_EQ(result3, OHOS::ERR_INVALID_VALUE); +} + +/* + * Feature: AbilityConnectManager + * Function: ScheduleDisconnectAbilityDoneLocked + * SubFunction: NA + * FunctionPoints: ScheduleDisconnectAbilityDoneLocked + * EnvConditions:NA + * CaseDescription: Verify the ScheduleDisconnectAbilityDoneLocked process + */ +HWTEST_F(AbilityConnectManageTest, AAFWK_Connect_Service_020, TestSize.Level1) +{ + auto handler = std::make_shared(EventRunner::Create()); + ConnectManager()->SetEventHandler(handler); + + OHOS::sptr nullToken = nullptr; + auto result = ConnectManager()->ScheduleDisconnectAbilityDoneLocked(nullToken); + EXPECT_EQ(result, OHOS::AAFwk::CONNECTION_NOT_EXIST); + + std::shared_ptr ability = nullptr; + OHOS::sptr token1 = new OHOS::AAFwk::Token(ability); + auto result1 = ConnectManager()->ScheduleDisconnectAbilityDoneLocked(token1); + EXPECT_EQ(result1, OHOS::AAFwk::CONNECTION_NOT_EXIST); + + ConnectManager()->ConnectAbilityLocked(abilityRequest_, callbackA_, nullptr); + auto elementName = abilityRequest_.want.GetElement(); + std::string elementNameUri = elementName.GetURI(); + auto serviceMap = ConnectManager()->GetServiceMap(); + auto abilityRecord = serviceMap.at(elementNameUri); + auto token = abilityRecord->GetToken(); + + auto listA = ConnectManager()->GetConnectRecordListByCallback(callbackA_); + for (auto &it : listA) { + it->SetConnectState(ConnectionState::CONNECTED); + } + + auto result2 = ConnectManager()->DisconnectAbilityLocked(callbackA_); + WaitUntilTaskDone(handler); + EXPECT_EQ(result2, OHOS::ERR_OK); + + auto result3 = ConnectManager()->ScheduleDisconnectAbilityDoneLocked(token); + EXPECT_EQ(result3, OHOS::AAFwk::INVALID_CONNECTION_STATE); + + abilityRecord->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + + auto result4 = ConnectManager()->ScheduleDisconnectAbilityDoneLocked(token); + EXPECT_EQ(result4, OHOS::ERR_OK); +} + +/* + * Feature: AbilityConnectManager + * Function: ScheduleCommandAbilityDoneLocked + * SubFunction: NA + * FunctionPoints: ScheduleCommandAbilityDoneLocked + * EnvConditions:NA + * CaseDescription: Verify the ScheduleCommandAbilityDoneLocked process + */ +HWTEST_F(AbilityConnectManageTest, AAFWK_Connect_Service_021, TestSize.Level1) +{ + auto handler = std::make_shared(EventRunner::Create()); + ConnectManager()->SetEventHandler(handler); + + OHOS::sptr nullToken = nullptr; + auto result = ConnectManager()->ScheduleCommandAbilityDoneLocked(nullToken); + EXPECT_EQ(result, OHOS::ERR_INVALID_VALUE); + + std::shared_ptr ability = nullptr; + OHOS::sptr token1 = new OHOS::AAFwk::Token(ability); + auto result1 = ConnectManager()->ScheduleCommandAbilityDoneLocked(token1); + EXPECT_EQ(result1, OHOS::ERR_INVALID_VALUE); + + ConnectManager()->ConnectAbilityLocked(abilityRequest_, callbackA_, nullptr); + auto elementName = abilityRequest_.want.GetElement(); + std::string elementNameUri = elementName.GetURI(); + auto serviceMap = ConnectManager()->GetServiceMap(); + auto abilityRecord = serviceMap.at(elementNameUri); + auto token = abilityRecord->GetToken(); + + auto result2 = ConnectManager()->ScheduleCommandAbilityDoneLocked(token); + EXPECT_EQ(result2, OHOS::AAFwk::INVALID_CONNECTION_STATE); + + abilityRecord->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + auto result3 = ConnectManager()->ScheduleCommandAbilityDoneLocked(token); + EXPECT_EQ(result3, OHOS::ERR_OK); +} + +/* + * Feature: AbilityConnectManager + * Function: GetServiceRecordByToken + * SubFunction: NA + * FunctionPoints: GetServiceRecordByToken + * EnvConditions:NA + * CaseDescription: Verify the GetServiceRecordByToken process + */ +HWTEST_F(AbilityConnectManageTest, AAFWK_Connect_Service_022, TestSize.Level1) +{ + ConnectManager()->ConnectAbilityLocked(abilityRequest_, callbackA_, nullptr); + auto elementName = abilityRequest_.want.GetElement(); + std::string elementNameUri = elementName.GetURI(); + auto serviceMap = ConnectManager()->GetServiceMap(); + auto abilityRecord = serviceMap.at(elementNameUri); + auto token = abilityRecord->GetToken(); + + auto ability = ConnectManager()->GetServiceRecordByToken(token); + EXPECT_EQ(abilityRecord, ability); + + OHOS::sptr nullToken = nullptr; + auto ability1 = ConnectManager()->GetServiceRecordByToken(nullToken); + EXPECT_EQ(nullptr, ability1); +} + +/* + * Feature: AbilityConnectManager + * Function: RemoveAll + * SubFunction: NA + * FunctionPoints: RemoveAll + * EnvConditions:NA + * CaseDescription: Verify the RemoveAll process + */ +HWTEST_F(AbilityConnectManageTest, AAFWK_Connect_Service_023, TestSize.Level1) +{ + ConnectManager()->ConnectAbilityLocked(abilityRequest_, callbackA_, nullptr); + auto elementName = abilityRequest_.want.GetElement(); + std::string elementNameUri = elementName.GetURI(); + auto serviceMap = ConnectManager()->GetServiceMap(); + auto abilityRecord = serviceMap.at(elementNameUri); + auto token = abilityRecord->GetToken(); + + auto conMap = ConnectManager()->GetConnectMap(); + EXPECT_EQ(conMap.empty(), false); + EXPECT_EQ(serviceMap.empty(), false); + + ConnectManager()->RemoveAll(); + conMap = ConnectManager()->GetConnectMap(); + serviceMap = ConnectManager()->GetServiceMap(); + EXPECT_EQ(conMap.empty(), true); + EXPECT_EQ(serviceMap.empty(), true); +} + +/* + * Feature: AbilityConnectManager + * Function: OnAbilityDied + * SubFunction: + * FunctionPoints: OnAbilityDied + * EnvConditions:NA + * CaseDescription: Verify the OnAbilityDied process + */ +HWTEST_F(AbilityConnectManageTest, AAFWK_Connect_Service_024, TestSize.Level1) +{ + auto handler = std::make_shared(EventRunner::Create()); + ConnectManager()->SetEventHandler(handler); + + auto result = ConnectManager()->ConnectAbilityLocked(abilityRequest_, callbackA_, nullptr); + EXPECT_EQ(0, result); + + auto result1 = ConnectManager()->ConnectAbilityLocked(abilityRequest_, callbackB_, nullptr); + EXPECT_EQ(0, result1); + + auto result2 = ConnectManager()->ConnectAbilityLocked(abilityRequest1_, callbackA_, nullptr); + EXPECT_EQ(0, result2); + + auto result3 = ConnectManager()->ConnectAbilityLocked(abilityRequest1_, callbackB_, nullptr); + EXPECT_EQ(0, result3); + + auto listA = ConnectManager()->GetConnectRecordListByCallback(callbackA_); + EXPECT_EQ(static_cast(listA.size()), 2); + + for (auto &it : listA) { + it->SetConnectState(ConnectionState::CONNECTED); + } + + auto listB = ConnectManager()->GetConnectRecordListByCallback(callbackB_); + EXPECT_EQ(static_cast(listB.size()), 2); + + for (auto &it : listB) { + it->SetConnectState(ConnectionState::CONNECTED); + } + + auto elementName = abilityRequest_.want.GetElement(); + std::string elementNameUri = elementName.GetURI(); + auto serviceMap = ConnectManager()->GetServiceMap(); + auto abilityRecord = serviceMap.at(elementNameUri); + auto token = abilityRecord->GetToken(); + + ConnectManager()->OnAbilityDied(abilityRecord); + WaitUntilTaskDone(handler); + auto list = abilityRecord->GetConnectRecordList(); + EXPECT_EQ(static_cast(list.size()), 0); + + auto elementName1 = abilityRequest1_.want.GetElement(); + std::string elementNameUri1 = elementName1.GetURI(); + serviceMap = ConnectManager()->GetServiceMap(); + auto abilityRecord1 = serviceMap.at(elementNameUri1); + auto token1 = abilityRecord1->GetToken(); + + ConnectManager()->OnAbilityDied(abilityRecord1); + WaitUntilTaskDone(handler); + auto list1 = abilityRecord1->GetConnectRecordList(); + EXPECT_EQ(static_cast(list1.size()), 0); +} + +/* + * Feature: AbilityConnectManager + * Function: DispatchInactive + * SubFunction: + * FunctionPoints: DispatchInactive + * EnvConditions:NA + * CaseDescription: Verify the DispatchInactive process + */ +HWTEST_F(AbilityConnectManageTest, AAFWK_Connect_Service_025, TestSize.Level1) +{ + std::shared_ptr ability = nullptr; + auto result = ConnectManager()->DispatchInactive(ability, OHOS::AAFwk::AbilityState::INACTIVATING); + EXPECT_EQ(result, OHOS::ERR_INVALID_VALUE); + + auto handler = std::make_shared(EventRunner::Create()); + ConnectManager()->SetEventHandler(handler); + + auto result3 = ConnectManager()->ConnectAbilityLocked(abilityRequest_, callbackA_, nullptr); + EXPECT_EQ(0, result3); + + auto elementName = abilityRequest_.want.GetElement(); + std::string elementNameUri = elementName.GetURI(); + auto serviceMap = ConnectManager()->GetServiceMap(); + auto abilityRecord = serviceMap.at(elementNameUri); + auto token = abilityRecord->GetToken(); + + abilityRecord->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + auto result1 = ConnectManager()->DispatchInactive(abilityRecord, OHOS::AAFwk::AbilityState::INACTIVATING); + EXPECT_EQ(result1, OHOS::ERR_INVALID_VALUE); + + abilityRecord->SetAbilityState(OHOS::AAFwk::AbilityState::INACTIVATING); + auto result2 = ConnectManager()->DispatchInactive(abilityRecord, OHOS::AAFwk::AbilityState::INACTIVATING); + EXPECT_EQ(result2, OHOS::ERR_OK); + EXPECT_EQ(abilityRecord->GetAbilityState(), OHOS::AAFwk::AbilityState::INACTIVE); +} + +/* + * Feature: AbilityConnectManager + * Function: DispatchInactive + * SubFunction: + * FunctionPoints: DispatchInactive + * EnvConditions:NA + * CaseDescription: Verify the DispatchInactive process + */ +HWTEST_F(AbilityConnectManageTest, AAFWK_Connect_Service_026, TestSize.Level1) +{ + std::shared_ptr ability = nullptr; + auto result = ConnectManager()->DispatchInactive(ability, OHOS::AAFwk::AbilityState::INACTIVATING); + EXPECT_EQ(result, OHOS::ERR_INVALID_VALUE); + + auto handler = std::make_shared(EventRunner::Create()); + ConnectManager()->SetEventHandler(handler); + + auto result3 = ConnectManager()->ConnectAbilityLocked(abilityRequest_, callbackA_, nullptr); + EXPECT_EQ(0, result3); + + auto elementName = abilityRequest_.want.GetElement(); + std::string elementNameUri = elementName.GetURI(); + auto serviceMap = ConnectManager()->GetServiceMap(); + auto abilityRecord = serviceMap.at(elementNameUri); + auto token = abilityRecord->GetToken(); + + abilityRecord->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + auto result1 = ConnectManager()->DispatchInactive(abilityRecord, OHOS::AAFwk::AbilityState::INACTIVATING); + EXPECT_EQ(result1, OHOS::ERR_INVALID_VALUE); + + abilityRecord->SetAbilityState(OHOS::AAFwk::AbilityState::INACTIVATING); + auto result2 = ConnectManager()->DispatchInactive(abilityRecord, OHOS::AAFwk::AbilityState::INACTIVATING); + EXPECT_EQ(result2, OHOS::ERR_OK); + EXPECT_EQ(abilityRecord->GetAbilityState(), OHOS::AAFwk::AbilityState::INACTIVE); +} + +/* + * Feature: AbilityConnectManager + * Function: AddConnectDeathRecipient + * SubFunction: + * FunctionPoints: AddConnectDeathRecipient + * EnvConditions:NA + * CaseDescription: Verify the AddConnectDeathRecipient process + */ +HWTEST_F(AbilityConnectManageTest, AAFWK_Connect_Service_027, TestSize.Level1) +{ + auto handler = std::make_shared(EventRunner::Create()); + ConnectManager()->SetEventHandler(handler); + + ConnectManager()->AddConnectDeathRecipient(nullptr); + EXPECT_TRUE(ConnectManager()->recipientMap_.empty()); + + ConnectManager()->AddConnectDeathRecipient(callbackA_); + EXPECT_EQ(static_cast(ConnectManager()->recipientMap_.size()), 1); + + // Add twice, do not add repeatedly + ConnectManager()->AddConnectDeathRecipient(callbackA_); + EXPECT_EQ(static_cast(ConnectManager()->recipientMap_.size()), 1); +} + +/* + * Feature: AbilityConnectManager + * Function: RemoveConnectDeathRecipient + * SubFunction: + * FunctionPoints: RemoveConnectDeathRecipient + * EnvConditions:NA + * CaseDescription: Verify the RemoveConnectDeathRecipient process + */ +HWTEST_F(AbilityConnectManageTest, AAFWK_Connect_Service_028, TestSize.Level1) +{ + auto handler = std::make_shared(EventRunner::Create()); + ConnectManager()->SetEventHandler(handler); + + ConnectManager()->AddConnectDeathRecipient(callbackA_); + EXPECT_EQ(static_cast(ConnectManager()->recipientMap_.size()), 1); + + ConnectManager()->RemoveConnectDeathRecipient(nullptr); + EXPECT_FALSE(ConnectManager()->recipientMap_.empty()); + + ConnectManager()->RemoveConnectDeathRecipient(callbackA_); + EXPECT_TRUE(ConnectManager()->recipientMap_.empty()); +} + +/* + * Feature: AbilityConnectManager + * Function: OnCallBackDied + * SubFunction: + * FunctionPoints: OnCallBackDied + * EnvConditions:NA + * CaseDescription: Verify the OnCallBackDied process + */ +HWTEST_F(AbilityConnectManageTest, AAFWK_Connect_Service_029, TestSize.Level1) +{ + auto handler = std::make_shared(EventRunner::Create()); + ConnectManager()->SetEventHandler(handler); + + auto result = ConnectManager()->ConnectAbilityLocked(abilityRequest_, callbackA_, nullptr); + WaitUntilTaskDone(handler); + EXPECT_EQ(0, result); + + ConnectManager()->OnCallBackDied(nullptr); + WaitUntilTaskDone(handler); + auto connectMap = ConnectManager()->GetConnectMap(); + auto connectRecordList = connectMap.at(callbackA_->AsObject()); + EXPECT_EQ(1, static_cast(connectRecordList.size())); + for (auto &it : connectRecordList) { + EXPECT_NE(it->GetAbilityConnectCallback(), nullptr); + } + + ConnectManager()->OnCallBackDied(callbackA_->AsObject()); + WaitUntilTaskDone(handler); + auto cMap = ConnectManager()->GetConnectMap(); + connectRecordList = connectMap.at(callbackA_->AsObject()); + EXPECT_EQ(1, static_cast(connectMap.size())); + for (auto &it : connectRecordList) { + EXPECT_EQ(it->GetAbilityConnectCallback(), nullptr); + } +} +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/abilitymgr/test/unittest/phone/ability_dump_test/BUILD.gn b/tools/services/abilitymgr/test/unittest/phone/ability_dump_test/BUILD.gn new file mode 100644 index 00000000000..65731e01dc1 --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/ability_dump_test/BUILD.gn @@ -0,0 +1,69 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/test.gni") +import("//foundation/aafwk/standard/aafwk.gni") + +module_output_path = "aafwk_standard/abilitymgr" + +ohos_unittest("ability_dump_test") { + module_out_path = module_output_path + + include_dirs = [ + "${services_path}/abilitymgr/test/mock/libs/system_ability_mock", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy/include", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core", + ] + + sources = [ + "${services_path}/abilitymgr/test/unittest/phone/ability_with_applications_test/mock_ability_scheduler.cpp", + "//foundation/aafwk/standard/services/abilitymgr/test/mock/libs/appexecfwk_core/src/appmgr/mock_app_scheduler.cpp", + "ability_dump_test.cpp", + ] + + configs = [ + "${services_path}/abilitymgr:abilityms_config", + "${services_path}/abilitymgr/test/mock:aafwk_mock_config", + ] + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + deps = [ + "${innerkits_path}/want:want", + "${services_path}/abilitymgr/test:abilityms_test_source", + "${services_path}/abilitymgr/test/mock/appmgr_test_service:appmgr_test_service", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_appmgr_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_bundlemgr_mock", + "${services_path}/abilitymgr/test/mock/libs/sa_mgr:sa_mgr_mock", + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/frameworks/kits/ability/native:dummy_classes", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//third_party/googletest:gmock_main", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] +} + +group("unittest") { + testonly = true + + deps = [ ":ability_dump_test" ] +} diff --git a/tools/services/abilitymgr/test/unittest/phone/ability_dump_test/ability_dump_test.cpp b/tools/services/abilitymgr/test/unittest/phone/ability_dump_test/ability_dump_test.cpp new file mode 100644 index 00000000000..70c42ba74ca --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/ability_dump_test/ability_dump_test.cpp @@ -0,0 +1,516 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include "system_ability_definition.h" +#define private public +#define protected public +#include "ability_manager_service.h" +#undef private +#undef protected +#include "bundlemgr/mock_bundle_manager.h" +#include "sa_mgr_client.h" +#include "appmgr_test_service.h" + +using namespace testing; +using namespace testing::ext; +using namespace OHOS::AppExecFwk; + +namespace OHOS { +namespace AAFwk { +static void WaitUntilTaskFinished() +{ + const uint32_t maxRetryCount = 1000; + const uint32_t sleepTime = 1000; + uint32_t count = 0; + auto handler = OHOS::DelayedSingleton::GetInstance()->GetEventHandler(); + std::atomic taskCalled(false); + auto f = [&taskCalled]() { taskCalled.store(true); }; + if (handler->PostTask(f)) { + while (!taskCalled.load()) { + ++count; + if (count >= maxRetryCount) { + break; + } + usleep(sleepTime); + } + } +} + +namespace { +const std::string NAME_BUNDLE_MGR_SERVICE = "BundleMgrService"; +static ElementName g_testAbility1("device", "com.ix.hiMusic", "MusicAbility"); +static ElementName g_testAbility2("device", "com.ix.hiMusic", "MusicTopAbility"); +static ElementName g_testAbility3("device", "com.ix.hiMusic", "MusicSAbility"); +static ElementName g_testAbility4("device", "com.ix.hiRadio", "RadioAbility"); +static ElementName g_testAbility5("device", "com.ix.hiRadio", "RadioTopAbility"); +static ElementName g_launcherAbility("device", "com.ix.hiWord", "LauncherAbility"); +static std::shared_ptr g_abilityMs = nullptr; +static std::shared_ptr g_appTestService = nullptr; +} // namespace + +bool IsTestAbility1Exist(const std::string &state) +{ + return std::string::npos != state.find("MusicAbility"); +} + +bool IsTestAbility2Exist(const std::string &state) +{ + return std::string::npos != state.find("MusicTopAbility"); +} + +bool IsTestAbility3Exist(const std::string &state) +{ + return std::string::npos != state.find("MusicSAbility"); +} + +bool IsTestAbility4Exist(const std::string &state) +{ + return std::string::npos != state.find("RadioAbility"); +} + +bool IsTestAbility5Exist(const std::string &state) +{ + return std::string::npos != state.find("RadioTopAbility"); +} + +bool IsLaunchAbilityExist(const std::string &state) +{ + return std::string::npos != state.find("LauncherAbility"); +} + +class AbilityDumpTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp(); + void TearDown(); + void StartAbilityes(); + void startAbility1(); + void startAbility2(); + void startAbility3(); + void startAbility4(); + void startAbility5(); + void startAbility6(); + +public: + static constexpr int TEST_WAIT_TIME = 100000; +}; + +void AbilityDumpTest::SetUpTestCase() +{ + OHOS::DelayedSingleton::GetInstance()->RegisterSystemAbility( + OHOS::BUNDLE_MGR_SERVICE_SYS_ABILITY_ID, new BundleMgrService()); +} + +void AbilityDumpTest::TearDownTestCase() +{ + OHOS::DelayedSingleton::DestroyInstance(); +} + +void AbilityDumpTest::SetUp() +{ + + g_abilityMs = OHOS::DelayedSingleton::GetInstance(); + g_appTestService = OHOS::DelayedSingleton::GetInstance(); + g_abilityMs->OnStart(); + WaitUntilTaskFinished(); + g_appTestService->Start(); + + StartAbilityes(); +} + +void AbilityDumpTest::TearDown() +{ + OHOS::DelayedSingleton::DestroyInstance(); +} + +void AbilityDumpTest::StartAbilityes() +{ + EXPECT_TRUE(g_abilityMs->currentStackManager_); + auto currentTopAbilityRecord = g_abilityMs->currentStackManager_->GetCurrentTopAbility(); + EXPECT_TRUE(currentTopAbilityRecord); + currentTopAbilityRecord->SetAbilityState(AbilityState::ACTIVE); + startAbility6(); + startAbility1(); + startAbility2(); + startAbility3(); + startAbility4(); + startAbility5(); +} + +void AbilityDumpTest::startAbility1() +{ + Want want; + want.SetElement(g_testAbility1); + g_abilityMs->StartAbility(want); + WaitUntilTaskFinished(); + auto topAbility = g_abilityMs->GetStackManager()->GetCurrentTopAbility(); + if (topAbility) { + topAbility->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + } +} + +void AbilityDumpTest::startAbility2() +{ + Want want; + want.SetElement(g_testAbility2); + g_abilityMs->StartAbility(want); + WaitUntilTaskFinished(); + auto topAbility = g_abilityMs->GetStackManager()->GetCurrentTopAbility(); + if (topAbility) { + topAbility->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + } +} + +void AbilityDumpTest::startAbility3() +{ + Want want; + want.SetElement(g_testAbility3); + g_abilityMs->StartAbility(want); + WaitUntilTaskFinished(); + auto topAbility = g_abilityMs->GetStackManager()->GetCurrentTopAbility(); + if (topAbility) { + topAbility->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + } +} + +void AbilityDumpTest::startAbility4() +{ + Want want; + want.SetElement(g_testAbility4); + g_abilityMs->StartAbility(want); + WaitUntilTaskFinished(); + auto topAbility = g_abilityMs->GetStackManager()->GetCurrentTopAbility(); + if (topAbility) { + topAbility->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + } +} + +void AbilityDumpTest::startAbility5() +{ + Want want; + want.SetElement(g_testAbility5); + g_abilityMs->StartAbility(want); + WaitUntilTaskFinished(); + auto topAbility = g_abilityMs->GetStackManager()->GetCurrentTopAbility(); + if (topAbility) { + topAbility->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + } +} + +void AbilityDumpTest::startAbility6() +{ + Want want; + want.SetElement(g_launcherAbility); + want.AddEntity(Want::ENTITY_HOME); + g_abilityMs->StartAbility(want); + WaitUntilTaskFinished(); + auto topAbility = g_abilityMs->GetStackManager()->GetCurrentTopAbility(); + if (topAbility) { + topAbility->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + } +} + +/* + * Feature: AbilityManagerService + * Function: DumpState + * SubFunction: NA + * FunctionPoints: AbilityManagerService DumpState + * EnvConditions: NA + * CaseDescription: DumpState when args empty + */ +HWTEST_F(AbilityDumpTest, Ability_Dump_001, TestSize.Level2) +{ + std::string args; + std::vector result; + g_abilityMs->DumpState(args, result); + + EXPECT_EQ(result.end(), std::find_if(result.begin(), result.end(), IsTestAbility1Exist)); + EXPECT_EQ(result.end(), std::find_if(result.begin(), result.end(), IsTestAbility2Exist)); + EXPECT_EQ(result.end(), std::find_if(result.begin(), result.end(), IsTestAbility3Exist)); + EXPECT_EQ(result.end(), std::find_if(result.begin(), result.end(), IsTestAbility4Exist)); + EXPECT_EQ(result.end(), std::find_if(result.begin(), result.end(), IsTestAbility5Exist)); + EXPECT_EQ(result.end(), std::find_if(result.begin(), result.end(), IsLaunchAbilityExist)); +} + +/* + * Feature: AbilityManagerService + * Function: DumpState + * SubFunction: NA + * FunctionPoints: AbilityManagerService DumpState + * EnvConditions: NA + * CaseDescription: DumpState when args empty + */ +HWTEST_F(AbilityDumpTest, Ability_Dump_002, TestSize.Level2) +{ + GTEST_LOG_(INFO) << "Ability_Dump_002 start"; + std::string args("--top"); + std::vector result; + g_abilityMs->DumpState(args, result); + + EXPECT_NE(result.end(), std::find_if(result.begin(), result.end(), IsTestAbility5Exist)); + GTEST_LOG_(INFO) << "Ability_Dump_002 end"; +} + +/* + * Feature: AbilityManagerService + * Function: DumpState + * SubFunction: NA + * FunctionPoints: AbilityManagerService DumpState + * EnvConditions: NA + * CaseDescription: DumpState when args fail + */ +HWTEST_F(AbilityDumpTest, Ability_Dump_003, TestSize.Level2) +{ + GTEST_LOG_(INFO) << "Ability_Dump_003 start"; + std::string expectResult = "error: invalid argument, please see 'ability dump -h'."; + std::string args("--stack"); + std::vector result; + g_abilityMs->DumpState(args, result); + EXPECT_EQ(1UL, result.size()); + EXPECT_EQ(result[0], expectResult); + GTEST_LOG_(INFO) << "Ability_Dump_003 end"; +} + +/* + * Feature: AbilityManagerService + * Function: DumpState + * SubFunction: NA + * FunctionPoints: AbilityManagerService DumpState + * EnvConditions: NA + * CaseDescription: Verify DumpState --stack 0 + */ +HWTEST_F(AbilityDumpTest, Ability_Dump_004, TestSize.Level2) +{ + GTEST_LOG_(INFO) << "Ability_Dump_004 start"; + std::string args("--stack 0"); + std::vector result; + g_abilityMs->DumpState(args, result); + EXPECT_EQ(result.end(), std::find_if(result.begin(), result.end(), IsTestAbility1Exist)); + EXPECT_EQ(result.end(), std::find_if(result.begin(), result.end(), IsTestAbility2Exist)); + EXPECT_EQ(result.end(), std::find_if(result.begin(), result.end(), IsTestAbility3Exist)); + EXPECT_EQ(result.end(), std::find_if(result.begin(), result.end(), IsTestAbility4Exist)); + EXPECT_EQ(result.end(), std::find_if(result.begin(), result.end(), IsTestAbility5Exist)); + GTEST_LOG_(INFO) << "Ability_Dump_004 end"; +} + +/* + * Feature: AbilityManagerService + * Function: DumpState + * SubFunction: NA + * FunctionPoints: AbilityManagerService DumpState + * EnvConditions: NA + * CaseDescription: Verify DumpState --stack 1 + */ +HWTEST_F(AbilityDumpTest, Ability_Dump_005, TestSize.Level2) +{ + GTEST_LOG_(INFO) << "Ability_Dump_005 start"; + std::string args("--stack 1"); + std::vector result; + g_abilityMs->DumpState(args, result); + + EXPECT_NE(result.end(), std::find_if(result.begin(), result.end(), IsTestAbility1Exist)); + EXPECT_NE(result.end(), std::find_if(result.begin(), result.end(), IsTestAbility2Exist)); + EXPECT_NE(result.end(), std::find_if(result.begin(), result.end(), IsTestAbility3Exist)); + EXPECT_NE(result.end(), std::find_if(result.begin(), result.end(), IsTestAbility4Exist)); + EXPECT_NE(result.end(), std::find_if(result.begin(), result.end(), IsTestAbility5Exist)); + GTEST_LOG_(INFO) << "Ability_Dump_005 end"; +} + +/* + * Feature: AbilityManagerService + * Function: DumpState + * SubFunction: NA + * FunctionPoints: AbilityManagerService DumpState + * EnvConditions: NA + * CaseDescription: Verify DumpState --stack 10 + */ +HWTEST_F(AbilityDumpTest, Ability_Dump_006, TestSize.Level2) +{ + GTEST_LOG_(INFO) << "Ability_Dump_006 start"; + std::string expectResult = "Invalid stack number, please see ability dump stack-list."; + std::string args("--stack 100"); + std::vector result; + g_abilityMs->DumpState(args, result); + auto isExist = std::find_if( + result.begin(), result.end(), [&expectResult](const std::string &str) -> bool { return str == expectResult; }); + EXPECT_TRUE(isExist != result.end()); + GTEST_LOG_(INFO) << "Ability_Dump_006 end"; +} + +/* + * Feature: AbilityManagerService + * Function: DumpState + * SubFunction: NA + * FunctionPoints: AbilityManagerService DumpState + * EnvConditions: NA + * CaseDescription: Verify DumpState --stack-list + */ +HWTEST_F(AbilityDumpTest, Ability_Dump_007, TestSize.Level2) +{ + GTEST_LOG_(INFO) << "Ability_Dump_007 start"; + std::string stack1(" MissionStack ID #1 [ #5 #4 #3 #2 #1 ]"); + std::string args("--stack-list"); + std::vector result; + g_abilityMs->DumpState(args, result); + + // Because the user ID is static, it will increase all the time + std::for_each(result.begin(), result.end(), [](std::string &s) { GTEST_LOG_(INFO) << s.c_str(); }); + int sum = result.size(); + EXPECT_NE(sum, 0); + GTEST_LOG_(INFO) << "Ability_Dump_007 end"; +} + +/* + * Feature: AbilityManagerService + * Function: DumpState + * SubFunction: NA + * FunctionPoints: AbilityManagerService DumpState + * EnvConditions: NA + * CaseDescription: Verify DumpState --mission fail + */ +HWTEST_F(AbilityDumpTest, Ability_Dump_008, TestSize.Level2) +{ + GTEST_LOG_(INFO) << "Ability_Dump_008 start"; + std::string expectResult = "error: invalid argument, please see 'ability dump -h'."; + std::string args("--mission"); + std::vector result; + g_abilityMs->DumpState(args, result); + EXPECT_EQ(result[0], expectResult); + + GTEST_LOG_(INFO) << "Ability_Dump_008 end"; +} + +/* + * Feature: AbilityManagerService + * Function: DumpState + * SubFunction: NA + * FunctionPoints: AbilityManagerService DumpState + * EnvConditions: NA + * CaseDescription: Verify DumpState --mission 0 + */ +HWTEST_F(AbilityDumpTest, Ability_Dump_009, TestSize.Level2) +{ + GTEST_LOG_(INFO) << "Ability_Dump_009 start"; + std::string args("--mission 0"); + std::vector result; + g_abilityMs->DumpState(args, result); + EXPECT_EQ(result.end(), std::find_if(result.begin(), result.end(), IsTestAbility2Exist)); + EXPECT_EQ(result.end(), std::find_if(result.begin(), result.end(), IsTestAbility3Exist)); + EXPECT_EQ(result.end(), std::find_if(result.begin(), result.end(), IsTestAbility4Exist)); + + GTEST_LOG_(INFO) << "Ability_Dump_009 end"; +} + +/* + * Feature: AbilityManagerService + * Function: DumpState + * SubFunction: NA + * FunctionPoints: AbilityManagerService DumpState + * EnvConditions: NA + * CaseDescription: Verify DumpState --mission 1 + */ +HWTEST_F(AbilityDumpTest, Ability_Dump_010, TestSize.Level2) +{ + GTEST_LOG_(INFO) << "Ability_Dump_010 start"; + std::string args("--mission 1"); + std::vector result; + g_abilityMs->DumpState(args, result); + + EXPECT_EQ(result.end(), std::find_if(result.begin(), result.end(), IsLaunchAbilityExist)); + EXPECT_EQ(result.end(), std::find_if(result.begin(), result.end(), IsTestAbility1Exist)); + EXPECT_EQ(result.end(), std::find_if(result.begin(), result.end(), IsTestAbility2Exist)); + EXPECT_EQ(result.end(), std::find_if(result.begin(), result.end(), IsTestAbility3Exist)); + EXPECT_EQ(result.end(), std::find_if(result.begin(), result.end(), IsTestAbility4Exist)); + GTEST_LOG_(INFO) << "Ability_Dump_010 end"; +} + +/* + * Feature: AbilityManagerService + * Function: DumpState + * SubFunction: NA + * FunctionPoints: AbilityManagerService DumpState + * EnvConditions: NA + * CaseDescription: Verify DumpState --mission 100 cause invalid + */ +HWTEST_F(AbilityDumpTest, Ability_Dump_011, TestSize.Level2) +{ + GTEST_LOG_(INFO) << "Ability_Dump_011 start"; + std::string expectResult = "error: invalid mission number, please see 'ability dump --stack-list'."; + std::string args("--mission 100"); + std::vector result; + g_abilityMs->DumpState(args, result); + EXPECT_EQ(result[1], expectResult); + GTEST_LOG_(INFO) << "Ability_Dump_011 end"; +} + +/* + * Feature: AbilityManagerService + * Function: DumpState + * SubFunction: NA + * FunctionPoints: AbilityManagerService DumpState + * EnvConditions: NA + * CaseDescription: Verify DumpState --waitting-queue + */ +HWTEST_F(AbilityDumpTest, Ability_Dump_012, TestSize.Level2) +{ + Want want1; + Want want2; + std::string expectResult("The waitting ability queue is empty."); + + want1.SetElement(g_testAbility1); + want2.SetElement(g_testAbility5); + + GTEST_LOG_(INFO) << "Ability_Dump_012 start"; + g_abilityMs->StartAbility(want1); + g_abilityMs->StartAbility(want2); + + std::string args("--waitting-queue"); + std::vector result; + g_abilityMs->DumpState(args, result); + EXPECT_NE(result.end(), std::find_if(result.begin(), result.end(), [](const std::string &state) { + return std::string::npos != state.find("RadioTopAbility"); + })); + usleep(TEST_WAIT_TIME * 6); + result.clear(); + g_abilityMs->DumpState(args, result); + EXPECT_NE(result[0], expectResult); + + GTEST_LOG_(INFO) << "Ability_Dump_012 end"; +} + +/* + * Feature: AbilityManagerService + * Function: DumpState + * SubFunction: NA + * FunctionPoints: AbilityManagerService DumpState + * EnvConditions: NA + * CaseDescription: Verify DumpState when args invalid + */ +HWTEST_F(AbilityDumpTest, Ability_Dump_013, TestSize.Level2) +{ + GTEST_LOG_(INFO) << "Ability_Dump_013 start"; + std::string args("x"); + std::vector result; + g_abilityMs->DumpState(args, result); + int size = result.size(); + EXPECT_EQ(size, 0); + GTEST_LOG_(INFO) << "Ability_Dump_013 end"; +} +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/abilitymgr/test/unittest/phone/ability_manager_proxy_test/BUILD.gn b/tools/services/abilitymgr/test/unittest/phone/ability_manager_proxy_test/BUILD.gn new file mode 100644 index 00000000000..57100a7456a --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/ability_manager_proxy_test/BUILD.gn @@ -0,0 +1,68 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/test.gni") +import("//foundation/aafwk/standard/aafwk.gni") + +module_output_path = "aafwk_standard/abilitymgr" + +ohos_unittest("ability_manager_proxy_test") { + module_out_path = module_output_path + + include_dirs = [ + "${services_path}/abilitymgr/test/mock/libs/system_ability_mock", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy/include", + "//foundation/aafwk/standard/services/abilitymgr/test/mock/libs/ability_scheduler_mock", + "//foundation/appexecfwk/standard/common/log/include", + ] + + sources = [ + "//foundation/aafwk/standard/services/abilitymgr/test/mock/libs/appexecfwk_core/src/appmgr/mock_app_scheduler.cpp", + "ability_manager_proxy_test.cpp", + ] + + configs = [ + "${services_path}/abilitymgr:abilityms_config", + "${services_path}/abilitymgr/test/mock:aafwk_mock_config", + ] + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + deps = [ + "${services_path}/abilitymgr/test:abilityms_test_source", + "${services_path}/abilitymgr/test/mock/libs/aakit:aakit_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_appmgr_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_bundlemgr_mock", + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/frameworks/kits/ability/native:dummy_classes", + + # "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//third_party/googletest:gmock_main", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] +} + +group("unittest") { + testonly = true + + deps = [ ":ability_manager_proxy_test" ] +} diff --git a/tools/services/abilitymgr/test/unittest/phone/ability_manager_proxy_test/ability_manager_proxy_test.cpp b/tools/services/abilitymgr/test/unittest/phone/ability_manager_proxy_test/ability_manager_proxy_test.cpp new file mode 100644 index 00000000000..9d4b85308b0 --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/ability_manager_proxy_test/ability_manager_proxy_test.cpp @@ -0,0 +1,716 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "ability_manager_proxy.h" +#include "ability_manager_stub_mock.h" +#include "mock_ability_connect_callback.h" +#include "ability_scheduler_mock.h" +#include "ability_record.h" +#include "ability_scheduler.h" + +using namespace testing::ext; +using namespace testing; +using namespace OHOS::AppExecFwk; + +namespace OHOS { +namespace AAFwk { +class AbilityManagerProxyTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + + std::shared_ptr proxy_{nullptr}; + sptr mock_{nullptr}; +}; + +void AbilityManagerProxyTest::SetUpTestCase(void) +{} +void AbilityManagerProxyTest::TearDownTestCase(void) +{} +void AbilityManagerProxyTest::TearDown() +{} + +void AbilityManagerProxyTest::SetUp() +{ + mock_ = new AbilityManagerStubMock(); + proxy_ = std::make_shared(mock_); +} + +/* + * Feature: AbilityManagerService + * Function: StartAbility + * SubFunction: NA + * FunctionPoints: AbilityManagerService StartAbility + * EnvConditions: NA + * CaseDescription: Verify the normal process of startability + */ +HWTEST_F(AbilityManagerProxyTest, AbilityManagerProxy_001, TestSize.Level0) +{ + EXPECT_CALL(*mock_, SendRequest(_, _, _, _)) + .Times(1) + .WillOnce(Invoke(mock_.GetRefPtr(), &AbilityManagerStubMock::InvokeSendRequest)); + const Want want; + auto res = proxy_->StartAbility(want, 9); + + EXPECT_EQ(IAbilityManager::START_ABILITY, mock_->code_); + EXPECT_EQ(res, NO_ERROR); +} + +/* + * Feature: AbilityManagerService + * Function: StartAbility + * SubFunction: NA + * FunctionPoints: AbilityManagerService StartAbility + * EnvConditions: NA + * CaseDescription: Verify that the return value of startability is abnormal + */ +HWTEST_F(AbilityManagerProxyTest, AbilityManagerProxy_002, TestSize.Level0) +{ + EXPECT_CALL(*mock_, SendRequest(_, _, _, _)) + .Times(1) + .WillOnce(Invoke(mock_.GetRefPtr(), &AbilityManagerStubMock::InvokeErrorSendRequest)); + const Want want; + auto res = proxy_->StartAbility(want, 9); + + EXPECT_EQ(IAbilityManager::START_ABILITY, mock_->code_); + EXPECT_NE(res, NO_ERROR); +} + +/* + * Feature: AbilityManagerService + * Function: TerminateAbility + * SubFunction: NA + * FunctionPoints: AbilityManagerService TerminateAbility + * EnvConditions: NA + * CaseDescription: Verify the normal process of TerminateAbility + */ +HWTEST_F(AbilityManagerProxyTest, AbilityManagerProxy_003, TestSize.Level0) +{ + EXPECT_CALL(*mock_, SendRequest(_, _, _, _)) + .Times(1) + .WillOnce(Invoke(mock_.GetRefPtr(), &AbilityManagerStubMock::InvokeSendRequest)); + const Want want; + OHOS::sptr token = nullptr; + auto res = proxy_->TerminateAbility(token, -1, &want); + + EXPECT_EQ(IAbilityManager::TERMINATE_ABILITY, mock_->code_); + EXPECT_EQ(res, NO_ERROR); +} + +/* + * Feature: AbilityManagerService + * Function: TerminateAbility + * SubFunction: NA + * FunctionPoints: AbilityManagerService TerminateAbility + * EnvConditions: NA + * CaseDescription: Verify that the return value of TerminateAbility is abnormal + */ +HWTEST_F(AbilityManagerProxyTest, AbilityManagerProxy_004, TestSize.Level0) +{ + EXPECT_CALL(*mock_, SendRequest(_, _, _, _)) + .Times(1) + .WillOnce(Invoke(mock_.GetRefPtr(), &AbilityManagerStubMock::InvokeErrorSendRequest)); + const Want want; + OHOS::sptr token = nullptr; + auto res = proxy_->TerminateAbility(token, -1, &want); + + EXPECT_EQ(IAbilityManager::TERMINATE_ABILITY, mock_->code_); + EXPECT_NE(res, NO_ERROR); +} + +/* + * Feature: AbilityManagerService + * Function: ConnectAbility + * SubFunction: NA + * FunctionPoints: AbilityManagerService ConnectAbility + * EnvConditions: NA + * CaseDescription: Verify the normal conditions of connectability + */ +HWTEST_F(AbilityManagerProxyTest, AbilityManagerProxy_005, TestSize.Level0) +{ + EXPECT_CALL(*mock_, SendRequest(_, _, _, _)) + .Times(1) + .WillOnce(Invoke(mock_.GetRefPtr(), &AbilityManagerStubMock::InvokeSendRequest)); + Want want; + want.SetFlags(10); + sptr nullConnect = nullptr; + sptr callerToken = nullptr; + int res = proxy_->ConnectAbility(want, nullConnect, callerToken); + EXPECT_NE(res, NO_ERROR); + sptr connect = new AbilityConnectCallback(); + int res1 = proxy_->ConnectAbility(want, connect, callerToken); + EXPECT_EQ(res1, NO_ERROR); + EXPECT_EQ(IAbilityManager::CONNECT_ABILITY, mock_->code_); +} + +/* + * Feature: AbilityManagerService + * Function: ConnectAbility + * SubFunction: NA + * FunctionPoints: AbilityManagerService ConnectAbility + * EnvConditions: NA + * CaseDescription: Verify the abnormal conditions of connectability + */ +HWTEST_F(AbilityManagerProxyTest, AbilityManagerProxy_006, TestSize.Level0) +{ + EXPECT_CALL(*mock_, SendRequest(_, _, _, _)) + .Times(1) + .WillOnce(Invoke(mock_.GetRefPtr(), &AbilityManagerStubMock::InvokeErrorSendRequest)); + const Want want; + sptr callerToken = nullptr; + sptr connect = new AbilityConnectCallback(); + int res = proxy_->ConnectAbility(want, connect, callerToken); + + EXPECT_EQ(IAbilityManager::CONNECT_ABILITY, mock_->code_); + EXPECT_NE(res, NO_ERROR); +} + +/* + * Feature: AbilityManagerService + * Function: DisconnectAbility + * SubFunction: NA + * FunctionPoints: AbilityManagerService DisconnectAbility + * EnvConditions: NA + * CaseDescription: Verify the normal conditions of disconnectAbility + */ +HWTEST_F(AbilityManagerProxyTest, AbilityManagerProxy_007, TestSize.Level0) +{ + EXPECT_CALL(*mock_, SendRequest(_, _, _, _)) + .Times(1) + .WillOnce(Invoke(mock_.GetRefPtr(), &AbilityManagerStubMock::InvokeSendRequest)); + sptr connect = new AbilityConnectCallback(); + int res = proxy_->DisconnectAbility(connect); + + EXPECT_EQ(IAbilityManager::DISCONNECT_ABILITY, mock_->code_); + EXPECT_EQ(res, NO_ERROR); +} + +/* + * Feature: AbilityManagerService + * Function: DisconnectAbility + * SubFunction: NA + * FunctionPoints: AbilityManagerService DisconnectAbility + * EnvConditions: NA + * CaseDescription: Verify the abnormal conditions of disconnectAbility + */ +HWTEST_F(AbilityManagerProxyTest, AbilityManagerProxy_008, TestSize.Level0) +{ + EXPECT_CALL(*mock_, SendRequest(_, _, _, _)) + .Times(1) + .WillOnce(Invoke(mock_.GetRefPtr(), &AbilityManagerStubMock::InvokeErrorSendRequest)); + sptr connect = new AbilityConnectCallback(); + int res = proxy_->DisconnectAbility(connect); + + EXPECT_EQ(IAbilityManager::DISCONNECT_ABILITY, mock_->code_); + EXPECT_NE(res, NO_ERROR); +} + +/* + * Feature: AbilityManagerService + * Function: AttachAbilityThread + * SubFunction: NA + * FunctionPoints: AbilityManagerService AttachAbilityThread + * EnvConditions: NA + * CaseDescription: Verify the normal conditions of attachAbilityThread + */ +HWTEST_F(AbilityManagerProxyTest, AbilityManagerProxy_009, TestSize.Level0) +{ + EXPECT_CALL(*mock_, SendRequest(_, _, _, _)) + .Times(1) + .WillOnce(Invoke(mock_.GetRefPtr(), &AbilityManagerStubMock::InvokeSendRequest)); + sptr scheduler = new AbilitySchedulerMock(); + sptr token = nullptr; + auto res = proxy_->AttachAbilityThread(scheduler, token); + + EXPECT_EQ(IAbilityManager::ATTACH_ABILITY_THREAD, mock_->code_); + EXPECT_EQ(res, NO_ERROR); +} + +/* + * Feature: AbilityManagerService + * Function: AttachAbilityThread + * SubFunction: NA + * FunctionPoints: AbilityManagerService AttachAbilityThread + * EnvConditions: NA + * CaseDescription: Verify the abnormal conditions of attachAbilityThread + */ +HWTEST_F(AbilityManagerProxyTest, AbilityManagerProxy_010, TestSize.Level0) +{ + EXPECT_CALL(*mock_, SendRequest(_, _, _, _)) + .Times(1) + .WillOnce(Invoke(mock_.GetRefPtr(), &AbilityManagerStubMock::InvokeErrorSendRequest)); + sptr scheduler = new AbilitySchedulerMock(); + sptr token = nullptr; + auto res = proxy_->AttachAbilityThread(scheduler, token); + + EXPECT_EQ(IAbilityManager::ATTACH_ABILITY_THREAD, mock_->code_); + EXPECT_NE(res, NO_ERROR); + + sptr nullScheduler = nullptr; + auto res1 = proxy_->AttachAbilityThread(nullScheduler, token); + EXPECT_NE(res1, NO_ERROR); +} + +/* + * Feature: AbilityManagerService + * Function: AbilityTransitionDone + * SubFunction: NA + * FunctionPoints: AbilityManagerService AbilityTransitionDone + * EnvConditions: NA + * CaseDescription: Verify the normal conditions of abilityTransitionDone + */ +HWTEST_F(AbilityManagerProxyTest, AbilityManagerProxy_0011, TestSize.Level0) +{ + EXPECT_CALL(*mock_, SendRequest(_, _, _, _)) + .Times(1) + .WillOnce(Invoke(mock_.GetRefPtr(), &AbilityManagerStubMock::InvokeSendRequest)); + sptr token = nullptr; + auto res = proxy_->AbilityTransitionDone(token, 1); + + EXPECT_EQ(IAbilityManager::ABILITY_TRANSITION_DONE, mock_->code_); + EXPECT_EQ(res, NO_ERROR); +} + +/* + * Feature: AbilityManagerService + * Function: AbilityTransitionDone + * SubFunction: NA + * FunctionPoints: AbilityManagerService AbilityTransitionDone + * EnvConditions: NA + * CaseDescription: Verify the abnormal conditions of abilityTransitionDone + */ +HWTEST_F(AbilityManagerProxyTest, AbilityManagerProxy_012, TestSize.Level0) +{ + EXPECT_CALL(*mock_, SendRequest(_, _, _, _)) + .Times(1) + .WillOnce(Invoke(mock_.GetRefPtr(), &AbilityManagerStubMock::InvokeErrorSendRequest)); + sptr token = nullptr; + auto res = proxy_->AbilityTransitionDone(token, 1); + + EXPECT_EQ(IAbilityManager::ABILITY_TRANSITION_DONE, mock_->code_); + EXPECT_NE(res, NO_ERROR); +} + +/* + * Feature: AbilityManagerService + * Function: ScheduleConnectAbilityDone + * SubFunction: NA + * FunctionPoints: AbilityManagerService ScheduleConnectAbilityDone + * EnvConditions: NA + * CaseDescription: Verify the normal conditions of scheduleConnectAbilityDone + */ +HWTEST_F(AbilityManagerProxyTest, AbilityManagerProxy_0013, TestSize.Level0) +{ + EXPECT_CALL(*mock_, SendRequest(_, _, _, _)) + .Times(1) + .WillOnce(Invoke(mock_.GetRefPtr(), &AbilityManagerStubMock::InvokeSendRequest)); + sptr token = nullptr; + sptr remoteObject = nullptr; + auto res = proxy_->ScheduleConnectAbilityDone(token, remoteObject); + + EXPECT_EQ(IAbilityManager::CONNECT_ABILITY_DONE, mock_->code_); + EXPECT_EQ(res, NO_ERROR); +} + +/* + * Feature: AbilityManagerService + * Function: ScheduleConnectAbilityDone + * SubFunction: NA + * FunctionPoints: AbilityManagerService ScheduleConnectAbilityDone + * EnvConditions: NA + * CaseDescription: Verify the abnormal conditions of scheduleConnectAbilityDone + */ +HWTEST_F(AbilityManagerProxyTest, AbilityManagerProxy_014, TestSize.Level0) +{ + EXPECT_CALL(*mock_, SendRequest(_, _, _, _)) + .Times(1) + .WillOnce(Invoke(mock_.GetRefPtr(), &AbilityManagerStubMock::InvokeErrorSendRequest)); + sptr token = nullptr; + sptr remoteObject = nullptr; + auto res = proxy_->ScheduleConnectAbilityDone(token, remoteObject); + + EXPECT_EQ(IAbilityManager::CONNECT_ABILITY_DONE, mock_->code_); + EXPECT_NE(res, NO_ERROR); +} + +/* + * Feature: AbilityManagerService + * Function: ScheduleDisconnectAbilityDone + * SubFunction: NA + * FunctionPoints: AbilityManagerService ScheduleDisconnectAbilityDone + * EnvConditions: NA + * CaseDescription: Verify the normal conditions of scheduleDisconnectAbilityDone + */ +HWTEST_F(AbilityManagerProxyTest, AbilityManagerProxy_0015, TestSize.Level0) +{ + sptr token = nullptr; + auto res = proxy_->ScheduleDisconnectAbilityDone(token); + EXPECT_EQ(res, NO_ERROR); +} + +/* + * Feature: AbilityManagerService + * Function: AddWindowInfo + * SubFunction: NA + * FunctionPoints: AbilityManagerService AddWindowInfo + * EnvConditions: NA + * CaseDescription: Verify the normal conditions of addWindowInfo + */ +HWTEST_F(AbilityManagerProxyTest, AbilityManagerProxy_0016, TestSize.Level0) +{ + EXPECT_CALL(*mock_, SendRequest(_, _, _, _)) + .Times(1) + .WillOnce(Invoke(mock_.GetRefPtr(), &AbilityManagerStubMock::InvokeSendRequest)); + sptr token = nullptr; + proxy_->AddWindowInfo(token, 1); + + EXPECT_EQ(IAbilityManager::ADD_WINDOW_INFO, mock_->code_); +} + +/* + * Feature: AbilityManagerService + * Function: DumpState + * SubFunction: NA + * FunctionPoints: AbilityManagerService DumpState + * EnvConditions: NA + * CaseDescription: Verify the normal conditions of dumpState + */ +HWTEST_F(AbilityManagerProxyTest, AbilityManagerProxy_0017, TestSize.Level0) +{ + EXPECT_CALL(*mock_, SendRequest(_, _, _, _)) + .Times(1) + .WillOnce(Invoke(mock_.GetRefPtr(), &AbilityManagerStubMock::InvokeSendRequest)); + std::string args = "aaa"; + std::vector info; + proxy_->DumpState(args, info); + + EXPECT_EQ(IAbilityManager::DUMP_STATE, mock_->code_); +} + +/* + * Feature: AbilityManagerService + * Function: TerminateAbilityResult + * SubFunction: NA + * FunctionPoints: AbilityManagerService TerminateAbilityResult + * EnvConditions: NA + * CaseDescription: Verify the normal conditions of terminateAbilityResult + */ +HWTEST_F(AbilityManagerProxyTest, AbilityManagerProxy_0018, TestSize.Level0) +{ + EXPECT_CALL(*mock_, SendRequest(_, _, _, _)) + .Times(1) + .WillOnce(Invoke(mock_.GetRefPtr(), &AbilityManagerStubMock::InvokeSendRequest)); + OHOS::sptr token = nullptr; + auto res = proxy_->TerminateAbilityResult(token, 1); + + EXPECT_EQ(IAbilityManager::TERMINATE_ABILITY_RESULT, mock_->code_); + EXPECT_EQ(res, NO_ERROR); +} + +/* + * Feature: AbilityManagerService + * Function: TerminateAbilityResult + * SubFunction: NA + * FunctionPoints: AbilityManagerService TerminateAbilityResult + * EnvConditions: NA + * CaseDescription: Verify the abnormal conditions of terminateAbilityResult + */ +HWTEST_F(AbilityManagerProxyTest, AbilityManagerProxy_019, TestSize.Level0) +{ + EXPECT_CALL(*mock_, SendRequest(_, _, _, _)) + .Times(1) + .WillOnce(Invoke(mock_.GetRefPtr(), &AbilityManagerStubMock::InvokeErrorSendRequest)); + OHOS::sptr token = nullptr; + auto res = proxy_->TerminateAbilityResult(token, 1); + + EXPECT_EQ(IAbilityManager::TERMINATE_ABILITY_RESULT, mock_->code_); + EXPECT_NE(res, NO_ERROR); +} + +/* + * Feature: AbilityManagerService + * Function: GetAllStackInfo + * SubFunction: NA + * FunctionPoints: AbilityManagerService GetAllStackInfo + * EnvConditions: NA + * CaseDescription: Verify the normal conditions of getAllStackInfo + */ +HWTEST_F(AbilityManagerProxyTest, AbilityManagerProxy_0020, TestSize.Level0) +{ + EXPECT_CALL(*mock_, SendRequest(_, _, _, _)) + .Times(1) + .WillOnce(Invoke(mock_.GetRefPtr(), &AbilityManagerStubMock::InvokeSendRequest)); + StackInfo stackInfo; + proxy_->GetAllStackInfo(stackInfo); + + EXPECT_EQ(IAbilityManager::LIST_STACK_INFO, mock_->code_); +} + +/* + * Feature: AbilityManagerService + * Function: GetRecentMissions + * SubFunction: NA + * FunctionPoints: AbilityManagerService GetRecentMissions + * EnvConditions: NA + * CaseDescription: Verify the normal conditions of getRecentMissions + */ +HWTEST_F(AbilityManagerProxyTest, AbilityManagerProxy_0021, TestSize.Level0) +{ + EXPECT_CALL(*mock_, SendRequest(_, _, _, _)) + .Times(1) + .WillOnce(Invoke(mock_.GetRefPtr(), &AbilityManagerStubMock::InvokeSendRequest)); + std::vector info; + auto res = proxy_->GetRecentMissions(INT_MAX, 1, info); + + EXPECT_EQ(res, 1); + EXPECT_EQ(IAbilityManager::GET_RECENT_MISSION, mock_->code_); + EXPECT_EQ(info[0].baseAbility.GetAbilityName(), "baseAbility"); + EXPECT_EQ(info[0].baseWant.GetElement().GetAbilityName(), ""); +} + +/* + * Feature: AbilityManagerService + * Function: RemoveMission + * SubFunction: NA + * FunctionPoints: AbilityManagerService RemoveMission + * EnvConditions: NA + * CaseDescription: Verify the normal conditions of RemoveMission + */ +HWTEST_F(AbilityManagerProxyTest, AbilityManagerProxy_0023, TestSize.Level0) +{ + EXPECT_CALL(*mock_, SendRequest(_, _, _, _)) + .Times(1) + .WillOnce(Invoke(mock_.GetRefPtr(), &AbilityManagerStubMock::InvokeSendRequest)); + proxy_->RemoveMission(1); + + EXPECT_EQ(IAbilityManager::REMOVE_MISSION, mock_->code_); +} + +/* + * Feature: AbilityManagerService + * Function: RemoveStack + * SubFunction: NA + * FunctionPoints: AbilityManagerService RemoveStack + * EnvConditions: NA + * CaseDescription: Verify the normal conditions of RemoveStack + */ +HWTEST_F(AbilityManagerProxyTest, AbilityManagerProxy_0024, TestSize.Level0) +{ + EXPECT_CALL(*mock_, SendRequest(_, _, _, _)) + .Times(1) + .WillOnce(Invoke(mock_.GetRefPtr(), &AbilityManagerStubMock::InvokeSendRequest)); + proxy_->RemoveStack(1); + + EXPECT_EQ(IAbilityManager::REMOVE_STACK, mock_->code_); +} + +/* + * Feature: AbilityManagerService + * Function: MoveMissionToTop + * SubFunction: NA + * FunctionPoints: AbilityManagerService MoveMissionToTop + * EnvConditions: NA + * CaseDescription: Verify the normal conditions of MoveMissionToTop + */ +HWTEST_F(AbilityManagerProxyTest, AbilityManagerProxy_0025, TestSize.Level0) +{ + EXPECT_CALL(*mock_, SendRequest(_, _, _, _)) + .Times(1) + .WillOnce(Invoke(mock_.GetRefPtr(), &AbilityManagerStubMock::InvokeSendRequest)); + proxy_->MoveMissionToTop(1); + + EXPECT_EQ(IAbilityManager::MOVE_MISSION_TO_TOP, mock_->code_); +} + +/* + * Feature: AbilityManagerService + * Function: ScheduleCommandAbilityDone + * SubFunction: NA + * FunctionPoints: AbilityManagerService ScheduleCommandAbilityDone + * EnvConditions: NA + * CaseDescription: Verify the abnormal conditions of ScheduleCommandAbilityDone + */ +HWTEST_F(AbilityManagerProxyTest, AbilityManagerProxy_026, TestSize.Level0) +{ + EXPECT_CALL(*mock_, SendRequest(_, _, _, _)) + .Times(1) + .WillOnce(Invoke(mock_.GetRefPtr(), &AbilityManagerStubMock::InvokeErrorSendRequest)); + sptr token = nullptr; + auto res = proxy_->ScheduleCommandAbilityDone(token); + + EXPECT_EQ(IAbilityManager::COMMAND_ABILITY_DONE, mock_->code_); + EXPECT_NE(res, NO_ERROR); +} + +/* + * Feature: AbilityManagerService + * Function: StopServiceAbility + * SubFunction: NA + * FunctionPoints: AbilityManagerService StopServiceAbility + * EnvConditions: NA + * CaseDescription: Verify the normal process of StopServiceAbility + */ +HWTEST_F(AbilityManagerProxyTest, AbilityManagerProxy_027, TestSize.Level0) +{ + EXPECT_CALL(*mock_, SendRequest(_, _, _, _)) + .Times(1) + .WillOnce(Invoke(mock_.GetRefPtr(), &AbilityManagerStubMock::InvokeSendRequest)); + const Want want; + auto res = proxy_->StopServiceAbility(want); + + EXPECT_EQ(IAbilityManager::STOP_SERVICE_ABILITY, mock_->code_); + EXPECT_EQ(res, NO_ERROR); +} + +/* + * Feature: AbilityManagerService + * Function: AcquireDataAbility + * SubFunction: NA + * FunctionPoints: AbilityManagerService AcquireDataAbility + * EnvConditions: NA + * CaseDescription: Verify the function AcquireDataAbility normal flow. + */ +HWTEST_F(AbilityManagerProxyTest, AbilityManagerProxy_AcquireDataAbility_001, TestSize.Level0) +{ + OHOS::Uri dataAbilityUri("dataability:///data.bundle.DataAbility"); + AbilityRequest abilityRequest; + abilityRequest.appInfo.bundleName = "data.client.bundle"; + abilityRequest.abilityInfo.name = "ClientAbility"; + abilityRequest.abilityInfo.type = AbilityType::DATA; + std::shared_ptr abilityRecord = AbilityRecord::CreateAbilityRecord(abilityRequest); + + EXPECT_CALL(*mock_, SendRequest(_, _, _, _)).WillOnce(Return(NO_ERROR)); + EXPECT_EQ(proxy_->AcquireDataAbility(dataAbilityUri, true, abilityRecord->GetToken()), nullptr); +} + +/* + * Feature: AbilityManagerService + * Function: AcquireDataAbility + * SubFunction: NA + * FunctionPoints: AbilityManagerService AcquireDataAbility + * EnvConditions: NA + * CaseDescription: Verify the function AcquireDataAbility callerToken is nullptr. + */ +HWTEST_F(AbilityManagerProxyTest, AbilityManagerProxy_AcquireDataAbility_002, TestSize.Level0) +{ + OHOS::Uri dataAbilityUri("dataability:///data.bundle.DataAbility"); + + EXPECT_CALL(*mock_, SendRequest(_, _, _, _)).Times(0); + EXPECT_EQ(proxy_->AcquireDataAbility(dataAbilityUri, true, nullptr), nullptr); +} + +/* + * Feature: AbilityManagerService + * Function: AcquireDataAbility + * SubFunction: NA + * FunctionPoints: AbilityManagerService AcquireDataAbility + * EnvConditions: NA + * CaseDescription: Verify the function AcquireDataAbility SendRequest return error. + */ +HWTEST_F(AbilityManagerProxyTest, AbilityManagerProxy_AcquireDataAbility_003, TestSize.Level0) +{ + OHOS::Uri dataAbilityUri("dataability:///data.bundle.DataAbility"); + AbilityRequest abilityRequest; + abilityRequest.appInfo.bundleName = "data.client.bundle"; + abilityRequest.abilityInfo.name = "ClientAbility"; + abilityRequest.abilityInfo.type = AbilityType::DATA; + std::shared_ptr abilityRecord = AbilityRecord::CreateAbilityRecord(abilityRequest); + + EXPECT_CALL(*mock_, SendRequest(_, _, _, _)).WillOnce(Return(TRANSACTION_ERR)); + EXPECT_EQ(proxy_->AcquireDataAbility(dataAbilityUri, true, abilityRecord->GetToken()), nullptr); +} + +/* + * Feature: AbilityManagerService + * Function: ReleaseDataAbility + * SubFunction: NA + * FunctionPoints: AbilityManagerService ReleaseDataAbility + * EnvConditions: NA + * CaseDescription: Verify the function ReleaseDataAbility normal flow. + */ +HWTEST_F(AbilityManagerProxyTest, AbilityManagerProxy_ReleaseDataAbility_001, TestSize.Level0) +{ + OHOS::sptr scheduler = new AbilityScheduler(); + AbilityRequest abilityRequest; + abilityRequest.appInfo.bundleName = "data.client.bundle"; + abilityRequest.abilityInfo.name = "ClientAbility"; + abilityRequest.abilityInfo.type = AbilityType::DATA; + std::shared_ptr abilityRecord = AbilityRecord::CreateAbilityRecord(abilityRequest); + + EXPECT_CALL(*mock_, SendRequest(_, _, _, _)).WillOnce(Return(NO_ERROR)); + EXPECT_EQ(proxy_->ReleaseDataAbility(scheduler, abilityRecord->GetToken()), 0); +} + +/* + * Feature: AbilityManagerService + * Function: ReleaseDataAbility + * SubFunction: NA + * FunctionPoints: AbilityManagerService ReleaseDataAbility + * EnvConditions: NA + * CaseDescription: Verify the function ReleaseDataAbility dataAbilityScheduler is nullptr. + */ +HWTEST_F(AbilityManagerProxyTest, AbilityManagerProxy_ReleaseDataAbility_002, TestSize.Level0) +{ + AbilityRequest abilityRequest; + abilityRequest.appInfo.bundleName = "data.client.bundle"; + abilityRequest.abilityInfo.name = "ClientAbility"; + abilityRequest.abilityInfo.type = AbilityType::DATA; + std::shared_ptr abilityRecord = AbilityRecord::CreateAbilityRecord(abilityRequest); + + EXPECT_CALL(*mock_, SendRequest(_, _, _, _)).Times(0); + EXPECT_EQ(proxy_->ReleaseDataAbility(nullptr, abilityRecord->GetToken()), ERR_INVALID_VALUE); +} + +/* + * Feature: AbilityManagerService + * Function: ReleaseDataAbility + * SubFunction: NA + * FunctionPoints: AbilityManagerService ReleaseDataAbility + * EnvConditions: NA + * CaseDescription: Verify the function ReleaseDataAbility callerToken is nullptr. + */ +HWTEST_F(AbilityManagerProxyTest, AbilityManagerProxy_ReleaseDataAbility_003, TestSize.Level0) +{ + OHOS::sptr scheduler = new AbilityScheduler(); + + EXPECT_CALL(*mock_, SendRequest(_, _, _, _)).Times(0); + EXPECT_EQ(proxy_->ReleaseDataAbility(scheduler, nullptr), ERR_INVALID_VALUE); +} + +/* + * Feature: AbilityManagerService + * Function: ReleaseDataAbility + * SubFunction: NA + * FunctionPoints: AbilityManagerService ReleaseDataAbility + * EnvConditions: NA + * CaseDescription: Verify the function ReleaseDataAbility SendRequest error. + */ +HWTEST_F(AbilityManagerProxyTest, AbilityManagerProxy_ReleaseDataAbility_004, TestSize.Level0) +{ + OHOS::sptr scheduler = new AbilityScheduler(); + AbilityRequest abilityRequest; + abilityRequest.appInfo.bundleName = "data.client.bundle"; + abilityRequest.abilityInfo.name = "ClientAbility"; + abilityRequest.abilityInfo.type = AbilityType::DATA; + std::shared_ptr abilityRecord = AbilityRecord::CreateAbilityRecord(abilityRequest); + + EXPECT_CALL(*mock_, SendRequest(_, _, _, _)).WillOnce(Return(TRANSACTION_ERR)); + EXPECT_EQ(proxy_->ReleaseDataAbility(scheduler, abilityRecord->GetToken()), TRANSACTION_ERR); +} +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/abilitymgr/test/unittest/phone/ability_manager_proxy_test/ability_manager_stub_mock.h b/tools/services/abilitymgr/test/unittest/phone/ability_manager_proxy_test/ability_manager_stub_mock.h new file mode 100755 index 00000000000..36a008e8432 --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/ability_manager_proxy_test/ability_manager_stub_mock.h @@ -0,0 +1,304 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ABILITY_UNITTEST_ABILITY_MANAGER_STUB_MOCK_H +#define ABILITY_UNITTEST_ABILITY_MANAGER_STUB_MOCK_H +#include +#include +#include +#include "ability_manager_interface.h" + +namespace OHOS { +namespace AAFwk { +class AbilityManagerStubMock : public IRemoteStub { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"IAbilityManagerMock"); + + AbilityManagerStubMock() : code_(0) + {} + virtual ~AbilityManagerStubMock() + {} + + MOCK_METHOD4(SendRequest, int(uint32_t, MessageParcel &, MessageParcel &, MessageOption &)); + + int InvokeSendRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) + { + code_ = code; + + if (GET_RECENT_MISSION == code) { + std::vector missionInfos; + AbilityMissionInfo info; + info.id = 1; + const Want want; + info.baseWant = want; + AppExecFwk::ElementName baseEle("baseDevice", "baseBundle", "baseAbility"); + info.baseAbility = baseEle; + AppExecFwk::ElementName topEle("topDevice", "topBundle", "topAbility"); + info.topAbility = topEle; + missionInfos.emplace_back(info); + + reply.WriteInt32(missionInfos.size()); + for (auto &it : missionInfos) { + if (!reply.WriteParcelable(&it)) { + return ERR_INVALID_VALUE; + } + } + + int res = 1; + if (!reply.WriteInt32(res)) { + return ERR_INVALID_VALUE; + } + } + + return 0; + } + + int InvokeErrorSendRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) + { + code_ = code; + return UNKNOWN_ERROR; + } + + int code_ = 0; + + virtual int StartAbility(const Want &want, int requestCode = -1) + { + return 0; + } + + int StartAbility(const Want &want, const AbilityStartSetting &abilityStartSetting, + const sptr &callerToken, int requestCode = DEFAULT_INVAL_VALUE) + { + return 0; + } + + virtual int TerminateAbility(const sptr &token, int resultCode, const Want *resultWant = nullptr) + { + return 0; + } + + virtual int ConnectAbility( + const Want &want, const sptr &connect, const sptr &callerToken) + { + return 0; + } + + virtual sptr AcquireDataAbility( + const Uri &uri, bool tryBind, const sptr &callerToken) override + { + return nullptr; + } + + virtual int ReleaseDataAbility(sptr dataAbilityScheduler, const sptr &callerToken) + { + return 0; + } + + virtual int DisconnectAbility(const sptr &connect) + { + return 0; + } + + virtual void AddWindowInfo(const sptr &token, int32_t windowToken) + {} + + virtual int AttachAbilityThread(const sptr &scheduler, const sptr &token) + { + return 0; + } + + virtual int AbilityTransitionDone(const sptr &token, int state) + { + return 0; + } + + virtual int ScheduleConnectAbilityDone(const sptr &token, const sptr &remoteObject) + { + return 0; + } + + virtual int ScheduleDisconnectAbilityDone(const sptr &token) + { + return 0; + } + + virtual int ScheduleCommandAbilityDone(const sptr &token) + { + return 0; + } + + virtual void DumpState(const std::string &args, std::vector &state) + {} + + virtual int TerminateAbilityResult(const sptr &token, int startId) + { + return 0; + } + + virtual int StopServiceAbility(const Want &want) + { + return 0; + } + + virtual int GetAllStackInfo(StackInfo &stackInfo) + { + return 0; + } + + virtual int GetRecentMissions( + const int32_t numMax, const int32_t flags, std::vector &recentList) + { + return 0; + } + + int GetMissionSnapshot(const int32_t missionId, MissionSnapshotInfo &snapshot) + { + return 0; + } + + virtual int RemoveMission(int id) + { + return 0; + } + + virtual int RemoveStack(int id) + { + return 0; + } + + virtual int KillProcess(const std::string &bundleName) + { + return 0; + } + + virtual int UninstallApp(const std::string &bundleName) + { + return 0; + } + + virtual int MoveMissionToTop(int32_t missionId) + { + return 0; + } + + bool IsFirstInMission(const sptr &token) override + { + return true; + } + + int CompelVerifyPermission(const std::string &permission, int pid, int uid, std::string &message) override + { + return 0; + } + + int MoveMissionToEnd(const sptr &token, const bool nonFirst) override + { + return 0; + } + + int PowerOff() override + { + return 0; + } + + int PowerOn() override + { + return 0; + } + + int LockMission(int missionId) override + { + return 0; + } + int UnlockMission(int missionId) override + { + return 0; + } + + int SetMissionDescriptionInfo( + const sptr &token, const MissionDescriptionInfo &missionDescriptionInfo) override + { + return 0; + } + + int GetMissionLockModeState() + { + return 0; + } + + int UpdateConfiguration(const DummyConfiguration &config) + { + return 0; + } + + int MoveMissionToFloatingStack(const MissionOption &missionOption) + { + return 0; + } + + int MoveMissionToSplitScreenStack(const MissionOption &missionOption) + { + return 0; + } + + int ChangeFocusAbility(const sptr &lostFocusToken, const sptr &getFocusToken) + { + return 0; + } + + int MinimizeMultiWindow(int missionId) + { + return 0; + } + + int MaximizeMultiWindow(int missionId) + { + return 0; + } + + int GetFloatingMissions(std::vector &list) + { + return 0; + } + + int CloseMultiWindow(int missionId) + { + return 0; + } + + int SetMissionStackSetting(const StackSetting &stackSetting) + { + return 0; + } + + MOCK_METHOD2(TerminateAbilityByCaller, int(const sptr &callerToken, int requestCode)); + MOCK_METHOD3(StartAbility, int(const Want &want, const sptr &callerToken, int requestCode)); + MOCK_METHOD2( + GetWantSender, sptr(const WantSenderInfo &wantSenderInfo, const sptr &callerToken)); + MOCK_METHOD2(SendWantSender, int(const sptr &target, const SenderInfo &senderInfo)); + MOCK_METHOD1(CancelWantSender, void(const sptr &sender)); + MOCK_METHOD1(GetPendingWantUid, int(const sptr &target)); + MOCK_METHOD1(GetPendingWantUserId, int(const sptr &target)); + MOCK_METHOD1(GetPendingWantBundleName, std::string(const sptr &target)); + MOCK_METHOD1(GetPendingWantCode, int(const sptr &target)); + MOCK_METHOD1(GetPendingWantType, int(const sptr &target)); + MOCK_METHOD2(RegisterCancelListener, void(const sptr &sender, const sptr &receiver)); + MOCK_METHOD2(UnregisterCancelListener, void(const sptr &sender, const sptr &receiver)); + MOCK_METHOD2(GetPendingRequestWant, int(const sptr &target, std::shared_ptr &want)); +}; +} // namespace AAFwk +} // namespace OHOS + +#endif diff --git a/tools/services/abilitymgr/test/unittest/phone/ability_manager_service_test/BUILD.gn b/tools/services/abilitymgr/test/unittest/phone/ability_manager_service_test/BUILD.gn new file mode 100644 index 00000000000..7ebfa48c034 --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/ability_manager_service_test/BUILD.gn @@ -0,0 +1,66 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/test.gni") +import("//foundation/aafwk/standard/aafwk.gni") + +module_output_path = "aafwk_standard/abilitymgr" + +ohos_unittest("ability_manager_service_test") { + module_out_path = module_output_path + + include_dirs = [ + "${services_path}/abilitymgr/test/mock/libs/system_ability_mock", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy/include", + "//foundation/distributedschedule/samgr/adapter/interfaces/innerkits/include/", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_core/include/appmgr", + ] + + sources = [ + # add mock file + "//foundation/aafwk/standard/services/abilitymgr/test/mock/libs/appexecfwk_core/src/appmgr/mock_app_scheduler.cpp", + "ability_manager_service_test.cpp", + ] + + configs = [ "${services_path}/abilitymgr:abilityms_config" ] + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + deps = [ + "${innerkits_path}/want:want", + "${services_path}/abilitymgr/test:abilityms_test_source", + "${services_path}/abilitymgr/test/mock/libs/aakit:aakit_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_appmgr_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_bundlemgr_mock", + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/frameworks/kits/ability/native:dummy_classes", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//third_party/googletest:gmock_main", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] +} + +group("unittest") { + testonly = true + + deps = [ ":ability_manager_service_test" ] +} diff --git a/tools/services/abilitymgr/test/unittest/phone/ability_manager_service_test/ability_manager_service_test.cpp b/tools/services/abilitymgr/test/unittest/phone/ability_manager_service_test/ability_manager_service_test.cpp new file mode 100644 index 00000000000..b8c59f50319 --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/ability_manager_service_test/ability_manager_service_test.cpp @@ -0,0 +1,2596 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#define private public +#define protected public +#include "ability_manager_service.h" +#include "ability_event_handler.h" +#undef private +#undef protected + +#include "app_process_data.h" +#include "system_ability_definition.h" +#include "ability_manager_errors.h" +#include "ability_scheduler.h" +#include "bundlemgr/mock_bundle_manager.h" +#include "sa_mgr_client.h" +#include "mock_ability_connect_callback.h" +#include "if_system_ability_manager.h" +#include "iservice_registry.h" + +using namespace testing; +using namespace testing::ext; +using namespace OHOS::AppExecFwk; + +namespace OHOS { +namespace AAFwk { + +static void WaitUntilTaskFinished() +{ + const uint32_t maxRetryCount = 1000; + const uint32_t sleepTime = 1000; + uint32_t count = 0; + auto handler = OHOS::DelayedSingleton::GetInstance()->GetEventHandler(); + std::atomic taskCalled(false); + auto f = [&taskCalled]() { taskCalled.store(true); }; + if (handler->PostTask(f)) { + while (!taskCalled.load()) { + ++count; + if (count >= maxRetryCount) { + break; + } + usleep(sleepTime); + } + } +} + +#define SLEEP(milli) std::this_thread::sleep_for(std::chrono::seconds(milli)) + +namespace { +const std::string NAME_BUNDLE_MGR_SERVICE = "BundleMgrService"; +static int32_t g_windowToken = 0; +} // namespace + +class AbilityManagerServiceTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp(); + void TearDown(); + int StartAbility(const Want &want); + static constexpr int TEST_WAIT_TIME = 100000; + +public: + std::shared_ptr abilityMs_{nullptr}; + AbilityRequest abilityRequest_{}; + std::shared_ptr abilityRecord_{nullptr}; +}; + +int AbilityManagerServiceTest::StartAbility(const Want &want) +{ + int ref = -1; + auto topAbility = abilityMs_->GetStackManager()->GetCurrentTopAbility(); + if (topAbility) { + topAbility->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + } + ref = abilityMs_->StartAbility(want); + WaitUntilTaskFinished(); + return ref; +} + +void AbilityManagerServiceTest::SetUpTestCase() +{ + OHOS::DelayedSingleton::GetInstance()->RegisterSystemAbility( + OHOS::BUNDLE_MGR_SERVICE_SYS_ABILITY_ID, new BundleMgrService()); +} + +void AbilityManagerServiceTest::TearDownTestCase() +{ + OHOS::DelayedSingleton::DestroyInstance(); +} + +void AbilityManagerServiceTest::SetUp() +{ + abilityMs_ = OHOS::DelayedSingleton::GetInstance(); + abilityMs_->OnStart(); + WaitUntilTaskFinished(); + if (abilityRecord_ == nullptr) { + abilityRequest_.appInfo.bundleName = "data.client.bundle"; + abilityRequest_.abilityInfo.name = "ClientAbility"; + abilityRequest_.abilityInfo.type = AbilityType::DATA; + abilityRecord_ = AbilityRecord::CreateAbilityRecord(abilityRequest_); + } +} + +void AbilityManagerServiceTest::TearDown() +{ + abilityMs_->OnStop(); + OHOS::DelayedSingleton::DestroyInstance(); +} + +/* + * Feature: AbilityManagerService + * Function: StartAbility + * SubFunction: NA + * FunctionPoints: AbilityManagerService StartAbility + * EnvConditions: NA + * CaseDescription: Verify that the result of StartAbility is failed if the param of StartAbility is illegal. + */ +HWTEST_F(AbilityManagerServiceTest, Interface_001, TestSize.Level1) +{ + Want want; + want.AddEntity(Want::ENTITY_HOME); + auto result = StartAbility(want); + WaitUntilTaskFinished(); + EXPECT_EQ(RESOLVE_ABILITY_ERR, result); +} + +/* + * Feature: AbilityManagerService + * Function: StartAbility QueryServiceState + * SubFunction: NA + * FunctionPoints: AbilityManagerService StartAbility + * EnvConditions: NA + * CaseDescription: Verify that the result of StartAbility is successful if the param of StartAbility is normal. + */ +HWTEST_F(AbilityManagerServiceTest, Interface_002, TestSize.Level1) +{ + Want want; + ElementName element("device", "com.ix.hiMusic", "MusicAbility"); + want.SetElement(element); + auto result = StartAbility(want); + WaitUntilTaskFinished(); + EXPECT_EQ(OHOS::ERR_OK, result); + EXPECT_EQ(ServiceRunningState::STATE_RUNNING, abilityMs_->QueryServiceState()); + auto stackManager = abilityMs_->GetStackManager(); + auto topAbility = stackManager->GetCurrentTopAbility(); + EXPECT_EQ(topAbility->GetAbilityInfo().bundleName, "com.ix.hiMusic"); +} + +/* + * Feature: AbilityManagerService + * Function: StartAbility QueryServiceState + * SubFunction: NA + * FunctionPoints: AbilityManagerService StartAbility + * EnvConditions: NA + * CaseDescription: Verify the singleton startup mode, start multiple times, and do not recreate + */ +HWTEST_F(AbilityManagerServiceTest, Interface_003, TestSize.Level1) +{ + Want want; + ElementName element("device", "com.ix.hiMusic", "MusicAbility"); + want.SetElement(element); + auto result = StartAbility(want); + WaitUntilTaskFinished(); + EXPECT_EQ(OHOS::ERR_OK, result); + auto stackManager = abilityMs_->GetStackManager(); + auto topAbility = stackManager->GetCurrentTopAbility(); + EXPECT_EQ(topAbility->GetAbilityInfo().bundleName, "com.ix.hiMusic"); + + topAbility->SetAbilityState(AAFwk::AbilityState::ACTIVE); + + Want want1; + ElementName element1("device", "com.ix.hiMusic", "MusicSAbility"); + want1.SetElement(element1); + auto result1 = StartAbility(want1); + WaitUntilTaskFinished(); + EXPECT_EQ(OHOS::ERR_OK, result1); + stackManager = abilityMs_->GetStackManager(); + topAbility = stackManager->GetCurrentTopAbility(); + auto abilityId = topAbility->GetRecordId(); + + topAbility->SetAbilityState(AAFwk::AbilityState::ACTIVE); + + Want want2; + ElementName element2("device", "com.ix.hiMusic", "MusicSAbility"); + want2.SetElement(element2); + auto result2 = StartAbility(want2); + WaitUntilTaskFinished(); + EXPECT_EQ(OHOS::ERR_OK, result2); + stackManager = abilityMs_->GetStackManager(); + topAbility = stackManager->GetCurrentTopAbility(); + + EXPECT_EQ(topAbility->GetRecordId(), abilityId); +} + +/* + * Feature: AbilityManagerService + * Function: StartAbility QueryServiceState + * SubFunction: NA + * FunctionPoints: AbilityManagerService StartAbility + * EnvConditions: NA + * CaseDescription: Verify the standard startup mode, start several times, and create a new record + */ +HWTEST_F(AbilityManagerServiceTest, Interface_004, TestSize.Level1) +{ + Want want; + ElementName element("device", "com.ix.hiMusic", "MusicAbility"); + want.SetElement(element); + auto result = StartAbility(want); + WaitUntilTaskFinished(); + EXPECT_EQ(OHOS::ERR_OK, result); + auto stackManager = abilityMs_->GetStackManager(); + auto topAbility = stackManager->GetCurrentTopAbility(); + auto id = topAbility->GetRecordId(); + EXPECT_EQ(topAbility->GetAbilityInfo().bundleName, "com.ix.hiMusic"); + + topAbility->SetAbilityState(AAFwk::AbilityState::ACTIVE); + + Want want1; + ElementName element1("device", "com.ix.hiMusic", "MusicAbility"); + want1.SetElement(element1); + auto result1 = StartAbility(want1); + WaitUntilTaskFinished(); + EXPECT_EQ(OHOS::ERR_OK, result1); + stackManager = abilityMs_->GetStackManager(); + topAbility = stackManager->GetCurrentTopAbility(); + auto abilityId = topAbility->GetRecordId(); + + EXPECT_NE(abilityId, id); +} + +/* + * Feature: AbilityManagerService + * Function: StartAbility QueryServiceState + * SubFunction: NA + * FunctionPoints: AbilityManagerService StartAbility + * EnvConditions: NA + * CaseDescription: Verify the singletop startup mode, start several times, and create a new record + */ +HWTEST_F(AbilityManagerServiceTest, Interface_005, TestSize.Level1) +{ + Want want; + ElementName element("device", "com.ix.hiMusic", "MusicAbility"); + want.SetElement(element); + auto result = StartAbility(want); + WaitUntilTaskFinished(); + EXPECT_EQ(OHOS::ERR_OK, result); + auto stackManager = abilityMs_->GetStackManager(); + auto topAbility = stackManager->GetCurrentTopAbility(); + EXPECT_EQ(topAbility->GetAbilityInfo().bundleName, "com.ix.hiMusic"); + + topAbility->SetAbilityState(AAFwk::AbilityState::ACTIVE); + + Want want1; + ElementName element1("device", "com.ix.hiMusic", "MusicTopAbility"); + want1.SetElement(element1); + auto result1 = StartAbility(want1); + WaitUntilTaskFinished(); + EXPECT_EQ(OHOS::ERR_OK, result1); + stackManager = abilityMs_->GetStackManager(); + topAbility = stackManager->GetCurrentTopAbility(); + auto abilityId = topAbility->GetRecordId(); + + topAbility->SetAbilityState(AAFwk::AbilityState::ACTIVE); + + Want want2; + ElementName element2("device", "com.ix.hiMusic", "MusicTopAbility"); + want2.SetElement(element2); + auto result2 = StartAbility(want2); + WaitUntilTaskFinished(); + EXPECT_EQ(OHOS::ERR_OK, result2); + stackManager = abilityMs_->GetStackManager(); + topAbility = stackManager->GetCurrentTopAbility(); + + EXPECT_EQ(topAbility->GetRecordId(), abilityId); +} + +/* + * Feature: AbilityManagerService + * Function: StartAbility QueryServiceState + * SubFunction: NA + * FunctionPoints: AbilityManagerService StartAbility + * EnvConditions: NA + * CaseDescription: Verify that service ability started successfully + */ +HWTEST_F(AbilityManagerServiceTest, Interface_006, TestSize.Level1) +{ + Want want; + ElementName element("device", "com.ix.musicService", "MusicService"); + want.SetElement(element); + auto result = StartAbility(want); + WaitUntilTaskFinished(); + EXPECT_EQ(OHOS::ERR_OK, result); + auto serviceMap = abilityMs_->connectManager_->GetServiceMap(); + EXPECT_EQ(1, static_cast(serviceMap.size())); +} + +/* + * Feature: AbilityManagerService + * Function: StartAbility + * SubFunction: NA + * FunctionPoints: AbilityManagerService StartAbility + * EnvConditions: NA + * CaseDescription: Top ability is not active, so enqueue ability for waiting. StartAbility failed + */ +HWTEST_F(AbilityManagerServiceTest, Interface_007, TestSize.Level1) +{ + Want want; + ElementName element("device", "com.ix.hiMusic", "MusicAbility"); + want.SetElement(element); + auto result = StartAbility(want); + WaitUntilTaskFinished(); + EXPECT_EQ(OHOS::ERR_OK, result); + auto stackManager = abilityMs_->GetStackManager(); + auto topAbility = stackManager->GetCurrentTopAbility(); + + Want want1; + ElementName element1("device", "com.ix.hiMusic", "MusicAbility"); + want1.SetElement(element1); + auto result1 = abilityMs_->StartAbility(want1); + WaitUntilTaskFinished(); + EXPECT_EQ(START_ABILITY_WAITING, result1); +} + +/* + * Feature: AbilityManagerService + * Function: TerminateAbility + * SubFunction: NA + * FunctionPoints: AbilityManagerService TerminateAbility + * EnvConditions: NA + * CaseDescription: Failed to verify terminate ability + */ +HWTEST_F(AbilityManagerServiceTest, Interface_008, TestSize.Level1) +{ + Want want; + ElementName element("device", "com.ix.hiData", "DataAbility"); + want.SetElement(element); + auto result = StartAbility(want); + WaitUntilTaskFinished(); + EXPECT_EQ(OHOS::ERR_INVALID_VALUE, result); + auto stackManager = abilityMs_->GetStackManager(); + auto topAbility = stackManager->GetCurrentTopAbility(); + sptr token = nullptr; + if (topAbility) { + token = topAbility->GetToken(); + } + + sptr nullToekn = nullptr; + auto result1 = abilityMs_->TerminateAbility(nullToekn, -1, &want); + WaitUntilTaskFinished(); + EXPECT_EQ(ERR_INVALID_VALUE, result1); + + std::shared_ptr ability = nullptr; + sptr toekn1 = new Token(ability); + auto result2 = abilityMs_->TerminateAbility(toekn1, -1, &want); + WaitUntilTaskFinished(); + EXPECT_EQ(ERR_INVALID_VALUE, result2); + + auto result3 = abilityMs_->TerminateAbility(token, -1, &want); + WaitUntilTaskFinished(); + EXPECT_EQ(ERR_INVALID_VALUE, result3); +} + +/* + * Feature: AbilityManagerService + * Function: TerminateAbility + * SubFunction: NA + * FunctionPoints: AbilityManagerService TerminateAbility + * EnvConditions: NA + * CaseDescription: Verification service terminate ability failure + */ +HWTEST_F(AbilityManagerServiceTest, Interface_009, TestSize.Level1) +{ + Want want; + ElementName element("device", "com.ix.musicService", "MusicService"); + want.SetElement(element); + auto result = StartAbility(want); + WaitUntilTaskFinished(); + EXPECT_EQ(OHOS::ERR_OK, result); + + auto serviceMap = abilityMs_->connectManager_->GetServiceMap(); + EXPECT_EQ(1, static_cast(serviceMap.size())); + for (auto &it : serviceMap) { + EXPECT_EQ(it.first, element.GetURI()); + } + auto service = serviceMap.at(element.GetURI()); + service->SetAbilityState(AAFwk::AbilityState::ACTIVE); + + auto result1 = abilityMs_->TerminateAbility(service->GetToken(), -1, &want); + WaitUntilTaskFinished(); + EXPECT_EQ(OHOS::ERR_OK, result1); +} + +/* + * Feature: AbilityManagerService + * Function: TerminateAbility + * SubFunction: NA + * FunctionPoints: AbilityManagerService TerminateAbility + * EnvConditions: NA + * CaseDescription: Verification service terminate ability failure + */ +HWTEST_F(AbilityManagerServiceTest, Interface_010, TestSize.Level1) +{ + Want want; + ElementName element("device", "com.ix.hiMusic", "MusicAbility"); + want.SetElement(element); + auto result = StartAbility(want); + WaitUntilTaskFinished(); + EXPECT_EQ(OHOS::ERR_OK, result); + auto stackManager = abilityMs_->GetStackManager(); + auto topAbility = stackManager->GetCurrentTopAbility(); + EXPECT_EQ(topAbility->GetAbilityInfo().bundleName, "com.ix.hiMusic"); + + topAbility->SetAbilityState(AAFwk::AbilityState::ACTIVE); + + Want want1; + ElementName element1("device", "com.ix.hiMusic", "MusicSAbility"); + want1.SetElement(element1); + auto result1 = StartAbility(want1); + WaitUntilTaskFinished(); + EXPECT_EQ(OHOS::ERR_OK, result1); + stackManager = abilityMs_->GetStackManager(); + topAbility = stackManager->GetCurrentTopAbility(); + + topAbility->SetAbilityState(AAFwk::AbilityState::ACTIVE); + + Want want2; + ElementName element2("device", "com.ix.hiRadio", "RadioAbility"); + want2.SetElement(element2); + auto result2 = StartAbility(want2); + WaitUntilTaskFinished(); + EXPECT_EQ(OHOS::ERR_OK, result2); + stackManager = abilityMs_->GetStackManager(); + topAbility = stackManager->GetCurrentTopAbility(); + + topAbility->SetAbilityState(AAFwk::AbilityState::ACTIVE); + + auto result3 = StartAbility(want); + WaitUntilTaskFinished(); + EXPECT_EQ(OHOS::ERR_OK, result3); + topAbility = stackManager->GetCurrentTopAbility(); + + auto result4 = abilityMs_->TerminateAbility(topAbility->GetToken(), -1, &want); + WaitUntilTaskFinished(); + EXPECT_EQ(OHOS::ERR_OK, result4); + + topAbility = stackManager->GetCurrentTopAbility(); + EXPECT_EQ(topAbility->GetAbilityInfo().bundleName, "com.ix.hiRadio"); + + auto result5 = abilityMs_->TerminateAbility(topAbility->GetToken(), -1, &want2); + WaitUntilTaskFinished(); + EXPECT_EQ(OHOS::ERR_OK, result5); + + topAbility = stackManager->GetCurrentTopAbility(); + EXPECT_EQ(topAbility->GetAbilityInfo().bundleName, "com.ix.hiMusic"); +} + +/* + * Feature: AbilityManagerService + * Function: AttachAbilityThread + * SubFunction: NA + * FunctionPoints: AbilityManagerService StartAbility + * EnvConditions: NA + * CaseDescription: Attachabilitythread failed due to empty token or scheduler + */ +HWTEST_F(AbilityManagerServiceTest, Interface_011, TestSize.Level1) +{ + Want wantLuncher; + ElementName elementLun("device", "com.ix.hiworld", "LauncherAbility"); + wantLuncher.SetElement(elementLun); + abilityMs_->StartAbility(wantLuncher); + WaitUntilTaskFinished(); + auto stackManager = abilityMs_->GetStackManager(); + auto topAbility = stackManager->GetCurrentTopAbility(); + EXPECT_EQ(topAbility->GetAbilityInfo().bundleName, "com.ix.hiworld"); + + OHOS::sptr scheduler = new AbilityScheduler(); + OHOS::sptr nullScheduler = nullptr; + EXPECT_EQ(abilityMs_->AttachAbilityThread(nullScheduler, topAbility->GetToken()), OHOS::ERR_INVALID_VALUE); + + std::shared_ptr record = nullptr; + OHOS::sptr nullToken = new Token(record); + EXPECT_EQ(abilityMs_->AttachAbilityThread(scheduler, nullToken), OHOS::ERR_INVALID_VALUE); + + EXPECT_EQ(abilityMs_->AttachAbilityThread(scheduler, topAbility->GetToken()), OHOS::ERR_OK); +} + +/* + * Feature: AbilityManagerService + * Function: AbilityTransitionDone + * SubFunction: NA + * FunctionPoints: AbilityManagerService StartAbility + * EnvConditions: NA + * CaseDescription: AbilityTransitionDone failed due to empty token or scheduler + */ +HWTEST_F(AbilityManagerServiceTest, Interface_012, TestSize.Level1) +{ + Want wantLuncher; + ElementName elementLun("device", "com.ix.hiworld", "LauncherAbility"); + wantLuncher.SetElement(elementLun); + abilityMs_->StartAbility(wantLuncher); + WaitUntilTaskFinished(); + auto stackManager = abilityMs_->GetStackManager(); + auto topAbility = stackManager->GetCurrentTopAbility(); + EXPECT_EQ(topAbility->GetAbilityInfo().bundleName, "com.ix.hiworld"); + OHOS::sptr nullToken = nullptr; + auto res = abilityMs_->AbilityTransitionDone(nullToken, OHOS::AAFwk::AbilityState::ACTIVE); + EXPECT_EQ(res, OHOS::ERR_INVALID_VALUE); + + std::shared_ptr record = nullptr; + OHOS::sptr token = new Token(record); + auto res1 = abilityMs_->AbilityTransitionDone(token, OHOS::AAFwk::AbilityState::ACTIVE); + EXPECT_EQ(res1, OHOS::ERR_INVALID_VALUE); +} + +/* + * Feature: AbilityManagerService + * Function: SetStackManager and GetStackManager + * SubFunction: NA + * FunctionPoints: AbilityManagerService SetStackManager and GetStackManager + * EnvConditions: NA + * CaseDescription: Verify set and get + */ +HWTEST_F(AbilityManagerServiceTest, Interface_013, TestSize.Level1) +{ + abilityMs_->SetStackManager(0); + EXPECT_NE(nullptr, abilityMs_->GetStackManager()); +} + +/* + * Feature: AbilityManagerService + * Function: DumpWaittingAbilityQueue + * SubFunction: NA + * FunctionPoints: AbilityManagerService DumpWaittingAbilityQueue + * EnvConditions: NA + * CaseDescription: Verify dumpwaittingabilityqueue result + */ +HWTEST_F(AbilityManagerServiceTest, Interface_014, TestSize.Level1) +{ + std::string dump; + abilityMs_->DumpWaittingAbilityQueue(dump); + EXPECT_EQ(false, (dump.find("User ID #0") != string::npos)); +} + +/* + * Feature: AbilityManagerService + * Function: OnAbilityRequestDone + * SubFunction: NA + * FunctionPoints: AbilityManagerService OnAbilityRequestDone + * EnvConditions: NA + * CaseDescription: OnAbilityRequestDone failed due to empty token + */ +HWTEST_F(AbilityManagerServiceTest, Interface_015, TestSize.Level1) +{ + Want wantLuncher; + ElementName elementLun("device", "com.ix.hiworld", "LauncherAbility"); + wantLuncher.SetElement(elementLun); + abilityMs_->StartAbility(wantLuncher); + WaitUntilTaskFinished(); + auto stackManager = abilityMs_->GetStackManager(); + auto topAbility = stackManager->GetCurrentTopAbility(); + topAbility->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + OHOS::sptr nullToken = nullptr; + + abilityMs_->OnAbilityRequestDone(nullToken, 2); + EXPECT_EQ(topAbility->GetAbilityState(), OHOS::AAFwk::AbilityState::ACTIVE); + + abilityMs_->OnAbilityRequestDone(topAbility->GetToken(), 2); + EXPECT_EQ(topAbility->GetAbilityState(), OHOS::AAFwk::AbilityState::ACTIVATING); +} + +/* + * Feature: AbilityManagerService + * Function: RemoveMission + * SubFunction: NA + * FunctionPoints: AbilityManagerService RemoveMission + * EnvConditions: NA + * CaseDescription: 1.MissionId < 0, RemoveMission failed + * 2.MissionId no exist, RemoveMission failed + * 3.Top mission is launcher, RemoveMission failed + * 4.The current mission cannot be removed + * 5.current mission is launcher, remove default mission is success + */ +HWTEST_F(AbilityManagerServiceTest, Interface_016, TestSize.Level1) +{ + Want wantLuncher; + ElementName elementLun("device", "com.ix.hiworld", "LauncherAbility"); + wantLuncher.SetElement(elementLun); + StartAbility(wantLuncher); + WaitUntilTaskFinished(); + + EXPECT_TRUE(abilityMs_->GetStackManager() != nullptr); + EXPECT_TRUE(abilityMs_->GetStackManager()->GetTopMissionRecord() != nullptr); + EXPECT_TRUE(abilityMs_->GetStackManager()->GetTopMissionRecord()->GetTopAbilityRecord() != nullptr); + auto launcherWant = abilityMs_->GetStackManager()->GetTopMissionRecord()->GetTopAbilityRecord()->GetWant(); + + EXPECT_EQ(abilityMs_->RemoveMission(-1), OHOS::ERR_INVALID_VALUE); + + EXPECT_EQ(abilityMs_->RemoveMission(100), REMOVE_MISSION_ID_NOT_EXIST); + + auto topMissionId = abilityMs_->GetStackManager()->GetTopMissionRecord()->GetMissionRecordId(); + EXPECT_EQ(abilityMs_->RemoveMission(topMissionId), REMOVE_MISSION_LAUNCHER_DENIED); + GTEST_LOG_(INFO) << "topMissionId " << topMissionId; + abilityMs_->GetStackManager()->GetCurrentTopAbility()->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + Want want; + want.AddEntity(Want::ENTITY_HOME); + ElementName element("device", "com.ix.music", "MusicAbility"); + want.SetElement(element); + auto result = StartAbility(want); + WaitUntilTaskFinished(); + EXPECT_EQ(OHOS::ERR_OK, result); + + topMissionId = abilityMs_->GetStackManager()->GetTopMissionRecord()->GetMissionRecordId(); + GTEST_LOG_(INFO) << "topMissionId " << topMissionId; + EXPECT_FALSE(abilityMs_->GetStackManager()->IsLauncherMission(topMissionId)); + EXPECT_EQ(abilityMs_->RemoveMission(topMissionId), ERR_OK); + + auto musicAbility = abilityMs_->GetStackManager()->GetCurrentTopAbility(); + musicAbility->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + EXPECT_EQ(abilityMs_->RemoveMission(topMissionId), ERR_OK); + + auto result1 = StartAbility(launcherWant); + WaitUntilTaskFinished(); + EXPECT_EQ(OHOS::ERR_OK, result1); + + EXPECT_EQ(musicAbility->GetAbilityState(), OHOS::AAFwk::AbilityState::INACTIVATING); + EXPECT_NE(topMissionId, abilityMs_->GetStackManager()->GetTopMissionRecord()->GetMissionRecordId()); + musicAbility->SetAbilityState(OHOS::AAFwk::AbilityState::MOVING_BACKGROUND); + + EXPECT_EQ(abilityMs_->RemoveMission(topMissionId), 0); + WaitUntilTaskFinished(); +} + +/* + * Feature: AbilityManagerService + * Function: RemoveMission + * SubFunction: NA + * FunctionPoints: AbilityManagerService RemoveMission + * EnvConditions: window visible is true, ability state is inactive + * CaseDescription: Verify RemoveMission operation fail + */ +HWTEST_F(AbilityManagerServiceTest, Interface_017, TestSize.Level1) +{ + Want wantLuncher; + ElementName elementLun("device", "com.ix.hiworld", "LauncherAbility"); + wantLuncher.SetElement(elementLun); + abilityMs_->StartAbility(wantLuncher); + WaitUntilTaskFinished(); + auto launcherWant = abilityMs_->GetStackManager()->GetTopMissionRecord()->GetTopAbilityRecord()->GetWant(); + + auto topMissionId = abilityMs_->GetStackManager()->GetTopMissionRecord()->GetMissionRecordId(); + EXPECT_EQ(abilityMs_->RemoveMission(topMissionId), REMOVE_MISSION_LAUNCHER_DENIED); + GTEST_LOG_(INFO) << "topMissionId " << topMissionId; + abilityMs_->GetStackManager()->GetCurrentTopAbility()->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + Want want; + want.AddEntity(Want::ENTITY_HOME); + ElementName element("device", "com.ix.music", "MusicAbility"); + want.SetElement(element); + auto result = StartAbility(want); + WaitUntilTaskFinished(); + EXPECT_EQ(OHOS::ERR_OK, result); + + auto topAbility = abilityMs_->GetStackManager()->GetCurrentTopAbility(); + abilityMs_->AddWindowInfo(topAbility->GetToken(), ++g_windowToken); + topAbility->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + topMissionId = abilityMs_->GetStackManager()->GetTopMissionRecord()->GetMissionRecordId(); + + auto result1 = abilityMs_->StartAbility(launcherWant); + WaitUntilTaskFinished(); + EXPECT_EQ(OHOS::ERR_OK, result1); + + topAbility->GetWindowInfo()->isVisible_ = true; + topAbility->SetAbilityState(OHOS::AAFwk::AbilityState::INACTIVE); + + EXPECT_EQ(abilityMs_->RemoveMission(topMissionId), OHOS::ERR_OK); + WaitUntilTaskFinished(); +} + +/* + * Feature: AbilityManagerService + * Function: GetRecentMissions + * SubFunction: NA + * FunctionPoints: AbilityManagerService GetRecentMissions + * EnvConditions: NA + * CaseDescription: Verify GetRecentMissions operation + */ +HWTEST_F(AbilityManagerServiceTest, Interface_018, TestSize.Level1) +{ + Want want; + want.AddEntity(Want::ENTITY_HOME); + ElementName element("device", "com.ix.music", "MusicAbility"); + want.SetElement(element); + auto result = StartAbility(want); + WaitUntilTaskFinished(); + EXPECT_EQ(OHOS::ERR_OK, result); + + abilityMs_->GetStackManager()->GetCurrentTopAbility()->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + Want want1; + want1.AddEntity(Want::ENTITY_HOME); + ElementName element1("device", "com.ix.radio", "RadioAbility"); + want1.SetElement(element1); + auto result1 = StartAbility(want1); + WaitUntilTaskFinished(); + EXPECT_EQ(OHOS::ERR_OK, result1); + + std::vector info; + auto res = abilityMs_->GetRecentMissions(-1, 1, info); + EXPECT_EQ(OHOS::ERR_INVALID_VALUE, res); + + auto res1 = abilityMs_->GetRecentMissions(INT_MAX, -1, info); + EXPECT_EQ(OHOS::ERR_INVALID_VALUE, res1); + + auto res2 = abilityMs_->GetRecentMissions(INT_MAX, 1, info); + EXPECT_EQ(OHOS::ERR_OK, res2); + EXPECT_EQ(static_cast(info.size()), 1); + EXPECT_EQ(info[0].runingState, -1); + EXPECT_EQ(info[0].missionDescription.label, "app label"); + EXPECT_EQ(info[0].missionDescription.iconPath, "icon path"); + EXPECT_EQ(info[0].baseWant.GetElement().GetAbilityName(), want.GetElement().GetAbilityName()); + EXPECT_EQ(info[0].baseWant.GetElement().GetBundleName(), want.GetElement().GetBundleName()); + EXPECT_EQ(info[0].baseWant.GetElement().GetDeviceID(), want.GetElement().GetDeviceID()); + + EXPECT_EQ(info[0].baseAbility.GetAbilityName(), want.GetElement().GetAbilityName()); + EXPECT_EQ(info[0].baseAbility.GetBundleName(), want.GetElement().GetBundleName()); + EXPECT_EQ(info[0].baseAbility.GetDeviceID(), want.GetElement().GetDeviceID()); + + EXPECT_EQ(info[0].topAbility.GetAbilityName(), want1.GetElement().GetAbilityName()); + EXPECT_EQ(info[0].topAbility.GetBundleName(), want1.GetElement().GetBundleName()); + EXPECT_EQ(info[0].topAbility.GetDeviceID(), want1.GetElement().GetDeviceID()); +} + +/* + * Feature: AbilityManagerService + * Function: RemoveStack + * SubFunction: NA + * FunctionPoints: AbilityManagerService RemoveStack + * EnvConditions: NA + * CaseDescription: 1.stackid < 0, RemoveStack failed + * 2.stackid no exist, RemoveStack failed + * 3.don't allow remove luncher mission stack + */ +HWTEST_F(AbilityManagerServiceTest, Interface_019, TestSize.Level1) +{ + EXPECT_EQ(abilityMs_->RemoveStack(-1), OHOS::ERR_INVALID_VALUE); + EXPECT_EQ(abilityMs_->RemoveStack(INT_MAX), ERR_INVALID_VALUE); + EXPECT_EQ(abilityMs_->RemoveStack(0), REMOVE_STACK_LAUNCHER_DENIED); +} + +/* + * Feature: AbilityManagerService + * Function: RemoveStack + * SubFunction: NA + * FunctionPoints: AbilityManagerService RemoveStack + * EnvConditions: NA + * CaseDescription: remove default stack success + */ +HWTEST_F(AbilityManagerServiceTest, Interface_020, TestSize.Level1) +{ + Want want; + ElementName element("device", "com.ix.music", "MusicAbility"); + want.SetElement(element); + auto result = StartAbility(want); + WaitUntilTaskFinished(); + EXPECT_EQ(OHOS::ERR_OK, result); + auto stackManage = abilityMs_->GetStackManager(); + stackManage->GetCurrentTopAbility()->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + + Want want1; + ElementName element1("device", "com.ix.music", "MusicAbility"); + want1.SetElement(element1); + auto result1 = StartAbility(want); + WaitUntilTaskFinished(); + EXPECT_EQ(OHOS::ERR_OK, result1); + + EXPECT_EQ(stackManage->GetCurrentMissionStack()->GetMissionRecordCount(), 1); + EXPECT_EQ(abilityMs_->RemoveStack(1), ERR_OK); + +} + +/* + * Feature: AbilityManagerService + * Function: ConnectAbility + * SubFunction: NA + * FunctionPoints: AbilityManagerService ConnectAbility + * EnvConditions: NA + * CaseDescription: Verify the following: + * 1.callback is nullptr, connectAbility failed + * 2.ability type is page, connectAbility failed + * 3.ability type is service and callback is not nullptr, connectAbility success + */ +HWTEST_F(AbilityManagerServiceTest, Interface_021, TestSize.Level1) +{ + Want want; + ElementName element("device", "com.ix.musicService", "MusicService"); + want.SetElement(element); + OHOS::sptr callback = new AbilityConnectCallback(); + ; + auto result = abilityMs_->ConnectAbility(want, nullptr, nullptr); + EXPECT_EQ(result, ERR_INVALID_VALUE); + + Want want1; + ElementName element1("device", "com.ix.hiMusic", "MusicAbility"); + want1.SetElement(element1); + auto result1 = abilityMs_->ConnectAbility(want1, callback, nullptr); + EXPECT_EQ(result1, TARGET_ABILITY_NOT_SERVICE); + + auto result2 = abilityMs_->ConnectAbility(want, callback, nullptr); + EXPECT_EQ(result2, ERR_OK); +} + +/* + * Feature: AbilityManagerService + * Function: DisconnectAbility + * SubFunction: NA + * FunctionPoints: AbilityManagerService DisconnectAbility + * EnvConditions: NA + * CaseDescription: Verify the following: + * 1.callback is nullptr, disconnect ability failed + * 2.connect ability is not connected, connectAbility failed + */ +HWTEST_F(AbilityManagerServiceTest, Interface_022, TestSize.Level1) +{ + Want want; + ElementName element("device", "com.ix.musicService", "MusicService"); + want.SetElement(element); + OHOS::sptr callback = new AbilityConnectCallback(); + ; + auto result = abilityMs_->ConnectAbility(want, callback, nullptr); + EXPECT_EQ(result, ERR_OK); + + auto serviceMap = abilityMs_->connectManager_->GetServiceMap(); + auto service = serviceMap.at(element.GetURI()); + service->SetAbilityState(AAFwk::AbilityState::ACTIVE); + + auto result1 = abilityMs_->DisconnectAbility(nullptr); + EXPECT_EQ(result1, ERR_INVALID_VALUE); + + auto result2 = abilityMs_->DisconnectAbility(callback); + EXPECT_EQ(result2, INVALID_CONNECTION_STATE); +} + +/* + * Feature: AbilityManagerService + * Function: ScheduleConnectAbilityDone + * SubFunction: NA + * FunctionPoints: AbilityManagerService ScheduleConnectAbilityDone + * EnvConditions: NA + * CaseDescription: Verify the following: + * 1.token is nullptr, ScheduleConnectAbilityDone failed + * 2.ability record is nullptr, ScheduleConnectAbilityDone failed + * 2.ability type is not service, ScheduleConnectAbilityDone failed + */ +HWTEST_F(AbilityManagerServiceTest, Interface_023, TestSize.Level1) +{ + Want want; + ElementName element("device", "com.ix.musicService", "MusicService"); + want.SetElement(element); + OHOS::sptr callback = new AbilityConnectCallback(); + auto result = abilityMs_->ConnectAbility(want, callback, nullptr); + WaitUntilTaskFinished(); + EXPECT_EQ(result, ERR_OK); + auto serviceMap = abilityMs_->connectManager_->GetServiceMap(); + auto service = serviceMap.at(element.GetURI()); + service->SetAbilityState(AAFwk::AbilityState::ACTIVE); + + const sptr nulltToken = nullptr; + auto result1 = abilityMs_->ScheduleConnectAbilityDone(nulltToken, callback->AsObject()); + WaitUntilTaskFinished(); + EXPECT_EQ(result1, ERR_INVALID_VALUE); + + std::shared_ptr ability = nullptr; + const sptr token = new Token(ability); + auto result2 = abilityMs_->ScheduleConnectAbilityDone(token, callback->AsObject()); + WaitUntilTaskFinished(); + EXPECT_EQ(result2, ERR_INVALID_VALUE); + + Want want1; + want1.AddEntity(Want::ENTITY_HOME); + ElementName element1("device", "com.ix.radio", "RadioAbility"); + want1.SetElement(element1); + auto result3 = StartAbility(want1); + WaitUntilTaskFinished(); + EXPECT_EQ(OHOS::ERR_OK, result3); + auto topAbility = abilityMs_->GetStackManager()->GetCurrentTopAbility(); + + auto result4 = abilityMs_->ScheduleConnectAbilityDone(topAbility->GetToken(), callback->AsObject()); + WaitUntilTaskFinished(); + EXPECT_EQ(result4, TARGET_ABILITY_NOT_SERVICE); + + auto result5 = abilityMs_->ScheduleConnectAbilityDone(service->GetToken(), callback->AsObject()); + WaitUntilTaskFinished(); + EXPECT_EQ(result5, ERR_OK); +} + +/* + * Feature: AbilityManagerService + * Function: ScheduleDisconnectAbilityDone + * SubFunction: NA + * FunctionPoints: AbilityManagerService ScheduleDisconnectAbilityDone + * EnvConditions: NA + * CaseDescription: Verify the following: + * 1.token is nullptr, ScheduleDisconnectAbilityDone failed + * 2.ability record is nullptr, ScheduleDisconnectAbilityDone failed + * 2.ability type is not service, ScheduleDisconnectAbilityDone failed + */ +HWTEST_F(AbilityManagerServiceTest, Interface_024, TestSize.Level1) +{ + Want want; + ElementName element("device", "com.ix.musicService", "MusicService"); + want.SetElement(element); + OHOS::sptr callback = new AbilityConnectCallback(); + ; + auto result = abilityMs_->ConnectAbility(want, callback, nullptr); + WaitUntilTaskFinished(); + EXPECT_EQ(result, ERR_OK); + auto serviceMap = abilityMs_->connectManager_->GetServiceMap(); + auto service = serviceMap.at(element.GetURI()); + service->SetAbilityState(AAFwk::AbilityState::ACTIVE); + + const sptr nulltToken = nullptr; + auto result1 = abilityMs_->ScheduleDisconnectAbilityDone(nulltToken); + WaitUntilTaskFinished(); + EXPECT_EQ(result1, ERR_INVALID_VALUE); + + std::shared_ptr ability = nullptr; + const sptr token = new Token(ability); + auto result2 = abilityMs_->ScheduleDisconnectAbilityDone(token); + WaitUntilTaskFinished(); + EXPECT_EQ(result2, ERR_INVALID_VALUE); + + Want want1; + want1.AddEntity(Want::ENTITY_HOME); + ElementName element1("device", "com.ix.radio", "RadioAbility"); + want1.SetElement(element1); + auto result3 = StartAbility(want1); + WaitUntilTaskFinished(); + EXPECT_EQ(OHOS::ERR_OK, result3); + auto topAbility = abilityMs_->GetStackManager()->GetCurrentTopAbility(); + + auto result4 = abilityMs_->ScheduleDisconnectAbilityDone(topAbility->GetToken()); + WaitUntilTaskFinished(); + EXPECT_EQ(result4, TARGET_ABILITY_NOT_SERVICE); + + auto result5 = abilityMs_->ScheduleDisconnectAbilityDone(service->GetToken()); + WaitUntilTaskFinished(); + EXPECT_EQ(result5, CONNECTION_NOT_EXIST); +} + +/* + * Feature: AbilityManagerService + * Function: ScheduleCommandAbilityDone + * SubFunction: NA + * FunctionPoints: AbilityManagerService ScheduleCommandAbilityDone + * EnvConditions: NA + * CaseDescription: Verify the following: + * 1.token is nullptr, ScheduleCommandAbilityDone failed + * 2.ability record is nullptr, ScheduleCommandAbilityDone failed + * 2.ability type is not service, ScheduleCommandAbilityDone failed + */ +HWTEST_F(AbilityManagerServiceTest, Interface_025, TestSize.Level1) +{ + Want want; + ElementName element("device", "com.ix.musicService", "MusicService"); + want.SetElement(element); + OHOS::sptr callback = new AbilityConnectCallback(); + ; + auto result = abilityMs_->ConnectAbility(want, callback, nullptr); + WaitUntilTaskFinished(); + EXPECT_EQ(result, ERR_OK); + auto serviceMap = abilityMs_->connectManager_->GetServiceMap(); + auto service = serviceMap.at(element.GetURI()); + service->SetAbilityState(AAFwk::AbilityState::ACTIVE); + + const sptr nulltToken = nullptr; + auto result1 = abilityMs_->ScheduleCommandAbilityDone(nulltToken); + WaitUntilTaskFinished(); + EXPECT_EQ(result1, ERR_INVALID_VALUE); + + std::shared_ptr ability = nullptr; + const sptr token = new Token(ability); + auto result2 = abilityMs_->ScheduleCommandAbilityDone(token); + WaitUntilTaskFinished(); + EXPECT_EQ(result2, ERR_INVALID_VALUE); + + Want want1; + want1.AddEntity(Want::ENTITY_HOME); + ElementName element1("device", "com.ix.radio", "RadioAbility"); + want1.SetElement(element1); + auto result3 = StartAbility(want1); + WaitUntilTaskFinished(); + EXPECT_EQ(OHOS::ERR_OK, result3); + auto topAbility = abilityMs_->GetStackManager()->GetCurrentTopAbility(); + + auto result4 = abilityMs_->ScheduleCommandAbilityDone(topAbility->GetToken()); + WaitUntilTaskFinished(); + EXPECT_EQ(result4, TARGET_ABILITY_NOT_SERVICE); + + auto result5 = abilityMs_->ScheduleCommandAbilityDone(service->GetToken()); + WaitUntilTaskFinished(); + EXPECT_EQ(result5, ERR_OK); +} + +/* + * Feature: AbilityManagerService + * Function: GetAllStackInfo + * SubFunction: NA + * FunctionPoints: AbilityManagerService GetAllStackInfo + * EnvConditions: NA + * CaseDescription: Verify getallstackenfo results + */ +HWTEST_F(AbilityManagerServiceTest, Interface_026, TestSize.Level1) +{ + EXPECT_TRUE(abilityMs_ != nullptr); + Want want; + ElementName element("device", "com.ix.hiMusic", "MusicAbility"); + want.SetElement(element); + auto result = StartAbility(want); + WaitUntilTaskFinished(); + EXPECT_EQ(OHOS::ERR_OK, result); + auto stackManager = abilityMs_->GetStackManager(); + auto topAbility = stackManager->GetCurrentTopAbility(); + topAbility->SetAbilityState(AAFwk::AbilityState::ACTIVE); + + Want want1; + ElementName element1("device", "com.ix.hiMusic", "MusicTopAbility"); + want1.SetElement(element1); + auto result1 = StartAbility(want1); + WaitUntilTaskFinished(); + EXPECT_EQ(OHOS::ERR_OK, result1); + stackManager = abilityMs_->GetStackManager(); + topAbility = stackManager->GetCurrentTopAbility(); + topAbility->SetAbilityState(AAFwk::AbilityState::ACTIVE); + + Want want2; + ElementName element2("device", "com.ix.hiMusic", "MusicTopAbility"); + want2.SetElement(element2); + auto result2 = StartAbility(want2); + WaitUntilTaskFinished(); + EXPECT_EQ(OHOS::ERR_OK, result2); + stackManager = abilityMs_->GetStackManager(); + topAbility = stackManager->GetCurrentTopAbility(); + + StackInfo info; + stackManager->GetAllStackInfo(info); + EXPECT_EQ(static_cast(info.missionStackInfos.size()), 2); +} + +/* + * Feature: AbilityManagerService + * Function: StopServiceAbility + * SubFunction: NA + * FunctionPoints: AbilityManagerService StopServiceAbility + * EnvConditions: NA + * CaseDescription: Verify StopServiceAbility results + */ +HWTEST_F(AbilityManagerServiceTest, Interface_027, TestSize.Level1) +{ + + Want want; + ElementName element("device", "com.ix.musicService", "MusicService"); + want.SetElement(element); + auto result = StartAbility(want); + WaitUntilTaskFinished(); + EXPECT_EQ(OHOS::ERR_OK, result); + auto serviceMap = abilityMs_->connectManager_->GetServiceMap(); + EXPECT_EQ(1, static_cast(serviceMap.size())); + for (auto &it : serviceMap) { + EXPECT_EQ(it.first, element.GetURI()); + } + auto service = serviceMap.at(element.GetURI()); + service->SetAbilityState(AAFwk::AbilityState::ACTIVE); + + Want want1; + ElementName element1("device", "com.ix.hiMusic", "MusicAbility"); + want1.SetElement(element1); + auto result1 = abilityMs_->StopServiceAbility(want1); + WaitUntilTaskFinished(); + EXPECT_EQ(TARGET_ABILITY_NOT_SERVICE, result1); + + auto result2 = abilityMs_->StopServiceAbility(want); + WaitUntilTaskFinished(); + EXPECT_EQ(ERR_OK, result2); +} + +/* + * Feature: AbilityManagerService + * Function: MoveMissionToTop + * SubFunction: NA + * FunctionPoints: AbilityManagerService MoveMissionToTop + * EnvConditions: NA + * CaseDescription: Verify MoveMissionToTop results + */ +HWTEST_F(AbilityManagerServiceTest, Interface_028, TestSize.Level1) +{ + + Want want; + ElementName element("device", "com.ix.hiMusic", "MusicAbility"); + want.SetElement(element); + auto result = StartAbility(want); + WaitUntilTaskFinished(); + EXPECT_EQ(OHOS::ERR_OK, result); + auto stackManager = abilityMs_->GetStackManager(); + auto topAbility = stackManager->GetCurrentTopAbility(); + auto mission = topAbility->GetMissionRecord(); + topAbility->SetAbilityState(AAFwk::AbilityState::ACTIVE); + + Want want1; + ElementName element1("device", "com.ix.hiMusic", "MusicSAbility"); + want1.SetElement(element1); + auto result1 = StartAbility(want1); + WaitUntilTaskFinished(); + EXPECT_EQ(OHOS::ERR_OK, result1); + stackManager = abilityMs_->GetStackManager(); + topAbility = stackManager->GetCurrentTopAbility(); + topAbility->SetAbilityState(AAFwk::AbilityState::ACTIVE); + + abilityMs_->MoveMissionToTop(mission->GetMissionRecordId()); + WaitUntilTaskFinished(); + stackManager = abilityMs_->GetStackManager(); + topAbility = stackManager->GetCurrentTopAbility(); + auto topMission = topAbility->GetMissionRecord(); + EXPECT_EQ(topMission, mission); +} + +/* + * Feature: AbilityManagerService + * Function: KillProcess + * SubFunction: NA + * FunctionPoints: AbilityManagerService KillProcess + * EnvConditions: NA + * CaseDescription: Verify KillProcess Failure situation + */ +HWTEST_F(AbilityManagerServiceTest, Interface_029, TestSize.Level1) +{ + + abilityMs_->currentStackManager_ = nullptr; + auto result = abilityMs_->KillProcess("bundle"); + EXPECT_EQ(ERR_OK, result); +} + +/* + * Feature: AbilityManagerService + * Function: UninstallApp + * SubFunction: NA + * FunctionPoints: AbilityManagerService UninstallApp + * EnvConditions: NA + * CaseDescription: Verify UninstallApp Failure situation + */ +HWTEST_F(AbilityManagerServiceTest, Interface_030, TestSize.Level1) +{ + + abilityMs_->currentStackManager_ = nullptr; + auto result = abilityMs_->UninstallApp("bundle"); + EXPECT_EQ(ERR_NO_INIT, result); +} + +/* + * Feature: AbilityManagerService + * Function: AcquireDataAbility + * SubFunction: NA + * FunctionPoints: AbilityManagerService AcquireDataAbility + * EnvConditions: NA + * CaseDescription: Verify function AcquireDataAbility return nullptr when AbilityManagerService not + * dataAbilityManager_. + */ +HWTEST_F(AbilityManagerServiceTest, AbilityManagerService_AcquireDataAbility_001, TestSize.Level1) +{ + OHOS::Uri dataAbilityUri("dataability:///data.bundle.DataAbility"); + + // assert ability record + EXPECT_TRUE(abilityRecord_); + + EXPECT_EQ(abilityMs_->AcquireDataAbility(dataAbilityUri, true, abilityRecord_->GetToken()), nullptr); +} + +/* + * Feature: AbilityManagerService + * Function: AcquireDataAbility + * SubFunction: NA + * FunctionPoints: AbilityManagerService AcquireDataAbility + * EnvConditions: NA + * CaseDescription: Verify function AcquireDataAbility return nullptr when AbilityManagerService not iBundleManager_. + */ +HWTEST_F(AbilityManagerServiceTest, AbilityManagerService_AcquireDataAbility_002, TestSize.Level1) +{ + OHOS::Uri dataAbilityUri("dataability:///data.bundle.DataAbility"); + // assert ability record + EXPECT_TRUE(abilityRecord_); + EXPECT_EQ(abilityMs_->AcquireDataAbility(dataAbilityUri, true, abilityRecord_->GetToken()), nullptr); +} + +/* + * Feature: AbilityManagerService + * Function: AcquireDataAbility + * SubFunction: NA + * FunctionPoints: AbilityManagerService AcquireDataAbility + * EnvConditions: NA + * CaseDescription: Verify function AcquireDataAbility return nullptr when uri not start with 'dataablity' + */ +HWTEST_F(AbilityManagerServiceTest, AbilityManagerService_AcquireDataAbility_003, TestSize.Level1) +{ + OHOS::Uri dataAbilityUri("mydataability:///data.bundle.DataAbility"); + // assert ability record + EXPECT_TRUE(abilityRecord_); + EXPECT_EQ(abilityMs_->AcquireDataAbility(dataAbilityUri, true, abilityRecord_->GetToken()), nullptr); +} + +/* + * Feature: AbilityManagerService + * Function: AcquireDataAbility + * SubFunction: NA + * FunctionPoints: AbilityManagerService AcquireDataAbility + * EnvConditions: NA + * CaseDescription: Verify function AcquireDataAbility return nullptr when uri start with empty + */ +HWTEST_F(AbilityManagerServiceTest, AbilityManagerService_AcquireDataAbility_004, TestSize.Level1) +{ + OHOS::Uri dataAbilityUri("dataability://"); + EXPECT_EQ(abilityMs_->AcquireDataAbility(dataAbilityUri, true, abilityRecord_->GetToken()), nullptr); +} + +/* + * Feature: AbilityManagerService + * Function: AcquireDataAbility + * SubFunction: NA + * FunctionPoints: AbilityManagerService AcquireDataAbility + * EnvConditions: NA + * CaseDescription: Verify function AcquireDataAbility return nullptr when QueryAbilityInfoByUri false. + */ +HWTEST_F(AbilityManagerServiceTest, AbilityManagerService_AcquireDataAbility_005, TestSize.Level1) +{ + OHOS::Uri dataAbilityUri("dataability:///data.bundle.DataAbility"); + EXPECT_EQ(abilityMs_->AcquireDataAbility(dataAbilityUri, true, abilityRecord_->GetToken()), nullptr); +} + +/* + * Feature: AbilityManagerService + * Function: AcquireDataAbility + * SubFunction: NA + * FunctionPoints: AbilityManagerService AcquireDataAbility + * EnvConditions: NA + * CaseDescription: Verify function AcquireDataAbility return nullptr when appInfo name empty + */ +HWTEST_F(AbilityManagerServiceTest, AbilityManagerService_AcquireDataAbility_006, TestSize.Level1) +{ + OHOS::Uri dataAbilityUri("dataability:///data.bundle.DataAbility"); + + if (abilityRecord_ == nullptr) { + abilityRequest_.appInfo.bundleName = "data.client.bundle"; + abilityRequest_.abilityInfo.name = "ClientAbility"; + abilityRequest_.abilityInfo.type = AbilityType::DATA; + abilityRecord_ = AbilityRecord::CreateAbilityRecord(abilityRequest_); + } + + EXPECT_EQ(abilityMs_->AcquireDataAbility(dataAbilityUri, true, abilityRecord_->GetToken()), nullptr); +} + +/* + * Feature: AbilityManagerService + * Function: ReleaseDataAbility + * SubFunction: NA + * FunctionPoints: AbilityManagerService ReleaseDataAbility + * EnvConditions: NA + * CaseDescription: Verify function ReleaseDataAbility + * return nullptr when AbilityManagerService not dataAbilityManager_. + */ +HWTEST_F(AbilityManagerServiceTest, AbilityManagerService_ReleaseDataAbility_001, TestSize.Level1) +{ + // assert ability record + EXPECT_TRUE(abilityRecord_); + EXPECT_EQ(abilityMs_->ReleaseDataAbility(nullptr, nullptr), OHOS::ERR_INVALID_STATE); +} + +/* + * Feature: AbilityManagerService + * Function: ReleaseDataAbility + * SubFunction: NA + * FunctionPoints: AbilityManagerService ReleaseDataAbility + * EnvConditions: NA + * CaseDescription: Verify function ReleaseDataAbility + * return nullptr when AbilityManagerService not dataAbilityManager_. + */ +HWTEST_F(AbilityManagerServiceTest, TerminateAbilityResult_001, TestSize.Level1) +{ + sptr token = nullptr; + auto result1 = abilityMs_->TerminateAbilityResult(token, -1); + WaitUntilTaskFinished(); + EXPECT_EQ(ERR_INVALID_VALUE, result1); + + // not service aa + Want want; + ElementName element("device", "com.ix.hiMusic", "MusicAbility"); + want.SetElement(element); + auto result = StartAbility(want); + WaitUntilTaskFinished(); + EXPECT_EQ(OHOS::ERR_OK, result); + auto stackManager = abilityMs_->GetStackManager(); + auto topAbility = stackManager->GetCurrentTopAbility(); + auto token1 = topAbility->GetToken(); + topAbility->SetAbilityState(AAFwk::AbilityState::ACTIVE); + + auto result2 = abilityMs_->TerminateAbilityResult(token1, topAbility->GetStartId()); + WaitUntilTaskFinished(); + EXPECT_EQ(TARGET_ABILITY_NOT_SERVICE, result2); + + // an service aa + Want want2; + ElementName element2("device", "com.ix.musicService", "MusicService"); + want2.SetElement(element2); + result = StartAbility(want2); + WaitUntilTaskFinished(); + EXPECT_EQ(OHOS::ERR_OK, result); + stackManager = abilityMs_->GetStackManager(); + auto topAbility2 = stackManager->GetCurrentTopAbility(); + auto token2 = topAbility->GetToken(); + topAbility2->SetAbilityState(AAFwk::AbilityState::ACTIVE); + + auto result3 = abilityMs_->TerminateAbilityResult(token2, -1); + EXPECT_NE(OHOS::ERR_OK, result3); + + // current stack top is com.ix.hiMusic + auto stackManagerAfter = abilityMs_->GetStackManager(); + auto topAbilityAfter = stackManagerAfter->GetCurrentTopAbility(); + Want want3 = topAbilityAfter->GetWant(); + EXPECT_EQ(want3.GetElement().GetURI(), want.GetElement().GetURI()); +} + +/* + * Feature: AbilityManagerService + * Function: ReleaseDataAbility + * SubFunction: NA + * FunctionPoints: AbilityManagerService ReleaseDataAbility + * EnvConditions: NA + * CaseDescription: Verify function ReleaseDataAbility + * return nullptr when AbilityManagerService not dataAbilityManager_. + */ +HWTEST_F(AbilityManagerServiceTest, startAbility_001, TestSize.Level1) +{ + // first run a service aa + Want want; + ElementName element("device", "com.ix.musicService", "MusicService"); + want.SetElement(element); + auto result = StartAbility(want); + EXPECT_EQ(OHOS::ERR_OK, result); + auto stackManager = abilityMs_->GetStackManager(); + auto topAbility = stackManager->GetCurrentTopAbility(); + + sptr token = nullptr; + if (topAbility) { + topAbility->SetAbilityState(AAFwk::AbilityState::ACTIVE); + token = topAbility->GetToken(); + } + + // start other aa + Want want1; + ElementName element1("device", "com.ix.hiMusic", "MusicAbility"); + want.SetElement(element1); + auto result1 = abilityMs_->StartAbility(want, token); + WaitUntilTaskFinished(); + EXPECT_EQ(OHOS::ERR_OK, result1); +} + +/* + * Feature: AbilityManagerService + * Function: startAbility + * SubFunction: NA + * FunctionPoints: AbilityManagerService startAbility + * EnvConditions: NA + * CaseDescription: Verify function startAbility + * return nullptr when AbilityManagerService not dataAbilityManager_. + */ +HWTEST_F(AbilityManagerServiceTest, startAbility_002, TestSize.Level1) +{ + // first run a service aa + Want want; + ElementName element("device", "com.ix.musicService", "MusicService"); + want.SetElement(element); + auto result = StartAbility(want); + EXPECT_EQ(OHOS::ERR_OK, result); + auto stackManager = abilityMs_->GetStackManager(); + auto topAbility = stackManager->GetCurrentTopAbility(); + + sptr token = nullptr; + if (topAbility) { + topAbility->SetAbilityState(AAFwk::AbilityState::ACTIVE); + token = topAbility->GetToken(); + } + + // start self + auto result1 = abilityMs_->StartAbility(want, token); + EXPECT_NE(OHOS::ERR_OK, result1); +} + +/* + * Feature: AbilityManagerService + * Function: startAbility + * SubFunction: NA + * FunctionPoints: AbilityManagerService startAbility + * EnvConditions: NA + * CaseDescription: Verify function startAbility + * return nullptr when AbilityManagerService not dataAbilityManager_. + */ +HWTEST_F(AbilityManagerServiceTest, startAbility_003, TestSize.Level1) +{ + // first run a service aa + Want want; + ElementName element("device", "com.ix.musicService", "MusicService"); + want.SetElement(element); + auto result = StartAbility(want); + EXPECT_EQ(OHOS::ERR_OK, result); + auto stackManager = abilityMs_->GetStackManager(); + auto topAbility = stackManager->GetCurrentTopAbility(); + sptr token = nullptr; + if (topAbility) { + topAbility->SetAbilityState(AAFwk::AbilityState::ACTIVE); + token = topAbility->GetToken(); + } + + // start a date aa + Want want1; + ElementName element1("device", "com.ix.hiData", "DataAbility"); + want.SetElement(element1); + auto result1 = abilityMs_->StartAbility(want1, token); + EXPECT_EQ(RESOLVE_ABILITY_ERR, result1); +} + +/* + * Feature: AbilityManagerService + * Function: startAbility + * SubFunction: NA + * FunctionPoints: AbilityManagerService startAbility + * EnvConditions: NA + * CaseDescription: Verify function startAbility + * return nullptr when AbilityManagerService not dataAbilityManager_. + */ +HWTEST_F(AbilityManagerServiceTest, startAbility_004, TestSize.Level1) +{ + // run a page aa + Want want; + ElementName element("device", "com.ix.hiworld", "WorldService"); + want.SetElement(element); + auto result = StartAbility(want); + EXPECT_EQ(OHOS::ERR_OK, result); + auto stackManager = abilityMs_->GetStackManager(); + auto topAbility = stackManager->GetCurrentTopAbility(); + sptr token = nullptr; + if (topAbility) { + topAbility->SetAbilityState(AAFwk::AbilityState::ACTIVE); + token = topAbility->GetToken(); + } + + // start a page aa + Want want1; + ElementName element1("device", "com.ix.hiMusic", "hiMusic"); + want1.SetElement(element1); + auto result1 = abilityMs_->StartAbility(want1, token); + EXPECT_EQ(OHOS::ERR_OK, result1); + + // current stack top is com.ix.hiMusic + auto stackManagerAfter = abilityMs_->GetStackManager(); + auto topAbilityAfter = stackManagerAfter->GetCurrentTopAbility(); + Want want2 = topAbilityAfter->GetWant(); + EXPECT_EQ(want1.GetElement().GetURI(), want2.GetElement().GetURI()); +} + +/* + * Feature: AbilityManagerService + * Function: startAbility + * SubFunction: NA + * FunctionPoints: AbilityManagerService startAbility + * EnvConditions: NA + * CaseDescription: Verify function startAbility + * return nullptr when AbilityManagerService not dataAbilityManager_. + */ +HWTEST_F(AbilityManagerServiceTest, systemDialog_001, TestSize.Level1) +{ + Want want; + ElementName element("device", "com.ix.hiworld", "WorldService"); + want.SetElement(element); + auto result = StartAbility(want); + WaitUntilTaskFinished(); + EXPECT_EQ(OHOS::ERR_OK, result); + auto stackManager = abilityMs_->GetStackManager(); + auto topAbility = stackManager->GetCurrentTopAbility(); + auto token = topAbility->GetToken(); + topAbility->SetAbilityState(AAFwk::AbilityState::ACTIVE); + + // statrt a dialog + Want want1; + ElementName elementdialog1("device", AbilityConfig::SYSTEM_UI_BUNDLE_NAME, AbilityConfig::SYSTEM_DIALOG_NAME); + want1.SetElement(elementdialog1); + auto result1 = abilityMs_->StartAbility(want1, token); + WaitUntilTaskFinished(); + EXPECT_EQ(OHOS::ERR_OK, result1); + auto dialogAbility = stackManager->GetCurrentTopAbility(); + auto dialogtoken = topAbility->GetToken(); + + // current stack top is dialog + auto stackManagerAfter = abilityMs_->GetStackManager(); + auto topAbilityAfter = stackManagerAfter->GetCurrentTopAbility(); + Want want2 = topAbilityAfter->GetWant(); + EXPECT_EQ(want1.GetElement().GetURI(), want2.GetElement().GetURI()); + + auto dialogRecord = stackManager->GetAbilityRecordByToken(dialogtoken); + EXPECT_EQ(dialogRecord->GetAbilityState(), AAFwk::AbilityState::INACTIVATING); + + // start other dialog + Want want3; + ElementName elementdialog2("device2", AbilityConfig::SYSTEM_UI_BUNDLE_NAME, AbilityConfig::SYSTEM_DIALOG_NAME); + want3.SetElement(elementdialog2); + auto result2 = abilityMs_->StartAbility(want3); + + EXPECT_NE(OHOS::ERR_OK, result2); + auto dialogAbility2 = stackManager->GetCurrentTopAbility(); + auto dialogtoken2 = dialogAbility2->GetToken(); + EXPECT_EQ(dialogAbility2->GetAbilityState(), AAFwk::AbilityState::INITIAL); + + // start a luncher aa,should be fail + Want wantLuncher; + ElementName elementLun("device", "com.ix.hiworld", "WorldService"); + wantLuncher.SetElement(elementLun); + auto result3 = abilityMs_->StartAbility(wantLuncher); + // should be fail + EXPECT_NE(OHOS::ERR_OK, result3); + auto topAbilityLun = stackManager->GetCurrentTopAbility(); + EXPECT_EQ(topAbilityLun->GetStartId(), dialogAbility2->GetStartId()); +} + +/* + * Feature: AbilityManagerService + * Function: startAbility + * SubFunction: NA + * FunctionPoints: AbilityManagerService startAbility + * EnvConditions: NA + * CaseDescription: Verify function startAbility + * return nullptr when AbilityManagerService not dataAbilityManager_. + */ +HWTEST_F(AbilityManagerServiceTest, systemDialog_002, TestSize.Level1) +{ + // start dialog when device get up + Want want; + ElementName elementdialog("device", AbilityConfig::SYSTEM_UI_BUNDLE_NAME, AbilityConfig::SYSTEM_DIALOG_NAME); + want.SetElement(elementdialog); + auto result = StartAbility(want); + EXPECT_EQ(OHOS::ERR_OK, result); + auto stackManager = abilityMs_->GetStackManager(); + auto dialogAbility = stackManager->GetCurrentTopAbility(); + auto dialogtoken = dialogAbility->GetToken(); + EXPECT_TRUE(dialogAbility->GetAbilityInfo().bundleName == AbilityConfig::SYSTEM_UI_BUNDLE_NAME); + + // other same aa + Want want1; + ElementName elementdialog1("device", AbilityConfig::SYSTEM_UI_BUNDLE_NAME, AbilityConfig::SYSTEM_DIALOG_NAME); + want1.SetElement(elementdialog1); + auto result1 = StartAbility(want1); + EXPECT_EQ(OHOS::ERR_OK, result1); + + // start a page aa, waiting + Want want2; + ElementName elementdialog2("device", "com.ix.hiMusic", "hiMusic"); + want2.SetElement(elementdialog2); + auto result2 = StartAbility(want2); + EXPECT_EQ(OHOS::ERR_OK, result2); + auto MusicAbility = stackManager->GetCurrentTopAbility(); + EXPECT_EQ(MusicAbility->GetAbilityInfo().bundleName, "com.ix.hiMusic"); +} + +/* + * Feature: AbilityManagerService + * Function: HandleLoadTimeOut + * SubFunction: NA + * FunctionPoints: AbilityManagerService HandleLoadTimeOut + * EnvConditions: NA + * CaseDescription: Verify function HandleLoadTimeOut + * When you start systemui, when HandleLoadTimeOut called, restart systemui + */ +HWTEST_F(AbilityManagerServiceTest, handleloadtimeout_001, TestSize.Level1) +{ + // start SYSTEM_UI_STATUS_BAR when device get up + Want want; + ElementName elementbar("device", AbilityConfig::SYSTEM_UI_BUNDLE_NAME, AbilityConfig::SYSTEM_UI_STATUS_BAR); + want.SetElement(elementbar); + auto result = StartAbility(want); + EXPECT_EQ(OHOS::ERR_OK, result); + auto stackManager = abilityMs_->systemAppManager_; + auto barAbility = stackManager->GetCurrentTopAbility(); + AbilityRecordInfo barAbilityInfo; + barAbility->GetAbilityRecordInfo(barAbilityInfo); + auto dialogtoken = barAbility->GetToken(); + OHOS::sptr scheduler = new AbilityScheduler(); + EXPECT_EQ(abilityMs_->AttachAbilityThread(scheduler, dialogtoken), OHOS::ERR_OK); + EXPECT_TRUE(barAbility->GetAbilityInfo().bundleName == AbilityConfig::SYSTEM_UI_BUNDLE_NAME); + abilityMs_->HandleLoadTimeOut(barAbility->GetEventId()); + WaitUntilTaskFinished(); + auto newStackManager = abilityMs_->systemAppManager_; + auto newBarAbility = newStackManager->GetCurrentTopAbility(); + AbilityRecordInfo newAbilityInfo; + newBarAbility->GetAbilityRecordInfo(newAbilityInfo); + EXPECT_TRUE(newBarAbility->GetAbilityInfo().bundleName == AbilityConfig::SYSTEM_UI_BUNDLE_NAME); + EXPECT_NE(barAbilityInfo.id, newAbilityInfo.id); +} + +/* + * Feature: AbilityManagerService + * Function: HandleLoadTimeOut + * SubFunction: NA + * FunctionPoints: AbilityManagerService HandleLoadTimeOut + * EnvConditions: NA + * CaseDescription: Verify function HandleLoadTimeOut + * When you start systemui, when HandleLoadTimeOut called, restart systemui + */ +HWTEST_F(AbilityManagerServiceTest, handleloadtimeout_002, TestSize.Level1) +{ + // start SYSTEM_UI_NAVIGATION_BAR when device get up + Want want; + ElementName elementdialog("device", AbilityConfig::SYSTEM_UI_BUNDLE_NAME, AbilityConfig::SYSTEM_UI_NAVIGATION_BAR); + want.SetElement(elementdialog); + auto result = StartAbility(want); + EXPECT_EQ(OHOS::ERR_OK, result); + auto stackManager = abilityMs_->systemAppManager_; + auto navigationAbility = stackManager->GetCurrentTopAbility(); + auto dialogtoken = navigationAbility->GetToken(); + OHOS::sptr scheduler = new AbilityScheduler(); + EXPECT_EQ(abilityMs_->AttachAbilityThread(scheduler, dialogtoken), OHOS::ERR_OK); + EXPECT_TRUE(navigationAbility->GetAbilityInfo().bundleName == AbilityConfig::SYSTEM_UI_BUNDLE_NAME); + abilityMs_->HandleLoadTimeOut(navigationAbility->GetEventId()); + auto newStackManager = abilityMs_->systemAppManager_; + auto newNavigationAbility = newStackManager->GetCurrentTopAbility(); + EXPECT_TRUE(newNavigationAbility->GetAbilityInfo().bundleName == AbilityConfig::SYSTEM_UI_BUNDLE_NAME); + EXPECT_NE(navigationAbility, newNavigationAbility); +} + +/* + * Feature: AbilityManagerService + * Function: HandleLoadTimeOut + * SubFunction: NA + * FunctionPoints: AbilityManagerService HandleLoadTimeOut + * EnvConditions: NA + * CaseDescription: Verify function HandleLoadTimeOut + * When you start systemui, when timeout ,the HandleLoadTimeOut called, restart systemui + */ +HWTEST_F(AbilityManagerServiceTest, handleloadtimeout_003, TestSize.Level1) +{ + // start SYSTEM_UI_STATUS_BAR when device get up + Want want; + ElementName elementbar("device", AbilityConfig::SYSTEM_UI_BUNDLE_NAME, AbilityConfig::SYSTEM_UI_STATUS_BAR); + want.SetElement(elementbar); + auto result = StartAbility(want); + EXPECT_EQ(OHOS::ERR_OK, result); + auto stackManager = abilityMs_->systemAppManager_; + auto barAbility = stackManager->GetCurrentTopAbility(); + AbilityRecordInfo barAbilityInfo; + barAbility->GetAbilityRecordInfo(barAbilityInfo); + EXPECT_TRUE(barAbility->GetAbilityInfo().bundleName == AbilityConfig::SYSTEM_UI_BUNDLE_NAME); + abilityMs_->HandleLoadTimeOut(barAbility->GetEventId()); + auto newStackManager = abilityMs_->systemAppManager_; + auto newBarAbility = newStackManager->GetCurrentTopAbility(); + AbilityRecordInfo newAbilityInfo; + newBarAbility->GetAbilityRecordInfo(newAbilityInfo); + EXPECT_TRUE(newBarAbility->GetAbilityInfo().bundleName == AbilityConfig::SYSTEM_UI_BUNDLE_NAME); + EXPECT_NE(barAbilityInfo.id, newAbilityInfo.id); +} + +/* + * Feature: AbilityManagerService + * Function: HandleLoadTimeOut + * SubFunction: NA + * FunctionPoints: AbilityManagerService HandleLoadTimeOut + * EnvConditions: NA + * CaseDescription: Verify function HandleLoadTimeOut + * When you start systemui, when timeout ,the HandleLoadTimeOut called, restart systemui + */ +HWTEST_F(AbilityManagerServiceTest, handleloadtimeout_004, TestSize.Level1) +{ + // start SYSTEM_UI_NAVIGATION_BAR when device get up + Want want; + ElementName elementbar("device", AbilityConfig::SYSTEM_UI_BUNDLE_NAME, AbilityConfig::SYSTEM_UI_NAVIGATION_BAR); + want.SetElement(elementbar); + auto result = StartAbility(want); + EXPECT_EQ(OHOS::ERR_OK, result); + auto stackManager = abilityMs_->systemAppManager_; + auto navigationAbility = stackManager->GetCurrentTopAbility(); + EXPECT_TRUE(navigationAbility->GetAbilityInfo().bundleName == AbilityConfig::SYSTEM_UI_BUNDLE_NAME); + abilityMs_->HandleLoadTimeOut(navigationAbility->GetEventId()); + auto newStackManager = abilityMs_->systemAppManager_; + auto newNavigationAbility = newStackManager->GetCurrentTopAbility(); + EXPECT_TRUE(newNavigationAbility->GetAbilityInfo().bundleName == AbilityConfig::SYSTEM_UI_BUNDLE_NAME); + EXPECT_NE(navigationAbility, newNavigationAbility); +} + +/* + * Feature: AbilityManagerService + * Function: HandleLoadTimeOut + * SubFunction: NA + * FunctionPoints: AbilityManagerService HandleLoadTimeOut + * EnvConditions: NA + * CaseDescription: Verify function HandleLoadTimeOut + * When you start systemui, when HandleLoadTimeOut called, restart systemui + */ +HWTEST_F(AbilityManagerServiceTest, handleloadtimeout_005, TestSize.Level1) +{ + // start SYSTEM_UI_STATUS_BAR when device get up + Want want; + ElementName elementbar("device", AbilityConfig::SYSTEM_UI_BUNDLE_NAME, AbilityConfig::SYSTEM_UI_STATUS_BAR); + want.SetElement(elementbar); + auto result = StartAbility(want); + EXPECT_EQ(OHOS::ERR_OK, result); + auto stackManager = abilityMs_->systemAppManager_; + auto barAbility = stackManager->GetCurrentTopAbility(); + auto bartoken = barAbility->GetToken(); + OHOS::sptr scheduler = new AbilityScheduler(); + EXPECT_EQ(abilityMs_->AttachAbilityThread(scheduler, bartoken), OHOS::ERR_OK); + EXPECT_TRUE(barAbility->GetAbilityInfo().bundleName == AbilityConfig::SYSTEM_UI_BUNDLE_NAME); + auto newStackManager = abilityMs_->systemAppManager_; + auto newBarAbility = newStackManager->GetCurrentTopAbility(); + EXPECT_TRUE(newBarAbility->GetAbilityInfo().bundleName == AbilityConfig::SYSTEM_UI_BUNDLE_NAME); + EXPECT_EQ(barAbility, newBarAbility); +} + +/* + * Feature: AbilityManagerService + * Function: HandleLoadTimeOut + * SubFunction: NA + * FunctionPoints: AbilityManagerService HandleLoadTimeOut + * EnvConditions: NA + * CaseDescription: Verify function HandleLoadTimeOut + * When you start systemui, when HandleLoadTimeOut called, restart systemui + */ +HWTEST_F(AbilityManagerServiceTest, handleloadtimeout_006, TestSize.Level1) +{ + // start SYSTEM_UI_NAVIGATION_BAR when device get up + Want want; + ElementName elementbar("device", AbilityConfig::SYSTEM_UI_BUNDLE_NAME, AbilityConfig::SYSTEM_UI_NAVIGATION_BAR); + want.SetElement(elementbar); + auto result = StartAbility(want); + EXPECT_EQ(OHOS::ERR_OK, result); + auto stackManager = abilityMs_->systemAppManager_; + auto navigationAbility = stackManager->GetCurrentTopAbility(); + auto navigationtoken = navigationAbility->GetToken(); + OHOS::sptr scheduler = new AbilityScheduler(); + EXPECT_EQ(abilityMs_->AttachAbilityThread(scheduler, navigationtoken), OHOS::ERR_OK); + EXPECT_TRUE(navigationAbility->GetAbilityInfo().bundleName == AbilityConfig::SYSTEM_UI_BUNDLE_NAME); + auto newStackManager = abilityMs_->systemAppManager_; + auto newNavigationAbility = newStackManager->GetCurrentTopAbility(); + EXPECT_TRUE(newNavigationAbility->GetAbilityInfo().bundleName == AbilityConfig::SYSTEM_UI_BUNDLE_NAME); + EXPECT_EQ(navigationAbility, newNavigationAbility); +} + +/* + * Feature: AbilityManagerService + * Function: HandleLoadTimeOut + * SubFunction: NA + * FunctionPoints: AbilityManagerService HandleLoadTimeOut + * EnvConditions: NA + * CaseDescription: Verify function HandleLoadTimeOut + * When you start page ability, when HandleLoadTimeOut called, restart previous ability + */ +HWTEST_F(AbilityManagerServiceTest, handleloadtimeout_007, TestSize.Level1) +{ + Want want; + ElementName element("device", "com.ix.hiMusic", "MusicAbility"); + want.SetElement(element); + auto result = StartAbility(want); + EXPECT_EQ(OHOS::ERR_OK, result); + auto stackManager = abilityMs_->GetStackManager(); + auto ability = stackManager->GetCurrentTopAbility(); + auto abilityToken = ability->GetToken(); + OHOS::sptr scheduler = new AbilityScheduler(); + EXPECT_EQ(abilityMs_->AttachAbilityThread(scheduler, abilityToken), OHOS::ERR_OK); + EXPECT_TRUE(ability->GetAbilityInfo().bundleName == "com.ix.hiMusic"); + ElementName elementTv("device", "com.ix.hiTv", "TvAbility"); + want.SetElement(elementTv); + auto resultTv = StartAbility(want); + EXPECT_EQ(OHOS::ERR_OK, resultTv); + auto stackManagerTv = abilityMs_->GetStackManager(); + auto abilityTv = stackManagerTv->GetCurrentTopAbility(); + abilityMs_->HandleLoadTimeOut(abilityTv->GetEventId()); + auto newStackManager = abilityMs_->GetStackManager(); + auto newAbility = newStackManager->GetCurrentTopAbility(); + EXPECT_TRUE(newAbility->GetAbilityInfo().bundleName == "com.ix.hiMusic"); +} + +/* + * Feature: AbilityManagerService + * Function: HandleLoadTimeOut + * SubFunction: NA + * FunctionPoints: AbilityManagerService HandleLoadTimeOut + * EnvConditions: NA + * CaseDescription: Verify function HandleLoadTimeOut + * When you start page ability, when HandleLoadTimeOut called, restart previous ability + */ +HWTEST_F(AbilityManagerServiceTest, handleloadtimeout_008, TestSize.Level1) +{ + Want want; + ElementName element("device", COM_IX_HIWORLD, "helloAbility"); + want.SetElement(element); + auto result = StartAbility(want); + EXPECT_EQ(OHOS::ERR_OK, result); + auto stackManager = abilityMs_->GetStackManager(); + auto ability = stackManager->GetCurrentTopAbility(); + auto abilityToken = ability->GetToken(); + OHOS::sptr scheduler = new AbilityScheduler(); + EXPECT_EQ(abilityMs_->AttachAbilityThread(scheduler, abilityToken), OHOS::ERR_OK); + EXPECT_TRUE(ability->GetAbilityInfo().bundleName == COM_IX_HIWORLD); + ElementName elementTv("device", "com.ix.hiTv", "TvAbility"); + want.SetElement(elementTv); + auto resultTv = StartAbility(want); + EXPECT_EQ(OHOS::ERR_OK, resultTv); + auto stackManagerTv = abilityMs_->GetStackManager(); + auto abilityTv = stackManagerTv->GetCurrentTopAbility(); + abilityMs_->HandleLoadTimeOut(abilityTv->GetEventId()); + auto newStackManager = abilityMs_->GetStackManager(); + auto newAbility = newStackManager->GetCurrentTopAbility(); + EXPECT_TRUE(newAbility->GetAbilityInfo().bundleName == COM_IX_HIWORLD); +} + +/* + * Feature: AbilityManagerService + * Function: HandleLoadTimeOut + * SubFunction: NA + * FunctionPoints: AbilityManagerService HandleLoadTimeOut + * EnvConditions: NA + * CaseDescription: Verify function HandleLoadTimeOut + * When you start page ability, when Activate timeout, the HandleLoadTimeOut called, restart launch + */ +HWTEST_F(AbilityManagerServiceTest, handleloadtimeout_009, TestSize.Level1) +{ + Want want; + ElementName element("device", COM_IX_HIWORLD, "helloAbility"); + want.SetElement(element); + auto result = StartAbility(want); + EXPECT_EQ(OHOS::ERR_OK, result); + auto stackManager = abilityMs_->GetStackManager(); + auto ability = stackManager->GetCurrentTopAbility(); + auto abilityToken = ability->GetToken(); + OHOS::sptr scheduler = new AbilityScheduler(); + EXPECT_EQ(abilityMs_->AttachAbilityThread(scheduler, abilityToken), OHOS::ERR_OK); + EXPECT_TRUE(ability->GetAbilityInfo().bundleName == COM_IX_HIWORLD); + ElementName elementTv("device", "com.ix.hiTv", "TvAbility"); + want.SetElement(elementTv); + auto resultTv = StartAbility(want); + EXPECT_EQ(OHOS::ERR_OK, resultTv); + auto stackManagerTv = abilityMs_->GetStackManager(); + auto abilityTv = stackManagerTv->GetCurrentTopAbility(); + auto abilityTokenTv = abilityTv->GetToken(); + OHOS::sptr newScheduler = new AbilityScheduler(); + EXPECT_EQ(abilityMs_->AttachAbilityThread(newScheduler, abilityTokenTv), OHOS::ERR_OK); + abilityTv->Activate(); + abilityMs_->HandleLoadTimeOut(abilityTv->GetEventId()); + auto newStackManager = abilityMs_->GetStackManager(); + auto newAbility = newStackManager->GetCurrentTopAbility(); + EXPECT_TRUE(newAbility->GetAbilityInfo().bundleName != "com.ix.hiTv"); +} + +/* + * Feature: AbilityManagerService + * Function: HandleLoadTimeOut + * SubFunction: NA + * FunctionPoints: AbilityManagerService HandleLoadTimeOut + * EnvConditions: NA + * CaseDescription: Verify function HandleLoadTimeOut + * When you start page ability, when InActivate timeout, the HandleLoadTimeOut called, restart launch + */ +HWTEST_F(AbilityManagerServiceTest, handleloadtimeout_010, TestSize.Level1) +{ + Want want; + ElementName element("device", COM_IX_HIWORLD, "helloAbility"); + want.SetElement(element); + auto result = StartAbility(want); + EXPECT_EQ(OHOS::ERR_OK, result); + auto stackManager = abilityMs_->GetStackManager(); + auto ability = stackManager->GetCurrentTopAbility(); + auto abilityToken = ability->GetToken(); + OHOS::sptr scheduler = new AbilityScheduler(); + EXPECT_EQ(abilityMs_->AttachAbilityThread(scheduler, abilityToken), OHOS::ERR_OK); + EXPECT_TRUE(ability->GetAbilityInfo().bundleName == COM_IX_HIWORLD); + ElementName elementTv("device", "com.ix.hiTv", "TvAbility"); + want.SetElement(elementTv); + auto resultTv = StartAbility(want); + EXPECT_EQ(OHOS::ERR_OK, resultTv); + auto stackManagerTv = abilityMs_->GetStackManager(); + auto abilityTv = stackManagerTv->GetCurrentTopAbility(); + auto abilityTokenTv = abilityTv->GetToken(); + OHOS::sptr newScheduler = new AbilityScheduler(); + EXPECT_EQ(abilityMs_->AttachAbilityThread(newScheduler, abilityTokenTv), OHOS::ERR_OK); + abilityTv->Inactivate(); + abilityMs_->HandleLoadTimeOut(abilityTv->GetEventId()); + auto newStackManager = abilityMs_->GetStackManager(); + auto newAbility = newStackManager->GetCurrentTopAbility(); + EXPECT_TRUE(newAbility->GetAbilityInfo().bundleName != "com.ix.hiTv"); +} + +/* + * Feature: AbilityManagerService + * Function: HandleLoadTimeOut + * SubFunction: NA + * FunctionPoints: AbilityManagerService HandleLoadTimeOut + * EnvConditions: NA + * CaseDescription: Verify function HandleLoadTimeOut + * When you start page ability, when HandleLoadTimeOut called,the parameter is the maximum,nothing is done. + */ +HWTEST_F(AbilityManagerServiceTest, handleloadtimeout_011, TestSize.Level1) +{ + Want want; + ElementName element("device", "com.ix.hiMusic", "MusicAbility"); + want.SetElement(element); + auto result = StartAbility(want); + EXPECT_EQ(OHOS::ERR_OK, result); + auto stackManager = abilityMs_->GetStackManager(); + auto ability = stackManager->GetCurrentTopAbility(); + auto abilityToken = ability->GetToken(); + OHOS::sptr scheduler = new AbilityScheduler(); + EXPECT_EQ(abilityMs_->AttachAbilityThread(scheduler, abilityToken), OHOS::ERR_OK); + EXPECT_TRUE(ability->GetAbilityInfo().bundleName == "com.ix.hiMusic"); + ElementName elementTv("device", "com.ix.hiTv", "TvAbility"); + want.SetElement(elementTv); + auto resultTv = StartAbility(want); + EXPECT_EQ(OHOS::ERR_OK, resultTv); + auto stackManagerTv = abilityMs_->GetStackManager(); + auto abilityTv = stackManagerTv->GetCurrentTopAbility(); + abilityMs_->HandleLoadTimeOut(INT32_MAX); + auto newStackManager = abilityMs_->GetStackManager(); + auto newAbility = newStackManager->GetCurrentTopAbility(); + EXPECT_TRUE(newAbility->GetAbilityInfo().bundleName == "com.ix.hiTv"); + EXPECT_NE(ability, newAbility); +} + +/* + * Feature: AbilityManagerService + * Function: HandleLoadTimeOut + * SubFunction: NA + * FunctionPoints: AbilityManagerService HandleLoadTimeOut + * EnvConditions: NA + * CaseDescription: Verify function HandleLoadTimeOut + * When you start page ability, when HandleLoadTimeOut called,the parameter is the minimum,nothing is done. + */ +HWTEST_F(AbilityManagerServiceTest, handleloadtimeout_012, TestSize.Level1) +{ + Want want; + ElementName element("device", "com.ix.hiMusic", "MusicAbility"); + want.SetElement(element); + auto result = StartAbility(want); + EXPECT_EQ(OHOS::ERR_OK, result); + auto stackManager = abilityMs_->GetStackManager(); + auto ability = stackManager->GetCurrentTopAbility(); + auto abilityToken = ability->GetToken(); + OHOS::sptr scheduler = new AbilityScheduler(); + EXPECT_EQ(abilityMs_->AttachAbilityThread(scheduler, abilityToken), OHOS::ERR_OK); + EXPECT_TRUE(ability->GetAbilityInfo().bundleName == "com.ix.hiMusic"); + ElementName elementTv("device", "com.ix.hiTv", "TvAbility"); + want.SetElement(elementTv); + auto resultTv = StartAbility(want); + EXPECT_EQ(OHOS::ERR_OK, resultTv); + auto stackManagerTv = abilityMs_->GetStackManager(); + auto abilityTv = stackManagerTv->GetCurrentTopAbility(); + abilityMs_->HandleLoadTimeOut(INT32_MIN); + auto newStackManager = abilityMs_->GetStackManager(); + auto newAbility = newStackManager->GetCurrentTopAbility(); + EXPECT_TRUE(newAbility->GetAbilityInfo().bundleName == "com.ix.hiTv"); + EXPECT_NE(ability, newAbility); +} + +/* + * Feature: AbilityManagerService + * Function: IsFirstInMission + * SubFunction: NA + * FunctionPoints: AbilityManagerService IsFirstInMission + * EnvConditions: NA + * CaseDescription: Verify function IsFirstInMission + * IsFirstInMission parameter + */ +HWTEST_F(AbilityManagerServiceTest, isfirstinmission_001, TestSize.Level1) +{ + auto result = abilityMs_->IsFirstInMission(nullptr); + EXPECT_EQ(result, false); +} + +/* + * Feature: AbilityManagerService + * Function: IsFirstInMission + * SubFunction: NA + * FunctionPoints: AbilityManagerService IsFirstInMission + * EnvConditions: NA + * CaseDescription: Verify function IsFirstInMission + * IsFirstInMission parameter + */ +HWTEST_F(AbilityManagerServiceTest, isfirstinmission_002, TestSize.Level1) +{ + Want want; + ElementName element("device", "com.ix.hiMusic", "MusicAbility"); + want.SetElement(element); + auto result = StartAbility(want); + EXPECT_EQ(OHOS::ERR_OK, result); + auto stackManager = abilityMs_->GetStackManager(); + auto ability = stackManager->GetCurrentTopAbility(); + AbilityRequest requestInfo; + requestInfo.want = ability->GetWant(); + requestInfo.abilityInfo = ability->GetAbilityInfo(); + requestInfo.appInfo = ability->GetApplicationInfo(); + requestInfo.requestCode = ability->GetRequestCode(); + auto abilitySelf = AbilityRecord::CreateAbilityRecord(requestInfo); + auto resultFunction = abilityMs_->IsFirstInMission(abilitySelf->GetToken()); + EXPECT_EQ(resultFunction, false); +} + +/* + * Feature: AbilityManagerService + * Function: IsFirstInMission + * SubFunction: NA + * FunctionPoints: AbilityManagerService IsFirstInMission + * EnvConditions: NA + * CaseDescription: Verify function IsFirstInMission + * IsFirstInMission parameter + */ +HWTEST_F(AbilityManagerServiceTest, isfirstinmission_003, TestSize.Level1) +{ + Want want; + ElementName element("device", "com.ix.hiMusic", "MusicAbility"); + want.SetElement(element); + auto result = StartAbility(want); + EXPECT_EQ(OHOS::ERR_OK, result); + auto stackManager = abilityMs_->GetStackManager(); + auto ability = stackManager->GetCurrentTopAbility(); + auto abilityToken = ability->GetToken(); + abilityMs_->currentStackManager_ = nullptr; + auto resultFunction = abilityMs_->IsFirstInMission(abilityToken); + EXPECT_EQ(resultFunction, false); +} + +/* + * Feature: AbilityManagerService + * Function: IsFirstInMission + * SubFunction: NA + * FunctionPoints: AbilityManagerService IsFirstInMission + * EnvConditions: NA + * CaseDescription: Verify function IsFirstInMission + * IsFirstInMission parameter + */ +HWTEST_F(AbilityManagerServiceTest, isfirstinmission_004, TestSize.Level1) +{ + Want want; + ElementName element("device", "com.ix.hiMusic", "MusicAbility"); + want.SetElement(element); + auto result = StartAbility(want); + EXPECT_EQ(OHOS::ERR_OK, result); + auto stackManager = abilityMs_->GetStackManager(); + auto ability = stackManager->GetCurrentTopAbility(); + auto abilityToken = ability->GetToken(); + auto resultFunction = abilityMs_->IsFirstInMission(abilityToken); + EXPECT_EQ(resultFunction, true); +} + +/* + * Feature: AbilityManagerService + * Function: IsFirstInMission + * SubFunction: NA + * FunctionPoints: AbilityManagerService IsFirstInMission + * EnvConditions: NA + * CaseDescription: Verify function IsFirstInMission + * Checks whether this ability is the first ability in a mission. + */ +HWTEST_F(AbilityManagerServiceTest, isfirstinmission_005, TestSize.Level1) +{ + Want want; + ElementName element("device", "com.ix.hiMusic", "MusicAbility"); + want.SetElement(element); + auto result = StartAbility(want); + EXPECT_EQ(OHOS::ERR_OK, result); + auto stackManager = abilityMs_->GetStackManager(); + auto ability = stackManager->GetCurrentTopAbility(); + auto abilityToken = ability->GetToken(); + OHOS::sptr scheduler = new AbilityScheduler(); + EXPECT_EQ(abilityMs_->AttachAbilityThread(scheduler, abilityToken), OHOS::ERR_OK); + EXPECT_TRUE(ability->GetAbilityInfo().bundleName == "com.ix.hiMusic"); + ElementName elementTv("device", "com.ix.hiTv", "TvAbility"); + want.SetElement(elementTv); + auto resultTv = StartAbility(want); + EXPECT_EQ(OHOS::ERR_OK, resultTv); + auto stackManagerTv = abilityMs_->GetStackManager(); + auto abilityTv = stackManagerTv->GetCurrentTopAbility(); + EXPECT_TRUE(abilityTv->GetAbilityInfo().bundleName == "com.ix.hiTv"); + auto resultFunction = abilityMs_->IsFirstInMission(abilityToken); + EXPECT_EQ(resultFunction, true); +} + +/* + * Feature: AbilityManagerService + * Function: IsFirstInMission + * SubFunction: NA + * FunctionPoints: AbilityManagerService IsFirstInMission + * EnvConditions: NA + * CaseDescription: Verify function IsFirstInMission + * Checks whether this ability is the first ability in a mission. + */ +HWTEST_F(AbilityManagerServiceTest, isfirstinmission_006, TestSize.Level1) +{ + Want want; + ElementName element("device", "com.ix.hiMusic", "MusicAbility"); + want.SetElement(element); + auto result = StartAbility(want); + EXPECT_EQ(OHOS::ERR_OK, result); + auto stackManager = abilityMs_->GetStackManager(); + auto ability = stackManager->GetCurrentTopAbility(); + auto abilityToken = ability->GetToken(); + OHOS::sptr scheduler = new AbilityScheduler(); + EXPECT_EQ(abilityMs_->AttachAbilityThread(scheduler, abilityToken), OHOS::ERR_OK); + EXPECT_TRUE(ability->GetAbilityInfo().bundleName == "com.ix.hiMusic"); + ElementName elementTv("device", "com.ix.hiTv", "TvAbility"); + want.SetElement(elementTv); + auto resultTv = StartAbility(want); + EXPECT_EQ(OHOS::ERR_OK, resultTv); + auto stackManagerTv = abilityMs_->GetStackManager(); + auto abilityTv = stackManagerTv->GetCurrentTopAbility(); + EXPECT_TRUE(abilityTv->GetAbilityInfo().bundleName == "com.ix.hiTv"); + auto resultFunction = abilityMs_->IsFirstInMission(abilityTv->GetToken()); + EXPECT_EQ(resultFunction, false); +} + +/* + * Feature: AbilityManagerService + * Function: IsFirstInMission + * SubFunction: NA + * FunctionPoints: AbilityManagerService IsFirstInMission + * EnvConditions: NA + * CaseDescription: Verify function IsFirstInMission + * Checks whether this ability is the first ability in a mission. + */ +HWTEST_F(AbilityManagerServiceTest, isfirstinmission_007, TestSize.Level1) +{ + Want want; + ElementName element("device", "com.ix.hiMusic", "MusicAbility"); + want.SetElement(element); + auto result = StartAbility(want); + EXPECT_EQ(OHOS::ERR_OK, result); + auto stackManager = abilityMs_->GetStackManager(); + auto ability = stackManager->GetCurrentTopAbility(); + ability->SetAbilityState(AbilityState::ACTIVE); + AbilityRequest requestInfo; + ElementName elementTv("device", "com.ix.hiTv", "TvAbility"); + want.SetElement(elementTv); + requestInfo.want = want; + requestInfo.abilityInfo = ability->GetAbilityInfo(); + requestInfo.abilityInfo.launchMode = AppExecFwk::LaunchMode::SINGLETON; + result = stackManager->StartAbility(requestInfo); + EXPECT_EQ(OHOS::ERR_OK, result); + auto abilityTv = stackManager->GetCurrentTopAbility(); + abilityTv->SetAbilityState(AbilityState::ACTIVE); + auto resultTvFunction = abilityMs_->IsFirstInMission(abilityTv->GetToken()); + EXPECT_EQ(resultTvFunction, true); + auto resultMusicFunction = abilityMs_->IsFirstInMission(ability->GetToken()); + EXPECT_EQ(resultMusicFunction, true); +} + +/* + * Feature: AbilityManagerService + * Function: MoveMissionToEnd + * SubFunction: NA + * FunctionPoints: AbilityManagerService MoveMissionToEnd + * EnvConditions: NA + * CaseDescription: Verify function MoveMissionToEnd + * MoveMissionToEnd parameter + */ +HWTEST_F(AbilityManagerServiceTest, movemissiontoend_001, TestSize.Level1) +{ + auto result = abilityMs_->MoveMissionToEnd(nullptr, true); + EXPECT_EQ(result, ERR_INVALID_VALUE); +} + +/* + * Feature: AbilityManagerService + * Function: MoveMissionToEnd + * SubFunction: NA + * FunctionPoints: AbilityManagerService MoveMissionToEnd + * EnvConditions: NA + * CaseDescription: Verify function MoveMissionToEnd + * MoveMissionToEnd parameter + */ +HWTEST_F(AbilityManagerServiceTest, movemissiontoend_002, TestSize.Level1) +{ + auto result = abilityMs_->MoveMissionToEnd(nullptr, false); + EXPECT_EQ(result, ERR_INVALID_VALUE); +} + +/* + * Feature: AbilityManagerService + * Function: MoveMissionToEnd + * SubFunction: NA + * FunctionPoints: AbilityManagerService MoveMissionToEnd + * EnvConditions: NA + * CaseDescription: Verify function MoveMissionToEnd + * MoveMissionToEnd parameter, Only one MissionRecord in Stack,MoveMissionToEnd failed + */ +HWTEST_F(AbilityManagerServiceTest, movemissiontoend_003, TestSize.Level1) +{ + Want want; + ElementName element("device", "com.ix.hiMusic", "MusicAbility"); + want.SetElement(element); + auto result = StartAbility(want); + EXPECT_EQ(OHOS::ERR_OK, result); + auto stackManager = abilityMs_->GetStackManager(); + auto ability = stackManager->GetCurrentTopAbility(); + auto abilityToken = ability->GetToken(); + auto resultFunction = abilityMs_->MoveMissionToEnd(abilityToken, true); + EXPECT_EQ(resultFunction, MOVE_MISSION_FAILED); +} + +/* + * Feature: AbilityManagerService + * Function: MoveMissionToEnd + * SubFunction: NA + * FunctionPoints: AbilityManagerService MoveMissionToEnd + * EnvConditions: NA + * CaseDescription: Verify function MoveMissionToEnd + * MoveMissionToEnd parameter, Only one MissionRecord in Stack,MoveMissionToEnd failed + */ +HWTEST_F(AbilityManagerServiceTest, movemissiontoend_004, TestSize.Level1) +{ + Want want; + ElementName element("device", "com.ix.hiMusic", "MusicAbility"); + want.SetElement(element); + auto result = StartAbility(want); + EXPECT_EQ(OHOS::ERR_OK, result); + auto stackManager = abilityMs_->GetStackManager(); + auto ability = stackManager->GetCurrentTopAbility(); + auto abilityToken = ability->GetToken(); + auto resultFunction = abilityMs_->MoveMissionToEnd(abilityToken, false); + EXPECT_EQ(resultFunction, MOVE_MISSION_FAILED); +} + +/* + * Feature: AbilityManagerService + * Function: MoveMissionToEnd + * SubFunction: NA + * FunctionPoints: AbilityManagerService MoveMissionToEnd + * EnvConditions: NA + * CaseDescription: Verify function MoveMissionToEnd + * Multiple MissionRecord in Stack,When AbilityState not equal ACTIVE,MoveMissionToEnd failed + */ +HWTEST_F(AbilityManagerServiceTest, movemissiontoend_005, TestSize.Level1) +{ + Want want; + ElementName element("device", "com.ix.hiMusic", "MusicAbility"); + want.SetElement(element); + auto result = StartAbility(want); + EXPECT_EQ(OHOS::ERR_OK, result); + auto stackManager = abilityMs_->GetStackManager(); + auto ability = stackManager->GetCurrentTopAbility(); + ability->SetAbilityState(AbilityState::ACTIVE); + AbilityRequest requestInfo; + ElementName elementTv("device", "com.ix.hiTv", "TvAbility"); + want.SetElement(elementTv); + requestInfo.want = want; + requestInfo.abilityInfo.launchMode = AppExecFwk::LaunchMode::SINGLETON; + result = stackManager->StartAbility(requestInfo); + EXPECT_EQ(OHOS::ERR_OK, result); + auto abilityTv = stackManager->GetCurrentTopAbility(); + auto resultFunction = abilityMs_->MoveMissionToEnd(abilityTv->GetToken(), false); + EXPECT_EQ(resultFunction, MOVE_MISSION_FAILED); +} + +/* + * Feature: AbilityManagerService + * Function: MoveMissionToEnd + * SubFunction: NA + * FunctionPoints: AbilityManagerService MoveMissionToEnd + * EnvConditions: NA + * CaseDescription: Verify function MoveMissionToEnd + * Multiple MissionRecord in Stack,When AbilityState not equal ACTIVE,MoveMissionToEnd failed + */ +HWTEST_F(AbilityManagerServiceTest, movemissiontoend_006, TestSize.Level1) +{ + Want want; + ElementName element("device", "com.ix.hiMusic", "MusicAbility"); + want.SetElement(element); + auto result = StartAbility(want); + EXPECT_EQ(OHOS::ERR_OK, result); + auto stackManager = abilityMs_->GetStackManager(); + auto ability = stackManager->GetCurrentTopAbility(); + ability->SetAbilityState(AbilityState::ACTIVE); + AbilityRequest requestInfo; + ElementName elementTv("device", "com.ix.hiTv", "TvAbility"); + want.SetElement(elementTv); + requestInfo.want = want; + requestInfo.abilityInfo = ability->GetAbilityInfo(); + requestInfo.abilityInfo.launchMode = AppExecFwk::LaunchMode::SINGLETON; + result = stackManager->StartAbility(requestInfo); + EXPECT_EQ(OHOS::ERR_OK, result); + auto abilityTv = stackManager->GetCurrentTopAbility(); + auto resultFunction = abilityMs_->MoveMissionToEnd(abilityTv->GetToken(), true); + EXPECT_EQ(resultFunction, MOVE_MISSION_FAILED); +} + +/* + * Feature: AbilityManagerService + * Function: MoveMissionToEnd + * SubFunction: NA + * FunctionPoints: AbilityManagerService MoveMissionToEnd + * EnvConditions: NA + * CaseDescription: Verify function MoveMissionToEnd + * Multiple MissionRecord in Stack,When AbilityState not equal ACTIVE,MoveMissionToEnd failed + */ +HWTEST_F(AbilityManagerServiceTest, movemissiontoend_007, TestSize.Level1) +{ + Want want; + ElementName element("device", "com.ix.hiMusic", "MusicAbility"); + want.SetElement(element); + auto result = StartAbility(want); + EXPECT_EQ(OHOS::ERR_OK, result); + auto stackManager = abilityMs_->GetStackManager(); + auto ability = stackManager->GetCurrentTopAbility(); + ability->SetAbilityState(AbilityState::ACTIVE); + AbilityRequest requestInfo; + ElementName elementTv("device", "com.ix.hiTv", "TvAbility"); + want.SetElement(elementTv); + requestInfo.want = want; + requestInfo.abilityInfo.launchMode = AppExecFwk::LaunchMode::SINGLETON; + result = stackManager->StartAbility(requestInfo); + EXPECT_EQ(OHOS::ERR_OK, result); + auto abilityTv = stackManager->GetCurrentTopAbility(); + abilityTv->SetAbilityState(AbilityState::ACTIVE); + auto resultFunction = abilityMs_->MoveMissionToEnd(abilityTv->GetToken(), false); + EXPECT_EQ(resultFunction, ERR_OK); +} + +/* + * Feature: AbilityManagerService + * Function: MoveMissionToEnd + * SubFunction: NA + * FunctionPoints: AbilityManagerService MoveMissionToEnd + * EnvConditions: NA + * CaseDescription: Verify function MoveMissionToEnd + * Multiple MissionRecord in Stack,When AbilityState not equal ACTIVE,MoveMissionToEnd failed + */ +HWTEST_F(AbilityManagerServiceTest, movemissiontoend_008, TestSize.Level1) +{ + Want want; + ElementName element("device", "com.ix.hiMusic", "MusicAbility"); + want.SetElement(element); + auto result = StartAbility(want); + EXPECT_EQ(OHOS::ERR_OK, result); + auto stackManager = abilityMs_->GetStackManager(); + auto ability = stackManager->GetCurrentTopAbility(); + ability->SetAbilityState(AbilityState::ACTIVE); + AbilityRequest requestInfo; + ElementName elementTv("device", "com.ix.hiTv", "TvAbility"); + want.SetElement(elementTv); + requestInfo.want = want; + requestInfo.abilityInfo = ability->GetAbilityInfo(); + requestInfo.abilityInfo.launchMode = AppExecFwk::LaunchMode::SINGLETON; + result = stackManager->StartAbility(requestInfo); + EXPECT_EQ(OHOS::ERR_OK, result); + auto abilityTv = stackManager->GetCurrentTopAbility(); + abilityTv->SetAbilityState(AbilityState::ACTIVE); + auto resultFunction = abilityMs_->MoveMissionToEnd(abilityTv->GetToken(), true); + EXPECT_EQ(resultFunction, ERR_OK); +} + +/* + * Feature: AbilityManagerService + * Function: MoveMissionToEnd + * SubFunction: NA + * FunctionPoints: AbilityManagerService MoveMissionToEnd + * EnvConditions: NA + * CaseDescription: Verify function MoveMissionToEnd + * Multiple MissionRecord in Stack,When this ability is not the first ability in a mission, + * and MoveMissionToEnd second parameter is false. + */ +HWTEST_F(AbilityManagerServiceTest, movemissiontoend_009, TestSize.Level1) +{ + Want want; + ElementName element("device", "com.ix.hiMusic", "MusicAbility"); + want.SetElement(element); + auto result = StartAbility(want); + EXPECT_EQ(OHOS::ERR_OK, result); + auto stackManager = abilityMs_->GetStackManager(); + auto ability = stackManager->GetCurrentTopAbility(); + ability->SetAbilityState(AbilityState::ACTIVE); + AbilityRequest requestInfo; + ElementName elementTv("device", "com.ix.hiTv", "TvAbility"); + want.SetElement(elementTv); + requestInfo.want = want; + requestInfo.abilityInfo = ability->GetAbilityInfo(); + requestInfo.abilityInfo.launchMode = AppExecFwk::LaunchMode::SINGLETON; + result = stackManager->StartAbility(requestInfo); + EXPECT_EQ(OHOS::ERR_OK, result); + auto abilityTv = stackManager->GetCurrentTopAbility(); + abilityTv->SetAbilityState(AbilityState::ACTIVE); + ElementName elementPhone("device", "com.ix.hiMusic", "PhoneAbility"); + want.SetElement(elementPhone); + auto resultPhone = StartAbility(want); + EXPECT_EQ(OHOS::ERR_OK, resultPhone); + auto abilityPhone = stackManager->GetCurrentTopAbility(); + abilityPhone->SetAbilityState(AbilityState::ACTIVE); + auto resultFunction = abilityMs_->MoveMissionToEnd(abilityPhone->GetToken(), false); + EXPECT_EQ(resultFunction, MOVE_MISSION_FAILED); +} + +/* + * Feature: AbilityManagerService + * Function: MoveMissionToEnd + * SubFunction: NA + * FunctionPoints: AbilityManagerService MoveMissionToEnd + * EnvConditions: NA + * CaseDescription: Verify function MoveMissionToEnd + * Multiple MissionRecord in Stack,When this ability is not the first ability in a mission, + * and MoveMissionToEnd second parameter is true. + */ +HWTEST_F(AbilityManagerServiceTest, movemissiontoend_010, TestSize.Level1) +{ + Want want; + ElementName element("device", "com.ix.hiMusic", "MusicAbility"); + want.SetElement(element); + auto result = StartAbility(want); + EXPECT_EQ(OHOS::ERR_OK, result); + auto stackManager = abilityMs_->GetStackManager(); + auto ability = stackManager->GetCurrentTopAbility(); + ability->SetAbilityState(AbilityState::ACTIVE); + AbilityRequest requestInfo; + ElementName elementTv("device", "com.ix.hiTv", "TvAbility"); + want.SetElement(elementTv); + requestInfo.want = want; + requestInfo.abilityInfo = ability->GetAbilityInfo(); + requestInfo.abilityInfo.launchMode = AppExecFwk::LaunchMode::SINGLETON; + result = stackManager->StartAbility(requestInfo); + EXPECT_EQ(OHOS::ERR_OK, result); + auto abilityTv = stackManager->GetCurrentTopAbility(); + abilityTv->SetAbilityState(AbilityState::ACTIVE); + ElementName elementPhone("device", "com.ix.hiMusic", "PhoneAbility"); + want.SetElement(elementPhone); + auto resultPhone = StartAbility(want); + EXPECT_EQ(OHOS::ERR_OK, resultPhone); + auto abilityPhone = stackManager->GetCurrentTopAbility(); + abilityPhone->SetAbilityState(AbilityState::ACTIVE); + auto resultFunction = abilityMs_->MoveMissionToEnd(abilityPhone->GetToken(), true); + EXPECT_EQ(resultFunction, ERR_OK); +} + +/* + * Feature: AbilityManagerService + * Function: MoveMissionToEnd + * SubFunction: NA + * FunctionPoints: AbilityManagerService MoveMissionToEnd + * EnvConditions: NA + * CaseDescription: Verify function MoveMissionToEnd + * Multiple MissionRecord in Stack,When this ability is the first ability in a mission, + * and MoveMissionToEnd second parameter is false,but this ability AbilityState not equal ACTIVE. + */ +HWTEST_F(AbilityManagerServiceTest, movemissiontoend_011, TestSize.Level1) +{ + Want want; + ElementName element("device", "com.ix.hiMusic", "MusicAbility"); + want.SetElement(element); + auto result = StartAbility(want); + EXPECT_EQ(OHOS::ERR_OK, result); + auto stackManager = abilityMs_->GetStackManager(); + auto ability = stackManager->GetCurrentTopAbility(); + ability->SetAbilityState(AbilityState::ACTIVE); + ElementName elementPhone("device", "com.ix.hiPhone", "PhoneAbility"); + want.SetElement(elementPhone); + auto resultPhone = StartAbility(want); + EXPECT_EQ(OHOS::ERR_OK, resultPhone); + auto abilityPhone = stackManager->GetCurrentTopAbility(); + abilityPhone->SetAbilityState(AbilityState::ACTIVE); + AbilityRequest requestInfo; + ElementName elementTv("device", "com.ix.hiTv", "TvAbility"); + want.SetElement(elementTv); + requestInfo.want = want; + requestInfo.abilityInfo = ability->GetAbilityInfo(); + requestInfo.abilityInfo.launchMode = AppExecFwk::LaunchMode::SINGLETON; + result = stackManager->StartAbility(requestInfo); + EXPECT_EQ(OHOS::ERR_OK, result); + auto abilityTv = stackManager->GetCurrentTopAbility(); + abilityTv->SetAbilityState(AbilityState::ACTIVE); + auto resultFunction = abilityMs_->MoveMissionToEnd(ability->GetToken(), false); + EXPECT_EQ(resultFunction, MOVE_MISSION_FAILED); +} + +/* + * Feature: AbilityManagerService + * Function: MoveMissionToEnd + * SubFunction: NA + * FunctionPoints: AbilityManagerService MoveMissionToEnd + * EnvConditions: NA + * CaseDescription: Verify function MoveMissionToEnd + * Multiple MissionRecord in Stack,When this ability is the first ability in a mission, + * and MoveMissionToEnd second parameter is true,but this ability AbilityState not equal ACTIVE. + */ +HWTEST_F(AbilityManagerServiceTest, movemissiontoend_012, TestSize.Level1) +{ + Want want; + ElementName element("device", "com.ix.hiMusic", "MusicAbility"); + want.SetElement(element); + auto result = StartAbility(want); + EXPECT_EQ(OHOS::ERR_OK, result); + auto stackManager = abilityMs_->GetStackManager(); + auto ability = stackManager->GetCurrentTopAbility(); + ability->SetAbilityState(AbilityState::ACTIVE); + ElementName elementPhone("device", "com.ix.hiPhone", "PhoneAbility"); + want.SetElement(elementPhone); + auto resultPhone = StartAbility(want); + EXPECT_EQ(OHOS::ERR_OK, resultPhone); + auto abilityPhone = stackManager->GetCurrentTopAbility(); + abilityPhone->SetAbilityState(AbilityState::ACTIVE); + AbilityRequest requestInfo; + ElementName elementTv("device", "com.ix.hiTv", "TvAbility"); + want.SetElement(elementTv); + requestInfo.want = want; + requestInfo.abilityInfo = ability->GetAbilityInfo(); + requestInfo.abilityInfo.launchMode = AppExecFwk::LaunchMode::SINGLETON; + result = stackManager->StartAbility(requestInfo); + EXPECT_EQ(OHOS::ERR_OK, result); + auto abilityTv = stackManager->GetCurrentTopAbility(); + abilityTv->SetAbilityState(AbilityState::ACTIVE); + auto resultFunction = abilityMs_->MoveMissionToEnd(ability->GetToken(), true); + EXPECT_EQ(resultFunction, MOVE_MISSION_FAILED); +} + +/* + * Feature: AbilityManagerService + * Function: CompelVerifyPermission + * SubFunction: NA + * FunctionPoints: AbilityManagerService CompelVerifyPermission + * EnvConditions: NA + * CaseDescription: Verify function CompelVerifyPermission + */ +HWTEST_F(AbilityManagerServiceTest, compelverifypermission_001, TestSize.Level1) +{ + const std::string permission = "permission"; + int pid = 100; + int uid = 1000; + std::string message; + auto resultFunction = abilityMs_->CompelVerifyPermission(permission, pid, uid, message); + EXPECT_EQ(resultFunction, ERR_OK); +} + +/* + * Feature: AbilityManagerService + * Function: AmsConfigurationParameter + * SubFunction: NA + * FunctionPoints: AbilityManagerService CompelVerifyPermission + * EnvConditions: NA + * CaseDescription: Already configured + */ +HWTEST_F(AbilityManagerServiceTest, AmsConfigurationParameter_001, TestSize.Level1) +{ + EXPECT_TRUE(abilityMs_->amsConfigResolver_); + EXPECT_FALSE(abilityMs_->amsConfigResolver_->NonConfigFile()); +} + +/* + * Feature: AbilityManagerService + * Function: AmsConfigurationParameter + * SubFunction: NA + * FunctionPoints: AbilityManagerService CompelVerifyPermission + * EnvConditions: NA + * CaseDescription: Already configured + */ +HWTEST_F(AbilityManagerServiceTest, AmsConfigurationParameter_002, TestSize.Level1) +{ + EXPECT_TRUE(abilityMs_->amsConfigResolver_); + // At present, all three are started and may be changed later + EXPECT_TRUE(abilityMs_->amsConfigResolver_->GetStartLauncherState()); + EXPECT_TRUE(abilityMs_->amsConfigResolver_->GetStatusBarState()); + EXPECT_TRUE(abilityMs_->amsConfigResolver_->GetNavigationBarState()); +} + +/* + * Feature: AbilityManagerService + * Function: AmsConfigurationParameter + * SubFunction: NA + * FunctionPoints: AbilityManagerService CompelVerifyPermission + * EnvConditions: NA + * CaseDescription: Already configured + */ +HWTEST_F(AbilityManagerServiceTest, AmsConfigurationParameter_003, TestSize.Level1) +{ + EXPECT_TRUE(abilityMs_->amsConfigResolver_); + auto ref = abilityMs_->amsConfigResolver_->LoadAmsConfiguration(" "); + EXPECT_EQ(ref, 1); +} + +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/abilitymgr/test/unittest/phone/ability_manager_stub_test/BUILD.gn b/tools/services/abilitymgr/test/unittest/phone/ability_manager_stub_test/BUILD.gn new file mode 100644 index 00000000000..9ad5ce7d603 --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/ability_manager_stub_test/BUILD.gn @@ -0,0 +1,67 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/test.gni") +import("//foundation/aafwk/standard/aafwk.gni") + +module_output_path = "aafwk_standard/abilitymgr" + +ohos_unittest("ability_manager_stub_test") { + module_out_path = module_output_path + + include_dirs = [ + "${services_path}/abilitymgr/test/mock/libs/system_ability_mock", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy/include", + "//foundation/distributedschedule/samgr/utils/native/include/", + ] + + sources = [ + # add mock file + "//foundation/aafwk/standard/services/abilitymgr/test/mock/libs/appexecfwk_core/src/appmgr/mock_app_scheduler.cpp", + "ability_manager_stub_test.cpp", + ] + + configs = [ + "${services_path}/abilitymgr:abilityms_config", + "${services_path}/abilitymgr/test/mock:aafwk_mock_config", + ] + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + deps = [ + "${services_path}/abilitymgr/test:abilityms_test_source", + "${services_path}/abilitymgr/test/mock/libs/aakit:aakit_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_appmgr_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_bundlemgr_mock", + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/frameworks/kits/ability/native:dummy_classes", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//third_party/googletest:gmock_main", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] +} + +group("unittest") { + testonly = true + + deps = [ ":ability_manager_stub_test" ] +} diff --git a/tools/services/abilitymgr/test/unittest/phone/ability_manager_stub_test/ability_manager_stub_impl_mock.h b/tools/services/abilitymgr/test/unittest/phone/ability_manager_stub_test/ability_manager_stub_impl_mock.h new file mode 100755 index 00000000000..43d8a3a9575 --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/ability_manager_stub_test/ability_manager_stub_impl_mock.h @@ -0,0 +1,287 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ABILITY_UNITTEST_ABILITY_MANAGER_STUB_IMPL_MOCK_H +#define ABILITY_UNITTEST_ABILITY_MANAGER_STUB_IMPL_MOCK_H +#include +#include +#include +#include "ability_manager_interface.h" +#include "ability_manager_stub.h" + +namespace OHOS { +namespace AAFwk { +class AbilityManagerStubImplMock : public AbilityManagerStub { +public: + AbilityManagerStubImplMock() + {} + virtual ~AbilityManagerStubImplMock() + {} + + MOCK_METHOD2(TerminateAbilityByCaller, int(const sptr &callerToken, int requestCode)); + MOCK_METHOD3(StartAbility, int(const Want &want, const sptr &callerToken, int requestCode)); + MOCK_METHOD2( + GetWantSender, sptr(const WantSenderInfo &wantSenderInfo, const sptr &callerToken)); + MOCK_METHOD2(SendWantSender, int(const sptr &target, const SenderInfo &senderInfo)); + MOCK_METHOD1(CancelWantSender, void(const sptr &sender)); + MOCK_METHOD1(GetPendingWantUid, int(const sptr &target)); + MOCK_METHOD1(GetPendingWantUserId, int(const sptr &target)); + MOCK_METHOD1(GetPendingWantBundleName, std::string(const sptr &target)); + MOCK_METHOD1(GetPendingWantCode, int(const sptr &target)); + MOCK_METHOD1(GetPendingWantType, int(const sptr &target)); + MOCK_METHOD2(RegisterCancelListener, void(const sptr &sender, const sptr &receiver)); + MOCK_METHOD2(UnregisterCancelListener, void(const sptr &sender, const sptr &receiver)); + MOCK_METHOD2(GetPendingRequestWant, int(const sptr &target, std::shared_ptr &want)); + + int InvokeSendRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) + { + code_ = code; + return 0; + } + + int InvokeErrorSendRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) + { + code_ = code; + return UNKNOWN_ERROR; + } + + int code_ = 0; + + virtual int StartAbility(const Want &want, int requestCode = -1) + { + return 0; + } + + int StartAbility(const Want &want, const AbilityStartSetting &abilityStartSetting, + const sptr &callerToken, int requestCode = DEFAULT_INVAL_VALUE) + { + return 0; + } + + virtual int TerminateAbility(const sptr &token, int resultCode, const Want *resultWant = nullptr) + { + return 0; + } + + virtual int ConnectAbility( + const Want &want, const sptr &connect, const sptr &callerToken) + { + return 0; + } + + virtual int DisconnectAbility(const sptr &connect) + { + return 0; + } + + virtual sptr AcquireDataAbility( + const Uri &uri, bool tryBind, const sptr &callerToken) override + { + return nullptr; + } + + virtual int ReleaseDataAbility(sptr dataAbilityScheduler, const sptr &callerToken) + { + return 0; + } + + virtual void AddWindowInfo(const sptr &token, int32_t windowToken) + {} + + virtual int AttachAbilityThread(const sptr &scheduler, const sptr &token) + { + return 0; + } + + virtual int AbilityTransitionDone(const sptr &token, int state) + { + return 0; + } + + virtual int ScheduleConnectAbilityDone(const sptr &token, const sptr &remoteObject) + { + return 0; + } + + virtual int ScheduleDisconnectAbilityDone(const sptr &token) + { + return 0; + } + + virtual int ScheduleCommandAbilityDone(const sptr &token) + { + return 0; + } + + virtual void DumpState(const std::string &args, std::vector &state) + {} + + virtual int TerminateAbilityResult(const sptr &token, int startId) + { + return 0; + } + + virtual int StopServiceAbility(const Want &want) + { + return 0; + } + + virtual int GetAllStackInfo(StackInfo &stackInfo) + { + return 0; + } + + virtual int GetRecentMissions( + const int32_t numMax, const int32_t flags, std::vector &recentList) + { + AbilityMissionInfo info; + info.id = 1; + AppExecFwk::ElementName baseEle("baseDevice", "baseBundle", "baseAbility"); + info.baseAbility = baseEle; + Want want; + want.SetElement(baseEle); + info.baseWant = want; + AppExecFwk::ElementName topEle("topDevice", "topBundle", "topAbility"); + info.topAbility = topEle; + info.size = 1; + info.missionDescription.iconPath = "icon path"; + info.missionDescription.label = "label"; + recentList.emplace_back(info); + return 0; + } + + int GetMissionSnapshot(const int32_t missionId, MissionSnapshotInfo &snapshot) + { + return 0; + } + + virtual int RemoveMission(int id) + { + return 0; + } + + virtual int RemoveStack(int id) + { + return 0; + } + + virtual int KillProcess(const std::string &bundleName) + { + return 0; + } + + virtual int UninstallApp(const std::string &bundleName) + { + return 0; + } + + virtual int MoveMissionToTop(int32_t missionId) + { + return 0; + } + + bool IsFirstInMission(const sptr &token) override + { + return true; + } + + int CompelVerifyPermission(const std::string &permission, int pid, int uid, std::string &message) override + { + return 0; + } + + int MoveMissionToEnd(const sptr &token, const bool nonFirst) override + { + return 0; + } + + int PowerOff() override + { + return 0; + } + + int PowerOn() override + { + return 0; + } + + int LockMission(int missionId) override + { + return 0; + } + int UnlockMission(int missionId) override + { + return 0; + } + int SetMissionDescriptionInfo( + const sptr &token, const MissionDescriptionInfo &missionDescriptionInfo) override + { + return 0; + } + + int GetMissionLockModeState() + { + return 0; + } + + int UpdateConfiguration(const DummyConfiguration &config) + { + return 0; + } + + int MoveMissionToFloatingStack(const MissionOption &missionOption) + { + return 0; + } + + int MoveMissionToSplitScreenStack(const MissionOption &missionOption) + { + return 0; + } + + int ChangeFocusAbility(const sptr &lostFocusToken, const sptr &getFocusToken) + { + return 0; + } + + int MinimizeMultiWindow(int missionId) + { + return 0; + } + + int MaximizeMultiWindow(int missionId) + { + return 0; + } + + int GetFloatingMissions(std::vector &list) + { + return 0; + } + + int CloseMultiWindow(int missionId) + { + return 0; + } + + int SetMissionStackSetting(const StackSetting &stackSetting) + { + return 0; + } +}; +} // namespace AAFwk +} // namespace OHOS + +#endif diff --git a/tools/services/abilitymgr/test/unittest/phone/ability_manager_stub_test/ability_manager_stub_test.cpp b/tools/services/abilitymgr/test/unittest/phone/ability_manager_stub_test/ability_manager_stub_test.cpp new file mode 100644 index 00000000000..7d191a7f13b --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/ability_manager_stub_test/ability_manager_stub_test.cpp @@ -0,0 +1,449 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "iremote_proxy.h" +#include "ability_manager_stub_impl_mock.h" +#include "ability_scheduler.h" +#include "mock_ability_connect_callback.h" + +using namespace testing::ext; +using namespace testing; + +namespace OHOS { +namespace AAFwk { +class AbilityManagerStubTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + void WriteInterfaceToken(MessageParcel &data); + sptr stub_{nullptr}; +}; + +void AbilityManagerStubTest::SetUpTestCase(void) +{} +void AbilityManagerStubTest::TearDownTestCase(void) +{} +void AbilityManagerStubTest::TearDown() +{} + +void AbilityManagerStubTest::SetUp() +{ + stub_ = new AbilityManagerStubImplMock(); +} + +void AbilityManagerStubTest::WriteInterfaceToken(MessageParcel &data) +{ + data.WriteInterfaceToken(AbilityManagerStub::GetDescriptor()); +} + +/* + * Feature: AbilityManagerService + * Function: OnRemoteRequest + * SubFunction: NA + * FunctionPoints: AbilityManagerService OnRemoteRequest + * EnvConditions: code is START_ABILITY + * CaseDescription: Verify that on remote request is normal and abnormal + */ +HWTEST_F(AbilityManagerStubTest, AbilityManagerStub_001, TestSize.Level0) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + Want want; + WriteInterfaceToken(data); + want.SetFlags(10); + data.WriteParcelable(&want); + data.WriteInt32(1); + int res = stub_->OnRemoteRequest(IAbilityManager::START_ABILITY, data, reply, option); + + EXPECT_EQ(res, NO_ERROR); + + data.WriteParcelable(nullptr); + data.WriteInt32(1); + int res1 = stub_->OnRemoteRequest(IAbilityManager::START_ABILITY, data, reply, option); + EXPECT_NE(res1, NO_ERROR); +} + +/* + * Feature: AbilityManagerService + * Function: OnRemoteRequest + * SubFunction: NA + * FunctionPoints: AbilityManagerService OnRemoteRequest + * EnvConditions: code is TERMINATE_ABILITY + * CaseDescription: Verify that on remote request is normal and abnormal + */ +HWTEST_F(AbilityManagerStubTest, AbilityManagerStub_002, TestSize.Level0) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + Want want; + want.SetFlags(10); + OHOS::sptr token = nullptr; + WriteInterfaceToken(data); + data.WriteParcelable(token); + data.WriteParcelable(&want); + int res = stub_->OnRemoteRequest(IAbilityManager::TERMINATE_ABILITY, data, reply, option); + + EXPECT_EQ(res, NO_ERROR); +} + +/* + * Feature: AbilityManagerService + * Function: OnRemoteRequest + * SubFunction: NA + * FunctionPoints: AbilityManagerService OnRemoteRequest + * EnvConditions: code is CONNECT_ABILITY + * CaseDescription: Verify that on remote request is normal + */ +HWTEST_F(AbilityManagerStubTest, AbilityManagerStub_004, TestSize.Level0) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + Want want; + want.SetFlags(10); + sptr connect = new AbilityConnectCallback(); + sptr callerToken = nullptr; + WriteInterfaceToken(data); + data.WriteParcelable(&want); + data.WriteParcelable(connect->AsObject()); + data.WriteParcelable(callerToken); + int res = stub_->OnRemoteRequest(IAbilityManager::CONNECT_ABILITY, data, reply, option); + + EXPECT_EQ(res, NO_ERROR); +} + +/* + * Feature: AbilityManagerService + * Function: OnRemoteRequest + * SubFunction: NA + * FunctionPoints: NA + * EnvConditions: NA + * CaseDescription: OnRemoteRequest IAbilityManager::CONNECT_ABILITY + */ +HWTEST_F(AbilityManagerStubTest, AbilityManagerStub_005, TestSize.Level0) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + Want want; + want.SetFlags(10); + sptr connect = new AbilityConnectCallback(); + sptr callerToken = nullptr; + WriteInterfaceToken(data); + data.WriteParcelable(&want); + data.WriteParcelable(connect->AsObject()); + data.WriteParcelable(callerToken); + int res = stub_->OnRemoteRequest(IAbilityManager::CONNECT_ABILITY, data, reply, option); + + EXPECT_EQ(res, NO_ERROR); +} + +/* + * Feature: AbilityManagerService + * Function: OnRemoteRequest + * SubFunction: NA + * FunctionPoints: NA + * EnvConditions: NA + * CaseDescription: OnRemoteRequest IAbilityManager::CONNECT_ABILITY + */ +HWTEST_F(AbilityManagerStubTest, AbilityManagerStub_006, TestSize.Level0) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + sptr connect = new AbilityConnectCallback(); + sptr callerToken = nullptr; + WriteInterfaceToken(data); + data.WriteParcelable(nullptr); + data.WriteParcelable(connect->AsObject()); + data.WriteParcelable(callerToken); + int res = stub_->OnRemoteRequest(IAbilityManager::CONNECT_ABILITY, data, reply, option); + + EXPECT_NE(res, NO_ERROR); +} + +/* + * Feature: AbilityManagerService + * Function: OnRemoteRequest + * SubFunction: NA + * FunctionPoints: AbilityManagerService OnRemoteRequest + * EnvConditions: code is DISCONNECT_ABILITY + * CaseDescription: Verify that on remote request is normal + */ +HWTEST_F(AbilityManagerStubTest, AbilityManagerStub_007, TestSize.Level0) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + sptr connect = new AbilityConnectCallback(); + WriteInterfaceToken(data); + data.WriteParcelable(connect->AsObject()); + int res = stub_->OnRemoteRequest(IAbilityManager::DISCONNECT_ABILITY, data, reply, option); + + EXPECT_EQ(res, NO_ERROR); +} + +/* + * Feature: AbilityManagerService + * Function: OnRemoteRequest + * SubFunction: NA + * FunctionPoints: AbilityManagerService OnRemoteRequest + * EnvConditions: code is ATTACH_ABILITY_THREAD + * CaseDescription: Verify that on remote request is normal + */ +HWTEST_F(AbilityManagerStubTest, AbilityManagerStub_008, TestSize.Level0) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + sptr scheduler = new AbilityScheduler(); + sptr token = nullptr; + WriteInterfaceToken(data); + data.WriteParcelable(scheduler->AsObject()); + data.WriteParcelable(token); + int res = stub_->OnRemoteRequest(IAbilityManager::ATTACH_ABILITY_THREAD, data, reply, option); + + EXPECT_EQ(res, NO_ERROR); +} + +/* + * Feature: AbilityManagerService + * Function: OnRemoteRequest + * SubFunction: NA + * FunctionPoints: AbilityManagerService OnRemoteRequest + * EnvConditions: code is ABILITY_TRANSITION_DONE + * CaseDescription: Verify that on remote request is normal + */ +HWTEST_F(AbilityManagerStubTest, AbilityManagerStub_009, TestSize.Level0) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + sptr token = nullptr; + WriteInterfaceToken(data); + data.WriteParcelable(token); + data.WriteInt32(1); + int res = stub_->OnRemoteRequest(IAbilityManager::ABILITY_TRANSITION_DONE, data, reply, option); + + EXPECT_EQ(res, NO_ERROR); +} + +/* + * Feature: AbilityManagerService + * Function: OnRemoteRequest + * SubFunction: NA + * FunctionPoints: AbilityManagerService OnRemoteRequest + * EnvConditions: code is CONNECT_ABILITY_DONE + * CaseDescription: Verify that on remote request is normal + */ +HWTEST_F(AbilityManagerStubTest, AbilityManagerStub_010, TestSize.Level0) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + sptr token = nullptr; + sptr remoteObject = nullptr; + WriteInterfaceToken(data); + data.WriteParcelable(token); + data.WriteParcelable(remoteObject); + int res = stub_->OnRemoteRequest(IAbilityManager::CONNECT_ABILITY_DONE, data, reply, option); + + EXPECT_EQ(res, NO_ERROR); +} + +/* + * Feature: AbilityManagerService + * Function: OnRemoteRequest + * SubFunction: NA + * FunctionPoints: AbilityManagerService OnRemoteRequest + * EnvConditions: code is DISCONNECT_ABILITY_DONE + * CaseDescription: Verify that on remote request is normal + */ +HWTEST_F(AbilityManagerStubTest, AbilityManagerStub_011, TestSize.Level0) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + sptr token = nullptr; + WriteInterfaceToken(data); + data.WriteParcelable(token); + int res = stub_->OnRemoteRequest(IAbilityManager::DISCONNECT_ABILITY_DONE, data, reply, option); + + EXPECT_EQ(res, NO_ERROR); +} + +/* + * Feature: AbilityManagerService + * Function: OnRemoteRequest + * SubFunction: NA + * FunctionPoints: AbilityManagerService OnRemoteRequest + * EnvConditions: code is ADD_WINDOW_INFO + * CaseDescription: Verify that on remote request is normal + */ +HWTEST_F(AbilityManagerStubTest, AbilityManagerStub_012, TestSize.Level0) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + sptr token = nullptr; + WriteInterfaceToken(data); + data.WriteParcelable(token); + data.WriteInt32(1); + int res = stub_->OnRemoteRequest(IAbilityManager::ADD_WINDOW_INFO, data, reply, option); + + EXPECT_EQ(res, NO_ERROR); +} + +/* + * Feature: AbilityManagerService + * Function: OnRemoteRequest + * SubFunction: NA + * FunctionPoints: AbilityManagerService OnRemoteRequest + * EnvConditions: code is DUMP_STATE + * CaseDescription: Verify that on remote request is normal + */ +HWTEST_F(AbilityManagerStubTest, AbilityManagerStub_013, TestSize.Level0) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + std::string args = "aaa"; + std::vector info; + WriteInterfaceToken(data); + data.WriteString16(Str8ToStr16(args)); + int res = stub_->OnRemoteRequest(IAbilityManager::DUMP_STATE, data, reply, option); + + EXPECT_EQ(res, NO_ERROR); +} + +/* + * Feature: AbilityManagerService + * Function: OnRemoteRequest + * SubFunction: NA + * FunctionPoints: AbilityManagerService OnRemoteRequest + * EnvConditions: code is LIST_STACK_INFO + * CaseDescription: Verify that on remote request is normal + */ +HWTEST_F(AbilityManagerStubTest, AbilityManagerStub_014, TestSize.Level0) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + WriteInterfaceToken(data); + int res = stub_->OnRemoteRequest(IAbilityManager::LIST_STACK_INFO, data, reply, option); + + EXPECT_EQ(res, NO_ERROR); +} + +/* + * Feature: AbilityManagerService + * Function: OnRemoteRequest + * SubFunction: NA + * FunctionPoints: AbilityManagerService OnRemoteRequest + * EnvConditions: code is TERMINATE_ABILITY_RESULT + * CaseDescription: Verify that on remote request is normal + */ +HWTEST_F(AbilityManagerStubTest, AbilityManagerStub_015, TestSize.Level0) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + WriteInterfaceToken(data); + int res = stub_->OnRemoteRequest(IAbilityManager::TERMINATE_ABILITY_RESULT, data, reply, option); + + EXPECT_EQ(res, NO_ERROR); +} + +/* + * Feature: AbilityManagerService + * Function: OnRemoteRequest + * SubFunction: NA + * FunctionPoints: AbilityManagerService OnRemoteRequest + * EnvConditions: code is default + * CaseDescription: Verify that on remote request is normal + */ +HWTEST_F(AbilityManagerStubTest, AbilityManagerStub_016, TestSize.Level0) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + WriteInterfaceToken(data); + int res = stub_->OnRemoteRequest(5000, data, reply, option); + + EXPECT_NE(res, NO_ERROR); +} + +/* + * Feature: AbilityManagerService + * Function: OnRemoteRequest + * SubFunction: NA + * FunctionPoints: AbilityManagerService OnRemoteRequest + * EnvConditions: code is GET_RECENT_MISSION + * CaseDescription: Verify that on remote request is normal + */ +HWTEST_F(AbilityManagerStubTest, AbilityManagerStub_017, TestSize.Level0) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + WriteInterfaceToken(data); + data.WriteInt32(INT_MAX); + data.WriteInt32(1); + int res = stub_->OnRemoteRequest(IAbilityManager::GET_RECENT_MISSION, data, reply, option); + + std::vector recentList; + int size = reply.ReadInt32(); + for (int32_t i = 0; i < size; i++) { + std::unique_ptr info(reply.ReadParcelable()); + recentList.emplace_back(*info); + } + + EXPECT_EQ(static_cast(recentList.size()), 1); + EXPECT_EQ(recentList[0].runingState, -1); + EXPECT_EQ(recentList[0].missionDescription.label, "label"); + EXPECT_EQ(recentList[0].missionDescription.iconPath, "icon path"); + EXPECT_EQ(recentList[0].baseWant.GetElement().GetAbilityName(), "baseAbility"); + EXPECT_EQ(recentList[0].baseWant.GetElement().GetBundleName(), "baseBundle"); + EXPECT_EQ(recentList[0].baseWant.GetElement().GetDeviceID(), "baseDevice"); + + EXPECT_EQ(recentList[0].baseAbility.GetAbilityName(), "baseAbility"); + EXPECT_EQ(recentList[0].baseAbility.GetBundleName(), "baseBundle"); + EXPECT_EQ(recentList[0].baseAbility.GetDeviceID(), "baseDevice"); + + EXPECT_EQ(recentList[0].topAbility.GetAbilityName(), "topAbility"); + EXPECT_EQ(recentList[0].topAbility.GetBundleName(), "topBundle"); + EXPECT_EQ(recentList[0].topAbility.GetDeviceID(), "topDevice"); + + EXPECT_EQ(res, NO_ERROR); +} +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/abilitymgr/test/unittest/phone/ability_manager_test/BUILD.gn b/tools/services/abilitymgr/test/unittest/phone/ability_manager_test/BUILD.gn new file mode 100644 index 00000000000..2a803436299 --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/ability_manager_test/BUILD.gn @@ -0,0 +1,86 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/test.gni") +import("//foundation/aafwk/standard/aafwk.gni") + +module_output_path = "aafwk_standard/abilitymgr" + +ohos_unittest("ability_manager_test") { + module_out_path = module_output_path + + sources = [ + "${services_path}/abilitymgr/src/ability_manager_client.cpp", + "//foundation/aafwk/standard/services/abilitymgr/test/mock/libs/appexecfwk_core/src/appmgr/mock_app_scheduler.cpp", + "ability_manager_test.cpp", + "iservice_registry.cpp", + "system_ability_manager.cpp", + "system_ability_manager_stub.cpp", + ] + + include_dirs = [ + "//foundation/aafwk/standard/interfaces/innerkits/ability_manager/include", + "//utils/system/safwk/native/include", + "//foundation/distributedschedule/samgr/services/samgr/native/include", + "//foundation/aafwk/standard/services/abilitymgr/test/mock/libs/ability_scheduler_mock", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy/include/", + "//foundation/aafwk/services/abilitymgr/test/mock/libs/ability_scheduler_mock/", + "//foundation/distributedschedule/samgr/adapter/interfaces/innerkits/include/", + "//foundation/distributeddatamgr/distributeddatamgr/interfaces/innerkits/app_distributeddata/include/", + "//foundation/distributedschedule/samgr/adapter/interfaces/innerkits/include/", + "//foundation/distributeddatamgr/distributeddatamgr/services/distributeddataservice/libs/distributeddb/communicator/include/", + "//foundation/distributedschedule/samgr/utils/native/include/", + "//foundation/communication/ipc/ipc/dnetwork_temp/", + ] + + configs = [ + "${services_path}/abilitymgr:abilityms_config", + "${services_path}/abilitymgr/test/mock:aafwk_mock_config", + ] + + cflags_cc = [ "-fexceptions" ] + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + deps = [ + "${innerkits_path}/want:want", + "${services_path}/abilitymgr/test:abilityms_test_source", + "${services_path}/abilitymgr/test/mock/libs/aakit:aakit_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_appmgr_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_bundlemgr_mock", + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/frameworks/kits/ability/native:dummy_classes", + + # "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + # "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_core:appexecfwk_core", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//foundation/distributedschedule/safwk/interfaces/innerkits/safwk:system_ability_fwk", + "//third_party/googletest:gmock_main", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + "ipc:libdbinder", + ] +} + +group("unittest") { + testonly = true + + deps = [ ":ability_manager_test" ] +} diff --git a/tools/services/abilitymgr/test/unittest/phone/ability_manager_test/ability_manager_stub_mock.h b/tools/services/abilitymgr/test/unittest/phone/ability_manager_test/ability_manager_stub_mock.h new file mode 100644 index 00000000000..dbdc314de42 --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/ability_manager_test/ability_manager_stub_mock.h @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ABILITY_UNITTEST_ABILITY_MANAGER_STUB_MOCK_H +#define ABILITY_UNITTEST_ABILITY_MANAGER_STUB_MOCK_H +#include +#include +#include +#include "hilog_wrapper.h" +#include "ability_manager_interface.h" + +namespace OHOS { +namespace AAFwk { +class AbilityManagerStubMock : public IRemoteStub { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"IAbilityManagerMock"); + + AbilityManagerStubMock() + {} + virtual ~AbilityManagerStubMock() + {} + + MOCK_METHOD4(SendRequest, int(uint32_t, MessageParcel &, MessageParcel &, MessageOption &)); + MOCK_METHOD2(StartAbility, int(const Want &, int)); + MOCK_METHOD3(TerminateAbility, int(const sptr &, int, const Want *)); + MOCK_METHOD3(ConnectAbility, int(const Want &, const sptr &, const sptr &)); + + MOCK_METHOD1(DisconnectAbility, int(const sptr &)); + MOCK_METHOD3(AcquireDataAbility, sptr(const Uri &, bool, const sptr &)); + MOCK_METHOD2(ReleaseDataAbility, int(sptr, const sptr &)); + MOCK_METHOD2(AddWindowInfo, void(const sptr &, int32_t)); + MOCK_METHOD2(AttachAbilityThread, int(const sptr &, const sptr &)); + MOCK_METHOD2(AbilityTransitionDone, int(const sptr &, int)); + MOCK_METHOD2(ScheduleConnectAbilityDone, int(const sptr &, const sptr &)); + MOCK_METHOD1(ScheduleDisconnectAbilityDone, int(const sptr &)); + MOCK_METHOD1(ScheduleCommandAbilityDone, int(const sptr &)); + MOCK_METHOD2(DumpState, void(const std::string &, std::vector &)); + MOCK_METHOD2(TerminateAbilityResult, int(const sptr &, int)); + MOCK_METHOD1(StopServiceAbility, int(const Want &)); + MOCK_METHOD1(GetAllStackInfo, int(StackInfo &)); + MOCK_METHOD3(GetRecentMissions, int(const int32_t, const int32_t, std::vector &)); + MOCK_METHOD2(GetMissionSnapshot, int(const int32_t, MissionSnapshotInfo &)); + MOCK_METHOD1(RemoveMission, int(int)); + MOCK_METHOD1(RemoveStack, int(int)); + MOCK_METHOD1(MoveMissionToTop, int(int32_t)); + MOCK_METHOD1(KillProcess, int(const std::string &)); + MOCK_METHOD1(UninstallApp, int(const std::string &)); + MOCK_METHOD2(TerminateAbilityByCaller, int(const sptr &callerToken, int requestCode)); + MOCK_METHOD3(StartAbility, int(const Want &want, const sptr &callerToken, int requestCode)); + MOCK_METHOD2(MoveMissionToEnd, int(const sptr &token, const bool nonFirst)); + MOCK_METHOD1(IsFirstInMission, bool(const sptr &token)); + MOCK_METHOD4(CompelVerifyPermission, int(const std::string &permission, int pid, int uid, std::string &message)); + MOCK_METHOD0(PowerOff, int()); + MOCK_METHOD0(PowerOn, int()); + MOCK_METHOD1(LockMission, int(int)); + MOCK_METHOD1(UnlockMission, int(int)); + MOCK_METHOD2(SetMissionDescriptionInfo, int(const sptr &token, const MissionDescriptionInfo &info)); + MOCK_METHOD0(GetMissionLockModeState, int()); + MOCK_METHOD1(UpdateConfiguration, int(const DummyConfiguration &)); + MOCK_METHOD2( + GetWantSender, sptr(const WantSenderInfo &wantSenderInfo, const sptr &callerToken)); + MOCK_METHOD2(SendWantSender, int(const sptr &target, const SenderInfo &senderInfo)); + MOCK_METHOD1(CancelWantSender, void(const sptr &sender)); + MOCK_METHOD1(GetPendingWantUid, int(const sptr &target)); + MOCK_METHOD1(GetPendingWantUserId, int(const sptr &target)); + MOCK_METHOD1(GetPendingWantBundleName, std::string(const sptr &target)); + MOCK_METHOD1(GetPendingWantCode, int(const sptr &target)); + MOCK_METHOD1(GetPendingWantType, int(const sptr &target)); + MOCK_METHOD2(RegisterCancelListener, void(const sptr &sender, const sptr &receiver)); + MOCK_METHOD2(UnregisterCancelListener, void(const sptr &sender, const sptr &receiver)); + MOCK_METHOD2(GetPendingRequestWant, int(const sptr &target, std::shared_ptr &want)); + + MOCK_METHOD4(StartAbility, int(const Want &want, const AbilityStartSetting &abilityStartSetting, + const sptr &callerToken, int requestCode)); + MOCK_METHOD1(MoveMissionToFloatingStack, int(const MissionOption &missionOption)); + MOCK_METHOD1(MoveMissionToSplitScreenStack, int(const MissionOption &missionOption)); + MOCK_METHOD2( + ChangeFocusAbility, int(const sptr &lostFocusToken, const sptr &getFocusToken)); + MOCK_METHOD1(MinimizeMultiWindow, int(int missionId)); + MOCK_METHOD1(GetFloatingMissions, int(std::vector &list)); + MOCK_METHOD1(CloseMultiWindow, int(int missionId)); + MOCK_METHOD1(SetMissionStackSetting, int(const StackSetting &stackSetting)); + MOCK_METHOD1(MaximizeMultiWindow, int(int missionId)); +}; +} // namespace AAFwk +} // namespace OHOS + +#endif diff --git a/tools/services/abilitymgr/test/unittest/phone/ability_manager_test/ability_manager_test.cpp b/tools/services/abilitymgr/test/unittest/phone/ability_manager_test/ability_manager_test.cpp new file mode 100644 index 00000000000..901a33f190c --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/ability_manager_test/ability_manager_test.cpp @@ -0,0 +1,330 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#define private public +#define protected public +#include "system_ability_definition.h" +#include "ability_manager_client.h" +#undef private +#undef protected + +#include "ability_manager_stub_mock.h" +#include "ability_scheduler_mock.h" +#include "ability_manager_service.h" +#include "iservice_registry.h" +#include "ability_record.h" +#include "ability_scheduler.h" +#include "mock_ability_connect_callback.h" +#include "mock_bundle_manager.h" +#include "sa_mgr_client.h" + +using namespace testing::ext; +using namespace OHOS::AppExecFwk; + +namespace OHOS { +namespace AAFwk { +namespace { +const std::string LAUNCHER_ABILITY = "MainAbility"; +const std::string LAUNCHER_BUNDLE = "com.ohos.hiworld"; +const std::string NAME_BUNDLE_MGR_SERVICE = "BundleMgrService"; +const std::string NAME_ABILITY_MGR_SERVICE = "AbilityManagerService"; +const std::string SERVICE_ABILITY = "ServiceAbility"; +const std::string SERVICE_BUNDLE = "com.ohos.hiservcie"; +} // namespace + +class AbilityManagerTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + +public: + static constexpr int TEST_WAIT_TIME = 100000; + std::shared_ptr abilityClient_ = nullptr; + sptr mock_{nullptr}; + Want want_{}; +}; + +void AbilityManagerTest::SetUpTestCase(void) +{} +void AbilityManagerTest::TearDownTestCase(void) +{} +void AbilityManagerTest::TearDown(void) +{} + +void AbilityManagerTest::SetUp(void) +{ + abilityClient_ = std::make_shared(); + mock_ = new AbilityManagerStubMock(); +} + +/* + * Feature: AbilityManagerClient + * Function: StartAbility + * SubFunction: NA + * FunctionPoints: AbilityManagerClient StartAbility + * EnvConditions: NA + * CaseDescription: Verify the normal and abnormal cases of startability + */ +HWTEST_F(AbilityManagerTest, AAFWK_AbilityMS_AbilityManager_test_001, TestSize.Level2) +{ + abilityClient_->remoteObject_ = mock_; + EXPECT_CALL(*mock_, StartAbility(::testing::_, ::testing::_)).Times(1); + EXPECT_EQ(abilityClient_->StartAbility(want_), 0); + + abilityClient_->remoteObject_ = nullptr; + EXPECT_EQ(abilityClient_->StartAbility(want_), ABILITY_SERVICE_NOT_CONNECTED); +} + +/* + * Feature: AbilityManagerClient + * Function: AttachAbilityThread + * SubFunction: NA + * FunctionPoints: AbilityManagerClient AttachAbilityThread + * EnvConditions: NA + * CaseDescription: Verify the normal and abnormal cases of attachAbilityThread + */ +HWTEST_F(AbilityManagerTest, AAFWK_AbilityMS_AbilityManager_test_002, TestSize.Level2) +{ + abilityClient_->remoteObject_ = mock_; + EXPECT_CALL(*mock_, AttachAbilityThread(::testing::_, ::testing::_)).Times(1); + + sptr scheduler = new AbilitySchedulerMock(); + sptr token = nullptr; + EXPECT_EQ(abilityClient_->AttachAbilityThread(scheduler, token), 0); + + abilityClient_->remoteObject_ = nullptr; + EXPECT_EQ(abilityClient_->AttachAbilityThread(scheduler, token), ABILITY_SERVICE_NOT_CONNECTED); +} + +/* + * Feature: AbilityManagerClient + * Function: AbilityTransitionDone + * SubFunction: NA + * FunctionPoints: AbilityManagerClient AbilityTransitionDone + * EnvConditions: NA + * CaseDescription: Verify the normal and abnormal cases of abilityTransitionDone + */ +HWTEST_F(AbilityManagerTest, AAFWK_AbilityMS_AbilityManager_test_003, TestSize.Level2) +{ + abilityClient_->remoteObject_ = mock_; + EXPECT_CALL(*mock_, AbilityTransitionDone(::testing::_, ::testing::_)).Times(1); + + sptr scheduler = new AbilitySchedulerMock(); + sptr token = nullptr; + EXPECT_EQ(abilityClient_->AbilityTransitionDone(token, 1), 0); + + abilityClient_->remoteObject_ = nullptr; + EXPECT_EQ(abilityClient_->AbilityTransitionDone(token, 1), ABILITY_SERVICE_NOT_CONNECTED); +} + +/* + * Feature: AbilityManagerClient + * Function: ScheduleConnectAbilityDone + * SubFunction: NA + * FunctionPoints: AbilityManagerClient ScheduleConnectAbilityDone + * EnvConditions: NA + * CaseDescription: Verify the normal and abnormal cases of scheduleConnectAbilityDone + */ +HWTEST_F(AbilityManagerTest, AAFWK_AbilityMS_AbilityManager_test_004, TestSize.Level2) +{ + abilityClient_->remoteObject_ = mock_; + EXPECT_CALL(*mock_, ScheduleConnectAbilityDone(::testing::_, ::testing::_)).Times(1); + + sptr scheduler = new AbilitySchedulerMock(); + sptr token = nullptr; + sptr remoteObject = nullptr; + EXPECT_EQ(abilityClient_->ScheduleConnectAbilityDone(token, remoteObject), 0); + + abilityClient_->remoteObject_ = nullptr; + EXPECT_EQ(abilityClient_->ScheduleConnectAbilityDone(token, remoteObject), ABILITY_SERVICE_NOT_CONNECTED); +} + +/* + * Feature: AbilityManagerClient + * Function: ScheduleDisconnectAbilityDone + * SubFunction: NA + * FunctionPoints: AbilityManagerClient ScheduleDisconnectAbilityDone + * EnvConditions: NA + * CaseDescription: Verify the normal and abnormal cases of scheduleDisconnectAbilityDone + */ +HWTEST_F(AbilityManagerTest, AAFWK_AbilityMS_AbilityManager_test_005, TestSize.Level2) +{ + abilityClient_->remoteObject_ = mock_; + EXPECT_CALL(*mock_, ScheduleDisconnectAbilityDone(::testing::_)).Times(1); + + sptr scheduler = new AbilitySchedulerMock(); + sptr token = nullptr; + sptr remoteObject = nullptr; + EXPECT_EQ(abilityClient_->ScheduleDisconnectAbilityDone(token), 0); + + abilityClient_->remoteObject_ = nullptr; + EXPECT_EQ(abilityClient_->ScheduleDisconnectAbilityDone(token), ABILITY_SERVICE_NOT_CONNECTED); +} + +/* + * Feature: AbilityManagerClient + * Function: AddWindowInfo + * SubFunction: NA + * FunctionPoints: AbilityManagerClient AddWindowInfo + * EnvConditions: NA + * CaseDescription: Verify the normal and abnormal cases of addWindowInfo + */ +HWTEST_F(AbilityManagerTest, AAFWK_AbilityMS_AbilityManager_test_006, TestSize.Level2) +{ + std::string args; + abilityClient_->remoteObject_ = mock_; + EXPECT_CALL(*mock_, AddWindowInfo(::testing::_, ::testing::_)).Times(1); + + sptr scheduler = new AbilitySchedulerMock(); + sptr token = nullptr; + int32_t t = 1; + abilityClient_->AddWindowInfo(token, t); + abilityClient_->remoteObject_ = nullptr; + abilityClient_->AddWindowInfo(token, 1); +} + +/* + * Feature: AbilityManagerClient + * Function: TerminateAbility + * SubFunction: NA + * FunctionPoints: AbilityManagerClient TerminateAbility + * EnvConditions: NA + * CaseDescription: Verify the normal and abnormal cases of terminateAbility + */ +HWTEST_F(AbilityManagerTest, AAFWK_AbilityMS_AbilityManager_test_007, TestSize.Level2) +{ + abilityClient_->remoteObject_ = mock_; + EXPECT_CALL(*mock_, TerminateAbility(::testing::_, ::testing::_, ::testing::_)).Times(1); + + sptr scheduler = new AbilitySchedulerMock(); + sptr token = nullptr; + EXPECT_EQ(abilityClient_->TerminateAbility(token, 1, &want_), 0); + + abilityClient_->remoteObject_ = nullptr; + EXPECT_EQ(abilityClient_->TerminateAbility(token, 1, &want_), ABILITY_SERVICE_NOT_CONNECTED); +} + +/* + * Feature: AbilityManagerClient + * Function: ConnectAbility + * SubFunction: NA + * FunctionPoints: AbilityManagerClient ConnectAbility + * EnvConditions: NA + * CaseDescription: Verify the normal and abnormal cases of ConnectAbility + */ +HWTEST_F(AbilityManagerTest, AAFWK_AbilityMS_AbilityManager_test_008, TestSize.Level2) +{ + abilityClient_->remoteObject_ = mock_; + EXPECT_CALL(*mock_, ConnectAbility(::testing::_, ::testing::_, ::testing::_)).Times(1); + + sptr connect = nullptr; + sptr callerToken = nullptr; + EXPECT_EQ(abilityClient_->ConnectAbility(want_, connect, callerToken), 0); + + abilityClient_->remoteObject_ = nullptr; + EXPECT_EQ(abilityClient_->ConnectAbility(want_, connect, callerToken), ABILITY_SERVICE_NOT_CONNECTED); +} + +/* + * Feature: AbilityManagerClient + * Function: DisconnectAbility + * SubFunction: NA + * FunctionPoints: AbilityManagerClient DisconnectAbility + * EnvConditions: NA + * CaseDescription: Verify the normal and abnormal cases of DisconnectAbility + */ +HWTEST_F(AbilityManagerTest, AAFWK_AbilityMS_AbilityManager_test_009, TestSize.Level2) +{ + abilityClient_->remoteObject_ = mock_; + EXPECT_CALL(*mock_, DisconnectAbility(::testing::_)).Times(1); + + sptr connect = nullptr; + EXPECT_EQ(abilityClient_->DisconnectAbility(connect), 0); + + abilityClient_->remoteObject_ = nullptr; + EXPECT_EQ(abilityClient_->DisconnectAbility(connect), ABILITY_SERVICE_NOT_CONNECTED); +} + +/* + * Feature: AbilityManagerClient + * Function: DumpState + * SubFunction: NA + * FunctionPoints: AbilityManagerClient DumpState + * EnvConditions: NA + * CaseDescription: Verify the normal and abnormal cases of DumpState + */ +HWTEST_F(AbilityManagerTest, AAFWK_AbilityMS_AbilityManager_test_010, TestSize.Level2) +{ + std::string args; + std::vector vec; + abilityClient_->remoteObject_ = mock_; + EXPECT_CALL(*mock_, DumpState(::testing::_, ::testing::_)).Times(1); + + sptr connect = nullptr; + EXPECT_EQ(abilityClient_->DumpState(args, vec), 0); + + abilityClient_->remoteObject_ = nullptr; + EXPECT_EQ(abilityClient_->DumpState(args, vec), ABILITY_SERVICE_NOT_CONNECTED); +} + +/* + * Feature: AbilityManagerClient + * Function: GetAllStackInfo + * SubFunction: NA + * FunctionPoints: AbilityManagerClient GetAllStackInfo + * EnvConditions: NA + * CaseDescription: Verify the normal and abnormal cases of GetAllStackInfo + */ +HWTEST_F(AbilityManagerTest, AAFWK_AbilityMS_AbilityManager_test_011, TestSize.Level2) +{ + std::string args; + std::vector vec; + abilityClient_->remoteObject_ = mock_; + EXPECT_CALL(*mock_, GetAllStackInfo(::testing::_)).Times(1); + + StackInfo info; + EXPECT_EQ(abilityClient_->GetAllStackInfo(info), 0); + + abilityClient_->remoteObject_ = nullptr; + EXPECT_EQ(abilityClient_->GetAllStackInfo(info), ABILITY_SERVICE_NOT_CONNECTED); +} + +/* + * Feature: AbilityManagerClient + * Function: Connect + * SubFunction: NA + * FunctionPoints: AbilityManagerClient Connect + * EnvConditions: NA + * CaseDescription: Verify Connect operation + */ +HWTEST_F(AbilityManagerTest, AAFWK_AbilityMS_AbilityManager_test_012, TestSize.Level2) +{ + abilityClient_->remoteObject_ = mock_; + EXPECT_EQ(abilityClient_->Connect(), 0); + + sptr manager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + ISystemAbilityManager::SAExtraProp prop; + manager->AddSystemAbility(ABILITY_MGR_SERVICE_ID, mock_, prop); + + abilityClient_->remoteObject_ = nullptr; + + EXPECT_EQ(abilityClient_->Connect(), 0); +} +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/abilitymgr/test/unittest/phone/ability_manager_test/iservice_registry.cpp b/tools/services/abilitymgr/test/unittest/phone/ability_manager_test/iservice_registry.cpp new file mode 100644 index 00000000000..ed29383e696 --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/ability_manager_test/iservice_registry.cpp @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "iservice_registry.h" +#include "hilog_wrapper.h" +#include "system_ability_manager.h" + +namespace OHOS { + +SystemAbilityManagerClient &SystemAbilityManagerClient::GetInstance() +{ + HILOG_ERROR(" SystemAbilityManagerClient::GetInstance()"); + static auto instance = new SystemAbilityManagerClient(); + return *instance; +} + +sptr SystemAbilityManagerClient::GetSystemAbilityManager() +{ + HILOG_ERROR(" SystemAbilityManagerClient::GetSystemAbilityManager()"); + return SystemAbilityManager::GetInstance(); +} + +sptr SystemAbilityManagerClient::GetRegistryRemoteObject() +{ + HILOG_ERROR("SystemAbilityManagerClient::GetRegistryRemoteObject()"); + return nullptr; +} + +void SystemAbilityManagerClient::DestroySystemAbilityManagerObject() +{ + HILOG_ERROR("SystemAbilityManagerClient::DestroySystemAbilityManagerObject()"); +} + +} // namespace OHOS diff --git a/tools/services/abilitymgr/test/unittest/phone/ability_manager_test/system_ability_manager.cpp b/tools/services/abilitymgr/test/unittest/phone/ability_manager_test/system_ability_manager.cpp new file mode 100644 index 00000000000..93ded4645ed --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/ability_manager_test/system_ability_manager.cpp @@ -0,0 +1,299 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "system_ability_manager.h" +#include +#include +#include "ability_death_recipient.h" +#include "datetime_ex.h" +#include "errors.h" +#include "if_local_ability_manager.h" +#include "local_ability_manager_proxy.h" +#include "sam_log.h" +#include "string_ex.h" +#include "system_ability_connection_callback_proxy.h" +#include "system_ability_definition.h" +#include "tools.h" +#include "hilog_wrapper.h" + +using namespace std; + +namespace OHOS { +namespace {} // namespace + +std::mutex SystemAbilityManager::instanceLock; +sptr SystemAbilityManager::instance; + +SystemAbilityManager::SystemAbilityManager() +{} + +SystemAbilityManager::~SystemAbilityManager() +{} + +void SystemAbilityManager::Init() +{} + +const sptr SystemAbilityManager::GetDBinder() const +{ + return nullptr; +} + +sptr SystemAbilityManager::GetInstance() +{ + HILOG_ERROR("SystemAbilityManager::GetInstance"); + std::lock_guard autoLock(instanceLock); + if (instance == nullptr) { + instance = new SystemAbilityManager; + } + return instance; +} + +void SystemAbilityManager::DoSADataStorageInit() +{} + +sptr SystemAbilityManager::GetSystemAbility(int32_t systemAbilityId) +{ + HILOG_ERROR("SystemAbilityManager::GetSystemAbility"); + auto iter = abilityMap_.find(systemAbilityId); + if (iter != abilityMap_.end()) { + return iter->second.remoteObj; + } + HILOG_ERROR("SystemAbilityManager::GetSystemAbility nullptr"); + return nullptr; +} + +bool SystemAbilityManager::GetSystemAbilityInfoList(int32_t systemAbilityId, const std::u16string &capability, + std::list> &saInfoList) +{ + return true; +} + +sptr SystemAbilityManager::CheckLocalAbilityManager(const u16string &strName) +{ + return nullptr; +} + +sptr SystemAbilityManager::GetSystemAbility(int32_t systemAbilityId, const std::string &deviceId) +{ + return nullptr; +} + +sptr SystemAbilityManager::CheckSystemAbility(int32_t systemAbilityId) +{ + return nullptr; +} + +bool SystemAbilityManager::CheckDistributedPermission() +{ + return true; +} + +sptr SystemAbilityManager::CheckSystemAbility(int32_t systemAbilityId, const std::string &deviceId) +{ + return nullptr; +} + +int32_t SystemAbilityManager::FindSystemAbilityManagerNotify(int32_t systemAbilityId, int code) +{ + return 0; +} + +int32_t SystemAbilityManager::FindSystemAbilityManagerNotify( + int32_t systemAbilityId, const std::string &deviceId, int code) +{ + return ERR_OK; +} + +bool SystemAbilityManager::IsNameInValid(const std::u16string &name) +{ + return false; +} + +int32_t SystemAbilityManager::AddOnDemandSystemAbilityInfo( + int32_t systemAbilityId, const std::u16string &localAbilityManagerName) +{ + return ERR_OK; +} + +int32_t SystemAbilityManager::RecycleOnDemandSystemAbility() +{ + return ERR_OK; +} + +int32_t SystemAbilityManager::StartOnDemandAbility(int32_t systemAbilityId) +{ + return ERR_INVALID_VALUE; +} + +sptr SystemAbilityManager::CheckSystemAbility(int32_t systemAbilityId, bool &isExist) +{ + return nullptr; +} + +int32_t SystemAbilityManager::ConnectSystemAbility( + int32_t systemAbilityId, const sptr &connectionCallback) +{ + return ERR_OK; +} + +int32_t SystemAbilityManager::DisConnectSystemAbility( + int32_t systemAbilityId, const sptr &connectionCallback) +{ + return ERR_OK; +} + +bool SystemAbilityManager::CheckCapability(const std::u16string &capability) +{ + return true; +} + +int32_t SystemAbilityManager::AddLocalAbilityManager(const u16string &strName, const sptr &ability) +{ + return ERR_OK; +} + +void SystemAbilityManager::DoInsertSaData( + const u16string &strName, const sptr &ability, const SAExtraProp &extraProp) +{} + +void SystemAbilityManager::DeleteStartingAbilityMember(int32_t systemAbilityId) +{} + +int32_t SystemAbilityManager::RemoveSystemAbility(int32_t systemAbilityId) +{ + abilityMap_.clear(); + return ERR_OK; +} + +int32_t SystemAbilityManager::RemoveLocalAbilityManager(const u16string &strName) +{ + return ERR_OK; +} + +int32_t SystemAbilityManager::RemoveLocalAbilityManager(const sptr &ability) +{ + return ERR_OK; +} + +int32_t SystemAbilityManager::RemoveSystemAbility(const sptr &ability) +{ + return ERR_OK; +} + +vector SystemAbilityManager::ListSystemAbilities(unsigned int dumpFlags) +{ + vector list; + return list; +} + +u16string SystemAbilityManager::GetSystemAbilityName(int32_t index) +{ + return u16string(); +} + +int32_t SystemAbilityManager::SubscribeSystemAbility(int32_t systemAbilityId, const u16string &listenerName) +{ + return ERR_OK; +} + +int32_t SystemAbilityManager::UnSubscribeSystemAbility(int32_t systemAbilityId, const u16string &listenerName) +{ + return ERR_OK; +} + +const std::u16string SystemAbilityManager::CheckOnDemandSystemAbility(int32_t systemAbilityId) +{ + return deviceName_; +} + +void SystemAbilityManager::SetDeviceName(const u16string &name) +{} + +const u16string &SystemAbilityManager::GetDeviceName() const +{ + return deviceName_; +} + +bool SystemAbilityManager::GetDeviceId(string &deviceId) +{ + return false; +} + +void SystemAbilityManager::NotifyRemoteSaDied(const std::u16string &name) +{} + +void SystemAbilityManager::NotifyRemoteDeviceOffline(const std::string &deviceId) +{} + +void SystemAbilityManager::ParseRemoteSaName(const std::u16string &name, std::string &deviceId, std::u16string &saName) +{} + +void SystemAbilityManager::OnDemandConnected(int32_t systemAbilityId, const sptr &ability) +{} + +int32_t SystemAbilityManager::AddSystemAbility( + int32_t systemAbilityId, const sptr &ability, const SAExtraProp &extraProp) +{ + SAInfo saInfo; + saInfo.remoteObj = ability; + saInfo.isDistributed = extraProp.isDistributed; + saInfo.capability = extraProp.capability; + saInfo.permission = Str16ToStr8(extraProp.permission); + abilityMap_[systemAbilityId] = std::move(saInfo); + return 0; +} + +bool SystemAbilityManager::IsLocalDeviceId(const std::string &deviceId) +{ + return false; +} + +bool SystemAbilityManager::CheckRemoteSa(const std::string &saName, std::string &selectedDeviceId) +{ + return false; +} + +bool SystemAbilityManager::CheckPermission(const std::string &permission) +{ + return true; +} + +int32_t SystemAbilityManager::AddSystemCapability(const std::string &sysCap) +{ + return 1; +} + +bool SystemAbilityManager::HasSystemCapability(const std::string &sysCap) +{ + return false; +} + +std::vector SystemAbilityManager::GetSystemAvailableCapabilities() +{ + std::vector v; + return v; +} + +int32_t SystemAbilityManager::RegisterSystemReadyCallback(const sptr &systemReadyCallback) +{ + return ERR_OK; +} + +int32_t SystemAbilityManager::GetCoreSystemAbilityList(vector &coreSaList, int dumpMode) +{ + return ERR_OK; +} + +} // namespace OHOS diff --git a/tools/services/abilitymgr/test/unittest/phone/ability_manager_test/system_ability_manager_stub.cpp b/tools/services/abilitymgr/test/unittest/phone/ability_manager_test/system_ability_manager_stub.cpp new file mode 100644 index 00000000000..5e000cad0c1 --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/ability_manager_test/system_ability_manager_stub.cpp @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "system_ability_manager_stub.h" +#include "errors.h" +#include "ipc_skeleton.h" +#include "ipc_types.h" +#include "sam_log.h" +#include "string_ex.h" +#include "system_ability_info.h" +#include "tools.h" + +namespace OHOS { + +SystemAbilityManagerStub::SystemAbilityManagerStub() +{} + +int32_t SystemAbilityManagerStub::OnRemoteRequest( + uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) +{ + return 0; +} + +bool SystemAbilityManagerStub::EnforceInterceToken(MessageParcel &data) +{ + return false; +} + +int32_t SystemAbilityManagerStub::GetSystemAbilityInfoListInner(MessageParcel &data, MessageParcel &reply) +{ + return ERR_NONE; +} + +int32_t SystemAbilityManagerStub::CheckLocalAbilityInner(MessageParcel &data, MessageParcel &reply) +{ + return ERR_NONE; +} + +int32_t SystemAbilityManagerStub::AddLocalAbilityInner(MessageParcel &data, MessageParcel &reply) +{ + return 0; +} + +int32_t SystemAbilityManagerStub::RemoveLocalAbilityInner(MessageParcel &data, MessageParcel &reply) +{ + return 0; +} + +int32_t SystemAbilityManagerStub::ListSystemAbilityInner(MessageParcel &data, MessageParcel &reply) +{ + return 0; +} + +int32_t SystemAbilityManagerStub::SubsSystemAbilityInner(MessageParcel &data, MessageParcel &reply) +{ + return 0; +} + +int32_t SystemAbilityManagerStub::UnSubsSystemAbilityInner(MessageParcel &data, MessageParcel &reply) +{ + return 0; +} + +int32_t SystemAbilityManagerStub::CheckRemtSystemAbilityInner(MessageParcel &data, MessageParcel &reply) +{ + return 0; +} + +int32_t SystemAbilityManagerStub::CheckRemtSystemAbilityForJavaInner(MessageParcel &data, MessageParcel &reply) +{ + return 0; +} + +int32_t SystemAbilityManagerStub::AddOndemandSystemAbilityInner(MessageParcel &data, MessageParcel &reply) +{ + return 0; +} + +int32_t SystemAbilityManagerStub::RecycleOndemandSystemAbilityInner(MessageParcel &data, MessageParcel &reply) +{ + return 0; +} + +int32_t SystemAbilityManagerStub::CheckSystemAbilityImmeInner(MessageParcel &data, MessageParcel &reply) +{ + return 0; +} + +int32_t SystemAbilityManagerStub::ConnOndemandSystemAbilityInner(MessageParcel &data, MessageParcel &reply) +{ + return 0; +} + +int32_t SystemAbilityManagerStub::DisConnOndemandSystemAbilityInner(MessageParcel &data, MessageParcel &reply) +{ + return 0; +} + +int32_t SystemAbilityManagerStub::CheckOndemandSystemAbilityInner(MessageParcel &data, MessageParcel &reply) +{ + return 0; +} + +int32_t SystemAbilityManagerStub::GetDeviceIdInner(MessageParcel &data, MessageParcel &reply) +{ + return 0; +} + +int32_t SystemAbilityManagerStub::UnmarshalingSaExtraProp(MessageParcel &data, SAExtraProp &extraProp) +{ + return 0; +} + +int32_t SystemAbilityManagerStub::AddSystemAbilityInner(MessageParcel &data, MessageParcel &reply) +{ + return 0; +} + +int32_t SystemAbilityManagerStub::GetSystemAbilityInner(MessageParcel &data, MessageParcel &reply) +{ + return 0; +} + +int32_t SystemAbilityManagerStub::CheckSystemAbilityInner(MessageParcel &data, MessageParcel &reply) +{ + return 0; +} + +int32_t SystemAbilityManagerStub::RemoveSystemAbilityInner(MessageParcel &data, MessageParcel &reply) +{ + return 0; +} + +int32_t SystemAbilityManagerStub::GetHapIdMultiuser(int32_t uid) +{ + return 0; +} + +bool SystemAbilityManagerStub::CanRequest() +{ + return true; +} +} // namespace OHOS diff --git a/tools/services/abilitymgr/test/unittest/phone/ability_record_test/BUILD.gn b/tools/services/abilitymgr/test/unittest/phone/ability_record_test/BUILD.gn new file mode 100644 index 00000000000..a9442dcb066 --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/ability_record_test/BUILD.gn @@ -0,0 +1,65 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/test.gni") +import("//foundation/aafwk/standard/aafwk.gni") + +module_output_path = "aafwk_standard/abilitymgr" + +ohos_unittest("ability_record_test") { + module_out_path = module_output_path + + include_dirs = [ + "${services_path}/abilitymgr/test/mock/libs/system_ability_mock", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy/include", + ] + + sources = [ + "//foundation/aafwk/standard/services/abilitymgr/test/mock/libs/appexecfwk_core/src/appmgr/mock_app_scheduler.cpp", + "ability_record_test.cpp", # add mock file + ] + + configs = [ + "${services_path}/abilitymgr:abilityms_config", + "${services_path}/abilitymgr/test/mock:aafwk_mock_config", + ] + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + deps = [ + "${innerkits_path}/want:want", + "${services_path}/abilitymgr/test:abilityms_test_source", + "${services_path}/abilitymgr/test/mock/libs/aakit:aakit_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_appmgr_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_bundlemgr_mock", + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/frameworks/kits/ability/native:dummy_classes", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] +} + +group("unittest") { + testonly = true + + deps = [ ":ability_record_test" ] +} diff --git a/tools/services/abilitymgr/test/unittest/phone/ability_record_test/ability_record_test.cpp b/tools/services/abilitymgr/test/unittest/phone/ability_record_test/ability_record_test.cpp new file mode 100755 index 00000000000..23ca762c114 --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/ability_record_test/ability_record_test.cpp @@ -0,0 +1,727 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#define private public +#define protected public +#include "ability_record.h" +#undef private +#undef protected + +#include "ability_manager_service.h" +#include "ability_scheduler.h" +#include "connection_record.h" +#include "mission_record.h" +#include "mock_ability_connect_callback.h" +#include "ability_connect_callback_stub.h" + +using namespace testing::ext; + +namespace OHOS { +namespace AAFwk { + +class AbilityRecordTest : public testing::TestWithParam { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + + std::shared_ptr abilityRecord_{nullptr}; + std::shared_ptr abilityResult_{nullptr}; + std::shared_ptr abilityRequest_{nullptr}; + static constexpr unsigned int CHANGE_CONFIG_LOCALE = 0x00000001; +}; + +void AbilityRecordTest::SetUpTestCase(void) +{ + OHOS::DelayedSingleton::GetInstance()->OnStart(); +} +void AbilityRecordTest::TearDownTestCase(void) +{ + OHOS::DelayedSingleton::GetInstance()->OnStop(); + OHOS::DelayedSingleton::DestroyInstance(); +} + +void AbilityRecordTest::SetUp(void) +{ + OHOS::AppExecFwk::AbilityInfo abilityInfo; + OHOS::AppExecFwk::ApplicationInfo applicationInfo; + Want want; + abilityRecord_ = std::make_shared(want, abilityInfo, applicationInfo); + abilityResult_ = std::make_shared(-1, -1, want); + abilityRequest_ = std::make_shared(); + abilityRecord_->Init(); +} + +void AbilityRecordTest::TearDown(void) +{ + abilityRecord_.reset(); +} + +bool IsTestAbilityExist(const std::string &data) +{ + return std::string::npos != data.find("previous ability app name [NULL]"); +} + +bool IsTestAbilityExist1(const std::string &data) +{ + return std::string::npos != data.find("test_pre_app"); +} + +bool IsTestAbilityExist2(const std::string &data) +{ + return std::string::npos != data.find("test_next_app"); +} + +/* + * Feature: AbilityRecord + * Function: GetRecordId + * SubFunction: GetRecordId + * FunctionPoints: NA + * EnvConditions:NA + * CaseDescription: Verify create one abilityRecord could through GetRecordId 1 + */ +HWTEST_F(AbilityRecordTest, AaFwk_AbilityMS_GetRecordId, TestSize.Level1) +{ + EXPECT_EQ(abilityRecord_->GetRecordId(), 0); +} + +/* + * Feature: AbilityRecord + * Function: create AbilityRecord + * SubFunction: NA + * FunctionPoints: LoadAbility Activate Inactivate MoveToBackground + * EnvConditions:NA + * CaseDescription: LoadAbility Activate Inactivate MoveToBackground UT. + */ +HWTEST_F(AbilityRecordTest, AaFwk_AbilityMS_UpdateLifeState, TestSize.Level1) +{ + abilityRecord_->LoadAbility(); + EXPECT_EQ(abilityRecord_->GetAbilityState(), OHOS::AAFwk::AbilityState::INITIAL); + abilityRecord_->Activate(); + EXPECT_EQ(abilityRecord_->GetAbilityState(), OHOS::AAFwk::AbilityState::ACTIVATING); + abilityRecord_->Inactivate(); + EXPECT_EQ(abilityRecord_->GetAbilityState(), OHOS::AAFwk::AbilityState::INACTIVATING); + abilityRecord_->MoveToBackground(nullptr); + EXPECT_EQ(abilityRecord_->GetAbilityState(), OHOS::AAFwk::AbilityState::MOVING_BACKGROUND); +} + +/* + * Feature: AbilityRecord + * Function: create AbilityRecord + * SubFunction: NA + * FunctionPoints: SetMissionRecord GetMissionRecord + * EnvConditions:NA + * CaseDescription: SetMissionRecord GetMissionRecord UT. + */ +HWTEST_F(AbilityRecordTest, AaFwk_AbilityMS_SetGetMissionRecord, TestSize.Level1) +{ + std::shared_ptr missionRecord = std::make_shared(); + abilityRecord_->SetMissionRecord(missionRecord); + EXPECT_EQ(abilityRecord_->GetMissionRecord().get(), missionRecord.get()); +} + +/* + * Feature: AbilityRecord + * Function: create AbilityRecord + * SubFunction: NA + * FunctionPoints: SetAbilityInfo GetAbilityInfo + * EnvConditions:NA + * CaseDescription: SetAbilityInfo GetAbilityInfo UT. + */ +HWTEST_F(AbilityRecordTest, AaFwk_AbilityMS_SetGetAbilityInfo, TestSize.Level1) +{ + Want want; + OHOS::AppExecFwk::AbilityInfo abilityInfo; + abilityInfo.applicationName = std::string("TestApp"); + OHOS::AppExecFwk::ApplicationInfo applicationInfo; + std::shared_ptr abilityRecord = std::make_shared(want, abilityInfo, applicationInfo); + EXPECT_EQ(abilityRecord->GetAbilityInfo().applicationName, std::string("TestApp")); +} + +/* + * Feature: AbilityRecord + * Function: create AbilityRecord + * SubFunction: NA + * FunctionPoints: SetApplicationInfo GetApplicationInfo + * EnvConditions:NA + * CaseDescription: SetApplicationInfo GetApplicationInfo UT. + */ +HWTEST_F(AbilityRecordTest, AaFwk_AbilityMS_SetGetApplicationInfo, TestSize.Level1) +{ + Want want; + OHOS::AppExecFwk::AbilityInfo abilityInfo; + OHOS::AppExecFwk::ApplicationInfo applicationInfo; + applicationInfo.name = "TestApp"; + std::shared_ptr abilityRecord = std::make_shared(want, abilityInfo, applicationInfo); + EXPECT_EQ(abilityRecord->GetApplicationInfo().name, "TestApp"); +} + +/* + * Feature: AbilityRecord + * Function: create AbilityRecord + * SubFunction: NA + * FunctionPoints: SetAbilityState GetAbilityState + * EnvConditions:NA + * CaseDescription: SetAbilityState GetAbilityState UT. + */ +HWTEST_P(AbilityRecordTest, AaFwk_AbilityMS_SetGetAbilityState, TestSize.Level1) +{ + OHOS::AAFwk::AbilityState state = GetParam(); + abilityRecord_->SetAbilityState(state); + EXPECT_EQ(static_cast(state), static_cast(abilityRecord_->GetAbilityState())); +} + +INSTANTIATE_TEST_CASE_P(AbilityRecordTestCaseP, AbilityRecordTest, + testing::Values(OHOS::AAFwk::AbilityState::INITIAL, OHOS::AAFwk::AbilityState::INACTIVE, + OHOS::AAFwk::AbilityState::ACTIVE, OHOS::AAFwk::AbilityState::BACKGROUND, + OHOS::AAFwk::AbilityState::SUSPENDED)); + +/* + * Feature: AbilityRecord + * Function: create AbilityRecord + * SubFunction: NA + * FunctionPoints: SetAbilityState GetAbilityState + * EnvConditions:NA + * CaseDescription: SetAbilityState GetAbilityState UT. + */ +HWTEST_F(AbilityRecordTest, AaFwk_AbilityMS_SetGetToken, TestSize.Level1) +{ + EXPECT_EQ(Token::GetAbilityRecordByToken(abilityRecord_->GetToken()).get(), abilityRecord_.get()); +} + +/* + * Feature: AbilityRecord + * Function: create AbilityRecord + * SubFunction: NA + * FunctionPoints: SetPreAbilityRecord SetNextAbilityRecord GetPreAbilityRecord GetNextAbilityRecord + * EnvConditions:NA + * CaseDescription: SetPreAbilityRecord SetNextAbilityRecord GetPreAbilityRecord GetNextAbilityRecord UT. + */ +HWTEST_F(AbilityRecordTest, AaFwk_AbilityMS_SetGetPreNextAbilityReocrd, TestSize.Level1) +{ + OHOS::AppExecFwk::AbilityInfo abilityInfo; + OHOS::AppExecFwk::ApplicationInfo applicationInfo; + Want want; + std::shared_ptr preAbilityRecord = + std::make_shared(want, abilityInfo, applicationInfo); + std::shared_ptr nextAbilityRecord = + std::make_shared(want, abilityInfo, applicationInfo); + abilityRecord_->SetPreAbilityRecord(preAbilityRecord); + abilityRecord_->SetNextAbilityRecord(nextAbilityRecord); + EXPECT_EQ(abilityRecord_->GetPreAbilityRecord().get(), preAbilityRecord.get()); + EXPECT_EQ(abilityRecord_->GetNextAbilityRecord().get(), nextAbilityRecord.get()); +} + +/* + * Feature: AbilityRecord + * Function: create AbilityRecord + * SubFunction: NA + * FunctionPoints: SetEventId GetEventId + * EnvConditions:NA + * CaseDescription: SetEventId GetEventId UT. + */ +HWTEST_F(AbilityRecordTest, AaFwk_AbilityMS_SetGetEventId, TestSize.Level1) +{ + int64_t eventId = 1; + abilityRecord_->SetEventId(eventId); + EXPECT_EQ(eventId, abilityRecord_->GetEventId()); +} + +/* + * Feature: AbilityRecord + * Function: create AbilityRecord + * SubFunction: NA + * FunctionPoints: IsReady + * EnvConditions:NA + * CaseDescription: IsReady UT. + */ +HWTEST_F(AbilityRecordTest, AaFwk_AbilityMS_IsReady, TestSize.Level1) +{ + EXPECT_EQ(false, abilityRecord_->IsReady()); + OHOS::sptr scheduler = new AbilityScheduler(); + abilityRecord_->SetScheduler(scheduler); + EXPECT_EQ(true, abilityRecord_->IsReady()); +} + +/* + * Feature: AbilityRecord + * Function: create AbilityRecord + * SubFunction: NA + * FunctionPoints: IsLauncherAbility + * EnvConditions:NA + * CaseDescription: IsLauncherAbility UT. + */ +HWTEST_F(AbilityRecordTest, AaFwk_AbilityMS_IsLauncherAbility, TestSize.Level1) +{ + EXPECT_EQ(false, abilityRecord_->IsLauncherAbility()); + Want launcherWant; + launcherWant.AddEntity(Want::ENTITY_HOME); + OHOS::AppExecFwk::AbilityInfo abilityInfo; + OHOS::AppExecFwk::ApplicationInfo applicationInfo; + std::unique_ptr launcherAbilityRecord = + std::make_unique(launcherWant, abilityInfo, applicationInfo); + launcherAbilityRecord->Init(); + EXPECT_EQ(false, launcherAbilityRecord->IsLauncherAbility()); +} + +/* + * Feature: AbilityRecord + * Function: Add connection record to ability record' list + * SubFunction: NA + * FunctionPoints: AddConnectRecordToList + * EnvConditions:NA + * CaseDescription: AddConnectRecordToList UT. + */ +HWTEST_F(AbilityRecordTest, AaFwk_AbilityMS_AddConnectRecordToList, TestSize.Level0) +{ + // test1 for input param is null + abilityRecord_->AddConnectRecordToList(nullptr); + auto connList = abilityRecord_->GetConnectRecordList(); + EXPECT_EQ(0, static_cast(connList.size())); + + // test2 for adding new connection record to empty list + OHOS::sptr callback1 = new AbilityConnectCallback(); + auto newConnRecord1 = + ConnectionRecord::CreateConnectionRecord(abilityRecord_->GetToken(), abilityRecord_, callback1); + abilityRecord_->AddConnectRecordToList(newConnRecord1); + connList = abilityRecord_->GetConnectRecordList(); + EXPECT_EQ(1, static_cast(connList.size())); + + // test3 for adding new connection record to non-empty list + OHOS::sptr callback2 = new AbilityConnectCallback(); + auto newConnRecord2 = + ConnectionRecord::CreateConnectionRecord(abilityRecord_->GetToken(), abilityRecord_, callback2); + abilityRecord_->AddConnectRecordToList(newConnRecord2); + connList = abilityRecord_->GetConnectRecordList(); + EXPECT_EQ(2, static_cast(connList.size())); + + // test4 for adding old connection record to non-empty list + abilityRecord_->AddConnectRecordToList(newConnRecord2); + connList = abilityRecord_->GetConnectRecordList(); + EXPECT_EQ(2, static_cast(connList.size())); + + // test5 for delete nullptr from list + abilityRecord_->RemoveConnectRecordFromList(nullptr); + connList = abilityRecord_->GetConnectRecordList(); + EXPECT_EQ(2, static_cast(connList.size())); + + // test6 for delete no-match member from list + auto newConnRecord3 = + ConnectionRecord::CreateConnectionRecord(abilityRecord_->GetToken(), abilityRecord_, callback2); + abilityRecord_->RemoveConnectRecordFromList(newConnRecord3); + connList = abilityRecord_->GetConnectRecordList(); + EXPECT_EQ(2, static_cast(connList.size())); + + // test7 for delete match member from list + abilityRecord_->RemoveConnectRecordFromList(newConnRecord2); + connList = abilityRecord_->GetConnectRecordList(); + EXPECT_EQ(1, static_cast(connList.size())); + + // test8 for get ability unknown type + EXPECT_EQ(OHOS::AppExecFwk::AbilityType::UNKNOWN, abilityRecord_->GetAbilityInfo().type); +} + +/* + * Feature: AbilityRecord + * Function: ConvertAbilityState + * SubFunction: NA + * FunctionPoints: NA + * EnvConditions:NA + * CaseDescription: Verify ConvertAbilityState convert success + */ +HWTEST_F(AbilityRecordTest, AaFwk_AbilityMS_ConvertAbilityState, TestSize.Level1) +{ + abilityRecord_->SetAbilityState(OHOS::AAFwk::AbilityState::INITIAL); + EXPECT_EQ(abilityRecord_->ConvertAbilityState(abilityRecord_->GetAbilityState()), "INITIAL"); + abilityRecord_->SetAbilityState(OHOS::AAFwk::AbilityState::INACTIVE); + EXPECT_EQ(abilityRecord_->ConvertAbilityState(abilityRecord_->GetAbilityState()), "INACTIVE"); + abilityRecord_->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + EXPECT_EQ(abilityRecord_->ConvertAbilityState(abilityRecord_->GetAbilityState()), "ACTIVE"); + abilityRecord_->SetAbilityState(OHOS::AAFwk::AbilityState::BACKGROUND); + EXPECT_EQ(abilityRecord_->ConvertAbilityState(abilityRecord_->GetAbilityState()), "BACKGROUND"); + abilityRecord_->SetAbilityState(OHOS::AAFwk::AbilityState::SUSPENDED); + EXPECT_EQ(abilityRecord_->ConvertAbilityState(abilityRecord_->GetAbilityState()), "SUSPENDED"); + abilityRecord_->SetAbilityState(OHOS::AAFwk::AbilityState::INACTIVATING); + EXPECT_EQ(abilityRecord_->ConvertAbilityState(abilityRecord_->GetAbilityState()), "INACTIVATING"); + abilityRecord_->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVATING); + EXPECT_EQ(abilityRecord_->ConvertAbilityState(abilityRecord_->GetAbilityState()), "ACTIVATING"); + abilityRecord_->SetAbilityState(OHOS::AAFwk::AbilityState::MOVING_BACKGROUND); + EXPECT_EQ(abilityRecord_->ConvertAbilityState(abilityRecord_->GetAbilityState()), "MOVING_BACKGROUND"); + abilityRecord_->SetAbilityState(OHOS::AAFwk::AbilityState::TERMINATING); + EXPECT_EQ(abilityRecord_->ConvertAbilityState(abilityRecord_->GetAbilityState()), "TERMINATING"); +} + +/* + * Feature: AbilityRecord + * Function: IsTerminating + * SubFunction: IsTerminating SetTerminatingState + * FunctionPoints: NA + * EnvConditions:NA + * CaseDescription: Verify IsTerminating SetTerminatingState success + */ +HWTEST_F(AbilityRecordTest, AaFwk_AbilityMS_IsTerminating, TestSize.Level1) +{ + abilityRecord_->SetTerminatingState(); + EXPECT_EQ(abilityRecord_->IsTerminating(), true); +} + +/* + * Feature: AbilityRecord + * Function: Activate + * SubFunction: Activate + * FunctionPoints: NA + * EnvConditions:NA + * CaseDescription: Verify lifecycleDeal_ is nullptr cause Activate is not call + */ +HWTEST_F(AbilityRecordTest, AaFwk_AbilityMS_Activate, TestSize.Level1) +{ + abilityRecord_->lifecycleDeal_ = nullptr; + abilityRecord_->currentState_ = OHOS::AAFwk::AbilityState::INITIAL; + abilityRecord_->Activate(); + EXPECT_EQ(abilityRecord_->currentState_, OHOS::AAFwk::AbilityState::INITIAL); + abilityRecord_->lifecycleDeal_ = std::make_unique(); + abilityRecord_->Activate(); + EXPECT_EQ(abilityRecord_->currentState_, OHOS::AAFwk::AbilityState::ACTIVATING); +} + +/* + * Feature: AbilityRecord + * Function: Inactivate + * SubFunction: Inactivate + * FunctionPoints: NA + * EnvConditions:NA + * CaseDescription: Verify lifecycleDeal_ is nullptr cause Inactivate is not call + */ +HWTEST_F(AbilityRecordTest, AaFwk_AbilityMS_Inactivate, TestSize.Level1) +{ + abilityRecord_->lifecycleDeal_ = nullptr; + abilityRecord_->currentState_ = OHOS::AAFwk::AbilityState::INITIAL; + abilityRecord_->Inactivate(); + EXPECT_EQ(abilityRecord_->currentState_, OHOS::AAFwk::AbilityState::INITIAL); + abilityRecord_->lifecycleDeal_ = std::make_unique(); + abilityRecord_->Inactivate(); + EXPECT_EQ(abilityRecord_->currentState_, OHOS::AAFwk::AbilityState::INACTIVATING); +} + +/* + * Feature: AbilityRecord + * Function: MoveToBackground + * SubFunction: MoveToBackground + * FunctionPoints: NA + * EnvConditions:NA + * CaseDescription: Verify lifecycleDeal_ is nullptr cause MoveToBackground is not call + */ +HWTEST_F(AbilityRecordTest, AaFwk_AbilityMS_MoveToBackground, TestSize.Level1) +{ + abilityRecord_->lifecycleDeal_ = nullptr; + abilityRecord_->currentState_ = OHOS::AAFwk::AbilityState::INITIAL; + abilityRecord_->MoveToBackground([]() { + + }); + EXPECT_EQ(abilityRecord_->currentState_, OHOS::AAFwk::AbilityState::INITIAL); + abilityRecord_->lifecycleDeal_ = std::make_unique(); + abilityRecord_->MoveToBackground([]() { + + }); + EXPECT_EQ(abilityRecord_->currentState_, OHOS::AAFwk::AbilityState::MOVING_BACKGROUND); +} + +/* + * Feature: AbilityRecord + * Function: Terminate + * SubFunction: Terminate + * FunctionPoints: NA + * EnvConditions:NA + * CaseDescription: Verify lifecycleDeal_ is nullptr cause Terminate is not call + */ +HWTEST_F(AbilityRecordTest, AaFwk_AbilityMS_Terminate, TestSize.Level1) +{ + abilityRecord_->lifecycleDeal_ = nullptr; + abilityRecord_->currentState_ = OHOS::AAFwk::AbilityState::INITIAL; + abilityRecord_->Terminate([]() { + + }); + EXPECT_EQ(abilityRecord_->currentState_, OHOS::AAFwk::AbilityState::INITIAL); + abilityRecord_->lifecycleDeal_ = std::make_unique(); + abilityRecord_->Terminate([]() { + + }); + EXPECT_EQ(abilityRecord_->currentState_, OHOS::AAFwk::AbilityState::TERMINATING); +} + +/* + * Feature: AbilityRecord + * Function: GetWindowInfo + * SubFunction: GetWindowInfo RemoveWindowInfo AddWindowInfo + * FunctionPoints: NA + * EnvConditions:NA + * CaseDescription: Verify windowInfo set get remove success + */ +HWTEST_F(AbilityRecordTest, AaFwk_AbilityMS_GetWindowInfo, TestSize.Level1) +{ + int windowToken = 1; + abilityRecord_->AddWindowInfo(windowToken); + EXPECT_NE(abilityRecord_->GetWindowInfo(), nullptr); + abilityRecord_->RemoveWindowInfo(); + EXPECT_EQ(abilityRecord_->GetWindowInfo(), nullptr); +} + +/* + * Feature: AbilityRecord + * Function: SetScheduler + * SubFunction: SetScheduler + * FunctionPoints: NA + * EnvConditions:NA + * CaseDescription: Verify AbilityRecord SetScheduler success + */ +HWTEST_F(AbilityRecordTest, AaFwk_AbilityMS_SetScheduler, TestSize.Level1) +{ + OHOS::sptr scheduler = new AbilityScheduler(); + abilityRecord_->lifecycleDeal_ = std::make_unique(); + EXPECT_EQ(false, abilityRecord_->IsReady()); + abilityRecord_->SetScheduler(scheduler); + EXPECT_EQ(true, abilityRecord_->IsReady()); +} + +/* + * Feature: Token + * Function: GetAbilityRecordByToken + * SubFunction: GetAbilityRecordByToken + * FunctionPoints: NA + * EnvConditions:NA + * CaseDescription: Verify AbilityRecord token GetAbilityRecordByToken success + */ +HWTEST_F(AbilityRecordTest, AaFwk_AbilityMS_GetAbilityRecordByToken, TestSize.Level1) +{ + EXPECT_EQ(Token::GetAbilityRecordByToken(abilityRecord_->GetToken()).get(), abilityRecord_.get()); + EXPECT_EQ(abilityRecord_->GetToken()->GetAbilityRecord(), abilityRecord_); +} + +/* + * Feature: AbilityRecord + * Function: Dump + * SubFunction: Dump + * FunctionPoints: NA + * EnvConditions:NA + * CaseDescription: Verify Dump success + */ +HWTEST_F(AbilityRecordTest, AaFwk_AbilityMS_Dump, TestSize.Level1) +{ + std::vector info; + info.push_back(std::string("0")); + abilityRecord_->Dump(info); + EXPECT_EQ(std::find_if(info.begin(), info.end(), IsTestAbilityExist) != info.end(), true); + Want wantPre; + std::string entity = Want::ENTITY_HOME; + wantPre.AddEntity(entity); + + std::string testAppName = "test_pre_app"; + OHOS::AppExecFwk::AbilityInfo abilityInfoPre; + abilityInfoPre.applicationName = testAppName; + OHOS::AppExecFwk::ApplicationInfo appinfoPre; + appinfoPre.name = testAppName; + + auto preAbilityRecord = std::make_shared(wantPre, abilityInfoPre, appinfoPre); + abilityRecord_->SetPreAbilityRecord(nullptr); + abilityRecord_->Dump(info); + abilityRecord_->SetPreAbilityRecord(preAbilityRecord); + abilityRecord_->Dump(info); + + Want wantNext; + std::string entityNext = Want::ENTITY_HOME; + wantNext.AddEntity(entityNext); + std::string testAppNameNext = "test_next_app"; + OHOS::AppExecFwk::AbilityInfo abilityInfoNext; + abilityInfoNext.applicationName = testAppNameNext; + OHOS::AppExecFwk::ApplicationInfo appinfoNext; + appinfoNext.name = testAppNameNext; + auto nextAbilityRecord = std::make_shared(wantNext, abilityInfoNext, appinfoNext); + abilityRecord_->SetNextAbilityRecord(nullptr); + abilityRecord_->Dump(info); + abilityRecord_->SetNextAbilityRecord(nextAbilityRecord); + abilityRecord_->Dump(info); +} // namespace AAFwk + +/* + * Feature: AbilityRecord + * Function: SetWant GetWant + * SubFunction: SetWant GetWant + * FunctionPoints: NA + * EnvConditions:NA + * CaseDescription: Verify SetWant GetWant can get,set success + */ +HWTEST_F(AbilityRecordTest, AaFwk_AbilityMS_Want, TestSize.Level1) +{ + Want want; + want.SetFlags(100); + abilityRecord_->SetWant(want); + EXPECT_EQ(want.GetFlags(), abilityRecord_->GetWant().GetFlags()); +} + +/* + * Feature: AbilityRecord + * Function: GetRequestCode + * SubFunction: GetRequestCode + * FunctionPoints: NA + * EnvConditions:NA + * CaseDescription: Verify GetRequestCode success + */ +HWTEST_F(AbilityRecordTest, AaFwk_AbilityMS_GetRequestCode, TestSize.Level1) +{ + EXPECT_EQ(abilityRecord_->GetRequestCode(), -1); +} + +/* + * Feature: AbilityRecord + * Function: GetAbilityTypeString + * SubFunction: GetAbilityTypeString + * FunctionPoints: NA + * EnvConditions:NA + * CaseDescription: Verify GetAbilityTypeString can get success + */ +HWTEST_F(AbilityRecordTest, AaFwk_AbilityMS_GetAbilityTypeString, TestSize.Level1) +{ + std::string typeStr; + std::shared_ptr recordUn; + OHOS::AppExecFwk::AbilityInfo ability; + OHOS::AppExecFwk::ApplicationInfo appInfo; + Want wantUn; + recordUn = std::make_shared(wantUn, ability, appInfo); + recordUn->GetAbilityTypeString(typeStr); + EXPECT_EQ(typeStr, "UNKNOWN"); + + std::shared_ptr recordService; + OHOS::AppExecFwk::AbilityInfo abilityService; + abilityService.type = OHOS::AppExecFwk::AbilityType::SERVICE; + OHOS::AppExecFwk::ApplicationInfo appInfoService; + Want wantService; + recordService = std::make_shared(wantService, abilityService, appInfoService); + recordService->GetAbilityTypeString(typeStr); + EXPECT_EQ(typeStr, "SERVICE"); + + std::shared_ptr recordPage; + OHOS::AppExecFwk::AbilityInfo abilityPage; + abilityPage.type = OHOS::AppExecFwk::AbilityType::PAGE; + OHOS::AppExecFwk::ApplicationInfo appInfoPage; + Want wantPage; + recordPage = std::make_shared(wantPage, abilityPage, appInfoPage); + recordPage->GetAbilityTypeString(typeStr); + EXPECT_EQ(typeStr, "PAGE"); + + std::shared_ptr recordData; + OHOS::AppExecFwk::AbilityInfo abilityData; + abilityData.type = OHOS::AppExecFwk::AbilityType::DATA; + OHOS::AppExecFwk::ApplicationInfo appInfoData; + Want wantData; + recordData = std::make_shared(wantData, abilityData, appInfoData); + recordData->GetAbilityTypeString(typeStr); + EXPECT_EQ(typeStr, "DATA"); +} + +/* + * Feature: AbilityRecord + * Function: SetResult GetResult + * SubFunction: SetResult GetResult + * FunctionPoints: NA + * EnvConditions:NA + * CaseDescription: Verify SetResult GetResult can get,set success + */ +HWTEST_F(AbilityRecordTest, AaFwk_AbilityMS_Result, TestSize.Level1) +{ + abilityResult_->requestCode_ = 10; + abilityRecord_->SetResult(abilityResult_); + EXPECT_EQ(10, abilityRecord_->GetResult()->requestCode_); +} + +/* + * Feature: AbilityRecord + * Function: SendResult + * SubFunction: SendResult + * FunctionPoints: NA + * EnvConditions:NA + * CaseDescription: Verify SendResult scheduler is nullptr + */ +HWTEST_F(AbilityRecordTest, AaFwk_AbilityMS_SendResult, TestSize.Level1) +{ + OHOS::sptr scheduler = new AbilityScheduler(); + abilityRecord_->SetScheduler(scheduler); + abilityRecord_->SetResult(abilityResult_); + abilityRecord_->SendResult(); + EXPECT_EQ(nullptr, abilityRecord_->GetResult()); +} + +/* + * Feature: AbilityRecord + * Function: SetConnRemoteObject GetConnRemoteObject + * SubFunction: SetConnRemoteObject GetConnRemoteObject + * FunctionPoints: NA + * EnvConditions:NA + * CaseDescription: Verify SetConnRemoteObject GetConnRemoteObject UT + */ +HWTEST_F(AbilityRecordTest, AaFwk_AbilityMS_ConnRemoteObject, TestSize.Level1) +{ + OHOS::sptr remote; + abilityRecord_->SetConnRemoteObject(remote); + EXPECT_EQ(remote, abilityRecord_->GetConnRemoteObject()); +} + +/* + * Feature: AbilityRecord + * Function: IsCreateByConnect SetCreateByConnectMode + * SubFunction: IsCreateByConnect SetCreateByConnectMode + * FunctionPoints: NA + * EnvConditions:NA + * CaseDescription: Verify IsCreateByConnect SetCreateByConnectMode UT + */ +HWTEST_F(AbilityRecordTest, AaFwk_AbilityMS_CreateByConnect, TestSize.Level1) +{ + abilityRecord_->SetCreateByConnectMode(); + EXPECT_EQ(true, abilityRecord_->IsCreateByConnect()); +} + +/* + * Feature: AbilityRecord + * Function: OnConfigurationChanged + * SubFunction: Configuration Changed + * FunctionPoints: NA + * EnvConditions:NA + * CaseDescription: Verify Configuration Changed UT + */ +HWTEST_F(AbilityRecordTest, AaFwk_AbilityMS_OnConfigurationChanged_001, TestSize.Level1) +{ + const DummyConfiguration config; + abilityRecord_->abilityInfo_.configChanges.push_back("locale"); + EXPECT_EQ(true, abilityRecord_->OnConfigurationChanged(config, CHANGE_CONFIG_LOCALE)); +} +/* + * Feature: AbilityRecord + * Function: OnConfigurationChanged + * SubFunction: Configuration Changed + * FunctionPoints: NA + * EnvConditions:NA + * CaseDescription: Verify Configuration Changed UT + */ +HWTEST_F(AbilityRecordTest, AaFwk_AbilityMS_OnConfigurationChanged_002, TestSize.Level1) +{ + const DummyConfiguration config("layout"); + abilityRecord_->abilityInfo_.configChanges.push_back("layout"); + EXPECT_EQ(true, abilityRecord_->OnConfigurationChanged(config, CHANGE_CONFIG_LOCALE)); +} + +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/abilitymgr/test/unittest/phone/ability_scheduler_proxy_test/BUILD.gn b/tools/services/abilitymgr/test/unittest/phone/ability_scheduler_proxy_test/BUILD.gn new file mode 100644 index 00000000000..e90a5a332f5 --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/ability_scheduler_proxy_test/BUILD.gn @@ -0,0 +1,68 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/test.gni") +import("//foundation/aafwk/standard/aafwk.gni") + +module_output_path = "aafwk_standard/abilitymgr" + +ohos_unittest("ability_scheduler_proxy_test") { + module_out_path = module_output_path + + include_dirs = [ + "${services_path}/abilitymgr/test/mock/libs/system_ability_mock", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy/include", + "//foundation/aafwk/standard/services/abilitymgr/test/mock/libs/ability_scheduler_mock", + ] + + sources = [ + "//foundation/aafwk/standard/services/abilitymgr/test/mock/libs/appexecfwk_core/src/appmgr/mock_app_scheduler.cpp", + "ability_scheduler_proxy_test.cpp", + ] + + configs = [ + "${services_path}/abilitymgr:abilityms_config", + "${services_path}/abilitymgr/test/mock:aafwk_mock_config", + ] + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + deps = [ + "${innerkits_path}/want:want", + "${services_path}/abilitymgr/test:abilityms_test_source", + "${services_path}/abilitymgr/test/mock/libs/aakit:aakit_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_appmgr_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_bundlemgr_mock", + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/frameworks/kits/ability/native:dummy_classes", + + # "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//third_party/googletest:gmock_main", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] +} + +group("unittest") { + testonly = true + + deps = [ ":ability_scheduler_proxy_test" ] +} diff --git a/tools/services/abilitymgr/test/unittest/phone/ability_scheduler_proxy_test/ability_scheduler_proxy_test.cpp b/tools/services/abilitymgr/test/unittest/phone/ability_scheduler_proxy_test/ability_scheduler_proxy_test.cpp new file mode 100644 index 00000000000..04e9596b97a --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/ability_scheduler_proxy_test/ability_scheduler_proxy_test.cpp @@ -0,0 +1,281 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "ability_scheduler_proxy.h" +#include "ability_scheduler_stub.h" +#include "ability_scheduler_mock.h" + +using namespace testing::ext; +using namespace testing; + +namespace OHOS { +namespace AAFwk { +class AbilitySchedulerProxyTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + + sptr abilitySchedulerProxy_{nullptr}; + sptr mock_{nullptr}; + sptr abilitySchedulerRecipient_{nullptr}; +}; + +void AbilitySchedulerProxyTest::SetUpTestCase(void) +{} +void AbilitySchedulerProxyTest::TearDownTestCase(void) +{} +void AbilitySchedulerProxyTest::TearDown(void) +{} + +void AbilitySchedulerProxyTest::SetUp(void) +{ + mock_ = new AbilitySchedulerMock(); + abilitySchedulerProxy_ = new AbilitySchedulerProxy(mock_); + OHOS::AAFwk::AbilitySchedulerRecipient::RemoteDiedHandler callbake; + abilitySchedulerRecipient_ = new AbilitySchedulerRecipient(callbake); +} + +/* + * Feature: AbilitySchedulerProxy + * Function: AbilitySchedulerProxy + * SubFunction: NA + * FunctionPoints: NA + * EnvConditions:NA + * CaseDescription: verify AbilitySchedulerProxy is create success + */ +HWTEST_F(AbilitySchedulerProxyTest, ability_scheduler_proxy_operating_001, TestSize.Level0) +{ + EXPECT_NE(abilitySchedulerProxy_, nullptr); +} + +/* + * Feature: AbilitySchedulerProxy + * Function: AbilitySchedulerRecipient + * SubFunction: NA + * FunctionPoints: NA + * EnvConditions:NA + * CaseDescription: verify AbilitySchedulerRecipient is create success + */ +HWTEST_F(AbilitySchedulerProxyTest, ability_scheduler_proxy_operating_002, TestSize.Level0) +{ + EXPECT_NE(abilitySchedulerRecipient_, nullptr); +} + +/* + * Feature: AbilitySchedulerProxy + * Function: ScheduleAbilityTransaction + * SubFunction: NA + * FunctionPoints: AbilitySchedulerProxy ScheduleAbilityTransaction + * EnvConditions: NA + * CaseDescription: verify ScheduleAbilityTransaction Normal case + */ +HWTEST_F(AbilitySchedulerProxyTest, ability_scheduler_proxy_operating_003, TestSize.Level0) +{ + EXPECT_CALL(*mock_, SendRequest(_, _, _, _)) + .Times(1) + .WillOnce(Invoke(mock_.GetRefPtr(), &AbilitySchedulerMock::InvokeSendRequest)); + Want want; + want.SetFlags(10); + LifeCycleStateInfo info; + abilitySchedulerProxy_->ScheduleAbilityTransaction(want, info); + + EXPECT_EQ(IAbilityScheduler::SCHEDULE_ABILITY_TRANSACTION, mock_->code_); +} + +/* + * Feature: AbilitySchedulerProxy + * Function: ScheduleAbilityTransaction + * SubFunction: NA + * FunctionPoints: AbilitySchedulerProxy ScheduleAbilityTransaction + * EnvConditions: NA + * CaseDescription: verify ScheduleAbilityTransaction Return value exception + */ +HWTEST_F(AbilitySchedulerProxyTest, ability_scheduler_proxy_operating_004, TestSize.Level0) +{ + EXPECT_CALL(*mock_, SendRequest(_, _, _, _)) + .Times(1) + .WillOnce(Invoke(mock_.GetRefPtr(), &AbilitySchedulerMock::InvokeErrorSendRequest)); + Want want; + want.SetFlags(10); + LifeCycleStateInfo info; + abilitySchedulerProxy_->ScheduleAbilityTransaction(want, info); + + EXPECT_EQ(IAbilityScheduler::SCHEDULE_ABILITY_TRANSACTION, mock_->code_); +} + +/* + * Feature: AbilitySchedulerProxy + * Function: SendResult + * SubFunction: NA + * FunctionPoints: AbilitySchedulerProxy SendResult + * EnvConditions: NA + * CaseDescription: verify SendResult Normal case + */ +HWTEST_F(AbilitySchedulerProxyTest, ability_scheduler_proxy_operating_005, TestSize.Level0) +{ + EXPECT_CALL(*mock_, SendRequest(_, _, _, _)) + .Times(1) + .WillOnce(Invoke(mock_.GetRefPtr(), &AbilitySchedulerMock::InvokeSendRequest)); + Want want; + want.SetFlags(10); + abilitySchedulerProxy_->SendResult(9, -1, want); + + EXPECT_EQ(IAbilityScheduler::SEND_RESULT, mock_->code_); +} + +/* + * Feature: AbilitySchedulerProxy + * Function: SendResult + * SubFunction: NA + * FunctionPoints: AbilitySchedulerProxy SendResult + * EnvConditions: NA + * CaseDescription: verify SendResult Return value exception + */ +HWTEST_F(AbilitySchedulerProxyTest, ability_scheduler_proxy_operating_006, TestSize.Level0) +{ + EXPECT_CALL(*mock_, SendRequest(_, _, _, _)) + .Times(1) + .WillOnce(Invoke(mock_.GetRefPtr(), &AbilitySchedulerMock::InvokeErrorSendRequest)); + Want want; + want.SetFlags(10); + abilitySchedulerProxy_->SendResult(9, -1, want); + + EXPECT_EQ(IAbilityScheduler::SEND_RESULT, mock_->code_); +} + +/* + * Feature: AbilitySchedulerProxy + * Function: ScheduleConnectAbility + * SubFunction: NA + * FunctionPoints: AbilitySchedulerProxy ScheduleConnectAbility + * EnvConditions: NA + * CaseDescription: verify ScheduleConnectAbility Normal case + */ +HWTEST_F(AbilitySchedulerProxyTest, ability_scheduler_proxy_operating_007, TestSize.Level0) +{ + EXPECT_CALL(*mock_, SendRequest(_, _, _, _)) + .Times(1) + .WillOnce(Invoke(mock_.GetRefPtr(), &AbilitySchedulerMock::InvokeSendRequest)); + Want want; + want.SetFlags(10); + abilitySchedulerProxy_->ScheduleConnectAbility(want); + + EXPECT_EQ(IAbilityScheduler::SCHEDULE_ABILITY_CONNECT, mock_->code_); +} + +/* + * Feature: AbilitySchedulerProxy + * Function: ScheduleConnectAbility + * SubFunction: NA + * FunctionPoints: AbilitySchedulerProxy ScheduleConnectAbility + * EnvConditions: NA + * CaseDescription: verify ScheduleConnectAbility Return value exception + */ +HWTEST_F(AbilitySchedulerProxyTest, ability_scheduler_proxy_operating_008, TestSize.Level0) +{ + EXPECT_CALL(*mock_, SendRequest(_, _, _, _)) + .Times(1) + .WillOnce(Invoke(mock_.GetRefPtr(), &AbilitySchedulerMock::InvokeErrorSendRequest)); + Want want; + want.SetFlags(10); + abilitySchedulerProxy_->ScheduleConnectAbility(want); + + EXPECT_EQ(IAbilityScheduler::SCHEDULE_ABILITY_CONNECT, mock_->code_); +} + +/* + * Feature: AbilitySchedulerProxy + * Function: ScheduleDisconnectAbility + * SubFunction: NA + * FunctionPoints: AbilitySchedulerProxy ScheduleDisconnectAbility + * EnvConditions: NA + * CaseDescription: verify ScheduleDisconnectAbility Normal case + */ +HWTEST_F(AbilitySchedulerProxyTest, ability_scheduler_proxy_operating_009, TestSize.Level0) +{ + EXPECT_CALL(*mock_, SendRequest(_, _, _, _)) + .Times(1) + .WillOnce(Invoke(mock_.GetRefPtr(), &AbilitySchedulerMock::InvokeSendRequest)); + Want want; + want.SetFlags(10); + abilitySchedulerProxy_->ScheduleDisconnectAbility(want); + + EXPECT_EQ(IAbilityScheduler::SCHEDULE_ABILITY_DISCONNECT, mock_->code_); +} + +/* + * Feature: AbilitySchedulerProxy + * Function: ScheduleDisconnectAbility + * SubFunction: NA + * FunctionPoints: AbilitySchedulerProxy ScheduleDisconnectAbility + * EnvConditions: NA + * CaseDescription: verify ScheduleDisconnectAbility Return value exception + */ +HWTEST_F(AbilitySchedulerProxyTest, ability_scheduler_proxy_operating_010, TestSize.Level0) +{ + EXPECT_CALL(*mock_, SendRequest(_, _, _, _)) + .Times(1) + .WillOnce(Invoke(mock_.GetRefPtr(), &AbilitySchedulerMock::InvokeErrorSendRequest)); + Want want; + want.SetFlags(10); + abilitySchedulerProxy_->ScheduleDisconnectAbility(want); + + EXPECT_EQ(IAbilityScheduler::SCHEDULE_ABILITY_DISCONNECT, mock_->code_); +} + +/* + * Feature: AbilitySchedulerProxy + * Function: ScheduleCommandAbility + * SubFunction: NA + * FunctionPoints: AbilitySchedulerProxy ScheduleCommandAbility + * EnvConditions: NA + * CaseDescription: verify ScheduleCommandAbility Normal case + */ +HWTEST_F(AbilitySchedulerProxyTest, ability_scheduler_proxy_operating_011, TestSize.Level0) +{ + EXPECT_CALL(*mock_, SendRequest(_, _, _, _)) + .Times(1) + .WillOnce(Invoke(mock_.GetRefPtr(), &AbilitySchedulerMock::InvokeSendRequest)); + Want want; + want.SetFlags(10); + abilitySchedulerProxy_->ScheduleCommandAbility(want, false, 1); + + EXPECT_EQ(IAbilityScheduler::SCHEDULE_ABILITY_COMMAND, mock_->code_); +} + +/* + * Feature: AbilitySchedulerProxy + * Function: ScheduleCommandAbility + * SubFunction: NA + * FunctionPoints: AbilitySchedulerProxy ScheduleCommandAbility + * EnvConditions: NA + * CaseDescription: verify ScheduleCommandAbility Return value exception + */ +HWTEST_F(AbilitySchedulerProxyTest, ability_scheduler_proxy_operating_012, TestSize.Level0) +{ + EXPECT_CALL(*mock_, SendRequest(_, _, _, _)) + .Times(1) + .WillOnce(Invoke(mock_.GetRefPtr(), &AbilitySchedulerMock::InvokeErrorSendRequest)); + Want want; + want.SetFlags(10); + abilitySchedulerProxy_->ScheduleCommandAbility(want, false, 1); + + EXPECT_EQ(IAbilityScheduler::SCHEDULE_ABILITY_COMMAND, mock_->code_); +} +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/abilitymgr/test/unittest/phone/ability_scheduler_stub_test/BUILD.gn b/tools/services/abilitymgr/test/unittest/phone/ability_scheduler_stub_test/BUILD.gn new file mode 100644 index 00000000000..b785fb10b0f --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/ability_scheduler_stub_test/BUILD.gn @@ -0,0 +1,65 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/test.gni") +import("//foundation/aafwk/standard/aafwk.gni") + +module_output_path = "aafwk_standard/abilitymgr" + +ohos_unittest("ability_scheduler_stub_test") { + module_out_path = module_output_path + + include_dirs = [ + "${services_path}/abilitymgr/test/mock/libs/system_ability_mock", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy/include", + ] + + sources = [ + "//foundation/aafwk/standard/services/abilitymgr/test/mock/libs/appexecfwk_core/src/appmgr/mock_app_scheduler.cpp", + "ability_scheduler_stub_test.cpp", # add mock file + ] + + configs = [ + "${services_path}/abilitymgr:abilityms_config", + "${services_path}/abilitymgr/test/mock:aafwk_mock_config", + ] + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + deps = [ + "${innerkits_path}/want:want", + "${services_path}/abilitymgr/test:abilityms_test_source", + "${services_path}/abilitymgr/test/mock/libs/aakit:aakit_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_appmgr_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_bundlemgr_mock", + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/frameworks/kits/ability/native:dummy_classes", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] +} + +group("unittest") { + testonly = true + + deps = [ ":ability_scheduler_stub_test" ] +} diff --git a/tools/services/abilitymgr/test/unittest/phone/ability_scheduler_stub_test/ability_schedule_stub_mock.h b/tools/services/abilitymgr/test/unittest/phone/ability_scheduler_stub_test/ability_schedule_stub_mock.h new file mode 100644 index 00000000000..d0c99fd441b --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/ability_scheduler_stub_test/ability_schedule_stub_mock.h @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ABILITY_UNITTEST_ABILITY_SCHEDULE_STUB_MOCK_H +#define ABILITY_UNITTEST_ABILITY_SCHEDULE_STUB_MOCK_H +#include "ability_scheduler_stub.h" + +namespace OHOS { +namespace AAFwk { +class AbilitySchedulerStubMock : public AbilitySchedulerStub { +public: + virtual void ScheduleAbilityTransaction(const Want &want, const LifeCycleStateInfo &targetState) override + {} + + virtual void SendResult(int requestCode, int resultCode, const Want &resultWant) override + {} + + virtual void ScheduleConnectAbility(const Want &want) override + {} + + virtual void ScheduleDisconnectAbility(const Want &want) override + {} + + virtual void ScheduleCommandAbility(const Want &want, bool restart, int startId) override + {} + + virtual void ScheduleSaveAbilityState(PacMap &outState) override + {} + virtual void ScheduleRestoreAbilityState(const PacMap &inState) override + {} + virtual void ScheduleUpdateConfiguration(const DummyConfiguration &config) override + {} + + virtual std::vector GetFileTypes(const Uri &uri, const std::string &mimeTypeFilter) override + { + std::vector types; + return types; + } + + virtual int OpenFile(const Uri &uri, const std::string &mode) override + { + return -1; + } + + virtual int Insert(const Uri &uri, const NativeRdb::ValuesBucket &value) override + { + return -1; + } + + virtual int Update(const Uri &uri, const NativeRdb::ValuesBucket &value, const NativeRdb::DataAbilityPredicates &predicates) override + { + return -1; + } + + virtual int Delete(const Uri &uri, const NativeRdb::DataAbilityPredicates &predicates) override + { + return -1; + } + + virtual std::shared_ptr Query( + const Uri &uri, std::vector &columns, const NativeRdb::DataAbilityPredicates &predicates) override + { + return nullptr; + } + + virtual std::string GetType(const Uri &uri) override + { + return " "; + } + + virtual int OpenRawFile(const Uri &uri, const std::string &mode) override + { + return -1; + } + + virtual bool Reload(const Uri &uri, const PacMap &extras) override + { + return false; + } + + virtual int BatchInsert(const Uri &uri, const std::vector &values) override + { + return -1; + } + + virtual Uri NormalizeUri(const Uri &uri) override + { + Uri urivalue(""); + return urivalue; + } + + virtual Uri DenormalizeUri(const Uri &uri) override + { + Uri urivalue(""); + return urivalue; + } + + void NotifyMultiWinModeChanged(int32_t winModeKey, bool flag) override + {} + + void NotifyTopActiveAbilityChanged(bool flag) override + {} + virtual bool ScheduleRegisterObserver(const Uri &uri, const sptr &dataObserver) override + { + return true; + } + virtual bool ScheduleUnregisterObserver(const Uri &uri, const sptr &dataObserver) override + { + return true; + } + virtual bool ScheduleNotifyChange(const Uri &uri) override + { + return true; + } + virtual std::vector> ExecuteBatch( + const std::vector> &operations) override + { + return std::vector>(); + } +}; +} // namespace AAFwk +} // namespace OHOS + +#endif \ No newline at end of file diff --git a/tools/services/abilitymgr/test/unittest/phone/ability_scheduler_stub_test/ability_scheduler_stub_test.cpp b/tools/services/abilitymgr/test/unittest/phone/ability_scheduler_stub_test/ability_scheduler_stub_test.cpp new file mode 100644 index 00000000000..cf9aeff4d07 --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/ability_scheduler_stub_test/ability_scheduler_stub_test.cpp @@ -0,0 +1,220 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "ability_schedule_stub_mock.h" + +using namespace testing::ext; + +namespace OHOS { +namespace AAFwk { +class AbilitySchedulerStubTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + void WriteInterfaceToken(MessageParcel &data); + sptr stub_{nullptr}; +}; + +void AbilitySchedulerStubTest::SetUpTestCase(void) +{} +void AbilitySchedulerStubTest::TearDownTestCase(void) +{} +void AbilitySchedulerStubTest::TearDown(void) +{} + +void AbilitySchedulerStubTest::SetUp(void) +{ + stub_ = new AbilitySchedulerStubMock(); +} +void AbilitySchedulerStubTest::WriteInterfaceToken(MessageParcel &data) +{ + data.WriteInterfaceToken(AbilitySchedulerStub::GetDescriptor()); +} + +/* + * Feature: AbilitySchedulerStub + * Function: OnRemoteRequest + * SubFunction: NA + * FunctionPoints: AbilitySchedulerStub OnRemoteRequest + * EnvConditions: code is SCHEDULE_ABILITY_TRANSACTION + * CaseDescription: Verify the normal process of onremoterequest + */ +HWTEST_F(AbilitySchedulerStubTest, AbilitySchedulerStub_001, TestSize.Level0) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + Want want; + LifeCycleStateInfo stateInfo; + WriteInterfaceToken(data); + data.WriteParcelable(&want); + data.WriteParcelable(&stateInfo); + auto res = stub_->OnRemoteRequest(IAbilityScheduler::SCHEDULE_ABILITY_TRANSACTION, data, reply, option); + EXPECT_EQ(res, NO_ERROR); +} + +/* + * Feature: AbilitySchedulerStub + * Function: OnRemoteRequest + * SubFunction: NA + * FunctionPoints: AbilitySchedulerStub OnRemoteRequest + * EnvConditions: code is SCHEDULE_ABILITY_TRANSACTION + * CaseDescription: Verifying stateinfo is nullptr causes onremoterequest to fail + */ +HWTEST_F(AbilitySchedulerStubTest, AbilitySchedulerStub_002, TestSize.Level0) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + Want want; + WriteInterfaceToken(data); + data.WriteParcelable(&want); + data.WriteParcelable(nullptr); + auto res = stub_->OnRemoteRequest(IAbilityScheduler::SCHEDULE_ABILITY_TRANSACTION, data, reply, option); + EXPECT_NE(res, NO_ERROR); +} + +/* + * Feature: AbilitySchedulerStub + * Function: OnRemoteRequest + * SubFunction: NA + * FunctionPoints: AbilitySchedulerStub OnRemoteRequest + * EnvConditions: code is SEND_RESULT + * CaseDescription: Verify the normal process of onremoterequest + */ +HWTEST_F(AbilitySchedulerStubTest, AbilitySchedulerStub_003, TestSize.Level0) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + Want want; + WriteInterfaceToken(data); + data.WriteInt32(1); + data.WriteInt32(1); + data.WriteParcelable(&want); + + auto res = stub_->OnRemoteRequest(IAbilityScheduler::SEND_RESULT, data, reply, option); + EXPECT_EQ(res, NO_ERROR); +} + +/* + * Feature: AbilitySchedulerStub + * Function: OnRemoteRequest + * SubFunction: NA + * FunctionPoints: AbilitySchedulerStub OnRemoteRequest + * EnvConditions: code is SEND_RESULT + * CaseDescription: Verifying want is nullptr causes onremoterequest to fail + */ +HWTEST_F(AbilitySchedulerStubTest, AbilitySchedulerStub_004, TestSize.Level0) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + WriteInterfaceToken(data); + data.WriteInt32(1); + data.WriteParcelable(nullptr); + + auto res = stub_->OnRemoteRequest(IAbilityScheduler::SEND_RESULT, data, reply, option); + EXPECT_NE(res, NO_ERROR); +} + +/* + * Feature: AbilitySchedulerStub + * Function: OnRemoteRequest + * SubFunction: NA + * FunctionPoints: AbilitySchedulerStub OnRemoteRequest + * EnvConditions: code is SCHEDULE_ABILITY_CONNECT + * CaseDescription: Verify the normal and failed conditions of onremoterequest + */ +HWTEST_F(AbilitySchedulerStubTest, AbilitySchedulerStub_005, TestSize.Level0) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + WriteInterfaceToken(data); + data.WriteParcelable(nullptr); + + auto res = stub_->OnRemoteRequest(IAbilityScheduler::SCHEDULE_ABILITY_CONNECT, data, reply, option); + EXPECT_NE(res, NO_ERROR); + + Want want; + WriteInterfaceToken(data); + data.WriteParcelable(&want); + auto res1 = stub_->OnRemoteRequest(IAbilityScheduler::SCHEDULE_ABILITY_CONNECT, data, reply, option); + EXPECT_EQ(res1, NO_ERROR); +} + +/* + * Feature: AbilitySchedulerStub + * Function: OnRemoteRequest + * SubFunction: NA + * FunctionPoints: AbilitySchedulerStub OnRemoteRequest + * EnvConditions: code is SCHEDULE_ABILITY_DISCONNECT + * CaseDescription: Verify the normal conditions of onremoterequest + */ +HWTEST_F(AbilitySchedulerStubTest, AbilitySchedulerStub_006, TestSize.Level0) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + WriteInterfaceToken(data); + auto res = stub_->OnRemoteRequest(IAbilityScheduler::SCHEDULE_ABILITY_DISCONNECT, data, reply, option); + EXPECT_EQ(res, ERR_INVALID_VALUE); +} + +/* + * Feature: AbilitySchedulerStub + * Function: OnRemoteRequest + * SubFunction: NA + * FunctionPoints: AbilitySchedulerStub OnRemoteRequest + * EnvConditions: code is SCHEDULE_SAVE_ABILITY_STATE + * CaseDescription: Verify the failed conditions of onremoterequest + */ +HWTEST_F(AbilitySchedulerStubTest, AbilitySchedulerStub_007, TestSize.Level0) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + WriteInterfaceToken(data); + auto res = stub_->OnRemoteRequest(IAbilityScheduler::SCHEDULE_SAVE_ABILITY_STATE, data, reply, option); + EXPECT_EQ(res, NO_ERROR); +} + +/* + * Feature: AbilitySchedulerStub + * Function: OnRemoteRequest + * SubFunction: NA + * FunctionPoints: AbilitySchedulerStub OnRemoteRequest + * EnvConditions: code is default + * CaseDescription: Verify the normal conditions of onremoterequest + */ +HWTEST_F(AbilitySchedulerStubTest, AbilitySchedulerStub_008, TestSize.Level0) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + WriteInterfaceToken(data); + auto res = stub_->OnRemoteRequest(INT_MAX, data, reply, option); + EXPECT_NE(res, NO_ERROR); +} +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/abilitymgr/test/unittest/phone/ability_service_start_test/BUILD.gn b/tools/services/abilitymgr/test/unittest/phone/ability_service_start_test/BUILD.gn new file mode 100644 index 00000000000..941270ed0bc --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/ability_service_start_test/BUILD.gn @@ -0,0 +1,67 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/test.gni") +import("//foundation/aafwk/standard/aafwk.gni") + +module_output_path = "aafwk_standard/abilitymgr" + +ohos_unittest("ability_service_start_test") { + module_out_path = module_output_path + + include_dirs = [ + "${services_path}/abilitymgr/test/mock/libs/system_ability_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy/include", + ] + + sources = [ + "//foundation/aafwk/standard/services/abilitymgr/test/mock/libs/appexecfwk_core/src/appmgr/mock_app_scheduler.cpp", + "ability_service_start_test.cpp", # add mock file + ] + + configs = [ + "${services_path}/abilitymgr:abilityms_config", + "${services_path}/abilitymgr/test/mock:aafwk_mock_config", + ] + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + deps = [ + "${innerkits_path}/want:want", + "${services_path}/abilitymgr/test:abilityms_test_source", + "${services_path}/abilitymgr/test/mock/libs/aakit:aakit_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_appmgr_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_bundlemgr_mock", + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/frameworks/kits/ability/native:dummy_classes", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//third_party/googletest:gmock_main", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] +} + +group("unittest") { + testonly = true + + deps = [ ":ability_service_start_test" ] +} diff --git a/tools/services/abilitymgr/test/unittest/phone/ability_service_start_test/ability_service_start_test.cpp b/tools/services/abilitymgr/test/unittest/phone/ability_service_start_test/ability_service_start_test.cpp new file mode 100644 index 00000000000..47f344f1f21 --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/ability_service_start_test/ability_service_start_test.cpp @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "ability_manager_service.h" +#include "system_ability_definition.h" +#include "bundlemgr/mock_bundle_manager.h" +#include "sa_mgr_client.h" + +using namespace testing::ext; +using namespace OHOS::AppExecFwk; + +namespace OHOS { +namespace AAFwk { +namespace { +const std::string NAME_BUNDLE_MGR_SERVICE = "BundleMgrService"; +} + +class AbilityServiceStartTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp(); + void TearDown(); + +public: + std::shared_ptr aams_{nullptr}; +}; + +void AbilityServiceStartTest::SetUpTestCase() +{ + OHOS::DelayedSingleton::GetInstance()->RegisterSystemAbility( + OHOS::BUNDLE_MGR_SERVICE_SYS_ABILITY_ID, new BundleMgrService()); +} +void AbilityServiceStartTest::TearDownTestCase() +{ + OHOS::DelayedSingleton::DestroyInstance(); +} + +void AbilityServiceStartTest::TearDown() +{} + +void AbilityServiceStartTest::SetUp() +{ + aams_ = OHOS::DelayedSingleton::GetInstance(); +} + +/* + * Feature: AbilityManagerService + * Function: Service + * SubFunction: NA + * FunctionPoints: AbilityManager startup & stop + * EnvConditions: NA + * CaseDescription: Verify if AbilityManagerService startup & stop successfully. + */ +HWTEST_F(AbilityServiceStartTest, StartUp_001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "ability_manager_service_startup_001 start"; + EXPECT_EQ(ServiceRunningState::STATE_NOT_START, aams_->QueryServiceState()); + aams_->OnStart(); + EXPECT_EQ(ServiceRunningState::STATE_RUNNING, aams_->QueryServiceState()); + aams_->OnStop(); + EXPECT_EQ(ServiceRunningState::STATE_NOT_START, aams_->QueryServiceState()); + GTEST_LOG_(INFO) << "ability_manager_service_startup_001 end"; +} + +/* + * Feature: AbilityManagerService + * Function: Service + * SubFunction: NA + * FunctionPoints: AbilityManager startup two times + * EnvConditions: NA + * CaseDescription: Verify if AbilityManagerService startup & stop successfully. + */ +HWTEST_F(AbilityServiceStartTest, StartUp_002, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "ability_manager_service_startup_002 start"; + aams_->OnStart(); + aams_->OnStart(); + EXPECT_EQ(ServiceRunningState::STATE_RUNNING, aams_->QueryServiceState()); + aams_->OnStop(); + EXPECT_EQ(ServiceRunningState::STATE_NOT_START, aams_->QueryServiceState()); + GTEST_LOG_(INFO) << "ability_manager_service_startup_002 end"; +} + +/* + * Feature: AbilityManagerService + * Function: Service + * SubFunction: NA + * FunctionPoints: AbilityManager stop + * EnvConditions: NA + * CaseDescription: Verify if AbilityManagerService stop successfully. + */ +HWTEST_F(AbilityServiceStartTest, StartUp_003, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "ability_manager_service_startup_003 start"; + aams_->OnStop(); + EXPECT_EQ(ServiceRunningState::STATE_NOT_START, aams_->QueryServiceState()); + GTEST_LOG_(INFO) << "ability_manager_service_startup_003 end"; +} + +/* + * Feature: AbilityManagerService + * Function: Service + * SubFunction: NA + * FunctionPoints: AbilityManager stop again + * EnvConditions: NA + * CaseDescription: Verify if AbilityManagerService stop successfully. + */ +HWTEST_F(AbilityServiceStartTest, StartUp_004, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "ability_manager_service_startup_004 start"; + aams_->OnStart(); + aams_->OnStop(); + aams_->OnStop(); + EXPECT_EQ(ServiceRunningState::STATE_NOT_START, aams_->QueryServiceState()); + GTEST_LOG_(INFO) << "ability_manager_service_startup_004 end"; +} + +/* + * Feature: AbilityManagerService + * Function: Service + * SubFunction: NA + * FunctionPoints: AbilityManager start & stop 10 times + * EnvConditions: NA + * CaseDescription: Verify if AbilityManagerService start & stop successfully. + */ +HWTEST_F(AbilityServiceStartTest, StartUp_005, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "ability_manager_service_startup_005 start"; + for (int i = 0; i < 10; i++) { + aams_->OnStart(); + auto handler = aams_->GetEventHandler(); + if (handler) { + handler->RemoveTask("startLauncherAbility"); + } + GTEST_LOG_(INFO) << "start " << i << "times"; + EXPECT_EQ(ServiceRunningState::STATE_RUNNING, aams_->QueryServiceState()); + aams_->OnStop(); + GTEST_LOG_(INFO) << "stop " << i << "times"; + EXPECT_EQ(ServiceRunningState::STATE_NOT_START, aams_->QueryServiceState()); + } + GTEST_LOG_(INFO) << "ability_manager_service_startup_005 end"; +} +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/abilitymgr/test/unittest/phone/ability_stack_manager_test/BUILD.gn b/tools/services/abilitymgr/test/unittest/phone/ability_stack_manager_test/BUILD.gn new file mode 100644 index 00000000000..5b3bd85c96e --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/ability_stack_manager_test/BUILD.gn @@ -0,0 +1,69 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/test.gni") +import("//foundation/aafwk/standard/aafwk.gni") + +module_output_path = "aafwk_standard/abilitymgr" + +ohos_unittest("ability_stack_manager_test") { + module_out_path = module_output_path + + include_dirs = [ + "${services_path}/abilitymgr/test/mock/libs/system_ability_mock", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy/include", + "//foundation/aafwk/standard/services/abilitymgr/test/mock/libs/ability_scheduler_mock", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_core/include/appmgr/", + ] + + sources = [ + "//foundation/aafwk/standard/services/abilitymgr/test/mock/libs/appexecfwk_core/src/appmgr/mock_app_scheduler.cpp", + "ability_stack_manager_test.cpp", # add mock file + ] + + configs = [ + "${services_path}/abilitymgr:abilityms_config", + "${services_path}/abilitymgr/test/mock:aafwk_mock_config", + ] + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + deps = [ + "${innerkits_path}/want:want", + "${services_path}/abilitymgr/test:abilityms_test_source", + "${services_path}/abilitymgr/test/mock/libs/aakit:aakit_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_appmgr_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_bundlemgr_mock", + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/frameworks/kits/ability/native:dummy_classes", + "//foundation/aafwk/standard/interfaces/innerkits/base:base", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//third_party/googletest:gmock_main", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] +} + +group("unittest") { + testonly = true + + deps = [ ":ability_stack_manager_test" ] +} diff --git a/tools/services/abilitymgr/test/unittest/phone/ability_stack_manager_test/ability_stack_manager_test.cpp b/tools/services/abilitymgr/test/unittest/phone/ability_stack_manager_test/ability_stack_manager_test.cpp new file mode 100644 index 00000000000..e98da047dc6 --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/ability_stack_manager_test/ability_stack_manager_test.cpp @@ -0,0 +1,3157 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#define private public +#define protected public +#include "ability_stack_manager.h" +#include "ability_record.h" +#include "ability_manager_service.h" +#undef private +#undef protected + +#include "app_process_data.h" +#include "mock_bundle_manager.h" +#include "sa_mgr_client.h" +#include "system_ability_definition.h" +#include "ability_manager_errors.h" +#include "ability_scheduler.h" +#include "mock_ability_connect_callback.h" +#include "ability_scheduler_mock.h" + +using namespace testing::ext; +using namespace OHOS::AppExecFwk; +namespace OHOS { +namespace AAFwk { +namespace { +const std::string LANGUAGE = "locale"; +const std::string LAYOUT = "layout"; +const std::string FONTSIZE = "fontsize"; +const std::string ORIENTATION = "orientation"; +const std::string DENSITY = "density"; +} // namespace + +class AbilityStackManagerTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + void init(); + + AbilityRequest GenerateAbilityRequest(const std::string &deviceName, const std::string &abilityName, + const std::string &appName, const std::string &bundleName, const std::vector config); + + void makeScene(const std::string &abilityName, const std::string &bundleName, AbilityInfo &abilityInfo, Want &want); + + std::shared_ptr stackManager_{nullptr}; + AbilityRequest launcherAbilityRequest_{}; + AbilityRequest musicAbilityRequest_{}; + AbilityRequest musicTopAbilityRequest_{}; + AbilityRequest musicSAbilityRequest_{}; + AbilityRequest radioAbilityRequest_{}; + AbilityRequest radioTopAbilityRequest_{}; + Want want_{}; + AbilityInfo abilityInfo_{}; + ApplicationInfo appInfo_{}; +}; + +void AbilityStackManagerTest::SetUpTestCase(void) +{ + OHOS::DelayedSingleton::GetInstance()->RegisterSystemAbility( + OHOS::BUNDLE_MGR_SERVICE_SYS_ABILITY_ID, new BundleMgrService()); +} +void AbilityStackManagerTest::TearDownTestCase(void) +{ + OHOS::DelayedSingleton::DestroyInstance(); +} + +void AbilityStackManagerTest::SetUp() +{ + init(); + + auto ams = DelayedSingleton::GetInstance(); + ams->Init(); + stackManager_ = std::make_shared(0); + auto bms = ams->GetBundleManager(); + EXPECT_NE(bms, nullptr); +} + +void AbilityStackManagerTest::TearDown() +{ + stackManager_.reset(); + OHOS::DelayedSingleton::DestroyInstance(); +} + +void AbilityStackManagerTest::init() +{ + std::vector config; + launcherAbilityRequest_ = GenerateAbilityRequest("device", "LauncherAbility", "launcher", "com.ix.hiworld", config); + + musicAbilityRequest_ = GenerateAbilityRequest("device", "MusicAbility", "music", "com.ix.hiMusic", config); + + musicTopAbilityRequest_ = GenerateAbilityRequest("device", "MusicTopAbility", "music", "com.ix.hiMusic", config); + + musicSAbilityRequest_ = GenerateAbilityRequest("device", "MusicSAbility", "music", "com.ix.hiMusic", config); + + radioAbilityRequest_ = GenerateAbilityRequest("device", "RadioAbility", "radio", "com.ix.hiRadio", config); + + radioTopAbilityRequest_ = GenerateAbilityRequest("device", "RadioTopAbility", "radio", "com.ix.hiRadio", config); +} + +void AbilityStackManagerTest::makeScene( + const std::string &abilityName, const std::string &bundleName, AbilityInfo &abilityInfo, Want &want) +{ + if (bundleName == "com.ix.hiworld") { + std::string entity = Want::ENTITY_HOME; + want.AddEntity(entity); + abilityInfo.type = AbilityType::PAGE; + abilityInfo.applicationInfo.isLauncherApp = true; + abilityInfo.process = "p"; + } + + if (bundleName == "com.ix.hiMusic") { + abilityInfo.type = AbilityType::PAGE; + abilityInfo.applicationInfo.isLauncherApp = false; + + if (abilityName == "MusicAbility") { + abilityInfo.process = "p1"; + abilityInfo.launchMode = LaunchMode::STANDARD; + } + if (abilityName == "MusicTopAbility") { + abilityInfo.process = "p1"; + abilityInfo.launchMode = LaunchMode::SINGLETOP; + } + if (abilityName == "MusicSAbility") { + abilityInfo.process = "p2"; + abilityInfo.launchMode = LaunchMode::SINGLETON; + } + } + + if (bundleName == "com.ix.hiRadio") { + abilityInfo.type = AbilityType::PAGE; + abilityInfo.process = "p3"; + if (abilityName == "RadioAbility") { + abilityInfo.launchMode = LaunchMode::STANDARD; + } + if (abilityName == "RadioTopAbility") { + abilityInfo.launchMode = LaunchMode::SINGLETON; + } + } +} + +AbilityRequest AbilityStackManagerTest::GenerateAbilityRequest(const std::string &deviceName, + const std::string &abilityName, const std::string &appName, const std::string &bundleName, + const std::vector config) +{ + ElementName element(deviceName, abilityName, bundleName); + Want want; + want.SetElement(element); + + AbilityInfo abilityInfo; + ApplicationInfo appinfo; + abilityInfo.visible = true; + abilityInfo.name = abilityName; + abilityInfo.bundleName = bundleName; + abilityInfo.applicationName = appName; + abilityInfo.applicationInfo.bundleName = bundleName; + abilityInfo.applicationInfo.name = appName; + abilityInfo.configChanges = config; + + makeScene(abilityName, bundleName, abilityInfo, want); + + appinfo = abilityInfo.applicationInfo; + AbilityRequest abilityRequest; + abilityRequest.want = want; + abilityRequest.abilityInfo = abilityInfo; + abilityRequest.appInfo = appinfo; + + return abilityRequest; +} + +/* + * Feature: AbilityStackManager + * Function: stack operate + * SubFunction: NA + * FunctionPoints: NA + * EnvConditions:NA + * CaseDescription: verify get ability by token success + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_001, TestSize.Level1) +{ + stackManager_->Init(); + stackManager_->StartAbility(launcherAbilityRequest_); + auto topAbility = stackManager_->GetCurrentTopAbility(); + auto token = topAbility->GetToken(); + auto tokenAbility = stackManager_->GetAbilityRecordByToken(token); + EXPECT_EQ(topAbility, tokenAbility); +} + +/* + * Feature: AbilityStackManager + * Function: stack operate + * SubFunction: NA + * FunctionPoints: NA + * EnvConditions:NA + * CaseDescription: verify get ability by token fail + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_002, TestSize.Level1) +{ + Want want; + AbilityInfo abilityInfo; + ApplicationInfo appinfo; + + stackManager_->Init(); + stackManager_->StartAbility(launcherAbilityRequest_); + + auto ability = std::make_shared(want, abilityInfo, appinfo); + ability->Init(); + auto token = ability->GetToken(); + auto tokenAbility = stackManager_->GetAbilityRecordByToken(token); + EXPECT_EQ(nullptr, tokenAbility); +} + +/* + * Feature: AbilityStackManager + * Function: stack operate + * SubFunction: NA + * FunctionPoints: NA + * EnvConditions:NA + * CaseDescription: verify start launcher ability + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_003, TestSize.Level1) +{ + stackManager_->Init(); + auto topAbility = stackManager_->GetCurrentTopAbility(); + EXPECT_EQ(nullptr, topAbility); + + auto result = stackManager_->StartAbility(launcherAbilityRequest_); + EXPECT_EQ(result, ERR_OK); + topAbility = stackManager_->GetCurrentTopAbility(); + EXPECT_NE(nullptr, stackManager_->GetCurrentTopAbility()); + AbilityInfo topAbilityInfo = topAbility->GetAbilityInfo(); + EXPECT_EQ("launcher", topAbilityInfo.applicationName); +} + +/* + * Feature: AbilityStackManager + * Function: stack operate + * SubFunction: NA + * FunctionPoints: NA + * EnvConditions:NA + * CaseDescription: verify repeated start launcher ability + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_004, TestSize.Level1) +{ + stackManager_->Init(); + stackManager_->StartAbility(musicSAbilityRequest_); + auto topAbility1 = stackManager_->GetCurrentTopAbility(); + topAbility1->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + stackManager_->StartAbility(musicSAbilityRequest_); + auto topAbility2 = stackManager_->GetCurrentTopAbility(); + topAbility2->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + EXPECT_EQ(topAbility1, topAbility2); +} + +/* + * Feature: AbilityStackManager + * Function: stack operate + * SubFunction: NA + * FunctionPoints: NA + * EnvConditions:NA + * CaseDescription: verify no launcher ability GetTopMissionRecord + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_005, TestSize.Level1) +{ + stackManager_->Init(); + auto topMissionRecord = stackManager_->GetTopMissionRecord(); + EXPECT_EQ(nullptr, topMissionRecord); +} + +/* + * Feature: AbilityStackManager + * Function: stack operate + * SubFunction: NA + * FunctionPoints: NA + * EnvConditions:NA + * CaseDescription: verify no launcher ability GetCurrentTopAbility + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_006, TestSize.Level1) +{ + stackManager_->Init(); + auto topAbility = stackManager_->GetCurrentTopAbility(); + EXPECT_EQ(nullptr, topAbility); +} + +/* + * Feature: AbilityStackManager + * Function: stack operate + * SubFunction: NA + * FunctionPoints: NA + * EnvConditions:NA + * CaseDescription: verify repeated start launcher ability, GetTopMissionRecord + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_007, TestSize.Level1) +{ + stackManager_->Init(); + + stackManager_->StartAbility(launcherAbilityRequest_); + auto topMissionRecord1 = stackManager_->GetTopMissionRecord(); + auto topAbility1 = stackManager_->GetCurrentTopAbility(); + topAbility1->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + EXPECT_NE(nullptr, topMissionRecord1); + + stackManager_->StartAbility(musicAbilityRequest_); + auto topMissionRecord2 = stackManager_->GetTopMissionRecord(); + auto topAbility2 = stackManager_->GetCurrentTopAbility(); + topAbility2->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + EXPECT_NE(nullptr, topMissionRecord2); + EXPECT_NE(topMissionRecord1->GetMissionRecordId(), topMissionRecord2->GetMissionRecordId()); +} + +/* + * Feature: AbilityStackManager + * Function: stack operate + * SubFunction: NA + * FunctionPoints: NA + * EnvConditions:NA + * CaseDescription: verify launcher ability RemoveMissionRecordById + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_008, TestSize.Level1) +{ + stackManager_->Init(); + stackManager_->StartAbility(launcherAbilityRequest_); + auto topAbility1 = stackManager_->GetCurrentTopAbility(); + EXPECT_NE(nullptr, topAbility1); + auto topMissionRecord1 = stackManager_->GetTopMissionRecord(); + EXPECT_NE(nullptr, topMissionRecord1); + auto topId = topMissionRecord1->GetMissionRecordId(); + bool ret = stackManager_->RemoveMissionRecordById(topId); + EXPECT_EQ(true, ret); + auto topAbility2 = stackManager_->GetCurrentTopAbility(); + EXPECT_EQ(nullptr, topAbility2); + auto topMissionRecord2 = stackManager_->GetTopMissionRecord(); + EXPECT_EQ(nullptr, topMissionRecord2); +} + +/* + * Feature: AbilityStackManager + * Function: StartAbility + * SubFunction: LoadFirstAbility + * FunctionPoints: NA + * EnvConditions: top ability is null + * CaseDescription: start the first ability. verify: + * 1. the MissionStack is launcher mission stack + * 2. the mission record count is 1. + * 3. the ability record count is 1. + * 4. the result of StartAbility is ERRO_OK. + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_009, TestSize.Level1) +{ + stackManager_->Init(); + auto result = stackManager_->StartAbility(launcherAbilityRequest_); + auto missionStack = stackManager_->GetCurrentMissionStack(); + EXPECT_EQ(0, missionStack->GetMissionStackId()); + EXPECT_EQ(1, missionStack->GetMissionRecordCount()); + auto missionRecord = missionStack->GetTopMissionRecord(); + EXPECT_TRUE(missionRecord != nullptr); + EXPECT_EQ(1, missionRecord->GetAbilityRecordCount()); + auto topAbility = stackManager_->GetCurrentTopAbility(); + auto realAppinfo = topAbility->GetApplicationInfo(); + EXPECT_EQ("launcher", realAppinfo.name); + EXPECT_EQ(0, result); +} + +/* + * Feature: AbilityStackManager + * Function: StartAbility + * SubFunction: LoadFirstAbility + * FunctionPoints: NA + * EnvConditions: top ability is null + * CaseDescription: start the first ability not belong to launcher. verify: + * 1. the MissionStack is common app mission stack + * 2. the mission record count is 1. + * 3. the ability record count is 1. + * 4. the result of StartAbility is ERRO_OK. + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_010, TestSize.Level1) +{ + stackManager_->Init(); + auto result = stackManager_->StartAbility(launcherAbilityRequest_); + auto missionStack = stackManager_->GetCurrentMissionStack(); + EXPECT_EQ(0, missionStack->GetMissionStackId()); + EXPECT_EQ(1, missionStack->GetMissionRecordCount()); + auto missionRecord = missionStack->GetTopMissionRecord(); + EXPECT_EQ(1, missionRecord->GetAbilityRecordCount()); + auto topAbility = stackManager_->GetCurrentTopAbility(); + auto realAppinfo = topAbility->GetApplicationInfo(); + EXPECT_EQ("launcher", realAppinfo.name); + EXPECT_EQ(0, result); +} + +/* + * Feature: AbilityStackManager + * Function: StartAbility + * SubFunction: MoveMissionStackToTop, LoadFirstAbility, LoadAbility ChooseMissionRecord, Inactivate + * FunctionPoints: NA + * EnvConditions: top ability is not null, and top is launcher + * CaseDescription: start the second ability belong to launcher. verify: + * 1. the MissionStack is launcher mission stack + * 2. the mission record count is 1. + * 3. the ability record count is 2. + * 4. the result of StartAbility is ERRO_OK. + * 5. the state of top ability is INACTIVATING. + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_011, TestSize.Level1) +{ + stackManager_->Init(); + auto result = stackManager_->StartAbility(launcherAbilityRequest_); + EXPECT_EQ(0, result); + auto firstTopAbility = stackManager_->GetCurrentTopAbility(); + firstTopAbility->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + + result = stackManager_->StartAbility(musicAbilityRequest_); + auto secondTopAbility = stackManager_->GetCurrentTopAbility(); + secondTopAbility->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + EXPECT_EQ(0, result); + + // verify + auto missionStack = stackManager_->GetCurrentMissionStack(); + EXPECT_EQ(1, missionStack->GetMissionStackId()); + EXPECT_EQ(1, missionStack->GetMissionRecordCount()); + auto missionRecord = missionStack->GetTopMissionRecord(); + EXPECT_EQ(1, missionRecord->GetAbilityRecordCount()); + auto realAbilityinfo = secondTopAbility->GetAbilityInfo(); + EXPECT_EQ("MusicAbility", realAbilityinfo.name); + + auto state = firstTopAbility->GetAbilityState(); + EXPECT_EQ(OHOS::AAFwk::INACTIVATING, state); +} + +/* + * Feature: AbilityStackManager + * Function: StartAbility + * SubFunction: MoveMissionStackToTop, LoadFirstAbility, LoadAbility ChooseMissionRecord, Inactivate + * FunctionPoints: NA + * EnvConditions: top ability is not null, and top is launcher + * CaseDescription: start the second ability not belong to launcher. verify: + * 1. the MissionStack is common app mission stack + * 2. the mission record count is 1. + * 3. the ability record count is 1. + * 4. the result of StartAbility is ERRO_OK. + * 5. the state of top ability is INACTIVATING. + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_012, TestSize.Level1) +{ + stackManager_->Init(); + + auto result = stackManager_->StartAbility(launcherAbilityRequest_); + EXPECT_EQ(0, result); + auto firstTopAbility = stackManager_->GetCurrentTopAbility(); + firstTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + result = stackManager_->StartAbility(musicAbilityRequest_); + EXPECT_EQ(0, result); + auto secondTopAbility = stackManager_->GetCurrentTopAbility(); + secondTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + auto missionStack = stackManager_->GetCurrentMissionStack(); + EXPECT_EQ(1, missionStack->GetMissionStackId()); + EXPECT_EQ(1, missionStack->GetMissionRecordCount()); + auto missionRecord = missionStack->GetTopMissionRecord(); + EXPECT_EQ(1, missionRecord->GetAbilityRecordCount()); + auto realAppinfo = secondTopAbility->GetApplicationInfo(); + EXPECT_EQ("music", realAppinfo.name); + + auto state = firstTopAbility->GetAbilityState(); + EXPECT_EQ(OHOS::AAFwk::INACTIVATING, state); +} + +/* + * Feature: AbilityStackManager + * Function: StartAbility + * SubFunction: MoveMissionStackToTop, LoadFirstAbility, LoadAbility ChooseMissionRecord, Inactivate + * FunctionPoints: NA + * EnvConditions: top ability is not null, and top is launcher + * CaseDescription: resort the first ability. verify: + * 1. the MissionStack is common app mission stack + * 2. the mission record count is 1. + * 3. the ability record count is 2. + * 4. the result of StartAbility is ERRO_OK. + * 5. the name of top ability is "secondAbility". + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_013, TestSize.Level1) +{ + // start first ability not belong to launcher. + stackManager_->Init(); + auto result = stackManager_->StartAbility(musicAbilityRequest_); + EXPECT_EQ(0, result); + auto firstAbility = stackManager_->GetCurrentTopAbility(); + firstAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + // start second ability not belong to launcher. + result = stackManager_->StartAbility(musicTopAbilityRequest_); + EXPECT_EQ(0, result); + auto secondAbility = stackManager_->GetCurrentTopAbility(); + secondAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + // start launcher ability. + result = stackManager_->StartAbility(launcherAbilityRequest_); + auto missionStack = stackManager_->GetCurrentMissionStack(); + EXPECT_EQ(0, missionStack->GetMissionStackId()); + EXPECT_EQ(0, result); + OHOS::AAFwk::AbilityState state = secondAbility->GetAbilityState(); + EXPECT_EQ(OHOS::AAFwk::INACTIVATING, state); + + auto topAbility = stackManager_->GetCurrentTopAbility(); + topAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + // restart first ability not belong to launcher. + result = stackManager_->StartAbility(musicAbilityRequest_); + EXPECT_EQ(0, result); + topAbility = stackManager_->GetCurrentTopAbility(); + topAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + // verify + missionStack = stackManager_->GetCurrentMissionStack(); + EXPECT_EQ(1, missionStack->GetMissionStackId()); + EXPECT_EQ(1, missionStack->GetMissionRecordCount()); + auto missionRecord = missionStack->GetTopMissionRecord(); + EXPECT_EQ(2, missionRecord->GetAbilityRecordCount()); + topAbility = stackManager_->GetCurrentTopAbility(); + auto realAbilityInfo = topAbility->GetAbilityInfo(); + EXPECT_EQ("MusicTopAbility", realAbilityInfo.name); +} + +/* + * Feature: AbilityStackManager + * Function: StartAbility + * SubFunction: MoveMissionStackToTop, LoadFirstAbility, LoadAbility ChooseMissionRecord, Inactivate + * FunctionPoints: NA + * EnvConditions: top ability is not null, and top is not launcher + * CaseDescription: start a new ability from the common app first ability.verify: + * 1. the MissionStack is common app mission stack + * 2. the mission record count is 1. + * 3. the ability record count is 2. + * 4. the result of StartAbility is ERRO_OK. + * 5. the name of top ability is "secondAbility". + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_014, TestSize.Level1) +{ + // start launcher ability + stackManager_->Init(); + auto result = stackManager_->StartAbility(launcherAbilityRequest_); + EXPECT_EQ(0, result); + auto launcherTopAbility = stackManager_->GetCurrentTopAbility(); + launcherTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + // start common app the first ability from launcher + result = stackManager_->StartAbility(musicAbilityRequest_); + auto missionStack = stackManager_->GetCurrentMissionStack(); + EXPECT_EQ(1, missionStack->GetMissionStackId()); + EXPECT_EQ(0, result); + auto secondTopAbility = stackManager_->GetCurrentTopAbility(); + secondTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + auto state = launcherTopAbility->GetAbilityState(); + EXPECT_EQ(OHOS::AAFwk::INACTIVATING, state); + + // start the second ability from the common first ability + result = stackManager_->StartAbility(musicTopAbilityRequest_); + EXPECT_EQ(0, result); + auto thirdTopAbility = stackManager_->GetCurrentTopAbility(); + thirdTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + // verify + missionStack = stackManager_->GetCurrentMissionStack(); + EXPECT_EQ(1, missionStack->GetMissionStackId()); + EXPECT_EQ(1, missionStack->GetMissionRecordCount()); + auto missionRecord = missionStack->GetTopMissionRecord(); + EXPECT_EQ(2, missionRecord->GetAbilityRecordCount()); + state = secondTopAbility->GetAbilityState(); + EXPECT_EQ(OHOS::AAFwk::INACTIVATING, state); + auto realAbilityInfo = thirdTopAbility->GetAbilityInfo(); + EXPECT_EQ("MusicTopAbility", realAbilityInfo.name); +} + +/* + * Feature: AbilityStackManager + * Function: StartAbility + * SubFunction: MoveMissionStackToTop, LoadFirstAbility, LoadAbility ChooseMissionRecord, Inactivate + * FunctionPoints: NA + * EnvConditions: top ability is not null, and top is not launcher + * CaseDescription: start launcher ability from the common app ability.verify: + * 1. the MissionStack is launcher mission stack + * 2. the mission record count is 1. + * 3. the ability record count is 1. + * 4. the result of StartAbility is ERRO_OK. + * 5. the name of top ability is "MainAbility". + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_015, TestSize.Level1) +{ + // start common app the first ability from launcher + stackManager_->Init(); + + int result = stackManager_->StartAbility(musicAbilityRequest_); + auto missionStack = stackManager_->GetCurrentMissionStack(); + EXPECT_EQ(1, missionStack->GetMissionStackId()); + EXPECT_EQ(0, result); + auto firstTopAbility = stackManager_->GetCurrentTopAbility(); + firstTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + // start the second ability from the common first ability + result = stackManager_->StartAbility(musicTopAbilityRequest_); + EXPECT_EQ(0, result); + auto secondTopAbility = stackManager_->GetCurrentTopAbility(); + secondTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + // start launcher ability + result = stackManager_->StartAbility(launcherAbilityRequest_); + EXPECT_EQ(0, result); + auto thirdopAbility = stackManager_->GetCurrentTopAbility(); + thirdopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + // verify + missionStack = stackManager_->GetCurrentMissionStack(); + EXPECT_EQ(0, missionStack->GetMissionStackId()); + EXPECT_EQ(1, missionStack->GetMissionRecordCount()); + auto missionRecord = missionStack->GetTopMissionRecord(); + EXPECT_EQ(1, missionRecord->GetAbilityRecordCount()); + auto thirdTopAbility = stackManager_->GetCurrentTopAbility(); + auto realAbilityInfo = thirdTopAbility->GetAbilityInfo(); + EXPECT_EQ("LauncherAbility", realAbilityInfo.name); + auto realAppInfo = thirdTopAbility->GetApplicationInfo(); + EXPECT_EQ("launcher", realAppInfo.name); +} + +/* + * Feature: AbilityStackManager + * Function: StartAbility + * SubFunction: MoveMissionStackToTop, LoadFirstAbility, LoadAbility ChooseMissionRecord, Inactivate + * FunctionPoints: NA + * EnvConditions: top ability is not null, and top is not launcher + * CaseDescription: start two same ability.verify: + * 1. the MissionStack is common app mission stack + * 2. the mission record count is 1. + * 3. the ability record count is 2. + * 4. the result of StartAbility is ERRO_OK. + * 5. the name of top ability is "MainAbility". + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_016, TestSize.Level1) +{ + // start common app the first ability from launcher + stackManager_->Init(); + auto result = stackManager_->StartAbility(musicAbilityRequest_); + auto missionStack = stackManager_->GetCurrentMissionStack(); + EXPECT_EQ(1, missionStack->GetMissionStackId()); + EXPECT_EQ(0, result); + auto firstTopAbility = stackManager_->GetCurrentTopAbility(); + firstTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + // start the same ability from the first ability + result = stackManager_->StartAbility(radioAbilityRequest_); + EXPECT_EQ(0, result); + auto secondTopAbility = stackManager_->GetCurrentTopAbility(); + secondTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + // verify + missionStack = stackManager_->GetCurrentMissionStack(); + EXPECT_EQ(1, missionStack->GetMissionStackId()); + EXPECT_EQ(1, missionStack->GetMissionRecordCount()); + auto missionRecord = missionStack->GetTopMissionRecord(); + EXPECT_EQ(2, missionRecord->GetAbilityRecordCount()); + auto topAbility = stackManager_->GetCurrentTopAbility(); + auto realAbilityInfo = topAbility->GetAbilityInfo(); + EXPECT_EQ("RadioAbility", realAbilityInfo.name); + auto realAppInfo = topAbility->GetApplicationInfo(); + EXPECT_EQ("radio", realAppInfo.name); +} + +/* + * Feature: AbilityStackManager + * Function: StartAbility + * SubFunction: MoveMissionStackToTop, LoadFirstAbility, LoadAbility ChooseMissionRecord, Inactivate + * FunctionPoints: NA + * EnvConditions: top ability is not null, and top is not launcher + * CaseDescription: start three ability. the bottom and the top are the same. + * 1. the MissionStack is common app mission stack + * 2. the mission record count is 1. + * 3. the ability record count is 3. + * 4. the result of StartAbility is ERRO_OK. + * 5. the name of top ability and bottom is "MainAbility". + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_017, TestSize.Level1) +{ + // start common app the first ability from launcher + stackManager_->Init(); + auto result = stackManager_->StartAbility(musicAbilityRequest_); + auto missionStack = stackManager_->GetCurrentMissionStack(); + EXPECT_EQ(1, missionStack->GetMissionStackId()); + EXPECT_EQ(0, result); + auto firstTopAbility = stackManager_->GetCurrentTopAbility(); + firstTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + // start the second ability from the first ability + result = stackManager_->StartAbility(musicTopAbilityRequest_); + EXPECT_EQ(0, result); + auto secondTopAbility = stackManager_->GetCurrentTopAbility(); + secondTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + // start the same ability with the first ability + result = stackManager_->StartAbility(radioAbilityRequest_); + EXPECT_EQ(0, result); + auto thirdTopAbility = stackManager_->GetCurrentTopAbility(); + thirdTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + // verify + missionStack = stackManager_->GetCurrentMissionStack(); + EXPECT_EQ(1, missionStack->GetMissionStackId()); + EXPECT_EQ(1, missionStack->GetMissionRecordCount()); + auto missionRecord = missionStack->GetTopMissionRecord(); + EXPECT_EQ(3, missionRecord->GetAbilityRecordCount()); + + auto topAbility = stackManager_->GetCurrentTopAbility(); + auto realAbilityInfo = topAbility->GetAbilityInfo(); + EXPECT_EQ("RadioAbility", realAbilityInfo.name); + + auto realAppInfo = topAbility->GetApplicationInfo(); + EXPECT_EQ("radio", realAppInfo.name); + + auto bottomAbility = missionRecord->GetBottomAbilityRecord(); + EXPECT_EQ("RadioAbility", realAbilityInfo.name); +} + +/* + * Feature: AbilityStackManager + * Function: GetAbilityStackManagerUserId + * SubFunction: NA + * FunctionPoints: NA + * EnvConditions:NA + * CaseDescription: Verify get user id value + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_018, TestSize.Level1) +{ + EXPECT_EQ(stackManager_->GetAbilityStackManagerUserId(), 0); +} + +/* + * Feature: AbilityStackManager + * Function: StartAbility + * SubFunction: NA + * FunctionPoints: AbilityStackManager StartAbility + * EnvConditions: NA + * CaseDescription: launchMode is STANDARD, Startability and verify value + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_019, TestSize.Level1) +{ + stackManager_->Init(); + auto result = stackManager_->StartAbility(launcherAbilityRequest_); + EXPECT_EQ(0, result); + + auto topAbility = stackManager_->GetCurrentTopAbility(); + topAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + auto result1 = stackManager_->StartAbility(musicAbilityRequest_); + EXPECT_EQ(0, result1); + + auto topAbility1 = stackManager_->GetCurrentTopAbility(); + topAbility1->SetAbilityState(OHOS::AAFwk::ACTIVE); + + auto result2 = stackManager_->StartAbility(radioAbilityRequest_); + EXPECT_EQ(0, result2); + + auto topAbility2 = stackManager_->GetCurrentTopAbility(); + topAbility2->SetAbilityState(OHOS::AAFwk::ACTIVE); + + std::vector info; + info.push_back("0"); + stackManager_->Dump(info); + stackManager_->DumpStackList(info); + info.push_back("1"); + stackManager_->DumpStack(stackManager_->GetTopMissionRecord()->GetMissionRecordId(), info); + stackManager_->DumpMission(stackManager_->GetTopMissionRecord()->GetMissionRecordId(), info); + stackManager_->DumpTopAbility(info); + std::string s = "0"; + stackManager_->DumpWaittingAbilityQueue(s); + + EXPECT_NE(stackManager_->GetMissionRecordById(stackManager_->GetTopMissionRecord()->GetMissionRecordId()), nullptr); + EXPECT_EQ(stackManager_->RemoveMissionRecordById(stackManager_->GetTopMissionRecord()->GetMissionRecordId()), true); +} + +/* + * Feature: AbilityStackManager + * Function: TerminateAbility + * SubFunction: NA + * FunctionPoints: AbilityStackManager TerminateAbility + * EnvConditions:NA + * CaseDescription: 1. ability record is nullptr cause TerminateAbility failed + * 2. Verify TerminateAbility succeeded + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_020, TestSize.Level1) +{ + stackManager_->Init(); + + auto result = stackManager_->StartAbility(musicAbilityRequest_); + EXPECT_EQ(0, result); + + auto topAbility = stackManager_->GetCurrentTopAbility(); + auto want = topAbility->GetWant(); + topAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + std::shared_ptr record = nullptr; + auto nullToken = new Token(record); + EXPECT_NE(0, stackManager_->TerminateAbility(nullToken, -1, &want)); + + auto token = topAbility->GetToken(); + auto res = stackManager_->TerminateAbility(token, -1, &want); + EXPECT_EQ(0, res); +} + +/* + * Feature: AbilityStackManager + * Function: TerminateAbility + * SubFunction: NA + * FunctionPoints: AbilityStackManager TerminateAbility + * EnvConditions:NA + * CaseDescription: isTerminating_ is true cause TerminateAbility success + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_021, TestSize.Level1) +{ + stackManager_->Init(); + int result = stackManager_->StartAbility(launcherAbilityRequest_); + EXPECT_EQ(0, result); + + auto topAbility = stackManager_->GetCurrentTopAbility(); + auto want = topAbility->GetWant(); + topAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + topAbility->SetTerminatingState(); + auto token = topAbility->GetToken(); + auto res = stackManager_->TerminateAbility(token, -1, &want); + EXPECT_EQ(0, res); +} + +/* + * Feature: AbilityStackManager + * Function: TerminateAbility + * SubFunction: NA + * FunctionPoints: NA + * EnvConditions:NA + * CaseDescription: Terminate other Ability cause fail + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_022, TestSize.Level1) +{ + stackManager_->Init(); + + auto result = stackManager_->StartAbility(launcherAbilityRequest_); + EXPECT_EQ(0, result); + + auto topAbility = stackManager_->GetCurrentTopAbility(); + auto want = topAbility->GetWant(); + topAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + std::string deviceName = "device"; + std::string abilityName = "otherAbility"; + std::string appName = "otherApp"; + std::string bundleName = "com.ix.other"; + std::vector config; + auto abilityReq = GenerateAbilityRequest(deviceName, abilityName, appName, bundleName, config); + auto record = AbilityRecord::CreateAbilityRecord(abilityReq); + auto nullToken = new Token(record); + EXPECT_NE(0, stackManager_->TerminateAbility(nullToken, -1, &want)); +} + +/* + * Feature: AbilityStackManager + * Function: AbilityTransitionDone + * SubFunction: NA + * FunctionPoints: AbilityStackManager AbilityTransitionDone + * EnvConditions:NA + * CaseDescription: handler is nullptr cause dispatchActive failed + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_023, TestSize.Level1) +{ + stackManager_->Init(); + auto result = stackManager_->StartAbility(launcherAbilityRequest_); + EXPECT_EQ(0, result); + + auto topAbility = stackManager_->GetCurrentTopAbility(); + topAbility->SetAbilityState(OHOS::AAFwk::INITIAL); + auto token = topAbility->GetToken(); + EXPECT_NE(stackManager_->AbilityTransitionDone(token, OHOS::AAFwk::ACTIVE), 0); + + std::shared_ptr record = nullptr; + auto nullToken = new Token(record); + EXPECT_NE(stackManager_->AbilityTransitionDone(nullToken, OHOS::AAFwk::INACTIVE), 0); + + auto token1 = topAbility->GetToken(); + EXPECT_NE(stackManager_->AbilityTransitionDone(token1, OHOS::AAFwk::BACKGROUND), 0); + + auto token2 = topAbility->GetToken(); + EXPECT_NE(stackManager_->AbilityTransitionDone(token2, OHOS::AAFwk::INITIAL), 0); + + auto token3 = topAbility->GetToken(); + EXPECT_NE(stackManager_->AbilityTransitionDone(token3, OHOS::AAFwk::TERMINATING), 0); + + auto token4 = topAbility->GetToken(); + EXPECT_NE(stackManager_->AbilityTransitionDone(token4, OHOS::AAFwk::INACTIVE), 0); +} + +/* + * Feature: AbilityStackManager + * Function: TerminateAbility + * SubFunction: NA + * FunctionPoints: AbilityStackManager TerminateAbility + * EnvConditions:NA + * CaseDescription: start ability and remove ability record, verify terminal ability fail + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_024, TestSize.Level1) +{ + stackManager_->Init(); + auto result = stackManager_->StartAbility(launcherAbilityRequest_); + EXPECT_EQ(0, result); + + auto topAbility = stackManager_->GetCurrentTopAbility(); + auto want = topAbility->GetWant(); + topAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + std::string deviceName = "device"; + std::string abilityName = "otherAbility"; + std::string appName = "otherApp"; + std::string bundleName = "com.ix.other"; + std::vector config; + auto abilityReq = GenerateAbilityRequest(deviceName, abilityName, appName, bundleName, config); + auto record = AbilityRecord::CreateAbilityRecord(abilityReq); + auto token = topAbility->GetToken(); + stackManager_->GetTopMissionRecord()->RemoveTopAbilityRecord(); + auto res = stackManager_->TerminateAbility(token, -1, &want); + EXPECT_NE(0, res); +} + +/* + * Feature: AbilityStackManager + * Function: TerminateAbility + * SubFunction: NA + * FunctionPoints: AbilityStackManager TerminateAbility + * EnvConditions:NA + * CaseDescription: MissionRecord is nullptr cause TerminateAbility fail + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_025, TestSize.Level1) +{ + stackManager_->Init(); + auto result = stackManager_->StartAbility(launcherAbilityRequest_); + EXPECT_EQ(0, result); + + auto topAbility = stackManager_->GetCurrentTopAbility(); + auto want = topAbility->GetWant(); + topAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + auto token = topAbility->GetToken(); + std::shared_ptr mission = nullptr; + topAbility->SetMissionRecord(mission); + auto res = stackManager_->TerminateAbility(token, -1, &want); + EXPECT_NE(0, res); + + topAbility->isLauncherAbility_ = true; +} + +/* + * Feature: AbilityStackManager + * Function: TerminateAbility + * SubFunction: NA + * FunctionPoints: AbilityStackManager TerminateAbility + * EnvConditions:NA + * CaseDescription: isLauncherAbility_ is true cause TerminateAbility failed + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_026, TestSize.Level1) +{ + stackManager_->Init(); + auto result = stackManager_->StartAbility(musicAbilityRequest_); + EXPECT_EQ(0, result); + + auto topAbility = stackManager_->GetCurrentTopAbility(); + topAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + auto want = topAbility->GetWant(); + auto token = topAbility->GetToken(); + topAbility->isLauncherAbility_ = true; + auto res = stackManager_->TerminateAbility(token, -1, &want); + EXPECT_NE(0, res); +} + +/* + * Feature: AbilityStackManager + * Function: GetTargetMissionStack + * SubFunction: NA + * FunctionPoints: AbilityStackManager GetTargetMissionStack + * EnvConditions:NA + * CaseDescription: Verify get target mission stack value + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_027, TestSize.Level1) +{ + stackManager_->Init(); + Want want; + want.AddEntity(Want::ENTITY_HOME); + AbilityRequest request; + request.want = want; + request.abilityInfo.applicationInfo.isLauncherApp = true; + EXPECT_EQ(stackManager_->launcherMissionStack_, stackManager_->GetTargetMissionStack(request)); + Want want1; + AbilityRequest request1; + want1.AddEntity(Want::ENTITY_VIDEO); + request.want = want1; + request.abilityInfo.applicationInfo.isLauncherApp = false; + EXPECT_EQ(stackManager_->defaultMissionStack_, stackManager_->GetTargetMissionStack(request1)); +} + +/* + * Feature: AbilityStackManager + * Function: AttachAbilityThread + * SubFunction: NA + * FunctionPoints: AbilityStackManager AttachAbilityThread + * EnvConditions:NA + * CaseDescription: handler is nullptr cause AttachAbilityThread fail + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_028, TestSize.Level1) +{ + stackManager_->Init(); + auto result = stackManager_->StartAbility(musicAbilityRequest_); + EXPECT_EQ(0, result); + + auto topAbility = stackManager_->GetCurrentTopAbility(); + topAbility->SetAbilityState(OHOS::AAFwk::INITIAL); + auto token = topAbility->GetToken(); + + OHOS::sptr scheduler = new AbilityScheduler(); + EXPECT_EQ(stackManager_->AttachAbilityThread(scheduler, token), ERR_OK); + + std::shared_ptr record = nullptr; + auto nullToken = new Token(record); + EXPECT_EQ(stackManager_->AttachAbilityThread(scheduler, nullToken), ERR_INVALID_VALUE); +} + +/* + * Feature: AbilityStackManager + * Function: AddWindowInfo + * SubFunction: NA + * FunctionPoints: AbilityStackManager AddWindowInfo + * EnvConditions:NA + * CaseDescription: Verify AddWindowInfo operation + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_029, TestSize.Level1) +{ + stackManager_->Init(); + int result = stackManager_->StartAbility(musicAbilityRequest_); + EXPECT_EQ(0, result); + + auto topAbility = stackManager_->GetCurrentTopAbility(); + topAbility->SetAbilityState(OHOS::AAFwk::INITIAL); + auto token = topAbility->GetToken(); + + std::shared_ptr nullAbility = nullptr; + auto nullToken = new Token(nullAbility); + stackManager_->AddWindowInfo(nullToken, 1); + EXPECT_EQ(static_cast(stackManager_->windowTokenToAbilityMap_.size()), 0); + topAbility->AddWindowInfo(1); + stackManager_->AddWindowInfo(token, 1); + EXPECT_EQ(static_cast(stackManager_->windowTokenToAbilityMap_.size()), 0); + topAbility->RemoveWindowInfo(); + stackManager_->AddWindowInfo(token, 1); + EXPECT_EQ(static_cast(stackManager_->windowTokenToAbilityMap_.size()), 1); + stackManager_->AddWindowInfo(token, 2); + EXPECT_EQ(static_cast(stackManager_->windowTokenToAbilityMap_.size()), 1); +} + +/* + * Feature: AbilityStackManager + * Function: MoveMissionStackToTop + * SubFunction: NA + * FunctionPoints: AbilityStackManager MoveMissionStackToTop + * EnvConditions:NA + * CaseDescription: MoveMissionStackToTop UT Exception case + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_030, TestSize.Level1) +{ + stackManager_->Init(); + int result = stackManager_->StartAbility(launcherAbilityRequest_); + EXPECT_EQ(0, result); + auto topAbility = stackManager_->GetCurrentTopAbility(); + topAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + int result1 = stackManager_->StartAbility(musicAbilityRequest_); + EXPECT_EQ(0, result1); + topAbility = stackManager_->GetCurrentTopAbility(); + topAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + std::shared_ptr mission = nullptr; + stackManager_->MoveMissionStackToTop(mission); + + EXPECT_EQ(topAbility->GetAbilityInfo().name, "MusicAbility"); + EXPECT_EQ(stackManager_->currentMissionStack_, stackManager_->defaultMissionStack_); + + stackManager_->MoveMissionStackToTop(stackManager_->launcherMissionStack_); + topAbility = stackManager_->GetCurrentTopAbility(); + + EXPECT_EQ(topAbility->GetAbilityInfo().name, "LauncherAbility"); + EXPECT_EQ(stackManager_->currentMissionStack_, stackManager_->launcherMissionStack_); +} + +/* + * Feature: AbilityStackManager + * Function: IsLauncherAbility + * SubFunction: NA + * FunctionPoints: IsLauncherAbility + * EnvConditions:NA + * CaseDescription: Verify that ability is a launcher + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_031, TestSize.Level1) +{ + Want want; + std::string entity = Want::ENTITY_HOME; + want.AddEntity(entity); + + std::string testAppName = "ability_stack_manager_test_app"; + AbilityInfo abilityInfo; + abilityInfo.applicationName = testAppName; + ApplicationInfo appinfo; + appinfo.name = testAppName; + appinfo.isLauncherApp = true; + abilityInfo.applicationInfo = appinfo; + AbilityRequest abilityRequest; + abilityRequest.want = want; + abilityRequest.abilityInfo = abilityInfo; + abilityRequest.appInfo = appinfo; + + stackManager_->Init(); + auto topAbility = stackManager_->GetCurrentTopAbility(); + stackManager_->StartAbility(abilityRequest); + EXPECT_EQ(stackManager_->IsLauncherAbility(abilityRequest), true); +} + +/* + * Feature: AbilityStackManager + * Function: GetRecentMissions + * SubFunction: NA + * FunctionPoints: GetRecentMissions + * EnvConditions: NA + * CaseDescription: Failed to verify getrecentmissions + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_033, TestSize.Level1) +{ + std::vector info; + auto result = stackManager_->GetRecentMissions(-1, 0, info); + EXPECT_EQ(ERR_INVALID_VALUE, result); + + result = stackManager_->GetRecentMissions(10, 10, info); + EXPECT_EQ(ERR_INVALID_VALUE, result); + + stackManager_->defaultMissionStack_ = nullptr; + result = stackManager_->GetRecentMissions(10, 1, info); + EXPECT_EQ(ERR_NO_INIT, result); +} + +/* + * Feature: AbilityStackManager + * Function: GetRecentMissions + * SubFunction: NA + * FunctionPoints: GetRecentMissions + * EnvConditions: NA + * CaseDescription: Get all recent missions list + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_034, TestSize.Level1) +{ + stackManager_->Init(); + auto result = stackManager_->StartAbility(launcherAbilityRequest_); + EXPECT_EQ(ERR_OK, result); + auto firstTopAbility = stackManager_->GetCurrentTopAbility(); + firstTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + result = stackManager_->StartAbility(musicAbilityRequest_); + EXPECT_EQ(ERR_OK, result); + auto secondTopAbility = stackManager_->GetCurrentTopAbility(); + secondTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + result = stackManager_->StartAbility(radioAbilityRequest_); + EXPECT_EQ(ERR_OK, result); + auto thirdTopAbility = stackManager_->GetCurrentTopAbility(); + thirdTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + std::vector info; + result = stackManager_->GetRecentMissions(10, 1, info); + EXPECT_EQ(ERR_OK, result); + + EXPECT_EQ(static_cast(info.size()), 1); + EXPECT_EQ(info[0].id, thirdTopAbility->GetMissionRecord()->GetMissionRecordId()); + EXPECT_EQ("RadioAbility", info[0].topAbility.GetAbilityName()); +} + +/* + * Feature: AbilityStackManager + * Function: GetRecentMissions + * SubFunction: NA + * FunctionPoints: GetRecentMissions + * EnvConditions: NA + * CaseDescription: Gets the list of recently active tasks + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_035, TestSize.Level1) +{ + stackManager_->Init(); + auto result = stackManager_->StartAbility(launcherAbilityRequest_); + EXPECT_EQ(ERR_OK, result); + auto firstTopAbility = stackManager_->GetCurrentTopAbility(); + firstTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + result = stackManager_->StartAbility(musicAbilityRequest_); + EXPECT_EQ(ERR_OK, result); + auto secondTopAbility = stackManager_->GetCurrentTopAbility(); + secondTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + result = stackManager_->StartAbility(radioAbilityRequest_); + EXPECT_EQ(ERR_OK, result); + auto thirdTopAbility = stackManager_->GetCurrentTopAbility(); + thirdTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + result = stackManager_->StartAbility(musicSAbilityRequest_); + EXPECT_EQ(ERR_OK, result); + auto topAbility = stackManager_->GetCurrentTopAbility(); + topAbility->SetAbilityState(OHOS::AAFwk::INITIAL); + + std::vector info; + result = stackManager_->GetRecentMissions(10, 2, info); + EXPECT_EQ(ERR_OK, result); + + EXPECT_EQ(static_cast(info.size()), 1); + EXPECT_EQ(info[0].id, thirdTopAbility->GetMissionRecord()->GetMissionRecordId()); + EXPECT_EQ("RadioAbility", info[0].topAbility.GetAbilityName()); +} + +/* + * Feature: AbilityStackManager + * Function: MoveMissionToTop + * SubFunction: NA + * FunctionPoints: MoveMissionToTop + * EnvConditions: NA + * CaseDescription: Failed to verify movemissiontotop + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_036, TestSize.Level1) +{ + stackManager_->Init(); + + auto result = stackManager_->MoveMissionToTop(-1); + EXPECT_EQ(ERR_INVALID_VALUE, result); + + stackManager_->launcherMissionStack_ = nullptr; + auto result1 = stackManager_->MoveMissionToTop(10); + EXPECT_EQ(ERR_NO_INIT, result1); +} + +/* + * Feature: AbilityStackManager + * Function: MoveMissionToTop + * SubFunction: NA + * FunctionPoints: MoveMissionToTop + * EnvConditions: NA + * CaseDescription: Failed to verify movemissiontotop + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_037, TestSize.Level1) +{ + stackManager_->Init(); + auto result = stackManager_->StartAbility(launcherAbilityRequest_); + EXPECT_EQ(ERR_OK, result); + auto firstTopAbility = stackManager_->GetCurrentTopAbility(); + firstTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + result = stackManager_->StartAbility(musicAbilityRequest_); + EXPECT_EQ(ERR_OK, result); + auto secondTopAbility = stackManager_->GetCurrentTopAbility(); + secondTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + auto mission = secondTopAbility->GetMissionRecord(); + mission->RemoveAbilityRecord(secondTopAbility); + + auto result1 = stackManager_->MoveMissionToTop(mission->GetMissionRecordId()); + EXPECT_EQ(MOVE_MISSION_FAILED, result1); +} + +/* + * Feature: AbilityStackManager + * Function: MoveMissionToTop + * SubFunction: NA + * FunctionPoints: MoveMissionToTop + * EnvConditions: NA + * CaseDescription: Succeeded to verify movemissiontotop + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_038, TestSize.Level1) +{ + stackManager_->Init(); + auto result = stackManager_->StartAbility(launcherAbilityRequest_); + EXPECT_EQ(ERR_OK, result); + auto firstTopAbility = stackManager_->GetCurrentTopAbility(); + firstTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + result = stackManager_->StartAbility(musicAbilityRequest_); + EXPECT_EQ(ERR_OK, result); + auto secondTopAbility = stackManager_->GetCurrentTopAbility(); + secondTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + result = stackManager_->StartAbility(radioAbilityRequest_); + EXPECT_EQ(ERR_OK, result); + auto thirdTopAbility = stackManager_->GetCurrentTopAbility(); + thirdTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + auto mission = thirdTopAbility->GetMissionRecord(); + + result = stackManager_->StartAbility(musicSAbilityRequest_); + EXPECT_EQ(ERR_OK, result); + auto topAbility = stackManager_->GetCurrentTopAbility(); + topAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + auto result1 = stackManager_->MoveMissionToTop(mission->GetMissionRecordId()); + EXPECT_EQ(ERR_OK, result1); + + topAbility = stackManager_->GetCurrentTopAbility(); + EXPECT_EQ("RadioAbility", topAbility->GetAbilityInfo().name); +} + +/* + * Feature: AbilityStackManager + * Function: OnAbilityDied + * SubFunction: NA + * FunctionPoints: OnAbilityDied + * EnvConditions: NA + * CaseDescription: If the current ability is active, if it is dead, it will return to the launcher and the state will + * be init + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_039, TestSize.Level1) +{ + stackManager_->Init(); + auto result = stackManager_->StartAbility(launcherAbilityRequest_); + EXPECT_EQ(ERR_OK, result); + auto firstTopAbility = stackManager_->GetCurrentTopAbility(); + firstTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + result = stackManager_->StartAbility(musicAbilityRequest_); + EXPECT_EQ(ERR_OK, result); + auto secondTopAbility = stackManager_->GetCurrentTopAbility(); + secondTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + result = stackManager_->StartAbility(radioAbilityRequest_); + EXPECT_EQ(ERR_OK, result); + auto thirdTopAbility = stackManager_->GetCurrentTopAbility(); + thirdTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + auto mission = thirdTopAbility->GetMissionRecord(); + + result = stackManager_->StartAbility(musicSAbilityRequest_); + EXPECT_EQ(ERR_OK, result); + auto topAbility = stackManager_->GetCurrentTopAbility(); + topAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + stackManager_->OnAbilityDied(topAbility); + EXPECT_EQ(OHOS::AAFwk::INITIAL, topAbility->GetAbilityState()); + topAbility = stackManager_->GetCurrentTopAbility(); + EXPECT_EQ("MusicSAbility", topAbility->GetAbilityInfo().name); +} + +/* + * Feature: AbilityStackManager + * Function: OnAbilityDied + * SubFunction: NA + * FunctionPoints: OnAbilityDied + * EnvConditions: NA + * CaseDescription: If the current ability is uninstall, if it is dead, delete record, it will return to the launcher + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_040, TestSize.Level1) +{ + stackManager_->Init(); + auto result = stackManager_->StartAbility(launcherAbilityRequest_); + EXPECT_EQ(ERR_OK, result); + auto firstTopAbility = stackManager_->GetCurrentTopAbility(); + firstTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + result = stackManager_->StartAbility(musicAbilityRequest_); + EXPECT_EQ(ERR_OK, result); + auto secondTopAbility = stackManager_->GetCurrentTopAbility(); + secondTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + result = stackManager_->StartAbility(radioAbilityRequest_); + EXPECT_EQ(ERR_OK, result); + auto thirdTopAbility = stackManager_->GetCurrentTopAbility(); + thirdTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + auto mission = thirdTopAbility->GetMissionRecord(); + + result = stackManager_->StartAbility(musicSAbilityRequest_); + EXPECT_EQ(ERR_OK, result); + auto topAbility = stackManager_->GetCurrentTopAbility(); + topAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + topAbility->SetIsUninstallAbility(); + + stackManager_->OnAbilityDied(topAbility); + EXPECT_EQ(topAbility->GetMissionRecord(), nullptr); + topAbility = stackManager_->GetCurrentTopAbility(); + EXPECT_EQ("RadioAbility", topAbility->GetAbilityInfo().name); +} + +/* + * Feature: AbilityStackManager + * Function: OnAbilityDied + * SubFunction: NA + * FunctionPoints: OnAbilityDied + * EnvConditions: NA + * CaseDescription: kill music process, music ability state is init, back to launcher + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_041, TestSize.Level1) +{ + stackManager_->Init(); + auto result = stackManager_->StartAbility(launcherAbilityRequest_); + EXPECT_EQ(ERR_OK, result); + auto firstTopAbility = stackManager_->GetCurrentTopAbility(); + firstTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + result = stackManager_->StartAbility(musicAbilityRequest_); + EXPECT_EQ(ERR_OK, result); + auto secondTopAbility = stackManager_->GetCurrentTopAbility(); + secondTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + result = stackManager_->StartAbility(musicTopAbilityRequest_); + EXPECT_EQ(ERR_OK, result); + auto thirdTopAbility = stackManager_->GetCurrentTopAbility(); + thirdTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + auto mission = thirdTopAbility->GetMissionRecord(); +} + +/* + * Feature: AbilityStackManager + * Function: OnAbilityDied + * SubFunction: NA + * FunctionPoints: OnAbilityDied + * EnvConditions: NA + * CaseDescription: Uninstall music process, delete music record, back to launcher + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_042, TestSize.Level1) +{ + stackManager_->Init(); + auto result = stackManager_->StartAbility(launcherAbilityRequest_); + EXPECT_EQ(ERR_OK, result); + auto firstTopAbility = stackManager_->GetCurrentTopAbility(); + firstTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + result = stackManager_->StartAbility(musicAbilityRequest_); + EXPECT_EQ(ERR_OK, result); + auto secondTopAbility = stackManager_->GetCurrentTopAbility(); + secondTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + result = stackManager_->StartAbility(musicTopAbilityRequest_); + EXPECT_EQ(ERR_OK, result); + auto thirdTopAbility = stackManager_->GetCurrentTopAbility(); + thirdTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + auto mission = thirdTopAbility->GetMissionRecord(); + + stackManager_->UninstallApp("com.ix.hiMusic"); + // process died + stackManager_->OnAbilityDied(secondTopAbility); + stackManager_->OnAbilityDied(thirdTopAbility); + auto topAbility = stackManager_->GetCurrentTopAbility(); + EXPECT_EQ("MusicAbility", topAbility->GetAbilityInfo().name); + int size = stackManager_->defaultMissionStack_->GetMissionRecordCount(); + // handle is nullptr, not delete + EXPECT_EQ(size, 1); +} + +/* + * Feature: AbilityStackManager + * Function: RemoveMissionById + * SubFunction: NA + * FunctionPoints: RemoveMissionById + * EnvConditions: NA + * CaseDescription: Failed to verify removemissionbyid + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_043, TestSize.Level1) +{ + stackManager_->Init(); + auto result = stackManager_->StartAbility(launcherAbilityRequest_); + EXPECT_EQ(ERR_OK, result); + auto firstTopAbility = stackManager_->GetCurrentTopAbility(); + firstTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + auto launcherMissionId = firstTopAbility->GetMissionRecord()->GetMissionRecordId(); + + result = stackManager_->StartAbility(musicAbilityRequest_); + EXPECT_EQ(ERR_OK, result); + auto secondTopAbility = stackManager_->GetCurrentTopAbility(); + secondTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + auto missionId = secondTopAbility->GetMissionRecord()->GetMissionRecordId(); + + result = stackManager_->RemoveMissionById(-1); + EXPECT_EQ(ERR_INVALID_VALUE, result); + + result = stackManager_->RemoveMissionById(10); + EXPECT_EQ(REMOVE_MISSION_ID_NOT_EXIST, result); + + result = stackManager_->RemoveMissionById(launcherMissionId); + EXPECT_EQ(REMOVE_MISSION_LAUNCHER_DENIED, result); + + result = stackManager_->RemoveMissionById(missionId); + EXPECT_EQ(ERR_OK, result); + + stackManager_->defaultMissionStack_ = nullptr; + result = stackManager_->RemoveMissionById(missionId); + EXPECT_EQ(ERR_NO_INIT, result); +} + +/* + * Feature: AbilityStackManager + * Function: RemoveMissionById + * SubFunction: NA + * FunctionPoints: RemoveMissionById + * EnvConditions: NA + * CaseDescription: Succeeded to verify removemissionbyid + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_044, TestSize.Level1) +{ + stackManager_->Init(); + auto result = stackManager_->StartAbility(launcherAbilityRequest_); + EXPECT_EQ(ERR_OK, result); + auto firstTopAbility = stackManager_->GetCurrentTopAbility(); + firstTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + result = stackManager_->StartAbility(musicAbilityRequest_); + EXPECT_EQ(ERR_OK, result); + auto secondTopAbility = stackManager_->GetCurrentTopAbility(); + secondTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + auto missionId = secondTopAbility->GetMissionRecord()->GetMissionRecordId(); + + result = stackManager_->StartAbility(musicSAbilityRequest_); + EXPECT_EQ(ERR_OK, result); + auto topAbility = stackManager_->GetCurrentTopAbility(); + topAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + result = stackManager_->RemoveMissionById(missionId); + EXPECT_EQ(ERR_OK, result); + auto size = stackManager_->defaultMissionStack_->GetMissionRecordCount(); + + EXPECT_EQ(size, 1); +} + +/* + * Feature: AbilityStackManager + * Function: RemoveStack + * SubFunction: NA + * FunctionPoints: RemoveStack + * EnvConditions: NA + * CaseDescription: Failed to verify RemoveStack + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_045, TestSize.Level1) +{ + stackManager_->Init(); + auto result = stackManager_->StartAbility(launcherAbilityRequest_); + EXPECT_EQ(ERR_OK, result); + auto firstTopAbility = stackManager_->GetCurrentTopAbility(); + firstTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + result = stackManager_->StartAbility(musicAbilityRequest_); + EXPECT_EQ(ERR_OK, result); + auto secondTopAbility = stackManager_->GetCurrentTopAbility(); + secondTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + result = stackManager_->RemoveStack(-1); + EXPECT_EQ(ERR_INVALID_VALUE, result); + + result = stackManager_->RemoveStack(10); + EXPECT_EQ(ERR_INVALID_VALUE, result); + + result = stackManager_->RemoveStack(0); + EXPECT_EQ(REMOVE_STACK_LAUNCHER_DENIED, result); + + stackManager_->missionStackList_.clear(); + result = stackManager_->RemoveStack(1); + EXPECT_EQ(MISSION_STACK_LIST_IS_EMPTY, result); +} + +/* + * Feature: AbilityStackManager + * Function: RemoveStack + * SubFunction: NA + * FunctionPoints: RemoveStack + * EnvConditions: NA + * CaseDescription: Succeeded to verify RemoveStack + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_046, TestSize.Level1) +{ + stackManager_->Init(); + auto result = stackManager_->StartAbility(launcherAbilityRequest_); + EXPECT_EQ(ERR_OK, result); + auto firstTopAbility = stackManager_->GetCurrentTopAbility(); + firstTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + result = stackManager_->StartAbility(musicAbilityRequest_); + EXPECT_EQ(ERR_OK, result); + auto secondTopAbility = stackManager_->GetCurrentTopAbility(); + secondTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + result = stackManager_->StartAbility(launcherAbilityRequest_); + EXPECT_EQ(ERR_OK, result); + auto topAbility = stackManager_->GetCurrentTopAbility(); + topAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + result = stackManager_->RemoveStack(1); + EXPECT_EQ(ERR_OK, result); +} + +/* + * Feature: AbilityStackManager + * Function: RemoveStack + * SubFunction: NA + * FunctionPoints: RemoveStack + * EnvConditions: NA + * CaseDescription: Succeeded to verify RemoveStack + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_047, TestSize.Level1) +{ + stackManager_->Init(); + auto result = stackManager_->StartAbility(launcherAbilityRequest_); + EXPECT_EQ(ERR_OK, result); + auto firstTopAbility = stackManager_->GetCurrentTopAbility(); + firstTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + result = stackManager_->StartAbility(musicAbilityRequest_); + EXPECT_EQ(ERR_OK, result); + auto secondTopAbility = stackManager_->GetCurrentTopAbility(); + EXPECT_NE(OHOS::AAFwk::ACTIVE, secondTopAbility->GetAbilityState()); + + result = stackManager_->PowerOff(); + EXPECT_EQ(POWER_OFF_WAITING, result); +} + +/* + * Feature: AbilityStackManager + * Function: RemoveStack + * SubFunction: NA + * FunctionPoints: RemoveStack + * EnvConditions: NA + * CaseDescription: Succeeded to verify RemoveStack + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_048, TestSize.Level1) +{ + stackManager_->Init(); + auto result = stackManager_->StartAbility(launcherAbilityRequest_); + EXPECT_EQ(ERR_OK, result); + auto firstTopAbility = stackManager_->GetCurrentTopAbility(); + firstTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + auto firstMissionId = firstTopAbility->GetMissionRecord()->GetMissionRecordId(); + + result = stackManager_->StartAbility(musicAbilityRequest_); + EXPECT_EQ(ERR_OK, result); + auto secondTopAbility = stackManager_->GetCurrentTopAbility(); + secondTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + auto secondMissionId = secondTopAbility->GetMissionRecord()->GetMissionRecordId(); + + result = stackManager_->StartAbility(radioAbilityRequest_); + EXPECT_EQ(ERR_OK, result); + auto thirdTopAbility = stackManager_->GetCurrentTopAbility(); + thirdTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + firstTopAbility->SetAbilityState(OHOS::AAFwk::INACTIVE); + secondTopAbility->SetAbilityState(OHOS::AAFwk::INACTIVE); + auto thridMissionId = thirdTopAbility->GetMissionRecord()->GetMissionRecordId(); + + EXPECT_EQ(secondMissionId, thridMissionId); + EXPECT_NE(firstMissionId, secondMissionId); + + OHOS::sptr scheduler(new AbilitySchedulerMock()); + + thirdTopAbility->SetScheduler(scheduler); + EXPECT_CALL(*scheduler, ScheduleAbilityTransaction(testing::_, testing::_)).Times(1); + + result = stackManager_->PowerOff(); + EXPECT_EQ(ERR_OK, result); + + auto missionInfo1 = stackManager_->GetMissionRecordFromAllStacks(firstMissionId); + EXPECT_EQ(missionInfo1->GetTopAbilityRecord()->GetAbilityState(), OHOS::AAFwk::MOVING_BACKGROUND); + auto missionInfo2 = stackManager_->GetMissionRecordFromAllStacks(secondMissionId); + EXPECT_EQ(missionInfo1->GetTopAbilityRecord()->GetAbilityState(), OHOS::AAFwk::MOVING_BACKGROUND); + + auto recordVector = stackManager_->powerStorage_->GetPowerOffInActiveRecord(); + int size = recordVector.size(); + EXPECT_EQ(size, 1); // Because we only focus on the top of the stack + + for (const auto &it : recordVector) { + if (it.missionId == thridMissionId) { + EXPECT_EQ(firstTopAbility->GetRecordId(), it.ability.lock()->GetRecordId()); + } + if (it.missionId == secondMissionId) { + EXPECT_EQ(secondTopAbility->GetRecordId(), it.ability.lock()->GetRecordId()); + } + } + + result = stackManager_->PowerOn(); + EXPECT_EQ(ERR_OK, result); + EXPECT_EQ(OHOS::AAFwk::INACTIVE, secondTopAbility->GetAbilityState()); +} + +/* + * Feature: AbilityStackManager + * Function: RemoveStack + * SubFunction: NA + * FunctionPoints: RemoveStack + * EnvConditions: NA + * CaseDescription: Succeeded to verify RemoveStack + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_049, TestSize.Level1) +{ + stackManager_->Init(); + auto result = stackManager_->StartAbility(launcherAbilityRequest_); + EXPECT_EQ(ERR_OK, result); + auto firstTopAbility = stackManager_->GetCurrentTopAbility(); + firstTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + auto firstMissionId = firstTopAbility->GetMissionRecord()->GetMissionRecordId(); + + result = stackManager_->StartAbility(musicAbilityRequest_); + EXPECT_EQ(ERR_OK, result); + auto secondTopAbility = stackManager_->GetCurrentTopAbility(); + secondTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + auto secondMissionId = secondTopAbility->GetMissionRecord()->GetMissionRecordId(); + + result = stackManager_->StartAbility(radioAbilityRequest_); + EXPECT_EQ(ERR_OK, result); + auto thirdTopAbility = stackManager_->GetCurrentTopAbility(); + thirdTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + auto thridMissionId = thirdTopAbility->GetMissionRecord()->GetMissionRecordId(); + + result = stackManager_->StartAbility(musicSAbilityRequest_); + EXPECT_EQ(ERR_OK, result); + auto fourthTopAbility = stackManager_->GetCurrentTopAbility(); + fourthTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + firstTopAbility->SetAbilityState(OHOS::AAFwk::INACTIVE); + secondTopAbility->SetAbilityState(OHOS::AAFwk::INACTIVE); + thirdTopAbility->SetAbilityState(OHOS::AAFwk::INACTIVE); + + auto fourthMissionId = fourthTopAbility->GetMissionRecord()->GetMissionRecordId(); + + EXPECT_EQ(secondMissionId, thridMissionId); + EXPECT_NE(fourthMissionId, secondMissionId); + + OHOS::sptr scheduler(new AbilitySchedulerMock()); + fourthTopAbility->SetScheduler(scheduler); + EXPECT_CALL(*scheduler, ScheduleAbilityTransaction(testing::_, testing::_)).Times(1); + + result = stackManager_->PowerOff(); + EXPECT_EQ(ERR_OK, result); + + auto missionInfo1 = stackManager_->GetMissionRecordFromAllStacks(firstMissionId); + EXPECT_EQ(missionInfo1->GetTopAbilityRecord()->GetAbilityState(), OHOS::AAFwk::MOVING_BACKGROUND); + auto missionInfo2 = stackManager_->GetMissionRecordFromAllStacks(secondMissionId); + EXPECT_EQ(missionInfo1->GetTopAbilityRecord()->GetAbilityState(), OHOS::AAFwk::MOVING_BACKGROUND); + auto missionInfo3 = stackManager_->GetMissionRecordFromAllStacks(fourthMissionId); + EXPECT_EQ(missionInfo1->GetTopAbilityRecord()->GetAbilityState(), OHOS::AAFwk::MOVING_BACKGROUND); + + auto recordVector = stackManager_->powerStorage_->GetPowerOffInActiveRecord(); + int size = recordVector.size(); + EXPECT_EQ(size, 2); + + for (const auto &it : recordVector) { + if (it.missionId == firstMissionId) { + EXPECT_TRUE(firstTopAbility->GetRecordId() == it.ability.lock()->GetRecordId()); + } + if (it.missionId == thridMissionId) { + EXPECT_TRUE(thirdTopAbility->GetRecordId() == it.ability.lock()->GetRecordId()); + } + } + result = stackManager_->PowerOn(); + EXPECT_EQ(ERR_OK, result); + EXPECT_EQ(OHOS::AAFwk::INACTIVATING, fourthTopAbility->GetAbilityState()); +} + +/* + * Feature: AbilityStackManager + * Function: StartLockMission + * SubFunction: NA + * FunctionPoints: StartLockMission + * EnvConditions: NA + * CaseDescription: lock a mission + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_050, TestSize.Level1) +{ + stackManager_->Init(); + auto result = stackManager_->StartLockMission(1000, 3, true, true); + EXPECT_EQ(LOCK_MISSION_DENY_FAILED, result); + + auto result1 = stackManager_->StartLockMission(1000, -2, true, true); + EXPECT_EQ(LOCK_MISSION_DENY_FAILED, result1); +} + +/* + * Feature: AbilityStackManager + * Function: StartLockMission + * SubFunction: NA + * FunctionPoints: StartLockMission + * EnvConditions: NA + * CaseDescription: lock a mission + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_051, TestSize.Level1) +{ + stackManager_->Init(); + auto result = stackManager_->StartAbility(musicAbilityRequest_); + EXPECT_EQ(0, result); + + auto topMisionRecord = stackManager_->GetTopMissionRecord(); + auto MisionRecordId = topMisionRecord->GetMissionRecordId(); + + auto topAbilityRecord = topMisionRecord->GetTopAbilityRecord(); + topAbilityRecord->SetAbilityState(OHOS::AAFwk::ACTIVE); + + auto result1 = stackManager_->StartLockMission(1000, MisionRecordId, false, true); + EXPECT_EQ(ERR_OK, result1); + + // can't repeat the lock + auto resul2 = stackManager_->StartLockMission(1000, MisionRecordId, false, true); + EXPECT_EQ(LOCK_MISSION_DENY_FAILED, resul2); + + auto lockState = stackManager_->GetMissionLockModeState(); + EXPECT_EQ(lockState, LockMissionContainer::LockMissionState::LOCK_MISSION_STATE_LOCKED); +} + +/* + * Feature: AbilityStackManager + * Function: StartLockMission + * SubFunction: NA + * FunctionPoints: StartLockMission + * EnvConditions: NA + * CaseDescription: lock a mission + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_052, TestSize.Level1) +{ + stackManager_->Init(); + auto result = stackManager_->StartAbility(launcherAbilityRequest_); + EXPECT_EQ(0, result); + + auto topAbility = stackManager_->GetCurrentTopAbility(); + topAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + auto luncherMissionRecord = stackManager_->GetTopMissionRecord(); + auto luncherMisionRecordId = luncherMissionRecord->GetMissionRecordId(); + + result = stackManager_->StartAbility(musicAbilityRequest_); + EXPECT_EQ(0, result); + + auto musicMisionRecord = stackManager_->GetTopMissionRecord(); + + auto topAbilityRecord = stackManager_->GetCurrentTopAbility(); + topAbilityRecord->SetAbilityState(OHOS::AAFwk::ACTIVE); + + auto result1 = stackManager_->StartLockMission(1000, luncherMisionRecordId, true, true); + EXPECT_EQ(ERR_OK, result1); + + auto missionRecord = stackManager_->GetTopMissionRecord(); + EXPECT_EQ(missionRecord->GetMissionRecordId(), luncherMisionRecordId); + + auto lockState = stackManager_->GetMissionLockModeState(); + EXPECT_EQ(lockState, LockMissionContainer::LockMissionState::LOCK_MISSION_STATE_PINNED); +} + +/* + * Feature: AbilityStackManager + * Function: StartLockMission + * SubFunction: NA + * FunctionPoints: StartLockMission + * EnvConditions: NA + * CaseDescription: lock a mission + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_053, TestSize.Level1) +{ + stackManager_->Init(); + auto result = stackManager_->StartAbility(musicAbilityRequest_); + EXPECT_EQ(0, result); + + auto musicMisionRecord = stackManager_->GetTopMissionRecord(); + auto musicMisionRecordId = musicMisionRecord->GetMissionRecordId(); + + auto topAbilityRecord = stackManager_->GetCurrentTopAbility(); + topAbilityRecord->SetAbilityState(OHOS::AAFwk::ACTIVE); + + // 2 + std::vector config; + auto musicAbilityRequest2th = + GenerateAbilityRequest("device", "MusicAbility2th", "music", "com.ix.hiMusic", config); + result = stackManager_->StartAbility(musicAbilityRequest2th); + EXPECT_EQ(0, result); + auto musicMisionRecord2th = stackManager_->GetTopMissionRecord(); + auto musicMisionRecordId2th = musicMisionRecord->GetMissionRecordId(); + EXPECT_EQ(musicMisionRecordId, musicMisionRecordId2th); + + topAbilityRecord = stackManager_->GetCurrentTopAbility(); + topAbilityRecord->SetAbilityState(OHOS::AAFwk::ACTIVE); + + auto result1 = stackManager_->StartLockMission(1000, musicMisionRecordId, false, true); + EXPECT_EQ(ERR_OK, result1); + + auto topRecord = stackManager_->GetCurrentTopAbility(); + auto abilityInfo = topRecord->GetAbilityInfo(); + EXPECT_EQ(abilityInfo.name, "MusicAbility2th"); + + auto lockState = stackManager_->GetMissionLockModeState(); + EXPECT_EQ(lockState, LockMissionContainer::LockMissionState::LOCK_MISSION_STATE_LOCKED); +} + +/* + * Feature: AbilityStackManager + * Function: StartLockMission + * SubFunction: NA + * FunctionPoints: StartLockMission + * EnvConditions: NA + * CaseDescription: lock a mission + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_054, TestSize.Level1) +{ + stackManager_->Init(); + auto result = stackManager_->StartAbility(musicAbilityRequest_); + EXPECT_EQ(0, result); + + auto topMisionRecord = stackManager_->GetTopMissionRecord(); + auto MisionRecordId = topMisionRecord->GetMissionRecordId(); + EXPECT_NE(0, MisionRecordId); + auto topAbilityRecord = topMisionRecord->GetTopAbilityRecord(); + topAbilityRecord->SetAbilityState(OHOS::AAFwk::ACTIVE); + + auto result1 = stackManager_->StartLockMission(1000, MisionRecordId, false, false); + EXPECT_EQ(LOCK_MISSION_DENY_FAILED, result1); +} + +/* + * Feature: AbilityStackManager + * Function: StartLockMission + * SubFunction: NA + * FunctionPoints: StartLockMission + * EnvConditions: NA + * CaseDescription: lock a mission and unlock + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_055, TestSize.Level1) +{ + stackManager_->Init(); + auto result = stackManager_->StartAbility(musicAbilityRequest_); + EXPECT_EQ(0, result); + + auto topMisionRecord = stackManager_->GetTopMissionRecord(); + auto MisionRecordId = topMisionRecord->GetMissionRecordId(); + EXPECT_NE(0, MisionRecordId); + auto topAbilityRecord = topMisionRecord->GetTopAbilityRecord(); + topAbilityRecord->SetAbilityState(OHOS::AAFwk::ACTIVE); + + auto result1 = stackManager_->StartLockMission(1000, MisionRecordId, false, true); + EXPECT_EQ(ERR_OK, result1); + + auto lockState = stackManager_->GetMissionLockModeState(); + EXPECT_EQ(lockState, LockMissionContainer::LockMissionState::LOCK_MISSION_STATE_LOCKED); + + // unlock + auto result2 = stackManager_->StartLockMission(1000, MisionRecordId, false, false); + EXPECT_EQ(ERR_OK, result2); +} + +/* + * Feature: AbilityStackManager + * Function: StartLockMission + * SubFunction: NA + * FunctionPoints: StartLockMission + * EnvConditions: NA + * CaseDescription: lock a luncher mission and unlock + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_056, TestSize.Level1) +{ + stackManager_->Init(); + auto result = stackManager_->StartAbility(launcherAbilityRequest_); + EXPECT_EQ(0, result); + + auto topMisionRecord = stackManager_->GetTopMissionRecord(); + auto MisionRecordId = topMisionRecord->GetMissionRecordId(); + EXPECT_NE(0, MisionRecordId); + auto topAbilityRecord = topMisionRecord->GetTopAbilityRecord(); + topAbilityRecord->SetAbilityState(OHOS::AAFwk::ACTIVE); + + auto result1 = stackManager_->StartLockMission(1000, MisionRecordId, true, true); + EXPECT_EQ(ERR_OK, result1); + + auto lockState = stackManager_->GetMissionLockModeState(); + EXPECT_EQ(lockState, LockMissionContainer::LockMissionState::LOCK_MISSION_STATE_PINNED); + + // unlock + auto result2 = stackManager_->StartLockMission(1000, MisionRecordId, true, false); + EXPECT_EQ(ERR_OK, result2); +} + +/* + * Feature: AbilityStackManager + * Function: StartLockMission + * SubFunction: NA + * FunctionPoints: StartLockMission + * EnvConditions: NA + * CaseDescription: lock a luncher mission and unlock + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_057, TestSize.Level1) +{ + stackManager_->Init(); + auto result = stackManager_->StartAbility(musicAbilityRequest_); + EXPECT_EQ(0, result); + + auto topMisionRecord = stackManager_->GetTopMissionRecord(); + auto MisionRecordId = topMisionRecord->GetMissionRecordId(); + EXPECT_NE(0, MisionRecordId); + auto topAbilityRecord = topMisionRecord->GetTopAbilityRecord(); + topAbilityRecord->SetAbilityState(OHOS::AAFwk::ACTIVE); + + auto result1 = stackManager_->StartLockMission(1000, MisionRecordId, false, true); + EXPECT_EQ(ERR_OK, result1); + + auto lockState = stackManager_->GetMissionLockModeState(); + EXPECT_EQ(lockState, LockMissionContainer::LockMissionState::LOCK_MISSION_STATE_LOCKED); + + // unlock + auto result2 = stackManager_->StartLockMission(1000, MisionRecordId, false, false); + EXPECT_EQ(ERR_OK, result2); +} + +/* + * Feature: AbilityStackManager + * Function: SetMissionDescriptionInfo + * SubFunction: NA + * FunctionPoints: SetMissionDescriptionInfo + * EnvConditions: NA + * CaseDescription: set details for a mission + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_058, TestSize.Level1) +{ + stackManager_->Init(); + EXPECT_TRUE(stackManager_); + auto result = stackManager_->StartAbility(musicAbilityRequest_); + EXPECT_EQ(0, result); + + auto topMissionRecord = stackManager_->GetTopMissionRecord(); + auto topAbilityRecord = topMissionRecord->GetTopAbilityRecord(); + EXPECT_TRUE(topMissionRecord); + EXPECT_TRUE(topAbilityRecord); + topAbilityRecord->SetAbilityState(OHOS::AAFwk::ACTIVE); + + Want want; + AbilityInfo abilityInfo; + ApplicationInfo appInfo; + auto abilityRecord = std::make_shared(want, abilityInfo, appInfo); + + MissionDescriptionInfo missionDescriptionInfo; + missionDescriptionInfo.label = "123456"; + missionDescriptionInfo.iconPath = "loacl"; + + result = stackManager_->SetMissionDescriptionInfo(abilityRecord, missionDescriptionInfo); + EXPECT_EQ(SET_MISSION_INFO_FAILED, result); + + result = stackManager_->SetMissionDescriptionInfo(topAbilityRecord, missionDescriptionInfo); + EXPECT_EQ(ERR_OK, result); + + auto descriptionInfo = topMissionRecord->GetMissionDescriptionInfo(); + EXPECT_TRUE(descriptionInfo); + + EXPECT_TRUE(descriptionInfo->label == missionDescriptionInfo.label); + EXPECT_TRUE(descriptionInfo->iconPath == missionDescriptionInfo.iconPath); +} + +/* + * Feature: AbilityStackManager + * Function: SetMissionDescriptionInfo + * SubFunction: NA + * FunctionPoints: SetMissionDescriptionInfo + * EnvConditions: NA + * CaseDescription: can stop or can start mission state + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_059, TestSize.Level1) +{ + stackManager_->Init(); + EXPECT_TRUE(stackManager_); + auto result = stackManager_->StartAbility(musicAbilityRequest_); + EXPECT_EQ(0, result); + + auto topMissionRecord = stackManager_->GetTopMissionRecord(); + auto topAbilityRecord = topMissionRecord->GetTopAbilityRecord(); + EXPECT_TRUE(topMissionRecord); + EXPECT_TRUE(topAbilityRecord); + topAbilityRecord->SetAbilityState(OHOS::AAFwk::ACTIVE); + + auto isCanStart = stackManager_->CanStartInLockMissionState(launcherAbilityRequest_, topAbilityRecord); + EXPECT_TRUE(isCanStart); + + // LOCK + auto MisionRecordId = topMissionRecord->GetMissionRecordId(); + auto result1 = stackManager_->StartLockMission(1000, MisionRecordId, false, true); + EXPECT_EQ(ERR_OK, result1); + + // check can terminal + auto isCanStop = stackManager_->CanStopInLockMissionState(topAbilityRecord); + EXPECT_FALSE(isCanStop); + + // check start agin + isCanStart = stackManager_->CanStartInLockMissionState(launcherAbilityRequest_, topAbilityRecord); + EXPECT_FALSE(isCanStart); + + // unlock + result1 = stackManager_->StartLockMission(1000, MisionRecordId, false, false); + EXPECT_EQ(ERR_OK, result1); + + isCanStop = stackManager_->CanStopInLockMissionState(topAbilityRecord); + EXPECT_TRUE(isCanStop); +} + +/* + * Feature: AbilityStackManager + * Function: SetMissionDescriptionInfo + * SubFunction: NA + * FunctionPoints: SetMissionDescriptionInfo + * EnvConditions: NA + * CaseDescription: when the uid defferent + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_060, TestSize.Level1) +{ + stackManager_->Init(); + EXPECT_TRUE(stackManager_); + auto result = stackManager_->StartAbility(musicAbilityRequest_); + EXPECT_EQ(0, result); + + auto topMissionRecord = stackManager_->GetTopMissionRecord(); + auto topAbilityRecord = topMissionRecord->GetTopAbilityRecord(); + EXPECT_TRUE(topMissionRecord); + EXPECT_TRUE(topAbilityRecord); + topAbilityRecord->SetAbilityState(OHOS::AAFwk::ACTIVE); + + auto isCanStart = stackManager_->CanStartInLockMissionState(launcherAbilityRequest_, topAbilityRecord); + EXPECT_TRUE(isCanStart); + + // LOCK + auto MisionRecordId = topMissionRecord->GetMissionRecordId(); + auto result1 = stackManager_->StartLockMission(99, MisionRecordId, false, true); + EXPECT_EQ(LOCK_MISSION_DENY_FAILED, result1); + + result1 = stackManager_->StartLockMission(1000, MisionRecordId, false, true); + EXPECT_EQ(ERR_OK, result1); + + // unlock defferent uid(99) + result1 = stackManager_->StartLockMission(99, MisionRecordId, false, false); + EXPECT_EQ(UNLOCK_MISSION_DENY_FAILED, result1); + + result1 = stackManager_->StartLockMission(1000, MisionRecordId, false, false); + EXPECT_EQ(ERR_OK, result1); +} + +/* + * Feature: AbilityStackManager + * Function: StartAbility + * SubFunction: NA + * FunctionPoints: Start the floating window according to the parameters + * EnvConditions: NA + * CaseDescription: Start a floating window application + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_061, TestSize.Level1) +{ + stackManager_->Init(); + auto abilityStartSetting = AbilityStartSetting::GetEmptySetting(); + + // defult mission id + abilityStartSetting->AddProperty(AbilityStartSetting::WINDOW_MODE_KEY, + std::to_string(AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_FULLSCREEN)); + EXPECT_TRUE(abilityStartSetting); + + musicAbilityRequest_.startSetting = abilityStartSetting; + auto result = stackManager_->StartAbility(musicAbilityRequest_); + EXPECT_EQ(0, result); + auto topMissionRecord = stackManager_->GetTopMissionRecord(); + auto topAbilityRecord = topMissionRecord->GetTopAbilityRecord(); + EXPECT_TRUE(topMissionRecord); + EXPECT_TRUE(topAbilityRecord); + topAbilityRecord->SetAbilityState(OHOS::AAFwk::ACTIVE); + + auto stact = stackManager_->GetCurrentMissionStack(); + EXPECT_TRUE(stact); + EXPECT_EQ(stact->GetMissionStackId(), DEFAULT_MISSION_STACK_ID); + + // promary mission id + abilityStartSetting->AddProperty( + AbilityStartSetting::WINDOW_MODE_KEY, std::to_string(AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_PRIMARY)); + EXPECT_TRUE(abilityStartSetting); + + musicAbilityRequest_.startSetting = abilityStartSetting; + result = stackManager_->StartAbility(musicAbilityRequest_); + EXPECT_EQ(0, result); + auto topMissionRecord2 = stackManager_->GetTopMissionRecord(); + auto topAbilityRecord2 = topMissionRecord->GetTopAbilityRecord(); + EXPECT_TRUE(topMissionRecord2); + EXPECT_TRUE(topAbilityRecord2); + topAbilityRecord2->SetAbilityState(OHOS::AAFwk::ACTIVE); + + stact = stackManager_->GetCurrentMissionStack(); + EXPECT_TRUE(stact); + EXPECT_EQ(stact->GetMissionStackId(), SPLIT_SCREEN_MISSION_STACK_ID); +} + +/* + * Feature: AbilityStackManager + * Function: StartAbility + * SubFunction: NA + * FunctionPoints: Start the floating window according to the parameters + * EnvConditions: NA + * CaseDescription: a lunchr + Start a floating window application + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_062, TestSize.Level1) +{ + stackManager_->Init(); + + // start a luncher + auto result = stackManager_->StartAbility(launcherAbilityRequest_); + EXPECT_EQ(0, result); + auto topMissionRecord = stackManager_->GetTopMissionRecord(); + auto topAbilityRecord = topMissionRecord->GetTopAbilityRecord(); + EXPECT_TRUE(topMissionRecord); + EXPECT_TRUE(topAbilityRecord); + topAbilityRecord->SetAbilityState(OHOS::AAFwk::ACTIVE); + + auto stact = stackManager_->GetCurrentMissionStack(); + EXPECT_TRUE(stact); + EXPECT_EQ(stact->GetMissionStackId(), LAUNCHER_MISSION_STACK_ID); + + auto abilityStartSetting = AbilityStartSetting::GetEmptySetting(); + + // Set floating window identification + abilityStartSetting->AddProperty(AbilityStartSetting::WINDOW_MODE_KEY, + std::to_string(AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_FLOATING)); + EXPECT_TRUE(abilityStartSetting); + + musicAbilityRequest_.startSetting = abilityStartSetting; + result = stackManager_->StartAbility(musicAbilityRequest_); + EXPECT_EQ(0, result); + auto topMissionRecord2 = stackManager_->GetTopMissionRecord(); + auto topAbilityRecord2 = topMissionRecord->GetTopAbilityRecord(); + EXPECT_TRUE(topMissionRecord2); + EXPECT_TRUE(topAbilityRecord2); + topAbilityRecord2->SetAbilityState(OHOS::AAFwk::ACTIVE); + + stact = stackManager_->GetCurrentMissionStack(); + EXPECT_TRUE(stact); + EXPECT_EQ(stact->GetMissionStackId(), FLOATING_MISSION_STACK_ID); +} + +/* + * Feature: AbilityStackManager + * Function: StartAbility + * SubFunction: NA + * FunctionPoints: Start the floating window according to the parameters + * EnvConditions: NA + * CaseDescription: a defult ability + Start a floating window application + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_063, TestSize.Level1) +{ + stackManager_->Init(); + + // start a ability + auto result = stackManager_->StartAbility(radioAbilityRequest_); + EXPECT_EQ(0, result); + auto topMissionRecord = stackManager_->GetTopMissionRecord(); + auto topAbilityRecord = topMissionRecord->GetTopAbilityRecord(); + EXPECT_TRUE(topMissionRecord); + EXPECT_TRUE(topAbilityRecord); + topAbilityRecord->SetAbilityState(OHOS::AAFwk::ACTIVE); + + auto stact = stackManager_->GetCurrentMissionStack(); + EXPECT_TRUE(stact); + EXPECT_EQ(stact->GetMissionStackId(), DEFAULT_MISSION_STACK_ID); + + auto abilityStartSetting = AbilityStartSetting::GetEmptySetting(); + + // Set floating window identification + abilityStartSetting->AddProperty(AbilityStartSetting::WINDOW_MODE_KEY, + std::to_string(AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_FLOATING)); + EXPECT_TRUE(abilityStartSetting); + + musicAbilityRequest_.startSetting = abilityStartSetting; + result = stackManager_->StartAbility(musicAbilityRequest_); + EXPECT_EQ(0, result); + auto topMissionRecord2 = stackManager_->GetTopMissionRecord(); + auto topAbilityRecord2 = topMissionRecord->GetTopAbilityRecord(); + EXPECT_TRUE(topMissionRecord2); + EXPECT_TRUE(topAbilityRecord2); + topAbilityRecord2->SetAbilityState(OHOS::AAFwk::ACTIVE); + + stact = stackManager_->GetCurrentMissionStack(); + EXPECT_TRUE(stact); + EXPECT_EQ(stact->GetMissionStackId(), FLOATING_MISSION_STACK_ID); +} + +/* + * Feature: AbilityStackManager + * Function: StartAbility + * SubFunction: NA + * FunctionPoints: Start the floating window according to the parameters + * EnvConditions: NA + * CaseDescription: When an application starts a floating window, it is put on the floating window stack + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_064, TestSize.Level1) +{ + stackManager_->Init(); + + auto result = stackManager_->StartAbility(radioAbilityRequest_); + EXPECT_EQ(0, result); + auto redioMissionRecord = stackManager_->GetTopMissionRecord(); + auto redioAbilityRecord = redioMissionRecord->GetTopAbilityRecord(); + EXPECT_TRUE(redioMissionRecord); + EXPECT_TRUE(redioAbilityRecord); + redioAbilityRecord->SetAbilityState(OHOS::AAFwk::ACTIVE); + + auto abilityStartSetting = AbilityStartSetting::GetEmptySetting(); + + // Set floating window identification + abilityStartSetting->AddProperty(AbilityStartSetting::WINDOW_MODE_KEY, + std::to_string(AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_FLOATING)); + EXPECT_TRUE(abilityStartSetting); + + musicAbilityRequest_.startSetting = abilityStartSetting; + result = stackManager_->StartAbility(musicAbilityRequest_); + EXPECT_EQ(0, result); + auto topMissionRecord = stackManager_->GetTopMissionRecord(); + auto topAbilityRecord = topMissionRecord->GetTopAbilityRecord(); + EXPECT_TRUE(topMissionRecord); + EXPECT_TRUE(topAbilityRecord); + topAbilityRecord->SetAbilityState(OHOS::AAFwk::ACTIVE); + + auto stact = stackManager_->GetCurrentMissionStack(); + EXPECT_TRUE(stact); + EXPECT_EQ(stact->GetMissionStackId(), FLOATING_MISSION_STACK_ID); + + // radioAbility move to floating stack + EXPECT_EQ(redioMissionRecord->GetMissionStack()->GetMissionStackId(), FLOATING_MISSION_STACK_ID); +} + +/* + * Feature: AbilityStackManager + * Function: StartAbility + * SubFunction: NA + * FunctionPoints: Start the floating window according to the parameters + * EnvConditions: NA + * CaseDescription: When an singlton application starts a floating window, it is ont put on the together + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_065, TestSize.Level1) +{ + stackManager_->Init(); + + // singlton ability + auto result = stackManager_->StartAbility(radioTopAbilityRequest_); + EXPECT_EQ(0, result); + auto redioMissionRecord = stackManager_->GetTopMissionRecord(); + auto redioAbilityRecord = redioMissionRecord->GetTopAbilityRecord(); + EXPECT_TRUE(redioMissionRecord); + EXPECT_TRUE(redioAbilityRecord); + redioAbilityRecord->SetAbilityState(OHOS::AAFwk::ACTIVE); + + auto abilityStartSetting = AbilityStartSetting::GetEmptySetting(); + + // Set floating window identification + abilityStartSetting->AddProperty(AbilityStartSetting::WINDOW_MODE_KEY, + std::to_string(AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_FLOATING)); + EXPECT_TRUE(abilityStartSetting); + + musicAbilityRequest_.startSetting = abilityStartSetting; + result = stackManager_->StartAbility(musicAbilityRequest_); + EXPECT_EQ(0, result); + auto topMissionRecord = stackManager_->GetTopMissionRecord(); + auto topAbilityRecord = topMissionRecord->GetTopAbilityRecord(); + EXPECT_TRUE(topMissionRecord); + EXPECT_TRUE(topAbilityRecord); + topAbilityRecord->SetAbilityState(OHOS::AAFwk::ACTIVE); + + auto stact = stackManager_->GetCurrentMissionStack(); + EXPECT_TRUE(stact); + EXPECT_EQ(stact->GetMissionStackId(), FLOATING_MISSION_STACK_ID); + + // radioAbility in the defult stack + EXPECT_EQ(redioMissionRecord->GetMissionStack()->GetMissionStackId(), DEFAULT_MISSION_STACK_ID); +} + +/* + * Feature: AbilityStackManager + * Function: MoveMissionToFloatingStack + * SubFunction: NA + * FunctionPoints: Move misson to floating window stack + * EnvConditions: NA + * CaseDescription: a ability move to floating window stack + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_066, TestSize.Level1) +{ + stackManager_->Init(); + + auto result = stackManager_->StartAbility(radioTopAbilityRequest_); + EXPECT_EQ(0, result); + auto redioMissionRecord = stackManager_->GetTopMissionRecord(); + auto redioAbilityRecord = redioMissionRecord->GetTopAbilityRecord(); + EXPECT_TRUE(redioMissionRecord); + EXPECT_TRUE(redioAbilityRecord); + redioAbilityRecord->SetAbilityState(OHOS::AAFwk::ACTIVE); + + MissionOption missionOption; + missionOption.missionId = -10; + + auto ref = stackManager_->MoveMissionToFloatingStack(missionOption); + EXPECT_EQ(ref, ERR_INVALID_DATA); + + missionOption.missionId = 13; + missionOption.winModeKey = AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_FULLSCREEN; + ref = stackManager_->MoveMissionToFloatingStack(missionOption); + EXPECT_EQ(ref, ERR_INVALID_DATA); + + missionOption.winModeKey = AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_PRIMARY; + ref = stackManager_->MoveMissionToFloatingStack(missionOption); + EXPECT_EQ(ref, ERR_INVALID_DATA); + + missionOption.winModeKey = AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_SECONDARY; + ref = stackManager_->MoveMissionToFloatingStack(missionOption); + EXPECT_EQ(ref, ERR_INVALID_DATA); + + missionOption.winModeKey = AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_FLOATING; + ref = stackManager_->MoveMissionToFloatingStack(missionOption); + EXPECT_EQ(ref, MOVE_MISSION_TO_STACK_NOT_EXIST_MISSION); +} + +/* + * Feature: AbilityStackManager + * Function: MoveMissionToFloatingStack + * SubFunction: NA + * FunctionPoints: Move misson to floating window stack + * EnvConditions: NA + * CaseDescription: a ability move to floating window stack + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_067, TestSize.Level1) +{ + stackManager_->Init(); + + auto result = stackManager_->StartAbility(musicAbilityRequest_); + EXPECT_EQ(0, result); + auto musicMissionRecord = stackManager_->GetTopMissionRecord(); + auto musicAbilityRecord = musicMissionRecord->GetTopAbilityRecord(); + EXPECT_TRUE(musicMissionRecord); + EXPECT_TRUE(musicAbilityRecord); + musicAbilityRecord->SetAbilityState(OHOS::AAFwk::ACTIVE); + + MissionOption missionOption; + missionOption.missionId = musicMissionRecord->GetMissionRecordId(); + missionOption.winModeKey = AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_FLOATING; + auto ref = stackManager_->MoveMissionToFloatingStack(missionOption); + EXPECT_EQ(ref, ERR_NONE); + + auto stack = musicMissionRecord->GetMissionStack(); + EXPECT_EQ(stack->GetMissionStackId(), FLOATING_MISSION_STACK_ID); +} + +/* + * Feature: AbilityStackManager + * Function: MoveMissionToFloatingStack + * SubFunction: NA + * FunctionPoints: Move misson to floating window stack + * EnvConditions: NA + * CaseDescription: a luncher ability move to floating window stack + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_068, TestSize.Level1) +{ + stackManager_->Init(); + + auto result = stackManager_->StartAbility(launcherAbilityRequest_); + EXPECT_EQ(0, result); + auto launcherMissionRecord = stackManager_->GetTopMissionRecord(); + auto launcherAbilityRecord = launcherMissionRecord->GetTopAbilityRecord(); + EXPECT_TRUE(launcherMissionRecord); + EXPECT_TRUE(launcherAbilityRecord); + launcherAbilityRecord->SetAbilityState(OHOS::AAFwk::ACTIVE); + + MissionOption missionOption; + missionOption.missionId = launcherMissionRecord->GetMissionRecordId(); + missionOption.winModeKey = AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_FLOATING; + auto ref = stackManager_->MoveMissionToFloatingStack(missionOption); + EXPECT_EQ(ref, MOVE_MISSION_TO_STACK_NOT_SUPPORT_MULTI_WIN); + + auto stack = launcherMissionRecord->GetMissionStack(); + EXPECT_EQ(stack->GetMissionStackId(), LAUNCHER_MISSION_STACK_ID); +} + +/* + * Feature: AbilityStackManager + * Function: ChangeFocusAbility + * SubFunction: NA + * FunctionPoints: Change Focus Ability + * EnvConditions: NA + * CaseDescription: Move focus from one application to another + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_069, TestSize.Level1) +{ + stackManager_->Init(); + + auto result = stackManager_->StartAbility(launcherAbilityRequest_); + EXPECT_EQ(0, result); + auto topMissionRecord = stackManager_->GetTopMissionRecord(); + auto topAbilityRecord = topMissionRecord->GetTopAbilityRecord(); + EXPECT_TRUE(topMissionRecord); + EXPECT_TRUE(topAbilityRecord); + topAbilityRecord->SetAbilityState(OHOS::AAFwk::ACTIVE); + + auto stactLuncher = stackManager_->GetCurrentMissionStack(); + EXPECT_TRUE(stactLuncher); + + auto abilityStartSetting = AbilityStartSetting::GetEmptySetting(); + + // Set floating window identification + abilityStartSetting->AddProperty(AbilityStartSetting::WINDOW_MODE_KEY, + std::to_string(AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_FLOATING)); + EXPECT_TRUE(abilityStartSetting); + + musicAbilityRequest_.startSetting = abilityStartSetting; + result = stackManager_->StartAbility(musicAbilityRequest_); + EXPECT_EQ(0, result); + auto topMissionRecord2 = stackManager_->GetTopMissionRecord(); + auto topAbilityRecord2 = stackManager_->GetCurrentTopAbility(); + EXPECT_TRUE(topMissionRecord2); + EXPECT_TRUE(topAbilityRecord2); + topAbilityRecord->SetAbilityState(OHOS::AAFwk::ACTIVE); + topAbilityRecord2->SetAbilityState(OHOS::AAFwk::ACTIVE); + + auto stact = topMissionRecord2->GetMissionStack(); + EXPECT_TRUE(stact); + + EXPECT_EQ(stact->GetMissionStackId(), FLOATING_MISSION_STACK_ID); + EXPECT_EQ(stactLuncher->GetMissionStackId(), LAUNCHER_MISSION_STACK_ID); + + // luncher get focus + auto ref = stackManager_->ChangeFocusAbility(topAbilityRecord2->GetToken(), topAbilityRecord->GetToken()); + EXPECT_EQ(0, ref); + stact = stackManager_->GetCurrentMissionStack(); + EXPECT_TRUE(stact); + EXPECT_EQ(stact->GetMissionStackId(), LAUNCHER_MISSION_STACK_ID); +} + +/* + * Feature: AbilityStackManager + * Function: ChangeFocusAbility + * SubFunction: NA + * FunctionPoints: Change Focus Ability + * EnvConditions: NA + * CaseDescription: Move focus from one application to another + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_070, TestSize.Level1) +{ + stackManager_->Init(); + auto ref = stackManager_->ChangeFocusAbility(nullptr, nullptr); + EXPECT_EQ(ref, ERR_INVALID_VALUE); + + auto abilityrecord = AbilityRecord::CreateAbilityRecord(musicAbilityRequest_); + auto abilityrecord1 = AbilityRecord::CreateAbilityRecord(radioAbilityRequest_); + EXPECT_TRUE(abilityrecord); + EXPECT_TRUE(abilityrecord1); + abilityrecord->Init(); + abilityrecord1->Init(); + + ref = stackManager_->ChangeFocusAbility(abilityrecord->GetToken(), abilityrecord1->GetToken()); + EXPECT_EQ(ref, CHANGE_FOCUS_ABILITY_FAILED); +} + +/* + * Feature: AbilityStackManager + * Function: MoveMissionToSplitScreenStack + * SubFunction: NA + * FunctionPoints: Move misson to Split window stack + * EnvConditions: NA + * CaseDescription: a ability move to Split window stack + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_071, TestSize.Level1) +{ + stackManager_->Init(); + + auto result = stackManager_->StartAbility(radioTopAbilityRequest_); + EXPECT_EQ(0, result); + auto redioMissionRecord = stackManager_->GetTopMissionRecord(); + auto redioAbilityRecord = redioMissionRecord->GetTopAbilityRecord(); + EXPECT_TRUE(redioMissionRecord); + EXPECT_TRUE(redioAbilityRecord); + redioAbilityRecord->SetAbilityState(OHOS::AAFwk::ACTIVE); + + MissionOption missionOption; + missionOption.missionId = -10; + + auto ref = stackManager_->MoveMissionToSplitScreenStack(missionOption); + EXPECT_EQ(ref, ERR_INVALID_DATA); + + missionOption.missionId = 13; + missionOption.winModeKey = AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_FULLSCREEN; + ref = stackManager_->MoveMissionToSplitScreenStack(missionOption); + EXPECT_EQ(ref, ERR_INVALID_DATA); + + missionOption.winModeKey = AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_PRIMARY; + ref = stackManager_->MoveMissionToSplitScreenStack(missionOption); + EXPECT_EQ(ref, MOVE_MISSION_TO_STACK_NOT_EXIST_MISSION); + + missionOption.winModeKey = AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_SECONDARY; + ref = stackManager_->MoveMissionToSplitScreenStack(missionOption); + EXPECT_EQ(ref, MOVE_MISSION_TO_STACK_NOT_EXIST_MISSION); + + missionOption.winModeKey = AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_FLOATING; + ref = stackManager_->MoveMissionToSplitScreenStack(missionOption); + EXPECT_EQ(ref, ERR_INVALID_DATA); +} + +/* + * Feature: AbilityStackManager + * Function: MoveMissionToSplitScreenStack + * SubFunction: NA + * FunctionPoints: Move misson to Split window stack + * EnvConditions: NA + * CaseDescription: a ability move to Split window stack + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_072, TestSize.Level1) +{ + stackManager_->Init(); + + auto result = stackManager_->StartAbility(musicAbilityRequest_); + EXPECT_EQ(0, result); + auto musicMissionRecord = stackManager_->GetTopMissionRecord(); + auto musicAbilityRecord = musicMissionRecord->GetTopAbilityRecord(); + EXPECT_TRUE(musicMissionRecord); + EXPECT_TRUE(musicAbilityRecord); + musicAbilityRecord->SetAbilityState(OHOS::AAFwk::ACTIVE); + + MissionOption missionOption; + missionOption.missionId = musicMissionRecord->GetMissionRecordId(); + missionOption.winModeKey = AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_PRIMARY; + auto ref = stackManager_->MoveMissionToSplitScreenStack(missionOption); + EXPECT_EQ(ref, ERR_NONE); + + auto stack = musicMissionRecord->GetMissionStack(); + EXPECT_EQ(stack->GetMissionStackId(), SPLIT_SCREEN_MISSION_STACK_ID); +} + +/* + * Feature: AbilityStackManager + * Function: MoveMissionToSplitScreenStack + * SubFunction: NA + * FunctionPoints: Move misson to Split window stack + * EnvConditions: NA + * CaseDescription: a luncher ability move to Split window stack + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_073, TestSize.Level1) +{ + stackManager_->Init(); + + auto result = stackManager_->StartAbility(launcherAbilityRequest_); + EXPECT_EQ(0, result); + auto launcherMissionRecord = stackManager_->GetTopMissionRecord(); + auto launcherAbilityRecord = launcherMissionRecord->GetTopAbilityRecord(); + EXPECT_TRUE(launcherMissionRecord); + EXPECT_TRUE(launcherAbilityRecord); + launcherAbilityRecord->SetAbilityState(OHOS::AAFwk::ACTIVE); + + MissionOption missionOption; + missionOption.missionId = launcherMissionRecord->GetMissionRecordId(); + missionOption.winModeKey = AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_SECONDARY; + auto ref = stackManager_->MoveMissionToSplitScreenStack(missionOption); + EXPECT_EQ(ref, MOVE_MISSION_TO_STACK_NOT_SUPPORT_MULTI_WIN); + + auto stack = launcherMissionRecord->GetMissionStack(); + EXPECT_EQ(stack->GetMissionStackId(), LAUNCHER_MISSION_STACK_ID); +} + +/* + * Feature: AbilityStackManager + * Function: MoveMissionToSplitScreenStack + * SubFunction: NA + * FunctionPoints: Move misson to Split window stack + * EnvConditions: NA + * CaseDescription: a luncher ability move to Split window stack + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_074, TestSize.Level1) +{ + stackManager_->Init(); + + auto result = stackManager_->StartAbility(launcherAbilityRequest_); + EXPECT_EQ(0, result); + auto launcherMissionRecord = stackManager_->GetTopMissionRecord(); + auto launcherAbilityRecord = launcherMissionRecord->GetTopAbilityRecord(); + EXPECT_TRUE(launcherMissionRecord); + EXPECT_TRUE(launcherAbilityRecord); + launcherAbilityRecord->SetAbilityState(OHOS::AAFwk::ACTIVE); + + MissionOption missionOption; + missionOption.missionId = launcherMissionRecord->GetMissionRecordId(); + missionOption.winModeKey = AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_SECONDARY; + auto ref = stackManager_->MoveMissionToSplitScreenStack(missionOption); + EXPECT_EQ(ref, MOVE_MISSION_TO_STACK_NOT_SUPPORT_MULTI_WIN); + + auto stack = launcherMissionRecord->GetMissionStack(); + EXPECT_EQ(stack->GetMissionStackId(), LAUNCHER_MISSION_STACK_ID); +} + +/* + * Feature: AbilityStackManager + * Function: MinimizeMultiWindow + * SubFunction: NA + * FunctionPoints: Move the floating window to the background + * EnvConditions: NA + * CaseDescription: Move the floating window to the background + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_075, TestSize.Level1) +{ + stackManager_->Init(); + + auto ref = stackManager_->MinimizeMultiWindow(-1); + EXPECT_EQ(ref, MINIMIZE_MULTI_WINDOW_FAILED); + + auto result = stackManager_->StartAbility(musicAbilityRequest_); + EXPECT_EQ(0, result); + auto musicMissionRecord = stackManager_->GetTopMissionRecord(); + auto musicAbilityRecord = musicMissionRecord->GetTopAbilityRecord(); + EXPECT_TRUE(musicMissionRecord); + EXPECT_TRUE(musicAbilityRecord); + musicAbilityRecord->SetAbilityState(OHOS::AAFwk::ACTIVE); + + ref = stackManager_->MinimizeMultiWindow(musicMissionRecord->GetMissionRecordId()); + EXPECT_EQ(ref, MINIMIZE_MULTI_WINDOW_FAILED); +} + +/* + * Feature: AbilityStackManager + * Function: MinimizeMultiWindow + * SubFunction: NA + * FunctionPoints: Move the floating window to the background + * EnvConditions: NA + * CaseDescription: Move the floating window to the background + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_076, TestSize.Level1) +{ + stackManager_->Init(); + + auto result = stackManager_->StartAbility(launcherAbilityRequest_); + EXPECT_EQ(0, result); + auto topMissionRecord = stackManager_->GetTopMissionRecord(); + auto topAbilityRecord = topMissionRecord->GetTopAbilityRecord(); + EXPECT_TRUE(topMissionRecord); + EXPECT_TRUE(topAbilityRecord); + topAbilityRecord->SetAbilityState(OHOS::AAFwk::ACTIVE); + + auto abilityStartSetting = AbilityStartSetting::GetEmptySetting(); + + abilityStartSetting->AddProperty(AbilityStartSetting::WINDOW_MODE_KEY, + std::to_string(AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_FLOATING)); + EXPECT_TRUE(abilityStartSetting); + + musicAbilityRequest_.startSetting = abilityStartSetting; + result = stackManager_->StartAbility(musicAbilityRequest_); + EXPECT_EQ(0, result); + auto topMissionRecord2 = stackManager_->GetTopMissionRecord(); + auto topAbilityRecord2 = stackManager_->GetCurrentTopAbility(); + EXPECT_TRUE(topMissionRecord2); + EXPECT_TRUE(topAbilityRecord2); + topAbilityRecord->SetAbilityState(OHOS::AAFwk::INACTIVE); + topAbilityRecord2->SetAbilityState(OHOS::AAFwk::ACTIVE); + + auto stact = topMissionRecord2->GetMissionStack(); + EXPECT_TRUE(stact); + + EXPECT_EQ(stact->GetMissionStackId(), FLOATING_MISSION_STACK_ID); + + auto topStack = stackManager_->GetCurrentMissionStack(); + EXPECT_TRUE(topStack); + EXPECT_EQ(topStack->GetMissionStackId(), FLOATING_MISSION_STACK_ID); + // luncher move to top + auto ref = stackManager_->MinimizeMultiWindow(topMissionRecord2->GetMissionRecordId()); + EXPECT_EQ(0, ref); + + stact = stackManager_->GetCurrentMissionStack(); + EXPECT_TRUE(stact); + EXPECT_EQ(stact->GetMissionStackId(), LAUNCHER_MISSION_STACK_ID); +} + +/* + * Feature: AbilityStackManager + * Function: MinimizeMultiWindow + * SubFunction: NA + * FunctionPoints: Move the floating window to the background + * EnvConditions: NA + * CaseDescription: Move the floating window to the background + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_077, TestSize.Level1) +{ + stackManager_->Init(); + + // start luncher + auto result = stackManager_->StartAbility(launcherAbilityRequest_); + EXPECT_EQ(0, result); + auto topMissionRecord = stackManager_->GetTopMissionRecord(); + auto topAbilityRecord = topMissionRecord->GetTopAbilityRecord(); + EXPECT_TRUE(topMissionRecord); + EXPECT_TRUE(topAbilityRecord); + topAbilityRecord->SetAbilityState(OHOS::AAFwk::ACTIVE); + + // start top ability + result = stackManager_->StartAbility(radioTopAbilityRequest_); + EXPECT_EQ(0, result); + auto radioMissionRecord = stackManager_->GetTopMissionRecord(); + auto radioAbilityRecord = radioMissionRecord->GetTopAbilityRecord(); + EXPECT_TRUE(radioMissionRecord); + EXPECT_TRUE(radioAbilityRecord); + radioAbilityRecord->SetAbilityState(OHOS::AAFwk::ACTIVE); + + // start float ability + auto abilityStartSetting = AbilityStartSetting::GetEmptySetting(); + + abilityStartSetting->AddProperty(AbilityStartSetting::WINDOW_MODE_KEY, + std::to_string(AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_FLOATING)); + EXPECT_TRUE(abilityStartSetting); + + musicAbilityRequest_.startSetting = abilityStartSetting; + result = stackManager_->StartAbility(musicAbilityRequest_); + EXPECT_EQ(0, result); + auto topMissionRecord2 = stackManager_->GetTopMissionRecord(); + auto topAbilityRecord2 = stackManager_->GetCurrentTopAbility(); + EXPECT_TRUE(topMissionRecord2); + EXPECT_TRUE(topAbilityRecord2); + topAbilityRecord2->SetAbilityState(OHOS::AAFwk::ACTIVE); + + auto stact = topMissionRecord2->GetMissionStack(); + EXPECT_TRUE(stact); + + EXPECT_EQ(stact->GetMissionStackId(), FLOATING_MISSION_STACK_ID); + + auto topStack = stackManager_->GetCurrentMissionStack(); + EXPECT_TRUE(topStack); + EXPECT_EQ(topStack->GetMissionStackId(), FLOATING_MISSION_STACK_ID); + // ton ability move to top + auto ref = stackManager_->MinimizeMultiWindow(topMissionRecord2->GetMissionRecordId()); + EXPECT_EQ(0, ref); + + stact = stackManager_->GetCurrentMissionStack(); + EXPECT_TRUE(stact); + // current top + EXPECT_EQ(stact->GetMissionStackId(), DEFAULT_MISSION_STACK_ID); +} + +/* + * Feature: AbilityStackManager + * Function: MaximizeMultiWindow + * SubFunction: NA + * FunctionPoints: Move the floating window to the default stack + * EnvConditions: NA + * CaseDescription: move the ability form float stack to default stack + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_078, TestSize.Level1) +{ + stackManager_->Init(); + + auto ref = stackManager_->MaximizeMultiWindow(-1); + EXPECT_EQ(ref, MAXIMIZE_MULTIWINDOW_NOT_EXIST); + + auto result = stackManager_->StartAbility(radioAbilityRequest_); + EXPECT_EQ(0, result); + auto musicMissionRecord = stackManager_->GetTopMissionRecord(); + auto musicAbilityRecord = musicMissionRecord->GetTopAbilityRecord(); + EXPECT_TRUE(musicMissionRecord); + EXPECT_TRUE(musicAbilityRecord); + musicAbilityRecord->SetAbilityState(OHOS::AAFwk::ACTIVE); + + ref = stackManager_->MaximizeMultiWindow(musicMissionRecord->GetMissionRecordId()); + EXPECT_EQ(ref, MAXIMIZE_MULTIWINDOW_NOT_EXIST); +} + +/* + * Feature: AbilityStackManager + * Function: MaximizeMultiWindow + * SubFunction: NA + * FunctionPoints: Move the floating window to the background + * EnvConditions: NA + * CaseDescription: Move the floating window to the background + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_079, TestSize.Level1) +{ + stackManager_->Init(); + + // start luncher + auto result = stackManager_->StartAbility(launcherAbilityRequest_); + EXPECT_EQ(0, result); + auto topMissionRecord = stackManager_->GetTopMissionRecord(); + auto topAbilityRecord = topMissionRecord->GetTopAbilityRecord(); + EXPECT_TRUE(topMissionRecord); + EXPECT_TRUE(topAbilityRecord); + topAbilityRecord->SetAbilityState(OHOS::AAFwk::ACTIVE); + + // start top ability + result = stackManager_->StartAbility(radioAbilityRequest_); + EXPECT_EQ(0, result); + auto radioMissionRecord = stackManager_->GetTopMissionRecord(); + auto radioAbilityRecord = radioMissionRecord->GetTopAbilityRecord(); + EXPECT_TRUE(radioMissionRecord); + EXPECT_TRUE(radioAbilityRecord); + radioAbilityRecord->SetAbilityState(OHOS::AAFwk::ACTIVE); + + // start float ability + auto abilityStartSetting = AbilityStartSetting::GetEmptySetting(); + + abilityStartSetting->AddProperty(AbilityStartSetting::WINDOW_MODE_KEY, + std::to_string(AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_FLOATING)); + EXPECT_TRUE(abilityStartSetting); + + musicAbilityRequest_.startSetting = abilityStartSetting; + result = stackManager_->StartAbility(musicAbilityRequest_); + EXPECT_EQ(0, result); + auto topMissionRecord2 = stackManager_->GetTopMissionRecord(); + auto topAbilityRecord2 = stackManager_->GetCurrentTopAbility(); + EXPECT_TRUE(topMissionRecord2); + EXPECT_TRUE(topAbilityRecord2); + topAbilityRecord2->SetAbilityState(OHOS::AAFwk::ACTIVE); + + auto stact = topMissionRecord2->GetMissionStack(); + EXPECT_TRUE(stact); + auto stack1 = radioMissionRecord->GetMissionStack(); + EXPECT_TRUE(stact); + + EXPECT_EQ(stact->GetMissionStackId(), FLOATING_MISSION_STACK_ID); + EXPECT_EQ(stack1->GetMissionStackId(), FLOATING_MISSION_STACK_ID); + + stackManager_->isMultiWinMoving_ = false; + auto topStack = stackManager_->GetCurrentMissionStack(); + EXPECT_TRUE(topStack); + EXPECT_EQ(topStack->GetMissionStackId(), FLOATING_MISSION_STACK_ID); + + auto ref = stackManager_->MaximizeMultiWindow(topMissionRecord2->GetMissionRecordId()); + EXPECT_EQ(0, ref); + + stact = stackManager_->GetCurrentMissionStack(); + EXPECT_TRUE(stact); + // current top + EXPECT_EQ(stact->GetMissionStackId(), DEFAULT_MISSION_STACK_ID); + + auto topAbility = stackManager_->GetTopMissionRecord()->GetTopAbilityRecord(); + EXPECT_TRUE(topAbility); +} + +/* + * Feature: AbilityStackManager + * Function: CloseMultiWindow + * SubFunction: NA + * FunctionPoints: Close multiple windows + * EnvConditions: NA + * CaseDescription: Can I exit the front desk by closing the floating window + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_080, TestSize.Level1) +{ + stackManager_->Init(); + + auto ref = stackManager_->CloseMultiWindow(-1); + EXPECT_EQ(ref, CLOSE_MULTI_WINDOW_FAILED); + + auto result = stackManager_->StartAbility(musicAbilityRequest_); + EXPECT_EQ(0, result); + auto musicMissionRecord = stackManager_->GetTopMissionRecord(); + auto musicAbilityRecord = musicMissionRecord->GetTopAbilityRecord(); + EXPECT_TRUE(musicMissionRecord); + EXPECT_TRUE(musicAbilityRecord); + musicAbilityRecord->SetAbilityState(OHOS::AAFwk::ACTIVE); + + ref = stackManager_->CloseMultiWindow(musicMissionRecord->GetMissionRecordId()); + EXPECT_EQ(ref, CLOSE_MULTI_WINDOW_FAILED); + + result = stackManager_->StartAbility(launcherAbilityRequest_); + EXPECT_EQ(0, result); + auto topMissionRecord = stackManager_->GetTopMissionRecord(); + auto topAbilityRecord = topMissionRecord->GetTopAbilityRecord(); + EXPECT_TRUE(topMissionRecord); + EXPECT_TRUE(topAbilityRecord); + topAbilityRecord->SetAbilityState(OHOS::AAFwk::ACTIVE); + + ref = stackManager_->CloseMultiWindow(musicMissionRecord->GetMissionRecordId()); + EXPECT_EQ(ref, CLOSE_MULTI_WINDOW_FAILED); +} + +/* + * Feature: AbilityStackManager + * Function: CloseMultiWindow + * SubFunction: NA + * FunctionPoints: Close multiple windows + * EnvConditions: NA + * CaseDescription: Can I exit the front desk by closing the floating window + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_081, TestSize.Level1) +{ + stackManager_->Init(); + + auto result = stackManager_->StartAbility(launcherAbilityRequest_); + EXPECT_EQ(0, result); + auto topMissionRecord = stackManager_->GetTopMissionRecord(); + auto topAbilityRecord = topMissionRecord->GetTopAbilityRecord(); + EXPECT_TRUE(topMissionRecord); + EXPECT_TRUE(topAbilityRecord); + topAbilityRecord->SetAbilityState(OHOS::AAFwk::ACTIVE); + + // start top ability + result = stackManager_->StartAbility(radioAbilityRequest_); + EXPECT_EQ(0, result); + auto radioMissionRecord = stackManager_->GetTopMissionRecord(); + auto radioAbilityRecord = radioMissionRecord->GetTopAbilityRecord(); + EXPECT_TRUE(radioMissionRecord); + EXPECT_TRUE(radioAbilityRecord); + radioAbilityRecord->SetAbilityState(OHOS::AAFwk::ACTIVE); + + // start float ability + auto abilityStartSetting = AbilityStartSetting::GetEmptySetting(); + + abilityStartSetting->AddProperty(AbilityStartSetting::WINDOW_MODE_KEY, + std::to_string(AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_FLOATING)); + EXPECT_TRUE(abilityStartSetting); + + musicAbilityRequest_.startSetting = abilityStartSetting; + result = stackManager_->StartAbility(musicAbilityRequest_); + EXPECT_EQ(0, result); + auto topMissionRecord2 = stackManager_->GetTopMissionRecord(); + auto topAbilityRecord2 = stackManager_->GetCurrentTopAbility(); + EXPECT_TRUE(topMissionRecord2); + EXPECT_TRUE(topAbilityRecord2); + topAbilityRecord2->SetAbilityState(OHOS::AAFwk::ACTIVE); + + auto stact = topMissionRecord2->GetMissionStack(); + EXPECT_TRUE(stact); + auto stack1 = radioMissionRecord->GetMissionStack(); + EXPECT_TRUE(stact); + + EXPECT_EQ(stact->GetMissionStackId(), FLOATING_MISSION_STACK_ID); + EXPECT_EQ(stack1->GetMissionStackId(), FLOATING_MISSION_STACK_ID); + + auto ref = stackManager_->CloseMultiWindow(topMissionRecord2->GetMissionRecordId()); + EXPECT_EQ(0, ref); + + auto topRecord = stackManager_->GetCurrentTopAbility(); + int state = topRecord->GetAbilityState(); + EXPECT_EQ(OHOS::AAFwk::INACTIVATING, state); +} + +/* + * Feature: AbilityStackManager + * Function: RestartAbility + * SubFunction: NA + * FunctionPoints: Restart ability + * EnvConditions: NA + * CaseDescription: Restart ability + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_082, TestSize.Level1) +{ + stackManager_->Init(); + EXPECT_TRUE(stackManager_); + + auto ability = std::make_shared(want_, abilityInfo_, appInfo_); + ability->Init(); + ability->SetAbilityState(AbilityState::ACTIVE); + stackManager_->RestartAbility(ability); + EXPECT_EQ(AbilityState::INACTIVATING, ability->GetAbilityState()); + + ability->SetAbilityState(AbilityState::ACTIVATING); + stackManager_->RestartAbility(ability); + EXPECT_EQ(AbilityState::INACTIVATING, ability->GetAbilityState()); +} + +/* + * Feature: AbilityStackManager + * Function: RestartAbility + * SubFunction: NA + * FunctionPoints: Restart ability + * EnvConditions: NA + * CaseDescription: Restart ability + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_083, TestSize.Level1) +{ + stackManager_->Init(); + EXPECT_TRUE(stackManager_); + auto ability = std::make_shared(want_, abilityInfo_, appInfo_); + ability->Init(); + ability->SetAbilityState(AbilityState::INACTIVE); + stackManager_->RestartAbility(ability); + EXPECT_FALSE(ability->IsNewWant()); + + ability->SetAbilityState(AbilityState::INACTIVATING); + stackManager_->RestartAbility(ability); + EXPECT_FALSE(ability->IsNewWant()); +} + +/* + * Feature: AbilityStackManager + * Function: RestartAbility + * SubFunction: NA + * FunctionPoints: Restart ability + * EnvConditions: NA + * CaseDescription: Restart ability + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_084, TestSize.Level1) +{ + stackManager_->Init(); + EXPECT_TRUE(stackManager_); + auto ability = std::make_shared(want_, abilityInfo_, appInfo_); + ability->Init(); + ability->SetAbilityState(AbilityState::BACKGROUND); + stackManager_->RestartAbility(ability); + EXPECT_EQ(AbilityState::TERMINATING, ability->GetAbilityState()); + + ability->SetAbilityState(AbilityState::MOVING_BACKGROUND); + stackManager_->RestartAbility(ability); + EXPECT_EQ(AbilityState::TERMINATING, ability->GetAbilityState()); +} + +/* + * Feature: AbilityStackManager + * Function: ProcessConfigurationChange + * SubFunction: NA + * FunctionPoints: Process Configuration Change + * EnvConditions: NA + * CaseDescription: Process Configuration Change + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_085, TestSize.Level1) +{ + stackManager_->Init(); + EXPECT_TRUE(stackManager_); + stackManager_->missionStackList_.clear(); + std::shared_ptr mission = nullptr; + stackManager_->missionStackList_.push_back(mission); + EXPECT_EQ(ERR_INVALID_VALUE, stackManager_->ProcessConfigurationChange()); +} + +/* + * Feature: AbilityStackManager + * Function: ProcessConfigurationChange + * SubFunction: NA + * FunctionPoints: Process Configuration Change + * EnvConditions: NA + * CaseDescription: Process Configuration Change + */ +HWTEST_F(AbilityStackManagerTest, ability_stack_manager_operating_086, TestSize.Level1) +{ + stackManager_->Init(); + EXPECT_TRUE(stackManager_); + stackManager_->missionStackList_.clear(); + stackManager_->missionStackList_.push_back(stackManager_->launcherMissionStack_); + + std::string bundleName = "ddddd"; + auto mission = std::make_shared(bundleName); + EXPECT_TRUE(mission); + mission->RemoveAll(); + Want want_; + AbilityInfo abilityInfo_; + ApplicationInfo appInfo_; + auto ability = std::make_shared(want_, abilityInfo_, appInfo_); + EXPECT_TRUE(ability); + mission->abilities_.push_back(ability); + stackManager_->launcherMissionStack_->RemoveAll(); + stackManager_->launcherMissionStack_->AddMissionRecordToTop(mission); + AbilityRecordInfo abilityInfo; + ability->GetAbilityRecordInfo(abilityInfo); + auto abilityRecord = mission->GetAbilityRecordById(abilityInfo.id); + EXPECT_TRUE(abilityRecord); + abilityRecord->SetAbilityState(AbilityState::ACTIVE); +} +} // namespace AAFwk +} // namespace OHOS diff --git a/tools/services/abilitymgr/test/unittest/phone/ability_token_proxy_test/BUILD.gn b/tools/services/abilitymgr/test/unittest/phone/ability_token_proxy_test/BUILD.gn new file mode 100644 index 00000000000..dad32d3fff5 --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/ability_token_proxy_test/BUILD.gn @@ -0,0 +1,65 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/test.gni") +import("//foundation/aafwk/standard/aafwk.gni") + +module_output_path = "aafwk_standard/abilitymgr" + +ohos_unittest("ability_token_proxy_test") { + module_out_path = module_output_path + + include_dirs = [ + "${services_path}/abilitymgr/test/mock/libs/system_ability_mock", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy/include", + ] + + sources = [ + "//foundation/aafwk/standard/services/abilitymgr/test/mock/libs/appexecfwk_core/src/appmgr/mock_app_scheduler.cpp", + "ability_token_proxy_test.cpp", # add mock file + ] + + configs = [ + "${services_path}/abilitymgr:abilityms_config", + "${services_path}/abilitymgr/test/mock:aafwk_mock_config", + ] + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + deps = [ + "${innerkits_path}/want:want", + "${services_path}/abilitymgr/test:abilityms_test_source", + "${services_path}/abilitymgr/test/mock/libs/aakit:aakit_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_appmgr_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_bundlemgr_mock", + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/frameworks/kits/ability/native:dummy_classes", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] +} + +group("unittest") { + testonly = true + + deps = [ ":ability_token_proxy_test" ] +} diff --git a/tools/services/abilitymgr/test/unittest/phone/ability_token_proxy_test/ability_token_proxy_test.cpp b/tools/services/abilitymgr/test/unittest/phone/ability_token_proxy_test/ability_token_proxy_test.cpp new file mode 100644 index 00000000000..e39762d4eeb --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/ability_token_proxy_test/ability_token_proxy_test.cpp @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "ability_token_proxy.h" + +using namespace testing::ext; +namespace OHOS { +namespace AAFwk { +class AbilityTokenProxyTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + + OHOS::sptr abilityTokenProxy_ = nullptr; + OHOS::sptr impl = nullptr; +}; + +void AbilityTokenProxyTest::SetUpTestCase(void) +{} +void AbilityTokenProxyTest::TearDownTestCase(void) +{} +void AbilityTokenProxyTest::TearDown(void) +{} + +void AbilityTokenProxyTest::SetUp(void) +{ + abilityTokenProxy_ = new AbilityTokenProxy(impl); +} + +/* + * Feature: AbilityTokenProxy + * Function: AbilityTokenProxy + * SubFunction: NA + * FunctionPoints: NA + * EnvConditions:NA + * CaseDescription: verify AbilityTokenProxy is create success + */ +HWTEST_F(AbilityTokenProxyTest, ability_token_proxy_operating_001, TestSize.Level0) +{ + EXPECT_NE(abilityTokenProxy_, nullptr); +} +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/abilitymgr/test/unittest/phone/ability_token_stub_test/BUILD.gn b/tools/services/abilitymgr/test/unittest/phone/ability_token_stub_test/BUILD.gn new file mode 100644 index 00000000000..52991999977 --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/ability_token_stub_test/BUILD.gn @@ -0,0 +1,65 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/test.gni") +import("//foundation/aafwk/standard/aafwk.gni") + +module_output_path = "aafwk_standard/abilitymgr" + +ohos_unittest("ability_token_stub_test") { + module_out_path = module_output_path + + include_dirs = [ + "${services_path}/abilitymgr/test/mock/libs/system_ability_mock", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy/include", + ] + + sources = [ + "//foundation/aafwk/standard/services/abilitymgr/test/mock/libs/appexecfwk_core/src/appmgr/mock_app_scheduler.cpp", + "ability_token_stub_test.cpp", # add mock file + ] + + configs = [ + "${services_path}/abilitymgr:abilityms_config", + "${services_path}/abilitymgr/test/mock:aafwk_mock_config", + ] + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + deps = [ + "${innerkits_path}/want:want", + "${services_path}/abilitymgr/test:abilityms_test_source", + "${services_path}/abilitymgr/test/mock/libs/aakit:aakit_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_appmgr_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_bundlemgr_mock", + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/frameworks/kits/ability/native:dummy_classes", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] +} + +group("unittest") { + testonly = true + + deps = [ ":ability_token_stub_test" ] +} diff --git a/tools/services/abilitymgr/test/unittest/phone/ability_token_stub_test/ability_token_stub_test.cpp b/tools/services/abilitymgr/test/unittest/phone/ability_token_stub_test/ability_token_stub_test.cpp new file mode 100644 index 00000000000..210639c8ef9 --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/ability_token_stub_test/ability_token_stub_test.cpp @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "ability_token_stub.h" + +using namespace testing::ext; +namespace OHOS { +namespace AAFwk { +class AbilityTokenStubTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + + OHOS::sptr abilityTokenStub_{nullptr}; + OHOS::sptr abilityTokenRecipient_{nullptr}; +}; + +void AbilityTokenStubTest::SetUpTestCase(void) +{} +void AbilityTokenStubTest::TearDownTestCase(void) +{} +void AbilityTokenStubTest::TearDown(void) +{} + +void AbilityTokenStubTest::SetUp(void) +{ + abilityTokenStub_ = new AbilityTokenStub(); + abilityTokenRecipient_ = new AbilityTokenRecipient(); +} + +/* + * Feature: AbilityTokenStub + * Function: AbilityTokenStub + * SubFunction: NA + * FunctionPoints: NA + * EnvConditions:NA + * CaseDescription: verify AbilityTokenStub is create success + */ +HWTEST_F(AbilityTokenStubTest, ability_token_stub_operating_001, TestSize.Level0) +{ + EXPECT_NE(abilityTokenStub_, nullptr); +} + +/* + * Feature: AbilityTokenStub + * Function: AbilityTokenRecipient + * SubFunction: NA + * FunctionPoints: NA + * EnvConditions:NA + * CaseDescription: verify AbilityTokenRecipient is create success + */ +HWTEST_F(AbilityTokenStubTest, ability_token_stub_operating_002, TestSize.Level0) +{ + EXPECT_NE(abilityTokenRecipient_, nullptr); +} +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/abilitymgr/test/unittest/phone/ability_with_applications_test/BUILD.gn b/tools/services/abilitymgr/test/unittest/phone/ability_with_applications_test/BUILD.gn new file mode 100644 index 00000000000..dc622d94bc4 --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/ability_with_applications_test/BUILD.gn @@ -0,0 +1,68 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/test.gni") +import("//foundation/aafwk/standard/aafwk.gni") + +module_output_path = "aafwk_standard/abilitymgr" + +ohos_unittest("ability_with_applications_test") { + module_out_path = module_output_path + + include_dirs = [ + "${services_path}/abilitymgr/test/mock/libs/system_ability_mock", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy/include", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_core/include/appmgr/", + ] + + sources = [ + "//foundation/aafwk/standard/services/abilitymgr/test/mock/libs/appexecfwk_core/src/appmgr/mock_app_scheduler.cpp", + "ability_with_applications_test.cpp", # add mock file + ] + + configs = [ + "${services_path}/abilitymgr:abilityms_config", + "${services_path}/abilitymgr/test/mock:aafwk_mock_config", + ] + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + deps = [ + "${innerkits_path}/want:want", + "${services_path}/abilitymgr/test:abilityms_test_source", + "${services_path}/abilitymgr/test/mock/appmgr_test_service:appmgr_test_service", + "${services_path}/abilitymgr/test/mock/libs/aakit:aakit_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_appmgr_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_bundlemgr_mock", + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/frameworks/kits/ability/native:dummy_classes", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//third_party/googletest:gmock_main", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] +} + +group("unittest") { + testonly = true + + deps = [ ":ability_with_applications_test" ] +} diff --git a/tools/services/abilitymgr/test/unittest/phone/ability_with_applications_test/ability_with_applications_test.cpp b/tools/services/abilitymgr/test/unittest/phone/ability_with_applications_test/ability_with_applications_test.cpp new file mode 100755 index 00000000000..fd4929cded3 --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/ability_with_applications_test/ability_with_applications_test.cpp @@ -0,0 +1,362 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include "system_ability_definition.h" +#include "ability_info.h" +#include "application_info.h" +#define private public +#define protected public +#include "ability_manager_service.h" +#undef private +#undef protected +#include "ability_manager_errors.h" +#include "gtest/gtest.h" +#include "mock_bundle_manager.h" +#include "want.h" +#include "sa_mgr_client.h" +#include "appmgr_test_service.h" + +using namespace testing; +using namespace testing::ext; +using namespace OHOS::AppExecFwk; + +namespace OHOS { +namespace AAFwk { +#define SLEEP(milli) std::this_thread::sleep_for(std::chrono::seconds(milli)) + +namespace { +const std::string NAME_BUNDLE_MGR_SERVICE = "BundleMgrService"; +static ElementName g_testAbility1("device", "com.ix.test1", "MainAbility1"); +static ElementName g_testAbility2("device", "com.ix.test2", "MainAbility2"); +static ElementName g_testAbility3("device", "com.ix.test3", "MainAbility3"); +static ElementName g_testAbility4("device", "com.ix.test4", "MainAbility4"); +static ElementName g_launcherAbility("device", "com.ix.hiworld", "MainAbility"); +} // namespace + +static void WaitUntilTaskFinished() +{ + const uint32_t maxRetryCount = 1000; + const uint32_t sleepTime = 1000; + uint32_t count = 0; + auto handler = OHOS::DelayedSingleton::GetInstance()->GetEventHandler(); + std::atomic taskCalled(false); + auto f = [&taskCalled]() { taskCalled.store(true); }; + if (handler->PostTask(f)) { + while (!taskCalled.load()) { + ++count; + if (count >= maxRetryCount) { + break; + } + usleep(sleepTime); + } + } +} +class AbilityWithApplicationsTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp(); + void TearDown(); + +public: + static constexpr int TEST_WAIT_TIME = 100000; + std::shared_ptr abilityMs_{nullptr}; +}; + +void AbilityWithApplicationsTest::SetUpTestCase() +{ + OHOS::DelayedSingleton::GetInstance()->RegisterSystemAbility( + OHOS::BUNDLE_MGR_SERVICE_SYS_ABILITY_ID, new BundleMgrService()); +} +void AbilityWithApplicationsTest::TearDownTestCase() +{ + OHOS::DelayedSingleton::DestroyInstance(); +} + +void AbilityWithApplicationsTest::SetUp() +{ + abilityMs_ = OHOS::DelayedSingleton::GetInstance(); + abilityMs_->OnStart(); + WaitUntilTaskFinished(); /* wait for Service Start Complete */ +} + +void AbilityWithApplicationsTest::TearDown() +{ + abilityMs_->OnStop(); + OHOS::DelayedSingleton::DestroyInstance(); +} + +/* + * Feature: AbilityManagerService + * Function: StartAbility + * SubFunction: NA + * FunctionPoints: AbilityManagerService StartAbility + * EnvConditions: NA + * CaseDescription: Verify that the result of StartAbility with applications + */ +HWTEST_F(AbilityWithApplicationsTest, Start_Ability_With_Applications_001, TestSize.Level2) +{ + GTEST_LOG_(INFO) << "AbilityWithApplicationTest_001 start"; + Want want1; + want1.SetElement(g_testAbility1); + Want want2; + want2.SetElement(g_testAbility2); + if (abilityMs_->GetStackManager()->GetCurrentTopAbility()) { + abilityMs_->GetStackManager()->GetCurrentTopAbility()->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + } + int result = abilityMs_->StartAbility(want1); + EXPECT_EQ(0, result); + if (abilityMs_->GetStackManager()->GetCurrentTopAbility()) { + abilityMs_->GetStackManager()->GetCurrentTopAbility()->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + } + result = abilityMs_->StartAbility(want2); + if (abilityMs_->GetStackManager()->GetCurrentTopAbility()) { + abilityMs_->GetStackManager()->GetCurrentTopAbility()->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + } + /* get stack manager */ + std::shared_ptr stackmgr = abilityMs_->GetStackManager(); + std::shared_ptr curMission; + if (stackmgr) { + curMission = stackmgr->GetCurrentMissionStack()->GetTopMissionRecord(); + } + std::shared_ptr topAbility; + if (curMission) { + topAbility = curMission->GetTopAbilityRecord(); + } + EXPECT_TRUE(topAbility != nullptr); + EXPECT_TRUE(curMission != nullptr); + if (topAbility) { + EXPECT_NE("com.ix.test1", topAbility->GetAbilityInfo().applicationName); + EXPECT_NE(BACKGROUND, topAbility->GetAbilityState()); + } + if (curMission) { + std::shared_ptr bottomAbility = curMission->GetBottomAbilityRecord(); + EXPECT_TRUE(bottomAbility != nullptr); + EXPECT_EQ("com.ix.test1", bottomAbility->GetAbilityInfo().applicationName); + EXPECT_NE(BACKGROUND, bottomAbility->GetAbilityState()); + } + /* clear the mission stack */ + AbilityRequest request; + abilityMs_->GetStackManager()->GetTargetMissionStack(request)->RemoveAll(); +} + +/* + * Feature: AbilityManagerService + * Function: StartAbility + * SubFunction: NA + * FunctionPoints: AbilityManagerService StartAbility + * EnvConditions: NA + * CaseDescription: Verify that the result of StartAbility with applications when launch active + */ +HWTEST_F(AbilityWithApplicationsTest, Start_Ability_With_Applications_002, TestSize.Level2) +{ + Want want1; + want1.SetElement(g_testAbility1); + Want want2; + want2.SetElement(g_testAbility2); + Want want3; + want3.SetElement(g_launcherAbility); + want3.AddEntity(Want::ENTITY_HOME); + Want want4; + want4.SetElement(g_testAbility4); + if (abilityMs_->GetStackManager()->GetCurrentTopAbility()) { + abilityMs_->GetStackManager()->GetCurrentTopAbility()->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + } + int result = abilityMs_->StartAbility(want1); + EXPECT_EQ(0, result); + SLEEP(2); + if (abilityMs_->GetStackManager()->GetCurrentTopAbility()) { + abilityMs_->GetStackManager()->GetCurrentTopAbility()->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + } + result = abilityMs_->StartAbility(want2); + SLEEP(2); + EXPECT_EQ(0, result); + if (abilityMs_->GetStackManager()->GetCurrentTopAbility()) { + abilityMs_->GetStackManager()->GetCurrentTopAbility()->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + } + result = abilityMs_->StartAbility(want3); + EXPECT_EQ(0, result); + SLEEP(2); + if (abilityMs_->GetStackManager()->GetCurrentTopAbility()) { + abilityMs_->GetStackManager()->GetCurrentTopAbility()->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + } + result = abilityMs_->StartAbility(want4); + EXPECT_EQ(0, result); + SLEEP(2); + if (abilityMs_->GetStackManager()->GetCurrentTopAbility()) { + abilityMs_->GetStackManager()->GetCurrentTopAbility()->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + } + auto stackmgr = abilityMs_->GetStackManager(); + auto curMission = stackmgr->GetCurrentMissionStack(); + EXPECT_NE(curMission, nullptr); + auto topAbility = curMission->GetTopAbilityRecord(); + EXPECT_TRUE(topAbility != nullptr); + EXPECT_NE("com.ix.test1", topAbility->GetAbilityInfo().applicationName); + EXPECT_NE(BACKGROUND, topAbility->GetAbilityState()); + AbilityRequest request; + abilityMs_->GetStackManager()->GetTargetMissionStack(request)->RemoveAll(); +} + +/* + * Feature: AbilityManagerService + * Function: TerminateAbility + * SubFunction: NA + * FunctionPoints: AbilityManagerService TerminateAbility + * EnvConditions: NA + * CaseDescription: terminate the ability in mission, and active launchAbility + */ +HWTEST_F(AbilityWithApplicationsTest, Teminate_Ability_With_Applications_001, TestSize.Level2) +{ + GTEST_LOG_(INFO) << "Teminate_Ability_With_Applications_001 begin"; + Want want1; + want1.SetElement(g_testAbility1); + + if (abilityMs_->GetStackManager()->GetCurrentTopAbility()) { + abilityMs_->GetStackManager()->GetCurrentTopAbility()->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + } + + int result = abilityMs_->StartAbility(want1); + EXPECT_EQ(0, result); + SLEEP(2); + + if (abilityMs_->GetStackManager()->GetCurrentTopAbility()) { + abilityMs_->GetStackManager()->GetCurrentTopAbility()->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + } + /* get stack manager */ + std::shared_ptr stackmgr = abilityMs_->GetStackManager(); + std::shared_ptr curMission; + if (stackmgr) { + curMission = stackmgr->GetCurrentMissionStack()->GetTopMissionRecord(); + } + + std::shared_ptr topAbility; + if (curMission) { + topAbility = curMission->GetTopAbilityRecord(); + } + + EXPECT_TRUE(topAbility != nullptr); + EXPECT_TRUE(curMission != nullptr); + + if (topAbility) { + EXPECT_EQ("com.ix.test1", topAbility->GetAbilityInfo().applicationName); + EXPECT_NE(BACKGROUND, topAbility->GetAbilityState()); + } + + if (curMission) { + std::shared_ptr bottomAbility = curMission->GetBottomAbilityRecord(); + EXPECT_TRUE(bottomAbility != nullptr); + EXPECT_EQ("com.ix.test1", bottomAbility->GetAbilityInfo().applicationName); + EXPECT_NE(BACKGROUND, bottomAbility->GetAbilityState()); + } + + EXPECT_TRUE(topAbility != nullptr); + abilityMs_->TerminateAbility(topAbility->GetToken(), -1); + SLEEP(2); + auto missionstack = stackmgr->GetCurrentMissionStack(); + + if (missionstack) { + topAbility = missionstack->GetTopAbilityRecord(); + } + + if (topAbility) { + EXPECT_EQ("com.ix.hiworld", topAbility->GetAbilityInfo().applicationName); + EXPECT_EQ(INACTIVATING, topAbility->GetAbilityState()); + } + + if (missionstack) { + missionstack->RemoveAll(); + } + + GTEST_LOG_(INFO) << "Teminate_Ability_With_Applications_001 end"; +} + +/* + * Feature: AbilityManagerService + * Function: TerminateAbility + * SubFunction: NA + * FunctionPoints: AbilityManagerService TerminateAbility + * EnvConditions: NA + * CaseDescription: terminate the ability in mission, and active prev app ability + */ +HWTEST_F(AbilityWithApplicationsTest, Teminate_Ability_With_Applications_002, TestSize.Level2) +{ + GTEST_LOG_(INFO) << "Teminate_Ability_With_Applications_002 begin"; + Want want1; + want1.SetElement(g_testAbility1); + Want want2; + want2.SetElement(g_testAbility2); + if (abilityMs_->GetStackManager()->GetCurrentTopAbility()) { + abilityMs_->GetStackManager()->GetCurrentTopAbility()->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + } + int result = abilityMs_->StartAbility(want1); + SLEEP(2); + EXPECT_EQ(0, result); + if (abilityMs_->GetStackManager()->GetCurrentTopAbility()) { + abilityMs_->GetStackManager()->GetCurrentTopAbility()->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + } + result = abilityMs_->StartAbility(want2); + SLEEP(2); + EXPECT_EQ(0, result); + + /* get stack manager */ + /* get stack manager */ + std::shared_ptr stackmgr = abilityMs_->GetStackManager(); + std::shared_ptr curMission; + if (stackmgr) { + curMission = stackmgr->GetCurrentMissionStack()->GetTopMissionRecord(); + } + GTEST_LOG_(INFO) << "GetTopAbilityRecord"; + std::shared_ptr topAbility; + if (curMission) { + topAbility = curMission->GetTopAbilityRecord(); + } + + EXPECT_TRUE(topAbility != nullptr); + EXPECT_TRUE(curMission != nullptr); + + if (topAbility) { + EXPECT_NE("com.ix.test1", topAbility->GetAbilityInfo().applicationName); + EXPECT_NE(BACKGROUND, topAbility->GetAbilityState()); + } + + if (curMission) { + std::shared_ptr bottomAbility = curMission->GetBottomAbilityRecord(); + EXPECT_TRUE(bottomAbility != nullptr); + EXPECT_EQ("com.ix.test1", bottomAbility->GetAbilityInfo().applicationName); + EXPECT_NE(BACKGROUND, bottomAbility->GetAbilityState()); + } + EXPECT_TRUE(topAbility != nullptr); + Want resultWant; + std::string key("key"); + int resultValue = 4; + resultWant.SetParam(key, resultValue); + result = abilityMs_->TerminateAbility(topAbility->GetToken(), -1, &resultWant); + SLEEP(2); + EXPECT_EQ(0, result); + + auto missionstack = stackmgr->GetCurrentMissionStack(); + EXPECT_EQ(1, missionstack->GetMissionStackId()); + topAbility = missionstack->GetTopAbilityRecord(); + EXPECT_TRUE(topAbility != nullptr); + EXPECT_EQ("com.ix.test1", topAbility->GetAbilityInfo().applicationName); + AbilityRequest request; + abilityMs_->GetStackManager()->GetTargetMissionStack(request)->RemoveAll(); + GTEST_LOG_(INFO) << "Teminate_Ability_With_Applications_002 end"; +} +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/abilitymgr/test/unittest/phone/ability_with_applications_test/mock_ability_scheduler.cpp b/tools/services/abilitymgr/test/unittest/phone/ability_with_applications_test/mock_ability_scheduler.cpp new file mode 100644 index 00000000000..3a6cbc8b1d3 --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/ability_with_applications_test/mock_ability_scheduler.cpp @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ability_scheduler.h" +#include "appmgr_test_service.h" +#include "hilog_wrapper.h" + +namespace OHOS { +namespace AAFwk { +AbilityScheduler::AbilityScheduler() +{} + +AbilityScheduler::~AbilityScheduler() +{} + +void AbilityScheduler::ScheduleAbilityTransaction(const Want &want, const LifeCycleStateInfo &targetState) +{} + +void AbilityScheduler::SendResult(int requestCode, int resultCode, const Want &resultWant) +{} + +const AbilityResult &AbilityScheduler::GetResult() const +{ + return result_; +} + +void AbilityScheduler::ScheduleConnectAbility(const Want &want) +{} + +void AbilityScheduler::ScheduleDisconnectAbility(const Want &want) +{} + +void AbilityScheduler::ScheduleCommandAbility(const Want &want, bool restart, int startId) +{} + +void AbilityScheduler::ScheduleSaveAbilityState(PacMap &outState) +{} + +void AbilityScheduler::ScheduleRestoreAbilityState(const PacMap &inState) +{} + +void AbilityScheduler::ScheduleUpdateConfiguration(const DummyConfiguration &config) +{} + +std::vector AbilityScheduler::GetFileTypes(const Uri &uri, const std::string &mimeTypeFilter) +{ + std::vector types; + return types; +} + +int AbilityScheduler::OpenFile(const Uri &uri, const std::string &mode) +{ + return -1; +} + +int AbilityScheduler::Insert(const Uri &uri, const NativeRdb::ValuesBucket &value) +{ + return -1; +} + +int AbilityScheduler::Update( + const Uri &uri, const NativeRdb::ValuesBucket &value, const NativeRdb::DataAbilityPredicates &predicates) +{ + return -1; +} + +int AbilityScheduler::Delete(const Uri &uri, const NativeRdb::DataAbilityPredicates &predicates) +{ + return -1; +} + +std::shared_ptr AbilityScheduler::Query( + const Uri &uri, std::vector &columns, const NativeRdb::DataAbilityPredicates &predicates) +{ + return nullptr; +} + +std::string AbilityScheduler::GetType(const Uri &uri) +{ + return "do_by_yourself"; +} + +int AbilityScheduler::OpenRawFile(const Uri &uri, const std::string &mode) +{ + return -1; +} + +bool AbilityScheduler::Reload(const Uri &uri, const PacMap &extras) +{ + return false; +} + +int AbilityScheduler::BatchInsert(const Uri &uri, const std::vector &values) +{ + return -1; +} + +Uri AbilityScheduler::NormalizeUri(const Uri &uri) +{ + Uri urivalue(""); + return urivalue; +} + +Uri AbilityScheduler::DenormalizeUri(const Uri &uri) +{ + Uri urivalue(""); + return urivalue; +} + +void AbilityScheduler::NotifyMultiWinModeChanged(int32_t winModeKey, bool flag) +{} +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/abilitymgr/test/unittest/phone/abilityms_appms_test/BUILD.gn b/tools/services/abilitymgr/test/unittest/phone/abilityms_appms_test/BUILD.gn new file mode 100644 index 00000000000..9c7f688ad8f --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/abilityms_appms_test/BUILD.gn @@ -0,0 +1,68 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/test.gni") +import("//foundation/aafwk/standard/aafwk.gni") + +module_output_path = "aafwk_standard/abilitymgr" + +ohos_unittest("abilityms_appms_test") { + module_out_path = module_output_path + + include_dirs = [ + "${services_path}/abilitymgr/test/mock/libs/system_ability_mock", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy/include", + "//foundation/aafwk/standard/services/abilitymgr/test/mock/include", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_core/include/appmgr", + ] + + sources = [ + "//foundation/aafwk/standard/services/abilitymgr/test/mock/libs/appexecfwk_core/src/appmgr/mock_app_scheduler.cpp", + "abilityms_appms_test.cpp", # add mock file + ] + + configs = [ + "${services_path}/abilitymgr:abilityms_config", + "${services_path}/abilitymgr/test/mock:aafwk_mock_config", + ] + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + deps = [ + "${innerkits_path}/want:want", + "${services_path}/abilitymgr/test:abilityms_test_source", + "${services_path}/abilitymgr/test/mock/libs/aakit:aakit_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_appmgr_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_bundlemgr_mock", + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/frameworks/kits/ability/native:dummy_classes", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//third_party/googletest:gmock_main", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] +} + +group("unittest") { + testonly = true + + deps = [ ":abilityms_appms_test" ] +} diff --git a/tools/services/abilitymgr/test/unittest/phone/abilityms_appms_test/abilityms_appms_test.cpp b/tools/services/abilitymgr/test/unittest/phone/abilityms_appms_test/abilityms_appms_test.cpp new file mode 100644 index 00000000000..91cd0b715e4 --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/abilityms_appms_test/abilityms_appms_test.cpp @@ -0,0 +1,284 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "gmock/gmock.h" +#include "system_ability_definition.h" + +#define private public +#define protected public +#include "ability_scheduler.h" +#include "app_scheduler.h" +#include "ability_manager_service.h" +#undef private +#undef protected + +#include "app_process_data.h" +#include "mock_bundle_manager.h" +#include "mock_app_manager_client.h" +#include "sa_mgr_client.h" +#include "app_state_callback_host.h" + +using namespace testing; +using namespace testing::ext; +using namespace OHOS::AppExecFwk; +using namespace testing::ext; +using testing::_; + +namespace OHOS { +namespace AAFwk { + +namespace { +const std::string NAME_BUNDLE_MGR_SERVICE = "BundleMgrService"; +} + +static void WaitUntilTaskFinished() +{ + const uint32_t maxRetryCount = 1000; + const uint32_t sleepTime = 1000; + uint32_t count = 0; + auto handler = OHOS::DelayedSingleton::GetInstance()->GetEventHandler(); + std::atomic taskCalled(false); + auto f = [&taskCalled]() { taskCalled.store(true); }; + if (handler->PostTask(f)) { + while (!taskCalled.load()) { + ++count; + if (count >= maxRetryCount) { + break; + } + usleep(sleepTime); + } + } +} + +class AppStateCallbackS : public AppStateCallback { +public: + AppStateCallbackS() + {} + ~AppStateCallbackS() + {} + MOCK_METHOD2(OnAbilityRequestDone, void(const sptr &token, const int32_t state)); + MOCK_METHOD1(OnAppStateChanged, void(const AppInfo &info)); +}; + +class AbilityMsAppmsTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + + std::shared_ptr GetAbilityRecord() const; + void ResetAbilityRecord(); + void startAbility(); + +public: + std::shared_ptr abilityRecord_{nullptr}; + std::shared_ptr callback_{nullptr}; +}; + +void AbilityMsAppmsTest::SetUpTestCase(void) +{} +void AbilityMsAppmsTest::TearDownTestCase(void) +{} + +void AbilityMsAppmsTest::SetUp(void) +{ + sptr bundleObject = new BundleMgrService(); + DelayedSingleton::GetInstance()->RegisterSystemAbility( + OHOS::BUNDLE_MGR_SERVICE_SYS_ABILITY_ID, bundleObject); + DelayedSingleton::GetInstance(); + + callback_ = std::make_shared(); + + DelayedSingleton::GetInstance()->Init(callback_); + DelayedSingleton::GetInstance()->OnStart(); + WaitUntilTaskFinished(); + startAbility(); + GTEST_LOG_(INFO) << "SetUp"; +} + +void AbilityMsAppmsTest::TearDown(void) +{ + DelayedSingleton::DestroyInstance(); + GTEST_LOG_(INFO) << "TearDown"; +} + +std::shared_ptr AbilityMsAppmsTest::GetAbilityRecord() const +{ + return abilityRecord_; +} + +void AbilityMsAppmsTest::ResetAbilityRecord() +{ + abilityRecord_.reset(); + const Want want; + AbilityInfo abilityInfo; + abilityInfo.name = "HelloWorld"; + abilityInfo.applicationName = "HelloWorld"; + abilityInfo.package = "com.ix.hiworld"; + ApplicationInfo applicationInfo; + applicationInfo.name = "HelloWorld"; + applicationInfo.bundleName = "HelloWorld"; + + abilityRecord_ = std::make_shared(want, abilityInfo, applicationInfo); + abilityRecord_->Init(); +} + +void AbilityMsAppmsTest::startAbility() +{ + Want want; + AbilityInfo abilityInfo; + ApplicationInfo applicationInfo; + + auto abilityMs_ = DelayedSingleton::GetInstance(); + EXPECT_TRUE(abilityMs_->currentStackManager_); + auto currentTopAbilityRecord = abilityMs_->currentStackManager_->GetCurrentTopAbility(); + EXPECT_TRUE(currentTopAbilityRecord); + currentTopAbilityRecord->SetAbilityState(AbilityState::ACTIVE); + ElementName element("device", "com.ix.hiworld", "luncherAbility"); + want.SetElement(element); + abilityMs_->StartAbility(want); + auto topAbility = abilityMs_->GetStackManager()->GetCurrentTopAbility(); + if (topAbility) { + topAbility->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + } + abilityRecord_ = std::make_shared(want, abilityInfo, applicationInfo); +} + +/* + * Feature: Interaction of abilityms and appms + * Function: Interaction of abilityms and appms + * SubFunction: NA + * FunctionPoints: LoadAbility + * EnvConditions:NA + * CaseDescription: verify LoadAbility parameters. LoadAbility fail if token is nullptr. + */ +HWTEST_F(AbilityMsAppmsTest, AaFwk_AbilityMS_AppMS_001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AbilityMsAppMsTest_AaFwk_AbilityMS_AppMS_001 start"; + auto result = GetAbilityRecord()->LoadAbility(); + EXPECT_EQ(ERR_INVALID_VALUE, result); + GTEST_LOG_(INFO) << "AbilityMsAppMsTest_AaFwk_AbilityMS_AppMS_001 end"; +} + +/* + * Feature: Interaction of abilityms and appms + * Function: Interaction of abilityms and appms + * SubFunction: NA + * FunctionPoints: LoadAbility + * EnvConditions:NA + * CaseDescription: verify LoadAbility parameters. LoadAbility fail if abilityinfo or appinfo is empty. + */ +HWTEST_F(AbilityMsAppmsTest, AaFwk_AbilityMS_AppMS_002, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AbilityMsAppMsTest_AaFwk_AbilityMS_AppMS_002 start"; + GetAbilityRecord()->Init(); + auto result = GetAbilityRecord()->LoadAbility(); + EXPECT_EQ(ERR_INVALID_VALUE, result); + GTEST_LOG_(INFO) << "AbilityMsAppMsTest_AaFwk_AbilityMS_AppMS_002 end"; +} + +/* + * Feature: Interaction of abilityms and appms + * Function: Interaction of abilityms and appms + * SubFunction: NA + * FunctionPoints: LoadAbility + * EnvConditions:NA + * CaseDescription: 1. abilityinfo or appinfo is empty. + * 2. Load ability + * 3. the result of load ability is successfully, + * the LoadAbility function of Appscheduler is called. + * 4. Ability state is still INITIAL, since called is asynchronous. + */ +HWTEST_F(AbilityMsAppmsTest, AaFwk_AbilityMS_AppMS_003, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AbilityMsAppMsTest_AaFwk_AbilityMS_AppMS_003 start"; + ResetAbilityRecord(); + int result = GetAbilityRecord()->LoadAbility(); + EXPECT_EQ(ERR_OK, result); + auto state = GetAbilityRecord()->GetAbilityState(); + EXPECT_EQ(AAFwk::AbilityState::INITIAL, state); + GTEST_LOG_(INFO) << "AbilityMsAppMsTest_AaFwk_AbilityMS_AppMS_003 end"; +} + +/* + * Feature: Interaction of abilityms and appms + * Function: Interaction of abilityms and appms + * SubFunction: NA + * FunctionPoints: MoveForeground + * EnvConditions:NA + * CaseDescription: 1. launcher ability is started. + * 2. the LoadAbility and MoveToForeground function of AppSchedule are called + * 3. the Active function of AbilityRecord is called. + * 4. the state of launcher ability is ACTIVATING. + */ +HWTEST_F(AbilityMsAppmsTest, AaFwk_AbilityMS_AppMS_004, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AbilityMsAppMsTest_AaFwk_AbilityMS_AppMS_004 start"; + auto handler = DelayedSingleton::GetInstance()->GetEventHandler(); + sptr scheduler = new AbilityScheduler(); + std::shared_ptr abilityRecord = nullptr; + sptr token = nullptr; + + auto checkStateFun = [&scheduler, &token, &abilityRecord]() { + auto stackManager = DelayedSingleton::GetInstance()->GetStackManager(); + abilityRecord = stackManager->GetCurrentTopAbility(); + token = abilityRecord->GetToken(); + DelayedSingleton::GetInstance()->AttachAbilityThread(scheduler, token); + }; + + handler->PostTask(checkStateFun); + WaitUntilTaskFinished(); + GTEST_LOG_(INFO) << "AbilityMsAppMsTest_AaFwk_AbilityMS_AppMS_004 end"; +} + +/* + * Feature: Interaction of abilityms and appms + * Function: Interaction of abilityms and appms + * SubFunction: NA + * FunctionPoints: MoveBackground + * EnvConditions:NA + * CaseDescription: 1. launcher ability is started. + * 2. the LoadAbility and MoveToForeground function of AppSchedule are called + * 3. the Active function of AbilityRecord is called. + * 4. the state of launcher ability is ACTIVATING. + * 5. perform ability to background + * 6. the MoveBackground fun of appSchedule is called. + */ +HWTEST_F(AbilityMsAppmsTest, AaFwk_AbilityMS_AppMS_005, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AbilityMsAppMsTest_AaFwk_AbilityMS_AppMS_005 start"; + auto handler = DelayedSingleton::GetInstance()->GetEventHandler(); + + sptr scheduler = new AbilityScheduler(); + std::shared_ptr sourceAbilityRecord = nullptr; + std::shared_ptr stackManager = nullptr; + sptr sourcetoken = nullptr; + + auto checkSourceActivtingState = [&stackManager, &sourceAbilityRecord, &scheduler, &sourcetoken]() { + stackManager = DelayedSingleton::GetInstance()->GetStackManager(); + sourceAbilityRecord = stackManager->GetCurrentTopAbility(); + sourcetoken = sourceAbilityRecord->GetToken(); + DelayedSingleton::GetInstance()->AttachAbilityThread(scheduler, sourcetoken); + auto sourceAbilityInfo = sourceAbilityRecord->GetAbilityInfo(); + EXPECT_EQ(sourceAbilityInfo.bundleName, "com.ix.hiworld"); + }; + handler->PostTask(checkSourceActivtingState); + WaitUntilTaskFinished(); + GTEST_LOG_(INFO) << "AbilityMsAppMsTest_AaFwk_AbilityMS_AppMS_005 end"; +} +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/abilitymgr/test/unittest/phone/app_scheduler_test/BUILD.gn b/tools/services/abilitymgr/test/unittest/phone/app_scheduler_test/BUILD.gn new file mode 100644 index 00000000000..dc230f5e615 --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/app_scheduler_test/BUILD.gn @@ -0,0 +1,67 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/test.gni") +import("//foundation/aafwk/standard/aafwk.gni") +import("//foundation/aafwk/standard/services/abilitymgr/abilitymgr.gni") + +module_output_path = "aafwk_standard/abilitymgr" + +ohos_unittest("app_scheduler_test") { + module_out_path = module_output_path + + include_dirs = [ + "${services_path}/abilitymgr/test/mock/libs/system_ability_mock", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy/include", + ] + + #sources = abilityms_files + sources = [ + "//foundation/aafwk/standard/services/abilitymgr/src/app_scheduler.cpp", + "app_scheduler_test.cpp", + ] + configs = [ + "${services_path}/abilitymgr:abilityms_config", + "${services_path}/abilitymgr/test/mock:aafwk_mock_config", + ] + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + deps = [ + "${innerkits_path}/want:want", + "${services_path}/abilitymgr/test:abilityms_test_source", + "${services_path}/abilitymgr/test/mock/libs/aakit:aakit_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_appmgr_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_bundlemgr_mock", + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/frameworks/kits/ability/native:dummy_classes", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//third_party/googletest:gmock_main", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] +} + +group("unittest") { + testonly = true + + deps = [ ":app_scheduler_test" ] +} diff --git a/tools/services/abilitymgr/test/unittest/phone/app_scheduler_test/app_scheduler_test.cpp b/tools/services/abilitymgr/test/unittest/phone/app_scheduler_test/app_scheduler_test.cpp new file mode 100644 index 00000000000..c0542777d59 --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/app_scheduler_test/app_scheduler_test.cpp @@ -0,0 +1,468 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#define private public +#define protected public +#include "app_scheduler.h" +#undef private +#undef protected + +#include "app_state_call_back_mock.h" +#include "ability_record.h" +#include "element_name.h" +#include "app_process_data.h" + +using namespace testing::ext; +using namespace OHOS::AppExecFwk; + +namespace OHOS { +namespace AAFwk { +class AppSchedulerTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + + static AbilityRequest GenerateAbilityRequest(const std::string &deviceName, const std::string &abilityName, + const std::string &appName, const std::string &bundleName); + + std::shared_ptr appStateMock_ = std::make_shared(); +}; + +void AppSchedulerTest::SetUpTestCase(void) +{} +void AppSchedulerTest::TearDownTestCase(void) +{} +void AppSchedulerTest::SetUp() +{} +void AppSchedulerTest::TearDown() +{} + +AbilityRequest AppSchedulerTest::GenerateAbilityRequest(const std::string &deviceName, const std::string &abilityName, + const std::string &appName, const std::string &bundleName) +{ + ElementName element(deviceName, abilityName, bundleName); + Want want; + want.SetElement(element); + + AbilityInfo abilityInfo; + abilityInfo.applicationName = appName; + ApplicationInfo appinfo; + appinfo.name = appName; + + AbilityRequest abilityRequest; + abilityRequest.want = want; + abilityRequest.abilityInfo = abilityInfo; + abilityRequest.appInfo = appinfo; + + return abilityRequest; +} + +/* + * Feature: AppScheduler + * Function: Init + * SubFunction: NA + * FunctionPoints: AppSchedulerTest Init + * EnvConditions:NA + * CaseDescription: Appstatecallback is nullptr causes init to fail + */ +HWTEST_F(AppSchedulerTest, AppScheduler_oprator_001, TestSize.Level0) +{ + std::shared_ptr appStateMock; + EXPECT_EQ(false, DelayedSingleton::GetInstance()->Init(appStateMock)); +} + +/* + * Feature: AppScheduler + * Function: Init + * SubFunction: NA + * FunctionPoints: AppScheduler Init + * EnvConditions:NA + * CaseDescription: Verify init success + */ +HWTEST_F(AppSchedulerTest, AppScheduler_oprator_002, TestSize.Level0) +{ + EXPECT_EQ(true, DelayedSingleton::GetInstance()->Init(appStateMock_)); +} + +/* + * Feature: AppScheduler + * Function: LoadAbility + * SubFunction: NA + * FunctionPoints: AppScheduler LoadAbility + * EnvConditions:NA + * CaseDescription: Verify the normal process of loadability + */ +HWTEST_F(AppSchedulerTest, AppScheduler_oprator_003, TestSize.Level0) +{ + std::string deviceName = "device"; + std::string abilityName = "FirstAbility"; + std::string appName = "FirstApp"; + std::string bundleName = "com.ix.First"; + auto abilityReq = GenerateAbilityRequest(deviceName, abilityName, appName, bundleName); + auto record = AbilityRecord::CreateAbilityRecord(abilityReq); + auto token = record->GetToken(); + + std::string preDeviceName = "device"; + std::string preAbilityName = "SecondAbility"; + std::string preAppName = "SecondApp"; + std::string preBundleName = "com.ix.Second"; + auto preAbilityReq = GenerateAbilityRequest(preDeviceName, preAbilityName, preAppName, preBundleName); + auto preRecord = AbilityRecord::CreateAbilityRecord(preAbilityReq); + auto pretoken = preRecord->GetToken(); + + EXPECT_EQ((int)ERR_OK, + DelayedSingleton::GetInstance()->LoadAbility( + token, pretoken, record->GetAbilityInfo(), record->GetApplicationInfo())); +} + +/* + * Feature: AppScheduler + * Function: LoadAbility + * SubFunction: NA + * FunctionPoints: AppScheduler LoadAbility + * EnvConditions:NA + * CaseDescription: Verify the fail process of loadability + */ +HWTEST_F(AppSchedulerTest, AppScheduler_oprator_004, TestSize.Level0) +{ + std::string deviceName = "device"; + std::string abilityName = "FirstAbility"; + std::string appName = "FirstApp"; + std::string bundleName = "com.ix.First.Test"; + auto abilityReq = GenerateAbilityRequest(deviceName, abilityName, appName, bundleName); + auto record = AbilityRecord::CreateAbilityRecord(abilityReq); + auto token = record->GetToken(); + + std::string preDeviceName = "device"; + std::string preAbilityName = "SecondAbility"; + std::string preAppName = "SecondApp"; + std::string preBundleName = "com.ix.Second.Test"; + auto preAbilityReq = GenerateAbilityRequest(preDeviceName, preAbilityName, preAppName, preBundleName); + auto preRecord = AbilityRecord::CreateAbilityRecord(preAbilityReq); + auto pretoken = preRecord->GetToken(); + DelayedSingleton::GetInstance()->appMgrClient_ = nullptr; + EXPECT_NE((int)ERR_OK, + DelayedSingleton::GetInstance()->LoadAbility( + token, pretoken, record->GetAbilityInfo(), record->GetApplicationInfo())); +} + +/* + * Feature: AppScheduler + * Function: Init + * SubFunction: NA + * FunctionPoints: AppScheduler Init + * EnvConditions:NA + * CaseDescription: Verify appmgrclient_ Is nullptr causes init to fail + */ +HWTEST_F(AppSchedulerTest, AppScheduler_oprator_005, TestSize.Level0) +{ + EXPECT_EQ(false, DelayedSingleton::GetInstance()->Init(appStateMock_)); +} + +/* + * Feature: AppScheduler + * Function: TerminateAbility + * SubFunction: NA + * FunctionPoints: AppScheduler TerminateAbility + * EnvConditions:NA + * CaseDescription: Verify appmgrclient_ Is nullptr causes TerminateAbility to fail + */ +HWTEST_F(AppSchedulerTest, AppScheduler_oprator_006, TestSize.Level0) +{ + std::string deviceName = "device"; + std::string abilityName = "FirstAbility"; + std::string appName = "FirstApp"; + std::string bundleName = "com.ix.First.Test"; + auto abilityReq = GenerateAbilityRequest(deviceName, abilityName, appName, bundleName); + auto record = AbilityRecord::CreateAbilityRecord(abilityReq); + auto token = record->GetToken(); + + EXPECT_NE((int)ERR_OK, DelayedSingleton::GetInstance()->TerminateAbility(token)); +} + +/* + * Feature: AppScheduler + * Function: TerminateAbility + * SubFunction: NA + * FunctionPoints: AppScheduler TerminateAbility + * EnvConditions:NA + * CaseDescription: Verify appmgrclient_ Is not nullptr causes TerminateAbility to success + */ +HWTEST_F(AppSchedulerTest, AppScheduler_oprator_007, TestSize.Level0) +{ + DelayedSingleton::GetInstance()->appMgrClient_ = std::make_unique(); + + std::string deviceName = "device"; + std::string abilityName = "FirstAbility"; + std::string appName = "FirstApp"; + std::string bundleName = "com.ix.First.Test"; + auto abilityReq = GenerateAbilityRequest(deviceName, abilityName, appName, bundleName); + auto record = AbilityRecord::CreateAbilityRecord(abilityReq); + auto token = record->GetToken(); + + EXPECT_EQ((int)ERR_OK, DelayedSingleton::GetInstance()->TerminateAbility(token)); +} + +/* + * Feature: AppScheduler + * Function: MoveToForground + * SubFunction: NA + * FunctionPoints: AppScheduler MoveToForground + * EnvConditions:NA + * CaseDescription: Verify appmgrclient_ Is null causes movetoforground to be invalid + */ +HWTEST_F(AppSchedulerTest, AppScheduler_oprator_008, TestSize.Level0) +{ + DelayedSingleton::GetInstance()->appMgrClient_ = nullptr; + + std::string deviceName = "device"; + std::string abilityName = "FirstAbility"; + std::string appName = "FirstApp"; + std::string bundleName = "com.ix.First.Test"; + auto abilityReq = GenerateAbilityRequest(deviceName, abilityName, appName, bundleName); + auto record = AbilityRecord::CreateAbilityRecord(abilityReq); + auto token = record->GetToken(); + + DelayedSingleton::GetInstance()->MoveToForground(token); +} + +/* + * Feature: AppScheduler + * Function: MoveToForground + * SubFunction: NA + * FunctionPoints: AppScheduler MoveToForground + * EnvConditions:NA + * CaseDescription: Verify the normal process of movetoforground + */ +HWTEST_F(AppSchedulerTest, AppScheduler_oprator_009, TestSize.Level0) +{ + DelayedSingleton::GetInstance()->appMgrClient_ = std::make_unique(); + + std::string deviceName = "device"; + std::string abilityName = "FirstAbility"; + std::string appName = "FirstApp"; + std::string bundleName = "com.ix.First.Test"; + auto abilityReq = GenerateAbilityRequest(deviceName, abilityName, appName, bundleName); + auto record = AbilityRecord::CreateAbilityRecord(abilityReq); + auto token = record->GetToken(); + + DelayedSingleton::GetInstance()->MoveToForground(token); +} + +/* + * Feature: AppScheduler + * Function: MoveToBackground + * SubFunction: NA + * FunctionPoints: AppScheduler MoveToBackground + * EnvConditions:NA + * CaseDescription: Verify appmgrclient_ Is null causes OnAbilityRequestDone to be invalid + */ +HWTEST_F(AppSchedulerTest, AppScheduler_oprator_010, TestSize.Level0) +{ + DelayedSingleton::GetInstance()->appMgrClient_ = nullptr; + + std::string deviceName = "device"; + std::string abilityName = "FirstAbility"; + std::string appName = "FirstApp"; + std::string bundleName = "com.ix.First"; + auto abilityReq = GenerateAbilityRequest(deviceName, abilityName, appName, bundleName); + auto record = AbilityRecord::CreateAbilityRecord(abilityReq); + auto token = record->GetToken(); + + DelayedSingleton::GetInstance()->MoveToBackground(token); +} + +/* + * Feature: AppScheduler + * Function: MoveToBackground GetAbilityState + * SubFunction: NA + * FunctionPoints: AppScheduler MoveToBackground and GetAbilityState + * EnvConditions:NA + * CaseDescription: Verify appmgrclient_ Is not nullptr causes onabilityrequestdone invoke + */ +HWTEST_F(AppSchedulerTest, AppScheduler_oprator_011, TestSize.Level0) +{ + DelayedSingleton::GetInstance()->appMgrClient_ = std::make_unique(); + std::string deviceName = "device"; + std::string abilityName = "FirstAbility"; + std::string appName = "FirstApp"; + std::string bundleName = "com.ix.First"; + auto abilityReq = GenerateAbilityRequest(deviceName, abilityName, appName, bundleName); + auto record = AbilityRecord::CreateAbilityRecord(abilityReq); + auto token = record->GetToken(); + + DelayedSingleton::GetInstance()->MoveToBackground(token); + EXPECT_EQ( + AppAbilityState::ABILITY_STATE_UNDEFINED, DelayedSingleton::GetInstance()->GetAbilityState()); +} + +/* + * Feature: AppScheduler + * Function: ConvertToAppAbilityState + * SubFunction: NA + * FunctionPoints: AppScheduler ConvertToAppAbilityState + * EnvConditions:NA + * CaseDescription: Verify ConvertToAppAbilityState result + */ +HWTEST_F(AppSchedulerTest, AppScheduler_oprator_012, TestSize.Level0) +{ + EXPECT_EQ(AppAbilityState::ABILITY_STATE_FOREGROUND, + DelayedSingleton::GetInstance()->ConvertToAppAbilityState( + static_cast(AppExecFwk::AbilityState::ABILITY_STATE_FOREGROUND))); + + EXPECT_EQ(AppAbilityState::ABILITY_STATE_BACKGROUND, + DelayedSingleton::GetInstance()->ConvertToAppAbilityState( + static_cast(AppExecFwk::AbilityState::ABILITY_STATE_BACKGROUND))); + + EXPECT_EQ(AppAbilityState::ABILITY_STATE_UNDEFINED, + DelayedSingleton::GetInstance()->ConvertToAppAbilityState( + static_cast(AppExecFwk::AbilityState::ABILITY_STATE_BEGIN))); +} + +/* + * Feature: AppScheduler + * Function: ConvertToAppAbilityState + * SubFunction: NA + * FunctionPoints: AppScheduler ConvertToAppAbilityState + * EnvConditions:NA + * CaseDescription: Verify ConvertToAppAbilityState result + */ +HWTEST_F(AppSchedulerTest, AppScheduler_oprator_013, TestSize.Level0) +{ + DelayedSingleton::GetInstance()->appMgrClient_ = nullptr; + EXPECT_EQ(false, DelayedSingleton::GetInstance()->Init(appStateMock_)); +} + +/* + * Feature: AppScheduler + * Function: AbilityBehaviorAnalysis + * SubFunction: NA + * FunctionPoints: AppScheduler AbilityBehaviorAnalysis + * EnvConditions:NA + * CaseDescription: Verify appmgrclient_ Is not nullptr causes AbilityBehaviorAnalysis to success + */ +HWTEST_F(AppSchedulerTest, AppScheduler_oprator_014, TestSize.Level0) +{ + DelayedSingleton::GetInstance()->appMgrClient_ = std::make_unique(); + + std::string deviceName = "device"; + std::string abilityName = "FirstAbility"; + std::string appName = "FirstApp"; + std::string bundleName = "com.ix.First"; + auto abilityReq = GenerateAbilityRequest(deviceName, abilityName, appName, bundleName); + auto record = AbilityRecord::CreateAbilityRecord(abilityReq); + auto token = record->GetToken(); + const int32_t visibility = 1; + const int32_t perceptibility = 1; + const int32_t connectionState = 1; + + DelayedSingleton::GetInstance()->AbilityBehaviorAnalysis( + token, nullptr, visibility, perceptibility, connectionState); + + auto pretoken = record->GetToken(); + DelayedSingleton::GetInstance()->AbilityBehaviorAnalysis( + token, pretoken, visibility, perceptibility, connectionState); + + const int32_t visibility_1 = 0; + DelayedSingleton::GetInstance()->AbilityBehaviorAnalysis( + token, token, visibility_1, perceptibility, connectionState); + + const int32_t perceptibility_1 = 0; + DelayedSingleton::GetInstance()->AbilityBehaviorAnalysis( + token, token, visibility_1, perceptibility_1, connectionState); + + const int32_t connectionState_1 = 0; + DelayedSingleton::GetInstance()->AbilityBehaviorAnalysis( + token, token, visibility_1, perceptibility_1, connectionState_1); +} + +/* + * Feature: AppScheduler + * Function: AbilityBehaviorAnalysis + * SubFunction: NA + * FunctionPoints: AppScheduler AbilityBehaviorAnalysis + * EnvConditions:NA + * CaseDescription: Verify appmgrclient_ Is nullptr causes AbilityBehaviorAnalysis to fail + */ +HWTEST_F(AppSchedulerTest, AppScheduler_oprator_015, TestSize.Level0) +{ + DelayedSingleton::GetInstance()->appMgrClient_ = nullptr; + + std::string deviceName = "device"; + std::string abilityName = "FirstAbility"; + std::string appName = "FirstApp"; + std::string bundleName = "com.ix.First"; + auto abilityReq = GenerateAbilityRequest(deviceName, abilityName, appName, bundleName); + auto record = AbilityRecord::CreateAbilityRecord(abilityReq); + auto token = record->GetToken(); + const int32_t visibility = 0; + const int32_t perceptibility = 1; + const int32_t connectionState = 1; + + DelayedSingleton::GetInstance()->AbilityBehaviorAnalysis( + token, nullptr, visibility, perceptibility, connectionState); +} + +/* + * Feature: AppScheduler + * Function: KillProcessByAbilityToken + * SubFunction: NA + * FunctionPoints: AppScheduler KillProcessByAbilityToken + * EnvConditions:NA + * CaseDescription: Verify appmgrclient_ Is not nullptr causes KillProcessByAbilityToken to success + */ +HWTEST_F(AppSchedulerTest, AppScheduler_oprator_016, TestSize.Level0) +{ + DelayedSingleton::GetInstance()->appMgrClient_ = std::make_unique(); + + std::string deviceName = "device"; + std::string abilityName = "FirstAbility"; + std::string appName = "FirstApp"; + std::string bundleName = "com.ix.First"; + auto abilityReq = GenerateAbilityRequest(deviceName, abilityName, appName, bundleName); + auto record = AbilityRecord::CreateAbilityRecord(abilityReq); + auto token = record->GetToken(); + + DelayedSingleton::GetInstance()->KillProcessByAbilityToken(token); +} + +/* + * Feature: AppScheduler + * Function: KillProcessByAbilityToken + * SubFunction: NA + * FunctionPoints: AppScheduler KillProcessByAbilityToken + * EnvConditions:NA + * CaseDescription: Verify appmgrclient_ Is nullptr causes KillProcessByAbilityToken to fail + */ +HWTEST_F(AppSchedulerTest, AppScheduler_oprator_017, TestSize.Level0) +{ + DelayedSingleton::GetInstance()->appMgrClient_ = nullptr; + + std::string deviceName = "device"; + std::string abilityName = "FirstAbility"; + std::string appName = "FirstApp"; + std::string bundleName = "com.ix.First"; + auto abilityReq = GenerateAbilityRequest(deviceName, abilityName, appName, bundleName); + auto record = AbilityRecord::CreateAbilityRecord(abilityReq); + auto token = record->GetToken(); + + DelayedSingleton::GetInstance()->KillProcessByAbilityToken(token); +} +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/abilitymgr/test/unittest/phone/app_scheduler_test/app_state_call_back_mock.h b/tools/services/abilitymgr/test/unittest/phone/app_scheduler_test/app_state_call_back_mock.h new file mode 100644 index 00000000000..e7a9d03f0d5 --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/app_scheduler_test/app_state_call_back_mock.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ABILITY_UNITTEST_APP_SCHEDULE_CALL_BACK_MOCK_H +#define ABILITY_UNITTEST_APP_SCHEDULE_CALL_BACK_MOCK_H + +#include +#include +#include +#include "app_scheduler.h" + +namespace OHOS { +namespace AAFwk { +class AppStateCallbackMock : public AppStateCallback { +public: + AppStateCallbackMock() + {} + virtual ~AppStateCallbackMock() + {} + MOCK_METHOD2(OnAbilityRequestDone, void(const sptr &, const int32_t)); + MOCK_METHOD1(OnAppStateChanged, void(const AppInfo &info)); +}; +} // namespace AAFwk +} // namespace OHOS + +#endif \ No newline at end of file diff --git a/tools/services/abilitymgr/test/unittest/phone/configuration_holder_test/BUILD.gn b/tools/services/abilitymgr/test/unittest/phone/configuration_holder_test/BUILD.gn new file mode 100644 index 00000000000..a70706426ec --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/configuration_holder_test/BUILD.gn @@ -0,0 +1,69 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/test.gni") +import("//foundation/aafwk/standard/aafwk.gni") + +module_output_path = "aafwk_standard/abilitymgr" + +ohos_unittest("configuration_holder_test") { + module_out_path = module_output_path + + include_dirs = [ + "${services_path}/abilitymgr/test/mock/libs/system_ability_mock", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy/include", + "//foundation/aafwk/standard/services/abilitymgr/test/mock/libs/ability_scheduler_mock", + "//foundation/aafwk/standard/services/abilitymgr/test/mock/include", + ] + + sources = [ + "//foundation/aafwk/standard/services/abilitymgr/test/mock/libs/appexecfwk_core/src/appmgr/mock_app_scheduler.cpp", + "configuration_holder_test.cpp", # add mock file + ] + + configs = [ + "${services_path}/abilitymgr:abilityms_config", + "${services_path}/abilitymgr/test/mock:aafwk_mock_config", + ] + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + deps = [ + "${innerkits_path}/want:want", + "${services_path}/abilitymgr/test:abilityms_test_source", + "${services_path}/abilitymgr/test/mock/libs/aakit:aakit_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_appmgr_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_bundlemgr_mock", + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/frameworks/kits/ability/native:dummy_classes", + "//foundation/aafwk/standard/interfaces/innerkits/base:base", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//third_party/googletest:gmock_main", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] +} + +group("unittest") { + testonly = true + + deps = [ ":configuration_holder_test" ] +} diff --git a/tools/services/abilitymgr/test/unittest/phone/configuration_holder_test/configuration_holder_test.cpp b/tools/services/abilitymgr/test/unittest/phone/configuration_holder_test/configuration_holder_test.cpp new file mode 100644 index 00000000000..6d9c642f813 --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/configuration_holder_test/configuration_holder_test.cpp @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#define private public +#define protected public +#include "configuration_holder.h" +#undef private +#undef protected + +#include "mock_configuration_holder.h" + +using namespace testing::ext; + +namespace OHOS { +namespace AAFwk { + +class ConfigurationHolderTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + + std::shared_ptr mockConfigurationHolder_; +}; + +void ConfigurationHolderTest::SetUpTestCase(void) +{} +void ConfigurationHolderTest::TearDownTestCase(void) +{} +void ConfigurationHolderTest::SetUp(void) +{ + mockConfigurationHolder_ = std::make_shared(); +} +void ConfigurationHolderTest::TearDown(void) +{} + +/* + * Feature: ConfigurationHolder + * Function: UpdateConfiguration + * SubFunction: NA + * FunctionPoints: NA + * EnvConditions:NA + * CaseDescription: Update Configuration + */ +HWTEST_F(ConfigurationHolderTest, UpdateConfiguration_001, TestSize.Level1) +{ + std::string name = "layout"; + auto config = std::make_shared(name); + auto config1 = std::make_shared(); + mockConfigurationHolder_->baseConfiguration_ = config1; + mockConfigurationHolder_->baseConfiguration_->testInfostr_ = "orientation"; + mockConfigurationHolder_->UpdateConfiguration(config); + + EXPECT_EQ(config, mockConfigurationHolder_->GetConfiguration()); +} + +/* + * Feature: ConfigurationHolder + * Function: ProcessConfigurationChange + * SubFunction: NA + * FunctionPoints: NA + * EnvConditions:NA + * CaseDescription: Process Configuration Change + */ +HWTEST_F(ConfigurationHolderTest, ProcessConfigurationChange_001, TestSize.Level1) +{ + mockConfigurationHolder_->baseConfiguration_ = nullptr; + EXPECT_EQ(false, mockConfigurationHolder_->ProcessConfigurationChange()); +} + +/* + * Feature: ConfigurationHolder + * Function: ProcessConfigurationChange + * SubFunction: NA + * FunctionPoints: NA + * EnvConditions:NA + * CaseDescription: Process Configuration Change + */ +HWTEST_F(ConfigurationHolderTest, ProcessConfigurationChange_002, TestSize.Level1) +{ + std::string name = "layout"; + auto config = std::make_shared(name); + mockConfigurationHolder_->baseConfiguration_ = config; + mockConfigurationHolder_->baseConfiguration_->testInfostr_ = "orientation"; + EXPECT_EQ(false, mockConfigurationHolder_->ProcessConfigurationChange()); +} + +/* + * Feature: ConfigurationHolder + * Function: ProcessConfigurationChangeInner + * SubFunction: Process Configuration Change Inner + * FunctionPoints: NA + * EnvConditions:NA + * CaseDescription: Process Configuration Change Inner + */ +HWTEST_F(ConfigurationHolderTest, ProcessConfigurationChangeInner_001, TestSize.Level1) +{ + std::string name = "layout"; + auto config = std::make_shared(name); + auto config1 = std::make_shared(); + mockConfigurationHolder_->baseConfiguration_ = config1; + mockConfigurationHolder_->baseConfiguration_->testInfostr_ = "orientation"; + EXPECT_EQ(false, mockConfigurationHolder_->ProcessConfigurationChangeInner(config)); + EXPECT_EQ(config, mockConfigurationHolder_->GetConfiguration()); +} + +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/abilitymgr/test/unittest/phone/connection_record_test/BUILD.gn b/tools/services/abilitymgr/test/unittest/phone/connection_record_test/BUILD.gn new file mode 100644 index 00000000000..48bbaa526e2 --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/connection_record_test/BUILD.gn @@ -0,0 +1,66 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/test.gni") +import("//foundation/aafwk/standard/aafwk.gni") + +module_output_path = "aafwk_standard/abilitymgr" + +ohos_unittest("connection_record_test") { + module_out_path = module_output_path + + include_dirs = [ + "${services_path}/abilitymgr/test/mock/libs/system_ability_mock", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy/include", + ] + + sources = [ + "//foundation/aafwk/standard/services/abilitymgr/test/mock/libs/appexecfwk_core/src/appmgr/mock_app_scheduler.cpp", + "connection_record_test.cpp", # add mock file + ] + + configs = [ + "${services_path}/abilitymgr:abilityms_config", + "${services_path}/abilitymgr/test/mock:aafwk_mock_config", + ] + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + deps = [ + "${innerkits_path}/want:want", + "${services_path}/abilitymgr/test:abilityms_test_source", + "${services_path}/abilitymgr/test/mock/libs/aakit:aakit_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_appmgr_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_bundlemgr_mock", + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/frameworks/kits/ability/native:dummy_classes", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//third_party/googletest:gmock_main", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] +} + +group("unittest") { + testonly = true + + deps = [ ":connection_record_test" ] +} diff --git a/tools/services/abilitymgr/test/unittest/phone/connection_record_test/connection_record_test.cpp b/tools/services/abilitymgr/test/unittest/phone/connection_record_test/connection_record_test.cpp new file mode 100644 index 00000000000..651571799fe --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/connection_record_test/connection_record_test.cpp @@ -0,0 +1,329 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#define private public +#define protected public +#include "ability_record.h" +#include "connection_record.h" +#undef private +#undef protected + +#include "app_process_data.h" +#include "ability_manager_errors.h" +#include "ability_connect_callback_stub.h" +#include "ability_scheduler.h" +#include "ability_record_info.h" + +using namespace testing::ext; +using namespace OHOS::AppExecFwk; + +namespace OHOS { +namespace AAFwk { +class AbilityConnectCallbackMock : public AbilityConnectionStub { +public: + AbilityConnectCallbackMock() + {} + virtual ~AbilityConnectCallbackMock() + {} + + MOCK_METHOD3(OnAbilityConnectDone, void(const ElementName &, const OHOS::sptr &, int)); + MOCK_METHOD2(OnAbilityDisconnectDone, void(const ElementName &, int)); +}; + +class ConnectionRecordTest : public testing::TestWithParam { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + + AbilityRequest GenerateAbilityRequest(const std::string &deviceName, const std::string &abilityName, + const std::string &appName, const std::string &bundleName); + + std::shared_ptr connectionRecord_{nullptr}; + OHOS::sptr callback_{nullptr}; + std::shared_ptr service_{nullptr}; +}; + +AbilityRequest ConnectionRecordTest::GenerateAbilityRequest(const std::string &deviceName, + const std::string &abilityName, const std::string &appName, const std::string &bundleName) +{ + ElementName element(deviceName, bundleName, abilityName); + Want want; + want.SetElement(element); + + AbilityInfo abilityInfo; + abilityInfo.applicationName = appName; + abilityInfo.bundleName = bundleName; + abilityInfo.type = AbilityType::SERVICE; + ApplicationInfo appinfo; + appinfo.name = appName; + + AbilityRequest abilityRequest; + abilityRequest.want = want; + abilityRequest.abilityInfo = abilityInfo; + abilityRequest.appInfo = appinfo; + + return abilityRequest; +} + +void ConnectionRecordTest::SetUpTestCase(void) +{} +void ConnectionRecordTest::TearDownTestCase(void) +{} + +void ConnectionRecordTest::SetUp(void) +{ + callback_ = new AbilityConnectCallbackMock(); + + std::string deviceName = "device"; + std::string abilityName = "ServiceAbility"; + std::string appName = "hiservcie"; + std::string bundleName = "com.ix.hiservcie"; + AbilityRequest abilityRequest = GenerateAbilityRequest(deviceName, abilityName, appName, bundleName); + service_ = AbilityRecord::CreateAbilityRecord(abilityRequest); + connectionRecord_ = std::make_shared(service_->GetToken(), service_, callback_); +} + +void ConnectionRecordTest::TearDown(void) +{ + connectionRecord_.reset(); +} + +bool IsExist(const std::string &state) +{ + return std::string::npos != state.find("com.ix.hiservcie"); +} + +/* + * Feature: ConnectionRecord + * Function: SetConnectState and GetConnectState + * SubFunction: NA + * FunctionPoints: SetConnectState and GetConnectState + * EnvConditions:NA + * CaseDescription: Verify set and get + */ +HWTEST_F(ConnectionRecordTest, AaFwk_ConnectionRecord_001, TestSize.Level1) +{ + connectionRecord_->SetConnectState(ConnectionState::CONNECTED); + EXPECT_EQ(connectionRecord_->GetConnectState(), ConnectionState::CONNECTED); +} + +/* + * Feature: ConnectionRecord + * Function: GetToken + * SubFunction: NA + * FunctionPoints: GetToken + * EnvConditions:NA + * CaseDescription: Verify that the tokens are equal + */ +HWTEST_F(ConnectionRecordTest, AaFwk_ConnectionRecord_002, TestSize.Level1) +{ + EXPECT_EQ(connectionRecord_->GetToken().GetRefPtr(), service_->GetToken().GetRefPtr()); +} + +/* + * Feature: ConnectionRecord + * Function: GetAbilityRecord + * SubFunction: NA + * FunctionPoints: GetAbilityRecord + * EnvConditions:NA + * CaseDescription: Verify that the ability record are equal + */ +HWTEST_F(ConnectionRecordTest, AaFwk_ConnectionRecord_003, TestSize.Level1) +{ + EXPECT_EQ(connectionRecord_->GetAbilityRecord(), service_); +} + +/* + * Feature: ConnectionRecord + * Function: GetAbilityConnectCallback + * SubFunction: NA + * FunctionPoints: GetAbilityConnectCallback + * EnvConditions:NA + * CaseDescription: Verify that the call back are equal + */ +HWTEST_F(ConnectionRecordTest, AaFwk_ConnectionRecord_004, TestSize.Level1) +{ + EXPECT_EQ(connectionRecord_->GetAbilityConnectCallback(), iface_cast(callback_)); +} + +/* + * Feature: ConnectionRecord + * Function: DisconnectAbility + * SubFunction: NA + * FunctionPoints: DisconnectAbility + * EnvConditions:NA + * CaseDescription: 1.Connection state is not connected, DisconnectAbility failed + * 2.Verify the correct process of disconnectability + */ +HWTEST_F(ConnectionRecordTest, AaFwk_ConnectionRecord_005, TestSize.Level1) +{ + auto result = connectionRecord_->DisconnectAbility(); + EXPECT_EQ(result, INVALID_CONNECTION_STATE); + + connectionRecord_->SetConnectState(ConnectionState::CONNECTED); + + result = connectionRecord_->DisconnectAbility(); + EXPECT_EQ(result, ERR_OK); + EXPECT_EQ(connectionRecord_->GetConnectState(), ConnectionState::DISCONNECTED); +} + +/* + * Feature: ConnectionRecord + * Function: CompleteConnect + * SubFunction: NA + * FunctionPoints: CompleteConnect + * EnvConditions:NA + * CaseDescription: Verify the correct process of completeconnect + */ +HWTEST_F(ConnectionRecordTest, AaFwk_ConnectionRecord_006, TestSize.Level1) +{ + EXPECT_CALL(*callback_, OnAbilityConnectDone(::testing::_, ::testing::_, ::testing::_)).Times(1); + + connectionRecord_->CompleteConnect(ERR_OK); + EXPECT_EQ(connectionRecord_->GetConnectState(), ConnectionState::CONNECTED); + EXPECT_EQ(service_->GetAbilityState(), AAFwk::AbilityState::ACTIVE); +} + +/* + * Feature: ConnectionRecord + * Function: CompleteDisconnect + * SubFunction: NA + * FunctionPoints: CompleteDisconnect + * EnvConditions:NA + * CaseDescription: Verify the correct process of complete disconnect + */ +HWTEST_F(ConnectionRecordTest, AaFwk_ConnectionRecord_007, TestSize.Level1) +{ + EXPECT_CALL(*callback_, OnAbilityDisconnectDone(::testing::_, ::testing::_)).Times(1); + + connectionRecord_->CompleteDisconnect(ERR_OK); + EXPECT_EQ(connectionRecord_->GetConnectState(), ConnectionState::DISCONNECTED); +} + +/* + * Feature: ConnectionRecord + * Function: ScheduleDisconnectAbilityDone + * SubFunction: NA + * FunctionPoints: ScheduleDisconnectAbilityDone + * EnvConditions:NA + * CaseDescription: 1.Connection state is not DISCONNECTING, Onabilitydisconnectdone is not called + * 2.Connection state is DISCONNECTING, Call onabilitydisconnect done + */ +HWTEST_F(ConnectionRecordTest, AaFwk_ConnectionRecord_008, TestSize.Level1) +{ + EXPECT_CALL(*callback_, OnAbilityDisconnectDone(::testing::_, ::testing::_)).Times(1); + + connectionRecord_->SetConnectState(ConnectionState::CONNECTED); + connectionRecord_->ScheduleDisconnectAbilityDone(); + + connectionRecord_->SetConnectState(ConnectionState::DISCONNECTING); + connectionRecord_->ScheduleDisconnectAbilityDone(); +} + +/* + * Feature: ConnectionRecord + * Function: ScheduleConnectAbilityDone + * SubFunction: NA + * FunctionPoints: ScheduleConnectAbilityDone + * EnvConditions:NA + * CaseDescription: 1.Connection state is not CONNECTING, OnAbilityConnectDone is not called + * 2.Connection state is CONNECTING, Call OnAbilityConnectDone done + */ +HWTEST_F(ConnectionRecordTest, AaFwk_ConnectionRecord_009, TestSize.Level1) +{ + EXPECT_CALL(*callback_, OnAbilityConnectDone(::testing::_, ::testing::_, ::testing::_)).Times(1); + + connectionRecord_->SetConnectState(ConnectionState::DISCONNECTING); + connectionRecord_->ScheduleConnectAbilityDone(); + + connectionRecord_->SetConnectState(ConnectionState::CONNECTING); + connectionRecord_->ScheduleConnectAbilityDone(); +} + +/* + * Feature: ConnectionRecord + * Function: GetRecordId + * SubFunction: NA + * FunctionPoints: GetRecordId + * EnvConditions:NA + * CaseDescription: Verify that getrecordids are equal + */ +HWTEST_F(ConnectionRecordTest, AaFwk_ConnectionRecord_010, TestSize.Level1) +{ + EXPECT_EQ(connectionRecord_->GetRecordId(), 9); +} + +/* + * Feature: ConnectionRecord + * Function: GetAbilityConnectCallback + * SubFunction: NA + * FunctionPoints: GetAbilityConnectCallback + * EnvConditions:NA + * CaseDescription: Verify that getabilityconnectcallback is nullptr + */ +HWTEST_F(ConnectionRecordTest, AaFwk_ConnectionRecord_011, TestSize.Level1) +{ + connectionRecord_->ClearConnCallBack(); + EXPECT_EQ(connectionRecord_->GetAbilityConnectCallback().GetRefPtr(), nullptr); +} + +/* + * Feature: ConnectionRecord + * Function: ConvertConnectionState + * SubFunction: NA + * FunctionPoints: ConvertConnectionState + * EnvConditions:NA + * CaseDescription: Verify ConvertConnectionState results + */ +HWTEST_F(ConnectionRecordTest, AaFwk_ConnectionRecord_012, TestSize.Level1) +{ + auto res = connectionRecord_->ConvertConnectionState(ConnectionState::INIT); + EXPECT_EQ(res, "INIT"); + res = connectionRecord_->ConvertConnectionState(ConnectionState::CONNECTING); + EXPECT_EQ(res, "CONNECTING"); + res = connectionRecord_->ConvertConnectionState(ConnectionState::CONNECTED); + EXPECT_EQ(res, "CONNECTED"); + res = connectionRecord_->ConvertConnectionState(ConnectionState::DISCONNECTING); + EXPECT_EQ(res, "DISCONNECTING"); + res = connectionRecord_->ConvertConnectionState(ConnectionState::DISCONNECTED); + EXPECT_EQ(res, "DISCONNECTED"); +} + +/* + * Feature: ConnectionRecord + * Function: Dump + * SubFunction: NA + * FunctionPoints: Dump + * EnvConditions:NA + * CaseDescription: Verify dump results + */ +HWTEST_F(ConnectionRecordTest, AaFwk_ConnectionRecord_013, TestSize.Level1) +{ + std::vector info; + connectionRecord_->Dump(info); + + for (auto &it : info) { + GTEST_LOG_(INFO) << it; + } + + EXPECT_NE(info.end(), std::find_if(info.begin(), info.end(), IsExist)); +} +} // namespace AAFwk +} // namespace OHOS diff --git a/tools/services/abilitymgr/test/unittest/phone/data_ability_manager_test/BUILD.gn b/tools/services/abilitymgr/test/unittest/phone/data_ability_manager_test/BUILD.gn new file mode 100644 index 00000000000..f1afd543644 --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/data_ability_manager_test/BUILD.gn @@ -0,0 +1,75 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/test.gni") +import("//foundation/aafwk/standard/aafwk.gni") + +module_output_path = "aafwk_standard/abilitymgr" + +ohos_unittest("data_ability_manager_test") { + module_out_path = module_output_path + + include_dirs = [ + "${services_path}/abilitymgr/test/mock/include", + "${services_path}/abilitymgr/test/mock/libs/system_ability_mock", + "${services_path}/abilitymgr/test/mock/libs/ability_scheduler_mock", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy/include", + + # "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base/include", + "//foundation/aafwk/standard/interfaces/innerkits/ability_manager/include", + "//foundation/aafwk/standard/frameworks/kits/ability/native/include", + "//foundation/aafwk/standard/services/common/include", + ] + + sources = [ + "//foundation/aafwk/standard/services/abilitymgr/src/app_scheduler.cpp", + "data_ability_manager_test.cpp", # add mock file + ] + + configs = [ + "${services_path}/abilitymgr:abilityms_config", + "//foundation/aafwk/standard/interfaces/innerkits/base:base_public_config", + "${services_path}/abilitymgr/test/mock:aafwk_mock_config", + ] + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + deps = [ + "${innerkits_path}/want:want", + "${services_path}/abilitymgr/test:abilityms_test_source", + "${services_path}/abilitymgr/test/mock/libs/aakit:aakit_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_appmgr_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_bundlemgr_mock", + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/frameworks/kits/ability/native:dummy_classes", + + #"//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//third_party/googletest:gmock_main", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] +} + +group("unittest") { + testonly = true + + deps = [ ":data_ability_manager_test" ] +} diff --git a/tools/services/abilitymgr/test/unittest/phone/data_ability_manager_test/data_ability_manager_test.cpp b/tools/services/abilitymgr/test/unittest/phone/data_ability_manager_test/data_ability_manager_test.cpp new file mode 100644 index 00000000000..3c5df9c1758 --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/data_ability_manager_test/data_ability_manager_test.cpp @@ -0,0 +1,482 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#define private public +#define protected public +#include "data_ability_manager.h" +#include "app_scheduler.h" +#undef private +#undef protected + +#include "ability_scheduler_mock.h" +#include "mock_app_mgr_client.h" + +using namespace testing::ext; +using namespace testing; +using namespace std::chrono; + +namespace OHOS { +namespace AAFwk { +class DataAbilityManagerTest : public testing::TestWithParam { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + +protected: + sptr abilitySchedulerMock_{nullptr}; + AbilityRequest abilityRequest_{}; + std::shared_ptr abilityRecordClient_{nullptr}; + OHOS::AAFwk::AbilityState abilityState_{}; +}; + +void DataAbilityManagerTest::SetUpTestCase(void) +{} +void DataAbilityManagerTest::TearDownTestCase(void) +{} + +void DataAbilityManagerTest::SetUp(void) +{ + if (abilitySchedulerMock_ == nullptr) { + abilitySchedulerMock_ = new AbilitySchedulerMock(); + } + + abilityRequest_.appInfo.bundleName = "com.test.data_ability"; + abilityRequest_.appInfo.name = "com.test.data_ability"; + abilityRequest_.abilityInfo.name = "DataAbilityHiworld"; + abilityRequest_.abilityInfo.type = AbilityType::DATA; + abilityRequest_.abilityInfo.bundleName = "com.test.data_ability"; + abilityRequest_.abilityInfo.deviceId = "device"; + + if (abilityRecordClient_ == nullptr) { + OHOS::AppExecFwk::AbilityInfo abilityInfo; + abilityInfo.name = "DataAbilityClient"; + abilityInfo.type = AbilityType::PAGE; + abilityInfo.bundleName = "com.test.request"; + abilityInfo.deviceId = "device"; + OHOS::AppExecFwk::ApplicationInfo applicationInfo; + applicationInfo.bundleName = "com.test.request"; + applicationInfo.name = "com.test.request"; + const Want want; + abilityRecordClient_ = std::make_shared(want, abilityInfo, applicationInfo); + abilityRecordClient_->Init(); + } + abilityState_ = INITIAL; +} + +void DataAbilityManagerTest::TearDown(void) +{ + abilitySchedulerMock_.clear(); +} + +/* + * Feature: AbilityManager + * Function: DataAbility + * SubFunction: Normal Flow + * FunctionPoints: DataAbilityManager simple flow. + * EnvConditions: Can run ohos test framework + * CaseDescription: Verify the DataAbilityManager simple flow. + */ +HWTEST_F(DataAbilityManagerTest, AaFwk_DataAbilityManager_Flow_001, TestSize.Level1) +{ + HILOG_INFO("AaFwk_DataAbilityManager_Flow_001 start."); + + std::shared_ptr dataAbilityManager = std::make_shared(); + std::unique_ptr mockAppMgrClient = std::make_unique(); + + // mock AppScheduler + DelayedSingleton::GetInstance()->appMgrClient_ = std::move(mockAppMgrClient); + + auto func = [this, &dataAbilityManager]() { + usleep(200 * 1000); // 200 ms + sptr tokenAsyn = + (reinterpret_cast(DelayedSingleton::GetInstance()->appMgrClient_.get())) + ->GetToken(); + dataAbilityManager->AttachAbilityThread(abilitySchedulerMock_, tokenAsyn); + dataAbilityManager->AbilityTransitionDone(tokenAsyn, ACTIVE); + }; + + std::thread(func).detach(); + EXPECT_CALL(*abilitySchedulerMock_, ScheduleAbilityTransaction(_, _)).Times(1); + EXPECT_NE(dataAbilityManager->Acquire(abilityRequest_, true, abilityRecordClient_->GetToken(), false), nullptr); + + sptr token = + (reinterpret_cast(DelayedSingleton::GetInstance()->appMgrClient_.get())) + ->GetToken(); + std::shared_ptr abilityRecord = Token::GetAbilityRecordByToken(token); + EXPECT_TRUE(abilityRecord); + + // existing ability record + EXPECT_NE(dataAbilityManager->GetAbilityRecordByToken(token), nullptr); + EXPECT_NE(dataAbilityManager->GetAbilityRecordByScheduler(abilitySchedulerMock_), nullptr); + EXPECT_NE(dataAbilityManager->GetAbilityRecordById(abilityRecord->GetRecordId()), nullptr); + + // ability died, clear data ability record + dataAbilityManager->OnAbilityDied(abilityRecord); + + // ability has released + EXPECT_EQ(dataAbilityManager->GetAbilityRecordByToken(token), nullptr); + EXPECT_EQ(dataAbilityManager->GetAbilityRecordByScheduler(abilitySchedulerMock_), nullptr); + EXPECT_EQ(dataAbilityManager->GetAbilityRecordById(abilityRecord->GetRecordId()), nullptr); + + HILOG_INFO("AaFwk_DataAbilityManager_Flow_001 end."); +} + +/* + * Feature: AbilityManager + * Function: DataAbility + * SubFunction: Acquire + * FunctionPoints: The parameter of function Acquire. + * EnvConditions: Can run ohos test framework + * CaseDescription: Verify function Acquire parameter is nullptr. + */ +HWTEST_F(DataAbilityManagerTest, AaFwk_DataAbilityManager_Acquire_001, TestSize.Level1) +{ + HILOG_INFO("AaFwk_DataAbilityManager_Acquire_001 start."); + + std::unique_ptr dataAbilityManager = std::make_unique(); + + EXPECT_EQ(dataAbilityManager->Acquire(abilityRequest_, true, nullptr, false), nullptr); + + HILOG_INFO("AaFwk_DataAbilityManager_Acquire_001 end."); +} + +/* + * Feature: AbilityManager + * Function: DataAbility + * SubFunction: Acquire + * FunctionPoints: The parameter of function Acquire. + * EnvConditions: Can run ohos test framework + * CaseDescription: Verify function Acquire parameter ability type is not data + */ +HWTEST_F(DataAbilityManagerTest, AaFwk_DataAbilityManager_Acquire_002, TestSize.Level1) +{ + HILOG_INFO("AaFwk_DataAbilityManager_Acquire_002 start."); + + std::unique_ptr dataAbilityManager = std::make_unique(); + + // page ability type + abilityRequest_.abilityInfo.type = AbilityType::PAGE; + EXPECT_EQ(dataAbilityManager->Acquire(abilityRequest_, true, abilityRecordClient_->GetToken(), false), nullptr); + + HILOG_INFO("AaFwk_DataAbilityManager_Acquire_002 end."); +} + +/* + * Feature: AbilityManager + * Function: DataAbility + * SubFunction: Acquire + * FunctionPoints: The parameter of function Acquire. + * EnvConditions: Can run ohos test framework + * CaseDescription: Verify function Acquire parameter appinfo bundlename empty + */ +HWTEST_F(DataAbilityManagerTest, AaFwk_DataAbilityManager_Acquire_003, TestSize.Level1) +{ + HILOG_INFO("AaFwk_DataAbilityManager_Acquire_003 start."); + + std::unique_ptr dataAbilityManager = std::make_unique(); + + // appinfo bundle name empty + abilityRequest_.appInfo.bundleName = ""; + EXPECT_EQ(dataAbilityManager->Acquire(abilityRequest_, true, abilityRecordClient_->GetToken(), false), nullptr); + + HILOG_INFO("AaFwk_DataAbilityManager_Acquire_003 end."); +} + +/* + * Feature: AbilityManager + * Function: DataAbility + * SubFunction: Acquire + * FunctionPoints: The parameter of function Acquire. + * EnvConditions: Can run ohos test framework + * CaseDescription: Verify function Acquire parameter ability name empty + */ +HWTEST_F(DataAbilityManagerTest, AaFwk_DataAbilityManager_Acquire_004, TestSize.Level1) +{ + HILOG_INFO("AaFwk_DataAbilityManager_Acquire_004 start."); + + std::unique_ptr dataAbilityManager = std::make_unique(); + + // ability name empty + abilityRequest_.abilityInfo.name = ""; + EXPECT_EQ(dataAbilityManager->Acquire(abilityRequest_, true, abilityRecordClient_->GetToken(), false), nullptr); + + HILOG_INFO("AaFwk_DataAbilityManager_Acquire_004 end."); +} + +/* + * Feature: AbilityManager + * Function: DataAbility + * SubFunction: Acquire + * FunctionPoints: The parameter of function Acquire. + * EnvConditions: Can run ohos test framework + * CaseDescription: Verify function Acquire parameter same bundle name and ability name + */ +HWTEST_F(DataAbilityManagerTest, AaFwk_DataAbilityManager_Acquire_005, TestSize.Level1) +{ + HILOG_INFO("AaFwk_DataAbilityManager_Acquire_005 start."); + + std::unique_ptr dataAbilityManager = std::make_unique(); + + // same bundle name and ability name + OHOS::AppExecFwk::AbilityInfo abilityInfo; + abilityInfo.name = abilityRequest_.abilityInfo.name; + abilityInfo.type = AbilityType::PAGE; + OHOS::AppExecFwk::ApplicationInfo applicationInfo; + applicationInfo.bundleName = abilityRequest_.appInfo.bundleName; + applicationInfo.name = abilityRequest_.appInfo.name; + const Want want; + std::shared_ptr abilityRecordClient = std::make_shared(want, abilityInfo, applicationInfo); + abilityRecordClient->Init(); + + EXPECT_EQ(dataAbilityManager->Acquire(abilityRequest_, true, abilityRecordClient->GetToken(), false), nullptr); + + HILOG_INFO("AaFwk_DataAbilityManager_Acquire_005 end."); +} + +/* + * Feature: AbilityManager + * Function: DataAbility + * SubFunction: Acquire + * FunctionPoints: The parameter of function Acquire. + * EnvConditions: Can run ohos test framework + * CaseDescription: Verify function Acquire waitforloaded timeout. + */ +HWTEST_F(DataAbilityManagerTest, AaFwk_DataAbilityManager_Acquire_006, TestSize.Level1) +{ + HILOG_INFO("AaFwk_DataAbilityManager_Acquire_006 start."); + + std::unique_ptr dataAbilityManager = std::make_unique(); + + EXPECT_EQ(dataAbilityManager->Acquire(abilityRequest_, true, abilityRecordClient_->GetToken(), false), nullptr); + + HILOG_INFO("AaFwk_DataAbilityManager_Acquire_006 end."); +} + +/* + * Feature: AbilityManager + * Function: DataAbility + * SubFunction: Release + * FunctionPoints: The parameter of function Release. + * EnvConditions: Can run ohos test framework + * CaseDescription: Verify function Release client is nullptr + */ +HWTEST_F(DataAbilityManagerTest, AaFwk_DataAbilityManager_Release_001, TestSize.Level1) +{ + HILOG_INFO("AaFwk_DataAbilityManager_Release_001 start."); + + std::unique_ptr dataAbilityManager = std::make_unique(); + + EXPECT_EQ(dataAbilityManager->Release(abilitySchedulerMock_, nullptr, false), ERR_NULL_OBJECT); + + HILOG_INFO("AaFwk_DataAbilityManager_Release_001 end."); +} + +/* + * Feature: AbilityManager + * Function: DataAbility + * SubFunction: Release + * FunctionPoints: The parameter of function Release. + * EnvConditions: Can run ohos test framework + * CaseDescription: Verify function Release scheduler is nullptr + */ +HWTEST_F(DataAbilityManagerTest, AaFwk_DataAbilityManager_Release_002, TestSize.Level1) +{ + HILOG_INFO("AaFwk_DataAbilityManager_Release_002 start."); + + std::unique_ptr dataAbilityManager = std::make_unique(); + + EXPECT_EQ(dataAbilityManager->Release(nullptr, abilityRecordClient_->GetToken(), false), ERR_NULL_OBJECT); + + HILOG_INFO("AaFwk_DataAbilityManager_Release_002 end."); +} + +/* + * Feature: AbilityManager + * Function: DataAbility + * SubFunction: Release + * FunctionPoints: The parameter of function Release. + * EnvConditions: Can run ohos test framework + * CaseDescription: Verify function Release ability record invalid + */ +HWTEST_F(DataAbilityManagerTest, AaFwk_DataAbilityManager_Release_003, TestSize.Level1) +{ + HILOG_INFO("AaFwk_DataAbilityManager_Release_003 start."); + + std::unique_ptr dataAbilityManager = std::make_unique(); + + EXPECT_EQ(dataAbilityManager->Release(abilitySchedulerMock_, abilityRecordClient_->GetToken(), false), + ERR_UNKNOWN_OBJECT); + + HILOG_INFO("AaFwk_DataAbilityManager_Release_003 end."); +} + +/* + * Feature: AbilityManager + * Function: DataAbility + * SubFunction: AttachAbilityThread + * FunctionPoints: The parameter of function AttachAbilityThread. + * EnvConditions: Can run ohos test framework + * CaseDescription: Verify function AttachAbilityThread client is nullptr + */ +HWTEST_F(DataAbilityManagerTest, AaFwk_DataAbilityManager_AttachAbilityThread_001, TestSize.Level1) +{ + HILOG_INFO("AaFwk_DataAbilityManager_AttachAbilityThread_001 start."); + + std::unique_ptr dataAbilityManager = std::make_unique(); + + EXPECT_EQ(dataAbilityManager->AttachAbilityThread(abilitySchedulerMock_, nullptr), ERR_NULL_OBJECT); + + HILOG_INFO("AaFwk_DataAbilityManager_AttachAbilityThread_001 end."); +} + +/* + * Feature: AbilityManager + * Function: DataAbility + * SubFunction: AttachAbilityThread + * FunctionPoints: The parameter of function AttachAbilityThread. + * EnvConditions: Can run ohos test framework + * CaseDescription: Verify function AttachAbilityThread scheduler is nullptr + */ +HWTEST_F(DataAbilityManagerTest, AaFwk_DataAbilityManager_AttachAbilityThread_002, TestSize.Level1) +{ + HILOG_INFO("AaFwk_DataAbilityManager_AttachAbilityThread_002 start."); + + std::unique_ptr dataAbilityManager = std::make_unique(); + + EXPECT_EQ(dataAbilityManager->AttachAbilityThread(nullptr, abilityRecordClient_->GetToken()), ERR_NULL_OBJECT); + + HILOG_INFO("AaFwk_DataAbilityManager_AttachAbilityThread_002 end."); +} + +/* + * Feature: AbilityManager + * Function: DataAbility + * SubFunction: AttachAbilityThread + * FunctionPoints: The parameter of function AttachAbilityThread. + * EnvConditions: Can run ohos test framework + * CaseDescription: Verify function AttachAbilityThread ability record invalid + */ +HWTEST_F(DataAbilityManagerTest, AaFwk_DataAbilityManager_AttachAbilityThread_003, TestSize.Level1) +{ + HILOG_INFO("AaFwk_DataAbilityManager_AttachAbilityThread_003 start."); + + std::unique_ptr dataAbilityManager = std::make_unique(); + + EXPECT_EQ(dataAbilityManager->AttachAbilityThread(abilitySchedulerMock_, abilityRecordClient_->GetToken()), + ERR_UNKNOWN_OBJECT); + + HILOG_INFO("AaFwk_DataAbilityManager_AttachAbilityThread_003 end."); +} + +/* + * Feature: AbilityManager + * Function: DataAbility + * SubFunction: AbilityTransitionDone + * FunctionPoints: The parameter of function AbilityTransitionDone. + * EnvConditions: Can run ohos test framework + * CaseDescription: Verify function AbilityTransitionDone token is nullptr + */ +HWTEST_F(DataAbilityManagerTest, AaFwk_DataAbilityManager_AbilityTransitionDone_001, TestSize.Level1) +{ + HILOG_INFO("AaFwk_DataAbilityManager_AbilityTransitionDone_001 start."); + + std::unique_ptr dataAbilityManager = std::make_unique(); + + EXPECT_EQ(dataAbilityManager->AbilityTransitionDone(nullptr, INACTIVE), ERR_NULL_OBJECT); + + HILOG_INFO("AaFwk_DataAbilityManager_AbilityTransitionDone_001 end."); +} + +/* + * Feature: AbilityManager + * Function: DataAbility + * SubFunction: AbilityTransitionDone + * FunctionPoints: The parameter of function AbilityTransitionDone. + * EnvConditions: Can run ohos test framework + * CaseDescription: Verify function AbilityTransitionDone ability record invalid + */ +HWTEST_F(DataAbilityManagerTest, AaFwk_DataAbilityManager_AbilityTransitionDone_002, TestSize.Level1) +{ + HILOG_INFO("AaFwk_DataAbilityManager_AbilityTransitionDone_002 start."); + + std::unique_ptr dataAbilityManager = std::make_unique(); + + EXPECT_EQ( + dataAbilityManager->AbilityTransitionDone(abilityRecordClient_->GetToken(), INACTIVE), ERR_UNKNOWN_OBJECT); + + HILOG_INFO("AaFwk_DataAbilityManager_AbilityTransitionDone_002 end."); +} + +/* + * Feature: AbilityManager + * Function: DataAbility + * SubFunction: GetAbilityRecordByToken + * FunctionPoints: The parameter of function GetAbilityRecordByToken. + * EnvConditions: Can run ohos test framework + * CaseDescription: Verify function GetAbilityRecordByToken token is nullptr. + */ +HWTEST_F(DataAbilityManagerTest, AaFwk_DataAbilityManager_GetAbilityRecordByToken_001, TestSize.Level1) +{ + HILOG_INFO("AaFwk_DataAbilityManager_GetAbilityRecordByToken_001 start."); + + std::unique_ptr dataAbilityManager = std::make_unique(); + EXPECT_EQ(dataAbilityManager->GetAbilityRecordByToken(nullptr), nullptr); + + HILOG_INFO("AaFwk_DataAbilityManager_GetAbilityRecordByToken_001 end."); +} + +/* + * Feature: AbilityManager + * Function: DataAbility + * SubFunction: GetAbilityRecordByScheduler + * FunctionPoints: The parameter of function GetAbilityRecordByScheduler. + * EnvConditions: Can run ohos test framework + * CaseDescription: Verify function GetAbilityRecordByScheduler token is nullptr. + */ +HWTEST_F(DataAbilityManagerTest, AaFwk_DataAbilityManager_GetAbilityRecordByScheduler_001, TestSize.Level1) +{ + HILOG_INFO("AaFwk_DataAbilityManager_GetAbilityRecordByScheduler_001 start."); + + std::unique_ptr dataAbilityManager = std::make_unique(); + EXPECT_EQ(dataAbilityManager->GetAbilityRecordByScheduler(nullptr), nullptr); + + HILOG_INFO("AaFwk_DataAbilityManager_GetAbilityRecordByScheduler_001 end."); +} + +/* + * Feature: AbilityManager + * Function: DataAbility + * SubFunction: GetAbilityRecordById + * FunctionPoints: The parameter of function GetAbilityRecordById. + * EnvConditions: Can run ohos test framework + * CaseDescription: Verify function GetAbilityRecordById id is -1. + */ +HWTEST_F(DataAbilityManagerTest, AaFwk_DataAbilityManager_GetAbilityRecordById_001, TestSize.Level1) +{ + HILOG_INFO("AaFwk_DataAbilityManager_GetAbilityRecordById_001 start."); + + std::unique_ptr dataAbilityManager = std::make_unique(); + EXPECT_EQ(dataAbilityManager->GetAbilityRecordById(-1), nullptr); + + HILOG_INFO("AaFwk_DataAbilityManager_GetAbilityRecordById_001 end."); +} +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/abilitymgr/test/unittest/phone/data_ability_record_test/BUILD.gn b/tools/services/abilitymgr/test/unittest/phone/data_ability_record_test/BUILD.gn new file mode 100644 index 00000000000..051f1ffcad0 --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/data_ability_record_test/BUILD.gn @@ -0,0 +1,73 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/test.gni") +import("//foundation/aafwk/standard/aafwk.gni") + +module_output_path = "aafwk_standard/abilitymgr" + +ohos_unittest("data_ability_record_test") { + module_out_path = module_output_path + + include_dirs = [ + "${services_path}/abilitymgr/test/mock/libs/system_ability_mock", + "${services_path}/abilitymgr/test/mock/libs/ability_scheduler_mock", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy/include", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base/include", + "//foundation/aafwk/standard/interfaces/innerkits/ability_manager/include", + "//foundation/aafwk/standard/frameworks/kits/ability/native/include", + "//foundation/aafwk/standard/services/common/include", + ] + + sources = [ + "//foundation/aafwk/standard/services/abilitymgr/test/mock/libs/appexecfwk_core/src/appmgr/mock_app_scheduler.cpp", + "data_ability_record_test.cpp", # add mock file + ] + + configs = [ + "${services_path}/abilitymgr:abilityms_config", + "//foundation/aafwk/standard/interfaces/innerkits/base:base_public_config", + "${services_path}/abilitymgr/test/mock:aafwk_mock_config", + ] + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + deps = [ + "${innerkits_path}/want:want", + "${services_path}/abilitymgr/test:abilityms_test_source", + "${services_path}/abilitymgr/test/mock/libs/aakit:aakit_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_appmgr_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_bundlemgr_mock", + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/frameworks/kits/ability/native:dummy_classes", + + #"//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//third_party/googletest:gmock_main", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] +} + +group("unittest") { + testonly = true + + deps = [ ":data_ability_record_test" ] +} diff --git a/tools/services/abilitymgr/test/unittest/phone/data_ability_record_test/data_ability_record_test.cpp b/tools/services/abilitymgr/test/unittest/phone/data_ability_record_test/data_ability_record_test.cpp new file mode 100644 index 00000000000..cfb98498785 --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/data_ability_record_test/data_ability_record_test.cpp @@ -0,0 +1,944 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#define private public +#define protected public +#include "data_ability_record.h" +#undef private +#undef protected + +#include "ability_scheduler_mock.h" +#include "app_process_data.h" + +using namespace testing::ext; +using namespace testing; +using namespace std::chrono; +using namespace OHOS::AppExecFwk; + +namespace OHOS { +namespace AAFwk { +class DataAbilityRecordTest : public testing::TestWithParam { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + +protected: + sptr abilitySchedulerMock_{nullptr}; + AbilityRequest abilityRequest_; + std::shared_ptr abilityRecord_{nullptr}; + OHOS::AAFwk::AbilityState abilityState_; +}; + +void DataAbilityRecordTest::SetUpTestCase(void) +{} +void DataAbilityRecordTest::TearDownTestCase(void) +{} + +void DataAbilityRecordTest::SetUp(void) +{ + if (abilitySchedulerMock_ == nullptr) { + abilitySchedulerMock_ = new AbilitySchedulerMock(); + } + + abilityRequest_.appInfo.bundleName = "com.data_ability.hiworld"; + abilityRequest_.appInfo.name = "com.data_ability.hiworld"; + abilityRequest_.abilityInfo.name = "DataAbilityHiworld"; + abilityRequest_.abilityInfo.type = AbilityType::DATA; + + if (abilityRecord_ == nullptr) { + OHOS::AppExecFwk::AbilityInfo abilityInfo; + OHOS::AppExecFwk::ApplicationInfo applicationInfo; + const Want want; + abilityRecord_ = std::make_shared(want, abilityInfo, applicationInfo); + abilityRecord_->Init(); + } + abilityState_ = INITIAL; +} + +void DataAbilityRecordTest::TearDown(void) +{ + abilitySchedulerMock_.clear(); +} + +/* + * Feature: AbilityManager + * Function: DataAbility + * SubFunction: NA + * FunctionPoints: Normal flow + * EnvConditions: Can run ohos test framework + * CaseDescription: Verify normal flow. + */ +HWTEST_F(DataAbilityRecordTest, AaFwk_DataAbilityRecord_Flow_001, TestSize.Level1) +{ + HILOG_INFO("AaFwk_DataAbilityRecord_Flow_001 start."); + + std::unique_ptr dataAbilityRecord = std::make_unique(abilityRequest_); + auto client = Token::GetAbilityRecordByToken(abilityRecord_->GetToken()); + + EXPECT_EQ(dataAbilityRecord->StartLoading(), ERR_OK); + EXPECT_CALL(*abilitySchedulerMock_, ScheduleAbilityTransaction(_, _)).Times(1); + EXPECT_EQ(dataAbilityRecord->Attach(abilitySchedulerMock_), ERR_OK); + abilityState_ = ACTIVE; + EXPECT_EQ(dataAbilityRecord->OnTransitionDone(abilityState_), ERR_OK); + EXPECT_NE(dataAbilityRecord->GetToken(), nullptr); + EXPECT_NE(dataAbilityRecord->GetAbilityRecord()->GetToken(), nullptr); + EXPECT_EQ(dataAbilityRecord->GetRequest().appInfo.name, abilityRequest_.appInfo.name); + + HILOG_INFO("AaFwk_DataAbilityRecord_Flow_001 end."); +} + +/* + * Feature: AbilityManager + * Function: DataAbility + * SubFunction: StartLoading + * FunctionPoints: The parameter of function Startloading. + * EnvConditions: Can run ohos test framework + * CaseDescription: Verify function StartLoading called twice. + */ +HWTEST_F(DataAbilityRecordTest, AaFwk_DataAbilityRecord_StartLoading_001, TestSize.Level1) +{ + HILOG_INFO("AaFwk_DataAbilityRecord_StartLoading_001 start."); + + std::unique_ptr dataAbilityRecord = std::make_unique(abilityRequest_); + EXPECT_EQ(dataAbilityRecord->StartLoading(), ERR_OK); + EXPECT_EQ(dataAbilityRecord->StartLoading(), ERR_ALREADY_EXISTS); + + HILOG_INFO("AaFwk_DataAbilityRecord_StartLoading_001 end."); +} + +/* + * Feature: AbilityManager + * Function: DataAbility + * SubFunction: StartLoading + * FunctionPoints: The parameter of function Startloading. + * EnvConditions: Can run ohos test framework + * CaseDescription: Verify function StartLoading request parameter without app name + */ +HWTEST_F(DataAbilityRecordTest, AaFwk_DataAbilityRecord_StartLoading_002, TestSize.Level1) +{ + HILOG_INFO("AaFwk_DataAbilityRecord_StartLoading_002 start."); + + // clear app name + abilityRequest_.appInfo.name = ""; + std::unique_ptr dataAbilityRecord = std::make_unique(abilityRequest_); + EXPECT_EQ(dataAbilityRecord->StartLoading(), ERR_INVALID_VALUE); + + HILOG_INFO("AaFwk_DataAbilityRecord_StartLoading_002 end."); +} + +/* + * Feature: AbilityManager + * Function: DataAbility + * SubFunction: WaitForLoaded + * FunctionPoints: The parameter of function WaitForLoaded. + * EnvConditions: Can run ohos test framework + * CaseDescription: Verify function WaitForLoaded, before call WaitForLoaded not startloading. + */ +HWTEST_F(DataAbilityRecordTest, AaFwk_DataAbilityRecord_WaitForLoaded_001, TestSize.Level1) +{ + HILOG_INFO("AaFwk_DataAbilityRecord_WaitForLoaded_001 start."); + + std::unique_ptr dataAbilityRecord = std::make_unique(abilityRequest_); + std::mutex mutex; + system_clock::duration timeout = 800ms; + + EXPECT_EQ(dataAbilityRecord->WaitForLoaded(mutex, timeout), ERR_INVALID_STATE); + + HILOG_INFO("AaFwk_DataAbilityRecord_WaitForLoaded_001 end."); +} + +/* + * Feature: AbilityManager + * Function: DataAbility + * SubFunction: WaitForLoaded + * FunctionPoints: The parameter of function WaitForLoaded. + * EnvConditions: Can run ohos test framework + * CaseDescription: Verify function WaitForLoaded wait state timeout. + */ +HWTEST_F(DataAbilityRecordTest, AaFwk_DataAbilityRecord_WaitForLoaded_002, TestSize.Level1) +{ + HILOG_INFO("AaFwk_DataAbilityRecord_WaitForLoaded_002 start."); + + std::unique_ptr dataAbilityRecord = std::make_unique(abilityRequest_); + std::mutex mutex; + system_clock::duration timeout = 800ms; + + EXPECT_EQ(dataAbilityRecord->StartLoading(), ERR_OK); + EXPECT_EQ(dataAbilityRecord->WaitForLoaded(mutex, timeout), ERR_TIMED_OUT); + + HILOG_INFO("AaFwk_DataAbilityRecord_WaitForLoaded_002 end."); +} + +/* + * Feature: AbilityManager + * Function: DataAbility + * SubFunction: WaitForLoaded + * FunctionPoints: The parameter of function WaitForLoaded. + * EnvConditions: Can run ohos test framework + * CaseDescription: Verify function WaitForLoaded ability has loaded. + */ +HWTEST_F(DataAbilityRecordTest, AaFwk_DataAbilityRecord_WaitForLoaded_003, TestSize.Level1) +{ + HILOG_INFO("AaFwk_DataAbilityRecord_WaitForLoaded_003 start."); + + std::unique_ptr dataAbilityRecord = std::make_unique(abilityRequest_); + std::mutex mutex; + system_clock::duration timeout = 800ms; + + EXPECT_EQ(dataAbilityRecord->StartLoading(), ERR_OK); + EXPECT_CALL(*abilitySchedulerMock_, ScheduleAbilityTransaction(_, _)).Times(1); + EXPECT_EQ(dataAbilityRecord->Attach(abilitySchedulerMock_), ERR_OK); + abilityState_ = ACTIVE; + EXPECT_EQ(dataAbilityRecord->OnTransitionDone(abilityState_), ERR_OK); + EXPECT_EQ(dataAbilityRecord->WaitForLoaded(mutex, timeout), ERR_OK); + + HILOG_INFO("AaFwk_DataAbilityRecord_WaitForLoaded_003 end."); +} + +/* + * Feature: AbilityManager + * Function: DataAbility + * SubFunction: Attach + * FunctionPoints: The parameter of function Attach. + * EnvConditions: Can run ohos test framework + * CaseDescription: Verify function Attach request parameter without call StartLoading. + */ +HWTEST_F(DataAbilityRecordTest, AaFwk_DataAbilityRecord_Attach_001, TestSize.Level1) +{ + HILOG_INFO("AaFwk_DataAbilityRecord_Attach_001 start."); + + std::unique_ptr dataAbilityRecord = std::make_unique(abilityRequest_); + EXPECT_EQ(dataAbilityRecord->Attach(abilitySchedulerMock_), ERR_INVALID_STATE); + + HILOG_INFO("AaFwk_DataAbilityRecord_Attach_001 end."); +} + +/* + * Feature: AbilityManager + * Function: DataAbility + * SubFunction: Attach + * FunctionPoints: The parameter of function Attach. + * EnvConditions: Can run ohos test framework + * CaseDescription: Verify function Attach request parameter with nullptr + */ +HWTEST_F(DataAbilityRecordTest, AaFwk_DataAbilityRecord_Attach_002, TestSize.Level1) +{ + HILOG_INFO("AaFwk_DataAbilityRecord_Attach_002 start."); + + std::unique_ptr dataAbilityRecord = std::make_unique(abilityRequest_); + EXPECT_EQ(dataAbilityRecord->StartLoading(), ERR_OK); + EXPECT_EQ(dataAbilityRecord->Attach(nullptr), ERR_INVALID_DATA); + + HILOG_INFO("AaFwk_DataAbilityRecord_Attach_002 end."); +} + +/* + * Feature: AbilityManager + * Function: DataAbility + * SubFunction: Attach + * FunctionPoints: The parameter of function Attach. + * EnvConditions: Can run ohos test framework + * CaseDescription: Verify function Attach called twice + */ +HWTEST_F(DataAbilityRecordTest, AaFwk_DataAbilityRecord_Attach_003, TestSize.Level1) +{ + HILOG_INFO("AaFwk_DataAbilityRecord_Attach_003 start."); + + std::unique_ptr dataAbilityRecord = std::make_unique(abilityRequest_); + EXPECT_EQ(dataAbilityRecord->StartLoading(), ERR_OK); + + EXPECT_CALL(*abilitySchedulerMock_, ScheduleAbilityTransaction(_, _)).Times(1); + EXPECT_EQ(dataAbilityRecord->Attach(abilitySchedulerMock_), ERR_OK); + EXPECT_EQ(dataAbilityRecord->Attach(abilitySchedulerMock_), ERR_INVALID_STATE); + + HILOG_INFO("AaFwk_DataAbilityRecord_Attach_003 end."); +} + +/* + * Feature: AbilityManager + * Function: DataAbility + * SubFunction: OnTransitionDone + * FunctionPoints: The parameter of function OnTransitionDone. + * EnvConditions: Can run ohos test framework + * CaseDescription: Verify function OnTransitionDone without call StartLoading and Attach. + */ +HWTEST_F(DataAbilityRecordTest, AaFwk_DataAbilityRecord_OnTransitionDone_001, TestSize.Level1) +{ + HILOG_INFO("AaFwk_DataAbilityRecord_OnTransitionDone_001 start."); + + std::unique_ptr dataAbilityRecord = std::make_unique(abilityRequest_); + EXPECT_EQ(dataAbilityRecord->OnTransitionDone(abilityState_), ERR_INVALID_STATE); + + HILOG_INFO("AaFwk_DataAbilityRecord_OnTransitionDone_001 end."); +} + +/* + * Feature: AbilityManager + * Function: DataAbility + * SubFunction: OnTransitionDone + * FunctionPoints: The parameter of function OnTransitionDone. + * EnvConditions: Can run ohos test framework + * CaseDescription: Verify function OnTransitionDone request parameter without call Attach. + */ +HWTEST_F(DataAbilityRecordTest, AaFwk_DataAbilityRecord_OnTransitionDone_002, TestSize.Level1) +{ + HILOG_INFO("AaFwk_DataAbilityRecord_OnTransitionDone_002 start."); + + std::unique_ptr dataAbilityRecord = std::make_unique(abilityRequest_); + EXPECT_EQ(dataAbilityRecord->StartLoading(), ERR_OK); + EXPECT_EQ(dataAbilityRecord->OnTransitionDone(abilityState_), ERR_INVALID_STATE); + + HILOG_INFO("AaFwk_DataAbilityRecord_OnTransitionDone_002 end."); +} + +/* + * Feature: AbilityManager + * Function: DataAbility + * SubFunction: OnTransitionDone + * FunctionPoints: The parameter of function OnTransitionDone. + * EnvConditions: Can run ohos test framework + * CaseDescription: Verify function OnTransitionDone request parameter state + */ +HWTEST_F(DataAbilityRecordTest, AaFwk_DataAbilityRecord_OnTransitionDone_003, TestSize.Level1) +{ + HILOG_INFO("AaFwk_DataAbilityRecord_OnTransitionDone_003 start."); + + std::unique_ptr dataAbilityRecord = std::make_unique(abilityRequest_); + EXPECT_EQ(dataAbilityRecord->StartLoading(), ERR_OK); + + EXPECT_CALL(*abilitySchedulerMock_, ScheduleAbilityTransaction(_, _)).Times(1); + EXPECT_EQ(dataAbilityRecord->Attach(abilitySchedulerMock_), ERR_OK); + + abilityState_ = INITIAL; + EXPECT_EQ(dataAbilityRecord->OnTransitionDone(abilityState_), ERR_INVALID_STATE); + + abilityState_ = ACTIVE; + EXPECT_EQ(dataAbilityRecord->OnTransitionDone(abilityState_), ERR_INVALID_STATE); + + abilityState_ = BACKGROUND; + EXPECT_EQ(dataAbilityRecord->OnTransitionDone(abilityState_), ERR_INVALID_STATE); + + abilityState_ = SUSPENDED; + EXPECT_EQ(dataAbilityRecord->OnTransitionDone(abilityState_), ERR_INVALID_STATE); + + abilityState_ = INACTIVATING; + EXPECT_EQ(dataAbilityRecord->OnTransitionDone(abilityState_), ERR_INVALID_STATE); + + abilityState_ = ACTIVATING; + EXPECT_EQ(dataAbilityRecord->OnTransitionDone(abilityState_), ERR_INVALID_STATE); + + abilityState_ = MOVING_BACKGROUND; + EXPECT_EQ(dataAbilityRecord->OnTransitionDone(abilityState_), ERR_INVALID_STATE); + + abilityState_ = TERMINATING; + EXPECT_EQ(dataAbilityRecord->OnTransitionDone(abilityState_), ERR_INVALID_STATE); + + abilityState_ = INACTIVE; + EXPECT_EQ(dataAbilityRecord->OnTransitionDone(abilityState_), ERR_INVALID_STATE); + + HILOG_INFO("AaFwk_DataAbilityRecord_OnTransitionDone_003 end."); +} + +/* + * Feature: AbilityManager + * Function: DataAbility + * SubFunction: OnTransitionDone + * FunctionPoints: The parameter of function OnTransitionDone. + * EnvConditions: Can run ohos test framework + * CaseDescription: Verify function OnTransitionDone ability state changed to inactive, and call OnTransitionDone. + */ +HWTEST_F(DataAbilityRecordTest, AaFwk_DataAbilityRecord_OnTransitionDone_004, TestSize.Level1) +{ + HILOG_INFO("AaFwk_DataAbilityRecord_OnTransitionDone_004 start."); + + std::unique_ptr dataAbilityRecord = std::make_unique(abilityRequest_); + + EXPECT_EQ(dataAbilityRecord->StartLoading(), ERR_OK); + EXPECT_CALL(*abilitySchedulerMock_, ScheduleAbilityTransaction(_, _)).Times(1); + EXPECT_EQ(dataAbilityRecord->Attach(abilitySchedulerMock_), ERR_OK); + + abilityState_ = ACTIVE; + EXPECT_EQ(dataAbilityRecord->OnTransitionDone(abilityState_), ERR_OK); + EXPECT_EQ(dataAbilityRecord->OnTransitionDone(abilityState_), ERR_INVALID_STATE); + + HILOG_INFO("AaFwk_DataAbilityRecord_OnTransitionDone_004 end."); +} + +/* + * Feature: AbilityManager + * Function: DataAbility + * SubFunction: AddClient + * FunctionPoints: The parameter of function AddClient. + * EnvConditions: Can run ohos test framework + * CaseDescription: Verify function OnTransitionDone with nullptr. + */ +HWTEST_F(DataAbilityRecordTest, AaFwk_DataAbilityRecord_AddClient_001, TestSize.Level1) +{ + HILOG_INFO("AaFwk_DataAbilityRecord_AddClient_001 start."); + + std::unique_ptr dataAbilityRecord = std::make_unique(abilityRequest_); + EXPECT_EQ(dataAbilityRecord->AddClient(nullptr, true, false), ERR_INVALID_STATE); + + HILOG_INFO("AaFwk_DataAbilityRecord_AddClient_001 end."); +} + +/* + * Feature: AbilityManager + * Function: DataAbility + * SubFunction: AddClient + * FunctionPoints: The parameter of function AddClient. + * EnvConditions: Can run ohos test framework + * CaseDescription: Verify function AddClient, before call AddClient not startloading and not attach. + */ +HWTEST_F(DataAbilityRecordTest, AaFwk_DataAbilityRecord_AddClient_002, TestSize.Level1) +{ + HILOG_INFO("AaFwk_DataAbilityRecord_AddClient_002 start."); + + std::unique_ptr dataAbilityRecord = std::make_unique(abilityRequest_); + auto client = Token::GetAbilityRecordByToken(abilityRecord_->GetToken()); + + EXPECT_EQ(dataAbilityRecord->AddClient(abilityRecord_->GetToken(), true, false), ERR_INVALID_STATE); + + HILOG_INFO("AaFwk_DataAbilityRecord_AddClient_002 end."); +} + +/* + * Feature: AbilityManager + * Function: DataAbility + * SubFunction: AddClient + * FunctionPoints: The parameter of function AddClient. + * EnvConditions: Can run ohos test framework + * CaseDescription: Verify function AddClient, before call AddClient not attach. + */ +HWTEST_F(DataAbilityRecordTest, AaFwk_DataAbilityRecord_AddClient_003, TestSize.Level1) +{ + HILOG_INFO("AaFwk_DataAbilityRecord_AddClient_003 start."); + + std::unique_ptr dataAbilityRecord = std::make_unique(abilityRequest_); + auto client = Token::GetAbilityRecordByToken(abilityRecord_->GetToken()); + + EXPECT_EQ(dataAbilityRecord->StartLoading(), ERR_OK); + EXPECT_EQ(dataAbilityRecord->AddClient(abilityRecord_->GetToken(), true, false), ERR_INVALID_STATE); + + HILOG_INFO("AaFwk_DataAbilityRecord_AddClient_003 end."); +} + +/* + * Feature: AbilityManager + * Function: DataAbility + * SubFunction: AddClient + * FunctionPoints: The parameter of function AddClient. + * EnvConditions: Can run ohos test framework + * CaseDescription: Verify function AddClient ability state is not inactive. + */ +HWTEST_F(DataAbilityRecordTest, AaFwk_DataAbilityRecord_AddClient_004, TestSize.Level1) +{ + HILOG_INFO("AaFwk_DataAbilityRecord_AddClient_004 start."); + + std::unique_ptr dataAbilityRecord = std::make_unique(abilityRequest_); + auto client = Token::GetAbilityRecordByToken(abilityRecord_->GetToken()); + + EXPECT_EQ(dataAbilityRecord->StartLoading(), ERR_OK); + EXPECT_CALL(*abilitySchedulerMock_, ScheduleAbilityTransaction(_, _)).Times(1); + EXPECT_EQ(dataAbilityRecord->Attach(abilitySchedulerMock_), ERR_OK); + EXPECT_EQ(dataAbilityRecord->AddClient(abilityRecord_->GetToken(), true, false), ERR_INVALID_STATE); + + HILOG_INFO("AaFwk_DataAbilityRecord_AddClient_004 end."); +} + +/* + * Feature: AbilityManager + * Function: DataAbility + * SubFunction: AddClient + * FunctionPoints: The parameter of function AddClient. + * EnvConditions: Can run ohos test framework + * CaseDescription: Verify function AddClient has add one client, and get count exact. + */ +HWTEST_F(DataAbilityRecordTest, AaFwk_DataAbilityRecord_AddClient_005, TestSize.Level1) +{ + HILOG_INFO("AaFwk_DataAbilityRecord_AddClient_005 start."); + + std::unique_ptr dataAbilityRecord = std::make_unique(abilityRequest_); + auto client = Token::GetAbilityRecordByToken(abilityRecord_->GetToken()); + + EXPECT_EQ(dataAbilityRecord->StartLoading(), ERR_OK); + EXPECT_CALL(*abilitySchedulerMock_, ScheduleAbilityTransaction(_, _)).Times(1); + EXPECT_EQ(dataAbilityRecord->Attach(abilitySchedulerMock_), ERR_OK); + abilityState_ = ACTIVE; + EXPECT_EQ(dataAbilityRecord->OnTransitionDone(abilityState_), ERR_OK); + EXPECT_EQ(dataAbilityRecord->AddClient(abilityRecord_->GetToken(), true, false), ERR_OK); + unsigned int count = 1; + EXPECT_EQ(dataAbilityRecord->GetClientCount(abilityRecord_->GetToken()), count); + + HILOG_INFO("AaFwk_DataAbilityRecord_AddClient_005 end."); +} + +/* + * Feature: AbilityManager + * Function: DataAbility + * SubFunction: RemoveClient + * FunctionPoints: The parameter of function RemoveClient. + * EnvConditions: Can run ohos test framework + * CaseDescription: Verify function RemoveClient with nullptr. + */ +HWTEST_F(DataAbilityRecordTest, AaFwk_DataAbilityRecord_RemoveClient_001, TestSize.Level1) +{ + HILOG_INFO("AaFwk_DataAbilityRecord_RemoveClient_001 start."); + + std::unique_ptr dataAbilityRecord = std::make_unique(abilityRequest_); + EXPECT_EQ(dataAbilityRecord->RemoveClient(nullptr, false), ERR_INVALID_STATE); + + HILOG_INFO("AaFwk_DataAbilityRecord_RemoveClient_001 end."); +} + +/* + * Feature: AbilityManager + * Function: DataAbility + * SubFunction: RemoveClient + * FunctionPoints: The parameter of function RemoveClient. + * EnvConditions: Can run ohos test framework + * CaseDescription: Verify function RemoveClient, before call RemoveClient not startloading and not attach. + */ +HWTEST_F(DataAbilityRecordTest, AaFwk_DataAbilityRecord_RemoveClient_002, TestSize.Level1) +{ + HILOG_INFO("AaFwk_DataAbilityRecord_RemoveClient_002 start."); + + std::unique_ptr dataAbilityRecord = std::make_unique(abilityRequest_); + auto client = Token::GetAbilityRecordByToken(abilityRecord_->GetToken()); + + EXPECT_EQ(dataAbilityRecord->RemoveClient(abilityRecord_->GetToken(), false), ERR_INVALID_STATE); + + HILOG_INFO("AaFwk_DataAbilityRecord_RemoveClient_002 end."); +} + +/* + * Feature: AbilityManager + * Function: DataAbility + * SubFunction: RemoveClient + * FunctionPoints: The parameter of function RemoveClient. + * EnvConditions: Can run ohos test framework + * CaseDescription: Verify function RemoveClient ability state is not attach. + */ +HWTEST_F(DataAbilityRecordTest, AaFwk_DataAbilityRecord_RemoveClient_003, TestSize.Level1) +{ + HILOG_INFO("AaFwk_DataAbilityRecord_RemoveClient_003 start."); + + std::unique_ptr dataAbilityRecord = std::make_unique(abilityRequest_); + auto client = Token::GetAbilityRecordByToken(abilityRecord_->GetToken()); + + EXPECT_EQ(dataAbilityRecord->StartLoading(), ERR_OK); + EXPECT_EQ(dataAbilityRecord->RemoveClient(abilityRecord_->GetToken(), false), ERR_INVALID_STATE); + + HILOG_INFO("AaFwk_DataAbilityRecord_RemoveClient_003 end."); +} + +/* + * Feature: AbilityManager + * Function: DataAbility + * SubFunction: RemoveClient + * FunctionPoints: The parameter of function RemoveClient. + * EnvConditions: Can run ohos test framework + * CaseDescription: Verify function RemoveClient ability state is not inactive. + */ +HWTEST_F(DataAbilityRecordTest, AaFwk_DataAbilityRecord_RemoveClient_004, TestSize.Level1) +{ + HILOG_INFO("AaFwk_DataAbilityRecord_RemoveClient_004 start."); + + std::unique_ptr dataAbilityRecord = std::make_unique(abilityRequest_); + auto client = Token::GetAbilityRecordByToken(abilityRecord_->GetToken()); + + EXPECT_EQ(dataAbilityRecord->StartLoading(), ERR_OK); + EXPECT_CALL(*abilitySchedulerMock_, ScheduleAbilityTransaction(_, _)).Times(1); + EXPECT_EQ(dataAbilityRecord->Attach(abilitySchedulerMock_), ERR_OK); + EXPECT_EQ(dataAbilityRecord->RemoveClient(abilityRecord_->GetToken(), false), ERR_INVALID_STATE); + + HILOG_INFO("AaFwk_DataAbilityRecord_RemoveClient_004 end."); +} + +/* + * Feature: AbilityManager + * Function: DataAbility + * SubFunction: RemoveClient + * FunctionPoints: The parameter of function RemoveClient. + * EnvConditions: Can run ohos test framework + * CaseDescription: Verify function RemoveClient return ok when not add client. + */ +HWTEST_F(DataAbilityRecordTest, AaFwk_DataAbilityRecord_RemoveClient_005, TestSize.Level1) +{ + HILOG_INFO("AaFwk_DataAbilityRecord_RemoveClient_005 start."); + + std::unique_ptr dataAbilityRecord = std::make_unique(abilityRequest_); + auto client = Token::GetAbilityRecordByToken(abilityRecord_->GetToken()); + + EXPECT_EQ(dataAbilityRecord->StartLoading(), ERR_OK); + EXPECT_CALL(*abilitySchedulerMock_, ScheduleAbilityTransaction(_, _)).Times(1); + EXPECT_EQ(dataAbilityRecord->Attach(abilitySchedulerMock_), ERR_OK); + abilityState_ = ACTIVE; + EXPECT_EQ(dataAbilityRecord->OnTransitionDone(abilityState_), ERR_OK); + EXPECT_EQ(dataAbilityRecord->RemoveClient(abilityRecord_->GetToken(), false), ERR_OK); + + HILOG_INFO("AaFwk_DataAbilityRecord_RemoveClient_005 end."); +} + +/* + * Feature: AbilityManager + * Function: DataAbility + * SubFunction: RemoveClient + * FunctionPoints: Add and remove client. + * EnvConditions: Can run ohos test framework + * CaseDescription: Verify function add one client and remove it, client count is exact. + */ +HWTEST_F(DataAbilityRecordTest, AaFwk_DataAbilityRecord_RemoveClient_006, TestSize.Level1) +{ + HILOG_INFO("AaFwk_DataAbilityRecord_RemoveClient_006 start."); + + std::unique_ptr dataAbilityRecord = std::make_unique(abilityRequest_); + auto client = Token::GetAbilityRecordByToken(abilityRecord_->GetToken()); + + EXPECT_EQ(dataAbilityRecord->StartLoading(), ERR_OK); + EXPECT_CALL(*abilitySchedulerMock_, ScheduleAbilityTransaction(_, _)).Times(1); + EXPECT_EQ(dataAbilityRecord->Attach(abilitySchedulerMock_), ERR_OK); + abilityState_ = ACTIVE; + EXPECT_EQ(dataAbilityRecord->OnTransitionDone(abilityState_), ERR_OK); + EXPECT_EQ(dataAbilityRecord->AddClient(abilityRecord_->GetToken(), true, false), ERR_OK); + unsigned int count = 1; + EXPECT_EQ(dataAbilityRecord->GetClientCount(abilityRecord_->GetToken()), count); + EXPECT_EQ(dataAbilityRecord->RemoveClient(abilityRecord_->GetToken(), false), ERR_OK); + count = 0; + EXPECT_EQ(dataAbilityRecord->GetClientCount(abilityRecord_->GetToken()), count); + + HILOG_INFO("AaFwk_DataAbilityRecord_RemoveClient_006 end."); +} + +/* + * Feature: AbilityManager + * Function: DataAbility + * SubFunction: RemoveClient + * FunctionPoints: Add and remove client. + * EnvConditions: Can run ohos test framework + * CaseDescription: Verify function add the same client twice and remove it twice. + */ +HWTEST_F(DataAbilityRecordTest, AaFwk_DataAbilityRecord_RemoveClient_007, TestSize.Level1) +{ + HILOG_INFO("AaFwk_DataAbilityRecord_RemoveClient_007 start."); + + std::unique_ptr dataAbilityRecord = std::make_unique(abilityRequest_); + auto client = Token::GetAbilityRecordByToken(abilityRecord_->GetToken()); + + EXPECT_EQ(dataAbilityRecord->StartLoading(), ERR_OK); + EXPECT_CALL(*abilitySchedulerMock_, ScheduleAbilityTransaction(_, _)).Times(1); + EXPECT_EQ(dataAbilityRecord->Attach(abilitySchedulerMock_), ERR_OK); + abilityState_ = ACTIVE; + EXPECT_EQ(dataAbilityRecord->OnTransitionDone(abilityState_), ERR_OK); + + // first add client + EXPECT_EQ(dataAbilityRecord->AddClient(abilityRecord_->GetToken(), true, false), ERR_OK); + EXPECT_EQ(dataAbilityRecord->GetClientCount(abilityRecord_->GetToken()), (uint32_t)1); + + // second add client + EXPECT_EQ(dataAbilityRecord->AddClient(abilityRecord_->GetToken(), true, false), ERR_OK); + EXPECT_EQ(dataAbilityRecord->GetClientCount(abilityRecord_->GetToken()), (uint32_t)2); + + // first remove client + EXPECT_EQ(dataAbilityRecord->RemoveClient(abilityRecord_->GetToken(), false), ERR_OK); + EXPECT_EQ(dataAbilityRecord->GetClientCount(abilityRecord_->GetToken()), (uint32_t)1); + + // second remove client + EXPECT_EQ(dataAbilityRecord->RemoveClient(abilityRecord_->GetToken(), false), ERR_OK); + EXPECT_EQ(dataAbilityRecord->GetClientCount(abilityRecord_->GetToken()), (uint32_t)0); + + HILOG_INFO("AaFwk_DataAbilityRecord_RemoveClient_007 end."); +} + +/* + * Feature: AbilityManager + * Function: DataAbility + * SubFunction: RemoveClients + * FunctionPoints: The parameter of function RemoveClients. + * EnvConditions: Can run ohos test framework + * CaseDescription: Verify function RemoveClients, before call RemoveClients not startloading and not attach. + */ +HWTEST_F(DataAbilityRecordTest, AaFwk_DataAbilityRecord_RemoveClients_001, TestSize.Level1) +{ + HILOG_INFO("AaFwk_DataAbilityRecord_RemoveClients_001 start."); + + std::unique_ptr dataAbilityRecord = std::make_unique(abilityRequest_); + auto client = Token::GetAbilityRecordByToken(abilityRecord_->GetToken()); + + EXPECT_EQ(dataAbilityRecord->RemoveClients(client), ERR_INVALID_STATE); + + HILOG_INFO("AaFwk_DataAbilityRecord_RemoveClients_001 end."); +} + +/* + * Feature: AbilityManager + * Function: DataAbility + * SubFunction: RemoveClients + * FunctionPoints: The parameter of function RemoveClients. + * EnvConditions: Can run ohos test framework + * CaseDescription: Verify function RemoveClients ability state is not attach. + */ +HWTEST_F(DataAbilityRecordTest, AaFwk_DataAbilityRecord_RemoveClients_002, TestSize.Level1) +{ + HILOG_INFO("AaFwk_DataAbilityRecord_RemoveClients_002 start."); + + std::unique_ptr dataAbilityRecord = std::make_unique(abilityRequest_); + auto client = Token::GetAbilityRecordByToken(abilityRecord_->GetToken()); + + EXPECT_EQ(dataAbilityRecord->StartLoading(), ERR_OK); + EXPECT_EQ(dataAbilityRecord->RemoveClients(client), ERR_INVALID_STATE); + + HILOG_INFO("AaFwk_DataAbilityRecord_RemoveClients_002 end."); +} + +/* + * Feature: AbilityManager + * Function: DataAbility + * SubFunction: RemoveClients + * FunctionPoints: The parameter of function RemoveClients. + * EnvConditions: Can run ohos test framework + * CaseDescription: Verify function RemoveClients ability state is not inactive. + */ +HWTEST_F(DataAbilityRecordTest, AaFwk_DataAbilityRecord_RemoveClients_003, TestSize.Level1) +{ + HILOG_INFO("AaFwk_DataAbilityRecord_RemoveClients_003 start."); + + std::unique_ptr dataAbilityRecord = std::make_unique(abilityRequest_); + auto client = Token::GetAbilityRecordByToken(abilityRecord_->GetToken()); + + EXPECT_EQ(dataAbilityRecord->StartLoading(), ERR_OK); + EXPECT_CALL(*abilitySchedulerMock_, ScheduleAbilityTransaction(_, _)).Times(1); + EXPECT_EQ(dataAbilityRecord->Attach(abilitySchedulerMock_), ERR_OK); + EXPECT_EQ(dataAbilityRecord->RemoveClients(client), ERR_INVALID_STATE); + + HILOG_INFO("AaFwk_DataAbilityRecord_RemoveClients_003 end."); +} + +/* + * Feature: AbilityManager + * Function: DataAbility + * SubFunction: RemoveClients + * FunctionPoints: The parameter of function RemoveClients. + * EnvConditions: Can run ohos test framework + * CaseDescription: Verify function RemoveClients return ok when not add client. + */ +HWTEST_F(DataAbilityRecordTest, AaFwk_DataAbilityRecord_RemoveClients_005, TestSize.Level1) +{ + HILOG_INFO("AaFwk_DataAbilityRecord_RemoveClients_005 start."); + + std::unique_ptr dataAbilityRecord = std::make_unique(abilityRequest_); + auto client = Token::GetAbilityRecordByToken(abilityRecord_->GetToken()); + + EXPECT_EQ(dataAbilityRecord->StartLoading(), ERR_OK); + EXPECT_CALL(*abilitySchedulerMock_, ScheduleAbilityTransaction(_, _)).Times(1); + EXPECT_EQ(dataAbilityRecord->Attach(abilitySchedulerMock_), ERR_OK); + abilityState_ = ACTIVE; + EXPECT_EQ(dataAbilityRecord->OnTransitionDone(abilityState_), ERR_OK); + EXPECT_EQ(dataAbilityRecord->RemoveClients(client), ERR_OK); + + HILOG_INFO("AaFwk_DataAbilityRecord_RemoveClients_005 end."); +} + +/* + * Feature: AbilityManager + * Function: DataAbility + * SubFunction: RemoveClients + * FunctionPoints: The parameter of function RemoveClients. + * EnvConditions: Can run ohos test framework + * CaseDescription: Verify function RemoveClients, add the same client twice and remove them once. + */ +HWTEST_F(DataAbilityRecordTest, AaFwk_DataAbilityRecord_RemoveClients_006, TestSize.Level1) +{ + HILOG_INFO("AaFwk_DataAbilityRecord_RemoveClients_006 start."); + + std::unique_ptr dataAbilityRecord = std::make_unique(abilityRequest_); + auto client = Token::GetAbilityRecordByToken(abilityRecord_->GetToken()); + + EXPECT_EQ(dataAbilityRecord->StartLoading(), ERR_OK); + EXPECT_CALL(*abilitySchedulerMock_, ScheduleAbilityTransaction(_, _)).Times(1); + EXPECT_EQ(dataAbilityRecord->Attach(abilitySchedulerMock_), ERR_OK); + abilityState_ = ACTIVE; + EXPECT_EQ(dataAbilityRecord->OnTransitionDone(abilityState_), ERR_OK); + + // first add client + EXPECT_EQ(dataAbilityRecord->AddClient(abilityRecord_->GetToken(), true, false), ERR_OK); + EXPECT_EQ(dataAbilityRecord->GetClientCount(abilityRecord_->GetToken()), (uint32_t)1); + + // second add client + EXPECT_EQ(dataAbilityRecord->AddClient(abilityRecord_->GetToken(), true, false), ERR_OK); + EXPECT_EQ(dataAbilityRecord->GetClientCount(abilityRecord_->GetToken()), (uint32_t)2); + + // remove the same client + EXPECT_EQ(dataAbilityRecord->RemoveClients(client), ERR_OK); + EXPECT_EQ(dataAbilityRecord->GetClientCount(abilityRecord_->GetToken()), (uint32_t)0); + + HILOG_INFO("AaFwk_DataAbilityRecord_RemoveClients_005 end."); +} + +/* + * Feature: AbilityManager + * Function: DataAbility + * SubFunction: GetClientCount + * FunctionPoints: The parameter of function GetClientCount. + * EnvConditions: Can run ohos test framework + * CaseDescription: Verify function GetClientCount, before call GetClientCount not startloading and not attach. + */ +HWTEST_F(DataAbilityRecordTest, AaFwk_DataAbilityRecord_GetClientCount_001, TestSize.Level1) +{ + HILOG_INFO("AaFwk_DataAbilityRecord_GetClientCount_001 start."); + + std::unique_ptr dataAbilityRecord = std::make_unique(abilityRequest_); + auto client = Token::GetAbilityRecordByToken(abilityRecord_->GetToken()); + + EXPECT_EQ(dataAbilityRecord->GetClientCount(abilityRecord_->GetToken()), (uint32_t)0); + + HILOG_INFO("AaFwk_DataAbilityRecord_GetClientCount_001 end."); +} + +/* + * Feature: AbilityManager + * Function: DataAbility + * SubFunction: GetClientCount + * FunctionPoints: The parameter of function GetClientCount. + * EnvConditions: Can run ohos test framework + * CaseDescription: Verify function GetClientCount ability state is not attach. + */ +HWTEST_F(DataAbilityRecordTest, AaFwk_DataAbilityRecord_GetClientCount_002, TestSize.Level1) +{ + HILOG_INFO("AaFwk_DataAbilityRecord_GetClientCount_002 start."); + + std::unique_ptr dataAbilityRecord = std::make_unique(abilityRequest_); + auto client = Token::GetAbilityRecordByToken(abilityRecord_->GetToken()); + + EXPECT_EQ(dataAbilityRecord->StartLoading(), ERR_OK); + EXPECT_EQ(dataAbilityRecord->GetClientCount(abilityRecord_->GetToken()), (uint32_t)0); + + HILOG_INFO("AaFwk_DataAbilityRecord_GetClientCount_002 end."); +} + +/* + * Feature: AbilityManager + * Function: DataAbility + * SubFunction: GetClientCount + * FunctionPoints: The parameter of function GetClientCount. + * EnvConditions: Can run ohos test framework + * CaseDescription: Verify function GetClientCount ability state is not inactive. + */ +HWTEST_F(DataAbilityRecordTest, AaFwk_DataAbilityRecord_GetClientCount_003, TestSize.Level1) +{ + HILOG_INFO("AaFwk_DataAbilityRecord_GetClientCount_003 start."); + + std::unique_ptr dataAbilityRecord = std::make_unique(abilityRequest_); + auto client = Token::GetAbilityRecordByToken(abilityRecord_->GetToken()); + + EXPECT_EQ(dataAbilityRecord->StartLoading(), ERR_OK); + EXPECT_CALL(*abilitySchedulerMock_, ScheduleAbilityTransaction(_, _)).Times(1); + EXPECT_EQ(dataAbilityRecord->Attach(abilitySchedulerMock_), ERR_OK); + EXPECT_EQ(dataAbilityRecord->GetClientCount(abilityRecord_->GetToken()), (uint32_t)0); + + HILOG_INFO("AaFwk_DataAbilityRecord_GetClientCount_003 end."); +} + +/* + * Feature: AbilityManager + * Function: DataAbility + * SubFunction: KillBoundClientProcesses + * FunctionPoints: The parameter of function KillBoundClientProcesses. + * EnvConditions: Can run ohos test framework + * CaseDescription: Verify function KillBoundClientProcesses, + * before call KillBoundClientProcesses not startloading and not attach. + */ +HWTEST_F(DataAbilityRecordTest, AaFwk_DataAbilityRecord_KillBoundClientProcesses_001, TestSize.Level1) +{ + HILOG_INFO("AaFwk_DataAbilityRecord_KillBoundClientProcesses_001 start."); + + std::unique_ptr dataAbilityRecord = std::make_unique(abilityRequest_); + + EXPECT_EQ(dataAbilityRecord->KillBoundClientProcesses(), ERR_INVALID_STATE); + + HILOG_INFO("AaFwk_DataAbilityRecord_KillBoundClientProcesses_001 end."); +} + +/* + * Feature: AbilityManager + * Function: DataAbility + * SubFunction: KillBoundClientProcesses + * FunctionPoints: The parameter of function KillBoundClientProcesses. + * EnvConditions: Can run ohos test framework + * CaseDescription: Verify function KillBoundClientProcesses ability state is not attach. + */ +HWTEST_F(DataAbilityRecordTest, AaFwk_DataAbilityRecord_KillBoundClientProcesses_002, TestSize.Level1) +{ + HILOG_INFO("AaFwk_DataAbilityRecord_KillBoundClientProcesses_002 start."); + + std::unique_ptr dataAbilityRecord = std::make_unique(abilityRequest_); + + EXPECT_EQ(dataAbilityRecord->StartLoading(), ERR_OK); + EXPECT_EQ(dataAbilityRecord->KillBoundClientProcesses(), ERR_INVALID_STATE); + + HILOG_INFO("AaFwk_DataAbilityRecord_KillBoundClientProcesses_002 end."); +} + +/* + * Feature: AbilityManager + * Function: DataAbility + * SubFunction: KillBoundClientProcesses + * FunctionPoints: The parameter of function KillBoundClientProcesses. + * EnvConditions: Can run ohos test framework + * CaseDescription: Verify function KillBoundClientProcesses ability state is not inactive. + */ +HWTEST_F(DataAbilityRecordTest, AaFwk_DataAbilityRecord_KillBoundClientProcesses_003, TestSize.Level1) +{ + HILOG_INFO("AaFwk_DataAbilityRecord_KillBoundClientProcesses_003 start."); + + std::unique_ptr dataAbilityRecord = std::make_unique(abilityRequest_); + + EXPECT_EQ(dataAbilityRecord->StartLoading(), ERR_OK); + EXPECT_CALL(*abilitySchedulerMock_, ScheduleAbilityTransaction(_, _)).Times(1); + EXPECT_EQ(dataAbilityRecord->Attach(abilitySchedulerMock_), ERR_OK); + EXPECT_EQ(dataAbilityRecord->KillBoundClientProcesses(), ERR_INVALID_STATE); + + HILOG_INFO("AaFwk_DataAbilityRecord_KillBoundClientProcesses_003 end."); +} + +/* + * Feature: AbilityManager + * Function: DataAbility + * SubFunction: KillBoundClientProcesses + * FunctionPoints: The parameter of function KillBoundClientProcesses. + * EnvConditions: Can run ohos test framework + * CaseDescription: Verify function KillBoundClientProcesses ability state is not inactive. + */ +HWTEST_F(DataAbilityRecordTest, AaFwk_DataAbilityRecord_KillBoundClientProcesses_004, TestSize.Level1) +{ + HILOG_INFO("AaFwk_DataAbilityRecord_KillBoundClientProcesses_004 start."); + + std::unique_ptr dataAbilityRecord = std::make_unique(abilityRequest_); + + EXPECT_EQ(dataAbilityRecord->StartLoading(), ERR_OK); + EXPECT_CALL(*abilitySchedulerMock_, ScheduleAbilityTransaction(_, _)).Times(1); + EXPECT_EQ(dataAbilityRecord->Attach(abilitySchedulerMock_), ERR_OK); + abilityState_ = ACTIVE; + EXPECT_EQ(dataAbilityRecord->OnTransitionDone(abilityState_), ERR_OK); + EXPECT_EQ(dataAbilityRecord->KillBoundClientProcesses(), ERR_OK); + + HILOG_INFO("AaFwk_DataAbilityRecord_KillBoundClientProcesses_004 end."); +} +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/abilitymgr/test/unittest/phone/info_test/BUILD.gn b/tools/services/abilitymgr/test/unittest/phone/info_test/BUILD.gn new file mode 100644 index 00000000000..f24ea06bb82 --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/info_test/BUILD.gn @@ -0,0 +1,67 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/test.gni") +import("//foundation/aafwk/standard/aafwk.gni") + +module_output_path = "aafwk_standard/abilitymgr" + +ohos_unittest("info_test") { + module_out_path = module_output_path + + include_dirs = [ + "${services_path}/abilitymgr/test/mock/libs/system_ability_mock", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy/include", + ] + + sources = [ + "//foundation/aafwk/standard/services/abilitymgr/test/mock/libs/appexecfwk_core/src/appmgr/mock_app_scheduler.cpp", + "info_test.cpp", # add mock file + ] + + configs = [ + "${services_path}/abilitymgr:abilityms_config", + "${services_path}/abilitymgr/test/mock:aafwk_mock_config", + ] + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + deps = [ + "${innerkits_path}/want:want", + "${services_path}/abilitymgr/test:abilityms_test_source", + "${services_path}/abilitymgr/test/mock/libs/aakit:aakit_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_appmgr_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_bundlemgr_mock", + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/frameworks/kits/ability/native:dummy_classes", + + # "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//third_party/googletest:gmock_main", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] +} + +group("unittest") { + testonly = true + + deps = [ ":info_test" ] +} diff --git a/tools/services/abilitymgr/test/unittest/phone/info_test/info_test.cpp b/tools/services/abilitymgr/test/unittest/phone/info_test/info_test.cpp new file mode 100755 index 00000000000..e8cfb14080c --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/info_test/info_test.cpp @@ -0,0 +1,311 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "stack_info.h" +#include "lifecycle_state_info.h" +#include "image_info.h" +#include "mission_snapshot_info.h" +#include "mission_description_info.h" +#include "ability_mission_info.h" + +using namespace testing::ext; + +namespace OHOS { +namespace AAFwk { +class InfoTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + + StackInfo Stackinfo_{}; + MissionStackInfo missionStackInfo_{}; + MissionRecordInfo missionRecordInfo_{}; + AbilityRecordInfo abilityRecordInfo_{}; + LifeCycleStateInfo lifeCycleStateInfo_{}; + ImageInfo imageInfo_{}; + ImageHeader imageHeader_{}; + MissionSnapshotInfo missionSnapshotInfo_{}; + MissionDescriptionInfo missionDescriptionInfo_{}; + AbilityMissionInfo recentMissionInfo_{}; +}; + +void InfoTest::SetUpTestCase(void) +{} +void InfoTest::TearDownTestCase(void) +{} +void InfoTest::SetUp() +{} +void InfoTest::TearDown() +{} + +/* + * Feature: StackInfo + * Function: ReadFromParcel and Marshalling and Unmarshalling + * SubFunction: NA + * FunctionPoints: StackInfo ReadFromParcel and Marshalling and Unmarshalling + * EnvConditions:NA + * CaseDescription: The process of verifying stackenfo parcel + */ +HWTEST_F(InfoTest, stack_info_oprator_001, TestSize.Level0) +{ + MissionStackInfo missionInfo; + missionInfo.id = 10; + Stackinfo_.missionStackInfos.emplace_back(missionInfo); + Parcel parcel; + Stackinfo_.Marshalling(parcel); + StackInfo info; + StackInfo *obj = info.Unmarshalling(parcel); + if (!obj) { + return; + } + EXPECT_TRUE(obj != nullptr); + + if (!obj->missionStackInfos.empty()) { + EXPECT_EQ(obj->missionStackInfos[0].id, missionInfo.id); + } +} + +/* + * Feature: MissionStackInfo + * Function: ReadFromParcel and Marshalling and Unmarshalling + * SubFunction: NA + * FunctionPoints: MissionStackInfo ReadFromParcel and Marshalling and Unmarshalling + * EnvConditions:NA + * CaseDescription: The process of verifying MissionStackInfo parcel + */ +HWTEST_F(InfoTest, stack_info_oprator_002, TestSize.Level0) +{ + MissionRecordInfo info; + info.id = 1; + missionStackInfo_.id = 10; + missionStackInfo_.missionRecords.emplace_back(info); + Parcel parcel; + missionStackInfo_.Marshalling(parcel); + MissionStackInfo *obj = missionStackInfo_.Unmarshalling(parcel); + if (!obj) { + return; + } + EXPECT_TRUE(obj); + EXPECT_EQ(obj->id, missionStackInfo_.id); + EXPECT_EQ(obj->missionRecords[0].id, info.id); +} + +/* + * Feature: MissionRecordInfo + * Function: ReadFromParcel and Marshalling and Unmarshalling + * SubFunction: NA + * FunctionPoints: MissionRecordInfo ReadFromParcel and Marshalling and Unmarshalling + * EnvConditions:NA + * CaseDescription: The process of verifying MissionRecordInfo parcel + */ +HWTEST_F(InfoTest, stack_info_oprator_003, TestSize.Level0) +{ + AbilityRecordInfo info; + info.id = 10; + info.elementName = "test"; + info.appName = "app"; + info.mainName = "main"; + info.abilityType = 3; + info.previousAppName = "preApp"; + info.previousMainName = "preMain"; + info.nextAppName = "nextApp"; + info.nextMainName = "nextMain"; + info.state = AbilityState::BACKGROUND; + info.startTime = "1:00"; + info.ready = true; + info.windowAttached = true; + info.lanucher = true; + missionRecordInfo_.id = 10; + missionRecordInfo_.abilityRecordInfos.emplace_back(info); + Parcel parcel; + missionRecordInfo_.Marshalling(parcel); + MissionRecordInfo *obj = missionRecordInfo_.Unmarshalling(parcel); + if (!obj) { + return; + } + EXPECT_TRUE(obj); + EXPECT_EQ(obj->id, missionRecordInfo_.id); + EXPECT_EQ(obj->abilityRecordInfos[0].id, info.id); + EXPECT_EQ(obj->abilityRecordInfos[0].elementName, info.elementName); + EXPECT_EQ(obj->abilityRecordInfos[0].appName, info.appName); + EXPECT_EQ(obj->abilityRecordInfos[0].mainName, info.mainName); + EXPECT_EQ(obj->abilityRecordInfos[0].abilityType, info.abilityType); + EXPECT_EQ(obj->abilityRecordInfos[0].previousAppName, info.previousAppName); + EXPECT_EQ(obj->abilityRecordInfos[0].previousMainName, info.previousMainName); + EXPECT_EQ(obj->abilityRecordInfos[0].nextAppName, info.nextAppName); + EXPECT_EQ(obj->abilityRecordInfos[0].nextMainName, info.nextMainName); + EXPECT_EQ(obj->abilityRecordInfos[0].state, info.state); + EXPECT_EQ(obj->abilityRecordInfos[0].startTime, info.startTime); + EXPECT_EQ(obj->abilityRecordInfos[0].ready, info.ready); + EXPECT_EQ(obj->abilityRecordInfos[0].windowAttached, info.windowAttached); + EXPECT_EQ(obj->abilityRecordInfos[0].lanucher, info.lanucher); +} + +/* + * Feature: AbilityRecordInfo + * Function: ReadFromParcel and Marshalling and Unmarshalling + * SubFunction: NA + * FunctionPoints: AbilityRecordInfo ReadFromParcel and Marshalling and Unmarshalling + * EnvConditions:NA + * CaseDescription: The process of verifying AbilityRecordInfo parcel + */ +HWTEST_F(InfoTest, stack_info_oprator_004, TestSize.Level0) +{ + abilityRecordInfo_.id = 10; + abilityRecordInfo_.elementName = "test"; + abilityRecordInfo_.appName = "app"; + abilityRecordInfo_.mainName = "main"; + abilityRecordInfo_.abilityType = 3; + abilityRecordInfo_.previousAppName = "preApp"; + abilityRecordInfo_.previousMainName = "preMain"; + abilityRecordInfo_.nextAppName = "nextApp"; + abilityRecordInfo_.nextMainName = "nextMain"; + abilityRecordInfo_.state = AbilityState::BACKGROUND; + abilityRecordInfo_.startTime = "1:00"; + abilityRecordInfo_.ready = true; + abilityRecordInfo_.windowAttached = true; + abilityRecordInfo_.lanucher = true; + Parcel parcel; + abilityRecordInfo_.Marshalling(parcel); + AbilityRecordInfo *obj = abilityRecordInfo_.Unmarshalling(parcel); + if (!obj) { + return; + } + EXPECT_TRUE(obj); + + EXPECT_EQ(obj->id, abilityRecordInfo_.id); + EXPECT_EQ(obj->elementName, abilityRecordInfo_.elementName); + EXPECT_EQ(obj->appName, abilityRecordInfo_.appName); + EXPECT_EQ(obj->mainName, abilityRecordInfo_.mainName); + EXPECT_EQ(obj->abilityType, abilityRecordInfo_.abilityType); + EXPECT_EQ(obj->previousAppName, abilityRecordInfo_.previousAppName); + EXPECT_EQ(obj->previousMainName, abilityRecordInfo_.previousMainName); + EXPECT_EQ(obj->nextAppName, abilityRecordInfo_.nextAppName); + EXPECT_EQ(obj->nextMainName, abilityRecordInfo_.nextMainName); + EXPECT_EQ(obj->state, abilityRecordInfo_.state); + EXPECT_EQ(obj->startTime, abilityRecordInfo_.startTime); + EXPECT_EQ(obj->ready, abilityRecordInfo_.ready); + EXPECT_EQ(obj->windowAttached, abilityRecordInfo_.windowAttached); + EXPECT_EQ(obj->lanucher, abilityRecordInfo_.lanucher); +} + +/* + * Feature: LifeCycleStateInfo + * Function: ReadFromParcel and Marshalling and Unmarshalling + * SubFunction: NA + * FunctionPoints: LifeCycleStateInfo ReadFromParcel and Marshalling and Unmarshalling + * EnvConditions:NA + * CaseDescription: The process of verifying LifeCycleStateInfo parcel + */ +HWTEST_F(InfoTest, stack_info_oprator_005, TestSize.Level0) +{ + lifeCycleStateInfo_.isNewWant = 10; + lifeCycleStateInfo_.state = AbilityLifeCycleState::ABILITY_STATE_BACKGROUND; + Parcel parcel; + lifeCycleStateInfo_.Marshalling(parcel); + LifeCycleStateInfo *obj = lifeCycleStateInfo_.Unmarshalling(parcel); + if (!obj) { + return; + } + EXPECT_TRUE(obj); + + EXPECT_EQ(obj->isNewWant, lifeCycleStateInfo_.isNewWant); + EXPECT_EQ(obj->state, lifeCycleStateInfo_.state); +} + +/* + * Feature: ImageHeader + * Function: ReadFromParcel and Marshalling and Unmarshalling + * SubFunction: NA + * FunctionPoints: ImageHeader ReadFromParcel and Marshalling and Unmarshalling + * EnvConditions:NA + * CaseDescription: The process of verifying ImageHeader parcel + */ +HWTEST_F(InfoTest, stack_info_oprator_007, TestSize.Level0) +{ + imageHeader_.colorMode = 8; + imageHeader_.reserved = 24; + imageHeader_.width = 10; + imageHeader_.height = 10; + Parcel parcel; + imageHeader_.Marshalling(parcel); + ImageHeader *obj = imageHeader_.Unmarshalling(parcel); + if (!obj) { + return; + } + EXPECT_TRUE(obj); + EXPECT_EQ(obj->colorMode, imageHeader_.colorMode); + EXPECT_EQ(obj->reserved, imageHeader_.reserved); + EXPECT_EQ(obj->width, imageHeader_.width); + EXPECT_EQ(obj->height, imageHeader_.height); +} + +/* + * Feature: MissionDescriptionInfo + * Function: ReadFromParcel and Marshalling and Unmarshalling + * SubFunction: NA + * FunctionPoints: MissionDescriptionInfo ReadFromParcel and Marshalling and Unmarshalling + * EnvConditions:NA + * CaseDescription: The process of verifying MissionDescriptionInfo parcel + */ +HWTEST_F(InfoTest, stack_info_oprator_008, TestSize.Level0) +{ + missionDescriptionInfo_.label = "label"; + missionDescriptionInfo_.iconPath = "iconpath"; + Parcel parcel; + missionDescriptionInfo_.Marshalling(parcel); + MissionDescriptionInfo *obj = missionDescriptionInfo_.Unmarshalling(parcel); + EXPECT_NE(obj, nullptr); + if (!obj) { + return; + } + EXPECT_EQ(obj->label, missionDescriptionInfo_.label); + EXPECT_EQ(obj->iconPath, missionDescriptionInfo_.iconPath); +} + +/* + * Feature: AbilityMissionInfo + * Function: ReadFromParcel and Marshalling and Unmarshalling + * SubFunction: NA + * FunctionPoints: AbilityMissionInfo ReadFromParcel and Marshalling and Unmarshalling + * EnvConditions:NA + * CaseDescription: The process of verifying AbilityMissionInfo parcel + */ +HWTEST_F(InfoTest, stack_info_oprator_009, TestSize.Level0) +{ + recentMissionInfo_.id = 10; + recentMissionInfo_.runingState = -1; + recentMissionInfo_.size = -1; + MissionDescriptionInfo missionDescriptionInfo; + missionDescriptionInfo.label = "label"; + missionDescriptionInfo.iconPath = "iconpath"; + recentMissionInfo_.missionDescription = missionDescriptionInfo; + Parcel parcel; + recentMissionInfo_.Marshalling(parcel); + AbilityMissionInfo *obj = recentMissionInfo_.Unmarshalling(parcel); + if (!obj) { + return; + } + EXPECT_TRUE(obj); + EXPECT_EQ(obj->id, recentMissionInfo_.id); + EXPECT_EQ(obj->runingState, recentMissionInfo_.runingState); + EXPECT_EQ(obj->size, recentMissionInfo_.size); + EXPECT_EQ(obj->missionDescription.label, missionDescriptionInfo.label); +} +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/abilitymgr/test/unittest/phone/kernal_system_app_manager_test/BUILD.gn b/tools/services/abilitymgr/test/unittest/phone/kernal_system_app_manager_test/BUILD.gn new file mode 100644 index 00000000000..9b5e5f529d1 --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/kernal_system_app_manager_test/BUILD.gn @@ -0,0 +1,68 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/test.gni") +import("//foundation/aafwk/standard/aafwk.gni") + +module_output_path = "aafwk_standard/abilitymgr" + +ohos_unittest("kernal_system_app_mgr_test") { + module_out_path = module_output_path + + include_dirs = [ + "${services_path}/abilitymgr/test/mock/libs/system_ability_mock", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy/include", + "//foundation/distributedschedule/samgr/adapter/interfaces/innerkits/include/", + "//foundation/aafwk/standard/services/abilitymgr/test/mock/libs/ability_scheduler_mock", + "//foundation/aafwk/standard/services/abilitymgr/include/", + "//foundation/aafwk/standard/services/abilitymgr/test/mock/libs/appexecfwk_core/include", + "//foundation/aafwk/standard/services/abilitymgr/test/mock/include", + "//foundation/aafwk/standard/services/abilitymgr/include", + ] + + sources = [ + "//foundation/aafwk/standard/services/abilitymgr/test/mock/libs/appexecfwk_core/src/appmgr/mock_app_scheduler.cpp", + "kernal_system_app_manager_test.cpp", # add mock file + ] + + configs = [ "${services_path}/abilitymgr:abilityms_config" ] + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + deps = [ + "${innerkits_path}/want:want", + "${services_path}/abilitymgr/test:abilityms_test_source", + "${services_path}/abilitymgr/test/mock/libs/aakit:aakit_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_appmgr_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_bundlemgr_mock", + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/frameworks/kits/ability/native:dummy_classes", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//third_party/googletest:gmock_main", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] +} + +group("unittest") { + testonly = true + + deps = [ ":kernal_system_app_mgr_test" ] +} diff --git a/tools/services/abilitymgr/test/unittest/phone/kernal_system_app_manager_test/kernal_system_app_manager_test.cpp b/tools/services/abilitymgr/test/unittest/phone/kernal_system_app_manager_test/kernal_system_app_manager_test.cpp new file mode 100755 index 00000000000..c30be1259cb --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/kernal_system_app_manager_test/kernal_system_app_manager_test.cpp @@ -0,0 +1,638 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#if 1 +#include + +#define private public +#include "sa_mgr_client.h" +#include "kernal_system_app_manager.h" +#include "app_scheduler.h" +#undef private + +#include "ability_config.h" +#include "ability_manager_service.h" +#include "ability_manager_errors.h" +#include "ability_scheduler_mock.h" +#include "bundlemgr/mock_bundle_manager.h" +#include "mock_app_manager_client.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace AAFwk { + +static void WaitUntilTaskFinished() +{ + const uint32_t maxRetryCount = 1000; + const uint32_t sleepTime = 1000; + uint32_t count = 0; + auto handler = OHOS::DelayedSingleton::GetInstance()->GetEventHandler(); + std::atomic taskCalled(false); + auto f = [&taskCalled]() { taskCalled.store(true); }; + if (handler->PostTask(f)) { + while (!taskCalled.load()) { + ++count; + if (count >= maxRetryCount) { + break; + } + usleep(sleepTime); + } + } +} + +class KernalSystemAppManagerTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp(); + void TearDown(); + void StartSystemUI(); + +public: + std::shared_ptr kernalSystemMgr_{nullptr}; + int usrId_ = 10; + Want want_{}; + AppExecFwk::AbilityInfo abilityInfo_{}; + AppExecFwk::ApplicationInfo appInfo_{}; +}; + +void KernalSystemAppManagerTest::SetUpTestCase() +{ + int systemAbilityId = 401; + OHOS::DelayedSingleton::GetInstance()->RegisterSystemAbility( + systemAbilityId, new (std::nothrow) AppExecFwk::BundleMgrService()); + DelayedSingleton::GetInstance(); + DelayedSingleton::GetInstance()->OnStart(); +} + +void KernalSystemAppManagerTest::TearDownTestCase() +{ + OHOS::DelayedSingleton::GetInstance()->OnStop(); + OHOS::DelayedSingleton::DestroyInstance(); + + OHOS::DelayedSingleton::DestroyInstance(); +} + +void KernalSystemAppManagerTest::SetUp() +{ + kernalSystemMgr_ = std::make_shared(usrId_); + kernalSystemMgr_->abilities_.clear(); + std::queue().swap(kernalSystemMgr_->waittingAbilityQueue_); +} + +void KernalSystemAppManagerTest::TearDown() +{ + kernalSystemMgr_.reset(); +} + +void KernalSystemAppManagerTest::StartSystemUI() +{ + Want want; + want.SetElementName(AbilityConfig::SYSTEM_UI_BUNDLE_NAME, AbilityConfig::SYSTEM_UI_STATUS_BAR); + + AbilityRequest request; + request.want = want; + request.requestCode = -1; + request.callerToken = nullptr; + request.abilityInfo.name = AbilityConfig::SYSTEM_UI_STATUS_BAR; + request.abilityInfo.bundleName = AbilityConfig::SYSTEM_UI_BUNDLE_NAME; + request.appInfo.isLauncherApp = true; + request.appInfo.name = AbilityConfig::SYSTEM_UI_STATUS_BAR; + request.appInfo.bundleName = AbilityConfig::SYSTEM_UI_BUNDLE_NAME; + + EXPECT_TRUE(kernalSystemMgr_); + + auto ref = kernalSystemMgr_->StartAbility(request); + WaitUntilTaskFinished(); + EXPECT_EQ(ERR_OK, ref); +} + +/* + * Feature: KernalSystemAppManager + * Function: StartAbility,StartAbilityLocked + * SubFunction: Processing preconditions + * FunctionPoints: KernalSystemAppManager StartAbility + * EnvConditions:Is Kernal System Ability + * CaseDescription: Start a system level aa + */ +HWTEST_F(KernalSystemAppManagerTest, StartAbility_001, TestSize.Level1) +{ + // start a system ui + Want want; + want.SetElementName(AbilityConfig::SYSTEM_UI_BUNDLE_NAME, AbilityConfig::SYSTEM_UI_STATUS_BAR); + + AbilityRequest request; + request.want = want; + request.requestCode = -1; + request.callerToken = nullptr; + request.abilityInfo.name = AbilityConfig::SYSTEM_UI_STATUS_BAR; + request.abilityInfo.bundleName = AbilityConfig::SYSTEM_UI_BUNDLE_NAME; + request.appInfo.isLauncherApp = true; + request.appInfo.name = "syetemUi"; + request.appInfo.bundleName = AbilityConfig::SYSTEM_UI_BUNDLE_NAME; + EXPECT_TRUE(kernalSystemMgr_); + + auto ref = kernalSystemMgr_->StartAbility(request); + WaitUntilTaskFinished(); + EXPECT_EQ(ERR_OK, ref); + EXPECT_EQ(static_cast(kernalSystemMgr_->abilities_.size()), 1); + + auto topAbilityRecord = kernalSystemMgr_->GetCurrentTopAbility(); + EXPECT_TRUE(topAbilityRecord); + EXPECT_TRUE(topAbilityRecord->IsKernalSystemAbility()); + topAbilityRecord->SetAbilityState(AbilityState::INITIAL); + + // start agin + auto refBegin = kernalSystemMgr_->StartAbility(request); + WaitUntilTaskFinished(); + EXPECT_EQ(ERR_OK, refBegin); + // same aa, so size is 1. Just update not push + EXPECT_EQ(static_cast(kernalSystemMgr_->abilities_.size()), 1); + EXPECT_TRUE(topAbilityRecord->IsNewWant()); +} + +/* + * Feature: KernalSystemAppManager + * Function: StartAbility,StartAbilityLocked + * SubFunction: Processing preconditions + * FunctionPoints: KernalSystemAppManager StartAbility + * EnvConditions:Is Kernal System Ability + * CaseDescription: Start a system level aa + */ +HWTEST_F(KernalSystemAppManagerTest, StartAbility_002, TestSize.Level1) +{ + // start a system ui + Want want; + want.SetElementName(AbilityConfig::SYSTEM_UI_BUNDLE_NAME, AbilityConfig::SYSTEM_UI_STATUS_BAR); + AbilityRequest request; + request.want = want; + request.requestCode = -1; + request.callerToken = nullptr; + request.abilityInfo.name = AbilityConfig::SYSTEM_UI_STATUS_BAR; + request.abilityInfo.bundleName = AbilityConfig::SYSTEM_UI_BUNDLE_NAME; + request.appInfo.isLauncherApp = true; + request.appInfo.name = "syetemUi"; + request.appInfo.bundleName = AbilityConfig::SYSTEM_UI_BUNDLE_NAME; + + Want wantBar; + wantBar.SetElementName(AbilityConfig::SYSTEM_UI_BUNDLE_NAME, AbilityConfig::SYSTEM_UI_NAVIGATION_BAR); + AbilityRequest requestBar; + requestBar.want = wantBar; + requestBar.requestCode = -1; + requestBar.callerToken = nullptr; + requestBar.abilityInfo.name = AbilityConfig::SYSTEM_UI_STATUS_BAR; + requestBar.abilityInfo.bundleName = AbilityConfig::SYSTEM_UI_NAVIGATION_BAR; + requestBar.appInfo.isLauncherApp = true; + requestBar.appInfo.name = "syetemUi"; + requestBar.appInfo.bundleName = AbilityConfig::SYSTEM_UI_BUNDLE_NAME; + + // nullptr name and bundlename + Want wantPage; + AbilityRequest requestPage; + requestPage.want = wantPage; + requestPage.requestCode = -1; + requestPage.callerToken = nullptr; + EXPECT_TRUE(kernalSystemMgr_); + + int firstStartRef = kernalSystemMgr_->StartAbility(request); + WaitUntilTaskFinished(); + auto topAbilityRecord = kernalSystemMgr_->GetCurrentTopAbility(); + EXPECT_TRUE(topAbilityRecord); + topAbilityRecord->SetAbilityState(AbilityState::ACTIVATING); + + int secondStartRef = kernalSystemMgr_->StartAbility(requestBar); + int thirdStartRef = kernalSystemMgr_->StartAbility(requestPage); + + EXPECT_EQ(static_cast(kernalSystemMgr_->abilities_.size()), 1); + EXPECT_EQ(static_cast(kernalSystemMgr_->waittingAbilityQueue_.size()), 2); + EXPECT_EQ(ERR_OK, firstStartRef); + EXPECT_EQ(START_ABILITY_WAITING, secondStartRef); + EXPECT_EQ(START_ABILITY_WAITING, thirdStartRef); +} + +/* + * Feature: KernalSystemAppManager + * Function: AttachAbilityThread + * SubFunction: binding app + * FunctionPoints: bingding app and move to forground + * EnvConditions:Is Kernal System Ability + * CaseDescription: have a ability to attach + */ +HWTEST_F(KernalSystemAppManagerTest, AttachAbilityThread_001, TestSize.Level1) +{ + EXPECT_TRUE(kernalSystemMgr_); + sptr scheduler = nullptr; + sptr token = nullptr; + + int ref = kernalSystemMgr_->AttachAbilityThread(scheduler, token); + EXPECT_EQ(ERR_INVALID_VALUE, ref); + + StartSystemUI(); + auto topAbilityRecord = kernalSystemMgr_->GetCurrentTopAbility(); + EXPECT_TRUE(topAbilityRecord); + // scheduler judge null is on the upper level, in ams, so is return ok + ref = kernalSystemMgr_->AttachAbilityThread(scheduler, topAbilityRecord->GetToken()); + EXPECT_EQ(ERR_OK, ref); + + sptr mokecheduler = new AbilitySchedulerMock(); + ref = kernalSystemMgr_->AttachAbilityThread(mokecheduler, topAbilityRecord->GetToken()); + EXPECT_EQ(ERR_OK, ref); +} + +/* + * Feature: KernalSystemAppManager + * Function: AbilityTransitionDone + * SubFunction: Processing preconditions + * FunctionPoints: KernalSystemAppManager StartAbility + * EnvConditions:Is Kernal System Ability + * CaseDescription: Notification status + */ +HWTEST_F(KernalSystemAppManagerTest, AbilityTransitionDone_001, TestSize.Level1) +{ + EXPECT_TRUE(kernalSystemMgr_); + sptr token = nullptr; + + int ref = kernalSystemMgr_->AbilityTransitionDone(token, -1); + EXPECT_EQ(ERR_INVALID_VALUE, ref); + + StartSystemUI(); + auto topAbilityRecord = kernalSystemMgr_->GetCurrentTopAbility(); + EXPECT_TRUE(topAbilityRecord); + ref = kernalSystemMgr_->AbilityTransitionDone(topAbilityRecord->GetToken(), -1); + EXPECT_EQ(ERR_INVALID_VALUE, ref); + + // The right example + topAbilityRecord->SetAbilityState(AbilityState::ACTIVATING); + ref = kernalSystemMgr_->AbilityTransitionDone(topAbilityRecord->GetToken(), AbilityState::ACTIVE); + EXPECT_EQ(ERR_OK, ref); + WaitUntilTaskFinished(); + + ref = kernalSystemMgr_->AbilityTransitionDone(topAbilityRecord->GetToken(), AbilityState::INITIAL); + EXPECT_EQ(ERR_INVALID_VALUE, ref); +} + +/* + * Feature: KernalSystemAppManagerssssssssssssssss + * Function: OnAbilityRequestDone + * SubFunction: Processing preconditions + * FunctionPoints: KernalSystemAppManager OnAbilityRequestDone + * EnvConditions:Is Kernal System Ability + * CaseDescription: Notification status + */ +HWTEST_F(KernalSystemAppManagerTest, OnAbilityRequestDone_001, TestSize.Level1) +{ + EXPECT_TRUE(kernalSystemMgr_); + StartSystemUI(); + auto topAbilityRecord = kernalSystemMgr_->GetCurrentTopAbility(); + EXPECT_TRUE(topAbilityRecord); + kernalSystemMgr_->OnAbilityRequestDone(topAbilityRecord->GetToken(), -1); + EXPECT_NE(topAbilityRecord->GetAbilityState(), AbilityState::ACTIVATING); + + kernalSystemMgr_->OnAbilityRequestDone( + topAbilityRecord->GetToken(), static_cast(AppExecFwk::AbilityState::ABILITY_STATE_FOREGROUND)); + EXPECT_EQ(topAbilityRecord->GetAbilityState(), AbilityState::ACTIVATING); +} + +/* + * Feature: KernalSystemAppManager + * Function: OnAbilityRequestDone + * SubFunction: Processing preconditions + * FunctionPoints: KernalSystemAppManager OnAbilityRequestDone + * EnvConditions:Is Kernal System Ability + * CaseDescription: Notification status + */ +HWTEST_F(KernalSystemAppManagerTest, GetManagerUserId_001, TestSize.Level1) +{ + EXPECT_TRUE(kernalSystemMgr_); + StartSystemUI(); + int testUserID = kernalSystemMgr_->GetManagerUserId(); + EXPECT_EQ(10, testUserID); +} + +/* + * Feature: KernalSystemAppManager + * Function: DumpState + * SubFunction: Processing preconditions + * FunctionPoints: + * EnvConditions:Is Kernal System Ability + * CaseDescription: Notification status + */ +HWTEST_F(KernalSystemAppManagerTest, DumpState_001, TestSize.Level1) +{ + EXPECT_TRUE(kernalSystemMgr_); + StartSystemUI(); + std::vector info; + kernalSystemMgr_->DumpState(info); + + auto isFindAbilityInfo = [](std::string &abilityInfo) { + return std::string::npos != abilityInfo.find(AbilityConfig::SYSTEM_UI_BUNDLE_NAME); + }; + // find the SYSTEM_UI_BUNDLE_NAME + EXPECT_NE(info.end(), std::find_if(info.begin(), info.end(), isFindAbilityInfo)); +} + +/* + * Feature: KernalSystemAppManager + * Function: OnAbilityDied + * SubFunction: Processing preconditions + * FunctionPoints: + * EnvConditions:Is Kernal System Ability + * CaseDescription: Notification ability died + */ +HWTEST_F(KernalSystemAppManagerTest, OnAbilityDied_001, TestSize.Level1) +{ + EXPECT_TRUE(kernalSystemMgr_); + StartSystemUI(); + auto topAbilityRecord = kernalSystemMgr_->GetCurrentTopAbility(); + EXPECT_TRUE(topAbilityRecord); + kernalSystemMgr_->OnAbilityDied(topAbilityRecord); + EXPECT_EQ(topAbilityRecord->GetAbilityState(), AbilityState::INITIAL); +} + +/* + * Feature: KernalSystemAppManager + * Function: OnAbilityDied + * SubFunction: Processing preconditions + * FunctionPoints: + * EnvConditions:Is Kernal System Ability + * CaseDescription: Notification status + */ +HWTEST_F(KernalSystemAppManagerTest, OnAbilityDied_002, TestSize.Level1) +{ + EXPECT_TRUE(kernalSystemMgr_); + StartSystemUI(); + auto topAbilityRecord = kernalSystemMgr_->GetCurrentTopAbility(); + EXPECT_TRUE(topAbilityRecord); + kernalSystemMgr_->OnAbilityDied(topAbilityRecord); + EXPECT_EQ(topAbilityRecord->GetAbilityState(), AbilityState::INITIAL); +} + +/* + * Feature: KernalSystemAppManager + * Function: OnAbilityDied + * SubFunction: Processing preconditions + * FunctionPoints: + * EnvConditions:Is Kernal System Ability + * CaseDescription: Notification status + */ +HWTEST_F(KernalSystemAppManagerTest, OnTimeOut_001, TestSize.Level1) +{ + EXPECT_TRUE(kernalSystemMgr_); + StartSystemUI(); + auto topAbilityRecord = kernalSystemMgr_->GetCurrentTopAbility(); + EXPECT_TRUE(topAbilityRecord); + std::vector info; + kernalSystemMgr_->DumpState(info); + auto isFindAbilityInfo = [](std::string &abilityInfo) { + return std::string::npos != abilityInfo.find(AbilityConfig::SYSTEM_UI_BUNDLE_NAME); + }; + EXPECT_NE(info.end(), std::find_if(info.begin(), info.end(), isFindAbilityInfo)); + + // remove form vector; + kernalSystemMgr_->OnTimeOut(AbilityManagerService::LOAD_TIMEOUT_MSG, topAbilityRecord->GetEventId()); + + info.clear(); + kernalSystemMgr_->DumpState(info); + // topAbilityRecord must be delete + EXPECT_EQ(info.end(), std::find_if(info.begin(), info.end(), isFindAbilityInfo)); +} +/* + * Feature: KernalSystemAppManager + * Function: DequeueWaittingAbility + * SubFunction: Processing preconditions + * FunctionPoints: + * EnvConditions:Is Kernal System Ability + * CaseDescription: Notification status + */ +HWTEST_F(KernalSystemAppManagerTest, DequeueWaittingAbility_001, TestSize.Level1) +{ + EXPECT_TRUE(kernalSystemMgr_); + StartSystemUI(); + auto topAbilityRecord = kernalSystemMgr_->GetCurrentTopAbility(); + EXPECT_TRUE(topAbilityRecord); + topAbilityRecord->SetAbilityState(AbilityState::ACTIVATING); + + Want want; + AbilityRequest request; + request.want = want; + request.requestCode = -1; + request.callerToken = nullptr; + request.abilityInfo.name = AbilityConfig::SYSTEM_UI_STATUS_BAR; + request.abilityInfo.bundleName = AbilityConfig::SYSTEM_UI_BUNDLE_NAME; + request.appInfo.isLauncherApp = true; + request.appInfo.name = "syetemUi"; + request.appInfo.bundleName = AbilityConfig::SYSTEM_UI_BUNDLE_NAME; + + // push in waiting queue; + kernalSystemMgr_->StartAbility(request); + EXPECT_EQ(static_cast(kernalSystemMgr_->waittingAbilityQueue_.size()), 1); + + topAbilityRecord->SetAbilityState(AbilityState::ACTIVE); + kernalSystemMgr_->DequeueWaittingAbility(); + EXPECT_EQ(static_cast(kernalSystemMgr_->waittingAbilityQueue_.size()), 0); +} + +/* + * Feature: KernalSystemAppManager + * Function: DequeueWaittingAbility + * SubFunction: Processing preconditions + * FunctionPoints: + * EnvConditions:Is Kernal System Ability + * CaseDescription: Notification status + */ +HWTEST_F(KernalSystemAppManagerTest, GetOrCreateAbilityRecord_001, TestSize.Level1) +{ + EXPECT_TRUE(kernalSystemMgr_); + + Want want; + AbilityRequest request; + request.want = want; + request.requestCode = -1; + request.callerToken = nullptr; + request.abilityInfo.name = AbilityConfig::SYSTEM_UI_STATUS_BAR; + request.abilityInfo.bundleName = AbilityConfig::SYSTEM_UI_BUNDLE_NAME; + request.appInfo.isLauncherApp = true; + request.appInfo.name = "syetemUi"; + request.appInfo.bundleName = AbilityConfig::SYSTEM_UI_BUNDLE_NAME; + + std::shared_ptr targetAbility; + EXPECT_FALSE(targetAbility); + kernalSystemMgr_->GetOrCreateAbilityRecord(request, targetAbility); + + EXPECT_EQ(static_cast(kernalSystemMgr_->abilities_.size()), 1); + EXPECT_TRUE(targetAbility); + EXPECT_FALSE(targetAbility->IsNewWant()); + + // again + kernalSystemMgr_->GetOrCreateAbilityRecord(request, targetAbility); + EXPECT_TRUE(targetAbility->IsNewWant()); +} + +/* + * Feature: KernalSystemAppManager + * Function: DequeueWaittingAbility + * SubFunction: Processing preconditions + * FunctionPoints: + * EnvConditions:Is Kernal System Ability + * CaseDescription: Notification status + */ +HWTEST_F(KernalSystemAppManagerTest, GetOrCreateAbilityRecord_002, TestSize.Level1) +{ + EXPECT_TRUE(kernalSystemMgr_); + + Want want; + AbilityRequest request; + request.want = want; + request.requestCode = -1; + request.callerToken = nullptr; + request.abilityInfo.name = AbilityConfig::SYSTEM_UI_STATUS_BAR; + request.abilityInfo.bundleName = AbilityConfig::SYSTEM_UI_BUNDLE_NAME; + request.appInfo.isLauncherApp = true; + request.appInfo.name = "syetemUi"; + request.appInfo.bundleName = AbilityConfig::SYSTEM_UI_BUNDLE_NAME; + + std::shared_ptr targetAbility; + EXPECT_FALSE(targetAbility); + kernalSystemMgr_->GetOrCreateAbilityRecord(request, targetAbility); + + EXPECT_EQ(static_cast(kernalSystemMgr_->abilities_.size()), 1); + EXPECT_TRUE(targetAbility); + EXPECT_FALSE(targetAbility->IsNewWant()); + + // again + kernalSystemMgr_->GetOrCreateAbilityRecord(request, targetAbility); + EXPECT_TRUE(targetAbility->IsNewWant()); + EXPECT_EQ(static_cast(kernalSystemMgr_->abilities_.size()), 1); + + std::string abilityNameInfo = AbilityConfig::SYSTEM_UI_BUNDLE_NAME + ":" + AbilityConfig::SYSTEM_UI_STATUS_BAR; + auto abilityFlag = + kernalSystemMgr_->GetFlagOfAbility(AbilityConfig::SYSTEM_UI_BUNDLE_NAME, AbilityConfig::SYSTEM_UI_STATUS_BAR); + EXPECT_TRUE(abilityNameInfo == abilityFlag); +} + +/* + * Feature: KernalSystemAppManager + * Function: DequeueWaittingAbility + * SubFunction: Processing preconditions + * FunctionPoints: + * EnvConditions:Is Kernal System Ability + * CaseDescription: Notification status + */ +HWTEST_F(KernalSystemAppManagerTest, GetAbilityRecordByToken_001, TestSize.Level1) +{ + EXPECT_TRUE(kernalSystemMgr_); + + StartSystemUI(); + auto topAbilityRecord = kernalSystemMgr_->GetCurrentTopAbility(); + EXPECT_TRUE(topAbilityRecord); + auto testRecord = kernalSystemMgr_->GetAbilityRecordByToken(topAbilityRecord->GetToken()); + EXPECT_TRUE(testRecord == topAbilityRecord); + + sptr token; + auto testRecord1 = kernalSystemMgr_->GetAbilityRecordByToken(token); + EXPECT_TRUE(testRecord1 == nullptr); + + auto testRecord2 = kernalSystemMgr_->GetAbilityRecordByEventId(topAbilityRecord->GetEventId()); + EXPECT_TRUE(testRecord2 == topAbilityRecord); + + auto testRecord3 = kernalSystemMgr_->GetAbilityRecordByEventId(-1); + EXPECT_TRUE(testRecord3 == nullptr); +} + +/* + * Feature: KernalSystemAppManager + * Function: DispatchActive + * SubFunction: Processing preconditions + * FunctionPoints: + * EnvConditions:Is Kernal System Ability + * CaseDescription: Notification status + */ +HWTEST_F(KernalSystemAppManagerTest, DispatchActive_001, TestSize.Level1) +{ + EXPECT_TRUE(kernalSystemMgr_); + + StartSystemUI(); + auto topAbilityRecord = kernalSystemMgr_->GetCurrentTopAbility(); + EXPECT_TRUE(topAbilityRecord); + topAbilityRecord->SetAbilityState(AbilityState::ACTIVATING); + + Want want; + AbilityRequest request; + request.want = want; + request.requestCode = -1; + request.callerToken = nullptr; + request.abilityInfo.name = AbilityConfig::SYSTEM_UI_STATUS_BAR; + request.abilityInfo.bundleName = AbilityConfig::SYSTEM_UI_BUNDLE_NAME; + request.appInfo.isLauncherApp = true; + request.appInfo.name = "syetemUi"; + request.appInfo.bundleName = AbilityConfig::SYSTEM_UI_BUNDLE_NAME; + + kernalSystemMgr_->EnqueueWaittingAbility(request); + EXPECT_EQ(static_cast(kernalSystemMgr_->waittingAbilityQueue_.size()), 1); + + int ref = kernalSystemMgr_->DispatchActive(topAbilityRecord, AbilityState::ACTIVE); + WaitUntilTaskFinished(); + EXPECT_EQ(ERR_OK, ref); +} + +/* + * Feature: KernalSystemAppManager + * Function: RemoveAbilityRecord + * SubFunction: Processing preconditions + * FunctionPoints: + * EnvConditions:Is Kernal System Ability + * CaseDescription: Notification status + */ +HWTEST_F(KernalSystemAppManagerTest, DispatchActive_002, TestSize.Level1) +{ + EXPECT_TRUE(kernalSystemMgr_); + StartSystemUI(); + auto topAbilityRecord = kernalSystemMgr_->GetCurrentTopAbility(); + EXPECT_TRUE(topAbilityRecord); + + EXPECT_EQ(static_cast(kernalSystemMgr_->abilities_.size()), 1); + bool isRemove = kernalSystemMgr_->RemoveAbilityRecord(topAbilityRecord); + EXPECT_TRUE(isRemove); + + isRemove = kernalSystemMgr_->RemoveAbilityRecord(nullptr); + EXPECT_FALSE(isRemove); +} + +/* + * Feature: KernalSystemAppManager + * Function: UpdateConfiguration + * SubFunction: Processing preconditions + * FunctionPoints: + * EnvConditions:Is Kernal System Ability + * CaseDescription: Notification status + */ +HWTEST_F(KernalSystemAppManagerTest, UpdateConfiguration_001, TestSize.Level1) +{ + EXPECT_TRUE(kernalSystemMgr_); + + auto targetAbility = std::make_shared(want_, abilityInfo_, appInfo_); + EXPECT_TRUE(targetAbility); + kernalSystemMgr_->abilities_.clear(); + kernalSystemMgr_->abilities_.push_front(targetAbility); + targetAbility->SetAbilityState(AbilityState::ACTIVE); + const DummyConfiguration config; + kernalSystemMgr_->UpdateConfiguration(config); +} + +} // namespace AAFwk +} // namespace OHOS + +#endif \ No newline at end of file diff --git a/tools/services/abilitymgr/test/unittest/phone/lifecycle_deal_test/BUILD.gn b/tools/services/abilitymgr/test/unittest/phone/lifecycle_deal_test/BUILD.gn new file mode 100644 index 00000000000..f2cd02f1925 --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/lifecycle_deal_test/BUILD.gn @@ -0,0 +1,67 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/test.gni") +import("//foundation/aafwk/standard/aafwk.gni") + +module_output_path = "aafwk_standard/abilitymgr" + +ohos_unittest("lifecycle_deal_test") { + module_out_path = module_output_path + + include_dirs = [ + "${services_path}/abilitymgr/test/mock/libs/system_ability_mock", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy/include", + "//foundation/aafwk/standard/services/abilitymgr/test/mock/libs/ability_scheduler_mock", + ] + + sources = [ + "//foundation/aafwk/standard/services/abilitymgr/test/mock/libs/appexecfwk_core/src/appmgr/mock_app_scheduler.cpp", + "lifecycle_deal_test.cpp", # add mock file + ] + + configs = [ + "${services_path}/abilitymgr:abilityms_config", + "${services_path}/abilitymgr/test/mock:aafwk_mock_config", + ] + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + deps = [ + "${innerkits_path}/want:want", + "${services_path}/abilitymgr/test:abilityms_test_source", + "${services_path}/abilitymgr/test/mock/libs/aakit:aakit_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_appmgr_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_bundlemgr_mock", + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/frameworks/kits/ability/native:dummy_classes", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//third_party/googletest:gmock_main", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] +} + +group("unittest") { + testonly = true + + deps = [ ":lifecycle_deal_test" ] +} diff --git a/tools/services/abilitymgr/test/unittest/phone/lifecycle_deal_test/lifecycle_deal_test.cpp b/tools/services/abilitymgr/test/unittest/phone/lifecycle_deal_test/lifecycle_deal_test.cpp new file mode 100644 index 00000000000..7164e0e4e98 --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/lifecycle_deal_test/lifecycle_deal_test.cpp @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "app_process_data.h" +#include "lifecycle_deal.h" +#include "ability_scheduler_mock.h" + +using namespace testing::ext; + +namespace OHOS { +namespace AAFwk { +class LifecycleDealTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + + std::shared_ptr lifecycleDeal_{nullptr}; + sptr abilityScheduler_{nullptr}; +}; + +void LifecycleDealTest::SetUpTestCase(void) +{} +void LifecycleDealTest::TearDownTestCase(void) +{} +void LifecycleDealTest::TearDown() +{} + +void LifecycleDealTest::SetUp() +{ + lifecycleDeal_ = std::make_shared(); + abilityScheduler_ = new AbilitySchedulerMock(); +} + +/* + * Feature: LifecycleDeal + * Function: Activate + * SubFunction: NA + * FunctionPoints: LifecycleDeal Activate + * EnvConditions:NA + * CaseDescription: Verify activate operation and call mock once + */ +HWTEST_F(LifecycleDealTest, LifecycleDeal_oprator_001, TestSize.Level0) +{ + LifeCycleStateInfo val; + EXPECT_CALL(*abilityScheduler_, ScheduleAbilityTransaction(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(testing::SaveArg<1>(&val)); + + const Want want; + CallerInfo caller; + caller.deviceId = "device"; + caller.bundleName = "bundle"; + caller.abilityName = "LifecycleDealTest"; + + LifeCycleStateInfo info; + info.caller = caller; + lifecycleDeal_->Activate(want, info); + lifecycleDeal_->SetScheduler(abilityScheduler_); + lifecycleDeal_->Activate(want, info); + + EXPECT_EQ(val.caller.deviceId, caller.deviceId); + EXPECT_EQ(val.caller.bundleName, caller.bundleName); + EXPECT_EQ(val.caller.abilityName, caller.abilityName); +} + +/* + * Feature: LifecycleDeal + * Function: Inactivate + * SubFunction: NA + * FunctionPoints: LifecycleDeal Inactivate + * EnvConditions:NA + * CaseDescription: Verify Inactivate operation and call mock once + */ +HWTEST_F(LifecycleDealTest, LifecycleDeal_oprator_002, TestSize.Level0) +{ + LifeCycleStateInfo val; + EXPECT_CALL(*abilityScheduler_, ScheduleAbilityTransaction(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(testing::SaveArg<1>(&val)); + + const Want want; + CallerInfo caller; + caller.deviceId = "device"; + caller.bundleName = "bundle"; + caller.abilityName = "LifecycleDealTest"; + + LifeCycleStateInfo info; + info.caller = caller; + lifecycleDeal_->Inactivate(want, info); + lifecycleDeal_->SetScheduler(abilityScheduler_); + lifecycleDeal_->Inactivate(want, info); + + EXPECT_EQ(val.caller.deviceId, caller.deviceId); + EXPECT_EQ(val.caller.bundleName, caller.bundleName); + EXPECT_EQ(val.caller.abilityName, caller.abilityName); +} + +/* + * Feature: LifecycleDeal + * Function: MoveToBackground + * SubFunction: NA + * FunctionPoints: LifecycleDeal MoveToBackground + * EnvConditions:NA + * CaseDescription: Verify MoveToBackground operation and call mock once + */ +HWTEST_F(LifecycleDealTest, LifecycleDeal_oprator_003, TestSize.Level0) +{ + LifeCycleStateInfo val; + EXPECT_CALL(*abilityScheduler_, ScheduleAbilityTransaction(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(testing::SaveArg<1>(&val)); + + const Want want; + CallerInfo caller; + caller.deviceId = "device"; + caller.bundleName = "bundle"; + caller.abilityName = "LifecycleDealTest"; + + LifeCycleStateInfo info; + info.caller = caller; + lifecycleDeal_->MoveToBackground(want, info); + lifecycleDeal_->SetScheduler(abilityScheduler_); + lifecycleDeal_->MoveToBackground(want, info); + + EXPECT_EQ(val.caller.deviceId, caller.deviceId); + EXPECT_EQ(val.caller.bundleName, caller.bundleName); + EXPECT_EQ(val.caller.abilityName, caller.abilityName); +} + +/* + * Feature: LifecycleDeal + * Function: ConnectAbility + * SubFunction: NA + * FunctionPoints: LifecycleDeal ConnectAbility + * EnvConditions:NA + * CaseDescription: Verify ConnectAbility operation and call mock once + */ +HWTEST_F(LifecycleDealTest, LifecycleDeal_oprator_004, TestSize.Level0) +{ + EXPECT_CALL(*abilityScheduler_, ScheduleConnectAbility(::testing::_)).Times(1); + const Want want; + lifecycleDeal_->ConnectAbility(want); + lifecycleDeal_->SetScheduler(abilityScheduler_); + lifecycleDeal_->ConnectAbility(want); +} + +/* + * Feature: LifecycleDeal + * Function: DisconnectAbility + * SubFunction: NA + * FunctionPoints: LifecycleDeal DisconnectAbility + * EnvConditions:NA + * CaseDescription: Verify DisconnectAbility operation and call mock once + */ +HWTEST_F(LifecycleDealTest, LifecycleDeal_oprator_005, TestSize.Level0) +{ + EXPECT_CALL(*abilityScheduler_, ScheduleDisconnectAbility(::testing::_)).Times(1); + + const Want want; + lifecycleDeal_->DisconnectAbility(want); + lifecycleDeal_->SetScheduler(abilityScheduler_); + lifecycleDeal_->DisconnectAbility(want); +} + +/* + * Feature: LifecycleDeal + * Function: Terminate + * SubFunction: NA + * FunctionPoints: LifecycleDeal Terminate + * EnvConditions:NA + * CaseDescription: Verify Terminate operation and call mock once + */ +HWTEST_F(LifecycleDealTest, LifecycleDeal_oprator_006, TestSize.Level0) +{ + EXPECT_CALL(*abilityScheduler_, ScheduleAbilityTransaction(::testing::_, ::testing::_)).Times(1); + + const Want want; + CallerInfo caller; + caller.deviceId = "device"; + caller.bundleName = "bundle"; + caller.abilityName = "LifecycleDealTest"; + + LifeCycleStateInfo info; + info.caller = caller; + lifecycleDeal_->Activate(want, info); + lifecycleDeal_->SetScheduler(abilityScheduler_); + lifecycleDeal_->Activate(want, info); +} + +/* + * Feature: LifecycleDeal + * Function: CommandAbility + * SubFunction: NA + * FunctionPoints: LifecycleDeal CommandAbility + * EnvConditions:NA + * CaseDescription: Verify CommandAbility operation and call mock once + */ +HWTEST_F(LifecycleDealTest, LifecycleDeal_oprator_007, TestSize.Level0) +{ + EXPECT_CALL(*abilityScheduler_, ScheduleCommandAbility(::testing::_, ::testing::_, ::testing::_)).Times(1); + const Want want; + LifeCycleStateInfo info; + lifecycleDeal_->CommandAbility(want, false, 1); + lifecycleDeal_->SetScheduler(abilityScheduler_); + lifecycleDeal_->CommandAbility(want, false, 1); +} +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/abilitymgr/test/unittest/phone/lifecycle_test/BUILD.gn b/tools/services/abilitymgr/test/unittest/phone/lifecycle_test/BUILD.gn new file mode 100644 index 00000000000..682ecb6a4f1 --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/lifecycle_test/BUILD.gn @@ -0,0 +1,67 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/test.gni") +import("//foundation/aafwk/standard/aafwk.gni") + +module_output_path = "aafwk_standard/abilitymgr" + +ohos_unittest("lifecycle_test") { + module_out_path = module_output_path + + include_dirs = [ + "${services_path}/abilitymgr/test/mock/libs/system_ability_mock", + "${services_path}/abilitymgr/test/mock/libs/system_ability_mock", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy/include", + ] + + sources = [ + "//foundation/aafwk/standard/services/abilitymgr/test/mock/libs/appexecfwk_core/src/appmgr/mock_app_scheduler.cpp", + "lifecycle_test.cpp", # add mock file + ] + + configs = [ + "${services_path}/abilitymgr:abilityms_config", + "${services_path}/abilitymgr/test/mock:aafwk_mock_config", + ] + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + deps = [ + "${innerkits_path}/want:want", + "${services_path}/abilitymgr/test:abilityms_test_source", + "${services_path}/abilitymgr/test/mock/libs/aakit:aakit_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_appmgr_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_bundlemgr_mock", + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/frameworks/kits/ability/native:dummy_classes", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//third_party/googletest:gmock_main", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] +} + +group("unittest") { + testonly = true + + deps = [ ":lifecycle_test" ] +} diff --git a/tools/services/abilitymgr/test/unittest/phone/lifecycle_test/lifecycle_test.cpp b/tools/services/abilitymgr/test/unittest/phone/lifecycle_test/lifecycle_test.cpp new file mode 100755 index 00000000000..3b0875dfc5e --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/lifecycle_test/lifecycle_test.cpp @@ -0,0 +1,578 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include "gmock/gmock.h" + +#include +#include + +#define private public +#define protected public +#include "system_ability_definition.h" +#include "lifecycle_test_base.h" +#include "mock_bundle_manager.h" +#include "sa_mgr_client.h" +#undef private +#undef protected + +using namespace testing::ext; +using namespace OHOS::AppExecFwk; + +namespace OHOS { +namespace AAFwk { +namespace { +const std::string NAME_BUNDLE_MGR_SERVICE = "BundleMgrService"; +} + +static void WaitUntilTaskFinished() +{ + const uint32_t maxRetryCount = 1000; + const uint32_t sleepTime = 1000; + uint32_t count = 0; + auto handler = OHOS::DelayedSingleton::GetInstance()->GetEventHandler(); + if (handler == nullptr) { + GTEST_LOG_(ERROR) << "handler is nullptr"; + return; + } + std::atomic taskCalled(false); + auto f = [&taskCalled]() { taskCalled.store(true); }; + if (handler->PostTask(f)) { + while (!taskCalled.load()) { + ++count; + if (count >= maxRetryCount) { + break; + } + usleep(sleepTime); + } + } +} + +class LifecycleTest : public testing::Test, public LifecycleTestBase { +public: + static void SetUpTestCase(void); + + static void TearDownTestCase(void); + + void SetUp() override; + + void TearDown() override; + + bool StartLauncherAbility() override; + + bool StartNextAbility() override; + + int AttachAbility(const OHOS::sptr &scheduler, + const OHOS::sptr &token) override; + +public: + int startLancherFlag_ = false; + + std::shared_ptr aams_{nullptr}; + std::shared_ptr launcherAbilityRecord_{nullptr}; // launcher ability + OHOS::sptr launcherToken_{nullptr}; // token of launcher ability + std::shared_ptr nextAbilityRecord_{nullptr}; // ability being launched + OHOS::sptr nextToken_{nullptr}; // token of ability being launched + OHOS::sptr launcherScheduler_{nullptr}; // launcher ability thread interface + OHOS::sptr nextScheduler_{nullptr}; // next ability thread interface + std::unique_ptr command_{nullptr}; // test command_ interact with ams_ +}; + +void LifecycleTest::SetUpTestCase(void) +{ + OHOS::DelayedSingleton::GetInstance()->RegisterSystemAbility( + OHOS::BUNDLE_MGR_SERVICE_SYS_ABILITY_ID, new BundleMgrService()); +} + +void LifecycleTest::TearDownTestCase(void) +{ + OHOS::DelayedSingleton::DestroyInstance(); +} + +void LifecycleTest::SetUp(void) +{ + aams_ = OHOS::DelayedSingleton::GetInstance(); + aams_->OnStart(); + WaitUntilTaskFinished(); + StartLauncherAbility(); + command_ = std::make_unique(); +} + +void LifecycleTest::TearDown(void) +{ + aams_->OnStop(); + OHOS::DelayedSingleton::DestroyInstance(); + launcherAbilityRecord_.reset(); + launcherToken_ = nullptr; + nextAbilityRecord_.reset(); + nextToken_ = nullptr; + launcherScheduler_ = nullptr; + nextScheduler_ = nullptr; + command_.reset(); + aams_.reset(); + startLancherFlag_ = false; +} + +bool LifecycleTest::StartLauncherAbility() +{ + ElementName element("device", "com.ix.hiWord", "LauncherAbility"); + Want want; + want.AddEntity(Want::FLAG_HOME_INTENT_FROM_SYSTEM); + want.SetElement(element); + int ref = aams_->StartAbility(want, -1); + WaitUntilTaskFinished(); + EXPECT_EQ(ref, 0); + if (ref != 0) { + GTEST_LOG_(ERROR) << "fail to start Launcher ability"; + return false; + } + auto stackManager = aams_->GetStackManager(); + EXPECT_TRUE(stackManager); + launcherAbilityRecord_ = (stackManager->GetCurrentTopAbility()); + EXPECT_TRUE(launcherAbilityRecord_); + if (launcherAbilityRecord_) { + GTEST_LOG_(ERROR) << "launcherAbilityRecord_ is not null"; + launcherAbilityRecord_->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + launcherToken_ = launcherAbilityRecord_->GetToken(); + launcherScheduler_ = new AbilityScheduler(); + startLancherFlag_ = true; + return true; + } + return false; +} + +bool LifecycleTest::StartNextAbility() +{ + Want want; + ElementName element("device", "com.ix.hiMusic", "MusicAbility"); + want.SetElement(element); + + auto stackManager = aams_->GetStackManager(); + EXPECT_TRUE(stackManager); + if (stackManager) { + GTEST_LOG_(ERROR) << "top BundleName :" + << stackManager->GetCurrentTopAbility()->GetWant().GetElement().GetBundleName(); + GTEST_LOG_(ERROR) << "top AbilityName :" + << stackManager->GetCurrentTopAbility()->GetWant().GetElement().GetAbilityName(); + stackManager->GetCurrentTopAbility()->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + } + int ref = aams_->StartAbility(want, -1); + WaitUntilTaskFinished(); + EXPECT_EQ(ref, 0); + if (ref != 0) { + GTEST_LOG_(ERROR) << "fail to start next ability"; + return false; + } + + nextAbilityRecord_ = stackManager->GetCurrentTopAbility(); + if (nextAbilityRecord_ != nullptr) { + nextToken_ = nextAbilityRecord_->GetToken(); + nextScheduler_ = new AbilityScheduler(); + nextAbilityRecord_->SetScheduler(nextScheduler_); + GTEST_LOG_(INFO) << "nextAbilityRecord_ is not null"; + } else { + GTEST_LOG_(ERROR) << "next ability is nullptr"; + return false; + } + nextScheduler_ = new AbilityScheduler(); + return true; +} + +int LifecycleTest::AttachAbility( + const OHOS::sptr &scheduler, const OHOS::sptr &token) +{ + int ret = aams_->AttachAbilityThread(scheduler, token); + static int32_t windowToken = 0; + aams_->AddWindowInfo(token, ++windowToken); + return ret; +} + +/* + * Feature: Lifecycle schedule + * Function: Lifecycle schedule + * SubFunction: NA + * FunctionPoints: AttachAbilityThread + * EnvConditions:NA + * CaseDescription: verify AttachAbilityThread parameters. + * AttachAbilityThread fail if IAbilityScheduler or token is nullptr. + */ +HWTEST_F(LifecycleTest, AAFWK_AbilityMS_StartLauncherAbilityLifeCycle_001, TestSize.Level1) +{ + if (startLancherFlag_) { + EXPECT_TRUE(aams_); + EXPECT_TRUE(launcherAbilityRecord_); + EXPECT_NE(aams_->AttachAbilityThread(nullptr, launcherToken_), 0); + EXPECT_NE(aams_->AttachAbilityThread(launcherScheduler_, nullptr), 0); + EXPECT_EQ(launcherAbilityRecord_->GetAbilityState(), OHOS::AAFwk::AbilityState::ACTIVE); + } +} + +/* + * Feature: Lifecycle schedule + * Function: Lifecycle schedule + * SubFunction: NA + * FunctionPoints: AttachAbilityThread + * EnvConditions:NA + * CaseDescription: verify launcher AbilityRecord state_ when AttachAbilityThread success. + * 1. AbilityState transferred from INITIAL to ACTIVATING. + * 2. AbilityRecord is attached. + */ +HWTEST_F(LifecycleTest, AAFWK_AbilityMS_StartLauncherAbilityLifeCycle_002, TestSize.Level1) +{ + if (startLancherFlag_) { + EXPECT_TRUE(aams_); + EXPECT_TRUE(launcherAbilityRecord_); + EXPECT_EQ(launcherAbilityRecord_->GetAbilityState(), OHOS::AAFwk::AbilityState::ACTIVE); + EXPECT_TRUE(launcherScheduler_); + EXPECT_TRUE(launcherToken_); + EXPECT_EQ(AttachAbility(launcherScheduler_, launcherToken_), 0); + EXPECT_EQ(launcherAbilityRecord_->IsReady(), true); + } +} + +/* + * Feature: Lifecycle schedule + * Function: Lifecycle schedule + * SubFunction: NA + * FunctionPoints: AttachAbilityThread + * EnvConditions:NA + * CaseDescription: verify AbilityRecord transition timeout handler. + */ +HWTEST_F(LifecycleTest, AAFWK_AbilityMS_StartLauncherAbilityLifeCycle_003, TestSize.Level1) +{ + if (startLancherFlag_) { + command_->callback_ = false; + command_->expectState_ = OHOS::AAFwk::AbilityState::ACTIVE; + command_->state_ = OHOS::AAFwk::AbilityState::INITIAL; + EXPECT_EQ(AttachAbility(launcherScheduler_, launcherToken_), 0); + pthread_t tid = 0; + pthread_create(&tid, nullptr, LifecycleTest::AbilityStartThread, command_.get()); + int ret = + LifecycleTest::SemTimedWaitMillis(AbilityManagerService::LOAD_TIMEOUT + DELAY_TEST_TIME, command_->sem_); + EXPECT_NE(ret, 0); + // check timeout handler + EXPECT_EQ(launcherAbilityRecord_->GetAbilityState(), OHOS::AAFwk::AbilityState::ACTIVE); + pthread_join(tid, nullptr); + } +} + +/* + * Feature: Lifecycle schedule + * Function: Lifecycle schedule + * SubFunction: NA + * FunctionPoints: AttachAbilityThread + * EnvConditions:NA + * CaseDescription: verify AbilityTransitionDone parameters. + * AbilityTransitionDone fail if launcher schedules incorrect Life state_. + */ +HWTEST_F(LifecycleTest, AAFWK_AbilityMS_StartLauncherAbilityLifeCycle_004, TestSize.Level1) +{ + if (startLancherFlag_) { + // AttachAbilityThread done and success + EXPECT_EQ(AttachAbility(launcherScheduler_, launcherToken_), 0); + + command_->callback_ = true; + command_->expectState_ = OHOS::AAFwk::AbilityState::ACTIVE; + command_->abnormalState_ = OHOS::AAFwk::AbilityState::INACTIVE; + pthread_t tid = 0; + pthread_create(&tid, nullptr, LifecycleTest::AbilityStartThread, command_.get()); + int ret = + LifecycleTest::SemTimedWaitMillis(AbilityManagerService::LOAD_TIMEOUT + DELAY_TEST_TIME, command_->sem_); + if (ret != 0) { + // check timeout handler + GTEST_LOG_(INFO) << "timeout. It shouldn't happen."; + pthread_join(tid, nullptr); + return; + } + pthread_join(tid, nullptr); + } +} + +/* + * Feature: Lifecycle schedule + * Function: Lifecycle schedule + * SubFunction: NA + * FunctionPoints: AttachAbilityThread + * EnvConditions:NA + * CaseDescription: AttachAbilityThread done, verify AbilityRecord state_ when AbilityStartThread success. + * 1. Life transition from UNDEFINED to ACTIVATING to ACTIVE. + * 2. AbilityRecord is attached. + */ +HWTEST_F(LifecycleTest, AAFWK_AbilityMS_StartLauncherAbilityLifeCycle_005, TestSize.Level1) +{ + if (startLancherFlag_) { + // AttachAbilityThread done and success + EXPECT_EQ(AttachAbility(launcherScheduler_, launcherToken_), 0); + command_->callback_ = true; + command_->expectState_ = OHOS::AAFwk::AbilityState::ACTIVE; + command_->state_ = OHOS::AAFwk::AbilityState::INITIAL; + pthread_t tid = 0; + + pthread_create(&tid, nullptr, LifecycleTest::AbilityStartThread, command_.get()); + int ret = + LifecycleTest::SemTimedWaitMillis(AbilityManagerService::LOAD_TIMEOUT + DELAY_TEST_TIME, command_->sem_); + if (ret != 0) { + // check timeout handler. It won't happen normally. + GTEST_LOG_(INFO) << "timeout. It shouldn't happen."; + pthread_join(tid, nullptr); + return; + } + EXPECT_EQ(aams_->AbilityTransitionDone(launcherToken_, command_->state_), OHOS::ERR_OK); + if (launcherAbilityRecord_->GetAbilityState() != OHOS::AAFwk::AbilityState::ACTIVE) { + WaitUntilTaskFinished(); + EXPECT_EQ(launcherAbilityRecord_->GetAbilityState(), OHOS::AAFwk::AbilityState::ACTIVE); + } + EXPECT_EQ(launcherAbilityRecord_->IsReady(), true); + pthread_join(tid, nullptr); + } +} + +/* + * Feature: Lifecycle schedule + * Function: Lifecycle schedule + * SubFunction: NA + * FunctionPoints: AttachAbilityThread + * EnvConditions:NA + * CaseDescription: hnadeler is timeout + */ +HWTEST_F(LifecycleTest, AAFWK_AbilityMS_StartLauncherAbilityLifeCycle_006, TestSize.Level1) +{ + if (startLancherFlag_) { + command_->callback_ = false; + command_->expectState_ = OHOS::AAFwk::AbilityState::ACTIVE; + command_->state_ = OHOS::AAFwk::AbilityState::INITIAL; + pthread_t tid = 0; + pthread_create(&tid, nullptr, LifecycleTest::AbilityStartThread, command_.get()); + int ret = LifecycleTest::SemTimedWaitMillis(AbilityManagerService::ACTIVE_TIMEOUT, command_->sem_); + EXPECT_NE(ret, 0); + // check AttachAbilityThread timeout handler + EXPECT_EQ(launcherAbilityRecord_->IsReady(), false); + pthread_join(tid, nullptr); + } +} + +/* + * Feature: Lifecycle schedule + * Function: Lifecycle schedule + * SubFunction: NA + * FunctionPoints: AbilityTransitionDone + * EnvConditions:NA + * CaseDescription: launcher OnInactive timeout, verify launcher AbilityTransitionDone timeout handler. + */ +HWTEST_F(LifecycleTest, AAFWK_AbilityMS_startAbilityLifeCycle_001, TestSize.Level1) +{ + if (startLancherFlag_) { + command_->callback_ = false; + command_->expectState_ = OHOS::AAFwk::AbilityState::INACTIVE; + command_->state_ = OHOS::AAFwk::AbilityState::INITIAL; + // launcher is in inactivating process. + EXPECT_EQ(AttachAbility(launcherScheduler_, launcherToken_), 0); + EXPECT_TRUE(StartNextAbility()); + launcherAbilityRecord_->SetAbilityState(OHOS::AAFwk::AbilityState::INACTIVATING); + pthread_t tid = 0; + pthread_create(&tid, nullptr, LifecycleTest::AbilityStartThread, command_.get()); + int ret = LifecycleTest::SemTimedWaitMillis(AbilityManagerService::INACTIVE_TIMEOUT, command_->sem_); + EXPECT_NE(ret, 0); + // check AbilityTransitionDone timeout handler + EXPECT_EQ(nextAbilityRecord_->GetAbilityState(), OHOS::AAFwk::AbilityState::INITIAL); + pthread_join(tid, nullptr); + } +} + +/* + * Feature: Lifecycle schedule + * Function: Lifecycle schedule + * SubFunction: NA + * FunctionPoints: AbilityTransitionDone + * EnvConditions:NA + * CaseDescription: verify AbilityTransitionDone parameters. + * AbilityTransitionDone fail if life state_ is incompatible with + * OnInactive process. Or launcher schedules incorrect life state_. + */ +HWTEST_F(LifecycleTest, AAFWK_AbilityMS_startAbilityLifeCycle_002, TestSize.Level1) +{ + if (startLancherFlag_) { + EXPECT_EQ(AttachAbility(launcherScheduler_, launcherToken_), 0); + EXPECT_TRUE(StartNextAbility()); + // launcher is in inactivating process. + EXPECT_NE(aams_->AbilityTransitionDone(launcherToken_, OHOS::AAFwk::AbilityState::ACTIVE), 0); + WaitUntilTaskFinished(); + EXPECT_EQ(launcherAbilityRecord_->GetAbilityState(), OHOS::AAFwk::AbilityState::INACTIVATING); + EXPECT_EQ(nextAbilityRecord_->GetAbilityState(), OHOS::AAFwk::AbilityState::INITIAL); + } +} + +/* + * Feature: Lifecycle schedule + * Function: Lifecycle schedule + * SubFunction: NA + * FunctionPoints: AttachAbilityThread + * EnvConditions:NA + * CaseDescription: launcher OnInactive done, verify new ability AttachAbilityThread timeout handler. + */ +HWTEST_F(LifecycleTest, AAFWK_AbilityMS_startAbilityLifeCycle_003, TestSize.Level1) +{ + if (startLancherFlag_) { + command_->callback_ = false; + command_->expectState_ = OHOS::AAFwk::AbilityState::ACTIVE; + command_->state_ = OHOS::AAFwk::AbilityState::INITIAL; + EXPECT_EQ(AttachAbility(launcherScheduler_, launcherToken_), 0); + WaitUntilTaskFinished(); + EXPECT_TRUE(StartNextAbility()); + launcherAbilityRecord_->SetAbilityState(OHOS::AAFwk::AbilityState::INACTIVATING); + EXPECT_EQ(aams_->AbilityTransitionDone(launcherToken_, OHOS::AAFwk::AbilityState::INACTIVE), 0); + // launcher oninactive done. + pthread_t tid = 0; + pthread_create(&tid, nullptr, LifecycleTest::AbilityStartThread, command_.get()); + int ret = LifecycleTest::SemTimedWaitMillis( + AbilityManagerService::INACTIVE_TIMEOUT + DELAY_TEST_TIME, command_->sem_); + EXPECT_NE(ret, 0); + // check timeout handler + EXPECT_EQ(nextAbilityRecord_->GetAbilityState(), OHOS::AAFwk::AbilityState::ACTIVATING); + pthread_join(tid, nullptr); + + WaitUntilTaskFinished(); + } +} + +/* + * Feature: Lifecycle schedule + * Function: Lifecycle schedule + * SubFunction: NA + * FunctionPoints: AbilityTransitionDone + * EnvConditions:NA + * CaseDescription: launcher OnInactive done, verify AbilityTransitionDone parameter. + * AbilityTransitionDone fail if new ability + * IAbilityScheduler is nullptr. + */ +HWTEST_F(LifecycleTest, AAFWK_AbilityMS_startAbilityLifeCycle_004, TestSize.Level1) +{ + if (startLancherFlag_) { + EXPECT_EQ(AttachAbility(launcherScheduler_, launcherToken_), 0); + EXPECT_TRUE(StartNextAbility()); + launcherAbilityRecord_->SetAbilityState(OHOS::AAFwk::AbilityState::INACTIVATING); + EXPECT_EQ(aams_->AbilityTransitionDone(launcherToken_, OHOS::AAFwk::AbilityState::INACTIVE), 0); + // launcher oninactive done. + nextAbilityRecord_->SetAbilityState(OHOS::AAFwk::AbilityState::INITIAL); + EXPECT_EQ(AttachAbility(nextScheduler_, nextToken_), 0); + EXPECT_NE(aams_->AbilityTransitionDone(nullptr, OHOS::AAFwk::AbilityState::ACTIVE), 0); + } +} + +/* + * Feature: Lifecycle schedule + * Function: Lifecycle schedule + * SubFunction: NA + * FunctionPoints: AbilityTransitionDone + * EnvConditions:NA + * CaseDescription: launcher OnInactive done. verify AbilityTransitionDone parameter. + * AbilityTransitionDone fail if new ability + * schedules incorrect state_. + */ +HWTEST_F(LifecycleTest, AAFWK_AbilityMS_startAbilityLifeCycle_005, TestSize.Level1) +{ + if (startLancherFlag_) { + command_->callback_ = true; + command_->expectState_ = OHOS::AAFwk::AbilityState::ACTIVE; + command_->abnormalState_ = OHOS::AAFwk::AbilityState::INACTIVE; + command_->state_ = OHOS::AAFwk::AbilityState::INITIAL; + EXPECT_EQ(AttachAbility(launcherScheduler_, launcherToken_), 0); + EXPECT_TRUE(StartNextAbility()); + launcherAbilityRecord_->SetAbilityState(OHOS::AAFwk::AbilityState::INACTIVATING); + EXPECT_EQ(aams_->AbilityTransitionDone(launcherToken_, OHOS::AAFwk::AbilityState::INACTIVE), 0); + WaitUntilTaskFinished(); + // launcher oninactive done. + nextAbilityRecord_->SetAbilityState(OHOS::AAFwk::AbilityState::INITIAL); + EXPECT_EQ(AttachAbility(nextScheduler_, nextToken_), 0); + pthread_t tid = 0; + pthread_create(&tid, nullptr, LifecycleTest::AbilityStartThread, command_.get()); + int ret = + LifecycleTest::SemTimedWaitMillis(AbilityManagerService::LOAD_TIMEOUT + DELAY_TEST_TIME, command_->sem_); + if (ret != 0) { + // check timeout handler + pthread_join(tid, nullptr); + return; + } + pthread_join(tid, nullptr); + } +} + +/* + * Feature: Lifecycle schedule + * Function: Lifecycle schedule + * SubFunction: NA + * FunctionPoints: AbilityTransitionDone + * EnvConditions:NA + * CaseDescription: launcher OnInactive done. verify new ability AbilityTransitionDone timeout handler. + */ +HWTEST_F(LifecycleTest, AAFWK_AbilityMS_startAbilityLifeCycle_006, TestSize.Level1) +{ + + if (startLancherFlag_) { + command_->callback_ = false; + command_->expectState_ = OHOS::AAFwk::AbilityState::ACTIVE; + command_->state_ = OHOS::AAFwk::AbilityState::INITIAL; + EXPECT_EQ(AttachAbility(launcherScheduler_, launcherToken_), 0); + EXPECT_TRUE(StartNextAbility()); + launcherAbilityRecord_->SetAbilityState(OHOS::AAFwk::AbilityState::INACTIVATING); + // launcher oninactive done. + EXPECT_EQ(AttachAbility(nextScheduler_, nextToken_), 0); + pthread_t tid = 0; + pthread_create(&tid, nullptr, LifecycleTest::AbilityStartThread, command_.get()); + int ret = + LifecycleTest::SemTimedWaitMillis(AbilityManagerService::ACTIVE_TIMEOUT + DELAY_TEST_TIME, command_->sem_); + EXPECT_NE(ret, 0); + pthread_join(tid, nullptr); + return; + } +} + +/* + * Feature: Lifecycle schedule + * Function: Lifecycle schedule + * SubFunction: NA + * FunctionPoints: AttachAbilityThread AbilityTransitionDone + * EnvConditions:NA + * CaseDescription: launcher OnInactive done and starts new ability success. verify new AbilityRecord. + * 1. Launcher oninactive done and is INACTIVE. + * 2. new ability is ACTIVE. + * 3. Launcher is transferred from INACTIVE to MOVING_BACKGROUND when new ability started. + */ +HWTEST_F(LifecycleTest, AAFWK_AbilityMS_startAbilityLifeCycle_007, TestSize.Level1) +{ + if (startLancherFlag_) { + command_->callback_ = true; + command_->expectState_ = OHOS::AAFwk::AbilityState::ACTIVE; + command_->state_ = OHOS::AAFwk::AbilityState::INITIAL; + EXPECT_EQ(AttachAbility(launcherScheduler_, launcherToken_), 0); + EXPECT_TRUE(StartNextAbility()); + launcherAbilityRecord_->SetAbilityState(OHOS::AAFwk::AbilityState::INACTIVATING); + EXPECT_EQ(aams_->AbilityTransitionDone(launcherToken_, OHOS::AAFwk::AbilityState::INACTIVE), OHOS::ERR_OK); + // launcher oninactive done. + WaitUntilTaskFinished(); + EXPECT_EQ(launcherAbilityRecord_->GetAbilityState(), OHOS::AAFwk::AbilityState::INACTIVE); + EXPECT_EQ(AttachAbility(nextScheduler_, nextToken_), 0); + pthread_t tid = 0; + pthread_create(&tid, nullptr, LifecycleTest::AbilityStartThread, command_.get()); + int ret = LifecycleTest::SemTimedWaitMillis(AbilityManagerService::ACTIVE_TIMEOUT * 2, command_->sem_); + if (ret != 0) { + // check timeout handler + pthread_join(tid, nullptr); + return; + } + pthread_join(tid, nullptr); + } +} +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/abilitymgr/test/unittest/phone/lifecycle_test/lifecycle_test_base.h b/tools/services/abilitymgr/test/unittest/phone/lifecycle_test/lifecycle_test_base.h new file mode 100644 index 00000000000..68f2f742027 --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/lifecycle_test/lifecycle_test_base.h @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIFECYCLE_TEST_BASE_H +#define LIFECYCLE_TEST_BASE_H + +#include +#include +#include +#include +#include "ability_manager_service.h" +#include "ability_record.h" +#include "ability_scheduler.h" + +/** + * @class LifeTestCommand + * asynchronous test thread use LifeTestCommand to call AbilityManagerService API. + */ +class LifeTestCommand { +public: + LifeTestCommand() + : state_(OHOS::AAFwk::AbilityState::INITIAL), + expectState_(OHOS::AAFwk::AbilityState::INITIAL), + abnormalState_(OHOS::AAFwk::AbilityState::INITIAL), + callback_(true) + { + sem_init(&sem_, 0, 0); + } + + ~LifeTestCommand() + { + sem_destroy(&sem_); + } + + OHOS::AAFwk::AbilityState state_; // actual life + OHOS::AAFwk::AbilityState expectState_; // expect life + OHOS::AAFwk::AbilityState abnormalState_; // test abnormal condition life + bool callback_; // if false client won't callback_ to construct timeout case. + sem_t sem_; +}; + +class LifecycleTestBase { +public: + virtual bool StartLauncherAbility() = 0; + virtual bool StartNextAbility() = 0; + virtual int AttachAbility( + const OHOS::sptr &scheduler, const OHOS::sptr &token) = 0; + + static constexpr uint32_t DELAY_TEST_TIME = 1000; // ms + static constexpr long MILLISECONDS = 1000; + static constexpr long NANOSECONDS = 1000000000; + + static void *AbilityStartThread(void *command) + { + auto c = static_cast(command); + if (c == nullptr) { + return nullptr; + } + if (c->callback_) { + if (c->abnormalState_ != OHOS::AAFwk::AbilityState::INITIAL) { + c->state_ = c->abnormalState_; + } else { + c->state_ = c->expectState_; + } + sem_post(&(c->sem_)); + } + return c; + } + + static int SemTimedWaitMillis(long msecs, sem_t &sem) + { + if (msecs <= 0) { + return 0; + } + msecs = msecs % MILLISECONDS; + long secs = msecs / MILLISECONDS; + struct timespec ts = {0, 0}; + clock_gettime(CLOCK_REALTIME, &ts); + msecs = msecs * MILLISECONDS * MILLISECONDS + ts.tv_nsec; + long add = msecs / NANOSECONDS; + ts.tv_sec += (add + secs); + ts.tv_nsec = msecs % NANOSECONDS; + return sem_timedwait(&sem, &ts); + } +}; + +#endif // LIFECYCLE_TEST_BASE_H \ No newline at end of file diff --git a/tools/services/abilitymgr/test/unittest/phone/mission_record_test/BUILD.gn b/tools/services/abilitymgr/test/unittest/phone/mission_record_test/BUILD.gn new file mode 100644 index 00000000000..eec190f2b11 --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/mission_record_test/BUILD.gn @@ -0,0 +1,65 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/test.gni") +import("//foundation/aafwk/standard/aafwk.gni") + +module_output_path = "aafwk_standard/abilitymgr" + +ohos_unittest("mission_record_test") { + module_out_path = module_output_path + + include_dirs = [ + "${services_path}/abilitymgr/test/mock/libs/system_ability_mock", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy/include", + ] + + sources = [ + "//foundation/aafwk/standard/services/abilitymgr/test/mock/libs/appexecfwk_core/src/appmgr/mock_app_scheduler.cpp", + "mission_record_test.cpp", # add mock file + ] + + configs = [ + "${services_path}/abilitymgr:abilityms_config", + "${services_path}/abilitymgr/test/mock:aafwk_mock_config", + ] + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + deps = [ + "${innerkits_path}/want:want", + "${services_path}/abilitymgr/test:abilityms_test_source", + "${services_path}/abilitymgr/test/mock/libs/aakit:aakit_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_appmgr_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_bundlemgr_mock", + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/frameworks/kits/ability/native:dummy_classes", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] +} + +group("unittest") { + testonly = true + + deps = [ ":mission_record_test" ] +} diff --git a/tools/services/abilitymgr/test/unittest/phone/mission_record_test/mission_record_test.cpp b/tools/services/abilitymgr/test/unittest/phone/mission_record_test/mission_record_test.cpp new file mode 100644 index 00000000000..4a51b68f85d --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/mission_record_test/mission_record_test.cpp @@ -0,0 +1,387 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#define private public +#define protected public +#include "mission_record.h" +#undef private +#undef protected + +using namespace testing::ext; +using namespace OHOS::AppExecFwk; + +namespace OHOS { +namespace AAFwk { +class MissionRecordTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + + static AbilityRequest GenerateAbilityRequest(const std::string &deviceName, const std::string &abilityName, + const std::string &appName, const std::string &bundleName); + + Want want_{}; + AbilityInfo abilityInfo_{}; + ApplicationInfo appInfo_{}; +}; + +void MissionRecordTest::SetUpTestCase(void) +{} +void MissionRecordTest::TearDownTestCase(void) +{} +void MissionRecordTest::SetUp(void) +{} +void MissionRecordTest::TearDown(void) +{} + +AbilityRequest MissionRecordTest::GenerateAbilityRequest(const std::string &deviceName, const std::string &abilityName, + const std::string &appName, const std::string &bundleName) +{ + ElementName element(deviceName, abilityName, bundleName); + Want want; + want.SetElement(element); + + AbilityInfo abilityInfo; + abilityInfo.visible = true; + abilityInfo.applicationName = appName; + ApplicationInfo appinfo; + appinfo.name = appName; + + AbilityRequest abilityRequest; + abilityRequest.want = want; + abilityRequest.abilityInfo = abilityInfo; + abilityRequest.appInfo = appinfo; + + return abilityRequest; +} + +/* + * Feature: MissionRecord + * Function: GetAbilityRecordCount and GetMissionRecordId + * SubFunction: NA + * FunctionPoints: MissionRecord GetAbilityRecordCount and GetMissionRecordId + * EnvConditions:NA + * CaseDescription: Verify GetAbilityRecordCount and GetMissionRecordId value + */ +HWTEST_F(MissionRecordTest, stack_operating_001, TestSize.Level1) +{ + auto missionRecord = std::make_shared(""); + EXPECT_EQ(0, missionRecord->GetAbilityRecordCount()); + EXPECT_EQ(0, missionRecord->GetMissionRecordId()); +} + +/* + * Feature: MissionRecord + * Function: AddAbilityRecordToTop and GetTopAbilityRecord + * SubFunction: NA + * FunctionPoints: MissionRecord AddAbilityRecordToTop and GetTopAbilityRecord + * EnvConditions:NA + * CaseDescription: add ability record, Verify get top ability record equality + */ +HWTEST_F(MissionRecordTest, stack_operating_002, TestSize.Level1) +{ + auto ability = std::make_shared(want_, abilityInfo_, appInfo_); + auto missionRecord = std::make_shared(abilityInfo_.bundleName); + missionRecord->AddAbilityRecordToTop(ability); + EXPECT_EQ(ability, missionRecord->GetTopAbilityRecord()); + EXPECT_EQ(1, missionRecord->GetMissionRecordId()); +} + +/* + * Feature: MissionRecord + * Function: AddAbilityRecordToTop and GetTopAbilityRecord + * SubFunction: NA + * FunctionPoints: MissionRecord AddAbilityRecordToTop and GetTopAbilityRecord + * EnvConditions:NA + * CaseDescription: add null ability record, Verify that get top ability record is empty + */ +HWTEST_F(MissionRecordTest, stack_operating_003, TestSize.Level1) +{ + auto ability = std::make_shared(want_, abilityInfo_, appInfo_); + auto missionRecord = std::make_shared(abilityInfo_.bundleName); + missionRecord->AddAbilityRecordToTop(nullptr); + EXPECT_EQ(0, missionRecord->GetAbilityRecordCount()); + EXPECT_EQ(nullptr, missionRecord->GetTopAbilityRecord()); +} + +/* + * Feature: MissionRecord + * Function: GetAbilityRecordCount and GetTopAbilityRecord + * SubFunction: NA + * FunctionPoints: MissionRecord GetAbilityRecordCount and GetTopAbilityRecord + * EnvConditions:NA + * CaseDescription: Create a mission record to view the value + */ +HWTEST_F(MissionRecordTest, stack_operating_005, TestSize.Level1) +{ + auto missionRecord = std::make_shared(""); + EXPECT_EQ(0, missionRecord->GetAbilityRecordCount()); + EXPECT_EQ(nullptr, missionRecord->GetTopAbilityRecord()); +} + +/* + * Feature: MissionRecord + * Function: RemoveAbilityRecord + * SubFunction: NA + * FunctionPoints: MissionRecord RemoveAbilityRecord + * EnvConditions:NA + * CaseDescription: Create a mission record, add ability, Verify the removeabilityrecord operation + */ +HWTEST_F(MissionRecordTest, stack_operating_006, TestSize.Level1) +{ + auto ability = std::make_shared(want_, abilityInfo_, appInfo_); + auto missionRecord = std::make_shared(abilityInfo_.bundleName); + missionRecord->AddAbilityRecordToTop(ability); + EXPECT_EQ(1, missionRecord->GetAbilityRecordCount()); + EXPECT_EQ(true, missionRecord->RemoveAbilityRecord(ability)); + EXPECT_EQ(0, missionRecord->GetAbilityRecordCount()); +} + +/* + * Feature: MissionRecord + * Function: RemoveAbilityRecord + * SubFunction: NA + * FunctionPoints: MissionRecord RemoveAbilityRecord + * EnvConditions:NA + * CaseDescription: Create a mission record, add ability, remove ability2 fail + */ +HWTEST_F(MissionRecordTest, stack_operating_007, TestSize.Level1) +{ + auto ability = std::make_shared(want_, abilityInfo_, appInfo_); + auto ability2 = std::make_shared(want_, abilityInfo_, appInfo_); + auto missionRecord = std::make_shared(abilityInfo_.bundleName); + missionRecord->AddAbilityRecordToTop(ability); + EXPECT_EQ(1, missionRecord->GetAbilityRecordCount()); + EXPECT_EQ(false, missionRecord->RemoveAbilityRecord(ability2)); +} + +/* + * Feature: MissionRecord + * Function: RemoveAll + * SubFunction: NA + * FunctionPoints: MissionRecord RemoveAll + * EnvConditions:NA + * CaseDescription: mission record reomve all, Verify count + */ +HWTEST_F(MissionRecordTest, stack_operating_008, TestSize.Level1) +{ + auto ability = std::make_shared(want_, abilityInfo_, appInfo_); + auto ability2 = std::make_shared(want_, abilityInfo_, appInfo_); + auto missionRecord = std::make_shared(abilityInfo_.bundleName); + missionRecord->AddAbilityRecordToTop(ability); + missionRecord->AddAbilityRecordToTop(ability2); + EXPECT_EQ(2, missionRecord->GetAbilityRecordCount()); + missionRecord->RemoveAll(); + EXPECT_EQ(0, missionRecord->GetAbilityRecordCount()); +} + +/* + * Feature: MissionRecord + * Function: GetBottomAbilityRecord + * SubFunction: NA + * FunctionPoints: MissionRecord GetBottomAbilityRecord + * EnvConditions:NA + * CaseDescription: Verify GetBottomAbilityRecord value + */ +HWTEST_F(MissionRecordTest, stack_operating_009, TestSize.Level1) +{ + auto ability = std::make_shared(want_, abilityInfo_, appInfo_); + auto missionRecord = std::make_shared(); + EXPECT_EQ(nullptr, missionRecord->GetBottomAbilityRecord()); + + missionRecord->AddAbilityRecordToTop(ability); + EXPECT_EQ(ability, missionRecord->GetBottomAbilityRecord()); + EXPECT_EQ(ability, missionRecord->GetTopAbilityRecord()); +} + +/* + * Feature: MissionRecord + * Function: GetAbilityRecordByToken + * SubFunction: NA + * FunctionPoints: MissionRecord GetAbilityRecordByToken + * EnvConditions:NA + * CaseDescription: Verify GetAbilityRecordByToken value + */ +HWTEST_F(MissionRecordTest, stack_operating_010, TestSize.Level1) +{ + std::string deviceName = "device"; + std::string abilityName = "ServiceAbility"; + std::string appName = "hiservcie"; + std::string bundleName = "com.ix.hiservcie"; + auto abilityReq = GenerateAbilityRequest(deviceName, abilityName, appName, bundleName); + auto record = AbilityRecord::CreateAbilityRecord(abilityReq); + auto token = record->GetToken(); + + auto missionRecord = std::make_shared(); + EXPECT_EQ(nullptr, missionRecord->GetAbilityRecordByToken(token)); + missionRecord->AddAbilityRecordToTop(record); + EXPECT_EQ(record, missionRecord->GetAbilityRecordByToken(token)); +} + +/* + * Feature: MissionRecord + * Function: RemoveTopAbilityRecord + * SubFunction: NA + * FunctionPoints: MissionRecord RemoveTopAbilityRecord + * EnvConditions:NA + * CaseDescription: Verify RemoveTopAbilityRecord operation + */ +HWTEST_F(MissionRecordTest, stack_operating_011, TestSize.Level1) +{ + auto missionRecord = std::make_shared(); + EXPECT_EQ(false, missionRecord->RemoveTopAbilityRecord()); + + auto ability = std::make_shared(want_, abilityInfo_, appInfo_); + missionRecord->AddAbilityRecordToTop(ability); + EXPECT_EQ(true, missionRecord->RemoveTopAbilityRecord()); +} + +/* + * Feature: MissionRecord + * Function: RemoveTopAbilityRecord + * SubFunction: NA + * FunctionPoints: MissionRecord RemoveTopAbilityRecord + * EnvConditions:NA + * CaseDescription: Verify RemoveTopAbilityRecord operation + */ +HWTEST_F(MissionRecordTest, stack_operating_012, TestSize.Level1) +{ + std::string deviceName = "device"; + std::string abilityName = "ServiceAbility"; + std::string appName = "hiservcie"; + std::string bundleName = "com.ix.hiservcie"; + auto abilityReq = GenerateAbilityRequest(deviceName, abilityName, appName, bundleName); + auto record = AbilityRecord::CreateAbilityRecord(abilityReq); + auto missionRecord = std::make_shared(); + missionRecord->AddAbilityRecordToTop(record); + std::vector info; + info.push_back(std::string("0")); + missionRecord->Dump(info); + + EXPECT_NE(info.end(), std::find_if(info.begin(), info.end(), [](std::string &it) { + return std::string::npos != it.find("hiservcie"); + })); +} + +/* + * Feature: MissionRecord + * Function: NA + * SubFunction: NA + * FunctionPoints: SetPreMissionRecord GetPreMissionRecord + * EnvConditions:NA + * CaseDescription: SetPreMissionRecord GetPreMissionRecord UT. + */ +HWTEST_F(MissionRecordTest, stack_operating_013, TestSize.Level1) +{ + auto missionRecordPre = std::make_shared(); + auto missionRecordTarget = std::make_shared(); + missionRecordTarget->SetPreMissionRecord(missionRecordPre); + EXPECT_EQ(missionRecordTarget->GetPreMissionRecord().get(), missionRecordPre.get()); +} + +/* + * Feature: MissionRecord + * Function: NA + * SubFunction: NA + * FunctionPoints: SetIsLauncherCreate IsLauncherCreate + * EnvConditions:NA + * CaseDescription: SetIsLauncherCreate IsLauncherCreate UT. + */ +HWTEST_F(MissionRecordTest, stack_operating_014, TestSize.Level1) +{ + auto missionRecord = std::make_shared(); + missionRecord->SetIsLauncherCreate(); + EXPECT_EQ(true, missionRecord->IsLauncherCreate()); +} + +/* + * Feature: MissionRecord + * Function: NA + * SubFunction: NA + * FunctionPoints: Find Child + * EnvConditions:NA + * CaseDescription: Find Child UT. + */ +HWTEST_F(MissionRecordTest, stack_operating_015, TestSize.Level1) +{ + auto missionRecord = std::make_shared(); + EXPECT_EQ(nullptr, missionRecord->FindChild(-1)); +} + +/* + * Feature: MissionRecord + * Function: NA + * SubFunction: NA + * FunctionPoints: Find Child + * EnvConditions:NA + * CaseDescription: Find Child UT. + */ +HWTEST_F(MissionRecordTest, stack_operating_016, TestSize.Level1) +{ + auto missionRecord = std::make_shared(); + missionRecord->RemoveAll(); + auto ability = std::make_shared(want_, abilityInfo_, appInfo_); + missionRecord->AddAbilityRecordToTop(ability); + + EXPECT_EQ(nullptr, missionRecord->FindChild(2)); +} + +/* + * Feature: MissionRecord + * Function: NA + * SubFunction: NA + * FunctionPoints: Find Child + * EnvConditions:NA + * CaseDescription: Find Child UT. + */ +HWTEST_F(MissionRecordTest, stack_operating_017, TestSize.Level1) +{ + auto missionRecord = std::make_shared(); + missionRecord->RemoveAll(); + auto ability = std::make_shared(want_, abilityInfo_, appInfo_); + missionRecord->AddAbilityRecordToTop(ability); + + auto iter = missionRecord->abilities_.begin(); + EXPECT_EQ((*iter), missionRecord->FindChild(0)); +} + +/* + * Feature: MissionRecord + * Function: NA + * SubFunction: NA + * FunctionPoints: SetIsLauncherCreate IsLauncherCreate + * EnvConditions:NA + * CaseDescription: SetIsLauncherCreate IsLauncherCreate UT. + */ +HWTEST_F(MissionRecordTest, stack_Resume_001, TestSize.Level1) +{ + auto missionRecord = std::make_shared(); + + std::shared_ptr backup; + backup = std::make_shared(missionRecord); + missionRecord->abilities_.clear(); + auto ability = std::make_shared(want_, abilityInfo_, appInfo_); + backup->abilities_.push_front(ability); + + missionRecord->Resume(backup); + EXPECT_TRUE(1 == missionRecord->abilities_.size()); + EXPECT_EQ(true, ability->IsRestarting()); +} + +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/abilitymgr/test/unittest/phone/mission_stack_test/BUILD.gn b/tools/services/abilitymgr/test/unittest/phone/mission_stack_test/BUILD.gn new file mode 100644 index 00000000000..42d9528a1cf --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/mission_stack_test/BUILD.gn @@ -0,0 +1,65 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/test.gni") +import("//foundation/aafwk/standard/aafwk.gni") + +module_output_path = "aafwk_standard/abilitymgr" + +ohos_unittest("mission_stack_test") { + module_out_path = module_output_path + + include_dirs = [ + "${services_path}/abilitymgr/test/mock/libs/system_ability_mock", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy/include", + ] + + sources = [ + "//foundation/aafwk/standard/services/abilitymgr/test/mock/libs/appexecfwk_core/src/appmgr/mock_app_scheduler.cpp", + "mission_stack_test.cpp", # add mock file + ] + + configs = [ + "${services_path}/abilitymgr:abilityms_config", + "${services_path}/abilitymgr/test/mock:aafwk_mock_config", + ] + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + deps = [ + "${innerkits_path}/want:want", + "${services_path}/abilitymgr/test:abilityms_test_source", + "${services_path}/abilitymgr/test/mock/libs/aakit:aakit_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_appmgr_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_bundlemgr_mock", + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/frameworks/kits/ability/native:dummy_classes", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] +} + +group("unittest") { + testonly = true + + deps = [ ":mission_stack_test" ] +} diff --git a/tools/services/abilitymgr/test/unittest/phone/mission_stack_test/mission_stack_test.cpp b/tools/services/abilitymgr/test/unittest/phone/mission_stack_test/mission_stack_test.cpp new file mode 100644 index 00000000000..ce73db676ab --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/mission_stack_test/mission_stack_test.cpp @@ -0,0 +1,507 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#define private public +#define protected public +#include "mission_record.h" +#include "mission_stack.h" +#undef private +#undef protected +#include "hilog_wrapper.h" + +using namespace testing::ext; +using namespace OHOS::AppExecFwk; + +namespace OHOS { +namespace AAFwk { +constexpr int id = 1; +constexpr int userId = 2; + +class MissionStackTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + + std::shared_ptr missionStack_{nullptr}; +}; + +void MissionStackTest::SetUpTestCase(void) +{} +void MissionStackTest::TearDownTestCase(void) +{} +void MissionStackTest::TearDown() +{} + +void MissionStackTest::SetUp() +{ + missionStack_ = std::make_shared(id, userId); +} + +AbilityRequest GenerateAbilityRequest(const std::string &deviceName, const std::string &abilityName, + const std::string &appName, const std::string &bundleName) +{ + ElementName element(deviceName, abilityName, bundleName); + Want want; + want.SetElement(element); + + AbilityInfo abilityInfo; + abilityInfo.visible = true; + abilityInfo.applicationName = appName; + ApplicationInfo appinfo; + appinfo.name = appName; + + AbilityRequest abilityRequest; + abilityRequest.want = want; + abilityRequest.abilityInfo = abilityInfo; + abilityRequest.appInfo = appinfo; + + return abilityRequest; +} + +std::shared_ptr getFirstMissionRecord() +{ + std::string deviceName = "device"; + std::string abilityName = "FirstAbility"; + std::string appName = "FirstApp"; + std::string bundleName = "com.ix.first"; + auto abilityReq = GenerateAbilityRequest(deviceName, abilityName, appName, bundleName); + auto record = AbilityRecord::CreateAbilityRecord(abilityReq); + auto missionRecord = std::make_shared(); + missionRecord->AddAbilityRecordToTop(record); + + return missionRecord; +} + +std::shared_ptr getSecondMissionRecord() +{ + std::string deviceName = "device"; + std::string abilityName = "SecondAbility"; + std::string appName = "SecondApp"; + std::string bundleName = "com.ix.second"; + auto abilityReq = GenerateAbilityRequest(deviceName, abilityName, appName, bundleName); + auto record = AbilityRecord::CreateAbilityRecord(abilityReq); + auto missionRecord = std::make_shared(); + missionRecord->AddAbilityRecordToTop(record); + + return missionRecord; +} + +/* + * Feature: MissionStack + * Function: RemoveAll + * SubFunction: NA + * FunctionPoints: MissionStack RemoveAll + * EnvConditions:NA + * CaseDescription: Results after verifying removeAll + */ +HWTEST_F(MissionStackTest, MS_oprator_01, TestSize.Level0) +{ + missionStack_->AddMissionRecordToTop(getFirstMissionRecord()); + missionStack_->RemoveAll(); + EXPECT_EQ(nullptr, missionStack_->GetTopMissionRecord()); +} + +/* + * Feature: MissionStack + * Function: AddMissionRecordToTop + * SubFunction: NA + * FunctionPoints: MissionStack AddMissionRecordToTop + * EnvConditions:NA + * CaseDescription: Verify that the top ability record is the same as the added record + */ +HWTEST_F(MissionStackTest, MS_oprator_002, TestSize.Level0) +{ + std::shared_ptr nullMissionRecord = nullptr; + missionStack_->AddMissionRecordToTop(nullMissionRecord); + + std::string deviceName = "device"; + std::string abilityName = "FirstAbility"; + std::string appName = "FirstApp"; + std::string bundleName = "com.ix.first"; + auto abilityReq = GenerateAbilityRequest(deviceName, abilityName, appName, bundleName); + auto record = AbilityRecord::CreateAbilityRecord(abilityReq); + auto missionRecord = std::make_shared(bundleName); + missionRecord->AddAbilityRecordToTop(record); + + missionStack_->AddMissionRecordToTop(missionRecord); + + auto ability = missionStack_->GetTopAbilityRecord(); + + EXPECT_EQ(missionStack_->GetTopAbilityRecord(), record); +} + +/* + * Feature: MissionStack + * Function: AddMissionRecordToTop + * SubFunction: NA + * FunctionPoints: MissionStack AddMissionRecordToTop + * EnvConditions:NA + * CaseDescription: Verify that the top mission record is not empty + */ +HWTEST_F(MissionStackTest, MS_oprator_003, TestSize.Level0) +{ + missionStack_->AddMissionRecordToTop(getFirstMissionRecord()); + missionStack_->AddMissionRecordToTop(getSecondMissionRecord()); + + EXPECT_NE(missionStack_->GetTopAbilityRecord(), nullptr); +} + +/* + * Feature: MissionStack + * Function: GetTopMissionRecord + * SubFunction: NA + * FunctionPoints: MissionStack GetTopMissionRecord + * EnvConditions:NA + * CaseDescription: Verify that the top mission record is the same as the added record + */ +HWTEST_F(MissionStackTest, MS_oprator_004, TestSize.Level0) +{ + EXPECT_EQ(missionStack_->GetTopMissionRecord(), nullptr); + + std::string deviceName = "device"; + std::string abilityName = "FirstAbility"; + std::string appName = "FirstApp"; + std::string bundleName = "com.ix.first"; + auto abilityReq = GenerateAbilityRequest(deviceName, abilityName, appName, bundleName); + auto record = AbilityRecord::CreateAbilityRecord(abilityReq); + auto missionRecord = std::make_shared(); + missionRecord->AddAbilityRecordToTop(record); + + missionStack_->AddMissionRecordToTop(missionRecord); + EXPECT_EQ(missionStack_->GetTopMissionRecord(), missionRecord); +} + +/* + * Feature: MissionStack + * Function: GetMissionStackId + * SubFunction: NA + * FunctionPoints: MissionStack GetMissionStackId + * EnvConditions:NA + * CaseDescription: Verify that the mission stack id is not 0 + */ +HWTEST_F(MissionStackTest, MS_oprator_005, TestSize.Level0) +{ + missionStack_->AddMissionRecordToTop(getFirstMissionRecord()); + EXPECT_NE(missionStack_->GetMissionStackId(), 0); +} + +/* + * Feature: MissionStack + * Function: GetTargetMissionRecord + * SubFunction: NA + * FunctionPoints: MissionStack GetTargetMissionRecord + * EnvConditions:NA + * CaseDescription: Verify that the get target mission record is equal to the one added + */ +HWTEST_F(MissionStackTest, MS_oprator_006, TestSize.Level0) +{ + EXPECT_EQ(nullptr, missionStack_->GetTargetMissionRecord("FirstApp")); + + std::string deviceName = "aaaa"; + std::string abilityName = "bbbb"; + std::string appName = "ccccc"; + std::string bundleName = "ddddd"; + auto abilityReq = GenerateAbilityRequest(deviceName, abilityName, appName, bundleName); + auto record = AbilityRecord::CreateAbilityRecord(abilityReq); + auto missionRecord = std::make_shared(bundleName); + missionRecord->AddAbilityRecordToTop(record); + + missionStack_->AddMissionRecordToTop(missionRecord); + + EXPECT_EQ(missionRecord, missionStack_->GetTargetMissionRecord("ddddd")); +} + +/* + * Feature: MissionStack + * Function: GetMissionStackId GetMissionStackUserId + * SubFunction: NA + * FunctionPoints: MissionStack GetMissionStackId and GetMissionStackUserId + * EnvConditions:NA + * CaseDescription: Verify the value of get mission stack ID and get mission stack user ID + */ +HWTEST_F(MissionStackTest, MS_oprator_007, TestSize.Level0) +{ + EXPECT_EQ(missionStack_->GetMissionStackId(), 1); + EXPECT_EQ(missionStack_->GetMissionStackUserId(), 2); +} + +/* + * Feature: MissionStack + * Function: GetMissionRecordCount + * SubFunction: NA + * FunctionPoints: MissionStack GetMissionRecordCount + * EnvConditions:NA + * CaseDescription: Verify the value of get mission record count + */ +HWTEST_F(MissionStackTest, MS_oprator_008, TestSize.Level0) +{ + EXPECT_EQ(missionStack_->GetMissionRecordCount(), 0); + missionStack_->AddMissionRecordToTop(getSecondMissionRecord()); + EXPECT_EQ(missionStack_->GetMissionRecordCount(), 1); +} + +/* + * Feature: MissionStack + * Function: GetTopMissionRecord + * SubFunction: NA + * FunctionPoints: MissionStack GetTopMissionRecord + * EnvConditions:NA + * CaseDescription: Verify that the get top mission record is equal to the one added + */ +HWTEST_F(MissionStackTest, MS_oprator_009, TestSize.Level0) +{ + std::string deviceName = "device"; + std::string abilityName = "FirstAbility"; + std::string appName = "FirstApp"; + std::string bundleName = "com.ix.first"; + auto abilityReq = GenerateAbilityRequest(deviceName, abilityName, appName, bundleName); + auto record = AbilityRecord::CreateAbilityRecord(abilityReq); + auto missionRecord = std::make_shared(); + missionRecord->AddAbilityRecordToTop(record); + + std::shared_ptr nullMR = nullptr; + missionStack_->MoveMissionRecordToTop(nullMR); + + missionStack_->AddMissionRecordToTop(getSecondMissionRecord()); + + missionStack_->MoveMissionRecordToTop(missionRecord); + EXPECT_EQ(missionStack_->GetTopMissionRecord(), missionRecord); +} + +/* + * Feature: MissionStack + * Function: Dump DumpStackList + * SubFunction: NA + * FunctionPoints: MissionStack Dump and DumpStackList + * EnvConditions:NA + * CaseDescription: Verify Dump and DumpStackList results + */ +HWTEST_F(MissionStackTest, MS_oprator_010, TestSize.Level0) +{ + std::vector info; + std::vector listInfo; + + const Want want; + AbilityInfo abilityInfo; + abilityInfo.name = "FirstAbility"; + abilityInfo.bundleName = "com.ix.first"; + ApplicationInfo appInfo; + appInfo.name = "FirstApp"; + appInfo.bundleName = "com.ix.first"; + + auto record = std::make_shared(want, abilityInfo, appInfo, -1); + auto missionRecord = std::make_shared(); + missionRecord->AddAbilityRecordToTop(record); + missionStack_->MoveMissionRecordToTop(missionRecord); + + missionStack_->Dump(info); + missionStack_->DumpStackList(listInfo); + + EXPECT_NE(info.end(), std::find_if(info.begin(), info.end(), [](std::string &it) { + return std::string::npos != it.find("FirstAbility"); + })); + + EXPECT_NE(listInfo.end(), std::find_if(listInfo.begin(), listInfo.end(), [](std::string &it) { + return std::string::npos != it.find("MissionStack ID #1 [ #10 ]"); + })); +} + +/* + * Feature: MissionStack + * Function: GetMissionRecordById + * SubFunction: NA + * FunctionPoints: MissionStack GetMissionRecordById + * EnvConditions:NA + * CaseDescription: Verify that the get mission record by ID value is empty + */ +HWTEST_F(MissionStackTest, MS_oprator_011, TestSize.Level0) +{ + EXPECT_EQ(missionStack_->GetMissionRecordById(0), nullptr); + + std::string deviceName = "device"; + std::string abilityName = "FirstAbility"; + std::string appName = "FirstApp"; + std::string bundleName = "com.ix.first"; + auto abilityReq = GenerateAbilityRequest(deviceName, abilityName, appName, bundleName); + auto record = AbilityRecord::CreateAbilityRecord(abilityReq); + auto missionRecord = std::make_shared(); + missionRecord->AddAbilityRecordToTop(record); + + missionStack_->AddMissionRecordToTop(missionRecord); + + EXPECT_NE(nullptr, missionStack_->GetMissionRecordById(11)); +} + +/* + * Feature: MissionStack + * Function: GetMissionRecordById + * SubFunction: NA + * FunctionPoints: MissionStack GetMissionRecordById + * EnvConditions:NA + * CaseDescription: Verify the get mission record by ID value + */ +HWTEST_F(MissionStackTest, MS_oprator_012, TestSize.Level0) +{ + EXPECT_EQ(missionStack_->GetMissionRecordById(0), nullptr); + + std::string deviceName = "device"; + std::string abilityName = "FirstAbility"; + std::string appName = "FirstApp"; + std::string bundleName = "com.ix.first"; + auto abilityReq = GenerateAbilityRequest(deviceName, abilityName, appName, bundleName); + auto record = AbilityRecord::CreateAbilityRecord(abilityReq); + auto missionRecord = std::make_shared(); + missionRecord->AddAbilityRecordToTop(record); + + missionStack_->AddMissionRecordToTop(missionRecord); + + EXPECT_NE(nullptr, missionStack_->GetMissionRecordById(12)); +} + +/* + * Feature: MissionStack + * Function: GetAbilityRecordByToken + * SubFunction: NA + * FunctionPoints: MissionStack GetAbilityRecordByToken + * EnvConditions:NA + * CaseDescription: Verify that the values of get ability record by token are equal + */ +HWTEST_F(MissionStackTest, MS_oprator_013, TestSize.Level0) +{ + OHOS::sptr token = nullptr; + EXPECT_EQ(missionStack_->GetAbilityRecordByToken(token), nullptr); + + std::string deviceName = "device"; + std::string abilityName = "FirstAbility"; + std::string appName = "FirstApp"; + std::string bundleName = "com.ix.first"; + auto abilityReq = GenerateAbilityRequest(deviceName, abilityName, appName, bundleName); + auto record = AbilityRecord::CreateAbilityRecord(abilityReq); + auto missionRecord = std::make_shared(); + missionRecord->AddAbilityRecordToTop(record); + auto firstToken = record->GetToken(); + + missionStack_->AddMissionRecordToTop(missionRecord); + + EXPECT_EQ(record, missionStack_->GetAbilityRecordByToken(firstToken)); +} + +/* + * Feature: MissionStack + * Function: RemoveAbilityRecordByToken + * SubFunction: NA + * FunctionPoints: MissionStack RemoveAbilityRecordByToken + * EnvConditions:NA + * CaseDescription: Verify that remove ability record by token is successful + */ +HWTEST_F(MissionStackTest, MS_oprator_014, TestSize.Level0) +{ + std::string deviceName = "device"; + std::string abilityName = "FirstAbility"; + std::string appName = "FirstApp"; + std::string bundleName = "com.ix.first"; + auto abilityReq = GenerateAbilityRequest(deviceName, abilityName, appName, bundleName); + auto record = AbilityRecord::CreateAbilityRecord(abilityReq); + auto missionRecord = std::make_shared(); + missionRecord->AddAbilityRecordToTop(record); + auto firstToken = record->GetToken(); + + EXPECT_EQ(missionStack_->RemoveAbilityRecordByToken(*(firstToken.GetRefPtr())), false); + + missionStack_->AddMissionRecordToTop(missionRecord); + + EXPECT_EQ(true, missionStack_->RemoveAbilityRecordByToken(*(firstToken.GetRefPtr()))); +} + +/* + * Feature: MissionStack + * Function: RemoveMissionRecord + * SubFunction: NA + * FunctionPoints: MissionStack RemoveMissionRecord + * EnvConditions:NA + * CaseDescription: Verify that remove mission record is successful + */ +HWTEST_F(MissionStackTest, MS_oprator_015, TestSize.Level0) +{ + EXPECT_EQ(missionStack_->RemoveMissionRecord(100), false); + + std::string deviceName = "device"; + std::string abilityName = "FirstAbility"; + std::string appName = "FirstApp"; + std::string bundleName = "com.ix.first"; + auto abilityReq = GenerateAbilityRequest(deviceName, abilityName, appName, bundleName); + auto record = AbilityRecord::CreateAbilityRecord(abilityReq); + auto missionRecord = std::make_shared("com.ix.first"); + missionRecord->AddAbilityRecordToTop(record); + + missionStack_->AddMissionRecordToTop(missionRecord); + + EXPECT_EQ(true, missionStack_->RemoveMissionRecord(15)); +} + +/* + * Feature: MissionStack + * Function: FindChild + * SubFunction: NA + * FunctionPoints: Find Child + * EnvConditions:NA + * CaseDescription: Find Child UT. + */ +HWTEST_F(MissionStackTest, MS_oprator_016, TestSize.Level1) +{ + EXPECT_EQ(nullptr, missionStack_->FindChild(-1)); +} + +/* + * Feature: MissionStack + * Function: FindChild + * SubFunction: NA + * FunctionPoints: Find Child + * EnvConditions:NA + * CaseDescription: Find Child UT. + */ +HWTEST_F(MissionStackTest, MS_oprator_017, TestSize.Level1) +{ + missionStack_->missions_.clear(); + auto missionRecord = std::make_shared(); + + missionStack_->missions_.push_back(missionRecord); + + EXPECT_EQ(nullptr, missionStack_->FindChild(2)); +} + +/* + * Feature: MissionStack + * Function: FindChild + * SubFunction: NA + * FunctionPoints: Find Child + * EnvConditions:NA + * CaseDescription: Find Child UT. + */ +HWTEST_F(MissionStackTest, MS_oprator_018, TestSize.Level1) +{ + missionStack_->missions_.clear(); + auto missionRecord = std::make_shared(); + + missionStack_->missions_.push_back(missionRecord); + auto iter = missionStack_->missions_.begin(); + EXPECT_EQ((*iter), missionStack_->FindChild(0)); +} + +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/abilitymgr/test/unittest/phone/pending_want_key_test/BUILD.gn b/tools/services/abilitymgr/test/unittest/phone/pending_want_key_test/BUILD.gn new file mode 100644 index 00000000000..bf06448b35e --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/pending_want_key_test/BUILD.gn @@ -0,0 +1,60 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/test.gni") +import("//foundation/aafwk/standard/aafwk.gni") + +module_output_path = "aafwk_standard/abilitymgr" + +ohos_unittest("pending_want_key_test") { + module_out_path = module_output_path + + include_dirs = [ + "//foundation/aafwk/standard/services/abilitymgr/include", + "//foundation/aafwk/standard/interfaces/innerkits/want/include/ohos/aafwk/content", + ] + + sources = [ + "//foundation/aafwk/standard/services/abilitymgr/test/mock/libs/appexecfwk_core/src/appmgr/mock_app_scheduler.cpp", + "pending_want_key_test.cpp", # add mock file + ] + + configs = [ "${services_path}/abilitymgr:abilityms_config" ] + + deps = [ + "${innerkits_path}/want:want", + "${services_path}/abilitymgr/test:abilityms_test_source", + "${services_path}/abilitymgr/test/mock/libs/aakit:aakit_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_appmgr_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_bundlemgr_mock", + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/frameworks/kits/ability/native:dummy_classes", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//third_party/googletest:gmock_main", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] +} + +group("unittest") { + testonly = true + + deps = [ ":pending_want_key_test" ] +} diff --git a/tools/services/abilitymgr/test/unittest/phone/pending_want_key_test/pending_want_key_test.cpp b/tools/services/abilitymgr/test/unittest/phone/pending_want_key_test/pending_want_key_test.cpp new file mode 100644 index 00000000000..e1c41ccd079 --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/pending_want_key_test/pending_want_key_test.cpp @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#define private public +#include "pending_want_key.h" +#undef private +#include "want.h" +#include "wants_info.h" + +constexpr int PENDING_WANT_TYPE = 1; +const std::string PENDING_WANT_BUNDLENAME = "bundleName"; +const std::string PENDING_WANT_WHO = "who"; +constexpr int PENDING_WANT_REQUESTCODE = 2; +const std::string PENDING_WANT_REQUESTRESLOVEDTYPE = "requestResolvedType"; +constexpr int PENDING_WANT_FLAGS = 10; +constexpr int PENDING_WANT_CODE = 20; +constexpr int PENDING_WANT_USERID = 123456; + +using namespace testing::ext; +using namespace OHOS::AppExecFwk; +namespace OHOS { +namespace AAFwk { +class PendingWantKeyTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void PendingWantKeyTest::SetUpTestCase(void) +{} +void PendingWantKeyTest::TearDownTestCase(void) +{} +void PendingWantKeyTest::SetUp(void) +{} +void PendingWantKeyTest::TearDown(void) +{} + +/* + * @tc.number : SetType_0100 + * @tc.name : set type + * @tc.desc : Set type, use GetType to verify whether the type value is set successfully + */ +HWTEST_F(PendingWantKeyTest, SetType_0100, TestSize.Level1) +{ + std::unique_ptr amsPendingWantKey = std::make_unique(); + + amsPendingWantKey->SetType(PENDING_WANT_TYPE); + EXPECT_EQ(PENDING_WANT_TYPE, amsPendingWantKey->GetType()); +} + +/* + * @tc.number : SetBundleName_0100 + * @tc.name : set BundleName + * @tc.desc : Set BundleName, use GetBundleName to verify whether the BundleName is set successfully + */ +HWTEST_F(PendingWantKeyTest, SetBundleName_0100, TestSize.Level1) +{ + std::unique_ptr amsPendingWantKey = std::make_unique(); + + amsPendingWantKey->SetBundleName(PENDING_WANT_BUNDLENAME); + EXPECT_EQ(PENDING_WANT_BUNDLENAME, amsPendingWantKey->GetBundleName()); +} + +/* + * @tc.number : SetRequestWho_0100 + * @tc.name : set RequestWho + * @tc.desc : Set RequestWho, use GetWho to verify whether the RequestWho is set successfully + */ +HWTEST_F(PendingWantKeyTest, SetRequestWho_0100, TestSize.Level1) +{ + std::unique_ptr amsPendingWantKey = std::make_unique(); + + amsPendingWantKey->SetRequestWho(PENDING_WANT_WHO); + EXPECT_EQ(PENDING_WANT_WHO, amsPendingWantKey->GetRequestWho()); +} + +/* + * @tc.number : SetRequestCode_0100 + * @tc.name : set RequestCode + * @tc.desc : Set RequestCode, use GetRequestCode to verify whether the RequestCode is set successfully + */ +HWTEST_F(PendingWantKeyTest, SetRequestCode_0100, TestSize.Level1) +{ + std::unique_ptr amsPendingWantKey = std::make_unique(); + + amsPendingWantKey->SetRequestCode(PENDING_WANT_REQUESTCODE); + EXPECT_EQ(PENDING_WANT_REQUESTCODE, amsPendingWantKey->GetRequestCode()); +} + +/* + * @tc.number : SetRequestWant_0100 + * @tc.name : set RequestWant + * @tc.desc : Set RequestWant, use GetRequestWant to verify whether the RequestWant is set successfully + */ +HWTEST_F(PendingWantKeyTest, SetRequestWant_0100, TestSize.Level1) +{ + std::unique_ptr amsPendingWantKey = std::make_unique(); + + Want requestWant; + OHOS::AAFwk::Operation operation; + std::string bundleName = "ohos.pending.want.key.test"; + operation.SetBundleName(bundleName); + requestWant.SetOperation(operation); + amsPendingWantKey->SetRequestWant(requestWant); + Want requestWant_ = amsPendingWantKey->GetRequestWant(); + EXPECT_EQ(bundleName, requestWant_.GetOperation().GetBundleName()); +} + +/* + * @tc.number : SetRequestResolvedType_0100 + * @tc.name : set request resolved Type + * @tc.desc : Set RequestResolvedType, use GetRequestResolvedType to verify whether the RequestResolvedType is + * set successfully + */ +HWTEST_F(PendingWantKeyTest, SetRequestResolvedType_0100, TestSize.Level1) +{ + std::unique_ptr amsPendingWantKey = std::make_unique(); + + amsPendingWantKey->SetRequestResolvedType(PENDING_WANT_REQUESTRESLOVEDTYPE); + EXPECT_EQ(PENDING_WANT_REQUESTRESLOVEDTYPE, amsPendingWantKey->GetRequestResolvedType()); +} + +/* + * @tc.number : SetAllWantsInfos_0100 + * @tc.name : set All WantsInfos + * @tc.desc : Set AllWantsInfos, use GetAllWantsInfos to verify whether the AllWantsInfos is set successfully + */ +HWTEST_F(PendingWantKeyTest, SetAllWantsInfos_0100, TestSize.Level1) +{ + std::unique_ptr amsPendingWantKey = std::make_unique(); + + amsPendingWantKey->allWantsInfos_.clear(); + std::vector allWantsInfos; + WantsInfo wantsInfo; + + wantsInfo.resolvedTypes = "resolvedTypes"; + allWantsInfos.push_back(wantsInfo); + amsPendingWantKey->SetAllWantsInfos(allWantsInfos); + std::vector wantsInfo_ = amsPendingWantKey->GetAllWantsInfos(); + EXPECT_EQ(wantsInfo.resolvedTypes, wantsInfo_.front().resolvedTypes); +} + +/* + * @tc.number : SetFlags_0100 + * @tc.name : set Flags + * @tc.desc : Set Flags, use GetFlags to verify whether the Flags is set successfully + */ +HWTEST_F(PendingWantKeyTest, SetFlags_0100, TestSize.Level1) +{ + std::unique_ptr amsPendingWantKey = std::make_unique(); + + amsPendingWantKey->SetFlags(PENDING_WANT_FLAGS); + EXPECT_EQ(PENDING_WANT_FLAGS, amsPendingWantKey->GetFlags()); +} + +/* + * @tc.number : SetCode_0100 + * @tc.name : set Code + * @tc.desc : Set Code, use GetCode to verify whether the Code is set successfully + */ +HWTEST_F(PendingWantKeyTest, SetCode_0100, TestSize.Level1) +{ + std::unique_ptr amsPendingWantKey = std::make_unique(); + + amsPendingWantKey->SetCode(PENDING_WANT_CODE); + EXPECT_EQ(PENDING_WANT_CODE, amsPendingWantKey->GetCode()); +} + +/* + * @tc.number : SetUserId_0100 + * @tc.name : set UserId + * @tc.desc : Set UserId, use GetUserId to verify whether the UserId is set successfully + */ +HWTEST_F(PendingWantKeyTest, SetUserId_0100, TestSize.Level1) +{ + std::unique_ptr amsPendingWantKey = std::make_unique(); + + amsPendingWantKey->SetUserId(PENDING_WANT_USERID); + EXPECT_EQ(PENDING_WANT_USERID, amsPendingWantKey->GetUserId()); +} +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/abilitymgr/test/unittest/phone/pending_want_manager_test/BUILD.gn b/tools/services/abilitymgr/test/unittest/phone/pending_want_manager_test/BUILD.gn new file mode 100644 index 00000000000..f2d3c06844e --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/pending_want_manager_test/BUILD.gn @@ -0,0 +1,64 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/test.gni") +import("//foundation/aafwk/standard/aafwk.gni") + +module_output_path = "aafwk_standard/abilitymgr" + +ohos_unittest("pending_want_manager_test") { + module_out_path = module_output_path + + include_dirs = [ + "${services_path}/abilitymgr/test/mock/libs/system_ability_mock", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy/include", + "//foundation/distributedschedule/samgr/adapter/interfaces/innerkits/include/", + ] + + sources = [ + "//foundation/aafwk/standard/services/abilitymgr/test/mock/libs/appexecfwk_core/src/appmgr/mock_app_scheduler.cpp", + "pending_want_manager_test.cpp", # add mock file + ] + + configs = [ "${services_path}/abilitymgr:abilityms_config" ] + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + deps = [ + "${innerkits_path}/want:want", + "${services_path}/abilitymgr/test:abilityms_test_source", + "${services_path}/abilitymgr/test/mock/libs/aakit:aakit_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_appmgr_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_bundlemgr_mock", + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/frameworks/kits/ability/native:dummy_classes", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//third_party/googletest:gmock_main", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] +} + +group("unittest") { + testonly = true + + deps = [ ":pending_want_manager_test" ] +} diff --git a/tools/services/abilitymgr/test/unittest/phone/pending_want_manager_test/pending_want_manager_test.cpp b/tools/services/abilitymgr/test/unittest/phone/pending_want_manager_test/pending_want_manager_test.cpp new file mode 100644 index 00000000000..aed8de4439c --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/pending_want_manager_test/pending_want_manager_test.cpp @@ -0,0 +1,875 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "bundlemgr/mock_bundle_manager.h" +#include "mock_ability_connect_callback.h" +#include "ability_manager_errors.h" +#include "ability_scheduler.h" +#define private public +#define protected public +#include "ability_event_handler.h" +#include "ability_manager_service.h" +#undef private +#undef protected +#include "if_system_ability_manager.h" +#include "iservice_registry.h" +#define private public +#define protected public +#include "pending_want_record.h" +#include "pending_want_manager.h" +#undef private +#undef protected +#include "sa_mgr_client.h" +#include "sender_info.h" +#include "system_ability_definition.h" +#include "wants_info.h" +#include "want_receiver_stub.h" +#include "want_sender_stub.h" + +using namespace testing; +using namespace testing::ext; +using namespace OHOS::AppExecFwk; +using OHOS::AppExecFwk::ElementName; + +namespace OHOS { +namespace AAFwk { +static void WaitUntilTaskFinished() +{ + const uint32_t maxRetryCount = 1000; + const uint32_t sleepTime = 1000; + uint32_t count = 0; + auto handler = OHOS::DelayedSingleton::GetInstance()->GetEventHandler(); + std::atomic taskCalled(false); + auto f = [&taskCalled]() { taskCalled.store(true); }; + if (handler->PostTask(f)) { + while (!taskCalled.load()) { + ++count; + if (count >= maxRetryCount) { + break; + } + usleep(sleepTime); + } + } +} + +#define SLEEP(milli) std::this_thread::sleep_for(std::chrono::seconds(milli)) + +namespace {} // namespace +class PendingWantManagerTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp(); + void TearDown(); + WantSenderInfo MakeWantSenderInfo(Want &want, int32_t flags, int32_t userId, int32_t type = 1); + std::shared_ptr MakeWantKey(WantSenderInfo &wantSenderInfo); + static constexpr int TEST_WAIT_TIME = 100000; + + class CancelReceiver : public AAFwk::WantReceiverStub { + public: + static int performReceiveCount; + static int sendCount; + void Send(const int32_t resultCode) override; + void PerformReceive(const AAFwk::Want &want, int resultCode, const std::string &data, + const AAFwk::WantParams &extras, bool serialized, bool sticky, int sendingUser) override; + virtual sptr AsObject() override + { + return nullptr; + } + }; + +public: + std::shared_ptr pendingManager_{nullptr}; + std::shared_ptr abilityMs_{nullptr}; +}; + +int PendingWantManagerTest::CancelReceiver::performReceiveCount = 0; +int PendingWantManagerTest::CancelReceiver::sendCount = 0; + +void PendingWantManagerTest::CancelReceiver::Send(const int32_t resultCode) +{ + sendCount = 100; +} +void PendingWantManagerTest::CancelReceiver::PerformReceive(const AAFwk::Want &want, int resultCode, + const std::string &data, const AAFwk::WantParams &extras, bool serialized, bool sticky, int sendingUser) +{ + performReceiveCount = 100; +} + +void PendingWantManagerTest::SetUpTestCase() +{ + OHOS::DelayedSingleton::GetInstance()->RegisterSystemAbility( + OHOS::BUNDLE_MGR_SERVICE_SYS_ABILITY_ID, new BundleMgrService()); +} + +void PendingWantManagerTest::TearDownTestCase() +{ + OHOS::DelayedSingleton::DestroyInstance(); +} + +void PendingWantManagerTest::SetUp() +{ + + abilityMs_ = OHOS::DelayedSingleton::GetInstance(); + abilityMs_->OnStart(); + WaitUntilTaskFinished(); +} + +void PendingWantManagerTest::TearDown() +{ + abilityMs_->OnStop(); + OHOS::DelayedSingleton::DestroyInstance(); +} + +WantSenderInfo PendingWantManagerTest::MakeWantSenderInfo(Want &want, int32_t flags, int32_t userId, int32_t type) +{ + WantSenderInfo wantSenderInfo; + wantSenderInfo.type = type; + // wantSenderInfo.type is OperationType::START_ABILITY + wantSenderInfo.bundleName = "com.ix.hiRadio"; + wantSenderInfo.resultWho = "RadioTopAbility"; + int requestCode = 10; + wantSenderInfo.requestCode = requestCode; + std::vector allWant; + WantsInfo wantInfo; + wantInfo.want = want; + wantInfo.resolvedTypes = "nihao"; + allWant.emplace_back(wantInfo); + wantSenderInfo.allWants = allWant; + wantSenderInfo.flags = flags; + wantSenderInfo.userId = userId; + return wantSenderInfo; +} + +std::shared_ptr PendingWantManagerTest::MakeWantKey(WantSenderInfo &wantSenderInfo) +{ + std::shared_ptr pendingKey = std::make_shared(); + pendingKey->SetBundleName(wantSenderInfo.bundleName); + pendingKey->SetRequestWho(wantSenderInfo.resultWho); + pendingKey->SetRequestCode(wantSenderInfo.requestCode); + pendingKey->SetFlags(wantSenderInfo.flags); + pendingKey->SetUserId(wantSenderInfo.userId); + pendingKey->SetType(wantSenderInfo.type); + if (wantSenderInfo.allWants.size() > 0) { + pendingKey->SetRequestWant(wantSenderInfo.allWants.back().want); + pendingKey->SetRequestResolvedType(wantSenderInfo.allWants.back().resolvedTypes); + pendingKey->SetAllWantsInfos(wantSenderInfo.allWants); + } + return pendingKey; +} + +/* + * @tc.number : PendingWantManagerTest_0100 + * @tc.name : PendingWantManager GetWantSender + * @tc.desc : 1.GetWantSender function callingUid = 0 + */ +HWTEST_F(PendingWantManagerTest, PendingWantManagerTest_0100, TestSize.Level1) +{ + int32_t callingUid = 0; + int32_t uid = 0; + WantSenderInfo wantSenderInfo; + pendingManager_ = std::make_shared(); + EXPECT_NE(pendingManager_, nullptr); + EXPECT_NE(pendingManager_->GetWantSender(callingUid, uid, false, wantSenderInfo, nullptr), nullptr); +} + +/* + * @tc.number : PendingWantManagerTest_0200 + * @tc.name : PendingWantManager GetWantSender + * @tc.desc : 1.GetWantSender function callingUid = SYSTEM_UID + */ +HWTEST_F(PendingWantManagerTest, PendingWantManagerTest_0200, TestSize.Level1) +{ + int32_t callingUid = SYSTEM_UID; + int32_t uid = 0; + WantSenderInfo wantSenderInfo; + pendingManager_ = std::make_shared(); + EXPECT_NE(pendingManager_, nullptr); + EXPECT_NE(pendingManager_->GetWantSender(callingUid, uid, false, wantSenderInfo, nullptr), nullptr); +} + +/* + * @tc.number : PendingWantManagerTest_0300 + * @tc.name : PendingWantManager GetWantSender + * @tc.desc : 1.GetWantSender function callingUid = 1 && callingUid != uid + */ +HWTEST_F(PendingWantManagerTest, PendingWantManagerTest_0300, TestSize.Level1) +{ + int32_t callingUid = 1; + int32_t uid = 0; + WantSenderInfo wantSenderInfo; + pendingManager_ = std::make_shared(); + EXPECT_NE(pendingManager_, nullptr); + EXPECT_EQ(pendingManager_->GetWantSender(callingUid, uid, false, wantSenderInfo, nullptr), nullptr); +} + +/* + * @tc.number : PendingWantManagerTest_0400 + * @tc.name : PendingWantManager GetWantSender + * @tc.desc : 1.GetWantSender function callingUid = 1 && callingUid == uid + */ +HWTEST_F(PendingWantManagerTest, PendingWantManagerTest_0400, TestSize.Level1) +{ + int32_t callingUid = 1; + int32_t uid = 1; + WantSenderInfo wantSenderInfo; + pendingManager_ = std::make_shared(); + EXPECT_NE(pendingManager_, nullptr); + EXPECT_NE(pendingManager_->GetWantSender(callingUid, uid, false, wantSenderInfo, nullptr), nullptr); +} + +/* + * @tc.number : PendingWantManagerTest_0500 + * @tc.name : PendingWantManager GetWantSenderLocked + * @tc.desc : 1.GetWantSenderLocked Flags::NO_BUILD_FLAG + */ +HWTEST_F(PendingWantManagerTest, PendingWantManagerTest_0500, TestSize.Level1) +{ + Want want; + ElementName element("device", "bundleName", "abilityName"); + want.SetElement(element); + WantSenderInfo wantSenderInfo = MakeWantSenderInfo(want, static_cast(Flags::NO_BUILD_FLAG), 0); + EXPECT_TRUE(((unsigned int)wantSenderInfo.flags & (unsigned int)Flags::NO_BUILD_FLAG) != 0); + pendingManager_ = std::make_shared(); + EXPECT_NE(pendingManager_, nullptr); + EXPECT_EQ(pendingManager_->GetWantSenderLocked(1, 1, wantSenderInfo.userId, wantSenderInfo, nullptr), nullptr); +} + +/* + * @tc.number : PendingWantManagerTest_0600 + * @tc.name : PendingWantManager GetWantSenderLocked + * @tc.desc : 1.GetWantSenderLocked Flags::ONE_TIME_FLAG ,Creat PendingWantRecord + */ +HWTEST_F(PendingWantManagerTest, PendingWantManagerTest_0600, TestSize.Level1) +{ + Want want; + ElementName element("device", "bundleName", "abilityName"); + want.SetElement(element); + WantSenderInfo wantSenderInfo = MakeWantSenderInfo(want, 0, 0); + EXPECT_FALSE(((unsigned int)wantSenderInfo.flags & (unsigned int)Flags::NO_BUILD_FLAG) != 0); + pendingManager_ = std::make_shared(); + EXPECT_NE(pendingManager_, nullptr); + EXPECT_NE(pendingManager_->GetWantSenderLocked(1, 1, wantSenderInfo.userId, wantSenderInfo, nullptr), nullptr); +} + +/* + * @tc.number : PendingWantManagerTest_0700 + * @tc.name : PendingWantManager GetWantSenderLocked + * @tc.desc : 1.GetWantSenderLocked Flags::NO_BUILD_FLAG ,cancel PendingWantRecord + */ +HWTEST_F(PendingWantManagerTest, PendingWantManagerTest_0700, TestSize.Level1) +{ + Want want; + ElementName element("device", "bundleName", "abilityName"); + want.SetElement(element); + WantSenderInfo wantSenderInfo = MakeWantSenderInfo(want, 0, 0); + EXPECT_FALSE(((unsigned int)wantSenderInfo.flags & (unsigned int)Flags::NO_BUILD_FLAG) != 0); + pendingManager_ = std::make_shared(); + EXPECT_NE(pendingManager_, nullptr); + EXPECT_NE(pendingManager_->GetWantSenderLocked(1, 1, wantSenderInfo.userId, wantSenderInfo, nullptr), nullptr); + EXPECT_EQ((int)pendingManager_->wantRecords_.size(), 1); + WantSenderInfo wantSenderInfo1 = MakeWantSenderInfo(want, static_cast(Flags::CANCEL_PRESENT_FLAG), 0); + EXPECT_TRUE(((unsigned int)wantSenderInfo1.flags & (unsigned int)Flags::CANCEL_PRESENT_FLAG) != 0); + EXPECT_EQ(pendingManager_->GetWantSenderLocked(1, 1, wantSenderInfo1.userId, wantSenderInfo1, nullptr), nullptr); + EXPECT_EQ((int)pendingManager_->wantRecords_.size(), 0); +} + +/* + * @tc.number : PendingWantManagerTest_0800 + * @tc.name : PendingWantManager GetWantSenderLocked + * @tc.desc : 1.GetWantSenderLocked,Flags::UPDATE_PRESENT_FLAG ,update PendingWantRecord + */ +HWTEST_F(PendingWantManagerTest, PendingWantManagerTest_0800, TestSize.Level1) +{ + Want want; + ElementName element("device", "bundleName", "abilityName"); + want.SetElement(element); + WantSenderInfo wantSenderInfo = MakeWantSenderInfo(want, 0, 0); + EXPECT_FALSE(((unsigned int)wantSenderInfo.flags & (unsigned int)Flags::NO_BUILD_FLAG) != 0); + pendingManager_ = std::make_shared(); + EXPECT_NE(pendingManager_, nullptr); + EXPECT_NE(pendingManager_->GetWantSenderLocked(1, 1, wantSenderInfo.userId, wantSenderInfo, nullptr), nullptr); + EXPECT_EQ((int)pendingManager_->wantRecords_.size(), 1); + WantSenderInfo wantSenderInfo1 = MakeWantSenderInfo(want, static_cast(Flags::UPDATE_PRESENT_FLAG), 0); + EXPECT_TRUE(((unsigned int)wantSenderInfo1.flags & (unsigned int)Flags::UPDATE_PRESENT_FLAG) != 0); + EXPECT_NE(pendingManager_->GetWantSenderLocked(1, 1, wantSenderInfo1.userId, wantSenderInfo1, nullptr), nullptr); + EXPECT_EQ((int)pendingManager_->wantRecords_.size(), 1); +} + +/* + * @tc.number : PendingWantManagerTest_0900 + * @tc.name : PendingWantManager GetPendingWantRecordByKey + * @tc.desc : 1.GetPendingWantRecordByKey,wantSenderInfo contain want info + */ +HWTEST_F(PendingWantManagerTest, PendingWantManagerTest_0900, TestSize.Level1) +{ + Want want; + ElementName element("device", "bundleName", "abilityName"); + want.SetElement(element); + WantSenderInfo wantSenderInfo = MakeWantSenderInfo(want, 0, 0); + EXPECT_FALSE(((unsigned int)wantSenderInfo.flags & (unsigned int)Flags::NO_BUILD_FLAG) != 0); + pendingManager_ = std::make_shared(); + EXPECT_NE(pendingManager_, nullptr); + EXPECT_NE(pendingManager_->GetWantSenderLocked(1, 1, wantSenderInfo.userId, wantSenderInfo, nullptr), nullptr); + EXPECT_EQ((int)pendingManager_->wantRecords_.size(), 1); + std::shared_ptr pendingKey = std::make_shared(); + pendingKey->SetBundleName(wantSenderInfo.bundleName); + pendingKey->SetRequestWho(wantSenderInfo.resultWho); + pendingKey->SetRequestCode(wantSenderInfo.requestCode); + pendingKey->SetFlags(wantSenderInfo.flags); + pendingKey->SetUserId(wantSenderInfo.userId); + pendingKey->SetType(wantSenderInfo.type); + if (wantSenderInfo.allWants.size() > 0) { + pendingKey->SetRequestWant(wantSenderInfo.allWants.back().want); + pendingKey->SetRequestResolvedType(wantSenderInfo.allWants.back().resolvedTypes); + pendingKey->SetAllWantsInfos(wantSenderInfo.allWants); + } + EXPECT_NE(pendingManager_->GetPendingWantRecordByKey(pendingKey), nullptr); +} + +/* + * @tc.number : PendingWantManagerTest_1000 + * @tc.name : PendingWantManager GetPendingWantRecordByKey + * @tc.desc : 1.GetPendingWantRecordByKey,wantSenderInfo not contain want info + */ +HWTEST_F(PendingWantManagerTest, PendingWantManagerTest_1000, TestSize.Level1) +{ + Want want; + ElementName element("device", "bundleName", "abilityName"); + want.SetElement(element); + WantSenderInfo wantSenderInfo = MakeWantSenderInfo(want, 0, 0); + wantSenderInfo.allWants.clear(); + EXPECT_FALSE(((unsigned int)wantSenderInfo.flags & (unsigned int)Flags::NO_BUILD_FLAG) != 0); + pendingManager_ = std::make_shared(); + EXPECT_NE(pendingManager_, nullptr); + EXPECT_NE(pendingManager_->GetWantSenderLocked(1, 1, wantSenderInfo.userId, wantSenderInfo, nullptr), nullptr); + EXPECT_EQ((int)pendingManager_->wantRecords_.size(), 1); + std::shared_ptr pendingKey = std::make_shared(); + pendingKey->SetBundleName(wantSenderInfo.bundleName); + pendingKey->SetRequestWho(wantSenderInfo.resultWho); + pendingKey->SetRequestCode(wantSenderInfo.requestCode); + pendingKey->SetFlags(wantSenderInfo.flags); + pendingKey->SetUserId(wantSenderInfo.userId); + pendingKey->SetType(wantSenderInfo.type); + if (wantSenderInfo.allWants.size() > 0) { + pendingKey->SetRequestWant(wantSenderInfo.allWants.back().want); + pendingKey->SetRequestResolvedType(wantSenderInfo.allWants.back().resolvedTypes); + pendingKey->SetAllWantsInfos(wantSenderInfo.allWants); + } + EXPECT_NE(pendingManager_->GetPendingWantRecordByKey(pendingKey), nullptr); +} + +/* + * @tc.number : PendingWantManagerTest_1100 + * @tc.name : PendingWantManager GetPendingWantRecordByKey + * @tc.desc : 1.GetPendingWantRecordByKey,pendingKey info different wantSenderInfo + */ +HWTEST_F(PendingWantManagerTest, PendingWantManagerTest_1100, TestSize.Level1) +{ + Want want; + ElementName element("device", "bundleName", "abilityName"); + want.SetElement(element); + WantSenderInfo wantSenderInfo = MakeWantSenderInfo(want, 0, 0); + std::shared_ptr pendingKey = std::make_shared(); + pendingManager_ = std::make_shared(); + EXPECT_NE(pendingManager_, nullptr); + pendingKey->SetBundleName(wantSenderInfo.bundleName + "A"); + pendingKey->SetRequestWho(wantSenderInfo.resultWho); + pendingKey->SetRequestCode(wantSenderInfo.requestCode); + pendingKey->SetFlags(wantSenderInfo.flags); + pendingKey->SetUserId(wantSenderInfo.userId); + pendingKey->SetType(wantSenderInfo.type); + if (wantSenderInfo.allWants.size() > 0) { + pendingKey->SetRequestWant(wantSenderInfo.allWants.back().want); + pendingKey->SetRequestResolvedType(wantSenderInfo.allWants.back().resolvedTypes); + pendingKey->SetAllWantsInfos(wantSenderInfo.allWants); + } + EXPECT_EQ(pendingManager_->GetPendingWantRecordByKey(pendingKey), nullptr); +} + +/* + * @tc.number : PendingWantManagerTest_1200 + * @tc.name : PendingWantManager CheckPendingWantRecordByKey + * @tc.desc : 1.CheckPendingWantRecordByKey,pendingKey and pendingKey1 is the same + */ +HWTEST_F(PendingWantManagerTest, PendingWantManagerTest_1200, TestSize.Level1) +{ + Want want; + ElementName element("device", "bundleName", "abilityName"); + want.SetElement(element); + WantSenderInfo wantSenderInfo = MakeWantSenderInfo(want, 0, 0); + std::shared_ptr pendingKey = std::make_shared(); + pendingManager_ = std::make_shared(); + EXPECT_NE(pendingManager_, nullptr); + pendingKey->SetBundleName(wantSenderInfo.bundleName); + pendingKey->SetRequestWho(wantSenderInfo.resultWho); + pendingKey->SetRequestCode(wantSenderInfo.requestCode); + pendingKey->SetFlags(wantSenderInfo.flags); + pendingKey->SetUserId(wantSenderInfo.userId); + pendingKey->SetType(wantSenderInfo.type); + if (wantSenderInfo.allWants.size() > 0) { + pendingKey->SetRequestWant(wantSenderInfo.allWants.back().want); + pendingKey->SetRequestResolvedType(wantSenderInfo.allWants.back().resolvedTypes); + pendingKey->SetAllWantsInfos(wantSenderInfo.allWants); + } + std::shared_ptr pendingKey1 = std::make_shared(); + pendingKey1->SetBundleName(wantSenderInfo.bundleName); + pendingKey1->SetRequestWho(wantSenderInfo.resultWho); + pendingKey1->SetRequestCode(wantSenderInfo.requestCode); + pendingKey1->SetFlags(wantSenderInfo.flags); + pendingKey1->SetUserId(wantSenderInfo.userId); + pendingKey1->SetType(wantSenderInfo.type); + if (wantSenderInfo.allWants.size() > 0) { + pendingKey1->SetRequestWant(wantSenderInfo.allWants.back().want); + pendingKey1->SetRequestResolvedType(wantSenderInfo.allWants.back().resolvedTypes); + pendingKey1->SetAllWantsInfos(wantSenderInfo.allWants); + } + EXPECT_EQ(pendingManager_->CheckPendingWantRecordByKey(pendingKey, pendingKey1), true); +} + +/* + * @tc.number : PendingWantManagerTest_1300 + * @tc.name : PendingWantManager CheckPendingWantRecordByKey + * @tc.desc : 1.CheckPendingWantRecordByKey,pendingKey and pendingKey1 is the different + */ +HWTEST_F(PendingWantManagerTest, PendingWantManagerTest_1300, TestSize.Level1) +{ + Want want; + ElementName element("device", "bundleName", "abilityName"); + want.SetElement(element); + WantSenderInfo wantSenderInfo = MakeWantSenderInfo(want, 0, 0); + WantSenderInfo wantSenderInfo1 = MakeWantSenderInfo(want, 0, 1); + pendingManager_ = std::make_shared(); + std::shared_ptr pendingKey = std::make_shared(); + EXPECT_NE(pendingManager_, nullptr); + pendingKey->SetBundleName(wantSenderInfo.bundleName); + pendingKey->SetRequestWho(wantSenderInfo.resultWho); + pendingKey->SetRequestCode(wantSenderInfo.requestCode); + pendingKey->SetFlags(wantSenderInfo.flags); + pendingKey->SetUserId(wantSenderInfo.userId); + pendingKey->SetType(wantSenderInfo.type); + if (wantSenderInfo.allWants.size() > 0) { + pendingKey->SetRequestWant(wantSenderInfo.allWants.back().want); + pendingKey->SetRequestResolvedType(wantSenderInfo.allWants.back().resolvedTypes); + pendingKey->SetAllWantsInfos(wantSenderInfo.allWants); + } + std::shared_ptr pendingKey1 = std::make_shared(); + pendingKey1->SetBundleName(wantSenderInfo1.bundleName); + pendingKey1->SetRequestWho(wantSenderInfo1.resultWho); + pendingKey1->SetRequestCode(wantSenderInfo1.requestCode); + pendingKey1->SetFlags(wantSenderInfo1.flags); + pendingKey1->SetUserId(wantSenderInfo1.userId); + pendingKey1->SetType(wantSenderInfo1.type); + if (wantSenderInfo1.allWants.size() > 0) { + pendingKey1->SetRequestWant(wantSenderInfo1.allWants.back().want); + pendingKey1->SetRequestResolvedType(wantSenderInfo1.allWants.back().resolvedTypes); + pendingKey1->SetAllWantsInfos(wantSenderInfo1.allWants); + } + EXPECT_EQ(pendingManager_->CheckPendingWantRecordByKey(pendingKey, pendingKey1), false); +} + +/* + * @tc.number : PendingWantManagerTest_1400 + * @tc.name : PendingWantManager SendWantSender + * @tc.desc : 1.SendWantSender,call the function(PerformReceive) of the callback class + */ +HWTEST_F(PendingWantManagerTest, PendingWantManagerTest_1400, TestSize.Level1) +{ + Want want; + ElementName element("device", "com.ix.hiMusic", "MusicSAbility"); + want.SetElement(element); + WantSenderInfo wantSenderInfo = + MakeWantSenderInfo(want, (int32_t)Flags::CONSTANT_FLAG, 0, (int32_t)OperationType::SEND_COMMON_EVENT); + pendingManager_ = std::make_shared(); + EXPECT_NE(pendingManager_, nullptr); + std::shared_ptr key = MakeWantKey(wantSenderInfo); + sptr pendingWantRecord = new PendingWantRecord(pendingManager_, 1, nullptr, key); + EXPECT_NE(pendingWantRecord, nullptr); + SenderInfo info; + info.finishedReceiver = new CancelReceiver(); + EXPECT_EQ(pendingManager_->SendWantSender(pendingWantRecord, info), -1); + EXPECT_TRUE(CancelReceiver::performReceiveCount == 100); + CancelReceiver::performReceiveCount = 0; +} + +/* + * @tc.number : PendingWantManagerTest_1500 + * @tc.name : PendingWantManager GetPendingWantRecordByCode + * @tc.desc : 1.GetPendingWantRecordByCode,parameter not nullptr + */ +HWTEST_F(PendingWantManagerTest, PendingWantManagerTest_1500, TestSize.Level1) +{ + Want want; + ElementName element("device", "bundleName", "abilityName"); + want.SetElement(element); + WantSenderInfo wantSenderInfo = MakeWantSenderInfo(want, 0, 0); + wantSenderInfo.allWants.clear(); + EXPECT_FALSE(((unsigned int)wantSenderInfo.flags & (unsigned int)Flags::NO_BUILD_FLAG) != 0); + pendingManager_ = std::make_shared(); + EXPECT_NE(pendingManager_, nullptr); + auto pendingRecord = pendingManager_->GetWantSenderLocked(1, 1, wantSenderInfo.userId, wantSenderInfo, nullptr); + EXPECT_NE(pendingRecord, nullptr); + EXPECT_EQ((int)pendingManager_->wantRecords_.size(), 1); + EXPECT_NE(pendingManager_->GetPendingWantRecordByCode(pendingManager_->GetPendingWantCode(pendingRecord)), nullptr); +} + +/* + * @tc.number : PendingWantManagerTest_1600 + * @tc.name : PendingWantManager GetPendingWantRecordByCode + * @tc.desc : 1.GetPendingWantRecordByCode,no pendingWantRecord + */ +HWTEST_F(PendingWantManagerTest, PendingWantManagerTest_1600, TestSize.Level1) +{ + pendingManager_ = std::make_shared(); + EXPECT_NE(pendingManager_, nullptr); + EXPECT_EQ((int)pendingManager_->wantRecords_.size(), 0); + EXPECT_EQ(pendingManager_->GetPendingWantRecordByCode(1), nullptr); +} + +/* + * @tc.number : PendingWantManagerTest_1700 + * @tc.name : PendingWantManager GetPendingWantRecordByCode + * @tc.desc : 1.GetPendingWantRecordByCode,parameter not nullptr + */ +HWTEST_F(PendingWantManagerTest, PendingWantManagerTest_1700, TestSize.Level1) +{ + Want want; + ElementName element("device", "bundleName", "abilityName"); + want.SetElement(element); + WantSenderInfo wantSenderInfo = MakeWantSenderInfo(want, 0, 0); + wantSenderInfo.allWants.clear(); + EXPECT_FALSE(((unsigned int)wantSenderInfo.flags & (unsigned int)Flags::NO_BUILD_FLAG) != 0); + pendingManager_ = std::make_shared(); + EXPECT_NE(pendingManager_, nullptr); + EXPECT_NE(pendingManager_->GetWantSenderLocked(1, 1, wantSenderInfo.userId, wantSenderInfo, nullptr), nullptr); + EXPECT_EQ((int)pendingManager_->wantRecords_.size(), 1); + EXPECT_EQ(pendingManager_->GetPendingWantRecordByCode(100), nullptr); +} + +/* + * @tc.number : PendingWantManagerTest_1800 + * @tc.name : PendingWantManager GetPendingWantUid + * @tc.desc : 1.GetPendingWantUid, parameter nullptr + */ +HWTEST_F(PendingWantManagerTest, PendingWantManagerTest_1800, TestSize.Level1) +{ + pendingManager_ = std::make_shared(); + EXPECT_NE(pendingManager_, nullptr); + EXPECT_EQ(pendingManager_->GetPendingWantUid(nullptr), -1); +} + +/* + * @tc.number : PendingWantManagerTest_1900 + * @tc.name : PendingWantManager GetPendingWantUid + * @tc.desc : 1.GetPendingWantUid, parameter not nullptr + */ +HWTEST_F(PendingWantManagerTest, PendingWantManagerTest_1900, TestSize.Level1) +{ + Want want; + ElementName element("device", "bundleName", "abilityName"); + want.SetElement(element); + WantSenderInfo wantSenderInfo = MakeWantSenderInfo(want, 0, 0); + EXPECT_FALSE(((unsigned int)wantSenderInfo.flags & (unsigned int)Flags::NO_BUILD_FLAG) != 0); + pendingManager_ = std::make_shared(); + EXPECT_NE(pendingManager_, nullptr); + auto pendingRecord = pendingManager_->GetWantSenderLocked(1, 1, wantSenderInfo.userId, wantSenderInfo, nullptr); + EXPECT_NE(pendingRecord, nullptr); + EXPECT_EQ(pendingManager_->GetPendingWantUid(pendingRecord), 1); +} + +/* + * @tc.number : PendingWantManagerTest_2000 + * @tc.name : PendingWantManager GetPendingWantUserId + * @tc.desc : 1.GetPendingWantUserId, parameter nullptr + */ +HWTEST_F(PendingWantManagerTest, PendingWantManagerTest_2000, TestSize.Level1) +{ + pendingManager_ = std::make_shared(); + EXPECT_NE(pendingManager_, nullptr); + EXPECT_EQ(pendingManager_->GetPendingWantUserId(nullptr), -1); +} + +/* + * @tc.number : PendingWantManagerTest_2100 + * @tc.name : PendingWantManager GetPendingWantUserId + * @tc.desc : 1.GetPendingWantUserId,parameter not nullptr + */ +HWTEST_F(PendingWantManagerTest, PendingWantManagerTest_2100, TestSize.Level1) +{ + Want want; + ElementName element("device", "bundleName", "abilityName"); + want.SetElement(element); + WantSenderInfo wantSenderInfo = MakeWantSenderInfo(want, 0, 0); + EXPECT_FALSE(((unsigned int)wantSenderInfo.flags & (unsigned int)Flags::NO_BUILD_FLAG) != 0); + pendingManager_ = std::make_shared(); + EXPECT_NE(pendingManager_, nullptr); + auto pendingRecord = pendingManager_->GetWantSenderLocked(1, 1, wantSenderInfo.userId, wantSenderInfo, nullptr); + EXPECT_NE(pendingRecord, nullptr); + EXPECT_EQ(pendingManager_->GetPendingWantUserId(pendingRecord), 0); +} + +/* + * @tc.number : PendingWantManagerTest_2200 + * @tc.name : PendingWantManager GetPendingWantBundleName + * @tc.desc : 1.GetPendingWantBundleName, parameter nullptr + */ +HWTEST_F(PendingWantManagerTest, PendingWantManagerTest_2200, TestSize.Level1) +{ + pendingManager_ = std::make_shared(); + EXPECT_NE(pendingManager_, nullptr); + EXPECT_EQ(pendingManager_->GetPendingWantBundleName(nullptr), ""); +} + +/* + * @tc.number : PendingWantManagerTest_2300 + * @tc.name : PendingWantManager GetPendingWantBundleName + * @tc.desc : 1.GetPendingWantBundleName, parameter not nullptr + */ +HWTEST_F(PendingWantManagerTest, PendingWantManagerTest_2300, TestSize.Level1) +{ + Want want; + ElementName element("device", "bundleName", "abilityName"); + want.SetElement(element); + WantSenderInfo wantSenderInfo = MakeWantSenderInfo(want, 0, 0); + EXPECT_FALSE(((unsigned int)wantSenderInfo.flags & (unsigned int)Flags::NO_BUILD_FLAG) != 0); + pendingManager_ = std::make_shared(); + EXPECT_NE(pendingManager_, nullptr); + auto pendingRecord = pendingManager_->GetWantSenderLocked(1, 1, wantSenderInfo.userId, wantSenderInfo, nullptr); + EXPECT_NE(pendingRecord, nullptr); + EXPECT_EQ(pendingManager_->GetPendingWantBundleName(pendingRecord), "com.ix.hiRadio"); +} + +/* + * @tc.number : PendingWantManagerTest_2400 + * @tc.name : PendingWantManager GetPendingWantCode + * @tc.desc : 1.GetPendingWantCode, parameter nullptr + */ +HWTEST_F(PendingWantManagerTest, PendingWantManagerTest_2400, TestSize.Level1) +{ + pendingManager_ = std::make_shared(); + EXPECT_NE(pendingManager_, nullptr); + EXPECT_EQ(pendingManager_->GetPendingWantCode(nullptr), -1); +} + +/* + * @tc.number : PendingWantManagerTest_2500 + * @tc.name : PendingWantManager GetPendingWantCode + * @tc.desc : 1.GetPendingWantCode, parameter not nullptr + */ +HWTEST_F(PendingWantManagerTest, PendingWantManagerTest_2500, TestSize.Level1) +{ + Want want; + ElementName element("device", "bundleName", "abilityName"); + want.SetElement(element); + WantSenderInfo wantSenderInfo = MakeWantSenderInfo(want, 0, 0); + EXPECT_FALSE(((unsigned int)wantSenderInfo.flags & (unsigned int)Flags::NO_BUILD_FLAG) != 0); + pendingManager_ = std::make_shared(); + EXPECT_NE(pendingManager_, nullptr); + auto pendingRecord = pendingManager_->GetWantSenderLocked(1, 1, wantSenderInfo.userId, wantSenderInfo, nullptr); + EXPECT_NE(pendingRecord, nullptr); + EXPECT_TRUE(pendingManager_->GetPendingWantCode(pendingRecord) != -1); +} + +/* + * @tc.number : PendingWantManagerTest_2600 + * @tc.name : PendingWantManager GetPendingWantType + * @tc.desc : 1.GetPendingWantType, parameter nullptr + */ +HWTEST_F(PendingWantManagerTest, PendingWantManagerTest_2600, TestSize.Level1) +{ + pendingManager_ = std::make_shared(); + EXPECT_NE(pendingManager_, nullptr); + EXPECT_EQ(pendingManager_->GetPendingWantType(nullptr), -1); +} + +/* + * @tc.number : PendingWantManagerTest_2700 + * @tc.name : PendingWantManager GetPendingWantType + * @tc.desc : 1.GetPendingWantType, parameter not nullptr + */ +HWTEST_F(PendingWantManagerTest, PendingWantManagerTest_2700, TestSize.Level1) +{ + Want want; + ElementName element("device", "bundleName", "abilityName"); + want.SetElement(element); + WantSenderInfo wantSenderInfo = MakeWantSenderInfo(want, 0, 0); + EXPECT_FALSE(((unsigned int)wantSenderInfo.flags & (unsigned int)Flags::NO_BUILD_FLAG) != 0); + pendingManager_ = std::make_shared(); + EXPECT_NE(pendingManager_, nullptr); + auto pendingRecord = pendingManager_->GetWantSenderLocked(1, 1, wantSenderInfo.userId, wantSenderInfo, nullptr); + EXPECT_NE(pendingRecord, nullptr); + EXPECT_TRUE(pendingManager_->GetPendingWantType(pendingRecord) != -1); +} + +/* + * @tc.number : PendingWantManagerTest_2800 + * @tc.name : PendingWantManager RegisterCancelListener + * @tc.desc : 1.RegisterCancelListener,Canceled == false + */ +HWTEST_F(PendingWantManagerTest, PendingWantManagerTest_2800, TestSize.Level1) +{ + sptr cance = new CancelReceiver(); + Want want; + ElementName element("device", "bundleName", "abilityName"); + want.SetElement(element); + WantSenderInfo wantSenderInfo = MakeWantSenderInfo(want, 0, 0); + EXPECT_FALSE(((unsigned int)wantSenderInfo.flags & (unsigned int)Flags::NO_BUILD_FLAG) != 0); + pendingManager_ = std::make_shared(); + EXPECT_NE(pendingManager_, nullptr); + auto pendingRecord = iface_cast( + pendingManager_->GetWantSenderLocked(1, 1, wantSenderInfo.userId, wantSenderInfo, nullptr)->AsObject()); + EXPECT_NE(pendingRecord, nullptr); + pendingManager_->RegisterCancelListener(pendingRecord, cance); + EXPECT_EQ(static_cast(pendingRecord->GetCancelCallbacks().size()), 1); +} + +/* + * @tc.number : PendingWantManagerTest_2900 + * @tc.name : PendingWantManager RegisterCancelListener + * @tc.desc : 1.RegisterCancelListener,Canceled == true + */ +HWTEST_F(PendingWantManagerTest, PendingWantManagerTest_2900, TestSize.Level1) +{ + sptr cance = new CancelReceiver(); + Want want; + ElementName element("device", "bundleName", "abilityName"); + want.SetElement(element); + WantSenderInfo wantSenderInfo = MakeWantSenderInfo(want, 0, 0); + EXPECT_FALSE(((unsigned int)wantSenderInfo.flags & (unsigned int)Flags::NO_BUILD_FLAG) != 0); + pendingManager_ = std::make_shared(); + EXPECT_NE(pendingManager_, nullptr); + auto pendingRecord = iface_cast( + pendingManager_->GetWantSenderLocked(1, 1, wantSenderInfo.userId, wantSenderInfo, nullptr)->AsObject()); + EXPECT_NE(pendingRecord, nullptr); + pendingRecord->SetCanceled(); + pendingManager_->RegisterCancelListener(pendingRecord, cance); + EXPECT_EQ(static_cast(pendingRecord->GetCancelCallbacks().size()), 0); +} + +/* + * @tc.number : PendingWantManagerTest_3000 + * @tc.name : PendingWantManager UnregisterCancelListener + * @tc.desc : 1.UnregisterCancelListener + */ +HWTEST_F(PendingWantManagerTest, PendingWantManagerTest_3000, TestSize.Level1) +{ + sptr cance = new CancelReceiver(); + Want want; + ElementName element("device", "bundleName", "abilityName"); + want.SetElement(element); + WantSenderInfo wantSenderInfo = MakeWantSenderInfo(want, 0, 0); + EXPECT_FALSE(((unsigned int)wantSenderInfo.flags & (unsigned int)Flags::NO_BUILD_FLAG) != 0); + pendingManager_ = std::make_shared(); + EXPECT_NE(pendingManager_, nullptr); + auto pendingRecord = iface_cast( + pendingManager_->GetWantSenderLocked(1, 1, wantSenderInfo.userId, wantSenderInfo, nullptr)->AsObject()); + EXPECT_NE(pendingRecord, nullptr); + pendingManager_->RegisterCancelListener(pendingRecord, cance); + EXPECT_EQ(static_cast(pendingRecord->GetCancelCallbacks().size()), 1); + pendingManager_->UnregisterCancelListener(pendingRecord, cance); + EXPECT_EQ(static_cast(pendingRecord->GetCancelCallbacks().size()), 0); +} + +/* + * @tc.number : PendingWantManagerTest_3100 + * @tc.name : PendingWantManager CancelWantSender + * @tc.desc : 1.CancelWantSender,,call the function(Send) of the callback class + */ +HWTEST_F(PendingWantManagerTest, PendingWantManagerTest_3100, TestSize.Level1) +{ + sptr cance = new CancelReceiver(); + Want want; + ElementName element("device", "bundleName", "abilityName"); + want.SetElement(element); + WantSenderInfo wantSenderInfo = MakeWantSenderInfo(want, 0, 0); + EXPECT_FALSE(((unsigned int)wantSenderInfo.flags & (unsigned int)Flags::NO_BUILD_FLAG) != 0); + pendingManager_ = std::make_shared(); + EXPECT_NE(pendingManager_, nullptr); + auto pendingRecord = iface_cast( + pendingManager_->GetWantSenderLocked(1, 1, wantSenderInfo.userId, wantSenderInfo, nullptr)->AsObject()); + EXPECT_NE(pendingRecord, nullptr); + pendingManager_->RegisterCancelListener(pendingRecord, cance); + pendingManager_->CancelWantSender(0, 0, false, pendingRecord); + EXPECT_TRUE(CancelReceiver::sendCount == 100); + EXPECT_TRUE((int)pendingManager_->wantRecords_.size() == 0); +} + +/* + * @tc.number : PendingWantManagerTest_3200 + * @tc.name : PendingWantManager GetPendingRequestWant + * @tc.desc : 1.GetPendingRequestWant, Get pendingRecord want object. + */ +HWTEST_F(PendingWantManagerTest, PendingWantManagerTest_3200, TestSize.Level1) +{ + Want want; + ElementName element("device", "bundleName", "abilityName"); + want.SetElement(element); + WantSenderInfo wantSenderInfo = MakeWantSenderInfo(want, 0, 0); + EXPECT_FALSE(((unsigned int)wantSenderInfo.flags & (unsigned int)Flags::NO_BUILD_FLAG) != 0); + pendingManager_ = std::make_shared(); + EXPECT_NE(pendingManager_, nullptr); + auto pendingRecord = iface_cast( + pendingManager_->GetWantSenderLocked(1, 1, wantSenderInfo.userId, wantSenderInfo, nullptr)->AsObject()); + EXPECT_NE(pendingRecord, nullptr); + std::shared_ptr getWantInfo = std::make_shared(); + EXPECT_EQ(pendingManager_->GetPendingRequestWant(pendingRecord, getWantInfo), NO_ERROR); + EXPECT_EQ(getWantInfo->GetElement().GetBundleName(), "bundleName"); + EXPECT_EQ(getWantInfo->GetElement().GetAbilityName(), "abilityName"); +} + +/* + * @tc.number : PendingWantManagerTest_3300 + * @tc.name : PendingWantManager GetPendingRequestWant + * @tc.desc : 1.GetPendingRequestWant, Get pendingRecord want object,pendingRecord is nullptr. + */ +HWTEST_F(PendingWantManagerTest, PendingWantManagerTest_3300, TestSize.Level1) +{ + Want want; + ElementName element("device", "bundleName", "abilityName"); + want.SetElement(element); + WantSenderInfo wantSenderInfo = MakeWantSenderInfo(want, 0, 0); + EXPECT_FALSE(((unsigned int)wantSenderInfo.flags & (unsigned int)Flags::NO_BUILD_FLAG) != 0); + pendingManager_ = std::make_shared(); + EXPECT_NE(pendingManager_, nullptr); + auto pendingRecord = iface_cast( + pendingManager_->GetWantSenderLocked(1, 1, wantSenderInfo.userId, wantSenderInfo, nullptr)->AsObject()); + EXPECT_NE(pendingRecord, nullptr); + std::shared_ptr getWantInfo = std::make_shared(); + EXPECT_EQ(pendingManager_->GetPendingRequestWant(nullptr, getWantInfo), ERR_INVALID_VALUE); +} + +/* + * @tc.number : PendingWantManagerTest_3400 + * @tc.name : PendingWantManager GetPendingRequestWant + * @tc.desc : 1.GetPendingRequestWant, Get pendingRecord want object,want is nullptr. + */ +HWTEST_F(PendingWantManagerTest, PendingWantManagerTest_3400, TestSize.Level1) +{ + Want want; + ElementName element("device", "bundleName", "abilityName"); + want.SetElement(element); + WantSenderInfo wantSenderInfo = MakeWantSenderInfo(want, 0, 0); + EXPECT_FALSE(((unsigned int)wantSenderInfo.flags & (unsigned int)Flags::NO_BUILD_FLAG) != 0); + pendingManager_ = std::make_shared(); + EXPECT_NE(pendingManager_, nullptr); + auto pendingRecord = iface_cast( + pendingManager_->GetWantSenderLocked(1, 1, wantSenderInfo.userId, wantSenderInfo, nullptr)->AsObject()); + EXPECT_NE(pendingRecord, nullptr); + std::shared_ptr getWantInfo; + EXPECT_EQ(pendingManager_->GetPendingRequestWant(pendingRecord, getWantInfo), ERR_INVALID_VALUE); +} +} // namespace AAFwk +} // namespace OHOS diff --git a/tools/services/abilitymgr/test/unittest/phone/pending_want_record_test/BUILD.gn b/tools/services/abilitymgr/test/unittest/phone/pending_want_record_test/BUILD.gn new file mode 100644 index 00000000000..383e8a92c0c --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/pending_want_record_test/BUILD.gn @@ -0,0 +1,64 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/test.gni") +import("//foundation/aafwk/standard/aafwk.gni") + +module_output_path = "aafwk_standard/abilitymgr" + +ohos_unittest("pending_want_record_test") { + module_out_path = module_output_path + + include_dirs = [ + "${services_path}/abilitymgr/test/mock/libs/system_ability_mock", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy/include", + "//foundation/distributedschedule/samgr/adapter/interfaces/innerkits/include/", + ] + + sources = [ + "//foundation/aafwk/standard/services/abilitymgr/test/mock/libs/appexecfwk_core/src/appmgr/mock_app_scheduler.cpp", + "pending_want_record_test.cpp", # add mock file + ] + + configs = [ "${services_path}/abilitymgr:abilityms_config" ] + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + deps = [ + "${innerkits_path}/want:want", + "${services_path}/abilitymgr/test:abilityms_test_source", + "${services_path}/abilitymgr/test/mock/libs/aakit:aakit_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_appmgr_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_bundlemgr_mock", + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/frameworks/kits/ability/native:dummy_classes", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//third_party/googletest:gmock_main", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] +} + +group("unittest") { + testonly = true + + deps = [ ":pending_want_record_test" ] +} diff --git a/tools/services/abilitymgr/test/unittest/phone/pending_want_record_test/pending_want_record_test.cpp b/tools/services/abilitymgr/test/unittest/phone/pending_want_record_test/pending_want_record_test.cpp new file mode 100644 index 00000000000..06cdf5d4052 --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/pending_want_record_test/pending_want_record_test.cpp @@ -0,0 +1,633 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "bundlemgr/mock_bundle_manager.h" +#include "mock_ability_connect_callback.h" +#include "ability_manager_errors.h" +#include "ability_scheduler.h" +#define private public +#define protected public +#include "ability_event_handler.h" +#include "ability_manager_service.h" +#undef private +#undef protected +#include "if_system_ability_manager.h" +#include "iservice_registry.h" +#define private public +#define protected public +#include "pending_want_record.h" +#include "pending_want_manager.h" +#undef private +#undef protected +#include "sa_mgr_client.h" +#include "sender_info.h" +#include "system_ability_definition.h" +#include "wants_info.h" +#include "want_receiver_stub.h" +#include "want_sender_stub.h" + +using namespace testing; +using namespace testing::ext; +using namespace OHOS::AppExecFwk; +using OHOS::AppExecFwk::ElementName; + +namespace OHOS { +namespace AAFwk { +#define SLEEP(milli) std::this_thread::sleep_for(std::chrono::seconds(milli)) + +namespace {} // namespace +class PendingWantRecordTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp(); + void TearDown(); + WantSenderInfo MakeWantSenderInfo(Want &want, int32_t flags, int32_t userId, int32_t type = 1); + std::shared_ptr MakeWantKey(WantSenderInfo &wantSenderInfo); + static constexpr int TEST_WAIT_TIME = 100000; + + class CancelReceiver : public AAFwk::WantReceiverStub { + public: + static int performReceiveCount; + static int sendCount; + void Send(const int32_t resultCode) override; + void PerformReceive(const AAFwk::Want &want, int resultCode, const std::string &data, + const AAFwk::WantParams &extras, bool serialized, bool sticky, int sendingUser) override; + virtual sptr AsObject() override + { + return nullptr; + } + }; + +public: + std::shared_ptr pendingManager_{nullptr}; + std::shared_ptr abilityMs_{nullptr}; +}; + +int PendingWantRecordTest::CancelReceiver::performReceiveCount = 0; +int PendingWantRecordTest::CancelReceiver::sendCount = 0; + +void PendingWantRecordTest::CancelReceiver::Send(const int32_t resultCode) +{ + sendCount = 100; +} + +void PendingWantRecordTest::CancelReceiver::PerformReceive(const AAFwk::Want &want, int resultCode, + const std::string &data, const AAFwk::WantParams &extras, bool serialized, bool sticky, int sendingUser) +{ + performReceiveCount = 100; +} + +void PendingWantRecordTest::SetUpTestCase() +{ + OHOS::DelayedSingleton::GetInstance()->RegisterSystemAbility( + OHOS::BUNDLE_MGR_SERVICE_SYS_ABILITY_ID, new BundleMgrService()); +} + +void PendingWantRecordTest::TearDownTestCase() +{ + OHOS::DelayedSingleton::DestroyInstance(); + OHOS::DelayedSingleton::DestroyInstance(); +} + +void PendingWantRecordTest::SetUp() +{ + abilityMs_ = OHOS::DelayedSingleton::GetInstance(); + abilityMs_->OnStart(); +} + +void PendingWantRecordTest::TearDown() +{} + +WantSenderInfo PendingWantRecordTest::MakeWantSenderInfo(Want &want, int32_t flags, int32_t userId, int32_t type) +{ + WantSenderInfo wantSenderInfo; + wantSenderInfo.type = type; + // wantSenderInfo.type is OperationType::START_ABILITY + wantSenderInfo.bundleName = "com.ix.hiRadio"; + wantSenderInfo.resultWho = "RadioTopAbility"; + int requestCode = 10; + wantSenderInfo.requestCode = requestCode; + std::vector allWant; + WantsInfo wantInfo; + wantInfo.want = want; + wantInfo.resolvedTypes = "nihao"; + allWant.emplace_back(wantInfo); + wantSenderInfo.allWants = allWant; + wantSenderInfo.flags = flags; + wantSenderInfo.userId = userId; + return wantSenderInfo; +} + +std::shared_ptr PendingWantRecordTest::MakeWantKey(WantSenderInfo &wantSenderInfo) +{ + std::shared_ptr pendingKey = std::make_shared(); + pendingKey->SetBundleName(wantSenderInfo.bundleName); + pendingKey->SetRequestWho(wantSenderInfo.resultWho); + pendingKey->SetRequestCode(wantSenderInfo.requestCode); + pendingKey->SetAllWantsInfos(wantSenderInfo.allWants); + pendingKey->SetFlags(wantSenderInfo.flags); + pendingKey->SetUserId(wantSenderInfo.userId); + pendingKey->SetType(wantSenderInfo.type); + pendingKey->SetRequestWant(wantSenderInfo.allWants.back().want); + pendingKey->SetRequestResolvedType(wantSenderInfo.allWants.back().resolvedTypes); + wantSenderInfo.allWants.back().want = pendingKey->GetRequestWant(); + wantSenderInfo.allWants.back().resolvedTypes = pendingKey->GetRequestResolvedType(); + pendingKey->SetAllWantsInfos(wantSenderInfo.allWants); + return pendingKey; +} + +/* + * @tc.number : PendingWantRecordTest_0100 + * @tc.name : PendingWantManager Constructors + * @tc.desc : 1.Constructors + */ +HWTEST_F(PendingWantRecordTest, PendingWantRecordTest_0100, TestSize.Level1) +{ + Want want; + ElementName element("device", "com.ix.hiMusic", "MusicSAbility"); + want.SetElement(element); + WantSenderInfo wantSenderInfo = MakeWantSenderInfo(want, 0, 0); + pendingManager_ = std::make_shared(); + EXPECT_NE(pendingManager_, nullptr); + std::shared_ptr key = MakeWantKey(wantSenderInfo); + std::shared_ptr pendingWantRecord = + std::make_shared(pendingManager_, 1, nullptr, key); + EXPECT_NE(pendingWantRecord, nullptr); + EXPECT_EQ(pendingWantRecord->uid_, 1); + EXPECT_EQ(pendingWantRecord->callerToken_, nullptr); +} + +/* + * @tc.number : PendingWantRecordTest_0200 + * @tc.name : PendingWantManager RegisterCancelListener + * @tc.desc : 1.RegisterCancelListener(nullptr) + */ +HWTEST_F(PendingWantRecordTest, PendingWantRecordTest_0200, TestSize.Level1) +{ + sptr cance = new CancelReceiver(); + Want want; + ElementName element("device", "com.ix.hiMusic", "MusicSAbility"); + want.SetElement(element); + WantSenderInfo wantSenderInfo = MakeWantSenderInfo(want, 0, 0); + pendingManager_ = std::make_shared(); + EXPECT_NE(pendingManager_, nullptr); + std::shared_ptr key = MakeWantKey(wantSenderInfo); + std::shared_ptr pendingWantRecord = + std::make_shared(pendingManager_, 1, nullptr, key); + EXPECT_NE(pendingWantRecord, nullptr); + pendingWantRecord->RegisterCancelListener(cance); + EXPECT_EQ(static_cast(pendingWantRecord->mCancelCallbacks_.size()), 1); +} + +/* + * @tc.number : PendingWantRecordTest_0300 + * @tc.name : PendingWantManager RegisterCancelListener + * @tc.desc : 1.RegisterCancelListener,one sptr + */ +HWTEST_F(PendingWantRecordTest, PendingWantRecordTest_0300, TestSize.Level1) +{ + sptr cance = new CancelReceiver(); + Want want; + ElementName element("device", "com.ix.hiMusic", "MusicSAbility"); + want.SetElement(element); + WantSenderInfo wantSenderInfo = MakeWantSenderInfo(want, 0, 0); + pendingManager_ = std::make_shared(); + EXPECT_NE(pendingManager_, nullptr); + std::shared_ptr key = MakeWantKey(wantSenderInfo); + std::shared_ptr pendingWantRecord = + std::make_shared(pendingManager_, 1, nullptr, key); + EXPECT_NE(pendingWantRecord, nullptr); + pendingWantRecord->RegisterCancelListener(nullptr); + EXPECT_EQ(static_cast(pendingWantRecord->mCancelCallbacks_.size()), 0); +} + +/* + * @tc.number : PendingWantRecordTest_0400 + * @tc.name : PendingWantManager RegisterCancelListener + * @tc.desc : 1.RegisterCancelListener,two sptr + */ +HWTEST_F(PendingWantRecordTest, PendingWantRecordTest_0400, TestSize.Level1) +{ + sptr cance = new CancelReceiver(); + sptr cance1 = new CancelReceiver(); + Want want; + ElementName element("device", "com.ix.hiMusic", "MusicSAbility"); + want.SetElement(element); + WantSenderInfo wantSenderInfo = MakeWantSenderInfo(want, 0, 0); + pendingManager_ = std::make_shared(); + EXPECT_NE(pendingManager_, nullptr); + std::shared_ptr key = MakeWantKey(wantSenderInfo); + std::shared_ptr pendingWantRecord = + std::make_shared(pendingManager_, 1, nullptr, key); + EXPECT_NE(pendingWantRecord, nullptr); + pendingWantRecord->RegisterCancelListener(cance); + pendingWantRecord->RegisterCancelListener(cance1); + EXPECT_EQ(static_cast(pendingWantRecord->mCancelCallbacks_.size()), 2); +} + +/* + * @tc.number : PendingWantRecordTest_0500 + * @tc.name : PendingWantManager UnregisterCancelListener + * @tc.desc : 1.UnregisterCancelListener(sptr) + */ +HWTEST_F(PendingWantRecordTest, PendingWantRecordTest_0500, TestSize.Level1) +{ + sptr cance = new CancelReceiver(); + sptr cance1 = new CancelReceiver(); + Want want; + ElementName element("device", "com.ix.hiMusic", "MusicSAbility"); + want.SetElement(element); + WantSenderInfo wantSenderInfo = MakeWantSenderInfo(want, 0, 0); + pendingManager_ = std::make_shared(); + EXPECT_NE(pendingManager_, nullptr); + std::shared_ptr key = MakeWantKey(wantSenderInfo); + std::shared_ptr pendingWantRecord = + std::make_shared(pendingManager_, 1, nullptr, key); + EXPECT_NE(pendingWantRecord, nullptr); + pendingWantRecord->RegisterCancelListener(cance); + pendingWantRecord->RegisterCancelListener(cance1); + pendingWantRecord->UnregisterCancelListener(cance); + EXPECT_EQ(static_cast(pendingWantRecord->mCancelCallbacks_.size()), 1); +} + +/* + * @tc.number : PendingWantRecordTest_0600 + * @tc.name : PendingWantManager UnregisterCancelListener + * @tc.desc : 1.UnregisterCancelListener(nullptr) + */ +HWTEST_F(PendingWantRecordTest, PendingWantRecordTest_0600, TestSize.Level1) +{ + sptr cance = new CancelReceiver(); + sptr cance1 = new CancelReceiver(); + Want want; + ElementName element("device", "com.ix.hiMusic", "MusicSAbility"); + want.SetElement(element); + WantSenderInfo wantSenderInfo = MakeWantSenderInfo(want, 0, 0); + pendingManager_ = std::make_shared(); + EXPECT_NE(pendingManager_, nullptr); + std::shared_ptr key = MakeWantKey(wantSenderInfo); + std::shared_ptr pendingWantRecord = + std::make_shared(pendingManager_, 1, nullptr, key); + EXPECT_NE(pendingWantRecord, nullptr); + pendingWantRecord->RegisterCancelListener(cance); + pendingWantRecord->RegisterCancelListener(cance1); + pendingWantRecord->UnregisterCancelListener(nullptr); + EXPECT_EQ(static_cast(pendingWantRecord->mCancelCallbacks_.size()), 2); +} + +/* + * @tc.number : PendingWantRecordTest_0700 + * @tc.name : PendingWantManager SenderInner + * @tc.desc : 1.SenderInner,pendingWantManager_ != nullptr,canceled_ == true + */ +HWTEST_F(PendingWantRecordTest, PendingWantRecordTest_0700, TestSize.Level1) +{ + Want want; + ElementName element("device", "com.ix.hiMusic", "MusicSAbility"); + want.SetElement(element); + WantSenderInfo wantSenderInfo = MakeWantSenderInfo(want, 0, 0); + pendingManager_ = std::make_shared(); + EXPECT_NE(pendingManager_, nullptr); + std::shared_ptr key = MakeWantKey(wantSenderInfo); + std::shared_ptr pendingWantRecord = + std::make_shared(pendingManager_, 1, nullptr, key); + EXPECT_NE(pendingWantRecord, nullptr); + SenderInfo info; + pendingWantRecord->canceled_ = true; + EXPECT_EQ(pendingWantRecord->SenderInner(info), -96); +} + +/* + * @tc.number : PendingWantRecordTest_0800 + * @tc.name : PendingWantManager SenderInner + * @tc.desc : 1.SenderInner,pendingWantManager_ != nullptr,flags:CONSTANT_FLAG,type:OperationType::START_ABILITY + */ +HWTEST_F(PendingWantRecordTest, PendingWantRecordTest_0800, TestSize.Level1) +{ + Want want; + ElementName element("device", "com.ix.hiMusic", "MusicSAbility"); + want.SetElement(element); + WantSenderInfo wantSenderInfo = + MakeWantSenderInfo(want, (int32_t)Flags::CONSTANT_FLAG, 0, (int32_t)OperationType::START_ABILITY); + pendingManager_ = std::make_shared(); + EXPECT_NE(pendingManager_, nullptr); + std::shared_ptr key = MakeWantKey(wantSenderInfo); + std::shared_ptr pendingWantRecord = + std::make_shared(pendingManager_, 1, nullptr, key); + EXPECT_NE(pendingWantRecord, nullptr); + SenderInfo info; + EXPECT_EQ(pendingWantRecord->SenderInner(info), NO_ERROR); + EXPECT_TRUE(info.resolvedType == key->GetRequestResolvedType()); +} + +/* + * @tc.number : PendingWantRecordTest_0900 + * @tc.name : PendingWantManager SenderInner + * @tc.desc : 1.SenderInner,pendingWantManager_ == nullptr,flags:CONSTANT_FLAG + */ +HWTEST_F(PendingWantRecordTest, PendingWantRecordTest_0900, TestSize.Level1) +{ + Want want; + ElementName element("device", "com.ix.hiMusic", "MusicSAbility"); + want.SetElement(element); + WantSenderInfo wantSenderInfo = MakeWantSenderInfo(want, (int32_t)Flags::CONSTANT_FLAG, 0); + std::shared_ptr key = MakeWantKey(wantSenderInfo); + std::shared_ptr pendingWantRecord = + std::make_shared(nullptr, 1, nullptr, key); + EXPECT_NE(pendingWantRecord, nullptr); + SenderInfo info; + EXPECT_EQ(pendingWantRecord->SenderInner(info), ERR_INVALID_VALUE); + EXPECT_TRUE(info.resolvedType != key->GetRequestResolvedType()); +} + +/* + * @tc.number : PendingWantRecordTest_1000 + * @tc.name : PendingWantManager SenderInner + * @tc.desc : 1.SenderInner,pendingWantManager_ == nullptr,flags:ONE_TIME_FLAG + */ +HWTEST_F(PendingWantRecordTest, PendingWantRecordTest_1000, TestSize.Level1) +{ + Want want; + ElementName element("device", "com.ix.hiMusic", "MusicSAbility"); + want.SetElement(element); + WantSenderInfo wantSenderInfo = MakeWantSenderInfo(want, (int32_t)Flags::ONE_TIME_FLAG, 0); + std::shared_ptr key = MakeWantKey(wantSenderInfo); + std::shared_ptr pendingWantRecord = + std::make_shared(nullptr, 1, nullptr, key); + EXPECT_NE(pendingWantRecord, nullptr); + SenderInfo info; + info.finishedReceiver = new CancelReceiver(); + EXPECT_EQ(pendingWantRecord->SenderInner(info), ERR_INVALID_VALUE); + EXPECT_TRUE(info.resolvedType != key->GetRequestResolvedType()); +} + +/* + * @tc.number : PendingWantRecordTest_1100 + * @tc.name : PendingWantManager SenderInner + * @tc.desc : 1.SenderInner,pendingWantManager_ != nullptr,flags:CONSTANT_FLAG,type:OperationType::START_ABILITIES + */ +HWTEST_F(PendingWantRecordTest, PendingWantRecordTest_1100, TestSize.Level1) +{ + Want want; + ElementName element("device", "com.ix.hiMusic", "MusicSAbility"); + want.SetElement(element); + WantSenderInfo wantSenderInfo = + MakeWantSenderInfo(want, (int32_t)Flags::CONSTANT_FLAG, 0, (int32_t)OperationType::START_ABILITIES); + pendingManager_ = std::make_shared(); + EXPECT_NE(pendingManager_, nullptr); + std::shared_ptr key = MakeWantKey(wantSenderInfo); + std::shared_ptr pendingWantRecord = + std::make_shared(pendingManager_, 1, nullptr, key); + EXPECT_NE(pendingWantRecord, nullptr); + SenderInfo info; + EXPECT_NE(pendingWantRecord->SenderInner(info), NO_ERROR); + EXPECT_TRUE(info.resolvedType == key->GetRequestResolvedType()); +} + +/* + * @tc.number : PendingWantRecordTest_1200 + * @tc.name : PendingWantManager SenderInner + * @tc.desc : 1.SenderInner,pendingWantManager_ != nullptr,flags:CONSTANT_FLAG,type:OperationType::START_SERVICE + */ +HWTEST_F(PendingWantRecordTest, PendingWantRecordTest_1200, TestSize.Level1) +{ + Want want; + ElementName element("device", "com.ix.hiMusic", "MusicSAbility"); + want.SetElement(element); + WantSenderInfo wantSenderInfo = + MakeWantSenderInfo(want, (int32_t)Flags::CONSTANT_FLAG, 0, (int32_t)OperationType::START_SERVICE); + pendingManager_ = std::make_shared(); + EXPECT_NE(pendingManager_, nullptr); + std::shared_ptr key = MakeWantKey(wantSenderInfo); + std::shared_ptr pendingWantRecord = + std::make_shared(pendingManager_, 1, nullptr, key); + EXPECT_NE(pendingWantRecord, nullptr); + SenderInfo info; + EXPECT_NE(pendingWantRecord->SenderInner(info), NO_ERROR); + EXPECT_TRUE(info.resolvedType == key->GetRequestResolvedType()); +} + +/* + * @tc.number : PendingWantRecordTest_1300 + * @tc.name : PendingWantManager SenderInner + * @tc.desc : 1.SenderInner,pendingWantManager_ != + * nullptr,flags:CONSTANT_FLAG,type:OperationType::START_FOREGROUND_SERVICE + */ +HWTEST_F(PendingWantRecordTest, PendingWantRecordTest_1300, TestSize.Level1) +{ + Want want; + ElementName element("device", "com.ix.hiMusic", "MusicSAbility"); + want.SetElement(element); + WantSenderInfo wantSenderInfo = + MakeWantSenderInfo(want, (int32_t)Flags::CONSTANT_FLAG, 0, (int32_t)OperationType::START_FOREGROUND_SERVICE); + pendingManager_ = std::make_shared(); + EXPECT_NE(pendingManager_, nullptr); + std::shared_ptr key = MakeWantKey(wantSenderInfo); + std::shared_ptr pendingWantRecord = + std::make_shared(pendingManager_, 1, nullptr, key); + EXPECT_NE(pendingWantRecord, nullptr); + SenderInfo info; + EXPECT_NE(pendingWantRecord->SenderInner(info), NO_ERROR); + EXPECT_TRUE(info.resolvedType == key->GetRequestResolvedType()); +} + +/* + * @tc.number : PendingWantRecordTest_1400 + * @tc.name : PendingWantManager SenderInner + * @tc.desc : 1.SenderInner,pendingWantManager_ != + * nullptr,flags:CONSTANT_FLAG,type:OperationType::SEND_COMMON_EVENT + */ +HWTEST_F(PendingWantRecordTest, PendingWantRecordTest_1400, TestSize.Level1) +{ + Want want; + ElementName element("device", "com.ix.hiMusic", "MusicSAbility"); + want.SetElement(element); + WantSenderInfo wantSenderInfo = + MakeWantSenderInfo(want, (int32_t)Flags::CONSTANT_FLAG, 0, (int32_t)OperationType::SEND_COMMON_EVENT); + pendingManager_ = std::make_shared(); + EXPECT_NE(pendingManager_, nullptr); + std::shared_ptr key = MakeWantKey(wantSenderInfo); + std::shared_ptr pendingWantRecord = + std::make_shared(pendingManager_, 1, nullptr, key); + EXPECT_NE(pendingWantRecord, nullptr); + SenderInfo info; + pendingWantRecord->SenderInner(info); + EXPECT_TRUE(info.resolvedType == key->GetRequestResolvedType()); +} + +/* + * @tc.number : PendingWantRecordTest_1500 + * @tc.name : PendingWantManager SenderInner + * @tc.desc : 1.SenderInner,pendingWantManager_ != + * nullptr,flags:CONSTANT_FLAG,type:OperationType::SEND_COMMON_EVENT, 2.PerformReceive Called + */ +HWTEST_F(PendingWantRecordTest, PendingWantRecordTest_1500, TestSize.Level1) +{ + Want want; + ElementName element("device", "com.ix.hiMusic", "MusicSAbility"); + want.SetElement(element); + WantSenderInfo wantSenderInfo = + MakeWantSenderInfo(want, (int32_t)Flags::CONSTANT_FLAG, 0, (int32_t)OperationType::SEND_COMMON_EVENT); + pendingManager_ = std::make_shared(); + EXPECT_NE(pendingManager_, nullptr); + std::shared_ptr key = MakeWantKey(wantSenderInfo); + std::shared_ptr pendingWantRecord = + std::make_shared(pendingManager_, 1, nullptr, key); + EXPECT_NE(pendingWantRecord, nullptr); + SenderInfo info; + info.finishedReceiver = new CancelReceiver(); + pendingWantRecord->SenderInner(info); + EXPECT_TRUE(info.resolvedType == key->GetRequestResolvedType()); + EXPECT_TRUE(CancelReceiver::performReceiveCount == 100); + CancelReceiver::performReceiveCount = 0; +} + +/* + * @tc.number : PendingWantRecordTest_1600 + * @tc.name : PendingWantManager GetKey + * @tc.desc : 1.GetKey + */ +HWTEST_F(PendingWantRecordTest, PendingWantRecordTest_1600, TestSize.Level1) +{ + Want want; + ElementName element("device", "com.ix.hiMusic", "MusicSAbility"); + want.SetElement(element); + WantSenderInfo wantSenderInfo = + MakeWantSenderInfo(want, (int32_t)Flags::CONSTANT_FLAG, 0, (int32_t)OperationType::SEND_COMMON_EVENT); + pendingManager_ = std::make_shared(); + EXPECT_NE(pendingManager_, nullptr); + std::shared_ptr key = MakeWantKey(wantSenderInfo); + std::shared_ptr pendingWantRecord = + std::make_shared(pendingManager_, 1, nullptr, key); + EXPECT_NE(pendingWantRecord, nullptr); + EXPECT_EQ(pendingWantRecord->GetKey(), key); +} + +/* + * @tc.number : PendingWantRecordTest_1700 + * @tc.name : PendingWantManager GetUid + * @tc.desc : 1.GetUid + */ +HWTEST_F(PendingWantRecordTest, PendingWantRecordTest_1700, TestSize.Level1) +{ + Want want; + ElementName element("device", "com.ix.hiMusic", "MusicSAbility"); + want.SetElement(element); + WantSenderInfo wantSenderInfo = + MakeWantSenderInfo(want, (int32_t)Flags::CONSTANT_FLAG, 0, (int32_t)OperationType::SEND_COMMON_EVENT); + pendingManager_ = std::make_shared(); + EXPECT_NE(pendingManager_, nullptr); + std::shared_ptr key = MakeWantKey(wantSenderInfo); + std::shared_ptr pendingWantRecord = + std::make_shared(pendingManager_, 1, nullptr, key); + EXPECT_NE(pendingWantRecord, nullptr); + EXPECT_EQ(pendingWantRecord->GetUid(), 1); +} + +/* + * @tc.number : PendingWantRecordTest_1800 + * @tc.name : PendingWantManager SetCanceled/GetCanceled + * @tc.desc : 1.SetCanceled/GetCanceled + */ +HWTEST_F(PendingWantRecordTest, PendingWantRecordTest_1800, TestSize.Level1) +{ + Want want; + ElementName element("device", "com.ix.hiMusic", "MusicSAbility"); + want.SetElement(element); + WantSenderInfo wantSenderInfo = + MakeWantSenderInfo(want, (int32_t)Flags::CONSTANT_FLAG, 0, (int32_t)OperationType::SEND_COMMON_EVENT); + pendingManager_ = std::make_shared(); + EXPECT_NE(pendingManager_, nullptr); + std::shared_ptr key = MakeWantKey(wantSenderInfo); + std::shared_ptr pendingWantRecord = + std::make_shared(pendingManager_, 1, nullptr, key); + EXPECT_NE(pendingWantRecord, nullptr); + EXPECT_EQ(pendingWantRecord->GetCanceled(), false); + pendingWantRecord->SetCanceled(); + EXPECT_EQ(pendingWantRecord->GetCanceled(), true); +} + +/* + * @tc.number : PendingWantRecordTest_1900 + * @tc.name : PendingWantManager GetCancelCallbacks + * @tc.desc : 1.GetCancelCallbacks + */ +HWTEST_F(PendingWantRecordTest, PendingWantRecordTest_1900, TestSize.Level1) +{ + sptr cance = new CancelReceiver(); + sptr cance1 = new CancelReceiver(); + Want want; + ElementName element("device", "com.ix.hiMusic", "MusicSAbility"); + want.SetElement(element); + WantSenderInfo wantSenderInfo = MakeWantSenderInfo(want, 0, 0); + pendingManager_ = std::make_shared(); + EXPECT_NE(pendingManager_, nullptr); + std::shared_ptr key = MakeWantKey(wantSenderInfo); + std::shared_ptr pendingWantRecord = + std::make_shared(pendingManager_, 1, nullptr, key); + EXPECT_NE(pendingWantRecord, nullptr); + pendingWantRecord->RegisterCancelListener(cance); + pendingWantRecord->RegisterCancelListener(cance1); + EXPECT_EQ(static_cast(pendingWantRecord->GetCancelCallbacks().size()), 2); +} + +/* + * @tc.number : PendingWantRecordTest_2000 + * @tc.name : PendingWantManager SenderInner + * @tc.desc : 1.SenderInner,pendingWantManager_ != nullptr,flags:CONSTANT_FLAG + */ +HWTEST_F(PendingWantRecordTest, PendingWantRecordTest_2000, TestSize.Level1) +{ + Want want; + ElementName element("device", "com.ix.hiMusic", "MusicSAbility"); + want.SetElement(element); + pendingManager_ = std::make_shared(); + EXPECT_NE(pendingManager_, nullptr); + WantSenderInfo wantSenderInfo = MakeWantSenderInfo(want, (int32_t)Flags::CONSTANT_FLAG, 0); + std::shared_ptr key = MakeWantKey(wantSenderInfo); + std::shared_ptr pendingWantRecord = + std::make_shared(pendingManager_, 1, nullptr, key); + EXPECT_NE(pendingWantRecord, nullptr); + SenderInfo info; + pendingWantRecord->SenderInner(info); + EXPECT_TRUE(info.resolvedType == key->GetRequestResolvedType()); +} + +/* + * @tc.number : PendingWantRecordTest_2100 + * @tc.name : PendingWantManager SenderInner + * @tc.desc : 1.SenderInner,pendingWantManager_ != nullptr,flags:ONE_TIME_FLAG + */ +HWTEST_F(PendingWantRecordTest, PendingWantRecordTest_2100, TestSize.Level1) +{ + Want want; + ElementName element("device", "com.ix.hiMusic", "MusicSAbility"); + want.SetElement(element); + pendingManager_ = std::make_shared(); + EXPECT_NE(pendingManager_, nullptr); + WantSenderInfo wantSenderInfo = MakeWantSenderInfo(want, (int32_t)Flags::ONE_TIME_FLAG, 0); + std::shared_ptr key = MakeWantKey(wantSenderInfo); + std::shared_ptr pendingWantRecord = + std::make_shared(pendingManager_, 1, nullptr, key); + EXPECT_NE(pendingWantRecord, nullptr); + SenderInfo info; + info.finishedReceiver = new CancelReceiver(); + pendingWantRecord->SenderInner(info); + EXPECT_TRUE(info.resolvedType == key->GetRequestResolvedType()); +} +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/abilitymgr/test/unittest/phone/resume_mission_container_test/BUILD.gn b/tools/services/abilitymgr/test/unittest/phone/resume_mission_container_test/BUILD.gn new file mode 100644 index 00000000000..f5793f7b477 --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/resume_mission_container_test/BUILD.gn @@ -0,0 +1,63 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/test.gni") +import("//foundation/aafwk/standard/aafwk.gni") + +module_output_path = "aafwk_standard/abilitymgr" + +ohos_unittest("resume_mission_container_test") { + module_out_path = module_output_path + + include_dirs = [ + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy/include", + "//foundation/aafwk/standard/services/abilitymgr/include", + "//foundation/aafwk/standard/services/test/mock/include", + ] + + sources = [ + "//foundation/aafwk/standard/services/abilitymgr/test/mock/libs/appexecfwk_core/src/appmgr/mock_app_scheduler.cpp", + "resume_mission_container_test.cpp", # add mock file + ] + + configs = [ "${services_path}/abilitymgr:abilityms_config" ] + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + deps = [ + "${innerkits_path}/want:want", + "${services_path}/abilitymgr/test:abilityms_test_source", + "${services_path}/abilitymgr/test/mock/libs/aakit:aakit_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_appmgr_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_bundlemgr_mock", + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/frameworks/kits/ability/native:dummy_classes", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] +} + +group("unittest") { + testonly = true + + deps = [ ":resume_mission_container_test" ] +} diff --git a/tools/services/abilitymgr/test/unittest/phone/resume_mission_container_test/resume_mission_container_test.cpp b/tools/services/abilitymgr/test/unittest/phone/resume_mission_container_test/resume_mission_container_test.cpp new file mode 100644 index 00000000000..a5cd986a518 --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/resume_mission_container_test/resume_mission_container_test.cpp @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#define private public +#include "resume_mission_container.h" +#undef private +#include "ability_manager_service.h" + +using namespace testing::ext; +using namespace OHOS::AppExecFwk; + +namespace OHOS { +namespace AAFwk { +class MissionRecordTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void MissionRecordTest::SetUpTestCase(void) +{} +void MissionRecordTest::TearDownTestCase(void) +{} +void MissionRecordTest::SetUp(void) +{} +void MissionRecordTest::TearDown(void) +{} + +/* + * Feature: ResumeMissionContainer + * Function: NA + * SubFunction: NA + * FunctionPoints: Resume Mission Container + * EnvConditions:NA + * CaseDescription: Resume Mission Container UT. + */ +HWTEST_F(MissionRecordTest, Save_01, TestSize.Level1) +{ + + auto eventLoop = AppExecFwk::EventRunner::Create(AbilityConfig::NAME_ABILITY_MGR_SERVICE); + auto handler = + std::make_shared(eventLoop, OHOS::DelayedSingleton::GetInstance()); + auto resumeMissionContainer = std::make_shared(handler); + resumeMissionContainer->missionMaps_.clear(); + std::string bundleName = "com.ix.aafwk.moduletest"; + auto mission = std::make_shared(bundleName); + resumeMissionContainer->Save(mission); + EXPECT_TRUE(1 == resumeMissionContainer->missionMaps_.size()); +} + +/* + * Feature: ResumeMissionContainer + * Function: NA + * SubFunction: NA + * FunctionPoints: Resume Mission Container + * EnvConditions:NA + * CaseDescription: Resume Mission Container UT. + */ +HWTEST_F(MissionRecordTest, Resume_01, TestSize.Level1) +{ + auto eventLoop = AppExecFwk::EventRunner::Create(AbilityConfig::NAME_ABILITY_MGR_SERVICE); + auto handler = + std::make_shared(eventLoop, OHOS::DelayedSingleton::GetInstance()); + auto resumeMissionContainer = std::make_shared(handler); + resumeMissionContainer->missionMaps_.clear(); + std::string bundleName = "com.ix.aafwk.moduletest"; + auto mission = std::make_shared(bundleName); + + auto missionId = mission->GetMissionRecordId(); + std::shared_ptr backup; + backup = std::make_shared(mission); + resumeMissionContainer->missionMaps_.emplace(missionId, backup); + + resumeMissionContainer->Resume(mission); + EXPECT_TRUE(0 == resumeMissionContainer->missionMaps_.size()); +} + +/* + * Feature: ResumeMissionContainer + * Function: NA + * SubFunction: NA + * FunctionPoints: Resume Mission Container + * EnvConditions:NA + * CaseDescription: Resume Mission Container UT. + */ +HWTEST_F(MissionRecordTest, Remove_01, TestSize.Level1) +{ + auto eventLoop = AppExecFwk::EventRunner::Create(AbilityConfig::NAME_ABILITY_MGR_SERVICE); + auto handler = + std::make_shared(eventLoop, OHOS::DelayedSingleton::GetInstance()); + auto resumeMissionContainer = std::make_shared(handler); + resumeMissionContainer->missionMaps_.clear(); + std::string bundleName = "com.ix.aafwk.moduletest"; + auto mission = std::make_shared(bundleName); + + auto missionId = mission->GetMissionRecordId(); + std::shared_ptr backup; + backup = std::make_shared(mission); + resumeMissionContainer->missionMaps_.emplace(missionId, backup); + + resumeMissionContainer->Remove(missionId); + EXPECT_TRUE(0 == resumeMissionContainer->missionMaps_.size()); +} + +/* + * Feature: ResumeMissionContainer + * Function: NA + * SubFunction: NA + * FunctionPoints: Resume Mission Container + * EnvConditions:NA + * CaseDescription: Resume Mission Container UT. + */ +HWTEST_F(MissionRecordTest, IsResume_01, TestSize.Level1) +{ + auto eventLoop = AppExecFwk::EventRunner::Create(AbilityConfig::NAME_ABILITY_MGR_SERVICE); + auto handler = + std::make_shared(eventLoop, OHOS::DelayedSingleton::GetInstance()); + auto resumeMissionContainer = std::make_shared(handler); + resumeMissionContainer->missionMaps_.clear(); + std::string bundleName = "com.ix.aafwk.moduletest"; + auto mission = std::make_shared(bundleName); + + auto missionId = mission->GetMissionRecordId(); + std::shared_ptr backup; + backup = std::make_shared(mission); + resumeMissionContainer->missionMaps_.emplace(missionId, backup); + + EXPECT_EQ(true, resumeMissionContainer->IsResume(missionId)); +} + +/* + * Feature: ResumeMissionContainer + * Function: NA + * SubFunction: NA + * FunctionPoints: Resume Mission Container + * EnvConditions:NA + * CaseDescription: Resume Mission Container UT. + */ +HWTEST_F(MissionRecordTest, IsResume_02, TestSize.Level1) +{ + auto eventLoop = AppExecFwk::EventRunner::Create(AbilityConfig::NAME_ABILITY_MGR_SERVICE); + auto handler = + std::make_shared(eventLoop, OHOS::DelayedSingleton::GetInstance()); + auto resumeMissionContainer = std::make_shared(handler); + resumeMissionContainer->missionMaps_.clear(); + std::string bundleName = "com.ix.aafwk.moduletest"; + auto mission = std::make_shared(bundleName); + auto missionId = mission->GetMissionRecordId(); + + EXPECT_EQ(false, resumeMissionContainer->IsResume(missionId)); +} + +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/abilitymgr/test/unittest/phone/sender_info_test/BUILD.gn b/tools/services/abilitymgr/test/unittest/phone/sender_info_test/BUILD.gn new file mode 100644 index 00000000000..e988d690158 --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/sender_info_test/BUILD.gn @@ -0,0 +1,64 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/test.gni") +import("//foundation/aafwk/standard/aafwk.gni") + +module_output_path = "aafwk_standard/abilitymgr" + +ohos_unittest("sender_info_test") { + module_out_path = module_output_path + + include_dirs = [ + "${services_path}/abilitymgr/test/mock/libs/system_ability_mock", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy/include", + "//foundation/distributedschedule/samgr/adapter/interfaces/innerkits/include/", + ] + + sources = [ + "//foundation/aafwk/standard/services/abilitymgr/test/mock/libs/appexecfwk_core/src/appmgr/mock_app_scheduler.cpp", + "sender_info_test.cpp", # add mock file + ] + + configs = [ "${services_path}/abilitymgr:abilityms_config" ] + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + deps = [ + "${innerkits_path}/want:want", + "${services_path}/abilitymgr/test:abilityms_test_source", + "${services_path}/abilitymgr/test/mock/libs/aakit:aakit_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_appmgr_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_bundlemgr_mock", + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/frameworks/kits/ability/native:dummy_classes", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//third_party/googletest:gmock_main", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] +} + +group("unittest") { + testonly = true + + deps = [ ":sender_info_test" ] +} diff --git a/tools/services/abilitymgr/test/unittest/phone/sender_info_test/sender_info_test.cpp b/tools/services/abilitymgr/test/unittest/phone/sender_info_test/sender_info_test.cpp new file mode 100644 index 00000000000..3d33bb40656 --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/sender_info_test/sender_info_test.cpp @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "parcel.h" +#define private public +#define protected public +#include "sender_info.h" +#undef private +#undef protected +#include "want_receiver_stub.h" + +using namespace testing; +using namespace testing::ext; +using namespace OHOS::AppExecFwk; +using OHOS::AppExecFwk::ElementName; + +namespace OHOS { +namespace AAFwk { +#define SLEEP(milli) std::this_thread::sleep_for(std::chrono::seconds(milli)) +class SenderInfoTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp(); + void TearDown(); + static constexpr int TEST_WAIT_TIME = 100000; + class CancelReceiver : public AAFwk::WantReceiverStub { + public: + int performReceiveCount = 0; + void Send(const int32_t resultCode) override; + void PerformReceive(const AAFwk::Want &want, int resultCode, const std::string &data, + const AAFwk::WantParams &extras, bool serialized, bool sticky, int sendingUser) override; + }; +public: +}; + +void SenderInfoTest::CancelReceiver::Send(const int32_t resultCode) +{} +void SenderInfoTest::CancelReceiver::PerformReceive(const AAFwk::Want &want, int resultCode, const std::string &data, + const AAFwk::WantParams &extras, bool serialized, bool sticky, int sendingUser) +{} + +void SenderInfoTest::SetUpTestCase() +{} + +void SenderInfoTest::TearDownTestCase() +{} + +void SenderInfoTest::SetUp() +{} + +void SenderInfoTest::TearDown() +{} + +/* + * @tc.number : SenderInfoTest_0100 + * @tc.name : Marshalling/UnMarshalling + * @tc.desc : 1.Marshalling/UnMarshalling + */ +HWTEST_F(SenderInfoTest, SenderInfoTest_0100, TestSize.Level1) +{ + SenderInfo info; + info.code = 10; + Want want; + ElementName element("device", "com.ix.hiMusic", "MusicSAbility"); + want.SetElement(element); + info.want = want; + info.resolvedType = "nihao"; + sptr cance = new CancelReceiver(); + cance->performReceiveCount = 10; + info.finishedReceiver = cance; + info.requiredPermission = "xiaoming"; + Parcel parcel; + info.Marshalling(parcel); + auto unInfo = SenderInfo::Unmarshalling(parcel); + EXPECT_NE(unInfo, nullptr); + if (!unInfo) { + return; + } + EXPECT_EQ(unInfo->code, 10); + EXPECT_EQ(unInfo->want.GetElement().GetBundleName(), "com.ix.hiMusic"); + EXPECT_EQ(unInfo->want.GetElement().GetAbilityName(), "MusicSAbility"); + EXPECT_EQ(unInfo->resolvedType, "nihao"); + auto callBackPtr = iface_cast(unInfo->finishedReceiver->AsObject()); + EXPECT_EQ(callBackPtr->performReceiveCount, 10); + EXPECT_EQ(unInfo->requiredPermission, "xiaoming"); + delete unInfo; +} +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/abilitymgr/test/unittest/phone/terminate_ability_test/BUILD.gn b/tools/services/abilitymgr/test/unittest/phone/terminate_ability_test/BUILD.gn new file mode 100644 index 00000000000..0d31d08e83f --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/terminate_ability_test/BUILD.gn @@ -0,0 +1,68 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/test.gni") +import("//foundation/aafwk/standard/aafwk.gni") + +module_output_path = "aafwk_standard/abilitymgr" + +ohos_unittest("terminate_ability_test") { + module_out_path = module_output_path + + include_dirs = [ + "${services_path}/abilitymgr/test/mock/libs/system_ability_mock", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy/include", + "//foundation/distributedschedule/samgr/adapter/interfaces/innerkits/include/", + "//foundation/aafwk/standard/interfaces/innerkits/ability_manager/include", + ] + + sources = [ + "//foundation/aafwk/standard/services/abilitymgr/src/app_scheduler.cpp", + "terminate_ability_test.cpp", # add mock file + ] + + configs = [ + "${services_path}/abilitymgr:abilityms_config", + "${services_path}/abilitymgr/test/mock:aafwk_mock_config", + ] + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + deps = [ + "${innerkits_path}/want:want", + "${services_path}/abilitymgr/test:abilityms_test_source", + "${services_path}/abilitymgr/test/mock/libs/aakit:aakit_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_appmgr_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_bundlemgr_mock", + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/frameworks/kits/ability/native:dummy_classes", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//third_party/googletest:gmock_main", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] +} + +group("unittest") { + testonly = true + + deps = [ ":terminate_ability_test" ] +} diff --git a/tools/services/abilitymgr/test/unittest/phone/terminate_ability_test/terminate_ability_test.cpp b/tools/services/abilitymgr/test/unittest/phone/terminate_ability_test/terminate_ability_test.cpp new file mode 100755 index 00000000000..ea4a294b9a6 --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/terminate_ability_test/terminate_ability_test.cpp @@ -0,0 +1,797 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include "system_ability_definition.h" + +#define private public +#define protected public +#include "ability_manager_service.h" +#undef private +#undef protected + +#include "ability_record.h" +#include "ability_scheduler.h" +#include "datetime_ex.h" +#include "if_system_ability_manager.h" +#include "iservice_registry.h" +#include "mock_bundle_manager.h" +#include "sa_mgr_client.h" +#include "string_ex.h" +#include "ability_manager_errors.h" + +using namespace testing::ext; +using namespace OHOS::AppExecFwk; + +namespace OHOS { +namespace AAFwk { +namespace { +const std::string NAME_BUNDLE_MGR_SERVICE = "BundleMgrService"; +const std::string NAME_ABILITY_MGR_SERVICE = "UTAbilityManagerService"; +static std::shared_ptr g_aams = nullptr; +static int32_t g_windowToken = 0; +AbilityRequest launcherAbilityRequest_; +AbilityRequest launcherAAbilityRequest_; +AbilityRequest otherLauncherAbilityRequest_; +AbilityRequest musicAbilityRequest_; +AbilityRequest musicTopAbilityRequest_; +AbilityRequest musicSAbilityRequest_; +AbilityRequest radioAbilityRequest_; +AbilityRequest radioTopAbilityRequest_; +} // namespace + +AbilityRequest GenerateAbilityRequest(const std::string &deviceName, const std::string &abilityName, + const std::string &appName, const std::string &bundleName) +{ + ElementName element(deviceName, bundleName, abilityName); + Want want; + want.SetElement(element); + + AbilityRequest abilityRequest; + abilityRequest.want = want; + AbilityInfo abilityInfo; + abilityInfo.visible = true; + abilityRequest.abilityInfo = abilityInfo; + + return abilityRequest; +} + +static void WaitUntilTaskFinished() +{ + const uint32_t maxRetryTime = 1000; + const uint32_t sleepTime = 1000; + uint32_t count = 0; + auto handler = OHOS::DelayedSingleton::GetInstance()->GetEventHandler(); + std::atomic taskCalled(false); + auto f = [&taskCalled]() { taskCalled.store(true); }; + if (handler->PostTask(f)) { + while (!taskCalled.load()) { + ++count; + if (count >= maxRetryTime) { + break; + } + usleep(sleepTime); + } + } +} + +class TerminateAbilityTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + static void init(); + void SetUp(); + void TearDown(); + bool StartAbility( + const AbilityRequest &request, OHOS::sptr &token, OHOS::sptr &abilityScheduler); + void TerminateAbility( + const OHOS::sptr &curToken, const OHOS::sptr &preToken, const Want *resultWant = nullptr); +}; + +void TerminateAbilityTest::init() +{ + launcherAbilityRequest_ = GenerateAbilityRequest("device", "LauncherAbility", "launcher", "com.ix.hiworld"); + + launcherAAbilityRequest_ = GenerateAbilityRequest("device", "LauncherAAbility", "launcher", "com.ix.hiworld"); + + otherLauncherAbilityRequest_ = + GenerateAbilityRequest("device", "OtherLauncherAbility", "launcher", "com.ix.hiworld"); + + musicAbilityRequest_ = GenerateAbilityRequest("device", "MusicAbility", "music", "com.ix.hiMusic"); + + musicTopAbilityRequest_ = GenerateAbilityRequest("device", "MusicTopAbility", "music", "com.ix.hiMusic"); + + musicSAbilityRequest_ = GenerateAbilityRequest("device", "MusicSAbility", "music", "com.ix.hiMusic"); + + radioAbilityRequest_ = GenerateAbilityRequest("device", "RadioAbility", "radio", "com.ix.hiRadio"); + + radioTopAbilityRequest_ = GenerateAbilityRequest("device", "RadioTopAbility", "radio", "com.ix.hiRadio"); +} + +void TerminateAbilityTest::SetUpTestCase(void) +{} + +void TerminateAbilityTest::TearDownTestCase(void) +{} + +void TerminateAbilityTest::SetUp(void) +{ + OHOS::sptr bundleObject = new BundleMgrService(); + OHOS::DelayedSingleton::GetInstance()->RegisterSystemAbility( + OHOS::BUNDLE_MGR_SERVICE_SYS_ABILITY_ID, bundleObject); + g_aams = OHOS::DelayedSingleton::GetInstance(); + g_aams->OnStart(); + WaitUntilTaskFinished(); + init(); +} + +void TerminateAbilityTest::TearDown(void) +{ + g_aams->OnStop(); + OHOS::DelayedSingleton::DestroyInstance(); +} + +bool TerminateAbilityTest::StartAbility( + const AbilityRequest &request, OHOS::sptr &token, OHOS::sptr &abilityScheduler) +{ + if (g_aams == nullptr) { + GTEST_LOG_(ERROR) << "stackManager is nullptr "; + return false; + } + std::shared_ptr stackManager = g_aams->GetStackManager(); + if (stackManager == nullptr) { + GTEST_LOG_(ERROR) << "stackManager is nullptr "; + return false; + } + bool previousExist = false; + std::shared_ptr last = stackManager->GetCurrentTopAbility(); + if (last != nullptr) { + last->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + previousExist = true; + } + + if (g_aams->StartAbility(request.want) != 0) { + GTEST_LOG_(ERROR) << "fail to StartAbility"; + return false; + } + + std::shared_ptr abilityRecord = stackManager->GetCurrentTopAbility(); + if (abilityRecord == nullptr) { + GTEST_LOG_(ERROR) << "new ability is nullptr"; + return false; + } + token = abilityRecord->GetToken(); + if (token == nullptr) { + GTEST_LOG_(ERROR) << "new token is nullptr"; + return false; + } + GTEST_LOG_(INFO) << "start ability: " << abilityRecord.get() << " token: " << token.GetRefPtr(); + abilityScheduler = new AbilityScheduler(); + if (g_aams->AttachAbilityThread(abilityScheduler, token) != 0) { + GTEST_LOG_(ERROR) << "fail to AttachAbilityThread"; + return false; + } + g_aams->AddWindowInfo(token, ++g_windowToken); + g_aams->AbilityTransitionDone(token, OHOS::AAFwk::AbilityState::ACTIVE); + WaitUntilTaskFinished(); + return true; +} + +void TerminateAbilityTest::TerminateAbility( + const OHOS::sptr &curToken, const OHOS::sptr &preToken, const Want *resultWant) +{ + EXPECT_EQ(g_aams->TerminateAbility(curToken, -1, resultWant), 0); + if (Token::GetAbilityRecordByToken(curToken)->GetAbilityState() != OHOS::AAFwk::AbilityState::INACTIVATING) { + EXPECT_EQ(g_aams->AbilityTransitionDone(curToken, OHOS::AAFwk::AbilityState::INITIAL), 0); + WaitUntilTaskFinished(); + return; + } + EXPECT_EQ(g_aams->AbilityTransitionDone(curToken, OHOS::AAFwk::AbilityState::INACTIVE), 0); + WaitUntilTaskFinished(); + EXPECT_EQ(g_aams->AbilityTransitionDone(preToken, OHOS::AAFwk::AbilityState::ACTIVE), 0); + WaitUntilTaskFinished(); + EXPECT_EQ(g_aams->AbilityTransitionDone(curToken, OHOS::AAFwk::AbilityState::BACKGROUND), 0); + WaitUntilTaskFinished(); + EXPECT_EQ(g_aams->AbilityTransitionDone(curToken, OHOS::AAFwk::AbilityState::INITIAL), 0); +} + +/* + * Feature: TerminateAbility + * Function: TerminateAbility + * SubFunction: AbilityManagerService::TerminateAbility + * FunctionPoints: param check. + * EnvConditions: Launcher has started. + * CaseDescription: verify TerminateAbility parameters. TerminateAbility fail if token is nullptr. + */ +HWTEST_F(TerminateAbilityTest, AAFWK_AbilityMS_TerminateAbility_001, TestSize.Level1) +{ + EXPECT_NE(g_aams->TerminateAbility(nullptr, -1, nullptr), 0); +} + +/* + * Feature: TerminateAbility + * Function: TerminateAbility + * SubFunction: AbilityStackManager::TerminateAbility GetAbilityFromTerminateList + * FunctionPoints: Don't terminate ability on terminating. + * EnvConditions: Launcher has started. + * CaseDescription: Terminate ability on terminating should return ERR_OK. + */ +HWTEST_F(TerminateAbilityTest, AAFWK_AbilityMS_TerminateAbility_002, TestSize.Level1) +{ + OHOS::sptr token0; + OHOS::sptr scheduler0; + EXPECT_TRUE(StartAbility(musicAbilityRequest_, token0, scheduler0)); + OHOS::sptr token; + OHOS::sptr scheduler; + EXPECT_TRUE(StartAbility(musicTopAbilityRequest_, token, scheduler)); + WaitUntilTaskFinished(); + EXPECT_EQ(g_aams->TerminateAbility(token, -1, nullptr), 0); + EXPECT_EQ(g_aams->TerminateAbility(token, -1, nullptr), 0); + std::shared_ptr abilityRecord = Token::GetAbilityRecordByToken(token0); + EXPECT_TRUE(abilityRecord != nullptr); + abilityRecord->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + EXPECT_EQ(g_aams->TerminateAbility(token0, -1, nullptr), 0); +} + +/* + * Feature: TerminateAbility + * Function: TerminateAbility + * SubFunction: AbilityStackManager::TerminateAbility + * FunctionPoints: Can't terminate launcher root ability. + * EnvConditions:Launcher has started. + * CaseDescription: Can't terminate launcher root ability. + */ +HWTEST_F(TerminateAbilityTest, AAFWK_AbilityMS_TerminateAbility_003, TestSize.Level1) +{ + // AbilityManagerService starts one launcher ability in default. + // Unable terminate root launcher ability. + std::shared_ptr stackManager = g_aams->GetStackManager(); + EXPECT_TRUE(stackManager != nullptr); + std::shared_ptr launcherAbilityRecord = nullptr; + OHOS::sptr launcherToken = nullptr; + if (stackManager && stackManager->GetCurrentTopAbility().get()) { + launcherAbilityRecord.reset(stackManager->GetCurrentTopAbility().get()); + launcherToken = launcherAbilityRecord->GetToken(); + } + + EXPECT_NE(g_aams->TerminateAbility(launcherToken, -1, nullptr), 0); + WaitUntilTaskFinished(); +} + +/* + * Feature: TerminateAbility + * Function: TerminateAbility + * SubFunction: AbilityStackManager::TerminateAbility TerminateAbilityLocked GetAbilityFromTerminateList + * DispatchTerminate CompleteTerminate + * AbilityRecord::Terminate AppScheduler::Terminate + * FunctionPoints: Remove the only one AbilityRecord and its MissionRecord. Active caller AbilityRecord. + * EnvConditions: start LauncherAbility and TestAbility. + * CaseDescription: Terminate the only one AbilityRecord of MissionRecord. + * 1. Remove AbilityRecord and MissionRecord from the stack. + * 2. Jump to Launcher. Launcher receives result and is active. + * 3. AbilityRecord and and MissionRecord are destroyed. + */ +HWTEST_F(TerminateAbilityTest, AAFWK_AbilityMS_TerminateAbility_004, TestSize.Level1) +{ + OHOS::sptr launcherToken; + OHOS::sptr launcherScheduler; + EXPECT_TRUE(StartAbility(launcherAbilityRequest_, launcherToken, launcherScheduler)); + std::shared_ptr launcherAbilityRecord = Token::GetAbilityRecordByToken(launcherToken); + EXPECT_TRUE(launcherAbilityRecord != nullptr); + + OHOS::sptr testToken; + OHOS::sptr testScheduler; + EXPECT_TRUE(StartAbility(musicAbilityRequest_, testToken, testScheduler)); + EXPECT_TRUE(testToken != nullptr); + std::shared_ptr testAbilityRecord = Token::GetAbilityRecordByToken(testToken); + EXPECT_TRUE(testAbilityRecord != nullptr); + std::shared_ptr missionRecord = testAbilityRecord->GetMissionRecord(); + EXPECT_TRUE(missionRecord != nullptr); + WaitUntilTaskFinished(); + Want want; + std::string key("key"); + int resultValue = 4; + want.SetParam(key, resultValue); + TerminateAbility(testToken, launcherToken, &want); + + // verify result + std::shared_ptr serverResult = launcherAbilityRecord->GetResult(); + EXPECT_TRUE(serverResult == nullptr); + AbilityResult result = launcherScheduler->GetResult(); + EXPECT_NE(result.resultWant_.GetIntParam(key, 0), resultValue); + // last launcherAbilityRecord + EXPECT_EQ(g_aams->TerminateAbility(launcherToken, -1, nullptr), TERMINATE_LAUNCHER_DENIED); + WaitUntilTaskFinished(); +} + +/* + * Feature: TerminateAbility + * Function: TerminateAbility + * SubFunction: AbilityStackManager::TerminateAbility TerminateAbilityLocked GetAbilityFromTerminateList + * DispatchTerminate CompleteTerminate + * AbilityRecord::Terminate AppScheduler::Terminate + * FunctionPoints: TerminateAbility + * EnvConditions: + * CaseDescription: Terminate the only one non-active AbilityRecord of MissionRecord in default stack. + * 1. destroy AbilityRecord + * 2. destroy MissionRecord + * 3. send result to caller + * 4. caller is in background + */ +HWTEST_F(TerminateAbilityTest, AAFWK_AbilityMS_TerminateAbility_005, TestSize.Level1) +{ + OHOS::sptr launcherToken; + OHOS::sptr launcherScheduler; + EXPECT_TRUE(StartAbility(launcherAbilityRequest_, launcherToken, launcherScheduler)); + std::shared_ptr launcherAbilityRecord = Token::GetAbilityRecordByToken(launcherToken); + EXPECT_TRUE(launcherAbilityRecord != nullptr); + + OHOS::sptr testToken; + OHOS::sptr testScheduler; + EXPECT_TRUE(StartAbility(musicAbilityRequest_, testToken, testScheduler)); + WaitUntilTaskFinished(); + EXPECT_TRUE(testToken != nullptr); + std::shared_ptr testAbilityRecord = Token::GetAbilityRecordByToken(testToken); + EXPECT_TRUE(testAbilityRecord != nullptr); + std::shared_ptr missionRecord = testAbilityRecord->GetMissionRecord(); + EXPECT_TRUE(missionRecord != nullptr); + + testAbilityRecord->SetAbilityState(OHOS::AAFwk::AbilityState::BACKGROUND); + Want want; + std::string key("key"); + int resultValue = 5; + want.SetParam(key, resultValue); + TerminateAbility(testToken, launcherToken, &want); + + EXPECT_NE(launcherAbilityRecord->GetAbilityState(), OHOS::AAFwk::AbilityState::BACKGROUND); + // clear launcherAbilityRecord + EXPECT_EQ(g_aams->TerminateAbility(launcherToken, -1, nullptr), TERMINATE_LAUNCHER_DENIED); + WaitUntilTaskFinished(); +} + +/* + * Feature: TerminateAbility + * Function: TerminateAbility + * SubFunction: AbilityStackManager::TerminateAbility TerminateAbilityLocked GetAbilityFromTerminateList + * AbilityRecord::Terminate AppScheduler::Terminate + * FunctionPoints: Remove AbilityRecord. Active caller AbilityRecord. + * EnvConditions: start TestAbilityA and TestAbilityB. + * CaseDescription: defaultStack has more than 2 abilities. Terminate top ACTIVE ability. + * 1. Remove AbilityRecord from the stack. + * 2. Jump to caller. caller receives result and is active. + * 3. AbilityRecord is destroyed. + */ +HWTEST_F(TerminateAbilityTest, AAFWK_AbilityMS_TerminateAbility_006, TestSize.Level1) +{ + OHOS::sptr tokenA; + OHOS::sptr schedulerA; + EXPECT_TRUE(StartAbility(musicAbilityRequest_, tokenA, schedulerA)); + std::shared_ptr testAbilityRecordA = Token::GetAbilityRecordByToken(tokenA); + EXPECT_TRUE(testAbilityRecordA != nullptr); + + OHOS::sptr tokenB; + OHOS::sptr schedulerB; + EXPECT_TRUE(StartAbility(musicTopAbilityRequest_, tokenB, schedulerB)); + WaitUntilTaskFinished(); + std::shared_ptr testAbilityRecordB = Token::GetAbilityRecordByToken(tokenB); + EXPECT_TRUE(testAbilityRecordB != nullptr); + std::shared_ptr missionRecord = testAbilityRecordB->GetMissionRecord(); + EXPECT_TRUE(missionRecord != nullptr); + + Want want; + std::string key("key"); + int resultValue = 0; + want.SetParam(key, resultValue); + TerminateAbility(tokenB, tokenA, &want); + // verify result + std::shared_ptr serverResult = testAbilityRecordA->GetResult(); + EXPECT_TRUE(serverResult == nullptr); + AbilityResult result = schedulerA->GetResult(); + EXPECT_EQ(result.resultWant_.GetIntParam(key, 0), resultValue); + // caller is active + EXPECT_EQ(testAbilityRecordA->GetAbilityState(), OHOS::AAFwk::AbilityState::ACTIVE); + // clear launcherAbilityRecord + EXPECT_EQ(g_aams->TerminateAbility(tokenA, -1, nullptr), 0); + WaitUntilTaskFinished(); +} + +/* + * Feature: TerminateAbility + * Function: TerminateAbility + * SubFunction: AbilityStackManager::TerminateAbility TerminateAbilityLocked + * DispatchTerminate CompleteTerminate + * AbilityRecord::Terminate AppScheduler::Terminate + * FunctionPoints: Remove AbilityRecord. Active caller AbilityRecord. + * EnvConditions: start LauncherAbilityA and LauncherAbilityB. + * CaseDescription: launcherStack has more than 2 abilities. Terminate top ACTIVE ability. + * 1. Remove AbilityRecord from the stack. + * 2. Jump to caller. caller receives result and is active. + * 3. AbilityRecord is destroyed. + */ +HWTEST_F(TerminateAbilityTest, AAFWK_AbilityMS_TerminateAbility_007, TestSize.Level1) +{ + OHOS::sptr launcherTokenA; + OHOS::sptr launcherSchedulerA; + EXPECT_TRUE(StartAbility(launcherAbilityRequest_, launcherTokenA, launcherSchedulerA)); + std::shared_ptr launcherAbilityRecordA = Token::GetAbilityRecordByToken(launcherTokenA); + EXPECT_TRUE(launcherAbilityRecordA != nullptr); + + OHOS::sptr launcherTokenB; + OHOS::sptr launcherSchedulerB; + EXPECT_TRUE(StartAbility(otherLauncherAbilityRequest_, launcherTokenB, launcherSchedulerB)); + WaitUntilTaskFinished(); + std::shared_ptr launcherAbilityRecordB = Token::GetAbilityRecordByToken(launcherTokenB); + EXPECT_TRUE(launcherAbilityRecordB != nullptr); + std::shared_ptr missionRecord = launcherAbilityRecordB->GetMissionRecord(); + EXPECT_TRUE(missionRecord != nullptr); + + Want want; + std::string key("key"); + int resultValue = 7; + want.SetParam(key, resultValue); + TerminateAbility(launcherTokenB, launcherTokenA, &want); + // verify result + std::shared_ptr serverResult = launcherAbilityRecordA->GetResult(); + EXPECT_TRUE(serverResult == nullptr); + AbilityResult result = launcherSchedulerA->GetResult(); + EXPECT_NE(result.resultWant_.GetIntParam(key, 0), resultValue); + // caller is active + EXPECT_EQ(launcherAbilityRecordA->GetAbilityState(), OHOS::AAFwk::AbilityState::ACTIVE); + // clear launcherAbilityRecord + EXPECT_EQ(g_aams->TerminateAbility(launcherTokenA, -1, nullptr), TERMINATE_LAUNCHER_DENIED); + WaitUntilTaskFinished(); +} + +/* + * Feature: TerminateAbility + * Function: TerminateAbility + * SubFunction: AbilityStackManager::TerminateAbility TerminateAbilityLocked + * DispatchTerminate CompleteTerminate + * AbilityRecord::Terminate AppScheduler::Terminate + * FunctionPoints: Terminate top non-active ability. + * EnvConditions: start TestAbilityA and TestAbilityB. + * CaseDescription: default stack has more than 2 abilities. Terminate top non-active ability. + * 1. remove AbilityRecord from the stack. + * 2. caller receives result. + * 3. caller is background. + * 4. AbilityRecord is destroyed. + */ +HWTEST_F(TerminateAbilityTest, AAFWK_AbilityMS_TerminateAbility_008, TestSize.Level1) +{ + OHOS::sptr tokenA; + OHOS::sptr schedulerA; + EXPECT_TRUE(StartAbility(musicAbilityRequest_, tokenA, schedulerA)); + std::shared_ptr testAbilityRecordA = Token::GetAbilityRecordByToken(tokenA); + EXPECT_TRUE(testAbilityRecordA != nullptr); + + OHOS::sptr tokenB; + OHOS::sptr schedulerB; + EXPECT_TRUE(StartAbility(musicTopAbilityRequest_, tokenB, schedulerB)); + WaitUntilTaskFinished(); + std::shared_ptr testAbilityRecordB = Token::GetAbilityRecordByToken(tokenB); + EXPECT_TRUE(testAbilityRecordB != nullptr); + std::shared_ptr missionRecord = testAbilityRecordB->GetMissionRecord(); + EXPECT_TRUE(missionRecord != nullptr); + + testAbilityRecordB->SetAbilityState(OHOS::AAFwk::AbilityState::BACKGROUND); + TerminateAbility(tokenB, tokenA, nullptr); + // caller is active + EXPECT_NE(testAbilityRecordA->GetAbilityState(), OHOS::AAFwk::AbilityState::BACKGROUND); + // clear launcherAbilityRecord + EXPECT_EQ(g_aams->TerminateAbility(tokenA, -1, nullptr), 0); + WaitUntilTaskFinished(); +} + +/* + * Feature: TerminateAbility + * Function: TerminateAbility + * SubFunction: AbilityStackManager::TerminateAbility TerminateAbilityLocked + * DispatchTerminate CompleteTerminate + * AbilityRecord::Terminate AppScheduler::Terminate + * FunctionPoints: Terminate top non-active ability. + * EnvConditions: start LauncherAbilityA and LauncherAbilityB. + * CaseDescription: launcherStack has more than 2 abilities. Terminate top non-active ability. + * 1. remove AbilityRecord from the stack. + * 2. caller receives result. + * 3. caller is background. + * 4. AbilityRecord is destroyed. + */ +HWTEST_F(TerminateAbilityTest, AAFWK_AbilityMS_TerminateAbility_009, TestSize.Level1) +{ + OHOS::sptr launcherTokenA; + OHOS::sptr launcherSchedulerA; + EXPECT_TRUE(StartAbility(launcherAbilityRequest_, launcherTokenA, launcherSchedulerA)); + WaitUntilTaskFinished(); + std::shared_ptr launcherAbilityRecordA = Token::GetAbilityRecordByToken(launcherTokenA); + EXPECT_TRUE(launcherAbilityRecordA != nullptr); + + OHOS::sptr launcherTokenB; + OHOS::sptr launcherSchedulerB; + EXPECT_TRUE(StartAbility(otherLauncherAbilityRequest_, launcherTokenB, launcherSchedulerB)); + WaitUntilTaskFinished(); + std::shared_ptr launcherAbilityRecordB = Token::GetAbilityRecordByToken(launcherTokenB); + EXPECT_TRUE(launcherAbilityRecordB != nullptr); + std::shared_ptr missionRecord = launcherAbilityRecordB->GetMissionRecord(); + EXPECT_TRUE(missionRecord != nullptr); + + launcherAbilityRecordB->SetAbilityState(OHOS::AAFwk::AbilityState::BACKGROUND); + TerminateAbility(launcherTokenB, launcherTokenA, nullptr); + // verify result. Has no result. + std::shared_ptr result = launcherAbilityRecordA->GetResult(); + EXPECT_TRUE(result == nullptr); + // caller is active + EXPECT_NE(launcherAbilityRecordA->GetAbilityState(), OHOS::AAFwk::AbilityState::BACKGROUND); + // clear launcherAbilityRecord + EXPECT_EQ(g_aams->TerminateAbility(launcherTokenA, -1, nullptr), TERMINATE_LAUNCHER_DENIED); +} + +/* + * Feature: TerminateAbility + * Function: TerminateAbility + * SubFunction: AbilityStackManager::TerminateAbility TerminateAbilityLocked + * DispatchTerminate CompleteTerminate + * AbilityRecord::Terminate AppScheduler::Terminate + * FunctionPoints: Terminate non-top ability. + * EnvConditions: start TestAbilityA TestAbilityB TestAbilityC. + * CaseDescription: default stack has more than 2 abilities. Terminate non-top ability. + * 1. Remove AbilityRecord from the stack. + * 2. caller receives result. + * 3. caller is in background. + * 4. AbilityRecord is destroyed. + */ +HWTEST_F(TerminateAbilityTest, AAFWK_AbilityMS_TerminateAbility_010, TestSize.Level1) +{ + OHOS::sptr tokenA; + OHOS::sptr schedulerA; + EXPECT_TRUE(StartAbility(musicAbilityRequest_, tokenA, schedulerA)); + WaitUntilTaskFinished(); + std::shared_ptr testAbilityRecordA = Token::GetAbilityRecordByToken(tokenA); + EXPECT_TRUE(testAbilityRecordA != nullptr); + + OHOS::sptr tokenB; + OHOS::sptr schedulerB; + EXPECT_TRUE(StartAbility(musicTopAbilityRequest_, tokenB, schedulerB)); + WaitUntilTaskFinished(); + std::shared_ptr testAbilityRecordB = Token::GetAbilityRecordByToken(tokenB); + EXPECT_TRUE(testAbilityRecordB != nullptr); + + OHOS::sptr tokenC; + OHOS::sptr schedulerC; + EXPECT_TRUE(StartAbility(musicSAbilityRequest_, tokenC, schedulerC)); + WaitUntilTaskFinished(); + std::shared_ptr testAbilityRecordC = Token::GetAbilityRecordByToken(tokenC); + EXPECT_TRUE(testAbilityRecordC != nullptr); + + Want want; + std::string key("key"); + int resultValue = 10; + want.SetParam(key, resultValue); + EXPECT_EQ(g_aams->TerminateAbility(tokenB, -1, &musicAbilityRequest_.want), 0); + EXPECT_NE(g_aams->AbilityTransitionDone(tokenA, OHOS::AAFwk::AbilityState::ACTIVE), 0); + // clear testAbilityRecordC testAbilityRecordA + EXPECT_EQ(g_aams->TerminateAbility(tokenC, -1, nullptr), 0); + EXPECT_EQ(g_aams->TerminateAbility(tokenA, -1, nullptr), 0); + WaitUntilTaskFinished(); +} + +/* + * Feature: TerminateAbility + * Function: TerminateAbility + * SubFunction: AbilityStackManager::TerminateAbility TerminateAbilityLocked + * DispatchTerminate CompleteTerminate + * AbilityRecord::Terminate AppScheduler::Terminate + * FunctionPoints: Terminate non-top ability. + * EnvConditions: start LauncherAbilityA and LauncherAbilityB LauncherAbilityC. + * CaseDescription: launcherStack has more than 2 abilities. Terminate non-top ability. + * 1. Remove AbilityRecord from the stack. + * 2. caller receives result. + * 3. caller is background. + * 4. AbilityRecord is destroyed. + */ +HWTEST_F(TerminateAbilityTest, AAFWK_AbilityMS_TerminateAbility_011, TestSize.Level1) +{ + OHOS::sptr launcherTokenA; + OHOS::sptr schedulerA; + EXPECT_TRUE(StartAbility(launcherAbilityRequest_, launcherTokenA, schedulerA)); + WaitUntilTaskFinished(); + std::shared_ptr launcherAbilityRecordA = Token::GetAbilityRecordByToken(launcherTokenA); + EXPECT_TRUE(launcherAbilityRecordA != nullptr); + + OHOS::sptr launcherTokenB; + OHOS::sptr schedulerB; + EXPECT_TRUE(StartAbility(otherLauncherAbilityRequest_, launcherTokenB, schedulerB)); + WaitUntilTaskFinished(); + std::shared_ptr launcherAbilityRecordB = Token::GetAbilityRecordByToken(launcherTokenB); + EXPECT_TRUE(launcherAbilityRecordB != nullptr); + + OHOS::sptr launcherTokenC; + OHOS::sptr schedulerC; + EXPECT_TRUE(StartAbility(launcherAAbilityRequest_, launcherTokenC, schedulerC)); + WaitUntilTaskFinished(); + std::shared_ptr launcherAbilityRecordC = Token::GetAbilityRecordByToken(launcherTokenC); + EXPECT_TRUE(launcherAbilityRecordC != nullptr); + + Want want; + std::string key("key"); + int resultValue = 11; + want.SetParam(key, resultValue); + EXPECT_EQ(g_aams->TerminateAbility(launcherTokenB, -1, &launcherAbilityRequest_.want), 0); + EXPECT_NE(g_aams->AbilityTransitionDone(launcherTokenA, OHOS::AAFwk::AbilityState::ACTIVE), 0); + EXPECT_EQ(g_aams->TerminateAbility(launcherTokenC, -1, &want), 0); + EXPECT_EQ(g_aams->TerminateAbility(launcherTokenA, -1, &want), TERMINATE_LAUNCHER_DENIED); + WaitUntilTaskFinished(); +} + +/* + * Feature: TerminateAbility + * Function: TerminateAbility + * SubFunction: AbilityStackManager::TerminateAbility TerminateAbilityLocked + * DispatchTerminate CompleteTerminate + * AbilityRecord::Terminate AppScheduler::Terminate + * FunctionPoints: Terminate timeout handle. + * EnvConditions: start TestAbilityA and TestAbilityB. + * CaseDescription: TestAbilityA start TestAbilityB. TestAbilityB terminate timeout. + * 1. Remove AbilityRecordB from the stack. + * 2. Caller TestAbilityA receives. + * 3. Caller is active. + * 4. AbilityRecordB is destroyed. + */ +HWTEST_F(TerminateAbilityTest, AAFWK_AbilityMS_TerminateAbility_012, TestSize.Level2) +{ + OHOS::sptr tokenA; + OHOS::sptr schedulerA; + EXPECT_TRUE(StartAbility(musicAbilityRequest_, tokenA, schedulerA)); + WaitUntilTaskFinished(); + std::shared_ptr testAbilityRecordA = Token::GetAbilityRecordByToken(tokenA); + EXPECT_TRUE(testAbilityRecordA != nullptr); + + OHOS::sptr tokenB; + OHOS::sptr schedulerB; + EXPECT_TRUE(StartAbility(musicTopAbilityRequest_, tokenB, schedulerB)); + WaitUntilTaskFinished(); + std::shared_ptr testAbilityRecordB = Token::GetAbilityRecordByToken(tokenB); + EXPECT_TRUE(testAbilityRecordB != nullptr); + + Want resultWant; + std::string key("key"); + int resultValue = 13; + resultWant.SetParam(key, resultValue); + EXPECT_EQ(g_aams->TerminateAbility(tokenB, -1, &resultWant), 0); + EXPECT_EQ(g_aams->AbilityTransitionDone(tokenB, OHOS::AAFwk::AbilityState::INACTIVE), 0); + WaitUntilTaskFinished(); + EXPECT_EQ(g_aams->AbilityTransitionDone(tokenA, OHOS::AAFwk::AbilityState::ACTIVE), 0); + WaitUntilTaskFinished(); + EXPECT_EQ(g_aams->AbilityTransitionDone(tokenB, OHOS::AAFwk::AbilityState::BACKGROUND), 0); + WaitUntilTaskFinished(); + + // AbilityTransitionDone TERMINATE timeout + sleep(AbilityManagerService::TERMINATE_TIMEOUT / OHOS::MICROSEC_TO_NANOSEC + 1); + // verify result + std::shared_ptr serverResult = testAbilityRecordB->GetResult(); + EXPECT_TRUE(serverResult == nullptr); + AbilityResult result = schedulerA->GetResult(); + EXPECT_NE(result.resultWant_.GetIntParam(key, 0), resultValue); + // clear testAbilityRecordC testAbilityRecordA + EXPECT_EQ(g_aams->TerminateAbility(tokenA, -1, nullptr), 0); + WaitUntilTaskFinished(); +} + +/* + * Feature: TerminateAbility + * Function: TerminateAbility + * SubFunction: AbilityStackManager::TerminateAbility TerminateAbilityLocked + * DispatchTerminate CompleteTerminate + * AbilityRecord::Terminate AppScheduler::Terminate + * FunctionPoints: Background timeout handle. + * EnvConditions: start TestAbilityA and TestAbilityB. + * CaseDescription: TestAbilityA start TestAbilityB. TestAbilityB Background timeout. + * 1. Remove AbilityRecordB from the stack. + * 2. Caller TestAbilityA receives. + * 3. Caller is active. + * 4. AbilityRecordB is destroyed. + */ +HWTEST_F(TerminateAbilityTest, AAFWK_AbilityMS_TerminateAbility_013, TestSize.Level2) +{ + OHOS::sptr tokenA; + OHOS::sptr schedulerA; + EXPECT_TRUE(StartAbility(musicAbilityRequest_, tokenA, schedulerA)); + WaitUntilTaskFinished(); + std::shared_ptr testAbilityRecordA = Token::GetAbilityRecordByToken(tokenA); + EXPECT_TRUE(testAbilityRecordA != nullptr); + + OHOS::sptr tokenB; + OHOS::sptr schedulerB; + EXPECT_TRUE(StartAbility(musicTopAbilityRequest_, tokenB, schedulerB)); + WaitUntilTaskFinished(); + std::shared_ptr testAbilityRecordB = Token::GetAbilityRecordByToken(tokenB); + EXPECT_TRUE(testAbilityRecordB != nullptr); + + Want resultWant; + std::string key("key"); + int resultValue = 14; + resultWant.SetParam(key, resultValue); + EXPECT_EQ(g_aams->TerminateAbility(tokenB, -1, &resultWant), 0); + EXPECT_EQ(g_aams->AbilityTransitionDone(tokenB, OHOS::AAFwk::AbilityState::INACTIVE), 0); + WaitUntilTaskFinished(); + EXPECT_EQ(g_aams->AbilityTransitionDone(tokenA, OHOS::AAFwk::AbilityState::ACTIVE), 0); + + // AbilityTransitionDone BACKGROUND timeout + sleep(AbilityManagerService::BACKGROUND_TIMEOUT / OHOS::MICROSEC_TO_NANOSEC + 1); + EXPECT_EQ(g_aams->AbilityTransitionDone(tokenB, OHOS::AAFwk::AbilityState::INITIAL), 0); + WaitUntilTaskFinished(); + // verify result + std::shared_ptr serverResult = testAbilityRecordB->GetResult(); + EXPECT_TRUE(serverResult == nullptr); + AbilityResult result = schedulerA->GetResult(); + EXPECT_NE(result.resultWant_.GetIntParam(key, 0), resultValue); + // clear testAbilityRecordC testAbilityRecordA + EXPECT_EQ(g_aams->TerminateAbility(tokenA, -1, nullptr), 0); + WaitUntilTaskFinished(); +} + +/* + * Feature: TerminateAbility + * Function: TerminateAbility + * SubFunction: AbilityStackManager::TerminateAbility TerminateAbilityLocked + * DispatchTerminate CompleteTerminate + * AbilityRecord::Terminate AppScheduler::Terminate + * FunctionPoints: Terminate ability on inactive. + * EnvConditions: start TestAbilityA and TestAbilityB. + * CaseDescription: TestAbilityA starts TestAbilityB. Terminate TestAbilityA when it's on inactive. + * 1. Remove AbilityRecordA from the stack. + * 2. caller TestAbilityA receives result. + * 3. AbilityRecordA is destroyed. + */ +HWTEST_F(TerminateAbilityTest, AAFWK_AbilityMS_TerminateAbility_014, TestSize.Level1) +{ + OHOS::sptr token; + OHOS::sptr scheduler; + EXPECT_TRUE(StartAbility(musicAbilityRequest_, token, scheduler)); + std::shared_ptr testAbilityRecord = Token::GetAbilityRecordByToken(token); + EXPECT_TRUE(testAbilityRecord != nullptr); + + OHOS::sptr tokenA; + OHOS::sptr schedulerA; + EXPECT_TRUE(StartAbility(musicTopAbilityRequest_, tokenA, schedulerA)); + WaitUntilTaskFinished(); + std::shared_ptr testAbilityRecordA = Token::GetAbilityRecordByToken(tokenA); + EXPECT_TRUE(testAbilityRecordA != nullptr); + + EXPECT_EQ(g_aams->StartAbility(musicSAbilityRequest_.want), 0); + WaitUntilTaskFinished(); + std::shared_ptr stackManager = g_aams->GetStackManager(); + EXPECT_TRUE(stackManager != nullptr); + std::shared_ptr testAbilityRecordB = stackManager->GetCurrentTopAbility(); + OHOS::sptr tokenB = testAbilityRecordB->GetToken(); + g_aams->AddWindowInfo(tokenB, ++g_windowToken); + EXPECT_EQ(g_aams->AttachAbilityThread(new AbilityScheduler(), tokenB), 0); + EXPECT_EQ(g_aams->AbilityTransitionDone(tokenA, OHOS::AAFwk::AbilityState::INACTIVE), 0); + + EXPECT_EQ(g_aams->TerminateAbility(tokenA, -1, &(musicSAbilityRequest_.want)), 0); + EXPECT_EQ(g_aams->AbilityTransitionDone(tokenB, OHOS::AAFwk::AbilityState::ACTIVE), 0); + WaitUntilTaskFinished(); + EXPECT_EQ(g_aams->AbilityTransitionDone(tokenA, OHOS::AAFwk::AbilityState::BACKGROUND), 0); + WaitUntilTaskFinished(); + EXPECT_EQ(g_aams->AbilityTransitionDone(tokenA, OHOS::AAFwk::AbilityState::INITIAL), 0); + WaitUntilTaskFinished(); + // clear testAbilityRecordB testAbilityRecord + EXPECT_EQ(g_aams->TerminateAbility(tokenB, -1, nullptr), 0); + EXPECT_EQ(g_aams->TerminateAbility(token, -1, nullptr), 0); +} +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/abilitymgr/test/unittest/phone/want_receiver_proxy_test/BUILD.gn b/tools/services/abilitymgr/test/unittest/phone/want_receiver_proxy_test/BUILD.gn new file mode 100644 index 00000000000..835ac46eb4a --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/want_receiver_proxy_test/BUILD.gn @@ -0,0 +1,65 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/test.gni") +import("//foundation/aafwk/standard/aafwk.gni") + +module_output_path = "aafwk_standard/abilitymgr" + +ohos_unittest("want_receiver_proxy_test") { + module_out_path = module_output_path + + include_dirs = [ + "${services_path}/abilitymgr/test/mock/libs/system_ability_mock", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy/include", + ] + + sources = [ + "//foundation/aafwk/standard/services/abilitymgr/test/mock/libs/appexecfwk_core/src/appmgr/mock_app_scheduler.cpp", + "want_receiver_proxy_test.cpp", + ] + + configs = [ + "${services_path}/abilitymgr:abilityms_config", + "${services_path}/abilitymgr/test/mock:aafwk_mock_config", + ] + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + deps = [ + "${services_path}/abilitymgr/test:abilityms_test_source", + "${services_path}/abilitymgr/test/mock/libs/aakit:aakit_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_appmgr_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_bundlemgr_mock", + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/frameworks/kits/ability/native:dummy_classes", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//third_party/googletest:gmock_main", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] +} + +group("unittest") { + testonly = true + + deps = [ ":want_receiver_proxy_test" ] +} diff --git a/tools/services/abilitymgr/test/unittest/phone/want_receiver_proxy_test/want_receiver_proxy_test.cpp b/tools/services/abilitymgr/test/unittest/phone/want_receiver_proxy_test/want_receiver_proxy_test.cpp new file mode 100644 index 00000000000..cba59c4fcad --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/want_receiver_proxy_test/want_receiver_proxy_test.cpp @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define private public +#include "want_receiver_proxy.h" +#undef private + +#include +#include "want_receiver_stub_mock.h" + +using namespace testing::ext; +using namespace testing; +using namespace OHOS::AppExecFwk; + +namespace OHOS { +namespace AAFwk { +class WantReceiverProxyTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + std::shared_ptr proxy_{nullptr}; + sptr mock_{nullptr}; +}; + +void WantReceiverProxyTest::SetUpTestCase(void) +{} +void WantReceiverProxyTest::TearDownTestCase(void) +{} +void WantReceiverProxyTest::TearDown() +{} +void WantReceiverProxyTest::SetUp() +{ + mock_ = new WantReceiverStubMock(); + proxy_ = std::make_shared(mock_); +} + +/* + * Feature: WantReceiverProxy + * Function: Send + * SubFunction: NA + * FunctionPoints: WantReceiverProxy Send + * EnvConditions: NA + * CaseDescription: Verify that the return value of Send is normal + */ +HWTEST_F(WantReceiverProxyTest, WantReceiverProxyTest_001, TestSize.Level0) +{ + EXPECT_CALL(*mock_, SendRequest(_, _, _, _)) + .Times(1) + .WillOnce(Invoke(mock_.GetRefPtr(), &WantReceiverStubMock::InvokeSendRequest)); + int32_t resultCode = 0; + proxy_->Send(resultCode); + + EXPECT_EQ(IWantReceiver::WANT_RECEIVER_SEND, mock_->code_); +} + +/* + * Feature: WantReceiverProxy + * Function: Send + * SubFunction: NA + * FunctionPoints: WantReceiverProxy Send + * EnvConditions: NA + * CaseDescription: Verify that the return value of PerformReceive is normal + */ +HWTEST_F(WantReceiverProxyTest, WantReceiverProxyTest_002, TestSize.Level0) +{ + EXPECT_CALL(*mock_, SendRequest(_, _, _, _)) + .Times(1) + .WillOnce(Invoke(mock_.GetRefPtr(), &WantReceiverStubMock::InvokeSendRequest)); + const Want want; + const WantParams wantParams; + std::string data = "hello world"; + proxy_->PerformReceive(want, 0, data, wantParams, true, true, 0); + + EXPECT_EQ(IWantReceiver::WANT_RECEIVER_PERFORM_RECEIVE, mock_->code_); +} +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/abilitymgr/test/unittest/phone/want_receiver_proxy_test/want_receiver_stub_mock.h b/tools/services/abilitymgr/test/unittest/phone/want_receiver_proxy_test/want_receiver_stub_mock.h new file mode 100644 index 00000000000..30af3ae257e --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/want_receiver_proxy_test/want_receiver_stub_mock.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ABILITY_UNITTEST_WANT_SENDER_STUB_MOCK_H +#define ABILITY_UNITTEST_WANT_SENDER_STUB_MOCK_H +#include +#include +#include +#include "want_receiver_interface.h" + +namespace OHOS { +namespace AAFwk { +class WantReceiverStubMock : public IRemoteStub { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"WantReceiverStubMock"); + + WantReceiverStubMock() : code_(0) {} + virtual ~WantReceiverStubMock() {} + + MOCK_METHOD4(SendRequest, int(uint32_t, MessageParcel &, MessageParcel &, MessageOption &)); + + int InvokeSendRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) + { + code_ = code; + return NO_ERROR; + } + + int code_ = 0; + + virtual void Send(const int32_t resultCode){}; + virtual void PerformReceive(const Want &want, int resultCode, const std::string &data, const WantParams &extras, + bool serialized, bool sticky, int sendingUser){} +}; +} // namespace AAFwk +} // namespace OHOS + +#endif // ABILITY_UNITTEST_WANT_SENDER_STUB_MOCK_H \ No newline at end of file diff --git a/tools/services/abilitymgr/test/unittest/phone/want_receiver_stub_test/BUILD.gn b/tools/services/abilitymgr/test/unittest/phone/want_receiver_stub_test/BUILD.gn new file mode 100644 index 00000000000..1f3c7b8305b --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/want_receiver_stub_test/BUILD.gn @@ -0,0 +1,66 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/test.gni") +import("//foundation/aafwk/standard/aafwk.gni") + +module_output_path = "aafwk_standard/abilitymgr" + +ohos_unittest("want_receiver_stub_test") { + module_out_path = module_output_path + + include_dirs = [ + "${services_path}/abilitymgr/test/mock/libs/system_ability_mock", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy/include", + "//foundation/distributedschedule/samgr/utils/native/include/", + ] + + sources = [ + "//foundation/aafwk/standard/services/abilitymgr/test/mock/libs/appexecfwk_core/src/appmgr/mock_app_scheduler.cpp", + "want_receiver_stub_test.cpp", + ] + + configs = [ + "${services_path}/abilitymgr:abilityms_config", + "${services_path}/abilitymgr/test/mock:aafwk_mock_config", + ] + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + deps = [ + "${services_path}/abilitymgr/test:abilityms_test_source", + "${services_path}/abilitymgr/test/mock/libs/aakit:aakit_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_appmgr_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_bundlemgr_mock", + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/frameworks/kits/ability/native:dummy_classes", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//third_party/googletest:gmock_main", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] +} + +group("unittest") { + testonly = true + + deps = [ ":want_receiver_stub_test" ] +} diff --git a/tools/services/abilitymgr/test/unittest/phone/want_receiver_stub_test/want_receiver_stub_impl_mock.h b/tools/services/abilitymgr/test/unittest/phone/want_receiver_stub_test/want_receiver_stub_impl_mock.h new file mode 100644 index 00000000000..2c34627230f --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/want_receiver_stub_test/want_receiver_stub_impl_mock.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ABILITY_UNITTEST_WANT_RECEIVER_STUB_IMPL_MOCK_H +#define ABILITY_UNITTEST_WANT_RECEIVER_STUB_IMPL_MOCK_H + +#define private public +#include "want_receiver_stub.h" +#undef private + +#include +#include +#include +#include "want_sender_interface.h" + +namespace OHOS { +namespace AAFwk { +class WantReceiverStubImplMock : public WantReceiverStub { +public: + WantReceiverStubImplMock() + {} + virtual ~WantReceiverStubImplMock() + {} + + int InvokeSendRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) + { + code_ = code; + return 0; + } + + int InvokeErrorSendRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) + { + code_ = code; + return UNKNOWN_ERROR; + } + + int code_ = 0; + + virtual void Send(const int32_t resultCode){}; + virtual void PerformReceive(const Want &want, int resultCode, const std::string &data, const WantParams &extras, + bool serialized, bool sticky, int sendingUser){}; +}; +} // namespace AAFwk +} // namespace OHOS + +#endif // ABILITY_UNITTEST_WANT_RECEIVER_STUB_IMPL_MOCK_H \ No newline at end of file diff --git a/tools/services/abilitymgr/test/unittest/phone/want_receiver_stub_test/want_receiver_stub_test.cpp b/tools/services/abilitymgr/test/unittest/phone/want_receiver_stub_test/want_receiver_stub_test.cpp new file mode 100644 index 00000000000..850b8cf86df --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/want_receiver_stub_test/want_receiver_stub_test.cpp @@ -0,0 +1,208 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "iremote_proxy.h" +#include "want_receiver_stub_impl_mock.h" + +using namespace testing::ext; +using namespace testing; + +namespace OHOS { +namespace AAFwk { +class WantReceiverStubTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + void WriteInterfaceToken(MessageParcel &data); + sptr stub_{nullptr}; +}; + +void WantReceiverStubTest::SetUpTestCase(void) +{} +void WantReceiverStubTest::TearDownTestCase(void) +{} +void WantReceiverStubTest::TearDown() +{} + +void WantReceiverStubTest::SetUp() +{ + stub_ = new WantReceiverStubImplMock(); +} + +void WantReceiverStubTest::WriteInterfaceToken(MessageParcel &data) +{ + data.WriteInterfaceToken(WantReceiverStubImplMock::GetDescriptor()); +} + +/* + * Feature: WantReceiverStub + * Function: OnRemoteRequest + * SubFunction: NA + * FunctionPoints: WantReceiverStub OnRemoteRequest + * EnvConditions: The code which not exist + * CaseDescription: Verify that on remote request is abnormal + */ +HWTEST_F(WantReceiverStubTest, WantReceiverStubTest_OnRemoteRequest_001, TestSize.Level0) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + WriteInterfaceToken(data); + int res = stub_->OnRemoteRequest(10000, data, reply, option); + + EXPECT_EQ(res, IPC_STUB_UNKNOW_TRANS_ERR); +} + +/* + * Feature: WantReceiverStub + * Function: OnRemoteRequest + * SubFunction: NA + * FunctionPoints: WantReceiverStub OnRemoteRequest + * EnvConditions: Description abnormal + * CaseDescription: Verify that on remote request is abnormal + */ +HWTEST_F(WantReceiverStubTest, WantReceiverStubTest_OnRemoteRequest_002, TestSize.Level0) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + int res = stub_->OnRemoteRequest(IWantSender::WANT_SENDER_SEND, data, reply, option); + + EXPECT_EQ(res, ERR_INVALID_STATE); +} + +/* + * Feature: WantReceiverStub + * Function: OnRemoteRequest + * SubFunction: NA + * FunctionPoints: WantReceiverStub OnRemoteRequest + * EnvConditions: Code is WANT_SENDER_SEND + * CaseDescription: Verify that on remote request is normal + */ +HWTEST_F(WantReceiverStubTest, WantReceiverStubTest_OnRemoteRequest_003, TestSize.Level0) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + SenderInfo info; + WriteInterfaceToken(data); + data.WriteParcelable(&info); + + int res = stub_->OnRemoteRequest(IWantSender::WANT_SENDER_SEND, data, reply, option); + + EXPECT_EQ(res, NO_ERROR); +} + +/* + * Feature: WantReceiverStub + * Function: OnRemoteRequest + * SubFunction: NA + * FunctionPoints: WantReceiverStub SendInner + * EnvConditions: Valid parameter + * CaseDescription: Verify the function SendInner request is normal. + */ +HWTEST_F(WantReceiverStubTest, WantReceiverStubTest_SendInner_001, TestSize.Level0) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + data.WriteInt32(1); + + int res = stub_->SendInner(data, reply); + + EXPECT_EQ(res, NO_ERROR); +} + +/* + * Feature: WantReceiverStub + * Function: PerformReceiveInner + * SubFunction: NA + * FunctionPoints: WantReceiverStub PerformReceiveInner + * EnvConditions: Invalid parameter + * CaseDescription: Verify the function PerformReceiveInner request is abnormal. + */ +HWTEST_F(WantReceiverStubTest, WantReceiverStubTest_PerformReceiveInner_001, TestSize.Level0) +{ + MessageParcel data; + MessageParcel reply; + + int res = stub_->PerformReceiveInner(data, reply); + + EXPECT_EQ(res, ERR_INVALID_VALUE); +} + +/* + * Feature: WantReceiverStub + * Function: PerformReceiveInner + * SubFunction: NA + * FunctionPoints: WantReceiverStub PerformReceiveInner + * EnvConditions: Invalid parameter + * CaseDescription: Verify the function PerformReceiveInner request is abnormal. + */ +HWTEST_F(WantReceiverStubTest, WantReceiverStubTest_PerformReceiveInner_002, TestSize.Level0) +{ + MessageParcel data; + MessageParcel reply; + + Want want; + data.WriteParcelable(&want); + + int res = stub_->PerformReceiveInner(data, reply); + + EXPECT_EQ(res, ERR_INVALID_VALUE); +} + +/* + * Feature: WantReceiverStub + * Function: PerformReceiveInner + * SubFunction: NA + * FunctionPoints: WantReceiverStub PerformReceiveInner + * EnvConditions: Valid parameter + * CaseDescription: Verify the function PerformReceiveInner request is normal. + */ +HWTEST_F(WantReceiverStubTest, WantReceiverStubTest_PerformReceiveInner_003, TestSize.Level0) +{ + MessageParcel data; + MessageParcel reply; + + Want want; + WantParams wantParams; + int senddingUser = 1000; + bool sticky = true; + bool serialized = true; + std::string bundleName = "com.ix.helloworld"; + int resultCode = 1; + + EXPECT_EQ(data.WriteParcelable(&want), true); + data.WriteInt32(resultCode); + data.WriteString16(Str8ToStr16(bundleName)); + EXPECT_EQ(data.WriteParcelable(&wantParams), true); + data.WriteBool(serialized); + data.WriteBool(sticky); + data.WriteInt32(senddingUser); + + int res = stub_->PerformReceiveInner(data, reply); + + EXPECT_EQ(res, NO_ERROR); +} +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/abilitymgr/test/unittest/phone/want_sender_info_test/BUILD.gn b/tools/services/abilitymgr/test/unittest/phone/want_sender_info_test/BUILD.gn new file mode 100644 index 00000000000..fc247cc5fb6 --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/want_sender_info_test/BUILD.gn @@ -0,0 +1,64 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/test.gni") +import("//foundation/aafwk/standard/aafwk.gni") + +module_output_path = "aafwk_standard/abilitymgr" + +ohos_unittest("want_sender_info_test") { + module_out_path = module_output_path + + include_dirs = [ + "${services_path}/abilitymgr/test/mock/libs/system_ability_mock", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy/include", + "//foundation/distributedschedule/samgr/adapter/interfaces/innerkits/include/", + ] + + sources = [ + "//foundation/aafwk/standard/services/abilitymgr/test/mock/libs/appexecfwk_core/src/appmgr/mock_app_scheduler.cpp", + "want_sender_info_test.cpp", + ] + + configs = [ "${services_path}/abilitymgr:abilityms_config" ] + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + deps = [ + "${innerkits_path}/want:want", + "${services_path}/abilitymgr/test:abilityms_test_source", + "${services_path}/abilitymgr/test/mock/libs/aakit:aakit_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_appmgr_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_bundlemgr_mock", + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/frameworks/kits/ability/native:dummy_classes", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//third_party/googletest:gmock_main", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] +} + +group("unittest") { + testonly = true + + deps = [ ":want_sender_info_test" ] +} diff --git a/tools/services/abilitymgr/test/unittest/phone/want_sender_info_test/want_sender_info_test.cpp b/tools/services/abilitymgr/test/unittest/phone/want_sender_info_test/want_sender_info_test.cpp new file mode 100644 index 00000000000..7e56fd0bc5c --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/want_sender_info_test/want_sender_info_test.cpp @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "parcel.h" +#include "sender_info.h" +#include "wants_info.h" +#define private public +#define protected public +#include "want_sender_info.h" +#undef private +#undef protected +#include "want_receiver_stub.h" + +using namespace testing; +using namespace testing::ext; +using namespace OHOS::AppExecFwk; +using OHOS::AppExecFwk::ElementName; + +namespace OHOS { +namespace AAFwk { +#define SLEEP(milli) std::this_thread::sleep_for(std::chrono::seconds(milli)) +namespace {} // namespace +class WantSenderInfoTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp(); + void TearDown(); + static constexpr int TEST_WAIT_TIME = 100000; + class CancelReceiver : public AAFwk::WantReceiverStub { + public: + int performReceiveCount = 0; + void Send(const int32_t resultCode) override; + void PerformReceive(const AAFwk::Want &want, int resultCode, const std::string &data, + const AAFwk::WantParams &extras, bool serialized, bool sticky, int sendingUser) override; + }; + +public: +}; + +void WantSenderInfoTest::CancelReceiver::Send(const int32_t resultCode) +{} +void WantSenderInfoTest::CancelReceiver::PerformReceive(const AAFwk::Want &want, int resultCode, + const std::string &data, const AAFwk::WantParams &extras, bool serialized, bool sticky, int sendingUser) +{} + +void WantSenderInfoTest::SetUpTestCase() +{} + +void WantSenderInfoTest::TearDownTestCase() +{} + +void WantSenderInfoTest::SetUp() +{} + +void WantSenderInfoTest::TearDown() +{} + +/* + * @tc.number : WantSenderInfoTest_0100 + * @tc.name : Marshalling/UnMarshalling + * @tc.desc : 1.Marshalling/UnMarshalling + */ +HWTEST_F(WantSenderInfoTest, WantSenderInfoTest_0100, TestSize.Level1) +{ + WantSenderInfo info; + info.type = 10; + info.bundleName = "bundleName"; + info.resultWho = "abilityA"; + info.requestCode = 100; + Want want; + ElementName element("device", "com.ix.hiMusic", "MusicSAbility"); + want.SetElement(element); + WantsInfo wantInfo; + wantInfo.want = want; + wantInfo.resolvedTypes = "nihao"; + info.allWants.emplace_back(wantInfo); + info.flags = 3; + info.userId = 99; + Parcel parcel; + info.Marshalling(parcel); + auto unInfo = WantSenderInfo::Unmarshalling(parcel); + EXPECT_NE(unInfo, nullptr); + if (!unInfo) { + return; + } + EXPECT_EQ(unInfo->type, 10); + EXPECT_EQ(unInfo->bundleName, "bundleName"); + EXPECT_EQ(unInfo->resultWho, "abilityA"); + EXPECT_EQ(static_cast(unInfo->allWants.size()), 1); + EXPECT_EQ(unInfo->allWants.at(0).want.GetElement().GetBundleName(), "com.ix.hiMusic"); + EXPECT_EQ(unInfo->allWants.at(0).want.GetElement().GetAbilityName(), "MusicSAbility"); + EXPECT_EQ(unInfo->allWants.at(0).resolvedTypes, "nihao"); + EXPECT_EQ(unInfo->requestCode, 100); + EXPECT_EQ(unInfo->flags, 3); + EXPECT_EQ(unInfo->userId, 99); + delete unInfo; +} +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/abilitymgr/test/unittest/phone/want_sender_proxy_test/BUILD.gn b/tools/services/abilitymgr/test/unittest/phone/want_sender_proxy_test/BUILD.gn new file mode 100644 index 00000000000..1fd52485f41 --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/want_sender_proxy_test/BUILD.gn @@ -0,0 +1,65 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/test.gni") +import("//foundation/aafwk/standard/aafwk.gni") + +module_output_path = "aafwk_standard/abilitymgr" + +ohos_unittest("want_sender_proxy_test") { + module_out_path = module_output_path + + include_dirs = [ + "${services_path}/abilitymgr/test/mock/libs/system_ability_mock", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy/include", + ] + + sources = [ + "//foundation/aafwk/standard/services/abilitymgr/test/mock/libs/appexecfwk_core/src/appmgr/mock_app_scheduler.cpp", + "want_sender_proxy_test.cpp", + ] + + configs = [ + "${services_path}/abilitymgr:abilityms_config", + "${services_path}/abilitymgr/test/mock:aafwk_mock_config", + ] + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + deps = [ + "${services_path}/abilitymgr/test:abilityms_test_source", + "${services_path}/abilitymgr/test/mock/libs/aakit:aakit_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_appmgr_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_bundlemgr_mock", + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/frameworks/kits/ability/native:dummy_classes", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//third_party/googletest:gmock_main", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] +} + +group("unittest") { + testonly = true + + deps = [ ":want_sender_proxy_test" ] +} diff --git a/tools/services/abilitymgr/test/unittest/phone/want_sender_proxy_test/want_sender_proxy_test.cpp b/tools/services/abilitymgr/test/unittest/phone/want_sender_proxy_test/want_sender_proxy_test.cpp new file mode 100644 index 00000000000..945b866cdcd --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/want_sender_proxy_test/want_sender_proxy_test.cpp @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define private public +#include "want_sender_proxy.h" +#undef private + +#include +#include "want_sender_stub_mock.h" + +using namespace testing::ext; +using namespace testing; +using namespace OHOS::AppExecFwk; + +namespace OHOS { +namespace AAFwk { +class WantSenderProxyTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + + std::shared_ptr proxy_{nullptr}; + sptr mock_{nullptr}; +}; + +void WantSenderProxyTest::SetUpTestCase(void) +{} +void WantSenderProxyTest::TearDownTestCase(void) +{} +void WantSenderProxyTest::TearDown() +{} +void WantSenderProxyTest::SetUp() +{ + mock_ = new WantSenderStubMock(); + proxy_ = std::make_shared(mock_); +} + +/* + * Feature: WantSendProxy + * Function: Send + * SubFunction: NA + * FunctionPoints: WantSendProxy Send + * EnvConditions: NA + * CaseDescription: Verify that the return value of Send is normal + */ +HWTEST_F(WantSenderProxyTest, WantSenderProxyTest_001, TestSize.Level0) +{ + EXPECT_CALL(*mock_, SendRequest(_, _, _, _)) + .Times(1) + .WillOnce(Invoke(mock_.GetRefPtr(), &WantSenderStubMock::InvokeSendRequest)); + SenderInfo senderInfo; + proxy_->Send(senderInfo); + + EXPECT_EQ(IWantSender::WANT_SENDER_SEND, mock_->code_); +} +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/abilitymgr/test/unittest/phone/want_sender_proxy_test/want_sender_stub_mock.h b/tools/services/abilitymgr/test/unittest/phone/want_sender_proxy_test/want_sender_stub_mock.h new file mode 100644 index 00000000000..e1b7444379c --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/want_sender_proxy_test/want_sender_stub_mock.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ABILITY_UNITTEST_WANT_SENDER_STUB_MOCK_H +#define ABILITY_UNITTEST_WANT_SENDER_STUB_MOCK_H +#include +#include +#include +#include "want_sender_interface.h" + +namespace OHOS { +namespace AAFwk { +class WantSenderStubMock : public IRemoteStub { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"WantSenderStubMock"); + + WantSenderStubMock() : code_(0) {} + virtual ~WantSenderStubMock() {} + + MOCK_METHOD4(SendRequest, int(uint32_t, MessageParcel &, MessageParcel &, MessageOption &)); + + int InvokeSendRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) + { + code_ = code; + return NO_ERROR; + } + + int code_ = 0; + + virtual void Send(SenderInfo &senderInfo){} +}; +} // namespace AAFwk +} // namespace OHOS + +#endif // ABILITY_UNITTEST_WANT_SENDER_STUB_MOCK_H \ No newline at end of file diff --git a/tools/services/abilitymgr/test/unittest/phone/want_sender_stub_test/BUILD.gn b/tools/services/abilitymgr/test/unittest/phone/want_sender_stub_test/BUILD.gn new file mode 100644 index 00000000000..6e9d693b39d --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/want_sender_stub_test/BUILD.gn @@ -0,0 +1,66 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/test.gni") +import("//foundation/aafwk/standard/aafwk.gni") + +module_output_path = "aafwk_standard/abilitymgr" + +ohos_unittest("want_sender_stub_test") { + module_out_path = module_output_path + + include_dirs = [ + "${services_path}/abilitymgr/test/mock/libs/system_ability_mock", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy/include", + "//foundation/distributedschedule/samgr/utils/native/include/", + ] + + sources = [ + "//foundation/aafwk/standard/services/abilitymgr/test/mock/libs/appexecfwk_core/src/appmgr/mock_app_scheduler.cpp", + "want_sender_stub_test.cpp", + ] + + configs = [ + "${services_path}/abilitymgr:abilityms_config", + "${services_path}/abilitymgr/test/mock:aafwk_mock_config", + ] + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + deps = [ + "${services_path}/abilitymgr/test:abilityms_test_source", + "${services_path}/abilitymgr/test/mock/libs/aakit:aakit_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_appmgr_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_bundlemgr_mock", + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/frameworks/kits/ability/native:dummy_classes", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//third_party/googletest:gmock_main", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] +} + +group("unittest") { + testonly = true + + deps = [ ":want_sender_stub_test" ] +} diff --git a/tools/services/abilitymgr/test/unittest/phone/want_sender_stub_test/want_sender_stub_impl_mock.h b/tools/services/abilitymgr/test/unittest/phone/want_sender_stub_test/want_sender_stub_impl_mock.h new file mode 100644 index 00000000000..2a7a5082121 --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/want_sender_stub_test/want_sender_stub_impl_mock.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ABILITY_UNITTEST_WANT_SENDER_STUB_IMPL_MOCK_H +#define ABILITY_UNITTEST_WANT_SENDER_STUB_IMPL_MOCK_H + +#define private public +#include "want_sender_stub.h" +#undef private + +#include +#include +#include +#include "want_sender_interface.h" + +namespace OHOS { +namespace AAFwk { +class WantSenderStubImplMock : public WantSenderStub { +public: + WantSenderStubImplMock() + {} + virtual ~WantSenderStubImplMock() + {} + + int InvokeSendRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) + { + code_ = code; + return 0; + } + + int InvokeErrorSendRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) + { + code_ = code; + return UNKNOWN_ERROR; + } + + int code_ = 0; + + virtual void Send(SenderInfo &senderInfo){}; +}; +} // namespace AAFwk +} // namespace OHOS + +#endif // ABILITY_UNITTEST_WANT_SENDER_STUB_IMPL_MOCK_H \ No newline at end of file diff --git a/tools/services/abilitymgr/test/unittest/phone/want_sender_stub_test/want_sender_stub_test.cpp b/tools/services/abilitymgr/test/unittest/phone/want_sender_stub_test/want_sender_stub_test.cpp new file mode 100644 index 00000000000..aa4310a8f01 --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/want_sender_stub_test/want_sender_stub_test.cpp @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "iremote_proxy.h" +#include "want_sender_stub_impl_mock.h" + +using namespace testing::ext; +using namespace testing; + +namespace OHOS { +namespace AAFwk { +class WantSenderStubTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + void WriteInterfaceToken(MessageParcel &data); + sptr stub_{nullptr}; +}; + +void WantSenderStubTest::SetUpTestCase(void) +{} +void WantSenderStubTest::TearDownTestCase(void) +{} +void WantSenderStubTest::TearDown() +{} + +void WantSenderStubTest::SetUp() +{ + stub_ = new WantSenderStubImplMock(); +} + +void WantSenderStubTest::WriteInterfaceToken(MessageParcel &data) +{ + data.WriteInterfaceToken(WantSenderStubImplMock::GetDescriptor()); +} + +/* + * Feature: WantSenderStub + * Function: OnRemoteRequest + * SubFunction: NA + * FunctionPoints: WantSenderStub OnRemoteRequest + * EnvConditions: The code which not exist + * CaseDescription: Verify that on remote request is abnormal + */ +HWTEST_F(WantSenderStubTest, WantSenderStubTest_OnRemoteRequest_001, TestSize.Level0) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + WriteInterfaceToken(data); + int res = stub_->OnRemoteRequest(10000, data, reply, option); + + EXPECT_EQ(res, IPC_STUB_UNKNOW_TRANS_ERR); +} + +/* + * Feature: WantSenderStub + * Function: OnRemoteRequest + * SubFunction: NA + * FunctionPoints: WantSenderStub OnRemoteRequest + * EnvConditions: Description abnormal + * CaseDescription: Verify that on remote request is abnormal + */ +HWTEST_F(WantSenderStubTest, WantSenderStubTest_OnRemoteRequest_002, TestSize.Level0) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + int res = stub_->OnRemoteRequest(IWantSender::WANT_SENDER_SEND, data, reply, option); + + EXPECT_EQ(res, ERR_INVALID_STATE); +} + +/* + * Feature: WantSenderStub + * Function: OnRemoteRequest + * SubFunction: NA + * FunctionPoints: WantSenderStub OnRemoteRequest + * EnvConditions: Code is WANT_SENDER_SEND + * CaseDescription: Verify that on remote request is normal + */ +HWTEST_F(WantSenderStubTest, WantSenderStubTest_OnRemoteRequest_003, TestSize.Level0) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + SenderInfo info; + WriteInterfaceToken(data); + data.WriteParcelable(&info); + + int res = stub_->OnRemoteRequest(IWantSender::WANT_SENDER_SEND, data, reply, option); + + EXPECT_EQ(res, NO_ERROR); +} + +/* + * Feature: WantSenderStub + * Function: SendInner + * SubFunction: NA + * FunctionPoints: WantSenderStub SendInner + * EnvConditions: Invalid parameter + * CaseDescription: Verify the function SendInner request is abnormal. + */ +HWTEST_F(WantSenderStubTest, WantSenderStubTest_SendInner_001, TestSize.Level0) +{ + MessageParcel data; + MessageParcel reply; + + int res = stub_->SendInner(data, reply); + + EXPECT_EQ(res, ERR_INVALID_VALUE); +} + +/* + * Feature: WantSenderStub + * Function: OnRemoteRequest + * SubFunction: NA + * FunctionPoints: WantSenderStub SendInner + * EnvConditions: Valid parameter + * CaseDescription: Verify the function SendInner request is normal. + */ +HWTEST_F(WantSenderStubTest, WantSenderStubTest_SendInner_002, TestSize.Level0) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + SenderInfo info; + data.WriteParcelable(&info); + + int res = stub_->SendInner(data, reply); + + EXPECT_EQ(res, NO_ERROR); +} +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/abilitymgr/test/unittest/phone/wants_info_test/BUILD.gn b/tools/services/abilitymgr/test/unittest/phone/wants_info_test/BUILD.gn new file mode 100644 index 00000000000..51752cff05b --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/wants_info_test/BUILD.gn @@ -0,0 +1,65 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/test.gni") +import("//foundation/aafwk/standard/aafwk.gni") + +module_output_path = "aafwk_standard/abilitymgr" + +ohos_unittest("wants_info_test") { + module_out_path = module_output_path + + include_dirs = [ + "${services_path}/abilitymgr/test/mock/libs/system_ability_mock", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy/include", + "//foundation/distributedschedule/samgr/adapter/interfaces/innerkits/include/", + "//foundation/communication/ipc/interfaces/innerkits/ipc_core/include", + ] + + sources = [ + "//foundation/aafwk/standard/services/abilitymgr/test/mock/libs/appexecfwk_core/src/appmgr/mock_app_scheduler.cpp", + "wants_info_test.cpp", + ] + + configs = [ "${services_path}/abilitymgr:abilityms_config" ] + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + deps = [ + "${innerkits_path}/want:want", + "${services_path}/abilitymgr/test:abilityms_test_source", + "${services_path}/abilitymgr/test/mock/libs/aakit:aakit_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_appmgr_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_bundlemgr_mock", + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/frameworks/kits/ability/native:dummy_classes", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//third_party/googletest:gmock_main", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] +} + +group("unittest") { + testonly = true + + deps = [ ":wants_info_test" ] +} diff --git a/tools/services/abilitymgr/test/unittest/phone/wants_info_test/wants_info_test.cpp b/tools/services/abilitymgr/test/unittest/phone/wants_info_test/wants_info_test.cpp new file mode 100644 index 00000000000..8069471505f --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/wants_info_test/wants_info_test.cpp @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "parcel.h" +#include "sender_info.h" +#define private public +#define protected public +#include "wants_info.h" +#undef private +#undef protected +#include "want_receiver_stub.h" + +using namespace testing; +using namespace testing::ext; +using namespace OHOS::AppExecFwk; +using OHOS::AppExecFwk::ElementName; + +namespace OHOS { +namespace AAFwk { +#define SLEEP(milli) std::this_thread::sleep_for(std::chrono::seconds(milli)) +namespace {} // namespace +class WantsInfoTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp(); + void TearDown(); + static constexpr int TEST_WAIT_TIME = 100000; + class CancelReceiver : public AAFwk::WantReceiverStub { + public: + int performReceiveCount = 0; + void Send(const int32_t resultCode) override; + void PerformReceive(const AAFwk::Want &want, int resultCode, const std::string &data, + const AAFwk::WantParams &extras, bool serialized, bool sticky, int sendingUser) override; + }; + +public: +}; + +void WantsInfoTest::CancelReceiver::Send(const int32_t resultCode) +{} +void WantsInfoTest::CancelReceiver::PerformReceive(const AAFwk::Want &want, int resultCode, const std::string &data, + const AAFwk::WantParams &extras, bool serialized, bool sticky, int sendingUser) +{} + +void WantsInfoTest::SetUpTestCase() +{} + +void WantsInfoTest::TearDownTestCase() +{} + +void WantsInfoTest::SetUp() +{} + +void WantsInfoTest::TearDown() +{} + +/* + * @tc.number : WantsInfoTest_0100 + * @tc.name : Marshalling/UnMarshalling + * @tc.desc : 1.Marshalling/UnMarshalling + */ +HWTEST_F(WantsInfoTest, WantsInfoTest_0100, TestSize.Level1) +{ + WantsInfo info; + Want want; + ElementName element("device", "com.ix.hiMusic", "MusicSAbility"); + want.SetElement(element); + info.want = want; + info.resolvedTypes = "nihao"; + Parcel parcel; + info.Marshalling(parcel); + auto unInfo = WantsInfo::Unmarshalling(parcel); + EXPECT_EQ(unInfo->want.GetElement().GetBundleName(), "com.ix.hiMusic"); + EXPECT_EQ(unInfo->want.GetElement().GetAbilityName(), "MusicSAbility"); + EXPECT_EQ(unInfo->resolvedTypes, "nihao"); + delete unInfo; +} +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/abilitymgr/test/unittest/phone/window_info_test/BUILD.gn b/tools/services/abilitymgr/test/unittest/phone/window_info_test/BUILD.gn new file mode 100644 index 00000000000..3e7d101d3a4 --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/window_info_test/BUILD.gn @@ -0,0 +1,53 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/test.gni") +import("//foundation/aafwk/standard/aafwk.gni") + +module_output_path = "aafwk_standard/abilitymgr" + +ohos_unittest("window_info_test") { + module_out_path = module_output_path + + include_dirs = [ + "${services_path}/abilitymgr/test/mock/libs/system_ability_mock", + "//foundation/communication/ipc/interfaces/innerkits/ipc_core/include", + "//foundation/communication/ipc/interfaces/innerkits/ipc_core/include", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy/include", + ] + + sources = [ + "//foundation/aafwk/standard/services/abilitymgr/test/mock/libs/appexecfwk_core/src/appmgr/mock_app_scheduler.cpp", + "window_info_test.cpp", + ] + + configs = [ "${services_path}/abilitymgr:abilityms_config" ] + + deps = [ + "${innerkits_path}/want:want", + "${services_path}/abilitymgr/test:abilityms_test_source", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_appmgr_mock", + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/frameworks/kits/ability/native:dummy_classes", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//third_party/googletest:gtest_main", + ] + + external_deps = [ "hiviewdfx_hilog_native:libhilog" ] +} + +group("unittest") { + testonly = true + + deps = [ ":window_info_test" ] +} diff --git a/tools/services/abilitymgr/test/unittest/phone/window_info_test/window_info_test.cpp b/tools/services/abilitymgr/test/unittest/phone/window_info_test/window_info_test.cpp new file mode 100644 index 00000000000..adc506e05e1 --- /dev/null +++ b/tools/services/abilitymgr/test/unittest/phone/window_info_test/window_info_test.cpp @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "window_info.h" + +using namespace testing::ext; +namespace OHOS { +namespace AAFwk { +class WindowInfoTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + + std::shared_ptr get() const; + +private: + std::shared_ptr windowInfo_{nullptr}; +}; + +void WindowInfoTest::SetUpTestCase(void) +{} +void WindowInfoTest::TearDownTestCase(void) +{} +void WindowInfoTest::TearDown() +{} + +void WindowInfoTest::SetUp() +{ + windowInfo_ = std::make_shared(1); +} + +std::shared_ptr WindowInfoTest::get() const +{ + return windowInfo_; +} + +/* + * Feature: WindowInfo + * Function: Constructors and Destructor + * SubFunction: NA + * FunctionPoints: NA + * EnvConditions:NA + * CaseDescription: Verify member variable values + */ +HWTEST_F(WindowInfoTest, AAFWK_Window_Info, TestSize.Level0) +{ + EXPECT_EQ((int)get()->windowToken_, 1); + EXPECT_FALSE(get()->isVisible_); +} +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/common/BUILD.gn b/tools/services/common/BUILD.gn new file mode 100644 index 00000000000..d2809197f08 --- /dev/null +++ b/tools/services/common/BUILD.gn @@ -0,0 +1,31 @@ +# +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +import("//build/ohos.gni") +import("//foundation/aafwk/standard/aafwk.gni") + +group("common_target") { + deps = [ ":abilitymgr_common" ] +} + +config("common_config") { + include_dirs = [ "include/" ] +} + +ohos_source_set("abilitymgr_common") { + configs = [ ":common_config" ] + + external_deps = [ "hiviewdfx_hilog_native:libhilog" ] +} diff --git a/tools/services/common/include/hilog_wrapper.h b/tools/services/common/include/hilog_wrapper.h new file mode 100644 index 00000000000..3e292f8ce73 --- /dev/null +++ b/tools/services/common/include/hilog_wrapper.h @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HILOG_WRAPPER_H +#define HILOG_WRAPPER_H + +#define CONFIG_HILOG +#ifdef CONFIG_HILOG +#include "hilog/log.h" + +#ifdef HILOG_FATAL +#undef HILOG_FATAL +#endif + +#ifdef HILOG_ERROR +#undef HILOG_ERROR +#endif + +#ifdef HILOG_WARN +#undef HILOG_WARN +#endif + +#ifdef HILOG_INFO +#undef HILOG_INFO +#endif + +#ifdef HILOG_DEBUG +#undef HILOG_DEBUG +#endif + +#ifndef AMS_LOG_DOMAIN +#define AMS_LOG_DOMAIN 0xD001000 +#endif + +#ifndef AMS_LOG_TAG +#define AMS_LOG_TAG "AbilityManagerService" +#endif + +#ifdef LOG_LABEL +#undef LOG_LABEL +#endif + +static constexpr OHOS::HiviewDFX::HiLogLabel LOG_LABEL = {LOG_CORE, AMS_LOG_DOMAIN, AMS_LOG_TAG}; + +#define __FILENAME__ (__builtin_strrchr(__FILE__, '/') ? __builtin_strrchr(__FILE__, '/') + 1 : __FILE__) + +#define HILOG_FATAL(fmt, ...) \ + (void)OHOS::HiviewDFX::HiLog::Fatal( \ + LOG_LABEL, "[%{public}s(%{public}s:%{public}d)]" fmt, __FILENAME__, __FUNCTION__, __LINE__, ##__VA_ARGS__) +#define HILOG_ERROR(fmt, ...) \ + (void)OHOS::HiviewDFX::HiLog::Error( \ + LOG_LABEL, "[%{public}s(%{public}s:%{public}d)]" fmt, __FILENAME__, __FUNCTION__, __LINE__, ##__VA_ARGS__) +#define HILOG_WARN(fmt, ...) \ + (void)OHOS::HiviewDFX::HiLog::Warn( \ + LOG_LABEL, "[%{public}s(%{public}s:%{public}d)]" fmt, __FILENAME__, __FUNCTION__, __LINE__, ##__VA_ARGS__) +#define HILOG_INFO(fmt, ...) \ + (void)OHOS::HiviewDFX::HiLog::Info( \ + LOG_LABEL, "[%{public}s(%{public}s:%{public}d)]" fmt, __FILENAME__, __FUNCTION__, __LINE__, ##__VA_ARGS__) +#define HILOG_DEBUG(fmt, ...) \ + (void)OHOS::HiviewDFX::HiLog::Debug( \ + LOG_LABEL, "[%{public}s(%{public}s:%{public}d)]" fmt, __FILENAME__, __FUNCTION__, __LINE__, ##__VA_ARGS__) +#else + +#define HILOG_FATAL(...) +#define HILOG_ERROR(...) +#define HILOG_WARN(...) +#define HILOG_INFO(...) +#define HILOG_DEBUG(...) +#endif // CONFIG_HILOG + +#endif // HILOG_WRAPPER_H \ No newline at end of file diff --git a/tools/services/dataobsmgr/BUILD.gn b/tools/services/dataobsmgr/BUILD.gn new file mode 100644 index 00000000000..474d2a4eb3f --- /dev/null +++ b/tools/services/dataobsmgr/BUILD.gn @@ -0,0 +1,70 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") +import("//foundation/aafwk/standard/aafwk.gni") +import("//foundation/aafwk/standard/services/dataobsmgr/dataobsms.gni") + +group("dataobsms_target") { + deps = [ ":dataobsms" ] +} + +group("unittest") { + testonly = true + + deps = [ "test:unittest" ] +} + +config("dataobsms_config") { + include_dirs = [ + "include/", + "${innerkits_path}/base/include", + "${services_path}/common/include", + "//utils/native/base/include", + "//utils/system/safwk/native/include", + "//prebuilts/jdk/jdk8/linux-x86/include", + "//prebuilts/jdk/jdk8/linux-x86/include/linux", + "//third_party/json/include", + "//foundation/aafwk/standard/interfaces/innerkits/dataobs_manager/include", + ] + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } +} + +ohos_shared_library("dataobsms") { + sources = dataobsms_files + + configs = [ ":dataobsms_config" ] + + deps = [ + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/interfaces/innerkits/base:base", + "//foundation/aafwk/standard/interfaces/innerkits/dataobs_manager:dataobs_manager", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_core:appexecfwk_core", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//foundation/distributedschedule/safwk/interfaces/innerkits/safwk:system_ability_fwk", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy:samgr_proxy", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] + + subsystem_name = "aafwk" + part_name = "aafwk_standard" +} diff --git a/tools/services/dataobsmgr/dataobsms.gni b/tools/services/dataobsmgr/dataobsms.gni new file mode 100644 index 00000000000..9e9c726fd85 --- /dev/null +++ b/tools/services/dataobsmgr/dataobsms.gni @@ -0,0 +1,22 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//foundation/aafwk/standard/aafwk.gni") + +dataobsms_files = [ + "${services_path}/dataobsmgr/src/dataobs_mgr_inner.cpp", + "${services_path}/dataobsmgr/src/dataobs_mgr_proxy.cpp", + "${services_path}/dataobsmgr/src/dataobs_mgr_stub.cpp", + "${services_path}/dataobsmgr/src/dataobs_mgr_service.cpp", + "${services_path}/dataobsmgr/src/data_ability_observer_proxy.cpp", +] diff --git a/tools/services/dataobsmgr/include/data_ability_observer_proxy.h b/tools/services/dataobsmgr/include/data_ability_observer_proxy.h new file mode 100644 index 00000000000..5072e72e519 --- /dev/null +++ b/tools/services/dataobsmgr/include/data_ability_observer_proxy.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef OHOS_AAFWK_DATA_ABILITY_OBSERVER_PROXY_H +#define OHOS_AAFWK_DATA_ABILITY_OBSERVER_PROXY_H + +#include "data_ability_observer_interface.h" + +#include + +namespace OHOS { +namespace AAFwk { + +class DataAbilityObserverProxy : public IRemoteProxy { +public: + explicit DataAbilityObserverProxy(const sptr &remote); + virtual ~DataAbilityObserverProxy(); + /** + * @brief Called back to notify that the data being observed has changed. + * + * @param uri Indicates the path of the data to operate. + */ + void OnChange() override; + +private: + static inline BrokerDelegator delegator_; +}; + +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_DATA_ABILITY_OBSERVER_PROXY_H \ No newline at end of file diff --git a/tools/services/dataobsmgr/include/dataobs_mgr_inner.h b/tools/services/dataobsmgr/include/dataobs_mgr_inner.h new file mode 100644 index 00000000000..89915c8adf1 --- /dev/null +++ b/tools/services/dataobsmgr/include/dataobs_mgr_inner.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_DATAOBS_MANAGER_INNER_H +#define OHOS_AAFWK_DATAOBS_MANAGER_INNER_H + +#include +#include +#include +#include +#include +#include + +#include "iremote_object.h" +#include "refbase.h" + +#include "data_ability_observer_interface.h" + +#include "event_handler.h" + +namespace OHOS { +namespace AAFwk { +using EventHandler = OHOS::AppExecFwk::EventHandler; +class DataObsMgrInner : public std::enable_shared_from_this { +public: + using ObsMapType = std::map>>; + using ObsListType = std::list>; + using ObsRecipientMapType = std::map, sptr>; + + DataObsMgrInner(); + virtual ~DataObsMgrInner(); + + void SetHandler(const std::shared_ptr &handler); + int HandleRegisterObserver(const Uri &uri, const sptr &dataObserver); + int HandleUnregisterObserver(const Uri &uri, const sptr &dataObserver); + int HandleNotifyChange(const Uri &uri); + bool CheckNeedLimmit(); + bool CheckRegisteFull(const Uri &uri); + void AtomicAddTaskCount(); + void AtomicSubTaskCount(); + void OnCallBackDied(const wptr &remote); + +private: + bool GetObsListFromMap(const Uri &uri, ObsListType &obslist); + void AddObsDeathRecipient(const sptr &dataObserver); + void RemoveObsDeathRecipient(const sptr &dataObserver); + void HandleCallBackDiedTask(const sptr &dataObserver); + void RemoveObsFromMap(const sptr &dataObserver); + bool ObsExistInMap(const sptr &dataObserver); + + std::atomic_int taskCount_; + const int taskCount_max_ = 50; + const unsigned int obs_max_ = 50; + static std::mutex innerMutex_; + std::shared_ptr handler_ = nullptr; + ObsMapType obsmap_; + ObsRecipientMapType recipientMap_; +}; + +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_DATAOBS_MANAGER_INNER_H diff --git a/tools/services/dataobsmgr/include/dataobs_mgr_proxy.h b/tools/services/dataobsmgr/include/dataobs_mgr_proxy.h new file mode 100644 index 00000000000..44b435a7fa6 --- /dev/null +++ b/tools/services/dataobsmgr/include/dataobs_mgr_proxy.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_DATAOBS_MANAGER_PROXY_H +#define OHOS_AAFWK_DATAOBS_MANAGER_PROXY_H + +#include "dataobs_mgr_interface.h" +#include "hilog_wrapper.h" +#include "iremote_proxy.h" + +namespace OHOS { +namespace AAFwk { +/** + * @class DataObsManagerProxy + * DataObsManagerProxy. + */ +class DataObsManagerProxy : public IRemoteProxy { +public: + explicit DataObsManagerProxy(const sptr &impl) : IRemoteProxy(impl) + {} + + virtual ~DataObsManagerProxy() + {} + + /** + * Registers an observer to DataObsMgr specified by the given Uri. + * + * @param uri, Indicates the path of the data to operate. + * @param dataObserver, Indicates the IDataAbilityObserver object. + * + * @return Returns ERR_OK on success, others on failure. + */ + + virtual int RegisterObserver(const Uri &uri, const sptr &dataObserver); + + /** + * Deregisters an observer used for DataObsMgr specified by the given Uri. + * + * @param uri, Indicates the path of the data to operate. + * @param dataObserver, Indicates the IDataAbilityObserver object. + * + * @return Returns ERR_OK on success, others on failure. + */ + virtual int UnregisterObserver(const Uri &uri, const sptr &dataObserver); + + /** + * Notifies the registered observers of a change to the data resource specified by Uri. + * + * @param uri, Indicates the path of the data to operate. + * + * @return Returns ERR_OK on success, others on failure. + */ + virtual int NotifyChange(const Uri &uri); + +private: + bool WriteInterfaceToken(MessageParcel &data); + +private: + static inline BrokerDelegator delegator_; +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_DATAOBS_MANAGER_PROXY_H diff --git a/tools/services/dataobsmgr/include/dataobs_mgr_service.h b/tools/services/dataobsmgr/include/dataobs_mgr_service.h new file mode 100644 index 00000000000..5a6f3189935 --- /dev/null +++ b/tools/services/dataobsmgr/include/dataobs_mgr_service.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_DATAOBS_MANAGER_SERVICE_H +#define OHOS_AAFWK_DATAOBS_MANAGER_SERVICE_H + +#include +#include +#include +#include + +#include "dataobs_mgr_inner.h" +#include "dataobs_mgr_stub.h" +#include "hilog_wrapper.h" +#include "iremote_object.h" +#include "system_ability.h" +#include "uri.h" +#include "event_runner.h" +#include "event_handler.h" + +namespace OHOS { +namespace AAFwk { +using EventRunner = OHOS::AppExecFwk::EventRunner; +using EventHandler = OHOS::AppExecFwk::EventHandler; +enum class DataObsServiceRunningState { STATE_NOT_START, STATE_RUNNING }; + +/** + * @class DataObsMgrService + * DataObsMgrService provides a facility for dataobserver. + */ +class DataObsMgrService : public SystemAbility, + public DataObsManagerStub, + public std::enable_shared_from_this { + DECLARE_DELAYED_SINGLETON(DataObsMgrService) + DECLEAR_SYSTEM_ABILITY(DataObsMgrService) +public: + void OnStart() override; + void OnStop() override; + DataObsServiceRunningState QueryServiceState() const; + + virtual int RegisterObserver(const Uri &uri, const sptr &dataObserver) override; + virtual int UnregisterObserver(const Uri &uri, const sptr &dataObserver) override; + virtual int NotifyChange(const Uri &uri) override; + + /** + * GetEventHandler, get the dataobs manager service's handler. + * + * @return Returns EventHandler ptr. + */ + std::shared_ptr GetEventHandler(); + +private: + bool Init(); + std::shared_ptr eventLoop_; + std::shared_ptr handler_; + DataObsServiceRunningState state_; + std::shared_ptr dataObsMgrInner_; + const int taskMax_ = 50; +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_DATAOBS_MANAGER_SERVICE_H diff --git a/tools/services/dataobsmgr/include/dataobs_mgr_stub.h b/tools/services/dataobsmgr/include/dataobs_mgr_stub.h new file mode 100644 index 00000000000..b7185e50fc5 --- /dev/null +++ b/tools/services/dataobsmgr/include/dataobs_mgr_stub.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_DATAOBS_MANAGER_STUB_H +#define OHOS_AAFWK_DATAOBS_MANAGER_STUB_H + +#include "dataobs_mgr_interface.h" + +#include +#include +#include + +#include "hilog_wrapper.h" + +namespace OHOS { +namespace AAFwk { +/** + * @class DataObsManagerStub + * DataObsManagerStub. + */ +class DataObsManagerStub : public IRemoteStub { +public: + DataObsManagerStub(); + ~DataObsManagerStub(); + virtual int OnRemoteRequest( + uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override; + +private: + int RegisterObserverInner(MessageParcel &data, MessageParcel &reply); + int UnregisterObserverInner(MessageParcel &data, MessageParcel &reply); + int NotifyChangeInner(MessageParcel &data, MessageParcel &reply); + + using RequestFuncType = int (DataObsManagerStub::*)(MessageParcel &data, MessageParcel &reply); + std::map requestFuncMap_; +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_DATAOBS_MANAGER_STUB_H diff --git a/tools/services/dataobsmgr/src/data_ability_observer_proxy.cpp b/tools/services/dataobsmgr/src/data_ability_observer_proxy.cpp new file mode 100644 index 00000000000..2d4b0cc6491 --- /dev/null +++ b/tools/services/dataobsmgr/src/data_ability_observer_proxy.cpp @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "data_ability_observer_proxy.h" +#include "hilog_wrapper.h" +#include "message_parcel.h" + +namespace OHOS { +namespace AAFwk { + +DataAbilityObserverProxy::DataAbilityObserverProxy(const sptr &remote) + : IRemoteProxy(remote) +{} +DataAbilityObserverProxy::~DataAbilityObserverProxy() +{} +/** + * @brief Called back to notify that the data being observed has changed. + * + * @param uri Indicates the path of the data to operate. + */ +void DataAbilityObserverProxy::OnChange() +{ + auto remote = Remote(); + if (remote == nullptr) { + HILOG_ERROR("%{public}s remote is nullptr", __func__); + return; + } + + OHOS::MessageParcel data; + OHOS::MessageParcel reply; + OHOS::MessageOption option; + + if (!data.WriteInterfaceToken(DataAbilityObserverProxy::GetDescriptor())) { + HILOG_ERROR("%{public}s data.WriteInterfaceToken(GetDescriptor()) return false", __func__); + return; + } + + int result = remote->SendRequest(IDataAbilityObserver::DATA_ABILITY_OBSERVER_CHANGE, data, reply, option); + if (result == ERR_NONE) { + HILOG_INFO("%{public}s SendRequest ok, retval is %d", __func__, reply.ReadInt32()); + return; + } else { + HILOG_ERROR("%{public}s SendRequest error, result=%{public}d", __func__, result); + return; + } +} + +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/dataobsmgr/src/data_ability_observer_stub.cpp b/tools/services/dataobsmgr/src/data_ability_observer_stub.cpp new file mode 100644 index 00000000000..f738a4aa592 --- /dev/null +++ b/tools/services/dataobsmgr/src/data_ability_observer_stub.cpp @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "data_ability_observer_stub.h" +#include "hilog_wrapper.h" + +namespace OHOS { +namespace AAFwk { + +DataAbilityObserverStub::DataAbilityObserverStub() +{ + requestFuncMap_[DATA_ABILITY_OBSERVER_CHANGE] = &DataAbilityObserverStub::OnChangeInner; +} + +DataAbilityObserverStub::~DataAbilityObserverStub() +{ + requestFuncMap_.clear(); +} + +int DataAbilityObserverStub::OnRemoteRequest( + uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) +{ + HILOG_DEBUG("%{public}s, cmd = %d, flags= %d", __func__, code, option.GetFlags()); + std::u16string descriptor = DataAbilityObserverStub::GetDescriptor(); + std::u16string remoteDescriptor = data.ReadInterfaceToken(); + if (descriptor != remoteDescriptor) { + HILOG_INFO("local descriptor is not equal to remote"); + return ERR_INVALID_STATE; + } + + auto itFunc = requestFuncMap_.find(code); + if (itFunc != requestFuncMap_.end()) { + auto requestFunc = itFunc->second; + if (requestFunc != nullptr) { + return (this->*requestFunc)(data, reply); + } + } + HILOG_WARN("%{public}s, default case, need check.", __func__); + return IPCObjectStub::OnRemoteRequest(code, data, reply, option); +} + +/** + * @brief Called back to notify that the data being observed has changed. + * + * @param uri Indicates the path of the data to operate. + * + * @return Returns 0 on success, others on failure. + */ +int DataAbilityObserverStub::OnChangeInner(MessageParcel &data, MessageParcel &reply) +{ + OnChange(); + return ERR_NONE; +} + +void DataObsCallbackRecipient::OnRemoteDied(const wptr &remote) +{ + HILOG_ERROR("recv DataObsCallbackRecipient death notice"); + + if (handler_) { + handler_(remote); + } +} + +DataObsCallbackRecipient::DataObsCallbackRecipient(RemoteDiedHandler handler) : handler_(handler) +{} + +DataObsCallbackRecipient::~DataObsCallbackRecipient() +{} +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/dataobsmgr/src/dataobs_mgr_client.cpp b/tools/services/dataobsmgr/src/dataobs_mgr_client.cpp new file mode 100644 index 00000000000..38600d490e7 --- /dev/null +++ b/tools/services/dataobsmgr/src/dataobs_mgr_client.cpp @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "dataobs_mgr_client.h" + +#include "string_ex.h" + +#include "hilog_wrapper.h" +#include "ipc_skeleton.h" +#include "iservice_registry.h" +#include "if_system_ability_manager.h" +#include "system_ability_definition.h" + +namespace OHOS { +namespace AAFwk { +std::shared_ptr DataObsMgrClient::instance_ = nullptr; +std::mutex DataObsMgrClient::mutex_; + +std::shared_ptr DataObsMgrClient::GetInstance() +{ + if (instance_ == nullptr) { + std::lock_guard lock_l(mutex_); + if (instance_ == nullptr) { + instance_ = std::make_shared(); + } + } + return instance_; +} + +DataObsMgrClient::DataObsMgrClient() +{} + +DataObsMgrClient::~DataObsMgrClient() +{} + +/** + * Registers an observer to DataObsMgr specified by the given Uri. + * + * @param uri, Indicates the path of the data to operate. + * @param dataObserver, Indicates the IDataAbilityObserver object. + * + * @return Returns ERR_OK on success, others on failure. + */ +ErrCode DataObsMgrClient::RegisterObserver(const Uri &uri, const sptr &dataObserver) +{ + if (remoteObject_ == nullptr) { + ErrCode err = Connect(); + if (err != ERR_OK) { + return DATAOBS_SERVICE_NOT_CONNECTED; + } + } + sptr doms = iface_cast(remoteObject_); + return doms->RegisterObserver(uri, dataObserver); +} + +/** + * Deregisters an observer used for DataObsMgr specified by the given Uri. + * + * @param uri, Indicates the path of the data to operate. + * @param dataObserver, Indicates the IDataAbilityObserver object. + * + * @return Returns ERR_OK on success, others on failure. + */ +ErrCode DataObsMgrClient::UnregisterObserver(const Uri &uri, const sptr &dataObserver) +{ + if (remoteObject_ == nullptr) { + ErrCode err = Connect(); + if (err != ERR_OK) { + return DATAOBS_SERVICE_NOT_CONNECTED; + } + } + sptr doms = iface_cast(remoteObject_); + return doms->UnregisterObserver(uri, dataObserver); +} + +/** + * Notifies the registered observers of a change to the data resource specified by Uri. + * + * @param uri, Indicates the path of the data to operate. + * + * @return Returns ERR_OK on success, others on failure. + */ +ErrCode DataObsMgrClient::NotifyChange(const Uri &uri) +{ + if (remoteObject_ == nullptr) { + ErrCode err = Connect(); + if (err != ERR_OK) { + return DATAOBS_SERVICE_NOT_CONNECTED; + } + } + sptr doms = iface_cast(remoteObject_); + return doms->NotifyChange(uri); +} + +/** + * Connect dataobs manager service. + * + * @return Returns ERR_OK on success, others on failure. + */ +ErrCode DataObsMgrClient::Connect() +{ + std::lock_guard lock(mutex_); + if (remoteObject_ != nullptr) { + return ERR_OK; + } + sptr systemManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + if (systemManager == nullptr) { + HILOG_ERROR("%{private}s:fail to get Registry", __func__); + return GET_DATAOBS_SERVICE_FAILED; + } + remoteObject_ = systemManager->GetSystemAbility(DATAOBS_MGR_SERVICE_SA_ID); + if (remoteObject_ == nullptr) { + HILOG_ERROR("%{private}s:fail to connect DataObsMgrService", __func__); + return GET_DATAOBS_SERVICE_FAILED; + } + HILOG_DEBUG("connect DataObsMgrService success"); + return ERR_OK; +} + +} // namespace AAFwk +} // namespace OHOS diff --git a/tools/services/dataobsmgr/src/dataobs_mgr_inner.cpp b/tools/services/dataobsmgr/src/dataobs_mgr_inner.cpp new file mode 100644 index 00000000000..5826ca8884a --- /dev/null +++ b/tools/services/dataobsmgr/src/dataobs_mgr_inner.cpp @@ -0,0 +1,257 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "dataobs_mgr_inner.h" +#include "dataobs_mgr_errors.h" +#include "hilog_wrapper.h" +#include "data_ability_observer_stub.h" + +namespace OHOS { +namespace AAFwk { + +std::mutex DataObsMgrInner::innerMutex_; + +DataObsMgrInner::DataObsMgrInner() +{ + taskCount_.store(0); +} + +DataObsMgrInner::~DataObsMgrInner() +{ + taskCount_.store(0); +} + +void DataObsMgrInner::SetHandler(const std::shared_ptr &handler) +{ + handler_ = handler; +} + +int DataObsMgrInner::HandleRegisterObserver(const Uri &uri, const sptr &dataObserver) +{ + HILOG_INFO("DataObsMgrInner::HandleRegisterObserver called start"); + std::lock_guard lock_l(innerMutex_); + + ObsListType obslist; + bool exist = GetObsListFromMap(uri, obslist); + + auto obs = std::find(obslist.begin(), obslist.end(), dataObserver); + if (obs != obslist.end()) { + HILOG_ERROR("DataObsMgrInner::HandleRegisterObserver the obs exist. no need to register."); + return OBS_EXIST; + } + + obslist.push_back(dataObserver); + + AddObsDeathRecipient(dataObserver); + + if (exist) { + obsmap_.erase(uri.ToString()); + } + + obsmap_.emplace(uri.ToString(), obslist); + + AtomicSubTaskCount(); + + HILOG_INFO("DataObsMgrInner::HandleRegisterObserver called end"); + return NO_ERROR; +} + +int DataObsMgrInner::HandleUnregisterObserver(const Uri &uri, const sptr &dataObserver) +{ + HILOG_INFO("DataObsMgrInner::HandleUnregisterObserver called start"); + std::lock_guard lock_l(innerMutex_); + + ObsListType obslist; + if (!GetObsListFromMap(uri, obslist)) { + AtomicSubTaskCount(); + HILOG_ERROR("DataObsMgrInner::HandleUnregisterObserver there is no obs in the uri."); + return NO_OBS_FOR_URI; + } + + auto obs = std::find(obslist.begin(), obslist.end(), dataObserver); + if (obs == obslist.end()) { + AtomicSubTaskCount(); + HILOG_ERROR("DataObsMgrInner::HandleUnregisterObserver the obs is not registered to the uri."); + return NO_OBS_FOR_URI; + } + + obslist.remove(dataObserver); + obsmap_.erase(uri.ToString()); + if (!obslist.empty()) { + obsmap_.emplace(uri.ToString(), obslist); + } + + if (!ObsExistInMap(dataObserver)) { + RemoveObsDeathRecipient(dataObserver); + } + + AtomicSubTaskCount(); + HILOG_INFO("DataObsMgrInner::HandleUnregisterObserver called end"); + return NO_ERROR; +} + +int DataObsMgrInner::HandleNotifyChange(const Uri &uri) +{ + HILOG_INFO("DataObsMgrInner::HandleNotifyChange called start"); + std::lock_guard lock_l(innerMutex_); + + ObsListType obslist; + if (!GetObsListFromMap(uri, obslist)) { + AtomicSubTaskCount(); + HILOG_INFO("DataObsMgrInner::HandleNotifyChange there is no obs in the uri."); + return NO_OBS_FOR_URI; + } + + for (auto obs : obslist) { + if (obs != nullptr) { + obs->OnChange(); + } + } + + AtomicSubTaskCount(); + HILOG_INFO("DataObsMgrInner::HandleNotifyChange called end"); + return NO_ERROR; +} + +bool DataObsMgrInner::CheckNeedLimmit() +{ + return (taskCount_.load() >= taskCount_max_) ? true : false; +} + +bool DataObsMgrInner::CheckRegisteFull(const Uri &uri) +{ + std::lock_guard lock_l(innerMutex_); + + ObsListType obslist; + if (GetObsListFromMap(uri, obslist)) { + // The obs size for input uri has been lager than max. + if (obslist.size() >= obs_max_) { + return true; + } + } + return false; +} + +void DataObsMgrInner::AtomicAddTaskCount() +{ + taskCount_.fetch_add(1); +} + +void DataObsMgrInner::AtomicSubTaskCount() +{ + taskCount_.fetch_sub(1); +} + +bool DataObsMgrInner::GetObsListFromMap(const Uri &uri, ObsListType &obslist) +{ + auto it = obsmap_.find(uri.ToString()); + if (it == obsmap_.end()) { + return false; + } + + obslist = it->second; + return true; +} + +void DataObsMgrInner::AddObsDeathRecipient(const sptr &dataObserver) +{ + if ((dataObserver == nullptr) || dataObserver->AsObject() == nullptr) { + return; + } + + auto it = recipientMap_.find(dataObserver->AsObject()); + if (it != recipientMap_.end()) { + HILOG_ERROR("%{public}s this death recipient has been added.", __func__); + return; + } else { + sptr deathRecipient = + new DataObsCallbackRecipient(std::bind(&DataObsMgrInner::OnCallBackDied, this, std::placeholders::_1)); + dataObserver->AsObject()->AddDeathRecipient(deathRecipient); + recipientMap_.emplace(dataObserver->AsObject(), deathRecipient); + } +} + +void DataObsMgrInner::RemoveObsDeathRecipient(const sptr &dataObserver) +{ + if ((dataObserver == nullptr) || dataObserver->AsObject() == nullptr) { + return; + } + + auto it = recipientMap_.find(dataObserver->AsObject()); + if (it != recipientMap_.end()) { + it->first->RemoveDeathRecipient(it->second); + recipientMap_.erase(it); + return; + } +} + +void DataObsMgrInner::OnCallBackDied(const wptr &remote) +{ + auto object = remote.promote(); + if (object == nullptr) { + return; + } + + if (handler_) { + auto task = [object, dataObsMgrInner = shared_from_this()]() { + dataObsMgrInner->HandleCallBackDiedTask(object); + }; + handler_->PostTask(task); + } +} + +void DataObsMgrInner::HandleCallBackDiedTask(const sptr &dataObserver) +{ + HILOG_INFO("%{public}s,called", __func__); + std::lock_guard lock_l(innerMutex_); + + if (dataObserver == nullptr) { + return; + } + + sptr object = iface_cast(dataObserver); + + RemoveObsFromMap(object); +} + +void DataObsMgrInner::RemoveObsFromMap(const sptr &dataObserver) +{ + for (auto &obsCallback : obsmap_) { + auto &obsList = obsCallback.second; + auto obs = std::find(obsList.begin(), obsList.end(), dataObserver); + if (obs != obsList.end()) { + obsList.remove(dataObserver); + if (obsList.empty()) { + HILOG_INFO("%{public}s: remove obsList from map ", __func__); + obsmap_.erase(obsCallback.first); + } + } + } + RemoveObsDeathRecipient(dataObserver); +} + +bool DataObsMgrInner::ObsExistInMap(const sptr &dataObserver) +{ + for (auto &obsCallback : obsmap_) { + auto &obsList = obsCallback.second; + auto obs = std::find(obsList.begin(), obsList.end(), dataObserver); + if (obs != obsList.end()) { + return true; + } + } + return false; +} + +} // namespace AAFwk +} // namespace OHOS diff --git a/tools/services/dataobsmgr/src/dataobs_mgr_proxy.cpp b/tools/services/dataobsmgr/src/dataobs_mgr_proxy.cpp new file mode 100644 index 00000000000..3fec040235a --- /dev/null +++ b/tools/services/dataobsmgr/src/dataobs_mgr_proxy.cpp @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "dataobs_mgr_proxy.h" + +#include "errors.h" +#include "string_ex.h" + +#include "data_ability_observer_proxy.h" +#include "data_ability_observer_stub.h" +#include "dataobs_mgr_errors.h" + +namespace OHOS { +namespace AAFwk { + +bool DataObsManagerProxy::WriteInterfaceToken(MessageParcel &data) +{ + if (!data.WriteInterfaceToken(DataObsManagerProxy::GetDescriptor())) { + HILOG_ERROR("write interface token failed"); + return false; + } + return true; +} + +int DataObsManagerProxy::RegisterObserver(const Uri &uri, const sptr &dataObserver) +{ + int error; + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!WriteInterfaceToken(data)) { + return DATAOBS_PROXY_INNER_ERR; + } + if (!data.WriteParcelable(&uri)) { + HILOG_ERROR("register observer fail, uri error"); + return ERR_INVALID_VALUE; + } + if (dataObserver == nullptr) { + HILOG_ERROR("register observer fail, dataObserver is nullptr"); + return ERR_INVALID_VALUE; + } + + if (!data.WriteParcelable(dataObserver->AsObject())) { + HILOG_ERROR("register observer fail, dataObserver error"); + return ERR_INVALID_VALUE; + } + + error = Remote()->SendRequest(IDataObsMgr::REGISTER_OBSERVER, data, reply, option); + if (error != NO_ERROR) { + HILOG_ERROR("register observer fail, error: %d", error); + return error; + } + return reply.ReadInt32(); +} + +int DataObsManagerProxy::UnregisterObserver(const Uri &uri, const sptr &dataObserver) +{ + int error; + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!WriteInterfaceToken(data)) { + return DATAOBS_PROXY_INNER_ERR; + } + if (!data.WriteParcelable(&uri)) { + HILOG_ERROR("unregister observer fail, uri error"); + return ERR_INVALID_VALUE; + } + if (dataObserver == nullptr) { + HILOG_ERROR("unregister observer fail, dataObserver is nullptr"); + return ERR_INVALID_VALUE; + } + + if (!data.WriteParcelable(dataObserver->AsObject())) { + HILOG_ERROR("unregister observer fail, dataObserver error"); + return ERR_INVALID_VALUE; + } + + error = Remote()->SendRequest(IDataObsMgr::UNREGISTER_OBSERVER, data, reply, option); + if (error != NO_ERROR) { + HILOG_ERROR("unregister observer fail, error: %d", error); + return error; + } + return reply.ReadInt32(); +} + +int DataObsManagerProxy::NotifyChange(const Uri &uri) +{ + int error; + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!WriteInterfaceToken(data)) { + return DATAOBS_PROXY_INNER_ERR; + } + if (!data.WriteParcelable(&uri)) { + HILOG_ERROR("notifyChange fail, uri error"); + return ERR_INVALID_VALUE; + } + + error = Remote()->SendRequest(IDataObsMgr::NOTIFY_CHANGE, data, reply, option); + if (error != NO_ERROR) { + HILOG_ERROR("notifyChange fail, error: %d", error); + return error; + } + return reply.ReadInt32(); +} + +} // namespace AAFwk +} // namespace OHOS diff --git a/tools/services/dataobsmgr/src/dataobs_mgr_service.cpp b/tools/services/dataobsmgr/src/dataobs_mgr_service.cpp new file mode 100644 index 00000000000..44295c8de81 --- /dev/null +++ b/tools/services/dataobsmgr/src/dataobs_mgr_service.cpp @@ -0,0 +1,213 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "dataobs_mgr_service.h" + +#include +#include +#include +#include +#include "string_ex.h" + +#include "dataobs_mgr_errors.h" +#include "hilog_wrapper.h" +#include "if_system_ability_manager.h" +#include "ipc_skeleton.h" +// #include "sa_mgr_client.h" +#include "system_ability_definition.h" + +namespace OHOS { +namespace AAFwk { +const bool REGISTER_RESULT = + SystemAbility::MakeAndRegisterAbility(DelayedSingleton::GetInstance().get()); + +DataObsMgrService::DataObsMgrService() + : SystemAbility(DATAOBS_MGR_SERVICE_SA_ID, true), + eventLoop_(nullptr), + handler_(nullptr), + state_(DataObsServiceRunningState::STATE_NOT_START) +{ + dataObsMgrInner_ = std::make_shared(); +} + +DataObsMgrService::~DataObsMgrService() +{} + +void DataObsMgrService::OnStart() +{ + if (state_ == DataObsServiceRunningState::STATE_RUNNING) { + HILOG_INFO("Dataobs Manager Service has already started."); + return; + } + HILOG_INFO("Dataobs Manager Service started."); + if (!Init()) { + HILOG_ERROR("failed to init service."); + return; + } + state_ = DataObsServiceRunningState::STATE_RUNNING; + eventLoop_->Run(); + /* Publish service maybe failed, so we need call this function at the last, + * so it can't affect the TDD test program */ + bool ret = Publish(DelayedSingleton::GetInstance().get()); + if (!ret) { + HILOG_ERROR("DataObsMgrService::Init Publish failed!"); + return; + } + + HILOG_INFO("Ability Manager Service start success."); +} + +bool DataObsMgrService::Init() +{ + eventLoop_ = AppExecFwk::EventRunner::Create("DataObsMgrService"); + if (eventLoop_ == nullptr) { + return false; + } + + handler_ = std::make_shared(eventLoop_); + if (handler_ == nullptr) { + return false; + } + + HILOG_INFO("init success"); + return true; +} + +void DataObsMgrService::OnStop() +{ + HILOG_INFO("stop service"); + eventLoop_.reset(); + handler_.reset(); + state_ = DataObsServiceRunningState::STATE_NOT_START; +} + +DataObsServiceRunningState DataObsMgrService::QueryServiceState() const +{ + return state_; +} + +int DataObsMgrService::RegisterObserver(const Uri &uri, const sptr &dataObserver) +{ + HILOG_INFO("DataObsMgrService::RegisterObserver called start"); + if (dataObserver == nullptr) { + HILOG_ERROR("DataObsMgrService::RegisterObserver failed!. dataObserver is nullptr"); + return DATA_OBSERVER_IS_NULL; + } + + if (handler_ == nullptr) { + HILOG_ERROR("DataObsMgrService::RegisterObserver failed!. handler is nullptr"); + return DATAOBS_SERVICE_HANDLER_IS_NULL; + } + + if (dataObsMgrInner_ == nullptr) { + HILOG_ERROR("DataObsMgrService::RegisterObserver failed!. dataObsMgrInner_ is nullptr"); + return DATAOBS_SERVICE_INNER_IS_NULL; + } + + if (dataObsMgrInner_->CheckNeedLimmit()) { + return DATAOBS_SERVICE_TASK_LIMMIT; + } + + if (dataObsMgrInner_->CheckRegisteFull(uri)) { + return DATAOBS_SERVICE_OBS_LIMMIT; + } + + std::function registerObserverFunc = + std::bind(&DataObsMgrInner::HandleRegisterObserver, dataObsMgrInner_, uri, dataObserver); + + dataObsMgrInner_->AtomicAddTaskCount(); + bool ret = handler_->PostTask(registerObserverFunc); + if (!ret) { + dataObsMgrInner_->AtomicSubTaskCount(); + HILOG_ERROR("DataObsMgrService::RegisterObserver PostTask error"); + return DATAOBS_SERVICE_POST_TASK_FAILED; + } + HILOG_INFO("DataObsMgrService::RegisterObserver called end"); + return NO_ERROR; +} + +int DataObsMgrService::UnregisterObserver(const Uri &uri, const sptr &dataObserver) +{ + HILOG_INFO("DataObsMgrService::UnregisterObserver called start"); + if (dataObserver == nullptr) { + HILOG_ERROR("DataObsMgrService::UnregisterObserver failed!. dataObserver is nullptr"); + return DATA_OBSERVER_IS_NULL; + } + + if (handler_ == nullptr) { + HILOG_ERROR("DataObsMgrService::UnregisterObserver failed!. handler is nullptr"); + return DATAOBS_SERVICE_HANDLER_IS_NULL; + } + + if (dataObsMgrInner_ == nullptr) { + HILOG_ERROR("DataObsMgrService::UnregisterObserver failed!. dataObsMgrInner_ is nullptr"); + return DATAOBS_SERVICE_INNER_IS_NULL; + } + + if (dataObsMgrInner_->CheckNeedLimmit()) { + return DATAOBS_SERVICE_TASK_LIMMIT; + } + + std::function unregisterObserverFunc = + std::bind(&DataObsMgrInner::HandleUnregisterObserver, dataObsMgrInner_, uri, dataObserver); + + dataObsMgrInner_->AtomicAddTaskCount(); + bool ret = handler_->PostTask(unregisterObserverFunc); + if (!ret) { + dataObsMgrInner_->AtomicSubTaskCount(); + HILOG_ERROR("DataObsMgrService::UnregisterObserver PostTask error"); + return DATAOBS_SERVICE_POST_TASK_FAILED; + } + HILOG_INFO("DataObsMgrService::UnregisterObserver called end"); + return NO_ERROR; +} + +int DataObsMgrService::NotifyChange(const Uri &uri) +{ + HILOG_INFO("DataObsMgrService::NotifyChange called start"); + if (handler_ == nullptr) { + HILOG_ERROR("DataObsMgrService::NotifyChange failed!. handler is nullptr"); + return DATAOBS_SERVICE_HANDLER_IS_NULL; + } + + if (dataObsMgrInner_ == nullptr) { + HILOG_ERROR("DataObsMgrService::NotifyChange failed!. dataObsMgrInner_ is nullptr"); + return DATAOBS_SERVICE_INNER_IS_NULL; + } + + if (dataObsMgrInner_->CheckNeedLimmit()) { + return DATAOBS_SERVICE_TASK_LIMMIT; + } + + std::function notifyChangeFunc = std::bind(&DataObsMgrInner::HandleNotifyChange, dataObsMgrInner_, uri); + + dataObsMgrInner_->AtomicAddTaskCount(); + bool ret = handler_->PostTask(notifyChangeFunc); + if (!ret) { + dataObsMgrInner_->AtomicSubTaskCount(); + HILOG_ERROR("DataObsMgrService::NotifyChange PostTask error"); + return DATAOBS_SERVICE_POST_TASK_FAILED; + } + return NO_ERROR; + HILOG_INFO("DataObsMgrService::NotifyChange called end"); +} + +std::shared_ptr DataObsMgrService::GetEventHandler() +{ + return handler_; +} + +} // namespace AAFwk +} // namespace OHOS diff --git a/tools/services/dataobsmgr/src/dataobs_mgr_stub.cpp b/tools/services/dataobsmgr/src/dataobs_mgr_stub.cpp new file mode 100644 index 00000000000..3c1e8ba343f --- /dev/null +++ b/tools/services/dataobsmgr/src/dataobs_mgr_stub.cpp @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "dataobs_mgr_stub.h" + +#include "errors.h" +#include "string_ex.h" + +#include "data_ability_observer_proxy.h" +#include "data_ability_observer_stub.h" +#include "dataobs_mgr_errors.h" + +namespace OHOS { +namespace AAFwk { +using Uri = OHOS::Uri; +DataObsManagerStub::DataObsManagerStub() +{ + requestFuncMap_[REGISTER_OBSERVER] = &DataObsManagerStub::RegisterObserverInner; + requestFuncMap_[UNREGISTER_OBSERVER] = &DataObsManagerStub::UnregisterObserverInner; + requestFuncMap_[NOTIFY_CHANGE] = &DataObsManagerStub::NotifyChangeInner; +} + +DataObsManagerStub::~DataObsManagerStub() +{ + requestFuncMap_.clear(); +} + +int DataObsManagerStub::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) +{ + HILOG_DEBUG("DataObsManagerStub::OnRemoteRequest, cmd = %d, flags= %d", code, option.GetFlags()); + std::u16string descriptor = DataObsManagerStub::GetDescriptor(); + std::u16string remoteDescriptor = data.ReadInterfaceToken(); + if (descriptor != remoteDescriptor) { + HILOG_INFO("local descriptor is not equal to remote"); + return ERR_INVALID_STATE; + } + + auto itFunc = requestFuncMap_.find(code); + if (itFunc != requestFuncMap_.end()) { + auto requestFunc = itFunc->second; + if (requestFunc != nullptr) { + return (this->*requestFunc)(data, reply); + } + } + HILOG_WARN("DataObsManagerStub::OnRemoteRequest, default case, need check."); + return IPCObjectStub::OnRemoteRequest(code, data, reply, option); +} + +int DataObsManagerStub::RegisterObserverInner(MessageParcel &data, MessageParcel &reply) +{ + Uri *uri = data.ReadParcelable(); + if (uri == nullptr) { + HILOG_ERROR("DataObsManagerStub: uri is nullptr"); + return ERR_INVALID_VALUE; + } + + auto observer = iface_cast(data.ReadParcelable()); + int32_t result = RegisterObserver(*uri, observer); + reply.WriteInt32(result); + if (uri != nullptr) { + delete uri; + } + return NO_ERROR; +} + +int DataObsManagerStub::UnregisterObserverInner(MessageParcel &data, MessageParcel &reply) +{ + Uri *uri = data.ReadParcelable(); + if (uri == nullptr) { + HILOG_ERROR("DataObsManagerStub: uri is nullptr"); + return ERR_INVALID_VALUE; + } + + auto observer = iface_cast(data.ReadParcelable()); + int32_t result = UnregisterObserver(*uri, observer); + reply.WriteInt32(result); + if (uri != nullptr) { + delete uri; + } + return NO_ERROR; +} + +int DataObsManagerStub::NotifyChangeInner(MessageParcel &data, MessageParcel &reply) +{ + Uri *uri = data.ReadParcelable(); + if (uri == nullptr) { + HILOG_ERROR("DataObsManagerStub: uri is nullptr"); + return ERR_INVALID_VALUE; + } + + int32_t result = NotifyChange(*uri); + reply.WriteInt32(result); + if (uri != nullptr) { + delete uri; + } + return NO_ERROR; +} + +} // namespace AAFwk +} // namespace OHOS diff --git a/tools/services/dataobsmgr/test/BUILD.gn b/tools/services/dataobsmgr/test/BUILD.gn new file mode 100644 index 00000000000..39003184c49 --- /dev/null +++ b/tools/services/dataobsmgr/test/BUILD.gn @@ -0,0 +1,26 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +group("unittest") { + testonly = true + + deps = [ + "unittest/phone/data_ability_observer_proxy_test:unittest", + "unittest/phone/data_ability_observer_stub_test:unittest", + "unittest/phone/dataobs_mgr_client_test:unittest", + "unittest/phone/dataobs_mgr_inner_test:unittest", + "unittest/phone/dataobs_mgr_proxy_test:unittest", + "unittest/phone/dataobs_mgr_service_test:unittest", + "unittest/phone/dataobs_mgr_stub_test:unittest", + ] +} diff --git a/tools/services/dataobsmgr/test/mock/libs/system_ability_mock/system_ability.h b/tools/services/dataobsmgr/test/mock/libs/system_ability_mock/system_ability.h new file mode 100644 index 00000000000..517061668ae --- /dev/null +++ b/tools/services/dataobsmgr/test/mock/libs/system_ability_mock/system_ability.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_AAFWK_SERVICES_TEST_MOCK_SYSTEM_ABILITY_H +#define FOUNDATION_AAFWK_SERVICES_TEST_MOCK_SYSTEM_ABILITY_H + +#include "hilog/log.h" +#include "iremote_object.h" + +namespace OHOS { + +#define REGISTER_SYSTEM_ABILITY_BY_ID(a, b, c) +#define REGISTER_SYSTEM_ABILITY(abilityClassName, abilityId, runOnCreate) +#define DECLEAR_SYSTEM_ABILITY(className) + +static constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, 0xD001100, "MockSystemAbility"}; + +class SystemAbility { +public: + static bool MakeAndRegisterAbility(SystemAbility *) + { + return true; + } + +protected: + virtual void OnStart() + { + HiviewDFX::HiLog::Debug(LABEL, "Mock SystemAbility OnStart called"); + } + + virtual void OnStop() + { + HiviewDFX::HiLog::Debug(LABEL, "Mock SystemAbility OnStop called"); + } + + bool Publish(sptr systemAbility) + { + HiviewDFX::HiLog::Debug(LABEL, "Mock SystemAbility Publish called"); + systemAbility.ForceSetRefPtr(nullptr); + // For test just mock to return true + return true; + } + + SystemAbility(bool runOnCreate = false) + { + HiviewDFX::HiLog::Debug(LABEL, "Mock SystemAbility default Creator called %d", runOnCreate); + } + + SystemAbility(const int32_t serviceId, bool runOnCreate = false) + { + HiviewDFX::HiLog::Debug(LABEL, "Mock SystemAbility Creator called %d", runOnCreate); + } + + virtual ~SystemAbility() + { + HiviewDFX::HiLog::Debug(LABEL, "Mock SystemAbility Destructor called"); + } +}; + +} // namespace OHOS +#endif // FOUNDATION_AAFWK_SERVICES_TEST_MOCK_SYSTEM_ABILITY_H diff --git a/tools/services/dataobsmgr/test/unittest/phone/data_ability_observer_proxy_test/BUILD.gn b/tools/services/dataobsmgr/test/unittest/phone/data_ability_observer_proxy_test/BUILD.gn new file mode 100644 index 00000000000..77f3aee3d7a --- /dev/null +++ b/tools/services/dataobsmgr/test/unittest/phone/data_ability_observer_proxy_test/BUILD.gn @@ -0,0 +1,53 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/test.gni") +import("//foundation/aafwk/standard/aafwk.gni") + +module_output_path = "aafwk_standard/dataobsmgr" + +ohos_unittest("data_ability_observer_proxy_test") { + module_out_path = module_output_path + + include_dirs = [] + + sources = [ "data_ability_observer_proxy_test.cpp" ] + + configs = [ "${services_path}/dataobsmgr:dataobsms_config" ] + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + deps = [ + "${innerkits_path}/want:want", + "//foundation/aafwk/standard/interfaces/innerkits/dataobs_manager:dataobs_manager", + "//foundation/aafwk/standard/services/dataobsmgr:dataobsms", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//third_party/googletest:gmock_main", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] +} + +group("unittest") { + testonly = true + + deps = [ ":data_ability_observer_proxy_test" ] +} diff --git a/tools/services/dataobsmgr/test/unittest/phone/data_ability_observer_proxy_test/data_ability_observer_proxy_test.cpp b/tools/services/dataobsmgr/test/unittest/phone/data_ability_observer_proxy_test/data_ability_observer_proxy_test.cpp new file mode 100644 index 00000000000..49d76cbcd57 --- /dev/null +++ b/tools/services/dataobsmgr/test/unittest/phone/data_ability_observer_proxy_test/data_ability_observer_proxy_test.cpp @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include +#define private public +#include "mock_data_obs_manager_onchange_callback.h" +#include "data_ability_observer_proxy.h" + +using namespace testing::ext; +using namespace testing; +namespace OHOS { +namespace AAFwk { +class DataAbilityObserverProxyTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + std::shared_ptr proxy_ = nullptr; +}; + +void DataAbilityObserverProxyTest::SetUpTestCase(void) +{} +void DataAbilityObserverProxyTest::TearDownTestCase(void) +{} +void DataAbilityObserverProxyTest::SetUp() +{} +void DataAbilityObserverProxyTest::TearDown() +{} + +/* + * Feature: DataAbilityObserverProxy. + * Function: DataObsManagerProxy::OnChange is called. + * SubFunction: NA. + * FunctionPoints: NA. + * EnvConditions: NA. + * CaseDescription: NA. + */ +HWTEST_F(DataAbilityObserverProxyTest, DataAbilityObserverProxy_OnChangeInner_001, TestSize.Level1) +{ + // 1.stub define + sptr mockDataAbilityObserverStub(new MockDataObsManagerOnChangeCallBack()); + + // 2.obsver1 define + sptr proxy(new DataAbilityObserverProxy(mockDataAbilityObserverStub)); + + EXPECT_CALL(*mockDataAbilityObserverStub, OnChange()).Times(1); + + if (proxy != nullptr) { + proxy->OnChange(); + } +} + +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/dataobsmgr/test/unittest/phone/data_ability_observer_proxy_test/mock_data_obs_manager_onchange_callback.h b/tools/services/dataobsmgr/test/unittest/phone/data_ability_observer_proxy_test/mock_data_obs_manager_onchange_callback.h new file mode 100644 index 00000000000..132ff49e788 --- /dev/null +++ b/tools/services/dataobsmgr/test/unittest/phone/data_ability_observer_proxy_test/mock_data_obs_manager_onchange_callback.h @@ -0,0 +1,54 @@ + +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MOCK_FOUNDATION_AAFWK_MOCK_DATA_OBS_MANAGER_ONCHANGE_CALLBACK_STUB_H +#define MOCK_FOUNDATION_AAFWK_MOCK_DATA_OBS_MANAGER_ONCHANGE_CALLBACK_STUB_H + +#include +#include +#include "data_ability_observer_stub.h" +#include "semaphore_ex.h" + +namespace OHOS { +namespace AAFwk { +class MockDataObsManagerOnChangeCallBack : public DataAbilityObserverStub { +public: + MOCK_METHOD0(OnChange, void()); + + void Wait() + { + sem_.Wait(); + } + + int Post() + { + sem_.Post(); + return 0; + } + + void PostVoid() + { + sem_.Post(); + } + +private: + Semaphore sem_; +}; + +} // namespace AAFwk +} // namespace OHOS + +#endif // MOCK_FOUNDATION_AAFWK_MOCK_DATA_OBS_MANAGER_ONCHANGE_CALLBACK_STUB_H \ No newline at end of file diff --git a/tools/services/dataobsmgr/test/unittest/phone/data_ability_observer_stub_test/BUILD.gn b/tools/services/dataobsmgr/test/unittest/phone/data_ability_observer_stub_test/BUILD.gn new file mode 100644 index 00000000000..1f51108585e --- /dev/null +++ b/tools/services/dataobsmgr/test/unittest/phone/data_ability_observer_stub_test/BUILD.gn @@ -0,0 +1,53 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/test.gni") +import("//foundation/aafwk/standard/aafwk.gni") + +module_output_path = "aafwk_standard/dataobsmgr" + +ohos_unittest("data_ability_observer_stub_test") { + module_out_path = module_output_path + + include_dirs = [ "//utils/native/base/include" ] + + sources = [ "data_ability_observer_stub_test.cpp" ] + + configs = [ "${services_path}/dataobsmgr:dataobsms_config" ] + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + deps = [ + "${innerkits_path}/want:want", + "//foundation/aafwk/standard/interfaces/innerkits/dataobs_manager:dataobs_manager", + "//foundation/aafwk/standard/services/dataobsmgr:dataobsms", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//third_party/googletest:gmock_main", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] +} + +group("unittest") { + testonly = true + + deps = [ ":data_ability_observer_stub_test" ] +} diff --git a/tools/services/dataobsmgr/test/unittest/phone/data_ability_observer_stub_test/data_ability_observer_stub_test.cpp b/tools/services/dataobsmgr/test/unittest/phone/data_ability_observer_stub_test/data_ability_observer_stub_test.cpp new file mode 100644 index 00000000000..5b2547049f6 --- /dev/null +++ b/tools/services/dataobsmgr/test/unittest/phone/data_ability_observer_stub_test/data_ability_observer_stub_test.cpp @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include +#include "mock_data_obs_manager_onchange_callback.h" +#define private public +#include "data_ability_observer_proxy.h" +#include "dataobs_mgr_interface.h" +#include "string_ex.h" + +using namespace testing::ext; +using namespace testing; + +namespace OHOS { +namespace AAFwk { + +class DataAbilityObserverStubTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void DataAbilityObserverStubTest::SetUpTestCase(void) +{} +void DataAbilityObserverStubTest::TearDownTestCase(void) +{} +void DataAbilityObserverStubTest::SetUp() +{} +void DataAbilityObserverStubTest::TearDown() +{} + +/* + * Feature: DataAbilityObserverStub. + * Function: DataAbilityObserverStub::UnregisterObserverInner is called. + * SubFunction: UnregisterObserverInner. + * FunctionPoints: NA. + * EnvConditions: NA. + * CaseDescription: NA. + */ +HWTEST_F(DataAbilityObserverStubTest, DataAbilityObserverStub_remoteDescriptor_001, TestSize.Level1) +{ + sptr mockDataObsManagerOnChangeStub(new MockDataObsManagerOnChangeCallBack()); + + MessageParcel data; + MessageParcel reply; + MessageOption option; + + data.WriteInterfaceToken(Str8ToStr16(std::string("descrip_test"))); + + EXPECT_CALL(*mockDataObsManagerOnChangeStub, OnChange()).Times(0); + int res = mockDataObsManagerOnChangeStub->OnRemoteRequest( + IDataAbilityObserver::DATA_ABILITY_OBSERVER_CHANGE, data, reply, option); + EXPECT_EQ(res, ERR_INVALID_STATE); +} +/* + * Feature: DataAbilityObserverStub. + * Function: DataAbilityObserverStub::UnregisterObserverInner is called. + * SubFunction: UnregisterObserverInner. + * FunctionPoints: NA. + * EnvConditions: NA. + * CaseDescription: NA. + */ +HWTEST_F(DataAbilityObserverStubTest, DataAbilityObserverStub_OnChange_001, TestSize.Level1) +{ + sptr mockDataObsManagerOnChangeStub(new MockDataObsManagerOnChangeCallBack()); + + MessageParcel data; + MessageParcel reply; + MessageOption option; + + data.WriteInterfaceToken(DataAbilityObserverProxy::GetDescriptor()); + + EXPECT_CALL(*mockDataObsManagerOnChangeStub, OnChange()).Times(1); + + int res = mockDataObsManagerOnChangeStub->OnRemoteRequest( + IDataAbilityObserver::DATA_ABILITY_OBSERVER_CHANGE, data, reply, option); + EXPECT_EQ(res, ERR_OK); +} +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/dataobsmgr/test/unittest/phone/data_ability_observer_stub_test/mock_data_obs_manager_onchange_callback.h b/tools/services/dataobsmgr/test/unittest/phone/data_ability_observer_stub_test/mock_data_obs_manager_onchange_callback.h new file mode 100644 index 00000000000..132ff49e788 --- /dev/null +++ b/tools/services/dataobsmgr/test/unittest/phone/data_ability_observer_stub_test/mock_data_obs_manager_onchange_callback.h @@ -0,0 +1,54 @@ + +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MOCK_FOUNDATION_AAFWK_MOCK_DATA_OBS_MANAGER_ONCHANGE_CALLBACK_STUB_H +#define MOCK_FOUNDATION_AAFWK_MOCK_DATA_OBS_MANAGER_ONCHANGE_CALLBACK_STUB_H + +#include +#include +#include "data_ability_observer_stub.h" +#include "semaphore_ex.h" + +namespace OHOS { +namespace AAFwk { +class MockDataObsManagerOnChangeCallBack : public DataAbilityObserverStub { +public: + MOCK_METHOD0(OnChange, void()); + + void Wait() + { + sem_.Wait(); + } + + int Post() + { + sem_.Post(); + return 0; + } + + void PostVoid() + { + sem_.Post(); + } + +private: + Semaphore sem_; +}; + +} // namespace AAFwk +} // namespace OHOS + +#endif // MOCK_FOUNDATION_AAFWK_MOCK_DATA_OBS_MANAGER_ONCHANGE_CALLBACK_STUB_H \ No newline at end of file diff --git a/tools/services/dataobsmgr/test/unittest/phone/dataobs_mgr_client_test/BUILD.gn b/tools/services/dataobsmgr/test/unittest/phone/dataobs_mgr_client_test/BUILD.gn new file mode 100644 index 00000000000..c6d47bf97e6 --- /dev/null +++ b/tools/services/dataobsmgr/test/unittest/phone/dataobs_mgr_client_test/BUILD.gn @@ -0,0 +1,57 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/test.gni") +import("//foundation/aafwk/standard/aafwk.gni") + +module_output_path = "aafwk_standard/dataobsmgr" + +ohos_unittest("dataobs_mgr_client_test") { + module_out_path = module_output_path + + include_dirs = [ + "//utils/native/base/include", + "//foundation/aafwk/standard/services/dataobsmgr/include", + "//foundation/distributedschedule/safwk/services/safwk/include", + ] + + sources = [ "dataobs_mgr_client_test.cpp" ] + + configs = [ "${services_path}/dataobsmgr:dataobsms_config" ] + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + deps = [ + "${innerkits_path}/want:want", + "//foundation/aafwk/standard/interfaces/innerkits/dataobs_manager:dataobs_manager", + "//foundation/aafwk/standard/services/dataobsmgr:dataobsms", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//third_party/googletest:gmock_main", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] +} + +group("unittest") { + testonly = true + + deps = [ ":dataobs_mgr_client_test" ] +} diff --git a/tools/services/dataobsmgr/test/unittest/phone/dataobs_mgr_client_test/dataobs_mgr_client_test.cpp b/tools/services/dataobsmgr/test/unittest/phone/dataobs_mgr_client_test/dataobs_mgr_client_test.cpp new file mode 100644 index 00000000000..e9bafc95e52 --- /dev/null +++ b/tools/services/dataobsmgr/test/unittest/phone/dataobs_mgr_client_test/dataobs_mgr_client_test.cpp @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include +#include "mock_dataobs_mgr_client.h" +#include "dataobs_mgr_proxy.h" +#define private public +#include "mock_dataobs_mgr_service.h" +#include "data_ability_observer_proxy.h" +#include "data_ability_observer_stub.h" +#include "mock_data_obs_manager_onchange_callback.h" + +using namespace testing::ext; +using namespace testing; + +namespace OHOS { +namespace AAFwk { + +class DataObsMgrClientTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void DataObsMgrClientTest::SetUpTestCase(void) +{} +void DataObsMgrClientTest::TearDownTestCase(void) +{} +void DataObsMgrClientTest::SetUp() +{} +void DataObsMgrClientTest::TearDown() +{} + +/* + * Feature: DataObsMgrClient. + * Function: The RegisterObserver function of dataobsmgrservice was called. + * SubFunction: DataObsMgrService::RegisterObserver is called. + * FunctionPoints: NA. + * EnvConditions: NA. + * CaseDescription: NA. + */ +HWTEST_F(DataObsMgrClientTest, DataObsMgrClient_RegisterObserver_0100, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "DataObsMgrClientTest_DataObsMgrClient_RegisterObserver_0100 start"; + + sptr callBack(new (std::nothrow) MockDataObsManagerOnChangeCallBack()); + sptr dataAbilityObserverProxy(new (std::nothrow) DataAbilityObserverProxy(callBack)); + + MockDataObsMgrClient::GetInstance(); + + EXPECT_CALL(*((MockDataObsMgrService *)(DataObsMgrClient::GetInstance()->remoteObject_).GetRefPtr()), + RegisterObserverCall(testing::_, testing::_)) + .Times(1); + Uri uri("dataability://device_id/com.domainname.dataability.persondata/person/25"); + MockDataObsMgrClient::GetInstance()->RegisterObserver(uri, dataAbilityObserverProxy); + + testing::Mock::AllowLeak(DataObsMgrClient::GetInstance()->remoteObject_); + GTEST_LOG_(INFO) << "DataObsMgrClientTest_DataObsMgrClient_RegisterObserver_0100 end"; +} +/* + * Feature: DataObsMgrClient. + * Function: The unregisterObserve function of dataobsmgrservice was called. + * SubFunction: DataObsMgrService::UnregisterObserve is called. + * FunctionPoints: NA. + * EnvConditions: NA. + * CaseDescription: NA. + */ +HWTEST_F(DataObsMgrClientTest, DataObsMgrClient_UnregisterObserver_0100, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "DataObsMgrClientTest_DataObsMgrClient_UnregisterObserver_0100 start"; + + sptr callBack(new (std::nothrow) MockDataObsManagerOnChangeCallBack()); + + sptr dataAbilityObserverProxy(new (std::nothrow) DataAbilityObserverProxy(callBack)); + + MockDataObsMgrClient::GetInstance(); + + EXPECT_CALL(*((MockDataObsMgrService *)(DataObsMgrClient::GetInstance()->remoteObject_).GetRefPtr()), + UnregisterObserverCall(testing::_, testing::_)) + .Times(1); + + Uri uri("dataability://device_id/com.domainname.dataability.persondata/person/25"); + MockDataObsMgrClient::GetInstance()->UnregisterObserver(uri, dataAbilityObserverProxy); + + testing::Mock::AllowLeak(DataObsMgrClient::GetInstance()->remoteObject_); + GTEST_LOG_(INFO) << "DataObsMgrClientTest_DataObsMgrClient_UnregisterObserver_0100 end"; +} + +/* + * Feature: DataObsMgrClient. + * Function: The NotifyChange function of dataobsmgrservice was called. + * SubFunction: DataObsMgrService::NotifyChange is called. + * FunctionPoints: NA. + * EnvConditions: NA. + * CaseDescription: NA. + */ +HWTEST_F(DataObsMgrClientTest, DataObsMgrClient_NotifyChange_0100, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "DataObsMgrClientTest_DataObsMgrClient_NotifyChange_0100 start"; + + MockDataObsMgrClient::GetInstance()->Connect(); + + EXPECT_CALL(*((MockDataObsMgrService *)(DataObsMgrClient::GetInstance()->remoteObject_).GetRefPtr()), + NotifyChangeCall(testing::_)) + .Times(1); + + Uri uri("dataability://device_id/com.domainname.dataability.persondata/person/25"); + MockDataObsMgrClient::GetInstance()->NotifyChange(uri); + + testing::Mock::AllowLeak(DataObsMgrClient::GetInstance()->remoteObject_); + GTEST_LOG_(INFO) << "DataObsMgrClientTest_DataObsMgrClient_NotifyChange_0100 end"; +} + +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/dataobsmgr/test/unittest/phone/dataobs_mgr_client_test/mock_data_obs_manager_onchange_callback.h b/tools/services/dataobsmgr/test/unittest/phone/dataobs_mgr_client_test/mock_data_obs_manager_onchange_callback.h new file mode 100644 index 00000000000..132ff49e788 --- /dev/null +++ b/tools/services/dataobsmgr/test/unittest/phone/dataobs_mgr_client_test/mock_data_obs_manager_onchange_callback.h @@ -0,0 +1,54 @@ + +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MOCK_FOUNDATION_AAFWK_MOCK_DATA_OBS_MANAGER_ONCHANGE_CALLBACK_STUB_H +#define MOCK_FOUNDATION_AAFWK_MOCK_DATA_OBS_MANAGER_ONCHANGE_CALLBACK_STUB_H + +#include +#include +#include "data_ability_observer_stub.h" +#include "semaphore_ex.h" + +namespace OHOS { +namespace AAFwk { +class MockDataObsManagerOnChangeCallBack : public DataAbilityObserverStub { +public: + MOCK_METHOD0(OnChange, void()); + + void Wait() + { + sem_.Wait(); + } + + int Post() + { + sem_.Post(); + return 0; + } + + void PostVoid() + { + sem_.Post(); + } + +private: + Semaphore sem_; +}; + +} // namespace AAFwk +} // namespace OHOS + +#endif // MOCK_FOUNDATION_AAFWK_MOCK_DATA_OBS_MANAGER_ONCHANGE_CALLBACK_STUB_H \ No newline at end of file diff --git a/tools/services/dataobsmgr/test/unittest/phone/dataobs_mgr_client_test/mock_dataobs_mgr_client.h b/tools/services/dataobsmgr/test/unittest/phone/dataobs_mgr_client_test/mock_dataobs_mgr_client.h new file mode 100644 index 00000000000..8d0b9dfd45e --- /dev/null +++ b/tools/services/dataobsmgr/test/unittest/phone/dataobs_mgr_client_test/mock_dataobs_mgr_client.h @@ -0,0 +1,69 @@ + +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MOCK_FOUNDATION_AAFWK_MOCK_DATAOBS_MGR_CLIENT_H +#define MOCK_FOUNDATION_AAFWK_MOCK_DATAOBS_MGR_CLIENT_H + +#include +#include +#include +#define protected public +#define private public +#include "system_ability.h" +#include "dataobs_mgr_service.h" +#include "semaphore_ex.h" +#include "mock_dataobs_mgr_service.h" +#include "dataobs_mgr_client.h" +#include "mock_dataobs_mgr_service.h" + +namespace OHOS { +namespace AAFwk { +class MockDataObsMgrClient : public DataObsMgrClient { +public: + static std::shared_ptr GetInstance(); + ErrCode Connect(); +}; + +std::shared_ptr MockDataObsMgrClient::GetInstance() +{ + if (instance_ == nullptr) { + if (instance_ == nullptr) { + std::shared_ptr client {new (std::nothrow) MockDataObsMgrClient()}; + if (client != nullptr) { + ((MockDataObsMgrClient *)client.get())->Connect(); + } + instance_ = client; + } + } + return instance_; +} + +ErrCode MockDataObsMgrClient::Connect() +{ + if (remoteObject_ == nullptr) { + sptr mockDataObsMgrService(new (std::nothrow) MockDataObsMgrService()); + if (mockDataObsMgrService != nullptr) { + ((MockDataObsMgrService *)mockDataObsMgrService.GetRefPtr())->OnStart(); + } + + remoteObject_ = mockDataObsMgrService; + } + return ERR_OK; +} + +} // namespace AAFwk +} // namespace OHOS +#endif // MOCK_FOUNDATION_AAFWK_MOCK_DATAOBS_MGR_CLIENT_H \ No newline at end of file diff --git a/tools/services/dataobsmgr/test/unittest/phone/dataobs_mgr_client_test/mock_dataobs_mgr_service.h b/tools/services/dataobsmgr/test/unittest/phone/dataobs_mgr_client_test/mock_dataobs_mgr_service.h new file mode 100644 index 00000000000..9701d53e0a0 --- /dev/null +++ b/tools/services/dataobsmgr/test/unittest/phone/dataobs_mgr_client_test/mock_dataobs_mgr_service.h @@ -0,0 +1,111 @@ + +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MOCK_FOUNDATION_AAFWK_MOCK_DATAOBS_MGR_SERVICE_H +#define MOCK_FOUNDATION_AAFWK_MOCK_DATAOBS_MGR_SERVICE_H + +#include +#define protected public +#define private public +#include "dataobs_mgr_stub.h" + +namespace OHOS { +namespace AAFwk { + +class MockDataObsMgrService : public DataObsManagerStub { +public: + MockDataObsMgrService() = default; + virtual ~MockDataObsMgrService() = default; + + MOCK_METHOD2(RegisterObserverCall, int(const Uri &, const sptr &)); + MOCK_METHOD2(UnregisterObserverCall, int(const Uri &, const sptr &)); + MOCK_METHOD1(NotifyChangeCall, int(const Uri &)); + + int RegisterObserver(const Uri &uri, const sptr &dataObserver) + { + RegisterObserverCall(uri, dataObserver); + return 1; + } + int UnregisterObserver(const Uri &uri, const sptr &dataObserver) + { + UnregisterObserverCall(uri, dataObserver); + return 1; + } + int NotifyChange(const Uri &uri) + { + NotifyChangeCall(uri); + return 1; + } + + void OnStart() + { + if (state_ == DataObsServiceRunningState::STATE_RUNNING) { + HILOG_INFO("Dataobs Manager Service has already started."); + return; + } + HILOG_INFO("Dataobs Manager Service started."); + if (!Init()) { + HILOG_ERROR("failed to init service."); + return; + } + state_ = DataObsServiceRunningState::STATE_RUNNING; + eventLoop_->Run(); + + HILOG_INFO("Ability Manager Service start success."); + } + void OnStop() + { + HILOG_INFO("stop service"); + eventLoop_.reset(); + handler_.reset(); + state_ = DataObsServiceRunningState::STATE_NOT_START; + } + /** + * GetEventHandler, get the dataobs manager service's handler. + * @return Returns EventHandler ptr. + */ + std::shared_ptr GetEventHandler() + { + return handler_; + } + +private: + bool Init() + { + eventLoop_ = AppExecFwk::EventRunner::Create("DataObsMgrService"); + if (eventLoop_ == nullptr) { + return false; + } + + handler_ = std::make_shared(eventLoop_); + if (handler_ == nullptr) { + return false; + } + + HILOG_INFO("init success"); + return true; + } + + std::shared_ptr eventLoop_; + std::shared_ptr handler_; + DataObsServiceRunningState state_; + std::shared_ptr dataObsMgrInner_; + const int taskMax_ = 50; +}; + +} // namespace AAFwk +} // namespace OHOS +#endif // MOCK_FOUNDATION_AAFWK_MOCK_DATAOBS_MGR_SERVICE_H diff --git a/tools/services/dataobsmgr/test/unittest/phone/dataobs_mgr_inner_test/BUILD.gn b/tools/services/dataobsmgr/test/unittest/phone/dataobs_mgr_inner_test/BUILD.gn new file mode 100644 index 00000000000..e6a4317cc8e --- /dev/null +++ b/tools/services/dataobsmgr/test/unittest/phone/dataobs_mgr_inner_test/BUILD.gn @@ -0,0 +1,53 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/test.gni") +import("//foundation/aafwk/standard/aafwk.gni") + +module_output_path = "aafwk_standard/dataobsmgr" + +ohos_unittest("dataobs_mgr_inner_test") { + module_out_path = module_output_path + + include_dirs = [ "//utils/native/base/include" ] + + sources = [ "dataobs_mgr_inner_test.cpp" ] + + configs = [ "${services_path}/dataobsmgr:dataobsms_config" ] + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + deps = [ + "${innerkits_path}/want:want", + "//foundation/aafwk/standard/interfaces/innerkits/dataobs_manager:dataobs_manager", + "//foundation/aafwk/standard/services/dataobsmgr:dataobsms", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//third_party/googletest:gmock_main", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] +} + +group("unittest") { + testonly = true + + deps = [ ":dataobs_mgr_inner_test" ] +} diff --git a/tools/services/dataobsmgr/test/unittest/phone/dataobs_mgr_inner_test/dataobs_mgr_inner_test.cpp b/tools/services/dataobsmgr/test/unittest/phone/dataobs_mgr_inner_test/dataobs_mgr_inner_test.cpp new file mode 100644 index 00000000000..ffd33530c64 --- /dev/null +++ b/tools/services/dataobsmgr/test/unittest/phone/dataobs_mgr_inner_test/dataobs_mgr_inner_test.cpp @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include +#include +#include +#include "uri.h" +#define private public +#include "data_ability_observer_proxy.h" +#include "dataobs_mgr_inner.h" +#include "mock_data_ability_observer_stub.h" + +using namespace OHOS; +using namespace testing::ext; +using namespace testing; + +using Uri = OHOS::Uri; +using ObsListType = OHOS::AAFwk::DataObsMgrInner::ObsListType; +using ObsRecipientMapType = OHOS::AAFwk::DataObsMgrInner::ObsRecipientMapType; + +namespace OHOS { +namespace AAFwk { + +class DataObsMgrInnerTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + std::shared_ptr dataObsMgrInner_ = nullptr; +}; +void DataObsMgrInnerTest::SetUpTestCase(void) +{} +void DataObsMgrInnerTest::TearDownTestCase(void) +{} +void DataObsMgrInnerTest::SetUp() +{ + std::shared_ptr dataObsMgrInner_ = std::make_shared(); +} +void DataObsMgrInnerTest::TearDown() +{} + +/* + * Feature: DataObsMgrInner + * Function: Register and unregister function test + * SubFunction: HandleRegisterObserver/HandleRegisterObserver + * FunctionPoints: NA + * EnvConditions: NA + * CaseDescription:NA + */ +HWTEST_F(DataObsMgrInnerTest, DataObsMgrInner_HandleRegisterObserver_0100, TestSize.Level1) +{ + if (dataObsMgrInner_ == nullptr) { + return; + } + + Uri uri("dataability://device_id/com.domainname.dataability.persondata/person/10"); + sptr observer(new (std::nothrow) MockDataAbilityObserverStub()); + + const sptr callback(new (std::nothrow) DataAbilityObserverProxy(observer)); + dataObsMgrInner_->HandleRegisterObserver(uri, callback); + + EXPECT_EQ(dataObsMgrInner_->ObsExistInMap(callback), true); + dataObsMgrInner_->HandleUnregisterObserver(uri, callback); + EXPECT_EQ(dataObsMgrInner_->ObsExistInMap(callback), false); +} + +/* + * Feature: DataObsMgrInner + * Function: Register and unregister function test + * SubFunction: OnChange + * FunctionPoints: When the data changes, call the OnChange function of the registered dataabilityobserver + * EnvConditions: NA + * CaseDescription:NA + */ +HWTEST_F(DataObsMgrInnerTest, DataObsMgrInner_HandleNotifyChange_0100, TestSize.Level1) +{ + if (dataObsMgrInner_ == nullptr) { + return; + } + Uri uri("dataability://device_id/com.domainname.dataability.persondata/person/10"); + sptr mockDataAbilityObserverStub(new (std::nothrow) MockDataAbilityObserverStub()); + + EXPECT_CALL(*mockDataAbilityObserverStub, OnChange()).Times(1); + + const sptr callback(new (std::nothrow) DataAbilityObserverProxy(mockDataAbilityObserverStub)); + dataObsMgrInner_->HandleRegisterObserver(uri, callback); + dataObsMgrInner_->HandleNotifyChange(uri); +} + +/* + * Feature: DataObsMgrInner + * Function: GetObsListFromMap/RemoveObsFromMap/ObsExistInMap function test + * SubFunction: NA + * FunctionPoints: NA + * EnvConditions: NA + * CaseDescription:NA + */ +HWTEST_F(DataObsMgrInnerTest, DataObsMgrInner_GetRemoveObsListFromMap_ObsExistInMap_0100, TestSize.Level1) +{ + if (dataObsMgrInner_ == nullptr) { + return; + } + Uri uri("dataability://device_id/com.domainname.dataability.persondata/person/10"); + sptr mockDataAbilityObserverStub(new (std::nothrow) MockDataAbilityObserverStub()); + const sptr callback(new (std::nothrow) DataAbilityObserverProxy(mockDataAbilityObserverStub)); + dataObsMgrInner_->HandleRegisterObserver(uri, callback); + + sptr mockDataAbilityObserverStub2(new (std::nothrow) MockDataAbilityObserverStub()); + const sptr callback2( + new (std::nothrow) DataAbilityObserverProxy(mockDataAbilityObserverStub2)); + + dataObsMgrInner_->HandleRegisterObserver(uri, callback2); + ObsListType obslist; + dataObsMgrInner_->GetObsListFromMap(uri, obslist); + EXPECT_EQ((std::size_t)2, obslist.size()); + EXPECT_EQ(true, dataObsMgrInner_->ObsExistInMap(callback)); + EXPECT_EQ(true, dataObsMgrInner_->ObsExistInMap(callback2)); + + dataObsMgrInner_->RemoveObsFromMap(callback); + EXPECT_EQ(false, dataObsMgrInner_->ObsExistInMap(callback)); + obslist.clear(); + dataObsMgrInner_->GetObsListFromMap(uri, obslist); + EXPECT_EQ((std::size_t)1, obslist.size()); + EXPECT_EQ(false, dataObsMgrInner_->ObsExistInMap(callback)); + + dataObsMgrInner_->RemoveObsFromMap(callback2); + EXPECT_EQ(false, dataObsMgrInner_->ObsExistInMap(callback2)); + obslist.clear(); + dataObsMgrInner_->GetObsListFromMap(uri, obslist); + EXPECT_EQ((std::size_t)0, obslist.size()); + EXPECT_EQ(false, dataObsMgrInner_->ObsExistInMap(callback2)); +} + +/* + * Feature: DataObsMgrInner + * Function: AddObsDeathRecipient/RemoveObsDeathRecipient function test + * SubFunction: NA + * FunctionPoints: NA + * EnvConditions: NA + * CaseDescription:NA + */ +HWTEST_F(DataObsMgrInnerTest, DataObsMgrInner_AddRemove_ObsDeathRecipient_0100, TestSize.Level1) +{ + if (dataObsMgrInner_ == nullptr) { + return; + } + + sptr observer(new (std::nothrow) MockDataAbilityObserverStub()); + sptr callback(new (std::nothrow) DataAbilityObserverProxy(observer)); + dataObsMgrInner_->AddObsDeathRecipient(callback); + + ObsRecipientMapType::const_iterator it; + it = dataObsMgrInner_->recipientMap_.find(observer); + EXPECT_EQ(true, it != dataObsMgrInner_->recipientMap_.end()); + + dataObsMgrInner_->RemoveObsDeathRecipient(callback); + it = dataObsMgrInner_->recipientMap_.find(observer); + EXPECT_EQ(false, it != dataObsMgrInner_->recipientMap_.end()); +} + +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/dataobsmgr/test/unittest/phone/dataobs_mgr_inner_test/mock_data_ability_observer_stub.h b/tools/services/dataobsmgr/test/unittest/phone/dataobs_mgr_inner_test/mock_data_ability_observer_stub.h new file mode 100644 index 00000000000..8fbc68e8e3a --- /dev/null +++ b/tools/services/dataobsmgr/test/unittest/phone/dataobs_mgr_inner_test/mock_data_ability_observer_stub.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MOCK_FOUNDATION_AAAFWK_INTERFACES_INNERKITS_MOCK_DATA_ABILITY_OBSERVER_STUB_CALL_H +#define MOCK_FOUNDATION_AAAFWK_INTERFACES_INNERKITS_MOCK_DATA_ABILITY_OBSERVER_STUB_CALL_H +#include +#include "semaphore_ex.h" +#include "data_ability_observer_stub.h" + +namespace OHOS { +namespace AAFwk { +class MockDataAbilityObserverStub : public DataAbilityObserverStub { +public: + MOCK_METHOD0(OnChange, void()); + + void Wait() + { + sem_.Wait(); + } + + int Post() + { + sem_.Post(); + return 0; + } + + void PostVoid() + { + sem_.Post(); + } + +private: + Semaphore sem_; +}; + +} // namespace AAFwk +} // namespace OHOS + +#endif // MOCK_FOUNDATION_AAAFWK_INTERFACES_INNERKITS_MOCK_DATA_ABILITY_OBSERVER_STUB_CALL_H \ No newline at end of file diff --git a/tools/services/dataobsmgr/test/unittest/phone/dataobs_mgr_proxy_test/BUILD.gn b/tools/services/dataobsmgr/test/unittest/phone/dataobs_mgr_proxy_test/BUILD.gn new file mode 100644 index 00000000000..0c2b2c22e3a --- /dev/null +++ b/tools/services/dataobsmgr/test/unittest/phone/dataobs_mgr_proxy_test/BUILD.gn @@ -0,0 +1,53 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/test.gni") +import("//foundation/aafwk/standard/aafwk.gni") + +module_output_path = "aafwk_standard/dataobsmgr" + +ohos_unittest("dataobs_mgr_proxy_test") { + module_out_path = module_output_path + + include_dirs = [] + + sources = [ "dataobs_mgr_proxy_test.cpp" ] + + configs = [ "${services_path}/dataobsmgr:dataobsms_config" ] + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + deps = [ + "${innerkits_path}/want:want", + "//foundation/aafwk/standard/interfaces/innerkits/dataobs_manager:dataobs_manager", + "//foundation/aafwk/standard/services/dataobsmgr:dataobsms", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//third_party/googletest:gmock_main", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] +} + +group("unittest") { + testonly = true + + deps = [ ":dataobs_mgr_proxy_test" ] +} diff --git a/tools/services/dataobsmgr/test/unittest/phone/dataobs_mgr_proxy_test/dataobs_mgr_proxy_test.cpp b/tools/services/dataobsmgr/test/unittest/phone/dataobs_mgr_proxy_test/dataobs_mgr_proxy_test.cpp new file mode 100644 index 00000000000..6f45574285a --- /dev/null +++ b/tools/services/dataobsmgr/test/unittest/phone/dataobs_mgr_proxy_test/dataobs_mgr_proxy_test.cpp @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include + +#include "gtest/gtest.h" +#include "gmock/gmock.h" + +#include "mock_data_obs_mgr_stub.h" + +#include "dataobs_mgr_proxy.h" + +namespace OHOS { +namespace AAFwk { +using namespace testing::ext; +using ::testing::_; + +class DataObsMgrServiceTest : public testing::Test { +public: + DataObsMgrServiceTest() = default; + virtual ~DataObsMgrServiceTest() = default; + + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; +void DataObsMgrServiceTest::SetUpTestCase(void) +{} +void DataObsMgrServiceTest::TearDownTestCase(void) +{} +void DataObsMgrServiceTest::SetUp() +{} +void DataObsMgrServiceTest::TearDown() +{} + +/* + * Feature: DataObsManagerStub + * Function: RegisterObserver + * SubFunction: NA + * FunctionPoints: DataObsManagerStub RegisterObserver + * EnvConditions: NA + * CaseDescription: Verify that the DataObsManagerStub RegisterObserver is normal. + */ +HWTEST_F(DataObsMgrServiceTest, AaFwk_DataObsMgrServiceTest_RegisterObserver_0100, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataObsMgrServiceTest_RegisterObserver_0100 start"; + const int testVal = static_cast(TEST_RETVAL_ONREMOTEREQUEST); + std::shared_ptr dataobs = std::make_shared(); + std::shared_ptr uri = + std::make_shared("dataability://device_id/com.domainname.dataability.persondata/person/10"); + sptr mockDataobsMgrStub(new (std::nothrow) MockDataObsMgrStub()); + std::shared_ptr dataObsManagerProxy = + std::make_shared(mockDataobsMgrStub); + sptr dataObserver(new (std::nothrow) MockDataAbilityObserverStub()); + + const int retVal = dataObsManagerProxy->RegisterObserver(*uri, dataObserver); + + EXPECT_EQ(testVal, retVal); + + GTEST_LOG_(INFO) << "AaFwk_DataObsMgrServiceTest_RegisterObserver_0100 end"; +} + +/* + * Feature: DataObsManagerStub + * Function: UnregisterObserver + * SubFunction: NA + * FunctionPoints: DataObsManagerStub UnregisterObserver + * EnvConditions: NA + * CaseDescription: Verify that the DataObsManagerStub UnregisterObserver is normal. + */ +HWTEST_F(DataObsMgrServiceTest, AaFwk_DataObsMgrServiceTest_UnregisterObserver_0100, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataObsMgrServiceTest_UnregisterObserver_0100 start"; + const int testVal = static_cast(TEST_RETVAL_ONREMOTEREQUEST); + std::shared_ptr dataobs = std::make_shared(); + std::shared_ptr uri = + std::make_shared("dataability://device_id/com.domainname.dataability.persondata/person/10"); + sptr mockDataobsMgrStub(new (std::nothrow) MockDataObsMgrStub()); + std::shared_ptr dataObsManagerProxy = + std::make_shared(mockDataobsMgrStub); + sptr dataObserver(new (std::nothrow) MockDataAbilityObserverStub()); + + const int retVal = dataObsManagerProxy->UnregisterObserver(*uri, dataObserver); + + EXPECT_EQ(testVal, retVal); + + GTEST_LOG_(INFO) << "AaFwk_DataObsMgrServiceTest_UnregisterObserver_0100 end"; +} + +/* + * Feature: DataObsManagerStub + * Function: NotifyChange + * SubFunction: NA + * FunctionPoints: DataObsManagerStub NotifyChange + * EnvConditions: NA + * CaseDescription: Verify that the DataObsManagerStub NotifyChange is normal. + */ +HWTEST_F(DataObsMgrServiceTest, AaFwk_DataObsMgrServiceTest_NotifyChange_0100, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataObsMgrServiceTest_NotifyChange_0100 start"; + const int testVal = static_cast(TEST_RETVAL_ONREMOTEREQUEST); + std::shared_ptr uri = + std::make_shared("dataability://device_id/com.domainname.dataability.persondata/person/10"); + sptr mockDataobsMgrStub(new (std::nothrow) MockDataObsMgrStub()); + std::shared_ptr dataObsManagerProxy = + std::make_shared(mockDataobsMgrStub); + + const int retVal = dataObsManagerProxy->NotifyChange(*uri); + + EXPECT_EQ(testVal, retVal); + + GTEST_LOG_(INFO) << "AaFwk_DataObsMgrServiceTest_NotifyChange_0100 end"; +} + +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/dataobsmgr/test/unittest/phone/dataobs_mgr_proxy_test/mock_data_obs_mgr_stub.h b/tools/services/dataobsmgr/test/unittest/phone/dataobs_mgr_proxy_test/mock_data_obs_mgr_stub.h new file mode 100644 index 00000000000..889ce8dd1b4 --- /dev/null +++ b/tools/services/dataobsmgr/test/unittest/phone/dataobs_mgr_proxy_test/mock_data_obs_mgr_stub.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MOCK_DATA_OBS_MGR_STUB_H +#define MOCK_DATA_OBS_MGR_STUB_H +#include + +#include "gtest/gtest.h" +#include "gmock/gmock.h" + +#include "dataobs_mgr_stub.h" +#include "data_ability_observer_stub.h" + +#define TEST_RETVAL_ONREMOTEREQUEST 1000 + +namespace OHOS { +int IPCObjectStub::SendRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) +{ + reply.WriteInt32(TEST_RETVAL_ONREMOTEREQUEST); + return NO_ERROR; +} +} // namespace OHOS + +namespace OHOS { +namespace AAFwk { + +class MockDataObsMgrStub : public DataObsManagerStub { +public: + MOCK_METHOD2(RegisterObserver, int(const Uri &, const sptr &)); + MOCK_METHOD2(UnregisterObserver, int(const Uri &, const sptr &)); + MOCK_METHOD1(NotifyChange, int(const Uri &)); +}; + +class MockDataAbilityObserverStub : public AAFwk::DataAbilityObserverStub { +public: + MockDataAbilityObserverStub() = default; + virtual ~MockDataAbilityObserverStub() = default; + MOCK_METHOD0(OnChange, void(void)); +}; + +} // namespace AAFwk +} // namespace OHOS +#endif /* MOCK_DATA_OBS_MGR_STUB_H */ \ No newline at end of file diff --git a/tools/services/dataobsmgr/test/unittest/phone/dataobs_mgr_service_test/BUILD.gn b/tools/services/dataobsmgr/test/unittest/phone/dataobs_mgr_service_test/BUILD.gn new file mode 100644 index 00000000000..19d61681b36 --- /dev/null +++ b/tools/services/dataobsmgr/test/unittest/phone/dataobs_mgr_service_test/BUILD.gn @@ -0,0 +1,54 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/test.gni") +import("//foundation/aafwk/standard/aafwk.gni") + +module_output_path = "aafwk_standard/dataobsmgr" + +ohos_unittest("dataobs_mgr_service_test") { + module_out_path = module_output_path + + include_dirs = + [ "//foundation/distributedschedule/safwk/services/safwk/include" ] + + sources = [ "dataobs_mgr_service_test.cpp" ] + + configs = [ "${services_path}/dataobsmgr:dataobsms_config" ] + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + deps = [ + "${innerkits_path}/want:want", + "//foundation/aafwk/standard/interfaces/innerkits/dataobs_manager:dataobs_manager", + "//foundation/aafwk/standard/services/dataobsmgr:dataobsms", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//third_party/googletest:gmock_main", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] +} + +group("unittest") { + testonly = true + + deps = [ ":dataobs_mgr_service_test" ] +} diff --git a/tools/services/dataobsmgr/test/unittest/phone/dataobs_mgr_service_test/dataobs_mgr_service_test.cpp b/tools/services/dataobsmgr/test/unittest/phone/dataobs_mgr_service_test/dataobs_mgr_service_test.cpp new file mode 100644 index 00000000000..e8cd7802466 --- /dev/null +++ b/tools/services/dataobsmgr/test/unittest/phone/dataobs_mgr_service_test/dataobs_mgr_service_test.cpp @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include + +#include "gtest/gtest.h" +#include "gmock/gmock.h" + +#include "mock_data_ability_observer_stub.h" + +#include "dataobs_mgr_service.h" + +namespace OHOS { +namespace AAFwk { +using namespace testing::ext; +class DataObsMgrServiceTest : public testing::Test { +public: + DataObsMgrServiceTest() = default; + virtual ~DataObsMgrServiceTest() = default; + + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; +void DataObsMgrServiceTest::SetUpTestCase(void) +{} +void DataObsMgrServiceTest::TearDownTestCase(void) +{} +void DataObsMgrServiceTest::SetUp() +{} +void DataObsMgrServiceTest::TearDown() +{} + +/* + * Feature: DataObsMgrService + * Function: QueryServiceState + * SubFunction: NA + * FunctionPoints: DataObsMgrService QueryServiceState + * EnvConditions: NA + * CaseDescription: Verify that the DataObsMgrService could query service state. + */ +HWTEST_F(DataObsMgrServiceTest, AaFwk_DataObsMgrServiceTest_QueryServiceState_0100, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataObsMgrServiceTest_QueryServiceState_0100 start"; + const DataObsServiceRunningState testValue = DataObsServiceRunningState::STATE_NOT_START; + auto dataObsMgrServer = DelayedSingleton::GetInstance(); + + EXPECT_EQ(testValue, dataObsMgrServer->QueryServiceState()); + + GTEST_LOG_(INFO) << "AaFwk_DataObsMgrServiceTest_QueryServiceState_0100 end"; +} + +/* + * Feature: DataObsMgrService + * Function: GetEventHandler + * SubFunction: NA + * FunctionPoints: DataObsMgrService GetEventHandler + * EnvConditions: NA + * CaseDescription: Verify that the DataObsMgrService could get eventHandler. + */ +HWTEST_F(DataObsMgrServiceTest, AaFwk_DataObsMgrServiceTest_GetEventHandler_0100, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataObsMgrServiceTest_GetEventHandler_0100 start"; + auto dataObsMgrServer = DelayedSingleton::GetInstance(); + + const std::shared_ptr retVal = dataObsMgrServer->GetEventHandler(); + + EXPECT_EQ(nullptr, retVal.get()); + + GTEST_LOG_(INFO) << "AaFwk_DataObsMgrServiceTest_GetEventHandler_0100 end"; +} + +/* + * Feature: DataObsMgrService + * Function: OnStart + * SubFunction: NA + * FunctionPoints: DataObsMgrService OnStart + * EnvConditions: NA + * CaseDescription: Verify that the DataObsMgrService OnStart is normal. + */ +HWTEST_F(DataObsMgrServiceTest, AaFwk_DataObsMgrServiceTest_OnStart_0100, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataObsMgrServiceTest_OnStart_0100 start"; + const DataObsServiceRunningState testValue = DataObsServiceRunningState::STATE_RUNNING; + auto dataObsMgrServer = DelayedSingleton::GetInstance(); + + dataObsMgrServer->OnStart(); + EXPECT_EQ(testValue, dataObsMgrServer->QueryServiceState()); + EXPECT_NE(nullptr, dataObsMgrServer->GetEventHandler().get()); + + GTEST_LOG_(INFO) << "AaFwk_DataObsMgrServiceTest_OnStart_0100 end"; +} + +/* + * Feature: DataObsMgrService + * Function: RegisterObserver + * SubFunction: NA + * FunctionPoints: DataObsMgrService RegisterObserver + * EnvConditions: NA + * CaseDescription: Verify that the DataObsMgrService RegisterObserver is normal. + */ +HWTEST_F(DataObsMgrServiceTest, AaFwk_DataObsMgrServiceTest_RegisterObserver_0100, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataObsMgrServiceTest_RegisterObserver_0100 start"; + const int testVal = static_cast(NO_ERROR); + const sptr dataobsAbility(new (std::nothrow) MockDataAbilityObserverStub()); + std::shared_ptr uri = + std::make_shared("dataability://device_id/com.domainname.dataability.persondata/person/10"); + auto dataObsMgrServer = DelayedSingleton::GetInstance(); + + EXPECT_CALL(*dataobsAbility, OnChange()).Times(1).WillOnce(testing::Return()); + EXPECT_EQ(testVal, dataObsMgrServer->RegisterObserver(*uri, dataobsAbility)); + + testing::Mock::AllowLeak(dataobsAbility); + GTEST_LOG_(INFO) << "AaFwk_DataObsMgrServiceTest_RegisterObserver_0100 end"; +} + +/* + * Feature: DataObsMgrService + * Function: UnregisterObserver + * SubFunction: NA + * FunctionPoints: DataObsMgrService UnregisterObserver + * EnvConditions: NA + * CaseDescription: Verify that the DataObsMgrService UnregisterObserver is normal. + */ +HWTEST_F(DataObsMgrServiceTest, AaFwk_DataObsMgrServiceTest_UnregisterObserver_0100, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataObsMgrServiceTest_UnregisterObserver_0100 start"; + const int testVal = static_cast(NO_ERROR); + const sptr dataobsAbility(new (std::nothrow) MockDataAbilityObserverStub()); + std::shared_ptr uri = + std::make_shared("dataability://device_id/com.domainname.dataability.persondata/person/10"); + auto dataObsMgrServer = DelayedSingleton::GetInstance(); + + EXPECT_EQ(testVal, dataObsMgrServer->UnregisterObserver(*uri, dataobsAbility)); + + GTEST_LOG_(INFO) << "AaFwk_DataObsMgrServiceTest_UnregisterObserver_0100 end"; +} + +/* + * Feature: DataObsMgrService + * Function: NotifyChange + * SubFunction: NA + * FunctionPoints: DataObsMgrService NotifyChange + * EnvConditions: NA + * CaseDescription: Verify that the DataObsMgrService NotifyChange is normal. + */ +HWTEST_F(DataObsMgrServiceTest, AaFwk_DataObsMgrServiceTest_NotifyChange_0100, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataObsMgrServiceTest_NotifyChange_0100 start"; + const int testVal = static_cast(NO_ERROR); + std::shared_ptr uri = + std::make_shared("dataability://device_id/com.domainname.dataability.persondata/person/10"); + auto dataObsMgrServer = DelayedSingleton::GetInstance(); + + EXPECT_EQ(testVal, dataObsMgrServer->NotifyChange(*uri)); + + GTEST_LOG_(INFO) << "AaFwk_DataObsMgrServiceTest_NotifyChange_0100 end"; +} + +/* + * Feature: DataObsMgrService + * Function: OnStop + * SubFunction: NA + * FunctionPoints: DataObsMgrService OnStop + * EnvConditions: NA + * CaseDescription: Verify that the DataObsMgrService OnStop is normal. + */ +HWTEST_F(DataObsMgrServiceTest, AaFwk_DataObsMgrServiceTest_OnStop_0100, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataObsMgrServiceTest_OnStop_0100 start"; + const DataObsServiceRunningState testValue = DataObsServiceRunningState::STATE_NOT_START; + auto dataObsMgrServer = DelayedSingleton::GetInstance(); + + dataObsMgrServer->OnStop(); + EXPECT_EQ(testValue, dataObsMgrServer->QueryServiceState()); + EXPECT_EQ(nullptr, dataObsMgrServer->GetEventHandler().get()); + + GTEST_LOG_(INFO) << "AaFwk_DataObsMgrServiceTest_OnStop_0100 end"; +} + +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/dataobsmgr/test/unittest/phone/dataobs_mgr_service_test/mock_data_ability_observer_stub.h b/tools/services/dataobsmgr/test/unittest/phone/dataobs_mgr_service_test/mock_data_ability_observer_stub.h new file mode 100644 index 00000000000..62f18912942 --- /dev/null +++ b/tools/services/dataobsmgr/test/unittest/phone/dataobs_mgr_service_test/mock_data_ability_observer_stub.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MOCK_DATA_ABILITY_OBSERVER_STUB_H +#define MOCK_DATA_ABILITY_OBSERVER_STUB_H +#include + +#include "gtest/gtest.h" +#include "gmock/gmock.h" + +#include "data_ability_observer_stub.h" + +namespace OHOS { +namespace AAFwk { +class MockDataAbilityObserverStub : public AAFwk::DataAbilityObserverStub { +public: + MockDataAbilityObserverStub() = default; + virtual ~MockDataAbilityObserverStub() = default; + MOCK_METHOD0(OnChange, void(void)); +}; + +} // namespace AAFwk +} // namespace OHOS +#endif /* MOCK_DATA_ABILITY_OBSERVER_STUB_H */ \ No newline at end of file diff --git a/tools/services/dataobsmgr/test/unittest/phone/dataobs_mgr_stub_test/BUILD.gn b/tools/services/dataobsmgr/test/unittest/phone/dataobs_mgr_stub_test/BUILD.gn new file mode 100644 index 00000000000..0ca427e7100 --- /dev/null +++ b/tools/services/dataobsmgr/test/unittest/phone/dataobs_mgr_stub_test/BUILD.gn @@ -0,0 +1,53 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/test.gni") +import("//foundation/aafwk/standard/aafwk.gni") + +module_output_path = "aafwk_standard/dataobsmgr" + +ohos_unittest("dataobs_mgr_stub_test") { + module_out_path = module_output_path + + include_dirs = [] + + sources = [ "dataobs_mgr_stub_test.cpp" ] + + configs = [ "${services_path}/dataobsmgr:dataobsms_config" ] + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + deps = [ + "${innerkits_path}/want:want", + "//foundation/aafwk/standard/interfaces/innerkits/dataobs_manager:dataobs_manager", + "//foundation/aafwk/standard/services/dataobsmgr:dataobsms", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//third_party/googletest:gmock_main", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] +} + +group("unittest") { + testonly = true + + deps = [ ":dataobs_mgr_stub_test" ] +} diff --git a/tools/services/dataobsmgr/test/unittest/phone/dataobs_mgr_stub_test/dataobs_mgr_stub_test.cpp b/tools/services/dataobsmgr/test/unittest/phone/dataobs_mgr_stub_test/dataobs_mgr_stub_test.cpp new file mode 100644 index 00000000000..72315963156 --- /dev/null +++ b/tools/services/dataobsmgr/test/unittest/phone/dataobs_mgr_stub_test/dataobs_mgr_stub_test.cpp @@ -0,0 +1,214 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include + +#include "gtest/gtest.h" +#include "gmock/gmock.h" + +#include "mock_data_obs_mgr_stub.h" + +#include "dataobs_mgr_proxy.h" + +namespace OHOS { +namespace AAFwk { +using namespace testing::ext; +class DataObsManagerStubTest : public testing::Test { +public: + DataObsManagerStubTest() = default; + virtual ~DataObsManagerStubTest() = default; + + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; +void DataObsManagerStubTest::SetUpTestCase(void) +{} +void DataObsManagerStubTest::TearDownTestCase(void) +{} +void DataObsManagerStubTest::SetUp() +{} +void DataObsManagerStubTest::TearDown() +{} + +/* + * Feature: DataObsManagerStub + * Function: OnRemoteRequest + * SubFunction: NA + * FunctionPoints: DataObsManagerStub OnRemoteRequest + * EnvConditions: NA + * CaseDescription: Verify that the DataObsManagerStub OnRemoteRequest is normal. + */ +HWTEST_F(DataObsManagerStubTest, AaFwk_DataObsManagerStubTest_OnRemoteRequest_0100, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataObsManagerStubTest_OnRemoteRequest_0100 start"; + std::shared_ptr dataobs = std::make_shared(); + const int testVal = static_cast(TEST_RETVAL_ONREMOTEREQUEST); + uint32_t code = IDataObsMgr::NOTIFY_CHANGE + 1; + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!data.WriteInterfaceToken(DataObsManagerProxy::GetDescriptor())) { + GTEST_LOG_(ERROR) << "---------- WriteInterfaceToken(data) retval is false end"; + return; + } + + const int retval = dataobs->OnRemoteRequest(code, data, reply, option); + + EXPECT_EQ(testVal, retval); + GTEST_LOG_(INFO) << "AaFwk_DataObsManagerStubTest_OnRemoteRequest_0100 end"; +} + +/* + * Feature: DataObsManagerStub + * Function: OnRemoteRequest + * SubFunction: NA + * FunctionPoints: DataObsManagerStub OnRemoteRequest + * EnvConditions: NA + * CaseDescription: Verify that the DataObsManagerStub OnRemoteRequest is normal. + */ +HWTEST_F(DataObsManagerStubTest, AaFwk_DataObsManagerStubTest_RegisterObserver_0100, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataObsManagerStubTest_RegisterObserver_0100 start"; + const int testVal1 = static_cast(NO_ERROR); + const int testVal2 = static_cast(TEST_RETVAL_ONREMOTEREQUEST); + std::shared_ptr dataobs = std::make_shared(); + sptr dataObserver(new (std::nothrow) MockDataAbilityObserverStub()); + std::shared_ptr uri = + std::make_shared("dataability://device_id/com.domainname.dataability.persondata/person/10"); + uint32_t code = IDataObsMgr::REGISTER_OBSERVER; + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!data.WriteInterfaceToken(DataObsManagerProxy::GetDescriptor())) { + GTEST_LOG_(ERROR) << "---------- WriteInterfaceToken(data) retval is false end"; + return; + } + if (!data.WriteParcelable(uri.get())) { + GTEST_LOG_(ERROR) << "---------- data.WriteParcelable(uri) retval is false end"; + return; + } + if (dataObserver == nullptr) { + return; + } + + if (!data.WriteParcelable(dataObserver->AsObject())) { + GTEST_LOG_(ERROR) << "---------- data.WriteParcelable(dataObserver->AsObject()) retval is false end"; + return; + } + + EXPECT_CALL(*dataobs, RegisterObserver(testing::_, testing::_)).Times(1).WillOnce(testing::Return(testVal2)); + + const int retval1 = dataobs->OnRemoteRequest(code, data, reply, option); + const int retval2 = reply.ReadInt32(); + + EXPECT_EQ(testVal1, retval1); + EXPECT_EQ(testVal2, retval2); + GTEST_LOG_(INFO) << "AaFwk_DataObsManagerStubTest_RegisterObserver_0100 end"; +} + +/* + * Feature: DataObsManagerStub + * Function: UnregisterObserver + * SubFunction: NA + * FunctionPoints: DataObsManagerStub UnregisterObserver + * EnvConditions: NA + * CaseDescription: Verify that the DataObsManagerStub UnregisterObserver is normal. + */ +HWTEST_F(DataObsManagerStubTest, AaFwk_DataObsManagerStubTest_UnregisterObserver_0100, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataObsManagerStubTest_UnregisterObserver_0100 start"; + const int testVal1 = static_cast(NO_ERROR); + const int testVal2 = static_cast(TEST_RETVAL_ONREMOTEREQUEST); + std::shared_ptr dataobs = std::make_shared(); + sptr dataObserver(new (std::nothrow) MockDataAbilityObserverStub()); + std::shared_ptr uri = + std::make_shared("dataability://device_id/com.domainname.dataability.persondata/person/10"); + uint32_t code = IDataObsMgr::UNREGISTER_OBSERVER; + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!data.WriteInterfaceToken(DataObsManagerProxy::GetDescriptor())) { + GTEST_LOG_(ERROR) << "---------- WriteInterfaceToken(data) retval is false end"; + return; + } + if (!data.WriteParcelable(uri.get())) { + GTEST_LOG_(ERROR) << "---------- data.WriteParcelable(uri) retval is false end"; + return; + } + if (dataObserver == nullptr) { + return; + } + + if (!data.WriteParcelable(dataObserver->AsObject())) { + GTEST_LOG_(ERROR) << "---------- data.WriteParcelable(dataObserver->AsObject()) retval is false end"; + return; + } + + EXPECT_CALL(*dataobs, UnregisterObserver(testing::_, testing::_)).Times(1).WillOnce(testing::Return(testVal2)); + + const int retval1 = dataobs->OnRemoteRequest(code, data, reply, option); + const int retval2 = reply.ReadInt32(); + + EXPECT_EQ(testVal1, retval1); + EXPECT_EQ(testVal2, retval2); + GTEST_LOG_(INFO) << "AaFwk_DataObsManagerStubTest_UnregisterObserver_0100 end"; +} + +/* + * Feature: DataObsManagerStub + * Function: NotifyChange + * SubFunction: NA + * FunctionPoints: DataObsManagerStub NotifyChange + * EnvConditions: NA + * CaseDescription: Verify that the DataObsManagerStub NotifyChange is normal. + */ +HWTEST_F(DataObsManagerStubTest, AaFwk_DataObsManagerStubTest_NotifyChange_0100, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AaFwk_DataObsManagerStubTest_NotifyChange_0100 start"; + std::shared_ptr dataobs = std::make_shared(); + std::shared_ptr uri = + std::make_shared("dataability://device_id/com.domainname.dataability.persondata/person/10"); + const int testVal1 = static_cast(NO_ERROR); + const int testVal2 = static_cast(TEST_RETVAL_ONREMOTEREQUEST); + uint32_t code = IDataObsMgr::NOTIFY_CHANGE; + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!data.WriteInterfaceToken(DataObsManagerProxy::GetDescriptor())) { + GTEST_LOG_(ERROR) << "---------- WriteInterfaceToken(data) retval is false end"; + return; + } + if (!data.WriteParcelable(uri.get())) { + GTEST_LOG_(ERROR) << "---------- data.WriteParcelable(uri) retval is false end"; + return; + } + + EXPECT_CALL(*dataobs, NotifyChange(testing::_)).Times(1).WillOnce(testing::Return(testVal2)); + + const int retval1 = dataobs->OnRemoteRequest(code, data, reply, option); + const int retval2 = reply.ReadInt32(); + + EXPECT_EQ(testVal1, retval1); + EXPECT_EQ(testVal2, retval2); + GTEST_LOG_(INFO) << "AaFwk_DataObsManagerStubTest_NotifyChange_0100 end"; +} + +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/dataobsmgr/test/unittest/phone/dataobs_mgr_stub_test/mock_data_obs_mgr_stub.h b/tools/services/dataobsmgr/test/unittest/phone/dataobs_mgr_stub_test/mock_data_obs_mgr_stub.h new file mode 100644 index 00000000000..3396352ee00 --- /dev/null +++ b/tools/services/dataobsmgr/test/unittest/phone/dataobs_mgr_stub_test/mock_data_obs_mgr_stub.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MOCK_DATA_OBS_MGR_STUB_H +#define MOCK_DATA_OBS_MGR_STUB_H +#include + +#include "gtest/gtest.h" +#include "gmock/gmock.h" + +#include "dataobs_mgr_stub.h" +#include "data_ability_observer_stub.h" + +#define TEST_RETVAL_ONREMOTEREQUEST 1000 + +namespace OHOS { +int IPCObjectStub::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) +{ + return TEST_RETVAL_ONREMOTEREQUEST; +} +} // namespace OHOS + +namespace OHOS { +namespace AAFwk { + +class MockDataObsMgrStub : public DataObsManagerStub { +public: + MOCK_METHOD2(RegisterObserver, int(const Uri &, const sptr &)); + MOCK_METHOD2(UnregisterObserver, int(const Uri &, const sptr &)); + MOCK_METHOD1(NotifyChange, int(const Uri &)); +}; + +class MockDataAbilityObserverStub : public AAFwk::DataAbilityObserverStub { +public: + MockDataAbilityObserverStub() = default; + virtual ~MockDataAbilityObserverStub() = default; + MOCK_METHOD0(OnChange, void(void)); +}; + +} // namespace AAFwk +} // namespace OHOS +#endif /* MOCK_DATA_OBS_MGR_STUB_H */ \ No newline at end of file diff --git a/tools/services/test/BUILD.gn b/tools/services/test/BUILD.gn new file mode 100755 index 00000000000..b43f69e222c --- /dev/null +++ b/tools/services/test/BUILD.gn @@ -0,0 +1,45 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//foundation/aafwk/standard/aafwk.gni") + +config("aafwk_module_test_config") { + defines = [ + # "APP_LOG_TAG = \"AbilityMgrService\"", + # "LOG_DOMAIN = 0xD00111F", + ] + + configs = [ "${services_path}/abilitymgr:abilityms_config" ] + + include_dirs = [ + "${services_path}/test/mock/include", + "//third_party/jsoncpp/include", + ] +} + +group("moduletest") { + testonly = true + + deps = [ + "moduletest/ability_mgr_service_test:moduletest", + "moduletest/ability_record_test:moduletest", + "moduletest/ability_stack_test:moduletest", + "moduletest/dump_module_test:moduletest", + "moduletest/ipc_ability_connect_test:moduletest", + "moduletest/ipc_ability_mgr_test:moduletest", + "moduletest/ipc_ability_scheduler_test:moduletest", + "moduletest/module_test_dump_util:module_test_dump_util", + "moduletest/panding_want_manager_test:moduletest", + "//third_party/jsoncpp:jsoncpp", + ] +} diff --git a/tools/services/test/mock/include/mock_ability_connect_callback.h b/tools/services/test/mock/include/mock_ability_connect_callback.h new file mode 100644 index 00000000000..c59848520e7 --- /dev/null +++ b/tools/services/test/mock/include/mock_ability_connect_callback.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MOCK_FOUNDATION_AAAFWK_INTERFACES_INNERKITS_ABILITY_CONNECT_CALLBACK_H +#define MOCK_FOUNDATION_AAAFWK_INTERFACES_INNERKITS_ABILITY_CONNECT_CALLBACK_H + +#include "ability_connect_callback_interface.h" +#include "gtest/gtest.h" +#include "gmock/gmock.h" + +namespace OHOS { +namespace AAFwk { +class MockAbilityConnectCallback : public IAbilityConnection { +public: + MOCK_METHOD3(OnAbilityConnectDone, + void(const AppExecFwk::ElementName &element, const sptr &remoteObject, int resultCode)); + MOCK_METHOD2(OnAbilityDisconnectDone, void(const AppExecFwk::ElementName &element, int resultCode)); + sptr AsObject() + { + return nullptr; + } + static int onAbilityConnectDoneCount; + static int onAbilityDisconnectDoneCount; +}; +} // namespace AAFwk +} // namespace OHOS + +#endif // MOCK_FOUNDATION_AAAFWK_INTERFACES_INNERKITS_ABILITY_CONNECT_CALLBACK_H \ No newline at end of file diff --git a/tools/services/test/mock/include/mock_ability_connect_callback_stub.h b/tools/services/test/mock/include/mock_ability_connect_callback_stub.h new file mode 100644 index 00000000000..8d973488669 --- /dev/null +++ b/tools/services/test/mock/include/mock_ability_connect_callback_stub.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MOCK_FOUNDATION_AAAFWK_INTERFACES_INNERKITS_ABILITY_CONNECT_CALLBACK_STUB_H +#define MOCK_FOUNDATION_AAAFWK_INTERFACES_INNERKITS_ABILITY_CONNECT_CALLBACK_STUB_H + +#include "ability_connect_callback_stub.h" +#include "gmock/gmock.h" +#include "semaphore_ex.h" + +namespace OHOS { +namespace AAFwk { +class MockAbilityConnectCallbackStub : public AbilityConnectionStub { +public: + MOCK_METHOD3(OnAbilityConnectDone, + void(const AppExecFwk::ElementName &element, const sptr &remoteObject, int resultCode)); + MOCK_METHOD2(OnAbilityDisconnectDone, void(const AppExecFwk::ElementName &element, int resultCode)); + + void Wait() + { + sem_.Wait(); + } + + int Post() + { + sem_.Post(); + return 0; + } + + void PostVoid() + { + sem_.Post(); + } + +private: + Semaphore sem_; +}; +} // namespace AAFwk +} // namespace OHOS + +#endif // MOCK_FOUNDATION_AAAFWK_INTERFACES_INNERKITS_ABILITY_CONNECT_CALLBACK_STUB_H \ No newline at end of file diff --git a/tools/services/test/mock/include/mock_ability_manager_proxy.h b/tools/services/test/mock/include/mock_ability_manager_proxy.h new file mode 100644 index 00000000000..934e073c12b --- /dev/null +++ b/tools/services/test/mock/include/mock_ability_manager_proxy.h @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_ABILITY_MANAGER_PROXY_MOCK_H +#define OHOS_AAFWK_ABILITY_MANAGER_PROXY_MOCK_H + +#include "gmock/gmock.h" +#include "ability_manager_interface.h" +#include "hilog_wrapper.h" +#include "iremote_proxy.h" + +namespace OHOS { +namespace AAFwk { +class MockAbilityManagerProxy : public IRemoteProxy { +public: + explicit MockAbilityManagerProxy(const sptr &impl) : IRemoteProxy(impl) + {} + virtual ~MockAbilityManagerProxy() + {} + + MOCK_METHOD2(StartAbility, int(const Want &want, int requestCode)); + MOCK_METHOD3(StartAbility, int(const Want &want, const sptr &callerToken, int requestCode)); + MOCK_METHOD2(TerminateAbilityByCaller, int(const sptr &callerToken, int requestCode)); + MOCK_METHOD3(TerminateAbility, int(const sptr &token, int resultCode, const Want *resultWant)); + MOCK_METHOD3(ConnectAbility, + int(const Want &want, const sptr &connect, const sptr &callerToken)); + MOCK_METHOD1(DisconnectAbility, int(const sptr &connect)); + MOCK_METHOD3(AcquireDataAbility, sptr(const Uri &, bool, const sptr &)); + MOCK_METHOD2(ReleaseDataAbility, int(sptr, const sptr &)); + MOCK_METHOD2(AddWindowInfo, void(const sptr &token, int32_t windowToken)); + MOCK_METHOD2(AttachAbilityThread, int(const sptr &scheduler, const sptr &token)); + MOCK_METHOD2(AbilityTransitionDone, int(const sptr &token, int state)); + MOCK_METHOD2( + ScheduleConnectAbilityDone, int(const sptr &token, const sptr &remoteObject)); + MOCK_METHOD1(ScheduleDisconnectAbilityDone, int(const sptr &token)); + MOCK_METHOD1(ScheduleCommandAbilityDone, int(const sptr &)); + MOCK_METHOD2(DumpState, void(const std::string &args, std::vector &state)); + MOCK_METHOD2(TerminateAbilityResult, int(const sptr &, int startId)); + MOCK_METHOD1(StopServiceAbility, int(const Want &)); + MOCK_METHOD1(GetAllStackInfo, int(StackInfo &stackInfo)); + MOCK_METHOD3(GetRecentMissions, int(const int32_t, const int32_t, std::vector &)); + MOCK_METHOD2(GetMissionSnapshot, int(const int32_t, MissionSnapshotInfo &)); + MOCK_METHOD1(RemoveMission, int(int)); + MOCK_METHOD1(RemoveStack, int(int)); + MOCK_METHOD1(MoveMissionToTop, int(int32_t)); + MOCK_METHOD1(KillProcess, int(const std::string &)); + MOCK_METHOD1(UninstallApp, int(const std::string &)); + MOCK_METHOD4(OnRemoteRequest, int(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option)); + MOCK_METHOD2( + GetWantSender, sptr(const WantSenderInfo &wantSenderInfo, const sptr &callerToken)); + MOCK_METHOD2(SendWantSender, int(const sptr &target, const SenderInfo &senderInfo)); + MOCK_METHOD1(CancelWantSender, void(const sptr &sender)); + MOCK_METHOD1(GetPendingWantUid, int(const sptr &target)); + MOCK_METHOD1(GetPendingWantBundleName, std::string(const sptr &target)); + MOCK_METHOD1(GetPendingWantCode, int(const sptr &target)); + MOCK_METHOD1(GetPendingWantType, int(const sptr &target)); + MOCK_METHOD2(RegisterCancelListener, void(const sptr &sender, const sptr &receiver)); + MOCK_METHOD2(UnregisterCancelListener, void(const sptr &sender, const sptr &receiver)); + MOCK_METHOD2(GetPendingRequestWant, int(const sptr &target, std::shared_ptr &want)); + + MOCK_METHOD2(MoveMissionToEnd, int(const sptr &token, const bool nonFirst)); + MOCK_METHOD1(IsFirstInMission, bool(const sptr &token)); + MOCK_METHOD4(CompelVerifyPermission, int(const std::string &permission, int pid, int uid, std::string &message)); + MOCK_METHOD0(PowerOff, int()); + MOCK_METHOD0(PowerOn, int()); + MOCK_METHOD1(GetPendingWantUserId, int(const sptr &target)); +public: + int id_; +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_AAFWK_ABILITY_MANAGER_PROXY_MOCK_H diff --git a/tools/services/test/mock/include/mock_ability_mgr_service.h b/tools/services/test/mock/include/mock_ability_mgr_service.h new file mode 100644 index 00000000000..64bc8040e07 --- /dev/null +++ b/tools/services/test/mock/include/mock_ability_mgr_service.h @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_AAFWK_SERVICES_MOCK_ABILITY_MGR_SERVICE_H +#define FOUNDATION_AAFWK_SERVICES_MOCK_ABILITY_MGR_SERVICE_H + +#include "gmock/gmock.h" +#include "semaphore_ex.h" +#include "ability_manager_stub.h" + +namespace OHOS { +namespace AAFwk { +class MockAbilityMgrService : public AbilityManagerStub { +public: + MOCK_METHOD2(StartAbility, int(const Want &want, int requestCode)); + MOCK_METHOD3(StartAbility, int(const Want &want, const sptr &callerToken, int requestCode)); + MOCK_METHOD2(TerminateAbilityByCaller, int(const sptr &callerToken, int requestCode)); + MOCK_METHOD3(TerminateAbility, int(const sptr &token, int resultCode, const Want *resultWant)); + MOCK_METHOD3(ConnectAbility, + int(const Want &want, const sptr &connect, const sptr &callerToken)); + MOCK_METHOD1(DisconnectAbility, int(const sptr &connect)); + MOCK_METHOD3(AcquireDataAbility, sptr(const Uri &, bool, const sptr &)); + MOCK_METHOD2(ReleaseDataAbility, int(sptr, const sptr &)); + MOCK_METHOD2(AddWindowInfo, void(const sptr &token, int32_t windowToken)); + MOCK_METHOD2(AttachAbilityThread, int(const sptr &scheduler, const sptr &token)); + MOCK_METHOD2(AbilityTransitionDone, int(const sptr &token, int state)); + MOCK_METHOD2( + ScheduleConnectAbilityDone, int(const sptr &token, const sptr &remoteObject)); + MOCK_METHOD1(ScheduleDisconnectAbilityDone, int(const sptr &token)); + MOCK_METHOD1(ScheduleCommandAbilityDone, int(const sptr &)); + MOCK_METHOD2(DumpState, void(const std::string &args, std::vector &state)); + MOCK_METHOD2(TerminateAbilityResult, int(const sptr &, int startId)); + MOCK_METHOD1(StopServiceAbility, int(const Want &)); + MOCK_METHOD1(GetAllStackInfo, int(StackInfo &stackInfo)); + MOCK_METHOD3(GetRecentMissions, int(const int32_t, const int32_t, std::vector &)); + MOCK_METHOD2(GetMissionSnapshot, int(const int32_t, MissionSnapshotInfo &)); + MOCK_METHOD1(RemoveMission, int(int)); + MOCK_METHOD1(RemoveStack, int(int)); + MOCK_METHOD1(MoveMissionToTop, int(int32_t)); + MOCK_METHOD1(KillProcess, int(const std::string &)); + MOCK_METHOD1(UninstallApp, int(const std::string &)); + MOCK_METHOD4(OnRemoteRequest, int(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option)); + MOCK_METHOD2(MoveMissionToEnd, int(const sptr &token, const bool nonFirst)); + MOCK_METHOD1(IsFirstInMission, bool(const sptr &token)); + MOCK_METHOD4(CompelVerifyPermission, int(const std::string &permission, int pid, int uid, std::string &message)); + MOCK_METHOD0(PowerOff, int()); + MOCK_METHOD0(PowerOn, int()); + MOCK_METHOD1(LockMission, int(int)); + MOCK_METHOD1(UnlockMission, int(int)); + MOCK_METHOD2(SetMissionDescriptionInfo, int(const sptr &token, const MissionDescriptionInfo &info)); + MOCK_METHOD0(GetMissionLockModeState, int()); + MOCK_METHOD1(UpdateConfiguration, int(const DummyConfiguration &)); + MOCK_METHOD2( + GetWantSender, sptr(const WantSenderInfo &wantSenderInfo, const sptr &callerToken)); + MOCK_METHOD2(SendWantSender, int(const sptr &target, const SenderInfo &senderInfo)); + MOCK_METHOD1(CancelWantSender, void(const sptr &sender)); + MOCK_METHOD1(GetPendingWantUid, int(const sptr &target)); + MOCK_METHOD1(GetPendingWantUserId, int(const sptr &target)); + MOCK_METHOD1(GetPendingWantBundleName, std::string(const sptr &target)); + MOCK_METHOD1(GetPendingWantCode, int(const sptr &target)); + MOCK_METHOD1(GetPendingWantType, int(const sptr &target)); + MOCK_METHOD2(RegisterCancelListener, void(const sptr &sender, const sptr &receiver)); + MOCK_METHOD2(UnregisterCancelListener, void(const sptr &sender, const sptr &receiver)); + MOCK_METHOD2(GetPendingRequestWant, int(const sptr &target, std::shared_ptr &want)); + MOCK_METHOD4(StartAbility, int(const Want &want, const AbilityStartSetting &abilityStartSetting, + const sptr &callerToken, int requestCode)); + MOCK_METHOD1(MoveMissionToFloatingStack, int(const MissionOption &missionOption)); + MOCK_METHOD1(MoveMissionToSplitScreenStack, int(const MissionOption &missionOption)); + MOCK_METHOD2( + ChangeFocusAbility, int(const sptr &lostFocusToken, const sptr &getFocusToken)); + MOCK_METHOD1(MinimizeMultiWindow, int(int missionId)); + MOCK_METHOD1(MaximizeMultiWindow, int(int missionId)); + MOCK_METHOD1(GetFloatingMissions, int(std::vector &list)); + MOCK_METHOD1(CloseMultiWindow, int(int missionId)); + MOCK_METHOD1(SetMissionStackSetting, int(const StackSetting &stackSetting)); + + void Wait() + { + sem_.Wait(); + } + + int Post() + { + sem_.Post(); + return 0; + } + + void PostVoid() + { + sem_.Post(); + } +private: + Semaphore sem_; +}; +} // namespace AAFwk +} // namespace OHOS +#endif // FOUNDATION_AAFWK_SERVICES_MOCK_ABILITY_MGR_SERVICE_H diff --git a/tools/services/test/mock/include/mock_ability_scheduler.h b/tools/services/test/mock/include/mock_ability_scheduler.h new file mode 100644 index 00000000000..f11b898d3d9 --- /dev/null +++ b/tools/services/test/mock/include/mock_ability_scheduler.h @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MOCK_OHOS_AAFWK_ABILITY_SCHEDULER_INTERFACE_H +#define MOCK_OHOS_AAFWK_ABILITY_SCHEDULER_INTERFACE_H + +#include "want.h" +#include "lifecycle_state_info.h" +#include "gmock/gmock.h" +#include "ability_scheduler_interface.h" + +namespace OHOS { +namespace AAFwk { +class MockAbilityScheduler : public IAbilityScheduler { +public: + MOCK_METHOD2(ScheduleAbilityTransaction, void(const Want &want, const LifeCycleStateInfo &targetState)); + MOCK_METHOD3(SendResult, void(int requestCode, int resultCode, const Want &resultWant)); + MOCK_METHOD1(ScheduleConnectAbility, void(const Want &want)); + MOCK_METHOD1(ScheduleDisconnectAbility, void(const Want &want)); + MOCK_METHOD3(ScheduleCommandAbility, void(const Want &want, bool restart, int startid)); + MOCK_METHOD0(AsObject, sptr()); + MOCK_METHOD1(ScheduleSaveAbilityState, void(PacMap &outState)); + MOCK_METHOD1(ScheduleRestoreAbilityState, void(const PacMap &inState)); + MOCK_METHOD1(ScheduleUpdateConfiguration, void(const DummyConfiguration &)); + MOCK_METHOD1(ScheduleNewWant, void(const Want &want)); + MOCK_METHOD1(NotifyTopActiveAbilityChanged, void(bool flag)); + MOCK_METHOD2(NotifyMultiWinModeChanged, void(int32_t winModeKey, bool flag)); + MOCK_METHOD2(ScheduleRegisterObserver, bool(const Uri &uri, const sptr &dataObserver)); + MOCK_METHOD2( + ScheduleUnregisterObserver, bool(const Uri &uri, const sptr &dataObserver)); + MOCK_METHOD1(ScheduleNotifyChange, bool(const Uri &uri)); + MOCK_METHOD1(ExecuteBatch, std::vector>(const std::vector> &operations)); + std::vector GetFileTypes(const Uri &uri, const std::string &mimeTypeFilter) + { + std::vector types; + return types; + } + + int OpenFile(const Uri &uri, const std::string &mode) + { + return -1; + } + + int Insert(const Uri &uri, const NativeRdb::ValuesBucket &value) + { + return -1; + } + + int Update(const Uri &uri, const NativeRdb::ValuesBucket &value, const NativeRdb::DataAbilityPredicates &predicates) + { + return -1; + } + + int Delete(const Uri &uri, const NativeRdb::DataAbilityPredicates &predicates) + { + return -1; + } + + std::shared_ptr Query( + const Uri &uri, std::vector &columns, const NativeRdb::DataAbilityPredicates &predicates) + { + return nullptr; + } + + virtual std::string GetType(const Uri &uri) override + { + return " "; + } + + virtual int OpenRawFile(const Uri &uri, const std::string &mode) override + { + return -1; + } + + virtual bool Reload(const Uri &uri, const PacMap &extras) override + { + return false; + } + + virtual int BatchInsert(const Uri &uri, const std::vector &values) override + { + return -1; + } + + virtual Uri NormalizeUri(const Uri &uri) override + { + Uri urivalue(""); + return urivalue; + } + + virtual Uri DenormalizeUri(const Uri &uri) override + { + Uri urivalue(""); + return urivalue; + } +}; +} // namespace AAFwk +} // namespace OHOS + +#endif // MOCK_OHOS_AAFWK_ABILITY_SCHEDULER_INTERFACE_H diff --git a/tools/services/test/mock/include/mock_ability_scheduler_stub.h b/tools/services/test/mock/include/mock_ability_scheduler_stub.h new file mode 100644 index 00000000000..d7b0c48f98d --- /dev/null +++ b/tools/services/test/mock/include/mock_ability_scheduler_stub.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_AAFWK_SERVICES_TEST_MT_MOCK_ABILITY_SCHEDULER_STUB_H +#define FOUNDATION_AAFWK_SERVICES_TEST_MT_MOCK_ABILITY_SCHEDULER_STUB_H + +#include "ability_scheduler_stub.h" + +namespace OHOS { +namespace AAFwk { +class MockAbilitySchedulerStub : public AbilitySchedulerStub { +public: + MOCK_METHOD2(ScheduleAbilityTransaction, void(const Want &, const LifeCycleStateInfo &)); + MOCK_METHOD3(SendResult, void(int, int, const Want &)); + MOCK_METHOD1(ScheduleConnectAbility, void(const Want &)); + MOCK_METHOD1(ScheduleDisconnectAbility, void(const Want &)); + MOCK_METHOD3(ScheduleCommandAbility, void(const Want &, bool, int)); + MOCK_METHOD1(ScheduleSaveAbilityState, void(PacMap &)); + MOCK_METHOD1(ScheduleRestoreAbilityState, void(const PacMap &)); + MOCK_METHOD1(ScheduleUpdateConfiguration, void(const DummyConfiguration &)); + MOCK_METHOD2(GetFileTypes, std::vector(const Uri &, const std::string &)); + MOCK_METHOD2(OpenFile, int(const Uri &, const std::string &)); + MOCK_METHOD2(Insert, int(const Uri &, const NativeRdb::ValuesBucket &)); + MOCK_METHOD3(Update, int(const Uri &, const NativeRdb::ValuesBucket &, const NativeRdb::DataAbilityPredicates &)); + MOCK_METHOD2(Delete, int(const Uri &, const NativeRdb::DataAbilityPredicates &)); + MOCK_METHOD3(Query, std::shared_ptr( + const Uri &, std::vector &, const NativeRdb::DataAbilityPredicates &)); + MOCK_METHOD1(GetType, std::string(const Uri &uri)); + MOCK_METHOD2(OpenRawFile, int(const Uri &uri, const std::string &mode)); + MOCK_METHOD2(Reload, bool(const Uri &uri, const PacMap &extras)); + MOCK_METHOD2(BatchInsert, int(const Uri &uri, const std::vector &values)); + MOCK_METHOD1(NormalizeUri, Uri(const Uri &)); + MOCK_METHOD1(DenormalizeUri, Uri(const Uri &)); + MOCK_METHOD2(NotifyMultiWinModeChanged, void(int32_t winModeKey, bool flag)); + MOCK_METHOD1(NotifyTopActiveAbilityChanged, void(bool flag)); + MOCK_METHOD2(ScheduleRegisterObserver, bool(const Uri &uri, const sptr &dataObserver)); + MOCK_METHOD2( + ScheduleUnregisterObserver, bool(const Uri &uri, const sptr &dataObserver)); + MOCK_METHOD1(ScheduleNotifyChange, bool(const Uri &uri)); + MOCK_METHOD1(ExecuteBatch, std::vector>( + const std::vector> &operations)); +}; +} // namespace AAFwk +} // namespace OHOS +#endif // FOUNDATION_AAFWK_SERVICES_TEST_MT_MOCK_ABILITY_SCHEDULER_STUB_H diff --git a/tools/services/test/mock/include/mock_app_mgr_client.h b/tools/services/test/mock/include/mock_app_mgr_client.h new file mode 100644 index 00000000000..47aefe463a8 --- /dev/null +++ b/tools/services/test/mock/include/mock_app_mgr_client.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_AAFWK_SERVICES_TEST_MT_MOCK_APP_MGR_CLIENT_H +#define FOUNDATION_AAFWK_SERVICES_TEST_MT_MOCK_APP_MGR_CLIENT_H + +#include +#include "app_mgr_client.h" + +namespace OHOS { +namespace AppExecFwk { +class MockAppMgrClient : public AppMgrClient { +public: + MockAppMgrClient(); + ~MockAppMgrClient(); + MOCK_METHOD4(LoadAbility, AppMgrResultCode(const sptr &, const sptr &, + const AbilityInfo &, const ApplicationInfo &)); + MOCK_METHOD1(TerminateAbility, AppMgrResultCode(const sptr &)); + MOCK_METHOD2(UpdateAbilityState, AppMgrResultCode(const sptr &token, const AbilityState state)); + MOCK_METHOD1(KillApplication, AppMgrResultCode(const std::string &)); + MOCK_METHOD1(KillProcessByAbilityToken, AppMgrResultCode(const sptr &token)); + MOCK_METHOD4(CompelVerifyPermission, int(const std::string &permission, int pid, int uid, std::string &message)); + MOCK_METHOD1(AbilityAttachTimeOut, void(const sptr &token)); + + AppMgrResultCode AbilityBehaviorAnalysis(const sptr &token, const sptr &preToken, + const int32_t visibility, const int32_t perceptibility, const int32_t connectionState) override; + AppMgrResultCode ConnectAppMgrService() override; + AppMgrResultCode RegisterAppStateCallback(const sptr &callback) override; +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_AAFWK_SERVICES_TEST_MT_MOCK_APP_MGR_CLIENT_H diff --git a/tools/services/test/mock/include/mock_app_scheduler.h b/tools/services/test/mock/include/mock_app_scheduler.h new file mode 100644 index 00000000000..55eafbea34d --- /dev/null +++ b/tools/services/test/mock/include/mock_app_scheduler.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_AAFWK_SERVICES_TEST_MOCK_APP_SCHEDULER_H +#define FOUNDATION_AAFWK_SERVICES_TEST_MOCK_APP_SCHEDULER_H + +#include "gmock/gmock.h" +#include "refbase.h" +#include "iremote_object.h" +#include "app_scheduler.h" +#include "app_launch_data.h" +#include "dummy_configuration.h" + +namespace OHOS { +namespace AAFwk { +class MockAppScheduler : public AppScheduler { +public: + MockAppScheduler(){}; + virtual ~MockAppScheduler(){}; + + MOCK_METHOD0(ScheduleForegroundApplication, void()); + MOCK_METHOD0(ScheduleBackgroundApplication, void()); + MOCK_METHOD0(ScheduleTerminateApplication, void()); + MOCK_METHOD1(ScheduleLaunchApplication, void(const AppExecFwk::AppLaunchData &)); + MOCK_METHOD2(ScheduleLaunchAbility, void(const AppExecFwk::AbilityInfo &, const sptr &)); + MOCK_METHOD1(ScheduleCleanAbility, void(const sptr &)); + MOCK_METHOD1(ScheduleProfileChanged, void(const AppExecFwk::Profile &)); + MOCK_METHOD1(ScheduleConfigurationUpdated, void(const AppExecFwk::Configuration &config)); + MOCK_METHOD1(ScheduleShrinkMemory, void(const int)); + MOCK_METHOD0(ScheduleLowMemory, void()); +}; +} // namespace AAFwk +} // namespace OHOS +#endif // FOUNDATION_AAFWK_SERVICES_TEST_MOCK_APP_SCHEDULER_H diff --git a/tools/services/test/mock/include/mock_bundle_mgr.h b/tools/services/test/mock/include/mock_bundle_mgr.h new file mode 100644 index 00000000000..3f78d8bb03e --- /dev/null +++ b/tools/services/test/mock/include/mock_bundle_mgr.h @@ -0,0 +1,360 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_AAFWK_ABILITY_MOCK_BUNDLE_MANAGER_H +#define OHOS_AAFWK_ABILITY_MOCK_BUNDLE_MANAGER_H + +#include +#include +#include "ability_info.h" +#include "application_info.h" +#include "bundlemgr/bundle_mgr_interface.h" +#include "ohos/aafwk/content/want.h" +#include "iremote_proxy.h" +#include "iremote_stub.h" + +namespace OHOS { +namespace AppExecFwk { +namespace { +const std::string COM_IX_HIWORLD = "com.ix.hiworld"; +const std::string COM_IX_HIMUSIC = "com.ix.hiMusic"; +const std::string COM_IX_HIRADIO = "com.ix.hiRadio"; +const std::string COM_IX_HISERVICE = "com.ix.hiService"; +const std::string COM_IX_MUSICSERVICE = "com.ix.musicService"; +const std::string COM_IX_HIDATA = "com.ix.hiData"; +const std::string COM_IX_PHONE = "com.ix.hiPhone"; +const std::string COM_IX_TV = "com.ix.hiTV"; +const std::string COM_IX_Film = "com.ix.hiFilm"; +constexpr int32_t MAX_SYS_UID = 2899; +constexpr int32_t ROOT_UID = 0; + +auto HiWordInfo = [](std::string bundleName, AbilityInfo &abilityInfo, ElementName &elementTemp) { + abilityInfo.name = elementTemp.GetAbilityName(); + abilityInfo.bundleName = elementTemp.GetBundleName(); + abilityInfo.applicationInfo.bundleName = elementTemp.GetBundleName(); + abilityInfo.applicationName = "Helloworld"; + abilityInfo.applicationInfo.name = "Helloworld"; + abilityInfo.type = AbilityType::PAGE; + abilityInfo.applicationInfo.isLauncherApp = true; + + if (elementTemp.GetAbilityName() == "luncher") { + abilityInfo.configChanges.push_back("fontSize"); + } + return true; +}; + +auto HiMusicInfo = [](std::string bundleName, AbilityInfo &abilityInfo, ElementName &elementTemp) { + abilityInfo.name = elementTemp.GetAbilityName(); + abilityInfo.bundleName = elementTemp.GetBundleName(); + abilityInfo.applicationInfo.bundleName = elementTemp.GetBundleName(); + abilityInfo.applicationName = "hiMusic"; + abilityInfo.applicationInfo.name = "hiMusic"; + abilityInfo.type = AbilityType::PAGE; + abilityInfo.applicationInfo.isLauncherApp = false; + + if (elementTemp.GetAbilityName() == "MusicAbility") { + abilityInfo.process = "p1"; + abilityInfo.launchMode = LaunchMode::STANDARD; + } + if (elementTemp.GetAbilityName() == "MusicTopAbility") { + abilityInfo.process = "p1"; + abilityInfo.launchMode = LaunchMode::SINGLETOP; + } + if (elementTemp.GetAbilityName() == "MusicSAbility") { + abilityInfo.process = "p2"; + abilityInfo.launchMode = LaunchMode::SINGLETON; + } + if (elementTemp.GetAbilityName() == "Music") { + abilityInfo.process = "p1"; + abilityInfo.launchMode = LaunchMode::STANDARD; + abilityInfo.configChanges.push_back("layout"); + } + + if (elementTemp.GetAbilityName() == "MusicTon") { + abilityInfo.process = "p1"; + abilityInfo.launchMode = LaunchMode::SINGLETON; + abilityInfo.configChanges.push_back("layout"); + } + return true; +}; + +auto HiRadioInfo = [](std::string bundleName, AbilityInfo &abilityInfo, ElementName &elementTemp) { + abilityInfo.name = elementTemp.GetAbilityName(); + abilityInfo.bundleName = elementTemp.GetBundleName(); + abilityInfo.applicationInfo.bundleName = elementTemp.GetBundleName(); + abilityInfo.applicationName = "hiRadio"; + abilityInfo.applicationInfo.name = "hiRadio"; + abilityInfo.type = AbilityType::PAGE; + abilityInfo.process = "p3"; + if (elementTemp.GetAbilityName() == "RadioAbility") { + abilityInfo.launchMode = LaunchMode::STANDARD; + } + if (elementTemp.GetAbilityName() == "RadioTopAbility") { + abilityInfo.launchMode = LaunchMode::SINGLETON; + } + if (elementTemp.GetAbilityName() == "Radio") { + abilityInfo.launchMode = LaunchMode::STANDARD; + abilityInfo.configChanges.push_back("orientation"); + } + return true; +}; + +auto HiServiceInfo = [](std::string bundleName, AbilityInfo &abilityInfo, ElementName &elementTemp) { + abilityInfo.name = elementTemp.GetAbilityName(); + abilityInfo.bundleName = elementTemp.GetBundleName(); + abilityInfo.applicationInfo.bundleName = elementTemp.GetBundleName(); + abilityInfo.applicationName = "hiService"; + abilityInfo.applicationInfo.name = "hiService"; + abilityInfo.type = AbilityType::SERVICE; + abilityInfo.process = "p4"; + return true; +}; + +auto MusicServiceInfo = [](std::string bundleName, AbilityInfo &abilityInfo, ElementName &elementTemp) { + abilityInfo.name = elementTemp.GetAbilityName(); + abilityInfo.bundleName = elementTemp.GetBundleName(); + abilityInfo.applicationInfo.bundleName = elementTemp.GetBundleName(); + abilityInfo.applicationName = "musicService"; + abilityInfo.applicationInfo.name = "musicService"; + abilityInfo.type = AbilityType::SERVICE; + abilityInfo.process = "p5"; + return true; +}; + +auto HiDataInfo = [](std::string bundleName, AbilityInfo &abilityInfo, ElementName &elementTemp) { + abilityInfo.name = elementTemp.GetAbilityName(); + abilityInfo.bundleName = elementTemp.GetBundleName(); + abilityInfo.applicationInfo.bundleName = elementTemp.GetBundleName(); + abilityInfo.applicationName = "hiData"; + abilityInfo.applicationInfo.name = "hiData"; + abilityInfo.type = AbilityType::DATA; + abilityInfo.process = "p6"; + return true; +}; + +auto HiPhoneInfo = [](std::string bundleName, AbilityInfo &abilityInfo, ElementName &elementTemp) { + abilityInfo.name = elementTemp.GetAbilityName(); + abilityInfo.bundleName = elementTemp.GetBundleName(); + abilityInfo.applicationInfo.bundleName = elementTemp.GetBundleName(); + abilityInfo.applicationName = "hiPhone"; + abilityInfo.applicationInfo.name = "hiPhone"; + abilityInfo.type = AbilityType::PAGE; + abilityInfo.applicationInfo.isLauncherApp = false; + abilityInfo.process = "p7"; + if (elementTemp.GetAbilityName() == "PhoneAbility1") { + abilityInfo.launchMode = LaunchMode::SINGLETON; + } + if (elementTemp.GetAbilityName() == "PhoneAbility2") { + abilityInfo.launchMode = LaunchMode::SINGLETON; + } + return true; +}; + +auto HiTVInfo = [](std::string bundleName, AbilityInfo &abilityInfo, ElementName &elementTemp) { + abilityInfo.name = elementTemp.GetAbilityName(); + abilityInfo.bundleName = elementTemp.GetBundleName(); + abilityInfo.applicationInfo.bundleName = elementTemp.GetBundleName(); + abilityInfo.applicationName = "hiTV"; + abilityInfo.applicationInfo.name = "hiTV"; + abilityInfo.type = AbilityType::PAGE; + abilityInfo.applicationInfo.isLauncherApp = false; + if (elementTemp.GetAbilityName() == "TVAbility") { + abilityInfo.process = "p8"; + abilityInfo.launchMode = LaunchMode::SINGLETON; + } + return true; +}; + +auto HiFilmInfo = [](std::string bundleName, AbilityInfo &abilityInfo, ElementName &elementTemp) { + abilityInfo.name = elementTemp.GetAbilityName(); + abilityInfo.bundleName = elementTemp.GetBundleName(); + abilityInfo.applicationInfo.bundleName = elementTemp.GetBundleName(); + abilityInfo.applicationName = "hiFilm"; + abilityInfo.applicationInfo.name = "hiFilm"; + abilityInfo.type = AbilityType::PAGE; + abilityInfo.applicationInfo.isLauncherApp = false; + if (elementTemp.GetAbilityName() == "FilmAbility") { + abilityInfo.process = "p9"; + abilityInfo.launchMode = LaunchMode::SINGLETON; + } + return true; +}; +} // namespace +class BundleMgrProxy : public IRemoteProxy { +public: + explicit BundleMgrProxy(const sptr &impl) : IRemoteProxy(impl) + {} + + int QueryWantAbility(const AAFwk::Want &want, std::vector &abilityInfos); + bool QueryAbilityInfo(const AAFwk::Want &want, AbilityInfo &abilityInfo) override; + bool QueryAbilityInfoByUri(const std::string &uri, AbilityInfo &abilityInfo) override; + bool GetApplicationInfo( + const std::string &appName, const ApplicationFlag flag, const int userId, ApplicationInfo &appInfo) override; + bool GetBundleInfo(const std::string &bundleName, const BundleFlag flag, BundleInfo &bundleInfo) override; + + virtual bool CheckIsSystemAppByUid(const int uid) override; + MOCK_METHOD3(GetApplicationInfos, + bool(const ApplicationFlag flag, const int userId, std::vector &appInfos)); + MOCK_METHOD2(GetBundleInfos, bool(const BundleFlag flag, std::vector &bundleInfos)); + MOCK_METHOD2(GetUidByBundleName, int(const std::string &bundleName, const int userId)); + MOCK_METHOD2(GetBundleNameForUid, bool(const int uid, std::string &bundleName)); + MOCK_METHOD2(GetBundleGids, bool(const std::string &bundleName, std::vector &gids)); + MOCK_METHOD1(GetAppType, std::string(const std::string &bundleName)); + MOCK_METHOD2(GetBundleInfosByMetaData, bool(const std::string &metaData, std::vector &bundleInfos)); + MOCK_METHOD1(QueryKeepAliveBundleInfos, bool(std::vector &bundleInfos)); + MOCK_METHOD2(GetAbilityLabel, std::string(const std::string &bundleName, const std::string &className)); + MOCK_METHOD3( + GetBundleArchiveInfo, bool(const std::string &hapFilePath, const BundleFlag flag, BundleInfo &bundleInfo)); + MOCK_METHOD2(GetHapModuleInfo, bool(const AbilityInfo &abilityInfo, HapModuleInfo &hapModuleInfo)); + MOCK_METHOD2(GetLaunchWantForBundle, bool(const std::string &bundleName, Want &want)); + MOCK_METHOD2(CheckPublicKeys, int(const std::string &firstBundleName, const std::string &secondBundleName)); + MOCK_METHOD2(CheckPermission, int(const std::string &bundleName, const std::string &permission)); + MOCK_METHOD2(GetPermissionDef, bool(const std::string &permissionName, PermissionDef &permissionDef)); + MOCK_METHOD1(GetAllPermissionGroupDefs, bool(std::vector &permissionDefs)); + MOCK_METHOD2(GetAppsGrantedPermissions, + bool(const std::vector &permissions, std::vector &appNames)); + MOCK_METHOD1(HasSystemCapability, bool(const std::string &capName)); + MOCK_METHOD1(GetSystemAvailableCapabilities, bool(std::vector &systemCaps)); + MOCK_METHOD0(IsSafeMode, bool()); + MOCK_METHOD2(CleanBundleCacheFiles, + bool(const std::string &bundleName, const sptr &cleanCacheCallback)); + MOCK_METHOD1(CleanBundleDataFiles, bool(const std::string &bundleName)); + MOCK_METHOD1(RegisterBundleStatusCallback, bool(const sptr &bundleStatusCallback)); + MOCK_METHOD1(ClearBundleStatusCallback, bool(const sptr &bundleStatusCallback)); + MOCK_METHOD0(UnregisterBundleStatusCallback, bool()); + MOCK_METHOD3(DumpInfos, bool(const DumpFlag flag, const std::string &bundleName, std::string &result)); + MOCK_METHOD1(IsApplicationEnabled, bool(const std::string &bundleName)); + MOCK_METHOD2(SetApplicationEnabled, bool(const std::string &bundleName, bool isEnable)); + MOCK_METHOD0(GetBundleInstaller, sptr()); + MOCK_METHOD2(GetNameForUid, bool(const int uid, std::string &name)); + MOCK_METHOD2(GetBundlesForUid, bool(const int uid, std::vector &)); + MOCK_METHOD2(SetAbilityEnabled, bool(const AbilityInfo &, bool)); + MOCK_METHOD1(IsAbilityEnabled, bool(const AbilityInfo &)); + MOCK_METHOD2(GetAbilityIcon, std::string(const std::string &bundleName, const std::string &className)); + MOCK_METHOD1(RegisterAllPermissionsChanged, bool(const sptr &callback)); + MOCK_METHOD2(RegisterPermissionsChanged, + bool(const std::vector &uids, const sptr &callback)); + MOCK_METHOD1(UnregisterPermissionsChanged, bool(const sptr &callback)); + MOCK_METHOD2(GetAppIdByBundleName, std::string(const std::string &bundleName, const int userId)); + MOCK_METHOD1(GetAllFormsInfo, bool(std::vector &formInfos)); + MOCK_METHOD2(GetFormsInfoByApp, bool(const std::string &bundleName, std::vector &formInfos)); + MOCK_METHOD3(GetFormsInfoByModule, + bool(const std::string &bundleName, const std::string &moduleName, std::vector &formInfos)); + MOCK_METHOD2(GetShortcutInfos, bool(const std::string &bundleName, std::vector &shortcutInfos)); + MOCK_METHOD2(QueryAbilityInfos, bool(const Want &want, std::vector &abilityInfos)); +}; + +class BundleMgrStub : public IRemoteStub { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"IBundleMgr"); + virtual int OnRemoteRequest( + uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override; +}; + +class BundleMgrService : public BundleMgrStub { +public: + MOCK_METHOD2(QueryAbilityInfoByUri, bool(const std::string &abilityUri, AbilityInfo &abilityInfo)); + MOCK_METHOD2(QueryWantAbility, int(const AAFwk::Want &want, std::vector &abilityInfos)); + MOCK_METHOD3(GetApplicationInfos, + bool(const ApplicationFlag flag, const int userId, std::vector &appInfos)); + MOCK_METHOD2(GetBundleInfos, bool(const BundleFlag flag, std::vector &bundleInfos)); + MOCK_METHOD2(GetBundleNameForUid, bool(const int uid, std::string &bundleName)); + MOCK_METHOD2(GetBundleGids, bool(const std::string &bundleName, std::vector &gids)); + MOCK_METHOD1(GetAppType, std::string(const std::string &bundleName)); + MOCK_METHOD2(GetBundleInfosByMetaData, bool(const std::string &metaData, std::vector &bundleInfos)); + MOCK_METHOD1(QueryKeepAliveBundleInfos, bool(std::vector &bundleInfos)); + MOCK_METHOD2(GetAbilityLabel, std::string(const std::string &bundleName, const std::string &className)); + MOCK_METHOD3( + GetBundleArchiveInfo, bool(const std::string &hapFilePath, const BundleFlag flag, BundleInfo &bundleInfo)); + MOCK_METHOD2(GetHapModuleInfo, bool(const AbilityInfo &abilityInfo, HapModuleInfo &hapModuleInfo)); + MOCK_METHOD2(GetLaunchWantForBundle, bool(const std::string &bundleName, Want &want)); + MOCK_METHOD2(CheckPublicKeys, int(const std::string &firstBundleName, const std::string &secondBundleName)); + MOCK_METHOD2(CheckPermission, int(const std::string &bundleName, const std::string &permission)); + MOCK_METHOD2(GetPermissionDef, bool(const std::string &permissionName, PermissionDef &permissionDef)); + MOCK_METHOD1(GetAllPermissionGroupDefs, bool(std::vector &permissionDefs)); + MOCK_METHOD2(GetAppsGrantedPermissions, + bool(const std::vector &permissions, std::vector &appNames)); + MOCK_METHOD1(HasSystemCapability, bool(const std::string &capName)); + MOCK_METHOD1(GetSystemAvailableCapabilities, bool(std::vector &systemCaps)); + MOCK_METHOD0(IsSafeMode, bool()); + MOCK_METHOD2(CleanBundleCacheFiles, + bool(const std::string &bundleName, const sptr &cleanCacheCallback)); + MOCK_METHOD1(CleanBundleDataFiles, bool(const std::string &bundleName)); + MOCK_METHOD1(RegisterBundleStatusCallback, bool(const sptr &bundleStatusCallback)); + MOCK_METHOD1(ClearBundleStatusCallback, bool(const sptr &bundleStatusCallback)); + MOCK_METHOD0(UnregisterBundleStatusCallback, bool()); + MOCK_METHOD3(DumpInfos, bool(const DumpFlag flag, const std::string &bundleName, std::string &result)); + MOCK_METHOD1(IsApplicationEnabled, bool(const std::string &bundleName)); + MOCK_METHOD2(SetApplicationEnabled, bool(const std::string &bundleName, bool isEnable)); + MOCK_METHOD0(GetBundleInstaller, sptr()); + MOCK_METHOD3( + CanRequestPermission, bool(const std::string &bundleName, const std::string &permissionName, const int userId)); + MOCK_METHOD3(RequestPermissionFromUser, + bool(const std::string &bundleName, const std::string &permission, const int userId)); + MOCK_METHOD2(GetNameForUid, bool(const int uid, std::string &name)); + MOCK_METHOD2(GetBundlesForUid, bool(const int uid, std::vector &)); + MOCK_METHOD2(SetAbilityEnabled, bool(const AbilityInfo &, bool)); + MOCK_METHOD1(IsAbilityEnabled, bool(const AbilityInfo &)); + MOCK_METHOD2(GetAbilityIcon, std::string(const std::string &bundleName, const std::string &className)); + MOCK_METHOD1(RegisterAllPermissionsChanged, bool(const sptr &callback)); + MOCK_METHOD2(RegisterPermissionsChanged, + bool(const std::vector &uids, const sptr &callback)); + MOCK_METHOD1(UnregisterPermissionsChanged, bool(const sptr &callback)); + MOCK_METHOD2(GetAppIdByBundleName, std::string(const std::string &bundleName, const int userId)); + MOCK_METHOD1(GetAllFormsInfo, bool(std::vector &formInfos)); + MOCK_METHOD2(GetFormsInfoByApp, bool(const std::string &bundleName, std::vector &formInfos)); + MOCK_METHOD3(GetFormsInfoByModule, + bool(const std::string &bundleName, const std::string &moduleName, std::vector &formInfos)); + MOCK_METHOD2(GetShortcutInfos, bool(const std::string &bundleName, std::vector &shortcutInfos)); + MOCK_METHOD2(GetUidByBundleName, int(const std::string &bundleName, const int userId)); + MOCK_METHOD2(GetModuleUsageRecords, bool(const int32_t number, std::vector &moduleUsageRecords)); + bool GetBundleInfo(const std::string &bundleName, const BundleFlag flag, BundleInfo &bundleInfo) override; + bool QueryAbilityInfo(const AAFwk::Want &want, AbilityInfo &abilityInfo) override; + bool QueryAbilityInfos(const Want &want, std::vector &abilityInfos) override + { + return true; + }; + bool GetApplicationInfo( + const std::string &appName, const ApplicationFlag flag, const int userId, ApplicationInfo &appInfo) override; + bool NotifyActivityLifeStatus( + const std::string &bundleName, const std::string &abilityName, const int64_t launchTime) override; + virtual bool CheckIsSystemAppByUid(const int uid) override; + BundleMgrService() + { + abilityInfoMap_.emplace(COM_IX_HIWORLD, HiWordInfo); + abilityInfoMap_.emplace(COM_IX_HIMUSIC, HiMusicInfo); + abilityInfoMap_.emplace(COM_IX_HIRADIO, HiRadioInfo); + abilityInfoMap_.emplace(COM_IX_HISERVICE, HiServiceInfo); + abilityInfoMap_.emplace(COM_IX_MUSICSERVICE, MusicServiceInfo); + abilityInfoMap_.emplace(COM_IX_HIDATA, HiDataInfo); + abilityInfoMap_.emplace(COM_IX_PHONE, HiPhoneInfo); + abilityInfoMap_.emplace(COM_IX_TV, HiTVInfo); + abilityInfoMap_.emplace(COM_IX_Film, HiFilmInfo); + } + + virtual ~BundleMgrService() + {} + + bool CheckWantEntity(const AAFwk::Want &, AbilityInfo &); + +public: + using QueryAbilityInfoFunType = + std::function; + std::map abilityInfoMap_; +}; +} // namespace AppExecFwk +} // namespace OHOS + +#endif // OHOS_AAFWK_ABILITY_MOCK_BUNDLE_MANAGER_H diff --git a/tools/services/test/mock/include/mock_compled_callback.h b/tools/services/test/mock/include/mock_compled_callback.h new file mode 100644 index 00000000000..803a3c83d56 --- /dev/null +++ b/tools/services/test/mock/include/mock_compled_callback.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BASE_NOTIFICATION_ANS_STANDARD_KITS_NATIVE_WANTAGENT_COMPLETED_CALLBACK_MOCK_H +#define BASE_NOTIFICATION_ANS_STANDARD_KITS_NATIVE_WANTAGENT_COMPLETED_CALLBACK_MOCK_H + +#include "gmock/gmock.h" +#include "completed_callback.h" + +namespace OHOS::Notification::WantAgent { +class MockCompletedCallback : public CompletedCallback { +public: + MOCK_METHOD4(OnSendFinished, void(const AAFwk::Want &want, int resultCode, const std::string &resultData, + const AAFwk::WantParams &resultExtras)); +}; +} // namespace OHOS::Notification::WantAgent +#endif \ No newline at end of file diff --git a/tools/services/test/mock/include/mock_context.h b/tools/services/test/mock/include/mock_context.h new file mode 100644 index 00000000000..9ccf7227c5e --- /dev/null +++ b/tools/services/test/mock/include/mock_context.h @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_APPEXECFWK_OHOS_CONTEXT_H +#define FOUNDATION_APPEXECFWK_OHOS_CONTEXT_H + +#include "context.h" +#include "gmock/gmock.h" + +class MockContext { +public: + MockContext() = default; + virtual ~MockContext() = default; + MOCK_METHOD0(GetProcessInfo, std::shared_ptr()); + MOCK_METHOD0(GetApplicationInfo, std::shared_ptr()); + MOCK_METHOD0(GetApplicationContext, std::shared_ptr()); + MOCK_METHOD0(GetBundleCodePath, std::string()); + MOCK_METHOD0(GetAbilityInfo, std::shared_ptr()); + MOCK_METHOD0(GetContext, std::shared_ptr()); + MOCK_METHOD0(GetBundleManager, sptr()); + MOCK_METHOD0(GetResourceManager, std::shared_ptr()); + MOCK_METHOD1(DeleteFile, bool(const std::string &fileName)); + MOCK_METHOD1(StopAbility, bool(const AAFwk::Want &want)); + MOCK_METHOD0(GetCacheDir, std::string ()); + + virtual std::string GetCodeCacheDir() = 0; + virtual std::string GetDatabaseDir() = 0; + virtual std::string GetDataDir() = 0; + virtual std::string GetDir(const std::string &name, int mode) = 0; + virtual std::string GetExternalCacheDir() = 0; + virtual std::string GetExternalFilesDir(std::string &type) = 0; + virtual std::string GetFilesDir() = 0; + virtual std::string GetNoBackupFilesDir() = 0; + virtual int VerifyCallingPermission(const std::string &permission) = 0; + virtual int VerifySelfPermission(const std::string &permission) = 0; + virtual std::string GetBundleName() = 0; + virtual std::string GetBundleResourcePath() = 0; + virtual void StartAbility(const AAFwk::Want &want, int requestCode) = 0; + virtual void UnauthUriPermission(const std::string &permission, const Uri &uri, int uid) = 0; + virtual sptr GetAbilityManager() = 0; + virtual std::string GetAppType() = 0; + virtual void TerminateAbility(int requestCode) = 0; + virtual void TerminateAbility() = 0; + virtual bool CanRequestPermission(const std::string &permission) = 0; + virtual int VerifyCallingOrSelfPermission(const std::string &permission) = 0; + virtual int VerifyPermission(const std::string &permission, int pid, int uid) = 0; + virtual std::string GetDistributedDir() = 0; + virtual void SetPattern(int patternId) = 0; + virtual std::shared_ptr GetAbilityPackageContext() = 0; + virtual std::shared_ptr GetHapModuleInfo() = 0; + virtual std::string GetProcessName() = 0; + virtual std::string GetCallingBundle() = 0; + virtual void RequestPermissionsFromUser(std::vector &permissions, int requestCode) = 0; + virtual void StartAbility(const Want &want, int requestCode, const AbilityStartSetting &abilityStartSetting) = 0; + virtual bool ConnectAbility(const Want &want, const sptr &conn) = 0; + virtual void DisconnectAbility(const sptr &conn) = 0; + virtual Uri GetCaller() = 0; + virtual std::string GetString(int resId) = 0; + virtual std::vector GetStringArray(int resId) = 0; + virtual std::vector GetIntArray(int resId) = 0; + virtual std::map GetTheme() = 0; + virtual void SetTheme(int themeId) = 0; + virtual std::map GetPattern() = 0; + virtual int GetColor(int resId) = 0; + virtual int GetThemeId() = 0; + virtual bool TerminateAbilityResult(int startId) = 0; + virtual int GetDisplayOrientation() = 0; + virtual std::string GetPreferencesDir() = 0; + virtual void SetColorMode(int mode) = 0; + virtual int GetColorMode() = 0; + virtual int GetMissionId() = 0; + virtual void TerminateAndRemoveMission() = 0; + virtual void StartAbilities(const std::vector &wants) = 0; + virtual bool IsFirstInMission() = 0; + virtual std::shared_ptr GetUITaskDispatcher() = 0; + virtual std::shared_ptr GetMainTaskDispatcher() = 0; + virtual std::shared_ptr CreateParallelTaskDispatcher( + const std::string &name, const TaskPriority &priority) = 0; + virtual std::shared_ptr CreateSerialTaskDispatcher( + const std::string &name, const TaskPriority &priority) = 0; + virtual std::shared_ptr GetGlobalTaskDispatcher(const TaskPriority &priority) = 0; + friend DataAbilityHelper; + friend ContinuationConnector; +protected: + virtual sptr GetToken() = 0; +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_APPEXECFWK_OHOS_CONTEXT_H diff --git a/tools/services/test/mock/include/mock_want_receiver.h b/tools/services/test/mock/include/mock_want_receiver.h new file mode 100644 index 00000000000..17b528b56b4 --- /dev/null +++ b/tools/services/test/mock/include/mock_want_receiver.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "want_receiver_interface.h" +#include "cancel_listener.h" +#include "gmock/gmock.h" + +namespace OHOS { +namespace AAFwk { +class MockWantReceiver : public IWantReceiver { +public: + MOCK_METHOD1(Send, void(const int32_t resultCode)); + MOCK_METHOD0(AsObject, sptr()); + MOCK_METHOD7(PerformReceive, void(const Want &want, int resultCode, const std::string &data, + const WantParams &extras, bool serialized, bool sticky, int sendingUser)); +}; + +class MockCancelListener : public Notification::WantAgent::CancelListener { +public: + MOCK_METHOD1(OnCancelled, void(int resultCode)); +}; +} // namespace AAFwk +} // namespace OHOS diff --git a/tools/services/test/mock/include/system_ability.h b/tools/services/test/mock/include/system_ability.h new file mode 100644 index 00000000000..585e22b8805 --- /dev/null +++ b/tools/services/test/mock/include/system_ability.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_AAFWK_SERVICES_TEST_MOCK_SYSTEM_ABILITY_H +#define FOUNDATION_AAFWK_SERVICES_TEST_MOCK_SYSTEM_ABILITY_H + +#include "hilog/log.h" +#include "iremote_object.h" +namespace OHOS { +#define REGISTER_SYSTEM_ABILITY_BY_ID(a, b, c) +#define REGISTER_SYSTEM_ABILITY(abilityClassName, abilityId, runOnCreate) +#define DECLEAR_SYSTEM_ABILITY(className) +static constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, 0xD001100, "MockSystemAbility"}; + +class SystemAbility { +public: + static bool MakeAndRegisterAbility(SystemAbility *) + { + return true; + } + +protected: + virtual void OnStart() + { + HiviewDFX::HiLog::Debug(LABEL, "Mock SystemAbility OnStart called"); + } + + virtual void OnStop() + { + HiviewDFX::HiLog::Debug(LABEL, "Mock SystemAbility OnStop called"); + } + + bool Publish(sptr systemAbility) + { + HiviewDFX::HiLog::Debug(LABEL, "Mock SystemAbility Publish called"); + systemAbility.ForceSetRefPtr(nullptr); + return true; + } + + explicit SystemAbility(bool runOnCreate = false) + { + HiviewDFX::HiLog::Debug(LABEL, "Mock SystemAbility default Creator called %d", runOnCreate); + } + + SystemAbility(const int32_t serviceId, bool runOnCreate = false) + { + HiviewDFX::HiLog::Debug(LABEL, "Mock SystemAbility Creator called %d", runOnCreate); + } + + virtual ~SystemAbility() + { + HiviewDFX::HiLog::Debug(LABEL, "Mock SystemAbility Destructor called"); + } +}; +} // namespace OHOS +#endif // FOUNDATION_AAFWK_SERVICES_TEST_MOCK_SYSTEM_ABILITY_H diff --git a/tools/services/test/mock/src/mock_app_mgr_client.cpp b/tools/services/test/mock/src/mock_app_mgr_client.cpp new file mode 100644 index 00000000000..ed8dd2251ea --- /dev/null +++ b/tools/services/test/mock/src/mock_app_mgr_client.cpp @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "mock_app_mgr_client.h" + +namespace OHOS { +namespace AppExecFwk { + +MockAppMgrClient::MockAppMgrClient() +{} +MockAppMgrClient::~MockAppMgrClient() +{} + +AppMgrResultCode MockAppMgrClient::AbilityBehaviorAnalysis(const sptr &token, + const sptr &preToken, const int32_t visibility, const int32_t perceptibility, + const int32_t connectionState) +{ + return AppMgrResultCode::RESULT_OK; +} + +AppMgrResultCode MockAppMgrClient::ConnectAppMgrService() +{ + return AppMgrResultCode::RESULT_OK; +} + +AppMgrResultCode MockAppMgrClient::RegisterAppStateCallback(const sptr &callback) +{ + return AppMgrResultCode::RESULT_OK; +} + +} // namespace AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/test/mock/src/mock_bundle_mgr.cpp b/tools/services/test/mock/src/mock_bundle_mgr.cpp new file mode 100755 index 00000000000..d2c836dc9f3 --- /dev/null +++ b/tools/services/test/mock/src/mock_bundle_mgr.cpp @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "mock_bundle_mgr.h" +#include "ability_info.h" +#include "application_info.h" +#include "hilog_wrapper.h" +#include "ability_config.h" +using namespace OHOS::AAFwk; + +namespace OHOS { +namespace AppExecFwk { + +int BundleMgrProxy::QueryWantAbility( + const AAFwk::Want &__attribute__((unused)) want, std::vector &__attribute__((unused)) abilityInfos) +{ + return 0; +} + +bool BundleMgrProxy::QueryAbilityInfo(const AAFwk::Want &want, AbilityInfo &abilityInfo) +{ + ElementName eleName = want.GetElement(); + if (eleName.GetBundleName().empty()) { + return false; + } + abilityInfo.visible = true; + abilityInfo.name = eleName.GetAbilityName(); + abilityInfo.bundleName = eleName.GetBundleName(); + abilityInfo.applicationName = eleName.GetAbilityName() + "App"; + if (abilityInfo.bundleName != "com.ix.hiworld") { + abilityInfo.applicationInfo.isLauncherApp = false; + } + return true; +} + +bool BundleMgrProxy::GetBundleInfo(const std::string &bundleName, const BundleFlag flag, BundleInfo &bundleInfo) +{ + return true; +} + +bool BundleMgrProxy::QueryAbilityInfoByUri(const std::string &uri, AbilityInfo &abilityInfo) +{ + return false; +} + +bool BundleMgrProxy::GetApplicationInfo( + const std::string &appName, const ApplicationFlag flag, const int userId, ApplicationInfo &appInfo) +{ + if (appName.empty()) { + return false; + } + appInfo.name = "Helloworld"; + appInfo.bundleName = "com.ix.hiworld"; + return true; +} + +int BundleMgrStub::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) +{ + return 0; +} + +bool BundleMgrService::GetBundleInfo(const std::string &bundleName, const BundleFlag flag, BundleInfo &bundleInfo) +{ + bundleInfo.uid = 0; + return true; +} + +bool BundleMgrService::QueryAbilityInfo(const AAFwk::Want &want, AbilityInfo &abilityInfo) +{ + if (CheckWantEntity(want, abilityInfo)) { + return true; + } + + ElementName elementTemp = want.GetElement(); + std::string abilityNameTemp = elementTemp.GetAbilityName(); + std::string bundleNameTemp = elementTemp.GetBundleName(); + abilityInfo.deviceId = elementTemp.GetDeviceID(); + abilityInfo.visible = true; + + if (bundleNameTemp.empty() || abilityNameTemp.empty()) { + return false; + } + + auto fun = abilityInfoMap_.find(bundleNameTemp); + if (fun != abilityInfoMap_.end()) { + auto call = fun->second; + if (call) { + call(bundleNameTemp, abilityInfo, elementTemp); + return true; + } + } + if (std::string::npos != elementTemp.GetBundleName().find("service")) { + abilityInfo.type = AppExecFwk::AbilityType::SERVICE; + } + abilityInfo.name = elementTemp.GetAbilityName(); + abilityInfo.bundleName = elementTemp.GetBundleName(); + abilityInfo.applicationName = elementTemp.GetBundleName(); + abilityInfo.deviceId = elementTemp.GetDeviceID(); + abilityInfo.applicationInfo.bundleName = elementTemp.GetBundleName(); + abilityInfo.applicationInfo.name = "hello"; + if (want.HasEntity(Want::ENTITY_HOME) && want.GetAction() == Want::ACTION_HOME) { + abilityInfo.applicationInfo.isLauncherApp = true; + } else { + abilityInfo.applicationInfo.isLauncherApp = false; + abilityInfo.applicationInfo.iconPath = "icon path"; + abilityInfo.applicationInfo.label = "app label"; + } + return true; +} + +bool BundleMgrService::GetApplicationInfo( + const std::string &appName, const ApplicationFlag flag, const int userId, ApplicationInfo &appInfo) +{ + if (appName.empty()) { + return false; + } + return true; +} + +bool BundleMgrService::CheckWantEntity(const AAFwk::Want &want, AbilityInfo &abilityInfo) +{ + auto entityVector = want.GetEntities(); + ElementName element = want.GetElement(); + + auto find = false; + // filter ams onstart + for (const auto &entity : entityVector) { + if (entity == Want::FLAG_HOME_INTENT_FROM_SYSTEM && element.GetAbilityName().empty() && + element.GetBundleName().empty()) { + find = true; + break; + } + } + + auto bundleName = element.GetBundleName(); + auto abilityName = element.GetAbilityName(); + if (find || (bundleName == AbilityConfig::SYSTEM_UI_BUNDLE_NAME && + (abilityName == AbilityConfig::SYSTEM_UI_STATUS_BAR || + abilityName == AbilityConfig::SYSTEM_UI_NAVIGATION_BAR))) { + return true; + } + + return false; +} + +bool BundleMgrService::NotifyActivityLifeStatus( + const std::string &bundleName, const std::string &abilityName, const int64_t launchTime) +{ + return true; +} + +bool BundleMgrService::CheckIsSystemAppByUid(const int uid) +{ + int maxSysUid{MAX_SYS_UID}; + int baseSysUid{ROOT_UID}; + if (uid >= baseSysUid && uid <= maxSysUid) { + return true; + } + return false; +} +} // namespace AppExecFwk +} // namespace OHOS diff --git a/tools/services/test/moduletest/ability_mgr_service_test/BUILD.gn b/tools/services/test/moduletest/ability_mgr_service_test/BUILD.gn new file mode 100755 index 00000000000..559db5bdfbe --- /dev/null +++ b/tools/services/test/moduletest/ability_mgr_service_test/BUILD.gn @@ -0,0 +1,118 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/test.gni") +import("//foundation/aafwk/standard/aafwk.gni") + +module_output_path = "aafwk_standard/mstabilitymgrservice" + +ohos_moduletest("ability_mgr_module_test") { + module_out_path = module_output_path + + include_dirs = [ + "${services_path}/test/mock/include", + "//third_party/jsoncpp/include", + "//foundation/aafwk/standard/interfaces/innerkits/dataobs_manager/include", + ] + + sources = [ "ability_mgr_module_test.cpp" ] + sources += [ + "//foundation/aafwk/standard/services/abilitymgr/src/aafwk_dummy_configuration.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/ability_connect_callback_stub.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/ability_connect_manager.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/ability_event_handler.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/ability_manager_proxy.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/ability_manager_service.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/ability_manager_stub.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/ability_mission_info.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/ability_record.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/ability_record_info.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/ability_scheduler_proxy.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/ability_scheduler_stub.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/ability_stack_manager.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/ability_token_stub.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/app_scheduler.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/caller_info.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/connection_record.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/data_ability_manager.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/data_ability_record.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/image_info.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/kernal_system_app_manager.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/lifecycle_deal.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/lifecycle_state_info.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/mission_description_info.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/mission_option.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/mission_record.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/mission_record_info.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/mission_snapshot_info.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/mission_stack.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/mission_stack_info.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/pending_want_key.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/pending_want_manager.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/pending_want_record.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/power_storage.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/sender_info.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/stack_info.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/want_receiver_stub.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/want_sender_info.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/want_sender_stub.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/wants_info.cpp", + "//foundation/aafwk/standard/services/abilitymgr/test/mock/libs/sa_mgr/src/sa_mgr_client_mock.cpp", + "//foundation/aafwk/standard/services/test/mock/src/mock_app_mgr_client.cpp", + "//foundation/aafwk/standard/services/test/mock/src/mock_bundle_mgr.cpp", + ] + + configs = [ + "${services_path}/test:aafwk_module_test_config", + "//foundation/aafwk/standard/interfaces/innerkits/ability_manager:ability_manager_public_config", + "//foundation/aafwk/standard/services/abilitymgr/test/mock/libs/sa_mgr:sa_mgr_mock_config", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base_sdk_config", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_core:appmgr_sdk_config", + ] + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + deps = [ + "${innerkits_path}/want:want", + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/frameworks/kits/ability/native:dummy_classes", + "//foundation/aafwk/standard/services/abilitymgr:abilityms", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_core:appexecfwk_core", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//foundation/distributedschedule/safwk/interfaces/innerkits/safwk:system_ability_fwk", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy:samgr_proxy", + "//third_party/googletest:gmock_main", + "//third_party/googletest:gtest_main", + "//third_party/jsoncpp:jsoncpp", + "//utils/native/base:utils", + ] + + external_deps = [ + "ces_standard:cesfwk_core", + "ces_standard:cesfwk_innerkits", + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + "native_appdatamgr:native_appdatafwk", + "native_appdatamgr:native_dataability", + "native_appdatamgr:native_rdb", + ] +} + +group("moduletest") { + testonly = true + + deps = [ ":ability_mgr_module_test" ] +} diff --git a/tools/services/test/moduletest/ability_mgr_service_test/ability_mgr_module_test.cpp b/tools/services/test/moduletest/ability_mgr_service_test/ability_mgr_module_test.cpp new file mode 100644 index 00000000000..eb7a6108b94 --- /dev/null +++ b/tools/services/test/moduletest/ability_mgr_service_test/ability_mgr_module_test.cpp @@ -0,0 +1,1688 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +#include +#include + +#define private public +#define protected public +#include "sa_mgr_client.h" +#include "mock_ability_connect_callback_stub.h" +#include "mock_ability_scheduler.h" +#include "mock_app_mgr_client.h" +#include "mock_bundle_mgr.h" +#include "ability_record_info.h" +#include "ability_manager_errors.h" +#include "sa_mgr_client.h" +#include "system_ability_definition.h" +#include "ability_manager_service.h" +#include "ability_connect_callback_proxy.h" +#include "ability_config.h" +#undef private +#undef protected + +using namespace std::placeholders; +using namespace testing::ext; +using namespace OHOS::AppExecFwk; +using OHOS::iface_cast; +using OHOS::IRemoteObject; +using OHOS::sptr; +using testing::_; +using testing::Invoke; +using testing::Return; + +namespace OHOS { +namespace AAFwk { +class AbilityMgrModuleTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + Want CreateWant(const std::string &entity); + AbilityInfo CreateAbilityInfo(const std::string &name, const std::string &appName, const std::string &bundleName); + ApplicationInfo CreateAppInfo(const std::string &appName, const std::string &name); + Want CreateWant(const std::string &abilityName, const std::string &bundleName); + void WaitAMS(); + std::shared_ptr GreatePageAbility(const std::string &abilityName, const std::string &bundleName); + void MockAbilityTransitionDone(bool &testFailed, sptr &dataAbilityToken, + sptr &mockDataAbilityScheduler, std::shared_ptr &abilityMgrServ); + void MockDataAbilityLoadHandlerInner(bool &testFailed, sptr &dataAbilityToken, + sptr &mockDataAbilityScheduler, std::shared_ptr &abilityMgrServ); + void CreateAbilityRequest(const std::string &abilityName, const std::string bundleName, Want &want, + std::shared_ptr &curMissionStack, sptr &recordToken); + void MockServiceAbilityLoadHandlerInner(bool &testResult, const std::string &bundleName, + const std::string &abilityName, sptr &testToken); + void CreateServiceRecord(std::shared_ptr &record, Want &want, + const sptr &callback1, const sptr &callback2); + void CheckTestRecord(std::shared_ptr &record1, std::shared_ptr &record2, + const sptr &callback1, const sptr &callback2); + void MockLoadHandlerInner(int &testId, sptr &scheduler); + bool MockAppClent(); + void SetActive(); + std::shared_ptr GetTopAbility(); + void ClearStack(); + + inline static std::shared_ptr mockAppMgrClient_{nullptr}; + inline static std::shared_ptr abilityMgrServ_{nullptr}; + sptr scheduler_{nullptr}; + inline static bool doOnce_ = false; // In order for mock to execute once + + static constexpr int TEST_WAIT_TIME = 100000; +}; + +void AbilityMgrModuleTest::SetActive() +{ + if (!abilityMgrServ_) { + return; + } + + auto stackMgr = abilityMgrServ_->GetStackManager(); + if (stackMgr) { + auto topAbility = stackMgr->GetCurrentTopAbility(); + if (topAbility) { + topAbility->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + } + } +} + +std::shared_ptr AbilityMgrModuleTest::GetTopAbility() +{ + if (!abilityMgrServ_) { + return nullptr; + } + auto stackMgr = abilityMgrServ_->GetStackManager(); + if (stackMgr) { + auto topAbility = stackMgr->GetCurrentTopAbility(); + if (topAbility) { + return topAbility; + } + } + return nullptr; +} + +void AbilityMgrModuleTest::ClearStack() +{ + if (!abilityMgrServ_) { + return; + } + auto stackMgr = abilityMgrServ_->GetStackManager(); + if (stackMgr) { + auto topAbility = stackMgr->GetCurrentTopAbility(); + stackMgr->missionStackList_.front()->RemoveAll(); + } +} + +bool AbilityMgrModuleTest::MockAppClent() +{ + if (!mockAppMgrClient_) { + GTEST_LOG_(INFO) << "MockAppClent::1"; + return false; + } + + if (!abilityMgrServ_->appScheduler_) { + GTEST_LOG_(INFO) << "MockAppClent::2"; + return false; + } + + abilityMgrServ_->appScheduler_->appMgrClient_.reset(mockAppMgrClient_.get()); + return true; +} + +void AbilityMgrModuleTest::SetUpTestCase(void) +{ + OHOS::DelayedSingleton::DestroyInstance(); + OHOS::DelayedSingleton::GetInstance()->RegisterSystemAbility( + OHOS::BUNDLE_MGR_SERVICE_SYS_ABILITY_ID, new (std::nothrow) BundleMgrService()); + + abilityMgrServ_ = OHOS::DelayedSingleton::GetInstance(); + mockAppMgrClient_ = std::make_shared(); +} + +void AbilityMgrModuleTest::TearDownTestCase(void) +{ + OHOS::DelayedSingleton::DestroyInstance(); + abilityMgrServ_.reset(); + mockAppMgrClient_.reset(); +} +void AbilityMgrModuleTest::SetUp(void) +{ + scheduler_ = new MockAbilityScheduler(); + if (!doOnce_) { + doOnce_ = true; + + MockAppClent(); + } + auto state = abilityMgrServ_->QueryServiceState(); + if (state != ServiceRunningState::STATE_RUNNING) { + abilityMgrServ_->OnStart(); + } + + WaitAMS(); +} + +void AbilityMgrModuleTest::TearDown(void) +{} + +Want AbilityMgrModuleTest::CreateWant(const std::string &entity) +{ + Want want; + if (!entity.empty()) { + want.AddEntity(entity); + } + return want; +} + +AbilityInfo AbilityMgrModuleTest::CreateAbilityInfo( + const std::string &name, const std::string &appName, const std::string &bundleName) +{ + AbilityInfo abilityInfo; + abilityInfo.visible = true; + abilityInfo.name = name; + abilityInfo.applicationName = appName; + abilityInfo.bundleName = bundleName; + abilityInfo.applicationInfo.bundleName = bundleName; + abilityInfo.applicationName = "hiMusic"; + abilityInfo.applicationInfo.name = "hiMusic"; + abilityInfo.type = AbilityType::PAGE; + abilityInfo.applicationInfo.isLauncherApp = false; + + return abilityInfo; +} + +ApplicationInfo AbilityMgrModuleTest::CreateAppInfo(const std::string &appName, const std::string &bundleName) +{ + ApplicationInfo appInfo; + appInfo.name = appName; + appInfo.bundleName = bundleName; + + return appInfo; +} + +Want AbilityMgrModuleTest::CreateWant(const std::string &abilityName, const std::string &bundleName) +{ + ElementName element; + element.SetDeviceID("devices"); + element.SetAbilityName(abilityName); + element.SetBundleName(bundleName); + Want want; + want.SetElement(element); + return want; +} + +std::shared_ptr AbilityMgrModuleTest::GreatePageAbility( + const std::string &abilityName, const std::string &bundleName) +{ + Want want = CreateWant(abilityName, bundleName); + EXPECT_CALL(*mockAppMgrClient_, LoadAbility(_, _, _, _)).Times(1).WillOnce(Return(AppMgrResultCode::RESULT_OK)); + int testRequestCode = 1; + SetActive(); + abilityMgrServ_->StartAbility(want, testRequestCode); + WaitAMS(); + + auto stack = abilityMgrServ_->GetStackManager(); + if (!stack) { + return nullptr; + } + auto topAbility = stack->GetCurrentTopAbility(); + if (!topAbility) { + return nullptr; + } + topAbility->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + + return topAbility; +} + +void AbilityMgrModuleTest::MockAbilityTransitionDone(bool &testFailed, sptr &dataAbilityToken, + sptr &mockDataAbilityScheduler, std::shared_ptr &abilityMgrServ) +{ + auto mockAbilityTransation = [&testFailed, &dataAbilityToken, &abilityMgrServ]( + const Want &want, const LifeCycleStateInfo &targetState) { + testFailed = testFailed || (targetState.state != ABILITY_STATE_ACTIVE); + std::thread(&AbilityManagerService::AbilityTransitionDone, abilityMgrServ.get(), dataAbilityToken, ACTIVE) + .detach(); + }; + + EXPECT_CALL(*mockDataAbilityScheduler, ScheduleAbilityTransaction(_, _)) + .Times(1) + .WillOnce(Invoke(mockAbilityTransation)); +} + +void AbilityMgrModuleTest::MockDataAbilityLoadHandlerInner(bool &testFailed, sptr &dataAbilityToken, + sptr &mockDataAbilityScheduler, std::shared_ptr &abilityMgrServ) +{ + // MOCK: data ability load handler + + auto mockLoadAbility = [&testFailed, &dataAbilityToken, &mockDataAbilityScheduler, &abilityMgrServ]( + const sptr &token, + const sptr &preToken, + const AbilityInfo &abilityInfo, + const ApplicationInfo &appInfo) { + dataAbilityToken = token; + testFailed = testFailed || (abilityInfo.type != AbilityType::DATA); + std::thread(&AbilityManagerService::AttachAbilityThread, abilityMgrServ.get(), mockDataAbilityScheduler, token) + .detach(); + return AppMgrResultCode::RESULT_OK; + }; + + EXPECT_CALL(*mockAppMgrClient_, LoadAbility(_, _, _, _)).Times(1).WillOnce(Invoke(mockLoadAbility)); + int counts = 2; + EXPECT_CALL(*mockAppMgrClient_, UpdateAbilityState(_, _)) + .Times(counts) + .WillOnce(Invoke([&testFailed](const sptr &token, const OHOS::AppExecFwk::AbilityState state) { + testFailed = testFailed || (state != OHOS::AppExecFwk::AbilityState::ABILITY_STATE_FOREGROUND); + return AppMgrResultCode::RESULT_OK; + })) + .WillOnce(Invoke([&testFailed](const sptr &token, const OHOS::AppExecFwk::AbilityState state) { + testFailed = testFailed || (state != OHOS::AppExecFwk::AbilityState::ABILITY_STATE_BACKGROUND); + return AppMgrResultCode::RESULT_OK; + })); +} + +void AbilityMgrModuleTest::CreateAbilityRequest(const std::string &abilityName, const std::string bundleName, + Want &want, std::shared_ptr &curMissionStack, sptr &recordToken) +{ + Want want2 = CreateWant(abilityName, bundleName); + AbilityRequest abilityRequest2; + abilityRequest2.want = want2; + abilityRequest2.abilityInfo.type = OHOS::AppExecFwk::AbilityType::PAGE; + abilityRequest2.abilityInfo = CreateAbilityInfo(abilityName, bundleName, bundleName); + + std::shared_ptr abilityRecord2 = AbilityRecord::CreateAbilityRecord(abilityRequest2); + abilityRecord2->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + std::shared_ptr mission = std::make_shared(bundleName); + mission->AddAbilityRecordToTop(abilityRecord2); + auto stackManager_ = abilityMgrServ_->GetStackManager(); + curMissionStack = stackManager_->GetCurrentMissionStack(); + curMissionStack->AddMissionRecordToTop(mission); + recordToken = abilityRecord2->GetToken(); + + want = CreateWant(abilityName + "_service", bundleName + "_service"); + AbilityRequest abilityRequest; + abilityRequest.want = want; + abilityRequest.abilityInfo = + CreateAbilityInfo(abilityName + "_service", bundleName + "_service", bundleName + "_service"); + abilityRequest.abilityInfo.type = OHOS::AppExecFwk::AbilityType::SERVICE; + abilityRequest.appInfo = CreateAppInfo(bundleName + "_service", bundleName + "_service"); + abilityMgrServ_->RemoveAllServiceRecord(); +} + +void AbilityMgrModuleTest::MockServiceAbilityLoadHandlerInner( + bool &testResult, const std::string &bundleName, const std::string &abilityName, sptr &testToken) +{ + auto mockHandler = [&testResult, &bundleName, &abilityName, &testToken](const sptr &token, + const sptr &preToken, + const AbilityInfo &abilityInfo, + const ApplicationInfo &appInfo) { + testToken = token; + testResult = !!testToken && abilityInfo.bundleName == bundleName && abilityInfo.name == abilityName && + appInfo.bundleName == bundleName; + return AppMgrResultCode::RESULT_OK; + }; + + EXPECT_CALL(*mockAppMgrClient_, LoadAbility(_, _, _, _)).Times(1).WillOnce(Invoke(mockHandler)); +} + +void AbilityMgrModuleTest::CreateServiceRecord(std::shared_ptr &record, Want &want, + const sptr &callback1, const sptr &callback2) +{ + record = abilityMgrServ_->connectManager_->GetServiceRecordByElementName(want.GetElement().GetURI()); + EXPECT_TRUE(record); + EXPECT_TRUE(abilityMgrServ_->connectManager_->IsAbilityConnected( + record, abilityMgrServ_->GetConnectRecordListByCallback(callback1))); + EXPECT_TRUE(abilityMgrServ_->connectManager_->IsAbilityConnected( + record, abilityMgrServ_->GetConnectRecordListByCallback(callback2))); + int size = 2; + EXPECT_EQ((std::size_t)size, record->GetConnectRecordList().size()); + record->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); +} + +void AbilityMgrModuleTest::CheckTestRecord(std::shared_ptr &record1, + std::shared_ptr &record2, const sptr &callback1, + const sptr &callback2) +{ + int size = 2; + int counts = 2; + EXPECT_EQ((std::size_t)1, record1->GetConnectRecordList().size()); + EXPECT_EQ((std::size_t)1, record2->GetConnectRecordList().size()); + EXPECT_EQ((std::size_t)0, abilityMgrServ_->GetConnectRecordListByCallback(callback1).size()); + EXPECT_EQ((std::size_t)size, abilityMgrServ_->connectManager_->GetServiceMap().size()); + + abilityMgrServ_->DisconnectAbility(callback2); + + abilityMgrServ_->ScheduleDisconnectAbilityDone(record1->GetToken()); + abilityMgrServ_->ScheduleDisconnectAbilityDone(record2->GetToken()); + EXPECT_EQ((std::size_t)0, record1->GetConnectRecordList().size()); + EXPECT_EQ((std::size_t)0, record2->GetConnectRecordList().size()); + EXPECT_EQ((std::size_t)0, abilityMgrServ_->GetConnectRecordListByCallback(callback2).size()); + + EXPECT_CALL(*mockAppMgrClient_, UpdateAbilityState(_, _)).Times(counts); + abilityMgrServ_->AbilityTransitionDone(record1->GetToken(), AbilityLifeCycleState::ABILITY_STATE_INITIAL); + abilityMgrServ_->AbilityTransitionDone(record2->GetToken(), AbilityLifeCycleState::ABILITY_STATE_INITIAL); + EXPECT_EQ(OHOS::AAFwk::AbilityState::TERMINATING, record1->GetAbilityState()); + EXPECT_EQ(OHOS::AAFwk::AbilityState::TERMINATING, record2->GetAbilityState()); + + EXPECT_CALL(*mockAppMgrClient_, TerminateAbility(_)).Times(counts); + abilityMgrServ_->OnAbilityRequestDone( + record1->GetToken(), (int32_t)OHOS::AppExecFwk::AbilityState::ABILITY_STATE_BACKGROUND); + abilityMgrServ_->OnAbilityRequestDone( + record2->GetToken(), (int32_t)OHOS::AppExecFwk::AbilityState::ABILITY_STATE_BACKGROUND); + EXPECT_EQ((std::size_t)0, abilityMgrServ_->connectManager_->GetServiceMap().size()); + EXPECT_EQ((std::size_t)0, abilityMgrServ_->connectManager_->GetConnectMap().size()); +} + +void AbilityMgrModuleTest::MockLoadHandlerInner(int &testId, sptr &scheduler) +{ + auto handler = [&testId](const Want &want, bool restart, int startid) { testId = startid; }; + int counts = 3; + EXPECT_CALL(*scheduler, ScheduleCommandAbility(_, _, _)) + .Times(counts) + .WillOnce(Invoke(handler)) + .WillOnce(Invoke(handler)) + .WillOnce(Invoke(handler)); +} + +void AbilityMgrModuleTest::WaitAMS() +{ + const uint32_t maxRetryCount = 1000; + const uint32_t sleepTime = 1000; + uint32_t count = 0; + if (!abilityMgrServ_) { + return; + } + auto handler = abilityMgrServ_->GetEventHandler(); + if (!handler) { + return; + } + std::atomic taskCalled(false); + auto f = [&taskCalled]() { taskCalled.store(true); }; + if (handler->PostTask(f)) { + while (!taskCalled.load()) { + ++count; + if (count >= maxRetryCount) { + break; + } + usleep(sleepTime); + } + } +} + +/* + * Feature: AaFwk + * Function: ability manager service + * SubFunction: NA + * FunctionPoints: NA + * EnvConditions: NA + * CaseDescription: start ability. + */ +HWTEST_F(AbilityMgrModuleTest, ability_mgr_service_test_001, TestSize.Level1) +{ + EXPECT_TRUE(abilityMgrServ_); + EXPECT_TRUE(mockAppMgrClient_); + + auto stackManager = abilityMgrServ_->GetStackManager(); + EXPECT_TRUE(stackManager); + + std::string abilityName = "MusicAbility"; + std::string bundleName = "com.ix.hiMusic"; + Want want = CreateWant(abilityName, bundleName); + bool testResult = false; + sptr testToken; + + auto mockHandler = [&](const sptr &token, + const sptr &preToken, + const AbilityInfo &abilityInfo, + const ApplicationInfo &appInfo) { + testToken = token; + testResult = !!testToken && abilityInfo.bundleName == bundleName && abilityInfo.name == abilityName && + appInfo.bundleName == bundleName; + return AppMgrResultCode::RESULT_OK; + }; + + EXPECT_CALL(*mockAppMgrClient_, LoadAbility(_, _, _, _)).Times(1).WillOnce(Invoke(mockHandler)); + + int testRequestCode = 123; + abilityMgrServ_->StartAbility(want, testRequestCode); + + EXPECT_TRUE(testResult); + EXPECT_TRUE(testToken); + + auto testAbilityRecord = stackManager->GetAbilityRecordByToken(testToken); + EXPECT_TRUE(testAbilityRecord); + EXPECT_EQ(testAbilityRecord->GetRequestCode(), testRequestCode); +} + +/* + * Feature: AaFwk + * Function: ability manager service + * SubFunction: NA + * FunctionPoints: NA + * EnvConditions: NA + * CaseDescription: terminate ability. + */ +HWTEST_F(AbilityMgrModuleTest, ability_mgr_service_test_002, TestSize.Level1) +{ + std::string abilityName = "MusicAbility"; + std::string appName = "test_app"; + std::string bundleName = "com.ix.hiMusic"; + + AbilityRequest abilityRequest; + abilityRequest.want = CreateWant(""); + abilityRequest.abilityInfo = CreateAbilityInfo(abilityName + "1", appName, bundleName); + abilityRequest.appInfo = CreateAppInfo(appName, bundleName); + + std::shared_ptr abilityRecord = AbilityRecord::CreateAbilityRecord(abilityRequest); + abilityRecord->SetAbilityState(OHOS::AAFwk::AbilityState::INACTIVE); + + abilityRequest.abilityInfo = CreateAbilityInfo(abilityName + "2", appName, bundleName); + std::shared_ptr abilityRecord2 = AbilityRecord::CreateAbilityRecord(abilityRequest); + abilityRecord2->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + sptr scheduler = new MockAbilityScheduler(); + EXPECT_TRUE(scheduler); + EXPECT_CALL(*scheduler, AsObject()).Times(2); + abilityRecord2->SetScheduler(scheduler); + + EXPECT_CALL(*scheduler, ScheduleAbilityTransaction(_, _)).Times(1); + std::shared_ptr mission = std::make_shared(bundleName); + mission->AddAbilityRecordToTop(abilityRecord); + mission->AddAbilityRecordToTop(abilityRecord2); + abilityRecord2->SetMissionRecord(mission); + + auto stackManager_ = abilityMgrServ_->GetStackManager(); + std::shared_ptr curMissionStack = stackManager_->GetCurrentMissionStack(); + curMissionStack->AddMissionRecordToTop(mission); + + int result = abilityMgrServ_->TerminateAbility(abilityRecord2->GetToken(), -1, nullptr); + EXPECT_EQ(OHOS::AAFwk::AbilityState::INACTIVATING, abilityRecord2->GetAbilityState()); + EXPECT_EQ(1, mission->GetAbilityRecordCount()); + EXPECT_EQ(OHOS::ERR_OK, result); +} + +/* + * Feature: AaFwk + * Function: ability manager service + * SubFunction: NA + * FunctionPoints: NA + * EnvConditions: NA + * CaseDescription: connect ability. + */ +HWTEST_F(AbilityMgrModuleTest, ability_mgr_service_test_003, TestSize.Level1) +{ + std::string abilityName = "MusicAbility"; + std::string bundleName = "com.ix.hiMusic"; + + Want want2 = CreateWant(abilityName, bundleName); + AbilityRequest abilityRequest2; + abilityRequest2.want = want2; + abilityRequest2.abilityInfo.type = OHOS::AppExecFwk::AbilityType::PAGE; + abilityRequest2.abilityInfo = CreateAbilityInfo(abilityName, bundleName, bundleName); + std::shared_ptr abilityRecord2 = AbilityRecord::CreateAbilityRecord(abilityRequest2); + abilityRecord2->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + std::shared_ptr mission = std::make_shared(bundleName); + mission->AddAbilityRecordToTop(abilityRecord2); + auto stackManager_ = abilityMgrServ_->GetStackManager(); + std::shared_ptr curMissionStack = stackManager_->GetCurrentMissionStack(); + curMissionStack->AddMissionRecordToTop(mission); + + Want want = CreateWant(abilityName + "_service", bundleName + "_service"); + AbilityRequest abilityRequest; + abilityRequest.want = want; + abilityRequest.abilityInfo = CreateAbilityInfo(abilityName + "_service", bundleName, bundleName + "_service"); + abilityRequest.abilityInfo.type = OHOS::AppExecFwk::AbilityType::SERVICE; + abilityRequest.appInfo = CreateAppInfo(bundleName, bundleName + "_service"); + std::shared_ptr abilityRecord = AbilityRecord::CreateAbilityRecord(abilityRequest); + abilityRecord->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + + abilityMgrServ_->RemoveAllServiceRecord(); + sptr stub(new MockAbilityConnectCallbackStub()); + const sptr callback(new AbilityConnectionProxy(stub)); + std::shared_ptr connectRecord = + ConnectionRecord::CreateConnectionRecord(abilityRecord->GetToken(), abilityRecord, callback); + EXPECT_TRUE(connectRecord != nullptr); + connectRecord->SetConnectState(ConnectionState::CONNECTED); + abilityRecord->AddConnectRecordToList(connectRecord); + std::list > connectList; + connectList.push_back(connectRecord); + abilityMgrServ_->connectManager_->connectMap_.emplace(callback->AsObject(), connectList); + abilityMgrServ_->connectManager_->serviceMap_.emplace(abilityRequest.want.GetElement().GetURI(), abilityRecord); + + int result = abilityMgrServ_->ConnectAbility(want, callback, abilityRecord2->GetToken()); + EXPECT_EQ(OHOS::ERR_OK, result); + EXPECT_EQ((std::size_t)1, abilityMgrServ_->connectManager_->connectMap_.size()); + EXPECT_EQ((std::size_t)1, abilityMgrServ_->connectManager_->serviceMap_.size()); + + abilityMgrServ_->RemoveAllServiceRecord(); + curMissionStack->RemoveAll(); + + testing::Mock::AllowLeak(stub); + testing::Mock::AllowLeak(callback); +} + +/* + * Feature: AaFwk + * Function: ability manager service + * SubFunction: OnStart/OnStop + * FunctionPoints: NA + * EnvConditions: NA + * CaseDescription: OnStart/OnStop + */ +HWTEST_F(AbilityMgrModuleTest, ability_mgr_service_test_004, TestSize.Level1) +{ + // It's turned on during initialization, so it's turned off here + abilityMgrServ_->OnStop(); + + auto state = abilityMgrServ_->QueryServiceState(); + EXPECT_EQ(state, ServiceRunningState::STATE_NOT_START); + + abilityMgrServ_->OnStart(); + WaitAMS(); + + EXPECT_TRUE(abilityMgrServ_->dataAbilityManager_); + state = abilityMgrServ_->QueryServiceState(); + EXPECT_EQ(state, ServiceRunningState::STATE_RUNNING); + + auto handler = abilityMgrServ_->GetEventHandler(); + EXPECT_TRUE(handler); + auto eventRunner = handler->GetEventRunner(); + EXPECT_TRUE(eventRunner); + EXPECT_TRUE(eventRunner->IsRunning()); + + abilityMgrServ_->OnStop(); + + state = abilityMgrServ_->QueryServiceState(); + EXPECT_EQ(state, ServiceRunningState::STATE_NOT_START); + EXPECT_FALSE(abilityMgrServ_->GetEventHandler()); +} + +/* + * Feature: AaFwk + * Function: ability manager service + * SubFunction: NA + * FunctionPoints: NA + * EnvConditions: NA + * CaseDescription: AddWindowInfo. + */ +HWTEST_F(AbilityMgrModuleTest, ability_mgr_service_test_005, TestSize.Level1) +{ + std::string abilityName = "MusicAbility"; + std::string bundleName = "com.ix.hiMusic"; + + Want want = CreateWant(abilityName, bundleName); + AbilityRequest abilityRequest; + abilityRequest.want = want; + abilityRequest.abilityInfo = CreateAbilityInfo(abilityName, bundleName, bundleName); + abilityRequest.appInfo = CreateAppInfo(bundleName, bundleName); + std::shared_ptr abilityRecord = AbilityRecord::CreateAbilityRecord(abilityRequest); + abilityRecord->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVATING); + std::shared_ptr mission = std::make_shared(bundleName); + mission->AddAbilityRecordToTop(abilityRecord); + auto stackManager_ = abilityMgrServ_->GetStackManager(); + std::shared_ptr curMissionStack = stackManager_->GetCurrentMissionStack(); + curMissionStack->AddMissionRecordToTop(mission); + + abilityMgrServ_->AddWindowInfo(abilityRecord->GetToken(), 1); + EXPECT_TRUE(abilityRecord->GetWindowInfo() != nullptr); + EXPECT_EQ((std::size_t)1, stackManager_->windowTokenToAbilityMap_.size()); + abilityRecord->RemoveWindowInfo(); + stackManager_->windowTokenToAbilityMap_.clear(); +} + +/* + * Feature: AaFwk + * Function: ability manager service + * SubFunction: NA + * FunctionPoints: NA + * EnvConditions: NA + * CaseDescription: AttachAbilityThread. + */ +HWTEST_F(AbilityMgrModuleTest, ability_mgr_service_test_006, TestSize.Level1) +{ + EXPECT_TRUE(abilityMgrServ_); + std::string abilityName = "MusicAbility"; + std::string bundleName = "com.ix.hiMusic"; + + Want want = CreateWant(abilityName, bundleName); + AbilityRequest abilityRequest; + abilityRequest.want = want; + abilityRequest.abilityInfo = CreateAbilityInfo(abilityName, bundleName, bundleName); + abilityRequest.appInfo = CreateAppInfo(bundleName, bundleName); + std::shared_ptr abilityRecord = AbilityRecord::CreateAbilityRecord(abilityRequest); + EXPECT_TRUE(abilityRecord); + abilityRecord->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVATING); + std::shared_ptr mission = std::make_shared(bundleName); + EXPECT_TRUE(mission); + mission->AddAbilityRecordToTop(abilityRecord); + + auto stackManager_ = abilityMgrServ_->GetStackManager(); + EXPECT_TRUE(stackManager_); + std::shared_ptr curMissionStack = stackManager_->GetCurrentMissionStack(); + curMissionStack->AddMissionRecordToTop(mission); + sptr scheduler(new MockAbilityScheduler()); + + EXPECT_CALL(*scheduler, AsObject()).Times(4); + abilityRecord->SetScheduler(scheduler); + auto eventLoop = OHOS::AppExecFwk::EventRunner::Create("NAME_ABILITY_MGR_SERVICE"); + std::shared_ptr handler = std::make_shared(eventLoop, abilityMgrServ_); + abilityMgrServ_->handler_ = handler; + EXPECT_CALL(*mockAppMgrClient_, UpdateAbilityState(_, _)).Times(1).WillOnce(Return(AppMgrResultCode::RESULT_OK)); + abilityMgrServ_->AttachAbilityThread(scheduler, abilityRecord->GetToken()); + + testing::Mock::AllowLeak(scheduler); +} + +/* + * Feature: AaFwk + * Function: ability manager service + * SubFunction: NA + * FunctionPoints: NA + * EnvConditions: NA + * CaseDescription: AbilityTransitionDone. + */ +HWTEST_F(AbilityMgrModuleTest, ability_mgr_service_test_007, TestSize.Level1) +{ + std::string abilityName = "MusicAbility"; + std::string bundleName = "com.ix.hiMusic"; + + Want want = CreateWant(abilityName, bundleName); + AbilityRequest abilityRequest; + abilityRequest.want = want; + abilityRequest.abilityInfo = CreateAbilityInfo(abilityName, bundleName, bundleName); + abilityRequest.appInfo = CreateAppInfo(bundleName, bundleName); + std::shared_ptr abilityRecord = AbilityRecord::CreateAbilityRecord(abilityRequest); + EXPECT_TRUE(abilityRecord); + abilityRecord->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVATING); + std::shared_ptr mission = std::make_shared(bundleName); + EXPECT_TRUE(mission); + mission->AddAbilityRecordToTop(abilityRecord); + auto stackManager_ = abilityMgrServ_->GetStackManager(); + EXPECT_TRUE(stackManager_); + std::shared_ptr curMissionStack = stackManager_->GetCurrentMissionStack(); + EXPECT_TRUE(curMissionStack); + curMissionStack->AddMissionRecordToTop(mission); + + int result = abilityMgrServ_->AbilityTransitionDone(abilityRecord->GetToken(), OHOS::AAFwk::AbilityState::ACTIVE); + usleep(50 * 1000); + EXPECT_EQ(OHOS::ERR_OK, result); + EXPECT_EQ(OHOS::AAFwk::AbilityState::ACTIVE, abilityRecord->GetAbilityState()); +} + +/* + * Feature: AaFwk + * Function: ability manager service + * SubFunction: NA + * FunctionPoints: NA + * EnvConditions: NA + * CaseDescription: connect ability. + */ +HWTEST_F(AbilityMgrModuleTest, ability_mgr_service_test_008, TestSize.Level1) +{ + + std::string abilityName = "MusicAbility"; + std::string bundleName = "com.ix.hiMusic"; + + Want want; + std::shared_ptr curMissionStack; + sptr recordToken; + CreateAbilityRequest(abilityName, bundleName, want, curMissionStack, recordToken); + + sptr stub(new MockAbilityConnectCallbackStub()); + const sptr callback(new AbilityConnectionProxy(stub)); + + bool testResult = false; + sptr testToken; + MockServiceAbilityLoadHandlerInner(testResult, bundleName, abilityName, testToken); + + int result = abilityMgrServ_->ConnectAbility(want, callback, recordToken); + EXPECT_EQ(testResult, result); + + EXPECT_EQ((std::size_t)1, abilityMgrServ_->connectManager_->connectMap_.size()); + EXPECT_EQ((std::size_t)1, abilityMgrServ_->connectManager_->serviceMap_.size()); + std::shared_ptr record = abilityMgrServ_->connectManager_->GetServiceRecordByToken(testToken); + EXPECT_TRUE(record); + ElementName element; + + std::shared_ptr connectRecord = record->GetConnectRecordList().front(); + EXPECT_TRUE(connectRecord); + + sptr scheduler = new MockAbilityScheduler(); + EXPECT_TRUE(scheduler); + + EXPECT_CALL(*scheduler, AsObject()).Times(1); + EXPECT_CALL(*mockAppMgrClient_, UpdateAbilityState(_, _)).Times(1); + abilityMgrServ_->AttachAbilityThread(scheduler, record->GetToken()); + EXPECT_TRUE(record->isReady_); + + EXPECT_CALL(*scheduler, ScheduleAbilityTransaction(_, _)).Times(1); + abilityMgrServ_->OnAbilityRequestDone( + record->GetToken(), (int32_t)OHOS::AppExecFwk::AbilityState::ABILITY_STATE_FOREGROUND); + EXPECT_EQ(OHOS::AAFwk::AbilityState::INACTIVATING, record->GetAbilityState()); + + EXPECT_CALL(*scheduler, ScheduleConnectAbility(_)).Times(1); + abilityMgrServ_->AbilityTransitionDone(record->GetToken(), AbilityLifeCycleState::ABILITY_STATE_INACTIVE); + EXPECT_TRUE(record->GetConnectingRecord()); + EXPECT_EQ(OHOS::AAFwk::ConnectionState::CONNECTING, connectRecord->GetConnectState()); + + EXPECT_CALL(*stub, OnAbilityConnectDone(_, _, _)).Times(1); + abilityMgrServ_->ScheduleConnectAbilityDone(record->GetToken(), nullptr); + + EXPECT_EQ(OHOS::AAFwk::ConnectionState::CONNECTED, connectRecord->GetConnectState()); + EXPECT_EQ(OHOS::AAFwk::AbilityState::ACTIVE, record->GetAbilityState()); + + abilityMgrServ_->RemoveAllServiceRecord(); + curMissionStack->RemoveAll(); + + testing::Mock::AllowLeak(scheduler); + testing::Mock::AllowLeak(stub); + testing::Mock::AllowLeak(callback); +} + +/* + * Feature: AaFwk + * Function: ability manager services + * SubFunction: NA + * FunctionPoints: NA + * EnvConditions: NA + * CaseDescription: disconnect ability. + */ +HWTEST_F(AbilityMgrModuleTest, ability_mgr_service_test_009, TestSize.Level1) +{ + + std::string abilityName = "MusicAbility_service"; + std::string bundleName = "com.ix.hiMusic_service"; + Want want = CreateWant(abilityName, bundleName); + sptr stub(new MockAbilityConnectCallbackStub()); + const sptr callback(new AbilityConnectionProxy(stub)); + + abilityMgrServ_->RemoveAllServiceRecord(); + EXPECT_CALL(*mockAppMgrClient_, LoadAbility(_, _, _, _)).Times(1); + abilityMgrServ_->ConnectAbility(want, callback, nullptr); + std::shared_ptr record = + abilityMgrServ_->connectManager_->GetServiceRecordByElementName(want.GetElement().GetURI()); + EXPECT_TRUE(record); + std::shared_ptr connectRecord = record->GetConnectingRecord(); + EXPECT_TRUE(connectRecord); + connectRecord->SetConnectState(ConnectionState::CONNECTED); + record->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + + sptr scheduler = new MockAbilityScheduler(); + EXPECT_TRUE(scheduler); + EXPECT_CALL(*scheduler, AsObject()).Times(2); + record->SetScheduler(scheduler); + EXPECT_CALL(*scheduler, ScheduleDisconnectAbility(_)).Times(1); + abilityMgrServ_->DisconnectAbility(callback); + EXPECT_EQ(OHOS::AAFwk::ConnectionState::DISCONNECTING, connectRecord->GetConnectState()); + + EXPECT_CALL(*scheduler, ScheduleAbilityTransaction(_, _)).Times(1); + EXPECT_CALL(*stub, OnAbilityDisconnectDone(_, _)).Times(1); + + abilityMgrServ_->ScheduleDisconnectAbilityDone(record->GetToken()); + EXPECT_EQ((std::size_t)0, record->GetConnectRecordList().size()); + EXPECT_EQ((std::size_t)0, abilityMgrServ_->connectManager_->GetConnectMap().size()); + + EXPECT_CALL(*mockAppMgrClient_, UpdateAbilityState(_, _)).Times(1); + abilityMgrServ_->AbilityTransitionDone(record->GetToken(), AbilityLifeCycleState::ABILITY_STATE_INITIAL); + EXPECT_EQ(OHOS::AAFwk::AbilityState::TERMINATING, record->GetAbilityState()); + + EXPECT_CALL(*mockAppMgrClient_, TerminateAbility(_)).Times(1); + abilityMgrServ_->OnAbilityRequestDone( + record->GetToken(), (int32_t)OHOS::AppExecFwk::AbilityState::ABILITY_STATE_BACKGROUND); + EXPECT_EQ((std::size_t)0, abilityMgrServ_->connectManager_->GetServiceMap().size()); + + testing::Mock::AllowLeak(scheduler); + testing::Mock::AllowLeak(stub); + testing::Mock::AllowLeak(callback); +} + +/* + * Feature: AaFwk + * Function: ability manager service + * SubFunction: NA + * FunctionPoints: NA + * EnvConditions: NA + * CaseDescription: disconnect ability. + */ +HWTEST_F(AbilityMgrModuleTest, ability_mgr_service_test_010, TestSize.Level1) +{ + std::string abilityName1 = "MusicAbility_service_1"; + std::string bundleName1 = "com.ix.hiMusic_service_1"; + Want want1 = CreateWant(abilityName1, bundleName1); + std::string abilityName2 = "MusicAbility_service_2"; + std::string bundleName2 = "com.ix.hiMusic_service_2"; + Want want2 = CreateWant(abilityName2, bundleName2); + + sptr stub1(new MockAbilityConnectCallbackStub()); + const sptr callback1(new AbilityConnectionProxy(stub1)); + sptr stub2(new MockAbilityConnectCallbackStub()); + const sptr callback2(new AbilityConnectionProxy(stub2)); + + abilityMgrServ_->RemoveAllServiceRecord(); + + EXPECT_CALL(*mockAppMgrClient_, LoadAbility(_, _, _, _)).Times(2); + abilityMgrServ_->ConnectAbility(want1, callback1, nullptr); + abilityMgrServ_->ConnectAbility(want2, callback1, nullptr); + abilityMgrServ_->ConnectAbility(want1, callback2, nullptr); + abilityMgrServ_->ConnectAbility(want2, callback2, nullptr); + + EXPECT_EQ((std::size_t)2, abilityMgrServ_->connectManager_->GetServiceMap().size()); + EXPECT_EQ((std::size_t)2, abilityMgrServ_->connectManager_->GetConnectMap().size()); + + std::shared_ptr record1; + std::shared_ptr record2; + CreateServiceRecord(record1, want1, callback1, callback2); + CreateServiceRecord(record2, want2, callback1, callback2); + + for (auto &connectRecord : record1->GetConnectRecordList()) { + connectRecord->SetConnectState(ConnectionState::CONNECTED); + } + for (auto &connectRecord : record2->GetConnectRecordList()) { + connectRecord->SetConnectState(ConnectionState::CONNECTED); + } + + sptr scheduler = new MockAbilityScheduler(); + EXPECT_TRUE(scheduler); + EXPECT_CALL(*scheduler, AsObject()).Times(4); + record1->SetScheduler(scheduler); + record2->SetScheduler(scheduler); + EXPECT_CALL(*stub1, OnAbilityDisconnectDone(_, _)).Times(2); + abilityMgrServ_->DisconnectAbility(callback1); + usleep(100); + + EXPECT_CALL(*scheduler, ScheduleDisconnectAbility(_)).Times(2); + EXPECT_CALL(*scheduler, ScheduleAbilityTransaction(_, _)).Times(2); + EXPECT_CALL(*stub2, OnAbilityDisconnectDone(_, _)).Times(2); + + CheckTestRecord(record1, record2, callback1, callback2); + testing::Mock::AllowLeak(stub1); + testing::Mock::AllowLeak(callback1); + testing::Mock::AllowLeak(stub2); + testing::Mock::AllowLeak(callback2); + testing::Mock::AllowLeak(scheduler); +} + +/* + * Feature: AaFwk + * Function: ability manager service + * SubFunction: NA + * FunctionPoints: NA + * EnvConditions: NA + * CaseDescription: start ability (serive ability). + */ +HWTEST_F(AbilityMgrModuleTest, ability_mgr_service_test_011, TestSize.Level1) +{ + std::string abilityName = "MusicAbility_service"; + std::string bundleName = "com.ix.hiMusic_service"; + Want want = CreateWant(abilityName, bundleName); + bool testResult = false; + sptr testToken; + auto mockHandler = [&](const sptr &token, + const sptr &preToken, + const AbilityInfo &abilityInfo, + const ApplicationInfo &appInfo) { + testToken = token; + testResult = !!testToken && abilityInfo.bundleName == bundleName && abilityInfo.name == abilityName && + appInfo.bundleName == bundleName; + return AppMgrResultCode::RESULT_OK; + }; + EXPECT_CALL(*mockAppMgrClient_, LoadAbility(_, _, _, _)).Times(1).WillOnce(Invoke(mockHandler)); + + int testRequestCode = 123; + SetActive(); + abilityMgrServ_->StartAbility(want, testRequestCode); + EXPECT_TRUE(testResult); + EXPECT_TRUE(testToken); + + std::shared_ptr record = abilityMgrServ_->GetServiceRecordByElementName(want.GetElement().GetURI()); + EXPECT_TRUE(record); + EXPECT_FALSE(record->IsCreateByConnect()); + + sptr scheduler = new MockAbilityScheduler(); + EXPECT_TRUE(scheduler); + EXPECT_CALL(*scheduler, AsObject()).Times(2); + EXPECT_CALL(*mockAppMgrClient_, UpdateAbilityState(_, _)).Times(1); + abilityMgrServ_->AttachAbilityThread(scheduler, record->GetToken()); + EXPECT_TRUE(record->isReady_); + + EXPECT_CALL(*scheduler, ScheduleAbilityTransaction(_, _)).Times(1); + abilityMgrServ_->OnAbilityRequestDone( + record->GetToken(), (int32_t)OHOS::AppExecFwk::AbilityState::ABILITY_STATE_FOREGROUND); + EXPECT_EQ(OHOS::AAFwk::AbilityState::INACTIVATING, record->GetAbilityState()); + + int testId = 0; + auto handler = [&](const Want &want, bool restart, int startid) { testId = startid; }; + EXPECT_CALL(*scheduler, ScheduleCommandAbility(_, _, _)).Times(1).WillOnce(Invoke(handler)); + abilityMgrServ_->AbilityTransitionDone(record->GetToken(), AbilityLifeCycleState::ABILITY_STATE_INACTIVE); + EXPECT_EQ(1, testId); + + abilityMgrServ_->ScheduleCommandAbilityDone(record->GetToken()); + EXPECT_EQ(OHOS::AAFwk::AbilityState::ACTIVE, record->GetAbilityState()); + + EXPECT_CALL(*scheduler, ScheduleCommandAbility(_, _, _)) + .Times(3) + .WillOnce(Invoke(handler)) + .WillOnce(Invoke(handler)) + .WillOnce(Invoke(handler)); + + for (int i = 0; i < 3; ++i) { + abilityMgrServ_->StartAbility(want, testRequestCode); + } + EXPECT_EQ(4, testId); + abilityMgrServ_->RemoveAllServiceRecord(); + testing::Mock::AllowLeak(scheduler); +} +/* + * Feature: AaFwk + * Function: ability manager service + * SubFunction: NA + * FunctionPoints: NA + * EnvConditions: NA + * CaseDescription: start ability (serive ability). + */ +HWTEST_F(AbilityMgrModuleTest, ability_mgr_service_test_012, TestSize.Level1) +{ + std::string abilityName = "MusicAbility_service"; + std::string bundleName = "com.ix.hiMusic_service"; + Want want = CreateWant(abilityName, bundleName); + bool testResult = false; + sptr testToken; + auto mockHandler = [&](const sptr &token, + const sptr &preToken, + const AbilityInfo &abilityInfo, + const ApplicationInfo &appInfo) { + testToken = token; + testResult = !!testToken && abilityInfo.bundleName == bundleName && abilityInfo.name == abilityName && + appInfo.bundleName == bundleName; + return AppMgrResultCode::RESULT_OK; + }; + EXPECT_CALL(*mockAppMgrClient_, LoadAbility(_, _, _, _)).Times(1).WillOnce(Invoke(mockHandler)); + + int testRequestCode = 123; + abilityMgrServ_->StartAbility(want, testRequestCode); + WaitAMS(); + EXPECT_TRUE(testResult); + EXPECT_TRUE(testToken); + + std::shared_ptr record = abilityMgrServ_->GetServiceRecordByElementName(want.GetElement().GetURI()); + EXPECT_TRUE(record); + EXPECT_FALSE(record->IsCreateByConnect()); + + sptr scheduler = new MockAbilityScheduler(); + EXPECT_TRUE(scheduler); + EXPECT_CALL(*scheduler, AsObject()).Times(2); + EXPECT_CALL(*mockAppMgrClient_, UpdateAbilityState(_, _)).Times(1); + abilityMgrServ_->AttachAbilityThread(scheduler, record->GetToken()); + EXPECT_TRUE(record->isReady_); + + EXPECT_CALL(*scheduler, ScheduleAbilityTransaction(_, _)).Times(1); + abilityMgrServ_->OnAbilityRequestDone( + record->GetToken(), (int32_t)OHOS::AppExecFwk::AbilityState::ABILITY_STATE_FOREGROUND); + EXPECT_EQ(OHOS::AAFwk::AbilityState::INACTIVATING, record->GetAbilityState()); + + int testId = 0; + auto handler = [&](const Want &want, bool restart, int startid) { testId = startid; }; + EXPECT_CALL(*scheduler, ScheduleCommandAbility(_, _, _)).Times(1).WillOnce(Invoke(handler)); + abilityMgrServ_->AbilityTransitionDone(record->GetToken(), AbilityLifeCycleState::ABILITY_STATE_INACTIVE); + EXPECT_EQ(1, testId); + + abilityMgrServ_->ScheduleCommandAbilityDone(record->GetToken()); + EXPECT_EQ(OHOS::AAFwk::AbilityState::ACTIVE, record->GetAbilityState()); + + sptr stub(new MockAbilityConnectCallbackStub()); + const sptr callback(new AbilityConnectionProxy(stub)); + EXPECT_CALL(*scheduler, ScheduleConnectAbility(_)).Times(1); + abilityMgrServ_->ConnectAbility(want, callback, nullptr); + std::shared_ptr connectRecord = record->GetConnectingRecord(); + EXPECT_TRUE(connectRecord); + EXPECT_EQ((size_t)1, abilityMgrServ_->GetConnectRecordListByCallback(callback).size()); + + EXPECT_CALL(*stub, OnAbilityConnectDone(_, _, _)).Times(1); + abilityMgrServ_->ScheduleConnectAbilityDone(record->GetToken(), nullptr); + EXPECT_EQ(ConnectionState::CONNECTED, connectRecord->GetConnectState()); + + abilityMgrServ_->RemoveAllServiceRecord(); + + testing::Mock::AllowLeak(scheduler); + testing::Mock::AllowLeak(stub); + testing::Mock::AllowLeak(callback); +} + +/* + * Feature: AaFwk + * Function: ability manager service + * SubFunction: NA + * FunctionPoints: NA + * EnvConditions: NA + * CaseDescription: start ability (serive ability). + */ +HWTEST_F(AbilityMgrModuleTest, ability_mgr_service_test_013, TestSize.Level1) +{ + std::string abilityName1 = "MusicAbility_service_1"; + std::string bundleName1 = "com.ix.hiMusic_service_1"; + Want want1 = CreateWant(abilityName1, bundleName1); + std::string abilityName2 = "MusicAbility_service_2"; + std::string bundleName2 = "com.ix.hiMusic_service_2"; + Want want2 = CreateWant(abilityName2, bundleName2); + + abilityMgrServ_->RemoveAllServiceRecord(); + EXPECT_CALL(*mockAppMgrClient_, LoadAbility(_, _, _, _)).Times(2); + int testRequestCode = 123; + abilityMgrServ_->StartAbility(want1, testRequestCode); + abilityMgrServ_->StartAbility(want2, testRequestCode); + + std::shared_ptr record1 = + abilityMgrServ_->GetServiceRecordByElementName(want1.GetElement().GetURI()); + EXPECT_TRUE(record1); + EXPECT_FALSE(record1->IsCreateByConnect()); + + std::shared_ptr record2 = + abilityMgrServ_->GetServiceRecordByElementName(want2.GetElement().GetURI()); + EXPECT_TRUE(record2); + EXPECT_FALSE(record2->IsCreateByConnect()); + + abilityMgrServ_->RemoveAllServiceRecord(); +} + +/* + * Feature: AaFwk + * Function: ability manager service + * SubFunction: NA + * FunctionPoints: NA + * EnvConditions: NA + * CaseDescription: TerminateAbility (serive ability). + */ +HWTEST_F(AbilityMgrModuleTest, ability_mgr_service_test_014, TestSize.Level1) +{ + std::string abilityName = "MusicAbility_service"; + std::string bundleName = "com.ix.hiMusic_service"; + Want want = CreateWant(abilityName, bundleName); + + abilityMgrServ_->RemoveAllServiceRecord(); + EXPECT_CALL(*mockAppMgrClient_, LoadAbility(_, _, _, _)).Times(1); + int testRequestCode = 123; + abilityMgrServ_->StartAbility(want, testRequestCode); + std::shared_ptr record = abilityMgrServ_->GetServiceRecordByElementName(want.GetElement().GetURI()); + EXPECT_TRUE(record); + EXPECT_FALSE(record->IsCreateByConnect()); + record->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + + sptr scheduler = new MockAbilityScheduler(); + EXPECT_TRUE(scheduler); + EXPECT_CALL(*scheduler, AsObject()).Times(2); + record->SetScheduler(scheduler); + + EXPECT_CALL(*scheduler, ScheduleAbilityTransaction(_, _)).Times(1); + abilityMgrServ_->TerminateAbility(record->GetToken(), -1); + EXPECT_EQ(OHOS::AAFwk::AbilityState::TERMINATING, record->GetAbilityState()); + + EXPECT_CALL(*mockAppMgrClient_, UpdateAbilityState(_, _)).Times(1); + abilityMgrServ_->AbilityTransitionDone(record->GetToken(), AbilityLifeCycleState::ABILITY_STATE_INITIAL); + + EXPECT_CALL(*mockAppMgrClient_, TerminateAbility(_)).Times(1); + abilityMgrServ_->OnAbilityRequestDone( + record->GetToken(), (int32_t)OHOS::AppExecFwk::AbilityState::ABILITY_STATE_BACKGROUND); + EXPECT_EQ((std::size_t)0, abilityMgrServ_->connectManager_->GetServiceMap().size()); + + abilityMgrServ_->RemoveAllServiceRecord(); + + testing::Mock::AllowLeak(scheduler); +} + +/* + * Feature: AaFwk + * Function: ability manager service + * SubFunction: NA + * FunctionPoints: NA + * EnvConditions: NA + * CaseDescription: TerminateAbility (serive ability). + */ +HWTEST_F(AbilityMgrModuleTest, ability_mgr_service_test_015, TestSize.Level1) +{ + std::string abilityName = "MusicAbility_service"; + std::string bundleName = "com.ix.hiMusic_service"; + Want want = CreateWant(abilityName, bundleName); + + abilityMgrServ_->RemoveAllServiceRecord(); + EXPECT_CALL(*mockAppMgrClient_, LoadAbility(_, _, _, _)).Times(1); + int testRequestCode = 123; + abilityMgrServ_->StartAbility(want, testRequestCode); + std::shared_ptr record = abilityMgrServ_->GetServiceRecordByElementName(want.GetElement().GetURI()); + EXPECT_TRUE(record); + EXPECT_FALSE(record->IsCreateByConnect()); + record->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + + sptr scheduler = new MockAbilityScheduler(); + EXPECT_TRUE(scheduler); + EXPECT_CALL(*scheduler, AsObject()).Times(2); + record->SetScheduler(scheduler); + + EXPECT_CALL(*scheduler, ScheduleAbilityTransaction(_, _)).Times(1); + abilityMgrServ_->StopServiceAbility(want); + EXPECT_EQ(OHOS::AAFwk::AbilityState::TERMINATING, record->GetAbilityState()); + + EXPECT_CALL(*mockAppMgrClient_, UpdateAbilityState(_, _)).Times(1); + abilityMgrServ_->AbilityTransitionDone(record->GetToken(), AbilityLifeCycleState::ABILITY_STATE_INITIAL); + + EXPECT_CALL(*mockAppMgrClient_, TerminateAbility(_)).Times(1); + abilityMgrServ_->OnAbilityRequestDone( + record->GetToken(), (int32_t)OHOS::AppExecFwk::AbilityState::ABILITY_STATE_BACKGROUND); + EXPECT_EQ((std::size_t)0, abilityMgrServ_->connectManager_->GetServiceMap().size()); + + abilityMgrServ_->RemoveAllServiceRecord(); + testing::Mock::AllowLeak(scheduler); +} + +/* + * Feature: AaFwk + * Function: ability manager service + * SubFunction: NA + * FunctionPoints: NA + * EnvConditions: NA + * CaseDescription: StopServiceAbility (serive ability). + */ +HWTEST_F(AbilityMgrModuleTest, ability_mgr_service_test_016, TestSize.Level1) +{ + std::string abilityName = "MusicAbility_service"; + std::string bundleName = "com.ix.hiMusic_service"; + Want want = CreateWant(abilityName, bundleName); + + abilityMgrServ_->RemoveAllServiceRecord(); + EXPECT_CALL(*mockAppMgrClient_, LoadAbility(_, _, _, _)).Times(1); + int testRequestCode = 123; + abilityMgrServ_->StartAbility(want, testRequestCode); + std::shared_ptr record = abilityMgrServ_->GetServiceRecordByElementName(want.GetElement().GetURI()); + EXPECT_TRUE(record); + EXPECT_FALSE(record->IsCreateByConnect()); + record->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + + sptr scheduler = new MockAbilityScheduler(); + EXPECT_TRUE(scheduler); + EXPECT_CALL(*scheduler, AsObject()).Times(2); + record->SetScheduler(scheduler); + + sptr stub(new MockAbilityConnectCallbackStub()); + const sptr callback(new AbilityConnectionProxy(stub)); + EXPECT_CALL(*scheduler, ScheduleConnectAbility(_)).Times(1); + abilityMgrServ_->ConnectAbility(want, callback, nullptr); + std::shared_ptr connectRecord = record->GetConnectingRecord(); + EXPECT_TRUE(connectRecord); + EXPECT_EQ((size_t)1, abilityMgrServ_->GetConnectRecordListByCallback(callback).size()); + EXPECT_CALL(*stub, OnAbilityConnectDone(_, _, _)).Times(1); + abilityMgrServ_->ScheduleConnectAbilityDone(record->GetToken(), nullptr); + EXPECT_EQ(ConnectionState::CONNECTED, connectRecord->GetConnectState()); + + int result = abilityMgrServ_->TerminateAbility(record->GetToken(), -1); + EXPECT_EQ(TERMINATE_SERVICE_IS_CONNECTED, result); + + abilityMgrServ_->RemoveAllServiceRecord(); + + testing::Mock::AllowLeak(scheduler); + testing::Mock::AllowLeak(stub); + testing::Mock::AllowLeak(callback); +} + +/* + * Feature: AaFwk + * Function: ability manager service + * SubFunction: NA + * FunctionPoints: NA + * EnvConditions: NA + * CaseDescription: StopServiceAbility (serive ability). + */ +HWTEST_F(AbilityMgrModuleTest, ability_mgr_service_test_017, TestSize.Level1) +{ + std::string abilityName = "MusicAbility_service"; + std::string bundleName = "com.ix.hiMusic_service"; + Want want = CreateWant(abilityName, bundleName); + + abilityMgrServ_->RemoveAllServiceRecord(); + EXPECT_CALL(*mockAppMgrClient_, LoadAbility(_, _, _, _)).Times(1); + int testRequestCode = 123; + abilityMgrServ_->StartAbility(want, testRequestCode); + std::shared_ptr record = abilityMgrServ_->GetServiceRecordByElementName(want.GetElement().GetURI()); + EXPECT_TRUE(record); + EXPECT_FALSE(record->IsCreateByConnect()); + record->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + + sptr scheduler = new MockAbilityScheduler(); + EXPECT_TRUE(scheduler); + EXPECT_CALL(*scheduler, AsObject()).Times(2); + record->SetScheduler(scheduler); + + sptr stub(new MockAbilityConnectCallbackStub()); + const sptr callback(new AbilityConnectionProxy(stub)); + EXPECT_CALL(*scheduler, ScheduleConnectAbility(_)).Times(1); + abilityMgrServ_->ConnectAbility(want, callback, nullptr); + std::shared_ptr connectRecord = record->GetConnectingRecord(); + EXPECT_TRUE(connectRecord); + EXPECT_EQ((size_t)1, abilityMgrServ_->GetConnectRecordListByCallback(callback).size()); + EXPECT_CALL(*stub, OnAbilityConnectDone(_, _, _)).Times(1); + abilityMgrServ_->ScheduleConnectAbilityDone(record->GetToken(), nullptr); + EXPECT_EQ(ConnectionState::CONNECTED, connectRecord->GetConnectState()); + + int result = abilityMgrServ_->StopServiceAbility(want); + EXPECT_EQ(TERMINATE_SERVICE_IS_CONNECTED, result); + + abilityMgrServ_->RemoveAllServiceRecord(); + + testing::Mock::AllowLeak(scheduler); + testing::Mock::AllowLeak(stub); + testing::Mock::AllowLeak(callback); +} + +/* + * Feature: AaFwk + * Function: ability manager service + * SubFunction: NA + * FunctionPoints: NA + * EnvConditions: NA + * CaseDescription: disconnectAbility and stop service ability (serive ability). + */ +HWTEST_F(AbilityMgrModuleTest, ability_mgr_service_test_018, TestSize.Level1) +{ + std::string abilityName = "MusicAbility_service"; + std::string bundleName = "com.ix.hiMusic_service"; + Want want = CreateWant(abilityName, bundleName); + + abilityMgrServ_->RemoveAllServiceRecord(); + EXPECT_CALL(*mockAppMgrClient_, LoadAbility(_, _, _, _)).Times(1); + int testRequestCode = 123; + SetActive(); + abilityMgrServ_->StartAbility(want, testRequestCode); + std::shared_ptr record = abilityMgrServ_->GetServiceRecordByElementName(want.GetElement().GetURI()); + EXPECT_TRUE(record); + EXPECT_FALSE(record->IsCreateByConnect()); + record->AddStartId(); + record->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + + sptr scheduler = new MockAbilityScheduler(); + EXPECT_TRUE(scheduler); + EXPECT_CALL(*scheduler, AsObject()).Times(2); + record->SetScheduler(scheduler); + + sptr stub(new MockAbilityConnectCallbackStub()); + const sptr callback(new AbilityConnectionProxy(stub)); + EXPECT_CALL(*scheduler, ScheduleConnectAbility(_)).Times(1); + abilityMgrServ_->ConnectAbility(want, callback, nullptr); + + std::shared_ptr connectRecord = record->GetConnectingRecord(); + EXPECT_TRUE(connectRecord); + EXPECT_EQ((size_t)1, abilityMgrServ_->GetConnectRecordListByCallback(callback).size()); + EXPECT_CALL(*stub, OnAbilityConnectDone(_, _, _)).Times(1); + abilityMgrServ_->ScheduleConnectAbilityDone(record->GetToken(), nullptr); + EXPECT_EQ(ConnectionState::CONNECTED, connectRecord->GetConnectState()); + + EXPECT_CALL(*scheduler, ScheduleDisconnectAbility(_)).Times(1); + abilityMgrServ_->DisconnectAbility(callback); + EXPECT_EQ(OHOS::AAFwk::ConnectionState::DISCONNECTING, connectRecord->GetConnectState()); + + EXPECT_CALL(*stub, OnAbilityDisconnectDone(_, _)).Times(1); + abilityMgrServ_->ScheduleDisconnectAbilityDone(record->GetToken()); + EXPECT_EQ((std::size_t)0, record->GetConnectRecordList().size()); + EXPECT_EQ((std::size_t)0, abilityMgrServ_->connectManager_->GetConnectMap().size()); + EXPECT_EQ(OHOS::AAFwk::ConnectionState::DISCONNECTED, connectRecord->GetConnectState()); + EXPECT_EQ((std::size_t)1, abilityMgrServ_->connectManager_->GetServiceMap().size()); + + EXPECT_CALL(*scheduler, ScheduleAbilityTransaction(_, _)).Times(1); + abilityMgrServ_->StopServiceAbility(want); + EXPECT_EQ(OHOS::AAFwk::AbilityState::TERMINATING, record->GetAbilityState()); + + EXPECT_CALL(*mockAppMgrClient_, UpdateAbilityState(_, _)).Times(1); + abilityMgrServ_->AbilityTransitionDone(record->GetToken(), AbilityLifeCycleState::ABILITY_STATE_INITIAL); + EXPECT_CALL(*mockAppMgrClient_, TerminateAbility(_)).Times(1); + abilityMgrServ_->OnAbilityRequestDone( + record->GetToken(), (int32_t)OHOS::AppExecFwk::AbilityState::ABILITY_STATE_BACKGROUND); + EXPECT_EQ((std::size_t)0, abilityMgrServ_->connectManager_->GetServiceMap().size()); + + abilityMgrServ_->RemoveAllServiceRecord(); + testing::Mock::AllowLeak(scheduler); + testing::Mock::AllowLeak(stub); + testing::Mock::AllowLeak(callback); +} + +/* + * Feature: AaFwk + * Function: ability manager service + * SubFunction: NA + * FunctionPoints: NA + * EnvConditions: NA + * CaseDescription: disconnectAbility and terminate (serive ability). + */ +HWTEST_F(AbilityMgrModuleTest, ability_mgr_service_test_019, TestSize.Level1) +{ + std::string abilityName = "MusicAbilityService"; + std::string bundleName = "com.ix.hiservice"; + Want want = CreateWant(abilityName, bundleName); + EXPECT_TRUE(abilityMgrServ_); + abilityMgrServ_->RemoveAllServiceRecord(); + EXPECT_CALL(*mockAppMgrClient_, LoadAbility(_, _, _, _)).Times(1); + int testRequestCode = 123; + abilityMgrServ_->StartAbility(want, testRequestCode); + std::shared_ptr record = abilityMgrServ_->GetServiceRecordByElementName(want.GetElement().GetURI()); + EXPECT_TRUE(record); + EXPECT_FALSE(record->IsCreateByConnect()); + record->AddStartId(); + record->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + + sptr scheduler = new MockAbilityScheduler(); + EXPECT_TRUE(scheduler); + EXPECT_CALL(*scheduler, AsObject()).Times(2); + record->SetScheduler(scheduler); + sptr stub(new MockAbilityConnectCallbackStub()); + const sptr callback(new AbilityConnectionProxy(stub)); + EXPECT_CALL(*scheduler, ScheduleConnectAbility(_)).Times(1); + abilityMgrServ_->ConnectAbility(want, callback, nullptr); + std::shared_ptr connectRecord = record->GetConnectingRecord(); + EXPECT_TRUE(connectRecord); + EXPECT_EQ((size_t)1, abilityMgrServ_->GetConnectRecordListByCallback(callback).size()); + EXPECT_CALL(*stub, OnAbilityConnectDone(_, _, _)).Times(1); + abilityMgrServ_->ScheduleConnectAbilityDone(record->GetToken(), nullptr); + EXPECT_EQ(ConnectionState::CONNECTED, connectRecord->GetConnectState()); + + EXPECT_CALL(*scheduler, ScheduleDisconnectAbility(_)).Times(1); + abilityMgrServ_->DisconnectAbility(callback); + EXPECT_EQ(OHOS::AAFwk::ConnectionState::DISCONNECTING, connectRecord->GetConnectState()); + + EXPECT_CALL(*stub, OnAbilityDisconnectDone(_, _)).Times(1); + abilityMgrServ_->ScheduleDisconnectAbilityDone(record->GetToken()); + EXPECT_EQ((std::size_t)0, record->GetConnectRecordList().size()); + EXPECT_EQ((std::size_t)0, abilityMgrServ_->connectManager_->GetConnectMap().size()); + EXPECT_EQ(OHOS::AAFwk::ConnectionState::DISCONNECTED, connectRecord->GetConnectState()); + EXPECT_EQ((std::size_t)1, abilityMgrServ_->connectManager_->GetServiceMap().size()); + + EXPECT_CALL(*scheduler, ScheduleAbilityTransaction(_, _)).Times(1); + abilityMgrServ_->TerminateAbility(record->GetToken(), -1); + EXPECT_EQ(OHOS::AAFwk::AbilityState::TERMINATING, record->GetAbilityState()); + + EXPECT_CALL(*mockAppMgrClient_, UpdateAbilityState(_, _)).Times(1); + abilityMgrServ_->AbilityTransitionDone(record->GetToken(), AbilityLifeCycleState::ABILITY_STATE_INITIAL); + EXPECT_CALL(*mockAppMgrClient_, TerminateAbility(_)).Times(1); + abilityMgrServ_->OnAbilityRequestDone( + record->GetToken(), (int32_t)OHOS::AppExecFwk::AbilityState::ABILITY_STATE_BACKGROUND); + EXPECT_EQ((std::size_t)0, abilityMgrServ_->connectManager_->GetServiceMap().size()); + + testing::Mock::AllowLeak(scheduler); + testing::Mock::AllowLeak(stub); + testing::Mock::AllowLeak(callback); +} + +/* + * Feature: AaFwk + * Function: ability manager service + * SubFunction: OnAbilityDied + * FunctionPoints: NA + * EnvConditions: NA + * CaseDescription: Test service abilities death notification. + */ +HWTEST_F(AbilityMgrModuleTest, ability_mgr_service_test_020, TestSize.Level3) +{ + std::string abilityName = "MusicAbility_service"; + std::string bundleName = "com.ix.hiMusic_service"; + Want want = CreateWant(abilityName, bundleName); + + abilityMgrServ_->RemoveAllServiceRecord(); + + sptr stub(new MockAbilityConnectCallbackStub()); + const sptr callback(new AbilityConnectionProxy(stub)); + EXPECT_CALL(*mockAppMgrClient_, LoadAbility(_, _, _, _)).Times(1); + abilityMgrServ_->ConnectAbility(want, callback, nullptr); + EXPECT_EQ((std::size_t)1, abilityMgrServ_->connectManager_->connectMap_.size()); + EXPECT_EQ((std::size_t)1, abilityMgrServ_->connectManager_->serviceMap_.size()); + std::shared_ptr record = + abilityMgrServ_->connectManager_->GetServiceRecordByElementName(want.GetElement().GetURI()); + EXPECT_TRUE(record); + EXPECT_TRUE(record->IsCreateByConnect()); + std::shared_ptr connectRecord = record->GetConnectingRecord(); + EXPECT_TRUE(connectRecord); + connectRecord->SetConnectState(ConnectionState::CONNECTED); + record->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + + EXPECT_CALL(*stub, OnAbilityDisconnectDone(_, _)).Times(1); + abilityMgrServ_->OnAbilityDied(record); + usleep(100 * 1000); + + EXPECT_EQ((std::size_t)0, abilityMgrServ_->connectManager_->GetServiceMap().size()); + EXPECT_EQ((std::size_t)0, abilityMgrServ_->connectManager_->connectMap_.size()); + + abilityMgrServ_->RemoveAllServiceRecord(); + testing::Mock::AllowLeak(stub); + testing::Mock::AllowLeak(callback); +} + +/* + * Feature: AbilityManagerService + * Function: HandleLoadTimeOut + * SubFunction: NA + * FunctionPoints: AbilityManagerService HandleLoadTimeOut + * EnvConditions: NA + * CaseDescription: Verify function HandleLoadTimeOut + */ +HWTEST_F(AbilityMgrModuleTest, ability_mgr_service_test_021, TestSize.Level1) +{ + EXPECT_TRUE(abilityMgrServ_); + EXPECT_TRUE(mockAppMgrClient_); + ClearStack(); + + std::string abilityName = "MusicSAbility"; + std::string bundleName = "com.ix.hiMusic"; + std::string abilityName2 = "RadioAbility"; + std::string bundleName2 = "com.ix.hiRadio"; + Want want = CreateWant(abilityName, bundleName); + Want want2 = CreateWant(abilityName2, bundleName2); + sptr scheduler = new MockAbilityScheduler(); + EXPECT_TRUE(scheduler); + EXPECT_CALL(*mockAppMgrClient_, LoadAbility(_, _, _, _)).Times(2); + EXPECT_CALL(*mockAppMgrClient_, AbilityAttachTimeOut(_)).Times(1); + EXPECT_CALL(*mockAppMgrClient_, UpdateAbilityState(_, _)).Times(2); + EXPECT_CALL(*scheduler, ScheduleAbilityTransaction(_, _)).Times(1); + EXPECT_CALL(*scheduler, AsObject()).Times(2); + abilityMgrServ_->StartAbility(want); + auto testAbilityRecord = GetTopAbility(); + EXPECT_TRUE(testAbilityRecord); + abilityMgrServ_->AttachAbilityThread(scheduler, testAbilityRecord->GetToken()); + SetActive(); + abilityMgrServ_->StartAbility(want2); + auto testAbilityRecord2 = GetTopAbility(); + EXPECT_TRUE(testAbilityRecord2); + auto stackMgr = abilityMgrServ_->GetStackManager(); + EXPECT_TRUE(stackMgr); + stackMgr->CompleteInactive(testAbilityRecord); + testAbilityRecord->SetAbilityState(OHOS::AAFwk::AbilityState::BACKGROUND); + abilityMgrServ_->HandleLoadTimeOut(testAbilityRecord2->GetEventId()); + testAbilityRecord = GetTopAbility(); + EXPECT_TRUE(testAbilityRecord); + EXPECT_TRUE(testAbilityRecord->GetAbilityInfo().bundleName == bundleName); + testing::Mock::AllowLeak(scheduler); +} + +/* + * Feature: AbilityManagerService + * Function: HandleLoadTimeOut + * SubFunction: NA + * FunctionPoints: AbilityManagerService HandleLoadTimeOut + * EnvConditions: NA + * CaseDescription: Verify function HandleLoadTimeOut + */ +HWTEST_F(AbilityMgrModuleTest, ability_mgr_service_test_022, TestSize.Level1) +{ + EXPECT_TRUE(abilityMgrServ_); + EXPECT_TRUE(mockAppMgrClient_); + ClearStack(); + + std::string abilityName = "TVAbility"; + std::string bundleName = COM_IX_TV; + std::string abilityName2 = "FilmAbility"; + std::string bundleName2 = COM_IX_Film; + Want want = CreateWant(abilityName, bundleName); + Want want2 = CreateWant(abilityName2, bundleName2); + sptr scheduler = new MockAbilityScheduler(); + EXPECT_TRUE(scheduler); + EXPECT_CALL(*mockAppMgrClient_, LoadAbility(_, _, _, _)).Times(2); + EXPECT_CALL(*mockAppMgrClient_, AbilityAttachTimeOut(_)).Times(1); + EXPECT_CALL(*mockAppMgrClient_, UpdateAbilityState(_, _)).Times(1); + EXPECT_CALL(*scheduler, ScheduleAbilityTransaction(_, _)).Times(2); + EXPECT_CALL(*scheduler, AsObject()).Times(2); + abilityMgrServ_->StartAbility(want); + auto testAbilityRecord = GetTopAbility(); + EXPECT_TRUE(testAbilityRecord); + abilityMgrServ_->AttachAbilityThread(scheduler, testAbilityRecord->GetToken()); + SetActive(); + abilityMgrServ_->StartAbility(want2); + auto testAbilityRecord2 = GetTopAbility(); + EXPECT_TRUE(testAbilityRecord2); + auto stackMgr = abilityMgrServ_->GetStackManager(); + EXPECT_TRUE(stackMgr); + stackMgr->CompleteInactive(testAbilityRecord); + abilityMgrServ_->HandleLoadTimeOut(testAbilityRecord2->GetEventId()); + testAbilityRecord = GetTopAbility(); + EXPECT_TRUE(testAbilityRecord); + EXPECT_TRUE(testAbilityRecord->GetAbilityInfo().bundleName == bundleName); + testing::Mock::AllowLeak(scheduler); +} + +/* + * Feature: AbilityManagerService + * Function: IsFirstInMission + * SubFunction: NA + * FunctionPoints: AbilityManagerService IsFirstInMission + * EnvConditions: NA + * CaseDescription: Verify function IsFirstInMission + * Checks whether this ability is the first ability in a mission. + */ +HWTEST_F(AbilityMgrModuleTest, ability_mgr_service_test_023, TestSize.Level1) +{ + EXPECT_TRUE(abilityMgrServ_); + EXPECT_TRUE(mockAppMgrClient_); + ClearStack(); + EXPECT_CALL(*mockAppMgrClient_, LoadAbility(_, _, _, _)).Times(1); + Want want = CreateWant("RadioTopAbility", COM_IX_HIRADIO); + abilityMgrServ_->StartAbility(want); + auto testAbilityRecord = GetTopAbility(); + EXPECT_TRUE(testAbilityRecord); + SetActive(); + auto resultTvFunction = abilityMgrServ_->IsFirstInMission(testAbilityRecord->GetToken()); + EXPECT_EQ(resultTvFunction, true); +} + +/* + * Feature: AbilityManagerService + * Function: MoveMissionToEnd + * SubFunction: NA + * FunctionPoints: AbilityManagerService MoveMissionToEnd + * EnvConditions: NA + * CaseDescription: Verify function MoveMissionToEnd + * Multiple MissionRecord in Stack,When this ability is not the first ability in a mission, + * and MoveMissionToEnd second parameter is true. + */ +HWTEST_F(AbilityMgrModuleTest, ability_mgr_service_test_024, TestSize.Level1) +{ + EXPECT_TRUE(abilityMgrServ_); + EXPECT_TRUE(mockAppMgrClient_); + ClearStack(); + auto stackManager = abilityMgrServ_->GetStackManager(); + EXPECT_TRUE(stackManager); + sptr scheduler = new MockAbilityScheduler(); + EXPECT_CALL(*mockAppMgrClient_, LoadAbility(_, _, _, _)).Times(1); + EXPECT_CALL(*scheduler, ScheduleAbilityTransaction(_, _)).Times(1); + EXPECT_CALL(*scheduler, AsObject()).Times(2); + Want want = CreateWant("PhoneAbility1", COM_IX_PHONE); + abilityMgrServ_->StartAbility(want); + auto ability = stackManager->GetCurrentTopAbility(); + EXPECT_TRUE(ability); + SetActive(); + Want want2 = CreateWant("PhoneAbility2", COM_IX_PHONE); + abilityMgrServ_->StartAbility(want2); + EXPECT_TRUE(scheduler); + auto abilityTv = stackManager->GetCurrentTopAbility(); + EXPECT_TRUE(abilityTv); + abilityTv->SetScheduler(scheduler); + SetActive(); + auto resultFunction = abilityMgrServ_->MoveMissionToEnd(abilityTv->GetToken(), true); + EXPECT_EQ(resultFunction, ERR_OK); + testing::Mock::AllowLeak(scheduler); +} + +/* + * Feature: AbilityManagerService + * Function: CompelVerifyPermission + * SubFunction: NA + * FunctionPoints: AbilityManagerService CompelVerifyPermission + * EnvConditions: NA + * CaseDescription: Verify function CompelVerifyPermission + */ +HWTEST_F(AbilityMgrModuleTest, ability_mgr_service_test_025, TestSize.Level1) +{ + EXPECT_TRUE(abilityMgrServ_); + EXPECT_TRUE(mockAppMgrClient_); + const std::string permission = "permission"; + int pid = 100; + int uid = 1000; + std::string message; + int runTimes = 1; + EXPECT_CALL(*mockAppMgrClient_, CompelVerifyPermission(_, _, _, _)).Times(runTimes); + auto resultFunction = abilityMgrServ_->CompelVerifyPermission(permission, pid, uid, message); + EXPECT_EQ(resultFunction, 0); +} +/* + * Feature: AbilityManagerService + * Function: AmsConfigurationParameter + * SubFunction: NA + * FunctionPoints: AbilityManagerService CompelVerifyPermission + * EnvConditions: NA + * CaseDescription: Judge the acquired properties + */ +HWTEST_F(AbilityMgrModuleTest, AmsConfigurationParameter_026, TestSize.Level1) +{ + EXPECT_TRUE(abilityMgrServ_->amsConfigResolver_); + EXPECT_FALSE(abilityMgrServ_->amsConfigResolver_->NonConfigFile()); + + // Open a path that does not exist + auto ref = abilityMgrServ_->amsConfigResolver_->LoadAmsConfiguration("/system/etc/ams.txt"); + // faild return 1 + EXPECT_EQ(ref, 1); +} + +/* + * Feature: AbilityManagerService + * Function: AmsConfigurationParameter + * SubFunction: NA + * FunctionPoints: AbilityManagerService CompelVerifyPermission + * EnvConditions: NA + * CaseDescription: Judge the acquired properties + */ +HWTEST_F(AbilityMgrModuleTest, AmsConfigurationParameter_027, TestSize.Level1) +{ + bool startLauncher = false; + bool startstatusbar = false; + bool startnavigationbar = false; + nlohmann::json info; + std::ifstream file(AmsConfig::AMS_CONFIG_FILE_PATH, std::ios::in); + if (file.is_open()) { + file >> info; + info.at(AmsConfig::SERVICE_ITEM_AMS).at(AmsConfig::STARTUP_LAUNCHER).get_to(startLauncher); + info.at(AmsConfig::SERVICE_ITEM_AMS).at(AmsConfig::STARTUP_STATUS_BAR).get_to(startstatusbar); + info.at(AmsConfig::SERVICE_ITEM_AMS).at(AmsConfig::STARTUP_NAVIGATION_BAR).get_to(startnavigationbar); + } + + EXPECT_EQ(startLauncher, abilityMgrServ_->amsConfigResolver_->GetStartLauncherState()); + EXPECT_EQ(startstatusbar, abilityMgrServ_->amsConfigResolver_->GetStatusBarState()); + EXPECT_EQ(startnavigationbar, abilityMgrServ_->amsConfigResolver_->GetNavigationBarState()); +} + +} // namespace AAFwk +} // namespace OHOS diff --git a/tools/services/test/moduletest/ability_record_test/BUILD.gn b/tools/services/test/moduletest/ability_record_test/BUILD.gn new file mode 100755 index 00000000000..014c1d4266d --- /dev/null +++ b/tools/services/test/moduletest/ability_record_test/BUILD.gn @@ -0,0 +1,121 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/test.gni") +import("//foundation/aafwk/standard/aafwk.gni") + +module_output_path = "aafwk_standard/mstabilitymgrservice" +EVENT_DIR = "//base/notification/ces_standard" + +ohos_moduletest("AbilityRecordModuleTest") { + module_out_path = module_output_path + + include_dirs = [ + "${EVENT_DIR}/frameworks/core/include", + "${EVENT_DIR}/interfaces/innerkits/native/include", + "//third_party/jsoncpp/include", + "//foundation/aafwk/standard/interfaces/innerkits/dataobs_manager/include", + ] + + sources = [ + "${services_path}/abilitymgr/src/ability_connect_callback_stub.cpp", + "${services_path}/abilitymgr/src/ability_connect_manager.cpp", + "${services_path}/abilitymgr/src/ability_event_handler.cpp", + "${services_path}/abilitymgr/src/ability_manager_proxy.cpp", + "${services_path}/abilitymgr/src/ability_manager_service.cpp", + "${services_path}/abilitymgr/src/ability_manager_stub.cpp", + "${services_path}/abilitymgr/src/ability_mission_info.cpp", + "${services_path}/abilitymgr/src/ability_record.cpp", + "${services_path}/abilitymgr/src/ability_record_info.cpp", + "${services_path}/abilitymgr/src/ability_scheduler_proxy.cpp", + "${services_path}/abilitymgr/src/ability_scheduler_stub.cpp", + "${services_path}/abilitymgr/src/ability_stack_manager.cpp", + "${services_path}/abilitymgr/src/ability_token_stub.cpp", + "${services_path}/abilitymgr/src/app_scheduler.cpp", + "${services_path}/abilitymgr/src/caller_info.cpp", + "${services_path}/abilitymgr/src/connection_record.cpp", + "${services_path}/abilitymgr/src/data_ability_manager.cpp", + "${services_path}/abilitymgr/src/data_ability_record.cpp", + + # "${services_path}/abilitymgr/src/dummy_configuration.cpp", + "${services_path}/abilitymgr/src/image_info.cpp", + "${services_path}/abilitymgr/src/kernal_system_app_manager.cpp", + "${services_path}/abilitymgr/src/lifecycle_deal.cpp", + "${services_path}/abilitymgr/src/lifecycle_state_info.cpp", + "${services_path}/abilitymgr/src/mission_description_info.cpp", + "${services_path}/abilitymgr/src/mission_record.cpp", + "${services_path}/abilitymgr/src/mission_record_info.cpp", + "${services_path}/abilitymgr/src/mission_snapshot_info.cpp", + "${services_path}/abilitymgr/src/mission_stack.cpp", + "${services_path}/abilitymgr/src/mission_stack_info.cpp", + "${services_path}/abilitymgr/src/pending_want_key.cpp", + "${services_path}/abilitymgr/src/pending_want_manager.cpp", + "${services_path}/abilitymgr/src/pending_want_record.cpp", + "${services_path}/abilitymgr/src/power_storage.cpp", + "${services_path}/abilitymgr/src/sa_mgr_client.cpp", + "${services_path}/abilitymgr/src/sender_info.cpp", + "${services_path}/abilitymgr/src/stack_info.cpp", + "${services_path}/abilitymgr/src/want_receiver_stub.cpp", + "${services_path}/abilitymgr/src/want_sender_info.cpp", + "${services_path}/abilitymgr/src/want_sender_stub.cpp", + "${services_path}/abilitymgr/src/wants_info.cpp", + "//foundation/aafwk/standard/services/test/mock/src/mock_app_mgr_client.cpp", + ] + + sources += [ "ability_record_module_test.cpp" ] + + configs = [ + "${services_path}/test:aafwk_module_test_config", + "//foundation/appexecfwk/standard/common:appexecfwk_common_config", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_core:appexecfwk_core_config", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:public_libeventhandler_config", + "//foundation/distributedschedule/safwk/interfaces/innerkits/safwk:system_ability_config", + "//foundation/aafwk/standard/interfaces/innerkits/want:want_public_config", + ] + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + deps = [ + "${innerkits_path}/want:want", + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/frameworks/kits/ability/native:dummy_classes", + "//foundation/aafwk/standard/services/abilitymgr:abilityms", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_core:appexecfwk_core", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//foundation/distributedschedule/safwk/interfaces/innerkits/safwk:system_ability_fwk", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy:samgr_proxy", + "//third_party/googletest:gmock_main", + "//third_party/googletest:gtest_main", + "//third_party/jsoncpp:jsoncpp", + "//utils/native/base:utilsbase", + ] + + external_deps = [ + "ces_standard:cesfwk_core", + "ces_standard:cesfwk_innerkits", + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + "native_appdatamgr:native_appdatafwk", + "native_appdatamgr:native_dataability", + "native_appdatamgr:native_rdb", + ] +} + +group("moduletest") { + testonly = true + + deps = [ ":AbilityRecordModuleTest" ] +} diff --git a/tools/services/test/moduletest/ability_record_test/ability_record_module_test.cpp b/tools/services/test/moduletest/ability_record_test/ability_record_module_test.cpp new file mode 100644 index 00000000000..d777ed27164 --- /dev/null +++ b/tools/services/test/moduletest/ability_record_test/ability_record_module_test.cpp @@ -0,0 +1,711 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include +#include + +#include "abs_shared_result_set.h" +#include "data_ability_predicates.h" +#include "values_bucket.h" + +#include "want.h" + +#define private public +#include "app_scheduler.h" +#include "ability_record.h" +#include "mission_record.h" +#include "connection_record.h" +#include "mock_app_mgr_client.h" +#include "mock_ability_scheduler_stub.h" +#undef private + +using namespace testing::ext; +using namespace OHOS::AppExecFwk; +using OHOS::iface_cast; +using OHOS::sptr; +using testing::_; +using testing::Invoke; +using testing::Return; + +namespace { +constexpr int COUNT = 1000; +} // namespace + +namespace OHOS::AppExecFwk { +bool operator==(const AbilityInfo &a, const AbilityInfo &b) +{ + if (&a != &b) { + return a.package == b.package && a.name == b.name && a.label == b.label && a.description == b.description && + a.iconPath == b.iconPath && a.visible == b.visible && a.kind == b.kind && + a.permissions == b.permissions && a.bundleName == b.bundleName && + a.applicationName == b.applicationName && a.deviceId == b.deviceId && a.codePath == b.codePath && + a.resourcePath == b.resourcePath && a.libPath == b.libPath; + } + + return true; +} + +bool operator!=(const AbilityInfo &a, const AbilityInfo &b) +{ + return !(a == b); +} + +bool operator==(const ApplicationInfo &a, const ApplicationInfo &b) +{ + if (&a != &b) { + return a.name == b.name && a.bundleName == b.bundleName && a.deviceId == b.deviceId && + a.signatureKey == b.signatureKey; + } + + return true; +} + +bool operator!=(const ApplicationInfo &a, const ApplicationInfo &b) +{ + return !(a == b); +} + +} // namespace OHOS::AppExecFwk + +namespace OHOS::AAFwk { + +bool operator==(const Want &a, const Want &b) +{ + if (&a != &b) { + return a.GetAction() == b.GetAction() && a.GetEntities() == b.GetEntities(); + } + + return true; +} + +bool operator!=(const Want &a, const Want &b) +{ + return !(a == b); +} + +} // namespace OHOS::AAFwk + +namespace OHOS { +namespace AAFwk { +class AbilityRecordModuleTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp(); + void TearDown(); + +protected: + static const AbilityRequest &MakeDefaultAbilityRequest(); + static const AbilityRequest &MakeHomeAbilityRequest(); + +private: + inline static AbilityRequest testAbilityRequest_; +}; + +void AbilityRecordModuleTest::SetUpTestCase() +{ + int testCode = 123; + testAbilityRequest_.requestCode = testCode; + + testAbilityRequest_.abilityInfo.package = "test"; + testAbilityRequest_.abilityInfo.name = "test"; + testAbilityRequest_.abilityInfo.label = "test"; + testAbilityRequest_.abilityInfo.description = "test"; + testAbilityRequest_.abilityInfo.iconPath = "/test"; + testAbilityRequest_.abilityInfo.visible = false; + testAbilityRequest_.abilityInfo.kind = "page"; + testAbilityRequest_.abilityInfo.permissions = {}; + testAbilityRequest_.abilityInfo.bundleName = "test"; + testAbilityRequest_.abilityInfo.applicationName = "test"; + testAbilityRequest_.abilityInfo.deviceId = "test"; + testAbilityRequest_.abilityInfo.codePath = "/test"; + testAbilityRequest_.abilityInfo.resourcePath = "/test"; + testAbilityRequest_.abilityInfo.libPath = "/test"; + + testAbilityRequest_.appInfo.name = "test"; + testAbilityRequest_.appInfo.bundleName = "test"; + testAbilityRequest_.appInfo.deviceId = "test"; + testAbilityRequest_.appInfo.signatureKey = "test"; +} + +void AbilityRecordModuleTest::TearDownTestCase() +{} + +void AbilityRecordModuleTest::SetUp() +{} + +void AbilityRecordModuleTest::TearDown() +{} + +const AbilityRequest &AbilityRecordModuleTest::MakeDefaultAbilityRequest() +{ + Want::ClearWant(&testAbilityRequest_.want); + testAbilityRequest_.want.SetAction("test"); + testAbilityRequest_.want.AddEntity("test"); + + return testAbilityRequest_; +} + +const AbilityRequest &AbilityRecordModuleTest::MakeHomeAbilityRequest() +{ + Want::ClearWant(&testAbilityRequest_.want); + testAbilityRequest_.want.SetAction(Want::ACTION_HOME); + testAbilityRequest_.want.AddEntity(Want::ENTITY_HOME); + testAbilityRequest_.appInfo.isLauncherApp = true; + + return testAbilityRequest_; +} + +/* + * Feature: AbilityRecord + * Function: Init + * SubFunction: Init/CreateAbilityRecord + * FunctionPoints: Normal AbilityRecord + * CaseDescription: Create a normal 'AbilityRecord' instance, and check its state. + */ +HWTEST_F(AbilityRecordModuleTest, Init_001, TestSize.Level2) +{ + auto &abilityRequest = MakeDefaultAbilityRequest(); + + for (int i = 0; i < COUNT; ++i) { + auto abilityRecord = AbilityRecord::CreateAbilityRecord(abilityRequest); + EXPECT_TRUE(abilityRecord); + EXPECT_TRUE(abilityRecord->GetToken()); + EXPECT_TRUE(abilityRecord->GetRecordId() >= 0); + EXPECT_FALSE(abilityRecord->IsLauncherAbility()); + EXPECT_EQ(abilityRecord->GetAbilityState(), INITIAL); + EXPECT_EQ(abilityRecord->GetRequestCode(), abilityRequest.requestCode); + EXPECT_EQ(abilityRecord->GetAbilityInfo(), abilityRequest.abilityInfo); + EXPECT_EQ(abilityRecord->GetApplicationInfo(), abilityRequest.appInfo); + } +} + +/* + * Feature: AbilityRecord + * Function: Init + * SubFunction: Init/CreateAbilityRecord + * FunctionPoints: Launcher AbilityRecord + * CaseDescription: Create a launcher 'AbilityRecord' instance, and check its state (includes 'IsLauncherAbility()). + */ +HWTEST_F(AbilityRecordModuleTest, Init_002, TestSize.Level2) +{ + auto &abilityRequest = MakeHomeAbilityRequest(); + + for (int i = 0; i < COUNT; ++i) { + auto abilityRecord = AbilityRecord::CreateAbilityRecord(abilityRequest); + EXPECT_TRUE(abilityRecord); + EXPECT_TRUE(abilityRecord->GetToken()); + EXPECT_TRUE(abilityRecord->IsLauncherAbility()); + EXPECT_EQ(abilityRecord->GetAbilityState(), INITIAL); + EXPECT_EQ(abilityRecord->GetRequestCode(), abilityRequest.requestCode); + EXPECT_EQ(abilityRecord->GetAbilityInfo(), abilityRequest.abilityInfo); + EXPECT_EQ(abilityRecord->GetApplicationInfo(), abilityRequest.appInfo); + } +} + +/* + * Feature: AbilityRecord + * Function: LoadAbility + * SubFunction: N/A + * FunctionPoints: Load a test ability + * CaseDescription: Load a test ability and check state in 'AppMgrClient' mocker. + */ +HWTEST_F(AbilityRecordModuleTest, LoadAbility_001, TestSize.Level3) +{ + auto &abilityRequest = MakeDefaultAbilityRequest(); + + for (int i = 0; i < COUNT; ++i) { + auto abilityRecord = AbilityRecord::CreateAbilityRecord(abilityRequest); + EXPECT_TRUE(abilityRecord); + + std::unique_ptr mockAppMgrClient(new MockAppMgrClient); + EXPECT_TRUE(mockAppMgrClient); + + auto mockHandler = [&](const sptr &token, + const sptr &preToken, + const AbilityInfo &abilityInfo, + const ApplicationInfo &appInfo) { + if (abilityInfo != abilityRequest.abilityInfo) { + return static_cast(ERR_INVALID_VALUE); + } + if (appInfo != abilityRequest.appInfo) { + return static_cast(ERR_INVALID_VALUE); + } + return AppExecFwk::RESULT_OK; + }; + + EXPECT_CALL(*mockAppMgrClient, LoadAbility(_, _, _, _)).Times(1).WillOnce(Invoke(mockHandler)); + + auto appScheduler = DelayedSingleton::GetInstance(); + auto backupAppMgrClient = std::move(appScheduler->appMgrClient_); + appScheduler->appMgrClient_ = std::move(mockAppMgrClient); + + auto result = abilityRecord->LoadAbility(); + EXPECT_EQ(result, ERR_OK); + + EXPECT_EQ(abilityRecord->GetAbilityInfo(), abilityRequest.abilityInfo); + EXPECT_EQ(abilityRecord->GetApplicationInfo(), abilityRequest.appInfo); + + appScheduler->appMgrClient_ = std::move(backupAppMgrClient); + } +} + +/* + * Feature: AbilityRecord + * Function: TerminateAbility + * SubFunction: N/A + * FunctionPoints: Terminate a ability + * CaseDescription: Terminate a test ability and check state in 'AppMgrClient' mocker. + */ +HWTEST_F(AbilityRecordModuleTest, TerminateAbility_001, TestSize.Level3) +{ + auto &abilityRequest = MakeDefaultAbilityRequest(); + + for (int i = 0; i < COUNT; ++i) { + auto abilityRecord = AbilityRecord::CreateAbilityRecord(abilityRequest); + EXPECT_TRUE(abilityRecord); + + auto mockAppMgrClient = std::make_unique(); + EXPECT_TRUE(mockAppMgrClient); + + EXPECT_CALL(*mockAppMgrClient, TerminateAbility(_)).Times(1).WillOnce(Return(RESULT_OK)); + + auto appScheduler = DelayedSingleton::GetInstance(); + auto backupAppMgrClient = std::move(appScheduler->appMgrClient_); + appScheduler->appMgrClient_ = std::move(mockAppMgrClient); + + auto result = abilityRecord->TerminateAbility(); + EXPECT_EQ(result, ERR_OK); + + appScheduler->appMgrClient_ = std::move(backupAppMgrClient); + } +} + +/* + * Feature: AbilityRecord + * Function: Scheduler + * SubFunction: Activate/Inactivate/MoveToBackground/Terminate/ConnectAbility/DisconnectAbility/SendResult + * FunctionPoints: Check scheduler work flow. + * CaseDescription: Change ability state and check if the work flow reachs the 'AbilityScheduler' mocker. + */ +HWTEST_F(AbilityRecordModuleTest, AbilityScheduler_001, TestSize.Level3) +{ + auto &abilityRequest = MakeDefaultAbilityRequest(); + auto abilityRecord = AbilityRecord::CreateAbilityRecord(abilityRequest); + EXPECT_TRUE(abilityRecord); + + sptr mockAbilityScheduerStub(new MockAbilitySchedulerStub); + EXPECT_TRUE(mockAbilityScheduerStub); + + bool testResult = false; + abilityRecord->SetScheduler(mockAbilityScheduerStub); + EXPECT_TRUE(abilityRecord->IsReady()); + + for (int i = 0; i < COUNT; ++i) { + // Activate + auto mockActivateHandler = [&](const Want &want, const LifeCycleStateInfo &lifeCycleStateInfo) { + testResult = (lifeCycleStateInfo.state == AbilityLifeCycleState::ABILITY_STATE_ACTIVE); + }; + testResult = false; + EXPECT_CALL(*mockAbilityScheduerStub, ScheduleAbilityTransaction(_, _)) + .Times(1) + .WillOnce(Invoke(mockActivateHandler)); + + abilityRecord->Activate(); + EXPECT_TRUE(testResult); + EXPECT_EQ(abilityRecord->GetAbilityState(), ACTIVATING); + + // Inactivate + testResult = false; + auto mockInactivateHandler = [&](const Want &want, const LifeCycleStateInfo &lifeCycleStateInfo) { + testResult = (lifeCycleStateInfo.state == AbilityLifeCycleState::ABILITY_STATE_INACTIVE); + }; + EXPECT_CALL(*mockAbilityScheduerStub, ScheduleAbilityTransaction(_, _)) + .Times(1) + .WillOnce(Invoke(mockInactivateHandler)); + + abilityRecord->Inactivate(); + EXPECT_TRUE(testResult); + EXPECT_EQ(abilityRecord->GetAbilityState(), INACTIVATING); + + // MoveToBackground + testResult = false; + auto mockBackgroundHandler = [&](const Want &want, const LifeCycleStateInfo &lifeCycleStateInfo) { + testResult = (lifeCycleStateInfo.state == AbilityLifeCycleState::ABILITY_STATE_BACKGROUND); + }; + EXPECT_CALL(*mockAbilityScheduerStub, ScheduleAbilityTransaction(_, _)) + .Times(1) + .WillOnce(Invoke(mockBackgroundHandler)); + + abilityRecord->MoveToBackground([] {}); + EXPECT_TRUE(testResult); + EXPECT_EQ(abilityRecord->GetAbilityState(), MOVING_BACKGROUND); + + // Terminate + EXPECT_CALL(*mockAbilityScheduerStub, ScheduleAbilityTransaction(_, _)).Times(1); + abilityRecord->Terminate([] {}); + EXPECT_EQ(abilityRecord->GetAbilityState(), TERMINATING); + + // Connect + testResult = false; + auto mockConnectHandler = [&](const Want &want) { testResult = want == abilityRequest.want; }; + EXPECT_CALL(*mockAbilityScheduerStub, ScheduleConnectAbility(_)).Times(1).WillOnce(Invoke(mockConnectHandler)); + abilityRecord->ConnectAbility(); + EXPECT_TRUE(testResult); + + // Disconnect + testResult = false; + auto mockDisconnectHandler = [&](const Want &want) { testResult = want == abilityRequest.want; }; + EXPECT_CALL(*mockAbilityScheduerStub, ScheduleDisconnectAbility(_)) + .Times(1) + .WillOnce(Invoke(mockDisconnectHandler)); + abilityRecord->DisconnectAbility(); + EXPECT_TRUE(testResult); + + // SendResult + testResult = false; + int testResultCode = 123; + auto mockSendResultHandler = [&](int requestCode, int resultCode, const Want &want) { + testResult = requestCode == abilityRequest.requestCode && resultCode == testResultCode && + want == abilityRequest.want; + }; + EXPECT_CALL(*mockAbilityScheduerStub, SendResult(_, _, _)).Times(1).WillOnce(Invoke(mockSendResultHandler)); + auto abilityResult = + std::make_shared(abilityRequest.requestCode, testResultCode, abilityRequest.want); + EXPECT_TRUE(abilityResult); + abilityRecord->SetResult(abilityResult); + abilityRecord->SendResult(); + EXPECT_TRUE(testResult); + } + + abilityRecord->SetScheduler(nullptr); +} + +/* + * Feature: AbilityRecord + * Function: MissionRecord + * SubFunction: SetMissionRecord/GetMissionRecord + * FunctionPoints: Mission record getter and setter + * CaseDescription: Check the mission record getter and setter. + */ +HWTEST_F(AbilityRecordModuleTest, MissionRecord_001, TestSize.Level1) +{ + auto &abilityRequest = MakeDefaultAbilityRequest(); + + auto abilityRecord = AbilityRecord::CreateAbilityRecord(abilityRequest); + EXPECT_TRUE(abilityRecord); + + auto missionRecord = std::make_shared("test"); + EXPECT_TRUE(missionRecord); + + abilityRecord->SetMissionRecord(missionRecord); + EXPECT_EQ(missionRecord, abilityRecord->GetMissionRecord()); +} + +/* + * Feature: AbilityRecord + * Function: Pre and Next Abilities + * SubFunction: SetPreAbilityRecord/GetPreAbility/SetNextAbilityRecord/GetNextAbilityRecord + * FunctionPoints: Pre and Next ability record getter and setter + * CaseDescription: Check the pre and next ability record getter and setter. + */ +HWTEST_F(AbilityRecordModuleTest, PreNextAbilities_001, TestSize.Level1) +{ + auto &abilityRequest = MakeDefaultAbilityRequest(); + + auto abilityRecord = AbilityRecord::CreateAbilityRecord(abilityRequest); + EXPECT_TRUE(abilityRecord); + + auto preAbilityRecord = AbilityRecord::CreateAbilityRecord(abilityRequest); + EXPECT_TRUE(preAbilityRecord); + + auto nextAbilityRecord = AbilityRecord::CreateAbilityRecord(abilityRequest); + EXPECT_TRUE(nextAbilityRecord); + + for (int i = 0; i < COUNT; ++i) { + abilityRecord->SetPreAbilityRecord(preAbilityRecord); + abilityRecord->SetNextAbilityRecord(nextAbilityRecord); + EXPECT_EQ(abilityRecord->GetPreAbilityRecord(), preAbilityRecord); + EXPECT_EQ(abilityRecord->GetNextAbilityRecord(), nextAbilityRecord); + } +} + +/* + * Feature: AbilityRecord + * Function: EventId + * SubFunction: SetEventId/GetEventId + * FunctionPoints: Event id getter and setter + * CaseDescription: Check ability record event id getter and setter. + */ +HWTEST_F(AbilityRecordModuleTest, EventId_001, TestSize.Level1) +{ + auto &abilityRequest = MakeDefaultAbilityRequest(); + + auto abilityRecord = AbilityRecord::CreateAbilityRecord(abilityRequest); + EXPECT_TRUE(abilityRecord); + + for (int i = 0; i < COUNT; ++i) { + abilityRecord->SetEventId(i); + EXPECT_EQ(abilityRecord->GetEventId(), i); + } +} + +/* + * Feature: AbilityRecord + * Function: AbilityState + * SubFunction: SetAbilityState/GetAbilityState + * FunctionPoints: Ability state getter and setter + * CaseDescription: Check ability state getter and setter. + */ +HWTEST_F(AbilityRecordModuleTest, AbilityState_001, TestSize.Level1) +{ + auto &abilityRequest = MakeDefaultAbilityRequest(); + + auto abilityRecord = AbilityRecord::CreateAbilityRecord(abilityRequest); + EXPECT_TRUE(abilityRecord); + + for (int i = 0; i < COUNT; ++i) { + abilityRecord->SetAbilityState(INITIAL); + EXPECT_EQ(abilityRecord->GetAbilityState(), INITIAL); + } +} + +/* + * Feature: AbilityRecord + * Function: Want + * SubFunction: SetWant/GetWant + * FunctionPoints: Ability want getter and setter + * CaseDescription: Check ability want getter and setter. + */ +HWTEST_F(AbilityRecordModuleTest, Want_001, TestSize.Level1) +{ + auto &abilityRequest = MakeDefaultAbilityRequest(); + + auto abilityRecord = AbilityRecord::CreateAbilityRecord(abilityRequest); + EXPECT_TRUE(abilityRecord); + + auto initWant = abilityRecord->GetWant(); + EXPECT_EQ(initWant, abilityRequest.want); + + Want setWant; + setWant.SetAction("newAction"); + setWant.AddEntity("newEntity"); + + for (int i = 0; i < COUNT; ++i) { + abilityRecord->SetWant(setWant); + auto newWant = abilityRecord->GetWant(); + EXPECT_EQ(setWant, newWant); + } +} + +/* + * Feature: AbilityRecord + * Function: ConnectionRecord + * SubFunction: AddConnectRecordToList/GetConnectRecordList/GetConnectingRecord/GetDisconnectingRecord + * FunctionPoints: Ability connect record getter and setter + * CaseDescription: Check ability connect record getter and setter. + */ +HWTEST_F(AbilityRecordModuleTest, ConnectionRecord_001, TestSize.Level2) +{ + auto &abilityRequest = MakeDefaultAbilityRequest(); + + auto abilityRecord = AbilityRecord::CreateAbilityRecord(abilityRequest); + EXPECT_TRUE(abilityRecord); + EXPECT_TRUE(abilityRecord->IsConnectListEmpty()); + + auto connectionRecord = ConnectionRecord::CreateConnectionRecord(nullptr, nullptr, nullptr); + EXPECT_TRUE(connectionRecord); + + for (int i = 0; i < COUNT; ++i) { + abilityRecord->AddConnectRecordToList(connectionRecord); + EXPECT_FALSE(abilityRecord->IsConnectListEmpty()); + auto connectionRecordList = abilityRecord->GetConnectRecordList(); + auto it = std::find(connectionRecordList.begin(), connectionRecordList.end(), connectionRecord); + EXPECT_TRUE(it != connectionRecordList.end()); + + EXPECT_FALSE(abilityRecord->GetConnectingRecord()); + connectionRecord->SetConnectState(ConnectionState::CONNECTING); + EXPECT_TRUE(abilityRecord->GetConnectingRecord()); + + EXPECT_FALSE(abilityRecord->GetDisconnectingRecord()); + connectionRecord->SetConnectState(ConnectionState::DISCONNECTING); + EXPECT_TRUE(abilityRecord->GetDisconnectingRecord()); + + abilityRecord->RemoveConnectRecordFromList(connectionRecord); + EXPECT_TRUE(abilityRecord->IsConnectListEmpty()); + connectionRecordList = abilityRecord->GetConnectRecordList(); + it = std::find(connectionRecordList.begin(), connectionRecordList.end(), connectionRecord); + EXPECT_TRUE(it == connectionRecordList.end()); + } +} + +/* + * Feature: AbilityRecord + * Function: ConnectionRecord + * SubFunction: AddWindowInfo/RemoveWindowInfo/GetWindowInfo + * FunctionPoints: Ability window info getter and setter + * CaseDescription: Check ability window info getter and setter. + */ +HWTEST_F(AbilityRecordModuleTest, WindowInfo_001, TestSize.Level1) +{ + auto &abilityRequest = MakeDefaultAbilityRequest(); + + auto abilityRecord = AbilityRecord::CreateAbilityRecord(abilityRequest); + EXPECT_TRUE(abilityRecord); + EXPECT_FALSE(abilityRecord->GetWindowInfo()); + + for (int i = 0; i < COUNT; ++i) { + abilityRecord->AddWindowInfo(123); + EXPECT_TRUE(abilityRecord->GetWindowInfo()); + abilityRecord->RemoveWindowInfo(); + EXPECT_FALSE(abilityRecord->GetWindowInfo()); + } +} + +/* + * Feature: AbilityRecord + * Function: Terminating + * SubFunction: IsTerminating/SetTerminatingState + * FunctionPoints: Ability terminating state + * CaseDescription: Check ability terminating state. + */ +HWTEST_F(AbilityRecordModuleTest, Terminating_001, TestSize.Level1) +{ + auto &abilityRequest = MakeDefaultAbilityRequest(); + + auto abilityRecord = AbilityRecord::CreateAbilityRecord(abilityRequest); + EXPECT_TRUE(abilityRecord); + + EXPECT_FALSE(abilityRecord->IsTerminating()); + abilityRecord->SetTerminatingState(); + EXPECT_TRUE(abilityRecord->IsTerminating()); +} + +/* + * Feature: AbilityRecord + * Function: NewWant + * SubFunction: IsNewWant/SetIsNewWant + * FunctionPoints: Ability 'IsNewWant' state + * CaseDescription: Check ability 'IsNewWant' state. + */ +HWTEST_F(AbilityRecordModuleTest, NewWant_001, TestSize.Level1) +{ + auto &abilityRequest = MakeDefaultAbilityRequest(); + + auto abilityRecord = AbilityRecord::CreateAbilityRecord(abilityRequest); + EXPECT_TRUE(abilityRecord); + EXPECT_FALSE(abilityRecord->IsNewWant()); + + for (int i = 0; i < COUNT; ++i) { + abilityRecord->SetIsNewWant(true); + EXPECT_TRUE(abilityRecord->IsNewWant()); + abilityRecord->SetIsNewWant(false); + EXPECT_FALSE(abilityRecord->IsNewWant()); + } +} + +/* + * Feature: AbilityRecord + * Function: ConvertAbilityState + * SubFunction: N/A + * FunctionPoints: ConvertAbilityState + * CaseDescription: Check function 'ConvertAbilityState'. + */ +HWTEST_F(AbilityRecordModuleTest, ConvertAbilityState_001, TestSize.Level1) +{ + static std::string result; + + result = AbilityRecord::ConvertAbilityState(INITIAL); + EXPECT_EQ(result, "INITIAL"); + + result = AbilityRecord::ConvertAbilityState(INACTIVE); + EXPECT_EQ(result, "INACTIVE"); + + result = AbilityRecord::ConvertAbilityState(ACTIVE); + EXPECT_EQ(result, "ACTIVE"); + + result = AbilityRecord::ConvertAbilityState(BACKGROUND); + EXPECT_EQ(result, "BACKGROUND"); + + result = AbilityRecord::ConvertAbilityState(SUSPENDED); + EXPECT_EQ(result, "SUSPENDED"); + + result = AbilityRecord::ConvertAbilityState(INACTIVATING); + EXPECT_EQ(result, "INACTIVATING"); + + result = AbilityRecord::ConvertAbilityState(ACTIVATING); + EXPECT_EQ(result, "ACTIVATING"); + + result = AbilityRecord::ConvertAbilityState(MOVING_BACKGROUND); + EXPECT_EQ(result, "MOVING_BACKGROUND"); + + result = AbilityRecord::ConvertAbilityState(TERMINATING); + EXPECT_EQ(result, "TERMINATING"); +} + +/* + * Feature: AbilityRecord + * Function: ConvertLifeCycleToAbilityState + * SubFunction: N/A + * FunctionPoints: ConvertLifeCycleToAbilityState + * CaseDescription: Check function 'ConvertLifeCycleToAbilityState'. + */ +HWTEST_F(AbilityRecordModuleTest, ConvertLifeCycle_001, TestSize.Level1) +{ + int result; + + result = AbilityRecord::ConvertLifeCycleToAbilityState(ABILITY_STATE_INITIAL); + EXPECT_EQ(result, INITIAL); + + result = AbilityRecord::ConvertLifeCycleToAbilityState(ABILITY_STATE_INACTIVE); + EXPECT_EQ(result, INACTIVE); + + result = AbilityRecord::ConvertLifeCycleToAbilityState(ABILITY_STATE_ACTIVE); + EXPECT_EQ(result, ACTIVE); + + result = AbilityRecord::ConvertLifeCycleToAbilityState(ABILITY_STATE_BACKGROUND); + EXPECT_EQ(result, BACKGROUND); + + result = AbilityRecord::ConvertLifeCycleToAbilityState(ABILITY_STATE_SUSPENDED); + EXPECT_EQ(result, SUSPENDED); + + result = AbilityRecord::ConvertLifeCycleToAbilityState(static_cast(-1)); + EXPECT_EQ(result, -1); +} + +/* + * Feature: AbilityRecord + * Function: Dump + * SubFunction: N/A + * FunctionPoints: Dump + * CaseDescription: Check 'Dump' result. + */ +HWTEST_F(AbilityRecordModuleTest, Dump_001, TestSize.Level2) +{ + auto &abilityRequest = MakeDefaultAbilityRequest(); + + auto abilityRecord = AbilityRecord::CreateAbilityRecord(abilityRequest); + EXPECT_TRUE(abilityRecord); + + std::vector info; + abilityRecord->Dump(info); + EXPECT_FALSE(info.empty()); +} + +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/test/moduletest/ability_stack_test/BUILD.gn b/tools/services/test/moduletest/ability_stack_test/BUILD.gn new file mode 100755 index 00000000000..4c0cf7e6584 --- /dev/null +++ b/tools/services/test/moduletest/ability_stack_test/BUILD.gn @@ -0,0 +1,117 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/test.gni") +import("//foundation/aafwk/standard/aafwk.gni") + +module_output_path = "aafwk_standard/mstabilitymgrservice" + +ohos_moduletest("ability_stack_module_test") { + module_out_path = module_output_path + + include_dirs = [ + "${services_path}/test/mock/include", + "//third_party/jsoncpp/include", + "//foundation/aafwk/standard/interfaces/innerkits/dataobs_manager/include", + ] + + sources = [ "ability_stack_module_test.cpp" ] + sources += [ + "//foundation/aafwk/standard/services/abilitymgr/src/aafwk_dummy_configuration.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/ability_connect_callback_stub.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/ability_connect_manager.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/ability_event_handler.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/ability_manager_proxy.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/ability_manager_service.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/ability_manager_stub.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/ability_mission_info.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/ability_record.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/ability_record_info.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/ability_scheduler_proxy.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/ability_scheduler_stub.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/ability_stack_manager.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/ability_token_stub.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/app_scheduler.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/caller_info.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/connection_record.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/data_ability_manager.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/data_ability_record.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/image_info.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/kernal_system_app_manager.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/lifecycle_deal.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/lifecycle_state_info.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/mission_description_info.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/mission_record.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/mission_record_info.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/mission_snapshot_info.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/mission_stack.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/mission_stack_info.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/pending_want_key.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/pending_want_manager.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/pending_want_record.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/power_storage.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/sender_info.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/stack_info.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/want_receiver_stub.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/want_sender_info.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/want_sender_stub.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/wants_info.cpp", + "//foundation/aafwk/standard/services/abilitymgr/test/mock/libs/sa_mgr/src/sa_mgr_client_mock.cpp", + "//foundation/aafwk/standard/services/test/mock/src/mock_app_mgr_client.cpp", + "//foundation/aafwk/standard/services/test/mock/src/mock_bundle_mgr.cpp", + ] + configs = [ + "${services_path}/test:aafwk_module_test_config", + "//foundation/aafwk/standard/interfaces/innerkits/ability_manager:ability_manager_public_config", + "//foundation/aafwk/standard/services/abilitymgr/test/mock/libs/sa_mgr:sa_mgr_mock_config", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base_sdk_config", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_core:appmgr_sdk_config", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_core:bundlemgr_sdk_config", + ] + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + deps = [ + "${innerkits_path}/want:want", + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/frameworks/kits/ability/native:dummy_classes", + "//foundation/aafwk/standard/services/abilitymgr:abilityms", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_core:appexecfwk_core", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//foundation/distributedschedule/safwk/interfaces/innerkits/safwk:system_ability_fwk", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy:samgr_proxy", + "//third_party/googletest:gmock_main", + "//third_party/googletest:gtest_main", + "//third_party/jsoncpp:jsoncpp", + "//utils/native/base:utils", + ] + + external_deps = [ + "ces_standard:cesfwk_core", + "ces_standard:cesfwk_innerkits", + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + "native_appdatamgr:native_appdatafwk", + "native_appdatamgr:native_dataability", + "native_appdatamgr:native_rdb", + ] +} + +group("moduletest") { + testonly = true + + deps = [ ":ability_stack_module_test" ] +} diff --git a/tools/services/test/moduletest/ability_stack_test/ability_stack_module_test.cpp b/tools/services/test/moduletest/ability_stack_test/ability_stack_module_test.cpp new file mode 100644 index 00000000000..726648174c3 --- /dev/null +++ b/tools/services/test/moduletest/ability_stack_test/ability_stack_module_test.cpp @@ -0,0 +1,3610 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#define private public +#define protected public +#include "ability_stack_manager.h" +#include "ability_manager_errors.h" +#include "ability_event_handler.h" +#include "mock_ability_scheduler.h" +#include "mock_app_mgr_client.h" +#include "mock_app_scheduler.h" +#include "ability_manager_service.h" +#undef private +#undef protected + +#include "mock_bundle_mgr.h" +#include "sa_mgr_client.h" +#include "system_ability_definition.h" + +using namespace testing::ext; +using namespace OHOS::AppExecFwk; +using namespace testing; + +namespace OHOS { +namespace AAFwk { +namespace { +const std::string LANGUAGE = "locale"; +const std::string LAYOUT = "layout"; +const std::string FONTSIZE = "fontsize"; +const std::string ORIENTATION = "orientation"; +const std::string DENSITY = "density"; +} // namespace +class AbilityStackModuleTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + Want CreateWant(const std::string &entity); + AbilityInfo CreateAbilityInfo(const std::string &name, const std::string &appName, const std::string &bundleName); + ApplicationInfo CreateAppInfo(const std::string &appName, const std::string &bundleName); + AbilityRequest GenerateAbilityRequest(const std::string &deviceName, const std::string &abilityName, + const std::string &appName, const std::string &bundleName); + void makeScene(const std::string &abilityName, const std::string &bundleName, AbilityInfo &abilityInfo, Want &want); + +public: + std::shared_ptr stackManager_{nullptr}; + inline static BundleMgrService *bundleObject_{nullptr}; + inline static MockAppMgrClient *mockAppMgrClient{nullptr}; + OHOS::sptr mockScheduler_ = nullptr; +}; + +void AbilityStackModuleTest::SetUpTestCase(void) +{ + GTEST_LOG_(INFO) << "SetUpTestCase"; + if (!mockAppMgrClient) { + mockAppMgrClient = new (std::nothrow) MockAppMgrClient(); + } + + auto appScheduler = OHOS::DelayedSingleton::GetInstance(); + + if (mockAppMgrClient && appScheduler) { + appScheduler->appMgrClient_.reset(mockAppMgrClient); + } + + if (!bundleObject_) { + bundleObject_ = new (std::nothrow) BundleMgrService(); + if (bundleObject_) { + OHOS::DelayedSingleton::GetInstance()->RegisterSystemAbility( + OHOS::BUNDLE_MGR_SERVICE_SYS_ABILITY_ID, bundleObject_); + } + } +} + +void AbilityStackModuleTest::TearDownTestCase(void) +{ + GTEST_LOG_(INFO) << "TearDownTestCase"; + if (mockAppMgrClient) { + delete mockAppMgrClient; + mockAppMgrClient = nullptr; + } + + if (bundleObject_) { + delete bundleObject_; + bundleObject_ = nullptr; + } +} + +void AbilityStackModuleTest::SetUp(void) +{ + GTEST_LOG_(INFO) << "SetUp"; + + auto ams = DelayedSingleton::GetInstance(); + auto bms = ams->GetBundleManager(); + ams->OnStart(); + stackManager_ = ams->GetStackManager(); + EXPECT_TRUE(stackManager_); + stackManager_->Init(); + EXPECT_NE(bms, nullptr); + + if (mockScheduler_ == nullptr) { + mockScheduler_ = new MockAbilityScheduler(); + } +} + +void AbilityStackModuleTest::TearDown(void) +{ + GTEST_LOG_(INFO) << "TearDown"; + auto ams = DelayedSingleton::GetInstance(); + OHOS::DelayedSingleton::DestroyInstance(); + + if (mockScheduler_ != nullptr) { + mockScheduler_.clear(); + } +} + +AbilityRequest AbilityStackModuleTest::GenerateAbilityRequest(const std::string &deviceName, + const std::string &abilityName, const std::string &appName, const std::string &bundleName) +{ + GTEST_LOG_(INFO) << "GenerateAbilityRequest start ability :" << abilityName; + ElementName element(deviceName, abilityName, bundleName); + Want want; + want.SetElement(element); + + AbilityInfo abilityInfo; + ApplicationInfo appinfo; + abilityInfo.visible = true; + abilityInfo.name = abilityName; + abilityInfo.bundleName = bundleName; + abilityInfo.applicationName = appName; + abilityInfo.applicationInfo.bundleName = bundleName; + abilityInfo.applicationInfo.name = appName; + + makeScene(abilityName, bundleName, abilityInfo, want); + + appinfo = abilityInfo.applicationInfo; + AbilityRequest abilityRequest; + abilityRequest.want = want; + abilityRequest.abilityInfo = abilityInfo; + abilityRequest.appInfo = appinfo; + + return abilityRequest; +} + +void AbilityStackModuleTest::makeScene( + const std::string &abilityName, const std::string &bundleName, AbilityInfo &abilityInfo, Want &want) +{ + GTEST_LOG_(INFO) << "makeScene"; + if (bundleName == "com.ix.hiworld") { + std::string entity = Want::ENTITY_HOME; + want.AddEntity(entity); + abilityInfo.type = AbilityType::PAGE; + abilityInfo.applicationInfo.isLauncherApp = true; + abilityInfo.process = "p"; + abilityInfo.launchMode = LaunchMode::SINGLETON; + } + + if (bundleName == "com.ix.hiMusic") { + abilityInfo.type = AbilityType::PAGE; + abilityInfo.applicationInfo.isLauncherApp = false; + + if (abilityName == "MusicAbility" || abilityName == "MusicAbility2th") { + abilityInfo.process = "p1"; + abilityInfo.launchMode = LaunchMode::STANDARD; + } + if (abilityName == "MusicTopAbility") { + abilityInfo.process = "p1"; + abilityInfo.launchMode = LaunchMode::SINGLETOP; + } + if (abilityName == "MusicSAbility") { + abilityInfo.process = "p2"; + abilityInfo.launchMode = LaunchMode::SINGLETON; + } + } + + if (bundleName == "com.ix.hiRadio") { + abilityInfo.type = AbilityType::PAGE; + abilityInfo.process = "p3"; + if (abilityName == "RadioAbility") { + abilityInfo.launchMode = LaunchMode::STANDARD; + } + if (abilityName == "RadioTopAbility") { + abilityInfo.launchMode = LaunchMode::SINGLETOP; + } + if (abilityName == "RadioSAbility") { + abilityInfo.launchMode = LaunchMode::SINGLETON; + } + } +} + +Want AbilityStackModuleTest::CreateWant(const std::string &entity) +{ + GTEST_LOG_(INFO) << "CreateWant"; + Want want; + if (!entity.empty()) { + want.AddEntity(entity); + } + return want; +} + +AbilityInfo AbilityStackModuleTest::CreateAbilityInfo( + const std::string &name, const std::string &appName, const std::string &bundleName) +{ + GTEST_LOG_(INFO) << "CreateAbilityInfo"; + AbilityInfo abilityInfo; + abilityInfo.visible = true; + abilityInfo.name = name; + abilityInfo.applicationName = appName; + abilityInfo.bundleName = bundleName; + return abilityInfo; +} + +ApplicationInfo AbilityStackModuleTest::CreateAppInfo(const std::string &appName, const std::string &bundleName) +{ + GTEST_LOG_(INFO) << "CreateAppInfo"; + AbilityInfo abilityInfo; + ApplicationInfo appInfo; + appInfo.name = appName; + appInfo.bundleName = bundleName; + + return appInfo; +} + +/* + * Feature: AaFwk + * Function: ability stack management + * SubFunction: start launcher ability + * FunctionPoints: launcher mission stack + * EnvConditions: NA + * CaseDescription: start launcher ability when current launcher mission stack empty. + */ +HWTEST_F(AbilityStackModuleTest, ability_stack_test_001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AbilityStackModuleTest ability_stack_test_001 start"; + EXPECT_CALL(*mockAppMgrClient, LoadAbility(_, _, _, _)).Times(1).WillOnce(Return(AppMgrResultCode::RESULT_OK)); + std::string abilityName = "ability_name"; + std::string bundleName = "com.ix.aafwk.moduletest"; + + AbilityInfo abilityInfo = CreateAbilityInfo(abilityName, bundleName, bundleName); + ApplicationInfo appInfo = CreateAppInfo(bundleName, bundleName); + Want want = CreateWant(Want::ENTITY_HOME); + + AbilityRequest abilityRequest; + abilityRequest.want = want; + abilityRequest.abilityInfo = abilityInfo; + abilityRequest.appInfo = appInfo; + abilityRequest.appInfo.isLauncherApp = true; // launcher ability + abilityRequest.abilityInfo.applicationInfo = abilityRequest.appInfo; + + stackManager_->Init(); + std::shared_ptr curMissionStack = stackManager_->GetCurrentMissionStack(); + EXPECT_TRUE(curMissionStack); + stackManager_->StartAbility(abilityRequest); + EXPECT_EQ(LAUNCHER_MISSION_STACK_ID, curMissionStack->GetMissionStackId()); + EXPECT_EQ(1, curMissionStack->GetMissionRecordCount()); + EXPECT_TRUE(curMissionStack->GetTopMissionRecord() != nullptr); + EXPECT_EQ(1, curMissionStack->GetTopMissionRecord()->GetAbilityRecordCount()); + EXPECT_TRUE(curMissionStack->GetTopAbilityRecord() != nullptr); + EXPECT_STREQ(abilityName.c_str(), curMissionStack->GetTopAbilityRecord()->GetAbilityInfo().name.c_str()); + EXPECT_STREQ(bundleName.c_str(), curMissionStack->GetTopAbilityRecord()->GetAbilityInfo().bundleName.c_str()); + + GTEST_LOG_(INFO) << "AbilityStackModuleTest ability_stack_test_001 end"; +} + +/* + * Feature: AaFwk + * Function: ability stack management + * SubFunction: start launcher ability + * FunctionPoints: launcher mission stack + * EnvConditions: NA + * CaseDescription: not add new ability to current mission record when start the same launcher ability twice. + */ +HWTEST_F(AbilityStackModuleTest, ability_stack_test_002, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AbilityStackModuleTest ability_stack_test_002 start"; + EXPECT_CALL(*mockAppMgrClient, LoadAbility(_, _, _, _)).Times(1).WillOnce(Return(AppMgrResultCode::RESULT_OK)); + std::string abilityName = "ability_name"; + std::string bundleName = "com.ix.aafwk.moduletest"; + + AbilityRequest abilityRequest; + abilityRequest.want = CreateWant(Want::ENTITY_HOME); + abilityRequest.abilityInfo = CreateAbilityInfo(abilityName, bundleName, bundleName); + abilityRequest.appInfo = CreateAppInfo(bundleName, bundleName); + abilityRequest.appInfo.isLauncherApp = true; // launcher ability + abilityRequest.abilityInfo.applicationInfo = abilityRequest.appInfo; + + EXPECT_EQ(true, stackManager_->waittingAbilityQueue_.empty()); + + int result = stackManager_->StartAbility(abilityRequest); + EXPECT_EQ(result, ERR_OK); + std::shared_ptr curMissionStack = stackManager_->GetCurrentMissionStack(); + EXPECT_EQ(LAUNCHER_MISSION_STACK_ID, curMissionStack->GetMissionStackId()); + EXPECT_EQ(1, curMissionStack->GetMissionRecordCount()); + EXPECT_EQ(1, curMissionStack->GetTopMissionRecord()->GetAbilityRecordCount()); + + result = stackManager_->StartAbility(abilityRequest); // same launcher ability + // not change current mission stack + EXPECT_EQ(LAUNCHER_MISSION_STACK_ID, curMissionStack->GetMissionStackId()); + // not add new mission to current mission stack + EXPECT_EQ(1, curMissionStack->GetMissionRecordCount()); + // not add new ability to current mission record + EXPECT_EQ(1, curMissionStack->GetTopMissionRecord()->GetAbilityRecordCount()); + EXPECT_TRUE(curMissionStack->GetTopAbilityRecord() != nullptr); + EXPECT_STREQ(abilityName.c_str(), curMissionStack->GetTopAbilityRecord()->GetAbilityInfo().name.c_str()); + EXPECT_STREQ(bundleName.c_str(), curMissionStack->GetTopAbilityRecord()->GetAbilityInfo().bundleName.c_str()); + GTEST_LOG_(INFO) << "AbilityStackModuleTest ability_stack_test_002 end"; +} + +/* + * Feature: AaFwk + * Function: ability stack management + * SubFunction: start launcher ability + * FunctionPoints: launcher mission stack + * EnvConditions: NA + * CaseDescription: add new mission to current mission stack whene start the different launcher ability. + */ +HWTEST_F(AbilityStackModuleTest, ability_stack_test_003, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AbilityStackModuleTest ability_stack_test_003 start"; + EXPECT_CALL(*mockAppMgrClient, LoadAbility(_, _, _, _)).Times(1).WillOnce(Return(AppMgrResultCode::RESULT_OK)); + std::string abilityName = "ability_name"; + std::string bundleName = "com.ix.aafwk.moduletest"; + int index = 1; + + AbilityRequest abilityRequest; + abilityRequest.want = CreateWant(Want::ENTITY_HOME); + std::string strInd = std::to_string(index); + abilityRequest.abilityInfo = CreateAbilityInfo(abilityName + strInd, bundleName + strInd, bundleName + strInd); + abilityRequest.appInfo = CreateAppInfo(bundleName + strInd, bundleName + strInd); + abilityRequest.appInfo.isLauncherApp = true; // launcher ability + abilityRequest.abilityInfo.applicationInfo = abilityRequest.appInfo; + + AbilityRequest abilityRequest2; + abilityRequest2.want = CreateWant(Want::ENTITY_HOME); + index++; + strInd = std::to_string(index); + abilityRequest2.abilityInfo = CreateAbilityInfo(abilityName + strInd, bundleName + strInd, bundleName + strInd); + abilityRequest2.appInfo = CreateAppInfo(bundleName + strInd, bundleName + strInd); + abilityRequest2.appInfo.isLauncherApp = true; // another launcher ability + abilityRequest2.abilityInfo.applicationInfo = abilityRequest2.appInfo; + + std::shared_ptr curMissionStack = stackManager_->GetCurrentMissionStack(); + int result = stackManager_->StartAbility(abilityRequest); + usleep(1000); + EXPECT_TRUE(curMissionStack->GetTopAbilityRecord() != nullptr); + curMissionStack->GetTopAbilityRecord()->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + result = stackManager_->StartAbility(abilityRequest2); + // not change current mission stack + EXPECT_EQ(LAUNCHER_MISSION_STACK_ID, curMissionStack->GetMissionStackId()); + // add new mission to current mission stack + EXPECT_EQ(1, curMissionStack->GetMissionRecordCount()); + EXPECT_EQ(2, curMissionStack->GetTopMissionRecord()->GetAbilityRecordCount()); + EXPECT_TRUE(curMissionStack->GetTopAbilityRecord() != nullptr); + EXPECT_STREQ((abilityName + strInd).c_str(), curMissionStack->GetTopAbilityRecord()->GetAbilityInfo().name.c_str()); + EXPECT_STREQ( + (bundleName + strInd).c_str(), curMissionStack->GetTopAbilityRecord()->GetAbilityInfo().bundleName.c_str()); + GTEST_LOG_(INFO) << "AbilityStackModuleTest ability_stack_test_003 end"; +} + +/* + * Feature: AaFwk + * Function: ability stack management + * SubFunction: start non-launcher ability + * FunctionPoints: non-launcher mission stack + * EnvConditions: NA + * CaseDescription: change current mission stack when start non-launcher ability. + */ +HWTEST_F(AbilityStackModuleTest, ability_stack_test_004, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AbilityStackModuleTest ability_stack_test_004 start"; + + std::string abilityName = "ability_name"; + std::string bundleName = "com.ix.aafwk.moduletest"; + int index = 1; + EXPECT_CALL(*mockAppMgrClient, LoadAbility(_, _, _, _)).Times(1).WillOnce(Return(AppMgrResultCode::RESULT_OK)); + AbilityRequest abilityRequest; + abilityRequest.want = CreateWant(Want::ENTITY_HOME); + std::string strInd = std::to_string(index); + abilityRequest.abilityInfo = CreateAbilityInfo(abilityName + strInd, bundleName + strInd, bundleName + strInd); + abilityRequest.appInfo = CreateAppInfo(bundleName + strInd, bundleName + strInd); + abilityRequest.appInfo.isLauncherApp = true; // launcher ability + abilityRequest.abilityInfo.applicationInfo = abilityRequest.appInfo; + + AbilityRequest abilityRequest2; + abilityRequest2.want = CreateWant(""); + strInd = std::to_string(++index); + abilityRequest2.abilityInfo = CreateAbilityInfo(abilityName + strInd, bundleName + strInd, bundleName + strInd); + abilityRequest2.appInfo = CreateAppInfo(bundleName + strInd, bundleName + strInd); + abilityRequest2.appInfo.isLauncherApp = false; // non-launcher ability + abilityRequest2.abilityInfo.applicationInfo = abilityRequest2.appInfo; + + int result = stackManager_->StartAbility(abilityRequest); + EXPECT_EQ(result, ERR_OK); + + std::shared_ptr curMissionStack = stackManager_->GetCurrentMissionStack(); + EXPECT_TRUE(curMissionStack->GetTopAbilityRecord() != nullptr); + curMissionStack->GetTopAbilityRecord()->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + EXPECT_EQ(LAUNCHER_MISSION_STACK_ID, curMissionStack->GetMissionStackId()); + result = stackManager_->StartAbility(abilityRequest2); + EXPECT_EQ(result, ERR_OK); + + curMissionStack = stackManager_->GetCurrentMissionStack(); + // change current mission stack + EXPECT_EQ(DEFAULT_MISSION_STACK_ID, curMissionStack->GetMissionStackId()); + // add new mission to current mission stack + EXPECT_EQ(1, curMissionStack->GetMissionRecordCount()); + EXPECT_EQ(1, curMissionStack->GetTopMissionRecord()->GetAbilityRecordCount()); + EXPECT_TRUE(curMissionStack->GetTopAbilityRecord() != nullptr); + EXPECT_STREQ((abilityName + strInd).c_str(), curMissionStack->GetTopAbilityRecord()->GetAbilityInfo().name.c_str()); + EXPECT_STREQ( + (bundleName + strInd).c_str(), curMissionStack->GetTopAbilityRecord()->GetAbilityInfo().bundleName.c_str()); + GTEST_LOG_(INFO) << "AbilityStackModuleTest ability_stack_test_004 end"; +} + +/* + * Feature: AaFwk + * Function: ability stack management + * SubFunction: terminate launcher ability + * FunctionPoints: launcher mission stack + * EnvConditions: NA + * CaseDescription: verify unique launcher ability can't be terminated. + */ +HWTEST_F(AbilityStackModuleTest, ability_stack_test_005, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AbilityStackModuleTest ability_stack_test_005 start"; + EXPECT_CALL(*mockAppMgrClient, LoadAbility(_, _, _, _)).Times(1).WillOnce(Return(AppMgrResultCode::RESULT_OK)); + std::string abilityName = "ability_name"; + std::string bundleName = "com.ix.aafwk.moduletest"; + + AbilityRequest abilityRequest; + abilityRequest.want = CreateWant(Want::ENTITY_HOME); + abilityRequest.abilityInfo = CreateAbilityInfo(abilityName, bundleName, bundleName); + abilityRequest.appInfo = CreateAppInfo(bundleName, bundleName); + abilityRequest.appInfo.isLauncherApp = true; // launcher ability + abilityRequest.abilityInfo.applicationInfo = abilityRequest.appInfo; + + std::shared_ptr curMissionStack = stackManager_->GetCurrentMissionStack(); + int result = stackManager_->StartAbility(abilityRequest); + usleep(1000); + EXPECT_TRUE(curMissionStack->GetTopAbilityRecord() != nullptr); + curMissionStack->GetTopAbilityRecord()->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + result = stackManager_->TerminateAbility(curMissionStack->GetTopAbilityRecord()->GetToken(), -1, nullptr); + EXPECT_EQ(TERMINATE_LAUNCHER_DENIED, result); + // not change current mission stack + EXPECT_EQ(LAUNCHER_MISSION_STACK_ID, curMissionStack->GetMissionStackId()); + EXPECT_EQ(1, curMissionStack->GetMissionRecordCount()); + // not change current ability state + EXPECT_TRUE(curMissionStack->GetTopAbilityRecord() != nullptr); + EXPECT_EQ(OHOS::AAFwk::AbilityState::ACTIVE, curMissionStack->GetTopAbilityRecord()->GetAbilityState()); + EXPECT_STREQ(abilityName.c_str(), curMissionStack->GetTopAbilityRecord()->GetAbilityInfo().name.c_str()); + EXPECT_STREQ(bundleName.c_str(), curMissionStack->GetTopAbilityRecord()->GetAbilityInfo().bundleName.c_str()); + + GTEST_LOG_(INFO) << "AbilityStackModuleTest ability_stack_test_005 end"; +} + +/* + * Feature: AaFwk + * Function: ability stack management + * SubFunction: start and terminate non-launcher ability + * FunctionPoints: single top + * EnvConditions: NA + * CaseDescription: start and terminate multiple non-launcher ability(single application). + */ +HWTEST_F(AbilityStackModuleTest, ability_stack_test_006, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AbilityStackModuleTest ability_stack_test_006 start"; + EXPECT_CALL(*mockAppMgrClient, LoadAbility(_, _, _, _)).Times(1).WillOnce(Return(AppMgrResultCode::RESULT_OK)); + std::string abilityName = "ability_name"; + std::string bundleName = "com.ix.aafwk.moduletest"; + + std::string appSuffix = "1"; + std::vector abilityRequests; + for (int i = 0; i < 3; i++) { + AbilityRequest abilityRequest; + abilityRequest.want = CreateWant(""); + std::string abilitySuffix = appSuffix + std::to_string(i + 1); + abilityRequest.abilityInfo = + CreateAbilityInfo(abilityName + abilitySuffix, bundleName + appSuffix, bundleName + appSuffix); + abilityRequest.abilityInfo.launchMode = LaunchMode::STANDARD; + abilityRequest.appInfo = CreateAppInfo(bundleName + appSuffix, bundleName + appSuffix); + abilityRequest.appInfo.isLauncherApp = false; // non-launcher ability + abilityRequest.abilityInfo.applicationInfo = abilityRequest.appInfo; + + abilityRequests.push_back(abilityRequest); + } + + // start "ability_name11" + int result = stackManager_->StartAbility(abilityRequests[0]); + usleep(1000); + std::shared_ptr curMissionStack = stackManager_->GetCurrentMissionStack(); + EXPECT_EQ(DEFAULT_MISSION_STACK_ID, curMissionStack->GetMissionStackId()); + std::shared_ptr currentTopAbilityRecord = stackManager_->GetCurrentTopAbility(); + EXPECT_STREQ("ability_name11", currentTopAbilityRecord->GetAbilityInfo().name.c_str()); + currentTopAbilityRecord->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + + // start "ability_name12" + result = stackManager_->StartAbility(abilityRequests[1]); + usleep(1000); + EXPECT_EQ(DEFAULT_MISSION_STACK_ID, curMissionStack->GetMissionStackId()); + currentTopAbilityRecord = stackManager_->GetCurrentTopAbility(); + EXPECT_STREQ("ability_name12", currentTopAbilityRecord->GetAbilityInfo().name.c_str()); + currentTopAbilityRecord->GetPreAbilityRecord()->SetAbilityState(OHOS::AAFwk::AbilityState::INACTIVE); + currentTopAbilityRecord->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + EXPECT_EQ(2, curMissionStack->GetTopMissionRecord()->GetAbilityRecordCount()); + + // start "ability_name12" + result = stackManager_->StartAbility(abilityRequests[1]); + usleep(1000); + currentTopAbilityRecord = stackManager_->GetCurrentTopAbility(); + EXPECT_STREQ("ability_name12", currentTopAbilityRecord->GetAbilityInfo().name.c_str()); + // EXPECT_STREQ("ability_name11", + currentTopAbilityRecord->GetPreAbilityRecord()->SetAbilityState(OHOS::AAFwk::AbilityState::INACTIVE); + currentTopAbilityRecord->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + EXPECT_EQ(3, curMissionStack->GetTopMissionRecord()->GetAbilityRecordCount()); + + // start "ability_name13" + result = stackManager_->StartAbility(abilityRequests[2]); + usleep(1000); + currentTopAbilityRecord = stackManager_->GetCurrentTopAbility(); + EXPECT_STREQ("ability_name13", currentTopAbilityRecord->GetAbilityInfo().name.c_str()); + currentTopAbilityRecord->GetPreAbilityRecord()->SetAbilityState(OHOS::AAFwk::AbilityState::INACTIVE); + currentTopAbilityRecord->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + EXPECT_EQ(4, curMissionStack->GetTopMissionRecord()->GetAbilityRecordCount()); + + // start "ability_name12" + result = stackManager_->StartAbility(abilityRequests[1]); + usleep(1000); + currentTopAbilityRecord = stackManager_->GetCurrentTopAbility(); + EXPECT_STREQ("ability_name12", currentTopAbilityRecord->GetAbilityInfo().name.c_str()); + EXPECT_STREQ("ability_name13", currentTopAbilityRecord->GetPreAbilityRecord()->GetAbilityInfo().name.c_str()); + currentTopAbilityRecord->GetPreAbilityRecord()->SetAbilityState(OHOS::AAFwk::AbilityState::INACTIVE); + currentTopAbilityRecord->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + EXPECT_EQ(5, curMissionStack->GetTopMissionRecord()->GetAbilityRecordCount()); + + // terminate stack top ability "ability_name12" + currentTopAbilityRecord->lifecycleDeal_ = nullptr; + Want want; + result = stackManager_->TerminateAbility(currentTopAbilityRecord->GetToken(), -1, &want); + EXPECT_EQ(DEFAULT_MISSION_STACK_ID, curMissionStack->GetMissionStackId()); + EXPECT_EQ(4, curMissionStack->GetTopMissionRecord()->GetAbilityRecordCount()); + currentTopAbilityRecord = curMissionStack->GetTopAbilityRecord(); + EXPECT_TRUE(currentTopAbilityRecord != nullptr); + EXPECT_STREQ("ability_name13", currentTopAbilityRecord->GetAbilityInfo().name.c_str()); + + // terminate stack bottom ability + auto bottomAbility = curMissionStack->GetTopMissionRecord()->abilities_.back(); + result = stackManager_->TerminateAbility(bottomAbility->GetToken(), -1, &want); + EXPECT_EQ(3, curMissionStack->GetTopMissionRecord()->GetAbilityRecordCount()); + currentTopAbilityRecord = curMissionStack->GetTopAbilityRecord(); + EXPECT_TRUE(currentTopAbilityRecord != nullptr); + EXPECT_STREQ("ability_name13", currentTopAbilityRecord->GetAbilityInfo().name.c_str()); + + GTEST_LOG_(INFO) << "AbilityStackModuleTest ability_stack_test_006 end"; +} + +/* + * Feature: AaFwk + * Function: attach ability + * SubFunction: attach ability thread + * FunctionPoints: update ability state + * EnvConditions: NA + * CaseDescription: update ability state when attach ability. + */ +HWTEST_F(AbilityStackModuleTest, ability_stack_test_007, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AbilityStackModuleTest ability_stack_test_007 start"; + + std::string abilityName = "ability_name"; + std::string bundleName = "com.ix.aafwk.moduletest"; + + AbilityRequest abilityRequest; + abilityRequest.want = CreateWant(""); + abilityRequest.abilityInfo = CreateAbilityInfo(abilityName, bundleName, bundleName); + abilityRequest.appInfo = CreateAppInfo(bundleName, bundleName); + abilityRequest.appInfo.isLauncherApp = false; // non-launcher ability + abilityRequest.abilityInfo.applicationInfo = abilityRequest.appInfo; + + std::shared_ptr abilityRecord = AbilityRecord::CreateAbilityRecord(abilityRequest); + abilityRecord->SetAbilityState(OHOS::AAFwk::AbilityState::INACTIVE); + std::shared_ptr mission = std::make_shared(bundleName); + mission->AddAbilityRecordToTop(abilityRecord); + + std::shared_ptr curMissionStack = stackManager_->GetCurrentMissionStack(); + curMissionStack->AddMissionRecordToTop(mission); + + OHOS::sptr abilityScheduler(new MockAbilityScheduler()); + EXPECT_CALL(*abilityScheduler, AsObject()).Times(2); + // ams handler is non statrt so times is 0 + EXPECT_CALL(*mockAppMgrClient, UpdateAbilityState(testing::_, testing::_)).Times(1); + + EXPECT_TRUE(abilityRecord->GetToken()); + + EXPECT_CALL(*abilityScheduler, AsObject()).WillRepeatedly(Return(nullptr)); + stackManager_->AttachAbilityThread(abilityScheduler, abilityRecord->GetToken()); + + GTEST_LOG_(INFO) << "AbilityStackModuleTest ability_stack_test_007 end"; +} + +/* + * Feature: AaFwk + * Function: ability state transition + * SubFunction: ability state transition done + * FunctionPoints: ability state transition(TERMINATING->INITIAL) + * EnvConditions: NA + * CaseDescription: complete ability state transition(TERMINATING->INITIAL). + */ +HWTEST_F(AbilityStackModuleTest, ability_stack_test_008, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AbilityStackModuleTest ability_stack_test_008 start"; + + std::string abilityName = "ability_name"; + std::string bundleName = "com.ix.aafwk.moduletest"; + + AbilityRequest abilityRequest; + abilityRequest.want = CreateWant(""); + abilityRequest.abilityInfo = CreateAbilityInfo(abilityName, bundleName, bundleName); + abilityRequest.appInfo = CreateAppInfo(bundleName, bundleName); + + std::shared_ptr abilityRecord = AbilityRecord::CreateAbilityRecord(abilityRequest); + abilityRecord->lifecycleDeal_ = nullptr; + abilityRecord->SetAbilityState(OHOS::AAFwk::AbilityState::TERMINATING); + std::shared_ptr mission = std::make_shared(bundleName); + mission->AddAbilityRecordToTop(abilityRecord); + + std::shared_ptr curMissionStack = stackManager_->GetCurrentMissionStack(); + curMissionStack->AddMissionRecordToTop(mission); + + std::shared_ptr handler = + std::make_shared(nullptr, OHOS::DelayedSingleton::GetInstance()); + OHOS::DelayedSingleton::GetInstance()->handler_ = handler; + + int result = stackManager_->AbilityTransitionDone(abilityRecord->GetToken(), OHOS::AAFwk::AbilityState::INITIAL); + EXPECT_EQ(OHOS::ERR_OK, result); + + GTEST_LOG_(INFO) << "AbilityStackModuleTest ability_stack_test_008 end"; +} + +/* + * Feature: AaFwk + * Function: add Window + * SubFunction: add window for ability + * FunctionPoints: add window for ability + * EnvConditions: NA + * CaseDescription: add window for ability. + */ +HWTEST_F(AbilityStackModuleTest, ability_stack_test_009, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AbilityStackModuleTest ability_stack_test_009 start"; + + std::string abilityName = "ability_name"; + std::string bundleName = "com.ix.aafwk.moduletest"; + + AbilityRequest abilityRequest; + abilityRequest.want = CreateWant(""); + abilityRequest.abilityInfo = CreateAbilityInfo(abilityName, bundleName, bundleName); + abilityRequest.appInfo = CreateAppInfo(bundleName, bundleName); + + std::shared_ptr abilityRecord = AbilityRecord::CreateAbilityRecord(abilityRequest); + abilityRecord->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + std::shared_ptr mission = std::make_shared(bundleName); + mission->AddAbilityRecordToTop(abilityRecord); + + std::shared_ptr curMissionStack = stackManager_->GetCurrentMissionStack(); + curMissionStack->AddMissionRecordToTop(mission); + + stackManager_->AddWindowInfo(abilityRecord->GetToken(), 1); + EXPECT_TRUE(abilityRecord->GetWindowInfo() != nullptr); + + GTEST_LOG_(INFO) << "AbilityStackModuleTest ability_stack_test_009 end"; +} + +/* + * Feature: AaFwk + * Function: app state callback + * SubFunction: OnAbilityRequestDone + * FunctionPoints: OnAbilityRequestDone + * EnvConditions: NA + * CaseDescription: activate ability(ABILITY_STATE_FOREGROUND). + */ +HWTEST_F(AbilityStackModuleTest, ability_stack_test_010, TestSize.Level1) +{ + std::string abilityName = "ability_name"; + std::string bundleName = "com.ix.aafwk.moduletest"; + + AbilityRequest abilityRequest; + abilityRequest.want = CreateWant(""); + abilityRequest.abilityInfo = CreateAbilityInfo(abilityName, bundleName, bundleName); + abilityRequest.appInfo = CreateAppInfo(bundleName, bundleName); + + std::shared_ptr abilityRecord = AbilityRecord::CreateAbilityRecord(abilityRequest); + + OHOS::sptr scheduler(new MockAbilityScheduler()); + EXPECT_CALL(*scheduler, AsObject()).WillRepeatedly(Return(nullptr)); + abilityRecord->SetScheduler(scheduler); + + abilityRecord->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + std::shared_ptr mission = std::make_shared(bundleName); + mission->AddAbilityRecordToTop(abilityRecord); + + std::shared_ptr curMissionStack = stackManager_->GetCurrentMissionStack(); + curMissionStack->AddMissionRecordToTop(mission); + + EXPECT_CALL(*scheduler, ScheduleAbilityTransaction(testing::_, testing::_)).Times(1); + stackManager_->OnAbilityRequestDone( + abilityRecord->GetToken(), static_cast(OHOS::AppExecFwk::AbilityState::ABILITY_STATE_FOREGROUND)); +} + +/* + * Feature: AbilityStackManager + * Function: PowerOff + * SubFunction: NA + * FunctionPoints: PowerOff + * EnvConditions: NA + * CaseDescription: Succeeded to verify PowerOff + */ +HWTEST_F(AbilityStackModuleTest, ability_stack_test_011, TestSize.Level1) +{ + EXPECT_CALL(*mockAppMgrClient, LoadAbility(_, _, _, _)).Times(1).WillOnce(Return(AppMgrResultCode::RESULT_OK)); + EXPECT_CALL(*mockAppMgrClient, UpdateAbilityState(testing::_, testing::_)) + .Times(1) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)); + + AbilityRequest launcherAbilityRequest_ = + GenerateAbilityRequest("device", "LauncherAbility", "launcher", "com.ix.hiworld"); + + stackManager_->StartAbility(launcherAbilityRequest_); + auto firstTopAbility = stackManager_->GetCurrentTopAbility(); + EXPECT_TRUE(firstTopAbility); + + firstTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + auto transactionDoneCaller = [&](const Want &want, const LifeCycleStateInfo &targetState) { + stackManager_->CompleteInactive(firstTopAbility); + }; + + auto transactionDoneCaller2 = [&](const Want &want, const LifeCycleStateInfo &targetState) { + stackManager_->CompleteBackground(firstTopAbility); + }; + OHOS::sptr scheduler(new MockAbilityScheduler()); + EXPECT_CALL(*scheduler, AsObject()).WillRepeatedly(Return(nullptr)); + EXPECT_CALL(*scheduler, ScheduleAbilityTransaction(testing::_, testing::_)) + .Times(testing::AtLeast(2)) + .WillOnce(testing::Invoke(transactionDoneCaller)) + .WillOnce(testing::Invoke(transactionDoneCaller2)); + EXPECT_CALL(*scheduler, ScheduleSaveAbilityState(_)).Times(AtLeast(1)); + + firstTopAbility->SetScheduler(scheduler); + + int result = stackManager_->PowerOff(); + EXPECT_EQ(ERR_OK, result); + + EXPECT_NE(stackManager_->powerStorage_, nullptr); + EXPECT_EQ(OHOS::AAFwk::BACKGROUND, firstTopAbility->GetAbilityState()); + + auto recordVector = stackManager_->powerStorage_->GetPowerOffInActiveRecord(); + EXPECT_TRUE(recordVector.empty()); +} + +/* + * Feature: AbilityStackManager + * Function: PowerOn + * SubFunction: NA + * FunctionPoints: PowerOn + * EnvConditions: NA + * CaseDescription: Succeeded to verify PowerOn + */ +HWTEST_F(AbilityStackModuleTest, ability_stack_test_012, TestSize.Level1) +{ + EXPECT_CALL(*mockAppMgrClient, LoadAbility(_, _, _, _)) + .Times(AtLeast(1)) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)); + EXPECT_CALL(*mockAppMgrClient, UpdateAbilityState(testing::_, testing::_)).Times(testing::AtLeast(2)); + + auto launcherAbilityRequest_ = GenerateAbilityRequest("device", "LauncherAbility", "launcher", "com.ix.hiworld"); + stackManager_->StartAbility(launcherAbilityRequest_); + auto firstTopAbility = stackManager_->GetCurrentTopAbility(); + firstTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + auto musicAbilityRequest_ = GenerateAbilityRequest("device", "MusicAbility", "music", "com.ix.hiMusic"); + stackManager_->StartAbility(musicAbilityRequest_); + auto secondTopAbility = stackManager_->GetCurrentTopAbility(); + secondTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + firstTopAbility->SetAbilityState(OHOS::AAFwk::INACTIVE); + + auto transactionDoneCaller = [&](const Want &want, const LifeCycleStateInfo &targetState) { + stackManager_->CompleteBackground(firstTopAbility); + }; + + auto transactionDoneCaller2 = [&](const Want &want, const LifeCycleStateInfo &targetState) { + stackManager_->CompleteActive(firstTopAbility); + }; + + auto transactionDoneCaller3 = [&](const Want &want, const LifeCycleStateInfo &targetState) { + stackManager_->CompleteInactive(firstTopAbility); + }; + + OHOS::sptr scheduler(new MockAbilityScheduler()); + EXPECT_CALL(*scheduler, AsObject()).WillRepeatedly(Return(nullptr)); + + firstTopAbility->SetScheduler(scheduler); + EXPECT_CALL(*scheduler, AsObject()) + .Times(testing::AtLeast(1)) + .WillOnce(Return(nullptr)) + .WillOnce(Return(nullptr)) + .WillOnce(Return(nullptr)); + + EXPECT_CALL(*scheduler, ScheduleSaveAbilityState(testing::_)).Times(testing::AtLeast(3)); + + EXPECT_CALL(*scheduler, ScheduleAbilityTransaction(testing::_, testing::_)) + .Times(testing::AtLeast(3)) + .WillOnce(testing::Invoke(transactionDoneCaller)) + .WillOnce(testing::Invoke(transactionDoneCaller2)) + .WillOnce(testing::Invoke(transactionDoneCaller3)) + .WillOnce(testing::Invoke(transactionDoneCaller)); + EXPECT_CALL(*scheduler, ScheduleSaveAbilityState(_)).Times(AtLeast(1)); + + firstTopAbility->SetScheduler(scheduler); + + auto transactionDoneCaller2_1 = [&](const Want &want, const LifeCycleStateInfo &targetState) { + stackManager_->CompleteInactive(secondTopAbility); + }; + + auto transactionDoneCaller2_2 = [&](const Want &want, const LifeCycleStateInfo &targetState) { + stackManager_->CompleteBackground(secondTopAbility); + }; + + auto transactionDoneCaller2_3 = [&](const Want &want, const LifeCycleStateInfo &targetState) { + stackManager_->CompleteActive(secondTopAbility); + }; + + OHOS::sptr scheduler2(new MockAbilityScheduler()); + + EXPECT_CALL(*scheduler2, AsObject()).WillRepeatedly(Return(nullptr)); + + secondTopAbility->SetScheduler(scheduler2); + EXPECT_CALL(*scheduler2, AsObject()) + .Times(testing::AtLeast(1)) + .WillOnce(Return(nullptr)) + .WillOnce(Return(nullptr)) + .WillOnce(Return(nullptr)); + + EXPECT_CALL(*scheduler2, ScheduleSaveAbilityState(testing::_)).Times(testing::AtLeast(3)); + + EXPECT_CALL(*scheduler2, ScheduleAbilityTransaction(testing::_, testing::_)) + .Times(testing::AtLeast(3)) + .WillOnce(testing::Invoke(transactionDoneCaller2_1)) + .WillOnce(testing::Invoke(transactionDoneCaller2_2)) + .WillOnce(testing::Invoke(transactionDoneCaller2_3)); + EXPECT_CALL(*scheduler2, ScheduleSaveAbilityState(_)).Times(AtLeast(1)); + + secondTopAbility->SetScheduler(scheduler2); + + int result = stackManager_->PowerOff(); + EXPECT_EQ(ERR_OK, result); + + EXPECT_EQ(OHOS::AAFwk::BACKGROUND, firstTopAbility->GetAbilityState()); + EXPECT_EQ(OHOS::AAFwk::BACKGROUND, secondTopAbility->GetAbilityState()); + + auto recordVector = stackManager_->powerStorage_->GetPowerOffInActiveRecord(); + int size = recordVector.size(); + EXPECT_EQ(size, 1); + + for (const auto &it : recordVector) { + EXPECT_EQ(it.ability.lock()->GetRecordId(), firstTopAbility->GetRecordId()); + EXPECT_EQ(it.ability.lock()->GetAbilityState(), OHOS::AAFwk::BACKGROUND); + } + + auto requestDone = [&](const sptr &token, const AppExecFwk::AbilityState state) -> AppMgrResultCode { + firstTopAbility->Activate(); + return AppMgrResultCode::RESULT_OK; + }; + + auto requestDone2 = [&](const sptr &token, + const AppExecFwk::AbilityState state) -> AppMgrResultCode { + secondTopAbility->Activate(); + return AppMgrResultCode::RESULT_OK; + }; + + auto requestDone3 = [&](const sptr &token, + const AppExecFwk::AbilityState state) -> AppMgrResultCode { + return AppMgrResultCode::RESULT_OK; + }; + + EXPECT_CALL(*mockAppMgrClient, UpdateAbilityState(testing::_, testing::_)) + .Times(3) + .WillOnce(Invoke(requestDone)) + .WillOnce(Invoke(requestDone2)) + .WillOnce(Invoke(requestDone3)); + + result = stackManager_->PowerOn(); + EXPECT_EQ(ERR_OK, result); + + EXPECT_EQ(OHOS::AAFwk::BACKGROUND, firstTopAbility->GetAbilityState()); // end last move to background + EXPECT_EQ(OHOS::AAFwk::ACTIVE, secondTopAbility->GetAbilityState()); + + testing::Mock::AllowLeak(mockAppMgrClient); + testing::Mock::AllowLeak(scheduler); + testing::Mock::AllowLeak(scheduler2); +} + +/* + * Feature: AaFwk + * Function: StartLockMission + * SubFunction: NA + * FunctionPoints: lock a mission , It's locked mission top ability will be active + * EnvConditions: NA + * CaseDescription: lock a mission + */ +HWTEST_F(AbilityStackModuleTest, ability_stack_test_013, TestSize.Level1) +{ + int sysUid = 1000; + EXPECT_CALL(*bundleObject_, GetUidByBundleName(_, _)) + .Times(AtLeast(2)) + .WillOnce(Return(sysUid)) + .WillOnce(Return(sysUid)); + + EXPECT_CALL(*mockAppMgrClient, LoadAbility(_, _, _, _)) + .Times(AtLeast(1)) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)); + + auto launcherAbilityRequest_ = GenerateAbilityRequest("device", "LauncherAbility", "launcher", "com.ix.hiworld"); + stackManager_->StartAbility(launcherAbilityRequest_); + auto firstTopAbility = stackManager_->GetCurrentTopAbility(); + firstTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + auto musicAbilityRequest_ = GenerateAbilityRequest("device", "MusicAbility", "music", "com.ix.hiMusic"); + stackManager_->StartAbility(musicAbilityRequest_); + auto secondTopAbility = stackManager_->GetCurrentTopAbility(); + secondTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + // lock LauncherAbility + auto launcherMisionRecord = firstTopAbility->GetMissionRecord(); + auto launcherMisionRecordId = launcherMisionRecord->GetMissionRecordId(); + auto result = stackManager_->StartLockMission(sysUid, launcherMisionRecordId, true, true); + EXPECT_EQ(ERR_OK, result); + + auto topRecord = stackManager_->GetCurrentTopAbility(); + auto abilityInfo = topRecord->GetAbilityInfo(); + EXPECT_EQ(abilityInfo.name, "LauncherAbility"); + topRecord->SetAbilityState(OHOS::AAFwk::ACTIVE); + + // unlock + result = stackManager_->StartLockMission(sysUid, launcherMisionRecordId, true, false); + EXPECT_EQ(ERR_OK, result); +} + +/* + * Feature: AaFwk + * Function: StartLockMissions + * SubFunction: NA + * FunctionPoints: lock a mission , It's locked mission top ability will be active + * EnvConditions: NA + * CaseDescription: multiple mission lock someone + */ +HWTEST_F(AbilityStackModuleTest, ability_stack_test_014, TestSize.Level1) +{ + int sysUid = 1000; + EXPECT_CALL(*bundleObject_, GetUidByBundleName(_, _)) + .Times(AtLeast(2)) + .WillOnce(Return(sysUid)) + .WillOnce(Return(sysUid)); + + EXPECT_CALL(*mockAppMgrClient, LoadAbility(_, _, _, _)) + .Times(AtLeast(1)) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)); + + auto launcherAbilityRequest_ = GenerateAbilityRequest("device", "MusicAbility", "launcher", "com.ix.hiworld"); + auto ref = stackManager_->StartAbility(launcherAbilityRequest_); + EXPECT_EQ(ERR_OK, ref); + auto firstTopAbility = stackManager_->GetCurrentTopAbility(); + firstTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + auto musicAbilityRequest_ = GenerateAbilityRequest("device", "MusicAbility2th", "launcher", "com.ix.hiMusic"); + ref = stackManager_->StartAbility(musicAbilityRequest_); + EXPECT_EQ(ERR_OK, ref); + auto secondTopAbility = stackManager_->GetCurrentTopAbility(); + secondTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + auto redioAbilityRequest_ = GenerateAbilityRequest("device", "RadioSAbility", "Radio", "com.ix.hiRadio"); + ref = stackManager_->StartAbility(redioAbilityRequest_); + EXPECT_EQ(ERR_OK, ref); + auto thirdTopAbility = stackManager_->GetCurrentTopAbility(); + thirdTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + auto transactionDoneCaller = [&](const Want &want, const LifeCycleStateInfo &targetState) { + stackManager_->CompleteActive(secondTopAbility); + }; + auto transactionDoneCaller2 = [&](const Want &want, const LifeCycleStateInfo &targetState) { + stackManager_->CompleteInactive(secondTopAbility); + }; + + OHOS::sptr scheduler(new MockAbilityScheduler()); + EXPECT_CALL(*scheduler, AsObject()).WillRepeatedly(Return(nullptr)); + secondTopAbility->SetScheduler(scheduler); + EXPECT_CALL(*scheduler, ScheduleAbilityTransaction(testing::_, testing::_)) + .Times(testing::AtLeast(2)) + .WillOnce(testing::Invoke(transactionDoneCaller)) + .WillOnce(testing::Invoke(transactionDoneCaller2)); + + auto transactionDoneCaller3 = [&](const Want &want, const LifeCycleStateInfo &targetState) { + stackManager_->CompleteInactive(thirdTopAbility); + }; + auto transactionDoneCaller4 = [&](const Want &want, const LifeCycleStateInfo &targetState) { + stackManager_->CompleteActive(thirdTopAbility); + }; + + OHOS::sptr scheduler2(new MockAbilityScheduler()); + EXPECT_CALL(*scheduler2, AsObject()).WillRepeatedly(Return(nullptr)); + thirdTopAbility->SetScheduler(scheduler2); + EXPECT_CALL(*scheduler2, ScheduleAbilityTransaction(testing::_, testing::_)) + .Times(testing::AtLeast(2)) + .WillOnce(testing::Invoke(transactionDoneCaller3)) + .WillOnce(testing::Invoke(transactionDoneCaller4)); + EXPECT_CALL(*scheduler2, ScheduleSaveAbilityState(_)).Times(AtLeast(1)); + + secondTopAbility->SetAbilityState(OHOS::AAFwk::INACTIVE); + auto musicMisionRecord = secondTopAbility->GetMissionRecord(); + auto musicMisionRecordId = musicMisionRecord->GetMissionRecordId(); + + auto result = stackManager_->StartLockMission(sysUid, musicMisionRecordId, false, true); + EXPECT_EQ(ERR_OK, result); + + auto topRecord = stackManager_->GetCurrentTopAbility(); + auto abilityInfo = topRecord->GetAbilityInfo(); + EXPECT_EQ(abilityInfo.name, "MusicAbility2th"); + + // unlock + result = stackManager_->StartLockMission(sysUid, musicMisionRecordId, false, false); + EXPECT_EQ(ERR_OK, result); +} + +/* + * Feature: AaFwk + * Function: StartLockMission + * SubFunction: NA + * FunctionPoints: lock a mission , It's locked mission top ability will be active + * EnvConditions: NA + * CaseDescription: when a misson locked other mission do not to statr ability + */ +HWTEST_F(AbilityStackModuleTest, ability_stack_test_015, TestSize.Level1) +{ + int userUid = 10; + EXPECT_CALL(*bundleObject_, GetUidByBundleName(_, _)) + .Times(AtLeast(2)) + .WillOnce(Return(userUid)) + .WillOnce(Return(userUid)); + + EXPECT_CALL(*mockAppMgrClient, LoadAbility(_, _, _, _)) + .Times(AtLeast(1)) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)); + + // start a SINGLETON ability + auto musicAbilityRequest_ = GenerateAbilityRequest("device", "MusicSAbility", "music", "com.ix.hiMusic"); + stackManager_->StartAbility(musicAbilityRequest_); + auto secondTopAbility = stackManager_->GetCurrentTopAbility(); + secondTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + // lock + auto musicMisionRecord = stackManager_->GetTopMissionRecord(); + auto musicMisionRecordId = musicMisionRecord->GetMissionRecordId(); + auto result = stackManager_->StartLockMission(userUid, musicMisionRecordId, false, true); + EXPECT_EQ(ERR_OK, result); + + // not can start a ability + auto redioAbilityRequest_ = GenerateAbilityRequest("device", "RedioAbility", "music", "com.ix.hiRadio"); + auto ref = stackManager_->StartAbility(redioAbilityRequest_); + EXPECT_EQ(LOCK_MISSION_STATE_DENY_REQUEST, ref); + + auto topAbility = stackManager_->GetCurrentTopAbility(); + topAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + // unlock + result = stackManager_->StartLockMission(userUid, musicMisionRecordId, false, false); + EXPECT_EQ(ERR_OK, result); + + // can start a ability + ref = stackManager_->StartAbility(redioAbilityRequest_); + EXPECT_EQ(ERR_OK, ref); +} + +/* + * Feature: AaFwk + * Function: StartLockMission + * SubFunction: NA + * FunctionPoints: lock a mission , It's locked mission top ability will be active + * EnvConditions: NA + * CaseDescription: when a mission locked, you cannot delete the last one + */ +HWTEST_F(AbilityStackModuleTest, ability_stack_test_016, TestSize.Level1) +{ + int userUid = 10; + EXPECT_CALL(*bundleObject_, GetUidByBundleName(_, _)) + .Times(AtLeast(2)) + .WillOnce(Return(userUid)) + .WillOnce(Return(userUid)); + + EXPECT_CALL(*mockAppMgrClient, LoadAbility(_, _, _, _)) + .Times(AtLeast(1)) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)); + + // start a SINGLETON ability + auto musicAbilityRequest_ = GenerateAbilityRequest("device", "MusicSAbility", "music", "com.ix.hiMusic"); + stackManager_->StartAbility(musicAbilityRequest_); + auto secondTopAbility = stackManager_->GetCurrentTopAbility(); + secondTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + // lock + auto musicMisionRecord = stackManager_->GetTopMissionRecord(); + auto musicMisionRecordId = musicMisionRecord->GetMissionRecordId(); + auto result = stackManager_->StartLockMission(userUid, musicMisionRecordId, false, true); + EXPECT_EQ(ERR_OK, result); + + result = stackManager_->TerminateAbility(secondTopAbility->GetToken(), -1, nullptr); + EXPECT_EQ(LOCK_MISSION_STATE_DENY_REQUEST, result); + + // unlock + result = stackManager_->StartLockMission(userUid, musicMisionRecordId, false, false); + EXPECT_EQ(ERR_OK, result); + + result = stackManager_->TerminateAbility(secondTopAbility->GetToken(), -1, nullptr); + EXPECT_EQ(ERR_OK, result); +} + +/* + * Feature: AaFwk + * Function: StartLockMissions + * SubFunction: NA + * FunctionPoints: lock a mission , It's locked mission top ability will be active + * EnvConditions: NA + * CaseDescription: lock a multi ability mission + */ +HWTEST_F(AbilityStackModuleTest, ability_stack_test_017, TestSize.Level1) +{ + int sysUid = 1000; + EXPECT_CALL(*bundleObject_, GetUidByBundleName(_, _)) + .Times(AtLeast(2)) + .WillOnce(Return(sysUid)) + .WillOnce(Return(sysUid)); + + EXPECT_CALL(*mockAppMgrClient, LoadAbility(_, _, _, _)) + .Times(AtLeast(1)) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)); + + auto launcherAbilityRequest_ = GenerateAbilityRequest("device", "MusicAbility", "launcher", "com.ix.hiMusic"); + auto ref = stackManager_->StartAbility(launcherAbilityRequest_); + EXPECT_EQ(ERR_OK, ref); + auto firstTopAbility = stackManager_->GetCurrentTopAbility(); + firstTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + auto musicAbilityRequest_ = GenerateAbilityRequest("device", "MusicAbility2th", "launcher", "com.ix.hiMusic"); + ref = stackManager_->StartAbility(musicAbilityRequest_); + EXPECT_EQ(ERR_OK, ref); + auto secondTopAbility = stackManager_->GetCurrentTopAbility(); + secondTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + auto redioAbilityRequest_ = GenerateAbilityRequest("device", "RadioSAbility", "Radio", "com.ix.hiRadio"); + ref = stackManager_->StartAbility(redioAbilityRequest_); + EXPECT_EQ(ERR_OK, ref); + auto thirdTopAbility = stackManager_->GetCurrentTopAbility(); + thirdTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + firstTopAbility->SetAbilityState(OHOS::AAFwk::BACKGROUND); + secondTopAbility->SetAbilityState(OHOS::AAFwk::BACKGROUND); + + auto musicMisionRecord = secondTopAbility->GetMissionRecord(); + auto musicMisionRecordId = musicMisionRecord->GetMissionRecordId(); + + auto result = stackManager_->StartLockMission(sysUid, musicMisionRecordId, true, true); + EXPECT_EQ(ERR_OK, result); + + auto topRecord = stackManager_->GetCurrentTopAbility(); + auto abilityInfo = topRecord->GetAbilityInfo(); + EXPECT_EQ(abilityInfo.name, "MusicAbility2th"); + + // unlock + result = stackManager_->StartLockMission(sysUid, musicMisionRecordId, true, false); + EXPECT_EQ(ERR_OK, result); +} + +/* + * Feature: AaFwk + * Function: OnAbilityDied + * SubFunction: NA + * FunctionPoints: Execute when application dies + * EnvConditions: NA + * CaseDescription: When the system attribute is changed, if the listener is not registered, the application needs to be + * restarted + */ +HWTEST_F(AbilityStackModuleTest, ability_stack_test_018, TestSize.Level1) +{ + int userUid = 10; + EXPECT_CALL(*bundleObject_, GetUidByBundleName(_, _)) + .Times(AtLeast(2)) + .WillOnce(Return(userUid)) + .WillOnce(Return(userUid)); + + EXPECT_CALL(*mockAppMgrClient, LoadAbility(_, _, _, _)) + .Times(AtLeast(1)) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)); + + // start a SINGLETON ability + auto musicAbilityRequest_ = GenerateAbilityRequest("device", "MusicSAbility", "music", "com.ix.hiMusic"); + stackManager_->StartAbility(musicAbilityRequest_); + auto secondTopAbility = stackManager_->GetCurrentTopAbility(); + secondTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + // lock + auto musicMisionRecord = stackManager_->GetTopMissionRecord(); + auto musicMisionRecordId = musicMisionRecord->GetMissionRecordId(); + auto result = stackManager_->StartLockMission(userUid, musicMisionRecordId, false, true); + EXPECT_EQ(ERR_OK, result); + + // let ability die + stackManager_->OnAbilityDied(secondTopAbility); + auto state = stackManager_->lockMissionContainer_->IsLockedMissionState(); + EXPECT_FALSE(state); +} + +/* + * Feature: AaFwk + * Function: UpdateConfiguration + * SubFunction: NA + * FunctionPoints:Update applied + * EnvConditions: NA + * CaseDescription: 1. launcher ability default concern locale and fontSize + * 2. We pass in locale to test whether it can be called onConfigurationUpdated(ResConfig) + * + */ +HWTEST_F(AbilityStackModuleTest, ability_stack_test_019, TestSize.Level1) +{ + OHOS::sptr scheduler(new MockAbilityScheduler()); + + EXPECT_CALL(*mockAppMgrClient, LoadAbility(_, _, _, _)) + .Times(AtLeast(1)) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)); + + auto launcherAbilityRequest_ = GenerateAbilityRequest("device", "luncher", "launcher", "com.ix.hiworld"); + stackManager_->StartAbility(launcherAbilityRequest_); + auto firstTopAbility = stackManager_->GetCurrentTopAbility(); + firstTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + firstTopAbility->SetScheduler(scheduler); + + EXPECT_CALL(*scheduler, AsObject()).Times(testing::AtLeast(1)); + // Notify application executionon ConfigurationUpdated + EXPECT_CALL(*scheduler, ScheduleUpdateConfiguration(testing::_)).Times(testing::AtLeast(1)); + EXPECT_CALL(*scheduler, ScheduleAbilityTransaction(testing::_, testing::_)).Times(testing::AtLeast(1)); + + DummyConfiguration DummyConfiguration(FONTSIZE); + // test fun + auto ref = stackManager_->UpdateConfiguration(DummyConfiguration); + EXPECT_EQ(ERR_OK, ref); +} + +/* + * Feature: AaFwk + * Function: UpdateConfiguration + * SubFunction: NA + * FunctionPoints:Update applied + * EnvConditions: NA + * CaseDescription: 1. launcher ability + default ability default concern locale and fontSize + * 2. default ability in active + * 3. We pass in locale to test whether it can be called onConfigurationUpdated + * + */ +HWTEST_F(AbilityStackModuleTest, ability_stack_test_020, TestSize.Level1) +{ + OHOS::sptr scheduler(new MockAbilityScheduler()); + + EXPECT_CALL(*mockAppMgrClient, LoadAbility(_, _, _, _)) + .Times(AtLeast(1)) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)); + + auto launcherAbilityRequest_ = GenerateAbilityRequest("device", "LauncherAbility", "launcher", "com.ix.hiworld"); + auto ref = stackManager_->StartAbility(launcherAbilityRequest_); + EXPECT_EQ(ERR_OK, ref); + auto firstTopAbility = stackManager_->GetCurrentTopAbility(); + firstTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + auto musicAbilityRequest_ = GenerateAbilityRequest("device", "Music", "launcher", "com.ix.hiMusic"); + ref = stackManager_->StartAbility(musicAbilityRequest_); + EXPECT_EQ(ERR_OK, ref); + auto secondTopAbility = stackManager_->GetCurrentTopAbility(); + secondTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + secondTopAbility->SetScheduler(scheduler); + + EXPECT_CALL(*scheduler, AsObject()).Times(testing::AtLeast(1)); + // Notify application executionon ConfigurationUpdated + EXPECT_CALL(*scheduler, ScheduleUpdateConfiguration(testing::_)).Times(testing::AtLeast(1)); + EXPECT_CALL(*scheduler, ScheduleAbilityTransaction(testing::_, testing::_)).Times(testing::AtLeast(1)); + + DummyConfiguration DummyConfiguration(LAYOUT); + ref = stackManager_->UpdateConfiguration(DummyConfiguration); + EXPECT_EQ(ERR_OK, ref); +} + +/* + * Feature: AaFwk + * Function: UpdateConfiguration + * SubFunction: NA + * FunctionPoints: Update applied + * EnvConditions: NA + * CaseDescription: 1.default ability default concern locale and fontSize + * 2. When ordinary applications do not pay attention to system attributes, they will be restart + * + */ +HWTEST_F(AbilityStackModuleTest, ability_stack_test_021, TestSize.Level1) +{ + OHOS::sptr scheduler(new MockAbilityScheduler()); + + // When the application restarts, it is called + auto restartCall = [&](const sptr &token, + const sptr &preToken, + const AbilityInfo &abilityInfo, + const ApplicationInfo &appInfo) { + return (AppMgrResultCode)stackManager_->AttachAbilityThread(scheduler, token); + }; + + EXPECT_CALL(*mockAppMgrClient, LoadAbility(_, _, _, _)) + .Times(AtLeast(2)) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)) + .WillOnce(testing::Invoke(restartCall)); + + EXPECT_CALL(*mockAppMgrClient, TerminateAbility(_)).Times(AtLeast(1)).WillOnce(Return(AppMgrResultCode::RESULT_OK)); + + auto launcherAbilityRequest_ = GenerateAbilityRequest("device", "LauncherAbility", "launcher", "com.ix.hiworld"); + stackManager_->StartAbility(launcherAbilityRequest_); + auto firstTopAbility = stackManager_->GetCurrentTopAbility(); + firstTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + EXPECT_CALL(*scheduler, AsObject()).WillRepeatedly(Return(nullptr)); + firstTopAbility->SetScheduler(scheduler); + + auto transactionDoneInactive = [&](const Want &want, const LifeCycleStateInfo &targetState) { + stackManager_->CompleteInactive(firstTopAbility); + }; + + auto transactionDoneBackground = [&](const Want &want, const LifeCycleStateInfo &targetState) { + stackManager_->CompleteBackground(firstTopAbility); + }; + + auto transactionDoneTerminate = [&](const Want &want, const LifeCycleStateInfo &targetState) { + stackManager_->CompleteTerminate(firstTopAbility); + }; + + // first time call + EXPECT_CALL(*scheduler, ScheduleAbilityTransaction(testing::_, testing::_)) + .Times(testing::AtLeast(3)) + .WillOnce(testing::Invoke(transactionDoneInactive)) + .WillOnce(testing::Invoke(transactionDoneBackground)) + .WillOnce(testing::Invoke(transactionDoneTerminate)); + + // when restart ability save the ability state + EXPECT_CALL(*scheduler, ScheduleSaveAbilityState(testing::_)).Times(testing::AtLeast(1)); + // when restart ability restore the ability state + EXPECT_CALL(*scheduler, ScheduleRestoreAbilityState(testing::_)).Times(testing::AtLeast(1)); + + DummyConfiguration DummyConfiguration(LANGUAGE); + auto ref = stackManager_->UpdateConfiguration(DummyConfiguration); + EXPECT_EQ(ERR_OK, ref); +} + +/* + * Feature: AaFwk + * Function: UpdateConfiguration + * SubFunction: NA + * FunctionPoints: Notification application attribute change + * EnvConditions: NA + * CaseDescription: Notify if the system property change notification is registered + */ +HWTEST_F(AbilityStackModuleTest, ability_stack_test_022, TestSize.Level1) +{ + OHOS::sptr scheduler(new MockAbilityScheduler()); + + // When the application restarts, it is called + auto restartCall = [&](const sptr &token, + const sptr &preToken, + const AbilityInfo &abilityInfo, + const ApplicationInfo &appInfo) { + return (AppMgrResultCode)stackManager_->AttachAbilityThread(scheduler, token); + }; + + EXPECT_CALL(*mockAppMgrClient, LoadAbility(_, _, _, _)) + .Times(AtLeast(3)) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)) + .WillOnce(testing::Invoke(restartCall)); + + EXPECT_CALL(*mockAppMgrClient, TerminateAbility(_)).Times(AtLeast(1)).WillOnce(Return(AppMgrResultCode::RESULT_OK)); + + // launcher ability + auto launcherAbilityRequest_ = GenerateAbilityRequest("device", "LauncherAbility", "launcher", "com.ix.hiworld"); + auto returen = stackManager_->StartAbility(launcherAbilityRequest_); + EXPECT_EQ(ERR_OK, returen); + auto launcherAbility = stackManager_->GetCurrentTopAbility(); + launcherAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + // test ability + auto musicAbilityRequest = GenerateAbilityRequest("device", "MusicAbility", "music", "com.ix.hiMusic"); + stackManager_->StartAbility(musicAbilityRequest); + auto firstTopAbility = stackManager_->GetCurrentTopAbility(); + firstTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + EXPECT_CALL(*scheduler, AsObject()).WillRepeatedly(Return(nullptr)); + firstTopAbility->SetScheduler(scheduler); + + auto transactionDoneInactive = [&](const Want &want, const LifeCycleStateInfo &targetState) { + stackManager_->CompleteInactive(firstTopAbility); + }; + + auto transactionDoneBackground = [&](const Want &want, const LifeCycleStateInfo &targetState) { + stackManager_->CompleteBackground(firstTopAbility); + }; + + auto transactionDoneTerminate = [&](const Want &want, const LifeCycleStateInfo &targetState) { + stackManager_->CompleteTerminate(firstTopAbility); + }; + + // first time call + EXPECT_CALL(*scheduler, ScheduleAbilityTransaction(testing::_, testing::_)) + .Times(testing::AtLeast(3)) + .WillOnce(testing::Invoke(transactionDoneInactive)) + .WillOnce(testing::Invoke(transactionDoneBackground)) + .WillOnce(testing::Invoke(transactionDoneTerminate)); + + // when restart ability save the ability state + EXPECT_CALL(*scheduler, ScheduleSaveAbilityState(testing::_)).Times(testing::AtLeast(1)); + // when restart ability restore the ability state + EXPECT_CALL(*scheduler, ScheduleRestoreAbilityState(testing::_)).Times(testing::AtLeast(1)); + + DummyConfiguration DummyConfiguration(""); + auto ref = stackManager_->UpdateConfiguration(DummyConfiguration); + + EXPECT_EQ(ERR_OK, ref); +} + +/* + * Feature: AaFwk + * Function: UpdateConfiguration + * SubFunction: NA + * FunctionPoints:Update applied + * EnvConditions: NA + * CaseDescription: 1. sigleton auncher ability + * 2. restart ability + * + */ +HWTEST_F(AbilityStackModuleTest, ability_stack_test_023, TestSize.Level1) +{ + OHOS::sptr scheduler(new MockAbilityScheduler()); + + // When the application restarts, it is called + auto restartCall = [&](const sptr &token, + const sptr &preToken, + const AbilityInfo &abilityInfo, + const ApplicationInfo &appInfo) { + return (AppMgrResultCode)stackManager_->AttachAbilityThread(scheduler, token); + }; + + EXPECT_CALL(*mockAppMgrClient, LoadAbility(_, _, _, _)) + .Times(AtLeast(2)) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)) + .WillOnce(testing::Invoke(restartCall)); + + EXPECT_CALL(*mockAppMgrClient, TerminateAbility(_)).Times(AtLeast(1)).WillOnce(Return(AppMgrResultCode::RESULT_OK)); + + auto musicRequest = GenerateAbilityRequest("device", "MusicSAbility", "music", "com.ix.hiMusic"); + stackManager_->StartAbility(musicRequest); + auto firstTopAbility = stackManager_->GetCurrentTopAbility(); + firstTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + EXPECT_CALL(*scheduler, AsObject()).WillRepeatedly(Return(nullptr)); + firstTopAbility->SetScheduler(scheduler); + + auto transactionDoneInactive = [&](const Want &want, const LifeCycleStateInfo &targetState) { + stackManager_->CompleteInactive(firstTopAbility); + }; + + auto transactionDoneBackground = [&](const Want &want, const LifeCycleStateInfo &targetState) { + stackManager_->CompleteBackground(firstTopAbility); + }; + + auto transactionDoneTerminate = [&](const Want &want, const LifeCycleStateInfo &targetState) { + stackManager_->CompleteTerminate(firstTopAbility); + }; + + // first time call + EXPECT_CALL(*scheduler, ScheduleAbilityTransaction(testing::_, testing::_)) + .Times(testing::AtLeast(3)) + .WillOnce(testing::Invoke(transactionDoneInactive)) + .WillOnce(testing::Invoke(transactionDoneBackground)) + .WillOnce(testing::Invoke(transactionDoneTerminate)); + + // when restart ability save the ability state + EXPECT_CALL(*scheduler, ScheduleSaveAbilityState(testing::_)).Times(testing::AtLeast(1)); + // when restart ability restore the ability state + EXPECT_CALL(*scheduler, ScheduleRestoreAbilityState(testing::_)).Times(testing::AtLeast(1)); + + DummyConfiguration DummyConfiguration(LANGUAGE); + auto ref = stackManager_->UpdateConfiguration(DummyConfiguration); + EXPECT_EQ(ERR_OK, ref); +} + +/* + * Feature: AaFwk + * Function: UpdateConfiguration + * SubFunction: NA + * FunctionPoints:Update applied + * EnvConditions: NA + * CaseDescription: 1.sigleton auncher ability + * 2. Will call onConfigurationUpdated(ResConfig) + * + */ +HWTEST_F(AbilityStackModuleTest, ability_stack_test_024, TestSize.Level1) +{ + OHOS::sptr scheduler(new MockAbilityScheduler()); + + EXPECT_CALL(*mockAppMgrClient, LoadAbility(_, _, _, _)) + .Times(AtLeast(1)) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)); + + // singleton,focus + auto musicAbilityRequest = GenerateAbilityRequest("device", "MusicTon", "music", "com.ix.hiMusic"); + stackManager_->StartAbility(musicAbilityRequest); + auto firstTopAbility = stackManager_->GetCurrentTopAbility(); + firstTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + firstTopAbility->SetScheduler(scheduler); + + EXPECT_CALL(*scheduler, AsObject()).Times(testing::AtLeast(1)); + // Notify application executionon ConfigurationUpdated + EXPECT_CALL(*scheduler, ScheduleUpdateConfiguration(testing::_)).Times(testing::AtLeast(1)); + EXPECT_CALL(*scheduler, ScheduleAbilityTransaction(testing::_, testing::_)).Times(testing::AtLeast(1)); + + DummyConfiguration DummyConfiguration(LAYOUT); + // test fun + auto ref = stackManager_->UpdateConfiguration(DummyConfiguration); + EXPECT_EQ(ERR_OK, ref); +} + +/* + * Feature: AaFwk + * Function: StartAbility + * SubFunction: NA + * FunctionPoints: Resume mission record + * EnvConditions: NA + * CaseDescription: 1. start music ability standard + * 2. start radio ability standard + * 3. radio ability died + * 4. start music ability standard again + * 5. resume radio ability + */ +HWTEST_F(AbilityStackModuleTest, ability_stack_test_025, TestSize.Level1) +{ + EXPECT_CALL(*mockAppMgrClient, LoadAbility(_, _, _, _)) + .Times(AtLeast(1)) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)); + + EXPECT_CALL(*mockAppMgrClient, UpdateAbilityState(_, _)) + .Times(AtLeast(1)) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)); + + // launcher ability + auto launcherAbilityRequest_ = GenerateAbilityRequest("device", "LauncherAbility", "launcher", "com.ix.hiworld"); + auto ref = stackManager_->StartAbility(launcherAbilityRequest_); + EXPECT_EQ(ERR_OK, ref); + auto launcherAbility = stackManager_->GetCurrentTopAbility(); + launcherAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + // music ability standard + auto musicAbilityRequest = GenerateAbilityRequest("device", "MusicAbility", "music", "com.ix.hiMusic"); + ref = stackManager_->StartAbility(musicAbilityRequest); + EXPECT_EQ(ERR_OK, ref); + auto musicAbility = stackManager_->GetCurrentTopAbility(); + musicAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + // radio ability standard + auto radioAbilityRequest = GenerateAbilityRequest("device", "RadioAbility", "radio", "com.ix.hiRadio"); + ref = stackManager_->StartAbility(radioAbilityRequest); + EXPECT_EQ(ERR_OK, ref); + auto radioAbility = stackManager_->GetCurrentTopAbility(); + radioAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + // set mock scheduler + EXPECT_CALL(*mockScheduler_, AsObject()).WillRepeatedly(Return(nullptr)); + radioAbility->SetScheduler(mockScheduler_); + + // radio ability die + stackManager_->OnAbilityDied(radioAbility); + + // set top ability active + auto topAbility = stackManager_->GetCurrentTopAbility(); + EXPECT_NE(topAbility->GetAbilityInfo().name, "RadioAbility"); + topAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + // start music ability again + auto musicAbilityRequest2 = GenerateAbilityRequest("device", "MusicAbility", "music", "com.ix.hiMusic"); + ref = stackManager_->StartAbility(musicAbilityRequest2); + EXPECT_EQ(ERR_OK, ref); + + // attach radio ability + EXPECT_CALL(*mockScheduler_, ScheduleRestoreAbilityState(_)).Times(1); + stackManager_->AttachAbilityThread(mockScheduler_, radioAbility->GetToken()); + radioAbility->SetScheduler(nullptr); +} + +/* + * Feature: AaFwk + * Function: StartAbility + * SubFunction: NA + * FunctionPoints: Resume mission record + * EnvConditions: NA + * CaseDescription: 1. start radio ability singleton + * 2. start music ability standard + * 3. radio ability died + * 4. start radio ability singleton again + * 5. resume radio ability + */ +HWTEST_F(AbilityStackModuleTest, ability_stack_test_026, TestSize.Level1) +{ + EXPECT_CALL(*mockAppMgrClient, LoadAbility(_, _, _, _)) + .Times(AtLeast(1)) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)); + EXPECT_CALL(*mockAppMgrClient, UpdateAbilityState(_, _)) + .Times(AtLeast(1)) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)); + + // launcher ability + auto launcherAbilityRequest_ = GenerateAbilityRequest("device", "LauncherAbility", "launcher", "com.ix.hiworld"); + auto ref = stackManager_->StartAbility(launcherAbilityRequest_); + EXPECT_EQ(ERR_OK, ref); + auto launcherAbility = stackManager_->GetCurrentTopAbility(); + launcherAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + // radio ability singleton + auto radioAbilityRequest = GenerateAbilityRequest("device", "RadioSAbility", "radio", "com.ix.hiRadio"); + ref = stackManager_->StartAbility(radioAbilityRequest); + EXPECT_EQ(ERR_OK, ref); + auto radioAbility = stackManager_->GetCurrentTopAbility(); + radioAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + // music ability standard + auto musicAbilityRequest = GenerateAbilityRequest("device", "MusicAbility", "music", "com.ix.hiMusic"); + ref = stackManager_->StartAbility(musicAbilityRequest); + EXPECT_EQ(ERR_OK, ref); + auto musicAbility = stackManager_->GetCurrentTopAbility(); + musicAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + // set mock scheduler + EXPECT_CALL(*mockScheduler_, AsObject()).WillRepeatedly(Return(nullptr)); + radioAbility->SetScheduler(mockScheduler_); + + // radio ability die + stackManager_->OnAbilityDied(radioAbility); + + // set top ability active + auto topAbility = stackManager_->GetCurrentTopAbility(); + EXPECT_NE(topAbility->GetAbilityInfo().name, "RadioAbility"); + topAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + // start radio ability singleton again + auto radioAbilityReques2 = GenerateAbilityRequest("device", "RadioSAbility", "radio", "com.ix.hiRadio"); + ref = stackManager_->StartAbility(radioAbilityReques2); + EXPECT_EQ(ERR_OK, ref); + + // attach radio ability + EXPECT_CALL(*mockScheduler_, ScheduleRestoreAbilityState(_)).Times(1); + stackManager_->AttachAbilityThread(mockScheduler_, radioAbility->GetToken()); + radioAbility->SetScheduler(nullptr); +} + +/* + * Feature: AaFwk + * Function: StartAbility + * SubFunction: NA + * FunctionPoints: Resume mission record + * EnvConditions: NA + * CaseDescription: 1. start music ability standard + * 2. start radio ability singletop + * 3. radio ability died + * 4. start radio ability singletop again + * 5. resume radio ability + */ +HWTEST_F(AbilityStackModuleTest, ability_stack_test_027, TestSize.Level1) +{ + EXPECT_CALL(*mockAppMgrClient, LoadAbility(_, _, _, _)) + .Times(AtLeast(1)) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)); + EXPECT_CALL(*mockAppMgrClient, UpdateAbilityState(_, _)) + .Times(AtLeast(1)) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)); + + // launcher ability + auto launcherAbilityRequest_ = GenerateAbilityRequest("device", "LauncherAbility", "launcher", "com.ix.hiworld"); + auto ref = stackManager_->StartAbility(launcherAbilityRequest_); + EXPECT_EQ(ERR_OK, ref); + auto launcherAbility = stackManager_->GetCurrentTopAbility(); + launcherAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + // music ability standard + auto musicAbilityRequest = GenerateAbilityRequest("device", "MusicAbility", "music", "com.ix.hiMusic"); + ref = stackManager_->StartAbility(musicAbilityRequest); + EXPECT_EQ(ERR_OK, ref); + auto musicAbility = stackManager_->GetCurrentTopAbility(); + musicAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + // radio ability singletop + auto radioAbilityRequest = GenerateAbilityRequest("device", "RadioTopAbility", "radio", "com.ix.hiRadio"); + ref = stackManager_->StartAbility(radioAbilityRequest); + EXPECT_EQ(ERR_OK, ref); + auto radioAbility = stackManager_->GetCurrentTopAbility(); + radioAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + // set mock scheduler + EXPECT_CALL(*mockScheduler_, AsObject()).WillRepeatedly(Return(nullptr)); + radioAbility->SetScheduler(mockScheduler_); + + // radio ability die + stackManager_->OnAbilityDied(radioAbility); + + // set top ability active + auto topAbility = stackManager_->GetCurrentTopAbility(); + EXPECT_NE(topAbility->GetAbilityInfo().name, "RadioAbility"); + topAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + // start radio ability singleton again + auto radioAbilityReques2 = GenerateAbilityRequest("device", "RadioTopAbility", "radio", "com.ix.hiRadio"); + ref = stackManager_->StartAbility(radioAbilityReques2); + EXPECT_EQ(ERR_OK, ref); + + // attach radio ability + EXPECT_CALL(*mockScheduler_, ScheduleRestoreAbilityState(_)).Times(1); + stackManager_->AttachAbilityThread(mockScheduler_, radioAbility->GetToken()); + radioAbility->SetScheduler(nullptr); +} + +/* + * Feature: AaFwk + * Function: MoveMissionToTop + * SubFunction: NA + * FunctionPoints: Resume mission record + * EnvConditions: NA + * CaseDescription: 1. start radio ability singleton + * 2. start music ability standard + * 3. radio ability died + * 4. move misstion to top which has radio ability + * 5. resume radio ability + */ +HWTEST_F(AbilityStackModuleTest, ability_stack_test_028, TestSize.Level1) +{ + EXPECT_CALL(*mockAppMgrClient, LoadAbility(_, _, _, _)) + .Times(AtLeast(1)) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)); + EXPECT_CALL(*mockAppMgrClient, UpdateAbilityState(_, _)) + .Times(AtLeast(1)) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)); + + // launcher ability + auto launcherAbilityRequest_ = GenerateAbilityRequest("device", "LauncherAbility", "launcher", "com.ix.hiworld"); + auto ref = stackManager_->StartAbility(launcherAbilityRequest_); + EXPECT_EQ(ERR_OK, ref); + auto launcherAbility = stackManager_->GetCurrentTopAbility(); + launcherAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + // radio ability singleton + auto radioAbilityRequest = GenerateAbilityRequest("device", "RadioSAbility", "radio", "com.ix.hiRadio"); + ref = stackManager_->StartAbility(radioAbilityRequest); + EXPECT_EQ(ERR_OK, ref); + auto radioAbility = stackManager_->GetCurrentTopAbility(); + radioAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + // music ability standard + auto musicAbilityRequest = GenerateAbilityRequest("device", "MusicAbility", "music", "com.ix.hiMusic"); + ref = stackManager_->StartAbility(musicAbilityRequest); + EXPECT_EQ(ERR_OK, ref); + auto musicAbility = stackManager_->GetCurrentTopAbility(); + musicAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + // set mock scheduler + EXPECT_CALL(*mockScheduler_, AsObject()).WillRepeatedly(Return(nullptr)); + radioAbility->SetScheduler(mockScheduler_); + + // radio ability die + stackManager_->OnAbilityDied(radioAbility); + + // set top ability active + auto topAbility = stackManager_->GetCurrentTopAbility(); + EXPECT_NE(topAbility->GetAbilityInfo().name, "RadioAbility"); + topAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + // move mission to top, radio ability singleton + auto missionId = radioAbility->GetMissionRecord()->GetMissionRecordId(); + stackManager_->MoveMissionToTop(missionId); + + // attach radio ability + EXPECT_CALL(*mockScheduler_, ScheduleRestoreAbilityState(_)).Times(1); + stackManager_->AttachAbilityThread(mockScheduler_, radioAbility->GetToken()); +} + +/* + * Feature: AaFwk + * Function: MoveMissionToTop + * SubFunction: NA + * FunctionPoints: Resume mission record + * EnvConditions: NA + * CaseDescription: 1. start radio ability standard + * 2. start music ability standard + * 3. start music ability singleton + * 4. radio ability died + * 5. move mission to top which has radio ability + * 6. resume radio ability + */ +HWTEST_F(AbilityStackModuleTest, ability_stack_test_029, TestSize.Level1) +{ + EXPECT_CALL(*mockAppMgrClient, LoadAbility(_, _, _, _)) + .Times(AtLeast(1)) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)); + EXPECT_CALL(*mockAppMgrClient, UpdateAbilityState(_, _)) + .Times(AtLeast(1)) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)); + + // launcher ability + auto launcherAbilityRequest_ = GenerateAbilityRequest("device", "LauncherAbility", "launcher", "com.ix.hiworld"); + auto ref = stackManager_->StartAbility(launcherAbilityRequest_); + EXPECT_EQ(ERR_OK, ref); + auto launcherAbility = stackManager_->GetCurrentTopAbility(); + launcherAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + // radio ability standard + auto radioAbilityRequest = GenerateAbilityRequest("device", "RadioAbility", "radio", "com.ix.hiRadio"); + ref = stackManager_->StartAbility(radioAbilityRequest); + EXPECT_EQ(ERR_OK, ref); + auto radioAbility = stackManager_->GetCurrentTopAbility(); + radioAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + // music ability standard + auto musicAbilityRequest = GenerateAbilityRequest("device", "MusicAbility", "music", "com.ix.hiMusic"); + ref = stackManager_->StartAbility(musicAbilityRequest); + EXPECT_EQ(ERR_OK, ref); + auto musicAbility = stackManager_->GetCurrentTopAbility(); + musicAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + // music ability singleton + auto musicSAbilityRequest = GenerateAbilityRequest("device", "MusicSAbility", "music", "com.ix.hiMusic"); + ref = stackManager_->StartAbility(musicSAbilityRequest); + EXPECT_EQ(ERR_OK, ref); + auto musicSAbility = stackManager_->GetCurrentTopAbility(); + musicSAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + // set mock scheduler + EXPECT_CALL(*mockScheduler_, AsObject()).WillRepeatedly(Return(nullptr)); + radioAbility->SetScheduler(mockScheduler_); + + // radio ability die + stackManager_->OnAbilityDied(radioAbility); + + // set top ability active + auto topAbility = stackManager_->GetCurrentTopAbility(); + EXPECT_NE(topAbility->GetAbilityInfo().name, "RadioAbility"); + topAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + // move mission to top + auto missionId = radioAbility->GetMissionRecord()->GetMissionRecordId(); + stackManager_->MoveMissionToTop(missionId); + + // attach radio ability + EXPECT_CALL(*mockScheduler_, ScheduleRestoreAbilityState(_)).Times(1); + stackManager_->AttachAbilityThread(mockScheduler_, radioAbility->GetToken()); + radioAbility->SetScheduler(nullptr); +} + +/* + * Feature: AaFwk + * Function: MoveMissionToEnd + * SubFunction: NA + * FunctionPoints: Resume mission record + * EnvConditions: NA + * CaseDescription: 1. start radio ability singleton + * 2. start music ability standard + * 3. radio ability died + * 4. move mission which at top to end + * 5. resume radio ability + */ +HWTEST_F(AbilityStackModuleTest, ability_stack_test_030, TestSize.Level1) +{ + EXPECT_CALL(*mockAppMgrClient, LoadAbility(_, _, _, _)) + .Times(AtLeast(1)) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)); + EXPECT_CALL(*mockAppMgrClient, UpdateAbilityState(_, _)) + .Times(AtLeast(1)) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)); + + // launcher ability + auto launcherAbilityRequest_ = GenerateAbilityRequest("device", "LauncherAbility", "launcher", "com.ix.hiworld"); + auto ref = stackManager_->StartAbility(launcherAbilityRequest_); + EXPECT_EQ(ERR_OK, ref); + auto launcherAbility = stackManager_->GetCurrentTopAbility(); + launcherAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + // radio ability singleton + auto radioSAbilityRequest = GenerateAbilityRequest("device", "RadioSAbility", "radio", "com.ix.hiRadio"); + ref = stackManager_->StartAbility(radioSAbilityRequest); + EXPECT_EQ(ERR_OK, ref); + auto radioSAbility = stackManager_->GetCurrentTopAbility(); + radioSAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + // music ability standard + auto musicAbilityRequest = GenerateAbilityRequest("device", "MusicAbility", "music", "com.ix.hiMusic"); + ref = stackManager_->StartAbility(musicAbilityRequest); + EXPECT_EQ(ERR_OK, ref); + auto musicAbility = stackManager_->GetCurrentTopAbility(); + musicAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + // set mock scheduler + EXPECT_CALL(*mockScheduler_, AsObject()).WillRepeatedly(Return(nullptr)); + radioSAbility->SetScheduler(mockScheduler_); + + // radio ability die + stackManager_->OnAbilityDied(radioSAbility); + + // set top ability active + auto topAbility = stackManager_->GetCurrentTopAbility(); + EXPECT_NE(topAbility->GetAbilityInfo().name, "RadioAbility"); + topAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + // move mission to end + stackManager_->MoveMissionToEnd(musicAbility->GetToken(), false); + + // attach radio ability + EXPECT_CALL(*mockScheduler_, ScheduleRestoreAbilityState(_)).Times(1); + stackManager_->AttachAbilityThread(mockScheduler_, radioSAbility->GetToken()); + radioSAbility->SetScheduler(nullptr); +} + +/* + * Feature: AaFwk + * Function: MoveMissionToEnd + * SubFunction: NA + * FunctionPoints: Resume mission record + * EnvConditions: NA + * CaseDescription: 1. start radio ability standard + * 2. start music ability singleton + * 3. radio ability died + * 4. move mission which at top to end + * 5. resume radio ability + */ +HWTEST_F(AbilityStackModuleTest, ability_stack_test_031, TestSize.Level1) +{ + EXPECT_CALL(*mockAppMgrClient, LoadAbility(_, _, _, _)) + .Times(AtLeast(1)) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)); + EXPECT_CALL(*mockAppMgrClient, UpdateAbilityState(_, _)) + .Times(AtLeast(1)) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)); + + // launcher ability + auto launcherAbilityRequest_ = GenerateAbilityRequest("device", "LauncherAbility", "launcher", "com.ix.hiworld"); + auto ref = stackManager_->StartAbility(launcherAbilityRequest_); + EXPECT_EQ(ERR_OK, ref); + auto launcherAbility = stackManager_->GetCurrentTopAbility(); + launcherAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + // radio ability standard + auto radioAbilityRequest = GenerateAbilityRequest("device", "RadioAbility", "radio", "com.ix.hiRadio"); + ref = stackManager_->StartAbility(radioAbilityRequest); + EXPECT_EQ(ERR_OK, ref); + auto radioAbility = stackManager_->GetCurrentTopAbility(); + radioAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + // music ability singleton + auto musicSAbilityRequest = GenerateAbilityRequest("device", "MusicSAbility", "music", "com.ix.hiMusic"); + ref = stackManager_->StartAbility(musicSAbilityRequest); + EXPECT_EQ(ERR_OK, ref); + auto musicSAbility = stackManager_->GetCurrentTopAbility(); + musicSAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + // set mock scheduler + EXPECT_CALL(*mockScheduler_, AsObject()).WillRepeatedly(Return(nullptr)); + radioAbility->SetScheduler(mockScheduler_); + + // radio ability die + stackManager_->OnAbilityDied(radioAbility); + + // set top ability active + auto topAbility = stackManager_->GetCurrentTopAbility(); + EXPECT_NE(topAbility->GetAbilityInfo().name, "RadioAbility"); + topAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + // move mission to end + stackManager_->MoveMissionToEnd(musicSAbility->GetToken(), false); + + // attach radio ability + EXPECT_CALL(*mockScheduler_, ScheduleRestoreAbilityState(_)).Times(1); + stackManager_->AttachAbilityThread(mockScheduler_, radioAbility->GetToken()); + radioAbility->SetScheduler(nullptr); +} + +/* + * Feature: AaFwk + * Function: MoveMissionToEnd + * SubFunction: NA + * FunctionPoints: Floating window and full screen movement + * EnvConditions: NA + * CaseDescription: When a full screen application and a floating window application are displayed, move the floating + * window application to the background + */ + +HWTEST_F(AbilityStackModuleTest, ability_stack_test_032, TestSize.Level1) +{ + OHOS::sptr scheduler(new MockAbilityScheduler()); + + EXPECT_CALL(*mockAppMgrClient, LoadAbility(_, _, _, _)) + .Times(AtLeast(2)) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)); + + auto launcherAbilityRequest_ = GenerateAbilityRequest("device", "LauncherAbility", "launcher", "com.ix.hiworld"); + auto ref = stackManager_->StartAbility(launcherAbilityRequest_); + EXPECT_EQ(ERR_OK, ref); + auto topMissionRecord1 = stackManager_->GetTopMissionRecord(); + auto topAbilityRecord1 = stackManager_->GetCurrentTopAbility(); + topAbilityRecord1->SetAbilityState(OHOS::AAFwk::ACTIVE); + + auto musicAbilityRequest_ = GenerateAbilityRequest("device", "Music", "launcher", "com.ix.hiMusic"); + // start float ability + auto abilityStartSetting = AbilityStartSetting::GetEmptySetting(); + EXPECT_TRUE(abilityStartSetting); + abilityStartSetting->AddProperty(AbilityStartSetting::WINDOW_MODE_KEY, + std::to_string(AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_FLOATING)); + + musicAbilityRequest_.startSetting = abilityStartSetting; + ref = stackManager_->StartAbility(musicAbilityRequest_); + EXPECT_EQ(0, ref); + auto topMissionRecord2 = stackManager_->GetTopMissionRecord(); + auto topAbilityRecord2 = stackManager_->GetCurrentTopAbility(); + EXPECT_TRUE(topMissionRecord2); + EXPECT_TRUE(topAbilityRecord2); + topAbilityRecord2->SetAbilityState(OHOS::AAFwk::ACTIVE); + + stackManager_->isMultiWinMoving_ = false; + // test case + EXPECT_EQ(topMissionRecord1->GetMissionStack()->GetMissionStackId(), LAUNCHER_MISSION_STACK_ID); + EXPECT_EQ(topMissionRecord2->GetMissionStack()->GetMissionStackId(), FLOATING_MISSION_STACK_ID); + + topAbilityRecord2->SetScheduler(scheduler); + + // Notify application executionon ConfigurationUpdated + EXPECT_CALL(*scheduler, ScheduleAbilityTransaction(testing::_, testing::_)).Times(testing::AtLeast(1)); + auto focusChangeFlag = [](bool flag) { EXPECT_TRUE(flag); }; + + EXPECT_CALL(*scheduler, NotifyTopActiveAbilityChanged(testing::_)) + .Times(testing::AtLeast(1)) + .WillOnce(testing::Invoke(focusChangeFlag)); + // test fun + ref = stackManager_->MoveMissionToEnd(topAbilityRecord2->GetToken(), true); + EXPECT_EQ(ERR_OK, ref); +} + +/* + * Feature: AaFwk + * Function: MoveMissionToEnd + * SubFunction: NA + * FunctionPoints: Floating window and full screen movement + * EnvConditions: NA + * CaseDescription: When a full screen application and a floating window application are displayed, move the floating + * window application to the background + */ + +HWTEST_F(AbilityStackModuleTest, ability_stack_test_033, TestSize.Level1) +{ + OHOS::sptr scheduler(new MockAbilityScheduler()); + OHOS::sptr schedulerRadio(new MockAbilityScheduler()); + + EXPECT_CALL(*mockAppMgrClient, LoadAbility(_, _, _, _)) + .Times(AtLeast(2)) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)); + + auto launcherAbilityRequest_ = GenerateAbilityRequest("device", "LauncherAbility", "launcher", "com.ix.hiworld"); + auto ref = stackManager_->StartAbility(launcherAbilityRequest_); + EXPECT_EQ(ERR_OK, ref); + auto topMissionRecord1 = stackManager_->GetTopMissionRecord(); + auto topAbilityRecord1 = stackManager_->GetCurrentTopAbility(); + topAbilityRecord1->SetAbilityState(OHOS::AAFwk::ACTIVE); + + // radio ability standard + auto radioAbilityRequest = GenerateAbilityRequest("device", "RadioAbility", "radio", "com.ix.hiRadio"); + ref = stackManager_->StartAbility(radioAbilityRequest); + EXPECT_EQ(ERR_OK, ref); + auto topMissionRecordRadio = stackManager_->GetTopMissionRecord(); + auto topAbilityRecordRadio = stackManager_->GetCurrentTopAbility(); + EXPECT_TRUE(topMissionRecordRadio); + EXPECT_TRUE(topAbilityRecordRadio); + topAbilityRecordRadio->SetAbilityState(OHOS::AAFwk::ACTIVE); + + auto musicAbilityRequest_ = GenerateAbilityRequest("device", "Music", "launcher", "com.ix.hiMusic"); + // start float ability + auto abilityStartSetting = AbilityStartSetting::GetEmptySetting(); + EXPECT_TRUE(abilityStartSetting); + abilityStartSetting->AddProperty(AbilityStartSetting::WINDOW_MODE_KEY, + std::to_string(AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_FLOATING)); + + musicAbilityRequest_.startSetting = abilityStartSetting; + ref = stackManager_->StartAbility(musicAbilityRequest_); + EXPECT_EQ(0, ref); + auto topMissionRecord2 = stackManager_->GetTopMissionRecord(); + auto topAbilityRecord2 = stackManager_->GetCurrentTopAbility(); + EXPECT_TRUE(topMissionRecord2); + EXPECT_TRUE(topAbilityRecord2); + topAbilityRecord2->SetAbilityState(OHOS::AAFwk::ACTIVE); + + // test case + EXPECT_EQ(topMissionRecord1->GetMissionStack()->GetMissionStackId(), LAUNCHER_MISSION_STACK_ID); + EXPECT_EQ(topMissionRecordRadio->GetMissionStack()->GetMissionStackId(), FLOATING_MISSION_STACK_ID); + EXPECT_EQ(topMissionRecord2->GetMissionStack()->GetMissionStackId(), FLOATING_MISSION_STACK_ID); + + stackManager_->isMultiWinMoving_ = false; + + // Music anility scheduler + topAbilityRecord2->SetScheduler(scheduler); + EXPECT_CALL(*scheduler, AsObject()).Times(testing::AtLeast(1)); + // Notify application executionon ConfigurationUpdated + EXPECT_CALL(*scheduler, ScheduleAbilityTransaction(testing::_, testing::_)).Times(testing::AtLeast(1)); + + auto focusChangeFlag = [](bool flag) { EXPECT_TRUE(flag); }; + + EXPECT_CALL(*scheduler, NotifyTopActiveAbilityChanged(testing::_)) + .Times(testing::AtLeast(1)) + .WillOnce(testing::Invoke(focusChangeFlag)); + + // test fun + ref = stackManager_->MoveMissionToEnd(topAbilityRecord2->GetToken(), true); + EXPECT_EQ(ERR_OK, ref); +} + +/* + * Feature: AaFwk + * Function: StartAbility + * SubFunction: NA + * FunctionPoints: StartAbility by setting info, satrt a Split screen or floating window + * EnvConditions: NA + * CaseDescription: Start a floating window in singleton mode? + */ +HWTEST_F(AbilityStackModuleTest, ability_stack_test_034, TestSize.Level1) +{ + EXPECT_CALL(*mockAppMgrClient, LoadAbility(_, _, _, _)) + .Times(AtLeast(2)) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)); + + auto launcherAbilityRequest_ = GenerateAbilityRequest("device", "LauncherAbility", "launcher", "com.ix.hiworld"); + auto ref = stackManager_->StartAbility(launcherAbilityRequest_); + EXPECT_EQ(ERR_OK, ref); + auto topAbilityRecord1 = stackManager_->GetCurrentTopAbility(); + topAbilityRecord1->SetAbilityState(OHOS::AAFwk::ACTIVE); + + // singleton ability + auto radioAbilityRequest = GenerateAbilityRequest("device", "RadioAbility", "radio", "com.ix.hiRadio"); + + // float flag + auto abilityStartSetting = AbilityStartSetting::GetEmptySetting(); + EXPECT_TRUE(abilityStartSetting); + abilityStartSetting->AddProperty(AbilityStartSetting::WINDOW_MODE_KEY, + std::to_string(AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_FLOATING)); + + radioAbilityRequest.startSetting = abilityStartSetting; + + ref = stackManager_->StartAbility(radioAbilityRequest); + EXPECT_EQ(ERR_OK, ref); + auto topMissionRecordRadio = stackManager_->GetTopMissionRecord(); + auto topAbilityRecordRadio = stackManager_->GetCurrentTopAbility(); + EXPECT_TRUE(topMissionRecordRadio); + EXPECT_TRUE(topAbilityRecordRadio); + topAbilityRecordRadio->SetAbilityState(OHOS::AAFwk::ACTIVE); + + EXPECT_EQ(topMissionRecordRadio->GetMissionStack()->GetMissionStackId(), FLOATING_MISSION_STACK_ID); + EXPECT_FALSE(stackManager_->isMultiWinMoving_); +} + +/* + * Feature: AaFwk + * Function: StartAbility + * SubFunction: NA + * FunctionPoints: StartAbility by setting info, satrt a Split screen or floating window + * EnvConditions: NA + * CaseDescription: Start a normal full screen stack when the top of the stack is a floating window + */ +HWTEST_F(AbilityStackModuleTest, ability_stack_test_035, TestSize.Level1) +{ + EXPECT_CALL(*mockAppMgrClient, LoadAbility(_, _, _, _)) + .Times(AtLeast(2)) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)); + + auto launcherAbilityRequest_ = GenerateAbilityRequest("device", "LauncherAbility", "launcher", "com.ix.hiworld"); + auto ref = stackManager_->StartAbility(launcherAbilityRequest_); + EXPECT_EQ(ERR_OK, ref); + auto topAbilityRecord1 = stackManager_->GetCurrentTopAbility(); + topAbilityRecord1->SetAbilityState(OHOS::AAFwk::ACTIVE); + + // singleton ability + auto radioAbilityRequest = GenerateAbilityRequest("device", "RadioTopAbility", "radio", "com.ix.hiRadio"); + + // float flag + auto abilityStartSetting = AbilityStartSetting::GetEmptySetting(); + EXPECT_TRUE(abilityStartSetting); + abilityStartSetting->AddProperty(AbilityStartSetting::WINDOW_MODE_KEY, + std::to_string(AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_FLOATING)); + + radioAbilityRequest.startSetting = abilityStartSetting; + + ref = stackManager_->StartAbility(radioAbilityRequest); + EXPECT_EQ(ERR_OK, ref); + auto topMissionRecordRadio = stackManager_->GetTopMissionRecord(); + auto topAbilityRecordRadio = stackManager_->GetCurrentTopAbility(); + EXPECT_TRUE(topMissionRecordRadio); + EXPECT_TRUE(topAbilityRecordRadio); + topAbilityRecordRadio->SetAbilityState(OHOS::AAFwk::ACTIVE); + + // start defult ability, put in float stack + auto musicAbilityRequest = GenerateAbilityRequest("device", "MusicAbility", "music", "com.ix.hiMusic"); + ref = stackManager_->StartAbility(musicAbilityRequest); + EXPECT_EQ(ERR_OK, ref); + + auto musicAbility = stackManager_->GetCurrentTopAbility(); + EXPECT_TRUE(musicAbility); + musicAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + EXPECT_EQ(musicAbility->GetMissionStackId(), FLOATING_MISSION_STACK_ID); +} + +/* + * Feature: AaFwk + * Function: StartAbility + * SubFunction: NA + * FunctionPoints: StartAbility by setting info, satrt a Split screen or floating window + * EnvConditions: NA + * CaseDescription: Start a singleton full screen stack when the top of the stack is a floating window + */ +HWTEST_F(AbilityStackModuleTest, ability_stack_test_036, TestSize.Level1) +{ + EXPECT_CALL(*mockAppMgrClient, LoadAbility(_, _, _, _)) + .Times(AtLeast(2)) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)); + + auto launcherAbilityRequest_ = GenerateAbilityRequest("device", "LauncherAbility", "launcher", "com.ix.hiworld"); + auto ref = stackManager_->StartAbility(launcherAbilityRequest_); + EXPECT_EQ(ERR_OK, ref); + auto topAbilityRecord1 = stackManager_->GetCurrentTopAbility(); + topAbilityRecord1->SetAbilityState(OHOS::AAFwk::ACTIVE); + + // singleton ability + auto radioAbilityRequest = GenerateAbilityRequest("device", "RadioTopAbility", "radio", "com.ix.hiRadio"); + + // float flag + auto abilityStartSetting = AbilityStartSetting::GetEmptySetting(); + EXPECT_TRUE(abilityStartSetting); + abilityStartSetting->AddProperty(AbilityStartSetting::WINDOW_MODE_KEY, + std::to_string(AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_FLOATING)); + + radioAbilityRequest.startSetting = abilityStartSetting; + + ref = stackManager_->StartAbility(radioAbilityRequest); + EXPECT_EQ(ERR_OK, ref); + auto topMissionRecordRadio = stackManager_->GetTopMissionRecord(); + auto topAbilityRecordRadio = stackManager_->GetCurrentTopAbility(); + EXPECT_TRUE(topMissionRecordRadio); + EXPECT_TRUE(topAbilityRecordRadio); + topAbilityRecordRadio->SetAbilityState(OHOS::AAFwk::ACTIVE); + + // start defult singleton ability, put in float stack + auto musicTonAbilityRequest = GenerateAbilityRequest("device", "MusicSAbility", "music", "com.ix.hiMusic"); + ref = stackManager_->StartAbility(musicTonAbilityRequest); + EXPECT_EQ(ERR_OK, ref); + auto musicTonMissionRecord = stackManager_->GetTopMissionRecord(); + auto musicTonAbility = stackManager_->GetCurrentTopAbility(); + EXPECT_TRUE(musicTonMissionRecord); + EXPECT_TRUE(musicTonAbility); + musicTonAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + EXPECT_EQ(musicTonMissionRecord->GetMissionStack()->GetMissionStackId(), DEFAULT_MISSION_STACK_ID); +} + +/* + * Feature: AaFwk + * Function: StartAbility + * SubFunction: NA + * FunctionPoints: StartAbility by setting info, satrt a Split screen or floating window + * EnvConditions: NA + * CaseDescription: Start a floating window based on a single column full screen stack + */ +HWTEST_F(AbilityStackModuleTest, ability_stack_test_037, TestSize.Level1) +{ + EXPECT_CALL(*mockAppMgrClient, LoadAbility(_, _, _, _)) + .Times(AtLeast(2)) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)); + + auto launcherAbilityRequest_ = GenerateAbilityRequest("device", "LauncherAbility", "launcher", "com.ix.hiworld"); + auto ref = stackManager_->StartAbility(launcherAbilityRequest_); + EXPECT_EQ(ERR_OK, ref); + auto topAbilityRecord1 = stackManager_->GetCurrentTopAbility(); + topAbilityRecord1->SetAbilityState(OHOS::AAFwk::ACTIVE); + + // start defult singleton ability, put in float stack + auto musicTonAbilityRequest = GenerateAbilityRequest("device", "MusicSAbility", "music", "com.ix.hiMusic"); + ref = stackManager_->StartAbility(musicTonAbilityRequest); + EXPECT_EQ(ERR_OK, ref); + auto musicTonMissionRecord = stackManager_->GetTopMissionRecord(); + auto musicTonAbility = stackManager_->GetCurrentTopAbility(); + EXPECT_TRUE(musicTonMissionRecord); + EXPECT_TRUE(musicTonAbility); + musicTonAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + // singleton ability + auto radioAbilityRequest = GenerateAbilityRequest("device", "RadioAbility", "radio", "com.ix.hiRadio"); + // float flag + auto abilityStartSetting = AbilityStartSetting::GetEmptySetting(); + EXPECT_TRUE(abilityStartSetting); + abilityStartSetting->AddProperty(AbilityStartSetting::WINDOW_MODE_KEY, + std::to_string(AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_FLOATING)); + + radioAbilityRequest.startSetting = abilityStartSetting; + + ref = stackManager_->StartAbility(radioAbilityRequest); + EXPECT_EQ(ERR_OK, ref); + auto topMissionRecordRadio = stackManager_->GetTopMissionRecord(); + auto topAbilityRecordRadio = stackManager_->GetCurrentTopAbility(); + EXPECT_TRUE(topMissionRecordRadio); + EXPECT_TRUE(topAbilityRecordRadio); + topAbilityRecordRadio->SetAbilityState(OHOS::AAFwk::ACTIVE); + + EXPECT_EQ(topMissionRecordRadio->GetMissionStack()->GetMissionStackId(), FLOATING_MISSION_STACK_ID); +} + +/* + * Feature: AaFwk + * Function: MoveMissionToFloatingStack + * SubFunction: Try moving other applications to the floating window stack + * FunctionPoints: + * EnvConditions: NA + * CaseDescription: Move the luncher to the floating window stack + */ +HWTEST_F(AbilityStackModuleTest, ability_stack_test_038, TestSize.Level1) +{ + EXPECT_CALL(*mockAppMgrClient, LoadAbility(_, _, _, _)) + .Times(AtLeast(1)) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)); + + auto launcherAbilityRequest_ = GenerateAbilityRequest("device", "LauncherAbility", "launcher", "com.ix.hiworld"); + auto ref = stackManager_->StartAbility(launcherAbilityRequest_); + EXPECT_EQ(ERR_OK, ref); + auto topAbilityRecord = stackManager_->GetCurrentTopAbility(); + topAbilityRecord->SetAbilityState(OHOS::AAFwk::ACTIVE); + + EXPECT_EQ(topAbilityRecord->GetMissionStackId(), LAUNCHER_MISSION_STACK_ID); + + // move luncher, will fail + MissionOption missionOption; + missionOption.missionId = topAbilityRecord->GetMissionRecordId(); + missionOption.winModeKey = AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_FLOATING; + ref = stackManager_->MoveMissionToFloatingStack(missionOption); + EXPECT_EQ(ref, MOVE_MISSION_TO_STACK_NOT_SUPPORT_MULTI_WIN); + + EXPECT_NE(topAbilityRecord->GetMissionStackId(), FLOATING_MISSION_STACK_ID); +} + +/* + * Feature: AaFwk + * Function: MoveMissionToFloatingStack + * SubFunction: Try moving other applications to the floating window stack + * FunctionPoints: + * EnvConditions: NA + * CaseDescription: Move the defult ability to the floating window stack + */ +HWTEST_F(AbilityStackModuleTest, ability_stack_test_039, TestSize.Level1) +{ + EXPECT_CALL(*mockAppMgrClient, LoadAbility(_, _, _, _)) + .Times(AtLeast(2)) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)); + + auto musicTonAbilityRequest = GenerateAbilityRequest("device", "MusicAbility", "music", "com.ix.hiMusic"); + auto ref = stackManager_->StartAbility(musicTonAbilityRequest); + EXPECT_EQ(ERR_OK, ref); + auto topAbilityRecord = stackManager_->GetCurrentTopAbility(); + EXPECT_TRUE(topAbilityRecord); + topAbilityRecord->SetAbilityState(OHOS::AAFwk::ACTIVE); + + EXPECT_EQ(topAbilityRecord->GetMissionStackId(), DEFAULT_MISSION_STACK_ID); + + MissionOption missionOption; + missionOption.missionId = topAbilityRecord->GetMissionRecordId(); + missionOption.winModeKey = AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_FLOATING; + ref = stackManager_->MoveMissionToFloatingStack(missionOption); + EXPECT_EQ(ref, ERR_OK); + + EXPECT_EQ(topAbilityRecord->GetMissionStackId(), FLOATING_MISSION_STACK_ID); + + // Starting another normal application should start on the floating window stack + auto radioAbilityRequest = GenerateAbilityRequest("device", "RadioAbility", "radio", "com.ix.hiRadio"); + ref = stackManager_->StartAbility(musicTonAbilityRequest); + EXPECT_EQ(ERR_OK, ref); + auto radioAbilityRecord = stackManager_->GetCurrentTopAbility(); + EXPECT_TRUE(radioAbilityRecord); + radioAbilityRecord->SetAbilityState(OHOS::AAFwk::ACTIVE); + + EXPECT_EQ(radioAbilityRecord->GetMissionStackId(), FLOATING_MISSION_STACK_ID); +} + +/* + * Feature: AaFwk + * Function: MoveMissionToFloatingStack + * SubFunction: Try moving other applications to the floating window stack + * FunctionPoints: + * EnvConditions: NA + * CaseDescription: Move a single instance of the common application to the floating window stack + */ +HWTEST_F(AbilityStackModuleTest, ability_stack_test_040, TestSize.Level1) +{ + EXPECT_CALL(*mockAppMgrClient, LoadAbility(_, _, _, _)) + .Times(AtLeast(2)) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)); + + auto musicTonAbilityRequest = GenerateAbilityRequest("device", "MusicSAbility", "music", "com.ix.hiMusic"); + auto ref = stackManager_->StartAbility(musicTonAbilityRequest); + EXPECT_EQ(ERR_OK, ref); + auto topAbilityRecord = stackManager_->GetCurrentTopAbility(); + EXPECT_TRUE(topAbilityRecord); + topAbilityRecord->SetAbilityState(OHOS::AAFwk::ACTIVE); + + EXPECT_EQ(topAbilityRecord->GetMissionStackId(), DEFAULT_MISSION_STACK_ID); + + MissionOption missionOption; + missionOption.missionId = topAbilityRecord->GetMissionRecordId(); + missionOption.winModeKey = AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_FLOATING; + ref = stackManager_->MoveMissionToFloatingStack(missionOption); + EXPECT_EQ(ref, ERR_OK); + + EXPECT_EQ(topAbilityRecord->GetMissionStackId(), FLOATING_MISSION_STACK_ID); + + // Starting another singletop application should start on the floating window stack + auto musicAbilityRequest = GenerateAbilityRequest("device", "MusicTopAbility", "music", "com.ix.hiMusic"); + ref = stackManager_->StartAbility(musicAbilityRequest); + EXPECT_EQ(ERR_OK, ref); + auto radioAbilityRecord = stackManager_->GetCurrentTopAbility(); + EXPECT_TRUE(radioAbilityRecord); + radioAbilityRecord->SetAbilityState(OHOS::AAFwk::ACTIVE); + + // To be discussed + EXPECT_EQ(radioAbilityRecord->GetMissionStackId(), DEFAULT_MISSION_STACK_ID); +} + +/* + * Feature: AaFwk + * Function: MoveMissionToFloatingStack + * SubFunction: Try moving other applications to the floating window stack + * FunctionPoints: + * EnvConditions: NA + * CaseDescription: Move a floating window to the floating window stack + */ +HWTEST_F(AbilityStackModuleTest, ability_stack_test_041, TestSize.Level1) +{ + EXPECT_CALL(*mockAppMgrClient, LoadAbility(_, _, _, _)) + .Times(AtLeast(2)) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)); + + auto launcherAbilityRequest_ = GenerateAbilityRequest("device", "LauncherAbility", "launcher", "com.ix.hiworld"); + auto ref = stackManager_->StartAbility(launcherAbilityRequest_); + EXPECT_EQ(ERR_OK, ref); + auto topAbilityRecord1 = stackManager_->GetCurrentTopAbility(); + topAbilityRecord1->SetAbilityState(OHOS::AAFwk::ACTIVE); + + // singleton ability + auto radioAbilityRequest = GenerateAbilityRequest("device", "RadioTopAbility", "radio", "com.ix.hiRadio"); + + // float flag + auto abilityStartSetting = AbilityStartSetting::GetEmptySetting(); + EXPECT_TRUE(abilityStartSetting); + abilityStartSetting->AddProperty(AbilityStartSetting::WINDOW_MODE_KEY, + std::to_string(AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_FLOATING)); + + radioAbilityRequest.startSetting = abilityStartSetting; + + ref = stackManager_->StartAbility(radioAbilityRequest); + EXPECT_EQ(ERR_OK, ref); + auto topAbilityRecordRadio = stackManager_->GetCurrentTopAbility(); + EXPECT_TRUE(topAbilityRecordRadio); + topAbilityRecordRadio->SetAbilityState(OHOS::AAFwk::ACTIVE); + EXPECT_EQ(topAbilityRecordRadio->GetMissionStackId(), FLOATING_MISSION_STACK_ID); + + // move float window + MissionOption missionOption; + missionOption.missionId = topAbilityRecordRadio->GetMissionRecordId(); + missionOption.winModeKey = AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_FLOATING; + ref = stackManager_->MoveMissionToFloatingStack(missionOption); + EXPECT_EQ(ref, MOVE_MISSION_TO_STACK_NOT_EXIST_MISSION); +} + +/* + * Feature: AaFwk + * Function: MinimizeMultiWindow and MaximizeMultiWindow + * SubFunction: moving other applications to the floating window stack or Full screen stack + * FunctionPoints: + * EnvConditions: NA + * CaseDescription: Move the luncher to the floating window stack + */ +HWTEST_F(AbilityStackModuleTest, ability_stack_test_042, TestSize.Level1) +{ + EXPECT_CALL(*mockAppMgrClient, LoadAbility(_, _, _, _)) + .Times(AtLeast(1)) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)); + + auto launcherAbilityRequest_ = GenerateAbilityRequest("device", "LauncherAbility", "launcher", "com.ix.hiworld"); + auto ref = stackManager_->StartAbility(launcherAbilityRequest_); + EXPECT_EQ(ERR_OK, ref); + auto topAbilityRecord = stackManager_->GetCurrentTopAbility(); + topAbilityRecord->SetAbilityState(OHOS::AAFwk::ACTIVE); + + // try move luncher to float stack + ref = stackManager_->MinimizeMultiWindow(topAbilityRecord->GetMissionRecordId()); + EXPECT_EQ(MINIMIZE_MULTI_WINDOW_FAILED, ref); + ref = stackManager_->MaximizeMultiWindow(topAbilityRecord->GetMissionRecordId()); + EXPECT_EQ(MAXIMIZE_MULTIWINDOW_NOT_EXIST, ref); +} + +/* + * Feature: AaFwk + * Function: MinimizeMultiWindow and MaximizeMultiWindow + * SubFunction: moving other applications to the floating window stack or Full screen stack + * FunctionPoints: + * EnvConditions: NA + * CaseDescription: Move the singleton ability to the floating window stack + */ +HWTEST_F(AbilityStackModuleTest, ability_stack_test_043, TestSize.Level1) +{ + EXPECT_CALL(*mockAppMgrClient, LoadAbility(_, _, _, _)) + .Times(AtLeast(2)) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)); + + auto launcherAbilityRequest_ = GenerateAbilityRequest("device", "LauncherAbility", "launcher", "com.ix.hiworld"); + auto ref = stackManager_->StartAbility(launcherAbilityRequest_); + EXPECT_EQ(ERR_OK, ref); + auto topAbilityRecordlauncher = stackManager_->GetCurrentTopAbility(); + topAbilityRecordlauncher->SetAbilityState(OHOS::AAFwk::ACTIVE); + + auto musicTonAbilityRequest = GenerateAbilityRequest("device", "MusicSAbility", "music", "com.ix.hiMusic"); + ref = stackManager_->StartAbility(musicTonAbilityRequest); + EXPECT_EQ(ERR_OK, ref); + auto topAbilityRecord = stackManager_->GetCurrentTopAbility(); + EXPECT_TRUE(topAbilityRecord); + topAbilityRecord->SetAbilityState(OHOS::AAFwk::ACTIVE); + + MissionOption missionOption; + missionOption.missionId = topAbilityRecord->GetMissionRecordId(); + missionOption.winModeKey = AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_FLOATING; + ref = stackManager_->MoveMissionToFloatingStack(missionOption); + EXPECT_EQ(ref, ERR_OK); + + topAbilityRecord->SetAbilityState(OHOS::AAFwk::ACTIVE); + stackManager_->isMultiWinMoving_ = false; + + // SetScheduler + OHOS::sptr scheduler(new MockAbilityScheduler()); + EXPECT_CALL(*scheduler, AsObject()).WillRepeatedly(Return(nullptr)); + topAbilityRecord->SetScheduler(scheduler); + + EXPECT_CALL(*scheduler, ScheduleAbilityTransaction(testing::_, testing::_)).Times(1); + + OHOS::sptr schedulerluncher(new MockAbilityScheduler()); + EXPECT_CALL(*schedulerluncher, AsObject()).WillRepeatedly(Return(nullptr)); + topAbilityRecordlauncher->SetScheduler(schedulerluncher); + + auto getFocusChangeFlag = [](bool flag) { EXPECT_TRUE(flag); }; + auto loseFocusChangeFlag = [](bool flag) { EXPECT_FALSE(flag); }; + + EXPECT_CALL(*schedulerluncher, NotifyTopActiveAbilityChanged(testing::_)) + .Times(testing::AtLeast(1)) + .WillOnce(testing::Invoke(getFocusChangeFlag)); + + EXPECT_CALL(*scheduler, NotifyTopActiveAbilityChanged(testing::_)) + .Times(testing::AtLeast(1)) + .WillOnce(testing::Invoke(loseFocusChangeFlag)); + + EXPECT_EQ(topAbilityRecord->GetMissionStackId(), FLOATING_MISSION_STACK_ID); + + EXPECT_FALSE(topAbilityRecord->IsToEnd()); + + ref = stackManager_->MinimizeMultiWindow(topAbilityRecord->GetMissionRecordId()); + EXPECT_EQ(ERR_OK, ref); + + EXPECT_TRUE(topAbilityRecord->IsToEnd()); +} + +/* + * Feature: AaFwk + * Function: MinimizeMultiWindow and MaximizeMultiWindow + * SubFunction: moving other applications to the floating window stack or Full screen stack + * FunctionPoints: + * EnvConditions: NA + * CaseDescription: Move the float ability to the defult stack + */ +HWTEST_F(AbilityStackModuleTest, ability_stack_test_044, TestSize.Level1) +{ + EXPECT_CALL(*mockAppMgrClient, LoadAbility(_, _, _, _)) + .Times(AtLeast(1)) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)); + + auto musicTonAbilityRequest = GenerateAbilityRequest("device", "MusicSAbility", "music", "com.ix.hiMusic"); + auto ref = stackManager_->StartAbility(musicTonAbilityRequest); + EXPECT_EQ(ERR_OK, ref); + auto topAbilityRecord = stackManager_->GetCurrentTopAbility(); + EXPECT_TRUE(topAbilityRecord); + topAbilityRecord->SetAbilityState(OHOS::AAFwk::ACTIVE); + + EXPECT_EQ(topAbilityRecord->GetMissionStackId(), DEFAULT_MISSION_STACK_ID); + + MissionOption missionOption; + missionOption.missionId = topAbilityRecord->GetMissionRecordId(); + missionOption.winModeKey = AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_FLOATING; + ref = stackManager_->MoveMissionToFloatingStack(missionOption); + EXPECT_EQ(ref, ERR_OK); + + // SetScheduler + OHOS::sptr scheduler(new MockAbilityScheduler()); + EXPECT_CALL(*scheduler, AsObject()).WillRepeatedly(Return(nullptr)); + topAbilityRecord->SetScheduler(scheduler); + + EXPECT_CALL(*scheduler, NotifyMultiWinModeChanged(testing::_, testing::_)).Times(1); + EXPECT_CALL(*scheduler, NotifyTopActiveAbilityChanged(testing::_)).Times(2); + + EXPECT_EQ(topAbilityRecord->GetMissionStackId(), FLOATING_MISSION_STACK_ID); + + ref = stackManager_->MaximizeMultiWindow(topAbilityRecord->GetMissionRecordId()); + EXPECT_EQ(ERR_OK, ref); + + EXPECT_EQ(topAbilityRecord->GetMissionStackId(), DEFAULT_MISSION_STACK_ID); +} + +/* + * Feature: AaFwk + * Function: MinimizeMultiWindow and MaximizeMultiWindow + * SubFunction: moving other applications to the floating window stack or Full screen stack + * FunctionPoints: + * EnvConditions: NA + * CaseDescription: Operate when there are two floating window + */ +HWTEST_F(AbilityStackModuleTest, ability_stack_test_045, TestSize.Level1) +{ + EXPECT_CALL(*mockAppMgrClient, LoadAbility(_, _, _, _)) + .Times(AtLeast(3)) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)); + + auto launcherAbilityRequest_ = GenerateAbilityRequest("device", "LauncherAbility", "launcher", "com.ix.hiworld"); + auto ref = stackManager_->StartAbility(launcherAbilityRequest_); + EXPECT_EQ(ERR_OK, ref); + auto topAbilityRecord1 = stackManager_->GetCurrentTopAbility(); + topAbilityRecord1->SetAbilityState(OHOS::AAFwk::ACTIVE); + + auto radioAbilityRequest = GenerateAbilityRequest("device", "RadioAbility", "radio", "com.ix.hiRadio"); + // float flag + auto abilityStartSetting = AbilityStartSetting::GetEmptySetting(); + EXPECT_TRUE(abilityStartSetting); + abilityStartSetting->AddProperty(AbilityStartSetting::WINDOW_MODE_KEY, + std::to_string(AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_FLOATING)); + radioAbilityRequest.startSetting = abilityStartSetting; + + ref = stackManager_->StartAbility(radioAbilityRequest); + EXPECT_EQ(ERR_OK, ref); + auto radioAbilityRecord = stackManager_->GetCurrentTopAbility(); + EXPECT_TRUE(radioAbilityRecord); + radioAbilityRecord->SetAbilityState(OHOS::AAFwk::ACTIVE); + + EXPECT_EQ(radioAbilityRecord->GetMissionStackId(), FLOATING_MISSION_STACK_ID); + + auto musicAbilityRequest = GenerateAbilityRequest("device", "MusicAbility", "music", "com.ix.hiMusic"); + ref = stackManager_->StartAbility(musicAbilityRequest); + EXPECT_EQ(ERR_OK, ref); + auto musicAbilityRecord = stackManager_->GetCurrentTopAbility(); + EXPECT_TRUE(musicAbilityRecord); + musicAbilityRecord->SetAbilityState(OHOS::AAFwk::ACTIVE); + radioAbilityRecord->SetAbilityState(OHOS::AAFwk::BACKGROUND); + + EXPECT_EQ(musicAbilityRecord->GetMissionStackId(), FLOATING_MISSION_STACK_ID); + + // SetScheduler + OHOS::sptr scheduler(new MockAbilityScheduler()); + EXPECT_CALL(*scheduler, AsObject()).WillRepeatedly(Return(nullptr)); + radioAbilityRecord->SetScheduler(scheduler); + + // top float ability move to defult stack + ref = stackManager_->MaximizeMultiWindow(radioAbilityRecord->GetMissionRecordId()); + EXPECT_EQ(ERR_OK, ref); + + EXPECT_EQ(musicAbilityRecord->GetMissionStackId(), DEFAULT_MISSION_STACK_ID); +} + +/* + * Feature: AaFwk + * Function: MinimizeMultiWindow and MaximizeMultiWindow + * SubFunction: moving other applications to the floating window stack or Full screen stack + * FunctionPoints: + * EnvConditions: NA + * CaseDescription: When the floating window application calls MinimizeMultiWindow, it will switch to the background + */ +HWTEST_F(AbilityStackModuleTest, ability_stack_test_046, TestSize.Level1) +{ + EXPECT_CALL(*mockAppMgrClient, LoadAbility(_, _, _, _)) + .Times(AtLeast(3)) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)); + + auto launcherAbilityRequest_ = GenerateAbilityRequest("device", "LauncherAbility", "launcher", "com.ix.hiworld"); + auto ref = stackManager_->StartAbility(launcherAbilityRequest_); + EXPECT_EQ(ERR_OK, ref); + auto topAbilityRecordlauncher = stackManager_->GetCurrentTopAbility(); + topAbilityRecordlauncher->SetAbilityState(OHOS::AAFwk::ACTIVE); + + auto radioAbilityRequest = GenerateAbilityRequest("device", "RadioAbility", "radio", "com.ix.hiRadio"); + // float flag + auto abilityStartSetting = AbilityStartSetting::GetEmptySetting(); + EXPECT_TRUE(abilityStartSetting); + abilityStartSetting->AddProperty(AbilityStartSetting::WINDOW_MODE_KEY, + std::to_string(AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_FLOATING)); + radioAbilityRequest.startSetting = abilityStartSetting; + + ref = stackManager_->StartAbility(radioAbilityRequest); + EXPECT_EQ(ERR_OK, ref); + auto radioAbilityRecord = stackManager_->GetCurrentTopAbility(); + EXPECT_TRUE(radioAbilityRecord); + radioAbilityRecord->SetAbilityState(OHOS::AAFwk::ACTIVE); + + EXPECT_EQ(radioAbilityRecord->GetMissionStackId(), FLOATING_MISSION_STACK_ID); + + auto musicAbilityRequest = GenerateAbilityRequest("device", "MusicAbility", "music", "com.ix.hiMusic"); + ref = stackManager_->StartAbility(musicAbilityRequest); + EXPECT_EQ(ERR_OK, ref); + auto musicAbilityRecord = stackManager_->GetCurrentTopAbility(); + EXPECT_TRUE(musicAbilityRecord); + musicAbilityRecord->SetAbilityState(OHOS::AAFwk::ACTIVE); + radioAbilityRecord->SetAbilityState(OHOS::AAFwk::BACKGROUND); + + EXPECT_EQ(musicAbilityRecord->GetMissionStackId(), FLOATING_MISSION_STACK_ID); + + // SetScheduler + OHOS::sptr scheduler(new MockAbilityScheduler()); + EXPECT_CALL(*scheduler, AsObject()).WillRepeatedly(Return(nullptr)); + musicAbilityRecord->SetScheduler(scheduler); + + EXPECT_CALL(*scheduler, ScheduleAbilityTransaction(testing::_, testing::_)).Times(1); + + OHOS::sptr schedulerluncher(new MockAbilityScheduler()); + EXPECT_CALL(*schedulerluncher, AsObject()).WillRepeatedly(Return(nullptr)); + topAbilityRecordlauncher->SetScheduler(schedulerluncher); + + auto getFocusChangeFlag = [](bool flag) { EXPECT_TRUE(flag); }; + auto loseFocusChangeFlag = [](bool flag) { EXPECT_FALSE(flag); }; + + EXPECT_CALL(*schedulerluncher, NotifyTopActiveAbilityChanged(testing::_)) + .Times(testing::AtLeast(1)) + .WillOnce(testing::Invoke(getFocusChangeFlag)); + + EXPECT_CALL(*scheduler, NotifyTopActiveAbilityChanged(testing::_)) + .Times(testing::AtLeast(1)) + .WillOnce(testing::Invoke(loseFocusChangeFlag)); + + EXPECT_FALSE(musicAbilityRecord->IsToEnd()); + + ref = stackManager_->MinimizeMultiWindow(radioAbilityRecord->GetMissionRecordId()); + EXPECT_EQ(ERR_OK, ref); + + EXPECT_TRUE(musicAbilityRecord->IsToEnd()); +} + +/* + * Feature: AaFwk + * Function:ChangeFocusAbility + * SubFunction: Change the focus state of two active states + * FunctionPoints: + * EnvConditions: NA + * CaseDescription:Switch from the focus of the floating window to the luncher + */ +HWTEST_F(AbilityStackModuleTest, ability_stack_test_047, TestSize.Level1) +{ + EXPECT_CALL(*mockAppMgrClient, LoadAbility(_, _, _, _)) + .Times(AtLeast(2)) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)); + + auto launcherAbilityRequest_ = GenerateAbilityRequest("device", "LauncherAbility", "launcher", "com.ix.hiworld"); + auto ref = stackManager_->StartAbility(launcherAbilityRequest_); + EXPECT_EQ(ERR_OK, ref); + auto topAbilityRecordLuncher = stackManager_->GetCurrentTopAbility(); + EXPECT_TRUE(topAbilityRecordLuncher); + stackManager_->CompleteActive(topAbilityRecordLuncher); + + auto radioAbilityRequest = GenerateAbilityRequest("device", "RadioAbility", "radio", "com.ix.hiRadio"); + // float flag + auto abilityStartSetting = AbilityStartSetting::GetEmptySetting(); + EXPECT_TRUE(abilityStartSetting); + abilityStartSetting->AddProperty(AbilityStartSetting::WINDOW_MODE_KEY, + std::to_string(AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_FLOATING)); + radioAbilityRequest.startSetting = abilityStartSetting; + + ref = stackManager_->StartAbility(radioAbilityRequest); + EXPECT_EQ(ERR_OK, ref); + auto topAbilityRecordRadio = stackManager_->GetCurrentTopAbility(); + EXPECT_TRUE(topAbilityRecordRadio); + stackManager_->CompleteActive(topAbilityRecordRadio); + + // set luncher scheduler + OHOS::sptr schedulerluncher(new MockAbilityScheduler()); + EXPECT_CALL(*schedulerluncher, AsObject()).WillRepeatedly(Return(nullptr)); + topAbilityRecordLuncher->SetScheduler(schedulerluncher); + + auto getFocusChangeFlag = [](bool flag) { EXPECT_TRUE(flag); }; + auto loseFocusChangeFlag = [](bool flag) { EXPECT_FALSE(flag); }; + + EXPECT_CALL(*schedulerluncher, NotifyTopActiveAbilityChanged(testing::_)) + .Times(testing::AtLeast(1)) + .WillOnce(testing::Invoke(getFocusChangeFlag)); + + // set float windows scheduler + OHOS::sptr scheduler(new MockAbilityScheduler()); + EXPECT_CALL(*scheduler, AsObject()).WillRepeatedly(Return(nullptr)); + topAbilityRecordRadio->SetScheduler(scheduler); + + EXPECT_CALL(*scheduler, NotifyTopActiveAbilityChanged(testing::_)) + .Times(testing::AtLeast(1)) + .WillOnce(testing::Invoke(loseFocusChangeFlag)); + + // make sure both are active + topAbilityRecordLuncher->SetAbilityState(OHOS::AAFwk::ACTIVE); + topAbilityRecordRadio->SetAbilityState(OHOS::AAFwk::ACTIVE); + // luncher get the focus + ref = stackManager_->ChangeFocusAbility(topAbilityRecordRadio->GetToken(), topAbilityRecordLuncher->GetToken()); + EXPECT_EQ(ERR_OK, ref); +} + +/* + * Feature: AaFwk + * Function:ChangeFocusAbility + * SubFunction: Change the focus state of two active states + * FunctionPoints: + * EnvConditions: NA + * CaseDescription:Switch focus between two floating windows + */ +HWTEST_F(AbilityStackModuleTest, ability_stack_test_048, TestSize.Level1) +{ + EXPECT_CALL(*mockAppMgrClient, LoadAbility(_, _, _, _)) + .Times(AtLeast(2)) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)); + + auto launcherAbilityRequest_ = GenerateAbilityRequest("device", "LauncherAbility", "launcher", "com.ix.hiworld"); + auto ref = stackManager_->StartAbility(launcherAbilityRequest_); + EXPECT_EQ(ERR_OK, ref); + auto topAbilityRecordLuncher = stackManager_->GetCurrentTopAbility(); + EXPECT_TRUE(topAbilityRecordLuncher); + stackManager_->CompleteActive(topAbilityRecordLuncher); + + auto radioAbilityRequest = GenerateAbilityRequest("device", "RadioAbility", "radio", "com.ix.hiRadio"); + // float flag + auto abilityStartSetting = AbilityStartSetting::GetEmptySetting(); + EXPECT_TRUE(abilityStartSetting); + abilityStartSetting->AddProperty(AbilityStartSetting::WINDOW_MODE_KEY, + std::to_string(AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_FLOATING)); + radioAbilityRequest.startSetting = abilityStartSetting; + + ref = stackManager_->StartAbility(radioAbilityRequest); + EXPECT_EQ(ERR_OK, ref); + auto topAbilityRecordRadio = stackManager_->GetCurrentTopAbility(); + EXPECT_TRUE(topAbilityRecordRadio); + stackManager_->CompleteActive(topAbilityRecordRadio); + + // in float stact + auto musicAbilityRequest = GenerateAbilityRequest("device", "MusicAbility", "music", "com.ix.hiMusic"); + ref = stackManager_->StartAbility(musicAbilityRequest); + EXPECT_EQ(ERR_OK, ref); + auto musicAbilityRecord = stackManager_->GetCurrentTopAbility(); + EXPECT_TRUE(musicAbilityRecord); + stackManager_->CompleteActive(musicAbilityRecord); + + // Make sure to start in the floating window stack + EXPECT_EQ(musicAbilityRecord->GetMissionStackId(), FLOATING_MISSION_STACK_ID); + EXPECT_EQ(topAbilityRecordRadio->GetMissionStackId(), FLOATING_MISSION_STACK_ID); + + // set MusicAbility scheduler + OHOS::sptr schedulerMusic(new MockAbilityScheduler()); + EXPECT_CALL(*schedulerMusic, AsObject()).WillRepeatedly(Return(nullptr)); + musicAbilityRecord->SetScheduler(schedulerMusic); + + auto loseFocusChangeFlag = [](bool flag) { EXPECT_FALSE(flag); }; + auto getFocusChangeFlag = [](bool flag) { EXPECT_TRUE(flag); }; + + EXPECT_CALL(*schedulerMusic, NotifyTopActiveAbilityChanged(testing::_)) + .Times(testing::AtLeast(1)) + .WillOnce(testing::Invoke(loseFocusChangeFlag)); + + // set RadioAbility scheduler + OHOS::sptr scheduler(new MockAbilityScheduler()); + EXPECT_CALL(*scheduler, AsObject()).WillRepeatedly(Return(nullptr)); + topAbilityRecordRadio->SetScheduler(scheduler); + + EXPECT_CALL(*scheduler, NotifyTopActiveAbilityChanged(testing::_)) + .Times(testing::AtLeast(1)) + .WillOnce(testing::Invoke(getFocusChangeFlag)); + + // make sure both are active + musicAbilityRecord->SetAbilityState(OHOS::AAFwk::ACTIVE); + topAbilityRecordRadio->SetAbilityState(OHOS::AAFwk::ACTIVE); + // RadioAbility get the focus + ref = stackManager_->ChangeFocusAbility(musicAbilityRecord->GetToken(), topAbilityRecordRadio->GetToken()); + EXPECT_EQ(ERR_OK, ref); +} + +/* + * Feature: AaFwk + * Function:ChangeFocusAbility + * SubFunction: Change the focus state of two active states + * FunctionPoints: + * EnvConditions: NA + * CaseDescription:The application of floating window gets the focus + */ +HWTEST_F(AbilityStackModuleTest, ability_stack_test_049, TestSize.Level1) +{ + EXPECT_CALL(*mockAppMgrClient, LoadAbility(_, _, _, _)) + .Times(AtLeast(2)) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)); + + auto launcherAbilityRequest_ = GenerateAbilityRequest("device", "LauncherAbility", "launcher", "com.ix.hiworld"); + auto ref = stackManager_->StartAbility(launcherAbilityRequest_); + EXPECT_EQ(ERR_OK, ref); + auto topAbilityRecordLuncher = stackManager_->GetCurrentTopAbility(); + EXPECT_TRUE(topAbilityRecordLuncher); + stackManager_->CompleteActive(topAbilityRecordLuncher); + + auto radioAbilityRequest = GenerateAbilityRequest("device", "RadioAbility", "radio", "com.ix.hiRadio"); + // float flag + auto abilityStartSetting = AbilityStartSetting::GetEmptySetting(); + EXPECT_TRUE(abilityStartSetting); + abilityStartSetting->AddProperty(AbilityStartSetting::WINDOW_MODE_KEY, + std::to_string(AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_FLOATING)); + radioAbilityRequest.startSetting = abilityStartSetting; + + ref = stackManager_->StartAbility(radioAbilityRequest); + EXPECT_EQ(ERR_OK, ref); + auto topAbilityRecordRadio = stackManager_->GetCurrentTopAbility(); + EXPECT_TRUE(topAbilityRecordRadio); + stackManager_->CompleteActive(topAbilityRecordRadio); + + // set luncher scheduler + OHOS::sptr schedulerluncher(new MockAbilityScheduler()); + EXPECT_CALL(*schedulerluncher, AsObject()).WillRepeatedly(Return(nullptr)); + topAbilityRecordLuncher->SetScheduler(schedulerluncher); + + auto getFocusChangeFlag = [](bool flag) { EXPECT_TRUE(flag); }; + auto loseFocusChangeFlag = [](bool flag) { EXPECT_FALSE(flag); }; + + EXPECT_CALL(*schedulerluncher, NotifyTopActiveAbilityChanged(testing::_)) + .Times(testing::AtLeast(1)) + .WillOnce(testing::Invoke(getFocusChangeFlag)) + .WillOnce(testing::Invoke(loseFocusChangeFlag)); + + // set float windows scheduler + OHOS::sptr scheduler(new MockAbilityScheduler()); + EXPECT_CALL(*scheduler, AsObject()).WillRepeatedly(Return(nullptr)); + topAbilityRecordRadio->SetScheduler(scheduler); + + EXPECT_CALL(*scheduler, NotifyTopActiveAbilityChanged(testing::_)) + .Times(testing::AtLeast(1)) + .WillOnce(testing::Invoke(loseFocusChangeFlag)) + .WillOnce(testing::Invoke(getFocusChangeFlag)); + + // make sure both are active + topAbilityRecordLuncher->SetAbilityState(OHOS::AAFwk::ACTIVE); + topAbilityRecordRadio->SetAbilityState(OHOS::AAFwk::ACTIVE); + // luncher get the focus + ref = stackManager_->ChangeFocusAbility(topAbilityRecordRadio->GetToken(), topAbilityRecordLuncher->GetToken()); + EXPECT_EQ(ERR_OK, ref); + + // make sure both are active + topAbilityRecordLuncher->SetAbilityState(OHOS::AAFwk::ACTIVE); + topAbilityRecordRadio->SetAbilityState(OHOS::AAFwk::ACTIVE); + // Click the floating window again to get the focus + ref = stackManager_->ChangeFocusAbility(topAbilityRecordLuncher->GetToken(), topAbilityRecordRadio->GetToken()); + EXPECT_EQ(ERR_OK, ref); +} + +/* + * Feature: AaFwk + * Function:GetFloatingMissions + * SubFunction: Get the information of floating window application + * FunctionPoints: + * EnvConditions: NA + * CaseDescription:Get the information of floating window application.. + */ +HWTEST_F(AbilityStackModuleTest, ability_stack_test_050, TestSize.Level1) +{ + EXPECT_CALL(*mockAppMgrClient, LoadAbility(_, _, _, _)) + .Times(AtLeast(1)) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)); + + auto musicAbilityRequest = GenerateAbilityRequest("device", "MusicAbility", "music", "com.ix.hiMusic"); + auto ref = stackManager_->StartAbility(musicAbilityRequest); + EXPECT_EQ(ERR_OK, ref); + auto topAbilityRecord = stackManager_->GetCurrentTopAbility(); + EXPECT_TRUE(topAbilityRecord); + topAbilityRecord->SetAbilityState(OHOS::AAFwk::ACTIVE); + + EXPECT_EQ(topAbilityRecord->GetMissionStackId(), DEFAULT_MISSION_STACK_ID); + + MissionOption missionOption; + missionOption.missionId = topAbilityRecord->GetMissionRecordId(); + missionOption.winModeKey = AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_FLOATING; + ref = stackManager_->MoveMissionToFloatingStack(missionOption); + EXPECT_EQ(ref, ERR_OK); + + EXPECT_EQ(topAbilityRecord->GetMissionStackId(), FLOATING_MISSION_STACK_ID); + + // Starting another singletop application should start on the floating window stack + auto musicTopAbilityRequest = GenerateAbilityRequest("device", "MusicTopAbility", "music", "com.ix.hiMusic"); + ref = stackManager_->StartAbility(musicTopAbilityRequest); + EXPECT_EQ(ERR_OK, ref); + auto musicAbilityRecord = stackManager_->GetCurrentTopAbility(); + EXPECT_TRUE(musicAbilityRecord); + musicAbilityRecord->SetAbilityState(OHOS::AAFwk::ACTIVE); + + EXPECT_EQ(musicAbilityRecord->GetMissionStackId(), FLOATING_MISSION_STACK_ID); + + // get missions + std::vector list; + stackManager_->GetFloatingMissions(list); + int size = list.size(); + EXPECT_EQ(size, 1); + + AbilityMissionInfo info = list.front(); + EXPECT_EQ(info.baseAbility.abilityName_, "MusicAbility"); + EXPECT_EQ(info.topAbility.abilityName_, "MusicTopAbility"); +} + +/* + * Feature: AaFwk + * Function:GetFloatingMissions + * SubFunction: Get the information of floating window application + * FunctionPoints: + * EnvConditions: NA + * CaseDescription:Get the information of floating window application + */ +HWTEST_F(AbilityStackModuleTest, ability_stack_test_051, TestSize.Level1) +{ + EXPECT_CALL(*mockAppMgrClient, LoadAbility(_, _, _, _)) + .Times(AtLeast(1)) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)); + + auto musicTonAbilityRequest = GenerateAbilityRequest("device", "MusicAbility", "music", "com.ix.hiMusic"); + auto ref = stackManager_->StartAbility(musicTonAbilityRequest); + EXPECT_EQ(ERR_OK, ref); + auto topAbilityRecord = stackManager_->GetCurrentTopAbility(); + EXPECT_TRUE(topAbilityRecord); + topAbilityRecord->SetAbilityState(OHOS::AAFwk::ACTIVE); + + EXPECT_EQ(topAbilityRecord->GetMissionStackId(), DEFAULT_MISSION_STACK_ID); + + MissionOption missionOption; + missionOption.missionId = topAbilityRecord->GetMissionRecordId(); + missionOption.winModeKey = AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_FLOATING; + ref = stackManager_->MoveMissionToFloatingStack(missionOption); + EXPECT_EQ(ref, ERR_OK); + + EXPECT_EQ(topAbilityRecord->GetMissionStackId(), FLOATING_MISSION_STACK_ID); + + // Starting another singletop application should start on the floating window stack + auto musicAbilityRequest = GenerateAbilityRequest("device", "MusicTopAbility", "music", "com.ix.hiMusic"); + ref = stackManager_->StartAbility(musicAbilityRequest); + EXPECT_EQ(ERR_OK, ref); + auto musicAbilityRecord = stackManager_->GetCurrentTopAbility(); + EXPECT_TRUE(musicAbilityRecord); + musicAbilityRecord->SetAbilityState(OHOS::AAFwk::ACTIVE); + + EXPECT_EQ(musicAbilityRecord->GetMissionStackId(), FLOATING_MISSION_STACK_ID); + + std::vector list; + stackManager_->GetFloatingMissions(list); + int size = list.size(); + EXPECT_EQ(size, 1); + + AbilityMissionInfo info = list.front(); + EXPECT_EQ(info.baseAbility.abilityName_, "MusicAbility"); + EXPECT_EQ(info.topAbility.abilityName_, "MusicTopAbility"); +} + +/* + * Feature: AaFwk + * Function:GetFloatingMissions + * SubFunction: Get the information of floating window application + * FunctionPoints: + * EnvConditions: NA + * CaseDescription:Get the information of floating window application + */ +HWTEST_F(AbilityStackModuleTest, ability_stack_test_052, TestSize.Level1) +{ + EXPECT_CALL(*mockAppMgrClient, LoadAbility(_, _, _, _)) + .Times(AtLeast(1)) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)); + + auto musicTonAbilityRequest = GenerateAbilityRequest("device", "MusicAbility", "music", "com.ix.hiMusic"); + auto ref = stackManager_->StartAbility(musicTonAbilityRequest); + EXPECT_EQ(ERR_OK, ref); + auto topAbilityRecord = stackManager_->GetCurrentTopAbility(); + EXPECT_TRUE(topAbilityRecord); + topAbilityRecord->SetAbilityState(OHOS::AAFwk::ACTIVE); + + EXPECT_EQ(topAbilityRecord->GetMissionStackId(), DEFAULT_MISSION_STACK_ID); + + MissionOption missionOption; + missionOption.missionId = topAbilityRecord->GetMissionRecordId(); + missionOption.winModeKey = AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_FLOATING; + ref = stackManager_->MoveMissionToFloatingStack(missionOption); + EXPECT_EQ(ref, ERR_OK); + + EXPECT_EQ(topAbilityRecord->GetMissionStackId(), FLOATING_MISSION_STACK_ID); + + // Starting another singletop application should start on the floating window stack + auto musicAbilityRequest = GenerateAbilityRequest("device", "MusicTopAbility", "music", "com.ix.hiMusic"); + ref = stackManager_->StartAbility(musicAbilityRequest); + EXPECT_EQ(ERR_OK, ref); + auto musicAbilityRecord = stackManager_->GetCurrentTopAbility(); + EXPECT_TRUE(musicAbilityRecord); + musicAbilityRecord->SetAbilityState(OHOS::AAFwk::ACTIVE); + + EXPECT_EQ(musicAbilityRecord->GetMissionStackId(), FLOATING_MISSION_STACK_ID); + + auto radioAbilityRequest = GenerateAbilityRequest("device", "RadioAbility", "radio", "com.ix.hiRadio"); + ref = stackManager_->StartAbility(radioAbilityRequest); + EXPECT_EQ(ERR_OK, ref); + auto radioAbilityRecord = stackManager_->GetCurrentTopAbility(); + EXPECT_TRUE(radioAbilityRecord); + radioAbilityRecord->SetAbilityState(OHOS::AAFwk::ACTIVE); + + EXPECT_EQ(radioAbilityRecord->GetMissionStackId(), FLOATING_MISSION_STACK_ID); + + std::vector list; + stackManager_->GetFloatingMissions(list); + int size = list.size(); + EXPECT_EQ(size, 1); + + AbilityMissionInfo info = list.front(); + EXPECT_EQ(info.baseAbility.abilityName_, "MusicAbility"); + EXPECT_EQ(info.topAbility.abilityName_, "RadioAbility"); +} + +/* + * Feature: AaFwk + * Function:GetFloatingMissions + * SubFunction: Get the information of floating window application + * FunctionPoints: + * EnvConditions: NA + * CaseDescription:Get the information of floating window application + */ +HWTEST_F(AbilityStackModuleTest, ability_stack_test_053, TestSize.Level1) +{ + EXPECT_CALL(*mockAppMgrClient, LoadAbility(_, _, _, _)) + .Times(AtLeast(2)) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)); + + auto launcherAbilityRequest_ = GenerateAbilityRequest("device", "LauncherAbility", "launcher", "com.ix.hiworld"); + auto ref = stackManager_->StartAbility(launcherAbilityRequest_); + EXPECT_EQ(ERR_OK, ref); + auto topAbilityRecordLuncher = stackManager_->GetCurrentTopAbility(); + EXPECT_TRUE(topAbilityRecordLuncher); + topAbilityRecordLuncher->SetAbilityState(OHOS::AAFwk::ACTIVE); + + auto radioAbilityRequest = GenerateAbilityRequest("device", "RadioAbility", "radio", "com.ix.hiRadio"); + // float flag + auto abilityStartSetting = AbilityStartSetting::GetEmptySetting(); + EXPECT_TRUE(abilityStartSetting); + abilityStartSetting->AddProperty(AbilityStartSetting::WINDOW_MODE_KEY, + std::to_string(AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_FLOATING)); + radioAbilityRequest.startSetting = abilityStartSetting; + + ref = stackManager_->StartAbility(radioAbilityRequest); + EXPECT_EQ(ERR_OK, ref); + auto topAbilityRecordRadio = stackManager_->GetCurrentTopAbility(); + EXPECT_TRUE(topAbilityRecordRadio); + topAbilityRecordRadio->SetAbilityState(OHOS::AAFwk::ACTIVE); + + std::vector list; + stackManager_->GetFloatingMissions(list); + int size = list.size(); + EXPECT_EQ(size, 1); + + AbilityMissionInfo info = list.front(); + EXPECT_EQ(info.topAbility.abilityName_, "RadioAbility"); + EXPECT_EQ(info.baseAbility.abilityName_, "RadioAbility"); +} + +/* + * Feature: AaFwk + * Function:RemoveMissionById + * SubFunction: delete mission by id + * FunctionPoints: + * EnvConditions: NA + * CaseDescription: 01 + */ +HWTEST_F(AbilityStackModuleTest, ability_stack_test_054, TestSize.Level1) +{ + EXPECT_CALL(*mockAppMgrClient, LoadAbility(_, _, _, _)) + .Times(AtLeast(2)) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)); + + auto launcherAbilityRequest_ = GenerateAbilityRequest("device", "LauncherAbility", "launcher", "com.ix.hiworld"); + auto ref = stackManager_->StartAbility(launcherAbilityRequest_); + EXPECT_EQ(ERR_OK, ref); + auto topAbilityRecordLuncher = stackManager_->GetCurrentTopAbility(); + EXPECT_TRUE(topAbilityRecordLuncher); + topAbilityRecordLuncher->SetAbilityState(OHOS::AAFwk::ACTIVE); + + auto music1AbilityRequest_ = GenerateAbilityRequest("device", "MusicAbility", "music", "com.ix.hiMusic"); + stackManager_->StartAbility(music1AbilityRequest_); + auto firstTopAbility = stackManager_->GetCurrentTopAbility(); + firstTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + auto music2AbilityRequest_ = GenerateAbilityRequest("device", "MusicAbility2", "music", "com.ix.hiMusic"); + stackManager_->StartAbility(music2AbilityRequest_); + auto secondTopAbility = stackManager_->GetCurrentTopAbility(); + secondTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + auto radioAbilityRequest = GenerateAbilityRequest("device", "RadioSAbility", "radio", "com.ix.hiRadio"); + // float flag + auto abilityStartSetting = AbilityStartSetting::GetEmptySetting(); + EXPECT_TRUE(abilityStartSetting); + abilityStartSetting->AddProperty(AbilityStartSetting::WINDOW_MODE_KEY, + std::to_string(AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_FLOATING)); + radioAbilityRequest.startSetting = abilityStartSetting; + + ref = stackManager_->StartAbility(radioAbilityRequest); + EXPECT_EQ(ERR_OK, ref); + auto topAbilityRecordRadio = stackManager_->GetCurrentTopAbility(); + EXPECT_TRUE(topAbilityRecordRadio); + topAbilityRecordRadio->SetAbilityState(OHOS::AAFwk::ACTIVE); + + GTEST_LOG_(INFO) << "firstTopAbility :" << firstTopAbility->GetMissionRecordId(); + GTEST_LOG_(INFO) << "secondTopAbility :" << secondTopAbility->GetMissionRecordId(); + GTEST_LOG_(INFO) << "topAbilityRecordRadio :" << topAbilityRecordRadio->GetMissionRecordId(); + + EXPECT_EQ(topAbilityRecordLuncher->GetMissionStackId(), LAUNCHER_MISSION_STACK_ID); + EXPECT_EQ(firstTopAbility->GetMissionStackId(), DEFAULT_MISSION_STACK_ID); + EXPECT_EQ(secondTopAbility->GetMissionStackId(), DEFAULT_MISSION_STACK_ID); + EXPECT_EQ(topAbilityRecordRadio->GetMissionStackId(), FLOATING_MISSION_STACK_ID); + + auto missionID = firstTopAbility->GetMissionRecordId(); + ref = stackManager_->RemoveMissionById(missionID); + EXPECT_EQ(ERR_OK, ref); + + auto missionRecord = stackManager_->GetMissionRecordById(missionID); + EXPECT_TRUE(missionRecord == nullptr); + + // luncher stack move to top + auto currentStack = stackManager_->GetCurrentMissionStack(); + EXPECT_TRUE(currentStack != nullptr); + EXPECT_EQ(currentStack->GetMissionStackId(), LAUNCHER_MISSION_STACK_ID); +} + +/* + * Feature: AaFwk + * Function:OnAbilityDied + * SubFunction: ability died + * FunctionPoints: + * EnvConditions: NA + * CaseDescription:02 + */ +HWTEST_F(AbilityStackModuleTest, ability_stack_test_055, TestSize.Level1) +{ + EXPECT_CALL(*mockAppMgrClient, LoadAbility(_, _, _, _)) + .Times(AtLeast(2)) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)); + + auto launcherAbilityRequest_ = GenerateAbilityRequest("device", "LauncherAbility", "launcher", "com.ix.hiworld"); + auto ref = stackManager_->StartAbility(launcherAbilityRequest_); + EXPECT_EQ(ERR_OK, ref); + auto topAbilityRecordLuncher = stackManager_->GetCurrentTopAbility(); + EXPECT_TRUE(topAbilityRecordLuncher); + topAbilityRecordLuncher->SetAbilityState(OHOS::AAFwk::ACTIVE); + + auto music1AbilityRequest_ = GenerateAbilityRequest("device", "MusicAbility", "music", "com.ix.hiMusic"); + stackManager_->StartAbility(music1AbilityRequest_); + auto firstTopAbility = stackManager_->GetCurrentTopAbility(); + firstTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + auto music2AbilityRequest_ = GenerateAbilityRequest("device", "MusicAbility2", "music", "com.ix.hiMusic"); + stackManager_->StartAbility(music2AbilityRequest_); + auto secondTopAbility = stackManager_->GetCurrentTopAbility(); + secondTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + auto radioAbilityRequest = GenerateAbilityRequest("device", "RadioSAbility", "radio", "com.ix.hiRadio"); + // float flag + auto abilityStartSetting = AbilityStartSetting::GetEmptySetting(); + EXPECT_TRUE(abilityStartSetting); + abilityStartSetting->AddProperty(AbilityStartSetting::WINDOW_MODE_KEY, + std::to_string(AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_FLOATING)); + radioAbilityRequest.startSetting = abilityStartSetting; + + ref = stackManager_->StartAbility(radioAbilityRequest); + EXPECT_EQ(ERR_OK, ref); + auto topAbilityRecordRadio = stackManager_->GetCurrentTopAbility(); + EXPECT_TRUE(topAbilityRecordRadio); + topAbilityRecordRadio->SetAbilityState(OHOS::AAFwk::ACTIVE); + + GTEST_LOG_(INFO) << "firstTopAbility :" << firstTopAbility->GetMissionRecordId(); + GTEST_LOG_(INFO) << "secondTopAbility :" << secondTopAbility->GetMissionRecordId(); + GTEST_LOG_(INFO) << "topAbilityRecordRadio :" << topAbilityRecordRadio->GetMissionRecordId(); + + topAbilityRecordLuncher->SetAbilityState(OHOS::AAFwk::BACKGROUND); + firstTopAbility->SetAbilityState(OHOS::AAFwk::BACKGROUND); + secondTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + EXPECT_EQ(topAbilityRecordLuncher->GetMissionStackId(), LAUNCHER_MISSION_STACK_ID); + EXPECT_EQ(firstTopAbility->GetMissionStackId(), DEFAULT_MISSION_STACK_ID); + EXPECT_EQ(secondTopAbility->GetMissionStackId(), DEFAULT_MISSION_STACK_ID); + EXPECT_EQ(topAbilityRecordRadio->GetMissionStackId(), FLOATING_MISSION_STACK_ID); + + // let ability died + stackManager_->OnAbilityDied(firstTopAbility); + + EXPECT_TRUE(secondTopAbility != nullptr); + EXPECT_EQ(firstTopAbility->GetAbilityState(), OHOS::AAFwk::INITIAL); +} + +/* + * Feature: AaFwk + * Function:OnAbilityDied + * SubFunction: ability died + * FunctionPoints: + * EnvConditions: NA + * CaseDescription:03 Delete the defult stack and pull it up again + */ +HWTEST_F(AbilityStackModuleTest, ability_stack_test_056, TestSize.Level1) +{ + EXPECT_CALL(*mockAppMgrClient, LoadAbility(_, _, _, _)) + .Times(AtLeast(2)) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)); + + auto launcherAbilityRequest_ = GenerateAbilityRequest("device", "LauncherAbility", "launcher", "com.ix.hiworld"); + auto ref = stackManager_->StartAbility(launcherAbilityRequest_); + EXPECT_EQ(ERR_OK, ref); + auto topAbilityRecordLuncher = stackManager_->GetCurrentTopAbility(); + EXPECT_TRUE(topAbilityRecordLuncher); + topAbilityRecordLuncher->SetAbilityState(OHOS::AAFwk::ACTIVE); + + auto music1AbilityRequest_ = GenerateAbilityRequest("device", "MusicAbility", "music", "com.ix.hiMusic"); + stackManager_->StartAbility(music1AbilityRequest_); + auto firstTopAbility = stackManager_->GetCurrentTopAbility(); + firstTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + auto music2AbilityRequest_ = GenerateAbilityRequest("device", "MusicAbility2", "music", "com.ix.hiMusic"); + stackManager_->StartAbility(music2AbilityRequest_); + auto secondTopAbility = stackManager_->GetCurrentTopAbility(); + secondTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + auto radioAbilityRequest = GenerateAbilityRequest("device", "RadioSAbility", "radio", "com.ix.hiRadio"); + // float flag + auto abilityStartSetting = AbilityStartSetting::GetEmptySetting(); + EXPECT_TRUE(abilityStartSetting); + abilityStartSetting->AddProperty(AbilityStartSetting::WINDOW_MODE_KEY, + std::to_string(AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_FLOATING)); + radioAbilityRequest.startSetting = abilityStartSetting; + + ref = stackManager_->StartAbility(radioAbilityRequest); + EXPECT_EQ(ERR_OK, ref); + auto topAbilityRecordRadio = stackManager_->GetCurrentTopAbility(); + EXPECT_TRUE(topAbilityRecordRadio); + topAbilityRecordRadio->SetAbilityState(OHOS::AAFwk::ACTIVE); + + GTEST_LOG_(INFO) << "firstTopAbility :" << firstTopAbility->GetMissionRecordId(); + GTEST_LOG_(INFO) << "secondTopAbility :" << secondTopAbility->GetMissionRecordId(); + GTEST_LOG_(INFO) << "topAbilityRecordRadio :" << topAbilityRecordRadio->GetMissionRecordId(); + + topAbilityRecordLuncher->SetAbilityState(OHOS::AAFwk::BACKGROUND); + firstTopAbility->SetAbilityState(OHOS::AAFwk::BACKGROUND); + secondTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + EXPECT_EQ(topAbilityRecordLuncher->GetMissionStackId(), LAUNCHER_MISSION_STACK_ID); + EXPECT_EQ(firstTopAbility->GetMissionStackId(), DEFAULT_MISSION_STACK_ID); + EXPECT_EQ(secondTopAbility->GetMissionStackId(), DEFAULT_MISSION_STACK_ID); + EXPECT_EQ(topAbilityRecordRadio->GetMissionStackId(), FLOATING_MISSION_STACK_ID); + + OHOS::sptr scheduler(new MockAbilityScheduler()); + EXPECT_CALL(*scheduler, AsObject()).WillRepeatedly(Return(nullptr)); + firstTopAbility->SetScheduler(scheduler); + + EXPECT_CALL(*scheduler, ScheduleRestoreAbilityState(testing::_)).Times(testing::AtLeast(1)); + EXPECT_CALL(*scheduler, ScheduleAbilityTransaction(testing::_, testing::_)).Times(1); + // let ability died + stackManager_->OnAbilityDied(firstTopAbility); + + EXPECT_TRUE(secondTopAbility != nullptr); + EXPECT_EQ(firstTopAbility->GetAbilityState(), OHOS::AAFwk::INITIAL); + + // restart + ref = stackManager_->StartAbility(music1AbilityRequest_); + EXPECT_EQ(ERR_OK, ref); +} + +/* + * Feature: AaFwk + * Function:RemoveMissionById + * SubFunction: delete mission by id + * FunctionPoints: + * EnvConditions: NA + * CaseDescription: 04 remove radioAbility mission. + */ +HWTEST_F(AbilityStackModuleTest, ability_stack_test_057, TestSize.Level1) +{ + EXPECT_CALL(*mockAppMgrClient, LoadAbility(_, _, _, _)) + .Times(AtLeast(2)) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)); + + auto launcherAbilityRequest_ = GenerateAbilityRequest("device", "LauncherAbility", "launcher", "com.ix.hiworld"); + auto ref = stackManager_->StartAbility(launcherAbilityRequest_); + EXPECT_EQ(ERR_OK, ref); + auto topAbilityRecordLuncher = stackManager_->GetCurrentTopAbility(); + EXPECT_TRUE(topAbilityRecordLuncher); + topAbilityRecordLuncher->SetAbilityState(OHOS::AAFwk::ACTIVE); + + auto radioAbilityRequest = GenerateAbilityRequest("device", "RadioAbility", "radio", "com.ix.hiRadio"); + // float flag + auto abilityStartSetting = AbilityStartSetting::GetEmptySetting(); + EXPECT_TRUE(abilityStartSetting); + abilityStartSetting->AddProperty(AbilityStartSetting::WINDOW_MODE_KEY, + std::to_string(AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_FLOATING)); + radioAbilityRequest.startSetting = abilityStartSetting; + + ref = stackManager_->StartAbility(radioAbilityRequest); + EXPECT_EQ(ERR_OK, ref); + auto topAbilityRecordRadio = stackManager_->GetCurrentTopAbility(); + EXPECT_TRUE(topAbilityRecordRadio); + topAbilityRecordRadio->SetAbilityState(OHOS::AAFwk::ACTIVE); + + auto music1AbilityRequest_ = GenerateAbilityRequest("device", "MusicSAbility", "music", "com.ix.hiMusic"); + stackManager_->StartAbility(music1AbilityRequest_); + auto firstTopAbility = stackManager_->GetCurrentTopAbility(); + firstTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + topAbilityRecordLuncher->SetAbilityState(OHOS::AAFwk::BACKGROUND); + topAbilityRecordRadio->SetAbilityState(OHOS::AAFwk::ACTIVE); + firstTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + EXPECT_EQ(topAbilityRecordLuncher->GetMissionStackId(), LAUNCHER_MISSION_STACK_ID); + EXPECT_EQ(topAbilityRecordRadio->GetMissionStackId(), FLOATING_MISSION_STACK_ID); + EXPECT_EQ(firstTopAbility->GetMissionStackId(), DEFAULT_MISSION_STACK_ID); + + auto missionID = topAbilityRecordRadio->GetMissionRecordId(); + ref = stackManager_->RemoveMissionById(missionID); + EXPECT_EQ(ERR_OK, ref); + + auto missionRecord = stackManager_->GetMissionRecordById(missionID); + EXPECT_TRUE(missionRecord == nullptr); + + auto currentStack = stackManager_->GetCurrentMissionStack(); + EXPECT_TRUE(currentStack != nullptr); + EXPECT_EQ(currentStack->GetMissionStackId(), DEFAULT_MISSION_STACK_ID); +} + +/* + * Feature: AaFwk + * Function:RemoveMissionById + * SubFunction: delete mission by id + * FunctionPoints: + * EnvConditions: NA + * CaseDescription: 05 ability died RadioAbility. + */ +HWTEST_F(AbilityStackModuleTest, ability_stack_test_058, TestSize.Level1) +{ + EXPECT_CALL(*mockAppMgrClient, LoadAbility(_, _, _, _)) + .Times(AtLeast(2)) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)); + + auto launcherAbilityRequest_ = GenerateAbilityRequest("device", "LauncherAbility", "launcher", "com.ix.hiworld"); + auto ref = stackManager_->StartAbility(launcherAbilityRequest_); + EXPECT_EQ(ERR_OK, ref); + auto topAbilityRecordLuncher = stackManager_->GetCurrentTopAbility(); + EXPECT_TRUE(topAbilityRecordLuncher); + topAbilityRecordLuncher->SetAbilityState(OHOS::AAFwk::ACTIVE); + + auto radioAbilityRequest = GenerateAbilityRequest("device", "RadioAbility", "radio", "com.ix.hiRadio"); + // float flag + auto abilityStartSetting = AbilityStartSetting::GetEmptySetting(); + EXPECT_TRUE(abilityStartSetting); + abilityStartSetting->AddProperty(AbilityStartSetting::WINDOW_MODE_KEY, + std::to_string(AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_FLOATING)); + radioAbilityRequest.startSetting = abilityStartSetting; + + ref = stackManager_->StartAbility(radioAbilityRequest); + EXPECT_EQ(ERR_OK, ref); + auto topAbilityRecordRadio = stackManager_->GetCurrentTopAbility(); + EXPECT_TRUE(topAbilityRecordRadio); + topAbilityRecordRadio->SetAbilityState(OHOS::AAFwk::ACTIVE); + + auto music1AbilityRequest_ = GenerateAbilityRequest("device", "MusicSAbility", "music", "com.ix.hiMusic"); + stackManager_->StartAbility(music1AbilityRequest_); + auto firstTopAbility = stackManager_->GetCurrentTopAbility(); + firstTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + topAbilityRecordLuncher->SetAbilityState(OHOS::AAFwk::BACKGROUND); + topAbilityRecordRadio->SetAbilityState(OHOS::AAFwk::ACTIVE); + firstTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + EXPECT_EQ(topAbilityRecordLuncher->GetMissionStackId(), LAUNCHER_MISSION_STACK_ID); + EXPECT_EQ(topAbilityRecordRadio->GetMissionStackId(), FLOATING_MISSION_STACK_ID); + EXPECT_EQ(firstTopAbility->GetMissionStackId(), DEFAULT_MISSION_STACK_ID); + + // let ability died + stackManager_->OnAbilityDied(topAbilityRecordRadio); + + EXPECT_EQ(topAbilityRecordRadio->GetAbilityState(), OHOS::AAFwk::INITIAL); +} + +/* + * Feature: AaFwk + * Function:RemoveMissionById + * SubFunction: delete mission by id + * FunctionPoints: + * EnvConditions: NA + * CaseDescription: 06 restart RadioAbility, it will be call onrestore + */ +HWTEST_F(AbilityStackModuleTest, ability_stack_test_059, TestSize.Level1) +{ + EXPECT_CALL(*mockAppMgrClient, LoadAbility(_, _, _, _)) + .Times(AtLeast(3)) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)) + .WillOnce(Return(AppMgrResultCode::RESULT_OK)); + + auto launcherAbilityRequest_ = GenerateAbilityRequest("device", "LauncherAbility", "launcher", "com.ix.hiworld"); + auto ref = stackManager_->StartAbility(launcherAbilityRequest_); + EXPECT_EQ(ERR_OK, ref); + auto topAbilityRecordLuncher = stackManager_->GetCurrentTopAbility(); + EXPECT_TRUE(topAbilityRecordLuncher); + topAbilityRecordLuncher->SetAbilityState(OHOS::AAFwk::ACTIVE); + + auto radioAbilityRequest = GenerateAbilityRequest("device", "RadioAbility", "radio", "com.ix.hiRadio"); + // float flag + auto abilityStartSetting = AbilityStartSetting::GetEmptySetting(); + EXPECT_TRUE(abilityStartSetting); + abilityStartSetting->AddProperty(AbilityStartSetting::WINDOW_MODE_KEY, + std::to_string(AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_FLOATING)); + radioAbilityRequest.startSetting = abilityStartSetting; + + ref = stackManager_->StartAbility(radioAbilityRequest); + EXPECT_EQ(ERR_OK, ref); + auto topAbilityRecordRadio = stackManager_->GetCurrentTopAbility(); + EXPECT_TRUE(topAbilityRecordRadio); + topAbilityRecordRadio->SetAbilityState(OHOS::AAFwk::ACTIVE); + + auto music1AbilityRequest_ = GenerateAbilityRequest("device", "MusicSAbility", "music", "com.ix.hiMusic"); + stackManager_->StartAbility(music1AbilityRequest_); + auto firstTopAbility = stackManager_->GetCurrentTopAbility(); + firstTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + topAbilityRecordLuncher->SetAbilityState(OHOS::AAFwk::BACKGROUND); + topAbilityRecordRadio->SetAbilityState(OHOS::AAFwk::ACTIVE); + firstTopAbility->SetAbilityState(OHOS::AAFwk::ACTIVE); + + EXPECT_EQ(topAbilityRecordLuncher->GetMissionStackId(), LAUNCHER_MISSION_STACK_ID); + EXPECT_EQ(topAbilityRecordRadio->GetMissionStackId(), FLOATING_MISSION_STACK_ID); + EXPECT_EQ(firstTopAbility->GetMissionStackId(), DEFAULT_MISSION_STACK_ID); + + OHOS::sptr scheduler(new MockAbilityScheduler()); + EXPECT_CALL(*scheduler, AsObject()).WillRepeatedly(Return(nullptr)); + topAbilityRecordRadio->SetScheduler(scheduler); + + EXPECT_CALL(*scheduler, ScheduleRestoreAbilityState(testing::_)).Times(testing::AtLeast(1)); + + // let ability died + stackManager_->OnAbilityDied(topAbilityRecordRadio); + + auto currentStack = stackManager_->GetCurrentMissionStack(); + EXPECT_TRUE(currentStack != nullptr); + EXPECT_EQ(currentStack->GetMissionStackId(), DEFAULT_MISSION_STACK_ID); + + EXPECT_EQ(topAbilityRecordRadio->GetAbilityState(), OHOS::AAFwk::INITIAL); + + // restart + ref = stackManager_->StartAbility(radioAbilityRequest); + EXPECT_EQ(ERR_OK, ref); +} +} // namespace AAFwk +} // namespace OHOS diff --git a/tools/services/test/moduletest/dump_module_test/BUILD.gn b/tools/services/test/moduletest/dump_module_test/BUILD.gn new file mode 100644 index 00000000000..9f1c521d12c --- /dev/null +++ b/tools/services/test/moduletest/dump_module_test/BUILD.gn @@ -0,0 +1,71 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import("//build/test.gni") +import("//foundation/aafwk/standard/aafwk.gni") + +module_output_path = "aafwk_standard/mstabilitymgrservice" + +ohos_moduletest("dump_module_test") { + module_out_path = module_output_path + + include_dirs = [ + "${services_path}/abilitymgr/test/mock/libs/system_ability_mock", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy/include", + "//foundation/aafwk/standard/services/test/moduletest/module_test_dump_util/", + "//foundation/aafwk/standard/services/test/mock/include", + ] + + sources = [ + "${services_path}/abilitymgr/test/unittest/phone/ability_with_applications_test/mock_ability_scheduler.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/app_scheduler.cpp", + "//foundation/aafwk/standard/services/test/moduletest/module_test_dump_util/module_test_dump_util.cpp", + "dump_module_test.cpp", + ] + + configs = [ + "${services_path}/abilitymgr:abilityms_config", + "${services_path}/abilitymgr/test/mock:aafwk_mock_config", + "//foundation/aafwk/standard/services/test/moduletest/module_test_dump_util:module_test_dump_util_config", + ] + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + deps = [ + "${innerkits_path}/want:want", + "${services_path}/abilitymgr/test:abilityms_test_source", + "${services_path}/abilitymgr/test/mock/appmgr_test_service:appmgr_test_service", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_appmgr_mock", + "${services_path}/abilitymgr/test/mock/libs/appexecfwk_core:appexecfwk_bundlemgr_mock", + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/frameworks/kits/ability/native:dummy_classes", + "//foundation/aafwk/standard/services/test/moduletest/module_test_dump_util:module_test_dump_util_lib", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//third_party/googletest:gmock_main", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] +} + +group("moduletest") { + testonly = true + + deps = [ ":dump_module_test" ] +} diff --git a/tools/services/test/moduletest/dump_module_test/dump_module_test.cpp b/tools/services/test/moduletest/dump_module_test/dump_module_test.cpp new file mode 100755 index 00000000000..7e9bd7682a9 --- /dev/null +++ b/tools/services/test/moduletest/dump_module_test/dump_module_test.cpp @@ -0,0 +1,664 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include "system_ability_definition.h" +#include "ability_info.h" +#include "application_info.h" +#define private public +#define protected public +#include "ability_manager_service.h" +#undef private +#undef protected +#include "ability_manager_errors.h" +#include "gtest/gtest.h" +#include "mock_bundle_mgr.h" +#include "want.h" +#include "sa_mgr_client.h" +#include "appmgr_test_service.h" +#include "module_test_dump_util.h" + +using namespace testing; +using namespace testing::ext; +using namespace OHOS::AppExecFwk; +using OHOS::MTUtil::MTDumpUtil; + +namespace OHOS { +namespace AAFwk { +namespace { +#define SLEEP(milli) std::this_thread::sleep_for(std::chrono::milliseconds(milli)) + +const std::string NAME_BUNDLE_MGR_SERVICE = "BundleMgrService"; +static std::shared_ptr g_abilityMs = nullptr; +static std::shared_ptr g_appTestService = nullptr; + +static const ElementName G_TESTABILITY1("device", "com.ix.hiMusic", "MainAbility1"); +static const ElementName G_TESTABILITY2("device", "com.ix.hiMusic", "MainAbility2"); +static const ElementName G_TESTABILITY3("device", "com.ix.hiRadio", "MainAbility3"); +static const ElementName G_TESTABILITY4("device", "com.ix.hiRadio", "MainAbility4"); +static const ElementName G_LAUNCHABILITY("device", "com.ix.hiworld", "LaunchAbility"); +static const ElementName G_TESTBLOCKACTIVEABILITY("device", "com.ix.musicService", "ServiceAbility"); +static const ElementName G_TESTABILITY5("device", "com.ix.hiRadio", "MainAbility5"); +static const ElementName G_TESTABILITY6("device", "com.ix.hiRadio", "MainAbility6"); +} // namespace + +static void WaitUntilTaskFinished() +{ + const uint32_t maxRetryCount = 1000; + const uint32_t sleepTime = 1000; + uint32_t count = 0; + auto handler = OHOS::DelayedSingleton::GetInstance()->GetEventHandler(); + std::atomic taskCalled(false); + auto f = [&taskCalled]() { taskCalled.store(true); }; + if (handler->PostTask(f)) { + while (!taskCalled.load()) { + ++count; + if (count >= maxRetryCount) { + break; + } + usleep(sleepTime); + } + } +} + +std::string ShowDump(const std::vector &strVec) +{ + std::string ret; + for (const auto &str : strVec) { + ret += str + "\n"; + } + return ret; +} + +class DumpModuleTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp(); + void TearDown(); + void StartAllAbilities(); + bool SearchAbilityNameFromStackInfo(const std::string &abilityName, const std::vector &vec); + + Want want11{}; + Want want22{}; + Want want33{}; + Want want44{}; + Want want55{}; + Want wantLauncher{}; +}; + +bool DumpModuleTest::SearchAbilityNameFromStackInfo( + const std::string &abilityName, const std::vector &vec) +{ + auto iter = std::find_if(vec.begin(), vec.end(), [&abilityName](const AbilityRecordInfo &abilityRecordInfo) { + return (abilityRecordInfo.mainName == abilityName); + }); + return ((iter == vec.end()) ? false : true); +} + +void DumpModuleTest::SetUpTestCase() +{} + +void DumpModuleTest::TearDownTestCase() +{} + +void DumpModuleTest::SetUp() +{ + OHOS::sptr bundleObject = new BundleMgrService(); + OHOS::DelayedSingleton::GetInstance()->RegisterSystemAbility( + OHOS::BUNDLE_MGR_SERVICE_SYS_ABILITY_ID, bundleObject); + + g_abilityMs = OHOS::DelayedSingleton::GetInstance(); + g_abilityMs->OnStart(); + WaitUntilTaskFinished(); + + want11.SetElement(G_TESTABILITY1); + want22.SetElement(G_TESTABILITY2); + want33.SetElement(G_TESTABILITY3); + want44.SetElement(G_TESTABILITY4); + want55.SetElement(G_TESTABILITY6); + wantLauncher.SetElement(G_LAUNCHABILITY); + StartAllAbilities(); +} + +void DumpModuleTest::StartAllAbilities() +{ + wantLauncher.AddEntity(Want::FLAG_HOME_INTENT_FROM_SYSTEM); + g_abilityMs->StartAbility(wantLauncher); + WaitUntilTaskFinished(); + auto topAbilityLuncher = g_abilityMs->GetStackManager()->GetCurrentTopAbility(); + if (topAbilityLuncher) { + topAbilityLuncher->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + } + + g_abilityMs->StartAbility(want11); + WaitUntilTaskFinished(); + auto topAbility11 = g_abilityMs->GetStackManager()->GetCurrentTopAbility(); + if (topAbility11) { + topAbility11->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + } + + g_abilityMs->StartAbility(want22); + WaitUntilTaskFinished(); + auto topAbility22 = g_abilityMs->GetStackManager()->GetCurrentTopAbility(); + if (topAbility22) { + topAbility22->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + } + + g_abilityMs->StartAbility(want33); + WaitUntilTaskFinished(); + auto topAbility33 = g_abilityMs->GetStackManager()->GetCurrentTopAbility(); + if (topAbility33) { + topAbility33->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + } + + g_abilityMs->StartAbility(want44); + WaitUntilTaskFinished(); + auto topAbility44 = g_abilityMs->GetStackManager()->GetCurrentTopAbility(); + if (topAbility44) { + topAbility44->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + } + + g_abilityMs->StartAbility(want55); + WaitUntilTaskFinished(); + auto topAbility55 = g_abilityMs->GetStackManager()->GetCurrentTopAbility(); + if (topAbility55) { + topAbility55->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + } +} + +void DumpModuleTest::TearDown() +{ + g_abilityMs->OnStop(); + OHOS::DelayedSingleton::DestroyInstance(); +} + +/* + * Feature: Aafwk + * Function: DumpState + * SubFunction: NA + * FunctionPoints: test AbilityManagerService DumpState + * EnvConditions: System running normally + * CaseDescription: DumpState to show info of stacks respectively + */ +HWTEST_F(DumpModuleTest, dump_module_test_001, TestSize.Level2) +{ + std::vector dumpInfo; + g_abilityMs->DumpState("--stack 1", dumpInfo); + std::vector abilitiesStarted = { + want55, + want44, + want33, + want22, + want11, + }; + std::vector abilityNames; + MTDumpUtil::GetInstance()->GetAll("AbilityName", dumpInfo, abilityNames); + EXPECT_EQ(abilitiesStarted.size(), abilityNames.size()); + for (unsigned int i = 0; i < abilityNames.size(); ++i) { + EXPECT_EQ(0, abilitiesStarted[i].GetElement().GetAbilityName().compare(abilityNames[i])); + } + + dumpInfo.clear(); + + g_abilityMs->DumpState("--stack 0", dumpInfo); + abilitiesStarted = { + wantLauncher, + }; + MTDumpUtil::GetInstance()->GetAll("AbilityName", dumpInfo, abilityNames); + EXPECT_EQ(abilitiesStarted.size(), abilityNames.size()); + for (unsigned int i = 0; i < abilityNames.size(); ++i) { + EXPECT_EQ(0, abilitiesStarted[i].GetElement().GetAbilityName().compare(abilityNames[i])); + } + + dumpInfo.clear(); + + g_abilityMs->DumpState("--stack 1 abc", dumpInfo); + abilitiesStarted = { + want55, + want44, + want33, + want22, + want11, + }; + MTDumpUtil::GetInstance()->GetAll("AbilityName", dumpInfo, abilityNames); + EXPECT_EQ(abilitiesStarted.size(), abilityNames.size()); + for (unsigned int i = 0; i < abilityNames.size(); ++i) { + EXPECT_EQ(0, abilitiesStarted[i].GetElement().GetAbilityName().compare(abilityNames[i])); + } + + dumpInfo.clear(); + + g_abilityMs->DumpState(" --stack 1", dumpInfo); + abilitiesStarted = { + want55, + want44, + want33, + want22, + want11, + }; + MTDumpUtil::GetInstance()->GetAll("AbilityName", dumpInfo, abilityNames); + EXPECT_EQ(abilitiesStarted.size(), abilityNames.size()); + for (unsigned int i = 0; i < abilityNames.size(); ++i) { + EXPECT_EQ(0, abilitiesStarted[i].GetElement().GetAbilityName().compare(abilityNames[i])); + } +} + +/* + * Feature: Aafwk + * Function: DumpStack + * SubFunction: NA + * FunctionPoints: test AbilityStackManager DumpStack + * EnvConditions: System running normally + * CaseDescription: DumpStack directly to show info of stacks respectively + */ +HWTEST_F(DumpModuleTest, dump_module_test_002, TestSize.Level2) +{ + std::vector dumpInfo; + g_abilityMs->GetStackManager()->DumpStack(1, dumpInfo); + std::vector abilitiesStarted = { + want55, + want44, + want33, + want22, + want11, + }; + std::vector abilityNames; + MTDumpUtil::GetInstance()->GetAll("AbilityName", dumpInfo, abilityNames); + + GTEST_LOG_(INFO) << "abilitiesStarted.size() = " << abilitiesStarted.size(); + GTEST_LOG_(INFO) << "abilityNames.size() = " << abilityNames.size(); + + EXPECT_EQ(abilitiesStarted.size(), abilityNames.size()); + for (unsigned int i = 0; i < abilityNames.size(); ++i) { + EXPECT_EQ(0, abilitiesStarted[i].GetElement().GetAbilityName().compare(abilityNames[i])); + } + + dumpInfo.clear(); + + g_abilityMs->GetStackManager()->DumpStack(0, dumpInfo); + abilitiesStarted = { + wantLauncher, + }; + MTDumpUtil::GetInstance()->GetAll("AbilityName", dumpInfo, abilityNames); + EXPECT_EQ(abilitiesStarted.size(), abilityNames.size()); + for (unsigned int i = 0; i < abilityNames.size(); ++i) { + EXPECT_EQ(0, abilitiesStarted[i].GetElement().GetAbilityName().compare(abilityNames[i])); + } +} + +/* + * Feature: Aafwk + * Function: DumpState + * SubFunction: NA + * FunctionPoints: testAbilityManagerService DumpState + * EnvConditions: System running normally + * CaseDescription: Handle wrong args about missionStack + */ +HWTEST_F(DumpModuleTest, dump_module_test_003, TestSize.Level2) +{ + std::string expectedResult1 = "error: invalid argument, please see 'ability dump -h'."; + std::string expectedResult2 = "Invalid stack number, please see ability dump stack-list."; + std::vector dumpInfo; + + g_abilityMs->DumpState("--stack", dumpInfo); + EXPECT_EQ(1UL, dumpInfo.size()); + EXPECT_EQ(dumpInfo[0], expectedResult1); + + dumpInfo.clear(); + + g_abilityMs->DumpState("--sta ck", dumpInfo); + EXPECT_EQ(0UL, dumpInfo.size()); + + dumpInfo.clear(); + + g_abilityMs->DumpState("--stack1", dumpInfo); + EXPECT_EQ(0UL, dumpInfo.size()); + + dumpInfo.clear(); + + g_abilityMs->DumpState("--stack a", dumpInfo); + EXPECT_EQ(2UL, dumpInfo.size()); + EXPECT_EQ(dumpInfo[1], expectedResult2); + + dumpInfo.clear(); + + g_abilityMs->DumpState("--stack 10", dumpInfo); + EXPECT_EQ(2UL, dumpInfo.size()); + EXPECT_EQ(dumpInfo[1], expectedResult2); + + dumpInfo.clear(); + + g_abilityMs->DumpState(" ", dumpInfo); + EXPECT_EQ(0UL, dumpInfo.size()); + + dumpInfo.clear(); + + g_abilityMs->DumpState("", dumpInfo); + EXPECT_EQ(0UL, dumpInfo.size()); + + dumpInfo.clear(); + + g_abilityMs->DumpState("--", dumpInfo); + EXPECT_EQ(0UL, dumpInfo.size()); + + dumpInfo.clear(); + + g_abilityMs->DumpState("-", dumpInfo); + EXPECT_EQ(0UL, dumpInfo.size()); + + dumpInfo.clear(); + + g_abilityMs->DumpState("-ss", dumpInfo); + EXPECT_EQ(0UL, dumpInfo.size()); + + dumpInfo.clear(); + + g_abilityMs->DumpState("!.. --stack 1", dumpInfo); + EXPECT_EQ(0UL, dumpInfo.size()); + + dumpInfo.clear(); + + g_abilityMs->GetStackManager()->DumpStack(10, dumpInfo); + // index 0 :"User ID #" + // index 2 :"Invalid stack number, please see ability dump stack-list." + EXPECT_EQ(2UL, dumpInfo.size()); + EXPECT_EQ(dumpInfo[0], "User ID #0"); + EXPECT_EQ(dumpInfo[1], expectedResult2); +} + +/* + * Feature: Aafwk + * Function: DumpState + * SubFunction: NA + * FunctionPoints: test AbilityManagerService DumpState + * EnvConditions: System running normally + * CaseDescription: DumpState to show info of the top ability + */ +HWTEST_F(DumpModuleTest, dump_module_test_004, TestSize.Level2) +{ + std::string args("--top"); + std::vector dumpInfo; + g_abilityMs->DumpState(args, dumpInfo); + std::vector abilityNames; + int abilityNum = MTDumpUtil::GetInstance()->GetAll("AbilityName", dumpInfo, abilityNames); + EXPECT_EQ(1, abilityNum); + EXPECT_EQ("MainAbility6", abilityNames[0]); +} + +/* + * Feature: Aafwk + * Function: DumpTopAbility + * SubFunction: NA + * FunctionPoints: test AbilityStackManager DumpTopAbility + * EnvConditions: System running normally + * CaseDescription: DumpTopAbility directly to show info of the top ability + */ +HWTEST_F(DumpModuleTest, dump_module_test_005, TestSize.Level2) +{ + std::vector dumpInfo; + std::vector abilityNames; + g_abilityMs->GetStackManager()->DumpTopAbility(dumpInfo); + int abilityNum = MTDumpUtil::GetInstance()->GetAll("AbilityName", dumpInfo, abilityNames); + EXPECT_EQ(1, abilityNum); + EXPECT_EQ("MainAbility6", abilityNames[0]); +} + +/* + * Feature: Aafwk + * Function: DumpState + * SubFunction: NA + * FunctionPoints: test AbilityManagerService DumpState + * EnvConditions: System running normally + * CaseDescription: DumpState to show all dump info + */ +HWTEST_F(DumpModuleTest, dump_module_test_006, TestSize.Level2) +{ + std::string args("--all"); + std::vector dumpInfo; + g_abilityMs->DumpState(args, dumpInfo); + std::vector abilitiesStarted = { + want55, + want44, + want33, + want22, + want11, + wantLauncher, + }; + std::vector abilityNames; + MTDumpUtil::GetInstance()->GetAll("AbilityName", dumpInfo, abilityNames); + EXPECT_EQ(abilitiesStarted.size(), abilityNames.size()); + for (unsigned int i = 0; i < abilityNames.size(); ++i) { + GTEST_LOG_(INFO) << "abilitiesStarted = " << abilitiesStarted[i].GetElement().GetAbilityName(); + GTEST_LOG_(INFO) << "abilityNames = " << abilityNames[i]; + EXPECT_EQ(0, abilitiesStarted[i].GetElement().GetAbilityName().compare(abilityNames[i])); + } + + dumpInfo.clear(); + g_abilityMs->GetStackManager()->Dump(dumpInfo); + MTDumpUtil::GetInstance()->GetAll("AbilityName", dumpInfo, abilityNames); + EXPECT_EQ(abilitiesStarted.size(), abilityNames.size()); + for (unsigned int i = 0; i < abilityNames.size(); ++i) { + EXPECT_EQ(0, abilitiesStarted[i].GetElement().GetAbilityName().compare(abilityNames[i])); + } +} + +/* + * Feature: Aafwk + * Function: DumpTopAbility + * SubFunction: NA + * FunctionPoints: test AbilityStackManager DumpTopAbility + * EnvConditions: System running normally + * CaseDescription: Dump directly to show all dump info + */ +HWTEST_F(DumpModuleTest, dump_module_test_007, TestSize.Level2) +{ + std::vector dumpInfo; + std::vector abilitiesStarted = {want55, want44, want33, want22, want11, wantLauncher}; + std::vector abilityNames; + g_abilityMs->GetStackManager()->Dump(dumpInfo); + MTDumpUtil::GetInstance()->GetAll("AbilityName", dumpInfo, abilityNames); + EXPECT_EQ(abilitiesStarted.size(), abilityNames.size()); + for (unsigned int i = 0; i < abilityNames.size(); ++i) { + GTEST_LOG_(INFO) << "abilitiesStarted = " << abilitiesStarted[i].GetElement().GetAbilityName(); + GTEST_LOG_(INFO) << "abilityNames = " << abilityNames[i]; + EXPECT_EQ(0, abilitiesStarted[i].GetElement().GetAbilityName().compare(abilityNames[i])); + } +} + +/* + * Feature: Aafwk + * Function: DumpState + * SubFunction: NA + * FunctionPoints: test AbilityManagerService DumpState + * EnvConditions: System running normally + * CaseDescription: DumpState to show info of missionRecords respectively + */ +HWTEST_F(DumpModuleTest, dump_module_test_008, TestSize.Level2) +{ + + std::string args("--mission"); + std::vector dumpInfo; + std::vector abilityNames; + + EXPECT_TRUE(g_abilityMs); + auto stackMgr = g_abilityMs->GetStackManager(); + EXPECT_TRUE(stackMgr); + auto missionRecord = stackMgr->GetTopMissionRecord(); + EXPECT_TRUE(missionRecord); + int id = missionRecord->GetMissionRecordId(); + args += " "; + args += std::to_string(id); + GTEST_LOG_(INFO) << "args = " << args; + + g_abilityMs->DumpState(args, dumpInfo); + + std::vector abilitiesStarted = { + want55, + want44, + want33, + want22, + want11, + }; + + MTDumpUtil::GetInstance()->GetAll("AbilityName", dumpInfo, abilityNames); + EXPECT_EQ(abilitiesStarted.size(), abilityNames.size()); + for (unsigned int i = 0; i < abilityNames.size(); ++i) { + EXPECT_EQ(0, abilitiesStarted[i].GetElement().GetAbilityName().compare(abilityNames[i])); + } +} + +/* + * Feature: Aafwk + * Function: DumpState + * SubFunction: NA + * FunctionPoints: test AbilityManagerService DumpState + * EnvConditions: System running normally + * CaseDescription: Handle wrong args about missionRecord + */ +HWTEST_F(DumpModuleTest, dump_module_test_09, TestSize.Level2) +{ + std::string args; + std::vector dumpInfo; + std::string expectedResult1 = "error: invalid argument, please see 'ability dump -h'."; + std::string expectedResult2 = "error: invalid mission number, please see 'ability dump --stack-list'."; + + args = "--mission 10"; + g_abilityMs->DumpState(args, dumpInfo); + EXPECT_EQ(2UL, dumpInfo.size()); + EXPECT_EQ(dumpInfo[1], expectedResult2); + + dumpInfo.clear(); + + args = "--mission a"; + g_abilityMs->DumpState(args, dumpInfo); + EXPECT_EQ(2UL, dumpInfo.size()); + EXPECT_EQ(dumpInfo[1], expectedResult2); + + dumpInfo.clear(); + + args = "--mission"; + g_abilityMs->DumpState(args, dumpInfo); + EXPECT_EQ(1UL, dumpInfo.size()); + EXPECT_EQ(dumpInfo[0], expectedResult1); + + dumpInfo.clear(); + + args = "--mission1"; + g_abilityMs->DumpState(args, dumpInfo); + EXPECT_EQ(0UL, dumpInfo.size()); + + dumpInfo.clear(); + + args = "--miss ion"; + g_abilityMs->DumpState(args, dumpInfo); + EXPECT_EQ(0UL, dumpInfo.size()); + + dumpInfo.clear(); + + args = "-m 1"; + g_abilityMs->DumpState(args, dumpInfo); + EXPECT_EQ(2UL, dumpInfo.size()); +} + +/* + * Feature: Aafwk + * Function: GetAllStackInfo + * SubFunction: NA + * FunctionPoints: test AbilityManagerService GetAllStackInfo + * EnvConditions: System running normally + * CaseDescription: Get info of all stacks + */ + +HWTEST_F(DumpModuleTest, dump_module_test_010, TestSize.Level2) +{ + std::string args; + StackInfo stackInfo; + g_abilityMs->GetAllStackInfo(stackInfo); + + int findFlag = 0; + for (auto &stackInfo : stackInfo.missionStackInfos) { + for (auto &missionRecord : stackInfo.missionRecords) { + + if (SearchAbilityNameFromStackInfo(G_TESTABILITY1.GetAbilityName(), missionRecord.abilityRecordInfos)) { + ++findFlag; + } + if (SearchAbilityNameFromStackInfo(G_TESTABILITY2.GetAbilityName(), missionRecord.abilityRecordInfos)) { + ++findFlag; + } + if (SearchAbilityNameFromStackInfo(G_TESTABILITY3.GetAbilityName(), missionRecord.abilityRecordInfos)) { + ++findFlag; + } + if (SearchAbilityNameFromStackInfo(G_TESTABILITY4.GetAbilityName(), missionRecord.abilityRecordInfos)) { + ++findFlag; + } + if (SearchAbilityNameFromStackInfo(G_TESTABILITY6.GetAbilityName(), missionRecord.abilityRecordInfos)) { + ++findFlag; + } + if (SearchAbilityNameFromStackInfo(G_LAUNCHABILITY.GetAbilityName(), missionRecord.abilityRecordInfos)) { + ++findFlag; + } + } + } + + EXPECT_EQ(6, findFlag); +} + +/* + * Feature: Aafwk + * Function: DumpWaittingAbilityQueue + * SubFunction: NA + * FunctionPoints: test AbilityStackManager DumpWaittingAbilityQueue + * EnvConditions: System running normally + * CaseDescription: Dump info of abilities in waiting queue + */ +HWTEST_F(DumpModuleTest, dump_module_test_011, TestSize.Level2) +{ + Want want1; + Want want2; + std::string expectResult("The waitting ability queue is empty."); + + std::string args("--waitting-queue"); + std::vector result; + std::string waitingQueueResult; + + g_abilityMs->DumpState(args, result); + auto stackMgr = g_abilityMs->GetStackManager(); + EXPECT_TRUE(stackMgr); + g_abilityMs->DumpWaittingAbilityQueue(waitingQueueResult); + EXPECT_EQ(waitingQueueResult, expectResult); + + result.clear(); + waitingQueueResult.clear(); + + want1.SetElement(G_TESTABILITY1); + want2.SetElement(G_TESTABILITY5); + + int ref = g_abilityMs->StartAbility(want1); + EXPECT_EQ(ref, 0); + int refwant2 = g_abilityMs->StartAbility(want2); + EXPECT_EQ(refwant2, START_ABILITY_WAITING); + + g_abilityMs->DumpState(args, result); + EXPECT_TRUE(stackMgr); + stackMgr->DumpWaittingAbilityQueue(waitingQueueResult); + EXPECT_NE(std::string::npos, waitingQueueResult.find("com.ix.hiRadio")); +} + +} // namespace AAFwk +} // namespace OHOS diff --git a/tools/services/test/moduletest/ipc_ability_connect_test/BUILD.gn b/tools/services/test/moduletest/ipc_ability_connect_test/BUILD.gn new file mode 100644 index 00000000000..4b226686fbd --- /dev/null +++ b/tools/services/test/moduletest/ipc_ability_connect_test/BUILD.gn @@ -0,0 +1,50 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/test.gni") +import("//foundation/aafwk/standard/aafwk.gni") + +module_output_path = "aafwk_standard/mstabilitymgrservice" + +ohos_moduletest("IpcAbilityConnectModuleTest") { + module_out_path = module_output_path + + sources = + [ "${services_path}/abilitymgr/src/ability_connect_callback_stub.cpp" ] + + sources += [ "ipc_ability_connect_module_test.cpp" ] + + configs = [ "${services_path}/test:aafwk_module_test_config" ] + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + deps = [ + "${innerkits_path}/want:want", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//third_party/googletest:gmock_main", + "//third_party/googletest:gtest_main", + "//utils/native/base:utilsbase", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] +} + +group("moduletest") { + testonly = true + + deps = [ ":IpcAbilityConnectModuleTest" ] +} diff --git a/tools/services/test/moduletest/ipc_ability_connect_test/ipc_ability_connect_module_test.cpp b/tools/services/test/moduletest/ipc_ability_connect_test/ipc_ability_connect_module_test.cpp new file mode 100644 index 00000000000..26e3c0591fe --- /dev/null +++ b/tools/services/test/moduletest/ipc_ability_connect_test/ipc_ability_connect_module_test.cpp @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "gtest/gtest.h" +#include + +#include "mock_ability_connect_callback_stub.h" +#include "ability_connect_callback_proxy.h" + +using namespace testing; +using namespace testing::ext; +using namespace OHOS; +using namespace OHOS::AppExecFwk; +using OHOS::iface_cast; +using OHOS::sptr; +using testing::_; +using testing::Invoke; +using testing::InvokeWithoutArgs; + +namespace OHOS { +namespace AAFwk { +class IpcAbilityConnectModuleTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp(); + void TearDown(); + static constexpr int COUNT = 5; +}; + +void IpcAbilityConnectModuleTest::SetUpTestCase() +{} + +void IpcAbilityConnectModuleTest::TearDownTestCase() +{} + +void IpcAbilityConnectModuleTest::SetUp() +{} + +void IpcAbilityConnectModuleTest::TearDown() +{} + +/* + * Feature: AAFwk + * Function: AbilityConnect + * SubFunction: IPC of client and server + * FunctionPoints: OnAbilityConnectDone + * EnvConditions: NA + * CaseDescription: verify OnAbilityConnectDone IPC between client and server. + */ +HWTEST_F(IpcAbilityConnectModuleTest, AbilityConnectCallBack_IPC_001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "IpcAbilityConnectModuleTest AbilityConnectCallBack_IPC_001 start"; + for (int i = 0; i < COUNT; i++) { + sptr mockAbilityConnectStub(new MockAbilityConnectCallbackStub()); + sptr callback(new AbilityConnectionProxy(mockAbilityConnectStub)); + + AppExecFwk::ElementName element; + sptr remoteObject; + EXPECT_CALL(*mockAbilityConnectStub, OnAbilityConnectDone(_, _, _)) + .Times(1) + .WillOnce(InvokeWithoutArgs(mockAbilityConnectStub.GetRefPtr(), &MockAbilityConnectCallbackStub::PostVoid)); + callback->OnAbilityConnectDone(element, remoteObject, 0); + + mockAbilityConnectStub->Wait(); + } + + GTEST_LOG_(INFO) << "IpcAbilityConnectModuleTest AbilityConnectCallBack_IPC_001 end"; +} + +/* + * Feature: AAFwk + * Function: AbilityConnect + * SubFunction: IPC of client and server + * FunctionPoints: OnAbilityDisconnectDone + * EnvConditions: NA + * CaseDescription: verify OnAbilityDisconnectDone IPC between client and server. + */ +HWTEST_F(IpcAbilityConnectModuleTest, AbilityConnectCallBack_IPC_002, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "IpcAbilityConnectModuleTest AbilityConnectCallBack_IPC_002 start"; + for (int i = 0; i < COUNT; i++) { + sptr mockAbilityConnectStub(new MockAbilityConnectCallbackStub()); + sptr callback(new AbilityConnectionProxy(mockAbilityConnectStub)); + + AppExecFwk::ElementName element; + EXPECT_CALL(*mockAbilityConnectStub, OnAbilityDisconnectDone(_, _)) + .Times(1) + .WillOnce(InvokeWithoutArgs(mockAbilityConnectStub.GetRefPtr(), &MockAbilityConnectCallbackStub::PostVoid)); + callback->OnAbilityDisconnectDone(element, 0); + + mockAbilityConnectStub->Wait(); + } + + GTEST_LOG_(INFO) << "IpcAbilityConnectModuleTest AbilityConnectCallBack_IPC_002 end"; +} +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/services/test/moduletest/ipc_ability_mgr_test/BUILD.gn b/tools/services/test/moduletest/ipc_ability_mgr_test/BUILD.gn new file mode 100755 index 00000000000..a07b9f281d4 --- /dev/null +++ b/tools/services/test/moduletest/ipc_ability_mgr_test/BUILD.gn @@ -0,0 +1,55 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/test.gni") +import("//foundation/aafwk/standard/aafwk.gni") + +module_output_path = "aafwk_standard/mstabilitymgrservice" + +ohos_moduletest("IpcAbilityMgrServiceModuleTest") { + module_out_path = module_output_path + include_dirs = [ "//third_party/jsoncpp/include" ] + sources = [ "ipc_ability_mgr_module_test.cpp" ] + + configs = [ + "${services_path}/test:aafwk_module_test_config", + "//foundation/appexecfwk/standard/common:appexecfwk_common_config", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_core:appmgr_sdk_config", + ] + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + deps = [ + "${innerkits_path}/want:want", + "//foundation/aafwk/standard/services/abilitymgr:abilityms", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_core:appexecfwk_core", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//third_party/googletest:gmock_main", + "//third_party/googletest:gtest_main", + "//third_party/jsoncpp:jsoncpp", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] +} + +group("moduletest") { + testonly = true + + deps = [ ":IpcAbilityMgrServiceModuleTest" ] +} diff --git a/tools/services/test/moduletest/ipc_ability_mgr_test/ipc_ability_mgr_module_test.cpp b/tools/services/test/moduletest/ipc_ability_mgr_test/ipc_ability_mgr_module_test.cpp new file mode 100644 index 00000000000..bea7a9e12ba --- /dev/null +++ b/tools/services/test/moduletest/ipc_ability_mgr_test/ipc_ability_mgr_module_test.cpp @@ -0,0 +1,612 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "gtest/gtest.h" +#include + +#include "mock_ability_mgr_service.h" +#include "ability_manager_interface.h" +#include "ohos/aafwk/content/want.h" +#include "iremote_object.h" +#include "mock_ability_scheduler.h" +#include "ability_record.h" +#include "ability_info.h" +#include "application_info.h" + +using namespace testing; +using namespace testing::ext; +using namespace OHOS; +using namespace OHOS::AAFwk; +using namespace OHOS::AppExecFwk; +using OHOS::iface_cast; +using OHOS::sptr; +using testing::_; +using testing::Invoke; +using testing::InvokeWithoutArgs; +class IpcAbilityMgrModuleTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp(); + void TearDown(); + AbilityRequest CreateAbilityRequest(const std::string &abilityName, const std::string &bundleName); + + static constexpr int COUNT = 5; +}; + +void IpcAbilityMgrModuleTest::SetUpTestCase() +{} + +void IpcAbilityMgrModuleTest::TearDownTestCase() +{} + +void IpcAbilityMgrModuleTest::SetUp() +{} + +void IpcAbilityMgrModuleTest::TearDown() +{} + +AbilityRequest IpcAbilityMgrModuleTest::CreateAbilityRequest( + const std::string &abilityName, const std::string &bundleName) +{ + AbilityRequest abilityRequest; + + ElementName element("device", bundleName, abilityName); + Want want; + want.SetElement(element); + + AbilityInfo abilityInfo; + abilityInfo.name = abilityName; + abilityInfo.applicationName = bundleName; + abilityInfo.bundleName = bundleName; + abilityInfo.type = AbilityType::PAGE; + + ApplicationInfo appInfo; + appInfo.name = bundleName; + appInfo.bundleName = bundleName; + + abilityRequest.want = want; + abilityRequest.abilityInfo = abilityInfo; + abilityRequest.appInfo = appInfo; + return abilityRequest; +} + +/* + * Feature: AAFwk + * Function: AbilityManagerService + * SubFunction: IPC of client and server + * FunctionPoints: start ability + * EnvConditions: NA + * CaseDescription: verify StartAbility IPC between client and server. + */ +HWTEST_F(IpcAbilityMgrModuleTest, AbilityMgrService_IPC_001, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "IpcAbilityMgrModuleTest AbilityMgrService_IPC_001 start"; + for (int i = 0; i < COUNT; i++) { + sptr mockAbilityMgr(new MockAbilityMgrService()); + sptr abilityMgrClient = iface_cast(mockAbilityMgr); + const Want want; + + EXPECT_CALL(*mockAbilityMgr, StartAbility(_, _)) + .Times(1) + .WillOnce(InvokeWithoutArgs(mockAbilityMgr.GetRefPtr(), &MockAbilityMgrService::Post)); + abilityMgrClient->StartAbility(want, 0); + mockAbilityMgr->Wait(); + } + + GTEST_LOG_(INFO) << "IpcAbilityMgrModuleTest AbilityMgrService_IPC_001 end"; +} + +/* + * Feature: AAFwk + * Function: AbilityManagerService + * SubFunction: IPC of client and server + * FunctionPoints: AbilityTransitionDone + * EnvConditions: NA + * CaseDescription: verify AbilityTransitionDone IPC between client and server. + */ +HWTEST_F(IpcAbilityMgrModuleTest, AbilityMgrService_IPC_002, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "IpcAbilityMgrModuleTest AbilityMgrService_IPC_002 start"; + std::string abilityName = "ability_name"; + std::string bundleName = "com.ix.aafwk.moduletest"; + auto abilityRequest = CreateAbilityRequest(abilityName, bundleName); + auto abilityRecord = AbilityRecord::CreateAbilityRecord(abilityRequest); + EXPECT_TRUE(abilityRecord); + for (int i = 0; i < COUNT; i++) { + sptr mockAbilityMgr(new MockAbilityMgrService()); + sptr abilityMgrClient = iface_cast(mockAbilityMgr); + EXPECT_CALL(*mockAbilityMgr, AbilityTransitionDone(_, _)) + .Times(1) + .WillOnce(InvokeWithoutArgs(mockAbilityMgr.GetRefPtr(), &MockAbilityMgrService::Post)); + abilityMgrClient->AbilityTransitionDone(abilityRecord->GetToken(), 0); + mockAbilityMgr->Wait(); + } + + GTEST_LOG_(INFO) << "IpcAbilityMgrModuleTest AbilityMgrService_IPC_002 end"; +} + +/* + * Feature: AAFwk + * Function: AbilityManagerService + * SubFunction: IPC of client and server + * FunctionPoints: ScheduleConnectAbilityDone + * EnvConditions: NA + * CaseDescription: verify ScheduleConnectAbilityDone IPC between client and server. + */ +HWTEST_F(IpcAbilityMgrModuleTest, AbilityMgrService_IPC_003, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "IpcAbilityMgrModuleTest AbilityMgrService_IPC_003 start"; + for (int i = 0; i < COUNT; i++) { + sptr mockAbilityMgr(new MockAbilityMgrService()); + sptr abilityMgrClient = iface_cast(mockAbilityMgr); + + EXPECT_CALL(*mockAbilityMgr, ScheduleConnectAbilityDone(_, _)) + .Times(1) + .WillOnce(InvokeWithoutArgs(mockAbilityMgr.GetRefPtr(), &MockAbilityMgrService::Post)); + abilityMgrClient->ScheduleConnectAbilityDone(nullptr, nullptr); + mockAbilityMgr->Wait(); + } + + GTEST_LOG_(INFO) << "IpcAbilityMgrModuleTest AbilityMgrService_IPC_003 end"; +} + +/* + * Feature: AAFwk + * Function: AbilityManagerService + * SubFunction: IPC of client and server + * FunctionPoints: ScheduleDisconnectAbilityDone + * EnvConditions: NA + * CaseDescription: verify ScheduleDisconnectAbilityDone IPC between client and server. + */ +HWTEST_F(IpcAbilityMgrModuleTest, AbilityMgrService_IPC_004, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "IpcAbilityMgrModuleTest AbilityMgrService_IPC_004 start"; + for (int i = 0; i < COUNT; i++) { + sptr mockAbilityMgr(new MockAbilityMgrService()); + sptr abilityMgrClient = iface_cast(mockAbilityMgr); + + EXPECT_CALL(*mockAbilityMgr, ScheduleDisconnectAbilityDone(_)) + .Times(1) + .WillOnce(InvokeWithoutArgs(mockAbilityMgr.GetRefPtr(), &MockAbilityMgrService::Post)); + abilityMgrClient->ScheduleDisconnectAbilityDone(nullptr); + mockAbilityMgr->Wait(); + } + + GTEST_LOG_(INFO) << "IpcAbilityMgrModuleTest AbilityMgrService_IPC_004 end"; +} + +/* + * Feature: AAFwk + * Function: AbilityManagerService + * SubFunction: IPC of client and server + * FunctionPoints: AddWindowInfo + * EnvConditions: NA + * CaseDescription: verify AddWindowInfo IPC between client and server. + */ +HWTEST_F(IpcAbilityMgrModuleTest, AbilityMgrService_IPC_005, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "IpcAbilityMgrModuleTest AbilityMgrService_IPC_005 start"; + for (int i = 0; i < COUNT; i++) { + sptr mockAbilityMgr(new MockAbilityMgrService()); + sptr abilityMgrClient = iface_cast(mockAbilityMgr); + + EXPECT_CALL(*mockAbilityMgr, AddWindowInfo(_, _)) + .Times(1) + .WillOnce(InvokeWithoutArgs(mockAbilityMgr.GetRefPtr(), &MockAbilityMgrService::PostVoid)); + abilityMgrClient->AddWindowInfo(nullptr, 0); + mockAbilityMgr->Wait(); + } + + GTEST_LOG_(INFO) << "IpcAbilityMgrModuleTest AbilityMgrService_IPC_005 end"; +} + +/* + * Feature: AAFwk + * Function: AbilityManagerService + * SubFunction: IPC of client and server + * FunctionPoints: ConnectAbility + * EnvConditions: NA + * CaseDescription: verify ConnectAbility IPC between client and server. + */ +HWTEST_F(IpcAbilityMgrModuleTest, AbilityMgrService_IPC_006, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "IpcAbilityMgrModuleTest AbilityMgrService_IPC_006 start"; + for (int i = 0; i < COUNT; i++) { + sptr mockAbilityMgr(new MockAbilityMgrService()); + sptr abilityMgrClient = iface_cast(mockAbilityMgr); + Want want; + + EXPECT_CALL(*mockAbilityMgr, ConnectAbility(_, _, _)) + .Times(1) + .WillOnce(InvokeWithoutArgs(mockAbilityMgr.GetRefPtr(), &MockAbilityMgrService::Post)); + abilityMgrClient->ConnectAbility(want, nullptr, nullptr); + mockAbilityMgr->Wait(); + } + + GTEST_LOG_(INFO) << "IpcAbilityMgrModuleTest AbilityMgrService_IPC_006 end"; +} + +/* + * Feature: AAFwk + * Function: AbilityManagerService + * SubFunction: IPC of client and server + * FunctionPoints: DisconnectAbility + * EnvConditions: NA + * CaseDescription: verify DisconnectAbility IPC between client and server. + */ +HWTEST_F(IpcAbilityMgrModuleTest, AbilityMgrService_IPC_007, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "IpcAbilityMgrModuleTest AbilityMgrService_IPC_007 start"; + for (int i = 0; i < COUNT; i++) { + sptr mockAbilityMgr(new MockAbilityMgrService()); + sptr abilityMgrClient = iface_cast(mockAbilityMgr); + Want want; + + EXPECT_CALL(*mockAbilityMgr, DisconnectAbility(_)) + .Times(1) + .WillOnce(InvokeWithoutArgs(mockAbilityMgr.GetRefPtr(), &MockAbilityMgrService::Post)); + abilityMgrClient->DisconnectAbility(nullptr); + mockAbilityMgr->Wait(); + } + + GTEST_LOG_(INFO) << "IpcAbilityMgrModuleTest AbilityMgrService_IPC_007 end"; +} + +/* + * Feature: AAFwk + * Function: AbilityManagerService + * SubFunction: IPC of client and server + * FunctionPoints: DumpState + * EnvConditions: NA + * CaseDescription: verify DumpState IPC between client and server. + */ +HWTEST_F(IpcAbilityMgrModuleTest, AbilityMgrService_IPC_008, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "IpcAbilityMgrModuleTest AbilityMgrService_IPC_008 start"; + for (int i = 0; i < COUNT; i++) { + sptr mockAbilityMgr(new MockAbilityMgrService()); + sptr abilityMgrClient = iface_cast(mockAbilityMgr); + std::vector state; + std::string args = "key"; + + EXPECT_CALL(*mockAbilityMgr, DumpState(_, _)) + .Times(1) + .WillOnce(InvokeWithoutArgs(mockAbilityMgr.GetRefPtr(), &MockAbilityMgrService::PostVoid)); + abilityMgrClient->DumpState(args, state); + mockAbilityMgr->Wait(); + } + + GTEST_LOG_(INFO) << "IpcAbilityMgrModuleTest AbilityMgrService_IPC_008 end"; +} + +/* + * Feature: AAFwk + * Function: AbilityManagerService + * SubFunction: IPC of client and server + * FunctionPoints: AttachAbilityThread + * EnvConditions: NA + * CaseDescription: verify AttachAbilityThread IPC between client and server. + */ +HWTEST_F(IpcAbilityMgrModuleTest, AbilityMgrService_IPC_009, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "IpcAbilityMgrModuleTest AbilityMgrService_IPC_009 start"; + sptr scheduler = new MockAbilityScheduler(); + std::string abilityName = "ability_name"; + std::string bundleName = "com.ix.aafwk.moduletest"; + + auto abilityRequest = CreateAbilityRequest(abilityName, bundleName); + auto abilityRecord = AbilityRecord::CreateAbilityRecord(abilityRequest); + abilityRecord->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + + for (int i = 0; i < COUNT; i++) { + sptr mockAbilityMgr(new MockAbilityMgrService()); + sptr abilityMgrClient = iface_cast(mockAbilityMgr); + + EXPECT_CALL(*mockAbilityMgr, AttachAbilityThread(_, _)) + .Times(1) + .WillOnce(InvokeWithoutArgs(mockAbilityMgr.GetRefPtr(), &MockAbilityMgrService::Post)); + abilityMgrClient->AttachAbilityThread(scheduler, abilityRecord->GetToken()); + mockAbilityMgr->Wait(); + } + + GTEST_LOG_(INFO) << "IpcAbilityMgrModuleTest AbilityMgrService_IPC_009 end"; +} + +/* + * Feature: AAFwk + * Function: AbilityManagerService + * SubFunction: IPC of client and server + * FunctionPoints: TerminateAbility + * EnvConditions: NA + * CaseDescription: verify TerminateAbility IPC between client and server. + */ +HWTEST_F(IpcAbilityMgrModuleTest, AbilityMgrService_IPC_010, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "IpcAbilityMgrModuleTest AbilityMgrService_IPC_010 start"; + sptr scheduler = new MockAbilityScheduler(); + std::string abilityName = "ability_name"; + std::string bundleName = "com.ix.aafwk.moduletest"; + + AbilityRequest abilityRequest = CreateAbilityRequest(abilityName, bundleName); + std::shared_ptr abilityRecord = AbilityRecord::CreateAbilityRecord(abilityRequest); + abilityRecord->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + + for (int i = 0; i < COUNT; i++) { + sptr mockAbilityMgr(new MockAbilityMgrService()); + sptr abilityMgrClient = iface_cast(mockAbilityMgr); + + EXPECT_CALL(*mockAbilityMgr, TerminateAbility(_, _, _)) + .Times(1) + .WillOnce(InvokeWithoutArgs(mockAbilityMgr.GetRefPtr(), &MockAbilityMgrService::Post)); + abilityMgrClient->TerminateAbility(abilityRecord->GetToken(), -1, nullptr); + mockAbilityMgr->Wait(); + } + + GTEST_LOG_(INFO) << "IpcAbilityMgrModuleTest AbilityMgrService_IPC_010 end"; +} + +/* + * Feature: AAFwk + * Function: AbilityManagerService + * SubFunction: IPC of client and server + * FunctionPoints: GetAllStackInfo + * EnvConditions: NA + * CaseDescription: verify GetAllStackInfo IPC between client and server. + */ +HWTEST_F(IpcAbilityMgrModuleTest, AbilityMgrService_IPC_011, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "IpcAbilityMgrModuleTest AbilityMgrService_IPC_011 start"; + + for (int i = 0; i < COUNT; i++) { + sptr mockAbilityMgr(new MockAbilityMgrService()); + sptr abilityMgrClient = iface_cast(mockAbilityMgr); + + StackInfo stackInfo; + EXPECT_CALL(*mockAbilityMgr, GetAllStackInfo(_)) + .Times(1) + .WillOnce(InvokeWithoutArgs(mockAbilityMgr.GetRefPtr(), &MockAbilityMgrService::Post)); + abilityMgrClient->GetAllStackInfo(stackInfo); + mockAbilityMgr->Wait(); + } + + GTEST_LOG_(INFO) << "IpcAbilityMgrModuleTest AbilityMgrService_IPC_011 end"; +} + +/* + * Feature: AAFwk + * Function: AbilityManagerService + * SubFunction: IPC of client and server + * FunctionPoints: ScheduleCommandAbilityDone + * EnvConditions: NA + * CaseDescription: verify ScheduleCommandAbilityDone IPC between client and server. + */ +HWTEST_F(IpcAbilityMgrModuleTest, AbilityMgrService_IPC_012, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "IpcAbilityMgrModuleTest AbilityMgrService_IPC_012 start"; + for (int i = 0; i < COUNT; i++) { + sptr mockAbilityMgr(new MockAbilityMgrService()); + sptr abilityMgrClient = iface_cast(mockAbilityMgr); + + EXPECT_CALL(*mockAbilityMgr, ScheduleCommandAbilityDone(_)) + .Times(1) + .WillOnce(InvokeWithoutArgs(mockAbilityMgr.GetRefPtr(), &MockAbilityMgrService::Post)); + abilityMgrClient->ScheduleCommandAbilityDone(nullptr); + mockAbilityMgr->Wait(); + } + + GTEST_LOG_(INFO) << "IpcAbilityMgrModuleTest AbilityMgrService_IPC_012 end"; +} + +/* + * Feature: AAFwk + * Function: AbilityManagerService + * SubFunction: IPC of client and server + * FunctionPoints: StopServiceAbility + * EnvConditions: NA + * CaseDescription: verify StopServiceAbility IPC between client and server. + */ +HWTEST_F(IpcAbilityMgrModuleTest, AbilityMgrService_IPC_013, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "IpcAbilityMgrModuleTest AbilityMgrService_IPC_013 start"; + for (int i = 0; i < COUNT; i++) { + sptr mockAbilityMgr(new MockAbilityMgrService()); + sptr abilityMgrClient = iface_cast(mockAbilityMgr); + const Want want; + + EXPECT_CALL(*mockAbilityMgr, StopServiceAbility(_)) + .Times(1) + .WillOnce(InvokeWithoutArgs(mockAbilityMgr.GetRefPtr(), &MockAbilityMgrService::Post)); + abilityMgrClient->StopServiceAbility(want); + mockAbilityMgr->Wait(); + } + + GTEST_LOG_(INFO) << "IpcAbilityMgrModuleTest AbilityMgrService_IPC_013 end"; +} + +/* + * Feature: AAFwk + * Function: AbilityManagerService + * SubFunction: IPC of client and server + * FunctionPoints: GetAllStackInfo + * EnvConditions: NA + * CaseDescription: verify GetRecentMissions IPC between client and server. + */ +HWTEST_F(IpcAbilityMgrModuleTest, AbilityMgrService_IPC_014, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "IpcAbilityMgrModuleTest AbilityMgrService_IPC_014 start"; + + for (int i = 0; i < COUNT; i++) { + sptr mockAbilityMgr(new MockAbilityMgrService()); + sptr abilityMgrClient = iface_cast(mockAbilityMgr); + + std::vector renCentList; + EXPECT_CALL(*mockAbilityMgr, GetRecentMissions(_, _, _)) + .Times(1) + .WillOnce(InvokeWithoutArgs(mockAbilityMgr.GetRefPtr(), &MockAbilityMgrService::Post)); + abilityMgrClient->GetRecentMissions(10, 0, renCentList); + mockAbilityMgr->Wait(); + } + + GTEST_LOG_(INFO) << "IpcAbilityMgrModuleTest AbilityMgrService_IPC_014 end"; +} + +/* + * Feature: AAFwk + * Function: AbilityManagerService + * SubFunction: IPC of client and server + * FunctionPoints: GetMissionSnapshot + * EnvConditions: NA + * CaseDescription: verify GetMissionSnapshot IPC between client and server. + */ +HWTEST_F(IpcAbilityMgrModuleTest, AbilityMgrService_IPC_015, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "IpcAbilityMgrModuleTest AbilityMgrService_IPC_015 start"; + + for (int i = 0; i < COUNT; i++) { + sptr mockAbilityMgr(new MockAbilityMgrService()); + sptr abilityMgrClient = iface_cast(mockAbilityMgr); + + MissionSnapshotInfo snapshot; + EXPECT_CALL(*mockAbilityMgr, GetMissionSnapshot(_, _)) + .Times(1) + .WillOnce(InvokeWithoutArgs(mockAbilityMgr.GetRefPtr(), &MockAbilityMgrService::Post)); + abilityMgrClient->GetMissionSnapshot(1, snapshot); + mockAbilityMgr->Wait(); + } + + GTEST_LOG_(INFO) << "IpcAbilityMgrModuleTest AbilityMgrService_IPC_015 end"; +} + +/* + * Feature: AAFwk + * Function: AbilityManagerService + * SubFunction: IPC of client and server + * FunctionPoints: RemoveMission + * EnvConditions: NA + * CaseDescription: verify RemoveMission IPC between client and server. + */ +HWTEST_F(IpcAbilityMgrModuleTest, AbilityMgrService_IPC_016, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "IpcAbilityMgrModuleTest AbilityMgrService_IPC_016 start"; + + for (int i = 0; i < COUNT; i++) { + sptr mockAbilityMgr(new MockAbilityMgrService()); + sptr abilityMgrClient = iface_cast(mockAbilityMgr); + + EXPECT_CALL(*mockAbilityMgr, RemoveMission(_)) + .Times(1) + .WillOnce(InvokeWithoutArgs(mockAbilityMgr.GetRefPtr(), &MockAbilityMgrService::Post)); + abilityMgrClient->RemoveMission(1); + mockAbilityMgr->Wait(); + } + + GTEST_LOG_(INFO) << "IpcAbilityMgrModuleTest AbilityMgrService_IPC_016 end"; +} + +/* + * Feature: AAFwk + * Function: AbilityManagerService + * SubFunction: IPC of client and server + * FunctionPoints: RemoveStack + * EnvConditions: NA + * CaseDescription: verify RemoveStack IPC between client and server. + */ +HWTEST_F(IpcAbilityMgrModuleTest, AbilityMgrService_IPC_017, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "IpcAbilityMgrModuleTest AbilityMgrService_IPC_017 start"; + + for (int i = 0; i < COUNT; i++) { + sptr mockAbilityMgr(new MockAbilityMgrService()); + sptr abilityMgrClient = iface_cast(mockAbilityMgr); + + EXPECT_CALL(*mockAbilityMgr, RemoveStack(_)) + .Times(1) + .WillOnce(InvokeWithoutArgs(mockAbilityMgr.GetRefPtr(), &MockAbilityMgrService::Post)); + abilityMgrClient->RemoveStack(1); + mockAbilityMgr->Wait(); + } + + GTEST_LOG_(INFO) << "IpcAbilityMgrModuleTest AbilityMgrService_IPC_017 end"; +} + +/* + * Feature: AAFwk + * Function: AbilityManagerService + * SubFunction: IPC of client and server + * FunctionPoints: MoveMissionToTop + * EnvConditions: NA + * CaseDescription: verify MoveMissionToTop IPC between client and server. + */ +HWTEST_F(IpcAbilityMgrModuleTest, AbilityMgrService_IPC_018, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "IpcAbilityMgrModuleTest AbilityMgrService_IPC_018 start"; + + for (int i = 0; i < COUNT; i++) { + sptr mockAbilityMgr(new MockAbilityMgrService()); + sptr abilityMgrClient = iface_cast(mockAbilityMgr); + + EXPECT_CALL(*mockAbilityMgr, MoveMissionToTop(_)) + .Times(1) + .WillOnce(InvokeWithoutArgs(mockAbilityMgr.GetRefPtr(), &MockAbilityMgrService::Post)); + abilityMgrClient->MoveMissionToTop(1); + mockAbilityMgr->Wait(); + } + + GTEST_LOG_(INFO) << "IpcAbilityMgrModuleTest AbilityMgrService_IPC_018 end"; +} + +/* + * Feature: AAFwk + * Function: AbilityManagerService + * SubFunction: IPC of client and server + * FunctionPoints: AcquireDataAbility + * EnvConditions: NA + * CaseDescription: verify data ability acquire IPC between client and server. + */ +HWTEST_F(IpcAbilityMgrModuleTest, AbilityMgrService_IPC_019, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "IpcAbilityMgrModuleTest AbilityMgrService_IPC_019 start"; + + AbilityRequest abilityRequest; + + auto clientAbilityRecord = AbilityRecord::CreateAbilityRecord(abilityRequest); + Uri testUri("testuri"); + bool testTryBind = true; + + for (int i = 0; i < COUNT; i++) { + sptr mockAbilityMgr(new MockAbilityMgrService()); + sptr abilityMgrClient = iface_cast(mockAbilityMgr); + + bool testResult = false; + + auto mockHandler = [&](const Uri &uri, bool tryBind, const sptr &callerToken) { + testResult = (uri.ToString() == testUri.ToString() && tryBind == testTryBind && + Token::GetAbilityRecordByToken(callerToken) == clientAbilityRecord); + mockAbilityMgr->Post(); + return nullptr; + }; + + EXPECT_CALL(*mockAbilityMgr, AcquireDataAbility(_, _, _)).Times(1).WillOnce(Invoke(mockHandler)); + + abilityMgrClient->AcquireDataAbility(testUri, testTryBind, clientAbilityRecord->GetToken()); + + mockAbilityMgr->Wait(); + + EXPECT_TRUE(testResult); + } + + GTEST_LOG_(INFO) << "IpcAbilityMgrModuleTest AbilityMgrService_IPC_019 end"; +} \ No newline at end of file diff --git a/tools/services/test/moduletest/ipc_ability_scheduler_test/BUILD.gn b/tools/services/test/moduletest/ipc_ability_scheduler_test/BUILD.gn new file mode 100755 index 00000000000..ce775176380 --- /dev/null +++ b/tools/services/test/moduletest/ipc_ability_scheduler_test/BUILD.gn @@ -0,0 +1,74 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/test.gni") +import("//foundation/aafwk/standard/aafwk.gni") + +module_output_path = "aafwk_standard/mstabilitymgrservice" + +ohos_moduletest("IpcAbilitySchedulerModuleTest") { + module_out_path = module_output_path + + include_dirs = [ + "//third_party/jsoncpp/include", + "//foundation/aafwk/standard/interfaces/innerkits/dataobs_manager/include", + ] + + sources = [ + "${services_path}/abilitymgr/src/ability_scheduler_proxy.cpp", + "${services_path}/abilitymgr/src/ability_scheduler_stub.cpp", + "${services_path}/abilitymgr/src/caller_info.cpp", + "${services_path}/abilitymgr/src/lifecycle_state_info.cpp", + "//foundation/aafwk/standard/frameworks/kits/content/cpp/src/ohos/aafwk/content/pac_map.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/aafwk_dummy_configuration.cpp", + "//foundation/appexecfwk/standard/common/log/src/app_log_wrapper.cpp", + ] + + sources += [ "ipc_ability_scheduler_module_test.cpp" ] + + configs = [ + "${services_path}/test:aafwk_module_test_config", + "//foundation/appexecfwk/standard/common:appexecfwk_common_config", + "//foundation/aafwk/standard/interfaces/innerkits/want:want_public_config", + ] + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + deps = [ + "${innerkits_path}/want:want", + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/frameworks/kits/ability/native:dummy_classes", + "//foundation/aafwk/standard/interfaces/innerkits/base:base", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//third_party/googletest:gmock_main", + "//third_party/googletest:gtest_main", + "//third_party/jsoncpp:jsoncpp", + "//utils/native/base:utilsbase", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + "native_appdatamgr:native_appdatafwk", + "native_appdatamgr:native_dataability", + "native_appdatamgr:native_rdb", + ] +} + +group("moduletest") { + testonly = true + + deps = [ ":IpcAbilitySchedulerModuleTest" ] +} diff --git a/tools/services/test/moduletest/ipc_ability_scheduler_test/ipc_ability_scheduler_module_test.cpp b/tools/services/test/moduletest/ipc_ability_scheduler_test/ipc_ability_scheduler_module_test.cpp new file mode 100644 index 00000000000..e97dd689da0 --- /dev/null +++ b/tools/services/test/moduletest/ipc_ability_scheduler_test/ipc_ability_scheduler_module_test.cpp @@ -0,0 +1,560 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include "abs_shared_result_set.h" +#include "data_ability_predicates.h" +#include "values_bucket.h" +#include "uri.h" +#include "want.h" +#include "semaphore_ex.h" +#include "ability_scheduler_stub.h" +#include "ability_scheduler_proxy.h" +#include "mock_ability_scheduler_stub.h" + +namespace { +constexpr int COUNT = 1; +} // namespace + +using namespace testing::ext; +using namespace OHOS; +using namespace OHOS::AAFwk; +using OHOS::iface_cast; +using OHOS::sptr; +using testing::_; +using testing::Invoke; +using testing::InvokeWithoutArgs; + +class IpcAbilitySchedulerModuleTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp(); + void TearDown(); +}; + +void IpcAbilitySchedulerModuleTest::SetUpTestCase() +{} + +void IpcAbilitySchedulerModuleTest::TearDownTestCase() +{} + +void IpcAbilitySchedulerModuleTest::SetUp() +{} + +void IpcAbilitySchedulerModuleTest::TearDown() +{} + +/* + * Feature: AAFwk + * Function: AbilityScheduler + * SubFunction: IPC of Aafwk and AppExecFwk + * FunctionPoints: ScheduleAbilityTransaction + * EnvConditions: NA + * CaseDescription: verify ScheduleAbilityTransaction IPC between Aafwk and AppExecFwk. + */ +HWTEST_F(IpcAbilitySchedulerModuleTest, ScheduleAbilityTransaction_001, TestSize.Level3) +{ + Semaphore sem(0); + struct { + Want want; + LifeCycleStateInfo lifeCycleStateInfo; + } proxyState, stubState; + + proxyState.want.SetAction("test"); + proxyState.lifeCycleStateInfo.isNewWant = true; + + for (int i = 0; i < COUNT; i++) { + sptr stub(new MockAbilitySchedulerStub()); + sptr proxy = iface_cast(stub); + + Want::ClearWant(&stubState.want); + stubState.lifeCycleStateInfo.isNewWant = false; + + auto stubHandler = [&](const Want &want, const LifeCycleStateInfo &lifeCycleStateInfo) { + stubState.want.SetAction(want.GetAction()); + stubState.lifeCycleStateInfo.isNewWant = lifeCycleStateInfo.isNewWant; + sem.Post(); + }; + + EXPECT_CALL(*stub, ScheduleAbilityTransaction(_, _)).Times(1).WillOnce(Invoke(stubHandler)); + + proxy->ScheduleAbilityTransaction(proxyState.want, proxyState.lifeCycleStateInfo); + + sem.Wait(); + + EXPECT_EQ(stubState.want.GetAction(), proxyState.want.GetAction()); + EXPECT_EQ(stubState.lifeCycleStateInfo.isNewWant, proxyState.lifeCycleStateInfo.isNewWant); + } +} + +/* + * Feature: AAFwk + * Function: AbilityScheduler + * SubFunction: IPC of Aafwk and AppExecFwk + * FunctionPoints: SendResult + * EnvConditions: NA + * CaseDescription: verify SendResult IPC between Aafwk and AppExecFwk. + */ +HWTEST_F(IpcAbilitySchedulerModuleTest, SendResult_001, TestSize.Level3) +{ + Semaphore sem(0); + struct { + int requestCode; + int resultCode; + Want resultWant; + } proxyState, stubState; + + proxyState.requestCode = 123; + proxyState.resultCode = 456; + proxyState.resultWant.SetAction("test"); + + for (int i = 0; i < COUNT; i++) { + sptr stub(new MockAbilitySchedulerStub()); + sptr proxy = iface_cast(stub); + + stubState.requestCode = 0; + Want::ClearWant(&stubState.resultWant); + + auto stubHandler = [&](int requestCode, int resultCode, const Want &resultWant) { + stubState.requestCode = requestCode; + stubState.resultCode = resultCode; + stubState.resultWant.SetAction(resultWant.GetAction()); + sem.Post(); + }; + + EXPECT_CALL(*stub, SendResult(_, _, _)).Times(1).WillOnce(Invoke(stubHandler)); + + proxy->SendResult(proxyState.requestCode, proxyState.resultCode, proxyState.resultWant); + + sem.Wait(); + + EXPECT_EQ(stubState.requestCode, proxyState.requestCode); + EXPECT_EQ(stubState.resultCode, proxyState.resultCode); + EXPECT_EQ(stubState.resultWant.GetAction(), proxyState.resultWant.GetAction()); + } +} + +/* + * Feature: AAFwk + * Function: AbilityScheduler + * SubFunction: IPC of Aafwk and AppExecFwk + * FunctionPoints: ScheduleConnectAbility + * EnvConditions: NA + * CaseDescription: verify ScheduleConnectAbility IPC between Aafwk and AppExecFwk. + */ +HWTEST_F(IpcAbilitySchedulerModuleTest, ScheduleConnectAbility_001, TestSize.Level3) +{ + Semaphore sem(0); + struct { + Want want; + } proxyState, stubState; + + proxyState.want.SetAction("test"); + + for (int i = 0; i < COUNT; i++) { + sptr stub(new MockAbilitySchedulerStub()); + sptr proxy = iface_cast(stub); + + Want::ClearWant(&stubState.want); + + auto stubHandler = [&](const Want &want) { + stubState.want.SetAction(want.GetAction()); + sem.Post(); + }; + + EXPECT_CALL(*stub, ScheduleConnectAbility(_)).Times(1).WillOnce(Invoke(stubHandler)); + + proxy->ScheduleConnectAbility(proxyState.want); + + sem.Wait(); + + EXPECT_EQ(stubState.want.GetAction(), proxyState.want.GetAction()); + } +} + +/* + * Feature: AAFwk + * Function: AbilityScheduler + * SubFunction: IPC of Aafwk and AppExecFwk + * FunctionPoints: ScheduleDisconnectAbility + * EnvConditions: NA + * CaseDescription: verify ScheduleDisconnectAbility IPC between Aafwk and AppExecFwk. + */ +HWTEST_F(IpcAbilitySchedulerModuleTest, ScheduleDisconnectAbility_001, TestSize.Level3) +{ + Semaphore sem(0); + struct { + Want want; + } proxyState, stubState; + + proxyState.want.SetAction("test"); + + for (int i = 0; i < COUNT; i++) { + sptr stub(new MockAbilitySchedulerStub()); + sptr proxy = iface_cast(stub); + + Want::ClearWant(&stubState.want); + auto stubHandler = [&](const Want &want) { + stubState.want.SetAction(want.GetAction()); + sem.Post(); + }; + EXPECT_CALL(*stub, ScheduleDisconnectAbility(_)).Times(1).WillOnce(Invoke(stubHandler)); + + proxy->ScheduleDisconnectAbility(proxyState.want); + + sem.Wait(); + } +} + +/* + * Feature: AAFwk + * Function: AbilityScheduler + * SubFunction: IPC of Aafwk and AppExecFwk + * FunctionPoints: ScheduleSaveAbilityState + * EnvConditions: NA + * CaseDescription: verify ScheduleSaveAbilityState IPC between Aafwk and AppExecFwk. + */ +HWTEST_F(IpcAbilitySchedulerModuleTest, ScheduleSaveAbilityState_001, TestSize.Level3) +{ + Semaphore sem(0); + + for (int i = 0; i < COUNT; i++) { + sptr stub(new MockAbilitySchedulerStub()); + sptr proxy = iface_cast(stub); + + bool testResult = false; + auto mockHandler = [&](const PacMap &pacMap) { + testResult = true; + sem.Post(); + }; + + EXPECT_CALL(*stub, ScheduleSaveAbilityState(_)).Times(1).WillOnce(Invoke(mockHandler)); + + PacMap pacMap; + proxy->ScheduleSaveAbilityState(pacMap); + + sem.Wait(); + + EXPECT_TRUE(testResult); + } +} + +/* + * Feature: AAFwk + * Function: AbilityScheduler + * SubFunction: IPC of Aafwk and AppExecFwk + * FunctionPoints: ScheduleRestoreAbilityState + * EnvConditions: NA + * CaseDescription: verify ScheduleRestoreAbilityState IPC between Aafwk and AppExecFwk. + */ +HWTEST_F(IpcAbilitySchedulerModuleTest, ScheduleRestoreAbilityState_001, TestSize.Level3) +{ + Semaphore sem(0); + + for (int i = 0; i < COUNT; i++) { + sptr stub(new MockAbilitySchedulerStub()); + sptr proxy = iface_cast(stub); + + bool testResult = false; + auto mockHandler = [&](const PacMap &pacMap) { + testResult = true; + sem.Post(); + }; + + EXPECT_CALL(*stub, ScheduleRestoreAbilityState(_)).Times(1).WillOnce(Invoke(mockHandler)); + + PacMap pacMap; + proxy->ScheduleRestoreAbilityState(pacMap); + + sem.Wait(); + + EXPECT_TRUE(testResult); + } +} + +/* + * Feature: AAFwk + * Function: AbilityScheduler + * SubFunction: IPC of AMS and App + * FunctionPoints: GetFileType + * EnvConditions: NA + * CaseDescription: verify GetFileType IPC between AMS and AppFwk. + */ +HWTEST_F(IpcAbilitySchedulerModuleTest, GetFileType_001, TestSize.Level1) +{ + Semaphore sem(0); + + for (int i = 0; i < COUNT; i++) { + sptr stub(new MockAbilitySchedulerStub()); + sptr proxy = iface_cast(stub); + + bool testResult = false; + std::string testUri("dataability://test/path"); + std::string testMime("text"); + + auto mockHandler = [&](const Uri &uri, const std::string &mime) { + testResult = (mime == testMime); + std::vector ret; + ret.emplace_back("type1"); + ret.emplace_back("type2"); + sem.Post(); + return ret; + }; + + EXPECT_CALL(*stub, GetFileTypes(_, _)).Times(1).WillOnce(Invoke(mockHandler)); + + auto result = proxy->GetFileTypes(Uri(testUri), testMime); + + sem.Wait(); + + EXPECT_TRUE(testResult); + EXPECT_EQ(result.size(), size_t(2)); + EXPECT_EQ(result[0], "type1"); + EXPECT_EQ(result[1], "type2"); + } +} + +/* + * Feature: AAFwk + * Function: AbilityScheduler + * SubFunction: IPC of AMS and App + * FunctionPoints: OpenFile + * EnvConditions: NA + * CaseDescription: verify OpenFile IPC between AMS and AppFwk. + */ +HWTEST_F(IpcAbilitySchedulerModuleTest, OpenFile_001, TestSize.Level1) +{ + Semaphore sem(0); + + for (int i = 0; i < COUNT; i++) { + sptr stub(new MockAbilitySchedulerStub()); + sptr proxy = iface_cast(stub); + + bool testResult = false; + std::string testUri("dataability://test/path"); + std::string testMode("RW"); + int testRet = 123; + + auto mockHandler = [&](const Uri &uri, const std::string &mode) { + testResult = (mode == testMode); + sem.Post(); + return testRet; + }; + + EXPECT_CALL(*stub, OpenFile(_, _)).Times(1).WillOnce(Invoke(mockHandler)); + + auto result = proxy->OpenFile(Uri(testUri), testMode); + + sem.Wait(); + + EXPECT_TRUE(testResult); + EXPECT_EQ(result, testRet); + } +} + +/* + * Feature: AAFwk + * Function: AbilityScheduler + * SubFunction: IPC of AMS and App + * FunctionPoints: Insert + * EnvConditions: NA + * CaseDescription: verify Insert IPC between AMS and AppFwk. + */ +HWTEST_F(IpcAbilitySchedulerModuleTest, Insert_001, TestSize.Level1) +{ + Semaphore sem(0); + + for (int i = 0; i < COUNT; i++) { + sptr stub(new MockAbilitySchedulerStub()); + sptr proxy = iface_cast(stub); + + bool testResult = false; + std::string testUri("dataability://test/path"); + NativeRdb::ValuesBucket testValues; + int testRet = 123; + + auto mockHandler = [&](const Uri &uri, const NativeRdb::ValuesBucket &vb) { + testResult = true; + sem.Post(); + return testRet; + }; + + EXPECT_CALL(*stub, Insert(_, _)).Times(1).WillOnce(Invoke(mockHandler)); + + auto result = proxy->Insert(Uri(testUri), testValues); + + sem.Wait(); + + EXPECT_TRUE(testResult); + EXPECT_EQ(result, testRet); + } +} + +/* + * Feature: AAFwk + * Function: AbilityScheduler + * SubFunction: IPC of AMS and App + * FunctionPoints: Update + * EnvConditions: NA + * CaseDescription: verify Update IPC between AMS and AppFwk. + */ +HWTEST_F(IpcAbilitySchedulerModuleTest, Update_001, TestSize.Level1) +{ + Semaphore sem(0); + + for (int i = 0; i < COUNT; i++) { + sptr stub(new MockAbilitySchedulerStub()); + sptr proxy = iface_cast(stub); + + bool testResult = false; + std::string testUri("dataability://test/path"); + NativeRdb::ValuesBucket testValues; + NativeRdb::DataAbilityPredicates testPred; + int testRet = 123; + + auto mockHandler = [&](const Uri &uri, const NativeRdb::ValuesBucket &vb, const NativeRdb::DataAbilityPredicates &pred) { + testResult = true; + sem.Post(); + return testRet; + }; + + EXPECT_CALL(*stub, Update(_, _, _)).Times(1).WillOnce(Invoke(mockHandler)); + + auto result = proxy->Update(Uri(testUri), testValues, testPred); + + sem.Wait(); + + EXPECT_TRUE(testResult); + EXPECT_EQ(result, testRet); + } +} + +/* + * Feature: AAFwk + * Function: AbilityScheduler + * SubFunction: IPC of AMS and App + * FunctionPoints: Delete + * EnvConditions: NA + * CaseDescription: verify Delete IPC between AMS and AppFwk. + */ +HWTEST_F(IpcAbilitySchedulerModuleTest, Delete_001, TestSize.Level1) +{ + Semaphore sem(0); + + for (int i = 0; i < COUNT; i++) { + sptr stub(new MockAbilitySchedulerStub()); + sptr proxy = iface_cast(stub); + + bool testResult = false; + std::string testUri("dataability://test/path"); + NativeRdb::DataAbilityPredicates testPred; + int testRet = 123; + + auto mockHandler = [&](const Uri &uri, const NativeRdb::DataAbilityPredicates &pred) { + testResult = true; + sem.Post(); + return testRet; + }; + + EXPECT_CALL(*stub, Delete(_, _)).Times(1).WillOnce(Invoke(mockHandler)); + + auto result = proxy->Delete(Uri(testUri), testPred); + + sem.Wait(); + + EXPECT_TRUE(testResult); + EXPECT_EQ(result, testRet); + } +} + +/* + * Feature: AAFwk + * Function: AbilityScheduler + * SubFunction: IPC of AMS and App + * FunctionPoints: Query + * EnvConditions: NA + * CaseDescription: verify Query IPC between AMS and AppFwk. + */ +HWTEST_F(IpcAbilitySchedulerModuleTest, Query_001, TestSize.Level1) +{ + Semaphore sem(0); + + for (int i = 0; i < COUNT; i++) { + sptr stub(new MockAbilitySchedulerStub()); + sptr proxy = iface_cast(stub); + + bool testResult = false; + std::string testUri("dataability://test/path"); + std::vector testColumns; + testColumns.emplace_back("col1"); + testColumns.emplace_back("col2"); + NativeRdb::DataAbilityPredicates testPred; + + auto mockHandler = [&](const Uri &uri, std::vector &columns, const NativeRdb::DataAbilityPredicates &pred) { + testResult = (columns == testColumns); + sem.Post(); + return std::make_shared("DataAbilityTest"); + }; + + EXPECT_CALL(*stub, Query(_, _, _)).Times(1).WillOnce(Invoke(mockHandler)); + + auto result = proxy->Query(Uri(testUri), testColumns, testPred); + + sem.Wait(); + + EXPECT_TRUE(testResult); + EXPECT_TRUE(result); + } +} + +/* + * Feature: AAFwk + * Function: AbilityScheduler + * SubFunction: IPC of Aafwk and AppExecFwk + * FunctionPoints: ScheduleCommandAbility + * EnvConditions: NA + * CaseDescription: verify ScheduleCommandAbility IPC between Aafwk and AppExecFwk. + */ +HWTEST_F(IpcAbilitySchedulerModuleTest, ScheduleCommandAbility_001, TestSize.Level1) +{ + Semaphore sem(0); + struct { + Want want; + } proxyState, stubState; + + proxyState.want.SetAction("test"); + static int count = 0; + for (int i = 0; i < COUNT; i++) { + sptr stub(new MockAbilitySchedulerStub()); + sptr proxy(new AbilitySchedulerProxy(stub)); + // sptr proxy = iface_cast(stub); + + Want::ClearWant(&stubState.want); + auto stubHandler = [&](const Want &want, bool reStart, int startId) { + stubState.want.SetAction(want.GetAction()); + count++; + sem.Post(); + }; + EXPECT_CALL(*stub, ScheduleCommandAbility(_, _, _)).Times(1).WillOnce(Invoke(stubHandler)); + proxy->ScheduleCommandAbility(proxyState.want, false, i + 1); + sem.Wait(); + } + + bool testResult = (count == COUNT); + EXPECT_TRUE(testResult); +} \ No newline at end of file diff --git a/tools/services/test/moduletest/module_test_dump_util/BUILD.gn b/tools/services/test/moduletest/module_test_dump_util/BUILD.gn new file mode 100644 index 00000000000..974a65c3c91 --- /dev/null +++ b/tools/services/test/moduletest/module_test_dump_util/BUILD.gn @@ -0,0 +1,37 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") +import("//foundation/aafwk/standard/aafwk.gni") +import("//foundation/aafwk/standard/services/abilitymgr/abilitymgr.gni") + +group("module_test_dump_util") { + deps = [ ":module_test_dump_util_lib" ] +} + +config("module_test_dump_util_config") { + include_dirs = [ "//foundation/aafwk/standard/services/test/moduletest/module_test_dump_util/" ] +} + +ohos_shared_library("module_test_dump_util_lib") { + sources = [ "//foundation/aafwk/standard/services/test/moduletest/module_test_dump_util/module_test_dump_util.cpp" ] + + configs = [ ":module_test_dump_util_config" ] + + deps = [ "//utils/native/base:utils" ] + + external_deps = [ "hiviewdfx_hilog_native:libhilog" ] + + subsystem_name = "aafwk" + part_name = "aafwk_standard" +} diff --git a/tools/services/test/moduletest/module_test_dump_util/module_test_dump_util.cpp b/tools/services/test/moduletest/module_test_dump_util/module_test_dump_util.cpp new file mode 100644 index 00000000000..35b63c205d0 --- /dev/null +++ b/tools/services/test/moduletest/module_test_dump_util/module_test_dump_util.cpp @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define private public +#include "module_test_dump_util.h" +#undef private + +namespace OHOS { +namespace MTUtil { +std::mutex MTDumpUtil::mutex_; +std::shared_ptr MTDumpUtil::instance_ = nullptr; + +std::shared_ptr MTDumpUtil::GetInstance() +{ + if (instance_ == nullptr) { + std::lock_guard lock_l(mutex_); + if (instance_ == nullptr) { + instance_ = std::make_shared(); + } + } + return instance_; +} + +MTDumpUtil::MTDumpUtil() +{ + findRgx_["Intent"] = regex(".*intent\\[(.+)\\].*"); + findRgx_["AbilityName"] = regex(".*main name \\[(.+)\\].*"); + findRgx_["AppName"] = regex(".*app name \\[(.+)\\].*"); + findRgx_["BundleName"] = regex(".*bundle name \\[(.+)\\].*"); + findRgx_["AbilityType"] = regex(".*ability type \\[(.+)\\].*"); + findRgx_["PreAbilityName"] = regex(".*previous ability app name \\[(.+)\\].*"); + findRgx_["PreAppName"] = regex(".*previous ability file name \\[(.+)\\].*"); + findRgx_["NextAbilityName"] = regex(".*next ability app name \\[(.+)\\].*"); + findRgx_["NextAppName"] = regex(".*next ability file name \\[(.+)\\].*"); + findRgx_["State"] = regex(".*state #(.+) .*"); + findRgx_["StartTime"] = regex(".*start time \\[(.+)\\].*"); + findRgx_["MissionRecordID"] = regex(".*MissionRecord ID #(.+) bottom app.*"); + findRgx_["MissionBottomApp"] = regex(".*bottom app \\[(.+)\\].*"); + findRgx_["UserID"] = regex(".*User ID #(.+)\\].*"); + findRgx_["MissionStackID"] = regex(".*MissionStack ID #(.+) \\[.*"); + findRgx_["Uri"] = regex(".*uri \\[(.+)\\].*"); + findRgx_["AbilityRecordID"] = regex(".*AbilityRecord ID #(.+) state.*"); + findRgx_["Bindings"] = regex(".+s: (\\d+).*"); + findRgx_["Component"] = regex(".*> (.+) .+#.+"); + findRgx_["BindState"] = regex(".*> .+/.+ #(.+)"); +} + +MTDumpUtil::~MTDumpUtil() +{ + instance_ = nullptr; + instance_.reset(); +} + +bool MTDumpUtil::CompStrVec(const str_vec &strVec_1, const str_vec &strVec_2) +{ + if (strVec_1.size() != strVec_2.size()) { + return false; + } + for (unsigned int i = 0; i < strVec_1.size(); ++i) { + if (strVec_1[i].compare(strVec_2[i]) != 0) { + return false; + } + } + return true; +} + +str_iter MTDumpUtil::GetSpecific(const string &matchStr, const str_vec &dumpInfo, const str_iter &begin) +{ + auto checkCondition = [&matchStr](const str_vec::value_type &value) -> bool { + return string::npos != value.find(matchStr); + }; + str_iter end; + std::advance(end, dumpInfo.size()); + return std::find_if(begin, end, checkCondition); +} + +bool MTDumpUtil::MatchRegex(const regex &rgx, const string &text, string &result) +{ + std::smatch baseMatch; + std::size_t size = 2; + if (std::regex_match(text, baseMatch, rgx)) { + if (baseMatch.size() == size) { + result = baseMatch[1].str(); + return true; + } + } + return false; +} + +size_t MTDumpUtil::GetAll(const string &args, const str_vec &dumpInfo, str_vec &results) +{ + results.clear(); + // args not exist + if (findRgx_.find(args) == findRgx_.end()) { + return 0; + } + string findResult; + for (const auto &info : dumpInfo) { + if (MatchRegex(findRgx_[args], info, findResult)) { + results.emplace_back(findResult); + } + } + return results.size(); +} + +str_iter MTDumpUtil::GetFirst(const string &args, const str_vec &dumpInfo, const str_iter &begin, string &result) +{ + result.clear(); + str_iter end; + std::advance(end, dumpInfo.size()); + // args not exist + if (findRgx_.find(args) == findRgx_.end()) { + return end; + } + string findResult; + for (auto it = begin; it != dumpInfo.end(); ++it) { + if (MatchRegex(findRgx_[args], *it, findResult)) { + result = std::move(findResult); + return it; + } + } + return end; +} + +string MTDumpUtil::GetBy(const string &key, const string &value, const string &args, const str_vec &dumpInfo) +{ + str_vec items; + size_t preSize = GetAll(key, dumpInfo, items); + auto iter = GetSpecific(value, items, items.begin()); + if (iter != items.end() && preSize == GetAll(args, dumpInfo, items)) { + return *iter; + } + return ""; +} + +size_t MTDumpUtil::GetBindingsByUri(const string &uri, const str_vec &dumpInfo, str_vec &result) +{ + result.clear(); + str_vec dump(dumpInfo); + string bindings; + auto uriBegin = GetSpecific("uri [" + uri + "]", dump, dump.begin()); + auto bindingsBegin = GetFirst("Bindings", dump, uriBegin, bindings) + 1; + size_t ret = std::stoul("0" + bindings); + std::for_each(bindingsBegin, + (((bindingsBegin + ret) > dump.end()) ? (dump.end()) : (bindingsBegin + ret)), + [&result](auto &&it) { result.push_back(it); }); + return ret; +} + +} // namespace MTUtil +} // namespace OHOS diff --git a/tools/services/test/moduletest/module_test_dump_util/module_test_dump_util.h b/tools/services/test/moduletest/module_test_dump_util/module_test_dump_util.h new file mode 100644 index 00000000000..a6083c61aad --- /dev/null +++ b/tools/services/test/moduletest/module_test_dump_util/module_test_dump_util.h @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_MODULE_TEST_DUMP_UTIL_H +#define OHOS_MODULE_TEST_DUMP_UTIL_H + +#include +#include +#include +#include +#include +#include +#include + +namespace OHOS { +namespace MTUtil { + +using str_vec = std::vector; +using str_iter = std::vector::iterator; +using dump_info_map = std::unordered_map; +using std::regex; +using std::string; + +class MTDumpUtil { +public: + virtual ~MTDumpUtil(); + static std::shared_ptr GetInstance(); + + /** + * + * @param {string} args : type to find + * @param {std::vector} dumpInfo : dump info + * @param {std::vector} results : all strings found that include @args + * @return {int} : size of @results + * @Introduction: Find all strings specified by @args in @dumpInfo and store them in @results. + */ + size_t GetAll(const string &args, const str_vec &dumpInfo, str_vec &results); + + /** + * + * @param {string} args : type to find + * @param {std::vector} dumpInfo : dump info + * @param {string} result : the first string found that includes @args + * @return {str_iter} : find or not + * @Introduction: Find the first string specified by @args in @dumpInfo and store it in @result. + */ + str_iter GetFirst(const string &args, const str_vec &dumpInfo, const str_iter &begin, string &result); + + /** + * + * @param {string} args : specific string to find + * @param {std::vector} dumpInfo : dump info + * @param {str_iter} begin : where to start searching + * @return {str_iter} : iter pointing to string containing @args + * @Introduction: Match the first @matchStr in @dumpInfo from @begin and return the iter. + */ + str_iter GetSpecific(const string &args, const str_vec &dumpInfo, const str_iter &begin); + + /** + * + * @param {str_vec} strVec_1 : the first vector of string + * @param {str_vec} strVec_2 : the second vector of string + * @return {bool} : the comparison result of the the params + * @Introduction: Return true if each item in @strVec_1 equals the corresponding one in @strVec_2. + */ + bool CompStrVec(const str_vec &strVec_1, const str_vec &strVec_2); + + /** + * + * @param {string} key : known type used to find info + * @param {string} value : value of the {key} + * @param {string} args : type to find + * @param {str_vec} dumpInfo : dump info + * @return {string} : string found in dumpInfo + * @Introduction: Return the value specified by @args with @key and @value in @dumpInfo. + */ + string GetBy(const string &key, const string &value, const string &args, const str_vec &dumpInfo); + + size_t GetBindingsByUri(const string &uri, const str_vec &dumpInfo, str_vec &result); + +private: + MTDumpUtil(); + static std::mutex mutex_; + static std::shared_ptr instance_; + std::unordered_map findRgx_; + + inline bool MatchRegex(const regex ®ex, const string &str, string &result); +}; + +} // namespace MTUtil +} // namespace OHOS +#endif // OHOS_MODULE_TEST_DUMP_UTIL_H diff --git a/tools/services/test/moduletest/panding_want_manager_test/BUILD.gn b/tools/services/test/moduletest/panding_want_manager_test/BUILD.gn new file mode 100755 index 00000000000..30fd8f67114 --- /dev/null +++ b/tools/services/test/moduletest/panding_want_manager_test/BUILD.gn @@ -0,0 +1,88 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/test.gni") +import("//foundation/aafwk/standard/aafwk.gni") +import("//foundation/aafwk/standard/services/abilitymgr/abilitymgr.gni") + +module_output_path = "aafwk_standard/mstabilitymgrservice" + +ohos_moduletest("PandingWantMgrTest") { + module_out_path = module_output_path + + include_dirs = [ + "//foundation/aafwk/standard/services/test/mock/include", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy/include", + "//foundation/distributedschedule/samgr/adapter/interfaces/innerkits/include/", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_core/include/appmg", + "//foundation/appexecfwk/standard/kits/appkit/native/app/include", + "//base/notification/ns_standard/interfaces/innerkits/wantagent/include", + "//third_party/jsoncpp/include", + "//base/notification/ans_standard/interfaces/innerkits/wantagent/include", + ] + + sources = abilityms_files + sources += [ + "//base/notification/ans_standard/frameworks/wantagent/src/completed_dispatcher.cpp", + "//base/notification/ans_standard/frameworks/wantagent/src/pending_want.cpp", + "//base/notification/ans_standard/frameworks/wantagent/src/trigger_info.cpp", + "//base/notification/ans_standard/frameworks/wantagent/src/want_agent.cpp", + "//base/notification/ans_standard/frameworks/wantagent/src/want_agent_helper.cpp", + "//base/notification/ans_standard/frameworks/wantagent/src/want_agent_info.cpp", + "//base/notification/ans_standard/frameworks/wantagent/src/want_agent_log_wrapper.cpp", + "//foundation/aafwk/standard/services/abilitymgr/src/ability_manager_client.cpp", + "//foundation/aafwk/standard/services/abilitymgr/test/mock/libs/sa_mgr/src/sa_mgr_client_mock.cpp", + "//foundation/aafwk/standard/services/test/mock/src/mock_app_mgr_client.cpp", + "//foundation/aafwk/standard/services/test/mock/src/mock_bundle_mgr.cpp", + "//foundation/appexecfwk/standard/common/log/src/app_log_wrapper.cpp", + "panding_want_manager_test.cpp", + ] + + configs = [ "${services_path}/abilitymgr:abilityms_config" ] + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + + deps = [ + "${innerkits_path}/want:want", + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/frameworks/kits/ability/native:dummy_classes", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_core:appexecfwk_core", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/distributedschedule/dmsfwk/interfaces/innerkits/uri:zuri", + "//foundation/distributedschedule/safwk/interfaces/innerkits/safwk:system_ability_fwk", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy:samgr_proxy", + "//third_party/googletest:gmock_main", + "//third_party/googletest:gtest_main", + "//third_party/jsoncpp:jsoncpp", + "//utils/native/base:utils", + ] + + external_deps = [ + "ces_standard:cesfwk_core", + "ces_standard:cesfwk_innerkits", + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + "native_appdatamgr:native_appdatafwk", + "native_appdatamgr:native_dataability", + "native_appdatamgr:native_rdb", + ] +} + +group("moduletest") { + testonly = true + + deps = [ ":PandingWantMgrTest" ] +} diff --git a/tools/services/test/moduletest/panding_want_manager_test/panding_want_manager_test.cpp b/tools/services/test/moduletest/panding_want_manager_test/panding_want_manager_test.cpp new file mode 100644 index 00000000000..b4732de8c88 --- /dev/null +++ b/tools/services/test/moduletest/panding_want_manager_test/panding_want_manager_test.cpp @@ -0,0 +1,734 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#define private public +#define protected public +#include "sa_mgr_client.h" +#include "pending_want_manager.h" +#include "app_scheduler.h" +#include "ability_manager_service.h" +#include "want_agent_helper.h" +#include "ability_manager_client.h" +#undef private +#undef protected + +#include "system_ability_definition.h" +#include "mock_ability_scheduler.h" +#include "mock_app_mgr_client.h" +#include "pending_want.h" +#include "mock_want_receiver.h" +#include "mock_bundle_mgr.h" +#include "ability_context.h" +#include "mock_compled_callback.h" +#include "mock_ability_mgr_service.h" + +using namespace OHOS::Notification::WantAgent; +using namespace OHOS::AppExecFwk; + +using namespace testing; +using testing::_; +using testing::Invoke; +using testing::Return; +using namespace testing::ext; + +namespace OHOS { +namespace AAFwk { +namespace { +static const int FLAG_ONE_SHOT = 1 << 30; +int abilityRequestCode = 1; +int abilitiesRequestCode = 2; +int serviceRequestCode = 3; +int foregroundServicesRequestCode = 4; +int commonEventRequestCode = 4; +} // namespace +class PandingWantManagerTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + WantSenderInfo GetAbility(); + WantSenderInfo GetAbilities(); + WantSenderInfo GetService(); + WantSenderInfo GetForegroundService(); + WantSenderInfo GetCommonEvent(); + std::shared_ptr GetWant(std::string abilityName, std::string bundleName); + WantAgentInfo MakeWantAgentInfo(WantAgentConstant::OperationType &type, int requestCode, + std::vector &flags, std::vector> wants); + +public: + MockWantReceiver *receiver = new MockWantReceiver(); + inline static MockAppMgrClient *appClient = nullptr; + inline static std::shared_ptr ams = nullptr; + MockAbilityMgrService *amsSerice = new MockAbilityMgrService(); +}; + +void PandingWantManagerTest::SetUpTestCase(void) +{ + OHOS::DelayedSingleton::DestroyInstance(); + OHOS::DelayedSingleton::GetInstance()->RegisterSystemAbility( + OHOS::BUNDLE_MGR_SERVICE_SYS_ABILITY_ID, new (std::nothrow) BundleMgrService()); + + ams = OHOS::DelayedSingleton::GetInstance(); + ams->OnStart(); + + auto appScheduler = DelayedSingleton::GetInstance(); + appClient = new MockAppMgrClient(); + if (appClient) { + appScheduler->appMgrClient_.reset(appClient); + GTEST_LOG_(INFO) << "mock appMgrClient_ ok"; + } +} + +void PandingWantManagerTest::TearDownTestCase(void) +{ + OHOS::DelayedSingleton::DestroyInstance(); + if (appClient) { + delete appClient; + appClient = nullptr; + } +} + +void PandingWantManagerTest::SetUp() +{ + if (amsSerice == nullptr) { + amsSerice = new MockAbilityMgrService(); + } + AbilityManagerClient::GetInstance(); + AbilityManagerClient::GetInstance()->remoteObject_ = amsSerice; +} + +void PandingWantManagerTest::TearDown() +{} + +std::shared_ptr PandingWantManagerTest::GetWant(std::string abilityName, std::string bundleName) +{ + if (abilityName == "") { + abilityName = "hiMusic"; + } + if (bundleName == "") { + bundleName = "com.ix.hiMusic"; + } + + ElementName element; + element.SetDeviceID("devices"); + element.SetAbilityName(abilityName); + element.SetBundleName(bundleName); + Want want; + want.SetElement(element); + return std::make_shared(want); +} + +WantSenderInfo PandingWantManagerTest::GetAbility() +{ + int32_t flags = FLAG_ONE_SHOT; + WantsInfo wantsInfo; + wantsInfo.want = *(GetWant("hiMusic", "com.ix.hiMusic")); + wantsInfo.resolvedTypes = wantsInfo.want.GetType(); + + WantSenderInfo wantSenderInfo; + wantSenderInfo.type = (int32_t)WantAgentConstant::OperationType::START_ABILITY; + wantSenderInfo.allWants.push_back(wantsInfo); + wantSenderInfo.bundleName = "ix.com.hiMusic"; + wantSenderInfo.flags = flags; + wantSenderInfo.userId = 0; + wantSenderInfo.requestCode = abilityRequestCode; + wantSenderInfo.resultWho = "GetAbility"; + GTEST_LOG_(INFO) << "GetAbility"; + return wantSenderInfo; +} + +WantSenderInfo PandingWantManagerTest::GetAbilities() +{ + int32_t flags = (int32_t)FLAG_ONE_SHOT; + + WantsInfo wantsInfo; + wantsInfo.want = *(GetWant("hiMusic", "com.ix.hiMusic")); + wantsInfo.resolvedTypes = wantsInfo.want.GetType(); + + WantsInfo wantsInfo2; + wantsInfo2.want = *(GetWant("hiRadio", "com.ix.hiRadio")); + wantsInfo2.resolvedTypes = wantsInfo2.want.GetType(); + + WantSenderInfo wantSenderInfo; + wantSenderInfo.type = (int32_t)WantAgentConstant::OperationType::START_ABILITIES; + wantSenderInfo.bundleName = "ix.com.hiRadio"; + wantSenderInfo.flags = flags; + wantSenderInfo.userId = 0; + wantSenderInfo.requestCode = abilitiesRequestCode; + wantSenderInfo.resultWho = "GetAbilities"; + wantSenderInfo.allWants.push_back(wantsInfo); + wantSenderInfo.allWants.push_back(wantsInfo2); + GTEST_LOG_(INFO) << "GetAbilities"; + return wantSenderInfo; +} + +WantSenderInfo PandingWantManagerTest::GetService() +{ + int32_t flags = FLAG_ONE_SHOT; + + WantsInfo wantsInfo; + wantsInfo.want = *(GetWant("hiService", "com.ix.hiService")); + wantsInfo.resolvedTypes = wantsInfo.want.GetType(); + + WantSenderInfo wantSenderInfo; + wantSenderInfo.type = (int32_t)WantAgentConstant::OperationType::START_SERVICE; + wantSenderInfo.allWants.push_back(wantsInfo); + wantSenderInfo.bundleName = "com.ix.hiService"; + wantSenderInfo.flags = flags; + wantSenderInfo.userId = 0; + wantSenderInfo.requestCode = serviceRequestCode; + wantSenderInfo.resultWho = "GetService"; + GTEST_LOG_(INFO) << "GetService"; + return wantSenderInfo; +} + +WantSenderInfo PandingWantManagerTest::GetForegroundService() +{ + int32_t flags = FLAG_ONE_SHOT; + + WantsInfo wantsInfo; + wantsInfo.want = *(GetWant("hiService", "com.ix.hiService")); + wantsInfo.resolvedTypes = wantsInfo.want.GetType(); + + WantSenderInfo wantSenderInfo; + wantSenderInfo.type = (int32_t)WantAgentConstant::OperationType::START_FOREGROUND_SERVICE; + wantSenderInfo.allWants.push_back(wantsInfo); + wantSenderInfo.bundleName = "ix.com.hiworld"; + wantSenderInfo.flags = flags; + wantSenderInfo.userId = 0; + wantSenderInfo.requestCode = foregroundServicesRequestCode; + GTEST_LOG_(INFO) << "GetForegroundService"; + return wantSenderInfo; +} + +WantSenderInfo PandingWantManagerTest::GetCommonEvent() +{ + int32_t flags = FLAG_ONE_SHOT; + + WantsInfo wantsInfo; + wantsInfo.want = *(GetWant("hiMusic", "com.ix.hiMusic")); + wantsInfo.resolvedTypes = wantsInfo.want.GetType(); + + WantSenderInfo wantSenderInfo; + wantSenderInfo.type = (int32_t)WantAgentConstant::OperationType::SEND_COMMON_EVENT; + wantSenderInfo.allWants.push_back(wantsInfo); + wantSenderInfo.bundleName = "ix.com.hiworld"; + wantSenderInfo.flags = flags; + wantSenderInfo.userId = 0; + wantSenderInfo.requestCode = commonEventRequestCode; + GTEST_LOG_(INFO) << "GetCommonEvent"; + return wantSenderInfo; +} + +WantAgentInfo PandingWantManagerTest::MakeWantAgentInfo(WantAgentConstant::OperationType &type, int requestCode, + std::vector &flags, std::vector> wants) +{ + WantAgentInfo info; + info.operationType_ = type; + info.requestCode_ = requestCode; + info.flags_ = flags; + info.wants_ = wants; + info.extraInfo_ = nullptr; + return info; +} + +/* + * Feature: AaFwk + * Function: GetWantSender + * SubFunction: start a page ability + * FunctionPoints: NA + * EnvConditions: NA + * CaseDescription: get want sender / send want sender + */ +HWTEST_F(PandingWantManagerTest, pending_want_mgr_test_001, TestSize.Level1) +{ + WantAgentConstant::OperationType type = WantAgentConstant::OperationType::START_ABILITY; + int requsetCode = 10; + WantAgentConstant::Flags flag = WantAgentConstant::Flags::ONE_TIME_FLAG; + std::vector flags; + flags.push_back(flag); + + auto abilityWant = GetWant("hiMusic", "com.ix.hiMusic"); + std::vector> wants; + wants.push_back(abilityWant); + + WantAgentInfo info = MakeWantAgentInfo(type, requsetCode, flags, wants); + std::shared_ptr context = std::make_shared(); + + // proxy start + auto amsProxyGetWantSenderReturn = [&](const WantSenderInfo &wantSenderInfo, + const sptr &callerToken) { + EXPECT_EQ(wantSenderInfo.type, (int32_t)WantAgentConstant::OperationType::START_ABILITY); + return ams->GetWantSender(wantSenderInfo, callerToken); + }; + EXPECT_CALL(*amsSerice, GetWantSender(_, _)).Times(1).WillOnce(Invoke(amsProxyGetWantSenderReturn)); + + auto amsProxySendWantSenderReturn = [&](const sptr &target, const SenderInfo &senderInfo) { + return ams->SendWantSender(target, senderInfo); + }; + EXPECT_CALL(*amsSerice, SendWantSender(_, _)).Times(1).WillOnce(Invoke(amsProxySendWantSenderReturn)); + EXPECT_CALL(*amsSerice, GetPendingWantType(_)).Times(1).WillOnce(Return(0)); + + // proxy end + // call GetWantAgent + std::shared_ptr wantAgent = WantAgentHelper::GetWantAgent(context, info); + EXPECT_NE(wantAgent, nullptr); + auto pandingWant = wantAgent->GetPendingWant(); + EXPECT_NE(pandingWant, nullptr); + + // ams mock + EXPECT_CALL(*appClient, LoadAbility(_, _, _, _)).Times(1).WillOnce(Return(AppMgrResultCode::RESULT_OK)); + + std::shared_ptr callback; + MockCompletedCallback *call = new MockCompletedCallback(); + callback.reset(call); + + TriggerInfo paramsInfo("", nullptr, abilityWant, 11); + + EXPECT_CALL(*call, OnSendFinished(_, _, _, _)).Times(1); + WantAgentHelper::TriggerWantAgent(context, wantAgent, callback, paramsInfo); + + // An ability should be activated + auto stackMgr = ams->GetStackManager(); + EXPECT_NE(stackMgr, nullptr); + auto topAbility = stackMgr->GetCurrentTopAbility(); + EXPECT_NE(topAbility, nullptr); + Want topAbilityWant = topAbility->GetWant(); + ElementName element = topAbilityWant.GetElement(); + + EXPECT_EQ(element.GetAbilityName(), "hiMusic"); + EXPECT_EQ(element.GetBundleName(), "com.ix.hiMusic"); +} + +/* + * Feature: AaFwk + * Function: GetWantSender + * SubFunction: start page abilites + * FunctionPoints: NA + * EnvConditions: NA + * CaseDescription: get want sender / send want sender + */ +HWTEST_F(PandingWantManagerTest, pending_want_mgr_test_002, TestSize.Level1) +{ + WantAgentConstant::OperationType type = WantAgentConstant::OperationType::START_ABILITIES; + int requsetCode = 10; + WantAgentConstant::Flags flag = WantAgentConstant::Flags::ONE_TIME_FLAG; + WantAgentConstant::Flags flag1 = WantAgentConstant::Flags::ONE_TIME_FLAG; + std::vector flags; + flags.push_back(flag); + flags.push_back(flag1); + + auto abilityWant = GetWant("hiMusic", "com.ix.hiMusic"); + auto abilityWant1 = GetWant("hiRedio", "com.ix.hiRedio"); + std::vector> wants; + wants.push_back(abilityWant); + wants.push_back(abilityWant1); + + WantAgentInfo info = MakeWantAgentInfo(type, requsetCode, flags, wants); + std::shared_ptr context = std::make_shared(); + + // proxy start + auto amsProxyGetWantSenderReturn = [&](const WantSenderInfo &wantSenderInfo, + const sptr &callerToken) { + EXPECT_EQ(wantSenderInfo.type, (int32_t)WantAgentConstant::OperationType::START_ABILITIES); + return ams->GetWantSender(wantSenderInfo, callerToken); + }; + EXPECT_CALL(*amsSerice, GetWantSender(_, _)).Times(1).WillOnce(Invoke(amsProxyGetWantSenderReturn)); + + auto amsProxySendWantSenderReturn = [&](const sptr &target, const SenderInfo &senderInfo) { + return ams->SendWantSender(target, senderInfo); + }; + EXPECT_CALL(*amsSerice, SendWantSender(_, _)).Times(1).WillOnce(Invoke(amsProxySendWantSenderReturn)); + EXPECT_CALL(*amsSerice, GetPendingWantType(_)).Times(1).WillOnce(Return(0)); + // proxy end + + // call GetWantAgent + std::shared_ptr wantAgent = WantAgentHelper::GetWantAgent(context, info); + EXPECT_NE(wantAgent, nullptr); + auto pandingWant = wantAgent->GetPendingWant(); + EXPECT_NE(pandingWant, nullptr); + + std::shared_ptr callback; + MockCompletedCallback *call = new MockCompletedCallback(); + callback.reset(call); + + TriggerInfo paramsInfo("", nullptr, abilityWant, 11); + + EXPECT_CALL(*call, OnSendFinished(_, _, _, _)).Times(1); + + auto stackMgr = ams->GetStackManager(); + EXPECT_NE(stackMgr, nullptr); + auto topAbility = stackMgr->GetCurrentTopAbility(); + EXPECT_NE(topAbility, nullptr); + topAbility->SetAbilityState(OHOS::AAFwk::AbilityState::ACTIVE); + + WantAgentHelper::TriggerWantAgent(context, wantAgent, callback, paramsInfo); +} + +/* + * Feature: AaFwk + * Function: GetWantSender + * SubFunction: start services ability + * FunctionPoints: NA + * EnvConditions: NA + * CaseDescription: get want sender / send want sender + */ +HWTEST_F(PandingWantManagerTest, pending_want_mgr_test_003, TestSize.Level1) +{ + WantAgentConstant::OperationType type = WantAgentConstant::OperationType::START_SERVICE; + int requsetCode = 10; + WantAgentConstant::Flags flag = WantAgentConstant::Flags::ONE_TIME_FLAG; + std::vector flags; + flags.push_back(flag); + + auto abilityWant = GetWant("hiService", "com.ix.hiService"); + std::vector> wants; + wants.push_back(abilityWant); + + WantAgentInfo info = MakeWantAgentInfo(type, requsetCode, flags, wants); + std::shared_ptr context = std::make_shared(); + + // proxy start + auto amsProxyGetWantSenderReturn = [&](const WantSenderInfo &wantSenderInfo, + const sptr &callerToken) { + EXPECT_EQ(wantSenderInfo.type, (int32_t)WantAgentConstant::OperationType::START_SERVICE); + return ams->GetWantSender(wantSenderInfo, callerToken); + }; + EXPECT_CALL(*amsSerice, GetWantSender(_, _)).Times(1).WillOnce(Invoke(amsProxyGetWantSenderReturn)); + + auto amsProxySendWantSenderReturn = [&](const sptr &target, const SenderInfo &senderInfo) { + return ams->SendWantSender(target, senderInfo); + }; + EXPECT_CALL(*amsSerice, SendWantSender(_, _)).Times(1).WillOnce(Invoke(amsProxySendWantSenderReturn)); + EXPECT_CALL(*amsSerice, GetPendingWantType(_)).Times(1).WillOnce(Return(0)); + + // proxy end + // call GetWantAgent + std::shared_ptr wantAgent = WantAgentHelper::GetWantAgent(context, info); + EXPECT_NE(wantAgent, nullptr); + auto pandingWant = wantAgent->GetPendingWant(); + EXPECT_NE(pandingWant, nullptr); + + // ams mock + EXPECT_CALL(*appClient, LoadAbility(_, _, _, _)).Times(1).WillOnce(Return(AppMgrResultCode::RESULT_OK)); + + std::shared_ptr callback; + MockCompletedCallback *call = new MockCompletedCallback(); + callback.reset(call); + + TriggerInfo paramsInfo("", nullptr, abilityWant, 11); + + EXPECT_CALL(*call, OnSendFinished(_, _, _, _)).Times(1); + WantAgentHelper::TriggerWantAgent(context, wantAgent, callback, paramsInfo); + + // An ability should be activated + auto serviceRecord = ams->connectManager_->GetServiceRecordByElementName(abilityWant->GetElement().GetURI()); + EXPECT_TRUE(serviceRecord); + Want serviceWant = serviceRecord->GetWant(); + ElementName element = serviceWant.GetElement(); + + EXPECT_EQ(element.GetAbilityName(), "hiService"); + EXPECT_EQ(element.GetBundleName(), "com.ix.hiService"); +} + +/* + * Feature: AaFwk + * Function: GetWantSender + * SubFunction: get foreground service ability + * FunctionPoints: NA + * EnvConditions: NA + * CaseDescription: get want sender / send want sender + */ +HWTEST_F(PandingWantManagerTest, pending_want_mgr_test_004, TestSize.Level1) +{ + WantAgentConstant::OperationType type = WantAgentConstant::OperationType::START_FOREGROUND_SERVICE; + int requsetCode = 112; + WantAgentConstant::Flags flag = WantAgentConstant::Flags::ONE_TIME_FLAG; + std::vector flags; + flags.push_back(flag); + + auto abilityWant = GetWant("hiServiceForground", "com.ix.hiService"); + std::vector> wants; + wants.push_back(abilityWant); + + WantAgentInfo info = MakeWantAgentInfo(type, requsetCode, flags, wants); + std::shared_ptr context = std::make_shared(); + + // proxy start + auto amsProxyGetWantSenderReturn = [&](const WantSenderInfo &wantSenderInfo, + const sptr &callerToken) { + EXPECT_EQ(wantSenderInfo.type, (int32_t)WantAgentConstant::OperationType::START_FOREGROUND_SERVICE); + return ams->GetWantSender(wantSenderInfo, callerToken); + }; + EXPECT_CALL(*amsSerice, GetWantSender(_, _)).Times(1).WillOnce(Invoke(amsProxyGetWantSenderReturn)); + + auto amsProxySendWantSenderReturn = [&](const sptr &target, const SenderInfo &senderInfo) { + return ams->SendWantSender(target, senderInfo); + }; + EXPECT_CALL(*amsSerice, SendWantSender(_, _)).Times(1).WillOnce(Invoke(amsProxySendWantSenderReturn)); + EXPECT_CALL(*amsSerice, GetPendingWantType(_)).Times(1).WillOnce(Return(0)); + + // proxy end + // call GetWantAgent + std::shared_ptr wantAgent = WantAgentHelper::GetWantAgent(context, info); + EXPECT_NE(wantAgent, nullptr); + auto pandingWant = wantAgent->GetPendingWant(); + EXPECT_NE(pandingWant, nullptr); + + // ams mock + EXPECT_CALL(*appClient, LoadAbility(_, _, _, _)).Times(1).WillOnce(Return(AppMgrResultCode::RESULT_OK)); + + std::shared_ptr callback; + MockCompletedCallback *call = new MockCompletedCallback(); + callback.reset(call); + + TriggerInfo paramsInfo("", nullptr, abilityWant, 11); + + EXPECT_CALL(*call, OnSendFinished(_, _, _, _)).Times(1); + WantAgentHelper::TriggerWantAgent(context, wantAgent, callback, paramsInfo); + + // An ability should be activated + auto serviceRecord = ams->connectManager_->GetServiceRecordByElementName(abilityWant->GetElement().GetURI()); + EXPECT_TRUE(serviceRecord); + Want serviceWant = serviceRecord->GetWant(); + ElementName element = serviceWant.GetElement(); + EXPECT_EQ(element.GetAbilityName(), "hiServiceForground"); + EXPECT_EQ(element.GetBundleName(), "com.ix.hiService"); +} + +/* + * Feature: AaFwk + * Function: GetWantSender + * SubFunction: get foreground service ability + * FunctionPoints: NA + * EnvConditions: NA + * CaseDescription: get want sender / send want sender + */ +HWTEST_F(PandingWantManagerTest, pending_want_mgr_test_005, TestSize.Level1) +{ + WantAgentConstant::OperationType type = WantAgentConstant::OperationType::SEND_COMMON_EVENT; + int requsetCode = 112; + WantAgentConstant::Flags flag = WantAgentConstant::Flags::ONE_TIME_FLAG; + std::vector flags; + flags.push_back(flag); + + auto abilityWant = GetWant("hiRedio", "com.ix.hiRedio"); + std::vector> wants; + wants.push_back(abilityWant); + + WantAgentInfo info = MakeWantAgentInfo(type, requsetCode, flags, wants); + std::shared_ptr context = std::make_shared(); + + // proxy start + auto amsProxyGetWantSenderReturn = [&](const WantSenderInfo &wantSenderInfo, + const sptr &callerToken) { + EXPECT_EQ(wantSenderInfo.type, (int32_t)WantAgentConstant::OperationType::SEND_COMMON_EVENT); + return ams->GetWantSender(wantSenderInfo, callerToken); + }; + EXPECT_CALL(*amsSerice, GetWantSender(_, _)).Times(1).WillOnce(Invoke(amsProxyGetWantSenderReturn)); + + auto amsProxySendWantSenderReturn = [&](const sptr &target, const SenderInfo &senderInfo) { + return ams->SendWantSender(target, senderInfo); + }; + EXPECT_CALL(*amsSerice, SendWantSender(_, _)).Times(1).WillOnce(Invoke(amsProxySendWantSenderReturn)); + EXPECT_CALL(*amsSerice, GetPendingWantType(_)).Times(1).WillOnce(Return(0)); + + // proxy end + // call GetWantAgent + std::shared_ptr wantAgent = WantAgentHelper::GetWantAgent(context, info); + EXPECT_NE(wantAgent, nullptr); + auto pandingWant = wantAgent->GetPendingWant(); + EXPECT_NE(pandingWant, nullptr); + + std::shared_ptr callback; + MockCompletedCallback *call = new MockCompletedCallback(); + callback.reset(call); + + TriggerInfo paramsInfo("", nullptr, abilityWant, 11); + + EXPECT_CALL(*call, OnSendFinished(_, _, _, _)).Times(1); + WantAgentHelper::TriggerWantAgent(context, wantAgent, callback, paramsInfo); +} + +/* + * Feature: AaFwk + * Function: GetWantSender + * SubFunction: get ability info + * FunctionPoints: NA + * EnvConditions: NA + * CaseDescription: get want sender / send want sender + */ +HWTEST_F(PandingWantManagerTest, pending_want_mgr_test_006, TestSize.Level1) +{ + WantAgentConstant::OperationType type = WantAgentConstant::OperationType::START_ABILITY; + int requsetCode = 18; + WantAgentConstant::Flags flag = WantAgentConstant::Flags::UPDATE_PRESENT_FLAG; + std::vector flags; + flags.push_back(flag); + + auto abilityWant = GetWant("hiMusic", "com.ix.hiMusic"); + std::vector> wants; + wants.push_back(abilityWant); + + WantAgentInfo info = MakeWantAgentInfo(type, requsetCode, flags, wants); + std::shared_ptr context = std::make_shared(); + + // proxy start + auto amsProxyGetWantSenderReturn = [&](const WantSenderInfo &wantSenderInfo, + const sptr &callerToken) { + EXPECT_EQ(wantSenderInfo.type, (int32_t)WantAgentConstant::OperationType::START_ABILITY); + return ams->GetWantSender(wantSenderInfo, callerToken); + }; + EXPECT_CALL(*amsSerice, GetWantSender(_, _)).Times(1).WillOnce(Invoke(amsProxyGetWantSenderReturn)); + + auto amsProxyGetPendingWantType = [&](const sptr &target) { return ams->GetPendingWantType(target); }; + EXPECT_CALL(*amsSerice, GetPendingWantType(_)).Times(1).WillOnce(Invoke(amsProxyGetPendingWantType)); + + auto amsProxyGetPendingWantCode = [&](const sptr &target) { return ams->GetPendingWantCode(target); }; + EXPECT_CALL(*amsSerice, GetPendingWantCode(_)).Times(1).WillOnce(Invoke(amsProxyGetPendingWantCode)); + + auto amsProxyRegisterCancelListener = [&](const sptr &sender, const sptr &recevier) { + return ams->RegisterCancelListener(sender, recevier); + }; + EXPECT_CALL(*amsSerice, RegisterCancelListener(_, _)).Times(1).WillOnce(Invoke(amsProxyRegisterCancelListener)); + + auto amsProxyCancelWantSender = [&](const sptr &sender) { return ams->CancelWantSender(sender); }; + EXPECT_CALL(*amsSerice, CancelWantSender(_)).Times(1).WillOnce(Invoke(amsProxyCancelWantSender)); + // proxy end + + // call GetWantAgent + std::shared_ptr wantAgent = WantAgentHelper::GetWantAgent(context, info); + EXPECT_NE(wantAgent, nullptr); + auto pandingWant = wantAgent->GetPendingWant(); + EXPECT_NE(pandingWant, nullptr); + + auto getType = WantAgentHelper::GetType(wantAgent); + EXPECT_EQ(getType, WantAgentConstant::OperationType::START_ABILITY); + + int code = WantAgentHelper::GetHashCode(wantAgent); + EXPECT_NE(code, -1); + + // mock CancelListener + auto cancalCall = [&](int resultCode) -> void { EXPECT_EQ(resultCode, requsetCode); }; + + std::shared_ptr listener = std::make_shared(); + EXPECT_CALL(*listener, OnCancelled(_)).Times(1).WillOnce(Invoke(cancalCall)); + WantAgentHelper::RegisterCancelListener(listener, wantAgent); + WantAgentHelper::Cancel(wantAgent); +} + +/* + * Feature: AaFwk + * Function: GetWantSender + * SubFunction: start a page ability + * FunctionPoints: NA + * EnvConditions: NA + * CaseDescription: get want sender different flag effects + */ +HWTEST_F(PandingWantManagerTest, pending_want_mgr_test_007, TestSize.Level1) +{ + WantAgentConstant::OperationType type = WantAgentConstant::OperationType::START_ABILITY; + int requsetCode = 21; + WantAgentConstant::Flags flag = WantAgentConstant::Flags::NO_BUILD_FLAG; + std::vector flags; + flags.push_back(flag); + + auto abilityWant = GetWant("Netease music", "com.ix.hiMusic"); + std::vector> wants; + wants.push_back(abilityWant); + + WantAgentInfo info = MakeWantAgentInfo(type, requsetCode, flags, wants); + std::shared_ptr context = std::make_shared(); + + // proxy start + auto amsProxyGetWantSenderReturn = [&](const WantSenderInfo &wantSenderInfo, + const sptr &callerToken) { + EXPECT_EQ(wantSenderInfo.type, (int32_t)WantAgentConstant::OperationType::START_ABILITY); + return ams->GetWantSender(wantSenderInfo, callerToken); + }; + EXPECT_CALL(*amsSerice, GetWantSender(_, _)) + .Times(4) + .WillOnce(Invoke(amsProxyGetWantSenderReturn)) + .WillOnce(Invoke(amsProxyGetWantSenderReturn)) + .WillOnce(Invoke(amsProxyGetWantSenderReturn)) + .WillOnce(Invoke(amsProxyGetWantSenderReturn)); + + auto amsProxyRegisterCancelListener = [&](const sptr &sender, const sptr &recevier) { + return ams->RegisterCancelListener(sender, recevier); + }; + EXPECT_CALL(*amsSerice, RegisterCancelListener(_, _)).Times(1).WillOnce(Invoke(amsProxyRegisterCancelListener)); + // proxy end + + // call GetWantAgent + std::shared_ptr wantAgent = WantAgentHelper::GetWantAgent(context, info); + // must be nullptr + EXPECT_EQ(wantAgent->GetPendingWant()->GetTarget(), nullptr); + + WantAgentConstant::Flags flag1 = WantAgentConstant::Flags::ONE_TIME_FLAG; + flags.clear(); + flags.push_back(flag1); + info = MakeWantAgentInfo(type, requsetCode, flags, wants); + + std::shared_ptr wantAgent1 = WantAgentHelper::GetWantAgent(context, info); + EXPECT_NE(wantAgent1->GetPendingWant()->GetTarget(), nullptr); + auto pandingWant1 = wantAgent1->GetPendingWant(); + EXPECT_NE(pandingWant1, nullptr); + + // update + WantAgentConstant::Flags flag2 = WantAgentConstant::Flags::UPDATE_PRESENT_FLAG; + flags.clear(); + flags.push_back(flag2); + + requsetCode = 24; + abilityWant = GetWant("redio", "com.ix.hiRedio"); + wants.clear(); + wants.push_back(abilityWant); + info = MakeWantAgentInfo(type, requsetCode, flags, wants); + + std::shared_ptr wantAgent2 = WantAgentHelper::GetWantAgent(context, info); + EXPECT_NE(wantAgent2->GetPendingWant()->GetTarget(), nullptr); + auto pandingWant2 = wantAgent2->GetPendingWant(); + EXPECT_NE(pandingWant2, nullptr); + + auto target = pandingWant2->GetTarget(); + EXPECT_NE(target, nullptr); + sptr targetRecord = iface_cast(target->AsObject()); + + auto requestWant = targetRecord->GetKey()->GetRequestWant(); + EXPECT_EQ(requestWant.GetElement().GetAbilityName(), "redio"); + EXPECT_EQ(requestWant.GetElement().GetBundleName(), "com.ix.hiRedio"); + + // cancal + WantAgentConstant::Flags flag3 = WantAgentConstant::Flags::CANCEL_PRESENT_FLAG; + flags.clear(); + flags.push_back(flag3); + + info = MakeWantAgentInfo(type, requsetCode, flags, wants); + + // mock CancelListener + auto cancalCall = [&](int resultCode) -> void { EXPECT_EQ(resultCode, requsetCode); }; + + std::shared_ptr listener = std::make_shared(); + EXPECT_CALL(*listener, OnCancelled(_)).Times(1).WillOnce(Invoke(cancalCall)); + WantAgentHelper::RegisterCancelListener(listener, wantAgent2); + + std::shared_ptr wantAgent3 = WantAgentHelper::GetWantAgent(context, info); + EXPECT_EQ(wantAgent3->GetPendingWant()->GetTarget(), nullptr); +} +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/tools/test/resource/tools/aa/dataAbilityBundleForDump.hap b/tools/test/resource/tools/aa/dataAbilityBundleForDump.hap new file mode 100644 index 0000000000000000000000000000000000000000..96a0d67b5dafeadc261145a6a5275b7fd9040fb8 GIT binary patch literal 20734 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 literal 0 HcmV?d00001 diff --git a/tools/test/resource/tools/aa/pageAbilityBundleForDump.hap b/tools/test/resource/tools/aa/pageAbilityBundleForDump.hap new file mode 100644 index 0000000000000000000000000000000000000000..569bf324c651d782e9d8115d694fd3892b9a52cb GIT binary patch literal 20613 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 literal 0 HcmV?d00001 diff --git a/tools/test/resource/tools/aa/pageAbilityBundleForStart.hap b/tools/test/resource/tools/aa/pageAbilityBundleForStart.hap new file mode 100644 index 0000000000000000000000000000000000000000..9c9537c49190b3c6c3e1ddab2c8277e8c239021c GIT binary patch literal 20626 zcmeIabyyrpw?B>y?he5nf(`C6gS)%C`{0Bi!QBb&?m>e?f?E=tK#(9ISnz~Ee#7qG z-R$1o_rBlXeV+HPTRhWENq_2e)#=mc^f^^(itqq@7-VE*7#J98A?V@vLeTt=Sia8jW@9O0;cX38LcI1=RQ$v%HL)Bp;uza%SmZK&mIpyWJKsOaV`7_3=FZ4yc9^wcjYM0 z&n@?LdjHe451ibO{_Y?A&tS+5VFTb@*I61g0=}R7NPM|R4 z1~-|^&&hoV{BUj3w|MvM^7FL`T3WHG0OogLwcyW0{fbDNW=MrFu%jt`v}A=OAUq&i zf#8c_zf^`ffO5|D0?(F4EKNKWh5!?t8Eq1i6#q1Gz1?)->c;}@~ zuQS>;H_QMU{Q(tLOTNH(BGea=fqEi>vcxEDZ4A8ZAz&O>*ihtCbqMu7I2ksf^sv(F zQ|bGGiglHCm@c&zxZ9)~dXc&BE!(b?8A{_GlkH3HvT%>SF;47Wn3KdPhD-#d$1=_!kowdUY+r)csxsjMr6vA?F$FLU!y@&;R0sfb0p0KeYB&l+!UT_A zi^injNOcjwB>4f3pCfzfD!%`wbCkM@E&`1Utp#3;p{i-pivKqroEij+@0Hj!^)4eU zuN@EyC?>O;96cGQ!$1H*@!rOWlca5KJ>cV4=5Q#GFECi#>8m$n663Ij9)sg=dV5~& zD+|xQMND*tcM?-gnAs>+-c=_Sa|_7}%y_yDguOO>0kazy$=)ZG)O>9q1xs;o%y&8L>Kl@GIOL$x{Q>$(cR_!7mpB&ON13{>!b$3>aG$A@TriI+ zf=YoSc-yGy{kq`u?*2uT<&Z7)u1w-r#)+44s;i+1Mgq1oA@6GjajP`I!}Rc6y|1v! zIKMD64yMO!`%S#BjdAz#&9KP;;spueSfK1PArS$^aAuG7ndsw$4UB1|V4sIlvmuy9HL4gu*NU;F5sISw@r?)vxyo}iu4iB45rp8!dM#D>*|8kG?4tYFb`tW& z@=y0s;hNyg3wU0k6>Zo}@9HgZ>C}BHr7@Q#8(SK_SEV@}M#J25^2i5Xwepq1gUiN; z==);!U)mbP zDU@psjEe zx$G4+IZ?-TQ|=$#K&!v@JXKd*+Ll-xvytlP3k zKgLN$qf-YY!(O&&=(PQ7fIm1-c8%` zAPdLd$k})tBE(O(JwZ|7_dWf*h!)G_+11cvY+MJmxeD3?JUB475gax+*_%d4bRvsS zmf1)b=P`01XqJ+F0P7H?%IvKf?OOtzI=@H*MjCr*f5(`C0>NWL-()L~I#u?RJ1?DP z3bF~1Cfj?Dgko+5w|hXrn7yP#B9Fyf}Qc@PyCNWHLIxO1WP7YLuHgZ0@DeWY<-)PUFSEQ;8*4V}r0n%eL3FtIt zWueB=N@#LznXL~b#|*cqg2wIv%T})Iy6?=24H^W6hjth6^YSvDk9>$EQ5KuBPs9** zq;_vcrJwz&9-dm*Sx;P6Lk(E*JT+kH?!eMI=Q?kSs@t5AV<*197HMQ)eeOE5VmD*ntyoI$tYNkwsj^iDTQ9 z=wN^me@`modM&qZ9fF=vSL~2q&f?Vq=Ep+UMt3=^$D_WPROZY=#zTS{b`^ew&upBS zabPzFChgr$2;3(8{L}I(6RVqNTC_yVN5nv)w z*sEto`R7Di+JiL=e>5$kirf?l$q9s->^ob?s7QUO5&J4 z3r1Wk@RPw3Bs0jic{1tf+cTG;bDz(A>V@4=QAJG#@A%X-d8vmp7N77B^yuc_v#`Nl zb3|5cZ}jD}p*-R)dL0JA?fueAH?fx|wn+N!bb*Vd^*T|OewP~^QA%3Jr((QSU^MgDv@?X#%=wAGd*Q{&snv$f))Yb(@>nv&AM{> zJjb;Wb*B?(vj3h6D|4#BDDv^(waZ)Q`nQ!WHQY4mI)dAp>8@{dGeeZ#wIk8b_C4{^ z-}yvb5L1zKP>NyD{Fa!DVzK~%(!?llY-{|*2K?R|A2qMar(I{Y2eW6JuiZ9l^94Io z)YL(!g=}angbw_Mts6tJx6gBEIxO8U_uW`Kjzp-02N9lQnQM?6iN#kBzScB<-(gb1 zHMhu~ZD4G`o&)Pm?h7hIAbH*6lav_KgI<1(2MSPeTZZV(Y8mhH&JXgw2r)tt6?{@x z)%LQ5H5YkLB@D=T0U=4hj@CMCdh}83HfA?2xrvJ%=d3P4Z{L}XYmHUKJkbx z5`#>b+DJrDal$?Gs@pl23!6ESb1Z5z7`%U$+3sA+nZ0z{QH(uqUQ{-vc)UiS) z^PRn^nTT&^|CH?tJtg1F$N%kqcrUJ1pu8>UQ3ZOim6C-o;JFHNv!9}H)ApsM5GQM? znW8)&QV1^bmoBTjBk9mUDxMEWr|_#XB`lbAnXf~!%V&^#z7u1*9htPm+^hg478Yx~ zV0Q%HNxN(MyY=d7EiPrO<0nKEWvG~X70vw7JLm_MeX(4SQwyeIeWTRTy z?+AjP7{l?Mge_tfbcVhUA~sn?;^GWN(6=1Qac=zbW7-HL)>Ub{&z9rCy)qHYgm^JkSM6r1yL>b$eTQvx?jx$$<{7d37aW!*o$n?=`)( zDRp6Sj609{dzWl9Pa$&lrH+&s zl?6voH4*V`#6qpIXI*0DWqeCG#xpn}k=WOo=f1(F!Ia`iiVP?j(~v5o$-*s(fDpfT z0h9N3=wx|;_xG7}tl=#9MXOKGFE9Ac!#9|?@6r#g~?*P*}( z1d$^hAZeynq;j1qDSmqe3^J{Gd7X=7+KF19&kLD+?~S~E&AsFUJbv4wrF~9!bC=g> zwl%wH)Q8r4hA+~?t5eal_nKOc#P?jnqVQ|m5MOp&q>we$^rEl7uu&h9ix|lu-M?uXni*s-o4`1lgz|C>-h63vB4o``FDx{2Fb;9XaM?W(MZ8TU zSZXwE+LNeur6#1t2*4bg5)Z4{9b{y`IK{AN8A495+LS<=)1z=S1aP!;WDn@bkB~5o zi~yYvFN&$ki`n37_=m2ZP^@AKBoPhgENNCqYQDtsTG{(pLUKPxI=fszRJU(1Y)pO6gTKNQmX)|HCP?VuTH*LWF4il zvA`!4jx}3G&kV(#dzof_*dMXhgk%L|AZk&o&qgZf0EW2E8mjPk(>WSSsiq|Ge$OSN zxOn|+QKZAZ!%zKWNA_!1V^CI9CS~Iu%$;GqG0@WE)7iFGGpg}@kUix@qLuhWVxIzt z@Ei~AG#^2758I7(;H)!rQ_O(GizDnTJ`#$)Z3sDB=q~51h>WeEk1(L^^^@7U zUZC}SII(d2Ne|BbMN`q`K``MgmP_#kdUgI~-fSO6nJyB9^!|c#t=wfsJ3Vo+(favj zQuCzS=rK?MMV-PyuEYgKXsWAjtEK2VV~O`%}EW!VFoZEzl@M||3wk7V49@iXKD zTpWzYW(p2TX(91Q?_@G|%BJ+!?R*5YU&PZ+*(RLZ$whQ`@P`u(5;cUA?&-?z0R+0+ z7C~`|x7vn&^Ft~~F1aU-?gdl)`2hZ^R`s_D9d;I&v_Y8ylb%(C{kN9pSfcajmwK&Ar(OJ;JH{(8DPLgO zhZ#pQPDRx?KSVx$+ifHUStTV5ygV=&xz{4rat)RC!jLyS;3I1Pu2O+TLeZk8Puoh1 zrMNqQ;VHPi5z*;3zwF;*WN)qZ#cg!kuVcq(dh*>dpf;)|PKs7PX&J^QF;cO@eR!~| z0yO1&`W=ULbQ+E|4{=XPz!Smm7@)_aEW9sUOVxwTP--4{Hc3$GI8@3*uvkYxV1<29 z-0DHRJF=O;!x0{VPav+;+B}@_Ha#*DK0^3yH@-v7hE&7hndIP?!BgOgT$}D^t3YSs z4d0L$SJkw1E;Z!v^-!)jM*?P$Ehrf+Ha)TiDL`0&+1ku?W%Ra4ySRlcBG zu{Y@%dy9sjs)?|xq;Yrz5qRn`E%KI3I?^?{8J|dXW(z~29eq2j0O|WHP_x3PB&2t? z2gZ3#U9GJzX$yJb9Sx}<3U*!>tqV$C_I`B)CTsA6^TQc9CknoL5Klyhjew)NI(b^& z&cj3WnfCJiQN7`1J?@;q;(p7i&nWD*78o5^2>^G7e`u$-AH3bxNaXeMjv z&rsafT2%6vv}MMFkrZt|rG+>nrN9r<$deIYY#-#IFKQ64QHs-s7qc_poE&9Q%7_9^ zV|6VsR*;nYe9QbHH`F4{1eJ-Jh&1NYeOc>x8ifgxpzhZMS+! zJ4Q|;KHd}Q>M%@IOlNr^@GcQ&=9Ms)4f3Vb$w$%;?3czzHY95{Z9P@R8b~%8OMb@C(lMJJ$#E|>lUbluk!S2xs@QJ7V@XfmZqP&@Q!6#A-5R7R z@{Ao8%lTO><+FnB%EYfMNN2F$Pd=X>BW)V0+Brg;iYFhZDGa)+voi6ylgUhb zP6$4Pls!nTJsL2tN{S6xW)iA74r~cA@coP(c%gfGx3?*YcB%d}mhm$0a~4)hrqx7{ zF`?5M<^_dmw=|?WP*Ipl^K{Uq!yb!O*f7%8NI;uXcxkc7)=zvZJuKAr8ab#_TRe8w z`B6p^p>zcX8F?C-0=Gg{M+Nf>iVsg5pU%9hJ`GLl;%Zhf{>l!vHmx>6zg(dD6`dhne9m zQ>pP%L4DoWQ98F(?eEwaWY2qjWQbN*aLJ}thE>jAJQ86jhpL=)oIaY;Zql9+L|BVS zUrL`-i3(IOtH#$YHH%xvDI#}RC`8y|mQN)PoSMB!BQvL4@&?*RD1zQb>#d|&58ZQ3 zPoHjV?Xn)_OHXXV9vmVY(53Jz&(ZBnZ#2wQ0U!fA>qHr1h4%Cy@_ijWZK1j$wpL98^PjBil&f ze>h`n2GL58xbb8awmRgD3Z{&I_#%?1CdHKWY;8T3x4%t&J&t%u=2dp_cPk$+8B(mA zTbZxi;QrlSJsYzysbTIi0H7whmSX3vFd1EqrM}n1v>5ZOqz4u(KW@^&6~m2?1Rv>W zvj*Z>QGcS8A187VChXx^ncpTg7HZKfFY0(d0ZRPDdAJ{Pc15hkGjoz7jU>r~lK2S` zYiN7bY8k-N$HvZz_VN8hS*2@a_{|lY(-Z{8=l}&Q%_QCiwg0PtiSWLg9Ev!gM8CJZ`Z#wqzUQg)|H?I-1Zzb_Odkszw@HrLieZA@%I08;? z!6zZL^x85&H5|4_Z0n?AE0R1ErnRpfCf65ZXXasF)bSns&f_EdcnVI_=nFG^Mq#&q zE~*p0OZ+!hpEDRs1uM@Kdv0t%@CGca4wKd@i63O+^yS9NGqdnuBt$gY%m`6SL?<`r#qD3>rPlLC@_%QyhS!>{l@>2MAkeB226WMdqh{L9ZL;l!9VCM5CB3t__+(bFDi}i-ChpPkdk4 z0q%Yoz-JXkG+QQz>;}n3%y4)fT01ZhZOjOeime2Agfmwx2X7C+G%ISXba4++07pd` zFQHQIgJ;8O!ZwgYCBac)dWQh-B0GdD>eI;L?H}UJPii$ryLV}zo(LFuX%(q@uvzGX zFK7N(d8w5c2Bs1E`)6kn3-qf0*;(Y`YW4raPXz7wzpx!VIjpR0%)Oi-9OiCr><*qs z2F|XlZG`tmKTwDHqjm-}R*L)CoQRE2n$1^@7tKGdiAjZk6kDdG7Y-65A8(`88{ zD#9U#U(jvD*-^MImZJ;Q_s_t37WB&NzyEr+KiZm zICy0n9DJHP`2GZ4f!|&Cu+JoAAN5V=yG&HIhVn~pp=<9}F`xGw$Bb$MGW>73y@Ru z3sx%8(ejK$Q_ZV8zDDlW<+OT_c*S2Jmlmen9F>TeDP}l-8q*K+Svhj8-^1+((Kbf% ztgH5?RRG8MH?t7j1WVjSf-^iAB^yC|>#JDzZVTI1P@u_{2}3(bL%Wv@JLhGZgH0uG zF*<`>j&X_{O+#@1Gz_5ZH3srm7T`2);t5M*2BUIZNd&P|Dt4-%HGnNDjc#=qG5Z{y z&An~Q=_q)OmItwD^=)fBdW0@EN5rklTW}~PFXz_${N0+-k3yX5_$_f;5&GvwCkoxt z&vsZ+Hub?WLeE+VX>Iq*KNz6!1r%nhL<0+HU=D&dtS~m_Hj_T5NnGUD>2l{6mW%-| zJ#0#cMIjy*wt-_aRx-<5v?hVn0$zxy)sDFzgEeOK=DW~xpTPMe2=(AP?gW#!)d6Me zQD?poyg9}XW@vh@Qx;xIwGZeaBLO*Z46Ht(r*LZLT#M`w*%Y}{qf`w)m&XKNMRfTFNJ?>(`GC*MpaZ&1lTQc9tW znbSM({I!*SXrM-q`{WdUT)(-VeORmawWlreJwPRmX z$1B>Fq@*q`L)TjcyZ3d>m&z+DJld}q=(PwAz6Gh>%YO;&<{mp`o0+DYwkjk*mLf!8 zQPOu~h9h-_Rnh#R(LE1X^T2m%bKV*%z-3r>mVJthS=BzCS+W=TG$B8d{29J2eqtzT zzA-`y^4A>yuiFPSuSsqq5(}Ha-;l>CL)i`A+6CNXdG0SIc}d*?#U*_5pBG|#Ykd_) zPXe4GYl`wH2YZo8H_8OmIk5dKidB!1zD&mjGjWOJrsBUNuz_IqFL9;=tMOGa zQvzgrpMYLo9S-XSq}eI#TaPlcRCcA?(Aaw7Yeu{TJ`j6^pQw$(t1&+4#C$oPHszF? z)N8D=H(E2BPO7%AP~*9<1xC?QpI#FL$-5fa5;<2BI(@U&v^l5jQnxF+wO6KJ-p>z+ z6iN`Od<|Xs4r~{(S-j8{DcAITj|l^A2+v7*%hjD-;kfYF$Usm@lhI(mxM`0X z;>VN%o#D&-_T|cL4aYlw2ey2J*uHs{vkMW?rwXa+9|HpWht6D<@5DuKDf`7+n*&FO z&(u}!kv7kKK8qLRSL~_wN!91Eujp$vh`MxjQpu51(kzF!1!F4^jm<^R|jkRHW7Fd#C%`~GuJ z>}b~(rj_Cv{3fz9Vm4zgi`DQVLAm!~uMu0P_3Cm<*6t*U&oFsI$kzE@o~gvaZ9S9t zmGY1Ln*2x;((fEb%$FkvncB0Vz?6X%;;Ds72~e4qd&*&2Ul^%R=mw?SsYvW-z$mhS z=#RZjN=6$+IIOZC2oDO$&SS-e6C@azLgs&^kdXZgrGeeq+^tnh-E{?sea{iJqxHfY zi&R93NSH_IK%t5_y;?NOEQ=J^wvBnB{O&pr9(|5lOWArgMyBKudU29o^Ch`I=Vaq}?lYg}3Z@ayW+e{36`P^zIyZ`zfC(6!LfKIqjs#X-#*=xDizi{ZPm~ z@{VNKh2398BE5D9zQrl&LeRif6Yw}O0;4NEeO4#SwYAg&>L{ze5ra#;nh`MwTu8nS z27&|;3JxE|1C*}E;Uc28kqLNsW>|5#I)$Ky@VWl}OKuEj) zp~X|(Yw<$PJ3FT7pgY6|#=+NSY&n63B;^DC72{C2jY^$yxv8-+q~Z_(>81S?Y#pP=y%@nfsZ5BNG(#A)e}= z73hD_t-l?cq{_eOHlMf7_a&quB|*b4NL>Y0?&Da3{Y=Fb)BFP5F9dw*&d=b2cK-1D zX96gpwZCcbKWW*{<}UU&)}D}Gy4RjoM+*gF_kU@?l}#Mt3GHu}3pJr(I-sV>$oDT4 zUd~|H@^O`<@h55jaNkHO!8auq;)}?<2%G5yH(~U=Fd4xmUn}{@r&d+R0c~&*Nx$S| zZ`eUY`f$If8^unY)Z&t@nCkmx26tj|aQ0kN3ZJd9X*vHM3+%n@_V6kXo1FDczDft$ zXk!`v%#$!p&1UdP9!rNOU&kx8qWZMuw`+?Nvuxj+bHBT@vxIHmz&;E<%O<>j1N6?m z{mXl2_}hDTGq<(&CZZSU4ji+oM&NCads3a|IxtZjXU`Ad566aYY?({*l$-ouU<_sdBbxE7js=(4&$%#_@cw`=j1ND|F1wnM3u6KTlUqPYFzJ=4_K-Lg||dUm6yXOC>O zaC!Z9J|@zPp)`*R;9ucnE5)hcNs2xv&igQ22qE7fVU+mZSvcy zK_c5VTBhi%*myLPM~t`X>6r4c$AIi{%T$|<;6Nx<9FxBO(YLH&CKiCgMkZ>+t3ipw z&KLBfHp9#04s!1uV;Ci^kdRtKAW=2~JEiw?dYpihd32H^xZ5d=Xw*h|tuJr3-pWoO zn&1$db=xZG(f1xL;e zmsqIorY!e{(_AUBmu;^MrRSx87&vM1D`${i~&Hw(wK(KDG5a*s3fgGN9Z5f^H35C&_g8vbT* z5D1AzwnF*|SMz|fd}uSL1nS2hgBdtk>QvBTLksaPAe9JXJ%G$x1ret9rqUol`W7s>X1{{VkUBd<%UGY}e z?~kDd2i3LKV?_cyPa)v97P)sX2kThsRsHg+MLnv}4SXYFwJui9Bcjcn2W^OSW*!lf z!2*oxUgR_4Iha0zNG~+Mf74j9AXN>4dkNaHyP=zqAgbmR=^`$Q7gx5cl~7OZei>wg zxN~jbpG0Qr$h2OGVEh4#rfsrOu3SDlir0YNB7~`=!aE0OxSW4e=JK6g8Tq|S*P4}m zm$-u6RNIl&hs@SV-D(4pH$K33??%dM=pl9;sbPdg>Kn>pKtET&@Dt|;iz7Y2EXU_! zwnxM&l-MKPjBDvT!Y-xGT*QmVt5?3kofNZ*5VO<*QtNA+`CL=U^7?=>B^{-AblDO- zYz(QQ2R4N+?ZPX%**#&nxC`~8i`K>{;a!|%o$@&$ZE;KG&nCf8vfqC|pBejbX>k+2 zvj?|FqlO9)Nerb|v2z=P$8(LzMrza=i@*QOk?~1U`h!=Pg{Dq?!4D6rgAd+wksGj6 zNj0DLzl8NAP(TfjQYw6`FoKB&I8et;L!c+nG6^4GF&Nn{>;DOvi#asZm`>d<;W;PM zeUiJyxrtfuu}Ba|3=9`<-owE}h`hyM{g7F57#} zuje#bgz}FHP=_@rB>cRqr``OL7&NIY=lVV(eYC?+Gh#8NCYbShuKX=*Bw(?oaK|Dq zsH@}gk+B->v`?r34ke*_lD;I*c&bt$wOniCP>4biaSK1p0KTfcgN%ud;HK2+m)Fam zk7_STXo7UO;HJK(&3;a0W!rVTc}gW1^R;S}b4LxAU3Kb)c`iZ?U~-1{6)|^aX6|Sn zR+N{XDk)b8lY7(ilT58}_dBAPw<`654CwS0=62L*Lke$z-5<^Ev@s-Q7lE~D7?Qd! z#10<^-6CTtG`38=7oduH*L#i~hm*>(`WcInyY-n<`Ra5|)LI_uxyfy`J@itWEGajU z+0H?ykgF2DQ$6P(7xqtGB}bZUmJO+sYJD=B`GOl%8kF4L3d!}@0X@k2wduVtKDE5P z_1QNZa&~uf^!^BTMIG+pBZ^YX=3##(pTUK!2#;7j-f_8#rTAA_vz{H23 z{m0V*HyE9=7g#2qH7VP%+N-8(pFJm@rXL=Bu&;D|j?KCfr4DEMzgQ?NdtPEcaXn&u@e&xIV*XcHC-k(li=d$nbo7 zV+CjO*Pl`um*Z*DJ5Pd0c0(p^PI$)xr~HP!zDkmv^zCV#H!dThZGL>7r4;*BcvRHm zh+l*=&;d^&&0_lLYsF&EL1-&B)k34yO{EUdvBV=V=X!(DPBbJ{kxSM zzOJifhYRa1E(*v+in#>=Q@K`)yMSZv>DZU8`uDfnhZk(QdA-}ppGQ9DR3cXICt~@+ zx8^i(EW%O^`nV;Gw3qRtuh6q-gooi)SG3c8)vz*Jxk_B^X>t!V z#glj|^VM`Rn`=C}9)+VP4U5jo=gs<5+RVQhw{H=vwNj1jNo@HR^li?rB~8-}A7@&h zU7hk8LMh=I?B6^AQ%KizpJX(I)9Aygk=ay6Y?{r{V5Z0}W~=zNVceOxabe*buh|*# zFngL;J_Al{Zk<-mNsfrEUmsEx=G|V;r)9Y7u~aZu`q~SHj6VgEj~0_QS=x)nm)k7?oXC z4q28cs^z|cH^m0Hm~zAPl$&81AsK?Z zlQ(H@DFSKqXDU`$?&(R|cHkX4+fiqaLR z@R5!Z>4oL+N_)3vYTcov%~4{0RHBQfwD+=17Y{W8$SZP}53(qMBe0O>rz>^q_wSCZGy6tq#X=6$E?l1k~SaH|f&^w9+l z<6BWc+CN0MjhS))Z(49~fu7#GaWj*wH$(w*oxJvgk0?WyAJy^`P7}&p3#w(Jd9U9j6M!8P#fOM4?Rf;7C&R48L+Br~i?8SjO2&1EeLE=#CU1 zQIw~;d05f2WNexUvHqPOO6~9THHAOJpbNhEgj#Ow(1gZmKLTeE6%JV!o^{FV@Pg&_ zXf+-yc~6G^Nd0zH>3EG(FMC`;fZ9hxCC%r$*7w>ByA_A9v>jWzLRUheW!>=APN6)o z>%CJ$cKsSvx%9X5*WUdK{_ZNi_JF*^Iy)2pi;HUJFaksT+uUa_1K)g9>aM!CEDT%v zQh6(c(=D)l^`RPz^b{{Y)&d@`-p&K7@2;$JMeXZ;Kgv<+H8N3D&som90AZLF_ouh) zNOP5kcn51pz*h}ENvMadqF!o1`U@OUv~=0K3=Z;}bj-V%-IbCz-m?=Y*t0)^EcPkv z8sFXVk6iWkl?UYM9bR)kFqS4BIuk4$bV&tt6~#X@78+E?hpxr2vA6xjmWkI;R(%h| z?m1_9TqDcUSc%=jZ>Jp%--AB@TbG14!=OpF+DuMmu+ztVk32>3_%g-UW<9XS4~e1H zdX)p|+cvyFq735;-Y^1KQUt4@?a2_h&CQ_ZHv=wIQ5f5-$crGVnb(ucEOz!r=sD}Y zF?=N%s6o-xJ8EN(5v$GO&e93Ujrc2pO8h9-?>atcaWv}Li$=$NBAtdXw^U6pDc#X^ zTcCZ2U$@LG#J#f6D(cSR^baGY4n?9JX+f{ceo5oooR5iaSmJ8!lhMo_4=%Y@U#@E-Adf(iRG*A*r9I=Meze(FS5DmAE`NhpjYL7t=)%7 zrS6paH8c1rcc+`)8p_=3k%a7uYB7PiHE$|421|bv$#Eq|rm>HLtra;$7_Zt;gbvzF zpKXTCY6y@dM)mG9u9>xy)k+j(9mT7BmoH^!SYs%#uabduiS&WrzPgAi>YJaFtkUon zJfvyP1zoolKZ%CFCo*Pnsp|j!{iy?rNeT2)F-XYuE^zfUwReG7+j^Koprz0&y}azLpyj+kE`AF^L2EW%8|Z1Ig6x%}rOUufuP)SN_XvxdSOMpxgmseg!!%1Hk z=&L9Na{jfAvX+sH9Plr#q-A_8WqsZBxnzLm(6Nx0QE;+=-mfK>wvVnBNDFLh`P=Bq zgC9oP$mQ3uRtAH8R3t$lEem~BNp*EMU0xe2M}0XJ9$s&t9ydtN+?SKfK@DsrE#>Md zqakm=X|3n%tE%s>DQo1S;G=BgDQBmxEeMnraFPdV>FFD|s5sjyb9%aZds$ekyMwe` zIpuw{r9d_hl*?%_7_ zwRY06=WsQ0@dr7{00pF6EEGIcRUxV_>h8Qga;j=hQu<&XRfx8~s=fjg#?lqyA?>2z ztKcu|X~$vY^2;Lu^{4;MWAexI_?u|4baiHbcm~-${X8Mo&R+J=77tRz#@Za>_3+Ho zJk*;0T5Afep@BZ*(5Khg-t$31c|JVS(B-O731kVewqpBJjiE8LEwr82gOH$cbF}|O zD0#S;JJCET3`INwhQf&eLt*<0;o)H6-~jv;&b>f%L}aMwoE8PZ!$akxB_|pX1rc5w zfQSbtsltg5#C^!1;-RU!S-Z%YdpNtg_;Hc|i5^PP@UVX>rP8uCcjlx8Qa@C|<30Mh z3gqVI^dMBA^ixTKfD}X+T%15IAQvYW^vr8Ogux@o$;Hk2TNdc{za#<(WdD^2#(yG0 z&BN8k-pQIu<5!^x)Cb}rBKC&M3x zkwpo+U-$S`-1_@X3gt@vOZc~6hF#!Tw8SaK<5{PC&g^CK+J~*Sg^1^004M6q+lTVLmm@A2*95( z|I}0AuQE52{^Hpo!rhfA2CT-P=M3H+251Av2~(R;j}mI(S1(7013pZ$?zBT}#?8a_ zkrBH)EY51*0w-F%x4GP`xY&$GT z!?33Ds2^6c@)O;Q5?*ZIs(a6%osU>Ap!_2R<)5+N_y=oKAokC+0PX&lQ^y2k_;ueo_8-iHz!Cz0p@Fx60VwmW`6WAIgyo)KC=A~- zxgJ}BoD~B)+0b&mdk*yV-x%f;ON4%Fd#4YOja8P-a?1dh)fQfKn%-)aqhqdFMkOxE z;*^AAtap?Z-&=f<^p^ zlZb?{i)u&$cVJX&-()d1XBqflPW^fI;B8@mR&YQc10P1tscWA~vCO;$y_Up!#&Xp7 z8T1aJPKxm0$GrYVWkqCc`E##b0krn|jF22SAYBbzq^of)Es_R)Y5YZD98f{rPwK0e z^p0DpcV6xVFw9nOXpW_PT9!Bh0m?__P(IrEjgKg-`$hju$$xP6eiBBUyxd$r z^U*{0KO+(UfrY5^k4N$vhb9(8GV!Ukwl@ssJjyLQkB-JZf0IQWee=|;g@y9wU~Dtt z8=H2CCD8m&!s%~$Av`!W-NsK39<;Q%r~DL5(=HTOhDQA0UhCg*um)OsQ**KA)) zRUmtVj=|z_l;1}EEyiM{|OoO zKdL9IW*bT1^v);C#ANG&ebU!3-c5^kGYD_siwD%H^Gr;fR4jQS7~v@!eYG^#0B0IJ z%HAZo%Z1#AOuf77;6l9rt$K3nUcYbcj;+?1>E@mt+qHtBuJ`EAbM@;3&k2)bFnhsQ z5j@)U&53nH5m^9x2XvV!;VWVXN*g7Qb^37TC)%9x0tZg~ji+1LZJ-1kkenrW*|toF zV}BAw`d$B?Q}(pby9#i<8`<^_MzF8YJhxz|)zt`7TN5KAuIHoCr~jv&{H$mHm!9+w zua^JQPX13j`FHKLe_)~i(@y?(+KDvu9S8bPYA3(ENdI@*i69pj5c=_vi|@Z{Cs$=} zY%+Pa**kNyCcHF{MYv<_IUe7#eyx341J|WM z3S6$I?SqoRM+iMYlN?BmO4Ht!3hd-+=}5)H^-!m#2n&Y~^T$45KW~inun*Xu)8DUe z_+wYFzoPxT3)VyM*B=Q5`qldH(f)aBt$&67u#?sw$>HBZ|I@x&{|fwJ8?8Um_`eJO z`=(ld#r}Cg$%D7=kHid}lmB^G{%c3AzvBKp+z-o9{z!bJ{|@f&i&Opz{BywRZ~lef zuv7j3{>fPh{VoS}G5r2!u=d^_YhO~N4oi2xIaZ0{uS(JpE306pV9^6-`(op z`HBCE`Lnz5&;0k4^WVk%yJ`8^9rfUB{39)K|H<{Jrig&}P>Bis^M(o;M5Tw^{|91s B9#8-P literal 0 HcmV?d00001 diff --git a/tools/test/resource/tools/aa/serviceAbilityBundleForStart.hap b/tools/test/resource/tools/aa/serviceAbilityBundleForStart.hap new file mode 100644 index 0000000000000000000000000000000000000000..5c84588bffc5a9354150c3c0ed2a05a5fd02ccea GIT binary patch literal 108920 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�u*%Gnq}Z49rfl?G|B& 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 literal 0 HcmV?d00001 diff --git a/tools/test/resource/tools/ohos_test.xml b/tools/test/resource/tools/ohos_test.xml new file mode 100644 index 00000000000..d94a2929fc9 --- /dev/null +++ b/tools/test/resource/tools/ohos_test.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tools/zip/include/checked_cast.h b/tools/zip/include/checked_cast.h index 8c67e4c0fb1..76e1cc60eed 100755 --- a/tools/zip/include/checked_cast.h +++ b/tools/zip/include/checked_cast.h @@ -18,6 +18,7 @@ #include #include #include +#include "hilog_wrapper.h" namespace hidden { // workaroud for T& equally matching f(T&) and f(T const&) @@ -88,10 +89,10 @@ struct checked_cast_impl { { #ifdef CHECKED_CAST_SAFE_CONVERSATION T t = dynamic_cast(x); - // check cross cast - if (t != static_cast(x)) + if (t != static_cast(x)) { BAD_CHECKED_CAST(x, T); + } return t; #else return static_cast(x); @@ -104,8 +105,9 @@ struct checked_cast_impl { T t = dynamic_cast(x); // check cross cast - if (t != static_cast(x)) + if (t != static_cast(x)) { BAD_CHECKED_CAST(x, T); + } return t; #else return static_cast(x); @@ -118,12 +120,12 @@ struct checked_cast_impl { static T cast(X &x, hidden::LookUpHelper2 const &) { #ifdef CHECKED_CAST_SAFE_CONVERSATION - T t = dynamic_cast(x); - // check cross cast - if (&t != &static_cast(x)) { - throw std::bad_cast(); - } - return t; + T t = dynamic_cast(x); + // check cross cast + if (&t != &static_cast(x)) { + HILOG_ERROR("!!!bad cast!!!"); + } + return t; #else return static_cast(x); #endif @@ -132,16 +134,12 @@ struct checked_cast_impl { static T cast(X const &x, hidden::LookUpHelper const &) { #ifdef CHECKED_CAST_SAFE_CONVERSATION - try { - T t = dynamic_cast(x); - - // check cross cast - if (&t != &static_cast(x)) - std::bad_cast(); - return t; - } catch (...) { - BAD_CHECKED_CAST(x, T); + T t = dynamic_cast(x); + // check cross cast + if (&t != &static_cast(x)) { + std::bad_cast(); } + return t; #else return static_cast(x); #endif diff --git a/tools/zip/include/zip_reader.h b/tools/zip/include/zip_reader.h index 4f92db6ec0c..f2da18cad56 100755 --- a/tools/zip/include/zip_reader.h +++ b/tools/zip/include/zip_reader.h @@ -53,7 +53,6 @@ public: class ZipReader { public: // A callback that is called when the operation is successful. - // using SuccessCallback = base::OnceClosure; using SuccessCallback = std::function; // A callback that is called when the operation fails. using FailureCallback = std::function; @@ -112,7 +111,14 @@ public: private: FilePath filePath_; int64_t originalSize_ = 0; - struct tm lastModified_; + struct tm lastModified_ { + .tm_year = 0, + .tm_mon = 0, + .tm_mday = 0, + .tm_hour = 0, + .tm_min = 0, + .tm_sec = 0 + }; bool isDirectory_ = false; bool isUnsafe_ = false; bool isEncrypted_ = false; diff --git a/tools/zip/kits/js/@ohos.zlib.d.ts b/tools/zip/kits/js/@ohos.zlib.d.ts index 2fc4a4dec04..6fc60c4080d 100644 --- a/tools/zip/kits/js/@ohos.zlib.d.ts +++ b/tools/zip/kits/js/@ohos.zlib.d.ts @@ -16,7 +16,7 @@ import { AsyncCallback } from './basic'; declare namespace zlib { - //Zlib library constant definition + // Zlib library constant definition export enum FlushType { FLUSH_TYPE_NO_FLUSH = 0, FLUSH_TYPE_PARTIAL_FLUSH = 1, @@ -42,7 +42,7 @@ declare namespace zlib { ERROR_CODE_VERSION_ERROR = -6 } - //enum CompressLevel + // enum CompressLevel export enum CompressLevel { COMPRESS_LEVEL_NO_COMPRESSION = 0, COMPRESS_LEVEL_BEST_SPEED = 1, @@ -50,7 +50,7 @@ declare namespace zlib { COMPRESS_LEVEL_DEFAULT_COMPRESSION = -1 } - //enum CompressStrategy + // enum CompressStrategy export enum CompressStrategy { COMPRESS_STRATEGY_DEFAULT_STRATEGY = 0, COMPRESS_STRATEGY_FILTERED = 1, @@ -59,34 +59,34 @@ declare namespace zlib { COMPRESS_STRATEGY_FIXED = 4 } - //enum MemLevel + // enum MemLevel export enum MemLevel { MEM_LEVEL_MIN_MEMLEVEL = 1, MEM_LEVEL_DEFAULT_MEMLEVEL = 8, MEM_LEVEL_MAX_MEMLEVEL = 9 } - //zip options + // zip options interface Options { - flush?: FlushType; //corresponding zlib library macro - finishFlush?: FlushType; //corresponding zlib library macro #define Z_FINISH 4 - chunkSize?: number; //Buffer size,>64 - level?: CompressLevel; //Compression level. The compression level is a number from 0 to 9. - //0 has the fastest compression speed (compression process), 9 has the slowest compression speed, + flush?: FlushType; // corresponding zlib library macro + finishFlush?: FlushType; // corresponding zlib library macro #define Z_FINISH 4 + chunkSize?: number; // Buffer size,>64 + level?: CompressLevel; // Compression level. The compression level is a number from 0 to 9. + // 0 has the fastest compression speed (compression process), 9 has the slowest compression speed, // the largest compression rate, and 0 does not compress. - memLevel?: MemLevel; //How much memory should be allocated for the specified internal compression state. + memLevel?: MemLevel; // How much memory should be allocated for the specified internal compression state. // Memlevel = 1 uses the minimum memory, but it is very slow, reducing the compression ratio; Memlevel = 9 uses the maximum memory to get the best speed. The default value is 8. - strategy?: CompressStrategy; //CompressStrategy - dictionary?: ArrayBuffer; //deflate/inflate only, empty dictionary by default + strategy?: CompressStrategy; // CompressStrategy + dictionary?: ArrayBuffer; // deflate/inflate only, empty dictionary by default } - //The interface for compressing the specified file. There is only one callback callback interface + // The interface for compressing the specified file. There is only one callback callback interface function zipFile(inFile:string, outFile:string, options: Options, callback: AsyncCallback): void; function zipFile(inFile:string, outFile:string, options: Options): Promise; - //The interface for decompressing the specified file. There is only one callback callback interface + // The interface for decompressing the specified file. There is only one callback callback interface function unzipFile(inFile:string, outFile:string, options: Options, callback: AsyncCallback): void; function unzipFile(inFile:string, outFile:string, options: Options): Promise; } diff --git a/tools/zip/kits/napi/napi_zlib.cpp b/tools/zip/kits/napi/napi_zlib.cpp index 7f6b765750d..4e88aceb1fc 100755 --- a/tools/zip/kits/napi/napi_zlib.cpp +++ b/tools/zip/kits/napi/napi_zlib.cpp @@ -26,9 +26,6 @@ namespace OHOS { namespace AAFwk { namespace LIBZIP { -namespace { -const int E_OK = 0; -} #define NO_ERROR 0 #define COMPRESS_LEVE_CHECK(level, ret) \ @@ -491,10 +488,10 @@ napi_value NAPI_UnzipFile(napi_env env, napi_callback_info info) g_unzipAceCallbackInfo = nullptr; } if (asyncZipCallbackInfo != nullptr) { + napi_delete_async_work(env, asyncZipCallbackInfo->asyncWork); delete asyncZipCallbackInfo; asyncZipCallbackInfo = nullptr; } - } HILOG_INFO("%{public}s,end", __func__); return ret; @@ -684,7 +681,7 @@ void ZipAndUnzipFileAsyncCallBack(std::shared_ptr &zipAceCallb zipAceCallbackInfo.reset(); zipAceCallbackInfo = nullptr; work->data = (void *)asyncCallbackInfo; - int rev = uv_queue_work( + uv_queue_work( loop, work, [](uv_work_t *work) {}, @@ -693,22 +690,19 @@ void ZipAndUnzipFileAsyncCallBack(std::shared_ptr &zipAceCallb ZipAndUnzipFileAsyncCallBackInnerJsThread(work); HILOG_INFO("ZipAndUnzipFileAsyncCallBack, uv_queue_work end."); }); - if (rev != E_OK) { - if (asyncCallbackInfo->isCallBack) { - if (asyncCallbackInfo->callback != nullptr) { - napi_delete_reference(asyncCallbackInfo->env, asyncCallbackInfo->callback); - } - } - if (asyncCallbackInfo != nullptr) { - delete asyncCallbackInfo; - asyncCallbackInfo = nullptr; - } - if (work != nullptr) { - delete work; - work = nullptr; + if (asyncCallbackInfo->isCallBack) { + if (asyncCallbackInfo->callback != nullptr) { + napi_delete_reference(asyncCallbackInfo->env, asyncCallbackInfo->callback); } } - return; + if (asyncCallbackInfo != nullptr) { + delete asyncCallbackInfo; + asyncCallbackInfo = nullptr; + } + if (work != nullptr) { + delete work; + work = nullptr; + } } } // namespace LIBZIP diff --git a/tools/zip/src/zip_internal.cpp b/tools/zip/src/zip_internal.cpp index 3674e618134..34b4258ee8d 100755 --- a/tools/zip/src/zip_internal.cpp +++ b/tools/zip/src/zip_internal.cpp @@ -27,7 +27,14 @@ namespace LIBZIP { struct tm GetTmDataFromTickts(int64_t sec) { time_t second = (time_t)sec; - struct tm now; + struct tm now { + .tm_year = 0, + .tm_mon = 0, + .tm_mday = 0, + .tm_hour = 0, + .tm_min = 0, + .tm_sec = 0, + }; struct tm *tmNow = localtime(&second); if (tmNow == nullptr) { return now; @@ -143,9 +150,9 @@ uLong ReadZipBuffer(void *opaque, void *, void *buf, uLong size) // Writes compressed data to the stream. This function always returns zero // because this implementation is only for reading compressed data. -uLong WriteZipBuffer(void *, void *, const void *, uLong) +uLong WriteZipBuffer(void *opaque, void *stream, const void *buf, uLong) { - HILOG_INFO("%{public}s called.", __func__); + HILOG_INFO("%{public}s called. opaque=%p, stream=%p, buf=%p", __func__, opaque, stream, buf); return 0; } @@ -236,8 +243,9 @@ unzFile PrepareMemoryForUnzipping(const std::string &data) return NULL; } ZipBuffer *buffer = static_cast(malloc(sizeof(ZipBuffer))); - if (!buffer) + if (!buffer) { return NULL; + } buffer->data = data.data(); buffer->length = data.length(); buffer->offset = 0; diff --git a/tools/zip/src/zip_writer.cpp b/tools/zip/src/zip_writer.cpp index 777c5510331..319685d1acc 100755 --- a/tools/zip/src/zip_writer.cpp +++ b/tools/zip/src/zip_writer.cpp @@ -197,9 +197,6 @@ bool ZipWriter::FlushEntriesIfNeeded(bool force, const OPTIONS &options, CALLBAC for (auto iter = pendingEntries_.begin(); iter != pendingEntries_.begin() + entry_count; ++iter) { // The FileAccessor requires absolute paths. absolutePaths.push_back(FilePath(rootDir_.Value() + iter->Value())); - - printf("--zip-33--relativePaths=%s--\n", relativePaths[0].Value().c_str()); - printf("--zip-55--absolutePaths=%s--\n", (rootDir_.Value() + iter->Value()).c_str()); } pendingEntries_.erase(pendingEntries_.begin(), pendingEntries_.begin() + entry_count); @@ -211,15 +208,12 @@ bool ZipWriter::FlushEntriesIfNeeded(bool force, const OPTIONS &options, CALLBAC FilePath &relativePath = relativePaths[i]; FilePath &absolutePath = absolutePaths[i]; if (FilePath::PathIsValid(absolutePath)) { - printf("--zip-88--relativePath=%s--\n", relativePath.Value().c_str()); - printf("--zip-99--absolutePath=%s--\n", absolutePath.Value().c_str()); if (!AddFileEntryToZip(zipFile_, relativePath, absolutePath, options)) { CALLING_CALL_BACK(callback, ERROR_CODE_ERRNO) HILOG_INFO("%{public}s called, Failed to write file", __func__); return false; } } else { - printf("--zip-66--\n"); // Missing file or directory case. struct tm *last_modified = GetCurrentSystemTime(); if (!AddDirectoryEntryToZip(zipFile_, relativePath, last_modified, options)) { -- Gitee