blob: 9a1c2729ea594106971d1239382110c9cc6c4ef5 [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 Zhang8677f1f2021-01-21 20:37:35 +000092 void setPidResourceLost(pid_t pid) override { mResourceLostPid = pid; }
Chong Zhangeffd8962020-12-02 14:29:09 -080093 // ~ResourcePolicyInterface
94
95 pid_t getPid() {
96 pid_t result = mResourceLostPid;
97 reset();
98 return result;
99 }
100
101private:
Chong Zhang8677f1f2021-01-21 20:37:35 +0000102 void reset() { mResourceLostPid = kInvalidPid; }
Chong Zhangeffd8962020-12-02 14:29:09 -0800103 pid_t mResourceLostPid;
Chong Zhangf47a3572020-12-02 11:35:35 -0800104};
105
Chong Zhang8677f1f2021-01-21 20:37:35 +0000106class TestThermalPolicy : public ThermalPolicyInterface {
107public:
108 TestThermalPolicy() = default;
109 virtual ~TestThermalPolicy() = default;
110
111 // ThermalPolicyInterface
112 void setCallback(const std::shared_ptr<ThermalPolicyCallbackInterface>& /*cb*/) override {}
113 bool getThrottlingStatus() { return false; }
114 // ~ThermalPolicyInterface
115
116private:
117};
118
Chong Zhangbc062482020-10-14 16:43:53 -0700119class TestTranscoder : public TranscoderInterface {
120public:
121 TestTranscoder() : mLastError(TranscodingErrorCode::kUnknown) {}
122 virtual ~TestTranscoder() {}
123
124 // TranscoderInterface
125 void setCallback(const std::shared_ptr<TranscoderCallbackInterface>& /*cb*/) override {}
126
127 void start(ClientIdType clientId, SessionIdType sessionId,
128 const TranscodingRequestParcel& /*request*/,
129 const std::shared_ptr<ITranscodingClientCallback>& /*clientCallback*/) override {
130 mEventQueue.push_back(Start(clientId, sessionId));
131 }
132 void pause(ClientIdType clientId, SessionIdType sessionId) override {
133 mEventQueue.push_back(Pause(clientId, sessionId));
134 }
135 void resume(ClientIdType clientId, SessionIdType sessionId,
136 const TranscodingRequestParcel& /*request*/,
137 const std::shared_ptr<ITranscodingClientCallback>& /*clientCallback*/) override {
138 mEventQueue.push_back(Resume(clientId, sessionId));
139 }
140 void stop(ClientIdType clientId, SessionIdType sessionId) override {
141 mEventQueue.push_back(Stop(clientId, sessionId));
142 }
143
144 void onFinished(ClientIdType clientId, SessionIdType sessionId) {
145 mEventQueue.push_back(Finished(clientId, sessionId));
146 }
147
148 void onFailed(ClientIdType clientId, SessionIdType sessionId, TranscodingErrorCode err) {
149 mLastError = err;
150 mEventQueue.push_back(Failed(clientId, sessionId));
151 }
152
153 TranscodingErrorCode getLastError() {
154 TranscodingErrorCode result = mLastError;
155 mLastError = TranscodingErrorCode::kUnknown;
156 return result;
157 }
158
159 struct Event {
160 enum { NoEvent, Start, Pause, Resume, Stop, Finished, Failed } type;
161 ClientIdType clientId;
162 SessionIdType sessionId;
163 };
164
165 static constexpr Event NoEvent = {Event::NoEvent, 0, 0};
166
167#define DECLARE_EVENT(action) \
168 static Event action(ClientIdType clientId, SessionIdType sessionId) { \
169 return {Event::action, clientId, sessionId}; \
170 }
171
172 DECLARE_EVENT(Start);
173 DECLARE_EVENT(Pause);
174 DECLARE_EVENT(Resume);
175 DECLARE_EVENT(Stop);
176 DECLARE_EVENT(Finished);
177 DECLARE_EVENT(Failed);
178
179 const Event& popEvent() {
180 if (mEventQueue.empty()) {
181 mPoppedEvent = NoEvent;
182 } else {
183 mPoppedEvent = *mEventQueue.begin();
184 mEventQueue.pop_front();
185 }
186 return mPoppedEvent;
187 }
188
189private:
190 Event mPoppedEvent;
191 std::list<Event> mEventQueue;
192 TranscodingErrorCode mLastError;
193};
194
195bool operator==(const TestTranscoder::Event& lhs, const TestTranscoder::Event& rhs) {
196 return lhs.type == rhs.type && lhs.clientId == rhs.clientId && lhs.sessionId == rhs.sessionId;
197}
198
199struct TestClientCallback : public BnTranscodingClientCallback {
200 TestClientCallback(TestTranscoder* owner, int64_t clientId)
201 : mOwner(owner), mClientId(clientId) {
202 ALOGD("TestClient Created");
203 }
204
205 Status openFileDescriptor(const std::string& /*in_fileUri*/, const std::string& /*in_mode*/,
206 ::ndk::ScopedFileDescriptor* /*_aidl_return*/) override {
207 return Status::ok();
208 }
209
210 Status onTranscodingStarted(int32_t /*in_sessionId*/) override { return Status::ok(); }
211
212 Status onTranscodingPaused(int32_t /*in_sessionId*/) override { return Status::ok(); }
213
214 Status onTranscodingResumed(int32_t /*in_sessionId*/) override { return Status::ok(); }
215
216 Status onTranscodingFinished(int32_t in_sessionId,
217 const TranscodingResultParcel& in_result) override {
218 EXPECT_EQ(in_sessionId, in_result.sessionId);
219 ALOGD("TestClientCallback: received onTranscodingFinished");
220 mOwner->onFinished(mClientId, in_sessionId);
221 return Status::ok();
222 }
223
224 Status onTranscodingFailed(int32_t in_sessionId, TranscodingErrorCode in_errorCode) override {
225 mOwner->onFailed(mClientId, in_sessionId, in_errorCode);
226 return Status::ok();
227 }
228
229 Status onAwaitNumberOfSessionsChanged(int32_t /* in_sessionId */,
230 int32_t /* in_oldAwaitNumber */,
231 int32_t /* in_newAwaitNumber */) override {
232 return Status::ok();
233 }
234
235 Status onProgressUpdate(int32_t /* in_sessionId */, int32_t /* in_progress */) override {
236 return Status::ok();
237 }
238
239 virtual ~TestClientCallback() { ALOGI("TestClient destroyed"); };
240
241private:
242 TestTranscoder* mOwner;
243 int64_t mClientId;
244 TestClientCallback(const TestClientCallback&) = delete;
245 TestClientCallback& operator=(const TestClientCallback&) = delete;
246};
247
248class TranscodingSessionControllerTest : public ::testing::Test {
249public:
250 TranscodingSessionControllerTest() { ALOGI("TranscodingSessionControllerTest created"); }
251
252 void SetUp() override {
253 ALOGI("TranscodingSessionControllerTest set up");
254 mTranscoder.reset(new TestTranscoder());
255 mUidPolicy.reset(new TestUidPolicy());
Chong Zhangf47a3572020-12-02 11:35:35 -0800256 mResourcePolicy.reset(new TestResourcePolicy());
Chong Zhang8677f1f2021-01-21 20:37:35 +0000257 mThermalPolicy.reset(new TestThermalPolicy());
258 mController.reset(new TranscodingSessionController(mTranscoder, mUidPolicy, mResourcePolicy,
259 mThermalPolicy));
Chong Zhangbc062482020-10-14 16:43:53 -0700260 mUidPolicy->setCallback(mController);
261
262 // Set priority only, ignore other fields for now.
263 mOfflineRequest.priority = TranscodingSessionPriority::kUnspecified;
264 mRealtimeRequest.priority = TranscodingSessionPriority::kHigh;
265 mClientCallback0 =
266 ::ndk::SharedRefBase::make<TestClientCallback>(mTranscoder.get(), CLIENT(0));
267 mClientCallback1 =
268 ::ndk::SharedRefBase::make<TestClientCallback>(mTranscoder.get(), CLIENT(1));
269 mClientCallback2 =
270 ::ndk::SharedRefBase::make<TestClientCallback>(mTranscoder.get(), CLIENT(2));
271 mClientCallback3 =
272 ::ndk::SharedRefBase::make<TestClientCallback>(mTranscoder.get(), CLIENT(3));
273 }
274
275 void TearDown() override { ALOGI("TranscodingSessionControllerTest tear down"); }
276
277 ~TranscodingSessionControllerTest() { ALOGD("TranscodingSessionControllerTest destroyed"); }
278
279 std::shared_ptr<TestTranscoder> mTranscoder;
280 std::shared_ptr<TestUidPolicy> mUidPolicy;
Chong Zhangf47a3572020-12-02 11:35:35 -0800281 std::shared_ptr<TestResourcePolicy> mResourcePolicy;
Chong Zhang8677f1f2021-01-21 20:37:35 +0000282 std::shared_ptr<TestThermalPolicy> mThermalPolicy;
Chong Zhangbc062482020-10-14 16:43:53 -0700283 std::shared_ptr<TranscodingSessionController> mController;
284 TranscodingRequestParcel mOfflineRequest;
285 TranscodingRequestParcel mRealtimeRequest;
286 std::shared_ptr<TestClientCallback> mClientCallback0;
287 std::shared_ptr<TestClientCallback> mClientCallback1;
288 std::shared_ptr<TestClientCallback> mClientCallback2;
289 std::shared_ptr<TestClientCallback> mClientCallback3;
290};
291
292TEST_F(TranscodingSessionControllerTest, TestSubmitSession) {
293 ALOGD("TestSubmitSession");
294
295 // Start with UID(1) on top.
296 mUidPolicy->setTop(UID(1));
297
298 // Submit offline session to CLIENT(0) in UID(0).
299 // Should start immediately (because this is the only session).
300 mController->submit(CLIENT(0), SESSION(0), UID(0), mOfflineRequest, mClientCallback0);
301 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), 0));
302
303 // Submit real-time session to CLIENT(0).
304 // Should pause offline session and start new session, even if UID(0) is not on top.
305 mController->submit(CLIENT(0), SESSION(1), UID(0), mRealtimeRequest, mClientCallback0);
306 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(0), SESSION(0)));
307 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), SESSION(1)));
308
309 // Submit real-time session to CLIENT(0), should be queued after the previous session.
310 mController->submit(CLIENT(0), SESSION(2), UID(0), mRealtimeRequest, mClientCallback0);
311 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
312
313 // Submit real-time session to CLIENT(1) in same uid, should be queued after the previous
314 // session.
315 mController->submit(CLIENT(1), SESSION(0), UID(0), mRealtimeRequest, mClientCallback1);
316 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
317
318 // Submit real-time session to CLIENT(2) in UID(1).
319 // Should pause previous session and start new session, because UID(1) is (has been) top.
320 mController->submit(CLIENT(2), SESSION(0), UID(1), mRealtimeRequest, mClientCallback2);
321 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(0), SESSION(1)));
322 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(2), SESSION(0)));
323
324 // Submit offline session, shouldn't generate any event.
325 mController->submit(CLIENT(2), SESSION(1), UID(1), mOfflineRequest, mClientCallback2);
326 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
327
328 // Bring UID(0) to top.
329 mUidPolicy->setTop(UID(0));
330 // Should pause current session, and resume last session in UID(0).
331 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(2), SESSION(0)));
332 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(0), SESSION(1)));
333}
334
335TEST_F(TranscodingSessionControllerTest, TestCancelSession) {
336 ALOGD("TestCancelSession");
337
338 // Submit real-time session SESSION(0), should start immediately.
339 mController->submit(CLIENT(0), SESSION(0), UID(0), mRealtimeRequest, mClientCallback0);
340 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), SESSION(0)));
341
342 // Submit real-time session SESSION(1), should not start.
343 mController->submit(CLIENT(0), SESSION(1), UID(0), mRealtimeRequest, mClientCallback0);
344 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
345
346 // Submit offline session SESSION(2), should not start.
347 mController->submit(CLIENT(0), SESSION(2), UID(0), mOfflineRequest, mClientCallback0);
348 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
349
350 // Cancel queued real-time session.
351 // Cancel real-time session SESSION(1), should be cancelled.
352 EXPECT_TRUE(mController->cancel(CLIENT(0), SESSION(1)));
353
354 // Cancel queued offline session.
355 // Cancel offline session SESSION(2), should be cancelled.
356 EXPECT_TRUE(mController->cancel(CLIENT(0), SESSION(2)));
357
358 // Submit offline session SESSION(3), shouldn't cause any event.
359 mController->submit(CLIENT(0), SESSION(3), UID(0), mOfflineRequest, mClientCallback0);
360 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
361
362 // Cancel running real-time session SESSION(0).
363 // - Should be stopped first then cancelled.
364 // - Should also start offline session SESSION(2) because real-time queue is empty.
365 EXPECT_TRUE(mController->cancel(CLIENT(0), SESSION(0)));
366 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Stop(CLIENT(0), SESSION(0)));
367 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), SESSION(3)));
368
369 // Submit real-time session SESSION(4), offline SESSION(3) should pause and SESSION(4)
370 // should start.
371 mController->submit(CLIENT(0), SESSION(4), UID(0), mRealtimeRequest, mClientCallback0);
372 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(0), SESSION(3)));
373 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), SESSION(4)));
374
375 // Cancel paused SESSION(3). SESSION(3) should be stopped.
376 EXPECT_TRUE(mController->cancel(CLIENT(0), SESSION(3)));
377 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Stop(CLIENT(0), SESSION(3)));
378}
379
380TEST_F(TranscodingSessionControllerTest, TestFinishSession) {
381 ALOGD("TestFinishSession");
382
383 // Start with unspecified top UID.
384 // Finish without any sessions submitted, should be ignored.
385 mController->onFinish(CLIENT(0), SESSION(0));
386 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
387
388 // Submit offline session SESSION(0), should start immediately.
389 mController->submit(CLIENT(0), SESSION(0), UID(0), mOfflineRequest, mClientCallback0);
390 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), SESSION(0)));
391
392 // Submit real-time session SESSION(1), should pause offline session and start immediately.
393 mController->submit(CLIENT(0), SESSION(1), UID(0), mRealtimeRequest, mClientCallback0);
394 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(0), SESSION(0)));
395 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), SESSION(1)));
396
397 // Submit real-time session SESSION(2), should not start.
398 mController->submit(CLIENT(0), SESSION(2), UID(0), mRealtimeRequest, mClientCallback0);
399 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
400
401 // Finish when the session never started, should be ignored.
402 mController->onFinish(CLIENT(0), SESSION(2));
403 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
404
405 // UID(1) moves to top.
406 mUidPolicy->setTop(UID(1));
407 // Submit real-time session to CLIENT(1) in UID(1), should pause previous session and start
408 // new session.
409 mController->submit(CLIENT(1), SESSION(0), UID(1), mRealtimeRequest, mClientCallback1);
410 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(0), SESSION(1)));
411 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(1), SESSION(0)));
412
413 // Simulate Finish that arrived late, after pause issued by controller.
414 // Should still be propagated to client, but shouldn't trigger any new start.
415 mController->onFinish(CLIENT(0), SESSION(1));
416 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Finished(CLIENT(0), SESSION(1)));
417
418 // Finish running real-time session, should start next real-time session in queue.
419 mController->onFinish(CLIENT(1), SESSION(0));
420 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Finished(CLIENT(1), SESSION(0)));
421 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), SESSION(2)));
422
423 // Finish running real-time session, should resume next session (offline session) in queue.
424 mController->onFinish(CLIENT(0), SESSION(2));
425 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Finished(CLIENT(0), SESSION(2)));
426 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(0), SESSION(0)));
427
428 // Finish running offline session.
429 mController->onFinish(CLIENT(0), SESSION(0));
430 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Finished(CLIENT(0), SESSION(0)));
431
432 // Duplicate finish for last session, should be ignored.
433 mController->onFinish(CLIENT(0), SESSION(0));
434 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
435}
436
437TEST_F(TranscodingSessionControllerTest, TestFailSession) {
438 ALOGD("TestFailSession");
439
440 // Start with unspecified top UID.
441 // Fail without any sessions submitted, should be ignored.
442 mController->onError(CLIENT(0), SESSION(0), TranscodingErrorCode::kUnknown);
443 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
444
445 // Submit offline session SESSION(0), should start immediately.
446 mController->submit(CLIENT(0), SESSION(0), UID(0), mOfflineRequest, mClientCallback0);
447 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), SESSION(0)));
448
449 // Submit real-time session SESSION(1), should pause offline session and start immediately.
450 mController->submit(CLIENT(0), SESSION(1), UID(0), mRealtimeRequest, mClientCallback0);
451 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(0), SESSION(0)));
452 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), SESSION(1)));
453
454 // Submit real-time session SESSION(2), should not start.
455 mController->submit(CLIENT(0), SESSION(2), UID(0), mRealtimeRequest, mClientCallback0);
456 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
457
458 // Fail when the session never started, should be ignored.
459 mController->onError(CLIENT(0), SESSION(2), TranscodingErrorCode::kUnknown);
460 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
461
462 // UID(1) moves to top.
463 mUidPolicy->setTop(UID(1));
464 // Submit real-time session to CLIENT(1) in UID(1), should pause previous session and start
465 // new session.
466 mController->submit(CLIENT(1), SESSION(0), UID(1), mRealtimeRequest, mClientCallback1);
467 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(0), SESSION(1)));
468 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(1), SESSION(0)));
469
470 // Simulate Fail that arrived late, after pause issued by controller.
471 // Should still be propagated to client, but shouldn't trigger any new start.
472 mController->onError(CLIENT(0), SESSION(1), TranscodingErrorCode::kUnknown);
473 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Failed(CLIENT(0), SESSION(1)));
474
475 // Fail running real-time session, should start next real-time session in queue.
476 mController->onError(CLIENT(1), SESSION(0), TranscodingErrorCode::kUnknown);
477 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Failed(CLIENT(1), SESSION(0)));
478 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), SESSION(2)));
479
480 // Fail running real-time session, should resume next session (offline session) in queue.
481 mController->onError(CLIENT(0), SESSION(2), TranscodingErrorCode::kUnknown);
482 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Failed(CLIENT(0), SESSION(2)));
483 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(0), SESSION(0)));
484
485 // Fail running offline session, and test error code propagation.
486 mController->onError(CLIENT(0), SESSION(0), TranscodingErrorCode::kInvalidOperation);
487 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Failed(CLIENT(0), SESSION(0)));
488 EXPECT_EQ(mTranscoder->getLastError(), TranscodingErrorCode::kInvalidOperation);
489
490 // Duplicate fail for last session, should be ignored.
491 mController->onError(CLIENT(0), SESSION(0), TranscodingErrorCode::kUnknown);
492 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
493}
494
495TEST_F(TranscodingSessionControllerTest, TestTopUidChanged) {
496 ALOGD("TestTopUidChanged");
497
498 // Start with unspecified top UID.
499 // Submit real-time session to CLIENT(0), session should start immediately.
500 mController->submit(CLIENT(0), SESSION(0), UID(0), mRealtimeRequest, mClientCallback0);
501 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), SESSION(0)));
502
503 // Submit offline session to CLIENT(0), should not start.
504 mController->submit(CLIENT(1), SESSION(0), UID(0), mOfflineRequest, mClientCallback1);
505 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
506
507 // Move UID(1) to top.
508 mUidPolicy->setTop(UID(1));
509 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
510
511 // Submit real-time session to CLIENT(2) in different uid UID(1).
512 // Should pause previous session and start new session.
513 mController->submit(CLIENT(2), SESSION(0), UID(1), mRealtimeRequest, mClientCallback2);
514 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(0), SESSION(0)));
515 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(2), SESSION(0)));
516
517 // Bring UID(0) back to top.
518 mUidPolicy->setTop(UID(0));
519 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(2), SESSION(0)));
520 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(0), SESSION(0)));
521
522 // Bring invalid uid to top.
523 mUidPolicy->setTop(kInvalidUid);
524 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
525
526 // Finish session, next real-time session should resume.
527 mController->onFinish(CLIENT(0), SESSION(0));
528 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Finished(CLIENT(0), SESSION(0)));
529 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(2), SESSION(0)));
530
531 // Finish session, offline session should start.
532 mController->onFinish(CLIENT(2), SESSION(0));
533 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Finished(CLIENT(2), SESSION(0)));
534 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(1), SESSION(0)));
535}
536
537TEST_F(TranscodingSessionControllerTest, TestTopUidSetChanged) {
538 ALOGD("TestTopUidChanged_MultipleUids");
539
540 // Start with unspecified top UID.
541 // Submit real-time session to CLIENT(0), session should start immediately.
542 mController->submit(CLIENT(0), SESSION(0), UID(0), mRealtimeRequest, mClientCallback0);
543 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), SESSION(0)));
544
545 // Submit offline session to CLIENT(0), should not start.
546 mController->submit(CLIENT(1), SESSION(0), UID(0), mOfflineRequest, mClientCallback1);
547 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
548
549 // Set UID(0), UID(1) to top set.
550 // UID(0) should continue to run.
551 mUidPolicy->setTop({UID(0), UID(1)});
552 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
553
554 // Submit real-time session to CLIENT(2) in different uid UID(1).
555 // UID(0) should pause and UID(1) should start.
556 mController->submit(CLIENT(2), SESSION(0), UID(1), mRealtimeRequest, mClientCallback2);
557 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(0), SESSION(0)));
558 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(2), SESSION(0)));
559
560 // Remove UID(0) from top set, and only leave UID(1) in the set.
561 // UID(1) should continue to run.
562 mUidPolicy->setTop(UID(1));
563 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
564
565 // Set UID(0), UID(2) to top set.
566 // UID(1) should continue to run.
567 mUidPolicy->setTop({UID(1), UID(2)});
568 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
569
570 // Bring UID(0) back to top.
571 mUidPolicy->setTop(UID(0));
572 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(2), SESSION(0)));
573 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(0), SESSION(0)));
574
575 // Bring invalid uid to top.
576 mUidPolicy->setTop(kInvalidUid);
577 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
578
579 // Finish session, next real-time session from UID(1) should resume, even if UID(1)
580 // no longer top.
581 mController->onFinish(CLIENT(0), SESSION(0));
582 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Finished(CLIENT(0), SESSION(0)));
583 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(2), SESSION(0)));
584
585 // Finish session, offline session should start.
586 mController->onFinish(CLIENT(2), SESSION(0));
587 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Finished(CLIENT(2), SESSION(0)));
588 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(1), SESSION(0)));
589}
590
Chong Zhang8677f1f2021-01-21 20:37:35 +0000591/* Test resource lost without thermal throttling */
Chong Zhangbc062482020-10-14 16:43:53 -0700592TEST_F(TranscodingSessionControllerTest, TestResourceLost) {
593 ALOGD("TestResourceLost");
594
595 // Start with unspecified top UID.
596 // Submit real-time session to CLIENT(0), session should start immediately.
Chong Zhangeffd8962020-12-02 14:29:09 -0800597 mRealtimeRequest.clientPid = PID(0);
Chong Zhangbc062482020-10-14 16:43:53 -0700598 mController->submit(CLIENT(0), SESSION(0), UID(0), mRealtimeRequest, mClientCallback0);
599 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), SESSION(0)));
600
601 // Submit offline session to CLIENT(0), should not start.
Chong Zhangeffd8962020-12-02 14:29:09 -0800602 mOfflineRequest.clientPid = PID(0);
Chong Zhangbc062482020-10-14 16:43:53 -0700603 mController->submit(CLIENT(1), SESSION(0), UID(0), mOfflineRequest, mClientCallback1);
604 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
605
606 // Move UID(1) to top.
607 mUidPolicy->setTop(UID(1));
608 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
609
610 // Submit real-time session to CLIENT(2) in different uid UID(1).
611 // Should pause previous session and start new session.
Chong Zhangeffd8962020-12-02 14:29:09 -0800612 mRealtimeRequest.clientPid = PID(1);
Chong Zhangbc062482020-10-14 16:43:53 -0700613 mController->submit(CLIENT(2), SESSION(0), UID(1), mRealtimeRequest, mClientCallback2);
614 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(0), SESSION(0)));
615 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(2), SESSION(0)));
616
Chong Zhangeffd8962020-12-02 14:29:09 -0800617 // Test 0: No call into ResourcePolicy if resource lost is from a non-running
618 // or non-existent session.
619 mController->onResourceLost(CLIENT(0), SESSION(0));
620 EXPECT_EQ(mResourcePolicy->getPid(), kInvalidPid);
621 mController->onResourceLost(CLIENT(3), SESSION(0));
622 EXPECT_EQ(mResourcePolicy->getPid(), kInvalidPid);
623
Chong Zhangbc062482020-10-14 16:43:53 -0700624 // Test 1: No queue change during resource loss.
625 // Signal resource lost.
Chong Zhangeffd8962020-12-02 14:29:09 -0800626 mController->onResourceLost(CLIENT(2), SESSION(0));
627 EXPECT_EQ(mResourcePolicy->getPid(), PID(1));
Chong Zhangbc062482020-10-14 16:43:53 -0700628 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
629
630 // Signal resource available, CLIENT(2) should resume.
631 mController->onResourceAvailable();
632 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(2), SESSION(0)));
633
634 // Test 2: Change of queue order during resource loss.
635 // Signal resource lost.
Chong Zhangeffd8962020-12-02 14:29:09 -0800636 mController->onResourceLost(CLIENT(2), SESSION(0));
637 EXPECT_EQ(mResourcePolicy->getPid(), PID(1));
Chong Zhangbc062482020-10-14 16:43:53 -0700638 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
639
640 // Move UID(0) back to top, should have no resume due to no resource.
641 mUidPolicy->setTop(UID(0));
642 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
643
644 // Signal resource available, CLIENT(0) should resume.
645 mController->onResourceAvailable();
646 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(0), SESSION(0)));
647
Chong Zhang8677f1f2021-01-21 20:37:35 +0000648 // Test 3:
Chong Zhangeffd8962020-12-02 14:29:09 -0800649 mController->onResourceLost(CLIENT(0), SESSION(0));
650 EXPECT_EQ(mResourcePolicy->getPid(), PID(0));
Chong Zhangbc062482020-10-14 16:43:53 -0700651 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
Chong Zhang8677f1f2021-01-21 20:37:35 +0000652 // Cancel the paused top session during resource lost.
653 EXPECT_TRUE(mController->cancel(CLIENT(0), SESSION(0)));
654 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Stop(CLIENT(0), SESSION(0)));
655 // Signal resource available, CLIENT(2)'s session should start.
656 mController->onResourceAvailable();
657 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(2), SESSION(0)));
658
659 // Test 4: Adding new queue during resource loss.
660 // Signal resource lost.
661 mController->onResourceLost(CLIENT(2), SESSION(0));
662 EXPECT_EQ(mResourcePolicy->getPid(), PID(1));
663 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
Chong Zhangbc062482020-10-14 16:43:53 -0700664
665 // Move UID(2) to top.
666 mUidPolicy->setTop(UID(2));
667
668 // 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 -0800669 mRealtimeRequest.clientPid = PID(2);
Chong Zhangbc062482020-10-14 16:43:53 -0700670 mController->submit(CLIENT(3), SESSION(0), UID(2), mRealtimeRequest, mClientCallback3);
671 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
672
673 // Signal resource available, CLIENT(3)'s session should start.
674 mController->onResourceAvailable();
675 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(3), SESSION(0)));
676}
677
Chong Zhang8677f1f2021-01-21 20:37:35 +0000678/* Test thermal throttling without resource lost */
679TEST_F(TranscodingSessionControllerTest, TestThermalCallback) {
680 ALOGD("TestThermalCallback");
681
682 // Start with unspecified top UID.
683 // Submit real-time session to CLIENT(0), session should start immediately.
684 mRealtimeRequest.clientPid = PID(0);
685 mController->submit(CLIENT(0), SESSION(0), UID(0), mRealtimeRequest, mClientCallback0);
686 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), SESSION(0)));
687
688 // Submit offline session to CLIENT(0), should not start.
689 mOfflineRequest.clientPid = PID(0);
690 mController->submit(CLIENT(1), SESSION(0), UID(0), mOfflineRequest, mClientCallback1);
691 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
692
693 // Move UID(1) to top.
694 mUidPolicy->setTop(UID(1));
695 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
696
697 // Submit real-time session to CLIENT(2) in different uid UID(1).
698 // Should pause previous session and start new session.
699 mRealtimeRequest.clientPid = PID(1);
700 mController->submit(CLIENT(2), SESSION(0), UID(1), mRealtimeRequest, mClientCallback2);
701 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(0), SESSION(0)));
702 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(2), SESSION(0)));
703
704 // Test 0: Basic case, no queue change during throttling, top session should pause/resume
705 // with throttling.
706 mController->onThrottlingStarted();
707 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(2), SESSION(0)));
708 mController->onThrottlingStopped();
709 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(2), SESSION(0)));
710
711 // Test 1: Change of queue order during thermal throttling, when throttling stops,
712 // new top session should resume.
713 mController->onThrottlingStarted();
714 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(2), SESSION(0)));
715 mUidPolicy->setTop(UID(0));
716 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
717 mController->onThrottlingStopped();
718 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(0), SESSION(0)));
719
720 // Test 2: Cancel session during throttling, when throttling stops, new top
721 // session should resume.
722 mController->onThrottlingStarted();
723 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(0), SESSION(0)));
724 // Cancel the paused top session during throttling.
725 EXPECT_TRUE(mController->cancel(CLIENT(0), SESSION(0)));
726 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Stop(CLIENT(0), SESSION(0)));
727 // Throttling stops, CLIENT(2)'s session should start.
728 mController->onThrottlingStopped();
729 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(2), SESSION(0)));
730
731 // Test 3: Add new queue during throttling, when throttling stops, new top
732 // session should resume.
733 mController->onThrottlingStarted();
734 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(2), SESSION(0)));
735 // Move UID(2) to top.
736 mUidPolicy->setTop(UID(2));
737 // Submit real-time session to CLIENT(3) in UID(2), session shouldn't start during throttling.
738 mRealtimeRequest.clientPid = PID(2);
739 mController->submit(CLIENT(3), SESSION(0), UID(2), mRealtimeRequest, mClientCallback3);
740 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
741 // Throttling stops, CLIENT(3)'s session should start.
742 mController->onThrottlingStopped();
743 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(3), SESSION(0)));
744}
745
746/* Test resource lost and thermal throttling happening simultaneously */
747TEST_F(TranscodingSessionControllerTest, TestResourceLostAndThermalCallback) {
748 ALOGD("TestResourceLostAndThermalCallback");
749
750 // Start with unspecified top UID.
751 // Submit real-time session to CLIENT(0), session should start immediately.
752 mRealtimeRequest.clientPid = PID(0);
753 mController->submit(CLIENT(0), SESSION(0), UID(0), mRealtimeRequest, mClientCallback0);
754 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), SESSION(0)));
755
756 // Submit offline session to CLIENT(0), should not start.
757 mOfflineRequest.clientPid = PID(0);
758 mController->submit(CLIENT(1), SESSION(0), UID(0), mOfflineRequest, mClientCallback1);
759 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
760
761 // Move UID(1) to top.
762 mUidPolicy->setTop(UID(1));
763 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
764
765 // Submit real-time session to CLIENT(2) in different uid UID(1).
766 // Should pause previous session and start new session.
767 mRealtimeRequest.clientPid = PID(1);
768 mController->submit(CLIENT(2), SESSION(0), UID(1), mRealtimeRequest, mClientCallback2);
769 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(0), SESSION(0)));
770 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(2), SESSION(0)));
771
772 // Test 0: Resource lost during throttling.
773 // Throttling starts, top session should pause.
774 mController->onThrottlingStarted();
775 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(2), SESSION(0)));
776 // Signal resource lost, this should get ignored because the session is now paused.
777 mController->onResourceLost(CLIENT(2), SESSION(0));
778 EXPECT_EQ(mResourcePolicy->getPid(), kInvalidPid);
779 // Signal resource available, CLIENT(2) shouldn't resume.
780 mController->onResourceAvailable();
781 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
782 // Throttling ends, top session should resume.
783 mController->onThrottlingStopped();
784 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(2), SESSION(0)));
785
786 // Test 1: Throttling during resource lost.
787 mController->onResourceLost(CLIENT(2), SESSION(0));
788 EXPECT_EQ(mResourcePolicy->getPid(), PID(1));
789 mController->onThrottlingStarted();
790 mController->onThrottlingStopped();
791 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
792 mController->onResourceAvailable();
793 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(2), SESSION(0)));
794
795 // Test 2: Interleaving resource lost and throttling.
796 mController->onResourceLost(CLIENT(2), SESSION(0));
797 EXPECT_EQ(mResourcePolicy->getPid(), PID(1));
798 mController->onThrottlingStarted();
799 mController->onResourceAvailable();
800 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
801 mController->onThrottlingStopped();
802 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(2), SESSION(0)));
803}
804
Chong Zhangbc062482020-10-14 16:43:53 -0700805} // namespace android