SF: fix binder thread priority

Add setMinSchedulerPolicy to all binder interfaces SF exposes.
It was missing from gui::ISurfaceComposer and
gui::IDisplayEventConnection.

Test: presubmit
Bug: 299378819
Change-Id: Ia0d99efa5a3bc58625c320d4df3c08bb597d2e38
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index b526a6c..ff6b558 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -25,6 +25,7 @@
 #include <gui/IGraphicBufferProducer.h>
 #include <gui/ISurfaceComposer.h>
 #include <gui/LayerState.h>
+#include <gui/SchedulingPolicy.h>
 #include <private/gui/ParcelUtils.h>
 #include <stdint.h>
 #include <sys/types.h>
@@ -201,6 +202,18 @@
                                        isAutoTimestamp, uncacheBuffers, hasListenerCallbacks,
                                        listenerCallbacks, transactionId, mergedTransactions);
         }
+        case GET_SCHEDULING_POLICY: {
+            gui::SchedulingPolicy policy;
+            const auto status = gui::getSchedulingPolicy(&policy);
+            if (!status.isOk()) {
+                return status.exceptionCode();
+            }
+
+            SAFE_PARCEL(reply->writeInt32, policy.policy);
+            SAFE_PARCEL(reply->writeInt32, policy.priority);
+            return NO_ERROR;
+        }
+
         default: {
             return BBinder::onTransact(code, data, reply, flags);
         }
diff --git a/libs/gui/aidl/android/gui/IDisplayEventConnection.aidl b/libs/gui/aidl/android/gui/IDisplayEventConnection.aidl
index 9781ca9..008ef19 100644
--- a/libs/gui/aidl/android/gui/IDisplayEventConnection.aidl
+++ b/libs/gui/aidl/android/gui/IDisplayEventConnection.aidl
@@ -18,6 +18,7 @@
 
 import android.gui.BitTube;
 import android.gui.ParcelableVsyncEventData;
+import android.gui.SchedulingPolicy;
 
 /** @hide */
 interface IDisplayEventConnection {
@@ -44,4 +45,9 @@
      * getLatestVsyncEventData() gets the latest vsync event data.
      */
     ParcelableVsyncEventData getLatestVsyncEventData();
+
+    /*
+     * getSchedulingPolicy() used in tests to validate the binder thread pririty
+     */
+    SchedulingPolicy getSchedulingPolicy();
 }
diff --git a/libs/gui/aidl/android/gui/ISurfaceComposer.aidl b/libs/gui/aidl/android/gui/ISurfaceComposer.aidl
index 1c604a1..507e086 100644
--- a/libs/gui/aidl/android/gui/ISurfaceComposer.aidl
+++ b/libs/gui/aidl/android/gui/ISurfaceComposer.aidl
@@ -46,6 +46,7 @@
 import android.gui.OverlayProperties;
 import android.gui.PullAtomData;
 import android.gui.ARect;
+import android.gui.SchedulingPolicy;
 import android.gui.StalledTransactionInfo;
 import android.gui.StaticDisplayInfo;
 import android.gui.WindowInfosListenerInfo;
@@ -545,4 +546,6 @@
      * applied in SurfaceFlinger due to an unsignaled fence. Otherwise, null is returned.
      */
     @nullable StalledTransactionInfo getStalledTransactionInfo(int pid);
+
+    SchedulingPolicy getSchedulingPolicy();
 }
diff --git a/libs/gui/aidl/android/gui/ISurfaceComposerClient.aidl b/libs/gui/aidl/android/gui/ISurfaceComposerClient.aidl
index 68781ce..920257c 100644
--- a/libs/gui/aidl/android/gui/ISurfaceComposerClient.aidl
+++ b/libs/gui/aidl/android/gui/ISurfaceComposerClient.aidl
@@ -19,6 +19,7 @@
 import android.gui.CreateSurfaceResult;
 import android.gui.FrameStats;
 import android.gui.LayerMetadata;
+import android.gui.SchedulingPolicy;
 
 /** @hide */
 interface ISurfaceComposerClient {
@@ -60,4 +61,6 @@
     CreateSurfaceResult mirrorSurface(IBinder mirrorFromHandle);
 
     CreateSurfaceResult mirrorDisplay(long displayId);
+
+    SchedulingPolicy getSchedulingPolicy();
 }
