• 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 
~CryptoAsync()33 CryptoAsync::~CryptoAsync() {
34 }
35 
decrypt(sp<AMessage> & msg)36 status_t CryptoAsync::decrypt(sp<AMessage> &msg) {
37     int32_t decryptAction;
38     CHECK(msg->findInt32("action", &decryptAction));
39     if (mCallback == nullptr) {
40        ALOGE("Crypto callback channel is not set");
41        return -ENOSYS;
42     }
43     bool shouldPost = false;
44     Mutexed<std::list<sp<AMessage>>>::Locked pendingBuffers(mPendingBuffers);
45     if (mState != kCryptoAsyncActive) {
46        ALOGE("Cannot decrypt in errored state");
47        return -ENOSYS;
48     }
49     shouldPost = pendingBuffers->size() == 0 ? true : false;
50     pendingBuffers->push_back(std::move(msg));
51     if (shouldPost) {
52        sp<AMessage> decryptMsg = new AMessage(kWhatDecrypt, this);
53        decryptMsg->post();
54     }
55     return OK;
56 }
57 
stop(std::list<sp<AMessage>> * const buffers)58 void CryptoAsync::stop(std::list<sp<AMessage>> * const buffers) {
59     sp<AMessage>  stopMsg = new AMessage(kWhatStop, this);
60     stopMsg->setPointer("remaining", static_cast<void*>(buffers));
61     sp<AMessage> response;
62     status_t err = stopMsg->postAndAwaitResponse(&response);
63     if (err == OK && response != NULL) {
64         CHECK(response->findInt32("err", &err));
65     } else {
66         ALOGE("Error handling stop in CryptoAsync");
67         //TODO: handle the error here.
68     }
69 }
70 
decryptAndQueue(sp<AMessage> & msg)71 status_t CryptoAsync::decryptAndQueue(sp<AMessage> & msg) {
72     std::shared_ptr<BufferChannelBase> channel = mBufferChannel.lock();
73     status_t err = OK;
74     sp<RefBase> obj;
75     size_t numSubSamples = 0;
76     int32_t secure = 0;
77     CryptoPlugin::Mode mode;
78     CryptoPlugin::Pattern pattern;
79     sp<ABuffer> keyBuffer;
80     sp<ABuffer> ivBuffer;
81     sp<ABuffer> subSamplesBuffer;
82     msg->findInt32("encryptBlocks", (int32_t*)&pattern.mEncryptBlocks);
83     msg->findInt32("skipBlocks", (int32_t*)&pattern.mSkipBlocks);
84     msg->findBuffer("key", &keyBuffer);
85     msg->findBuffer("iv", &ivBuffer);
86     msg->findBuffer("subSamples", &subSamplesBuffer);
87     msg->findInt32("secure", &secure);
88     msg->findSize("numSubSamples", &numSubSamples);
89     msg->findObject("buffer", &obj);
90     msg->findInt32("mode", (int32_t*)&mode);
91     AString errorDetailMsg;
92     const uint8_t * key = keyBuffer.get() != nullptr ? keyBuffer.get()->data() : nullptr;
93     const uint8_t * iv = ivBuffer.get() != nullptr ? ivBuffer.get()->data() : nullptr;
94     const CryptoPlugin::SubSample * subSamples =
95        (CryptoPlugin::SubSample *)(subSamplesBuffer.get()->data());
96     sp<MediaCodecBuffer> buffer = static_cast<MediaCodecBuffer *>(obj.get());
97     err = channel->queueSecureInputBuffer(buffer, secure, key, iv, mode,
98         pattern, subSamples, numSubSamples, &errorDetailMsg);
99     if (err != OK) {
100         std::list<sp<AMessage>> errorList;
101         msg->removeEntryByName("buffer");
102         msg->setInt32("err", err);
103         msg->setInt32("actionCode", ACTION_CODE_FATAL);
104         msg->setString("errorDetail", errorDetailMsg);
105         errorList.push_back(std::move(msg));
106         mCallback->onDecryptError(errorList);
107    }
108    return err;
109 }
110 
attachEncryptedBufferAndQueue(sp<AMessage> & msg)111 status_t CryptoAsync::attachEncryptedBufferAndQueue(sp<AMessage> & msg) {
112     std::shared_ptr<BufferChannelBase> channel = mBufferChannel.lock();
113     status_t err = OK;
114     sp<RefBase> obj;
115     sp<RefBase> mem_obj;
116     sp<hardware::HidlMemory> memory;
117     size_t numSubSamples = 0;
118     int32_t secure = 0;
119     size_t offset;
120     size_t size;
121     CryptoPlugin::Mode mode;
122     CryptoPlugin::Pattern pattern;
123     sp<ABuffer> keyBuffer;
124     sp<ABuffer> ivBuffer;
125     sp<ABuffer> subSamplesBuffer;
126     msg->findInt32("encryptBlocks", (int32_t*)&pattern.mEncryptBlocks);
127     msg->findInt32("skipBlocks", (int32_t*)&pattern.mSkipBlocks);
128     msg->findBuffer("key", &keyBuffer);
129     msg->findBuffer("iv", &ivBuffer);
130     msg->findBuffer("subSamples", &subSamplesBuffer);
131     msg->findInt32("secure", &secure);
132     msg->findSize("numSubSamples", &numSubSamples);
133     msg->findObject("buffer", &obj);
134     msg->findInt32("mode", (int32_t*)&mode);
135     CHECK(msg->findObject("memory", &mem_obj));
136     CHECK(msg->findSize("offset", (size_t*)&offset));
137     AString errorDetailMsg;
138     // get key info
139     const uint8_t * key = keyBuffer.get() != nullptr ? keyBuffer.get()->data() : nullptr;
140     // get iv info
141     const uint8_t * iv = ivBuffer.get() != nullptr ? ivBuffer.get()->data() : nullptr;
142 
143     const CryptoPlugin::SubSample * subSamples =
144      (CryptoPlugin::SubSample *)(subSamplesBuffer.get()->data());
145 
146     // get MediaCodecBuffer
147     sp<MediaCodecBuffer> buffer = static_cast<MediaCodecBuffer *>(obj.get());
148 
149     // get HidlMemory
150     memory = static_cast<MediaCodec::WrapperObject<sp<hardware::HidlMemory>> *>
151         (mem_obj.get())->value;
152 
153     // attach buffer
154     err = channel->attachEncryptedBuffer(
155         memory, secure, key, iv, mode, pattern,
156         offset, subSamples, numSubSamples, buffer, &errorDetailMsg);
157 
158     // a generic error
159     auto handleError = [this, &err, &msg]() {
160         std::list<sp<AMessage>> errorList;
161         msg->removeEntryByName("buffer");
162         msg->setInt32("err", err);
163         msg->setInt32("actionCode", ACTION_CODE_FATAL);
164         errorList.push_back(std::move(msg));
165         mCallback->onDecryptError(errorList);
166     };
167     if (err != OK) {
168         handleError();
169         return err;
170      }
171      offset = buffer->offset();
172      size = buffer->size();
173 
174     if (offset + size > buffer->capacity()) {
175         err = -ENOSYS;
176         handleError();
177         return err;
178     }
179     buffer->setRange(offset, size);
180     err = channel->queueInputBuffer(buffer);
181     if (err != OK) {
182         handleError();
183         return err;
184     }
185    return err;
186 }
187 
onMessageReceived(const sp<AMessage> & msg)188 void CryptoAsync::onMessageReceived(const sp<AMessage> & msg) {
189     status_t err = OK;
190     auto getCurrentAndNextTask =
191         [this](sp<AMessage> * const  current, uint32_t & nextTask) -> status_t {
192         sp<AMessage> obj;
193         Mutexed<std::list<sp<AMessage>>>::Locked pendingBuffers(mPendingBuffers);
194         if ((pendingBuffers->size() == 0) || (mState != kCryptoAsyncActive)) {
195            return -ENOMSG;
196         }
197         *current = std::move(*(pendingBuffers->begin()));
198         pendingBuffers->pop_front();
199         //Try to see if we will be able to process next buffer
200         while((nextTask == kWhatDoNothing) && pendingBuffers->size() > 0)
201         {
202             sp<AMessage> & nextBuffer = pendingBuffers->front();
203             if (nextBuffer == nullptr) {
204                 pendingBuffers->pop_front();
205                 continue;
206             }
207             nextTask = kWhatDecrypt;
208         }
209         return OK;
210     };
211     switch(msg->what()) {
212         case kWhatDecrypt:
213         {
214             sp<AMessage> thisMsg;
215             uint32_t nextTask = kWhatDoNothing;
216             if(OK != getCurrentAndNextTask(&thisMsg, nextTask)) {
217                 return;
218             }
219             if (thisMsg != nullptr) {
220                 int32_t action;
221                 err = OK;
222                 CHECK(thisMsg->findInt32("action", &action));
223                 switch(action) {
224                     case kActionDecrypt:
225                     {
226                         err = decryptAndQueue(thisMsg);
227                         break;
228                     }
229 
230                     case kActionAttachEncryptedBuffer:
231                     {
232                         err = attachEncryptedBufferAndQueue(thisMsg);
233                         break;
234                     }
235 
236                     default:
237                     {
238                         ALOGE("Unrecognized action in decrypt");
239                     }
240                 }
241                 if (err != OK) {
242                     Mutexed<std::list<sp<AMessage>>>::Locked pendingBuffers(mPendingBuffers);
243                     mState = kCryptoAsyncError;
244                 }
245             }
246             // we won't take  next buffers if buffer caused
247             // an error. We want the caller to deal with the error first
248             // Expected behahiour is that the caller acknowledge the error
249             // with a call to stop() which clear the queues.
250             // Then move forward with processing of next set of buffers.
251             if (mState == kCryptoAsyncActive && nextTask != kWhatDoNothing) {
252                 sp<AMessage> nextMsg = new AMessage(nextTask,this);
253                 nextMsg->post();
254             }
255             break;
256         }
257 
258         case kWhatStop:
259         {
260             typedef std::list<sp<AMessage>> ReturnListType;
261             ReturnListType * returnList = nullptr;
262             sp<AReplyToken> replyID;
263             CHECK(msg->senderAwaitsResponse(&replyID));
264             sp<AMessage> response = new AMessage;
265             msg->findPointer("remaining", (void**)(&returnList));
266             Mutexed<std::list<sp<AMessage>>>::Locked pendingBuffers(mPendingBuffers);
267             if (returnList) {
268                 returnList->clear();
269                 returnList->splice(returnList->end(), std::move(*pendingBuffers));
270             }
271             pendingBuffers->clear();
272             mState = kCryptoAsyncActive;
273             response->setInt32("err", OK);
274             response->postReply(replyID);
275 
276             break;
277         }
278 
279         default:
280         {
281             status_t err = OK;
282             //TODO: do something with error here.
283             (void)err;
284             break;
285         }
286     }
287 }
288 
289 }  // namespace android
290