1/*
2 * Copyright (C) 2017 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_TAG "mediacas_hidl_hal_test"
18
19#include <VtsHalHidlTargetTestBase.h>
20#include <VtsHalHidlTargetTestEnvBase.h>
21#include <android-base/logging.h>
22#include <android/hardware/cas/1.0/ICas.h>
23#include <android/hardware/cas/1.0/ICasListener.h>
24#include <android/hardware/cas/1.0/IDescramblerBase.h>
25#include <android/hardware/cas/1.0/IMediaCasService.h>
26#include <android/hardware/cas/1.0/types.h>
27#include <android/hardware/cas/native/1.0/IDescrambler.h>
28#include <android/hardware/cas/native/1.0/types.h>
29#include <binder/MemoryDealer.h>
30#include <hidl/HidlSupport.h>
31#include <hidl/HidlTransportSupport.h>
32#include <hidl/Status.h>
33#include <hidlmemory/FrameworkUtils.h>
34#include <utils/Condition.h>
35#include <utils/Mutex.h>
36
37#define CLEAR_KEY_SYSTEM_ID 0xF6D8
38#define INVALID_SYSTEM_ID 0
39#define WAIT_TIMEOUT 3000000000
40
41#define PROVISION_STR                                      \
42    "{                                                   " \
43    "  \"id\": 21140844,                                 " \
44    "  \"name\": \"Test Title\",                         " \
45    "  \"lowercase_organization_name\": \"Android\",     " \
46    "  \"asset_key\": {                                  " \
47    "  \"encryption_key\": \"nezAr3CHFrmBR9R8Tedotw==\"  " \
48    "  },                                                " \
49    "  \"cas_type\": 1,                                  " \
50    "  \"track_types\": [ ]                              " \
51    "}                                                   "
52
53using android::Condition;
54using android::hardware::cas::V1_0::ICas;
55using android::hardware::cas::V1_0::ICasListener;
56using android::hardware::cas::V1_0::IDescramblerBase;
57using android::hardware::cas::V1_0::Status;
58using android::hardware::cas::native::V1_0::IDescrambler;
59using android::hardware::cas::native::V1_0::SubSample;
60using android::hardware::cas::native::V1_0::SharedBuffer;
61using android::hardware::cas::native::V1_0::DestinationBuffer;
62using android::hardware::cas::native::V1_0::BufferType;
63using android::hardware::cas::native::V1_0::ScramblingControl;
64using android::hardware::cas::V1_0::IMediaCasService;
65using android::hardware::cas::V1_0::HidlCasPluginDescriptor;
66using android::hardware::fromHeap;
67using android::hardware::hidl_vec;
68using android::hardware::hidl_string;
69using android::hardware::HidlMemory;
70using android::hardware::Return;
71using android::hardware::Void;
72using android::IMemory;
73using android::IMemoryHeap;
74using android::MemoryDealer;
75using android::Mutex;
76using android::sp;
77
78namespace {
79
80const uint8_t kEcmBinaryBuffer[] = {
81    0x00, 0x00, 0x01, 0xf0, 0x00, 0x50, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x46, 0x00,
82    0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x27, 0x10, 0x02, 0x00,
83    0x01, 0x77, 0x01, 0x42, 0x95, 0x6c, 0x0e, 0xe3, 0x91, 0xbc, 0xfd, 0x05, 0xb1, 0x60, 0x4f,
84    0x17, 0x82, 0xa4, 0x86, 0x9b, 0x23, 0x56, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
85    0x27, 0x10, 0x02, 0x00, 0x01, 0x77, 0x01, 0x42, 0x95, 0x6c, 0xd7, 0x43, 0x62, 0xf8, 0x1c,
86    0x62, 0x19, 0x05, 0xc7, 0x3a, 0x42, 0xcd, 0xfd, 0xd9, 0x13, 0x48,
87};
88
89const SubSample kSubSamples[] = {{162, 0}, {0, 184}, {0, 184}};
90
91const uint8_t kInBinaryBuffer[] = {
92    0x00, 0x00, 0x00, 0x01, 0x09, 0xf0, 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0xc0, 0x1e, 0xdb, 0x01,
93    0x40, 0x16, 0xec, 0x04, 0x40, 0x00, 0x00, 0x03, 0x00, 0x40, 0x00, 0x00, 0x0f, 0x03, 0xc5, 0x8b,
94    0xb8, 0x00, 0x00, 0x00, 0x01, 0x68, 0xca, 0x8c, 0xb2, 0x00, 0x00, 0x01, 0x06, 0x05, 0xff, 0xff,
95    0x70, 0xdc, 0x45, 0xe9, 0xbd, 0xe6, 0xd9, 0x48, 0xb7, 0x96, 0x2c, 0xd8, 0x20, 0xd9, 0x23, 0xee,
96    0xef, 0x78, 0x32, 0x36, 0x34, 0x20, 0x2d, 0x20, 0x63, 0x6f, 0x72, 0x65, 0x20, 0x31, 0x34, 0x32,
97    0x20, 0x2d, 0x20, 0x48, 0x2e, 0x32, 0x36, 0x34, 0x2f, 0x4d, 0x50, 0x45, 0x47, 0x2d, 0x34, 0x20,
98    0x41, 0x56, 0x43, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x63, 0x20, 0x2d, 0x20, 0x43, 0x6f, 0x70, 0x79,
99    0x6c, 0x65, 0x66, 0x74, 0x20, 0x32, 0x30, 0x30, 0x33, 0x2d, 0x32, 0x30, 0x31, 0x34, 0x20, 0x2d,
100    0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x76, 0x69, 0x64, 0x65,
101    0x6f, 0x6c, 0x61, 0x6e, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x78, 0x32, 0x36, 0x34, 0x2e, 0x68, 0x74,
102    0x6d, 0x6c, 0x6e, 0x45, 0x21, 0x82, 0x38, 0xf0, 0x9d, 0x7d, 0x96, 0xe6, 0x94, 0xae, 0xe2, 0x87,
103    0x8f, 0x04, 0x49, 0xe5, 0xf6, 0x8c, 0x8b, 0x9a, 0x10, 0x18, 0xba, 0x94, 0xe9, 0x22, 0x31, 0x04,
104    0x7e, 0x60, 0x5b, 0xc4, 0x24, 0x00, 0x90, 0x62, 0x0d, 0xdc, 0x85, 0x74, 0x75, 0x78, 0xd0, 0x14,
105    0x08, 0xcb, 0x02, 0x1d, 0x7d, 0x9d, 0x34, 0xe8, 0x81, 0xb9, 0xf7, 0x09, 0x28, 0x79, 0x29, 0x8d,
106    0xe3, 0x14, 0xed, 0x5f, 0xca, 0xaf, 0xf4, 0x1c, 0x49, 0x15, 0xe1, 0x80, 0x29, 0x61, 0x76, 0x80,
107    0x43, 0xf8, 0x58, 0x53, 0x40, 0xd7, 0x31, 0x6d, 0x61, 0x81, 0x41, 0xe9, 0x77, 0x9f, 0x9c, 0xe1,
108    0x6d, 0xf2, 0xee, 0xd9, 0xc8, 0x67, 0xd2, 0x5f, 0x48, 0x73, 0xe3, 0x5c, 0xcd, 0xa7, 0x45, 0x58,
109    0xbb, 0xdd, 0x28, 0x1d, 0x68, 0xfc, 0xb4, 0xc6, 0xf6, 0x92, 0xf6, 0x30, 0x03, 0xaa, 0xe4, 0x32,
110    0xf6, 0x34, 0x51, 0x4b, 0x0f, 0x8c, 0xf9, 0xac, 0x98, 0x22, 0xfb, 0x49, 0xc8, 0xbf, 0xca, 0x8c,
111    0x80, 0x86, 0x5d, 0xd7, 0xa4, 0x52, 0xb1, 0xd9, 0xa6, 0x04, 0x4e, 0xb3, 0x2d, 0x1f, 0xb8, 0x35,
112    0xcc, 0x45, 0x6d, 0x9c, 0x20, 0xa7, 0xa4, 0x34, 0x59, 0x72, 0xe3, 0xae, 0xba, 0x49, 0xde, 0xd1,
113    0xaa, 0xee, 0x3d, 0x77, 0xfc, 0x5d, 0xc6, 0x1f, 0x9d, 0xac, 0xc2, 0x15, 0x66, 0xb8, 0xe1, 0x54,
114    0x4e, 0x74, 0x93, 0xdb, 0x9a, 0x24, 0x15, 0x6e, 0x20, 0xa3, 0x67, 0x3e, 0x5a, 0x24, 0x41, 0x5e,
115    0xb0, 0xe6, 0x35, 0x87, 0x1b, 0xc8, 0x7a, 0xf9, 0x77, 0x65, 0xe0, 0x01, 0xf2, 0x4c, 0xe4, 0x2b,
116    0xa9, 0x64, 0x96, 0x96, 0x0b, 0x46, 0xca, 0xea, 0x79, 0x0e, 0x78, 0xa3, 0x5f, 0x43, 0xfc, 0x47,
117    0x6a, 0x12, 0xfa, 0xc4, 0x33, 0x0e, 0x88, 0x1c, 0x19, 0x3a, 0x00, 0xc3, 0x4e, 0xb5, 0xd8, 0xfa,
118    0x8e, 0xf1, 0xbc, 0x3d, 0xb2, 0x7e, 0x50, 0x8d, 0x67, 0xc3, 0x6b, 0xed, 0xe2, 0xea, 0xa6, 0x1f,
119    0x25, 0x24, 0x7c, 0x94, 0x74, 0x50, 0x49, 0xe3, 0xc6, 0x58, 0x2e, 0xfd, 0x28, 0xb4, 0xc6, 0x73,
120    0xb1, 0x53, 0x74, 0x27, 0x94, 0x5c, 0xdf, 0x69, 0xb7, 0xa1, 0xd7, 0xf5, 0xd3, 0x8a, 0x2c, 0x2d,
121    0xb4, 0x5e, 0x8a, 0x16, 0x14, 0x54, 0x64, 0x6e, 0x00, 0x6b, 0x11, 0x59, 0x8a, 0x63, 0x38, 0x80,
122    0x76, 0xc3, 0xd5, 0x59, 0xf7, 0x3f, 0xd2, 0xfa, 0xa5, 0xca, 0x82, 0xff, 0x4a, 0x62, 0xf0, 0xe3,
123    0x42, 0xf9, 0x3b, 0x38, 0x27, 0x8a, 0x89, 0xaa, 0x50, 0x55, 0x4b, 0x29, 0xf1, 0x46, 0x7c, 0x75,
124    0xef, 0x65, 0xaf, 0x9b, 0x0d, 0x6d, 0xda, 0x25, 0x94, 0x14, 0xc1, 0x1b, 0xf0, 0xc5, 0x4c, 0x24,
125    0x0e, 0x65,
126};
127
128const uint8_t kOutRefBinaryBuffer[] = {
129    0x00, 0x00, 0x00, 0x01, 0x09, 0xf0, 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0xc0, 0x1e, 0xdb, 0x01,
130    0x40, 0x16, 0xec, 0x04, 0x40, 0x00, 0x00, 0x03, 0x00, 0x40, 0x00, 0x00, 0x0f, 0x03, 0xc5, 0x8b,
131    0xb8, 0x00, 0x00, 0x00, 0x01, 0x68, 0xca, 0x8c, 0xb2, 0x00, 0x00, 0x01, 0x06, 0x05, 0xff, 0xff,
132    0x70, 0xdc, 0x45, 0xe9, 0xbd, 0xe6, 0xd9, 0x48, 0xb7, 0x96, 0x2c, 0xd8, 0x20, 0xd9, 0x23, 0xee,
133    0xef, 0x78, 0x32, 0x36, 0x34, 0x20, 0x2d, 0x20, 0x63, 0x6f, 0x72, 0x65, 0x20, 0x31, 0x34, 0x32,
134    0x20, 0x2d, 0x20, 0x48, 0x2e, 0x32, 0x36, 0x34, 0x2f, 0x4d, 0x50, 0x45, 0x47, 0x2d, 0x34, 0x20,
135    0x41, 0x56, 0x43, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x63, 0x20, 0x2d, 0x20, 0x43, 0x6f, 0x70, 0x79,
136    0x6c, 0x65, 0x66, 0x74, 0x20, 0x32, 0x30, 0x30, 0x33, 0x2d, 0x32, 0x30, 0x31, 0x34, 0x20, 0x2d,
137    0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x76, 0x69, 0x64, 0x65,
138    0x6f, 0x6c, 0x61, 0x6e, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x78, 0x32, 0x36, 0x34, 0x2e, 0x68, 0x74,
139    0x6d, 0x6c, 0x20, 0x2d, 0x20, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x3a, 0x20, 0x63, 0x61,
140    0x62, 0x61, 0x63, 0x3d, 0x30, 0x20, 0x72, 0x65, 0x66, 0x3d, 0x32, 0x20, 0x64, 0x65, 0x62, 0x6c,
141    0x6f, 0x63, 0x6b, 0x3d, 0x31, 0x3a, 0x30, 0x3a, 0x30, 0x20, 0x61, 0x6e, 0x61, 0x6c, 0x79, 0x73,
142    0x65, 0x3d, 0x30, 0x78, 0x31, 0x3a, 0x30, 0x78, 0x31, 0x31, 0x31, 0x20, 0x6d, 0x65, 0x3d, 0x68,
143    0x65, 0x78, 0x20, 0x73, 0x75, 0x62, 0x6d, 0x65, 0x3d, 0x37, 0x20, 0x70, 0x73, 0x79, 0x3d, 0x31,
144    0x20, 0x70, 0x73, 0x79, 0x5f, 0x72, 0x64, 0x3d, 0x31, 0x2e, 0x30, 0x30, 0x3a, 0x30, 0x2e, 0x30,
145    0x30, 0x20, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x72, 0x65, 0x66, 0x3d, 0x31, 0x20, 0x6d, 0x65,
146    0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x3d, 0x31, 0x36, 0x20, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x61,
147    0x5f, 0x6d, 0x65, 0x3d, 0x31, 0x20, 0x74, 0x72, 0x65, 0x6c, 0x6c, 0x69, 0x73, 0x3d, 0x31, 0x20,
148    0x38, 0x78, 0x38, 0x64, 0x63, 0x74, 0x3d, 0x30, 0x20, 0x63, 0x71, 0x6d, 0x3d, 0x30, 0x20, 0x64,
149    0x65, 0x61, 0x64, 0x7a, 0x6f, 0x6e, 0x65, 0x3d, 0x32, 0x31, 0x2c, 0x31, 0x31, 0x20, 0x66, 0x61,
150    0x73, 0x74, 0x5f, 0x70, 0x73, 0x6b, 0x69, 0x70, 0x3d, 0x31, 0x20, 0x63, 0x68, 0x72, 0x6f, 0x6d,
151    0x61, 0x5f, 0x71, 0x70, 0x5f, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x3d, 0x2d, 0x32, 0x20, 0x74,
152    0x68, 0x72, 0x65, 0x61, 0x64, 0x73, 0x3d, 0x36, 0x30, 0x20, 0x6c, 0x6f, 0x6f, 0x6b, 0x61, 0x68,
153    0x65, 0x61, 0x64, 0x5f, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x73, 0x3d, 0x35, 0x20, 0x73, 0x6c,
154    0x69, 0x63, 0x65, 0x64, 0x5f, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x73, 0x3d, 0x30, 0x20, 0x6e,
155    0x72, 0x3d, 0x30, 0x20, 0x64, 0x65, 0x63, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x3d, 0x31, 0x20, 0x69,
156    0x6e, 0x74, 0x65, 0x72, 0x6c, 0x61, 0x63, 0x65, 0x64, 0x3d, 0x30, 0x20, 0x62, 0x6c, 0x75, 0x72,
157    0x61, 0x79, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x74, 0x3d, 0x30, 0x20, 0x63, 0x6f, 0x6e, 0x73,
158    0x74, 0x72, 0x61, 0x69, 0x6e, 0x65, 0x64, 0x5f, 0x69, 0x6e, 0x74, 0x72, 0x61, 0x3d, 0x30, 0x20,
159    0x62, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x3d, 0x30, 0x20, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74,
160    0x70, 0x3d, 0x30, 0x20, 0x6b, 0x65, 0x79, 0x69, 0x6e, 0x74, 0x3d, 0x32, 0x35, 0x30, 0x20, 0x6b,
161    0x65, 0x79, 0x69, 0x6e, 0x74, 0x5f, 0x6d, 0x69, 0x6e, 0x3d, 0x32, 0x35, 0x20, 0x73, 0x63, 0x65,
162    0x6e, 0x65,
163};
164
165class MediaCasListener : public ICasListener {
166   public:
167    virtual Return<void> onEvent(int32_t event, int32_t arg,
168                                 const hidl_vec<uint8_t>& data) override {
169        android::Mutex::Autolock autoLock(mMsgLock);
170        mEvent = event;
171        mEventArg = arg;
172        mEventData = data;
173
174        mEventReceived = true;
175        mMsgCondition.signal();
176        return Void();
177    }
178
179    void testEventEcho(sp<ICas>& mediaCas, int32_t& event, int32_t& eventArg,
180                       hidl_vec<uint8_t>& eventData);
181
182   private:
183    int32_t mEvent = -1;
184    int32_t mEventArg = -1;
185    bool mEventReceived = false;
186    hidl_vec<uint8_t> mEventData;
187    android::Mutex mMsgLock;
188    android::Condition mMsgCondition;
189};
190
191void MediaCasListener::testEventEcho(sp<ICas>& mediaCas, int32_t& event, int32_t& eventArg,
192                                     hidl_vec<uint8_t>& eventData) {
193    mEventReceived = false;
194    auto returnStatus = mediaCas->sendEvent(event, eventArg, eventData);
195    EXPECT_TRUE(returnStatus.isOk());
196    EXPECT_EQ(Status::OK, returnStatus);
197
198    android::Mutex::Autolock autoLock(mMsgLock);
199    while (!mEventReceived) {
200        if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
201            EXPECT_TRUE(false) << "event not received within timeout";
202            return;
203        }
204    }
205
206    EXPECT_EQ(mEvent, event);
207    EXPECT_EQ(mEventArg, eventArg);
208    EXPECT_TRUE(mEventData == eventData);
209}
210
211// Test environment for Cas HIDL HAL.
212class CasHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
213   public:
214    // get the test environment singleton
215    static CasHidlEnvironment* Instance() {
216        static CasHidlEnvironment* instance = new CasHidlEnvironment;
217        return instance;
218    }
219
220    virtual void registerTestServices() override { registerTestService<IMediaCasService>(); }
221};
222
223class MediaCasHidlTest : public ::testing::VtsHalHidlTargetTestBase {
224   public:
225    virtual void SetUp() override {
226        mService = ::testing::VtsHalHidlTargetTestBase::getService<IMediaCasService>(
227            CasHidlEnvironment::Instance()->getServiceName<IMediaCasService>());
228        ASSERT_NE(mService, nullptr);
229    }
230
231    sp<IMediaCasService> mService;
232
233   protected:
234    static void description(const std::string& description) {
235        RecordProperty("description", description);
236    }
237
238    sp<ICas> mMediaCas;
239    sp<IDescramblerBase> mDescramblerBase;
240    sp<MediaCasListener> mCasListener;
241    typedef struct _OobInputTestParams {
242        const SubSample* subSamples;
243        uint32_t numSubSamples;
244        size_t imemSizeActual;
245        uint64_t imemOffset;
246        uint64_t imemSize;
247        uint64_t srcOffset;
248        uint64_t dstOffset;
249    } OobInputTestParams;
250
251    ::testing::AssertionResult createCasPlugin(int32_t caSystemId);
252    ::testing::AssertionResult openCasSession(std::vector<uint8_t>* sessionId);
253    ::testing::AssertionResult descrambleTestInputBuffer(
254            const sp<IDescrambler>& descrambler,
255            Status* descrambleStatus,
256            sp<IMemory>* hidlInMemory);
257    ::testing::AssertionResult descrambleTestOobInput(
258            const sp<IDescrambler>& descrambler,
259            Status* descrambleStatus,
260            const OobInputTestParams& params);
261};
262
263::testing::AssertionResult MediaCasHidlTest::createCasPlugin(int32_t caSystemId) {
264    auto status = mService->isSystemIdSupported(caSystemId);
265    if (!status.isOk() || !status) {
266        return ::testing::AssertionFailure();
267    }
268    status = mService->isDescramblerSupported(caSystemId);
269    if (!status.isOk() || !status) {
270        return ::testing::AssertionFailure();
271    }
272
273    mCasListener = new MediaCasListener();
274    auto pluginStatus = mService->createPlugin(caSystemId, mCasListener);
275    if (!pluginStatus.isOk()) {
276        return ::testing::AssertionFailure();
277    }
278    mMediaCas = pluginStatus;
279    if (mMediaCas == nullptr) {
280        return ::testing::AssertionFailure();
281    }
282
283    auto descramblerStatus = mService->createDescrambler(caSystemId);
284    if (!descramblerStatus.isOk()) {
285        return ::testing::AssertionFailure();
286    }
287    mDescramblerBase = descramblerStatus;
288    return ::testing::AssertionResult(mDescramblerBase != nullptr);
289}
290
291::testing::AssertionResult MediaCasHidlTest::openCasSession(std::vector<uint8_t>* sessionId) {
292    Status sessionStatus;
293    auto returnVoid = mMediaCas->openSession([&](Status status, const hidl_vec<uint8_t>& id) {
294        sessionStatus = status;
295        *sessionId = id;
296    });
297    return ::testing::AssertionResult(returnVoid.isOk() && (Status::OK == sessionStatus));
298}
299
300::testing::AssertionResult MediaCasHidlTest::descrambleTestInputBuffer(
301    const sp<IDescrambler>& descrambler, Status* descrambleStatus, sp<IMemory>* inMemory) {
302    hidl_vec<SubSample> hidlSubSamples;
303    hidlSubSamples.setToExternal(const_cast<SubSample*>(kSubSamples),
304                                 (sizeof(kSubSamples) / sizeof(SubSample)), false /*own*/);
305
306    sp<MemoryDealer> dealer = new MemoryDealer(sizeof(kInBinaryBuffer), "vts-cas");
307    if (nullptr == dealer.get()) {
308        ALOGE("couldn't get MemoryDealer!");
309        return ::testing::AssertionFailure();
310    }
311
312    sp<IMemory> mem = dealer->allocate(sizeof(kInBinaryBuffer));
313    if (nullptr == mem.get()) {
314        ALOGE("couldn't allocate IMemory!");
315        return ::testing::AssertionFailure();
316    }
317    *inMemory = mem;
318
319    // build HidlMemory from memory heap
320    ssize_t offset;
321    size_t size;
322    sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
323    if (nullptr == heap.get()) {
324        ALOGE("couldn't get memory heap!");
325        return ::testing::AssertionFailure();
326    }
327
328    uint8_t* ipBuffer = static_cast<uint8_t*>(static_cast<void*>(mem->pointer()));
329    memcpy(ipBuffer, kInBinaryBuffer, sizeof(kInBinaryBuffer));
330
331    // hidlMemory is not to be passed out of scope!
332    sp<HidlMemory> hidlMemory = fromHeap(heap);
333
334    SharedBuffer srcBuffer = {
335            .heapBase = *hidlMemory,
336            .offset = (uint64_t) offset,
337            .size = (uint64_t) size
338    };
339
340    DestinationBuffer dstBuffer;
341    dstBuffer.type = BufferType::SHARED_MEMORY;
342    dstBuffer.nonsecureMemory = srcBuffer;
343
344    uint32_t outBytes;
345    hidl_string detailedError;
346    auto returnVoid = descrambler->descramble(
347        ScramblingControl::EVENKEY /*2*/, hidlSubSamples, srcBuffer, 0, dstBuffer, 0,
348        [&](Status status, uint32_t bytesWritten, const hidl_string& detailedErr) {
349            *descrambleStatus = status;
350            outBytes = bytesWritten;
351            detailedError = detailedErr;
352        });
353    if (!returnVoid.isOk() || *descrambleStatus != Status::OK) {
354        ALOGI("descramble failed, trans=%s, status=%d, outBytes=%u, error=%s",
355              returnVoid.description().c_str(), *descrambleStatus, outBytes, detailedError.c_str());
356    }
357    return ::testing::AssertionResult(returnVoid.isOk());
358}
359
360::testing::AssertionResult MediaCasHidlTest::descrambleTestOobInput(
361        const sp<IDescrambler>& descrambler,
362        Status* descrambleStatus,
363        const OobInputTestParams& params) {
364    hidl_vec<SubSample> hidlSubSamples;
365    hidlSubSamples.setToExternal(
366            const_cast<SubSample*>(params.subSamples), params.numSubSamples, false /*own*/);
367
368    sp<MemoryDealer> dealer = new MemoryDealer(params.imemSizeActual, "vts-cas");
369    if (nullptr == dealer.get()) {
370        ALOGE("couldn't get MemoryDealer!");
371        return ::testing::AssertionFailure();
372    }
373
374    sp<IMemory> mem = dealer->allocate(params.imemSizeActual);
375    if (nullptr == mem.get()) {
376        ALOGE("couldn't allocate IMemory!");
377        return ::testing::AssertionFailure();
378    }
379
380    // build HidlMemory from memory heap
381    ssize_t offset;
382    size_t size;
383    sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
384    if (nullptr == heap.get()) {
385        ALOGE("couldn't get memory heap!");
386        return ::testing::AssertionFailure();
387    }
388
389    // hidlMemory is not to be passed out of scope!
390    sp<HidlMemory> hidlMemory = fromHeap(heap);
391
392    SharedBuffer srcBuffer = {
393            .heapBase = *hidlMemory,
394            .offset = (uint64_t) offset + params.imemOffset,
395            .size = (uint64_t) params.imemSize,
396    };
397
398    DestinationBuffer dstBuffer;
399    dstBuffer.type = BufferType::SHARED_MEMORY;
400    dstBuffer.nonsecureMemory = srcBuffer;
401
402    uint32_t outBytes;
403    hidl_string detailedError;
404    auto returnVoid = descrambler->descramble(
405        ScramblingControl::EVENKEY /*2*/, hidlSubSamples,
406        srcBuffer,
407        params.srcOffset,
408        dstBuffer,
409        params.dstOffset,
410        [&](Status status, uint32_t bytesWritten, const hidl_string& detailedErr) {
411            *descrambleStatus = status;
412            outBytes = bytesWritten;
413            detailedError = detailedErr;
414        });
415    if (!returnVoid.isOk() || *descrambleStatus != Status::OK) {
416        ALOGI("descramble failed, trans=%s, status=%d, outBytes=%u, error=%s",
417              returnVoid.description().c_str(), *descrambleStatus, outBytes, detailedError.c_str());
418    }
419    return ::testing::AssertionResult(returnVoid.isOk());
420}
421
422TEST_F(MediaCasHidlTest, EnumeratePlugins) {
423    description("Test enumerate plugins");
424    hidl_vec<HidlCasPluginDescriptor> descriptors;
425    EXPECT_TRUE(mService
426                    ->enumeratePlugins([&descriptors](
427                        hidl_vec<HidlCasPluginDescriptor> const& desc) { descriptors = desc; })
428                    .isOk());
429
430    if (descriptors.size() == 0) {
431        ALOGW("[   WARN   ] enumeratePlugins list empty");
432        return;
433    }
434
435    sp<MediaCasListener> casListener = new MediaCasListener();
436    for (size_t i = 0; i < descriptors.size(); i++) {
437        int32_t caSystemId = descriptors[i].caSystemId;
438
439        ASSERT_TRUE(createCasPlugin(caSystemId));
440    }
441}
442
443TEST_F(MediaCasHidlTest, TestInvalidSystemIdFails) {
444    description("Test failure for invalid system ID");
445    sp<MediaCasListener> casListener = new MediaCasListener();
446
447    ASSERT_FALSE(mService->isSystemIdSupported(INVALID_SYSTEM_ID));
448    ASSERT_FALSE(mService->isDescramblerSupported(INVALID_SYSTEM_ID));
449
450    auto pluginStatus = mService->createPlugin(INVALID_SYSTEM_ID, casListener);
451    ASSERT_TRUE(pluginStatus.isOk());
452    sp<ICas> mediaCas = pluginStatus;
453    EXPECT_EQ(mediaCas, nullptr);
454
455    auto descramblerStatus = mService->createDescrambler(INVALID_SYSTEM_ID);
456    ASSERT_TRUE(descramblerStatus.isOk());
457    sp<IDescramblerBase> descramblerBase = descramblerStatus;
458    EXPECT_EQ(descramblerBase, nullptr);
459}
460
461TEST_F(MediaCasHidlTest, TestClearKeyPluginInstalled) {
462    description("Test if ClearKey plugin is installed");
463    hidl_vec<HidlCasPluginDescriptor> descriptors;
464    EXPECT_TRUE(mService
465                    ->enumeratePlugins([&descriptors](
466                        hidl_vec<HidlCasPluginDescriptor> const& desc) { descriptors = desc; })
467                    .isOk());
468
469    if (descriptors.size() == 0) {
470        ALOGW("[   WARN   ] enumeratePlugins list empty");
471    }
472
473    for (size_t i = 0; i < descriptors.size(); i++) {
474        int32_t caSystemId = descriptors[i].caSystemId;
475        if (CLEAR_KEY_SYSTEM_ID == caSystemId) {
476            return;
477        }
478    }
479
480    ASSERT_TRUE(false) << "ClearKey plugin not installed";
481}
482
483TEST_F(MediaCasHidlTest, TestClearKeyApis) {
484    description("Test that valid call sequences succeed");
485
486    ASSERT_TRUE(createCasPlugin(CLEAR_KEY_SYSTEM_ID));
487
488    auto returnStatus = mMediaCas->provision(hidl_string(PROVISION_STR));
489    EXPECT_TRUE(returnStatus.isOk());
490    EXPECT_EQ(Status::OK, returnStatus);
491
492    hidl_vec<uint8_t> hidlPvtData;
493    hidlPvtData.resize(256);
494    returnStatus = mMediaCas->setPrivateData(hidlPvtData);
495    EXPECT_TRUE(returnStatus.isOk());
496    EXPECT_EQ(Status::OK, returnStatus);
497
498    std::vector<uint8_t> sessionId;
499    ASSERT_TRUE(openCasSession(&sessionId));
500    returnStatus = mMediaCas->setSessionPrivateData(sessionId, hidlPvtData);
501    EXPECT_TRUE(returnStatus.isOk());
502    EXPECT_EQ(Status::OK, returnStatus);
503
504    std::vector<uint8_t> streamSessionId;
505    ASSERT_TRUE(openCasSession(&streamSessionId));
506    returnStatus = mMediaCas->setSessionPrivateData(streamSessionId, hidlPvtData);
507    EXPECT_TRUE(returnStatus.isOk());
508    EXPECT_EQ(Status::OK, returnStatus);
509
510    returnStatus = mDescramblerBase->setMediaCasSession(sessionId);
511    EXPECT_TRUE(returnStatus.isOk());
512    EXPECT_EQ(Status::OK, returnStatus);
513
514    returnStatus = mDescramblerBase->setMediaCasSession(streamSessionId);
515    EXPECT_TRUE(returnStatus.isOk());
516    EXPECT_EQ(Status::OK, returnStatus);
517
518    hidl_vec<uint8_t> hidlNullPtr;
519    hidlNullPtr.setToExternal(static_cast<uint8_t*>(nullptr), 0);
520    returnStatus = mMediaCas->refreshEntitlements(3, hidlNullPtr);
521    EXPECT_TRUE(returnStatus.isOk());
522    EXPECT_EQ(Status::OK, returnStatus);
523
524    uint8_t refreshData[] = {0, 1, 2, 3};
525    hidl_vec<uint8_t> hidlRefreshData;
526    hidlRefreshData.setToExternal(static_cast<uint8_t*>(refreshData), sizeof(refreshData));
527    returnStatus = mMediaCas->refreshEntitlements(10, hidlRefreshData);
528    EXPECT_TRUE(returnStatus.isOk());
529    EXPECT_EQ(Status::OK, returnStatus);
530
531    int32_t eventID = 1;
532    int32_t eventArg = 2;
533    mCasListener->testEventEcho(mMediaCas, eventID, eventArg, hidlNullPtr);
534
535    eventID = 3;
536    eventArg = 4;
537    uint8_t eventData[] = {'e', 'v', 'e', 'n', 't', 'd', 'a', 't', 'a'};
538    hidl_vec<uint8_t> hidlEventData;
539    hidlEventData.setToExternal(static_cast<uint8_t*>(eventData), sizeof(eventData));
540    mCasListener->testEventEcho(mMediaCas, eventID, eventArg, hidlEventData);
541
542    uint8_t clearKeyEmmData[] = {'c', 'l', 'e', 'a', 'r', 'k', 'e', 'y', 'e', 'm', 'm'};
543    hidl_vec<uint8_t> hidlClearKeyEmm;
544    hidlClearKeyEmm.setToExternal(static_cast<uint8_t*>(clearKeyEmmData), sizeof(clearKeyEmmData));
545    returnStatus = mMediaCas->processEmm(hidlClearKeyEmm);
546    EXPECT_TRUE(returnStatus.isOk());
547    EXPECT_EQ(Status::OK, returnStatus);
548
549    hidl_vec<uint8_t> hidlEcm;
550    hidlEcm.setToExternal(const_cast<uint8_t*>(kEcmBinaryBuffer), sizeof(kEcmBinaryBuffer));
551    returnStatus = mMediaCas->processEcm(sessionId, hidlEcm);
552    EXPECT_TRUE(returnStatus.isOk());
553    EXPECT_EQ(Status::OK, returnStatus);
554    returnStatus = mMediaCas->processEcm(streamSessionId, hidlEcm);
555    EXPECT_TRUE(returnStatus.isOk());
556    EXPECT_EQ(Status::OK, returnStatus);
557
558    EXPECT_FALSE(mDescramblerBase->requiresSecureDecoderComponent("video/avc"));
559
560    sp<IDescrambler> descrambler;
561    descrambler = IDescrambler::castFrom(mDescramblerBase);
562    ASSERT_NE(descrambler, nullptr);
563
564    Status descrambleStatus = Status::OK;
565    sp<IMemory> dataMemory;
566
567    ASSERT_TRUE(descrambleTestInputBuffer(descrambler, &descrambleStatus, &dataMemory));
568    EXPECT_EQ(Status::OK, descrambleStatus);
569
570    ASSERT_NE(nullptr, dataMemory.get());
571    uint8_t* opBuffer = static_cast<uint8_t*>(static_cast<void*>(dataMemory->pointer()));
572
573    int compareResult =
574        memcmp(static_cast<const void*>(opBuffer), static_cast<const void*>(kOutRefBinaryBuffer),
575               sizeof(kOutRefBinaryBuffer));
576    EXPECT_EQ(0, compareResult);
577
578    returnStatus = mDescramblerBase->release();
579    EXPECT_TRUE(returnStatus.isOk());
580    EXPECT_EQ(Status::OK, returnStatus);
581
582    returnStatus = mMediaCas->release();
583    EXPECT_TRUE(returnStatus.isOk());
584    EXPECT_EQ(Status::OK, returnStatus);
585}
586
587TEST_F(MediaCasHidlTest, TestClearKeySessionClosedAfterRelease) {
588    description("Test that all sessions are closed after a MediaCas object is released");
589
590    ASSERT_TRUE(createCasPlugin(CLEAR_KEY_SYSTEM_ID));
591
592    auto returnStatus = mMediaCas->provision(hidl_string(PROVISION_STR));
593    EXPECT_TRUE(returnStatus.isOk());
594    EXPECT_EQ(Status::OK, returnStatus);
595
596    std::vector<uint8_t> sessionId;
597    ASSERT_TRUE(openCasSession(&sessionId));
598    std::vector<uint8_t> streamSessionId;
599    ASSERT_TRUE(openCasSession(&streamSessionId));
600
601    returnStatus = mMediaCas->release();
602    EXPECT_TRUE(returnStatus.isOk());
603    EXPECT_EQ(Status::OK, returnStatus);
604
605    returnStatus = mDescramblerBase->setMediaCasSession(sessionId);
606    EXPECT_TRUE(returnStatus.isOk());
607    EXPECT_EQ(Status::ERROR_CAS_SESSION_NOT_OPENED, returnStatus);
608
609    returnStatus = mDescramblerBase->setMediaCasSession(streamSessionId);
610    EXPECT_TRUE(returnStatus.isOk());
611    EXPECT_EQ(Status::ERROR_CAS_SESSION_NOT_OPENED, returnStatus);
612}
613
614TEST_F(MediaCasHidlTest, TestClearKeyErrors) {
615    description("Test that invalid call sequences fail with expected error codes");
616
617    ASSERT_TRUE(createCasPlugin(CLEAR_KEY_SYSTEM_ID));
618
619    /*
620     * Test MediaCas error codes
621     */
622    // Provision should fail with an invalid asset string
623    auto returnStatus = mMediaCas->provision(hidl_string("invalid asset string"));
624    EXPECT_TRUE(returnStatus.isOk());
625    EXPECT_EQ(Status::ERROR_CAS_NO_LICENSE, returnStatus);
626
627    // Open a session, then close it so that it should become invalid
628    std::vector<uint8_t> invalidSessionId;
629    ASSERT_TRUE(openCasSession(&invalidSessionId));
630    returnStatus = mMediaCas->closeSession(invalidSessionId);
631    EXPECT_TRUE(returnStatus.isOk());
632    EXPECT_EQ(Status::OK, returnStatus);
633
634    // processEcm should fail with an invalid session id
635    hidl_vec<uint8_t> hidlEcm;
636    hidlEcm.setToExternal(const_cast<uint8_t*>(kEcmBinaryBuffer), sizeof(kEcmBinaryBuffer));
637    returnStatus = mMediaCas->processEcm(invalidSessionId, hidlEcm);
638    EXPECT_TRUE(returnStatus.isOk());
639    EXPECT_EQ(Status::ERROR_CAS_SESSION_NOT_OPENED, returnStatus);
640
641    std::vector<uint8_t> sessionId;
642    ASSERT_TRUE(openCasSession(&sessionId));
643
644    // processEcm should fail without provisioning
645    hidlEcm.setToExternal(const_cast<uint8_t*>(kEcmBinaryBuffer), sizeof(kEcmBinaryBuffer));
646    returnStatus = mMediaCas->processEcm(sessionId, hidlEcm);
647    EXPECT_TRUE(returnStatus.isOk());
648    EXPECT_EQ(Status::ERROR_CAS_NOT_PROVISIONED, returnStatus);
649
650    returnStatus = mMediaCas->provision(hidl_string(PROVISION_STR));
651    EXPECT_TRUE(returnStatus.isOk());
652    EXPECT_EQ(Status::OK, returnStatus);
653
654    // processEcm should fail with ecm buffer that's too short
655    hidlEcm.setToExternal(const_cast<uint8_t*>(kEcmBinaryBuffer), 8);
656    returnStatus = mMediaCas->processEcm(sessionId, hidlEcm);
657    EXPECT_TRUE(returnStatus.isOk());
658    EXPECT_EQ(Status::BAD_VALUE, returnStatus);
659
660    // processEcm should fail with ecm with bad descriptor count
661    uint8_t badDescriptor[sizeof(kEcmBinaryBuffer)];
662    memcpy(badDescriptor, kEcmBinaryBuffer, sizeof(kEcmBinaryBuffer));
663    badDescriptor[17] = 0x03;  // change the descriptor count field to 3 (invalid)
664    hidlEcm.setToExternal(static_cast<uint8_t*>(badDescriptor), sizeof(badDescriptor));
665    returnStatus = mMediaCas->processEcm(sessionId, hidlEcm);
666    EXPECT_TRUE(returnStatus.isOk());
667    EXPECT_EQ(Status::ERROR_CAS_UNKNOWN, returnStatus);
668
669    /*
670     * Test MediaDescrambler error codes
671     */
672    // setMediaCasSession should fail with an invalid session id
673    returnStatus = mDescramblerBase->setMediaCasSession(invalidSessionId);
674    EXPECT_TRUE(returnStatus.isOk());
675    EXPECT_EQ(Status::ERROR_CAS_SESSION_NOT_OPENED, returnStatus);
676
677    // descramble should fail without a valid session
678    sp<IDescrambler> descrambler;
679    descrambler = IDescrambler::castFrom(mDescramblerBase);
680    ASSERT_NE(descrambler, nullptr);
681
682    Status descrambleStatus = Status::OK;
683    sp<IMemory> dataMemory;
684
685    ASSERT_TRUE(descrambleTestInputBuffer(descrambler, &descrambleStatus, &dataMemory));
686    EXPECT_EQ(Status::ERROR_CAS_DECRYPT_UNIT_NOT_INITIALIZED, descrambleStatus);
687
688    // Now set a valid session, should still fail because no valid ecm is processed
689    returnStatus = mDescramblerBase->setMediaCasSession(sessionId);
690    EXPECT_TRUE(returnStatus.isOk());
691    EXPECT_EQ(Status::OK, returnStatus);
692
693    ASSERT_TRUE(descrambleTestInputBuffer(descrambler, &descrambleStatus, &dataMemory));
694    EXPECT_EQ(Status::ERROR_CAS_DECRYPT, descrambleStatus);
695
696    // Verify that requiresSecureDecoderComponent handles empty mime
697    EXPECT_FALSE(mDescramblerBase->requiresSecureDecoderComponent(""));
698
699    // Verify that requiresSecureDecoderComponent handles invalid mime
700    EXPECT_FALSE(mDescramblerBase->requiresSecureDecoderComponent("bad"));
701}
702
703TEST_F(MediaCasHidlTest, TestClearKeyOobFails) {
704    description("Test that oob descramble request fails with expected error");
705
706    ASSERT_TRUE(createCasPlugin(CLEAR_KEY_SYSTEM_ID));
707
708    auto returnStatus = mMediaCas->provision(hidl_string(PROVISION_STR));
709    EXPECT_TRUE(returnStatus.isOk());
710    EXPECT_EQ(Status::OK, returnStatus);
711
712    std::vector<uint8_t> sessionId;
713    ASSERT_TRUE(openCasSession(&sessionId));
714
715    returnStatus = mDescramblerBase->setMediaCasSession(sessionId);
716    EXPECT_TRUE(returnStatus.isOk());
717    EXPECT_EQ(Status::OK, returnStatus);
718
719    hidl_vec<uint8_t> hidlEcm;
720    hidlEcm.setToExternal(const_cast<uint8_t*>(kEcmBinaryBuffer), sizeof(kEcmBinaryBuffer));
721    returnStatus = mMediaCas->processEcm(sessionId, hidlEcm);
722    EXPECT_TRUE(returnStatus.isOk());
723    EXPECT_EQ(Status::OK, returnStatus);
724
725    sp<IDescrambler> descrambler = IDescrambler::castFrom(mDescramblerBase);
726    ASSERT_NE(nullptr, descrambler.get());
727
728    Status descrambleStatus = Status::OK;
729
730    // test invalid src buffer offset
731    ASSERT_TRUE(descrambleTestOobInput(
732            descrambler,
733            &descrambleStatus,
734            {
735                .subSamples     = kSubSamples,
736                .numSubSamples  = sizeof(kSubSamples)/sizeof(SubSample),
737                .imemSizeActual = sizeof(kInBinaryBuffer),
738                .imemOffset     = 0xcccccc,
739                .imemSize       = sizeof(kInBinaryBuffer),
740                .srcOffset      = 0,
741                .dstOffset      = 0
742            }));
743    EXPECT_EQ(Status::BAD_VALUE, descrambleStatus);
744
745    // test invalid src buffer size
746    ASSERT_TRUE(descrambleTestOobInput(
747            descrambler,
748            &descrambleStatus,
749            {
750                .subSamples     = kSubSamples,
751                .numSubSamples  = sizeof(kSubSamples)/sizeof(SubSample),
752                .imemSizeActual = sizeof(kInBinaryBuffer),
753                .imemOffset     = 0,
754                .imemSize       = 0xcccccc,
755                .srcOffset      = 0,
756                .dstOffset      = 0
757            }));
758    EXPECT_EQ(Status::BAD_VALUE, descrambleStatus);
759
760    // test invalid src buffer size
761    ASSERT_TRUE(descrambleTestOobInput(
762            descrambler,
763            &descrambleStatus,
764            {
765                .subSamples     = kSubSamples,
766                .numSubSamples  = sizeof(kSubSamples)/sizeof(SubSample),
767                .imemSizeActual = sizeof(kInBinaryBuffer),
768                .imemOffset     = 1,
769                .imemSize       = (uint64_t)-1,
770                .srcOffset      = 0,
771                .dstOffset      = 0
772            }));
773    EXPECT_EQ(Status::BAD_VALUE, descrambleStatus);
774
775    // test invalid srcOffset
776    ASSERT_TRUE(descrambleTestOobInput(
777            descrambler,
778            &descrambleStatus,
779            {
780                .subSamples     = kSubSamples,
781                .numSubSamples  = sizeof(kSubSamples)/sizeof(SubSample),
782                .imemSizeActual = sizeof(kInBinaryBuffer),
783                .imemOffset     = 0,
784                .imemSize       = sizeof(kInBinaryBuffer),
785                .srcOffset      = 0xcccccc,
786                .dstOffset      = 0
787            }));
788    EXPECT_EQ(Status::BAD_VALUE, descrambleStatus);
789
790    // test invalid dstOffset
791    ASSERT_TRUE(descrambleTestOobInput(
792            descrambler,
793            &descrambleStatus,
794            {
795                .subSamples     = kSubSamples,
796                .numSubSamples  = sizeof(kSubSamples)/sizeof(SubSample),
797                .imemSizeActual = sizeof(kInBinaryBuffer),
798                .imemOffset     = 0,
799                .imemSize       = sizeof(kInBinaryBuffer),
800                .srcOffset      = 0,
801                .dstOffset      = 0xcccccc
802            }));
803    EXPECT_EQ(Status::BAD_VALUE, descrambleStatus);
804
805    // test detection of oob subsample sizes
806    const SubSample invalidSubSamples1[] =
807        {{162, 0}, {0, 184}, {0, 0xdddddd}};
808
809    ASSERT_TRUE(descrambleTestOobInput(
810            descrambler,
811            &descrambleStatus,
812            {
813                .subSamples     = invalidSubSamples1,
814                .numSubSamples  = sizeof(invalidSubSamples1)/sizeof(SubSample),
815                .imemSizeActual = sizeof(kInBinaryBuffer),
816                .imemOffset     = 0,
817                .imemSize       = sizeof(kInBinaryBuffer),
818                .srcOffset      = 0,
819                .dstOffset      = 0
820            }));
821    EXPECT_EQ(Status::BAD_VALUE, descrambleStatus);
822
823    // test detection of overflowing subsample sizes
824    const SubSample invalidSubSamples2[] =
825        {{162, 0}, {0, 184}, {2, (uint32_t)-1}};
826
827    ASSERT_TRUE(descrambleTestOobInput(
828            descrambler,
829            &descrambleStatus,
830            {
831                .subSamples     = invalidSubSamples2,
832                .numSubSamples  = sizeof(invalidSubSamples2)/sizeof(SubSample),
833                .imemSizeActual = sizeof(kInBinaryBuffer),
834                .imemOffset     = 0,
835                .imemSize       = sizeof(kInBinaryBuffer),
836                .srcOffset      = 0,
837                .dstOffset      = 0
838            }));
839    EXPECT_EQ(Status::BAD_VALUE, descrambleStatus);
840
841    returnStatus = mDescramblerBase->release();
842    EXPECT_TRUE(returnStatus.isOk());
843    EXPECT_EQ(Status::OK, returnStatus);
844
845    returnStatus = mMediaCas->release();
846    EXPECT_TRUE(returnStatus.isOk());
847    EXPECT_EQ(Status::OK, returnStatus);
848}
849
850}  // anonymous namespace
851
852int main(int argc, char** argv) {
853    ::testing::AddGlobalTestEnvironment(CasHidlEnvironment::Instance());
854    ::testing::InitGoogleTest(&argc, argv);
855    CasHidlEnvironment::Instance()->init(&argc, argv);
856    int status = RUN_ALL_TESTS();
857    LOG(INFO) << "Test result = " << status;
858    return status;
859}
860