diff --git a/libs/gui/aidl/android/gui/SchedulingPolicy.aidl b/libs/gui/aidl/android/gui/SchedulingPolicy.aidl
new file mode 100644
index 0000000..4f7cf0a
--- /dev/null
+++ b/libs/gui/aidl/android/gui/SchedulingPolicy.aidl
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2023 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.
+ */
+
+package android.gui;
+
+/** @hide */
+parcelable SchedulingPolicy {
+    int policy;
+    int priority;
+}
diff --git a/libs/gui/fuzzer/libgui_fuzzer_utils.h b/libs/gui/fuzzer/libgui_fuzzer_utils.h
index bdf8856..3142103 100644
--- a/libs/gui/fuzzer/libgui_fuzzer_utils.h
+++ b/libs/gui/fuzzer/libgui_fuzzer_utils.h
@@ -166,6 +166,7 @@
     MOCK_METHOD(binder::Status, getOverlaySupport, (gui::OverlayProperties*), (override));
     MOCK_METHOD(binder::Status, getStalledTransactionInfo,
                 (int32_t, std::optional<gui::StalledTransactionInfo>*), (override));
+    MOCK_METHOD(binder::Status, getSchedulingPolicy, (gui::SchedulingPolicy*), (override));
 };
 
 class FakeBnSurfaceComposerClient : public gui::BnSurfaceComposerClient {
@@ -186,6 +187,8 @@
 
     MOCK_METHOD(binder::Status, mirrorDisplay,
                 (int64_t displayId, gui::CreateSurfaceResult* outResult), (override));
+
+    MOCK_METHOD(binder::Status, getSchedulingPolicy, (gui::SchedulingPolicy*), (override));
 };
 
 class FakeDisplayEventDispatcher : public DisplayEventDispatcher {
diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h
index 3ff6735..a836f46 100644
--- a/libs/gui/include/gui/ISurfaceComposer.h
+++ b/libs/gui/include/gui/ISurfaceComposer.h
@@ -199,6 +199,7 @@
         SET_BOOT_DISPLAY_MODE,         // Deprecated. Autogenerated by .aidl now.
         CLEAR_BOOT_DISPLAY_MODE,       // Deprecated. Autogenerated by .aidl now.
         SET_OVERRIDE_FRAME_RATE,       // Deprecated. Autogenerated by .aidl now.
+        GET_SCHEDULING_POLICY,
         // Always append new enum to the end.
     };
 
diff --git a/libs/gui/include/gui/SchedulingPolicy.h b/libs/gui/include/gui/SchedulingPolicy.h
new file mode 100644
index 0000000..48c9f0c
--- /dev/null
+++ b/libs/gui/include/gui/SchedulingPolicy.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2023 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.
+ */
+
+#pragma once
+
+#include <sched.h>
+
+#include <android/gui/SchedulingPolicy.h>
+#include <binder/Status.h>
+
+namespace android::gui {
+
+static binder::Status getSchedulingPolicy(gui::SchedulingPolicy* outPolicy) {
+    outPolicy->policy = sched_getscheduler(0);
+    if (outPolicy->policy < 0) {
+        return binder::Status::fromExceptionCode(EX_ILLEGAL_STATE);
+    }
+
+    struct sched_param param;
+    if (sched_getparam(0, &param) < 0) {
+        return binder::Status::fromExceptionCode(EX_ILLEGAL_STATE);
+    }
+    outPolicy->priority = param.sched_priority;
+    return binder::Status::ok();
+}
+
+} // namespace android::gui
\ No newline at end of file
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index daed764..9eee699 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -1036,6 +1036,10 @@
         return binder::Status::ok();
     }
 
+    binder::Status getSchedulingPolicy(gui::SchedulingPolicy*) override {
+        return binder::Status::ok();
+    }
+
 protected:
     IBinder* onAsBinder() override { return nullptr; }
 
diff --git a/services/surfaceflinger/Client.cpp b/services/surfaceflinger/Client.cpp
index bdbc79b..6b4215e 100644
--- a/services/surfaceflinger/Client.cpp
+++ b/services/surfaceflinger/Client.cpp
@@ -22,6 +22,7 @@
 #include <private/android_filesystem_config.h>
 
 #include <gui/AidlStatusUtil.h>
+#include <gui/SchedulingPolicy.h>
 
 #include "Client.h"
 #include "FrontEnd/LayerCreationArgs.h"
@@ -117,5 +118,9 @@
     return binderStatusFromStatusT(status);
 }
 
