Line data Source code
1 : /*
2 : * If not stated otherwise in this file or this component's LICENSE file the
3 : * following copyright and licenses apply:
4 : *
5 : * Copyright 2023 Sky UK
6 : *
7 : * Licensed under the Apache License, Version 2.0 (the "License");
8 : * you may not use this file except in compliance with the License.
9 : * You may obtain a copy of the License at
10 : *
11 : * http://www.apache.org/licenses/LICENSE-2.0
12 : *
13 : * Unless required by applicable law or agreed to in writing, software
14 : * distributed under the License is distributed on an "AS IS" BASIS,
15 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 : * See the License for the specific language governing permissions and
17 : * limitations under the License.
18 : */
19 :
20 : #include "CdmBackend.h"
21 :
22 85 : CdmBackend::CdmBackend(const std::string &keySystem,
23 : const std::shared_ptr<firebolt::rialto::IMediaKeysClient> &mediaKeysClient,
24 85 : const std::shared_ptr<firebolt::rialto::IMediaKeysFactory> &mediaKeysFactory)
25 170 : : m_log{"CdmBackend"}, m_appState{firebolt::rialto::ApplicationState::UNKNOWN}, m_keySystem{keySystem},
26 255 : m_mediaKeysClient{mediaKeysClient}, m_mediaKeysFactory{mediaKeysFactory}
27 : {
28 85 : }
29 :
30 46 : void CdmBackend::notifyApplicationState(firebolt::rialto::ApplicationState state)
31 : {
32 46 : std::unique_lock<std::mutex> lock{m_mutex};
33 46 : if (state == m_appState)
34 : {
35 1 : return;
36 : }
37 45 : if (firebolt::rialto::ApplicationState::RUNNING == state)
38 : {
39 42 : m_log << info << "Rialto state changed to: RUNNING";
40 42 : if (createMediaKeys())
41 : {
42 42 : m_appState = state;
43 42 : m_cv.notify_one();
44 : }
45 : }
46 : else
47 : {
48 3 : m_log << info << "Rialto state changed to: INACTIVE";
49 3 : m_mediaKeys.reset();
50 3 : m_appState = state;
51 : }
52 46 : }
53 :
54 23 : bool CdmBackend::initialize(const firebolt::rialto::ApplicationState &initialState)
55 : {
56 23 : std::unique_lock<std::mutex> lock{m_mutex};
57 23 : if (firebolt::rialto::ApplicationState::UNKNOWN != m_appState)
58 : {
59 : // CdmBackend initialized by Rialto Client thread in notifyApplicationState()
60 1 : return true;
61 : }
62 22 : if (firebolt::rialto::ApplicationState::RUNNING == initialState)
63 : {
64 20 : if (!createMediaKeys())
65 : {
66 2 : return false;
67 : }
68 : }
69 20 : m_log << info << "CdmBackend initialized in "
70 20 : << (firebolt::rialto::ApplicationState::RUNNING == initialState ? "RUNNING" : "INACTIVE") << " state";
71 20 : m_appState = initialState;
72 20 : return true;
73 23 : }
74 :
75 3 : bool CdmBackend::selectKeyId(int32_t keySessionId, const std::vector<uint8_t> &keyId)
76 : {
77 3 : std::unique_lock<std::mutex> lock{m_mutex};
78 3 : if (!m_mediaKeys)
79 : {
80 1 : return false;
81 : }
82 2 : return firebolt::rialto::MediaKeyErrorStatus::OK == m_mediaKeys->selectKeyId(keySessionId, keyId);
83 3 : }
84 :
85 3 : bool CdmBackend::containsKey(int32_t keySessionId, const std::vector<uint8_t> &keyId)
86 : {
87 3 : std::unique_lock<std::mutex> lock{m_mutex};
88 3 : if (!m_mediaKeys)
89 : {
90 1 : return false;
91 : }
92 2 : return m_mediaKeys->containsKey(keySessionId, keyId);
93 3 : }
94 :
95 3 : bool CdmBackend::createKeySession(firebolt::rialto::KeySessionType sessionType, int32_t &keySessionId)
96 : {
97 3 : std::unique_lock<std::mutex> lock{m_mutex};
98 : // Sometimes app tries to create session before reaching RUNNING state. We have to wait for it.
99 3 : m_cv.wait_for(lock, std::chrono::seconds(1),
100 4 : [this]() { return firebolt::rialto::ApplicationState::RUNNING == m_appState; });
101 3 : if (!m_mediaKeys)
102 : {
103 1 : return false;
104 : }
105 : return firebolt::rialto::MediaKeyErrorStatus::OK ==
106 2 : m_mediaKeys->createKeySession(sessionType, m_mediaKeysClient, keySessionId);
107 3 : }
108 :
109 3 : bool CdmBackend::generateRequest(int32_t keySessionId, firebolt::rialto::InitDataType initDataType,
110 : const std::vector<uint8_t> &initData,
111 : const firebolt::rialto::LimitedDurationLicense &ldlState)
112 : {
113 3 : std::unique_lock<std::mutex> lock{m_mutex};
114 3 : if (!m_mediaKeys)
115 : {
116 1 : return false;
117 : }
118 : return firebolt::rialto::MediaKeyErrorStatus::OK ==
119 2 : m_mediaKeys->generateRequest(keySessionId, initDataType, initData, ldlState);
120 3 : }
121 :
122 3 : bool CdmBackend::loadSession(int32_t keySessionId)
123 : {
124 3 : std::unique_lock<std::mutex> lock{m_mutex};
125 3 : if (!m_mediaKeys)
126 : {
127 1 : return false;
128 : }
129 2 : return firebolt::rialto::MediaKeyErrorStatus::OK == m_mediaKeys->loadSession(keySessionId);
130 3 : }
131 :
132 3 : bool CdmBackend::updateSession(int32_t keySessionId, const std::vector<uint8_t> &responseData)
133 : {
134 3 : std::unique_lock<std::mutex> lock{m_mutex};
135 3 : if (!m_mediaKeys)
136 : {
137 1 : return false;
138 : }
139 2 : return firebolt::rialto::MediaKeyErrorStatus::OK == m_mediaKeys->updateSession(keySessionId, responseData);
140 3 : }
141 :
142 3 : bool CdmBackend::setDrmHeader(int32_t keySessionId, const std::vector<uint8_t> &requestData)
143 : {
144 3 : std::unique_lock<std::mutex> lock{m_mutex};
145 3 : if (!m_mediaKeys)
146 : {
147 1 : return false;
148 : }
149 2 : return firebolt::rialto::MediaKeyErrorStatus::OK == m_mediaKeys->setDrmHeader(keySessionId, requestData);
150 3 : }
151 :
152 3 : bool CdmBackend::closeKeySession(int32_t keySessionId)
153 : {
154 3 : std::unique_lock<std::mutex> lock{m_mutex};
155 3 : if (!m_mediaKeys)
156 : {
157 1 : return false;
158 : }
159 2 : return firebolt::rialto::MediaKeyErrorStatus::OK == m_mediaKeys->closeKeySession(keySessionId);
160 3 : }
161 :
162 3 : bool CdmBackend::removeKeySession(int32_t keySessionId)
163 : {
164 3 : std::unique_lock<std::mutex> lock{m_mutex};
165 3 : if (!m_mediaKeys)
166 : {
167 1 : return false;
168 : }
169 2 : return firebolt::rialto::MediaKeyErrorStatus::OK == m_mediaKeys->removeKeySession(keySessionId);
170 3 : }
171 :
172 5 : bool CdmBackend::deleteDrmStore()
173 : {
174 5 : std::unique_lock<std::mutex> lock{m_mutex};
175 5 : if (!m_mediaKeys)
176 : {
177 1 : return false;
178 : }
179 4 : return firebolt::rialto::MediaKeyErrorStatus::OK == m_mediaKeys->deleteDrmStore();
180 5 : }
181 :
182 5 : bool CdmBackend::deleteKeyStore()
183 : {
184 5 : std::unique_lock<std::mutex> lock{m_mutex};
185 5 : if (!m_mediaKeys)
186 : {
187 1 : return false;
188 : }
189 4 : return firebolt::rialto::MediaKeyErrorStatus::OK == m_mediaKeys->deleteKeyStore();
190 5 : }
191 :
192 5 : bool CdmBackend::getDrmStoreHash(std::vector<unsigned char> &drmStoreHash)
193 : {
194 5 : std::unique_lock<std::mutex> lock{m_mutex};
195 5 : if (!m_mediaKeys)
196 : {
197 1 : return false;
198 : }
199 4 : return firebolt::rialto::MediaKeyErrorStatus::OK == m_mediaKeys->getDrmStoreHash(drmStoreHash);
200 5 : }
201 :
202 5 : bool CdmBackend::getKeyStoreHash(std::vector<unsigned char> &keyStoreHash)
203 : {
204 5 : std::unique_lock<std::mutex> lock{m_mutex};
205 5 : if (!m_mediaKeys)
206 : {
207 1 : return false;
208 : }
209 4 : return firebolt::rialto::MediaKeyErrorStatus::OK == m_mediaKeys->getKeyStoreHash(keyStoreHash);
210 5 : }
211 :
212 5 : bool CdmBackend::getLdlSessionsLimit(uint32_t &ldlLimit)
213 : {
214 5 : std::unique_lock<std::mutex> lock{m_mutex};
215 5 : if (!m_mediaKeys)
216 : {
217 1 : return false;
218 : }
219 4 : return firebolt::rialto::MediaKeyErrorStatus::OK == m_mediaKeys->getLdlSessionsLimit(ldlLimit);
220 5 : }
221 :
222 3 : bool CdmBackend::getLastDrmError(int32_t keySessionId, uint32_t &errorCode)
223 : {
224 3 : std::unique_lock<std::mutex> lock{m_mutex};
225 3 : if (!m_mediaKeys)
226 : {
227 1 : return false;
228 : }
229 2 : return firebolt::rialto::MediaKeyErrorStatus::OK == m_mediaKeys->getLastDrmError(keySessionId, errorCode);
230 3 : }
231 :
232 5 : bool CdmBackend::getDrmTime(uint64_t &drmTime)
233 : {
234 5 : std::unique_lock<std::mutex> lock{m_mutex};
235 5 : if (!m_mediaKeys)
236 : {
237 1 : return false;
238 : }
239 4 : return firebolt::rialto::MediaKeyErrorStatus::OK == m_mediaKeys->getDrmTime(drmTime);
240 5 : }
241 :
242 3 : bool CdmBackend::getCdmKeySessionId(int32_t keySessionId, std::string &cdmKeySessionId)
243 : {
244 3 : std::unique_lock<std::mutex> lock{m_mutex};
245 3 : if (!m_mediaKeys)
246 : {
247 1 : return false;
248 : }
249 2 : return firebolt::rialto::MediaKeyErrorStatus::OK == m_mediaKeys->getCdmKeySessionId(keySessionId, cdmKeySessionId);
250 3 : }
251 :
252 3 : bool CdmBackend::releaseKeySession(int32_t keySessionId)
253 : {
254 3 : std::unique_lock<std::mutex> lock{m_mutex};
255 3 : if (!m_mediaKeys)
256 : {
257 1 : return false;
258 : }
259 2 : return firebolt::rialto::MediaKeyErrorStatus::OK == m_mediaKeys->releaseKeySession(keySessionId);
260 3 : }
261 :
262 62 : bool CdmBackend::createMediaKeys()
263 : {
264 62 : if (!m_mediaKeysFactory)
265 : {
266 1 : m_log << error << "Failed to initialize media keys - not possible to create factory";
267 1 : return false;
268 : }
269 :
270 61 : m_mediaKeys = m_mediaKeysFactory->createMediaKeys(m_keySystem);
271 61 : if (!m_mediaKeys)
272 : {
273 1 : m_log << error << "Failed to initialize media keys - not possible to create media keys";
274 1 : return false;
275 : }
276 60 : return true;
277 : }
278 :
279 5 : bool CdmBackend::getMetricSystemData(std::vector<uint8_t> &buffer)
280 : {
281 5 : std::unique_lock<std::mutex> lock{m_mutex};
282 5 : if (!m_mediaKeys)
283 : {
284 1 : return false;
285 : }
286 4 : return firebolt::rialto::MediaKeyErrorStatus::OK == m_mediaKeys->getMetricSystemData(buffer);
287 5 : }
|