1/*
2 * Copyright (c) 2022-2023 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 <iostream>
17#include <ctime>
18
19#include "avsession_errors.h"
20#include "avsession_dumper.h"
21
22namespace OHOS::AVSession {
23const int32_t TIME_MAX = 64;
24const std::string ARGS_HELP = "-h";
25const std::string ILLEGAL_INFORMATION = "AVSession service, enter '-h' for usage.\n";
26const std::string ARGS_SHOW_METADATA = "-show_metadata";
27const std::string ARGS_SHOW_SESSION_INFO = "-show_session_info";
28const std::string ARGS_SHOW_CONTROLLER_INFO = "-show_controller_info";
29const std::string ARGS_SHOW_ERROR_INFO = "-show_error_info";
30const std::string ARGS_TRUSTED_DEVICES_INFO = "-show_trusted_devices_Info";
31
32std::map<std::string, AVSessionDumper::DumpActionType> AVSessionDumper::funcMap_ = {
33    { ARGS_SHOW_METADATA, AVSessionDumper::ShowMetaData },
34    { ARGS_SHOW_SESSION_INFO, AVSessionDumper::ShowSessionInfo },
35    { ARGS_SHOW_CONTROLLER_INFO, AVSessionDumper::ShowControllerInfo },
36    { ARGS_SHOW_ERROR_INFO, AVSessionDumper::ShowErrorInfo },
37    { ARGS_TRUSTED_DEVICES_INFO, AVSessionDumper::ShowTrustedDevicesInfo },
38};
39
40std::map<int32_t, std::string> AVSessionDumper::playBackStates_ = {
41    { AVPlaybackState::PLAYBACK_STATE_INITIAL, "initial" },
42    { AVPlaybackState::PLAYBACK_STATE_PREPARE, "preparing" },
43    { AVPlaybackState::PLAYBACK_STATE_PLAY, "playing" },
44    { AVPlaybackState::PLAYBACK_STATE_PAUSE, "paused" },
45    { AVPlaybackState::PLAYBACK_STATE_FAST_FORWARD, "fast_forward" },
46    { AVPlaybackState::PLAYBACK_STATE_REWIND, "rewind" },
47    { AVPlaybackState::PLAYBACK_STATE_STOP, "stop" },
48    { AVPlaybackState::PLAYBACK_STATE_COMPLETED, "complete" },
49    { AVPlaybackState::PLAYBACK_STATE_RELEASED, "released" },
50    { AVPlaybackState::PLAYBACK_STATE_ERROR, "error" },
51    { AVPlaybackState::PLAYBACK_STATE_IDLE, "idle" },
52    { AVPlaybackState::PLAYBACK_STATE_BUFFERING, "buffering" },
53};
54
55std::map<int32_t, std::string> AVSessionDumper::deviceTypeId_ = {
56    {DistributedHardware::DEVICE_TYPE_UNKNOWN, "unknown" },
57    {DistributedHardware::DEVICE_TYPE_WIFI_CAMERA, "camera" },
58    {DistributedHardware::DEVICE_TYPE_AUDIO, "audio" },
59    {DistributedHardware::DEVICE_TYPE_PC, "pc" },
60    {DistributedHardware::DEVICE_TYPE_PHONE, "phone" },
61    {DistributedHardware::DEVICE_TYPE_PAD, "pad" },
62    {DistributedHardware::DEVICE_TYPE_WATCH, "watch" },
63    {DistributedHardware::DEVICE_TYPE_CAR, "car" },
64    {DistributedHardware::DEVICE_TYPE_TV, "tv" },
65};
66
67std::map<int32_t, std::string> AVSessionDumper::loopMode_ = {
68    { AVPlaybackState::LOOP_MODE_SEQUENCE, "sequence" },
69    { AVPlaybackState::LOOP_MODE_SINGLE, "single" },
70    { AVPlaybackState::LOOP_MODE_LIST, "list" },
71    { AVPlaybackState::LOOP_MODE_SHUFFLE, "shuffle" },
72    { AVPlaybackState::LOOP_MODE_CUSTOM, "custom" },
73};
74
75std::vector<std::string> AVSessionDumper::errMessage_ = {};
76
77void AVSessionDumper::ShowHelp(std::string& result) const
78{
79    result.append("Usage:dump <command> [options]\n")
80        .append("Description:\n")
81        .append("-show_metadata               :show all avsession metadata in the system\n")
82        .append("-show_session_info           :show information of all sessions\n")
83        .append("-show_controller_info        :show information of all controllers \n")
84        .append("-show_error_info             :show error information about avsession\n")
85        .append("-show_trusted_devices_Info   :show trusted devices Info\n");
86}
87
88void AVSessionDumper::ShowMetaData(std::string& result, const AVSessionService& sessionService)
89{
90    int32_t controllerIndex = 0;
91    int32_t itemIndex = 0;
92    for (const auto& it : sessionService.controllers_) {
93        result.append("ControllerIndex: " + std::to_string(++controllerIndex) + "\n");
94        for (const auto& item : it.second) {
95            result.append("ItemIndex: " + std::to_string(++itemIndex)+ "\n");
96            AVMetaData metaData;
97            item->GetAVMetaData(metaData);
98
99            result.append("Metadata:\n");
100            result.append("        assetid              : " + metaData.GetAssetId() + "\n");
101            result.append("        title                : " + metaData.GetTitle() + "\n");
102            result.append("        artist               : " + metaData.GetArtist() + "\n");
103            result.append("        author               : " + metaData.GetAuthor() + "\n");
104            result.append("        avqueue name         : " + metaData.GetAVQueueName() + "\n");
105            result.append("        avqueue id           : " + metaData.GetAVQueueId() + "\n");
106            result.append("        avqueue url          : " + metaData.GetAVQueueImageUri() + "\n");
107            result.append("        album                : " + metaData.GetAlbum() + "\n");
108            result.append("        writer               : " + metaData.GetWriter() + "\n");
109            result.append("        composer             : " + metaData.GetComposer() + "\n");
110            result.append("        duration             : " + std::to_string(metaData.GetDuration()) + "\n");
111            result.append("        media image url      : " + metaData.GetMediaImageUri() + "\n");
112            result.append("        publish date         : " + std::to_string(metaData.GetPublishDate()) + "\n");
113            result.append("        subtitle             : " + metaData.GetSubTitle() + "\n");
114            result.append("        description          : " + metaData.GetDescription() + "\n");
115            result.append("        lyric                : " + metaData.GetLyric() + "\n");
116            result.append("        previous assetid     : " + metaData.GetPreviousAssetId() + "\n");
117            result.append("        next assetid         : " + metaData.GetNextAssetId() + "\n");
118            result.append("        skip intervals       : " + std::to_string(metaData.GetSkipIntervals()) + "\n");
119            result.append("        filter               : " + std::to_string(metaData.GetFilter()) + "\n");
120        }
121    }
122}
123
124void AVSessionDumper::ShowTrustedDevicesInfo(std::string& result, const AVSessionService& sessionService)
125{
126    std::vector<OHOS::DistributedHardware::DmDeviceInfo> deviceList;
127    DistributedHardware::DeviceManager::GetInstance().GetTrustedDeviceList("av_session", "", deviceList);
128
129    std::string buff;
130    result.append("Trusted Devices Info:\n\n")
131        .append("Count                          : " + std::to_string(deviceList.size()) + "\n");
132    for (const auto& device : deviceList) {
133        buff=device.deviceId;
134        result.append("         device id             : ");
135        result.append(buff + "  ");
136
137        buff=device.deviceName;
138        result.append("\n        device name            : ");
139        result.append(buff + "  ");
140
141        result.append("\n        device type id         : " + deviceTypeId_.find(device.deviceTypeId)->second);
142
143        buff=device.networkId;
144        result.append("\n        network  id            : ");
145        result.append(buff + "  ");
146
147        result.append("\n        range                  : " + std::to_string(device.range));
148        result.append("\n");
149    }
150}
151
152void AVSessionDumper::ShowSessionInfo(std::string& result, const AVSessionService& sessionService)
153{
154    std::vector<sptr<AVSessionItem>> sessions = sessionService.GetContainer().GetAllSessions();
155    result.append("Session Information:\n\n")
156        .append("Count                        : " + std::to_string(sessions.size()));
157
158    AVSessionDescriptor descriptor;
159    for (const auto& session : sessions) {
160        descriptor = session->GetDescriptor();
161        std::string isActive = descriptor.isActive_ ? "true" : "false";
162        std::string isTopSession = descriptor.isTopSession_ ? "true" : "false";
163        result.append("\n\ncurrent session id           : " + descriptor.sessionId_ + "\n")
164            .append("State:\n")
165            .append("is active                    : " + isActive + "\n")
166            .append("is the topsession            : " + isTopSession)
167            .append("\n\nConfiguration:\n")
168            .append("pid                          : " + std::to_string(session->GetPid()) + "\n")
169            .append("uid                          : " + std::to_string(session->GetUid()) + "\n");
170        if (descriptor.sessionType_ == AVSession::SESSION_TYPE_AUDIO) {
171            result.append("session type                 : audio\n");
172        } else if (descriptor.sessionType_ == AVSession::SESSION_TYPE_VIDEO) {
173            result.append("session type                 : video\n");
174        } else if (descriptor.sessionType_ == AVSession::SESSION_TYPE_VOICE_CALL) {
175            result.append("session type                 : voice_call\n");
176        } else if (descriptor.sessionType_ == AVSession::SESSION_TYPE_VIDEO_CALL) {
177            result.append("session type                 : video_call\n");
178        } else {
179            result.append("session type is invalid.\n");
180        }
181
182        result.append("session tag                  : " + descriptor.sessionTag_ + "\n")
183            .append("bundle name                  : " + descriptor.elementName_.GetBundleName() + "\n")
184            .append("ability name                 : " + descriptor.elementName_.GetAbilityName() + "\n");
185
186        result.append("outputdevice\n")
187            .append("        the count of devices         : " +
188            std::to_string(descriptor.outputDeviceInfo_.deviceInfos_.size()) +
189            "\n        device id                    : ");
190        for (const auto& deviceInfo : descriptor.outputDeviceInfo_.deviceInfos_) {
191            result.append(deviceInfo.deviceId_ + "  ");
192        }
193        result.append("\n        device name                  : ");
194        for (const auto& deviceInfo : descriptor.outputDeviceInfo_.deviceInfos_) {
195            result.append(deviceInfo.deviceName_ + "  ");
196        }
197        result.append("\n\nRelated Controllers:\n")
198            .append("the count of controllers     : " + std::to_string(session->controllers_.size()) + "\n")
199            .append("pid of controllers           : ");
200        for (const auto& it : session->controllers_) {
201            result.append(std::to_string(it.first) + "  ");
202        }
203    }
204}
205
206void AVSessionDumper::ShowControllerInfo(std::string& result, const AVSessionService& sessionService)
207{
208    AVPlaybackState playbackState;
209    std::string temp;
210    int32_t controllerCount = 0;
211    for (const auto& it : sessionService.controllers_) {
212        for (const auto& controller : it.second) {
213            controllerCount++;
214            controller->GetAVPlaybackState(playbackState);
215
216            int32_t state = playbackState.GetState();
217            double speed = playbackState.GetSpeed();
218            AVPlaybackState::Position position = playbackState.GetPosition();
219            int64_t bufferedTime = playbackState.GetBufferedTime();
220            int32_t loopMode = playbackState.GetLoopMode();
221            std::string isFavorite = playbackState.GetFavorite() ? "true" : "false";
222
223            temp.append("\n\ncurretn controller pid       : " + std::to_string(controller->GetPid()) + "\n")
224                .append("State:\n")
225                .append("state                        : " + playBackStates_.find(state)->second + "\n")
226                .append("speed                        : " + std::to_string(speed) + "\n")
227                .append("position\n")
228                .append("        elapsed time                 : " + std::to_string(position.elapsedTime_) + "\n")
229                .append("        update time                  : " + std::to_string(position.updateTime_) + "\n")
230                .append("buffered time                : " + std::to_string(bufferedTime) + "\n")
231                .append("loopmode                     : " + loopMode_.find(loopMode)->second + "\n")
232                .append("is favorite                  : " + isFavorite + "\n")
233                .append("\nRelated Sessionid            : " + controller->GetSessionId());
234        }
235    }
236    result.append("Controller Information:\n\n")
237        .append("Count                        : " + std::to_string(controllerCount))
238        .append(temp);
239}
240
241void AVSessionDumper::SetErrorInfo(const std::string& inErrMsg)
242{
243    time_t now = time(nullptr);
244    if (now == -1) {
245        SLOGE("get time failed");
246        return;
247    }
248    struct tm *locTime = localtime(&now);
249    if (locTime == nullptr) {
250        SLOGE("get localtime failed");
251        return;
252    }
253    char tempTime [TIME_MAX];
254    auto ret = strftime(tempTime, sizeof(tempTime), "%Y-%m-%d %H:%M:%S", locTime);
255    if (ret == 0) {
256        SLOGE("strftime failed");
257        return;
258    }
259    auto time  = tempTime;
260    std::string msgInfo;
261    msgInfo.append(time + inErrMsg);
262    errMessage_.push_back(msgInfo);
263}
264
265void AVSessionDumper::ShowErrorInfo(std::string& result, const AVSessionService& sessionService)
266{
267    if (errMessage_.empty()) {
268        result.append("No Error Information!\n");
269        return;
270    }
271
272    int32_t errMsgCount = 0;
273    result.append("Error Information:\n\n");
274    for (auto iter = errMessage_.begin(); iter != errMessage_.end(); iter++) {
275        result.append(errMessage_.at(errMsgCount++) + "\n");
276    }
277}
278
279void AVSessionDumper::ProcessParameter(const std::string& arg, std::string& result,
280                                       const AVSessionService& sessionService) const
281{
282    if (arg == ARGS_HELP) {
283        ShowHelp(result);
284    } else {
285        auto it = funcMap_.find(arg);
286        if (it != funcMap_.end()) {
287            it->second(result, sessionService);
288        } else {
289            ShowIllegalInfo(result);
290        }
291    }
292}
293
294void AVSessionDumper::ShowIllegalInfo(std::string& result) const
295{
296    result.append(ILLEGAL_INFORMATION);
297}
298
299void AVSessionDumper::Dump(const std::vector<std::string>& args, std::string& result,
300    const AVSessionService& sessionService) const
301{
302    result.clear();
303    auto argsSize = args.size();
304    if (argsSize == 1) {
305        ProcessParameter(args[0], result, sessionService);
306    } else {
307        ShowIllegalInfo(result);
308    }
309}
310} // namespace OHOS::AVSession