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