blob: 6204f475c8e5513c0b59402ab83fee85926eb848 [file] [log] [blame]
hkuang26587cb2020-01-16 10:36:08 -08001/*
2 * Copyright (C) 2020 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// Unit Test for TranscodingClientManager
18
19// #define LOG_NDEBUG 0
20#define LOG_TAG "TranscodingClientManagerTest"
21
Chong Zhang6d58e4b2020-03-31 09:41:10 -070022#include <aidl/android/media/BnTranscodingClientCallback.h>
hkuang26587cb2020-01-16 10:36:08 -080023#include <aidl/android/media/IMediaTranscodingService.h>
hkuang26587cb2020-01-16 10:36:08 -080024#include <android-base/logging.h>
25#include <android/binder_manager.h>
26#include <android/binder_process.h>
27#include <gtest/gtest.h>
Chong Zhang6d58e4b2020-03-31 09:41:10 -070028#include <media/SchedulerClientInterface.h>
hkuang26587cb2020-01-16 10:36:08 -080029#include <media/TranscodingClientManager.h>
Chong Zhang6d58e4b2020-03-31 09:41:10 -070030#include <media/TranscodingRequest.h>
hkuang26587cb2020-01-16 10:36:08 -080031#include <utils/Log.h>
32
Chong Zhang6d58e4b2020-03-31 09:41:10 -070033#include <list>
34
hkuang26587cb2020-01-16 10:36:08 -080035namespace android {
36
37using Status = ::ndk::ScopedAStatus;
Chong Zhang6d58e4b2020-03-31 09:41:10 -070038using ::aidl::android::media::BnTranscodingClientCallback;
39using ::aidl::android::media::IMediaTranscodingService;
40using ::aidl::android::media::TranscodingErrorCode;
41using ::aidl::android::media::TranscodingJobParcel;
42using ::aidl::android::media::TranscodingRequestParcel;
43using ::aidl::android::media::TranscodingResultParcel;
hkuang26587cb2020-01-16 10:36:08 -080044
Chong Zhang6d58e4b2020-03-31 09:41:10 -070045constexpr pid_t kInvalidClientPid = -1;
Chong Zhang8e062632020-03-31 10:56:37 -070046constexpr const char* kInvalidClientName = "";
47constexpr const char* kInvalidClientPackage = "";
hkuang26587cb2020-01-16 10:36:08 -080048
Chong Zhang6d58e4b2020-03-31 09:41:10 -070049constexpr pid_t kClientPid = 2;
50constexpr uid_t kClientUid = 3;
Chong Zhang8e062632020-03-31 10:56:37 -070051constexpr const char* kClientName = "TestClientName";
52constexpr const char* kClientPackage = "TestClientPackage";
hkuang26587cb2020-01-16 10:36:08 -080053
Chong Zhang6d58e4b2020-03-31 09:41:10 -070054struct TestClientCallback : public BnTranscodingClientCallback {
55 TestClientCallback() { ALOGI("TestClientCallback Created"); }
hkuang26587cb2020-01-16 10:36:08 -080056
Chong Zhang6d58e4b2020-03-31 09:41:10 -070057 virtual ~TestClientCallback() { ALOGI("TestClientCallback destroyed"); };
58
59 Status onTranscodingFinished(int32_t in_jobId,
60 const TranscodingResultParcel& in_result) override {
61 EXPECT_EQ(in_jobId, in_result.jobId);
62 mEventQueue.push_back(Finished(in_jobId));
hkuang26587cb2020-01-16 10:36:08 -080063 return Status::ok();
64 }
65
Chong Zhang6d58e4b2020-03-31 09:41:10 -070066 Status onTranscodingFailed(int32_t in_jobId, TranscodingErrorCode /*in_errorCode */) override {
67 mEventQueue.push_back(Failed(in_jobId));
hkuang26587cb2020-01-16 10:36:08 -080068 return Status::ok();
69 }
70
71 Status onAwaitNumberOfJobsChanged(int32_t /* in_jobId */, int32_t /* in_oldAwaitNumber */,
72 int32_t /* in_newAwaitNumber */) override {
73 return Status::ok();
74 }
75
76 Status onProgressUpdate(int32_t /* in_jobId */, int32_t /* in_progress */) override {
77 return Status::ok();
78 }
79
Chong Zhang6d58e4b2020-03-31 09:41:10 -070080 struct Event {
81 enum {
82 NoEvent,
83 Finished,
84 Failed,
85 } type;
Chong Zhang3fa408f2020-04-30 11:04:28 -070086 JobIdType jobId;
Chong Zhang6d58e4b2020-03-31 09:41:10 -070087 };
88
89 static constexpr Event NoEvent = {Event::NoEvent, 0};
90#define DECLARE_EVENT(action) \
Chong Zhang3fa408f2020-04-30 11:04:28 -070091 static Event action(JobIdType jobId) { return {Event::action, jobId}; }
Chong Zhang6d58e4b2020-03-31 09:41:10 -070092
93 DECLARE_EVENT(Finished);
94 DECLARE_EVENT(Failed);
95
96 const Event& popEvent() {
97 if (mEventQueue.empty()) {
98 mPoppedEvent = NoEvent;
99 } else {
100 mPoppedEvent = *mEventQueue.begin();
101 mEventQueue.pop_front();
102 }
103 return mPoppedEvent;
104 }
hkuang26587cb2020-01-16 10:36:08 -0800105
Chong Zhang8e062632020-03-31 10:56:37 -0700106private:
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700107 Event mPoppedEvent;
108 std::list<Event> mEventQueue;
109
110 TestClientCallback(const TestClientCallback&) = delete;
111 TestClientCallback& operator=(const TestClientCallback&) = delete;
112};
113
114bool operator==(const TestClientCallback::Event& lhs, const TestClientCallback::Event& rhs) {
115 return lhs.type == rhs.type && lhs.jobId == rhs.jobId;
116}
117
118struct TestScheduler : public SchedulerClientInterface {
119 TestScheduler() { ALOGI("TestScheduler Created"); }
120
121 virtual ~TestScheduler() { ALOGI("TestScheduler Destroyed"); }
122
Chong Zhang3fa408f2020-04-30 11:04:28 -0700123 bool submit(ClientIdType clientId, JobIdType jobId, uid_t /*uid*/,
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700124 const TranscodingRequestParcel& request,
125 const std::weak_ptr<ITranscodingClientCallback>& clientCallback) override {
126 JobKeyType jobKey = std::make_pair(clientId, jobId);
127 if (mJobs.count(jobKey) > 0) {
128 return false;
129 }
130
131 // This is the secret name we'll check, to test error propagation from
132 // the scheduler back to client.
133 if (request.fileName == "bad_file") {
134 return false;
135 }
136
137 mJobs[jobKey].request = request;
138 mJobs[jobKey].callback = clientCallback;
139
140 mLastJob = jobKey;
141 return true;
142 }
143
Chong Zhang3fa408f2020-04-30 11:04:28 -0700144 bool cancel(ClientIdType clientId, JobIdType jobId) override {
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700145 JobKeyType jobKey = std::make_pair(clientId, jobId);
146
147 if (mJobs.count(jobKey) == 0) {
148 return false;
149 }
150 mJobs.erase(jobKey);
151 return true;
152 }
153
Chong Zhang3fa408f2020-04-30 11:04:28 -0700154 bool getJob(ClientIdType clientId, JobIdType jobId,
155 TranscodingRequestParcel* request) override {
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700156 JobKeyType jobKey = std::make_pair(clientId, jobId);
157 if (mJobs.count(jobKey) == 0) {
158 return false;
159 }
160
161 *(TranscodingRequest*)request = mJobs[jobKey].request;
162 return true;
163 }
164
165 void finishLastJob() {
166 auto it = mJobs.find(mLastJob);
167 if (it == mJobs.end()) {
168 return;
169 }
170 {
171 auto clientCallback = it->second.callback.lock();
172 if (clientCallback != nullptr) {
173 clientCallback->onTranscodingFinished(
174 mLastJob.second, TranscodingResultParcel({mLastJob.second, 0}));
175 }
176 }
177 mJobs.erase(it);
178 }
179
180 void abortLastJob() {
181 auto it = mJobs.find(mLastJob);
182 if (it == mJobs.end()) {
183 return;
184 }
185 {
186 auto clientCallback = it->second.callback.lock();
187 if (clientCallback != nullptr) {
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700188 clientCallback->onTranscodingFailed(mLastJob.second,
189 TranscodingErrorCode::kUnknown);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700190 }
191 }
192 mJobs.erase(it);
193 }
194
195 struct Job {
196 TranscodingRequest request;
197 std::weak_ptr<ITranscodingClientCallback> callback;
198 };
199
Chong Zhang3fa408f2020-04-30 11:04:28 -0700200 typedef std::pair<ClientIdType, JobIdType> JobKeyType;
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700201 std::map<JobKeyType, Job> mJobs;
202 JobKeyType mLastJob;
hkuang26587cb2020-01-16 10:36:08 -0800203};
204
205class TranscodingClientManagerTest : public ::testing::Test {
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700206public:
207 TranscodingClientManagerTest()
208 : mScheduler(new TestScheduler()),
209 mClientManager(new TranscodingClientManager(mScheduler)) {
hkuang5172cab2020-01-31 12:40:28 -0800210 ALOGD("TranscodingClientManagerTest created");
211 }
hkuang26587cb2020-01-16 10:36:08 -0800212
213 void SetUp() override {
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700214 mClientCallback1 = ::ndk::SharedRefBase::make<TestClientCallback>();
215 mClientCallback2 = ::ndk::SharedRefBase::make<TestClientCallback>();
216 mClientCallback3 = ::ndk::SharedRefBase::make<TestClientCallback>();
hkuang26587cb2020-01-16 10:36:08 -0800217 }
218
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700219 void TearDown() override { ALOGI("TranscodingClientManagerTest tear down"); }
hkuang26587cb2020-01-16 10:36:08 -0800220
221 ~TranscodingClientManagerTest() { ALOGD("TranscodingClientManagerTest destroyed"); }
222
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700223 void addMultipleClients() {
224 EXPECT_EQ(mClientManager->addClient(mClientCallback1, kClientPid, kClientUid, kClientName,
225 kClientPackage, &mClient1),
226 OK);
227 EXPECT_NE(mClient1, nullptr);
228
229 EXPECT_EQ(mClientManager->addClient(mClientCallback2, kClientPid, kClientUid, kClientName,
230 kClientPackage, &mClient2),
231 OK);
232 EXPECT_NE(mClient2, nullptr);
233
234 EXPECT_EQ(mClientManager->addClient(mClientCallback3, kClientPid, kClientUid, kClientName,
235 kClientPackage, &mClient3),
236 OK);
237 EXPECT_NE(mClient3, nullptr);
238
239 EXPECT_EQ(mClientManager->getNumOfClients(), 3);
240 }
241
242 void unregisterMultipleClients() {
243 EXPECT_TRUE(mClient1->unregister().isOk());
244 EXPECT_TRUE(mClient2->unregister().isOk());
245 EXPECT_TRUE(mClient3->unregister().isOk());
246 EXPECT_EQ(mClientManager->getNumOfClients(), 0);
247 }
248
249 std::shared_ptr<TestScheduler> mScheduler;
250 std::shared_ptr<TranscodingClientManager> mClientManager;
251 std::shared_ptr<ITranscodingClient> mClient1;
252 std::shared_ptr<ITranscodingClient> mClient2;
253 std::shared_ptr<ITranscodingClient> mClient3;
254 std::shared_ptr<TestClientCallback> mClientCallback1;
255 std::shared_ptr<TestClientCallback> mClientCallback2;
256 std::shared_ptr<TestClientCallback> mClientCallback3;
hkuang26587cb2020-01-16 10:36:08 -0800257};
258
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700259TEST_F(TranscodingClientManagerTest, TestAddingWithInvalidClientCallback) {
260 // Add a client with null callback and expect failure.
Chong Zhang8e062632020-03-31 10:56:37 -0700261 std::shared_ptr<ITranscodingClient> client;
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700262 status_t err = mClientManager->addClient(nullptr, kClientPid, kClientUid, kClientName,
263 kClientPackage, &client);
Chong Zhang8e062632020-03-31 10:56:37 -0700264 EXPECT_EQ(err, BAD_VALUE);
hkuang26587cb2020-01-16 10:36:08 -0800265}
266
267TEST_F(TranscodingClientManagerTest, TestAddingWithInvalidClientPid) {
Chong Zhang8e062632020-03-31 10:56:37 -0700268 // Add a client with invalid Pid and expect failure.
269 std::shared_ptr<ITranscodingClient> client;
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700270 status_t err = mClientManager->addClient(mClientCallback1, kInvalidClientPid, kClientUid,
271 kClientName, kClientPackage, &client);
Chong Zhang8e062632020-03-31 10:56:37 -0700272 EXPECT_EQ(err, BAD_VALUE);
273}
hkuang26587cb2020-01-16 10:36:08 -0800274
Chong Zhang8e062632020-03-31 10:56:37 -0700275TEST_F(TranscodingClientManagerTest, TestAddingWithInvalidClientName) {
276 // Add a client with invalid name and expect failure.
277 std::shared_ptr<ITranscodingClient> client;
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700278 status_t err = mClientManager->addClient(mClientCallback1, kClientPid, kClientUid,
279 kInvalidClientName, kClientPackage, &client);
Chong Zhang8e062632020-03-31 10:56:37 -0700280 EXPECT_EQ(err, BAD_VALUE);
hkuang26587cb2020-01-16 10:36:08 -0800281}
282
283TEST_F(TranscodingClientManagerTest, TestAddingWithInvalidClientPackageName) {
Chong Zhang8e062632020-03-31 10:56:37 -0700284 // Add a client with invalid packagename and expect failure.
285 std::shared_ptr<ITranscodingClient> client;
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700286 status_t err = mClientManager->addClient(mClientCallback1, kClientPid, kClientUid, kClientName,
287 kInvalidClientPackage, &client);
Chong Zhang8e062632020-03-31 10:56:37 -0700288 EXPECT_EQ(err, BAD_VALUE);
hkuang26587cb2020-01-16 10:36:08 -0800289}
290
291TEST_F(TranscodingClientManagerTest, TestAddingValidClient) {
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700292 // Add a valid client, should succeed.
Chong Zhang8e062632020-03-31 10:56:37 -0700293 std::shared_ptr<ITranscodingClient> client;
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700294 status_t err = mClientManager->addClient(mClientCallback1, kClientPid, kClientUid, kClientName,
295 kClientPackage, &client);
Chong Zhang8e062632020-03-31 10:56:37 -0700296 EXPECT_EQ(err, OK);
297 EXPECT_NE(client.get(), nullptr);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700298 EXPECT_EQ(mClientManager->getNumOfClients(), 1);
hkuang26587cb2020-01-16 10:36:08 -0800299
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700300 // Unregister client, should succeed.
Chong Zhang8e062632020-03-31 10:56:37 -0700301 Status status = client->unregister();
302 EXPECT_TRUE(status.isOk());
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700303 EXPECT_EQ(mClientManager->getNumOfClients(), 0);
hkuang26587cb2020-01-16 10:36:08 -0800304}
305
306TEST_F(TranscodingClientManagerTest, TestAddingDupliacteClient) {
Chong Zhang8e062632020-03-31 10:56:37 -0700307 std::shared_ptr<ITranscodingClient> client;
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700308 status_t err = mClientManager->addClient(mClientCallback1, kClientPid, kClientUid, kClientName,
309 kClientPackage, &client);
Chong Zhang8e062632020-03-31 10:56:37 -0700310 EXPECT_EQ(err, OK);
311 EXPECT_NE(client.get(), nullptr);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700312 EXPECT_EQ(mClientManager->getNumOfClients(), 1);
hkuang26587cb2020-01-16 10:36:08 -0800313
Chong Zhang8e062632020-03-31 10:56:37 -0700314 std::shared_ptr<ITranscodingClient> dupClient;
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700315 err = mClientManager->addClient(mClientCallback1, kClientPid, kClientUid, "dupClient",
316 "dupPackage", &dupClient);
Chong Zhang8e062632020-03-31 10:56:37 -0700317 EXPECT_EQ(err, ALREADY_EXISTS);
318 EXPECT_EQ(dupClient.get(), nullptr);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700319 EXPECT_EQ(mClientManager->getNumOfClients(), 1);
hkuang26587cb2020-01-16 10:36:08 -0800320
Chong Zhang8e062632020-03-31 10:56:37 -0700321 Status status = client->unregister();
322 EXPECT_TRUE(status.isOk());
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700323 EXPECT_EQ(mClientManager->getNumOfClients(), 0);
hkuang26587cb2020-01-16 10:36:08 -0800324
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700325 err = mClientManager->addClient(mClientCallback1, kClientPid, kClientUid, "dupClient",
326 "dupPackage", &dupClient);
Chong Zhang8e062632020-03-31 10:56:37 -0700327 EXPECT_EQ(err, OK);
328 EXPECT_NE(dupClient.get(), nullptr);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700329 EXPECT_EQ(mClientManager->getNumOfClients(), 1);
hkuang26587cb2020-01-16 10:36:08 -0800330
Chong Zhang8e062632020-03-31 10:56:37 -0700331 status = dupClient->unregister();
332 EXPECT_TRUE(status.isOk());
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700333 EXPECT_EQ(mClientManager->getNumOfClients(), 0);
hkuang26587cb2020-01-16 10:36:08 -0800334}
335
336TEST_F(TranscodingClientManagerTest, TestAddingMultipleClient) {
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700337 addMultipleClients();
338 unregisterMultipleClients();
339}
hkuang26587cb2020-01-16 10:36:08 -0800340
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700341TEST_F(TranscodingClientManagerTest, TestSubmitCancelGetJobs) {
342 addMultipleClients();
hkuang26587cb2020-01-16 10:36:08 -0800343
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700344 // Test jobId assignment.
345 TranscodingRequestParcel request;
346 request.fileName = "test_file_0";
347 TranscodingJobParcel job;
348 bool result;
349 EXPECT_TRUE(mClient1->submitRequest(request, &job, &result).isOk());
350 EXPECT_TRUE(result);
351 EXPECT_EQ(job.jobId, 0);
hkuang26587cb2020-01-16 10:36:08 -0800352
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700353 request.fileName = "test_file_1";
354 EXPECT_TRUE(mClient1->submitRequest(request, &job, &result).isOk());
355 EXPECT_TRUE(result);
356 EXPECT_EQ(job.jobId, 1);
hkuang26587cb2020-01-16 10:36:08 -0800357
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700358 request.fileName = "test_file_2";
359 EXPECT_TRUE(mClient1->submitRequest(request, &job, &result).isOk());
360 EXPECT_TRUE(result);
361 EXPECT_EQ(job.jobId, 2);
362
363 // Test submit bad request (no valid fileName) fails.
364 TranscodingRequestParcel badRequest;
365 badRequest.fileName = "bad_file";
366 EXPECT_TRUE(mClient1->submitRequest(badRequest, &job, &result).isOk());
367 EXPECT_FALSE(result);
368
369 // Test get jobs by id.
370 EXPECT_TRUE(mClient1->getJobWithId(2, &job, &result).isOk());
371 EXPECT_EQ(job.jobId, 2);
372 EXPECT_EQ(job.request.fileName, "test_file_2");
373 EXPECT_TRUE(result);
374
375 // Test get jobs by invalid id fails.
376 EXPECT_TRUE(mClient1->getJobWithId(100, &job, &result).isOk());
377 EXPECT_FALSE(result);
378
379 // Test cancel non-existent job fail.
380 EXPECT_TRUE(mClient2->cancelJob(100, &result).isOk());
381 EXPECT_FALSE(result);
382
383 // Test cancel valid jobId in arbitrary order.
384 EXPECT_TRUE(mClient1->cancelJob(2, &result).isOk());
385 EXPECT_TRUE(result);
386
387 EXPECT_TRUE(mClient1->cancelJob(0, &result).isOk());
388 EXPECT_TRUE(result);
389
390 EXPECT_TRUE(mClient1->cancelJob(1, &result).isOk());
391 EXPECT_TRUE(result);
392
393 // Test cancel job again fails.
394 EXPECT_TRUE(mClient1->cancelJob(1, &result).isOk());
395 EXPECT_FALSE(result);
396
397 // Test get job after cancel fails.
398 EXPECT_TRUE(mClient1->getJobWithId(2, &job, &result).isOk());
399 EXPECT_FALSE(result);
400
401 // Test jobId independence for each client.
402 EXPECT_TRUE(mClient2->submitRequest(request, &job, &result).isOk());
403 EXPECT_TRUE(result);
404 EXPECT_EQ(job.jobId, 0);
405
406 EXPECT_TRUE(mClient2->submitRequest(request, &job, &result).isOk());
407 EXPECT_TRUE(result);
408 EXPECT_EQ(job.jobId, 1);
409
410 unregisterMultipleClients();
411}
412
413TEST_F(TranscodingClientManagerTest, TestClientCallback) {
414 addMultipleClients();
415
416 TranscodingRequestParcel request;
417 request.fileName = "test_file_name";
418 TranscodingJobParcel job;
419 bool result;
420 EXPECT_TRUE(mClient1->submitRequest(request, &job, &result).isOk());
421 EXPECT_TRUE(result);
422 EXPECT_EQ(job.jobId, 0);
423
424 mScheduler->finishLastJob();
425 EXPECT_EQ(mClientCallback1->popEvent(), TestClientCallback::Finished(job.jobId));
426
427 EXPECT_TRUE(mClient1->submitRequest(request, &job, &result).isOk());
428 EXPECT_TRUE(result);
429 EXPECT_EQ(job.jobId, 1);
430
431 mScheduler->abortLastJob();
432 EXPECT_EQ(mClientCallback1->popEvent(), TestClientCallback::Failed(job.jobId));
433
434 EXPECT_TRUE(mClient1->submitRequest(request, &job, &result).isOk());
435 EXPECT_TRUE(result);
436 EXPECT_EQ(job.jobId, 2);
437
438 EXPECT_TRUE(mClient2->submitRequest(request, &job, &result).isOk());
439 EXPECT_TRUE(result);
440 EXPECT_EQ(job.jobId, 0);
441
442 mScheduler->finishLastJob();
443 EXPECT_EQ(mClientCallback2->popEvent(), TestClientCallback::Finished(job.jobId));
444
445 unregisterMultipleClients();
hkuang26587cb2020-01-16 10:36:08 -0800446}
447
Chong Zhang8e062632020-03-31 10:56:37 -0700448} // namespace android