+binder::Status Client::getSchedulingPolicy(gui::SchedulingPolicy* outPolicy) {
+    return gui::getSchedulingPolicy(outPolicy);
+}
+
 // ---------------------------------------------------------------------------
 }; // namespace android
diff --git a/services/surfaceflinger/Client.h b/services/surfaceflinger/Client.h
index af410ea..77916e0 100644
--- a/services/surfaceflinger/Client.h
+++ b/services/surfaceflinger/Client.h
@@ -55,6 +55,8 @@
 
     binder::Status mirrorDisplay(int64_t displayId, gui::CreateSurfaceResult* outResult) override;
 
+    binder::Status getSchedulingPolicy(gui::SchedulingPolicy* outPolicy) override;
+
     // constant
     sp<SurfaceFlinger> mFlinger;
 
diff --git a/services/surfaceflinger/Scheduler/EventThread.cpp b/services/surfaceflinger/Scheduler/EventThread.cpp
index edab7ec..9a55c94 100644
--- a/services/surfaceflinger/Scheduler/EventThread.cpp
+++ b/services/surfaceflinger/Scheduler/EventThread.cpp
@@ -38,6 +38,7 @@
 #include <cutils/sched_policy.h>
 
 #include <gui/DisplayEventReceiver.h>
+#include <gui/SchedulingPolicy.h>
 
 #include <utils/Errors.h>
 #include <utils/Trace.h>
@@ -218,6 +219,10 @@
     return binder::Status::ok();
 }
 
