blob: fa52f63a22a2845b056c5c672f52bf3fbe2a25b4 [file] [log] [blame]
Chong Zhangbc062482020-10-14 16:43:53 -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 TranscodingSessionController
18
19// #define LOG_NDEBUG 0
20#define LOG_TAG "TranscodingSessionControllerTest"
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/TranscodingSessionController.h>
32#include <utils/Log.h>
33
34#include <unordered_set>
35
36namespace android {
37
38using Status = ::ndk::ScopedAStatus;
39using aidl::android::media::BnTranscodingClientCallback;
40using aidl::android::media::IMediaTranscodingService;
41using aidl::android::media::ITranscodingClient;
42using aidl::android::media::TranscodingRequestParcel;
43
44constexpr ClientIdType kClientId = 1000;
45constexpr SessionIdType kClientSessionId = 0;
46constexpr uid_t kClientUid = 5000;
Chong Zhangeffd8962020-12-02 14:29:09 -080047constexpr pid_t kClientPid = 10000;
Chong Zhangbc062482020-10-14 16:43:53 -070048constexpr uid_t kInvalidUid = (uid_t)-1;
Chong Zhangeffd8962020-12-02 14:29:09 -080049constexpr pid_t kInvalidPid = (pid_t)-1;
Chong Zhangbc062482020-10-14 16:43:53 -070050
51#define CLIENT(n) (kClientId + (n))
52#define SESSION(n) (kClientSessionId + (n))
53#define UID(n) (kClientUid + (n))
Chong Zhangeffd8962020-12-02 14:29:09 -080054#define PID(n) (kClientPid + (n))
Chong Zhangbc062482020-10-14 16:43:53 -070055
56class TestUidPolicy : public UidPolicyInterface {
57public:
58 TestUidPolicy() = default;
59 virtual ~TestUidPolicy() = default;
60
61 // UidPolicyInterface
62 void registerMonitorUid(uid_t /*uid*/) override {}
63 void unregisterMonitorUid(uid_t /*uid*/) override {}
64 bool isUidOnTop(uid_t uid) override { return mTopUids.count(uid) > 0; }
65 std::unordered_set<uid_t> getTopUids() const override { return mTopUids; }
66 void setCallback(const std::shared_ptr<UidPolicyCallbackInterface>& cb) override {
67 mUidPolicyCallback = cb;
68 }
69 void setTop(uid_t uid) {
70 std::unordered_set<uid_t> uids = {uid};
71 setTop(uids);
72 }
73 void setTop(const std::unordered_set<uid_t>& uids) {
74 mTopUids = uids;
75 auto uidPolicyCb = mUidPolicyCallback.lock();
76 if (uidPolicyCb != nullptr) {
77 uidPolicyCb->onTopUidsChanged(mTopUids);
78 }
79 }
80
81 std::unordered_set<uid_t> mTopUids;
82 std::weak_ptr<UidPolicyCallbackInterface> mUidPolicyCallback;
83};
84
Chong Zhangf47a3572020-12-02 11:35:35 -080085class TestResourcePolicy : public ResourcePolicyInterface {
86public:
Chong Zhangeffd8962020-12-02 14:29:09 -080087 TestResourcePolicy() { reset(); }
Chong Zhangf47a3572020-12-02 11:35:35 -080088 virtual ~TestResourcePolicy() = default;
89
Chong Zhangeffd8962020-12-02 14:29:09 -080090 // ResourcePolicyInterface
Chong Zhangf47a3572020-12-02 11:35:35 -080091 void setCallback(const std::shared_ptr<ResourcePolicyCallbackInterface>& /*cb*/) override {}
Chong Zhangeffd8962020-12-02 14:29:09 -080092 void setPidResourceLost(pid_t pid) override {
93 mResourceLostPid = pid;
94 }
95 // ~ResourcePolicyInterface
96
97 pid_t getPid() {
98 pid_t result = mResourceLostPid;
99 reset();
100 return result;
101 }
102
103private:
104 void reset() {
105 mResourceLostPid = kInvalidPid;
106 }
107 pid_t mResourceLostPid;
Chong Zhangf47a3572020-12-02 11:35:35 -0800108};
109
Chong Zhangbc062482020-10-14 16:43:53 -0700110class TestTranscoder : public TranscoderInterface {
111public:
112 TestTranscoder() : mLastError(TranscodingErrorCode::kUnknown) {}
113 virtual ~TestTranscoder() {}
114
115 // TranscoderInterface
116 void setCallback(const std::shared_ptr<TranscoderCallbackInterface>& /*cb*/) override {}
117
118 void start(ClientIdType clientId, SessionIdType sessionId,
119 const TranscodingRequestParcel& /*request*/,
120 const std::shared_ptr<ITranscodingClientCallback>& /*clientCallback*/) override {
121 mEventQueue.push_back(Start(clientId, sessionId));
122 }
123 void pause(ClientIdType clientId, SessionIdType sessionId) override {
124 mEventQueue.push_back(Pause(clientId, sessionId));
125 }
126 void resume(ClientIdType clientId, SessionIdType sessionId,
127 const TranscodingRequestParcel& /*request*/,
128 const std::shared_ptr<ITranscodingClientCallback>& /*clientCallback*/) override {
129 mEventQueue.push_back(Resume(clientId, sessionId));
130 }
131 void stop(ClientIdType clientId, SessionIdType sessionId) override {
132 mEventQueue.push_back(Stop(clientId, sessionId));
133 }
134
135 void onFinished(ClientIdType clientId, SessionIdType sessionId) {
136 mEventQueue.push_back(Finished(clientId, sessionId));
137 }
138
139 void onFailed(ClientIdType clientId, SessionIdType sessionId, TranscodingErrorCode err) {
140 mLastError = err;
141 mEventQueue.push_back(Failed(clientId, sessionId));
142 }
143
144 TranscodingErrorCode getLastError() {
145 TranscodingErrorCode result = mLastError;
146 mLastError = TranscodingErrorCode::kUnknown;
147 return result;
148 }
149
150 struct Event {
151 enum { NoEvent, Start, Pause, Resume, Stop, Finished, Failed } type;
152 ClientIdType clientId;
153 SessionIdType sessionId;
154 };
155
156 static constexpr Event NoEvent = {Event::NoEvent, 0, 0};
157
158#define DECLARE_EVENT(action) \
159 static Event action(ClientIdType clientId, SessionIdType sessionId) { \
160 return {Event::action, clientId, sessionId}; \
161 }
162
163 DECLARE_EVENT(Start);
164 DECLARE_EVENT(Pause);
165 DECLARE_EVENT(Resume);
166 DECLARE_EVENT(Stop);
167 DECLARE_EVENT(Finished);
168 DECLARE_EVENT(Failed);
169
170 const Event& popEvent() {
171 if (mEventQueue.empty()) {
172 mPoppedEvent = NoEvent;
173 } else {
174 mPoppedEvent = *mEventQueue.begin();
175 mEventQueue.pop_front();
176 }
177 return mPoppedEvent;
178 }
179
180private:
181 Event mPoppedEvent;
182 std::list<Event> mEventQueue;
183 TranscodingErrorCode mLastError;
184};
185
186bool operator==(const TestTranscoder::Event& lhs, const TestTranscoder::Event& rhs) {
187 return lhs.type == rhs.type && lhs.clientId == rhs.clientId && lhs.sessionId == rhs.sessionId;
188}
189
190struct TestClientCallback : public BnTranscodingClientCallback {
191 TestClientCallback(TestTranscoder* owner, int64_t clientId)
192 : mOwner(owner), mClientId(clientId) {
193 ALOGD("TestClient Created");
194 }
195
196 Status openFileDescriptor(const std::string& /*in_fileUri*/, const std::string& /*in_mode*/,
197 ::ndk::ScopedFileDescriptor* /*_aidl_return*/) override {
198 return Status::ok();
199 }
200
201 Status onTranscodingStarted(int32_t /*in_sessionId*/) override { return Status::ok(); }
202
203 Status onTranscodingPaused(int32_t /*in_sessionId*/) override { return Status::ok(); }
204
205 Status onTranscodingResumed(int32_t /*in_sessionId*/) override { return Status::ok(); }
206
207 Status onTranscodingFinished(int32_t in_sessionId,
208 const TranscodingResultParcel& in_result) override {
209 EXPECT_EQ(in_sessionId, in_result.sessionId);
210 ALOGD("TestClientCallback: received onTranscodingFinished");
211 mOwner->onFinished(mClientId, in_sessionId);
212 return Status::ok();
213 }
214
215 Status onTranscodingFailed(int32_t in_sessionId, TranscodingErrorCode in_errorCode) override {
216 mOwner->onFailed(mClientId, in_sessionId, in_errorCode);
217 return Status::ok();
218 }
219
220 Status onAwaitNumberOfSessionsChanged(int32_t /* in_sessionId */,
221 int32_t /* in_oldAwaitNumber */,
222 int32_t /* in_newAwaitNumber */) override {
223 return Status::ok();
224 }
225
226 Status onProgressUpdate(int32_t /* in_sessionId */, int32_t /* in_progress */) override {
227 return Status::ok();
228 }
229
230 virtual ~TestClientCallback() { ALOGI("TestClient destroyed"); };
231
232private:
233 TestTranscoder* mOwner;
234 int64_t mClientId;
235 TestClientCallback(const TestClientCallback&) = delete;
236 TestClientCallback& operator=(const TestClientCallback&) = delete;
237};
238
239class TranscodingSessionControllerTest : public ::testing::Test {
240public:
241 TranscodingSessionControllerTest() { ALOGI("TranscodingSessionControllerTest created"); }
242
243 void SetUp() override {
244 ALOGI("TranscodingSessionControllerTest set up");
245 mTranscoder.reset(new TestTranscoder());
246 mUidPolicy.reset(new TestUidPolicy());
Chong Zhangf47a3572020-12-02 11:35:35 -0800247 mResourcePolicy.reset(new TestResourcePolicy());
248 mController.reset(
249 new TranscodingSessionController(mTranscoder, mUidPolicy, mResourcePolicy));
Chong Zhangbc062482020-10-14 16:43:53 -0700250 mUidPolicy->setCallback(mController);
251
252 // Set priority only, ignore other fields for now.
253 mOfflineRequest.priority = TranscodingSessionPriority::kUnspecified;
254 mRealtimeRequest.priority = TranscodingSessionPriority::kHigh;
255 mClientCallback0 =
256 ::ndk::SharedRefBase::make<TestClientCallback>(mTranscoder.get(), CLIENT(0));
257 mClientCallback1 =
258 ::ndk::SharedRefBase::make<TestClientCallback>(mTranscoder.get(), CLIENT(1));
259 mClientCallback2 =
260 ::ndk::SharedRefBase::make<TestClientCallback>(mTranscoder.get(), CLIENT(2));
261 mClientCallback3 =
262 ::ndk::SharedRefBase::make<TestClientCallback>(mTranscoder.get(), CLIENT(3));
263 }
264
265 void TearDown() override { ALOGI("TranscodingSessionControllerTest tear down"); }
266
267 ~TranscodingSessionControllerTest() { ALOGD("TranscodingSessionControllerTest destroyed"); }
268
269 std::shared_ptr<TestTranscoder> mTranscoder;
270 std::shared_ptr<TestUidPolicy> mUidPolicy;
Chong Zhangf47a3572020-12-02 11:35:35 -0800271 std::shared_ptr<TestResourcePolicy> mResourcePolicy;
Chong Zhangbc062482020-10-14 16:43:53 -0700272 std::shared_ptr<TranscodingSessionController> mController;
273 TranscodingRequestParcel mOfflineRequest;
274 TranscodingRequestParcel mRealtimeRequest;
275 std::shared_ptr<TestClientCallback> mClientCallback0;
276 std::shared_ptr<TestClientCallback> mClientCallback1;
277 std::shared_ptr<TestClientCallback> mClientCallback2;
278 std::shared_ptr<TestClientCallback> mClientCallback3;
279};
280
281TEST_F(TranscodingSessionControllerTest, TestSubmitSession) {
282 ALOGD("TestSubmitSession");
283
284 // Start with UID(1) on top.
285 mUidPolicy->setTop(UID(1));
286
287 // Submit offline session to CLIENT(0) in UID(0).
288 // Should start immediately (because this is the only session).
289 mController->submit(CLIENT(0), SESSION(0), UID(0), mOfflineRequest, mClientCallback0);
290 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), 0));
291
292 // Submit real-time session to CLIENT(0).
293 // Should pause offline session and start new session, even if UID(0) is not on top.
294 mController->submit(CLIENT(0), SESSION(1), UID(0), mRealtimeRequest, mClientCallback0);
295 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(0), SESSION(0)));
296 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), SESSION(1)));
297
298 // Submit real-time session to CLIENT(0), should be queued after the previous session.
299 mController->submit(CLIENT(0), SESSION(2), UID(0), mRealtimeRequest, mClientCallback0);
300 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
301
302 // Submit real-time session to CLIENT(1) in same uid, should be queued after the previous
303 // session.
304 mController->submit(CLIENT(1), SESSION(0), UID(0), mRealtimeRequest, mClientCallback1);
305 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
306
307 // Submit real-time session to CLIENT(2) in UID(1).
308 // Should pause previous session and start new session, because UID(1) is (has been) top.
309 mController->submit(CLIENT(2), SESSION(0), UID(1), mRealtimeRequest, mClientCallback2);
310 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(0), SESSION(1)));
311 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(2), SESSION(0)));
312
313 // Submit offline session, shouldn't generate any event.
314 mController->submit(CLIENT(2), SESSION(1), UID(1), mOfflineRequest, mClientCallback2);
315 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
316
317 // Bring UID(0) to top.
318 mUidPolicy->setTop(UID(0));
319 // Should pause current session, and resume last session in UID(0).
320 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(2), SESSION(0)));
321 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(0), SESSION(1)));
322}
323
324TEST_F(TranscodingSessionControllerTest, TestCancelSession) {
325 ALOGD("TestCancelSession");
326
327 // Submit real-time session SESSION(0), should start immediately.
328 mController->submit(CLIENT(0), SESSION(0), UID(0), mRealtimeRequest, mClientCallback0);
329 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), SESSION(0)));
330
331 // Submit real-time session SESSION(1), should not start.
332 mController->submit(CLIENT(0), SESSION(1), UID(0), mRealtimeRequest, mClientCallback0);
333 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
334
335 // Submit offline session SESSION(2), should not start.
336 mController->submit(CLIENT(0), SESSION(2), UID(0), mOfflineRequest, mClientCallback0);
337 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
338
339 // Cancel queued real-time session.
340 // Cancel real-time session SESSION(1), should be cancelled.
341 EXPECT_TRUE(mController->cancel(CLIENT(0), SESSION(1)));
342
343 // Cancel queued offline session.
344 // Cancel offline session SESSION(2), should be cancelled.
345 EXPECT_TRUE(mController->cancel(CLIENT(0), SESSION(2)));
346
347 // Submit offline session SESSION(3), shouldn't cause any event.
348 mController->submit(CLIENT(0), SESSION(3), UID(0), mOfflineRequest, mClientCallback0);
349 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
350
351 // Cancel running real-time session SESSION(0).
352 // - Should be stopped first then cancelled.
353 // - Should also start offline session SESSION(2) because real-time queue is empty.
354 EXPECT_TRUE(mController->cancel(CLIENT(0), SESSION(0)));
355 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Stop(CLIENT(0), SESSION(0)));
356 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), SESSION(3)));
357
358 // Submit real-time session SESSION(4), offline SESSION(3) should pause and SESSION(4)
359 // should start.
360 mController->submit(CLIENT(0), SESSION(4), UID(0), mRealtimeRequest, mClientCallback0);
361 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(0), SESSION(3)));
362 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), SESSION(4)));
363
364 // Cancel paused SESSION(3). SESSION(3) should be stopped.
365 EXPECT_TRUE(mController->cancel(CLIENT(0), SESSION(3)));
366 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Stop(CLIENT(0), SESSION(3)));
367}
368
369TEST_F(TranscodingSessionControllerTest, TestFinishSession) {
370 ALOGD("TestFinishSession");
371
372 // Start with unspecified top UID.
373 // Finish without any sessions submitted, should be ignored.
374 mController->onFinish(CLIENT(0), SESSION(0));
375 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
376
377 // Submit offline session SESSION(0), should start immediately.
378 mController->submit(CLIENT(0), SESSION(0), UID(0), mOfflineRequest, mClientCallback0);
379 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), SESSION(0)));
380
381 // Submit real-time session SESSION(1), should pause offline session and start immediately.
382 mController->submit(CLIENT(0), SESSION(1), UID(0), mRealtimeRequest, mClientCallback0);
383 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(0), SESSION(0)));
384 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), SESSION(1)));
385
386 // Submit real-time session SESSION(2), should not start.
387 mController->submit(CLIENT(0), SESSION(2), UID(0), mRealtimeRequest, mClientCallback0);
388 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
389
390 // Finish when the session never started, should be ignored.
391 mController->onFinish(CLIENT(0), SESSION(2));
392 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
393
394 // UID(1) moves to top.
395 mUidPolicy->setTop(UID(1));
396 // Submit real-time session to CLIENT(1) in UID(1), should pause previous session and start
397 // new session.
398 mController->submit(CLIENT(1), SESSION(0), UID(1), mRealtimeRequest, mClientCallback1);
399 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(0), SESSION(1)));
400 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(1), SESSION(0)));
401
402 // Simulate Finish that arrived late, after pause issued by controller.
403 // Should still be propagated to client, but shouldn't trigger any new start.
404 mController->onFinish(CLIENT(0), SESSION(1));
405 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Finished(CLIENT(0), SESSION(1)));
406
407 // Finish running real-time session, should start next real-time session in queue.
408 mController->onFinish(CLIENT(1), SESSION(0));
409 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Finished(CLIENT(1), SESSION(0)));
410 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), SESSION(2)));
411
412 // Finish running real-time session, should resume next session (offline session) in queue.
413 mController->onFinish(CLIENT(0), SESSION(2));
414 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Finished(CLIENT(0), SESSION(2)));
415 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(0), SESSION(0)));
416
417 // Finish running offline session.
418 mController->onFinish(CLIENT(0), SESSION(0));
419 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Finished(CLIENT(0), SESSION(0)));
420
421 // Duplicate finish for last session, should be ignored.
422 mController->onFinish(CLIENT(0), SESSION(0));
423 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
424}
425
426TEST_F(TranscodingSessionControllerTest, TestFailSession) {
427 ALOGD("TestFailSession");
428
429 // Start with unspecified top UID.
430 // Fail without any sessions submitted, should be ignored.
431 mController->onError(CLIENT(0), SESSION(0), TranscodingErrorCode::kUnknown);
432 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
433
434 // Submit offline session SESSION(0), should start immediately.
435 mController->submit(CLIENT(0), SESSION(0), UID(0), mOfflineRequest, mClientCallback0);
436 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), SESSION(0)));
437
438 // Submit real-time session SESSION(1), should pause offline session and start immediately.
439 mController->submit(CLIENT(0), SESSION(1), UID(0), mRealtimeRequest, mClientCallback0);
440 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(0), SESSION(0)));
441 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), SESSION(1)));
442
443 // Submit real-time session SESSION(2), should not start.
444 mController->submit(CLIENT(0), SESSION(2), UID(0), mRealtimeRequest, mClientCallback0);
445 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
446
447 // Fail when the session never started, should be ignored.
448 mController->onError(CLIENT(0), SESSION(2), TranscodingErrorCode::kUnknown);
449 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
450
451 // UID(1) moves to top.
452 mUidPolicy->setTop(UID(1));
453 // Submit real-time session to CLIENT(1) in UID(1), should pause previous session and start
454 // new session.
455 mController->submit(CLIENT(1), SESSION(0), UID(1), mRealtimeRequest, mClientCallback1);
456 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(0), SESSION(1)));
457 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(1), SESSION(0)));
458
459 // Simulate Fail that arrived late, after pause issued by controller.
460 // Should still be propagated to client, but shouldn't trigger any new start.
461 mController->onError(CLIENT(0), SESSION(1), TranscodingErrorCode::kUnknown);
462 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Failed(CLIENT(0), SESSION(1)));
463
464 // Fail running real-time session, should start next real-time session in queue.
465 mController->onError(CLIENT(1), SESSION(0), TranscodingErrorCode::kUnknown);
466 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Failed(CLIENT(1), SESSION(0)));
467 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), SESSION(2)));
468
469 // Fail running real-time session, should resume next session (offline session) in queue.
470 mController->onError(CLIENT(0), SESSION(2), TranscodingErrorCode::kUnknown);
471 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Failed(CLIENT(0), SESSION(2)));
472 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(0), SESSION(0)));
473
474 // Fail running offline session, and test error code propagation.
475 mController->onError(CLIENT(0), SESSION(0), TranscodingErrorCode::kInvalidOperation);
476 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Failed(CLIENT(0), SESSION(0)));
477 EXPECT_EQ(mTranscoder->getLastError(), TranscodingErrorCode::kInvalidOperation);
478
479 // Duplicate fail for last session, should be ignored.
480 mController->onError(CLIENT(0), SESSION(0), TranscodingErrorCode::kUnknown);
481 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
482}
483
484TEST_F(TranscodingSessionControllerTest, TestTopUidChanged) {
485 ALOGD("TestTopUidChanged");
486
487 // Start with unspecified top UID.
488 // Submit real-time session to CLIENT(0), session should start immediately.
489 mController->submit(CLIENT(0), SESSION(0), UID(0), mRealtimeRequest, mClientCallback0);
490 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), SESSION(0)));
491
492 // Submit offline session to CLIENT(0), should not start.
493 mController->submit(CLIENT(1), SESSION(0), UID(0), mOfflineRequest, mClientCallback1);
494 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
495
496 // Move UID(1) to top.
497 mUidPolicy->setTop(UID(1));
498 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
499
500 // Submit real-time session to CLIENT(2) in different uid UID(1).
501 // Should pause previous session and start new session.
502 mController->submit(CLIENT(2), SESSION(0), UID(1), mRealtimeRequest, mClientCallback2);
503 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(0), SESSION(0)));
504 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(2), SESSION(0)));
505
506 // Bring UID(0) back to top.
507 mUidPolicy->setTop(UID(0));
508 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(2), SESSION(0)));
509 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(0), SESSION(0)));
510
511 // Bring invalid uid to top.
512 mUidPolicy->setTop(kInvalidUid);
513 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
514
515 // Finish session, next real-time session should resume.
516 mController->onFinish(CLIENT(0), SESSION(0));
517 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Finished(CLIENT(0), SESSION(0)));
518 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(2), SESSION(0)));
519
520 // Finish session, offline session should start.
521 mController->onFinish(CLIENT(2), SESSION(0));
522 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Finished(CLIENT(2), SESSION(0)));
523 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(1), SESSION(0)));
524}
525
526TEST_F(TranscodingSessionControllerTest, TestTopUidSetChanged) {
527 ALOGD("TestTopUidChanged_MultipleUids");
528
529 // Start with unspecified top UID.
530 // Submit real-time session to CLIENT(0), session should start immediately.
531 mController->submit(CLIENT(0), SESSION(0), UID(0), mRealtimeRequest, mClientCallback0);
532 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), SESSION(0)));
533
534 // Submit offline session to CLIENT(0), should not start.
535 mController->submit(CLIENT(1), SESSION(0), UID(0), mOfflineRequest, mClientCallback1);
536 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
537
538 // Set UID(0), UID(1) to top set.
539 // UID(0) should continue to run.
540 mUidPolicy->setTop({UID(0), UID(1)});
541 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
542
543 // Submit real-time session to CLIENT(2) in different uid UID(1).
544 // UID(0) should pause and UID(1) should start.
545 mController->submit(CLIENT(2), SESSION(0), UID(1), mRealtimeRequest, mClientCallback2);
546 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(0), SESSION(0)));
547 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(2), SESSION(0)));
548
549 // Remove UID(0) from top set, and only leave UID(1) in the set.
550 // UID(1) should continue to run.
551 mUidPolicy->setTop(UID(1));
552 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
553
554 // Set UID(0), UID(2) to top set.
555 // UID(1) should continue to run.
556 mUidPolicy->setTop({UID(1), UID(2)});
557 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
558
559 // Bring UID(0) back to top.
560 mUidPolicy->setTop(UID(0));
561 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(2), SESSION(0)));
562 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(0), SESSION(0)));
563
564 // Bring invalid uid to top.
565 mUidPolicy->setTop(kInvalidUid);
566 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
567
568 // Finish session, next real-time session from UID(1) should resume, even if UID(1)
569 // no longer top.
570 mController->onFinish(CLIENT(0), SESSION(0));
571 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Finished(CLIENT(0), SESSION(0)));
572 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(2), SESSION(0)));
573
574 // Finish session, offline session should start.
575 mController->onFinish(CLIENT(2), SESSION(0));
576 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Finished(CLIENT(2), SESSION(0)));
577 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(1), SESSION(0)));
578}
579
580TEST_F(TranscodingSessionControllerTest, TestResourceLost) {
581 ALOGD("TestResourceLost");
582
583 // Start with unspecified top UID.
584 // Submit real-time session to CLIENT(0), session should start immediately.
Chong Zhangeffd8962020-12-02 14:29:09 -0800585 mRealtimeRequest.clientPid = PID(0);
Chong Zhangbc062482020-10-14 16:43:53 -0700586 mController->submit(CLIENT(0), SESSION(0), UID(0), mRealtimeRequest, mClientCallback0);
587 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), SESSION(0)));
588
589 // Submit offline session to CLIENT(0), should not start.
Chong Zhangeffd8962020-12-02 14:29:09 -0800590 mOfflineRequest.clientPid = PID(0);
Chong Zhangbc062482020-10-14 16:43:53 -0700591 mController->submit(CLIENT(1), SESSION(0), UID(0), mOfflineRequest, mClientCallback1);
592 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
593
594 // Move UID(1) to top.
595 mUidPolicy->setTop(UID(1));
596 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
597
598 // Submit real-time session to CLIENT(2) in different uid UID(1).
599 // Should pause previous session and start new session.
Chong Zhangeffd8962020-12-02 14:29:09 -0800600 mRealtimeRequest.clientPid = PID(1);
Chong Zhangbc062482020-10-14 16:43:53 -0700601 mController->submit(CLIENT(2), SESSION(0), UID(1), mRealtimeRequest, mClientCallback2);
602 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(0), SESSION(0)));
603 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(2), SESSION(0)));
604
Chong Zhangeffd8962020-12-02 14:29:09 -0800605 // Test 0: No call into ResourcePolicy if resource lost is from a non-running
606 // or non-existent session.
607 mController->onResourceLost(CLIENT(0), SESSION(0));
608 EXPECT_EQ(mResourcePolicy->getPid(), kInvalidPid);
609 mController->onResourceLost(CLIENT(3), SESSION(0));
610 EXPECT_EQ(mResourcePolicy->getPid(), kInvalidPid);
611
Chong Zhangbc062482020-10-14 16:43:53 -0700612 // Test 1: No queue change during resource loss.
613 // Signal resource lost.
Chong Zhangeffd8962020-12-02 14:29:09 -0800614 mController->onResourceLost(CLIENT(2), SESSION(0));
615 EXPECT_EQ(mResourcePolicy->getPid(), PID(1));
Chong Zhangbc062482020-10-14 16:43:53 -0700616 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
617
618 // Signal resource available, CLIENT(2) should resume.
619 mController->onResourceAvailable();
620 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(2), SESSION(0)));
621
622 // Test 2: Change of queue order during resource loss.
623 // Signal resource lost.
Chong Zhangeffd8962020-12-02 14:29:09 -0800624 mController->onResourceLost(CLIENT(2), SESSION(0));
625 EXPECT_EQ(mResourcePolicy->getPid(), PID(1));
Chong Zhangbc062482020-10-14 16:43:53 -0700626 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
627
628 // Move UID(0) back to top, should have no resume due to no resource.
629 mUidPolicy->setTop(UID(0));
630 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
631
632 // Signal resource available, CLIENT(0) should resume.
633 mController->onResourceAvailable();
634 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(0), SESSION(0)));
635
636 // Test 3: Adding new queue during resource loss.
637 // Signal resource lost.
Chong Zhangeffd8962020-12-02 14:29:09 -0800638 mController->onResourceLost(CLIENT(0), SESSION(0));
639 EXPECT_EQ(mResourcePolicy->getPid(), PID(0));
Chong Zhangbc062482020-10-14 16:43:53 -0700640 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
641
642 // Move UID(2) to top.
643 mUidPolicy->setTop(UID(2));
644
645 // Submit real-time session to CLIENT(3) in UID(2), session shouldn't start due to no resource.
Chong Zhangeffd8962020-12-02 14:29:09 -0800646 mRealtimeRequest.clientPid = PID(2);
Chong Zhangbc062482020-10-14 16:43:53 -0700647 mController->submit(CLIENT(3), SESSION(0), UID(2), mRealtimeRequest, mClientCallback3);
648 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
649
650 // Signal resource available, CLIENT(3)'s session should start.
651 mController->onResourceAvailable();
652 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(3), SESSION(0)));
653}
654
655} // namespace android