Merge "GpuService: secure setUpdatableDriverPath" into rvc-dev am: 916c766b31

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/native/+/12257974

Change-Id: I630ad28304ca52e8c2d9cc759b2f93b3d204d87b
diff --git a/libs/binder/Binder.cpp b/libs/binder/Binder.cpp
index e0fb543..6ca3b16 100644
--- a/libs/binder/Binder.cpp
+++ b/libs/binder/Binder.cpp
@@ -24,6 +24,7 @@
 #include <binder/IShellCallback.h>
 #include <binder/Parcel.h>
 
+#include <linux/sched.h>
 #include <stdio.h>
 
 namespace android {
@@ -133,6 +134,8 @@
     // unlocked objects
     bool mRequestingSid = false;
     sp<IBinder> mExtension;
+    int mPolicy = SCHED_NORMAL;
+    int mPriority = 0;
 
     // for below objects
     Mutex mLock;
@@ -279,6 +282,47 @@
     return e->mExtension;
 }
 
+void BBinder::setMinSchedulerPolicy(int policy, int priority) {
+    switch (policy) {
+    case SCHED_NORMAL:
+      LOG_ALWAYS_FATAL_IF(priority < -20 || priority > 19, "Invalid priority for SCHED_NORMAL: %d", priority);
+      break;
+    case SCHED_RR:
+    case SCHED_FIFO:
+      LOG_ALWAYS_FATAL_IF(priority < 1 || priority > 99, "Invalid priority for sched %d: %d", policy, priority);
+      break;
+    default:
+      LOG_ALWAYS_FATAL("Unrecognized scheduling policy: %d", policy);
+    }
+
+    Extras* e = mExtras.load(std::memory_order_acquire);
+
+    if (e == nullptr) {
+        // Avoid allocations if called with default.
+        if (policy == SCHED_NORMAL && priority == 0) {
+            return;
+        }
+
+        e = getOrCreateExtras();
+        if (!e) return; // out of memory
+    }
+
+    e->mPolicy = policy;
+    e->mPriority = priority;
+}
+
+int BBinder::getMinSchedulerPolicy() {
+    Extras* e = mExtras.load(std::memory_order_acquire);
+    if (e == nullptr) return SCHED_NORMAL;
+    return e->mPolicy;
+}
+
+int BBinder::getMinSchedulerPriority() {
+    Extras* e = mExtras.load(std::memory_order_acquire);
+    if (e == nullptr) return 0;
+    return e->mPriority;
+}
+
 pid_t BBinder::getDebugPid() {
     return getpid();
 }
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 9642a87..d5d7435 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -20,6 +20,7 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <inttypes.h>
+#include <linux/sched.h>
 #include <pthread.h>
 #include <stdint.h>
 #include <stdio.h>
@@ -188,16 +189,18 @@
     return OK;
 }
 
