1 /*
2 * Copyright (C) 2021 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 "drm_hal_test@1.4"
18
19 #include "android/hardware/drm/1.4/vts/drm_hal_test.h"
20
21 namespace android {
22 namespace hardware {
23 namespace drm {
24 namespace V1_4 {
25 namespace vts {
26
27 const char* const DrmHalTest::kVideoMp4 = "video/mp4";
28 const char* const DrmHalTest::kAudioMp4 = "audio/mp4";
29 const uint32_t DrmHalTest::kSecLevelDefault = DrmHalTest::kSecLevelMax + 1;
30
DrmPluginV1_4() const31 sp<drm::V1_4::IDrmPlugin> DrmHalTest::DrmPluginV1_4() const {
32 sp<drm::V1_4::IDrmPlugin> plugin(drm::V1_4::IDrmPlugin::castFrom(drmPlugin));
33 EXPECT_NE(nullptr, plugin.get());
34 return plugin;
35 }
36
CryptoPlugin(const SessionId & sid)37 sp<V1_0::ICryptoPlugin> DrmHalTest::CryptoPlugin(const SessionId& sid) {
38 sp<V1_0::ICryptoPlugin> crypto;
39 auto res = cryptoFactory->createPlugin(
40 getUUID(), sid,
41 [&](V1_0::Status status, const sp<V1_0::ICryptoPlugin>& plugin) {
42 EXPECT_EQ(V1_0::Status::OK, status);
43 EXPECT_NE(nullptr, plugin.get());
44 crypto = plugin;
45 });
46 EXPECT_OK(res);
47 return crypto;
48 }
49
OpenSession(uint32_t level=kSecLevelDefault)50 SessionId DrmHalTest::OpenSession(uint32_t level = kSecLevelDefault) {
51 V1_0::Status err;
52 SessionId sessionId;
53 bool attemptedProvision = false;
54
55 V1_0::IDrmPlugin::openSession_cb cb = [&](
56 V1_0::Status status,
57 const hidl_vec<unsigned char> &id) {
58 err = status;
59 sessionId = id;
60 };
61
62 while (true) {
63 Return<void> res;
64 if (level > kSecLevelMax) {
65 res = drmPlugin->openSession(cb);
66 } else if (level >= kSecLevelMin) {
67 auto securityLevel = static_cast<SecurityLevel>(level);
68 res = drmPlugin->openSession_1_1(securityLevel, cb);
69 }
70 EXPECT_OK(res);
71 if (V1_0::Status::ERROR_DRM_NOT_PROVISIONED == err
72 && !attemptedProvision) {
73 // provision once if necessary
74 provision();
75 attemptedProvision = true;
76 continue;
77 } else if (V1_0::Status::ERROR_DRM_CANNOT_HANDLE == err) {
78 // must be able to handle default level
79 EXPECT_NE(kSecLevelDefault, level);
80 sessionId = {};
81 } else {
82 EXPECT_EQ(V1_0::Status::OK, err);
83 EXPECT_NE(sessionId.size(), 0u);
84 }
85 break;
86 }
87
88 return sessionId;
89 }
90
TEST_P(DrmHalTest,RequiresSecureDecoder)91 TEST_P(DrmHalTest, RequiresSecureDecoder) {
92 for (uint32_t level : {kSecLevelMin, kSecLevelMax, kSecLevelDefault}) {
93 for (auto mime : {kVideoMp4, kAudioMp4}) {
94 auto sid = OpenSession(level);
95 if (sid.size() == 0u) {
96 continue;
97 }
98 auto drm = DrmPluginV1_4();
99 sp<V1_0::ICryptoPlugin> crypto(CryptoPlugin(sid));
100 if (drm == nullptr || crypto == nullptr) {
101 continue;
102 }
103 bool r1 = crypto->requiresSecureDecoderComponent(mime);
104 bool r2;
105 if (level == kSecLevelDefault) {
106 r2 = drm->requiresSecureDecoderDefault(mime);
107 } else {
108 auto sL = static_cast<SecurityLevel>(level);
109 r2 = drm->requiresSecureDecoder(mime, sL);
110 }
111 EXPECT_EQ(r1, r2);
112 closeSession(sid);
113 }
114 }
115 }
116
TEST_P(DrmHalTest,SetPlaybackId)117 TEST_P(DrmHalTest, SetPlaybackId) {
118 auto testInfo = ::testing::UnitTest::GetInstance()->current_test_info();
119 auto testName = testInfo->name();
120 const hidl_string& pbId{testName};
121 auto sid = OpenSession();
122 auto drm = DrmPluginV1_4();
123 if (drm == nullptr) {
124 return;
125 }
126 V1_0::Status err = drm->setPlaybackId(sid, pbId);
127 EXPECT_EQ(V1_0::Status::OK, err);
128 closeSession(sid);
129
130 // search for playback id among metric attributes/values
131 bool foundPbId = false;
132 auto res = drmPlugin->getMetrics([&](
133 V1_0::Status status,
134 hidl_vec<V1_1::DrmMetricGroup> metricGroups) {
135 EXPECT_EQ(V1_0::Status::OK, status);
136 for (const auto& group : metricGroups) {
137 for (const auto& metric : group.metrics) {
138 for (const auto& value : metric.values) {
139 if (value.stringValue == pbId) {
140 foundPbId = true;
141 break;
142 }
143 }
144 for (const auto& attr : metric.attributes) {
145 if (attr.stringValue == pbId) {
146 foundPbId = true;
147 break;
148 }
149 }
150 }
151 }
152 });
153 EXPECT_OK(res);
154 EXPECT_TRUE(foundPbId);
155 }
156
TEST_P(DrmHalTest,GetLogMessages)157 TEST_P(DrmHalTest, GetLogMessages) {
158 auto drm = DrmPluginV1_4();
159 auto sid = OpenSession();
160 auto crypto_1_0 = CryptoPlugin(sid);
161 sp<V1_4::ICryptoPlugin> crypto(V1_4::ICryptoPlugin::castFrom(crypto_1_0));
162
163 hidl_vec<uint8_t> initData;
164 hidl_string mime{"text/plain"};
165 V1_0::KeyedVector optionalParameters;
166 auto res = drmPlugin->getKeyRequest_1_2(
167 sid, initData, mime, V1_0::KeyType::STREAMING,
168 optionalParameters, [&](V1_2::Status status, const hidl_vec<uint8_t>&,
169 V1_1::KeyRequestType, const hidl_string&) {
170 EXPECT_NE(V1_2::Status::OK, status);
171 });
172 EXPECT_OK(res);
173
174 V1_4::IDrmPlugin::getLogMessages_cb cb = [&](
175 V1_4::Status status,
176 hidl_vec<V1_4::LogMessage> logs) {
177 EXPECT_EQ(V1_4::Status::OK, status);
178 EXPECT_NE(0, logs.size());
179 for (auto log: logs) {
180 ALOGI("priority=[%u] message='%s'", log.priority, log.message.c_str());
181 }
182 };
183
184 auto res2 = drm->getLogMessages(cb);
185 EXPECT_OK(res2);
186
187 auto res3 = crypto->getLogMessages(cb);
188 EXPECT_OK(res3);
189
190 closeSession(sid);
191 }
192
193 } // namespace vts
194 } // namespace V1_4
195 } // namespace drm
196 } // namespace hardware
197 } // namespace android
198