1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "media_avsession_adapter_impl.h"
17 
18 #include "ability_manager_client.h"
19 #include "avsession_errors.h"
20 #include "avsession_manager.h"
21 #include "bundle_mgr_proxy.h"
22 #include "element_name.h"
23 #include "if_system_ability_manager.h"
24 #include "iservice_registry.h"
25 #include "nweb_log.h"
26 #include "parameters.h"
27 #include "system_ability_definition.h"
28 
29 namespace OHOS::NWeb {
30 
31 std::unordered_map<std::string, std::shared_ptr<AVSession::AVSession>> MediaAVSessionAdapterImpl::avSessionMap;
32 
33 constexpr int64_t LIVE_STREAM_INFINITE_DURATION = -1;
34 
MediaAVSessionCallbackImpl(std::shared_ptr<MediaAVSessionCallbackAdapter> callbackAdapter)35 MediaAVSessionCallbackImpl::MediaAVSessionCallbackImpl(
36     std::shared_ptr<MediaAVSessionCallbackAdapter> callbackAdapter)
37     : callbackAdapter_(callbackAdapter)
38 {
39 }
40 
OnPlay()41 void MediaAVSessionCallbackImpl::OnPlay()
42 {
43     if (callbackAdapter_) {
44         callbackAdapter_->Play();
45     }
46 }
47 
OnPause()48 void MediaAVSessionCallbackImpl::OnPause()
49 {
50     if (callbackAdapter_) {
51         callbackAdapter_->Pause();
52     }
53 }
54 
OnStop()55 void MediaAVSessionCallbackImpl::OnStop()
56 {
57     if (callbackAdapter_) {
58         callbackAdapter_->Stop();
59     }
60 }
61 
OnPlayNext()62 void MediaAVSessionCallbackImpl::OnPlayNext()
63 {
64 }
65 
OnPlayPrevious()66 void MediaAVSessionCallbackImpl::OnPlayPrevious()
67 {
68 }
69 
OnFastForward(int64_t time)70 void MediaAVSessionCallbackImpl::OnFastForward(int64_t time)
71 {
72 }
73 
OnRewind(int64_t time)74 void MediaAVSessionCallbackImpl::OnRewind(int64_t time)
75 {
76 }
77 
OnSeek(int64_t time)78 void MediaAVSessionCallbackImpl::OnSeek(int64_t time)
79 {
80     if (callbackAdapter_) {
81         callbackAdapter_->SeekTo(time);
82     }
83 }
84 
OnSetSpeed(double speed)85 void MediaAVSessionCallbackImpl::OnSetSpeed(double speed)
86 {
87 }
88 
OnSetLoopMode(int32_t loopMode)89 void MediaAVSessionCallbackImpl::OnSetLoopMode(int32_t loopMode)
90 {
91 }
92 
OnToggleFavorite(const std::string & assertId)93 void MediaAVSessionCallbackImpl::OnToggleFavorite(const std::string& assertId)
94 {
95 }
96 
OnMediaKeyEvent(const MMI::KeyEvent & keyEvent)97 void MediaAVSessionCallbackImpl::OnMediaKeyEvent(const MMI::KeyEvent& keyEvent)
98 {
99 }
100 
OnOutputDeviceChange(const int32_t connectionState,const AVSession::OutputDeviceInfo & outputDeviceInfo)101 void MediaAVSessionCallbackImpl::OnOutputDeviceChange(const int32_t connectionState,
102     const AVSession::OutputDeviceInfo& outputDeviceInfo)
103 {
104 }
105 
OnCommonCommand(const std::string & commonCommand,const AAFwk::WantParams & commandArgs)106 void MediaAVSessionCallbackImpl::OnCommonCommand(
107     const std::string& commonCommand,
108     const AAFwk::WantParams& commandArgs)
109 {
110 }
111 
OnSkipToQueueItem(int32_t itemId)112 void MediaAVSessionCallbackImpl::OnSkipToQueueItem(int32_t itemId)
113 {
114 }
115 
OnAVCallAnswer()116 void MediaAVSessionCallbackImpl::OnAVCallAnswer()
117 {
118 }
119 
OnAVCallHangUp()120 void MediaAVSessionCallbackImpl::OnAVCallHangUp()
121 {
122 }
123 
OnAVCallToggleCallMute()124 void MediaAVSessionCallbackImpl::OnAVCallToggleCallMute()
125 {
126 }
127 
OnPlayFromAssetId(int64_t assetId)128 void MediaAVSessionCallbackImpl::OnPlayFromAssetId(int64_t assetId)
129 {
130 }
131 
OnCastDisplayChange(const AVSession::CastDisplayInfo & castDisplayInfo)132 void MediaAVSessionCallbackImpl::OnCastDisplayChange(
133     const AVSession::CastDisplayInfo& castDisplayInfo)
134 {
135 }
136 
Init()137 void MediaAVSessionKey::Init()
138 {
139     pid_ = getprocpid();
140     element_ = AAFwk::AbilityManagerClient::GetInstance()->GetTopAbility();
141     auto context = AbilityRuntime::ApplicationContext::GetApplicationContext();
142     if (context) {
143         element_.SetBundleName(context->GetBundleName());
144     }
145     type_ = MediaAVSessionType::MEDIA_TYPE_INVALID;
146 
147     // SA application can get AbilityName by GetTopAbility, but others cannnot.
148     if (!element_.GetAbilityName().empty()) {
149         return;
150     }
151 
152     sptr<ISystemAbilityManager> systemAbilityManager =
153         SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
154     if (systemAbilityManager == nullptr) {
155         WVLOG_E("get SystemAbilityManager failed");
156         return;
157     }
158     sptr<IRemoteObject> remoteObject =
159         systemAbilityManager->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
160     if (remoteObject == nullptr) {
161         WVLOG_E("get Bundle Manager failed");
162         return;
163     }
164     auto bundleMgr = iface_cast<AppExecFwk::IBundleMgr>(remoteObject);
165     if (bundleMgr == nullptr) {
166         WVLOG_E("get Bundle Manager failed");
167         return;
168     }
169     AppExecFwk::BundleInfo bundleInfo;
170     auto flag = (static_cast<int32_t>(AppExecFwk::GetBundleInfoFlag::GET_BUNDLE_INFO_WITH_HAP_MODULE) |
171                  static_cast<int32_t>(AppExecFwk::GetBundleInfoFlag::GET_BUNDLE_INFO_WITH_ABILITY));
172     if (bundleMgr->GetBundleInfoForSelf(flag, bundleInfo) != 0) {
173         WVLOG_E("get bundle info failed");
174         return;
175     }
176     auto hapModuleInfos = bundleInfo.hapModuleInfos;
177     if (hapModuleInfos.empty()) {
178         WVLOG_E("get hapModuleInfos failed");
179         return;
180     }
181     auto abilityInfos = hapModuleInfos[0].abilityInfos;
182     if (abilityInfos.empty()) {
183         WVLOG_E("get abilityInfos failed");
184         return;
185     }
186     element_.SetAbilityName(abilityInfos[0].name);
187     return;
188 }
189 
GetPID()190 int32_t MediaAVSessionKey::GetPID()
191 {
192     return pid_;
193 }
194 
GetElement()195 AppExecFwk::ElementName MediaAVSessionKey::GetElement()
196 {
197     return element_;
198 }
199 
SetType(MediaAVSessionType type)200 void MediaAVSessionKey::SetType(MediaAVSessionType type)
201 {
202     type_ = type;
203 }
204 
GetType()205 MediaAVSessionType MediaAVSessionKey::GetType()
206 {
207     return type_;
208 }
209 
ToString()210 std::string MediaAVSessionKey::ToString()
211 {
212     return (std::to_string(pid_) + "_" + element_.GetBundleName() + "_" + element_.GetAbilityName());
213 }
214 
MediaAVSessionAdapterImpl()215 MediaAVSessionAdapterImpl::MediaAVSessionAdapterImpl()
216 {
217     avSessionKey_ = std::make_shared<MediaAVSessionKey>();
218     avSessionKey_->Init();
219     avMetadata_ = std::make_shared<AVSession::AVMetaData>();
220     avMetadata_->SetAssetId(std::to_string(avSessionKey_->GetPID()));
221     avPlaybackState_ = std::make_shared<AVSession::AVPlaybackState>();
222 }
223 
~MediaAVSessionAdapterImpl()224 MediaAVSessionAdapterImpl::~MediaAVSessionAdapterImpl()
225 {
226     DestroyAVSession();
227 }
228 
CreateAVSession(MediaAVSessionType type)229 bool MediaAVSessionAdapterImpl::CreateAVSession(MediaAVSessionType type)
230 {
231     if (MediaAVSessionType::MEDIA_TYPE_INVALID == type) {
232         return false;
233     }
234     if (avSession_ && (type != avSessionKey_->GetType())) {
235         DestroyAVSession();
236     }
237     auto findIter = avSessionMap.find(avSessionKey_->ToString());
238     if (!avSession_) {
239         if (findIter != avSessionMap.end()) {
240             DestroyAndEraseSession();
241         }
242         return CreateNewSession(type);
243     } else {
244         if (findIter != avSessionMap.end()) {
245             if (findIter->second.get() != avSession_.get()) {
246                 DestroyAndEraseSession();
247                 DestroyAVSession();
248             } else {
249                 return false;
250             }
251         }
252         return CreateNewSession(type);
253     }
254 }
255 
DestroyAVSession()256 void MediaAVSessionAdapterImpl::DestroyAVSession()
257 {
258     if (avSession_) {
259         int32_t ret = avSession_->Destroy();
260         if (ret != AVSession::AVSESSION_SUCCESS) {
261             WVLOG_E("media avsession adapter destroy avsession failed, ret: %{public}d", ret);
262         }
263         avSession_.reset();
264     }
265     auto iter = avSessionMap.find(avSessionKey_->ToString());
266     if (iter != avSessionMap.end()) {
267         avSessionMap.erase(iter);
268     }
269 }
270 
RegistCallback(std::shared_ptr<MediaAVSessionCallbackAdapter> callbackAdapter)271 bool MediaAVSessionAdapterImpl::RegistCallback(
272     std::shared_ptr<MediaAVSessionCallbackAdapter> callbackAdapter)
273 {
274     if (avSession_ && Activate()) {
275         auto callback = std::make_shared<MediaAVSessionCallbackImpl>(callbackAdapter);
276         int32_t ret = avSession_->RegisterCallback(callback);
277         if (ret != AVSession::AVSESSION_SUCCESS) {
278             WVLOG_E("media avsession adapter register callback failed, ret: %{public}d", ret);
279             return false;
280         }
281         static const std::vector<int32_t> commands = {
282             AVSession::AVControlCommand::SESSION_CMD_PLAY,
283             AVSession::AVControlCommand::SESSION_CMD_PAUSE,
284             AVSession::AVControlCommand::SESSION_CMD_STOP,
285             AVSession::AVControlCommand::SESSION_CMD_SEEK
286         };
287         for (auto command : commands) {
288             ret = avSession_->AddSupportCommand(command);
289             if (ret != AVSession::AVSESSION_SUCCESS) {
290                 WVLOG_E("media avsession adapter add command '%{public}d' failed, ret: %{public}d", command, ret);
291             }
292         }
293         return true;
294     }
295     return false;
296 }
297 
IsActivated()298 bool MediaAVSessionAdapterImpl::IsActivated()
299 {
300     if (avSession_) {
301         return avSession_->IsActive();
302     }
303     return false;
304 }
305 
Activate()306 bool MediaAVSessionAdapterImpl::Activate()
307 {
308     if (!avSession_) {
309         return false;
310     } else if (avSession_->IsActive()) {
311         return true;
312     }
313     int32_t ret = avSession_->Activate();
314     if (ret != AVSession::AVSESSION_SUCCESS) {
315         WVLOG_E("media avsession adapter activate avsession failed, ret: %{public}d", ret);
316         return false;
317     }
318     return true;
319 }
320 
DeActivate()321 void MediaAVSessionAdapterImpl::DeActivate()
322 {
323     if (avSession_ && avSession_->IsActive()) {
324         int32_t ret = avSession_->Deactivate();
325         if (ret != AVSession::AVSESSION_SUCCESS) {
326             WVLOG_E("media avsession adapter deactivate avsession failed, ret: %{public}d", ret);
327         }
328     }
329 }
330 
SetMetadata(const std::shared_ptr<MediaAVSessionMetadataAdapter> metadata)331 void MediaAVSessionAdapterImpl::SetMetadata(const std::shared_ptr<MediaAVSessionMetadataAdapter> metadata)
332 {
333     UpdateMetaDataCache(metadata);
334     if (avSession_) {
335         Activate();
336         auto avMetadata = avMetadata_.get();
337         int32_t ret = avSession_->SetAVMetaData(*avMetadata);
338         if (ret != AVSession::AVSESSION_SUCCESS) {
339             WVLOG_E("media avsession adapter update metadata info failed, ret: %{public}d", ret);
340         }
341     }
342 }
343 
SetPlaybackState(MediaAVSessionPlayState state)344 void MediaAVSessionAdapterImpl::SetPlaybackState(MediaAVSessionPlayState state)
345 {
346     if (UpdatePlaybackStateCache(state) && avSession_) {
347         Activate();
348         auto avPlaybackState = avPlaybackState_.get();
349         int32_t ret = avSession_->SetAVPlaybackState(*avPlaybackState);
350         if (ret != AVSession::AVSESSION_SUCCESS) {
351             WVLOG_E("media avsession adapter update playback state failed, ret: %{public}d", ret);
352         }
353     }
354 }
355 
SetPlaybackPosition(const std::shared_ptr<MediaAVSessionPositionAdapter> position)356 void MediaAVSessionAdapterImpl::SetPlaybackPosition(const std::shared_ptr<MediaAVSessionPositionAdapter> position)
357 {
358     if (UpdateMetaDataCache(position) && avSession_) {
359         Activate();
360         auto avMetadata = avMetadata_.get();
361         int32_t ret = avSession_->SetAVMetaData(*avMetadata);
362         if (ret != AVSession::AVSESSION_SUCCESS) {
363             WVLOG_E("media avsession adapter update metadata duration failed, ret: %{public}d", ret);
364         }
365     }
366     if (UpdatePlaybackStateCache(position) && avSession_) {
367         Activate();
368         auto avPlaybackState = avPlaybackState_.get();
369         int32_t ret = avSession_->SetAVPlaybackState(*avPlaybackState);
370         if (ret != AVSession::AVSESSION_SUCCESS) {
371             WVLOG_E("media avsession adapter update playback position failed, ret: %{public}d", ret);
372         }
373     }
374 }
375 
UpdateMetaDataCache(const std::shared_ptr<MediaAVSessionMetadataAdapter> metadata)376 bool MediaAVSessionAdapterImpl::UpdateMetaDataCache(const std::shared_ptr<MediaAVSessionMetadataAdapter> metadata)
377 {
378     bool updated = false;
379     if (avMetadata_->GetTitle() != metadata->GetTitle()) {
380         avMetadata_->SetTitle(metadata->GetTitle());
381         updated = true;
382     }
383     if (avMetadata_->GetArtist() != metadata->GetArtist()) {
384         avMetadata_->SetArtist(metadata->GetArtist());
385         updated = true;
386     }
387     if (avMetadata_->GetAlbum() != metadata->GetAlbum()) {
388         avMetadata_->SetAlbum(metadata->GetAlbum());
389         updated = true;
390     }
391     return updated;
392 }
393 
UpdateMetaDataCache(const std::shared_ptr<MediaAVSessionPositionAdapter> position)394 bool MediaAVSessionAdapterImpl::UpdateMetaDataCache(const std::shared_ptr<MediaAVSessionPositionAdapter> position)
395 {
396     if (!position) {
397         WVLOG_E("position is nullptr, media avsession adapter UpdateMetaDataCache return false");
398         return false;
399     }
400     int64_t getDuration = position->GetDuration();
401     if (avMetadata_->GetDuration() != getDuration) {
402         if (getDuration < INT64_MAX) {
403             avMetadata_->SetDuration(getDuration);
404         } else {
405             avMetadata_->SetDuration(LIVE_STREAM_INFINITE_DURATION);
406         }
407         return true;
408     }
409     WVLOG_E("media avsession adapter UpdateMetaDataCache return false");
410     return false;
411 }
412 
UpdatePlaybackStateCache(MediaAVSessionPlayState state)413 bool MediaAVSessionAdapterImpl::UpdatePlaybackStateCache(MediaAVSessionPlayState state)
414 {
415     int32_t currentState;
416     switch (state) {
417         case MediaAVSessionPlayState::STATE_PLAY:
418             currentState = AVSession::AVPlaybackState::PLAYBACK_STATE_PLAY;
419             break;
420         case MediaAVSessionPlayState::STATE_PAUSE:
421             currentState = AVSession::AVPlaybackState::PLAYBACK_STATE_PAUSE;
422             break;
423         case MediaAVSessionPlayState::STATE_INITIAL:
424         default:
425             currentState = AVSession::AVPlaybackState::PLAYBACK_STATE_INITIAL;
426             break;
427     }
428     if (avPlaybackState_->GetState() != currentState) {
429         avPlaybackState_->SetState(currentState);
430         return true;
431     }
432     return false;
433 }
434 
UpdatePlaybackStateCache(const std::shared_ptr<MediaAVSessionPositionAdapter> position)435 bool MediaAVSessionAdapterImpl::UpdatePlaybackStateCache(
436     const std::shared_ptr<MediaAVSessionPositionAdapter> position)
437 {
438     bool updated = false;
439     auto duration = static_cast<int32_t>(position->GetDuration());
440     if (avPlaybackState_->GetDuration() != duration) {
441         avPlaybackState_->SetDuration(duration);
442         updated = true;
443     }
444     auto avPosition = avPlaybackState_->GetPosition();
445     if ((avPosition.elapsedTime_ != position->GetElapsedTime()) ||
446         (avPosition.updateTime_ != position->GetUpdateTime())) {
447         avPosition.elapsedTime_ = position->GetElapsedTime();
448         avPosition.updateTime_ = position->GetUpdateTime();
449         avPlaybackState_->SetPosition(avPosition);
450         updated = true;
451     }
452     return updated;
453 }
454 
DestroyAndEraseSession()455 void MediaAVSessionAdapterImpl::DestroyAndEraseSession()
456 {
457     auto iter = avSessionMap.find(avSessionKey_->ToString());
458     if (iter == avSessionMap.end()) {
459         WVLOG_E("media avsession adapter invalid iterator");
460         return;
461     }
462     if (!iter->second) {
463         WVLOG_E("media avsession adapter avsession is null pointer in map");
464         avSessionMap.erase(iter);
465         return;
466     }
467     int32_t ret = iter->second->Destroy();
468     if (ret != AVSession::AVSESSION_SUCCESS) {
469         WVLOG_E("media avsession adapter destroy previous avsession failed, ret: %{public}d", ret);
470     }
471     iter->second.reset();
472     avSessionMap.erase(iter);
473 }
474 
CreateNewSession(const MediaAVSessionType & type)475 bool MediaAVSessionAdapterImpl::CreateNewSession(const MediaAVSessionType& type)
476 {
477     avSession_ = AVSession::AVSessionManager::GetInstance().CreateSession(
478         avSessionKey_->GetElement().GetBundleName(),
479         static_cast<int32_t>(type),
480         avSessionKey_->GetElement());
481     if (avSession_) {
482         avSessionKey_->SetType(type);
483         avSessionMap.insert(std::make_pair(avSessionKey_->ToString(), avSession_));
484         return true;
485     } else {
486         WVLOG_E("media avsession adapter create avsession failed");
487         return false;
488     }
489 }
490 
491 } // namespace OHOS::NWeb