+static constexpr inline int schedPolicyMask(int policy, int priority) {
+    return (priority & FLAT_BINDER_FLAG_PRIORITY_MASK) | ((policy & 3) << FLAT_BINDER_FLAG_SCHED_POLICY_SHIFT);
+}
+
 status_t Parcel::flattenBinder(const sp<IBinder>& binder)
 {
     flat_binder_object obj;
+    obj.flags = FLAT_BINDER_FLAG_ACCEPTS_FDS;
 
-    if (IPCThreadState::self()->backgroundSchedulingDisabled()) {
-        /* minimum priority for all nodes is nice 0 */
-        obj.flags = FLAT_BINDER_FLAG_ACCEPTS_FDS;
-    } else {
-        /* minimum priority for all nodes is MAX_NICE(19) */
-        obj.flags = 0x13 | FLAT_BINDER_FLAG_ACCEPTS_FDS;
+    int schedBits = 0;
+    if (!IPCThreadState::self()->backgroundSchedulingDisabled()) {
+        schedBits = schedPolicyMask(SCHED_NORMAL, 19);
     }
 
     if (binder != nullptr) {
@@ -213,6 +216,13 @@
             obj.handle = handle;
             obj.cookie = 0;
         } else {
+            int policy = local->getMinSchedulerPolicy();
+            int priority = local->getMinSchedulerPriority();
+
+            if (policy != 0 || priority != 0) {
+                // override value, since it is set explicitly
+                schedBits = schedPolicyMask(policy, priority);
+            }
             if (local->isRequestingSid()) {
                 obj.flags |= FLAT_BINDER_FLAG_TXN_SECURITY_CTX;
             }
@@ -226,6 +236,8 @@
         obj.cookie = 0;
     }
 
+    obj.flags |= schedBits;
+
     return finishFlattenBinder(binder, obj);
 }
 
diff --git a/libs/binder/include/binder/Binder.h b/libs/binder/include/binder/Binder.h
index 74e52db..4cf0515 100644
--- a/libs/binder/include/binder/Binder.h
+++ b/libs/binder/include/binder/Binder.h
@@ -72,6 +72,25 @@
     // This must be called before the object is sent to another process. Not thread safe.
     void                setExtension(const sp<IBinder>& extension);
 
+    // This must be called before the object is sent to another process. Not thread safe.
+    //
+    // This function will abort if improper parameters are set. This is like
+    // sched_setscheduler. However, it sets the minimum scheduling policy
+    // only for the duration that this specific binder object is handling the
+    // call in a threadpool. By default, this API is set to SCHED_NORMAL/0. In
+    // this case, the scheduling priority will not actually be modified from
+    // binder defaults. See also IPCThreadState::disableBackgroundScheduling.
+    //
+    // Appropriate values are:
+    // SCHED_NORMAL: -20 <= priority <= 19
+    // SCHED_RR/SCHED_FIFO: 1 <= priority <= 99
+    __attribute__((weak))
+    void                setMinSchedulerPolicy(int policy, int priority);
+    __attribute__((weak))
+    int                 getMinSchedulerPolicy();
+    __attribute__((weak))
+    int                 getMinSchedulerPriority();
+
     pid_t               getDebugPid();
 
 protected:
diff --git a/libs/binder/tests/binderLibTest.cpp b/libs/binder/tests/binderLibTest.cpp
index 40de2db..917751e 100644
--- a/libs/binder/tests/binderLibTest.cpp
+++ b/libs/binder/tests/binderLibTest.cpp
@@ -50,6 +50,9 @@
 static char *binderserversuffix;
 static char binderserverarg[] = "--binderserver";
 
+static constexpr int kSchedPolicy = SCHED_RR;
+static constexpr int kSchedPriority = 7;
+
 static String16 binderLibTestServiceName = String16("test.binderLib");
 
 enum BinderLibTestTranscationCode {
@@ -75,6 +78,7 @@
     BINDER_LIB_TEST_GET_PTR_SIZE_TRANSACTION,
     BINDER_LIB_TEST_CREATE_BINDER_TRANSACTION,
     BINDER_LIB_TEST_GET_WORK_SOURCE_TRANSACTION,
+    BINDER_LIB_TEST_GET_SCHEDULING_POLICY,
     BINDER_LIB_TEST_ECHO_VECTOR,
     BINDER_LIB_TEST_REJECT_BUF,
 };
@@ -1015,6 +1019,22 @@
     EXPECT_EQ(NO_ERROR, ret2);
 }
 
+TEST_F(BinderLibTest, SchedPolicySet) {
+    sp<IBinder> server = addServer();
+    ASSERT_TRUE(server != nullptr);
+
+    Parcel data, reply;
+    status_t ret = server->transact(BINDER_LIB_TEST_GET_SCHEDULING_POLICY, data, &reply);
+    EXPECT_EQ(NO_ERROR, ret);
+
+    int policy = reply.readInt32();
+    int priority = reply.readInt32();
+
+    EXPECT_EQ(kSchedPolicy, policy & (~SCHED_RESET_ON_FORK));
+    EXPECT_EQ(kSchedPriority, priority);
+}
+
+
 TEST_F(BinderLibTest, VectorSent) {
     Parcel data, reply;
     sp<IBinder> server = addServer();
@@ -1332,6 +1352,16 @@
                 reply->writeInt32(IPCThreadState::self()->getCallingWorkSourceUid());
                 return NO_ERROR;
             }
