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, &param);
-        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, &param);
+        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