blob: 6bc9e20b40dcd670b4d0de6dd208eb94c3a731f7 [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
34namespace android {
35
36using Status = ::ndk::ScopedAStatus;
37using aidl::android::media::BnTranscodingClientCallback;
38using aidl::android::media::IMediaTranscodingService;
39using aidl::android::media::ITranscodingClient;
40
41constexpr int64_t kClientId = 1000;
42constexpr int32_t kClientJobId = 0;
Chong Zhang7ae4e2f2020-04-17 15:24:34 -070043constexpr uid_t kClientUid = 5000;
44constexpr uid_t kInvalidUid = (uid_t)-1;
Chong Zhang6d58e4b2020-03-31 09:41:10 -070045
46#define CLIENT(n) (kClientId + (n))
47#define JOB(n) (kClientJobId + (n))
Chong Zhang7ae4e2f2020-04-17 15:24:34 -070048#define UID(n) (kClientUid + (n))
Chong Zhang6d58e4b2020-03-31 09:41:10 -070049
Chong Zhang7ae4e2f2020-04-17 15:24:34 -070050class TestCallback : public TranscoderInterface, public UidPolicyInterface {
Chong Zhang6d58e4b2020-03-31 09:41:10 -070051public:
Chong Zhang7ae4e2f2020-04-17 15:24:34 -070052 TestCallback() : mTopUid(kInvalidUid), mLastError(TranscodingErrorCode::kUnknown) {}
Chong Zhang6d58e4b2020-03-31 09:41:10 -070053 virtual ~TestCallback() {}
54
55 // TranscoderInterface
56 void start(int64_t clientId, int32_t jobId) override {
57 mEventQueue.push_back(Start(clientId, jobId));
58 }
59 void pause(int64_t clientId, int32_t jobId) override {
60 mEventQueue.push_back(Pause(clientId, jobId));
61 }
62 void resume(int64_t clientId, int32_t jobId) override {
63 mEventQueue.push_back(Resume(clientId, jobId));
64 }
65
Chong Zhang7ae4e2f2020-04-17 15:24:34 -070066 // UidPolicyInterface
67 bool isUidOnTop(uid_t uid) override { return uid == mTopUid; }
Chong Zhang6d58e4b2020-03-31 09:41:10 -070068
69 void onFinished(int64_t clientId, int32_t jobId) {
70 mEventQueue.push_back(Finished(clientId, jobId));
71 }
72
73 void onFailed(int64_t clientId, int32_t jobId, TranscodingErrorCode err) {
74 mLastError = err;
75 mEventQueue.push_back(Failed(clientId, jobId));
76 }
77
Chong Zhang7ae4e2f2020-04-17 15:24:34 -070078 void setTop(uid_t uid) { mTopUid = uid; }
Chong Zhang6d58e4b2020-03-31 09:41:10 -070079
80 TranscodingErrorCode getLastError() {
81 TranscodingErrorCode result = mLastError;
82 mLastError = TranscodingErrorCode::kUnknown;
83 return result;
84 }
85
86 struct Event {
87 enum { NoEvent, Start, Pause, Resume, Finished, Failed } type;
88 int64_t clientId;
89 int32_t jobId;
90 };
91
92 static constexpr Event NoEvent = {Event::NoEvent, 0, 0};
93
94#define DECLARE_EVENT(action) \
95 static Event action(int64_t clientId, int32_t jobId) { \
96 return {Event::action, clientId, jobId}; \
97 }
98
99 DECLARE_EVENT(Start);
100 DECLARE_EVENT(Pause);
101 DECLARE_EVENT(Resume);
102 DECLARE_EVENT(Finished);
103 DECLARE_EVENT(Failed);
104
105 const Event& popEvent() {
106 if (mEventQueue.empty()) {
107 mPoppedEvent = NoEvent;
108 } else {
109 mPoppedEvent = *mEventQueue.begin();
110 mEventQueue.pop_front();
111 }
112 return mPoppedEvent;
113 }
114
115private:
116 Event mPoppedEvent;
117 std::list<Event> mEventQueue;
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700118 uid_t mTopUid;
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700119 TranscodingErrorCode mLastError;
120};
121
122bool operator==(const TestCallback::Event& lhs, const TestCallback::Event& rhs) {
123 return lhs.type == rhs.type && lhs.clientId == rhs.clientId && lhs.jobId == rhs.jobId;
124}
125
126struct TestClientCallback : public BnTranscodingClientCallback {
127 TestClientCallback(TestCallback* owner, int64_t clientId) : mOwner(owner), mClientId(clientId) {
128 ALOGD("TestClient Created");
129 }
130
131 Status onTranscodingFinished(int32_t in_jobId,
132 const TranscodingResultParcel& in_result) override {
133 EXPECT_EQ(in_jobId, in_result.jobId);
134 mOwner->onFinished(mClientId, in_jobId);
135 return Status::ok();
136 }
137
138 Status onTranscodingFailed(int32_t in_jobId, TranscodingErrorCode in_errorCode) override {
139 mOwner->onFailed(mClientId, in_jobId, in_errorCode);
140 return Status::ok();
141 }
142
143 Status onAwaitNumberOfJobsChanged(int32_t /* in_jobId */, int32_t /* in_oldAwaitNumber */,
144 int32_t /* in_newAwaitNumber */) override {
145 return Status::ok();
146 }
147
148 Status onProgressUpdate(int32_t /* in_jobId */, int32_t /* in_progress */) override {
149 return Status::ok();
150 }
151
152 virtual ~TestClientCallback() { ALOGI("TestClient destroyed"); };
153
154private:
155 TestCallback* mOwner;
156 int64_t mClientId;
157 TestClientCallback(const TestClientCallback&) = delete;
158 TestClientCallback& operator=(const TestClientCallback&) = delete;
159};
160
161class TranscodingJobSchedulerTest : public ::testing::Test {
162public:
163 TranscodingJobSchedulerTest() { ALOGI("TranscodingJobSchedulerTest created"); }
164
165 void SetUp() override {
166 ALOGI("TranscodingJobSchedulerTest set up");
167 mCallback.reset(new TestCallback());
168 mScheduler.reset(new TranscodingJobScheduler(mCallback, mCallback));
169
170 // Set priority only, ignore other fields for now.
171 mOfflineRequest.priority = TranscodingJobPriority::kUnspecified;
172 mRealtimeRequest.priority = TranscodingJobPriority::kHigh;
173 mClientCallback0 =
174 ::ndk::SharedRefBase::make<TestClientCallback>(mCallback.get(), CLIENT(0));
175 mClientCallback1 =
176 ::ndk::SharedRefBase::make<TestClientCallback>(mCallback.get(), CLIENT(1));
177 mClientCallback2 =
178 ::ndk::SharedRefBase::make<TestClientCallback>(mCallback.get(), CLIENT(2));
179 mClientCallback3 =
180 ::ndk::SharedRefBase::make<TestClientCallback>(mCallback.get(), CLIENT(3));
181 }
182
183 void TearDown() override { ALOGI("TranscodingJobSchedulerTest tear down"); }
184
185 ~TranscodingJobSchedulerTest() { ALOGD("TranscodingJobSchedulerTest destroyed"); }
186
187 std::shared_ptr<TestCallback> mCallback;
188 std::shared_ptr<TranscodingJobScheduler> mScheduler;
189 TranscodingRequestParcel mOfflineRequest;
190 TranscodingRequestParcel mRealtimeRequest;
191 std::shared_ptr<TestClientCallback> mClientCallback0;
192 std::shared_ptr<TestClientCallback> mClientCallback1;
193 std::shared_ptr<TestClientCallback> mClientCallback2;
194 std::shared_ptr<TestClientCallback> mClientCallback3;
195};
196
197TEST_F(TranscodingJobSchedulerTest, TestSubmitJob) {
198 ALOGD("TestSubmitJob");
199
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700200 // Start with UID(1) on top.
201 mCallback->setTop(UID(1));
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700202
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700203 // Submit offline job to CLIENT(0) in UID(0).
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700204 // Should start immediately (because this is the only job).
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700205 mScheduler->submit(CLIENT(0), JOB(0), UID(0), mOfflineRequest, mClientCallback0);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700206 EXPECT_EQ(mCallback->popEvent(), TestCallback::Start(CLIENT(0), 0));
207
208 // Submit real-time job to CLIENT(0).
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700209 // Should pause offline job and start new job, even if UID(0) is not on top.
210 mScheduler->submit(CLIENT(0), JOB(1), UID(0), mRealtimeRequest, mClientCallback0);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700211 EXPECT_EQ(mCallback->popEvent(), TestCallback::Pause(CLIENT(0), JOB(0)));
212 EXPECT_EQ(mCallback->popEvent(), TestCallback::Start(CLIENT(0), JOB(1)));
213
214 // Submit real-time job to CLIENT(0), should be queued after the previous job.
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700215 mScheduler->submit(CLIENT(0), JOB(2), UID(0), mRealtimeRequest, mClientCallback0);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700216 EXPECT_EQ(mCallback->popEvent(), TestCallback::NoEvent);
217
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700218 // Submit real-time job to CLIENT(1) in same uid, should be queued after the previous job.
219 mScheduler->submit(CLIENT(1), JOB(0), UID(0), mRealtimeRequest, mClientCallback1);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700220 EXPECT_EQ(mCallback->popEvent(), TestCallback::NoEvent);
221
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700222 // Submit real-time job to CLIENT(2) in UID(1).
223 // Should pause previous job and start new job, because UID(1) is top.
224 mCallback->setTop(UID(1));
225 mScheduler->submit(CLIENT(2), JOB(0), UID(1), mRealtimeRequest, mClientCallback2);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700226 EXPECT_EQ(mCallback->popEvent(), TestCallback::Pause(CLIENT(0), JOB(1)));
227 EXPECT_EQ(mCallback->popEvent(), TestCallback::Start(CLIENT(2), JOB(0)));
228
229 // Submit offline job, shouldn't generate any event.
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700230 mScheduler->submit(CLIENT(2), JOB(1), UID(1), mOfflineRequest, mClientCallback2);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700231 EXPECT_EQ(mCallback->popEvent(), TestCallback::NoEvent);
232
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700233 mCallback->setTop(UID(0));
234 // Submit real-time job to CLIENT(1) in UID(0).
235 // Should pause current job, and resume last job in UID(0).
236 mScheduler->submit(CLIENT(1), JOB(1), UID(0), mRealtimeRequest, mClientCallback1);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700237 EXPECT_EQ(mCallback->popEvent(), TestCallback::Pause(CLIENT(2), JOB(0)));
238 EXPECT_EQ(mCallback->popEvent(), TestCallback::Resume(CLIENT(0), JOB(1)));
239}
240
241TEST_F(TranscodingJobSchedulerTest, TestCancelJob) {
242 ALOGD("TestCancelJob");
243
244 // Submit real-time job JOB(0), should start immediately.
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700245 mScheduler->submit(CLIENT(0), JOB(0), UID(0), mRealtimeRequest, mClientCallback0);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700246 EXPECT_EQ(mCallback->popEvent(), TestCallback::Start(CLIENT(0), JOB(0)));
247
248 // Submit real-time job JOB(1), should not start.
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700249 mScheduler->submit(CLIENT(0), JOB(1), UID(0), mRealtimeRequest, mClientCallback0);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700250 EXPECT_EQ(mCallback->popEvent(), TestCallback::NoEvent);
251
252 // Submit offline job JOB(2), should not start.
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700253 mScheduler->submit(CLIENT(0), JOB(2), UID(0), mOfflineRequest, mClientCallback0);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700254 EXPECT_EQ(mCallback->popEvent(), TestCallback::NoEvent);
255
256 // Cancel queued real-time job.
257 // Cancel real-time job JOB(1), should be cancelled.
258 EXPECT_TRUE(mScheduler->cancel(CLIENT(0), JOB(1)));
259
260 // Cancel queued offline job.
261 // Cancel offline job JOB(2), should be cancelled.
262 EXPECT_TRUE(mScheduler->cancel(CLIENT(0), JOB(2)));
263
264 // Submit offline job JOB(3), shouldn't cause any event.
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700265 mScheduler->submit(CLIENT(0), JOB(3), UID(0), mOfflineRequest, mClientCallback0);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700266 EXPECT_EQ(mCallback->popEvent(), TestCallback::NoEvent);
267
268 // Cancel running real-time job JOB(0).
269 // - Should be paused first then cancelled.
270 // - Should also start offline job JOB(2) because real-time queue is empty.
271 EXPECT_TRUE(mScheduler->cancel(CLIENT(0), JOB(0)));
272 EXPECT_EQ(mCallback->popEvent(), TestCallback::Pause(CLIENT(0), JOB(0)));
273 EXPECT_EQ(mCallback->popEvent(), TestCallback::Start(CLIENT(0), JOB(3)));
274}
275
276TEST_F(TranscodingJobSchedulerTest, TestFinishJob) {
277 ALOGD("TestFinishJob");
278
279 // Fail without any jobs submitted, should be ignored.
280 mScheduler->onFinish(CLIENT(0), JOB(0));
281 EXPECT_EQ(mCallback->popEvent(), TestCallback::NoEvent);
282
283 // Submit offline job JOB(0), should start immediately.
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700284 mScheduler->submit(CLIENT(0), JOB(0), UID(0), mOfflineRequest, mClientCallback0);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700285 EXPECT_EQ(mCallback->popEvent(), TestCallback::Start(CLIENT(0), JOB(0)));
286
287 // Submit real-time job JOB(1), should pause offline job and start immediately.
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700288 mScheduler->submit(CLIENT(0), JOB(1), UID(0), mRealtimeRequest, mClientCallback0);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700289 EXPECT_EQ(mCallback->popEvent(), TestCallback::Pause(CLIENT(0), JOB(0)));
290 EXPECT_EQ(mCallback->popEvent(), TestCallback::Start(CLIENT(0), JOB(1)));
291
292 // Submit real-time job JOB(2), should not start.
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700293 mScheduler->submit(CLIENT(0), JOB(2), UID(0), mRealtimeRequest, mClientCallback0);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700294 EXPECT_EQ(mCallback->popEvent(), TestCallback::NoEvent);
295
296 // Fail when the job never started, should be ignored.
297 mScheduler->onFinish(CLIENT(0), JOB(2));
298 EXPECT_EQ(mCallback->popEvent(), TestCallback::NoEvent);
299
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700300 // UID(1) moves to top.
301 mCallback->setTop(UID(1));
302 // Submit real-time job to CLIENT(1) in UID(1), should pause previous job and start new job.
303 mScheduler->submit(CLIENT(1), JOB(0), UID(1), mRealtimeRequest, mClientCallback1);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700304 EXPECT_EQ(mCallback->popEvent(), TestCallback::Pause(CLIENT(0), JOB(1)));
305 EXPECT_EQ(mCallback->popEvent(), TestCallback::Start(CLIENT(1), JOB(0)));
306
307 // Simulate Fail that arrived late, after pause issued by scheduler.
308 // Should still be propagated to client, but shouldn't trigger any new start.
309 mScheduler->onFinish(CLIENT(0), JOB(1));
310 EXPECT_EQ(mCallback->popEvent(), TestCallback::Finished(CLIENT(0), JOB(1)));
311
312 // Fail running real-time job, should start next real-time job in queue.
313 mScheduler->onFinish(CLIENT(1), JOB(0));
314 EXPECT_EQ(mCallback->popEvent(), TestCallback::Finished(CLIENT(1), JOB(0)));
315 EXPECT_EQ(mCallback->popEvent(), TestCallback::Start(CLIENT(0), JOB(2)));
316
317 // Fail running real-time job, should resume next job (offline job) in queue.
318 mScheduler->onFinish(CLIENT(0), JOB(2));
319 EXPECT_EQ(mCallback->popEvent(), TestCallback::Finished(CLIENT(0), JOB(2)));
320 EXPECT_EQ(mCallback->popEvent(), TestCallback::Resume(CLIENT(0), JOB(0)));
321
322 // Fail running offline job.
323 mScheduler->onFinish(CLIENT(0), JOB(0));
324 EXPECT_EQ(mCallback->popEvent(), TestCallback::Finished(CLIENT(0), JOB(0)));
325
326 // Duplicate fail for last job, should be ignored.
327 mScheduler->onFinish(CLIENT(0), JOB(0));
328 EXPECT_EQ(mCallback->popEvent(), TestCallback::NoEvent);
329}
330
331TEST_F(TranscodingJobSchedulerTest, TestFailJob) {
332 ALOGD("TestFailJob");
333
334 // Fail without any jobs submitted, should be ignored.
335 mScheduler->onError(CLIENT(0), JOB(0), TranscodingErrorCode::kUnknown);
336 EXPECT_EQ(mCallback->popEvent(), TestCallback::NoEvent);
337
338 // Submit offline job JOB(0), should start immediately.
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700339 mScheduler->submit(CLIENT(0), JOB(0), UID(0), mOfflineRequest, mClientCallback0);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700340 EXPECT_EQ(mCallback->popEvent(), TestCallback::Start(CLIENT(0), JOB(0)));
341
342 // Submit real-time job JOB(1), should pause offline job and start immediately.
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700343 mScheduler->submit(CLIENT(0), JOB(1), UID(0), mRealtimeRequest, mClientCallback0);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700344 EXPECT_EQ(mCallback->popEvent(), TestCallback::Pause(CLIENT(0), JOB(0)));
345 EXPECT_EQ(mCallback->popEvent(), TestCallback::Start(CLIENT(0), JOB(1)));
346
347 // Submit real-time job JOB(2), should not start.
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700348 mScheduler->submit(CLIENT(0), JOB(2), UID(0), mRealtimeRequest, mClientCallback0);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700349 EXPECT_EQ(mCallback->popEvent(), TestCallback::NoEvent);
350
351 // Fail when the job never started, should be ignored.
352 mScheduler->onError(CLIENT(0), JOB(2), TranscodingErrorCode::kUnknown);
353 EXPECT_EQ(mCallback->popEvent(), TestCallback::NoEvent);
354
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700355 // UID(1) moves to top.
356 mCallback->setTop(UID(1));
357 // Submit real-time job to CLIENT(1) in UID(1), should pause previous job and start new job.
358 mScheduler->submit(CLIENT(1), JOB(0), UID(1), mRealtimeRequest, mClientCallback1);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700359 EXPECT_EQ(mCallback->popEvent(), TestCallback::Pause(CLIENT(0), JOB(1)));
360 EXPECT_EQ(mCallback->popEvent(), TestCallback::Start(CLIENT(1), JOB(0)));
361
362 // Simulate Fail that arrived late, after pause issued by scheduler.
363 // Should still be propagated to client, but shouldn't trigger any new start.
364 mScheduler->onError(CLIENT(0), JOB(1), TranscodingErrorCode::kUnknown);
365 EXPECT_EQ(mCallback->popEvent(), TestCallback::Failed(CLIENT(0), JOB(1)));
366
367 // Fail running real-time job, should start next real-time job in queue.
368 mScheduler->onError(CLIENT(1), JOB(0), TranscodingErrorCode::kUnknown);
369 EXPECT_EQ(mCallback->popEvent(), TestCallback::Failed(CLIENT(1), JOB(0)));
370 EXPECT_EQ(mCallback->popEvent(), TestCallback::Start(CLIENT(0), JOB(2)));
371
372 // Fail running real-time job, should resume next job (offline job) in queue.
373 mScheduler->onError(CLIENT(0), JOB(2), TranscodingErrorCode::kUnknown);
374 EXPECT_EQ(mCallback->popEvent(), TestCallback::Failed(CLIENT(0), JOB(2)));
375 EXPECT_EQ(mCallback->popEvent(), TestCallback::Resume(CLIENT(0), JOB(0)));
376
377 // Fail running offline job, and test error code propagation.
378 mScheduler->onError(CLIENT(0), JOB(0), TranscodingErrorCode::kInvalidBitstream);
379 EXPECT_EQ(mCallback->popEvent(), TestCallback::Failed(CLIENT(0), JOB(0)));
380 EXPECT_EQ(mCallback->getLastError(), TranscodingErrorCode::kInvalidBitstream);
381
382 // Duplicate fail for last job, should be ignored.
383 mScheduler->onError(CLIENT(0), JOB(0), TranscodingErrorCode::kUnknown);
384 EXPECT_EQ(mCallback->popEvent(), TestCallback::NoEvent);
385}
386
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700387TEST_F(TranscodingJobSchedulerTest, TestTopUidChanged) {
388 ALOGD("TestTopUidChanged");
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700389
390 // Submit real-time job to CLIENT(0), job should start immediately.
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700391 mScheduler->submit(CLIENT(0), JOB(0), UID(0), mRealtimeRequest, mClientCallback0);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700392 EXPECT_EQ(mCallback->popEvent(), TestCallback::Start(CLIENT(0), JOB(0)));
393
394 // Submit offline job to CLIENT(0), should not start.
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700395 mScheduler->submit(CLIENT(1), JOB(0), UID(0), mOfflineRequest, mClientCallback1);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700396 EXPECT_EQ(mCallback->popEvent(), TestCallback::NoEvent);
397
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700398 // Move UID(1) to top.
399 mCallback->setTop(UID(1));
400 // Submit real-time job to CLIENT(2) in different uid UID(1).
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700401 // Should pause previous job and start new job.
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700402 mScheduler->submit(CLIENT(2), JOB(0), UID(1), mRealtimeRequest, mClientCallback2);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700403 EXPECT_EQ(mCallback->popEvent(), TestCallback::Pause(CLIENT(0), JOB(0)));
404 EXPECT_EQ(mCallback->popEvent(), TestCallback::Start(CLIENT(2), JOB(0)));
405
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700406 // Bring UID(0) back to top.
407 mCallback->setTop(UID(0));
408 mScheduler->onTopUidChanged(UID(0));
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700409 EXPECT_EQ(mCallback->popEvent(), TestCallback::Pause(CLIENT(2), JOB(0)));
410 EXPECT_EQ(mCallback->popEvent(), TestCallback::Resume(CLIENT(0), JOB(0)));
411
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700412 // Bring invalid uid to top.
413 mScheduler->onTopUidChanged(kInvalidUid);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700414 EXPECT_EQ(mCallback->popEvent(), TestCallback::NoEvent);
415
416 // Finish job, next real-time job should resume.
417 mScheduler->onFinish(CLIENT(0), JOB(0));
418 EXPECT_EQ(mCallback->popEvent(), TestCallback::Finished(CLIENT(0), JOB(0)));
419 EXPECT_EQ(mCallback->popEvent(), TestCallback::Resume(CLIENT(2), JOB(0)));
420
421 // Finish job, offline job should start.
422 mScheduler->onFinish(CLIENT(2), JOB(0));
423 EXPECT_EQ(mCallback->popEvent(), TestCallback::Finished(CLIENT(2), JOB(0)));
424 EXPECT_EQ(mCallback->popEvent(), TestCallback::Start(CLIENT(1), JOB(0)));
425}
426
427TEST_F(TranscodingJobSchedulerTest, TestResourceLost) {
428 ALOGD("TestResourceLost");
429
430 // Submit real-time job to CLIENT(0), job should start immediately.
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700431 mScheduler->submit(CLIENT(0), JOB(0), UID(0), mRealtimeRequest, mClientCallback0);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700432 EXPECT_EQ(mCallback->popEvent(), TestCallback::Start(CLIENT(0), JOB(0)));
433
434 // Submit offline job to CLIENT(0), should not start.
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700435 mScheduler->submit(CLIENT(1), JOB(0), UID(0), mOfflineRequest, mClientCallback1);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700436 EXPECT_EQ(mCallback->popEvent(), TestCallback::NoEvent);
437
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700438 // Move UID(1) to top.
439 mCallback->setTop(UID(1));
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700440
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700441 // Submit real-time job to CLIENT(2) in different uid UID(1).
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700442 // Should pause previous job and start new job.
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700443 mScheduler->submit(CLIENT(2), JOB(0), UID(1), mRealtimeRequest, mClientCallback2);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700444 EXPECT_EQ(mCallback->popEvent(), TestCallback::Pause(CLIENT(0), JOB(0)));
445 EXPECT_EQ(mCallback->popEvent(), TestCallback::Start(CLIENT(2), JOB(0)));
446
447 // Test 1: No queue change during resource loss.
448 // Signal resource lost.
449 mScheduler->onResourceLost();
450 EXPECT_EQ(mCallback->popEvent(), TestCallback::NoEvent);
451
452 // Signal resource available, CLIENT(2) should resume.
453 mScheduler->onResourceAvailable();
454 EXPECT_EQ(mCallback->popEvent(), TestCallback::Resume(CLIENT(2), JOB(0)));
455
456 // Test 2: Change of queue order during resource loss.
457 // Signal resource lost.
458 mScheduler->onResourceLost();
459 EXPECT_EQ(mCallback->popEvent(), TestCallback::NoEvent);
460
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700461 // Move UID(0) back to top, should have no resume due to no resource.
462 mScheduler->onTopUidChanged(UID(0));
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700463 EXPECT_EQ(mCallback->popEvent(), TestCallback::NoEvent);
464
465 // Signal resource available, CLIENT(0) should resume.
466 mScheduler->onResourceAvailable();
467 EXPECT_EQ(mCallback->popEvent(), TestCallback::Resume(CLIENT(0), JOB(0)));
468
469 // Test 3: Adding new queue during resource loss.
470 // Signal resource lost.
471 mScheduler->onResourceLost();
472 EXPECT_EQ(mCallback->popEvent(), TestCallback::NoEvent);
473
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700474 // Move UID(2) to top.
475 mCallback->setTop(UID(2));
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700476
Chong Zhang7ae4e2f2020-04-17 15:24:34 -0700477 // Submit real-time job to CLIENT(3) in UID(2), job shouldn't start due to no resource.
478 mScheduler->submit(CLIENT(3), JOB(0), UID(2), mRealtimeRequest, mClientCallback3);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700479 EXPECT_EQ(mCallback->popEvent(), TestCallback::NoEvent);
480
481 // Signal resource available, CLIENT(3)'s job should start.
482 mScheduler->onResourceAvailable();
483 EXPECT_EQ(mCallback->popEvent(), TestCallback::Start(CLIENT(3), JOB(0)));
484}
485
486} // namespace android