+            case BINDER_LIB_TEST_GET_SCHEDULING_POLICY: {
+                int policy = 0;
+                sched_param param;
+                if (0 != pthread_getschedparam(pthread_self(), &policy, &param)) {
+                    return UNKNOWN_ERROR;
+                }
+                reply->writeInt32(policy);
+                reply->writeInt32(param.sched_priority);
+                return NO_ERROR;
+            }
             case BINDER_LIB_TEST_ECHO_VECTOR: {
                 std::vector<uint64_t> vector;
                 auto err = data.readUint64Vector(&vector);
@@ -1368,6 +1398,8 @@
     {
         sp<BinderLibTestService> testService = new BinderLibTestService(index);
 
+        testService->setMinSchedulerPolicy(kSchedPolicy, kSchedPriority);
+
         /*
          * Normally would also contain functionality as well, but we are only
          * testing the extension mechanism.
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index cf269b3..e1a17db 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -732,6 +732,8 @@
         mSharedBufferHasBeenQueued = false;
     }
 
+    mDequeuedSlots.insert(buf);
+
     return OK;
 }
 
@@ -760,6 +762,8 @@
         mSharedBufferHasBeenQueued = true;
     }
 
+    mDequeuedSlots.erase(i);
+
     return OK;
 }
 
@@ -895,6 +899,8 @@
         ALOGE("queueBuffer: error queuing buffer to SurfaceTexture, %d", err);
     }
 
+    mDequeuedSlots.erase(i);
+
     if (mEnableFrameTimestamps) {
         mFrameEventHistory->applyDelta(output.frameTimestamps);
         // Update timestamps with the local acquire fence.
@@ -1660,6 +1666,7 @@
         mRemovedBuffers.push_back(mSlots[attachedSlot].buffer);
     }
     mSlots[attachedSlot].buffer = graphicBuffer;
+    mDequeuedSlots.insert(attachedSlot);
 
     return NO_ERROR;
 }
@@ -1926,6 +1933,10 @@
 }
 
 void Surface::freeAllBuffers() {
+    if (!mDequeuedSlots.empty()) {
+        ALOGE("%s: %zu buffers were freed while being dequeued!",
+                __FUNCTION__, mDequeuedSlots.size());
+    }
     for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
         mSlots[i].buffer = nullptr;
     }
@@ -1947,6 +1958,10 @@
             ALOGW("%s: Discarded slot %d doesn't contain buffer!", __FUNCTION__, i);
             continue;
         }
+        // Don't flush currently dequeued buffers
+        if (mDequeuedSlots.count(i) > 0) {
+            continue;
+        }
         outBuffers->push_back(mSlots[i].buffer);
         mSlots[i].buffer = nullptr;
     }
diff --git a/libs/gui/include/gui/Surface.h b/libs/gui/include/gui/Surface.h
index 49c83da..55b4101 100644
--- a/libs/gui/include/gui/Surface.h
+++ b/libs/gui/include/gui/Surface.h
@@ -30,6 +30,7 @@
 #include <utils/RefBase.h>
 
 #include <shared_mutex>
+#include <unordered_set>
 
 namespace android {
 
@@ -543,8 +544,15 @@
     int mMaxBufferCount;
 
     sp<IProducerListener> mListenerProxy;
+
+    // Get and flush the buffers of given slots, if the buffer in the slot
+    // is currently dequeued then it won't be flushed and won't be returned
+    // in outBuffers.
     status_t getAndFlushBuffersFromSlots(const std::vector<int32_t>& slots,
             std::vector<sp<GraphicBuffer>>* outBuffers);
+
+    // Buffers that are successfully dequeued/attached and handed to clients
+    std::unordered_set<int> mDequeuedSlots;
 };
 
 } // namespace android
diff --git a/services/inputflinger/reader/include/TouchVideoDevice.h b/services/inputflinger/reader/include/TouchVideoDevice.h
index 5a32443..7de9b830 100644
--- a/services/inputflinger/reader/include/TouchVideoDevice.h
+++ b/services/inputflinger/reader/include/TouchVideoDevice.h
@@ -102,7 +102,7 @@
      * How many buffers to keep for the internal queue. When the internal buffer
      * exceeds this capacity, oldest frames will be dropped.
      */
-    static constexpr size_t MAX_QUEUE_SIZE = 10;
+    static constexpr size_t MAX_QUEUE_SIZE = 20;
     std::vector<TouchVideoFrame> mFrames;
 
     /**
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 07690cb..0ac3d32 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -2121,7 +2121,8 @@
         mTimeStats->incrementCompositionStrategyChanges();
     }
 
-    mVSyncModulator->onRefreshed(mHadClientComposition);
+    // TODO: b/160583065 Enable skip validation when SF caches all client composition layers
+    mVSyncModulator->onRefreshed(mHadClientComposition || mReusedClientComposition);
 
     mLayersWithQueuedFrames.clear();
     if (mVisibleRegionsDirty) {