blob: d21b595a629e5cf0cd98e57a7834344b6df7d066 [file] [log] [blame]
Chong Zhang6d58e4b2020-03-31 09:41:10 -07001/*
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 TranscodingJobScheduler
18
19// #define LOG_NDEBUG 0
20#define LOG_TAG "TranscodingJobSchedulerTest"
21
22#include <aidl/android/media/BnTranscodingClientCallback.h>
23#include <aidl/android/media/IMediaTranscodingService.h>
24#include <aidl/android/media/ITranscodingClient.h>
25#include <aidl/android/media/ITranscodingClientCallback.h>
26#include <android-base/logging.h>
27#include <android/binder_manager.h>
28#include <android/binder_process.h>
29#include <gtest/gtest.h>
30#include <media/TranscodingClientManager.h>
31#include <media/TranscodingJobScheduler.h>
32#include <utils/Log.h>
33
Chong Zhangacb33502020-04-20 11:04:48 -070034#include <unordered_set>
35
Chong Zhang6d58e4b2020-03-31 09:41:10 -070036namespace android {
37
38using Status = ::ndk::ScopedAStatus;
39using aidl::android::media::BnTranscodingClientCallback;
40using aidl::android::media::IMediaTranscodingService;
41using aidl::android::media::ITranscodingClient;
Chong Zhang00feca22020-05-08 15:02:06 -070042using aidl::android::media::TranscodingRequestParcel;
Chong Zhang6d58e4b2020-03-31 09:41:10 -070043
Chong Zhang3fa408f2020-04-30 11:04:28 -070044constexpr ClientIdType kClientId = 1000;
45constexpr JobIdType kClientJobId = 0;
Chong Zhang7ae4e2f2020-04-17 15:24:34 -070046constexpr uid_t kClientUid = 5000;
47constexpr uid_t kInvalidUid = (uid_t)-1;
Chong Zhang6d58e4b2020-03-31 09:41:10 -070048
49#define CLIENT(n) (kClientId + (n))
50#define JOB(n) (kClientJobId + (n))
Chong Zhang7ae4e2f2020-04-17 15:24:34 -070051#define UID(n) (kClientUid + (n))
Chong Zhang6d58e4b2020-03-31 09:41:10 -070052
Chong Zhangacb33502020-04-20 11:04:48 -070053class TestUidPolicy : public UidPolicyInterface {
Chong Zhang6d58e4b2020-03-31 09:41:10 -070054public:
Chong Zhangacb33502020-04-20 11:04:48 -070055 TestUidPolicy() = default;
56 virtual ~TestUidPolicy() = default;
57
58 // UidPolicyInterface
59 void registerMonitorUid(uid_t /*uid*/) override {}
60 void unregisterMonitorUid(uid_t /*uid*/) override {}
61 bool isUidOnTop(uid_t uid) override { return mTopUids.count(uid) > 0; }
62 std::unordered_set<uid_t> getTopUids() const override { return mTopUids; }
63 void setCallback(const std::shared_ptr<UidPolicyCallbackInterface>& cb) override {
64 mUidPolicyCallback = cb;
65 }
66 void setTop(uid_t uid) {
67 std::unordered_set<uid_t> uids = {uid};
68 setTop(uids);
69 }
70 void setTop(const std::unordered_set<uid_t>& uids) {
71 mTopUids = uids;
72 auto uidPolicyCb = mUidPolicyCallback.lock();
73 if (uidPolicyCb != nullptr) {
74 uidPolicyCb->onTopUidsChanged(mTopUids);
75 }
76 }
77
78 std::unordered_set<uid_t> mTopUids;
79 std::weak_ptr<UidPolicyCallbackInterface> mUidPolicyCallback;
80};
81
82class TestTranscoder : public TranscoderInterface {
83public:
84 TestTranscoder() : mLastError(TranscodingErrorCode::kUnknown) {}
85 virtual ~TestTranscoder() {}
Chong Zhang6d58e4b2020-03-31 09:41:10 -070086
87 // TranscoderInterface
Chong Zhang75222182020-04-29 14:43:42 -070088 void setCallback(const std::shared_ptr<TranscoderCallbackInterface>& /*cb*/) override {}
89
Chong Zhang66469272020-06-04 16:51:55 -070090 void start(ClientIdType clientId, JobIdType jobId, const TranscodingRequestParcel& /*request*/,
91 const std::shared_ptr<ITranscodingClientCallback>& /*clientCallback*/) override {
Chong Zhang6d58e4b2020-03-31 09:41:10 -070092 mEventQueue.push_back(Start(clientId, jobId));
93 }
Chong Zhang3fa408f2020-04-30 11:04:28 -070094 void pause(ClientIdType clientId, JobIdType jobId) override {
Chong Zhang6d58e4b2020-03-31 09:41:10 -070095 mEventQueue.push_back(Pause(clientId, jobId));
96 }
Chong Zhangb55c5452020-06-26 14:32:12 -070097 void resume(ClientIdType clientId, JobIdType jobId, const TranscodingRequestParcel& /*request*/,
98 const std::shared_ptr<ITranscodingClientCallback>& /*clientCallback*/) override {
Chong Zhang6d58e4b2020-03-31 09:41:10 -070099 mEventQueue.push_back(Resume(clientId, jobId));
100 }
Chong Zhang00feca22020-05-08 15:02:06 -0700101 void stop(ClientIdType clientId, JobIdType jobId) override {
102 mEventQueue.push_back(Stop(clientId, jobId));
103 }
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700104
Chong Zhang3fa408f2020-04-30 11:04:28 -0700105 void onFinished(ClientIdType clientId, JobIdType jobId) {
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700106 mEventQueue.push_back(Finished(clientId, jobId));
107 }
108
Chong Zhang3fa408f2020-04-30 11:04:28 -0700109 void onFailed(ClientIdType clientId, JobIdType jobId, TranscodingErrorCode err) {
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700110 mLastError = err;
111 mEventQueue.push_back(Failed(clientId, jobId));
112 }
113
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700114 TranscodingErrorCode getLastError() {
115 TranscodingErrorCode result = mLastError;
116 mLastError = TranscodingErrorCode::kUnknown;
117 return result;
118 }
119
120 struct Event {
Chong Zhang00feca22020-05-08 15:02:06 -0700121 enum { NoEvent, Start, Pause, Resume, Stop, Finished, Failed } type;
Chong Zhang3fa408f2020-04-30 11:04:28 -0700122 ClientIdType clientId;
123 JobIdType jobId;
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700124 };
125
126 static constexpr Event NoEvent = {Event::NoEvent, 0, 0};
127
Chong Zhang3fa408f2020-04-30 11:04:28 -0700128#define DECLARE_EVENT(action) \
129 static Event action(ClientIdType clientId, JobIdType jobId) { \
130 return {Event::action, clientId, jobId}; \
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700131 }
132
133 DECLARE_EVENT(Start);
134 DECLARE_EVENT(Pause);
135 DECLARE_EVENT(Resume);
Chong Zhang00feca22020-05-08 15:02:06 -0700136 DECLARE_EVENT(Stop);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700137 DECLARE_EVENT(Finished);
138 DECLARE_EVENT(Failed);
139
140 const Event& popEvent() {
141 if (mEventQueue.empty()) {
142 mPoppedEvent = NoEvent;
143 } else {
144 mPoppedEvent = *mEventQueue.begin();
145 mEventQueue.pop_front();
146 }
147 return mPoppedEvent;
148 }
149
150private:
151 Event mPoppedEvent;
152 std::list<Event> mEventQueue;
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700153 TranscodingErrorCode mLastError;
154};
155
Chong Zhangacb33502020-04-20 11:04:48 -0700156bool operator==(const TestTranscoder::Event& lhs, const TestTranscoder::Event& rhs) {
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700157 return lhs.type == rhs.type && lhs.clientId == rhs.clientId && lhs.jobId == rhs.jobId;
158}
159
160struct TestClientCallback : public BnTranscodingClientCallback {
Chong Zhangacb33502020-04-20 11:04:48 -0700161 TestClientCallback(TestTranscoder* owner, int64_t clientId)
162 : mOwner(owner), mClientId(clientId) {
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700163 ALOGD("TestClient Created");
164 }
165
hkuang19253092020-06-01 09:10:49 -0700166 Status openFileDescriptor(const std::string& /*in_fileUri*/, const std::string& /*in_mode*/,
167 ::ndk::ScopedFileDescriptor* /*_aidl_return*/) override {
168 return Status::ok();
169 }
170
hkuang96471b82020-06-08 11:12:46 -0700171 Status onTranscodingStarted(int32_t /*in_jobId*/) override { return Status::ok(); }
172
173 Status onTranscodingPaused(int32_t /*in_jobId*/) override { return Status::ok(); }
174
175 Status onTranscodingResumed(int32_t /*in_jobId*/) override { return Status::ok(); }
176
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700177 Status onTranscodingFinished(int32_t in_jobId,
178 const TranscodingResultParcel& in_result) override {
179 EXPECT_EQ(in_jobId, in_result.jobId);
Chong Zhang75222182020-04-29 14:43:42 -0700180 ALOGD("TestClientCallback: received onTranscodingFinished");
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700181 mOwner->onFinished(mClientId, in_jobId);
182 return Status::ok();
183 }
184
185 Status onTranscodingFailed(int32_t in_jobId, TranscodingErrorCode in_errorCode) override {
186 mOwner->onFailed(mClientId, in_jobId, in_errorCode);
187 return Status::ok();
188 }
189
190 Status onAwaitNumberOfJobsChanged(int32_t /* in_jobId */, int32_t /* in_oldAwaitNumber */,
191 int32_t /* in_newAwaitNumber */) override {
192 return Status::ok();
193 }
194
195 Status onProgressUpdate(int32_t /* in_jobId */, int32_t /* in_progress */) override {
196 return Status::ok();
197 }
198
199 virtual ~TestClientCallback() { ALOGI("TestClient destroyed"); };
200
201private:
Chong Zhangacb33502020-04-20 11:04:48 -0700202 TestTranscoder* mOwner;
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700203 int64_t mClientId;
204 TestClientCallback(const TestClientCallback&) = delete;
205 TestClientCallback& operator=(const TestClientCallback&) = delete;
206};
207
208class TranscodingJobSchedulerTest : public ::testing::Test {
209public:
210 TranscodingJobSchedulerTest() { ALOGI("TranscodingJobSchedulerTest created"); }
211
212 void SetUp() override {
213 ALOGI("TranscodingJobSchedulerTest set up");
Chong Zhangacb33502020-04-20 11:04:48 -0700214 mTranscoder.reset(new TestTranscoder());
215 mUidPolicy.reset(new TestUidPolicy());
216 mScheduler.reset(new TranscodingJobScheduler(mTranscoder, mUidPolicy));
217 mUidPolicy->setCallback(mScheduler);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700218
219 // Set priority only, ignore other fields for now.
220 mOfflineRequest.priority = TranscodingJobPriority::kUnspecified;
221 mRealtimeRequest.priority = TranscodingJobPriority::kHigh;
222 mClientCallback0 =
Chong Zhangacb33502020-04-20 11:04:48 -0700223 ::ndk::SharedRefBase::make<TestClientCallback>(mTranscoder.get(), CLIENT(0));
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700224 mClientCallback1 =
Chong Zhangacb33502020-04-20 11:04:48 -0700225 ::ndk::SharedRefBase::make<TestClientCallback>(mTranscoder.get(), CLIENT(1));
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700226 mClientCallback2 =
Chong Zhangacb33502020-04-20 11:04:48 -0700227 ::ndk::SharedRefBase::make<TestClientCallback>(mTranscoder.get(), CLIENT(2));
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700228 mClientCallback3 =
Chong Zhangacb33502020-04-20 11:04:48 -0700229 ::ndk::SharedRefBase::make<TestClientCallback>(mTranscoder.get(), CLIENT(3));
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700230 }
231
232 void TearDown() override { ALOGI("TranscodingJobSchedulerTest tear down"); }
233
234 ~TranscodingJobSchedulerTest() { ALOGD("TranscodingJobSchedulerTest destroyed"); }
235
Chong Zhangacb33502020-04-20 11:04:48 -0700236 std::shared_ptr<TestTranscoder> mTranscoder;
237 std::shared_ptr<TestUidPolicy> mUidPolicy;
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700238 std::shared_ptr<TranscodingJobScheduler> mScheduler;
239 TranscodingRequestParcel mOfflineRequest;
240 TranscodingRequestParcel mRealtimeRequest;
241 std::shared_ptr<TestClientCallback> mClientCallback0;
242 std::shared_ptr<TestClientCallback> mClientCallback1;
243 std::shared_ptr<TestClientCallback> mClientCallback2;
244 std::shared_ptr<TestClientCallback> mClientCallback3;
245};
246
247TEST_F(TranscodingJobSchedulerTest, TestSubmitJob) {
248 ALOGD("TestSubmitJob");
249
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700250 // Start with UID(1) on top.
Chong Zhangacb33502020-04-20 11:04:48 -0700251 mUidPolicy->setTop(UID(1));
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700252
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700253 // Submit offline job to CLIENT(0) in UID(0).
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700254 // Should start immediately (because this is the only job).
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700255 mScheduler->submit(CLIENT(0), JOB(0), UID(0), mOfflineRequest, mClientCallback0);
Chong Zhangacb33502020-04-20 11:04:48 -0700256 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), 0));
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700257
258 // Submit real-time job to CLIENT(0).
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700259 // Should pause offline job and start new job, even if UID(0) is not on top.
260 mScheduler->submit(CLIENT(0), JOB(1), UID(0), mRealtimeRequest, mClientCallback0);
Chong Zhangacb33502020-04-20 11:04:48 -0700261 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(0), JOB(0)));
262 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), JOB(1)));
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700263
264 // Submit real-time job to CLIENT(0), should be queued after the previous job.
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700265 mScheduler->submit(CLIENT(0), JOB(2), UID(0), mRealtimeRequest, mClientCallback0);
Chong Zhangacb33502020-04-20 11:04:48 -0700266 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700267
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700268 // Submit real-time job to CLIENT(1) in same uid, should be queued after the previous job.
269 mScheduler->submit(CLIENT(1), JOB(0), UID(0), mRealtimeRequest, mClientCallback1);
Chong Zhangacb33502020-04-20 11:04:48 -0700270 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700271
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700272 // Submit real-time job to CLIENT(2) in UID(1).
Chong Zhangacb33502020-04-20 11:04:48 -0700273 // Should pause previous job and start new job, because UID(1) is (has been) top.
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700274 mScheduler->submit(CLIENT(2), JOB(0), UID(1), mRealtimeRequest, mClientCallback2);
Chong Zhangacb33502020-04-20 11:04:48 -0700275 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(0), JOB(1)));
276 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(2), JOB(0)));
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700277
278 // Submit offline job, shouldn't generate any event.
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700279 mScheduler->submit(CLIENT(2), JOB(1), UID(1), mOfflineRequest, mClientCallback2);
Chong Zhangacb33502020-04-20 11:04:48 -0700280 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700281
Chong Zhangacb33502020-04-20 11:04:48 -0700282 // Bring UID(0) to top.
283 mUidPolicy->setTop(UID(0));
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700284 // Should pause current job, and resume last job in UID(0).
Chong Zhangacb33502020-04-20 11:04:48 -0700285 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(2), JOB(0)));
286 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(0), JOB(1)));
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700287}
288
289TEST_F(TranscodingJobSchedulerTest, TestCancelJob) {
290 ALOGD("TestCancelJob");
291
292 // Submit real-time job JOB(0), should start immediately.
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700293 mScheduler->submit(CLIENT(0), JOB(0), UID(0), mRealtimeRequest, mClientCallback0);
Chong Zhangacb33502020-04-20 11:04:48 -0700294 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), JOB(0)));
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700295
296 // Submit real-time job JOB(1), should not start.
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700297 mScheduler->submit(CLIENT(0), JOB(1), UID(0), mRealtimeRequest, mClientCallback0);
Chong Zhangacb33502020-04-20 11:04:48 -0700298 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700299
300 // Submit offline job JOB(2), should not start.
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700301 mScheduler->submit(CLIENT(0), JOB(2), UID(0), mOfflineRequest, mClientCallback0);
Chong Zhangacb33502020-04-20 11:04:48 -0700302 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700303
304 // Cancel queued real-time job.
305 // Cancel real-time job JOB(1), should be cancelled.
306 EXPECT_TRUE(mScheduler->cancel(CLIENT(0), JOB(1)));
307
308 // Cancel queued offline job.
309 // Cancel offline job JOB(2), should be cancelled.
310 EXPECT_TRUE(mScheduler->cancel(CLIENT(0), JOB(2)));
311
312 // Submit offline job JOB(3), shouldn't cause any event.
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700313 mScheduler->submit(CLIENT(0), JOB(3), UID(0), mOfflineRequest, mClientCallback0);
Chong Zhangacb33502020-04-20 11:04:48 -0700314 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700315
316 // Cancel running real-time job JOB(0).
Chong Zhang00feca22020-05-08 15:02:06 -0700317 // - Should be stopped first then cancelled.
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700318 // - Should also start offline job JOB(2) because real-time queue is empty.
319 EXPECT_TRUE(mScheduler->cancel(CLIENT(0), JOB(0)));
Chong Zhang00feca22020-05-08 15:02:06 -0700320 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Stop(CLIENT(0), JOB(0)));
Chong Zhangacb33502020-04-20 11:04:48 -0700321 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), JOB(3)));
Chong Zhang00feca22020-05-08 15:02:06 -0700322
323 // Submit real-time job JOB(4), offline JOB(3) should pause and JOB(4) should start.
324 mScheduler->submit(CLIENT(0), JOB(4), UID(0), mRealtimeRequest, mClientCallback0);
325 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(0), JOB(3)));
326 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), JOB(4)));
327
328 // Cancel paused JOB(3). JOB(3) should be stopped.
329 EXPECT_TRUE(mScheduler->cancel(CLIENT(0), JOB(3)));
330 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Stop(CLIENT(0), JOB(3)));
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700331}
332
333TEST_F(TranscodingJobSchedulerTest, TestFinishJob) {
334 ALOGD("TestFinishJob");
335
Chong Zhangacb33502020-04-20 11:04:48 -0700336 // Start with unspecified top UID.
337 // Finish without any jobs submitted, should be ignored.
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700338 mScheduler->onFinish(CLIENT(0), JOB(0));
Chong Zhangacb33502020-04-20 11:04:48 -0700339 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700340
341 // Submit offline job JOB(0), should start immediately.
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700342 mScheduler->submit(CLIENT(0), JOB(0), UID(0), mOfflineRequest, mClientCallback0);
Chong Zhangacb33502020-04-20 11:04:48 -0700343 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), JOB(0)));
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700344
345 // Submit real-time job JOB(1), should pause offline job and start immediately.
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700346 mScheduler->submit(CLIENT(0), JOB(1), UID(0), mRealtimeRequest, mClientCallback0);
Chong Zhangacb33502020-04-20 11:04:48 -0700347 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(0), JOB(0)));
348 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), JOB(1)));
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700349
350 // Submit real-time job JOB(2), should not start.
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700351 mScheduler->submit(CLIENT(0), JOB(2), UID(0), mRealtimeRequest, mClientCallback0);
Chong Zhangacb33502020-04-20 11:04:48 -0700352 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700353
Chong Zhangacb33502020-04-20 11:04:48 -0700354 // Finish when the job never started, should be ignored.
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700355 mScheduler->onFinish(CLIENT(0), JOB(2));
Chong Zhangacb33502020-04-20 11:04:48 -0700356 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700357
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700358 // UID(1) moves to top.
Chong Zhangacb33502020-04-20 11:04:48 -0700359 mUidPolicy->setTop(UID(1));
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700360 // Submit real-time job to CLIENT(1) in UID(1), should pause previous job and start new job.
361 mScheduler->submit(CLIENT(1), JOB(0), UID(1), mRealtimeRequest, mClientCallback1);
Chong Zhangacb33502020-04-20 11:04:48 -0700362 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(0), JOB(1)));
363 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(1), JOB(0)));
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700364
Chong Zhangacb33502020-04-20 11:04:48 -0700365 // Simulate Finish that arrived late, after pause issued by scheduler.
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700366 // Should still be propagated to client, but shouldn't trigger any new start.
367 mScheduler->onFinish(CLIENT(0), JOB(1));
Chong Zhangacb33502020-04-20 11:04:48 -0700368 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Finished(CLIENT(0), JOB(1)));
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700369
Chong Zhangacb33502020-04-20 11:04:48 -0700370 // Finish running real-time job, should start next real-time job in queue.
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700371 mScheduler->onFinish(CLIENT(1), JOB(0));
Chong Zhangacb33502020-04-20 11:04:48 -0700372 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Finished(CLIENT(1), JOB(0)));
373 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), JOB(2)));
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700374
Chong Zhangacb33502020-04-20 11:04:48 -0700375 // Finish running real-time job, should resume next job (offline job) in queue.
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700376 mScheduler->onFinish(CLIENT(0), JOB(2));
Chong Zhangacb33502020-04-20 11:04:48 -0700377 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Finished(CLIENT(0), JOB(2)));
378 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(0), JOB(0)));
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700379
Chong Zhangacb33502020-04-20 11:04:48 -0700380 // Finish running offline job.
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700381 mScheduler->onFinish(CLIENT(0), JOB(0));
Chong Zhangacb33502020-04-20 11:04:48 -0700382 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Finished(CLIENT(0), JOB(0)));
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700383
Chong Zhangacb33502020-04-20 11:04:48 -0700384 // Duplicate finish for last job, should be ignored.
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700385 mScheduler->onFinish(CLIENT(0), JOB(0));
Chong Zhangacb33502020-04-20 11:04:48 -0700386 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700387}
388
389TEST_F(TranscodingJobSchedulerTest, TestFailJob) {
390 ALOGD("TestFailJob");
391
Chong Zhangacb33502020-04-20 11:04:48 -0700392 // Start with unspecified top UID.
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700393 // Fail without any jobs submitted, should be ignored.
394 mScheduler->onError(CLIENT(0), JOB(0), TranscodingErrorCode::kUnknown);
Chong Zhangacb33502020-04-20 11:04:48 -0700395 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700396
397 // Submit offline job JOB(0), should start immediately.
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700398 mScheduler->submit(CLIENT(0), JOB(0), UID(0), mOfflineRequest, mClientCallback0);
Chong Zhangacb33502020-04-20 11:04:48 -0700399 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), JOB(0)));
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700400
401 // Submit real-time job JOB(1), should pause offline job and start immediately.
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700402 mScheduler->submit(CLIENT(0), JOB(1), UID(0), mRealtimeRequest, mClientCallback0);
Chong Zhangacb33502020-04-20 11:04:48 -0700403 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(0), JOB(0)));
404 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), JOB(1)));
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700405
406 // Submit real-time job JOB(2), should not start.
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700407 mScheduler->submit(CLIENT(0), JOB(2), UID(0), mRealtimeRequest, mClientCallback0);
Chong Zhangacb33502020-04-20 11:04:48 -0700408 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700409
410 // Fail when the job never started, should be ignored.
411 mScheduler->onError(CLIENT(0), JOB(2), TranscodingErrorCode::kUnknown);
Chong Zhangacb33502020-04-20 11:04:48 -0700412 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700413
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700414 // UID(1) moves to top.
Chong Zhangacb33502020-04-20 11:04:48 -0700415 mUidPolicy->setTop(UID(1));
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700416 // Submit real-time job to CLIENT(1) in UID(1), should pause previous job and start new job.
417 mScheduler->submit(CLIENT(1), JOB(0), UID(1), mRealtimeRequest, mClientCallback1);
Chong Zhangacb33502020-04-20 11:04:48 -0700418 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(0), JOB(1)));
419 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(1), JOB(0)));
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700420
421 // Simulate Fail that arrived late, after pause issued by scheduler.
422 // Should still be propagated to client, but shouldn't trigger any new start.
423 mScheduler->onError(CLIENT(0), JOB(1), TranscodingErrorCode::kUnknown);
Chong Zhangacb33502020-04-20 11:04:48 -0700424 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Failed(CLIENT(0), JOB(1)));
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700425
426 // Fail running real-time job, should start next real-time job in queue.
427 mScheduler->onError(CLIENT(1), JOB(0), TranscodingErrorCode::kUnknown);
Chong Zhangacb33502020-04-20 11:04:48 -0700428 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Failed(CLIENT(1), JOB(0)));
429 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), JOB(2)));
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700430
431 // Fail running real-time job, should resume next job (offline job) in queue.
432 mScheduler->onError(CLIENT(0), JOB(2), TranscodingErrorCode::kUnknown);
Chong Zhangacb33502020-04-20 11:04:48 -0700433 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Failed(CLIENT(0), JOB(2)));
434 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(0), JOB(0)));
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700435
436 // Fail running offline job, and test error code propagation.
Chong Zhang66469272020-06-04 16:51:55 -0700437 mScheduler->onError(CLIENT(0), JOB(0), TranscodingErrorCode::kInvalidOperation);
Chong Zhangacb33502020-04-20 11:04:48 -0700438 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Failed(CLIENT(0), JOB(0)));
Chong Zhang66469272020-06-04 16:51:55 -0700439 EXPECT_EQ(mTranscoder->getLastError(), TranscodingErrorCode::kInvalidOperation);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700440
441 // Duplicate fail for last job, should be ignored.
442 mScheduler->onError(CLIENT(0), JOB(0), TranscodingErrorCode::kUnknown);
Chong Zhangacb33502020-04-20 11:04:48 -0700443 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700444}
445
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700446TEST_F(TranscodingJobSchedulerTest, TestTopUidChanged) {
447 ALOGD("TestTopUidChanged");
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700448
Chong Zhangacb33502020-04-20 11:04:48 -0700449 // Start with unspecified top UID.
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700450 // Submit real-time job to CLIENT(0), job should start immediately.
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700451 mScheduler->submit(CLIENT(0), JOB(0), UID(0), mRealtimeRequest, mClientCallback0);
Chong Zhangacb33502020-04-20 11:04:48 -0700452 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), JOB(0)));
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700453
454 // Submit offline job to CLIENT(0), should not start.
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700455 mScheduler->submit(CLIENT(1), JOB(0), UID(0), mOfflineRequest, mClientCallback1);
Chong Zhangacb33502020-04-20 11:04:48 -0700456 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700457
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700458 // Move UID(1) to top.
Chong Zhangacb33502020-04-20 11:04:48 -0700459 mUidPolicy->setTop(UID(1));
460 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
461
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700462 // Submit real-time job to CLIENT(2) in different uid UID(1).
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700463 // Should pause previous job and start new job.
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700464 mScheduler->submit(CLIENT(2), JOB(0), UID(1), mRealtimeRequest, mClientCallback2);
Chong Zhangacb33502020-04-20 11:04:48 -0700465 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(0), JOB(0)));
466 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(2), JOB(0)));
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700467
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700468 // Bring UID(0) back to top.
Chong Zhangacb33502020-04-20 11:04:48 -0700469 mUidPolicy->setTop(UID(0));
470 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(2), JOB(0)));
471 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(0), JOB(0)));
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700472
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700473 // Bring invalid uid to top.
Chong Zhangacb33502020-04-20 11:04:48 -0700474 mUidPolicy->setTop(kInvalidUid);
475 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700476
477 // Finish job, next real-time job should resume.
478 mScheduler->onFinish(CLIENT(0), JOB(0));
Chong Zhangacb33502020-04-20 11:04:48 -0700479 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Finished(CLIENT(0), JOB(0)));
480 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(2), JOB(0)));
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700481
482 // Finish job, offline job should start.
483 mScheduler->onFinish(CLIENT(2), JOB(0));
Chong Zhangacb33502020-04-20 11:04:48 -0700484 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Finished(CLIENT(2), JOB(0)));
485 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(1), JOB(0)));
486}
487
488TEST_F(TranscodingJobSchedulerTest, TestTopUidSetChanged) {
489 ALOGD("TestTopUidChanged_MultipleUids");
490
491 // Start with unspecified top UID.
492 // Submit real-time job to CLIENT(0), job should start immediately.
493 mScheduler->submit(CLIENT(0), JOB(0), UID(0), mRealtimeRequest, mClientCallback0);
494 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), JOB(0)));
495
496 // Submit offline job to CLIENT(0), should not start.
497 mScheduler->submit(CLIENT(1), JOB(0), UID(0), mOfflineRequest, mClientCallback1);
498 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
499
500 // Set UID(0), UID(1) to top set.
501 // UID(0) should continue to run.
502 mUidPolicy->setTop({UID(0), UID(1)});
503 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
504
505 // Submit real-time job to CLIENT(2) in different uid UID(1).
506 // UID(0) should pause and UID(1) should start.
507 mScheduler->submit(CLIENT(2), JOB(0), UID(1), mRealtimeRequest, mClientCallback2);
508 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(0), JOB(0)));
509 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(2), JOB(0)));
510
511 // Remove UID(0) from top set, and only leave UID(1) in the set.
512 // UID(1) should continue to run.
513 mUidPolicy->setTop(UID(1));
514 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
515
516 // Set UID(0), UID(2) to top set.
517 // UID(1) should continue to run.
518 mUidPolicy->setTop({UID(1), UID(2)});
519 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
520
521 // Bring UID(0) back to top.
522 mUidPolicy->setTop(UID(0));
523 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(2), JOB(0)));
524 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(0), JOB(0)));
525
526 // Bring invalid uid to top.
527 mUidPolicy->setTop(kInvalidUid);
528 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
529
530 // Finish job, next real-time job from UID(1) should resume, even if UID(1) no longer top.
531 mScheduler->onFinish(CLIENT(0), JOB(0));
532 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Finished(CLIENT(0), JOB(0)));
533 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(2), JOB(0)));
534
535 // Finish job, offline job should start.
536 mScheduler->onFinish(CLIENT(2), JOB(0));
537 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Finished(CLIENT(2), JOB(0)));
538 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(1), JOB(0)));
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700539}
540
541TEST_F(TranscodingJobSchedulerTest, TestResourceLost) {
542 ALOGD("TestResourceLost");
543
Chong Zhangacb33502020-04-20 11:04:48 -0700544 // Start with unspecified top UID.
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700545 // Submit real-time job to CLIENT(0), job should start immediately.
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700546 mScheduler->submit(CLIENT(0), JOB(0), UID(0), mRealtimeRequest, mClientCallback0);
Chong Zhangacb33502020-04-20 11:04:48 -0700547 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), JOB(0)));
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700548
549 // Submit offline job to CLIENT(0), should not start.
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700550 mScheduler->submit(CLIENT(1), JOB(0), UID(0), mOfflineRequest, mClientCallback1);
Chong Zhangacb33502020-04-20 11:04:48 -0700551 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700552
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700553 // Move UID(1) to top.
Chong Zhangacb33502020-04-20 11:04:48 -0700554 mUidPolicy->setTop(UID(1));
555 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700556
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700557 // Submit real-time job to CLIENT(2) in different uid UID(1).
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700558 // Should pause previous job and start new job.
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700559 mScheduler->submit(CLIENT(2), JOB(0), UID(1), mRealtimeRequest, mClientCallback2);
Chong Zhangacb33502020-04-20 11:04:48 -0700560 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(0), JOB(0)));
561 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(2), JOB(0)));
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700562
563 // Test 1: No queue change during resource loss.
564 // Signal resource lost.
565 mScheduler->onResourceLost();
Chong Zhangacb33502020-04-20 11:04:48 -0700566 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700567
568 // Signal resource available, CLIENT(2) should resume.
569 mScheduler->onResourceAvailable();
Chong Zhangacb33502020-04-20 11:04:48 -0700570 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(2), JOB(0)));
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700571
572 // Test 2: Change of queue order during resource loss.
573 // Signal resource lost.
574 mScheduler->onResourceLost();
Chong Zhangacb33502020-04-20 11:04:48 -0700575 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700576
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700577 // Move UID(0) back to top, should have no resume due to no resource.
Chong Zhangacb33502020-04-20 11:04:48 -0700578 mUidPolicy->setTop(UID(0));
579 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700580
581 // Signal resource available, CLIENT(0) should resume.
582 mScheduler->onResourceAvailable();
Chong Zhangacb33502020-04-20 11:04:48 -0700583 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(0), JOB(0)));
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700584
585 // Test 3: Adding new queue during resource loss.
586 // Signal resource lost.
587 mScheduler->onResourceLost();
Chong Zhangacb33502020-04-20 11:04:48 -0700588 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700589
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700590 // Move UID(2) to top.
Chong Zhangacb33502020-04-20 11:04:48 -0700591 mUidPolicy->setTop(UID(2));
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700592
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700593 // Submit real-time job to CLIENT(3) in UID(2), job shouldn't start due to no resource.
594 mScheduler->submit(CLIENT(3), JOB(0), UID(2), mRealtimeRequest, mClientCallback3);
Chong Zhangacb33502020-04-20 11:04:48 -0700595 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700596
597 // Signal resource available, CLIENT(3)'s job should start.
598 mScheduler->onResourceAvailable();
Chong Zhangacb33502020-04-20 11:04:48 -0700599 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(3), JOB(0)));
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700600}
601
602} // namespace android