Revert "Revert "transcoding: add thermal status listener""
This reverts commit b253cec66de2986379ef94e1d372123dee1b826f.
Reason for revert: reland with fix
Change-Id: Ieab554dc2dc4187e75fc223997387f4875832e52
diff --git a/media/libmediatranscoding/Android.bp b/media/libmediatranscoding/Android.bp
index 094d7c3..23e83f9 100644
--- a/media/libmediatranscoding/Android.bp
+++ b/media/libmediatranscoding/Android.bp
@@ -71,11 +71,12 @@
],
srcs: [
- "TranscodingClientManager.cpp",
- "TranscodingSessionController.cpp",
- "TranscodingResourcePolicy.cpp",
- "TranscodingUidPolicy.cpp",
"TranscoderWrapper.cpp",
+ "TranscodingClientManager.cpp",
+ "TranscodingResourcePolicy.cpp",
+ "TranscodingSessionController.cpp",
+ "TranscodingThermalPolicy.cpp",
+ "TranscodingUidPolicy.cpp",
],
shared_libs: [
diff --git a/media/libmediatranscoding/TranscodingClientManager.cpp b/media/libmediatranscoding/TranscodingClientManager.cpp
index 46d1da2..b6a2381 100644
--- a/media/libmediatranscoding/TranscodingClientManager.cpp
+++ b/media/libmediatranscoding/TranscodingClientManager.cpp
@@ -138,11 +138,10 @@
ALOGE("submitRequest rejected (clientPid %d, clientUid %d) "
"(don't trust callingUid %d)",
in_clientPid, in_clientUid, callingUid);
- return STATUS_ERROR_FMT(
- IMediaTranscodingService::ERROR_PERMISSION_DENIED,
- "submitRequest rejected (clientPid %d, clientUid %d) "
- "(don't trust callingUid %d)",
- in_clientPid, in_clientUid, callingUid);
+ return STATUS_ERROR_FMT(IMediaTranscodingService::ERROR_PERMISSION_DENIED,
+ "submitRequest rejected (clientPid %d, clientUid %d) "
+ "(don't trust callingUid %d)",
+ in_clientPid, in_clientUid, callingUid);
}
// Check if we can trust clientPid. Only privilege caller could forward the
@@ -155,11 +154,10 @@
ALOGE("submitRequest rejected (clientPid %d, clientUid %d) "
"(don't trust callingUid %d)",
in_clientPid, in_clientUid, callingUid);
- return STATUS_ERROR_FMT(
- IMediaTranscodingService::ERROR_PERMISSION_DENIED,
- "submitRequest rejected (clientPid %d, clientUid %d) "
- "(don't trust callingUid %d)",
- in_clientPid, in_clientUid, callingUid);
+ return STATUS_ERROR_FMT(IMediaTranscodingService::ERROR_PERMISSION_DENIED,
+ "submitRequest rejected (clientPid %d, clientUid %d) "
+ "(don't trust callingUid %d)",
+ in_clientPid, in_clientUid, callingUid);
}
int32_t sessionId = mNextSessionId.fetch_add(1);
diff --git a/media/libmediatranscoding/TranscodingSessionController.cpp b/media/libmediatranscoding/TranscodingSessionController.cpp
index b77a3a4..09ad3cd 100644
--- a/media/libmediatranscoding/TranscodingSessionController.cpp
+++ b/media/libmediatranscoding/TranscodingSessionController.cpp
@@ -63,10 +63,12 @@
TranscodingSessionController::TranscodingSessionController(
const std::shared_ptr<TranscoderInterface>& transcoder,
const std::shared_ptr<UidPolicyInterface>& uidPolicy,
- const std::shared_ptr<ResourcePolicyInterface>& resourcePolicy)
+ const std::shared_ptr<ResourcePolicyInterface>& resourcePolicy,
+ const std::shared_ptr<ThermalPolicyInterface>& thermalPolicy)
: mTranscoder(transcoder),
mUidPolicy(uidPolicy),
mResourcePolicy(resourcePolicy),
+ mThermalPolicy(thermalPolicy),
mCurrentSession(nullptr),
mResourceLost(false) {
// Only push empty offline queue initially. Realtime queues are added when requests come in.
@@ -74,6 +76,7 @@
mOfflineUidIterator = mUidSortedList.begin();
mSessionQueues.emplace(OFFLINE_UID, SessionQueueType());
mUidPackageNames[OFFLINE_UID] = "(offline)";
+ mThermalThrottling = thermalPolicy->getThrottlingStatus();
}
TranscodingSessionController::~TranscodingSessionController() {}
@@ -141,7 +144,7 @@
snprintf(buffer, SIZE, "\n========== Dumping past sessions =========\n");
result.append(buffer);
- for (auto &session : mSessionHistory) {
+ for (auto& session : mSessionHistory) {
dumpSession_l(session, result, true /*closedSession*/);
}
@@ -192,18 +195,27 @@
topSession == nullptr ? "null" : sessionToString(topSession->key).c_str(),
curSession == nullptr ? "null" : sessionToString(curSession->key).c_str());
+ if (topSession == nullptr) {
+ mCurrentSession = nullptr;
+ return;
+ }
+
+ bool shouldBeRunning = !((mResourcePolicy != nullptr && mResourceLost) ||
+ (mThermalPolicy != nullptr && mThermalThrottling));
// If we found a topSession that should be run, and it's not already running,
// take some actions to ensure it's running.
- if (topSession != nullptr &&
- (topSession != curSession || topSession->getState() != Session::RUNNING)) {
- // If another session is currently running, pause it first.
+ if (topSession != curSession ||
+ (shouldBeRunning ^ (topSession->getState() == Session::RUNNING))) {
+ // If current session is running, pause it first. Note this is true for either
+ // cases: 1) If top session is changing, or 2) if top session is not changing but
+ // the topSession's state is changing.
if (curSession != nullptr && curSession->getState() == Session::RUNNING) {
mTranscoder->pause(curSession->key.first, curSession->key.second);
curSession->setState(Session::PAUSED);
}
- // If we are not experiencing resource loss, we can start or resume
- // the topSession now.
- if (!mResourceLost) {
+ // If we are not experiencing resource loss nor thermal throttling, we can start
+ // or resume the topSession now.
+ if (shouldBeRunning) {
if (topSession->getState() == Session::NOT_STARTED) {
mTranscoder->start(topSession->key.first, topSession->key.second,
topSession->request, topSession->callback.lock());
@@ -566,7 +578,9 @@
if (clientCallback != nullptr) {
clientCallback->onTranscodingPaused(sessionKey.second);
}
- mResourcePolicy->setPidResourceLost(resourceLostSession->request.clientPid);
+ if (mResourcePolicy != nullptr) {
+ mResourcePolicy->setPidResourceLost(resourceLostSession->request.clientPid);
+ }
mResourceLost = true;
validateState_l();
@@ -613,6 +627,36 @@
validateState_l();
}
+void TranscodingSessionController::onThrottlingStarted() {
+ std::scoped_lock lock{mLock};
+
+ if (mThermalThrottling) {
+ return;
+ }
+
+ ALOGI("%s", __FUNCTION__);
+
+ mThermalThrottling = true;
+ updateCurrentSession_l();
+
+ validateState_l();
+}
+
+void TranscodingSessionController::onThrottlingStopped() {
+ std::scoped_lock lock{mLock};
+
+ if (!mThermalThrottling) {
+ return;
+ }
+
+ ALOGI("%s", __FUNCTION__);
+
+ mThermalThrottling = false;
+ updateCurrentSession_l();
+
+ validateState_l();
+}
+
void TranscodingSessionController::validateState_l() {
#ifdef VALIDATE_STATE
LOG_ALWAYS_FATAL_IF(mSessionQueues.count(OFFLINE_UID) != 1,
diff --git a/media/libmediatranscoding/TranscodingThermalPolicy.cpp b/media/libmediatranscoding/TranscodingThermalPolicy.cpp
new file mode 100644
index 0000000..9984abe
--- /dev/null
+++ b/media/libmediatranscoding/TranscodingThermalPolicy.cpp
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "TranscodingThermalPolicy"
+
+#include <media/TranscodingThermalPolicy.h>
+#include <media/TranscodingUidPolicy.h>
+#include <utils/Log.h>
+
+namespace android {
+
+static bool needThrottling(AThermalStatus status) {
+ return (status >= ATHERMAL_STATUS_SEVERE);
+}
+
+//static
+void TranscodingThermalPolicy::onStatusChange(void* data, AThermalStatus status) {
+ TranscodingThermalPolicy* policy = static_cast<TranscodingThermalPolicy*>(data);
+ policy->onStatusChange(status);
+}
+
+TranscodingThermalPolicy::TranscodingThermalPolicy()
+ : mRegistered(false), mThermalManager(nullptr), mIsThrottling(false) {
+ registerSelf();
+}
+
+TranscodingThermalPolicy::~TranscodingThermalPolicy() {
+ unregisterSelf();
+}
+
+void TranscodingThermalPolicy::registerSelf() {
+ ALOGI("TranscodingThermalPolicy: registerSelf");
+
+ std::scoped_lock lock{mRegisteredLock};
+
+ if (mRegistered) {
+ return;
+ }
+
+ if (__builtin_available(android __TRANSCODING_MIN_API__, *)) {
+ AThermalManager* thermalManager = AThermal_acquireManager();
+ if (thermalManager == nullptr) {
+ ALOGE("Failed to acquire thermal manager");
+ return;
+ }
+
+ int ret = AThermal_registerThermalStatusListener(thermalManager, onStatusChange, this);
+ if (ret != 0) {
+ ALOGE("Failed to register thermal status listener");
+ AThermal_releaseManager(thermalManager);
+ return;
+ }
+
+ mIsThrottling = needThrottling(AThermal_getCurrentThermalStatus(thermalManager));
+ mThermalManager = thermalManager;
+ }
+
+ mRegistered = true;
+}
+
+void TranscodingThermalPolicy::unregisterSelf() {
+ ALOGI("TranscodingThermalPolicy: unregisterSelf");
+
+ std::scoped_lock lock{mRegisteredLock};
+
+ if (!mRegistered) {
+ return;
+ }
+
+ if (__builtin_available(android __TRANSCODING_MIN_API__, *)) {
+ if (mThermalManager != nullptr) {
+ // Unregister listener
+ int ret =
+ AThermal_unregisterThermalStatusListener(mThermalManager, onStatusChange, this);
+ if (ret != 0) {
+ ALOGW("Failed to unregister thermal status listener");
+ }
+ AThermal_releaseManager(mThermalManager);
+ mThermalManager = nullptr;
+ }
+ }
+
+ mRegistered = false;
+}
+
+void TranscodingThermalPolicy::setCallback(
+ const std::shared_ptr<ThermalPolicyCallbackInterface>& cb) {
+ std::scoped_lock lock{mCallbackLock};
+ mThermalPolicyCallback = cb;
+}
+
+bool TranscodingThermalPolicy::getThrottlingStatus() {
+ std::scoped_lock lock{mRegisteredLock};
+ return mIsThrottling;
+}
+
+void TranscodingThermalPolicy::onStatusChange(AThermalStatus status) {
+ bool isThrottling = needThrottling(status);
+
+ {
+ std::scoped_lock lock{mRegisteredLock};
+ if (isThrottling == mIsThrottling) {
+ return;
+ }
+ ALOGI("Transcoding thermal throttling changed: %d", isThrottling);
+ mIsThrottling = isThrottling;
+ }
+
+ std::scoped_lock lock{mCallbackLock};
+ std::shared_ptr<ThermalPolicyCallbackInterface> cb;
+ if ((cb = mThermalPolicyCallback.lock()) != nullptr) {
+ if (isThrottling) {
+ cb->onThrottlingStarted();
+ } else {
+ cb->onThrottlingStopped();
+ }
+ }
+}
+} // namespace android
diff --git a/media/libmediatranscoding/TranscodingUidPolicy.cpp b/media/libmediatranscoding/TranscodingUidPolicy.cpp
index feaecc6..b5eb028 100644
--- a/media/libmediatranscoding/TranscodingUidPolicy.cpp
+++ b/media/libmediatranscoding/TranscodingUidPolicy.cpp
@@ -32,9 +32,7 @@
constexpr static int32_t IMPORTANCE_UNKNOWN = INT32_MAX;
TranscodingUidPolicy::TranscodingUidPolicy()
- : mUidObserver(nullptr),
- mRegistered(false),
- mTopUidState(IMPORTANCE_UNKNOWN) {
+ : mUidObserver(nullptr), mRegistered(false), mTopUidState(IMPORTANCE_UNKNOWN) {
registerSelf();
}
@@ -129,8 +127,7 @@
bool TranscodingUidPolicy::isUidOnTop(uid_t uid) {
Mutex::Autolock _l(mUidLock);
- return mTopUidState != IMPORTANCE_UNKNOWN &&
- mTopUidState == getProcState_l(uid);
+ return mTopUidState != IMPORTANCE_UNKNOWN && mTopUidState == getProcState_l(uid);
}
std::unordered_set<uid_t> TranscodingUidPolicy::getTopUids() const {
@@ -155,12 +152,10 @@
// Top set changed if 1) the uid is in the current top uid set, or 2) the
// new procState is at least the same priority as the current top uid state.
bool isUidCurrentTop =
- mTopUidState != IMPORTANCE_UNKNOWN &&
- mStateUidMap[mTopUidState].count(uid) > 0;
+ mTopUidState != IMPORTANCE_UNKNOWN && mStateUidMap[mTopUidState].count(uid) > 0;
bool isNewStateHigherThanTop =
procState != IMPORTANCE_UNKNOWN &&
- (procState <= mTopUidState ||
- mTopUidState == IMPORTANCE_UNKNOWN);
+ (procState <= mTopUidState || mTopUidState == IMPORTANCE_UNKNOWN);
topUidSetChanged = (isUidCurrentTop || isNewStateHigherThanTop);
// Move uid to the new procState.
@@ -192,8 +187,7 @@
// Find the lowest uid state (ignoring PROCESS_STATE_UNKNOWN) with some monitored uids.
for (auto stateIt = mStateUidMap.begin(); stateIt != mStateUidMap.end(); stateIt++) {
- if (stateIt->first != IMPORTANCE_UNKNOWN &&
- !stateIt->second.empty()) {
+ if (stateIt->first != IMPORTANCE_UNKNOWN && !stateIt->second.empty()) {
mTopUidState = stateIt->first;
break;
}
diff --git a/media/libmediatranscoding/include/media/ThermalPolicyInterface.h b/media/libmediatranscoding/include/media/ThermalPolicyInterface.h
new file mode 100644
index 0000000..1cc0cc1
--- /dev/null
+++ b/media/libmediatranscoding/include/media/ThermalPolicyInterface.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_MEDIA_THERMAL_POLICY_INTERFACE_H
+#define ANDROID_MEDIA_THERMAL_POLICY_INTERFACE_H
+#include <memory>
+
+namespace android {
+
+class ThermalPolicyCallbackInterface;
+
+// Interface for the SessionController to control the thermal policy.
+class ThermalPolicyInterface {
+public:
+ // Set the associated callback interface to send the events when the thermal
+ // status changes.
+ virtual void setCallback(const std::shared_ptr<ThermalPolicyCallbackInterface>& cb) = 0;
+
+ // Get the current thermal throttling status. Returns true if throttling is on,
+ // false otherwise.
+ virtual bool getThrottlingStatus() = 0;
+
+protected:
+ virtual ~ThermalPolicyInterface() = default;
+};
+
+// Interface for notifying the SessionController of thermal throttling status.
+class ThermalPolicyCallbackInterface {
+public:
+ // Called when the session controller should start or stop thermal throttling.
+ virtual void onThrottlingStarted() = 0;
+ virtual void onThrottlingStopped() = 0;
+
+protected:
+ virtual ~ThermalPolicyCallbackInterface() = default;
+};
+
+} // namespace android
+#endif // ANDROID_MEDIA_THERMAL_POLICY_INTERFACE_H
diff --git a/media/libmediatranscoding/include/media/TranscodingSessionController.h b/media/libmediatranscoding/include/media/TranscodingSessionController.h
index a443265..4fcc423 100644
--- a/media/libmediatranscoding/include/media/TranscodingSessionController.h
+++ b/media/libmediatranscoding/include/media/TranscodingSessionController.h
@@ -20,6 +20,7 @@
#include <aidl/android/media/TranscodingSessionPriority.h>
#include <media/ControllerClientInterface.h>
#include <media/ResourcePolicyInterface.h>
+#include <media/ThermalPolicyInterface.h>
#include <media/TranscoderInterface.h>
#include <media/TranscodingRequest.h>
#include <media/UidPolicyInterface.h>
@@ -38,7 +39,8 @@
class TranscodingSessionController : public UidPolicyCallbackInterface,
public ControllerClientInterface,
public TranscoderCallbackInterface,
- public ResourcePolicyCallbackInterface {
+ public ResourcePolicyCallbackInterface,
+ public ThermalPolicyCallbackInterface {
public:
virtual ~TranscodingSessionController();
@@ -70,6 +72,11 @@
void onResourceAvailable() override;
// ~ResourcePolicyCallbackInterface
+ // ThermalPolicyCallbackInterface
+ void onThrottlingStarted() override;
+ void onThrottlingStopped() override;
+ // ~ResourcePolicyCallbackInterface
+
/**
* Dump all the session information to the fd.
*/
@@ -88,6 +95,8 @@
NOT_STARTED = 0,
RUNNING,
PAUSED,
+ // The following states would not appear in live sessions map, but could
+ // appear in past sessions map for logging purpose.
FINISHED,
CANCELED,
ERROR,
@@ -130,15 +139,18 @@
std::shared_ptr<TranscoderInterface> mTranscoder;
std::shared_ptr<UidPolicyInterface> mUidPolicy;
std::shared_ptr<ResourcePolicyInterface> mResourcePolicy;
+ std::shared_ptr<ThermalPolicyInterface> mThermalPolicy;
Session* mCurrentSession;
bool mResourceLost;
+ bool mThermalThrottling;
std::list<Session> mSessionHistory;
// Only allow MediaTranscodingService and unit tests to instantiate.
TranscodingSessionController(const std::shared_ptr<TranscoderInterface>& transcoder,
const std::shared_ptr<UidPolicyInterface>& uidPolicy,
- const std::shared_ptr<ResourcePolicyInterface>& resourcePolicy);
+ const std::shared_ptr<ResourcePolicyInterface>& resourcePolicy,
+ const std::shared_ptr<ThermalPolicyInterface>& thermalPolicy);
void dumpSession_l(const Session& session, String8& result, bool closedSession = false);
Session* getTopSession_l();
diff --git a/media/libmediatranscoding/include/media/TranscodingThermalPolicy.h b/media/libmediatranscoding/include/media/TranscodingThermalPolicy.h
new file mode 100644
index 0000000..81c6eac
--- /dev/null
+++ b/media/libmediatranscoding/include/media/TranscodingThermalPolicy.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_MEDIA_TRANSCODING_THERMAL_POLICY_H
+#define ANDROID_MEDIA_TRANSCODING_THERMAL_POLICY_H
+
+#include <android/thermal.h>
+#include <media/ThermalPolicyInterface.h>
+#include <utils/Condition.h>
+
+#include <mutex>
+
+namespace android {
+
+class TranscodingThermalPolicy : public ThermalPolicyInterface {
+public:
+ explicit TranscodingThermalPolicy();
+ ~TranscodingThermalPolicy();
+
+ void setCallback(const std::shared_ptr<ThermalPolicyCallbackInterface>& cb) override;
+ bool getThrottlingStatus() override;
+
+private:
+ mutable std::mutex mRegisteredLock;
+ bool mRegistered GUARDED_BY(mRegisteredLock);
+
+ mutable std::mutex mCallbackLock;
+ std::weak_ptr<ThermalPolicyCallbackInterface> mThermalPolicyCallback GUARDED_BY(mCallbackLock);
+
+ AThermalManager* mThermalManager;
+ bool mIsThrottling;
+
+ static void onStatusChange(void* data, AThermalStatus status);
+ void onStatusChange(AThermalStatus status);
+ void registerSelf();
+ void unregisterSelf();
+};
+
+} // namespace android
+#endif // ANDROID_MEDIA_TRANSCODING_THERMAL_POLICY_H
diff --git a/media/libmediatranscoding/tests/TranscodingSessionController_tests.cpp b/media/libmediatranscoding/tests/TranscodingSessionController_tests.cpp
index fa52f63..9a1c272 100644
--- a/media/libmediatranscoding/tests/TranscodingSessionController_tests.cpp
+++ b/media/libmediatranscoding/tests/TranscodingSessionController_tests.cpp
@@ -89,9 +89,7 @@
// ResourcePolicyInterface
void setCallback(const std::shared_ptr<ResourcePolicyCallbackInterface>& /*cb*/) override {}
- void setPidResourceLost(pid_t pid) override {
- mResourceLostPid = pid;
- }
+ void setPidResourceLost(pid_t pid) override { mResourceLostPid = pid; }
// ~ResourcePolicyInterface
pid_t getPid() {
@@ -101,12 +99,23 @@
}
private:
- void reset() {
- mResourceLostPid = kInvalidPid;
- }
+ void reset() { mResourceLostPid = kInvalidPid; }
pid_t mResourceLostPid;
};
+class TestThermalPolicy : public ThermalPolicyInterface {
+public:
+ TestThermalPolicy() = default;
+ virtual ~TestThermalPolicy() = default;
+
+ // ThermalPolicyInterface
+ void setCallback(const std::shared_ptr<ThermalPolicyCallbackInterface>& /*cb*/) override {}
+ bool getThrottlingStatus() { return false; }
+ // ~ThermalPolicyInterface
+
+private:
+};
+
class TestTranscoder : public TranscoderInterface {
public:
TestTranscoder() : mLastError(TranscodingErrorCode::kUnknown) {}
@@ -245,8 +254,9 @@
mTranscoder.reset(new TestTranscoder());
mUidPolicy.reset(new TestUidPolicy());
mResourcePolicy.reset(new TestResourcePolicy());
- mController.reset(
- new TranscodingSessionController(mTranscoder, mUidPolicy, mResourcePolicy));
+ mThermalPolicy.reset(new TestThermalPolicy());
+ mController.reset(new TranscodingSessionController(mTranscoder, mUidPolicy, mResourcePolicy,
+ mThermalPolicy));
mUidPolicy->setCallback(mController);
// Set priority only, ignore other fields for now.
@@ -269,6 +279,7 @@
std::shared_ptr<TestTranscoder> mTranscoder;
std::shared_ptr<TestUidPolicy> mUidPolicy;
std::shared_ptr<TestResourcePolicy> mResourcePolicy;
+ std::shared_ptr<TestThermalPolicy> mThermalPolicy;
std::shared_ptr<TranscodingSessionController> mController;
TranscodingRequestParcel mOfflineRequest;
TranscodingRequestParcel mRealtimeRequest;
@@ -577,6 +588,7 @@
EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(1), SESSION(0)));
}
+/* Test resource lost without thermal throttling */
TEST_F(TranscodingSessionControllerTest, TestResourceLost) {
ALOGD("TestResourceLost");
@@ -633,11 +645,22 @@
mController->onResourceAvailable();
EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(0), SESSION(0)));
- // Test 3: Adding new queue during resource loss.
- // Signal resource lost.
+ // Test 3:
mController->onResourceLost(CLIENT(0), SESSION(0));
EXPECT_EQ(mResourcePolicy->getPid(), PID(0));
EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
+ // Cancel the paused top session during resource lost.
+ EXPECT_TRUE(mController->cancel(CLIENT(0), SESSION(0)));
+ EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Stop(CLIENT(0), SESSION(0)));
+ // Signal resource available, CLIENT(2)'s session should start.
+ mController->onResourceAvailable();
+ EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(2), SESSION(0)));
+
+ // Test 4: Adding new queue during resource loss.
+ // Signal resource lost.
+ mController->onResourceLost(CLIENT(2), SESSION(0));
+ EXPECT_EQ(mResourcePolicy->getPid(), PID(1));
+ EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
// Move UID(2) to top.
mUidPolicy->setTop(UID(2));
@@ -652,4 +675,131 @@
EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(3), SESSION(0)));
}
+/* Test thermal throttling without resource lost */
+TEST_F(TranscodingSessionControllerTest, TestThermalCallback) {
+ ALOGD("TestThermalCallback");
+
+ // Start with unspecified top UID.
+ // Submit real-time session to CLIENT(0), session should start immediately.
+ mRealtimeRequest.clientPid = PID(0);
+ mController->submit(CLIENT(0), SESSION(0), UID(0), mRealtimeRequest, mClientCallback0);
+ EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), SESSION(0)));
+
+ // Submit offline session to CLIENT(0), should not start.
+ mOfflineRequest.clientPid = PID(0);
+ mController->submit(CLIENT(1), SESSION(0), UID(0), mOfflineRequest, mClientCallback1);
+ EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
+
+ // Move UID(1) to top.
+ mUidPolicy->setTop(UID(1));
+ EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
+
+ // Submit real-time session to CLIENT(2) in different uid UID(1).
+ // Should pause previous session and start new session.
+ mRealtimeRequest.clientPid = PID(1);
+ mController->submit(CLIENT(2), SESSION(0), UID(1), mRealtimeRequest, mClientCallback2);
+ EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(0), SESSION(0)));
+ EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(2), SESSION(0)));
+
+ // Test 0: Basic case, no queue change during throttling, top session should pause/resume
+ // with throttling.
+ mController->onThrottlingStarted();
+ EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(2), SESSION(0)));
+ mController->onThrottlingStopped();
+ EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(2), SESSION(0)));
+
+ // Test 1: Change of queue order during thermal throttling, when throttling stops,
+ // new top session should resume.
+ mController->onThrottlingStarted();
+ EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(2), SESSION(0)));
+ mUidPolicy->setTop(UID(0));
+ EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
+ mController->onThrottlingStopped();
+ EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(0), SESSION(0)));
+
+ // Test 2: Cancel session during throttling, when throttling stops, new top
+ // session should resume.
+ mController->onThrottlingStarted();
+ EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(0), SESSION(0)));
+ // Cancel the paused top session during throttling.
+ EXPECT_TRUE(mController->cancel(CLIENT(0), SESSION(0)));
+ EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Stop(CLIENT(0), SESSION(0)));
+ // Throttling stops, CLIENT(2)'s session should start.
+ mController->onThrottlingStopped();
+ EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(2), SESSION(0)));
+
+ // Test 3: Add new queue during throttling, when throttling stops, new top
+ // session should resume.
+ mController->onThrottlingStarted();
+ EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(2), SESSION(0)));
+ // Move UID(2) to top.
+ mUidPolicy->setTop(UID(2));
+ // Submit real-time session to CLIENT(3) in UID(2), session shouldn't start during throttling.
+ mRealtimeRequest.clientPid = PID(2);
+ mController->submit(CLIENT(3), SESSION(0), UID(2), mRealtimeRequest, mClientCallback3);
+ EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
+ // Throttling stops, CLIENT(3)'s session should start.
+ mController->onThrottlingStopped();
+ EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(3), SESSION(0)));
+}
+
+/* Test resource lost and thermal throttling happening simultaneously */
+TEST_F(TranscodingSessionControllerTest, TestResourceLostAndThermalCallback) {
+ ALOGD("TestResourceLostAndThermalCallback");
+
+ // Start with unspecified top UID.
+ // Submit real-time session to CLIENT(0), session should start immediately.
+ mRealtimeRequest.clientPid = PID(0);
+ mController->submit(CLIENT(0), SESSION(0), UID(0), mRealtimeRequest, mClientCallback0);
+ EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), SESSION(0)));
+
+ // Submit offline session to CLIENT(0), should not start.
+ mOfflineRequest.clientPid = PID(0);
+ mController->submit(CLIENT(1), SESSION(0), UID(0), mOfflineRequest, mClientCallback1);
+ EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
+
+ // Move UID(1) to top.
+ mUidPolicy->setTop(UID(1));
+ EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
+
+ // Submit real-time session to CLIENT(2) in different uid UID(1).
+ // Should pause previous session and start new session.
+ mRealtimeRequest.clientPid = PID(1);
+ mController->submit(CLIENT(2), SESSION(0), UID(1), mRealtimeRequest, mClientCallback2);
+ EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(0), SESSION(0)));
+ EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(2), SESSION(0)));
+
+ // Test 0: Resource lost during throttling.
+ // Throttling starts, top session should pause.
+ mController->onThrottlingStarted();
+ EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(2), SESSION(0)));
+ // Signal resource lost, this should get ignored because the session is now paused.
+ mController->onResourceLost(CLIENT(2), SESSION(0));
+ EXPECT_EQ(mResourcePolicy->getPid(), kInvalidPid);
+ // Signal resource available, CLIENT(2) shouldn't resume.
+ mController->onResourceAvailable();
+ EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
+ // Throttling ends, top session should resume.
+ mController->onThrottlingStopped();
+ EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(2), SESSION(0)));
+
+ // Test 1: Throttling during resource lost.
+ mController->onResourceLost(CLIENT(2), SESSION(0));
+ EXPECT_EQ(mResourcePolicy->getPid(), PID(1));
+ mController->onThrottlingStarted();
+ mController->onThrottlingStopped();
+ EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
+ mController->onResourceAvailable();
+ EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(2), SESSION(0)));
+
+ // Test 2: Interleaving resource lost and throttling.
+ mController->onResourceLost(CLIENT(2), SESSION(0));
+ EXPECT_EQ(mResourcePolicy->getPid(), PID(1));
+ mController->onThrottlingStarted();
+ mController->onResourceAvailable();
+ EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
+ mController->onThrottlingStopped();
+ EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(2), SESSION(0)));
+}
+
} // namespace android