1 /*
2  * Copyright (c) 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 <memory>
17 #include <unistd.h>
18 #include <securec.h>
19 #include <algorithm>
20 #include "ashmem.h"
21 #include "system_ability_definition.h"
22 #include "mem_mgr_client.h"
23 #include "mem_mgr_proxy.h"
24 #include "drm_trace.h"
25 #include "drm_dfx_utils.h"
26 #include "drm_error_code.h"
27 #include "hitrace/tracechain.h"
28 #include "ipc_skeleton.h"
29 #include "media_decrypt_module_service.h"
30 
31 namespace OHOS {
32 namespace DrmStandard {
33 
34 const uint32_t TOP_THREE_SIZE = 3;
35 const uint32_t TOP_ONE = 0;
36 const uint32_t TOP_SEC = 1;
37 const uint32_t TOP_THD = 2;
38 
MediaDecryptModuleService(sptr<OHOS::HDI::Drm::V1_0::IMediaDecryptModule> hdiMediaDecryptModule)39 MediaDecryptModuleService::MediaDecryptModuleService(
40     sptr<OHOS::HDI::Drm::V1_0::IMediaDecryptModule> hdiMediaDecryptModule)
41 {
42     DRM_INFO_LOG("MediaDecryptModuleService 0x%{public}06" PRIXPTR " Instances create.", FAKE_POINTER(this));
43     hdiMediaDecryptModule_ = hdiMediaDecryptModule;
44     instanceId_ = HiTraceChain::GetId().GetChainId();
45 }
46 
MediaDecryptModuleService(sptr<OHOS::HDI::Drm::V1_0::IMediaDecryptModule> hdiMediaDecryptModule,StatisticsInfo statisticsInfo)47 MediaDecryptModuleService::MediaDecryptModuleService(
48     sptr<OHOS::HDI::Drm::V1_0::IMediaDecryptModule> hdiMediaDecryptModule,
49     StatisticsInfo statisticsInfo)
50 {
51     DRM_INFO_LOG("MediaDecryptModuleService 0x%{public}06" PRIXPTR " Instances create.", FAKE_POINTER(this));
52     std::lock_guard<std::recursive_mutex> lock(moduleLock_);
53     hdiMediaDecryptModule_ = hdiMediaDecryptModule;
54     statisticsInfo_ = statisticsInfo;
55     instanceId_ = HiTraceChain::GetId().GetChainId();
56 }
57 
~MediaDecryptModuleService()58 MediaDecryptModuleService::~MediaDecryptModuleService()
59 {
60     DRM_INFO_LOG("~MediaDecryptModuleService 0x%{public}06" PRIXPTR " Instances destroy.", FAKE_POINTER(this));
61     std::lock_guard<std::recursive_mutex> lock(moduleLock_);
62     if (hdiMediaDecryptModule_ != nullptr) {
63         Release();
64     }
65     std::lock_guard<std::recursive_mutex> statisticsLock(statisticsMutex_);
66     ReportDecryptionStatisticsEvent(instanceId_, statisticsInfo_.bundleName, decryptStatistics_);
67 }
68 
Release()69 int32_t MediaDecryptModuleService::Release()
70 {
71     DrmTrace trace("Release");
72     DRM_INFO_LOG("Release enter.");
73     int32_t errCode = DRM_OK;
74     std::lock_guard<std::recursive_mutex> lock(moduleLock_);
75     if (hdiMediaDecryptModule_ != nullptr) {
76         DRM_INFO_LOG("hdiMediaDecryptModule_ call Close");
77         hdiMediaDecryptModule_ = nullptr;
78     }
79     return errCode;
80 }
81 
DecryptMediaData(bool secureDecodrtState,IMediaDecryptModuleService::CryptInfo & cryptInfo,IMediaDecryptModuleService::DrmBuffer & srcBuffer,IMediaDecryptModuleService::DrmBuffer & dstBuffer)82 int32_t MediaDecryptModuleService::DecryptMediaData(bool secureDecodrtState,
83     IMediaDecryptModuleService::CryptInfo &cryptInfo, IMediaDecryptModuleService::DrmBuffer &srcBuffer,
84     IMediaDecryptModuleService::DrmBuffer &dstBuffer)
85 {
86     DrmTrace trace("DecryptMediaData");
87     DRM_DEBUG_LOG("DecryptMediaData enter.");
88     int32_t ret = DRM_OK;
89     uint32_t bufLen = 0;
90     OHOS::HDI::Drm::V1_0::CryptoInfo cryptInfoTmp;
91     SetCryptInfo(cryptInfoTmp, cryptInfo, bufLen);
92     OHOS::HDI::Drm::V1_0::DrmBuffer drmSrcBuffer;
93     OHOS::HDI::Drm::V1_0::DrmBuffer drmDstBuffer;
94     memset_s(&drmSrcBuffer, sizeof(drmSrcBuffer), 0, sizeof(drmSrcBuffer));
95     memset_s(&drmDstBuffer, sizeof(drmDstBuffer), 0, sizeof(drmDstBuffer));
96     SetDrmBufferInfo(&drmSrcBuffer, &drmDstBuffer, srcBuffer, dstBuffer, bufLen);
97     auto timeBefore = std::chrono::system_clock::now();
98     std::lock_guard<std::recursive_mutex> lock(moduleLock_);
99     ret = hdiMediaDecryptModule_->DecryptMediaData(secureDecodrtState, cryptInfoTmp, drmSrcBuffer, drmDstBuffer);
100     uint32_t decryptDuration = CalculateTimeDiff(timeBefore, std::chrono::system_clock::now());
101     UpdateDecryptionStatistics(ret, bufLen, decryptDuration);
102     if (ret != DRM_OK) {
103         DRM_ERR_LOG("DecryptMediaData failed.");
104         ReportDecryptionFaultEvent(ret, "DecryptMediaData failed",
105             std::to_string(static_cast<int32_t>(cryptInfoTmp.type)),
106             CastToHexString(cryptInfoTmp.keyId), CastToHexString(cryptInfoTmp.iv));
107     }
108     (void)::close(srcBuffer.fd);
109     (void)::close(dstBuffer.fd);
110     return ret;
111 }
112 
SetCryptInfo(OHOS::HDI::Drm::V1_0::CryptoInfo & cryptInfoTmp,IMediaDecryptModuleService::CryptInfo & cryptInfo,uint32_t & bufLen)113 void MediaDecryptModuleService::SetCryptInfo(OHOS::HDI::Drm::V1_0::CryptoInfo &cryptInfoTmp,
114     IMediaDecryptModuleService::CryptInfo &cryptInfo, uint32_t &bufLen)
115 {
116     cryptInfoTmp.type = (OHOS::HDI::Drm::V1_0::CryptoAlgorithmType)cryptInfo.type;
117     cryptInfoTmp.keyId.assign(cryptInfo.keyId.begin(), cryptInfo.keyId.end());
118     cryptInfoTmp.iv.assign(cryptInfo.iv.begin(), cryptInfo.iv.end());
119     cryptInfoTmp.pattern.encryptBlocks = cryptInfo.pattern.encryptBlocks;
120     cryptInfoTmp.pattern.skipBlocks = cryptInfo.pattern.skipBlocks;
121     cryptInfoTmp.subSamples.resize(cryptInfo.subSample.size());
122     for (size_t i = 0; i < cryptInfo.subSample.size(); i++) {
123         cryptInfoTmp.subSamples[i].clearHeaderLen = cryptInfo.subSample[i].clearHeaderLen;
124         bufLen += cryptInfoTmp.subSamples[i].clearHeaderLen;
125         cryptInfoTmp.subSamples[i].payLoadLen = cryptInfo.subSample[i].payLoadLen;
126         bufLen += cryptInfoTmp.subSamples[i].payLoadLen;
127     }
128 }
129 
SetDrmBufferInfo(OHOS::HDI::Drm::V1_0::DrmBuffer * drmSrcBuffer,OHOS::HDI::Drm::V1_0::DrmBuffer * drmDstBuffer,IMediaDecryptModuleService::DrmBuffer & srcBuffer,IMediaDecryptModuleService::DrmBuffer & dstBuffer,uint32_t bufLen)130 void MediaDecryptModuleService::SetDrmBufferInfo(OHOS::HDI::Drm::V1_0::DrmBuffer* drmSrcBuffer,
131     OHOS::HDI::Drm::V1_0::DrmBuffer* drmDstBuffer, IMediaDecryptModuleService::DrmBuffer &srcBuffer,
132     IMediaDecryptModuleService::DrmBuffer &dstBuffer, uint32_t bufLen)
133 {
134     DRM_DEBUG_LOG("SetDrmBufferInfo enter");
135     drmSrcBuffer->bufferType = srcBuffer.bufferType;
136     drmSrcBuffer->fd = srcBuffer.fd;
137     drmSrcBuffer->bufferLen = bufLen;
138     drmSrcBuffer->allocLen = srcBuffer.allocLen;
139     drmSrcBuffer->filledLen = srcBuffer.filledLen;
140     drmSrcBuffer->offset = srcBuffer.offset;
141     drmSrcBuffer->fd = srcBuffer.fd;
142 
143     drmDstBuffer->bufferType = dstBuffer.bufferType;
144     drmDstBuffer->fd = dstBuffer.fd;
145     drmDstBuffer->bufferLen = bufLen;
146     drmDstBuffer->allocLen = dstBuffer.allocLen;
147     drmDstBuffer->filledLen = dstBuffer.filledLen;
148     drmDstBuffer->offset = dstBuffer.offset;
149     drmDstBuffer->sharedMemType = dstBuffer.sharedMemType;
150 }
151 
UpdateDecryptionStatistics(int32_t decryptionResult,uint32_t bufLen,uint32_t curDuration)152 void MediaDecryptModuleService::UpdateDecryptionStatistics(int32_t decryptionResult,
153     uint32_t bufLen, uint32_t curDuration)
154 {
155     std::lock_guard<std::recursive_mutex> statisticsLock(statisticsMutex_);
156     decryptStatistics_.topThree.push(curDuration);
157     if (decryptStatistics_.topThree.size() > TOP_THREE_SIZE) {
158         decryptStatistics_.topThree.pop();
159     }
160 
161     decryptStatistics_.decryptMaxSize = std::max(decryptStatistics_.decryptMaxSize, bufLen);
162     decryptStatistics_.decryptMaxDuration = std::max(decryptStatistics_.decryptMaxDuration, curDuration);
163 
164     if (decryptionResult != DRM_OK) {
165         decryptStatistics_.errorDecryptTimes++;
166     }
167     if (decryptStatistics_.decryptTimes == UINT32_MAX) {
168         decryptStatistics_.decryptTimes = 0;
169         decryptStatistics_.decryptSumSize = 0;
170         decryptStatistics_.decryptSumDuration = 0;
171     }
172     decryptStatistics_.decryptTimes++;
173     decryptStatistics_.decryptSumSize += bufLen;
174     decryptStatistics_.decryptSumDuration += curDuration;
175 }
176 
GetTopThreeDecryptionDurations()177 const std::string MediaDecryptModuleService::GetTopThreeDecryptionDurations()
178 {
179     DRM_DEBUG_LOG("GetTopThreeDecryptionDurations");
180     std::vector<uint32_t> topThreeDurations(TOP_THREE_SIZE, 0);
181     std::lock_guard<std::recursive_mutex> statisticsLock(statisticsMutex_);
182     uint32_t currentTopThreeSize = decryptStatistics_.topThree.size();
183     for (uint32_t i = 0; i < currentTopThreeSize; i++) {
184         uint32_t tmp = decryptStatistics_.topThree.top();
185         decryptStatistics_.topThree.pop();
186         topThreeDurations[i] = tmp;
187     }
188     for (uint32_t i = 0; i < currentTopThreeSize; i++) {
189         decryptStatistics_.topThree.push(topThreeDurations[i]);
190     }
191     return std::to_string(topThreeDurations[TOP_ONE]) + " " +
192            std::to_string(topThreeDurations[TOP_SEC]) + " " +
193            std::to_string(topThreeDurations[TOP_THD]) + "\n";
194 }
195 
GetDumpInfo()196 std::string MediaDecryptModuleService::GetDumpInfo()
197 {
198     DRM_DEBUG_LOG("GetDumpInfo");
199     std::lock_guard<std::recursive_mutex> statisticsLock(statisticsMutex_);
200     std::string dumpInfo = "Total Decryption Times: " + std::to_string(decryptStatistics_.decryptTimes) + "\n"
201                            "Error Decryption Times: " + std::to_string(decryptStatistics_.errorDecryptTimes) + "\n"
202                            "Top3 Decryption Duration: " + GetTopThreeDecryptionDurations();
203     return dumpInfo;
204 }
205 
206 } // DrmStandard
207 } // OHOS