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