Merge "Check FLAG_CLEAR_BUF behavior."
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 9bba369..8087443 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -1477,6 +1477,31 @@
     goto data_sorted;
 }
 
+status_t Parcel::readVectorSizeWithCoarseBoundCheck(int32_t *size) const {
+    int32_t requestedSize;
+    const status_t status = readInt32(&requestedSize);
+    if (status != NO_ERROR) return status;
+
+    // We permit negative sizes, which indicate presence of a nullable vector,
+    // i.e. a vector embedded in std::optional, std::unique_ptr, or std::shared_ptr.
+    if (requestedSize > 0) {
+        // Check if there are fewer bytes than vector elements.
+        // A lower bound is 1 byte per element, satisfied by some enum and int8_t and uint8_t.
+        const size_t availableBytes = dataAvail();
+        if (static_cast<size_t>(requestedSize) > availableBytes) {
+            // We have a size that is greater than the number of bytes available.
+            // On bounds failure we do not 'rewind' position by 4 bytes of the size already read.
+            ALOGW("%s: rejecting out of bounds vector size (requestedSize):%d "
+                    "Parcel{dataAvail:%zu mDataSize:%zu mDataPos:%zu mDataCapacity:%zu}",
+                    __func__, requestedSize, availableBytes, mDataSize, mDataPos, mDataCapacity);
+            return BAD_VALUE;
+        }
+    }
+
+    *size = requestedSize;
+    return NO_ERROR;
+}
+
 status_t Parcel::read(void* outData, size_t len) const
 {
     if (len > INT32_MAX) {
@@ -1699,7 +1724,7 @@
 status_t Parcel::readBoolVector(std::optional<std::vector<bool>>* val) const {
     const int32_t start = dataPosition();
     int32_t size;
-    status_t status = readInt32(&size);
+    status_t status = readVectorSizeWithCoarseBoundCheck(&size);
     val->reset();
 
     if (status != OK || size < 0) {
@@ -1721,7 +1746,7 @@
 status_t Parcel::readBoolVector(std::unique_ptr<std::vector<bool>>* val) const {
     const int32_t start = dataPosition();
     int32_t size;
-    status_t status = readInt32(&size);
+    status_t status = readVectorSizeWithCoarseBoundCheck(&size);
     val->reset();
 
     if (status != OK || size < 0) {
@@ -1742,7 +1767,7 @@
 
 status_t Parcel::readBoolVector(std::vector<bool>* val) const {
     int32_t size;
-    status_t status = readInt32(&size);
+    status_t status = readVectorSizeWithCoarseBoundCheck(&size);
 
     if (status != OK) {
         return status;
diff --git a/libs/binder/ParcelableHolder.cpp b/libs/binder/ParcelableHolder.cpp
index b2b8671..2e86b74 100644
--- a/libs/binder/ParcelableHolder.cpp
+++ b/libs/binder/ParcelableHolder.cpp
@@ -37,7 +37,7 @@
         size_t sizePos = p->dataPosition();
         RETURN_ON_FAILURE(p->writeInt32(0));
         size_t dataStartPos = p->dataPosition();
-        RETURN_ON_FAILURE(p->writeUtf8AsUtf16(this->mParcelableName));
+        RETURN_ON_FAILURE(p->writeString16(this->mParcelableName));
         this->mParcelable->writeToParcel(p);
         size_t dataSize = p->dataPosition() - dataStartPos;
 
diff --git a/libs/binder/include/binder/Parcel.h b/libs/binder/include/binder/Parcel.h
index b49951b..54c49e4 100644
--- a/libs/binder/include/binder/Parcel.h
+++ b/libs/binder/include/binder/Parcel.h
@@ -517,6 +517,11 @@
     void                initState();
     void                scanForFds() const;
     status_t            validateReadData(size_t len) const;
+
+    // Reads an int32 size and does a coarse bounds check against the number
+    // of available bytes in the Parcel.
+    status_t            readVectorSizeWithCoarseBoundCheck(int32_t *size) const;
+
     void                updateWorkSourceRequestHeaderPosition() const;
 
     status_t            finishFlattenBinder(const sp<IBinder>& binder);
@@ -787,6 +792,7 @@
 template<typename T>
 status_t Parcel::resizeOutVector(std::vector<T>* val) const {
     int32_t size;
+    // used for allocating 'out' vector args, do not use readVectorSizeWithCoarseBoundCheck() here
     status_t err = readInt32(&size);
     if (err != NO_ERROR) {
         return err;
@@ -802,6 +808,7 @@
 template<typename T>
 status_t Parcel::resizeOutVector(std::optional<std::vector<T>>* val) const {
     int32_t size;
+    // used for allocating 'out' vector args, do not use readVectorSizeWithCoarseBoundCheck() here
     status_t err = readInt32(&size);
     if (err != NO_ERROR) {
         return err;
@@ -818,6 +825,7 @@
 template<typename T>
 status_t Parcel::resizeOutVector(std::unique_ptr<std::vector<T>>* val) const {
     int32_t size;
+    // used for allocating 'out' vector args, do not use readVectorSizeWithCoarseBoundCheck() here
     status_t err = readInt32(&size);
     if (err != NO_ERROR) {
         return err;
@@ -834,7 +842,7 @@
 template<typename T>
 status_t Parcel::reserveOutVector(std::vector<T>* val, size_t* size) const {
     int32_t read_size;
-    status_t err = readInt32(&read_size);
+    status_t err = readVectorSizeWithCoarseBoundCheck(&read_size);
     if (err != NO_ERROR) {
         return err;
     }
@@ -850,7 +858,7 @@
 template<typename T>
 status_t Parcel::reserveOutVector(std::optional<std::vector<T>>* val, size_t* size) const {
     int32_t read_size;
-    status_t err = readInt32(&read_size);
+    status_t err = readVectorSizeWithCoarseBoundCheck(&read_size);
     if (err != NO_ERROR) {
         return err;
     }
@@ -870,7 +878,7 @@
 status_t Parcel::reserveOutVector(std::unique_ptr<std::vector<T>>* val,
                                   size_t* size) const {
     int32_t read_size;
-    status_t err = readInt32(&read_size);
+    status_t err = readVectorSizeWithCoarseBoundCheck(&read_size);
     if (err != NO_ERROR) {
         return err;
     }
@@ -923,7 +931,7 @@
         std::vector<T>* val,
         status_t(Parcel::*read_func)(U*) const) const {
     int32_t size;
-    status_t status = this->readInt32(&size);
+    status_t status = this->readVectorSizeWithCoarseBoundCheck(&size);
 
     if (status != OK) {
         return status;
@@ -965,7 +973,7 @@
                                          status_t(Parcel::*read_func)(T*) const) const {
     const size_t start = dataPosition();
     int32_t size;
-    status_t status = readInt32(&size);
+    status_t status = readVectorSizeWithCoarseBoundCheck(&size);
     val->reset();
 
     if (status != OK || size < 0) {
@@ -989,7 +997,7 @@
                                          status_t(Parcel::*read_func)(T*) const) const {
     const size_t start = dataPosition();
     int32_t size;
-    status_t status = readInt32(&size);
+    status_t status = readVectorSizeWithCoarseBoundCheck(&size);
     val->reset();
 
     if (status != OK || size < 0) {
@@ -1093,7 +1101,7 @@
 status_t Parcel::readParcelableVector(std::optional<std::vector<std::optional<T>>>* val) const {
     const size_t start = dataPosition();
     int32_t size;
-    status_t status = readInt32(&size);
+    status_t status = readVectorSizeWithCoarseBoundCheck(&size);
     val->reset();
 
     if (status != OK || size < 0) {
@@ -1117,7 +1125,7 @@
 status_t Parcel::readParcelableVector(std::unique_ptr<std::vector<std::unique_ptr<T>>>* val) const {
     const size_t start = dataPosition();
     int32_t size;
-    status_t status = readInt32(&size);
+    status_t status = readVectorSizeWithCoarseBoundCheck(&size);
     val->reset();
 
     if (status != OK || size < 0) {
diff --git a/libs/binder/include/binder/ParcelableHolder.h b/libs/binder/include/binder/ParcelableHolder.h
index ff0a686..9e4475c 100644
--- a/libs/binder/include/binder/ParcelableHolder.h
+++ b/libs/binder/include/binder/ParcelableHolder.h
@@ -18,6 +18,7 @@
 
 #include <binder/Parcel.h>
 #include <binder/Parcelable.h>
+#include <utils/String16.h>
 #include <mutex>
 #include <optional>
 #include <tuple>
@@ -72,7 +73,7 @@
     template <typename T>
     status_t getParcelable(std::shared_ptr<T>* ret) const {
         static_assert(std::is_base_of<Parcelable, T>::value, "T must be derived from Parcelable");
-        const std::string& parcelableDesc = T::getParcelableDescriptor();
+        const String16& parcelableDesc = T::getParcelableDescriptor();
         if (!this->mParcelPtr) {
             if (!this->mParcelable || !this->mParcelableName) {
                 ALOGD("empty ParcelableHolder");
@@ -80,7 +81,7 @@
                 return android::OK;
             } else if (parcelableDesc != *mParcelableName) {
                 ALOGD("extension class name mismatch expected:%s actual:%s",
-                      mParcelableName->c_str(), parcelableDesc.c_str());
+                      String8(*mParcelableName).c_str(), String8(parcelableDesc).c_str());
                 *ret = nullptr;
                 return android::BAD_VALUE;
             }
@@ -88,7 +89,7 @@
             return android::OK;
         }
         this->mParcelPtr->setDataPosition(0);
-        status_t status = this->mParcelPtr->readUtf8FromUtf16(&this->mParcelableName);
+        status_t status = this->mParcelPtr->readString16(&this->mParcelableName);
         if (status != android::OK || parcelableDesc != this->mParcelableName) {
             this->mParcelableName = std::nullopt;
             *ret = nullptr;
@@ -130,7 +131,7 @@
 
 private:
     mutable std::shared_ptr<Parcelable> mParcelable;
-    mutable std::optional<std::string> mParcelableName;
+    mutable std::optional<String16> mParcelableName;
     mutable std::unique_ptr<Parcel> mParcelPtr;
     Stability mStability;
 };
diff --git a/libs/cputimeinstate/cputimeinstate.cpp b/libs/cputimeinstate/cputimeinstate.cpp
index 4209dc5..2e72cc4 100644
--- a/libs/cputimeinstate/cputimeinstate.cpp
+++ b/libs/cputimeinstate/cputimeinstate.cpp
@@ -56,6 +56,7 @@
 static std::vector<std::vector<uint32_t>> gPolicyFreqs;
 static std::vector<std::vector<uint32_t>> gPolicyCpus;
 static std::set<uint32_t> gAllFreqs;
+static unique_fd gTisTotalMapFd;
 static unique_fd gTisMapFd;
 static unique_fd gConcurrentMapFd;
 static unique_fd gUidLastUpdateMapFd;
@@ -129,6 +130,10 @@
         gPolicyCpus.emplace_back(*cpus);
     }
 
+    gTisTotalMapFd =
+            unique_fd{bpf_obj_get(BPF_FS_PATH "map_time_in_state_total_time_in_state_map")};
+    if (gTisTotalMapFd < 0) return false;
+
     gTisMapFd = unique_fd{bpf_obj_get(BPF_FS_PATH "map_time_in_state_uid_time_in_state_map")};
     if (gTisMapFd < 0) return false;
 
@@ -239,6 +244,31 @@
     return gPolicyFreqs;
 }
 
+std::optional<std::vector<std::vector<uint64_t>>> getTotalCpuFreqTimes() {
+    if (!gInitialized && !initGlobals()) return {};
+
+    std::vector<std::vector<uint64_t>> out;
+    uint32_t maxFreqCount = 0;
+    for (const auto &freqList : gPolicyFreqs) {
+        if (freqList.size() > maxFreqCount) maxFreqCount = freqList.size();
+        out.emplace_back(freqList.size(), 0);
+    }
+
+    std::vector<uint64_t> vals(gNCpus);
+    const uint32_t freqCount = maxFreqCount <= MAX_FREQS_FOR_TOTAL ? maxFreqCount :
+            MAX_FREQS_FOR_TOTAL;
+    for (uint32_t freqIdx = 0; freqIdx < freqCount; ++freqIdx) {
+        if (findMapEntry(gTisTotalMapFd, &freqIdx, vals.data())) return {};
+        for (uint32_t policyIdx = 0; policyIdx < gNPolicies; ++policyIdx) {
+            if (freqIdx >= gPolicyFreqs[policyIdx].size()) continue;
+            for (const auto &cpu : gPolicyCpus[policyIdx]) {
+                out[policyIdx][freqIdx] += vals[cpu];
+            }
+        }
+    }
+
+    return out;
+}
 // Retrieve the times in ns that uid spent running at each CPU frequency.
 // Return contains no value on error, otherwise it contains a vector of vectors using the format:
 // [[t0_0, t0_1, ...],
diff --git a/libs/cputimeinstate/cputimeinstate.h b/libs/cputimeinstate/cputimeinstate.h
index 87a328a..46de669 100644
--- a/libs/cputimeinstate/cputimeinstate.h
+++ b/libs/cputimeinstate/cputimeinstate.h
@@ -23,6 +23,7 @@
 namespace bpf {
 
 bool startTrackingUidTimes();
+std::optional<std::vector<std::vector<uint64_t>>> getTotalCpuFreqTimes();
 std::optional<std::vector<std::vector<uint64_t>>> getUidCpuFreqTimes(uint32_t uid);
 std::optional<std::unordered_map<uint32_t, std::vector<std::vector<uint64_t>>>>
     getUidsCpuFreqTimes();
diff --git a/libs/cputimeinstate/testtimeinstate.cpp b/libs/cputimeinstate/testtimeinstate.cpp
index 519689b..d25b2e9 100644
--- a/libs/cputimeinstate/testtimeinstate.cpp
+++ b/libs/cputimeinstate/testtimeinstate.cpp
@@ -40,6 +40,12 @@
 
 using std::vector;
 
+TEST(TimeInStateTest, TotalTimeInState) {
+    auto times = getTotalCpuFreqTimes();
+    ASSERT_TRUE(times.has_value());
+    EXPECT_FALSE(times->empty());
+}
+
 TEST(TimeInStateTest, SingleUidTimeInState) {
     auto times = getUidCpuFreqTimes(0);
     ASSERT_TRUE(times.has_value());
@@ -186,6 +192,31 @@
     }
 }
 
+TEST(TimeInStateTest, TotalAndAllUidTimeInStateConsistent) {
+    auto allUid = getUidsCpuFreqTimes();
+    auto total = getTotalCpuFreqTimes();
+
+    ASSERT_TRUE(allUid.has_value() && total.has_value());
+
+    // Check the number of policies.
+    ASSERT_EQ(allUid->at(0).size(), total->size());
+
+    for (uint32_t policyIdx = 0; policyIdx < total->size(); ++policyIdx) {
+        std::vector<uint64_t> totalTimes = total->at(policyIdx);
+        uint32_t totalFreqsCount = totalTimes.size();
+        std::vector<uint64_t> allUidTimes(totalFreqsCount, 0);
+        for (auto const &[uid, uidTimes]: *allUid) {
+            for (uint32_t freqIdx = 0; freqIdx < uidTimes[policyIdx].size(); ++freqIdx) {
+                allUidTimes[std::min(freqIdx, totalFreqsCount - 1)] += uidTimes[policyIdx][freqIdx];
+            }
+        }
+
+        for (uint32_t freqIdx = 0; freqIdx < totalFreqsCount; ++freqIdx) {
+            ASSERT_LE(allUidTimes[freqIdx], totalTimes[freqIdx]);
+        }
+    }
+}
+
 TEST(TimeInStateTest, SingleAndAllUidTimeInStateConsistent) {
     uint64_t zero = 0;
     auto maps = {getUidsCpuFreqTimes(), getUidsUpdatedCpuFreqTimes(&zero)};
@@ -292,6 +323,22 @@
     ASSERT_LE(after - before, NSEC_PER_SEC * 2 * get_nprocs_conf());
 }
 
+TEST(TimeInStateTest, TotalTimeInStateMonotonic) {
+    auto before = getTotalCpuFreqTimes();
+    ASSERT_TRUE(before.has_value());
+    sleep(1);
+    auto after = getTotalCpuFreqTimes();
+    ASSERT_TRUE(after.has_value());
+
+    for (uint32_t policyIdx = 0; policyIdx < after->size(); ++policyIdx) {
+        auto timesBefore = before->at(policyIdx);
+        auto timesAfter = after->at(policyIdx);
+        for (uint32_t freqIdx = 0; freqIdx < timesAfter.size(); ++freqIdx) {
+            ASSERT_NO_FATAL_FAILURE(TestCheckDelta(timesBefore[freqIdx], timesAfter[freqIdx]));
+        }
+    }
+}
+
 TEST(TimeInStateTest, AllUidTimeInStateMonotonic) {
     auto map1 = getUidsCpuFreqTimes();
     ASSERT_TRUE(map1.has_value());
diff --git a/services/gpuservice/tests/unittests/GpuMemTest.cpp b/services/gpuservice/tests/unittests/GpuMemTest.cpp
index c5f8859..e916221 100644
--- a/services/gpuservice/tests/unittests/GpuMemTest.cpp
+++ b/services/gpuservice/tests/unittests/GpuMemTest.cpp
@@ -59,7 +59,6 @@
     }
 
     void SetUp() override {
-        SKIP_IF_BPF_NOT_SUPPORTED;
         bpf::setrlimitForTest();
 
         mGpuMem = std::make_unique<GpuMem>();
@@ -87,8 +86,6 @@
 };
 
 TEST_F(GpuMemTest, validGpuMemTotalBpfPaths) {
-    SKIP_IF_BPF_NOT_SUPPORTED;
-
     EXPECT_EQ(mTestableGpuMem.getGpuMemTraceGroup(), "gpu_mem");
     EXPECT_EQ(mTestableGpuMem.getGpuMemTotalTracepoint(), "gpu_mem_total");
     EXPECT_EQ(mTestableGpuMem.getGpuMemTotalProgPath(),
@@ -97,20 +94,16 @@
 }
 
 TEST_F(GpuMemTest, bpfInitializationFailed) {
-    SKIP_IF_BPF_NOT_SUPPORTED;
-
     EXPECT_EQ(dumpsys(), "Failed to initialize GPU memory eBPF\n");
 }
 
 TEST_F(GpuMemTest, gpuMemTotalMapEmpty) {
-    SKIP_IF_BPF_NOT_SUPPORTED;
     mTestableGpuMem.setGpuMemTotalMap(mTestMap);
 
     EXPECT_EQ(dumpsys(), "GPU memory total usage map is empty\n");
 }
 
 TEST_F(GpuMemTest, globalMemTotal) {
-    SKIP_IF_BPF_NOT_SUPPORTED;
     ASSERT_RESULT_OK(mTestMap.writeValue(TEST_GLOBAL_KEY, TEST_GLOBAL_VAL, BPF_ANY));
     mTestableGpuMem.setGpuMemTotalMap(mTestMap);
 
@@ -118,7 +111,6 @@
 }
 
 TEST_F(GpuMemTest, missingGlobalMemTotal) {
-    SKIP_IF_BPF_NOT_SUPPORTED;
     ASSERT_RESULT_OK(mTestMap.writeValue(TEST_PROC_KEY_1, TEST_PROC_VAL_1, BPF_ANY));
     mTestableGpuMem.setGpuMemTotalMap(mTestMap);
 
@@ -126,7 +118,6 @@
 }
 
 TEST_F(GpuMemTest, procMemTotal) {
-    SKIP_IF_BPF_NOT_SUPPORTED;
     ASSERT_RESULT_OK(mTestMap.writeValue(TEST_PROC_KEY_1, TEST_PROC_VAL_1, BPF_ANY));
     ASSERT_RESULT_OK(mTestMap.writeValue(TEST_PROC_KEY_2, TEST_PROC_VAL_2, BPF_ANY));
     mTestableGpuMem.setGpuMemTotalMap(mTestMap);
@@ -146,7 +137,6 @@
 }
 
 TEST_F(GpuMemTest, traverseGpuMemTotals) {
-    SKIP_IF_BPF_NOT_SUPPORTED;
     ASSERT_RESULT_OK(mTestMap.writeValue(TEST_GLOBAL_KEY, TEST_GLOBAL_VAL, BPF_ANY));
     ASSERT_RESULT_OK(mTestMap.writeValue(TEST_PROC_KEY_1, TEST_PROC_VAL_1, BPF_ANY));
     ASSERT_RESULT_OK(mTestMap.writeValue(TEST_PROC_KEY_2, TEST_PROC_VAL_2, BPF_ANY));
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 39f923f..02b5324 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -4501,12 +4501,9 @@
 
 void SurfaceFlinger::dumpFrameEventsLocked(std::string& result) {
     result.append("Layer frame timestamps:\n");
-
-    const LayerVector& currentLayers = mCurrentState.layersSortedByZ;
-    const size_t count = currentLayers.size();
-    for (size_t i=0 ; i<count ; i++) {
-        currentLayers[i]->dumpFrameEvents(result);
-    }
+    // Traverse all layers to dump frame-events for each layer
+    mCurrentState.traverseInZOrder(
+        [&] (Layer* layer) { layer->dumpFrameEvents(result); });
 }
 
 void SurfaceFlinger::dumpBufferingStats(std::string& result) const {