blob: 9b9df8760387fa1dcb14140e1b5e8bbc0bfd824c [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());
Chong Zhangf9077512020-09-21 21:02:06 -0700216 mScheduler.reset(
217 new TranscodingJobScheduler(mTranscoder, mUidPolicy, nullptr /*resourcePolicy*/));
Chong Zhangacb33502020-04-20 11:04:48 -0700218 mUidPolicy->setCallback(mScheduler);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700219
220 // Set priority only, ignore other fields for now.
221 mOfflineRequest.priority = TranscodingJobPriority::kUnspecified;
222 mRealtimeRequest.priority = TranscodingJobPriority::kHigh;
223 mClientCallback0 =
Chong Zhangacb33502020-04-20 11:04:48 -0700224 ::ndk::SharedRefBase::make<TestClientCallback>(mTranscoder.get(), CLIENT(0));
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700225 mClientCallback1 =
Chong Zhangacb33502020-04-20 11:04:48 -0700226 ::ndk::SharedRefBase::make<TestClientCallback>(mTranscoder.get(), CLIENT(1));
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700227 mClientCallback2 =
Chong Zhangacb33502020-04-20 11:04:48 -0700228 ::ndk::SharedRefBase::make<TestClientCallback>(mTranscoder.get(), CLIENT(2));
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700229 mClientCallback3 =
Chong Zhangacb33502020-04-20 11:04:48 -0700230 ::ndk::SharedRefBase::make<TestClientCallback>(mTranscoder.get(), CLIENT(3));
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700231 }
232
233 void TearDown() override { ALOGI("TranscodingJobSchedulerTest tear down"); }
234
235 ~TranscodingJobSchedulerTest() { ALOGD("TranscodingJobSchedulerTest destroyed"); }
236
Chong Zhangacb33502020-04-20 11:04:48 -0700237 std::shared_ptr<TestTranscoder> mTranscoder;
238 std::shared_ptr<TestUidPolicy> mUidPolicy;
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700239 std::shared_ptr<TranscodingJobScheduler> mScheduler;
240 TranscodingRequestParcel mOfflineRequest;
241 TranscodingRequestParcel mRealtimeRequest;
242 std::shared_ptr<TestClientCallback> mClientCallback0;
243 std::shared_ptr<TestClientCallback> mClientCallback1;
244 std::shared_ptr<TestClientCallback> mClientCallback2;
245 std::shared_ptr<TestClientCallback> mClientCallback3;
246};
247
248TEST_F(TranscodingJobSchedulerTest, TestSubmitJob) {
249 ALOGD("TestSubmitJob");
250
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700251 // Start with UID(1) on top.
Chong Zhangacb33502020-04-20 11:04:48 -0700252 mUidPolicy->setTop(UID(1));
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700253
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700254 // Submit offline job to CLIENT(0) in UID(0).
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700255 // Should start immediately (because this is the only job).
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700256 mScheduler->submit(CLIENT(0), JOB(0), UID(0), mOfflineRequest, mClientCallback0);
Chong Zhangacb33502020-04-20 11:04:48 -0700257 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), 0));
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700258
259 // Submit real-time job to CLIENT(0).
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700260 // Should pause offline job and start new job, even if UID(0) is not on top.
261 mScheduler->submit(CLIENT(0), JOB(1), UID(0), mRealtimeRequest, mClientCallback0);
Chong Zhangacb33502020-04-20 11:04:48 -0700262 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(0), JOB(0)));
263 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), JOB(1)));
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700264
265 // Submit real-time job to CLIENT(0), should be queued after the previous job.
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700266 mScheduler->submit(CLIENT(0), JOB(2), UID(0), mRealtimeRequest, mClientCallback0);
Chong Zhangacb33502020-04-20 11:04:48 -0700267 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700268
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700269 // Submit real-time job to CLIENT(1) in same uid, should be queued after the previous job.
270 mScheduler->submit(CLIENT(1), JOB(0), UID(0), mRealtimeRequest, mClientCallback1);
Chong Zhangacb33502020-04-20 11:04:48 -0700271 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700272
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700273 // Submit real-time job to CLIENT(2) in UID(1).
Chong Zhangacb33502020-04-20 11:04:48 -0700274 // Should pause previous job and start new job, because UID(1) is (has been) top.
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700275 mScheduler->submit(CLIENT(2), JOB(0), UID(1), mRealtimeRequest, mClientCallback2);
Chong Zhangacb33502020-04-20 11:04:48 -0700276 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(0), JOB(1)));
277 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(2), JOB(0)));
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700278
279 // Submit offline job, shouldn't generate any event.
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700280 mScheduler->submit(CLIENT(2), JOB(1), UID(1), mOfflineRequest, mClientCallback2);
Chong Zhangacb33502020-04-20 11:04:48 -0700281 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700282
Chong Zhangacb33502020-04-20 11:04:48 -0700283 // Bring UID(0) to top.
284 mUidPolicy->setTop(UID(0));
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700285 // Should pause current job, and resume last job in UID(0).
Chong Zhangacb33502020-04-20 11:04:48 -0700286 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(2), JOB(0)));
287 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(0), JOB(1)));
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700288}
289
290TEST_F(TranscodingJobSchedulerTest, TestCancelJob) {
291 ALOGD("TestCancelJob");
292
293 // Submit real-time job JOB(0), should start immediately.
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700294 mScheduler->submit(CLIENT(0), JOB(0), UID(0), mRealtimeRequest, mClientCallback0);
Chong Zhangacb33502020-04-20 11:04:48 -0700295 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), JOB(0)));
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700296
297 // Submit real-time job JOB(1), should not start.
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700298 mScheduler->submit(CLIENT(0), JOB(1), UID(0), mRealtimeRequest, mClientCallback0);
Chong Zhangacb33502020-04-20 11:04:48 -0700299 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700300
301 // Submit offline job JOB(2), should not start.
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700302 mScheduler->submit(CLIENT(0), JOB(2), UID(0), mOfflineRequest, mClientCallback0);
Chong Zhangacb33502020-04-20 11:04:48 -0700303 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700304
305 // Cancel queued real-time job.
306 // Cancel real-time job JOB(1), should be cancelled.
307 EXPECT_TRUE(mScheduler->cancel(CLIENT(0), JOB(1)));
308
309 // Cancel queued offline job.
310 // Cancel offline job JOB(2), should be cancelled.
311 EXPECT_TRUE(mScheduler->cancel(CLIENT(0), JOB(2)));
312
313 // Submit offline job JOB(3), shouldn't cause any event.
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700314 mScheduler->submit(CLIENT(0), JOB(3), UID(0), mOfflineRequest, mClientCallback0);
Chong Zhangacb33502020-04-20 11:04:48 -0700315 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700316
317 // Cancel running real-time job JOB(0).
Chong Zhang00feca22020-05-08 15:02:06 -0700318 // - Should be stopped first then cancelled.
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700319 // - Should also start offline job JOB(2) because real-time queue is empty.
320 EXPECT_TRUE(mScheduler->cancel(CLIENT(0), JOB(0)));
Chong Zhang00feca22020-05-08 15:02:06 -0700321 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Stop(CLIENT(0), JOB(0)));
Chong Zhangacb33502020-04-20 11:04:48 -0700322 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), JOB(3)));
Chong Zhang00feca22020-05-08 15:02:06 -0700323
324 // Submit real-time job JOB(4), offline JOB(3) should pause and JOB(4) should start.
325 mScheduler->submit(CLIENT(0), JOB(4), UID(0), mRealtimeRequest, mClientCallback0);
326 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(0), JOB(3)));
327 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), JOB(4)));
328
329 // Cancel paused JOB(3). JOB(3) should be stopped.
330 EXPECT_TRUE(mScheduler->cancel(CLIENT(0), JOB(3)));
331 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Stop(CLIENT(0), JOB(3)));
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700332}
333
334TEST_F(TranscodingJobSchedulerTest, TestFinishJob) {
335 ALOGD("TestFinishJob");
336
Chong Zhangacb33502020-04-20 11:04:48 -0700337 // Start with unspecified top UID.
338 // Finish without any jobs submitted, should be ignored.
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700339 mScheduler->onFinish(CLIENT(0), JOB(0));
Chong Zhangacb33502020-04-20 11:04:48 -0700340 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700341
342 // Submit offline job JOB(0), should start immediately.
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700343 mScheduler->submit(CLIENT(0), JOB(0), UID(0), mOfflineRequest, mClientCallback0);
Chong Zhangacb33502020-04-20 11:04:48 -0700344 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), JOB(0)));
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700345
346 // Submit real-time job JOB(1), should pause offline job and start immediately.
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700347 mScheduler->submit(CLIENT(0), JOB(1), UID(0), mRealtimeRequest, mClientCallback0);
Chong Zhangacb33502020-04-20 11:04:48 -0700348 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(0), JOB(0)));
349 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), JOB(1)));
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700350
351 // Submit real-time job JOB(2), should not start.
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700352 mScheduler->submit(CLIENT(0), JOB(2), UID(0), mRealtimeRequest, mClientCallback0);
Chong Zhangacb33502020-04-20 11:04:48 -0700353 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700354
Chong Zhangacb33502020-04-20 11:04:48 -0700355 // Finish when the job never started, should be ignored.
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700356 mScheduler->onFinish(CLIENT(0), JOB(2));
Chong Zhangacb33502020-04-20 11:04:48 -0700357 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700358
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700359 // UID(1) moves to top.
Chong Zhangacb33502020-04-20 11:04:48 -0700360 mUidPolicy->setTop(UID(1));
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700361 // Submit real-time job to CLIENT(1) in UID(1), should pause previous job and start new job.
362 mScheduler->submit(CLIENT(1), JOB(0), UID(1), mRealtimeRequest, mClientCallback1);
Chong Zhangacb33502020-04-20 11:04:48 -0700363 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(0), JOB(1)));
364 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(1), JOB(0)));
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700365
Chong Zhangacb33502020-04-20 11:04:48 -0700366 // Simulate Finish that arrived late, after pause issued by scheduler.
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700367 // Should still be propagated to client, but shouldn't trigger any new start.
368 mScheduler->onFinish(CLIENT(0), JOB(1));
Chong Zhangacb33502020-04-20 11:04:48 -0700369 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Finished(CLIENT(0), JOB(1)));
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700370
Chong Zhangacb33502020-04-20 11:04:48 -0700371 // Finish running real-time job, should start next real-time job in queue.
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700372 mScheduler->onFinish(CLIENT(1), JOB(0));
Chong Zhangacb33502020-04-20 11:04:48 -0700373 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Finished(CLIENT(1), JOB(0)));
374 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), JOB(2)));
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700375
Chong Zhangacb33502020-04-20 11:04:48 -0700376 // Finish running real-time job, should resume next job (offline job) in queue.
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700377 mScheduler->onFinish(CLIENT(0), JOB(2));
Chong Zhangacb33502020-04-20 11:04:48 -0700378 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Finished(CLIENT(0), JOB(2)));
379 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(0), JOB(0)));
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700380
Chong Zhangacb33502020-04-20 11:04:48 -0700381 // Finish running offline job.
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700382 mScheduler->onFinish(CLIENT(0), JOB(0));
Chong Zhangacb33502020-04-20 11:04:48 -0700383 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Finished(CLIENT(0), JOB(0)));
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700384
Chong Zhangacb33502020-04-20 11:04:48 -0700385 // Duplicate finish for last job, should be ignored.
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700386 mScheduler->onFinish(CLIENT(0), JOB(0));
Chong Zhangacb33502020-04-20 11:04:48 -0700387 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700388}
389
390TEST_F(TranscodingJobSchedulerTest, TestFailJob) {
391 ALOGD("TestFailJob");
392
Chong Zhangacb33502020-04-20 11:04:48 -0700393 // Start with unspecified top UID.
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700394 // Fail without any jobs submitted, should be ignored.
395 mScheduler->onError(CLIENT(0), JOB(0), TranscodingErrorCode::kUnknown);
Chong Zhangacb33502020-04-20 11:04:48 -0700396 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700397
398 // Submit offline job JOB(0), should start immediately.
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700399 mScheduler->submit(CLIENT(0), JOB(0), UID(0), mOfflineRequest, mClientCallback0);
Chong Zhangacb33502020-04-20 11:04:48 -0700400 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), JOB(0)));
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700401
402 // Submit real-time job JOB(1), should pause offline job and start immediately.
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700403 mScheduler->submit(CLIENT(0), JOB(1), UID(0), mRealtimeRequest, mClientCallback0);
Chong Zhangacb33502020-04-20 11:04:48 -0700404 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(0), JOB(0)));
405 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), JOB(1)));
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700406
407 // Submit real-time job JOB(2), should not start.
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700408 mScheduler->submit(CLIENT(0), JOB(2), UID(0), mRealtimeRequest, mClientCallback0);
Chong Zhangacb33502020-04-20 11:04:48 -0700409 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700410
411 // Fail when the job never started, should be ignored.
412 mScheduler->onError(CLIENT(0), JOB(2), TranscodingErrorCode::kUnknown);
Chong Zhangacb33502020-04-20 11:04:48 -0700413 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700414
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700415 // UID(1) moves to top.
Chong Zhangacb33502020-04-20 11:04:48 -0700416 mUidPolicy->setTop(UID(1));
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700417 // Submit real-time job to CLIENT(1) in UID(1), should pause previous job and start new job.
418 mScheduler->submit(CLIENT(1), JOB(0), UID(1), mRealtimeRequest, mClientCallback1);
Chong Zhangacb33502020-04-20 11:04:48 -0700419 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(0), JOB(1)));
420 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(1), JOB(0)));
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700421
422 // Simulate Fail that arrived late, after pause issued by scheduler.
423 // Should still be propagated to client, but shouldn't trigger any new start.
424 mScheduler->onError(CLIENT(0), JOB(1), TranscodingErrorCode::kUnknown);
Chong Zhangacb33502020-04-20 11:04:48 -0700425 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Failed(CLIENT(0), JOB(1)));
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700426
427 // Fail running real-time job, should start next real-time job in queue.
428 mScheduler->onError(CLIENT(1), JOB(0), TranscodingErrorCode::kUnknown);
Chong Zhangacb33502020-04-20 11:04:48 -0700429 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Failed(CLIENT(1), JOB(0)));
430 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), JOB(2)));
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700431
432 // Fail running real-time job, should resume next job (offline job) in queue.
433 mScheduler->onError(CLIENT(0), JOB(2), TranscodingErrorCode::kUnknown);
Chong Zhangacb33502020-04-20 11:04:48 -0700434 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Failed(CLIENT(0), JOB(2)));
435 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(0), JOB(0)));
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700436
437 // Fail running offline job, and test error code propagation.
Chong Zhang66469272020-06-04 16:51:55 -0700438 mScheduler->onError(CLIENT(0), JOB(0), TranscodingErrorCode::kInvalidOperation);
Chong Zhangacb33502020-04-20 11:04:48 -0700439 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Failed(CLIENT(0), JOB(0)));
Chong Zhang66469272020-06-04 16:51:55 -0700440 EXPECT_EQ(mTranscoder->getLastError(), TranscodingErrorCode::kInvalidOperation);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700441
442 // Duplicate fail for last job, should be ignored.
443 mScheduler->onError(CLIENT(0), JOB(0), TranscodingErrorCode::kUnknown);
Chong Zhangacb33502020-04-20 11:04:48 -0700444 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700445}
446
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700447TEST_F(TranscodingJobSchedulerTest, TestTopUidChanged) {
448 ALOGD("TestTopUidChanged");
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700449
Chong Zhangacb33502020-04-20 11:04:48 -0700450 // Start with unspecified top UID.
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700451 // Submit real-time job to CLIENT(0), job should start immediately.
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700452 mScheduler->submit(CLIENT(0), JOB(0), UID(0), mRealtimeRequest, mClientCallback0);
Chong Zhangacb33502020-04-20 11:04:48 -0700453 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), JOB(0)));
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700454
455 // Submit offline job to CLIENT(0), should not start.
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700456 mScheduler->submit(CLIENT(1), JOB(0), UID(0), mOfflineRequest, mClientCallback1);
Chong Zhangacb33502020-04-20 11:04:48 -0700457 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700458
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700459 // Move UID(1) to top.
Chong Zhangacb33502020-04-20 11:04:48 -0700460 mUidPolicy->setTop(UID(1));
461 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
462
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700463 // Submit real-time job to CLIENT(2) in different uid UID(1).
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700464 // Should pause previous job and start new job.
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700465 mScheduler->submit(CLIENT(2), JOB(0), UID(1), mRealtimeRequest, mClientCallback2);
Chong Zhangacb33502020-04-20 11:04:48 -0700466 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(0), JOB(0)));
467 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(2), JOB(0)));
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700468
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700469 // Bring UID(0) back to top.
Chong Zhangacb33502020-04-20 11:04:48 -0700470 mUidPolicy->setTop(UID(0));
471 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(2), JOB(0)));
472 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(0), JOB(0)));
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700473
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700474 // Bring invalid uid to top.
Chong Zhangacb33502020-04-20 11:04:48 -0700475 mUidPolicy->setTop(kInvalidUid);
476 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700477
478 // Finish job, next real-time job should resume.
479 mScheduler->onFinish(CLIENT(0), JOB(0));
Chong Zhangacb33502020-04-20 11:04:48 -0700480 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Finished(CLIENT(0), JOB(0)));
481 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(2), JOB(0)));
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700482
483 // Finish job, offline job should start.
484 mScheduler->onFinish(CLIENT(2), JOB(0));
Chong Zhangacb33502020-04-20 11:04:48 -0700485 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Finished(CLIENT(2), JOB(0)));
486 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(1), JOB(0)));
487}
488
489TEST_F(TranscodingJobSchedulerTest, TestTopUidSetChanged) {
490 ALOGD("TestTopUidChanged_MultipleUids");
491
492 // Start with unspecified top UID.
493 // Submit real-time job to CLIENT(0), job should start immediately.
494 mScheduler->submit(CLIENT(0), JOB(0), UID(0), mRealtimeRequest, mClientCallback0);
495 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), JOB(0)));
496
497 // Submit offline job to CLIENT(0), should not start.
498 mScheduler->submit(CLIENT(1), JOB(0), UID(0), mOfflineRequest, mClientCallback1);
499 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
500
501 // Set UID(0), UID(1) to top set.
502 // UID(0) should continue to run.
503 mUidPolicy->setTop({UID(0), UID(1)});
504 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
505
506 // Submit real-time job to CLIENT(2) in different uid UID(1).
507 // UID(0) should pause and UID(1) should start.
508 mScheduler->submit(CLIENT(2), JOB(0), UID(1), mRealtimeRequest, mClientCallback2);
509 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(0), JOB(0)));
510 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(2), JOB(0)));
511
512 // Remove UID(0) from top set, and only leave UID(1) in the set.
513 // UID(1) should continue to run.
514 mUidPolicy->setTop(UID(1));
515 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
516
517 // Set UID(0), UID(2) to top set.
518 // UID(1) should continue to run.
519 mUidPolicy->setTop({UID(1), UID(2)});
520 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
521
522 // Bring UID(0) back to top.
523 mUidPolicy->setTop(UID(0));
524 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(2), JOB(0)));
525 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(0), JOB(0)));
526
527 // Bring invalid uid to top.
528 mUidPolicy->setTop(kInvalidUid);
529 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
530
531 // Finish job, next real-time job from UID(1) should resume, even if UID(1) no longer top.
532 mScheduler->onFinish(CLIENT(0), JOB(0));
533 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Finished(CLIENT(0), JOB(0)));
534 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(2), JOB(0)));
535
536 // Finish job, offline job should start.
537 mScheduler->onFinish(CLIENT(2), JOB(0));
538 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Finished(CLIENT(2), JOB(0)));
539 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(1), JOB(0)));
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700540}
541
542TEST_F(TranscodingJobSchedulerTest, TestResourceLost) {
543 ALOGD("TestResourceLost");
544
Chong Zhangacb33502020-04-20 11:04:48 -0700545 // Start with unspecified top UID.
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700546 // Submit real-time job to CLIENT(0), job should start immediately.
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700547 mScheduler->submit(CLIENT(0), JOB(0), UID(0), mRealtimeRequest, mClientCallback0);
Chong Zhangacb33502020-04-20 11:04:48 -0700548 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), JOB(0)));
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700549
550 // Submit offline job to CLIENT(0), should not start.
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700551 mScheduler->submit(CLIENT(1), JOB(0), UID(0), mOfflineRequest, mClientCallback1);
Chong Zhangacb33502020-04-20 11:04:48 -0700552 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700553
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700554 // Move UID(1) to top.
Chong Zhangacb33502020-04-20 11:04:48 -0700555 mUidPolicy->setTop(UID(1));
556 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700557
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700558 // Submit real-time job to CLIENT(2) in different uid UID(1).
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700559 // Should pause previous job and start new job.
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700560 mScheduler->submit(CLIENT(2), JOB(0), UID(1), mRealtimeRequest, mClientCallback2);
Chong Zhangacb33502020-04-20 11:04:48 -0700561 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(0), JOB(0)));
562 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(2), JOB(0)));
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700563
564 // Test 1: No queue change during resource loss.
565 // Signal resource lost.
566 mScheduler->onResourceLost();
Chong Zhangacb33502020-04-20 11:04:48 -0700567 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700568
569 // Signal resource available, CLIENT(2) should resume.
570 mScheduler->onResourceAvailable();
Chong Zhangacb33502020-04-20 11:04:48 -0700571 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(2), JOB(0)));
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700572
573 // Test 2: Change of queue order during resource loss.
574 // Signal resource lost.
575 mScheduler->onResourceLost();
Chong Zhangacb33502020-04-20 11:04:48 -0700576 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700577
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700578 // Move UID(0) back to top, should have no resume due to no resource.
Chong Zhangacb33502020-04-20 11:04:48 -0700579 mUidPolicy->setTop(UID(0));
580 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700581
582 // Signal resource available, CLIENT(0) should resume.
583 mScheduler->onResourceAvailable();
Chong Zhangacb33502020-04-20 11:04:48 -0700584 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(0), JOB(0)));
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700585
586 // Test 3: Adding new queue during resource loss.
587 // Signal resource lost.
588 mScheduler->onResourceLost();
Chong Zhangacb33502020-04-20 11:04:48 -0700589 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700590
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700591 // Move UID(2) to top.
Chong Zhangacb33502020-04-20 11:04:48 -0700592 mUidPolicy->setTop(UID(2));
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700593
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700594 // Submit real-time job to CLIENT(3) in UID(2), job shouldn't start due to no resource.
595 mScheduler->submit(CLIENT(3), JOB(0), UID(2), mRealtimeRequest, mClientCallback3);
Chong Zhangacb33502020-04-20 11:04:48 -0700596 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700597
598 // Signal resource available, CLIENT(3)'s job should start.
599 mScheduler->onResourceAvailable();
Chong Zhangacb33502020-04-20 11:04:48 -0700600 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(3), JOB(0)));
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700601}
602
603} // namespace android