Camera: Bump the thread priority during stream configuration and open
Bump the scheduling priority of two critical performance paths
that include stream configuration and camera device open.
Flag: com.android.internal.camera.flags.realtime_priority_bump
Bug: 336628522
Test: Camera CTS,
Manual using camera application
Change-Id: I8ac10099e74bfae91bcc3b5caadc2276510c97e3
diff --git a/camera/camera_platform.aconfig b/camera/camera_platform.aconfig
index 4fcceae..2620074 100644
--- a/camera/camera_platform.aconfig
+++ b/camera/camera_platform.aconfig
@@ -217,3 +217,13 @@
description: "Miscellaneous camera platform metrics for 24Q3"
bug: "332557570"
}
+
+flag {
+ namespace: "camera_platform"
+ name: "realtime_priority_bump"
+ description: "Bump the scheduling priority of performance critical code paths"
+ bug: "336628522"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 9ec8e35..3025fb4 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -82,10 +82,11 @@
#include "CameraService.h"
#include "api1/Camera2Client.h"
#include "api2/CameraDeviceClient.h"
-#include "utils/CameraTraces.h"
-#include "utils/TagMonitor.h"
#include "utils/CameraServiceProxyWrapper.h"
+#include "utils/CameraTraces.h"
#include "utils/SessionConfigurationUtils.h"
+#include "utils/TagMonitor.h"
+#include "utils/Utils.h"
namespace {
const char* kPermissionServiceName = "permission";
@@ -2423,6 +2424,7 @@
/*out*/
sp<hardware::camera2::ICameraDeviceUser>* device) {
ATRACE_CALL();
+ RunThreadWithRealtimePriority priorityBump;
Status ret = Status::ok();
sp<CameraDeviceClient> client = nullptr;
std::string clientPackageNameAdj = clientPackageName;
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index f4d8f7f..6fc4d5c 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -2378,46 +2378,15 @@
return ret;
}
-Camera3Device::RunThreadWithRealtimePriority::RunThreadWithRealtimePriority(int tid) : mTid(tid),
- mPreviousPolicy(sched_getscheduler(tid)) {
- if (flags::surface_ipc()) {
- auto res = sched_getparam(mTid, &mPreviousParams);
- if (res != OK) {
- ALOGE("Can't retrieve thread scheduler parameters: %s (%d)",
- strerror(-res), res);
- return;
- }
-
- struct sched_param param = {0};
- param.sched_priority = kRequestThreadPriority;
-
- res = sched_setscheduler(mTid, SCHED_FIFO, ¶m);
- if (res != OK) {
- ALOGW("Can't set realtime priority for thread: %s (%d)",
- strerror(-res), res);
- } else {
- ALOGD("Set real time priority for thread (tid %d)", mTid);
- mPolicyBumped = true;
- }
- }
-}
-
-Camera3Device::RunThreadWithRealtimePriority::~RunThreadWithRealtimePriority() {
- if (mPolicyBumped && flags::surface_ipc()) {
- auto res = sched_setscheduler(mTid, mPreviousPolicy, &mPreviousParams);
- if (res != OK) {
- ALOGE("Can't set regular priority for thread: %s (%d)",
- strerror(-res), res);
- } else {
- ALOGD("Set regular priority for thread (tid %d)", mTid);
- }
- }
-}
status_t Camera3Device::configureStreamsLocked(int operatingMode,
const CameraMetadata& sessionParams, bool notifyRequestThread) {
ATRACE_CALL();
status_t res;
+ // Stream/surface setup can include a lot of binder IPC. Raise the
+ // thread priority when running the binder IPC heavy configuration
+ // sequence.
+ RunThreadWithRealtimePriority priorityBump;
if (mStatus != STATUS_UNCONFIGURED && mStatus != STATUS_CONFIGURED) {
CLOGE("Not idle");
@@ -2610,50 +2579,43 @@
mRequestThread->setHalBufferManagedStreams(mHalBufManagedStreamIds);
}
- {
- // Stream/surface setup can include a lot of binder IPC. Raise the
- // thread priority when running the binder IPC heavy configuration
- // sequence.
- RunThreadWithRealtimePriority priorityBump;
+ // Finish all stream configuration immediately.
+ // TODO: Try to relax this later back to lazy completion, which should be
+ // faster
- // Finish all stream configuration immediately.
- // TODO: Try to relax this later back to lazy completion, which should be
- // faster
+ if (mInputStream != NULL && mInputStream->isConfiguring()) {
+ bool streamReConfigured = false;
+ res = mInputStream->finishConfiguration(&streamReConfigured);
+ if (res != OK) {
+ CLOGE("Can't finish configuring input stream %d: %s (%d)", mInputStream->getId(),
+ strerror(-res), res);
+ cancelStreamsConfigurationLocked();
+ if ((res == NO_INIT || res == DEAD_OBJECT) && mInputStream->isAbandoned()) {
+ return DEAD_OBJECT;
+ }
+ return BAD_VALUE;
+ }
+ if (streamReConfigured) {
+ mInterface->onStreamReConfigured(mInputStream->getId());
+ }
+ }
- if (mInputStream != NULL && mInputStream->isConfiguring()) {
+ for (size_t i = 0; i < mOutputStreams.size(); i++) {
+ sp<Camera3OutputStreamInterface> outputStream = mOutputStreams[i];
+ if (outputStream->isConfiguring() && !outputStream->isConsumerConfigurationDeferred()) {
bool streamReConfigured = false;
- res = mInputStream->finishConfiguration(&streamReConfigured);
+ res = outputStream->finishConfiguration(&streamReConfigured);
if (res != OK) {
- CLOGE("Can't finish configuring input stream %d: %s (%d)",
- mInputStream->getId(), strerror(-res), res);
+ CLOGE("Can't finish configuring output stream %d: %s (%d)", outputStream->getId(),
+ strerror(-res), res);
cancelStreamsConfigurationLocked();
- if ((res == NO_INIT || res == DEAD_OBJECT) && mInputStream->isAbandoned()) {
+ if ((res == NO_INIT || res == DEAD_OBJECT) && outputStream->isAbandoned()) {
return DEAD_OBJECT;
}
return BAD_VALUE;
}
if (streamReConfigured) {
- mInterface->onStreamReConfigured(mInputStream->getId());
- }
- }
-
- for (size_t i = 0; i < mOutputStreams.size(); i++) {
- sp<Camera3OutputStreamInterface> outputStream = mOutputStreams[i];
- if (outputStream->isConfiguring() && !outputStream->isConsumerConfigurationDeferred()) {
- bool streamReConfigured = false;
- res = outputStream->finishConfiguration(&streamReConfigured);
- if (res != OK) {
- CLOGE("Can't finish configuring output stream %d: %s (%d)",
- outputStream->getId(), strerror(-res), res);
- cancelStreamsConfigurationLocked();
- if ((res == NO_INIT || res == DEAD_OBJECT) && outputStream->isAbandoned()) {
- return DEAD_OBJECT;
- }
- return BAD_VALUE;
- }
- if (streamReConfigured) {
- mInterface->onStreamReConfigured(outputStream->getId());
- }
+ mInterface->onStreamReConfigured(outputStream->getId());
}
}
}
@@ -2673,8 +2635,8 @@
if (disableFifo != 1) {
// Boost priority of request thread to SCHED_FIFO.
pid_t requestThreadTid = mRequestThread->getTid();
- res = SchedulingPolicyUtils::requestPriorityDirect(getpid(), requestThreadTid,
- kRequestThreadPriority);
+ res = SchedulingPolicyUtils::requestPriorityDirect(
+ getpid(), requestThreadTid, RunThreadWithRealtimePriority::kRequestThreadPriority);
if (res != OK) {
ALOGW("Can't set realtime priority for request processing thread: %s (%d)",
strerror(-res), res);
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index d646886..0cf17ae 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -373,8 +373,6 @@
static const size_t kInFlightWarnLimitHighSpeed = 256; // batch size 32 * pipe depth 8
static const nsecs_t kMinInflightDuration = 5000000000; // 5 s
static const nsecs_t kBaseGetBufferWait = 3000000000; // 3 sec.
- // SCHED_FIFO priority for request submission thread in HFR mode
- static const int kRequestThreadPriority = 1;
struct RequestTrigger;
// minimal jpeg buffer size: 256KB + blob header
@@ -1630,34 +1628,6 @@
void overrideStreamUseCaseLocked();
- // An instance of this class will raise the scheduling policy of a given
- // given thread to real time and keep it this way throughout the lifetime
- // of the object. The thread scheduling policy will revert back to its original
- // state after the instances is released. By default the implementation will
- // raise the priority of the current thread unless clients explicitly specify
- // another thread id.
- // Client must avoid:
- // - Keeping an instance of this class for extended and long running operations.
- // This is only intended for short/temporarily priority bumps that mitigate
- // scheduling delays within critical camera paths.
- // - Allocating instances of this class on the memory heap unless clients have
- // complete control over the object lifetime. It is preferable to allocate
- // instances of this class on the stack instead.
- // - Nesting multiple instances of this class using the same default or same thread id.
- class RunThreadWithRealtimePriority final {
- public:
- RunThreadWithRealtimePriority(int tid = gettid());
- ~RunThreadWithRealtimePriority();
-
- RunThreadWithRealtimePriority(const RunThreadWithRealtimePriority&) = delete;
- RunThreadWithRealtimePriority& operator=(const RunThreadWithRealtimePriority&) = delete;
-
- private:
- int mTid;
- int mPreviousPolicy;
- bool mPolicyBumped = false;
- struct sched_param mPreviousParams;
- };
}; // class Camera3Device
diff --git a/services/camera/libcameraservice/utils/Utils.cpp b/services/camera/libcameraservice/utils/Utils.cpp
index c8f5e86..34c0ed8 100644
--- a/services/camera/libcameraservice/utils/Utils.cpp
+++ b/services/camera/libcameraservice/utils/Utils.cpp
@@ -14,14 +14,17 @@
* limitations under the License.
*/
+#define LOG_TAG "Camera3-Utils"
+
#include "Utils.h"
#include <android-base/properties.h>
#include <com_android_internal_camera_flags.h>
-
+#include <utils/Errors.h>
+#include <utils/Log.h>
namespace android {
-using namespace com::android::internal::camera::flags;
+namespace flags = com::android::internal::camera::flags;
constexpr const char *LEGACY_VNDK_VERSION_PROP = "ro.vndk.version";
constexpr const char *BOARD_API_LEVEL_PROP = "ro.board.api_level";
@@ -52,4 +55,37 @@
return __ANDROID_API_V__ + vndkVersion;
}
-} // namespace android
+RunThreadWithRealtimePriority::RunThreadWithRealtimePriority(int tid)
+ : mTid(tid), mPreviousPolicy(sched_getscheduler(tid)) {
+ if (flags::realtime_priority_bump()) {
+ auto res = sched_getparam(mTid, &mPreviousParams);
+ if (res != OK) {
+ ALOGE("Can't retrieve thread scheduler parameters: %s (%d)", strerror(-res), res);
+ return;
+ }
+
+ struct sched_param param = {0};
+ param.sched_priority = kRequestThreadPriority;
+
+ res = sched_setscheduler(mTid, SCHED_FIFO, ¶m);
+ if (res != OK) {
+ ALOGW("Can't set realtime priority for thread: %s (%d)", strerror(-res), res);
+ } else {
+ ALOGD("Set real time priority for thread (tid %d)", mTid);
+ mPolicyBumped = true;
+ }
+ }
+}
+
+RunThreadWithRealtimePriority::~RunThreadWithRealtimePriority() {
+ if (mPolicyBumped && flags::realtime_priority_bump()) {
+ auto res = sched_setscheduler(mTid, mPreviousPolicy, &mPreviousParams);
+ if (res != OK) {
+ ALOGE("Can't set regular priority for thread: %s (%d)", strerror(-res), res);
+ } else {
+ ALOGD("Set regular priority for thread (tid %d)", mTid);
+ }
+ }
+}
+
+} // namespace android
diff --git a/services/camera/libcameraservice/utils/Utils.h b/services/camera/libcameraservice/utils/Utils.h
index f8a107d..4e90871 100644
--- a/services/camera/libcameraservice/utils/Utils.h
+++ b/services/camera/libcameraservice/utils/Utils.h
@@ -17,6 +17,9 @@
#ifndef ANDROID_SERVERS_CAMERA_UTILS_H
#define ANDROID_SERVERS_CAMERA_UTILS_H
+#include <sched.h>
+#include <unistd.h>
+
namespace android {
/**
@@ -28,6 +31,40 @@
*/
int getVNDKVersionFromProp(int defaultVersion);
+/**
+ * An instance of this class will raise the scheduling policy of a given
+ * given thread to real time and keep it this way throughout the lifetime
+ * of the object. The thread scheduling policy will revert back to its original
+ * state after the instances is released. By default the implementation will
+ * raise the priority of the current thread unless clients explicitly specify
+ * another thread id.
+ * Client must avoid:
+ * - Keeping an instance of this class for extended and long running operations.
+ * This is only intended for short/temporarily priority bumps that mitigate
+ * scheduling delays within critical camera paths.
+ * - Allocating instances of this class on the memory heap unless clients have
+ * complete control over the object lifetime. It is preferable to allocate
+ * instances of this class on the stack instead.
+ * - Nesting multiple instances of this class using the same default or same thread id.
+ */
+class RunThreadWithRealtimePriority final {
+ public:
+ RunThreadWithRealtimePriority(int tid = gettid());
+ ~RunThreadWithRealtimePriority();
+
+ RunThreadWithRealtimePriority(const RunThreadWithRealtimePriority&) = delete;
+ RunThreadWithRealtimePriority& operator=(const RunThreadWithRealtimePriority&) = delete;
+
+ // SCHED_FIFO priority for request submission thread in HFR mode
+ static const int kRequestThreadPriority = 1;
+
+ private:
+ int mTid;
+ int mPreviousPolicy;
+ bool mPolicyBumped = false;
+ struct sched_param mPreviousParams;
+};
+
} // namespace android
#endif //ANDROID_SERVERS_CAMERA_UTILS_H