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