1 /*
2 * Copyright 2022 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 //#define LOG_NDEBUG 0
18 #define LOG_TAG "CryptoAsync"
19
20 #include <log/log.h>
21
22 #include "hidl/HidlSupport.h"
23 #include <media/stagefright/foundation/AMessage.h>
24 #include <media/stagefright/foundation/ABuffer.h>
25 #include <media/stagefright/foundation/ADebug.h>
26
27 #include <media/MediaCodecBuffer.h>
28 #include <media/stagefright/MediaCodec.h>
29 #include <media/stagefright/CryptoAsync.h>
30
31 namespace android {
32
CryptoAsyncInfo(const std::unique_ptr<CodecCryptoInfo> & info)33 CryptoAsync::CryptoAsyncInfo::CryptoAsyncInfo(const std::unique_ptr<CodecCryptoInfo> &info) {
34 if (info == nullptr) {
35 return;
36 }
37 size_t key_len = (info->mKey != nullptr)? 16 : 0;
38 size_t iv_len = (info->mIv != nullptr)? 16 : 0;
39 mNumSubSamples = info->mNumSubSamples;
40 mMode = info->mMode;
41 mPattern = info->mPattern;
42 if (key_len > 0) {
43 mKeyBuffer = ABuffer::CreateAsCopy((void*)info->mKey, key_len);
44 mKey = (uint8_t*)(mKeyBuffer.get() != nullptr ? mKeyBuffer.get()->data() : nullptr);
45 }
46 if (iv_len > 0) {
47 mIvBuffer = ABuffer::CreateAsCopy((void*)info->mIv, iv_len);
48 mIv = (uint8_t*)(mIvBuffer.get() != nullptr ? mIvBuffer.get()->data() : nullptr);
49 }
50 mSubSamplesBuffer =
51 new ABuffer(sizeof(CryptoPlugin::SubSample) * mNumSubSamples);
52 if (mSubSamplesBuffer.get()) {
53 CryptoPlugin::SubSample * samples =
54 (CryptoPlugin::SubSample *)(mSubSamplesBuffer.get()->data());
55 for (int s = 0 ; s < mNumSubSamples ; s++) {
56 samples[s].mNumBytesOfClearData = info->mSubSamples[s].mNumBytesOfClearData;
57 samples[s].mNumBytesOfEncryptedData = info->mSubSamples[s].mNumBytesOfEncryptedData;
58 }
59 mSubSamples = (CryptoPlugin::SubSample *)mSubSamplesBuffer.get()->data();
60 }
61 }
62
~CryptoAsync()63 CryptoAsync::~CryptoAsync() {
64 }
65
decrypt(sp<AMessage> & msg)66 status_t CryptoAsync::decrypt(sp<AMessage> &msg) {
67 int32_t decryptAction;
68 CHECK(msg->findInt32("action", &decryptAction));
69 if (mCallback == nullptr) {
70 ALOGE("Crypto callback channel is not set");
71 return -ENOSYS;
72 }
73 bool shouldPost = false;
74 msg->setWhat(kWhatDecrypt);
75 Mutexed<std::list<sp<AMessage>>>::Locked pendingBuffers(mPendingBuffers);
76 if (mState != kCryptoAsyncActive) {
77 ALOGE("Cannot decrypt in errored state");
78 return -ENOSYS;
79 }
80 shouldPost = pendingBuffers->size() == 0 ? true : false;
81 pendingBuffers->push_back(std::move(msg));
82 if (shouldPost) {
83 sp<AMessage> decryptMsg = new AMessage(kWhatDecrypt, this);
84 decryptMsg->post();
85 }
86 return OK;
87 }
88
stop(std::list<sp<AMessage>> * const buffers)89 void CryptoAsync::stop(std::list<sp<AMessage>> * const buffers) {
90 sp<AMessage> stopMsg = new AMessage(kWhatStop, this);
91 stopMsg->setPointer("remaining", static_cast<void*>(buffers));
92 sp<AMessage> response;
93 status_t err = stopMsg->postAndAwaitResponse(&response);
94 if (err == OK && response != NULL) {
95 CHECK(response->findInt32("err", &err));
96 } else {
97 ALOGE("Error handling stop in CryptoAsync");
98 //TODO: handle the error here.
99 }
100 }
101
decryptAndQueue(sp<AMessage> & msg)102 status_t CryptoAsync::decryptAndQueue(sp<AMessage> & msg) {
103 std::shared_ptr<BufferChannelBase> channel = mBufferChannel.lock();
104 status_t err = OK;
105 sp<RefBase> obj;
106 size_t numSubSamples = 0;
107 int32_t secure = 0;
108 CryptoPlugin::Mode mode;
109 CryptoPlugin::Pattern pattern;
110 sp<ABuffer> keyBuffer;
111 sp<ABuffer> ivBuffer;
112 sp<ABuffer> subSamplesBuffer;
113 AString errorDetailMsg;
114 msg->findObject("buffer", &obj);
115 msg->findInt32("secure", &secure);
116 sp<MediaCodecBuffer> buffer = static_cast<MediaCodecBuffer *>(obj.get());
117 if (buffer->meta()->findObject("cryptoInfos", &obj)) {
118 err = channel->queueSecureInputBuffers(buffer, secure, &errorDetailMsg);
119 } else {
120 msg->findInt32("encryptBlocks", (int32_t*)&pattern.mEncryptBlocks);
121 msg->findInt32("skipBlocks", (int32_t*)&pattern.mSkipBlocks);
122 msg->findBuffer("key", &keyBuffer);
123 msg->findBuffer("iv", &ivBuffer);
124 msg->findBuffer("subSamples", &subSamplesBuffer);
125 msg->findSize("numSubSamples", &numSubSamples);
126 msg->findInt32("mode", (int32_t*)&mode);
127 const uint8_t * key = keyBuffer.get() != nullptr ? keyBuffer.get()->data() : nullptr;
128 const uint8_t * iv = ivBuffer.get() != nullptr ? ivBuffer.get()->data() : nullptr;
129 const CryptoPlugin::SubSample * subSamples =
130 (CryptoPlugin::SubSample *)(subSamplesBuffer.get()->data());
131 err = channel->queueSecureInputBuffer(buffer, secure, key, iv, mode,
132 pattern, subSamples, numSubSamples, &errorDetailMsg);
133 }
134 if (err != OK) {
135 std::list<sp<AMessage>> errorList;
136 if (buffer->meta()->findObject("cryptoInfos", &obj)) {
137 msg->setObject("cryptoInfos", obj);
138 }
139 msg->removeEntryByName("buffer");
140 msg->setInt32("err", err);
141 msg->setInt32("actionCode", ACTION_CODE_FATAL);
142 msg->setString("errorDetail", errorDetailMsg);
143 errorList.push_back(std::move(msg));
144 mCallback->onDecryptError(errorList);
145 }
146 return err;
147 }
148
attachEncryptedBufferAndQueue(sp<AMessage> & msg)149 status_t CryptoAsync::attachEncryptedBufferAndQueue(sp<AMessage> & msg) {
150 std::shared_ptr<BufferChannelBase> channel = mBufferChannel.lock();
151 status_t err = OK;
152 sp<RefBase> obj;
153 sp<RefBase> mem_obj;
154 sp<hardware::HidlMemory> memory;
155 size_t numSubSamples = 0;
156 int32_t secure = 0;
157 size_t offset;
158 size_t size;
159 CryptoPlugin::Mode mode;
160 CryptoPlugin::Pattern pattern;
161 sp<ABuffer> keyBuffer;
162 sp<ABuffer> ivBuffer;
163 sp<ABuffer> subSamplesBuffer;
164 msg->findInt32("encryptBlocks", (int32_t*)&pattern.mEncryptBlocks);
165 msg->findInt32("skipBlocks", (int32_t*)&pattern.mSkipBlocks);
166 msg->findBuffer("key", &keyBuffer);
167 msg->findBuffer("iv", &ivBuffer);
168 msg->findBuffer("subSamples", &subSamplesBuffer);
169 msg->findInt32("secure", &secure);
170 msg->findSize("numSubSamples", &numSubSamples);
171 msg->findObject("buffer", &obj);
172 msg->findInt32("mode", (int32_t*)&mode);
173 CHECK(msg->findObject("memory", &mem_obj));
174 CHECK(msg->findSize("offset", (size_t*)&offset));
175 AString errorDetailMsg;
176 // get key info
177 const uint8_t * key = keyBuffer.get() != nullptr ? keyBuffer.get()->data() : nullptr;
178 // get iv info
179 const uint8_t * iv = ivBuffer.get() != nullptr ? ivBuffer.get()->data() : nullptr;
180
181 const CryptoPlugin::SubSample * subSamples =
182 (CryptoPlugin::SubSample *)(subSamplesBuffer.get()->data());
183
184 // get MediaCodecBuffer
185 sp<MediaCodecBuffer> buffer = static_cast<MediaCodecBuffer *>(obj.get());
186
187 // get HidlMemory
188 memory = static_cast<MediaCodec::WrapperObject<sp<hardware::HidlMemory>> *>
189 (mem_obj.get())->value;
190
191 // attach buffer
192 err = channel->attachEncryptedBuffer(
193 memory, secure, key, iv, mode, pattern,
194 offset, subSamples, numSubSamples, buffer, &errorDetailMsg);
195
196 // a generic error
197 auto handleError = [this, &err, &msg]() {
198 std::list<sp<AMessage>> errorList;
199 msg->removeEntryByName("buffer");
200 msg->setInt32("err", err);
201 msg->setInt32("actionCode", ACTION_CODE_FATAL);
202 errorList.push_back(std::move(msg));
203 mCallback->onDecryptError(errorList);
204 };
205 if (err != OK) {
206 handleError();
207 return err;
208 }
209 offset = buffer->offset();
210 size = buffer->size();
211
212 if (offset + size > buffer->capacity()) {
213 err = -ENOSYS;
214 handleError();
215 return err;
216 }
217 buffer->setRange(offset, size);
218 err = channel->queueInputBuffer(buffer);
219 if (err != OK) {
220 handleError();
221 return err;
222 }
223 return err;
224 }
225
onMessageReceived(const sp<AMessage> & msg)226 void CryptoAsync::onMessageReceived(const sp<AMessage> & msg) {
227 status_t err = OK;
228 auto getCurrentAndNextTask =
229 [this](sp<AMessage> * const current, uint32_t & nextTask) -> status_t {
230 sp<AMessage> obj;
231 Mutexed<std::list<sp<AMessage>>>::Locked pendingBuffers(mPendingBuffers);
232 if ((pendingBuffers->size() == 0) || (mState != kCryptoAsyncActive)) {
233 return -ENOMSG;
234 }
235 *current = std::move(*(pendingBuffers->begin()));
236 pendingBuffers->pop_front();
237 //Try to see if we will be able to process next buffer
238 while((nextTask == kWhatDoNothing) && pendingBuffers->size() > 0)
239 {
240 sp<AMessage> & nextBuffer = pendingBuffers->front();
241 if (nextBuffer == nullptr) {
242 pendingBuffers->pop_front();
243 continue;
244 }
245 nextTask = nextBuffer->what();
246 }
247 return OK;
248 };
249 sp<AMessage> thisMsg;
250 uint32_t nextTask = kWhatDoNothing;
251 getCurrentAndNextTask(&thisMsg, nextTask);
252 switch(msg->what()) {
253 case kWhatDecrypt:
254 {
255 if (thisMsg != nullptr) {
256 int32_t action;
257 err = OK;
258 CHECK(thisMsg->findInt32("action", &action));
259 switch(action) {
260 case kActionDecrypt:
261 {
262 err = decryptAndQueue(thisMsg);
263 break;
264 }
265
266 case kActionAttachEncryptedBuffer:
267 {
268 err = attachEncryptedBufferAndQueue(thisMsg);
269 break;
270 }
271
272 default:
273 {
274 ALOGE("Unrecognized action in decrypt");
275 }
276 }
277 if (err != OK) {
278 Mutexed<std::list<sp<AMessage>>>::Locked pendingBuffers(mPendingBuffers);
279 mState = kCryptoAsyncError;
280 }
281 }
282 break;
283 }
284
285 case kWhatStop:
286 {
287 typedef std::list<sp<AMessage>> ReturnListType;
288 ReturnListType * returnList = nullptr;
289 sp<AReplyToken> replyID;
290 CHECK(msg->senderAwaitsResponse(&replyID));
291 sp<AMessage> response = new AMessage;
292 msg->findPointer("remaining", (void**)(&returnList));
293 Mutexed<std::list<sp<AMessage>>>::Locked pendingBuffers(mPendingBuffers);
294 if (returnList) {
295 returnList->clear();
296 returnList->splice(returnList->end(), std::move(*pendingBuffers));
297 }
298 pendingBuffers->clear();
299 // stop() is a blocking call.
300 // this is needed as the queue is cleared now and there should
301 // not be any next task. The next buffer when queued will kick off this loop
302 nextTask = kWhatDoNothing;
303 mState = kCryptoAsyncActive;
304 response->setInt32("err", OK);
305 response->postReply(replyID);
306 break;
307 }
308
309 default:
310 {
311 status_t err = OK;
312 //TODO: do something with error here.
313 (void)err;
314 break;
315 }
316 }
317 // we won't take next buffers if buffer caused
318 // an error. We want the caller to deal with the error first
319 // Expected behahiour is that the caller acknowledge the error
320 // with a call to stop() which clear the queues.
321 // Then move forward with processing of next set of buffers.
322 if (mState == kCryptoAsyncActive && nextTask != kWhatDoNothing) {
323 sp<AMessage> nextMsg = new AMessage(nextTask,this);
324 nextMsg->post();
325 }
326 }
327
328 } // namespace android
329