1 /*
2 * Copyright (C) 2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <string>
17 #include <dlfcn.h>
18 #include <thread>
19 #include <cstdint>
20 #define MLOG_TAG "MediaMtpServiceManager"
21
22 #include "media_mtp_service_manager.h"
23 #include "media_log.h"
24
25 namespace OHOS {
26 namespace Media {
27 namespace {
28 constexpr int64_t WAIT_TIMEOUT = 60000; // 60s
29 const std::string PLUGIN_SO_PATH = "libmedia_mtp.z.so";
30 const std::string STOP_MTP_SERVICE = "StopMtpService";
31 const std::string START_MTP_SERVICE = "StartMtpService";
32 }
33
StopMtpService()34 void MediaMtpServiceManager::StopMtpService()
35 {
36 MEDIA_INFO_LOG("mtp MediaMtpServiceManager StopMtpService");
37 CHECK_AND_RETURN_LOG(handler_, "Dynamic library libmedia_mtp.z.so not loaded");
38
39 using StopMtpServiceFunc = void(*)();
40 StopMtpServiceFunc stopMtpService = (StopMtpServiceFunc)dlsym(handler_, STOP_MTP_SERVICE.c_str());
41 if (stopMtpService == nullptr) {
42 MEDIA_ERR_LOG("Not find stopMtpService func.");
43 CloseLibrary();
44 return;
45 }
46
47 stopMtpService();
48 isNeedClose_.store(true);
49 NotifyRefreshStopWaitTime();
50 }
51
StartMtpService(const MtpMode mode)52 void MediaMtpServiceManager::StartMtpService(const MtpMode mode)
53 {
54 MEDIA_INFO_LOG("mtp MediaMtpServiceManager StartMtpService");
55 if (handler_ == nullptr) {
56 handler_ = dlopen(PLUGIN_SO_PATH.c_str(), RTLD_NOW);
57 CHECK_AND_RETURN_LOG(handler_, "Not find libmedia_mtp.z.so");
58 }
59
60 using StartMtpServiceFunc = void(*)(uint32_t mtpMode);
61 StartMtpServiceFunc startMtpServiceFunc = (StartMtpServiceFunc) dlsym(handler_, START_MTP_SERVICE.c_str());
62 if (startMtpServiceFunc == nullptr) {
63 MEDIA_ERR_LOG("mtp dlsym failed: %{public}s", dlerror());
64 CloseLibrary();
65 return;
66 }
67 startMtpServiceFunc(static_cast<uint32_t>(mode));
68 isNeedClose_.store(false);
69 isTimerRefresh_.store(true);
70 cv_.notify_all();
71 }
72
NotifyRefreshStopWaitTime()73 void MediaMtpServiceManager::NotifyRefreshStopWaitTime()
74 {
75 MEDIA_INFO_LOG("mtp NotifyRefreshStopWaitTime");
76 isTimerRefresh_.store(true);
77 if (isThreadRunning_.load()) {
78 cv_.notify_all();
79 } else {
80 isThreadRunning_.store(true);
81 std::thread([&] { CloseDlopenByStop(); }).detach();
82 }
83 }
84
CloseDlopenByStop()85 void MediaMtpServiceManager::CloseDlopenByStop()
86 {
87 while (isThreadRunning_.load()) {
88 {
89 std::unique_lock<std::mutex> lock(mutex_);
90 isTimerRefresh_.store(false);
91 cv_.wait_for(lock, std::chrono::milliseconds(WAIT_TIMEOUT), [] {
92 return isTimerRefresh_.load() || !isThreadRunning_.load();
93 });
94 CHECK_AND_CONTINUE(!isTimerRefresh_.load());
95 }
96 if (!isThreadRunning_.load()) {
97 CloseLibrary();
98 return;
99 }
100 MEDIA_INFO_LOG("mtp CloseDlopenByStop dlclose start isNeedClose_: %{public}d", isNeedClose_.load());
101 if (isNeedClose_.load()) {
102 CloseLibrary();
103 }
104 }
105 }
106
CloseLibrary()107 void MediaMtpServiceManager::CloseLibrary()
108 {
109 isThreadRunning_.store(false);
110 isNeedClose_.store(false);
111 isTimerRefresh_.store(false);
112 cv_.notify_all();
113 if (handler_ != nullptr) {
114 dlclose(handler_);
115 handler_ = nullptr;
116 MEDIA_DEBUG_LOG("Dynamic library libmedia_mtp.z.so closed");
117 }
118 }
119 } // namespace Media
120 } // namespace OHOS