• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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