+binder::Status EventThreadConnection::getSchedulingPolicy(gui::SchedulingPolicy* outPolicy) {
+    return gui::getSchedulingPolicy(outPolicy);
+}
+
 status_t EventThreadConnection::postEvent(const DisplayEventReceiver::Event& event) {
     constexpr auto toStatus = [](ssize_t size) {
         return size < 0 ? status_t(size) : status_t(NO_ERROR);
@@ -300,9 +305,14 @@
 
 sp<EventThreadConnection> EventThread::createEventConnection(
         EventRegistrationFlags eventRegistration) const {
-    return sp<EventThreadConnection>::make(const_cast<EventThread*>(this),
-                                           IPCThreadState::self()->getCallingUid(),
-                                           eventRegistration);
+    auto connection = sp<EventThreadConnection>::make(const_cast<EventThread*>(this),
+                                                      IPCThreadState::self()->getCallingUid(),
+                                                      eventRegistration);
+    if (flags::misc1()) {
+        const int policy = SCHED_FIFO;
+        connection->setMinSchedulerPolicy(policy, sched_get_priority_min(policy));
+    }
+    return connection;
 }
 
 status_t EventThread::registerDisplayEventConnection(const sp<EventThreadConnection>& connection) {
diff --git a/services/surfaceflinger/Scheduler/EventThread.h b/services/surfaceflinger/Scheduler/EventThread.h
index a7c8b74..7842318 100644
--- a/services/surfaceflinger/Scheduler/EventThread.h
+++ b/services/surfaceflinger/Scheduler/EventThread.h
@@ -78,6 +78,7 @@
     binder::Status setVsyncRate(int rate) override;
     binder::Status requestNextVsync() override; // asynchronous
     binder::Status getLatestVsyncEventData(ParcelableVsyncEventData* outVsyncEventData) override;
+    binder::Status getSchedulingPolicy(gui::SchedulingPolicy* outPolicy) override;
 
     VSyncRequest vsyncRequest = VSyncRequest::None;
     const uid_t mOwnerUid;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 12aacad..3f52444 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -113,6 +113,7 @@
 #include <vector>
 
 #include <gui/LayerStatePermissions.h>
+#include <gui/SchedulingPolicy.h>
 #include <ui/DisplayIdentification.h>
 #include "BackgroundExecutor.h"
 #include "Client.h"
@@ -6579,6 +6580,7 @@
         case GET_ACTIVE_DISPLAY_MODE:
         case GET_DISPLAY_COLOR_MODES:
         case GET_DISPLAY_MODES:
+        case GET_SCHEDULING_POLICY:
         // Calling setTransactionState is safe, because you need to have been
         // granted a reference to Client* and Handle* to do anything with it.
         case SET_TRANSACTION_STATE: {
@@ -9016,6 +9018,10 @@
     const sp<Client> client = sp<Client>::make(mFlinger);
     if (client->initCheck() == NO_ERROR) {
         *outClient = client;
+        if (flags::misc1()) {
+            const int policy = SCHED_FIFO;
+            client->setMinSchedulerPolicy(policy, sched_get_priority_min(policy));
+        }
         return binder::Status::ok();
     } else {
         *outClient = nullptr;
@@ -9797,6 +9803,10 @@
     return binderStatusFromStatusT(status);
 }
 
+binder::Status SurfaceComposerAIDL::getSchedulingPolicy(gui::SchedulingPolicy* outPolicy) {
+    return gui::getSchedulingPolicy(outPolicy);
+}
+
 status_t SurfaceComposerAIDL::checkAccessPermission(bool usePermissionCache) {
     if (!mFlinger->callingThreadHasUnscopedSurfaceFlingerAccess(usePermissionCache)) {
         IPCThreadState* ipc = IPCThreadState::self();
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 42825f7..a5a2341 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -1581,8 +1581,9 @@
                                           gui::WindowInfosListenerInfo* outInfo) override;
     binder::Status removeWindowInfosListener(
             const sp<gui::IWindowInfosListener>& windowInfosListener) override;
-    binder::Status getStalledTransactionInfo(int pid,
-                                             std::optional<gui::StalledTransactionInfo>* outInfo);
+    binder::Status getStalledTransactionInfo(
+            int pid, std::optional<gui::StalledTransactionInfo>* outInfo) override;
+    binder::Status getSchedulingPolicy(gui::SchedulingPolicy* outPolicy) override;
 
 private:
     static const constexpr bool kUsePermissionCache = true;
diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzer.cpp b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzer.cpp
index ed8bb7f..d13189e 100644
--- a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzer.cpp
+++ b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzer.cpp
@@ -94,6 +94,7 @@
         BnSurfaceComposer::REMOVE_TUNNEL_MODE_ENABLED_LISTENER,
         BnSurfaceComposer::ADD_WINDOW_INFOS_LISTENER,
         BnSurfaceComposer::REMOVE_WINDOW_INFOS_LISTENER,
+        BnSurfaceComposer::GET_SCHEDULING_POLICY,
 };
 
 static constexpr uint32_t kMinCode = 1000;
diff --git a/services/surfaceflinger/main_surfaceflinger.cpp b/services/surfaceflinger/main_surfaceflinger.cpp
index cf23169..9599452 100644
--- a/services/surfaceflinger/main_surfaceflinger.cpp
+++ b/services/surfaceflinger/main_surfaceflinger.cpp
@@ -149,6 +149,9 @@
 
     // publish gui::ISurfaceComposer, the new AIDL interface
     sp<SurfaceComposerAIDL> composerAIDL = sp<SurfaceComposerAIDL>::make(flinger);
+    if (flags::misc1()) {
+        composerAIDL->setMinSchedulerPolicy(SCHED_FIFO, newPriority);
+    }
     sm->addService(String16("SurfaceFlingerAIDL"), composerAIDL, false,
                    IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL | IServiceManager::DUMP_FLAG_PROTO);
 
diff --git a/services/surfaceflinger/tests/Android.bp b/services/surfaceflinger/tests/Android.bp
index b5168b0..36b1972 100644
--- a/services/surfaceflinger/tests/Android.bp
+++ b/services/surfaceflinger/tests/Android.bp
@@ -30,6 +30,7 @@
     test_suites: ["device-tests"],
     srcs: [
         "BootDisplayMode_test.cpp",
+        "Binder_test.cpp",
         "BufferGenerator.cpp",
         "CommonTypes_test.cpp",
         "Credentials_test.cpp",
diff --git a/services/surfaceflinger/tests/Binder_test.cpp b/services/surfaceflinger/tests/Binder_test.cpp
new file mode 100644
index 0000000..3152973
--- /dev/null
+++ b/services/surfaceflinger/tests/Binder_test.cpp
@@ -0,0 +1,225 @@
+/*
+ * Copyright 2023 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.
+ */
+
+#include <errno.h>
+#include <sched.h>
+
+#include <android/gui/ISurfaceComposer.h>
+#include <android/gui/ISurfaceComposerClient.h>
+#include <binder/IBinder.h>
+#include <binder/IServiceManager.h>
+#include <gtest/gtest.h>
+#include <gui/ISurfaceComposer.h>
+
+#include <com_android_graphics_surfaceflinger_flags.h>
+
+namespace android::test {
+using namespace com::android::graphics::surfaceflinger;
+
+class BinderTest : public ::testing::Test {
+protected:
+    BinderTest();
+
+    void SetUp() override;
+
+    void getSchedulingPolicy(gui::SchedulingPolicy* outPolicy);
+    void getNonAidlSchedulingPolicy(gui::SchedulingPolicy* outPolicy);
+    void getClientSchedulingPolicy(gui::SchedulingPolicy* outPolicy);
+    void getDisplayEventConnectionSchedulingPolicy(gui::SchedulingPolicy* outPolicy);
+
+private:
+    sp<gui::ISurfaceComposer> mISurfaceComposerAidl;
+    sp<ISurfaceComposer> mISurfaceComposer;
+    sp<gui::ISurfaceComposerClient> mISurfaceComposerClient;
+    sp<gui::IDisplayEventConnection> mConnection;
+};
+
+BinderTest::BinderTest() {
+    const String16 name("SurfaceFlingerAIDL");
+    mISurfaceComposerAidl = waitForService<gui::ISurfaceComposer>(String16("SurfaceFlingerAIDL"));
+    mISurfaceComposer = waitForService<ISurfaceComposer>(String16("SurfaceFlinger"));
+    mISurfaceComposerAidl->createConnection(&mISurfaceComposerClient);
+    mISurfaceComposerAidl
+            ->createDisplayEventConnection(gui::ISurfaceComposer::VsyncSource::eVsyncSourceApp,
+                                           gui::ISurfaceComposer::EventRegistration(0), {},
+                                           &mConnection);
+}
+
+void BinderTest::SetUp() {
+    ASSERT_TRUE(mISurfaceComposerAidl);
+    ASSERT_TRUE(mISurfaceComposer);
+    ASSERT_TRUE(mISurfaceComposerClient);
+    ASSERT_TRUE(mConnection);
+}
+
+void BinderTest::getSchedulingPolicy(gui::SchedulingPolicy* outPolicy) {
+    const auto status = mISurfaceComposerAidl->getSchedulingPolicy(outPolicy);
+    ASSERT_TRUE(status.isOk());
+}
+
+void BinderTest::getNonAidlSchedulingPolicy(gui::SchedulingPolicy* outPolicy) {
+    Parcel data, reply;
+    const status_t status =
+            IInterface::asBinder(mISurfaceComposer)
+                    ->transact(BnSurfaceComposer::GET_SCHEDULING_POLICY, data, &reply);
+    ASSERT_EQ(OK, status);
+
+    outPolicy->policy = reply.readInt32();
+    outPolicy->priority = reply.readInt32();
+}
+
+void BinderTest::getClientSchedulingPolicy(gui::SchedulingPolicy* outPolicy) {
+    const auto status = mISurfaceComposerClient->getSchedulingPolicy(outPolicy);
+    ASSERT_TRUE(status.isOk());
+}
+
+void BinderTest::getDisplayEventConnectionSchedulingPolicy(gui::SchedulingPolicy* outPolicy) {
+    const auto status = mConnection->getSchedulingPolicy(outPolicy);
+    ASSERT_TRUE(status.isOk());
+}
+
+TEST_F(BinderTest, SchedulingPolicy) {
+    if (!flags::misc1()) GTEST_SKIP();
+
+    const int policy = SCHED_FIFO;
+    const int priority = sched_get_priority_min(policy);
+
+    gui::SchedulingPolicy sfPolicy;
+    ASSERT_NO_FATAL_FAILURE(getSchedulingPolicy(&sfPolicy));
+
+    ASSERT_EQ(policy, sfPolicy.policy & (~SCHED_RESET_ON_FORK));
+    ASSERT_EQ(priority, sfPolicy.priority);
+}
+
+TEST_F(BinderTest, NonAidlSchedulingPolicy) {
+    const int policy = SCHED_FIFO;
+    const int priority = sched_get_priority_min(policy);
+
+    gui::SchedulingPolicy sfPolicy;
+    ASSERT_NO_FATAL_FAILURE(getNonAidlSchedulingPolicy(&sfPolicy));
+
+    ASSERT_EQ(policy, sfPolicy.policy & (~SCHED_RESET_ON_FORK));
+    ASSERT_EQ(priority, sfPolicy.priority);
+}
+
+TEST_F(BinderTest, ClientSchedulingPolicy) {
+    if (!flags::misc1()) GTEST_SKIP();
+
+    const int policy = SCHED_FIFO;
+    const int priority = sched_get_priority_min(policy);
+
+    gui::SchedulingPolicy sfPolicy;
+    ASSERT_NO_FATAL_FAILURE(getClientSchedulingPolicy(&sfPolicy));
+
+    ASSERT_EQ(policy, sfPolicy.policy & (~SCHED_RESET_ON_FORK));
+    ASSERT_EQ(priority, sfPolicy.priority);
+}
+
+TEST_F(BinderTest, DisplayEventConnectionSchedulingPolicy) {
+    if (!flags::misc1()) GTEST_SKIP();
+
+    const int policy = SCHED_FIFO;
+    const int priority = sched_get_priority_min(policy);
+
+    gui::SchedulingPolicy sfPolicy;
+    ASSERT_NO_FATAL_FAILURE(getDisplayEventConnectionSchedulingPolicy(&sfPolicy));
+
+    ASSERT_EQ(policy, sfPolicy.policy & (~SCHED_RESET_ON_FORK));
+    ASSERT_EQ(priority, sfPolicy.priority);
+}
+
+class BinderTestRtCaller : public BinderTest {
+protected:
+    void SetUp() override;
+    void TearDown() override;
+
+private:
+    int mOrigPolicy;
+    int mOrigPriority;
+};
+
+void BinderTestRtCaller::SetUp() {
+    const int policy = SCHED_FIFO;
+    const int priority = sched_get_priority_min(policy);
+
+    mOrigPolicy = sched_getscheduler(0);
+    struct sched_param origSchedParam;
+    ASSERT_GE(0, sched_getparam(0, &origSchedParam)) << "errno: " << strerror(errno);
+    mOrigPriority = origSchedParam.sched_priority;
+
+    struct sched_param param;
+    param.sched_priority = priority;
+    ASSERT_GE(0, sched_setscheduler(0, policy, &param)) << "errno: " << strerror(errno);
+}
+
+void BinderTestRtCaller::TearDown() {
+    struct sched_param origSchedParam;
+    origSchedParam.sched_priority = mOrigPriority;
+    ASSERT_GE(0, sched_setscheduler(0, mOrigPolicy, &origSchedParam))
+            << "errno: " << strerror(errno);
+}
+
+TEST_F(BinderTestRtCaller, SchedulingPolicy) {
+    if (!flags::misc1()) GTEST_SKIP();
+
+    const int policy = SCHED_FIFO;
+    const int priority = sched_get_priority_min(policy);
+
+    gui::SchedulingPolicy sfPolicy;
+    ASSERT_NO_FATAL_FAILURE(getSchedulingPolicy(&sfPolicy));
+
+    ASSERT_EQ(policy, sfPolicy.policy & (~SCHED_RESET_ON_FORK));
+    ASSERT_EQ(priority, sfPolicy.priority);
+}
+
+TEST_F(BinderTestRtCaller, NonAidlSchedulingPolicy) {
+    const int policy = SCHED_FIFO;
+    const int priority = sched_get_priority_min(policy);
+
+    gui::SchedulingPolicy sfPolicy;
+    ASSERT_NO_FATAL_FAILURE(getNonAidlSchedulingPolicy(&sfPolicy));
+
+    ASSERT_EQ(policy, sfPolicy.policy & (~SCHED_RESET_ON_FORK));
+    ASSERT_EQ(priority, sfPolicy.priority);
+}
+
+TEST_F(BinderTestRtCaller, ClientSchedulingPolicy) {
+    if (!flags::misc1()) GTEST_SKIP();
+
+    const int policy = SCHED_FIFO;
+    const int priority = sched_get_priority_min(policy);
+
+    gui::SchedulingPolicy sfPolicy;
+    ASSERT_NO_FATAL_FAILURE(getClientSchedulingPolicy(&sfPolicy));
+
+    ASSERT_EQ(policy, sfPolicy.policy & (~SCHED_RESET_ON_FORK));
+    ASSERT_EQ(priority, sfPolicy.priority);
+}
+
+TEST_F(BinderTestRtCaller, DisplayEventConnectionSchedulingPolicy) {
+    if (!flags::misc1()) GTEST_SKIP();
+
+    const int policy = SCHED_FIFO;
+    const int priority = sched_get_priority_min(policy);
+
+    gui::SchedulingPolicy sfPolicy;
+    ASSERT_NO_FATAL_FAILURE(getDisplayEventConnectionSchedulingPolicy(&sfPolicy));
+
+    ASSERT_EQ(policy, sfPolicy.policy & (~SCHED_RESET_ON_FORK));
+    ASSERT_EQ(priority, sfPolicy.priority);
+}
+
+} // namespace android::test