• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024-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 #include "charging_sound.h"
16 
17 #include <dlfcn.h>
18 #include <mutex>
19 #include <securec.h>
20 #include "audio_stream_info.h"
21 #include "battery_log.h"
22 #include "config_policy_utils.h"
23 #include "errors.h"
24 #include "player.h"
25 
26 namespace OHOS {
27 namespace PowerMgr {
28 // static non-local initializations
29 constexpr const char* CHARGER_SOUND_DEFAULT_PATH = "/vendor/etc/battery/PowerConnected.ogg";
30 constexpr const char* CHARGER_SOUND_RELATIVE_PATH = "resource/media/audio/ui/PowerConnected.ogg";
31 std::mutex g_playerPtrMutex;
32 
33 // this static object is used as constructor/destructor, for now only one single instance is allowed.
34 std::shared_ptr<ChargingSound> ChargingSound::instance_ = std::make_shared<ChargingSound>();
35 
36 namespace {
ICUCleanUp()37 void ICUCleanUp()
38 {
39     void* icuHandle = dlopen("libhmicuuc.z.so", RTLD_LAZY);
40     if (!icuHandle) {
41         BATTERY_HILOGE(COMP_SVC, "%{public}s: open so failed", __func__);
42         return;
43     }
44     auto getIcuVersion = reinterpret_cast<const char* (*)(void)>(dlsym(icuHandle, "GetIcuVersion"));
45     if (!getIcuVersion) {
46         BATTERY_HILOGE(COMP_SVC, "find GetIcuVersion symbol failed");
47         dlclose(icuHandle);
48         return;
49     }
50     const char* version = getIcuVersion();
51     constexpr int maxLength = 100;
52     constexpr const char* icuCleanFuncName = "u_cleanup";
53     auto buffer = std::make_unique<char[]>(maxLength);
54     int ret = sprintf_s(buffer.get(), maxLength, "%s_%s", icuCleanFuncName, version);
55     if (ret < 0) {
56         BATTERY_HILOGE(COMP_SVC, "string operation failed");
57         dlclose(icuHandle);
58         return;
59     }
60     auto CleanUp = reinterpret_cast<void (*)(void)>(dlsym(icuHandle, buffer.get()));
61     if (!CleanUp) {
62         BATTERY_HILOGE(COMP_SVC, "find u_cleanup symbol failed");
63         dlclose(icuHandle);
64     }
65     CleanUp();
66     dlclose(icuHandle);
67 }
68 } // namespace
69 
GetPath(const char * uri) const70 std::string ChargingSound::GetPath(const char* uri) const
71 {
72     std::string ret {};
73     char buf[MAX_PATH_LEN] = {0};
74     char* path = GetOneCfgFile(uri, buf, MAX_PATH_LEN);
75     if (path) {
76         ret = path;
77     }
78     return ret;
79 }
80 
ChargingSound()81 ChargingSound::ChargingSound()
82 {
83     uri_ = GetPath(CHARGER_SOUND_RELATIVE_PATH);
84     if (uri_.empty()) {
85         BATTERY_HILOGE(COMP_SVC, "get sound path failed, using fallback path");
86         uri_ = std::string{CHARGER_SOUND_DEFAULT_PATH};
87     }
88     BATTERY_HILOGI(COMP_SVC, "ChargingSound instance created");
89 }
90 
~ChargingSound()91 ChargingSound::~ChargingSound()
92 {
93     Release();
94     std::shared_ptr<Media::Player> tmp = std::atomic_load_explicit(&player_, std::memory_order_acquire);
95     if (tmp) {
96         tmp->ReleaseClientListener();
97     }
98     ICUCleanUp();
99     BATTERY_HILOGI(COMP_SVC, "ChargingSound instance destroyed");
100 }
101 
Stop()102 void ChargingSound::Stop()
103 {
104     std::shared_ptr<Media::Player> tmp = std::atomic_load_explicit(&player_, std::memory_order_acquire);
105     if (tmp) {
106         tmp->Stop();
107     }
108     isPlaying_.store(false);
109 }
110 
Release()111 void ChargingSound::Release()
112 {
113     std::shared_ptr<Media::Player> tmp = std::atomic_load_explicit(&player_, std::memory_order_acquire);
114     if (tmp) {
115         tmp->ReleaseSync();
116     }
117     isPlaying_.store(false);
118 }
119 
Play()120 bool ChargingSound::Play()
121 {
122     std::shared_ptr<Media::Player> tmp = std::atomic_load_explicit(&player_, std::memory_order_acquire);
123     if (!tmp) {
124         std::lock_guard<std::mutex> lock(g_playerPtrMutex);
125         tmp = std::atomic_load_explicit(&player_, std::memory_order_relaxed);
126         if (!tmp) {
127             tmp = Media::PlayerFactory::CreatePlayer();
128         }
129         std::atomic_store_explicit(&player_, tmp, std::memory_order_release);
130     }
131     if (!tmp) {
132         BATTERY_HILOGE(COMP_SVC, "create player failed");
133         return false;
134     }
135     tmp->Reset(); // reset avplayer
136     int32_t ret = Media::MSERR_OK;
137     ret = tmp->SetSource(uri_);
138     if (ret != Media::MSERR_OK) {
139         BATTERY_HILOGE(COMP_SVC, "set stream source failed, ret=%{public}d", ret);
140         return false;
141     }
142     Media::Format format;
143     format.PutIntValue(Media::PlayerKeys::CONTENT_TYPE, AudioStandard::CONTENT_TYPE_UNKNOWN);
144     format.PutIntValue(Media::PlayerKeys::STREAM_USAGE, AudioStandard::STREAM_USAGE_SYSTEM);
145     ret = tmp->SetParameter(format);
146     if (ret != Media::MSERR_OK) {
147         BATTERY_HILOGE(COMP_SVC, "Set stream usage to Player failed, ret=%{public}d", ret);
148         return false;
149     }
150     ret = tmp->Prepare();
151     if (ret != Media::MSERR_OK) {
152         BATTERY_HILOGE(COMP_SVC, "prepare failed, ret=%{public}d", ret);
153         return false;
154     }
155     isPlaying_.store(true);
156     ret = tmp->Play();
157     if (ret != Media::MSERR_OK) {
158         BATTERY_HILOGE(COMP_SVC, "play failed, ret=%{public}d", ret);
159         isPlaying_.store(false);
160         return false;
161     }
162     return true;
163 }
164 
IsPlaying()165 bool ChargingSound::IsPlaying()
166 {
167     return isPlaying_.load();
168 }
169 
IsPlayingGlobal()170 bool ChargingSound::IsPlayingGlobal()
171 {
172     return instance_->IsPlaying();
173 }
174 
PlayGlobal()175 bool ChargingSound::PlayGlobal()
176 {
177     bool ret = instance_->Play();
178     if (!ret) {
179         instance_->Release();
180     }
181     return ret;
182 }
183 
ReleaseGlobal()184 void ChargingSound::ReleaseGlobal()
185 {
186     instance_->Release();
187 }
188 
189 //APIs
ChargingSoundStart()190 bool ChargingSoundStart()
191 {
192     return ChargingSound::PlayGlobal();
193 }
194 
IsPlaying()195 bool IsPlaying()
196 {
197     return ChargingSound::IsPlayingGlobal();
198 }
199 
200 } // namespace PowerMgr
201 } // namespace OHOS