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 <android-base/logging.h>
21#include <android/hardware/cas/1.0/ICas.h>
22#include <android/hardware/cas/1.0/ICasListener.h>
23#include <android/hardware/cas/1.0/IDescramblerBase.h>
24#include <android/hardware/cas/1.0/IMediaCasService.h>
25#include <android/hardware/cas/1.0/types.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 <hidl/HidlSupport.h>
30#include <hidl/HidlTransportSupport.h>
31#include <hidl/Status.h>
32#include <utils/Condition.h>
33#include <utils/Mutex.h>
34
35#define CLEAR_KEY_SYSTEM_ID 0xF6D8
36#define INVALID_SYSTEM_ID 0
37#define WAIT_TIMEOUT 3000000000
38
39#define PROVISION_STR                                      \
40    "{                                                   " \
41    "  \"id\": 21140844,                                 " \
42    "  \"name\": \"Test Title\",                         " \
43    "  \"lowercase_organization_name\": \"Android\",     " \
44    "  \"asset_key\": {                                  " \
45    "  \"encryption_key\": \"nezAr3CHFrmBR9R8Tedotw==\"  " \
46    "  },                                                " \
47    "  \"cas_type\": 1,                                  " \
48    "  \"track_types\": [ ]                              " \
49    "}                                                   "
50
51using android::Condition;
52using android::hardware::cas::V1_0::ICas;
53using android::hardware::cas::V1_0::ICasListener;
54using android::hardware::cas::V1_0::IDescramblerBase;
55using android::hardware::cas::native::V1_0::IDescrambler;
56using android::hardware::cas::native::V1_0::SubSample;
57using android::hardware::cas::native::V1_0::SharedBuffer;
58using android::hardware::cas::native::V1_0::DestinationBuffer;
59using android::hardware::cas::native::V1_0::BufferType;
60using android::hardware::cas::native::V1_0::ScramblingControl;
61using android::hardware::cas::V1_0::IMediaCasService;
62using android::hardware::cas::V1_0::HidlCasPluginDescriptor;
63using android::hardware::Void;
64using android::hardware::hidl_vec;
65using android::hardware::hidl_string;
66using android::hardware::hidl_handle;
67using android::hardware::hidl_memory;
68using android::hardware::Return;
69using android::hardware::cas::V1_0::Status;
70using android::IMemory;
71using android::IMemoryHeap;
72using android::MemoryDealer;
73using android::Mutex;
74using android::sp;
75
76namespace {
77
78const uint8_t kEcmBinaryBuffer[] = {
79    0x00, 0x00, 0x01, 0xf0, 0x00, 0x50, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x46, 0x00,
80    0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x27, 0x10, 0x02, 0x00,
81    0x01, 0x77, 0x01, 0x42, 0x95, 0x6c, 0x0e, 0xe3, 0x91, 0xbc, 0xfd, 0x05, 0xb1, 0x60, 0x4f,
82    0x17, 0x82, 0xa4, 0x86, 0x9b, 0x23, 0x56, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
83    0x27, 0x10, 0x02, 0x00, 0x01, 0x77, 0x01, 0x42, 0x95, 0x6c, 0xd7, 0x43, 0x62, 0xf8, 0x1c,
84    0x62, 0x19, 0x05, 0xc7, 0x3a, 0x42, 0xcd, 0xfd, 0xd9, 0x13, 0x48,
85};
86
87const SubSample kSubSamples[] = {{162, 0}, {0, 184}, {0, 184}};
88
89const uint8_t kInBinaryBuffer[] = {
90    0x00, 0x00, 0x00, 0x01, 0x09, 0xf0, 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0xc0, 0x1e, 0xdb, 0x01,
91    0x40, 0x16, 0xec, 0x04, 0x40, 0x00, 0x00, 0x03, 0x00, 0x40, 0x00, 0x00, 0x0f, 0x03, 0xc5, 0x8b,
92    0xb8, 0x00, 0x00, 0x00, 0x01, 0x68, 0xca, 0x8c, 0xb2, 0x00, 0x00, 0x01, 0x06, 0x05, 0xff, 0xff,
93    0x70, 0xdc, 0x45, 0xe9, 0xbd, 0xe6, 0xd9, 0x48, 0xb7, 0x96, 0x2c, 0xd8, 0x20, 0xd9, 0x23, 0xee,
94    0xef, 0x78, 0x32, 0x36, 0x34, 0x20, 0x2d, 0x20, 0x63, 0x6f, 0x72, 0x65, 0x20, 0x31, 0x34, 0x32,
95    0x20, 0x2d, 0x20, 0x48, 0x2e, 0x32, 0x36, 0x34, 0x2f, 0x4d, 0x50, 0x45, 0x47, 0x2d, 0x34, 0x20,
96    0x41, 0x56, 0x43, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x63, 0x20, 0x2d, 0x20, 0x43, 0x6f, 0x70, 0x79,
97    0x6c, 0x65, 0x66, 0x74, 0x20, 0x32, 0x30, 0x30, 0x33, 0x2d, 0x32, 0x30, 0x31, 0x34, 0x20, 0x2d,
98    0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x76, 0x69, 0x64, 0x65,
99    0x6f, 0x6c, 0x61, 0x6e, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x78, 0x32, 0x36, 0x34, 0x2e, 0x68, 0x74,
100    0x6d, 0x6c, 0x6e, 0x45, 0x21, 0x82, 0x38, 0xf0, 0x9d, 0x7d, 0x96, 0xe6, 0x94, 0xae, 0xe2, 0x87,
101    0x8f, 0x04, 0x49, 0xe5, 0xf6, 0x8c, 0x8b, 0x9a, 0x10, 0x18, 0xba, 0x94, 0xe9, 0x22, 0x31, 0x04,
102    0x7e, 0x60, 0x5b, 0xc4, 0x24, 0x00, 0x90, 0x62, 0x0d, 0xdc, 0x85, 0x74, 0x75, 0x78, 0xd0, 0x14,
103    0x08, 0xcb, 0x02, 0x1d, 0x7d, 0x9d, 0x34, 0xe8, 0x81, 0xb9, 0xf7, 0x09, 0x28, 0x79, 0x29, 0x8d,
104    0xe3, 0x14, 0xed, 0x5f, 0xca, 0xaf, 0xf4, 0x1c, 0x49, 0x15, 0xe1, 0x80, 0x29, 0x61, 0x76, 0x80,
105    0x43, 0xf8, 0x58, 0x53, 0x40, 0xd7, 0x31, 0x6d, 0x61, 0x81, 0x41, 0xe9, 0x77, 0x9f, 0x9c, 0xe1,
106    0x6d, 0xf2, 0xee, 0xd9, 0xc8, 0x67, 0xd2, 0x5f, 0x48, 0x73, 0xe3, 0x5c, 0xcd, 0xa7, 0x45, 0x58,
107    0xbb, 0xdd, 0x28, 0x1d, 0x68, 0xfc, 0xb4, 0xc6, 0xf6, 0x92, 0xf6, 0x30, 0x03, 0xaa, 0xe4, 0x32,
108    0xf6, 0x34, 0x51, 0x4b, 0x0f, 0x8c, 0xf9, 0xac, 0x98, 0x22, 0xfb, 0x49, 0xc8, 0xbf, 0xca, 0x8c,
109    0x80, 0x86, 0x5d, 0xd7, 0xa4, 0x52, 0xb1, 0xd9, 0xa6, 0x04, 0x4e, 0xb3, 0x2d, 0x1f, 0xb8, 0x35,
110    0xcc, 0x45, 0x6d, 0x9c, 0x20, 0xa7, 0xa4, 0x34, 0x59, 0x72, 0xe3, 0xae, 0xba, 0x49, 0xde, 0xd1,
111    0xaa, 0xee, 0x3d, 0x77, 0xfc, 0x5d, 0xc6, 0x1f, 0x9d, 0xac, 0xc2, 0x15, 0x66, 0xb8, 0xe1, 0x54,
112    0x4e, 0x74, 0x93, 0xdb, 0x9a, 0x24, 0x15, 0x6e, 0x20, 0xa3, 0x67, 0x3e, 0x5a, 0x24, 0x41, 0x5e,
113    0xb0, 0xe6, 0x35, 0x87, 0x1b, 0xc8, 0x7a, 0xf9, 0x77, 0x65, 0xe0, 0x01, 0xf2, 0x4c, 0xe4, 0x2b,
114    0xa9, 0x64, 0x96, 0x96, 0x0b, 0x46, 0xca, 0xea, 0x79, 0x0e, 0x78, 0xa3, 0x5f, 0x43, 0xfc, 0x47,
115    0x6a, 0x12, 0xfa, 0xc4, 0x33, 0x0e, 0x88, 0x1c, 0x19, 0x3a, 0x00, 0xc3, 0x4e, 0xb5, 0xd8, 0xfa,
116    0x8e, 0xf1, 0xbc, 0x3d, 0xb2, 0x7e, 0x50, 0x8d, 0x67, 0xc3, 0x6b, 0xed, 0xe2, 0xea, 0xa6, 0x1f,
117    0x25, 0x24, 0x7c, 0x94, 0x74, 0x50, 0x49, 0xe3, 0xc6, 0x58, 0x2e, 0xfd, 0x28, 0xb4, 0xc6, 0x73,
118    0xb1, 0x53, 0x74, 0x27, 0x94, 0x5c, 0xdf, 0x69, 0xb7, 0xa1, 0xd7, 0xf5, 0xd3, 0x8a, 0x2c, 0x2d,
119    0xb4, 0x5e, 0x8a, 0x16, 0x14, 0x54, 0x64, 0x6e, 0x00, 0x6b, 0x11, 0x59, 0x8a, 0x63, 0x38, 0x80,
120    0x76, 0xc3, 0xd5, 0x59, 0xf7, 0x3f, 0xd2, 0xfa, 0xa5, 0xca, 0x82, 0xff, 0x4a, 0x62, 0xf0, 0xe3,
121    0x42, 0xf9, 0x3b, 0x38, 0x27, 0x8a, 0x89, 0xaa, 0x50, 0x55, 0x4b, 0x29, 0xf1, 0x46, 0x7c, 0x75,
122    0xef, 0x65, 0xaf, 0x9b, 0x0d, 0x6d, 0xda, 0x25, 0x94, 0x14, 0xc1, 0x1b, 0xf0, 0xc5, 0x4c, 0x24,
123    0x0e, 0x65,
124};
125
126const uint8_t kOutRefBinaryBuffer[] = {
127    0x00, 0x00, 0x00, 0x01, 0x09, 0xf0, 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0xc0, 0x1e, 0xdb, 0x01,
128    0x40, 0x16, 0xec, 0x04, 0x40, 0x00, 0x00, 0x03, 0x00, 0x40, 0x00, 0x00, 0x0f, 0x03, 0xc5, 0x8b,
129    0xb8, 0x00, 0x00, 0x00, 0x01, 0x68, 0xca, 0x8c, 0xb2, 0x00, 0x00, 0x01, 0x06, 0x05, 0xff, 0xff,
130    0x70, 0xdc, 0x45, 0xe9, 0xbd, 0xe6, 0xd9, 0x48, 0xb7, 0x96, 0x2c, 0xd8, 0x20, 0xd9, 0x23, 0xee,
131    0xef, 0x78, 0x32, 0x36, 0x34, 0x20, 0x2d, 0x20, 0x63, 0x6f, 0x72, 0x65, 0x20, 0x31, 0x34, 0x32,
132    0x20, 0x2d, 0x20, 0x48, 0x2e, 0x32, 0x36, 0x34, 0x2f, 0x4d, 0x50, 0x45, 0x47, 0x2d, 0x34, 0x20,
133    0x41, 0x56, 0x43, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x63, 0x20, 0x2d, 0x20, 0x43, 0x6f, 0x70, 0x79,
134    0x6c, 0x65, 0x66, 0x74, 0x20, 0x32, 0x30, 0x30, 0x33, 0x2d, 0x32, 0x30, 0x31, 0x34, 0x20, 0x2d,
135    0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x76, 0x69, 0x64, 0x65,
136    0x6f, 0x6c, 0x61, 0x6e, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x78, 0x32, 0x36, 0x34, 0x2e, 0x68, 0x74,
137    0x6d, 0x6c, 0x20, 0x2d, 0x20, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x3a, 0x20, 0x63, 0x61,
138    0x62, 0x61, 0x63, 0x3d, 0x30, 0x20, 0x72, 0x65, 0x66, 0x3d, 0x32, 0x20, 0x64, 0x65, 0x62, 0x6c,
139    0x6f, 0x63, 0x6b, 0x3d, 0x31, 0x3a, 0x30, 0x3a, 0x30, 0x20, 0x61, 0x6e, 0x61, 0x6c, 0x79, 0x73,
140    0x65, 0x3d, 0x30, 0x78, 0x31, 0x3a, 0x30, 0x78, 0x31, 0x31, 0x31, 0x20, 0x6d, 0x65, 0x3d, 0x68,
141    0x65, 0x78, 0x20, 0x73, 0x75, 0x62, 0x6d, 0x65, 0x3d, 0x37, 0x20, 0x70, 0x73, 0x79, 0x3d, 0x31,
142    0x20, 0x70, 0x73, 0x79, 0x5f, 0x72, 0x64, 0x3d, 0x31, 0x2e, 0x30, 0x30, 0x3a, 0x30, 0x2e, 0x30,
143    0x30, 0x20, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x72, 0x65, 0x66, 0x3d, 0x31, 0x20, 0x6d, 0x65,
144    0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x3d, 0x31, 0x36, 0x20, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x61,
145    0x5f, 0x6d, 0x65, 0x3d, 0x31, 0x20, 0x74, 0x72, 0x65, 0x6c, 0x6c, 0x69, 0x73, 0x3d, 0x31, 0x20,
146    0x38, 0x78, 0x38, 0x64, 0x63, 0x74, 0x3d, 0x30, 0x20, 0x63, 0x71, 0x6d, 0x3d, 0x30, 0x20, 0x64,
147    0x65, 0x61, 0x64, 0x7a, 0x6f, 0x6e, 0x65, 0x3d, 0x32, 0x31, 0x2c, 0x31, 0x31, 0x20, 0x66, 0x61,
148    0x73, 0x74, 0x5f, 0x70, 0x73, 0x6b, 0x69, 0x70, 0x3d, 0x31, 0x20, 0x63, 0x68, 0x72, 0x6f, 0x6d,
149    0x61, 0x5f, 0x71, 0x70, 0x5f, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x3d, 0x2d, 0x32, 0x20, 0x74,
150    0x68, 0x72, 0x65, 0x61, 0x64, 0x73, 0x3d, 0x36, 0x30, 0x20, 0x6c, 0x6f, 0x6f, 0x6b, 0x61, 0x68,
151    0x65, 0x61, 0x64, 0x5f, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x73, 0x3d, 0x35, 0x20, 0x73, 0x6c,
152    0x69, 0x63, 0x65, 0x64, 0x5f, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x73, 0x3d, 0x30, 0x20, 0x6e,
153    0x72, 0x3d, 0x30, 0x20, 0x64, 0x65, 0x63, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x3d, 0x31, 0x20, 0x69,
154    0x6e, 0x74, 0x65, 0x72, 0x6c, 0x61, 0x63, 0x65, 0x64, 0x3d, 0x30, 0x20, 0x62, 0x6c, 0x75, 0x72,
155    0x61, 0x79, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x74, 0x3d, 0x30, 0x20, 0x63, 0x6f, 0x6e, 0x73,
156    0x74, 0x72, 0x61, 0x69, 0x6e, 0x65, 0x64, 0x5f, 0x69, 0x6e, 0x74, 0x72, 0x61, 0x3d, 0x30, 0x20,
157    0x62, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x3d, 0x30, 0x20, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74,
158    0x70, 0x3d, 0x30, 0x20, 0x6b, 0x65, 0x79, 0x69, 0x6e, 0x74, 0x3d, 0x32, 0x35, 0x30, 0x20, 0x6b,
159    0x65, 0x79, 0x69, 0x6e, 0x74, 0x5f, 0x6d, 0x69, 0x6e, 0x3d, 0x32, 0x35, 0x20, 0x73, 0x63, 0x65,
160    0x6e, 0x65,
161};
162
163class MediaCasListener : public ICasListener {
164   public:
165    virtual Return<void> onEvent(int32_t event, int32_t arg,
166                                 const hidl_vec<uint8_t>& data) override {
167        android::Mutex::Autolock autoLock(mMsgLock);
168        mEvent = event;
169        mEventArg = arg;
170        mEventData = data;
171
172        mEventReceived = true;
173        mMsgCondition.signal();
174        return Void();
175    }
176
177    void testEventEcho(sp<ICas>& mediaCas, int32_t& event, int32_t& eventArg,
178                       hidl_vec<uint8_t>& eventData);
179
180   private:
181    int32_t mEvent = -1;
182    int32_t mEventArg = -1;
183    bool mEventReceived = false;
184    hidl_vec<uint8_t> mEventData;
185    android::Mutex mMsgLock;
186    android::Condition mMsgCondition;
187};
188
189void MediaCasListener::testEventEcho(sp<ICas>& mediaCas, int32_t& event, int32_t& eventArg,
190                                     hidl_vec<uint8_t>& eventData) {
191    mEventReceived = false;
192    auto returnStatus = mediaCas->sendEvent(event, eventArg, eventData);
193    EXPECT_TRUE(returnStatus.isOk());
194    EXPECT_EQ(Status::OK, returnStatus);
195
196    android::Mutex::Autolock autoLock(mMsgLock);
197    while (!mEventReceived) {
198        if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
199            EXPECT_TRUE(false) << "event not received within timeout";
200            return;
201        }
202    }
203
204    EXPECT_EQ(mEvent, event);
205    EXPECT_EQ(mEventArg, eventArg);
206    EXPECT_TRUE(mEventData == eventData);
207}
208
209class MediaCasHidlTest : public ::testing::VtsHalHidlTargetTestBase {
210   public:
211    virtual void SetUp() override {
212        mService = ::testing::VtsHalHidlTargetTestBase::getService<IMediaCasService>();
213        ASSERT_NE(mService, nullptr);
214    }
215
216    sp<IMediaCasService> mService;
217
218   protected:
219    static void description(const std::string& description) {
220        RecordProperty("description", description);
221    }
222
223    sp<ICas> mMediaCas;
224    sp<IDescramblerBase> mDescramblerBase;
225    sp<MediaCasListener> mCasListener;
226
227    ::testing::AssertionResult createCasPlugin(int32_t caSystemId);
228    ::testing::AssertionResult openCasSession(std::vector<uint8_t>* sessionId);
229    ::testing::AssertionResult descrambleTestInputBuffer(const sp<IDescrambler>& descrambler,
230                                                         Status* descrambleStatus,
231                                                         sp<IMemory>* hidlInMemory);
232};
233
234::testing::AssertionResult MediaCasHidlTest::createCasPlugin(int32_t caSystemId) {
235    auto status = mService->isSystemIdSupported(caSystemId);
236    if (!status.isOk() || !status) {
237        return ::testing::AssertionFailure();
238    }
239    status = mService->isDescramblerSupported(caSystemId);
240    if (!status.isOk() || !status) {
241        return ::testing::AssertionFailure();
242    }
243
244    mCasListener = new MediaCasListener();
245    auto pluginStatus = mService->createPlugin(caSystemId, mCasListener);
246    if (!pluginStatus.isOk()) {
247        return ::testing::AssertionFailure();
248    }
249    mMediaCas = pluginStatus;
250    if (mMediaCas == nullptr) {
251        return ::testing::AssertionFailure();
252    }
253
254    auto descramblerStatus = mService->createDescrambler(caSystemId);
255    if (!descramblerStatus.isOk()) {
256        return ::testing::AssertionFailure();
257    }
258    mDescramblerBase = descramblerStatus;
259    return ::testing::AssertionResult(mDescramblerBase != nullptr);
260}
261
262::testing::AssertionResult MediaCasHidlTest::openCasSession(std::vector<uint8_t>* sessionId) {
263    Status sessionStatus;
264    auto returnVoid = mMediaCas->openSession([&](Status status, const hidl_vec<uint8_t>& id) {
265        sessionStatus = status;
266        *sessionId = id;
267    });
268    return ::testing::AssertionResult(returnVoid.isOk() && (Status::OK == sessionStatus));
269}
270
271::testing::AssertionResult MediaCasHidlTest::descrambleTestInputBuffer(
272    const sp<IDescrambler>& descrambler, Status* descrambleStatus, sp<IMemory>* inMemory) {
273    hidl_vec<SubSample> hidlSubSamples;
274    hidlSubSamples.setToExternal(const_cast<SubSample*>(kSubSamples),
275                                 (sizeof(kSubSamples) / sizeof(SubSample)), false /*own*/);
276
277    sp<MemoryDealer> dealer = new MemoryDealer(sizeof(kInBinaryBuffer), "vts-cas");
278    if (nullptr == dealer.get()) {
279        ALOGE("couldn't get MemoryDealer!");
280        return ::testing::AssertionFailure();
281    }
282
283    sp<IMemory> mem = dealer->allocate(sizeof(kInBinaryBuffer));
284    if (nullptr == mem.get()) {
285        ALOGE("couldn't allocate IMemory!");
286        return ::testing::AssertionFailure();
287    }
288    *inMemory = mem;
289
290    // build hidl_memory from memory heap
291    ssize_t offset;
292    size_t size;
293    sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
294    if (nullptr == heap.get()) {
295        ALOGE("couldn't get memory heap!");
296        return ::testing::AssertionFailure();
297    }
298
299    native_handle_t* nativeHandle = native_handle_create(1, 0);
300    if (!nativeHandle) {
301        ALOGE("failed to create native handle!");
302        return ::testing::AssertionFailure();
303    }
304    nativeHandle->data[0] = heap->getHeapID();
305
306    uint8_t* ipBuffer = static_cast<uint8_t*>(static_cast<void*>(mem->pointer()));
307    memcpy(ipBuffer, kInBinaryBuffer, sizeof(kInBinaryBuffer));
308
309    SharedBuffer srcBuffer = {
310            .heapBase = hidl_memory("ashmem", hidl_handle(nativeHandle), heap->getSize()),
311            .offset = (uint64_t) offset,
312            .size = (uint64_t) size
313    };
314
315    DestinationBuffer dstBuffer;
316    dstBuffer.type = BufferType::SHARED_MEMORY;
317    dstBuffer.nonsecureMemory = srcBuffer;
318
319    uint32_t outBytes;
320    hidl_string detailedError;
321    auto returnVoid = descrambler->descramble(
322        ScramblingControl::EVENKEY /*2*/, hidlSubSamples, srcBuffer, 0, dstBuffer, 0,
323        [&](Status status, uint32_t bytesWritten, const hidl_string& detailedErr) {
324            *descrambleStatus = status;
325            outBytes = bytesWritten;
326            detailedError = detailedErr;
327        });
328    if (!returnVoid.isOk() || *descrambleStatus != Status::OK) {
329        ALOGI("descramble failed, trans=%s, status=%d, outBytes=%u, error=%s",
330              returnVoid.description().c_str(), *descrambleStatus, outBytes, detailedError.c_str());
331    }
332    return ::testing::AssertionResult(returnVoid.isOk());
333}
334
335TEST_F(MediaCasHidlTest, EnumeratePlugins) {
336    description("Test enumerate plugins");
337    hidl_vec<HidlCasPluginDescriptor> descriptors;
338    EXPECT_TRUE(mService
339                    ->enumeratePlugins([&descriptors](
340                        hidl_vec<HidlCasPluginDescriptor> const& desc) { descriptors = desc; })
341                    .isOk());
342
343    if (descriptors.size() == 0) {
344        ALOGW("[   WARN   ] enumeratePlugins list empty");
345        return;
346    }
347
348    sp<MediaCasListener> casListener = new MediaCasListener();
349    for (size_t i = 0; i < descriptors.size(); i++) {
350        int32_t caSystemId = descriptors[i].caSystemId;
351
352        ASSERT_TRUE(createCasPlugin(caSystemId));
353    }
354}
355
356TEST_F(MediaCasHidlTest, TestInvalidSystemIdFails) {
357    description("Test failure for invalid system ID");
358    sp<MediaCasListener> casListener = new MediaCasListener();
359
360    ASSERT_FALSE(mService->isSystemIdSupported(INVALID_SYSTEM_ID));
361    ASSERT_FALSE(mService->isDescramblerSupported(INVALID_SYSTEM_ID));
362
363    auto pluginStatus = mService->createPlugin(INVALID_SYSTEM_ID, casListener);
364    ASSERT_TRUE(pluginStatus.isOk());
365    sp<ICas> mediaCas = pluginStatus;
366    EXPECT_EQ(mediaCas, nullptr);
367
368    auto descramblerStatus = mService->createDescrambler(INVALID_SYSTEM_ID);
369    ASSERT_TRUE(descramblerStatus.isOk());
370    sp<IDescramblerBase> descramblerBase = descramblerStatus;
371    EXPECT_EQ(descramblerBase, nullptr);
372}
373
374TEST_F(MediaCasHidlTest, TestClearKeyPluginInstalled) {
375    description("Test if ClearKey plugin is installed");
376    hidl_vec<HidlCasPluginDescriptor> descriptors;
377    EXPECT_TRUE(mService
378                    ->enumeratePlugins([&descriptors](
379                        hidl_vec<HidlCasPluginDescriptor> const& desc) { descriptors = desc; })
380                    .isOk());
381
382    if (descriptors.size() == 0) {
383        ALOGW("[   WARN   ] enumeratePlugins list empty");
384    }
385
386    for (size_t i = 0; i < descriptors.size(); i++) {
387        int32_t caSystemId = descriptors[i].caSystemId;
388        if (CLEAR_KEY_SYSTEM_ID == caSystemId) {
389            return;
390        }
391    }
392
393    ASSERT_TRUE(false) << "ClearKey plugin not installed";
394}
395
396TEST_F(MediaCasHidlTest, TestClearKeyApis) {
397    description("Test that valid call sequences succeed");
398
399    ASSERT_TRUE(createCasPlugin(CLEAR_KEY_SYSTEM_ID));
400
401    auto returnStatus = mMediaCas->provision(hidl_string(PROVISION_STR));
402    EXPECT_TRUE(returnStatus.isOk());
403    EXPECT_EQ(Status::OK, returnStatus);
404
405    hidl_vec<uint8_t> hidlPvtData;
406    hidlPvtData.resize(256);
407    returnStatus = mMediaCas->setPrivateData(hidlPvtData);
408    EXPECT_TRUE(returnStatus.isOk());
409    EXPECT_EQ(Status::OK, returnStatus);
410
411    std::vector<uint8_t> sessionId;
412    ASSERT_TRUE(openCasSession(&sessionId));
413    returnStatus = mMediaCas->setSessionPrivateData(sessionId, hidlPvtData);
414    EXPECT_TRUE(returnStatus.isOk());
415    EXPECT_EQ(Status::OK, returnStatus);
416
417    std::vector<uint8_t> streamSessionId;
418    ASSERT_TRUE(openCasSession(&streamSessionId));
419    returnStatus = mMediaCas->setSessionPrivateData(streamSessionId, hidlPvtData);
420    EXPECT_TRUE(returnStatus.isOk());
421    EXPECT_EQ(Status::OK, returnStatus);
422
423    returnStatus = mDescramblerBase->setMediaCasSession(sessionId);
424    EXPECT_TRUE(returnStatus.isOk());
425    EXPECT_EQ(Status::OK, returnStatus);
426
427    returnStatus = mDescramblerBase->setMediaCasSession(streamSessionId);
428    EXPECT_TRUE(returnStatus.isOk());
429    EXPECT_EQ(Status::OK, returnStatus);
430
431    hidl_vec<uint8_t> hidlNullPtr;
432    hidlNullPtr.setToExternal(static_cast<uint8_t*>(nullptr), 0);
433    returnStatus = mMediaCas->refreshEntitlements(3, hidlNullPtr);
434    EXPECT_TRUE(returnStatus.isOk());
435    EXPECT_EQ(Status::OK, returnStatus);
436
437    uint8_t refreshData[] = {0, 1, 2, 3};
438    hidl_vec<uint8_t> hidlRefreshData;
439    hidlRefreshData.setToExternal(static_cast<uint8_t*>(refreshData), sizeof(refreshData));
440    returnStatus = mMediaCas->refreshEntitlements(10, hidlRefreshData);
441    EXPECT_TRUE(returnStatus.isOk());
442    EXPECT_EQ(Status::OK, returnStatus);
443
444    int32_t eventID = 1;
445    int32_t eventArg = 2;
446    mCasListener->testEventEcho(mMediaCas, eventID, eventArg, hidlNullPtr);
447
448    eventID = 3;
449    eventArg = 4;
450    uint8_t eventData[] = {'e', 'v', 'e', 'n', 't', 'd', 'a', 't', 'a'};
451    hidl_vec<uint8_t> hidlEventData;
452    hidlEventData.setToExternal(static_cast<uint8_t*>(eventData), sizeof(eventData));
453    mCasListener->testEventEcho(mMediaCas, eventID, eventArg, hidlEventData);
454
455    uint8_t clearKeyEmmData[] = {'c', 'l', 'e', 'a', 'r', 'k', 'e', 'y', 'e', 'm', 'm'};
456    hidl_vec<uint8_t> hidlClearKeyEmm;
457    hidlClearKeyEmm.setToExternal(static_cast<uint8_t*>(clearKeyEmmData), sizeof(clearKeyEmmData));
458    returnStatus = mMediaCas->processEmm(hidlClearKeyEmm);
459    EXPECT_TRUE(returnStatus.isOk());
460    EXPECT_EQ(Status::OK, returnStatus);
461
462    hidl_vec<uint8_t> hidlEcm;
463    hidlEcm.setToExternal(const_cast<uint8_t*>(kEcmBinaryBuffer), sizeof(kEcmBinaryBuffer));
464    returnStatus = mMediaCas->processEcm(sessionId, hidlEcm);
465    EXPECT_TRUE(returnStatus.isOk());
466    EXPECT_EQ(Status::OK, returnStatus);
467    returnStatus = mMediaCas->processEcm(streamSessionId, hidlEcm);
468    EXPECT_TRUE(returnStatus.isOk());
469    EXPECT_EQ(Status::OK, returnStatus);
470
471    EXPECT_FALSE(mDescramblerBase->requiresSecureDecoderComponent("video/avc"));
472
473    sp<IDescrambler> descrambler;
474    descrambler = IDescrambler::castFrom(mDescramblerBase);
475    ASSERT_NE(descrambler, nullptr);
476
477    Status descrambleStatus = Status::OK;
478    sp<IMemory> dataMemory;
479
480    ASSERT_TRUE(descrambleTestInputBuffer(descrambler, &descrambleStatus, &dataMemory));
481    EXPECT_EQ(Status::OK, descrambleStatus);
482
483    ASSERT_NE(nullptr, dataMemory.get());
484    uint8_t* opBuffer = static_cast<uint8_t*>(static_cast<void*>(dataMemory->pointer()));
485
486    int compareResult =
487        memcmp(static_cast<const void*>(opBuffer), static_cast<const void*>(kOutRefBinaryBuffer),
488               sizeof(kOutRefBinaryBuffer));
489    EXPECT_EQ(0, compareResult);
490
491    returnStatus = mDescramblerBase->release();
492    EXPECT_TRUE(returnStatus.isOk());
493    EXPECT_EQ(Status::OK, returnStatus);
494
495    returnStatus = mMediaCas->release();
496    EXPECT_TRUE(returnStatus.isOk());
497    EXPECT_EQ(Status::OK, returnStatus);
498}
499
500TEST_F(MediaCasHidlTest, TestClearKeySessionClosedAfterRelease) {
501    description("Test that all sessions are closed after a MediaCas object is released");
502
503    ASSERT_TRUE(createCasPlugin(CLEAR_KEY_SYSTEM_ID));
504
505    auto returnStatus = mMediaCas->provision(hidl_string(PROVISION_STR));
506    EXPECT_TRUE(returnStatus.isOk());
507    EXPECT_EQ(Status::OK, returnStatus);
508
509    std::vector<uint8_t> sessionId;
510    ASSERT_TRUE(openCasSession(&sessionId));
511    std::vector<uint8_t> streamSessionId;
512    ASSERT_TRUE(openCasSession(&streamSessionId));
513
514    returnStatus = mMediaCas->release();
515    EXPECT_TRUE(returnStatus.isOk());
516    EXPECT_EQ(Status::OK, returnStatus);
517
518    returnStatus = mDescramblerBase->setMediaCasSession(sessionId);
519    EXPECT_TRUE(returnStatus.isOk());
520    EXPECT_EQ(Status::ERROR_CAS_SESSION_NOT_OPENED, returnStatus);
521
522    returnStatus = mDescramblerBase->setMediaCasSession(streamSessionId);
523    EXPECT_TRUE(returnStatus.isOk());
524    EXPECT_EQ(Status::ERROR_CAS_SESSION_NOT_OPENED, returnStatus);
525}
526
527TEST_F(MediaCasHidlTest, TestClearKeyErrors) {
528    description("Test that invalid call sequences fail with expected error codes");
529
530    ASSERT_TRUE(createCasPlugin(CLEAR_KEY_SYSTEM_ID));
531
532    /*
533     * Test MediaCas error codes
534     */
535    // Provision should fail with an invalid asset string
536    auto returnStatus = mMediaCas->provision(hidl_string("invalid asset string"));
537    EXPECT_TRUE(returnStatus.isOk());
538    EXPECT_EQ(Status::ERROR_CAS_NO_LICENSE, returnStatus);
539
540    // Open a session, then close it so that it should become invalid
541    std::vector<uint8_t> invalidSessionId;
542    ASSERT_TRUE(openCasSession(&invalidSessionId));
543    returnStatus = mMediaCas->closeSession(invalidSessionId);
544    EXPECT_TRUE(returnStatus.isOk());
545    EXPECT_EQ(Status::OK, returnStatus);
546
547    // processEcm should fail with an invalid session id
548    hidl_vec<uint8_t> hidlEcm;
549    hidlEcm.setToExternal(const_cast<uint8_t*>(kEcmBinaryBuffer), sizeof(kEcmBinaryBuffer));
550    returnStatus = mMediaCas->processEcm(invalidSessionId, hidlEcm);
551    EXPECT_TRUE(returnStatus.isOk());
552    EXPECT_EQ(Status::ERROR_CAS_SESSION_NOT_OPENED, returnStatus);
553
554    std::vector<uint8_t> sessionId;
555    ASSERT_TRUE(openCasSession(&sessionId));
556
557    // processEcm should fail without provisioning
558    hidlEcm.setToExternal(const_cast<uint8_t*>(kEcmBinaryBuffer), sizeof(kEcmBinaryBuffer));
559    returnStatus = mMediaCas->processEcm(sessionId, hidlEcm);
560    EXPECT_TRUE(returnStatus.isOk());
561    EXPECT_EQ(Status::ERROR_CAS_NOT_PROVISIONED, returnStatus);
562
563    returnStatus = mMediaCas->provision(hidl_string(PROVISION_STR));
564    EXPECT_TRUE(returnStatus.isOk());
565    EXPECT_EQ(Status::OK, returnStatus);
566
567    // processEcm should fail with ecm buffer that's too short
568    hidlEcm.setToExternal(const_cast<uint8_t*>(kEcmBinaryBuffer), 8);
569    returnStatus = mMediaCas->processEcm(sessionId, hidlEcm);
570    EXPECT_TRUE(returnStatus.isOk());
571    EXPECT_EQ(Status::BAD_VALUE, returnStatus);
572
573    // processEcm should fail with ecm with bad descriptor count
574    uint8_t badDescriptor[sizeof(kEcmBinaryBuffer)];
575    memcpy(badDescriptor, kEcmBinaryBuffer, sizeof(kEcmBinaryBuffer));
576    badDescriptor[17] = 0x03;  // change the descriptor count field to 3 (invalid)
577    hidlEcm.setToExternal(static_cast<uint8_t*>(badDescriptor), sizeof(badDescriptor));
578    returnStatus = mMediaCas->processEcm(sessionId, hidlEcm);
579    EXPECT_TRUE(returnStatus.isOk());
580    EXPECT_EQ(Status::ERROR_CAS_UNKNOWN, returnStatus);
581
582    /*
583     * Test MediaDescrambler error codes
584     */
585    // setMediaCasSession should fail with an invalid session id
586    returnStatus = mDescramblerBase->setMediaCasSession(invalidSessionId);
587    EXPECT_TRUE(returnStatus.isOk());
588    EXPECT_EQ(Status::ERROR_CAS_SESSION_NOT_OPENED, returnStatus);
589
590    // descramble should fail without a valid session
591    sp<IDescrambler> descrambler;
592    descrambler = IDescrambler::castFrom(mDescramblerBase);
593    ASSERT_NE(descrambler, nullptr);
594
595    Status descrambleStatus = Status::OK;
596    sp<IMemory> dataMemory;
597
598    ASSERT_TRUE(descrambleTestInputBuffer(descrambler, &descrambleStatus, &dataMemory));
599    EXPECT_EQ(Status::ERROR_CAS_DECRYPT_UNIT_NOT_INITIALIZED, descrambleStatus);
600
601    // Now set a valid session, should still fail because no valid ecm is processed
602    returnStatus = mDescramblerBase->setMediaCasSession(sessionId);
603    EXPECT_TRUE(returnStatus.isOk());
604    EXPECT_EQ(Status::OK, returnStatus);
605
606    ASSERT_TRUE(descrambleTestInputBuffer(descrambler, &descrambleStatus, &dataMemory));
607    EXPECT_EQ(Status::ERROR_CAS_DECRYPT, descrambleStatus);
608
609    // Verify that requiresSecureDecoderComponent handles empty mime
610    EXPECT_FALSE(mDescramblerBase->requiresSecureDecoderComponent(""));
611
612    // Verify that requiresSecureDecoderComponent handles invalid mime
613    EXPECT_FALSE(mDescramblerBase->requiresSecureDecoderComponent("bad"));
614}
615
616}  // anonymous namespace
617
618int main(int argc, char** argv) {
619    ::testing::InitGoogleTest(&argc, argv);
620    int status = RUN_ALL_TESTS();
621    LOG(INFO) << "Test result = " << status;
622    return status;
623}
624