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 #ifndef CRYPTO_ASYNC_H_
18 #define CRYPTO_ASYNC_H_
19 
20 #include <media/stagefright/CodecBase.h>
21 #include <media/stagefright/foundation/Mutexed.h>
22 namespace android {
23 
24 class CryptoAsync: public AHandler {
25 public:
26 
27     class CryptoAsyncCallback {
28     public:
29 
30         virtual ~CryptoAsyncCallback() = default;
31 
32         /*
33          * Callback with result for queuing the decrypted buffer to the
34          * underlying codec. Cannot block this function
35          */
36         virtual void onDecryptComplete(const sp<AMessage>& result) = 0;
37 
38         /*
39          * Callback with error information while decryption. Cannot block
40          * this call. The return should contain the error information
41          * and the buffer the caused the error.
42          */
43         virtual void onDecryptError(const std::list<sp<AMessage>>& errorMsg) = 0;
44     };
45 
46     // Ideally we should be returning the output of the decryption in
47     // onDecryptComple() calback and let the next module take over the
48     // rest of the processing. In the current state, the next step will
49     // be to queue the output the codec which is done using BufferChannel
50 
51     // In order to prevent thread hop to just do that, we have created
52     // a dependency on BufferChannel here to queue the buffer to the codec
53     // immediately after decryption.
CryptoAsync(std::weak_ptr<BufferChannelBase> bufferChannel)54     CryptoAsync(std::weak_ptr<BufferChannelBase> bufferChannel)
55         :mState(kCryptoAsyncActive) {
56         mBufferChannel = std::move(bufferChannel);
57     }
58 
59     // Destructor
60     virtual ~CryptoAsync();
61 
setCallback(std::unique_ptr<CryptoAsyncCallback> && callback)62     inline void setCallback(std::unique_ptr<CryptoAsyncCallback>&& callback) {
63         mCallback = std::move(callback);
64     }
65 
66     // Call this function to decrypt the buffer in the message.
67     status_t decrypt(sp<AMessage>& msg);
68 
69     // This function stops further processing in the thread and returns
70     // with any unprocessed buffers from the queue.
71     // We can use this method in case of flush or clearing the queue
72     // upon error. When the processing hits an error, the self processing
73     // in this looper stops and in-fact., there is a need to clear (call stop())
74     // for the queue to become operational again. Also acts like a rest.
75     void stop(std::list<sp<AMessage>> * const buffers = nullptr);
76 
77     // Describes two actions for decrypt();
78     // kActionDecrypt - decrypts the buffer and queues to codec
79     // kActionAttachEncryptedBuffer - decrypts and attaches the buffer
80     //                               and queues to the codec.
81     // TODO: kActionAttachEncryptedBuffer is meant to work with
82     // BLOCK_MODEL which is not yet implemented.
83     enum : uint32_t {
84         // decryption types
85         kActionDecrypt                 = (1 <<  0),
86         kActionAttachEncryptedBuffer   = (1 <<  1)
87     };
88 
89     // This struct is meant to copy the mapped contents from the original info.
90     struct CryptoAsyncInfo : public CodecCryptoInfo {
91         public:
92             explicit CryptoAsyncInfo(const std::unique_ptr<CodecCryptoInfo> &info);
93             virtual ~CryptoAsyncInfo() = default;
94         protected:
95             // all backup buffers for the base object.
96             sp<ABuffer> mKeyBuffer;
97             sp<ABuffer> mIvBuffer;
98             sp<ABuffer> mSubSamplesBuffer;
99     };
100 protected:
101 
102     // Message types for the looper
103     enum : uint32_t {
104         // used with decrypt()
105         // Exact decryption type as described by the above enum
106         // decides what "action" to take. The "action" should be
107         // part of this message
108         kWhatDecrypt         = 1,
109         // used with stop()
110         kWhatStop            = 2,
111         // place holder
112         kWhatDoNothing       = 10
113     };
114 
115     // Defines the staste of this thread.
116     typedef enum : uint32_t {
117         // kCryptoAsyncActive as long as we have not encountered
118         // any errors during processing. Any errors will
119         // put the state to error and the thread now refuses to
120         // do further processing until the error state is cleared
121         // with a call to stop()
122 
123         kCryptoAsyncActive  = (0 <<  0),
124         // state of the looper when encountered with error during
125         // processing
126         kCryptoAsyncError   = (1 <<  8)
127     } CryptoAsyncState;
128 
129     // Implements kActionDecrypt
130     status_t decryptAndQueue(sp<AMessage>& msg);
131 
132     // Implements kActionAttachEncryptedBuffer
133     status_t attachEncryptedBufferAndQueue(sp<AMessage>& msg);
134 
135     // Implements the Looper
136     void onMessageReceived(const sp<AMessage>& msg) override;
137 
138     std::unique_ptr<CryptoAsyncCallback> mCallback;
139 private:
140 
141     CryptoAsyncState mState;
142 
143     // Queue holding any pending buffers
144     Mutexed<std::list<sp<AMessage>>> mPendingBuffers;
145 
146     std::weak_ptr<BufferChannelBase> mBufferChannel;
147 };
148 
149 }  // namespace android
150 
151 #endif  // CRYPTO_ASYNC_H_
152