blob: 560d1fe0ebcc5b0022537b0e2c834159a543be99 [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:
Chong Zhang87d199c2021-03-01 19:02:18 -0800121 TestTranscoder() : mGeneration(0) {}
Chong Zhangbc062482020-10-14 16:43:53 -0700122 virtual ~TestTranscoder() {}
123
124 // TranscoderInterface
Chong Zhangbc062482020-10-14 16:43:53 -0700125 void start(ClientIdType clientId, SessionIdType sessionId,
Linus Nilssona99f4042021-02-25 15:49:43 -0800126 const TranscodingRequestParcel& /*request*/, uid_t /*callingUid*/,
Chong Zhangbc062482020-10-14 16:43:53 -0700127 const std::shared_ptr<ITranscodingClientCallback>& /*clientCallback*/) override {
Chong Zhang457c6892021-02-01 15:34:20 -0800128 append(Start(clientId, sessionId));
Chong Zhangbc062482020-10-14 16:43:53 -0700129 }
130 void pause(ClientIdType clientId, SessionIdType sessionId) override {
Chong Zhang457c6892021-02-01 15:34:20 -0800131 append(Pause(clientId, sessionId));
Chong Zhangbc062482020-10-14 16:43:53 -0700132 }
133 void resume(ClientIdType clientId, SessionIdType sessionId,
Linus Nilssona99f4042021-02-25 15:49:43 -0800134 const TranscodingRequestParcel& /*request*/, uid_t /*callingUid*/,
Chong Zhangbc062482020-10-14 16:43:53 -0700135 const std::shared_ptr<ITranscodingClientCallback>& /*clientCallback*/) override {
Chong Zhang457c6892021-02-01 15:34:20 -0800136 append(Resume(clientId, sessionId));
Chong Zhangbc062482020-10-14 16:43:53 -0700137 }
Chong Zhang457c6892021-02-01 15:34:20 -0800138 void stop(ClientIdType clientId, SessionIdType sessionId, bool abandon) override {
139 append(abandon ? Abandon(clientId, sessionId) : Stop(clientId, sessionId));
Chong Zhangbc062482020-10-14 16:43:53 -0700140 }
141
142 void onFinished(ClientIdType clientId, SessionIdType sessionId) {
Chong Zhang457c6892021-02-01 15:34:20 -0800143 append(Finished(clientId, sessionId));
Chong Zhangbc062482020-10-14 16:43:53 -0700144 }
145
146 void onFailed(ClientIdType clientId, SessionIdType sessionId, TranscodingErrorCode err) {
Chong Zhang457c6892021-02-01 15:34:20 -0800147 append(Failed(clientId, sessionId), err);
148 }
149
150 void onCreated() {
151 std::scoped_lock lock{mLock};
152 mGeneration++;
Chong Zhangbc062482020-10-14 16:43:53 -0700153 }
154
Chong Zhangbc062482020-10-14 16:43:53 -0700155 struct Event {
Chong Zhang457c6892021-02-01 15:34:20 -0800156 enum { NoEvent, Start, Pause, Resume, Stop, Finished, Failed, Abandon } type;
Chong Zhangbc062482020-10-14 16:43:53 -0700157 ClientIdType clientId;
158 SessionIdType sessionId;
159 };
160
161 static constexpr Event NoEvent = {Event::NoEvent, 0, 0};
162
163#define DECLARE_EVENT(action) \
164 static Event action(ClientIdType clientId, SessionIdType sessionId) { \
165 return {Event::action, clientId, sessionId}; \
166 }
167
168 DECLARE_EVENT(Start);
169 DECLARE_EVENT(Pause);
170 DECLARE_EVENT(Resume);
171 DECLARE_EVENT(Stop);
172 DECLARE_EVENT(Finished);
173 DECLARE_EVENT(Failed);
Chong Zhang457c6892021-02-01 15:34:20 -0800174 DECLARE_EVENT(Abandon);
Chong Zhangbc062482020-10-14 16:43:53 -0700175
Chong Zhang457c6892021-02-01 15:34:20 -0800176 // Push 1 event to back.
177 void append(const Event& event,
178 const TranscodingErrorCode err = TranscodingErrorCode::kNoError) {
179 std::unique_lock lock(mLock);
180
181 mEventQueue.push_back(event);
182 // Error is sticky, non-error event will not erase it, only getLastError()
183 // clears last error.
184 if (err != TranscodingErrorCode::kNoError) {
Chong Zhang87d199c2021-03-01 19:02:18 -0800185 mLastErrorQueue.push_back(err);
Chong Zhang457c6892021-02-01 15:34:20 -0800186 }
187 mCondition.notify_one();
188 }
189
190 // Pop 1 event from front, wait for up to timeoutUs if empty.
191 const Event& popEvent(int64_t timeoutUs = 0) {
192 std::unique_lock lock(mLock);
193
194 if (mEventQueue.empty() && timeoutUs > 0) {
195 mCondition.wait_for(lock, std::chrono::microseconds(timeoutUs));
196 }
197
Chong Zhangbc062482020-10-14 16:43:53 -0700198 if (mEventQueue.empty()) {
199 mPoppedEvent = NoEvent;
200 } else {
201 mPoppedEvent = *mEventQueue.begin();
202 mEventQueue.pop_front();
203 }
Chong Zhang457c6892021-02-01 15:34:20 -0800204
Chong Zhangbc062482020-10-14 16:43:53 -0700205 return mPoppedEvent;
206 }
207
Chong Zhang87d199c2021-03-01 19:02:18 -0800208 TranscodingErrorCode getLastError() {
209 std::scoped_lock lock{mLock};
210 if (mLastErrorQueue.empty()) {
211 return TranscodingErrorCode::kNoError;
212 }
213 TranscodingErrorCode err = mLastErrorQueue.front();
214 mLastErrorQueue.pop_front();
215 return err;
216 }
217
218 int32_t getGeneration() {
219 std::scoped_lock lock{mLock};
220 return mGeneration;
221 }
222
Chong Zhangbc062482020-10-14 16:43:53 -0700223private:
Chong Zhang457c6892021-02-01 15:34:20 -0800224 std::mutex mLock;
225 std::condition_variable mCondition;
Chong Zhangbc062482020-10-14 16:43:53 -0700226 Event mPoppedEvent;
227 std::list<Event> mEventQueue;
Chong Zhang87d199c2021-03-01 19:02:18 -0800228 std::list<TranscodingErrorCode> mLastErrorQueue;
Chong Zhang457c6892021-02-01 15:34:20 -0800229 int32_t mGeneration;
Chong Zhangbc062482020-10-14 16:43:53 -0700230};
231
232bool operator==(const TestTranscoder::Event& lhs, const TestTranscoder::Event& rhs) {
233 return lhs.type == rhs.type && lhs.clientId == rhs.clientId && lhs.sessionId == rhs.sessionId;
234}
235
236struct TestClientCallback : public BnTranscodingClientCallback {
237 TestClientCallback(TestTranscoder* owner, int64_t clientId)
238 : mOwner(owner), mClientId(clientId) {
239 ALOGD("TestClient Created");
240 }
241
242 Status openFileDescriptor(const std::string& /*in_fileUri*/, const std::string& /*in_mode*/,
243 ::ndk::ScopedFileDescriptor* /*_aidl_return*/) override {
244 return Status::ok();
245 }
246
247 Status onTranscodingStarted(int32_t /*in_sessionId*/) override { return Status::ok(); }
248
249 Status onTranscodingPaused(int32_t /*in_sessionId*/) override { return Status::ok(); }
250
251 Status onTranscodingResumed(int32_t /*in_sessionId*/) override { return Status::ok(); }
252
253 Status onTranscodingFinished(int32_t in_sessionId,
254 const TranscodingResultParcel& in_result) override {
255 EXPECT_EQ(in_sessionId, in_result.sessionId);
256 ALOGD("TestClientCallback: received onTranscodingFinished");
257 mOwner->onFinished(mClientId, in_sessionId);
258 return Status::ok();
259 }
260
261 Status onTranscodingFailed(int32_t in_sessionId, TranscodingErrorCode in_errorCode) override {
262 mOwner->onFailed(mClientId, in_sessionId, in_errorCode);
263 return Status::ok();
264 }
265
266 Status onAwaitNumberOfSessionsChanged(int32_t /* in_sessionId */,
267 int32_t /* in_oldAwaitNumber */,
268 int32_t /* in_newAwaitNumber */) override {
269 return Status::ok();
270 }
271
272 Status onProgressUpdate(int32_t /* in_sessionId */, int32_t /* in_progress */) override {
273 return Status::ok();
274 }
275
276 virtual ~TestClientCallback() { ALOGI("TestClient destroyed"); };
277
278private:
279 TestTranscoder* mOwner;
280 int64_t mClientId;
281 TestClientCallback(const TestClientCallback&) = delete;
282 TestClientCallback& operator=(const TestClientCallback&) = delete;
283};
284
285class TranscodingSessionControllerTest : public ::testing::Test {
286public:
287 TranscodingSessionControllerTest() { ALOGI("TranscodingSessionControllerTest created"); }
Chong Zhang457c6892021-02-01 15:34:20 -0800288 ~TranscodingSessionControllerTest() { ALOGD("TranscodingSessionControllerTest destroyed"); }
Chong Zhangbc062482020-10-14 16:43:53 -0700289
290 void SetUp() override {
291 ALOGI("TranscodingSessionControllerTest set up");
292 mTranscoder.reset(new TestTranscoder());
293 mUidPolicy.reset(new TestUidPolicy());
Chong Zhangf47a3572020-12-02 11:35:35 -0800294 mResourcePolicy.reset(new TestResourcePolicy());
Chong Zhang8677f1f2021-01-21 20:37:35 +0000295 mThermalPolicy.reset(new TestThermalPolicy());
Chong Zhang87d199c2021-03-01 19:02:18 -0800296 // Overrid default burst params with shorter values for testing.
297 TranscodingSessionController::ControllerConfig config = {
298 .pacerBurstThresholdMs = 500,
299 .pacerBurstCountQuota = 10,
300 .pacerBurstTimeQuotaSeconds = 3,
301 };
Chong Zhang457c6892021-02-01 15:34:20 -0800302 mController.reset(new TranscodingSessionController(
Chong Zhang87d199c2021-03-01 19:02:18 -0800303 [this](const std::shared_ptr<TranscoderCallbackInterface>& /*cb*/) {
Chong Zhang457c6892021-02-01 15:34:20 -0800304 // Here we require that the SessionController clears out all its refcounts of
305 // the transcoder object when it calls create.
306 EXPECT_EQ(mTranscoder.use_count(), 1);
307 mTranscoder->onCreated();
308 return mTranscoder;
309 },
Chong Zhang87d199c2021-03-01 19:02:18 -0800310 mUidPolicy, mResourcePolicy, mThermalPolicy, &config));
Chong Zhangbc062482020-10-14 16:43:53 -0700311 mUidPolicy->setCallback(mController);
312
313 // Set priority only, ignore other fields for now.
314 mOfflineRequest.priority = TranscodingSessionPriority::kUnspecified;
315 mRealtimeRequest.priority = TranscodingSessionPriority::kHigh;
316 mClientCallback0 =
317 ::ndk::SharedRefBase::make<TestClientCallback>(mTranscoder.get(), CLIENT(0));
318 mClientCallback1 =
319 ::ndk::SharedRefBase::make<TestClientCallback>(mTranscoder.get(), CLIENT(1));
320 mClientCallback2 =
321 ::ndk::SharedRefBase::make<TestClientCallback>(mTranscoder.get(), CLIENT(2));
322 mClientCallback3 =
323 ::ndk::SharedRefBase::make<TestClientCallback>(mTranscoder.get(), CLIENT(3));
324 }
325
326 void TearDown() override { ALOGI("TranscodingSessionControllerTest tear down"); }
327
Chong Zhang457c6892021-02-01 15:34:20 -0800328 void expectTimeout(int64_t clientId, int32_t sessionId, int32_t generation) {
329 EXPECT_EQ(mTranscoder->popEvent(2900000), TestTranscoder::NoEvent);
330 EXPECT_EQ(mTranscoder->popEvent(200000), TestTranscoder::Abandon(clientId, sessionId));
331 EXPECT_EQ(mTranscoder->popEvent(100000), TestTranscoder::Failed(clientId, sessionId));
332 EXPECT_EQ(mTranscoder->getLastError(), TranscodingErrorCode::kWatchdogTimeout);
333 // Should have created new transcoder.
334 EXPECT_EQ(mTranscoder->getGeneration(), generation);
335 EXPECT_EQ(mTranscoder.use_count(), 2);
336 }
Chong Zhangbc062482020-10-14 16:43:53 -0700337
Chong Zhang87d199c2021-03-01 19:02:18 -0800338 void testPacerHelper(int numSubmits, int sessionDurationMs, int expectedSuccess,
339 bool pauseLastSuccessSession = false) {
340 for (int i = 0; i < numSubmits; i++) {
341 mController->submit(CLIENT(0), SESSION(i), UID(0), UID(0),
342 mRealtimeRequest, mClientCallback0);
343 }
344 for (int i = 0; i < expectedSuccess; i++) {
345 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), SESSION(i)));
346 if ((i == expectedSuccess - 1) && pauseLastSuccessSession) {
347 // Insert a pause of 3 sec to the last success running session
348 mController->onThrottlingStarted();
349 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(0), SESSION(i)));
350 sleep(3);
351 mController->onThrottlingStopped();
352 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(0), SESSION(i)));
353 }
354 usleep(sessionDurationMs * 1000);
355 // Test half of Finish and half of Error, both should be counted as burst runs.
356 if (i & 1) {
357 mController->onFinish(CLIENT(0), SESSION(i));
358 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Finished(CLIENT(0), SESSION(i)));
359 } else {
360 mController->onError(CLIENT(0), SESSION(i), TranscodingErrorCode::kUnknown);
361 EXPECT_EQ(mTranscoder->popEvent(100000),
362 TestTranscoder::Failed(CLIENT(0), SESSION(i)));
363 EXPECT_EQ(mTranscoder->getLastError(), TranscodingErrorCode::kUnknown);
364 }
365 }
366 for (int i = expectedSuccess; i < numSubmits; i++) {
367 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Failed(CLIENT(0), SESSION(i)));
368 EXPECT_EQ(mTranscoder->getLastError(), TranscodingErrorCode::kDroppedByService);
369 }
370 }
371
Chong Zhangbc062482020-10-14 16:43:53 -0700372 std::shared_ptr<TestTranscoder> mTranscoder;
373 std::shared_ptr<TestUidPolicy> mUidPolicy;
Chong Zhangf47a3572020-12-02 11:35:35 -0800374 std::shared_ptr<TestResourcePolicy> mResourcePolicy;
Chong Zhang8677f1f2021-01-21 20:37:35 +0000375 std::shared_ptr<TestThermalPolicy> mThermalPolicy;
Chong Zhangbc062482020-10-14 16:43:53 -0700376 std::shared_ptr<TranscodingSessionController> mController;
377 TranscodingRequestParcel mOfflineRequest;
378 TranscodingRequestParcel mRealtimeRequest;
379 std::shared_ptr<TestClientCallback> mClientCallback0;
380 std::shared_ptr<TestClientCallback> mClientCallback1;
381 std::shared_ptr<TestClientCallback> mClientCallback2;
382 std::shared_ptr<TestClientCallback> mClientCallback3;
383};
384
385TEST_F(TranscodingSessionControllerTest, TestSubmitSession) {
386 ALOGD("TestSubmitSession");
387
388 // Start with UID(1) on top.
389 mUidPolicy->setTop(UID(1));
390
391 // Submit offline session to CLIENT(0) in UID(0).
392 // Should start immediately (because this is the only session).
Linus Nilssona99f4042021-02-25 15:49:43 -0800393 mController->submit(CLIENT(0), SESSION(0), UID(0), UID(0), mOfflineRequest, mClientCallback0);
Chong Zhangbc062482020-10-14 16:43:53 -0700394 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), 0));
395
396 // Submit real-time session to CLIENT(0).
397 // Should pause offline session and start new session, even if UID(0) is not on top.
Linus Nilssona99f4042021-02-25 15:49:43 -0800398 mController->submit(CLIENT(0), SESSION(1), UID(0), UID(0), mRealtimeRequest, mClientCallback0);
Chong Zhangbc062482020-10-14 16:43:53 -0700399 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(0), SESSION(0)));
400 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), SESSION(1)));
401
402 // Submit real-time session to CLIENT(0), should be queued after the previous session.
Linus Nilssona99f4042021-02-25 15:49:43 -0800403 mController->submit(CLIENT(0), SESSION(2), UID(0), UID(0), mRealtimeRequest, mClientCallback0);
Chong Zhangbc062482020-10-14 16:43:53 -0700404 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
405
406 // Submit real-time session to CLIENT(1) in same uid, should be queued after the previous
407 // session.
Linus Nilssona99f4042021-02-25 15:49:43 -0800408 mController->submit(CLIENT(1), SESSION(0), UID(1), UID(0), mRealtimeRequest, mClientCallback1);
Chong Zhangbc062482020-10-14 16:43:53 -0700409 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
410
411 // Submit real-time session to CLIENT(2) in UID(1).
412 // Should pause previous session and start new session, because UID(1) is (has been) top.
Linus Nilssona99f4042021-02-25 15:49:43 -0800413 mController->submit(CLIENT(2), SESSION(0), UID(2), UID(1), mRealtimeRequest, mClientCallback2);
Chong Zhangbc062482020-10-14 16:43:53 -0700414 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(0), SESSION(1)));
415 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(2), SESSION(0)));
416
417 // Submit offline session, shouldn't generate any event.
Linus Nilssona99f4042021-02-25 15:49:43 -0800418 mController->submit(CLIENT(2), SESSION(1), UID(2), UID(1), mOfflineRequest, mClientCallback2);
Chong Zhangbc062482020-10-14 16:43:53 -0700419 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
420
421 // Bring UID(0) to top.
422 mUidPolicy->setTop(UID(0));
423 // Should pause current session, and resume last session in UID(0).
424 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(2), SESSION(0)));
425 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(0), SESSION(1)));
426}
427
428TEST_F(TranscodingSessionControllerTest, TestCancelSession) {
429 ALOGD("TestCancelSession");
430
431 // Submit real-time session SESSION(0), should start immediately.
Linus Nilssona99f4042021-02-25 15:49:43 -0800432 mController->submit(CLIENT(0), SESSION(0), UID(0), UID(0), mRealtimeRequest, mClientCallback0);
Chong Zhangbc062482020-10-14 16:43:53 -0700433 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), SESSION(0)));
434
435 // Submit real-time session SESSION(1), should not start.
Linus Nilssona99f4042021-02-25 15:49:43 -0800436 mController->submit(CLIENT(0), SESSION(1), UID(0), UID(0), mRealtimeRequest, mClientCallback0);
Chong Zhangbc062482020-10-14 16:43:53 -0700437 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
438
439 // Submit offline session SESSION(2), should not start.
Linus Nilssona99f4042021-02-25 15:49:43 -0800440 mController->submit(CLIENT(0), SESSION(2), UID(0), UID(0), mOfflineRequest, mClientCallback0);
Chong Zhangbc062482020-10-14 16:43:53 -0700441 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
442
443 // Cancel queued real-time session.
444 // Cancel real-time session SESSION(1), should be cancelled.
445 EXPECT_TRUE(mController->cancel(CLIENT(0), SESSION(1)));
446
447 // Cancel queued offline session.
448 // Cancel offline session SESSION(2), should be cancelled.
449 EXPECT_TRUE(mController->cancel(CLIENT(0), SESSION(2)));
450
451 // Submit offline session SESSION(3), shouldn't cause any event.
Linus Nilssona99f4042021-02-25 15:49:43 -0800452 mController->submit(CLIENT(0), SESSION(3), UID(0), UID(0), mOfflineRequest, mClientCallback0);
Chong Zhangbc062482020-10-14 16:43:53 -0700453 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
454
455 // Cancel running real-time session SESSION(0).
456 // - Should be stopped first then cancelled.
457 // - Should also start offline session SESSION(2) because real-time queue is empty.
458 EXPECT_TRUE(mController->cancel(CLIENT(0), SESSION(0)));
459 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Stop(CLIENT(0), SESSION(0)));
460 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), SESSION(3)));
461
462 // Submit real-time session SESSION(4), offline SESSION(3) should pause and SESSION(4)
463 // should start.
Linus Nilssona99f4042021-02-25 15:49:43 -0800464 mController->submit(CLIENT(0), SESSION(4), UID(0), UID(0), mRealtimeRequest, mClientCallback0);
Chong Zhangbc062482020-10-14 16:43:53 -0700465 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(0), SESSION(3)));
466 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), SESSION(4)));
467
468 // Cancel paused SESSION(3). SESSION(3) should be stopped.
469 EXPECT_TRUE(mController->cancel(CLIENT(0), SESSION(3)));
470 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Stop(CLIENT(0), SESSION(3)));
471}
472
473TEST_F(TranscodingSessionControllerTest, TestFinishSession) {
474 ALOGD("TestFinishSession");
475
476 // Start with unspecified top UID.
477 // Finish without any sessions submitted, should be ignored.
478 mController->onFinish(CLIENT(0), SESSION(0));
479 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
480
481 // Submit offline session SESSION(0), should start immediately.
Linus Nilssona99f4042021-02-25 15:49:43 -0800482 mController->submit(CLIENT(0), SESSION(0), UID(0), UID(0), mOfflineRequest, mClientCallback0);
Chong Zhangbc062482020-10-14 16:43:53 -0700483 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), SESSION(0)));
484
485 // Submit real-time session SESSION(1), should pause offline session and start immediately.
Linus Nilssona99f4042021-02-25 15:49:43 -0800486 mController->submit(CLIENT(0), SESSION(1), UID(0), UID(0), mRealtimeRequest, mClientCallback0);
Chong Zhangbc062482020-10-14 16:43:53 -0700487 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(0), SESSION(0)));
488 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), SESSION(1)));
489
490 // Submit real-time session SESSION(2), should not start.
Linus Nilssona99f4042021-02-25 15:49:43 -0800491 mController->submit(CLIENT(0), SESSION(2), UID(0), UID(0), mRealtimeRequest, mClientCallback0);
Chong Zhangbc062482020-10-14 16:43:53 -0700492 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
493
494 // Finish when the session never started, should be ignored.
495 mController->onFinish(CLIENT(0), SESSION(2));
496 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
497
498 // UID(1) moves to top.
499 mUidPolicy->setTop(UID(1));
500 // Submit real-time session to CLIENT(1) in UID(1), should pause previous session and start
501 // new session.
Linus Nilssona99f4042021-02-25 15:49:43 -0800502 mController->submit(CLIENT(1), SESSION(0), UID(1), UID(1), mRealtimeRequest, mClientCallback1);
Chong Zhangbc062482020-10-14 16:43:53 -0700503 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(0), SESSION(1)));
504 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(1), SESSION(0)));
505
506 // Simulate Finish that arrived late, after pause issued by controller.
507 // Should still be propagated to client, but shouldn't trigger any new start.
508 mController->onFinish(CLIENT(0), SESSION(1));
509 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Finished(CLIENT(0), SESSION(1)));
510
511 // Finish running real-time session, should start next real-time session in queue.
512 mController->onFinish(CLIENT(1), SESSION(0));
513 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Finished(CLIENT(1), SESSION(0)));
514 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), SESSION(2)));
515
516 // Finish running real-time session, should resume next session (offline session) in queue.
517 mController->onFinish(CLIENT(0), SESSION(2));
518 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Finished(CLIENT(0), SESSION(2)));
519 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(0), SESSION(0)));
520
521 // Finish running offline session.
522 mController->onFinish(CLIENT(0), SESSION(0));
523 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Finished(CLIENT(0), SESSION(0)));
524
525 // Duplicate finish for last session, should be ignored.
526 mController->onFinish(CLIENT(0), SESSION(0));
527 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
528}
529
530TEST_F(TranscodingSessionControllerTest, TestFailSession) {
531 ALOGD("TestFailSession");
532
533 // Start with unspecified top UID.
534 // Fail without any sessions submitted, should be ignored.
535 mController->onError(CLIENT(0), SESSION(0), TranscodingErrorCode::kUnknown);
536 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
537
538 // Submit offline session SESSION(0), should start immediately.
Linus Nilssona99f4042021-02-25 15:49:43 -0800539 mController->submit(CLIENT(0), SESSION(0), UID(0), UID(0), mOfflineRequest, mClientCallback0);
Chong Zhangbc062482020-10-14 16:43:53 -0700540 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), SESSION(0)));
541
542 // Submit real-time session SESSION(1), should pause offline session and start immediately.
Linus Nilssona99f4042021-02-25 15:49:43 -0800543 mController->submit(CLIENT(0), SESSION(1), UID(0), UID(0), mRealtimeRequest, mClientCallback0);
Chong Zhangbc062482020-10-14 16:43:53 -0700544 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(0), SESSION(0)));
545 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), SESSION(1)));
546
547 // Submit real-time session SESSION(2), should not start.
Linus Nilssona99f4042021-02-25 15:49:43 -0800548 mController->submit(CLIENT(0), SESSION(2), UID(0), UID(0), mRealtimeRequest, mClientCallback0);
Chong Zhangbc062482020-10-14 16:43:53 -0700549 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
550
551 // Fail when the session never started, should be ignored.
552 mController->onError(CLIENT(0), SESSION(2), TranscodingErrorCode::kUnknown);
553 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
554
555 // UID(1) moves to top.
556 mUidPolicy->setTop(UID(1));
557 // Submit real-time session to CLIENT(1) in UID(1), should pause previous session and start
558 // new session.
Linus Nilssona99f4042021-02-25 15:49:43 -0800559 mController->submit(CLIENT(1), SESSION(0), UID(1), UID(1), mRealtimeRequest, mClientCallback1);
Chong Zhangbc062482020-10-14 16:43:53 -0700560 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(0), SESSION(1)));
561 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(1), SESSION(0)));
562
563 // Simulate Fail that arrived late, after pause issued by controller.
564 // Should still be propagated to client, but shouldn't trigger any new start.
565 mController->onError(CLIENT(0), SESSION(1), TranscodingErrorCode::kUnknown);
566 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Failed(CLIENT(0), SESSION(1)));
Chong Zhang87d199c2021-03-01 19:02:18 -0800567 EXPECT_EQ(mTranscoder->getLastError(), TranscodingErrorCode::kUnknown);
Chong Zhangbc062482020-10-14 16:43:53 -0700568
569 // Fail running real-time session, should start next real-time session in queue.
570 mController->onError(CLIENT(1), SESSION(0), TranscodingErrorCode::kUnknown);
571 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Failed(CLIENT(1), SESSION(0)));
Chong Zhang87d199c2021-03-01 19:02:18 -0800572 EXPECT_EQ(mTranscoder->getLastError(), TranscodingErrorCode::kUnknown);
Chong Zhangbc062482020-10-14 16:43:53 -0700573 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), SESSION(2)));
574
575 // Fail running real-time session, should resume next session (offline session) in queue.
576 mController->onError(CLIENT(0), SESSION(2), TranscodingErrorCode::kUnknown);
577 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Failed(CLIENT(0), SESSION(2)));
Chong Zhang87d199c2021-03-01 19:02:18 -0800578 EXPECT_EQ(mTranscoder->getLastError(), TranscodingErrorCode::kUnknown);
Chong Zhangbc062482020-10-14 16:43:53 -0700579 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(0), SESSION(0)));
580
581 // Fail running offline session, and test error code propagation.
582 mController->onError(CLIENT(0), SESSION(0), TranscodingErrorCode::kInvalidOperation);
583 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Failed(CLIENT(0), SESSION(0)));
584 EXPECT_EQ(mTranscoder->getLastError(), TranscodingErrorCode::kInvalidOperation);
585
586 // Duplicate fail for last session, should be ignored.
587 mController->onError(CLIENT(0), SESSION(0), TranscodingErrorCode::kUnknown);
588 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
589}
590
591TEST_F(TranscodingSessionControllerTest, TestTopUidChanged) {
592 ALOGD("TestTopUidChanged");
593
594 // Start with unspecified top UID.
595 // Submit real-time session to CLIENT(0), session should start immediately.
Linus Nilssona99f4042021-02-25 15:49:43 -0800596 mController->submit(CLIENT(0), SESSION(0), UID(0), UID(0), mRealtimeRequest, mClientCallback0);
Chong Zhangbc062482020-10-14 16:43:53 -0700597 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), SESSION(0)));
598
599 // Submit offline session to CLIENT(0), should not start.
Linus Nilssona99f4042021-02-25 15:49:43 -0800600 mController->submit(CLIENT(1), SESSION(0), UID(1), UID(0), mOfflineRequest, mClientCallback1);
Chong Zhangbc062482020-10-14 16:43:53 -0700601 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
602
603 // Move UID(1) to top.
604 mUidPolicy->setTop(UID(1));
605 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
606
607 // Submit real-time session to CLIENT(2) in different uid UID(1).
608 // Should pause previous session and start new session.
Linus Nilssona99f4042021-02-25 15:49:43 -0800609 mController->submit(CLIENT(2), SESSION(0), UID(2), UID(1), mRealtimeRequest, mClientCallback2);
Chong Zhangbc062482020-10-14 16:43:53 -0700610 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(0), SESSION(0)));
611 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(2), SESSION(0)));
612
613 // Bring UID(0) back to top.
614 mUidPolicy->setTop(UID(0));
615 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(2), SESSION(0)));
616 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(0), SESSION(0)));
617
618 // Bring invalid uid to top.
619 mUidPolicy->setTop(kInvalidUid);
620 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
621
622 // Finish session, next real-time session should resume.
623 mController->onFinish(CLIENT(0), SESSION(0));
624 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Finished(CLIENT(0), SESSION(0)));
625 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(2), SESSION(0)));
626
627 // Finish session, offline session should start.
628 mController->onFinish(CLIENT(2), SESSION(0));
629 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Finished(CLIENT(2), SESSION(0)));
630 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(1), SESSION(0)));
631}
632
633TEST_F(TranscodingSessionControllerTest, TestTopUidSetChanged) {
634 ALOGD("TestTopUidChanged_MultipleUids");
635
636 // Start with unspecified top UID.
637 // Submit real-time session to CLIENT(0), session should start immediately.
Linus Nilssona99f4042021-02-25 15:49:43 -0800638 mController->submit(CLIENT(0), SESSION(0), UID(0), UID(0), mRealtimeRequest, mClientCallback0);
Chong Zhangbc062482020-10-14 16:43:53 -0700639 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), SESSION(0)));
640
641 // Submit offline session to CLIENT(0), should not start.
Linus Nilssona99f4042021-02-25 15:49:43 -0800642 mController->submit(CLIENT(1), SESSION(0), UID(1), UID(0), mOfflineRequest, mClientCallback1);
Chong Zhangbc062482020-10-14 16:43:53 -0700643 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
644
645 // Set UID(0), UID(1) to top set.
646 // UID(0) should continue to run.
647 mUidPolicy->setTop({UID(0), UID(1)});
648 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
649
650 // Submit real-time session to CLIENT(2) in different uid UID(1).
651 // UID(0) should pause and UID(1) should start.
Linus Nilssona99f4042021-02-25 15:49:43 -0800652 mController->submit(CLIENT(2), SESSION(0), UID(2), UID(1), mRealtimeRequest, mClientCallback2);
Chong Zhangbc062482020-10-14 16:43:53 -0700653 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(0), SESSION(0)));
654 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(2), SESSION(0)));
655
656 // Remove UID(0) from top set, and only leave UID(1) in the set.
657 // UID(1) should continue to run.
658 mUidPolicy->setTop(UID(1));
659 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
660
661 // Set UID(0), UID(2) to top set.
662 // UID(1) should continue to run.
663 mUidPolicy->setTop({UID(1), UID(2)});
664 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
665
666 // Bring UID(0) back to top.
667 mUidPolicy->setTop(UID(0));
668 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(2), SESSION(0)));
669 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(0), SESSION(0)));
670
671 // Bring invalid uid to top.
672 mUidPolicy->setTop(kInvalidUid);
673 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
674
675 // Finish session, next real-time session from UID(1) should resume, even if UID(1)
676 // no longer top.
677 mController->onFinish(CLIENT(0), SESSION(0));
678 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Finished(CLIENT(0), SESSION(0)));
679 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(2), SESSION(0)));
680
681 // Finish session, offline session should start.
682 mController->onFinish(CLIENT(2), SESSION(0));
683 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Finished(CLIENT(2), SESSION(0)));
684 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(1), SESSION(0)));
685}
686
Chong Zhang8677f1f2021-01-21 20:37:35 +0000687/* Test resource lost without thermal throttling */
Chong Zhangbc062482020-10-14 16:43:53 -0700688TEST_F(TranscodingSessionControllerTest, TestResourceLost) {
689 ALOGD("TestResourceLost");
690
691 // Start with unspecified top UID.
692 // Submit real-time session to CLIENT(0), session should start immediately.
Chong Zhangeffd8962020-12-02 14:29:09 -0800693 mRealtimeRequest.clientPid = PID(0);
Linus Nilssona99f4042021-02-25 15:49:43 -0800694 mController->submit(CLIENT(0), SESSION(0), UID(0), UID(0), mRealtimeRequest, mClientCallback0);
Chong Zhangbc062482020-10-14 16:43:53 -0700695 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), SESSION(0)));
696
697 // Submit offline session to CLIENT(0), should not start.
Chong Zhangeffd8962020-12-02 14:29:09 -0800698 mOfflineRequest.clientPid = PID(0);
Linus Nilssona99f4042021-02-25 15:49:43 -0800699 mController->submit(CLIENT(1), SESSION(0), UID(1), UID(0), mOfflineRequest, mClientCallback1);
Chong Zhangbc062482020-10-14 16:43:53 -0700700 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
701
702 // Move UID(1) to top.
703 mUidPolicy->setTop(UID(1));
704 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
705
706 // Submit real-time session to CLIENT(2) in different uid UID(1).
707 // Should pause previous session and start new session.
Chong Zhangeffd8962020-12-02 14:29:09 -0800708 mRealtimeRequest.clientPid = PID(1);
Linus Nilssona99f4042021-02-25 15:49:43 -0800709 mController->submit(CLIENT(2), SESSION(0), UID(2), UID(1), mRealtimeRequest, mClientCallback2);
Chong Zhangbc062482020-10-14 16:43:53 -0700710 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(0), SESSION(0)));
711 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(2), SESSION(0)));
712
Chong Zhangeffd8962020-12-02 14:29:09 -0800713 // Test 0: No call into ResourcePolicy if resource lost is from a non-running
714 // or non-existent session.
715 mController->onResourceLost(CLIENT(0), SESSION(0));
716 EXPECT_EQ(mResourcePolicy->getPid(), kInvalidPid);
717 mController->onResourceLost(CLIENT(3), SESSION(0));
718 EXPECT_EQ(mResourcePolicy->getPid(), kInvalidPid);
719
Chong Zhangbc062482020-10-14 16:43:53 -0700720 // Test 1: No queue change during resource loss.
721 // Signal resource lost.
Chong Zhangeffd8962020-12-02 14:29:09 -0800722 mController->onResourceLost(CLIENT(2), SESSION(0));
723 EXPECT_EQ(mResourcePolicy->getPid(), PID(1));
Chong Zhangbc062482020-10-14 16:43:53 -0700724 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
725
726 // Signal resource available, CLIENT(2) should resume.
727 mController->onResourceAvailable();
728 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(2), SESSION(0)));
729
730 // Test 2: Change of queue order during resource loss.
731 // Signal resource lost.
Chong Zhangeffd8962020-12-02 14:29:09 -0800732 mController->onResourceLost(CLIENT(2), SESSION(0));
733 EXPECT_EQ(mResourcePolicy->getPid(), PID(1));
Chong Zhangbc062482020-10-14 16:43:53 -0700734 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
735
736 // Move UID(0) back to top, should have no resume due to no resource.
737 mUidPolicy->setTop(UID(0));
738 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
739
740 // Signal resource available, CLIENT(0) should resume.
741 mController->onResourceAvailable();
742 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(0), SESSION(0)));
743
Chong Zhang8677f1f2021-01-21 20:37:35 +0000744 // Test 3:
Chong Zhangeffd8962020-12-02 14:29:09 -0800745 mController->onResourceLost(CLIENT(0), SESSION(0));
746 EXPECT_EQ(mResourcePolicy->getPid(), PID(0));
Chong Zhangbc062482020-10-14 16:43:53 -0700747 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
Chong Zhang8677f1f2021-01-21 20:37:35 +0000748 // Cancel the paused top session during resource lost.
749 EXPECT_TRUE(mController->cancel(CLIENT(0), SESSION(0)));
750 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Stop(CLIENT(0), SESSION(0)));
751 // Signal resource available, CLIENT(2)'s session should start.
752 mController->onResourceAvailable();
753 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(2), SESSION(0)));
754
755 // Test 4: Adding new queue during resource loss.
756 // Signal resource lost.
757 mController->onResourceLost(CLIENT(2), SESSION(0));
758 EXPECT_EQ(mResourcePolicy->getPid(), PID(1));
759 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
Chong Zhangbc062482020-10-14 16:43:53 -0700760
761 // Move UID(2) to top.
762 mUidPolicy->setTop(UID(2));
763
764 // 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 -0800765 mRealtimeRequest.clientPid = PID(2);
Linus Nilssona99f4042021-02-25 15:49:43 -0800766 mController->submit(CLIENT(3), SESSION(0), UID(3), UID(2), mRealtimeRequest, mClientCallback3);
Chong Zhangbc062482020-10-14 16:43:53 -0700767 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
768
769 // Signal resource available, CLIENT(3)'s session should start.
770 mController->onResourceAvailable();
771 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(3), SESSION(0)));
772}
773
Chong Zhang8677f1f2021-01-21 20:37:35 +0000774/* Test thermal throttling without resource lost */
775TEST_F(TranscodingSessionControllerTest, TestThermalCallback) {
776 ALOGD("TestThermalCallback");
777
778 // Start with unspecified top UID.
779 // Submit real-time session to CLIENT(0), session should start immediately.
780 mRealtimeRequest.clientPid = PID(0);
Linus Nilssona99f4042021-02-25 15:49:43 -0800781 mController->submit(CLIENT(0), SESSION(0), UID(0), UID(0), mRealtimeRequest, mClientCallback0);
Chong Zhang8677f1f2021-01-21 20:37:35 +0000782 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), SESSION(0)));
783
784 // Submit offline session to CLIENT(0), should not start.
785 mOfflineRequest.clientPid = PID(0);
Linus Nilssona99f4042021-02-25 15:49:43 -0800786 mController->submit(CLIENT(1), SESSION(0), UID(1), UID(0), mOfflineRequest, mClientCallback1);
Chong Zhang8677f1f2021-01-21 20:37:35 +0000787 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
788
789 // Move UID(1) to top.
790 mUidPolicy->setTop(UID(1));
791 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
792
793 // Submit real-time session to CLIENT(2) in different uid UID(1).
794 // Should pause previous session and start new session.
795 mRealtimeRequest.clientPid = PID(1);
Linus Nilssona99f4042021-02-25 15:49:43 -0800796 mController->submit(CLIENT(2), SESSION(0), UID(2), UID(1), mRealtimeRequest, mClientCallback2);
Chong Zhang8677f1f2021-01-21 20:37:35 +0000797 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(0), SESSION(0)));
798 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(2), SESSION(0)));
799
800 // Test 0: Basic case, no queue change during throttling, top session should pause/resume
801 // with throttling.
802 mController->onThrottlingStarted();
803 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(2), SESSION(0)));
804 mController->onThrottlingStopped();
805 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(2), SESSION(0)));
806
807 // Test 1: Change of queue order during thermal throttling, when throttling stops,
808 // new top session should resume.
809 mController->onThrottlingStarted();
810 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(2), SESSION(0)));
811 mUidPolicy->setTop(UID(0));
812 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
813 mController->onThrottlingStopped();
814 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(0), SESSION(0)));
815
816 // Test 2: Cancel session during throttling, when throttling stops, new top
817 // session should resume.
818 mController->onThrottlingStarted();
819 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(0), SESSION(0)));
820 // Cancel the paused top session during throttling.
821 EXPECT_TRUE(mController->cancel(CLIENT(0), SESSION(0)));
822 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Stop(CLIENT(0), SESSION(0)));
823 // Throttling stops, CLIENT(2)'s session should start.
824 mController->onThrottlingStopped();
825 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(2), SESSION(0)));
826
827 // Test 3: Add new queue during throttling, when throttling stops, new top
828 // session should resume.
829 mController->onThrottlingStarted();
830 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(2), SESSION(0)));
831 // Move UID(2) to top.
832 mUidPolicy->setTop(UID(2));
833 // Submit real-time session to CLIENT(3) in UID(2), session shouldn't start during throttling.
834 mRealtimeRequest.clientPid = PID(2);
Linus Nilssona99f4042021-02-25 15:49:43 -0800835 mController->submit(CLIENT(3), SESSION(0), UID(3), UID(2), mRealtimeRequest, mClientCallback3);
Chong Zhang8677f1f2021-01-21 20:37:35 +0000836 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
837 // Throttling stops, CLIENT(3)'s session should start.
838 mController->onThrottlingStopped();
839 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(3), SESSION(0)));
840}
841
842/* Test resource lost and thermal throttling happening simultaneously */
843TEST_F(TranscodingSessionControllerTest, TestResourceLostAndThermalCallback) {
844 ALOGD("TestResourceLostAndThermalCallback");
845
846 // Start with unspecified top UID.
847 // Submit real-time session to CLIENT(0), session should start immediately.
848 mRealtimeRequest.clientPid = PID(0);
Linus Nilssona99f4042021-02-25 15:49:43 -0800849 mController->submit(CLIENT(0), SESSION(0), UID(0), UID(0), mRealtimeRequest, mClientCallback0);
Chong Zhang8677f1f2021-01-21 20:37:35 +0000850 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), SESSION(0)));
851
852 // Submit offline session to CLIENT(0), should not start.
853 mOfflineRequest.clientPid = PID(0);
Linus Nilssona99f4042021-02-25 15:49:43 -0800854 mController->submit(CLIENT(1), SESSION(0), UID(1), UID(0), mOfflineRequest, mClientCallback1);
Chong Zhang8677f1f2021-01-21 20:37:35 +0000855 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
856
857 // Move UID(1) to top.
858 mUidPolicy->setTop(UID(1));
859 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
860
861 // Submit real-time session to CLIENT(2) in different uid UID(1).
862 // Should pause previous session and start new session.
863 mRealtimeRequest.clientPid = PID(1);
Linus Nilssona99f4042021-02-25 15:49:43 -0800864 mController->submit(CLIENT(2), SESSION(0), UID(2), UID(1), mRealtimeRequest, mClientCallback2);
Chong Zhang8677f1f2021-01-21 20:37:35 +0000865 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(0), SESSION(0)));
866 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(2), SESSION(0)));
867
868 // Test 0: Resource lost during throttling.
869 // Throttling starts, top session should pause.
870 mController->onThrottlingStarted();
871 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(2), SESSION(0)));
872 // Signal resource lost, this should get ignored because the session is now paused.
873 mController->onResourceLost(CLIENT(2), SESSION(0));
874 EXPECT_EQ(mResourcePolicy->getPid(), kInvalidPid);
875 // Signal resource available, CLIENT(2) shouldn't resume.
876 mController->onResourceAvailable();
877 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
878 // Throttling ends, top session should resume.
879 mController->onThrottlingStopped();
880 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(2), SESSION(0)));
881
882 // Test 1: Throttling during resource lost.
883 mController->onResourceLost(CLIENT(2), SESSION(0));
884 EXPECT_EQ(mResourcePolicy->getPid(), PID(1));
885 mController->onThrottlingStarted();
886 mController->onThrottlingStopped();
887 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
888 mController->onResourceAvailable();
889 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(2), SESSION(0)));
890
891 // Test 2: Interleaving resource lost and throttling.
892 mController->onResourceLost(CLIENT(2), SESSION(0));
893 EXPECT_EQ(mResourcePolicy->getPid(), PID(1));
894 mController->onThrottlingStarted();
895 mController->onResourceAvailable();
896 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
897 mController->onThrottlingStopped();
898 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(2), SESSION(0)));
899}
900
Chong Zhang87d199c2021-03-01 19:02:18 -0800901TEST_F(TranscodingSessionControllerTest, TestTranscoderWatchdogNoHeartbeat) {
Chong Zhang457c6892021-02-01 15:34:20 -0800902 ALOGD("TestTranscoderWatchdogTimeout");
903
904 // Submit session to CLIENT(0) in UID(0).
905 // Should start immediately (because this is the only session).
Linus Nilssona99f4042021-02-25 15:49:43 -0800906 mController->submit(CLIENT(0), SESSION(0), UID(0), UID(0), mRealtimeRequest, mClientCallback0);
Chong Zhang457c6892021-02-01 15:34:20 -0800907 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), SESSION(0)));
908
Chong Zhang457c6892021-02-01 15:34:20 -0800909 // Test 1: If not sending keep-alive at all, timeout after 3 seconds.
Chong Zhang87d199c2021-03-01 19:02:18 -0800910 expectTimeout(CLIENT(0), SESSION(0), 2);
911}
Chong Zhang457c6892021-02-01 15:34:20 -0800912
Chong Zhang87d199c2021-03-01 19:02:18 -0800913TEST_F(TranscodingSessionControllerTest, TestTranscoderWatchdogHeartbeat) {
Chong Zhang457c6892021-02-01 15:34:20 -0800914 // Test 2: No timeout as long as keep-alive coming; timeout after keep-alive stops.
Linus Nilssona99f4042021-02-25 15:49:43 -0800915 mController->submit(CLIENT(0), SESSION(1), UID(0), UID(0), mRealtimeRequest, mClientCallback0);
Chong Zhang457c6892021-02-01 15:34:20 -0800916 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), SESSION(1)));
Chong Zhang87d199c2021-03-01 19:02:18 -0800917
Chong Zhang457c6892021-02-01 15:34:20 -0800918 for (int i = 0; i < 5; i++) {
919 EXPECT_EQ(mTranscoder->popEvent(1000000), TestTranscoder::NoEvent);
920 mController->onHeartBeat(CLIENT(0), SESSION(1));
921 }
Chong Zhang87d199c2021-03-01 19:02:18 -0800922 expectTimeout(CLIENT(0), SESSION(1), 2);
923}
924
925TEST_F(TranscodingSessionControllerTest, TestTranscoderWatchdogDuringPause) {
926 int expectedGen = 2;
Chong Zhang457c6892021-02-01 15:34:20 -0800927
928 // Test 3a: No timeout for paused session even if no keep-alive is sent.
Linus Nilssona99f4042021-02-25 15:49:43 -0800929 mController->submit(CLIENT(0), SESSION(2), UID(0), UID(0), mOfflineRequest, mClientCallback0);
Chong Zhang457c6892021-02-01 15:34:20 -0800930 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), SESSION(2)));
931 // Trigger a pause by sending a resource lost.
932 mController->onResourceLost(CLIENT(0), SESSION(2));
933 EXPECT_EQ(mTranscoder->popEvent(3100000), TestTranscoder::NoEvent);
934 mController->onResourceAvailable();
935 EXPECT_EQ(mTranscoder->popEvent(100000), TestTranscoder::Resume(CLIENT(0), SESSION(2)));
936 expectTimeout(CLIENT(0), SESSION(2), expectedGen++);
937
938 // Test 3b: No timeout for paused session even if no keep-alive is sent.
Linus Nilssona99f4042021-02-25 15:49:43 -0800939 mController->submit(CLIENT(0), SESSION(3), UID(0), UID(0), mOfflineRequest, mClientCallback0);
Chong Zhang457c6892021-02-01 15:34:20 -0800940 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), SESSION(3)));
941 // Let the session run almost to timeout, to test timeout reset after pause.
942 EXPECT_EQ(mTranscoder->popEvent(2900000), TestTranscoder::NoEvent);
943 // Trigger a pause by submitting a higher-priority request.
Linus Nilssona99f4042021-02-25 15:49:43 -0800944 mController->submit(CLIENT(0), SESSION(4), UID(0), UID(0), mRealtimeRequest, mClientCallback0);
Chong Zhang457c6892021-02-01 15:34:20 -0800945 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(0), SESSION(3)));
946 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), SESSION(4)));
947 // Finish the higher-priority session, lower-priority session should resume,
948 // and the timeout should reset to full value.
949 mController->onFinish(CLIENT(0), SESSION(4));
950 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Finished(CLIENT(0), SESSION(4)));
951 EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(0), SESSION(3)));
952 expectTimeout(CLIENT(0), SESSION(3), expectedGen++);
953}
954
Chong Zhang87d199c2021-03-01 19:02:18 -0800955TEST_F(TranscodingSessionControllerTest, TestTranscoderPacerOverCountOnly) {
956 ALOGD("TestTranscoderPacerOverCountOnly");
957 testPacerHelper(12 /*numSubmits*/, 100 /*sessionDurationMs*/, 12 /*expectedSuccess*/);
958}
959
960TEST_F(TranscodingSessionControllerTest, TestTranscoderPacerOverTimeOnly) {
961 ALOGD("TestTranscoderPacerOverTimeOnly");
962 testPacerHelper(5 /*numSubmits*/, 1000 /*sessionDurationMs*/, 5 /*expectedSuccess*/);
963}
964
965TEST_F(TranscodingSessionControllerTest, TestTranscoderPacerOverQuota) {
966 ALOGD("TestTranscoderPacerOverQuota");
967 testPacerHelper(12 /*numSubmits*/, 400 /*sessionDurationMs*/, 10 /*expectedSuccess*/);
968}
969
970TEST_F(TranscodingSessionControllerTest, TestTranscoderPacerWithPause) {
971 ALOGD("TestTranscoderPacerDuringPause");
972 testPacerHelper(12 /*numSubmits*/, 400 /*sessionDurationMs*/, 10 /*expectedSuccess*/,
973 true /*pauseLastSuccessSession*/);
974}
975
Chong Zhangbc062482020-10-14 16:43:53 -0700976} // namespace android