Merge "EGL: default to HAL_DATASPACE_UNKNOWN." into pi-dev
diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp
index 711143c..be3bbf7 100644
--- a/libs/binder/IServiceManager.cpp
+++ b/libs/binder/IServiceManager.cpp
@@ -24,6 +24,7 @@
 #include <binder/IPermissionController.h>
 #endif
 #include <binder/Parcel.h>
+#include <cutils/properties.h>
 #include <utils/String8.h>
 #include <utils/SystemClock.h>
 #include <utils/CallStack.h>
@@ -142,20 +143,35 @@
 
     virtual sp<IBinder> getService(const String16& name) const
     {
-        unsigned n;
-        for (n = 0; n < 5; n++){
-            if (n > 0) {
-                if (!strcmp(ProcessState::self()->getDriverName().c_str(), "/dev/vndbinder")) {
-                    ALOGI("Waiting for vendor service %s...", String8(name).string());
-                    CallStack stack(LOG_TAG);
-                } else {
-                    ALOGI("Waiting for service %s...", String8(name).string());
-                }
-                sleep(1);
+        sp<IBinder> svc = checkService(name);
+        if (svc != NULL) return svc;
+
+        const bool isVendorService =
+            strcmp(ProcessState::self()->getDriverName().c_str(), "/dev/vndbinder") == 0;
+        const long timeout = uptimeMillis() + 5000;
+        if (!gSystemBootCompleted) {
+            char bootCompleted[PROPERTY_VALUE_MAX];
+            property_get("sys.boot_completed", bootCompleted, "0");
+            gSystemBootCompleted = strcmp(bootCompleted, "1") == 0 ? true : false;
+        }
+        // retry interval in millisecond.
+        const long sleepTime = gSystemBootCompleted ? 1000 : 100;
+
+        int n = 0;
+        while (uptimeMillis() < timeout) {
+            n++;
+            if (isVendorService) {
+                ALOGI("Waiting for vendor service %s...", String8(name).string());
+                CallStack stack(LOG_TAG);
+            } else if (n%10 == 0) {
+                ALOGI("Waiting for service %s...", String8(name).string());
             }
+            usleep(1000*sleepTime);
+
             sp<IBinder> svc = checkService(name);
             if (svc != NULL) return svc;
         }
+        ALOGW("Service %s didn't start. Returning NULL", String8(name).string());
         return NULL;
     }
 
diff --git a/libs/binder/Static.cpp b/libs/binder/Static.cpp
index 9899b65..c5c3fd5 100644
--- a/libs/binder/Static.cpp
+++ b/libs/binder/Static.cpp
@@ -97,5 +97,6 @@
 #ifndef __ANDROID_VNDK__
 sp<IPermissionController> gPermissionController;
 #endif
+bool gSystemBootCompleted = false;
 
 }   // namespace android
diff --git a/libs/binder/include/private/binder/Static.h b/libs/binder/include/private/binder/Static.h
index f04bcae..6ca7592 100644
--- a/libs/binder/include/private/binder/Static.h
+++ b/libs/binder/include/private/binder/Static.h
@@ -41,5 +41,6 @@
 #ifndef __ANDROID_VNDK__
 extern sp<IPermissionController> gPermissionController;
 #endif
+extern bool gSystemBootCompleted;
 
 }   // namespace android
diff --git a/services/surfaceflinger/RenderEngine/ProgramCache.cpp b/services/surfaceflinger/RenderEngine/ProgramCache.cpp
index 5f09ac0..abb0290 100644
--- a/services/surfaceflinger/RenderEngine/ProgramCache.cpp
+++ b/services/surfaceflinger/RenderEngine/ProgramCache.cpp
@@ -232,104 +232,170 @@
     }
 }
 
-// Generate OOTF that modifies the relative scence light to relative display light.
-void ProgramCache::generateOOTF(Formatter& fs, const Key& needs) {
-    fs << R"__SHADER__(
-        highp float CalculateY(const highp vec3 color) {
-            // BT2020 standard uses the unadjusted KR = 0.2627,
-            // KB = 0.0593 luminance interpretation for RGB conversion.
-            return color.r * 0.262700 + color.g * 0.677998 + color.b * 0.059302;
-        }
-    )__SHADER__";
-
-    // Generate OOTF that modifies the relative display light.
-    switch(needs.getInputTF()) {
+void ProgramCache::generateToneMappingProcess(Formatter& fs, const Key& needs) {
+    // Convert relative light to absolute light.
+    switch (needs.getInputTF()) {
         case Key::INPUT_TF_ST2084:
             fs << R"__SHADER__(
-                highp vec3 OOTF(const highp vec3 color) {
-                    const float maxLumi = 10000.0;
-                    const float maxMasteringLumi = 1000.0;
-                    const float maxContentLumi = 1000.0;
-                    const float maxInLumi = min(maxMasteringLumi, maxContentLumi);
-                    float maxOutLumi = displayMaxLuminance;
-
-                    // Calculate Y value in XYZ color space.
-                    float colorY = CalculateY(color);
-
-                    // convert to nits first
-                    float nits = colorY * maxLumi;
-
-                    // clamp to max input luminance
-                    nits = clamp(nits, 0.0, maxInLumi);
-
-                    // scale [0.0, maxInLumi] to [0.0, maxOutLumi]
-                    if (maxInLumi <= maxOutLumi) {
-                        nits *= maxOutLumi / maxInLumi;
-                    } else {
-                        // three control points
-                        const float x0 = 10.0;
-                        const float y0 = 17.0;
-                        float x1 = maxOutLumi * 0.75;
-                        float y1 = x1;
-                        float x2 = x1 + (maxInLumi - x1) / 2.0;
-                        float y2 = y1 + (maxOutLumi - y1) * 0.75;
-
-                        // horizontal distances between the last three control points
-                        float h12 = x2 - x1;
-                        float h23 = maxInLumi - x2;
-                        // tangents at the last three control points
-                        float m1 = (y2 - y1) / h12;
-                        float m3 = (maxOutLumi - y2) / h23;
-                        float m2 = (m1 + m3) / 2.0;
-
-                        if (nits < x0) {
-                            // scale [0.0, x0] to [0.0, y0] linearly
-                            const float slope = y0 / x0;
-                            nits *= slope;
-                        } else if (nits < x1) {
-                            // scale [x0, x1] to [y0, y1] linearly
-                            float slope = (y1 - y0) / (x1 - x0);
-                            nits = y0 + (nits - x0) * slope;
-                        } else if (nits < x2) {
-                            // scale [x1, x2] to [y1, y2] using Hermite interp
-                            float t = (nits - x1) / h12;
-                            nits = (y1 * (1.0 + 2.0 * t) + h12 * m1 * t) * (1.0 - t) * (1.0 - t) +
-                                    (y2 * (3.0 - 2.0 * t) + h12 * m2 * (t - 1.0)) * t * t;
-                        } else {
-                            // scale [x2, maxInLumi] to [y2, maxOutLumi] using Hermite interp
-                            float t = (nits - x2) / h23;
-                            nits = (y2 * (1.0 + 2.0 * t) + h23 * m2 * t) * (1.0 - t) * (1.0 - t) +
-                                    (maxOutLumi * (3.0 - 2.0 * t) + h23 * m3 * (t - 1.0)) * t * t;
-                        }
-                    }
-
-                    // convert back to [0.0, 1.0]
-                    float targetY = nits / maxOutLumi;
-                    return color * (targetY / max(1e-6, colorY));
+                highp vec3 ScaleLuminance(highp vec3 color) {
+                    return color * 10000.0;
                 }
             )__SHADER__";
             break;
         case Key::INPUT_TF_HLG:
             fs << R"__SHADER__(
-                highp vec3 OOTF(const highp vec3 color) {
-                    const float maxOutLumi = 500.0;
-                    const float gamma = 1.2 + 0.42 * log(maxOutLumi / 1000.0) / log(10.0);
+                highp vec3 ScaleLuminance(highp vec3 color) {
                     // The formula is:
                     // alpha * pow(Y, gamma - 1.0) * color + beta;
-                    // where alpha is 1.0, beta is 0.0 as recommended in
-                    // Rec. ITU-R BT.2100-1 TABLE 5.
-                    return pow(CalculateY(color), gamma - 1.0) * color;
+                    // where alpha is 1000.0, gamma is 1.2, beta is 0.0.
+                    return color * 1000.0 * pow(color.y, 0.2);
                 }
             )__SHADER__";
             break;
         default:
             fs << R"__SHADER__(
-                highp vec3 OOTF(const highp vec3 color) {
+                highp vec3 ScaleLuminance(highp vec3 color) {
+                    return color * displayMaxLuminance;
+                }
+            )__SHADER__";
+            break;
+    }
+
+    // Tone map absolute light to display luminance range.
+    switch (needs.getInputTF()) {
+        case Key::INPUT_TF_ST2084:
+        case Key::INPUT_TF_HLG:
+            switch (needs.getOutputTF()) {
+                case Key::OUTPUT_TF_HLG:
+                    // Right now when mixed PQ and HLG contents are presented,
+                    // HLG content will always be converted to PQ. However, for
+                    // completeness, we simply clamp the value to [0.0, 1000.0].
+                    fs << R"__SHADER__(
+                        highp vec3 ToneMap(highp vec3 color) {
+                            return clamp(color, 0.0, 1000.0);
+                        }
+                    )__SHADER__";
+                    break;
+                case Key::OUTPUT_TF_ST2084:
+                    fs << R"__SHADER__(
+                        highp vec3 ToneMap(highp vec3 color) {
+                            return color;
+                        }
+                    )__SHADER__";
+                    break;
+                default:
+                    fs << R"__SHADER__(
+                        highp vec3 ToneMap(highp vec3 color) {
+                            const float maxMasteringLumi = 1000.0;
+                            const float maxContentLumi = 1000.0;
+                            const float maxInLumi = min(maxMasteringLumi, maxContentLumi);
+                            float maxOutLumi = displayMaxLuminance;
+
+                            float nits = color.y;
+
+                            // clamp to max input luminance
+                            nits = clamp(nits, 0.0, maxInLumi);
+
+                            // scale [0.0, maxInLumi] to [0.0, maxOutLumi]
+                            if (maxInLumi <= maxOutLumi) {
+                                nits *= maxOutLumi / maxInLumi;
+                            } else {
+                                // three control points
+                                const float x0 = 10.0;
+                                const float y0 = 17.0;
+                                float x1 = maxOutLumi * 0.75;
+                                float y1 = x1;
+                                float x2 = x1 + (maxInLumi - x1) / 2.0;
+                                float y2 = y1 + (maxOutLumi - y1) * 0.75;
+
+                                // horizontal distances between the last three control points
+                                const float h12 = x2 - x1;
+                                const float h23 = maxInLumi - x2;
+                                // tangents at the last three control points
+                                const float m1 = (y2 - y1) / h12;
+                                const float m3 = (maxOutLumi - y2) / h23;
+                                const float m2 = (m1 + m3) / 2.0;
+
+                                if (nits < x0) {
+                                    // scale [0.0, x0] to [0.0, y0] linearly
+                                    const float slope = y0 / x0;
+                                    nits *= slope;
+                                } else if (nits < x1) {
+                                    // scale [x0, x1] to [y0, y1] linearly
+                                    const float slope = (y1 - y0) / (x1 - x0);
+                                    nits = y0 + (nits - x0) * slope;
+                                } else if (nits < x2) {
+                                    // scale [x1, x2] to [y1, y2] using Hermite interp
+                                    float t = (nits - x1) / h12;
+                                    nits = (y1 * (1.0 + 2.0 * t) + h12 * m1 * t) * (1.0 - t) * (1.0 - t) +
+                                            (y2 * (3.0 - 2.0 * t) + h12 * m2 * (t - 1.0)) * t * t;
+                                } else {
+                                    // scale [x2, maxInLumi] to [y2, maxOutLumi] using Hermite interp
+                                    float t = (nits - x2) / h23;
+                                    nits = (y2 * (1.0 + 2.0 * t) + h23 * m2 * t) * (1.0 - t) * (1.0 - t) +
+                                            (maxOutLumi * (3.0 - 2.0 * t) + h23 * m3 * (t - 1.0)) * t * t;
+                                }
+                            }
+
+                            return color * (nits / max(1e-6, color.y));
+                        }
+                    )__SHADER__";
+                    break;
+            }
+            break;
+        default:
+            // TODO(73825729) We need to revert the tone mapping in
+            // hardware composer properly.
+            fs << R"__SHADER__(
+                highp vec3 ToneMap(highp vec3 color) {
                     return color;
                 }
             )__SHADER__";
             break;
     }
+
+    // convert absolute light to relative light.
+    switch (needs.getOutputTF()) {
+        case Key::OUTPUT_TF_ST2084:
+            fs << R"__SHADER__(
+                highp vec3 NormalizeLuminance(highp vec3 color) {
+                    return color / 10000.0;
+                }
+            )__SHADER__";
+            break;
+        case Key::OUTPUT_TF_HLG:
+            fs << R"__SHADER__(
+                highp vec3 NormalizeLuminance(highp vec3 color) {
+                    return color / 1000.0 * pow(color.y / 1000.0, -0.2 / 1.2);
+                }
+            )__SHADER__";
+            break;
+        default:
+            fs << R"__SHADER__(
+                highp vec3 NormalizeLuminance(highp vec3 color) {
+                    return color / displayMaxLuminance;
+                }
+            )__SHADER__";
+            break;
+    }
+}
+
+// Generate OOTF that modifies the relative scence light to relative display light.
+void ProgramCache::generateOOTF(Formatter& fs, const ProgramCache::Key& needs) {
+    if (!needs.needsToneMapping()) {
+        fs << R"__SHADER__(
+            highp vec3 OOTF(const highp vec3 color) {
+                return color;
+            }
+        )__SHADER__";
+    } else {
+        generateToneMappingProcess(fs, needs);
+        fs << R"__SHADER__(
+            highp vec3 OOTF(const highp vec3 color) {
+                return NormalizeLuminance(ToneMap(ScaleLuminance(color)));
+            }
+        )__SHADER__";
+    }
 }
 
 // Generate OETF that converts relative display light to signal values,
@@ -446,8 +512,8 @@
     }
 
     if (needs.hasTransformMatrix() || (needs.getInputTF() != needs.getOutputTF())) {
-        // Currently, only the OOTF of BT2020 PQ needs display maximum luminance.
-        if (needs.getInputTF() == Key::INPUT_TF_ST2084) {
+        // Currently, display maximum luminance is needed when doing tone mapping.
+        if (needs.needsToneMapping()) {
             fs << "uniform float displayMaxLuminance;";
         }
 
diff --git a/services/surfaceflinger/RenderEngine/ProgramCache.h b/services/surfaceflinger/RenderEngine/ProgramCache.h
index e1398eb..864bc3f 100644
--- a/services/surfaceflinger/RenderEngine/ProgramCache.h
+++ b/services/surfaceflinger/RenderEngine/ProgramCache.h
@@ -126,6 +126,29 @@
         }
         inline int getInputTF() const { return (mKey & INPUT_TF_MASK); }
         inline int getOutputTF() const { return (mKey & OUTPUT_TF_MASK); }
+
+        // When HDR and non-HDR contents are mixed, or different types of HDR contents are
+        // mixed, we will do a tone mapping process to tone map the input content to output
+        // content. Currently, the following conversions handled, they are:
+        // * SDR -> HLG
+        // * SDR -> PQ
+        // * HLG -> PQ
+        inline bool needsToneMapping() const {
+            int inputTF = getInputTF();
+            int outputTF = getOutputTF();
+
+            // Return false when converting from SDR to SDR.
+            if (inputTF == Key::INPUT_TF_SRGB && outputTF == Key::OUTPUT_TF_LINEAR) {
+                return false;
+            }
+            if (inputTF == Key::INPUT_TF_LINEAR && outputTF == Key::OUTPUT_TF_SRGB) {
+                return false;
+            }
+
+            inputTF >>= Key::INPUT_TF_SHIFT;
+            outputTF >>= Key::OUTPUT_TF_SHIFT;
+            return inputTF != outputTF;
+        }
         inline bool isY410BT2020() const { return (mKey & Y410_BT2020_MASK) == Y410_BT2020_ON; }
 
         // this is the definition of a friend function -- not a method of class Needs
@@ -148,6 +171,8 @@
     static Key computeKey(const Description& description);
     // Generate EOTF based from Key.
     static void generateEOTF(Formatter& fs, const Key& needs);
+    // Generate necessary tone mapping methods for OOTF.
+    static void generateToneMappingProcess(Formatter& fs, const Key& needs);
     // Generate OOTF based from Key.
     static void generateOOTF(Formatter& fs, const Key& needs);
     // Generate OETF based from Key.
diff --git a/services/surfaceflinger/TimeStats/TimeStats.cpp b/services/surfaceflinger/TimeStats/TimeStats.cpp
index a6833a5..d4f1e29 100644
--- a/services/surfaceflinger/TimeStats/TimeStats.cpp
+++ b/services/surfaceflinger/TimeStats/TimeStats.cpp
@@ -59,14 +59,15 @@
     }
 
     if (argsMap.count("-dump")) {
-        int64_t maxLayers = 0;
+        std::optional<uint32_t> maxLayers = std::nullopt;
         auto iter = argsMap.find("-maxlayers");
         if (iter != argsMap.end() && iter->second + 1 < static_cast<int32_t>(args.size())) {
-            maxLayers = strtol(String8(args[iter->second + 1]).c_str(), nullptr, 10);
-            maxLayers = std::clamp(maxLayers, int64_t(0), int64_t(UINT32_MAX));
+            int64_t value = strtol(String8(args[iter->second + 1]).c_str(), nullptr, 10);
+            value = std::clamp(value, int64_t(0), int64_t(UINT32_MAX));
+            maxLayers = static_cast<uint32_t>(value);
         }
 
-        dump(asProto, static_cast<uint32_t>(maxLayers), result);
+        dump(asProto, maxLayers, result);
     }
 
     if (argsMap.count("-clear")) {
@@ -147,12 +148,27 @@
     return static_cast<int32_t>(delta);
 }
 
+static std::string getPackageName(const std::string& layerName) {
+    // This regular expression captures the following for instance:
+    // StatusBar in StatusBar#0
+    // com.appname in com.appname/com.appname.activity#0
+    // com.appname in SurfaceView - com.appname/com.appname.activity#0
+    const std::regex re("(?:SurfaceView[-\\s\\t]+)?([^/]+).*#\\d+");
+    std::smatch match;
+    if (std::regex_match(layerName.begin(), layerName.end(), match, re)) {
+        // There must be a match for group 1 otherwise the whole string is not
+        // matched and the above will return false
+        return match[1];
+    }
+    return "";
+}
+
 void TimeStats::flushAvailableRecordsToStatsLocked(const std::string& layerName) {
     ATRACE_CALL();
 
     LayerRecord& layerRecord = timeStatsTracker[layerName];
     TimeRecord& prevTimeRecord = layerRecord.prevTimeRecord;
-    std::vector<TimeRecord>& timeRecords = layerRecord.timeRecords;
+    std::deque<TimeRecord>& timeRecords = layerRecord.timeRecords;
     while (!timeRecords.empty()) {
         if (!recordReadyLocked(layerName, &timeRecords[0])) break;
         ALOGV("[%s]-[%" PRIu64 "]-presentFenceTime[%" PRId64 "]", layerName.c_str(),
@@ -161,6 +177,7 @@
         if (prevTimeRecord.ready) {
             if (!timeStats.stats.count(layerName)) {
                 timeStats.stats[layerName].layerName = layerName;
+                timeStats.stats[layerName].packageName = getPackageName(layerName);
                 timeStats.stats[layerName].statsStart = static_cast<int64_t>(std::time(0));
             }
             TimeStatsHelper::TimeStatsLayer& timeStatsLayer = timeStats.stats[layerName];
@@ -199,8 +216,7 @@
             timeStats.stats[layerName].statsEnd = static_cast<int64_t>(std::time(0));
         }
         prevTimeRecord = timeRecords[0];
-        // TODO(zzyiwei): change timeRecords to use std::deque
-        timeRecords.erase(timeRecords.begin());
+        timeRecords.pop_front();
         layerRecord.waitData--;
     }
 }
@@ -434,7 +450,6 @@
 
     std::lock_guard<std::mutex> lock(mMutex);
     ALOGD("Cleared");
-    timeStats.dumpStats.clear();
     timeStats.stats.clear();
     timeStats.statsStart = (mEnabled.load() ? static_cast<int64_t>(std::time(0)) : 0);
     timeStats.statsEnd = 0;
@@ -447,7 +462,7 @@
     return mEnabled.load();
 }
 
-void TimeStats::dump(bool asProto, uint32_t maxLayers, String8& result) {
+void TimeStats::dump(bool asProto, std::optional<uint32_t> maxLayers, String8& result) {
     ATRACE_CALL();
 
     std::lock_guard<std::mutex> lock(mMutex);
@@ -457,39 +472,15 @@
 
     timeStats.statsEnd = static_cast<int64_t>(std::time(0));
 
-    // TODO(zzyiwei): refactor dumpStats into TimeStatsHelper
-    timeStats.dumpStats.clear();
-    for (auto& ele : timeStats.stats) {
-        timeStats.dumpStats.push_back(&ele.second);
-    }
-
-    std::sort(timeStats.dumpStats.begin(), timeStats.dumpStats.end(),
-              [](TimeStatsHelper::TimeStatsLayer* const& l,
-                 TimeStatsHelper::TimeStatsLayer* const& r) {
-                  return l->totalFrames > r->totalFrames;
-              });
-
-    if (maxLayers != 0 && maxLayers < timeStats.dumpStats.size()) {
-        timeStats.dumpStats.resize(maxLayers);
-    }
-
     if (asProto) {
-        dumpAsProtoLocked(result);
+        ALOGD("Dumping TimeStats as proto");
+        SFTimeStatsGlobalProto timeStatsProto = timeStats.toProto(maxLayers);
+        result.append(timeStatsProto.SerializeAsString().c_str(), timeStatsProto.ByteSize());
     } else {
-        dumpAsTextLocked(result);
+        ALOGD("Dumping TimeStats as text");
+        result.append(timeStats.toString(maxLayers).c_str());
+        result.append("\n");
     }
 }
 
-void TimeStats::dumpAsTextLocked(String8& result) {
-    ALOGD("Dumping TimeStats as text");
-    result.append(timeStats.toString().c_str());
-    result.append("\n");
-}
-
-void TimeStats::dumpAsProtoLocked(String8& result) {
-    ALOGD("Dumping TimeStats as proto");
-    SFTimeStatsGlobalProto timeStatsProto = timeStats.toProto();
-    result.append(timeStatsProto.SerializeAsString().c_str(), timeStatsProto.ByteSize());
-}
-
 } // namespace android
diff --git a/services/surfaceflinger/TimeStats/TimeStats.h b/services/surfaceflinger/TimeStats/TimeStats.h
index f76a62e..8318210 100644
--- a/services/surfaceflinger/TimeStats/TimeStats.h
+++ b/services/surfaceflinger/TimeStats/TimeStats.h
@@ -25,9 +25,10 @@
 #include <utils/String8.h>
 #include <utils/Vector.h>
 
+#include <deque>
 #include <mutex>
+#include <optional>
 #include <unordered_map>
-#include <vector>
 
 using namespace android::surfaceflinger;
 
@@ -57,7 +58,7 @@
         // fences to signal, but rather waiting to receive those fences/timestamps.
         int32_t waitData = -1;
         TimeRecord prevTimeRecord;
-        std::vector<TimeRecord> timeRecords;
+        std::deque<TimeRecord> timeRecords;
     };
 
 public:
@@ -90,9 +91,7 @@
     void disable();
     void clear();
     bool isEnabled();
-    void dump(bool asProto, uint32_t maxLayer, String8& result);
-    void dumpAsTextLocked(String8& result);
-    void dumpAsProtoLocked(String8& result);
+    void dump(bool asProto, std::optional<uint32_t> maxLayers, String8& result);
 
     std::atomic<bool> mEnabled = false;
     std::mutex mMutex;
diff --git a/services/surfaceflinger/TimeStats/timestatsproto/Android.bp b/services/surfaceflinger/TimeStats/timestatsproto/Android.bp
index 66aa719..bef6b7c 100644
--- a/services/surfaceflinger/TimeStats/timestatsproto/Android.bp
+++ b/services/surfaceflinger/TimeStats/timestatsproto/Android.bp
@@ -1,6 +1,5 @@
 cc_library_shared {
     name: "libtimestats_proto",
-    vendor_available: true,
     export_include_dirs: ["include"],
 
     srcs: [
@@ -9,11 +8,8 @@
     ],
 
     shared_libs: [
-        "android.hardware.graphics.common@1.1",
-        "libui",
-        "libprotobuf-cpp-lite",
         "libbase",
-        "liblog",
+        "libprotobuf-cpp-lite",
     ],
 
     proto: {
@@ -21,35 +17,17 @@
     },
 
     cppflags: [
+        "-std=c++1z",
         "-Werror",
-        "-Wno-unused-parameter",
-        "-Wno-format",
         "-Wno-c++98-compat-pedantic",
-        "-Wno-float-conversion",
         "-Wno-disabled-macro-expansion",
+        "-Wno-float-conversion",
         "-Wno-float-equal",
-        "-Wno-sign-conversion",
-        "-Wno-padded",
+        "-Wno-format",
         "-Wno-old-style-cast",
+        "-Wno-padded",
+        "-Wno-sign-conversion",
         "-Wno-undef",
+        "-Wno-unused-parameter",
     ],
-
-}
-
-java_library_static {
-    name: "timestatsprotosnano",
-    host_supported: true,
-    proto: {
-        type: "nano",
-    },
-    srcs: ["*.proto"],
-    no_framework_libs: true,
-    target: {
-        android: {
-            jarjar_rules: "jarjar-rules.txt",
-        },
-        host: {
-            static_libs: ["libprotobuf-java-nano"],
-        },
-    },
 }
diff --git a/services/surfaceflinger/TimeStats/timestatsproto/TimeStatsHelper.cpp b/services/surfaceflinger/TimeStats/timestatsproto/TimeStatsHelper.cpp
index 3e5007c..21f3ef3 100644
--- a/services/surfaceflinger/TimeStats/timestatsproto/TimeStatsHelper.cpp
+++ b/services/surfaceflinger/TimeStats/timestatsproto/TimeStatsHelper.cpp
@@ -17,7 +17,6 @@
 #include <timestatsproto/TimeStatsHelper.h>
 
 #include <array>
-#include <regex>
 
 #define HISTOGRAM_SIZE 85
 
@@ -47,55 +46,39 @@
     hist[*iter]++;
 }
 
-float TimeStatsHelper::Histogram::averageTime() {
+float TimeStatsHelper::Histogram::averageTime() const {
     int64_t ret = 0;
     int64_t count = 0;
-    for (auto ele : hist) {
+    for (auto& ele : hist) {
         count += ele.second;
         ret += ele.first * ele.second;
     }
     return static_cast<float>(ret) / count;
 }
 
-std::string TimeStatsHelper::Histogram::toString() {
+std::string TimeStatsHelper::Histogram::toString() const {
     std::string result;
     for (int32_t i = 0; i < HISTOGRAM_SIZE; ++i) {
         int32_t bucket = histogramConfig[i];
-        int32_t count = (hist.count(bucket) == 0) ? 0 : hist[bucket];
+        int32_t count = (hist.count(bucket) == 0) ? 0 : hist.at(bucket);
         StringAppendF(&result, "%dms=%d ", bucket, count);
     }
     result.back() = '\n';
     return result;
 }
 
-static std::string getPackageName(const std::string& layerName) {
-    // This regular expression captures the following for instance:
-    // StatusBar in StatusBar#0
-    // com.appname in com.appname/com.appname.activity#0
-    // com.appname in SurfaceView - com.appname/com.appname.activity#0
-    const std::regex re("(?:SurfaceView[-\\s\\t]+)?([^/]+).*#\\d+");
-    std::smatch match;
-    if (std::regex_match(layerName.begin(), layerName.end(), match, re)) {
-        // There must be a match for group 1 otherwise the whole string is not
-        // matched and the above will return false
-        return match[1];
-    }
-    return "";
-}
-
-std::string TimeStatsHelper::TimeStatsLayer::toString() {
+std::string TimeStatsHelper::TimeStatsLayer::toString() const {
     std::string result = "";
     StringAppendF(&result, "layerName = %s\n", layerName.c_str());
-    packageName = getPackageName(layerName);
     StringAppendF(&result, "packageName = %s\n", packageName.c_str());
     StringAppendF(&result, "statsStart = %lld\n", static_cast<long long int>(statsStart));
     StringAppendF(&result, "statsEnd = %lld\n", static_cast<long long int>(statsEnd));
     StringAppendF(&result, "totalFrames= %d\n", totalFrames);
-    if (deltas.find("present2present") != deltas.end()) {
-        StringAppendF(&result, "averageFPS = %.3f\n",
-                      1000.0 / deltas["present2present"].averageTime());
+    auto iter = deltas.find("present2present");
+    if (iter != deltas.end()) {
+        StringAppendF(&result, "averageFPS = %.3f\n", 1000.0 / iter->second.averageTime());
     }
-    for (auto ele : deltas) {
+    for (auto& ele : deltas) {
         StringAppendF(&result, "%s histogram is as below:\n", ele.first.c_str());
         StringAppendF(&result, "%s", ele.second.toString().c_str());
     }
@@ -103,7 +86,7 @@
     return result;
 }
 
-std::string TimeStatsHelper::TimeStatsGlobal::toString() {
+std::string TimeStatsHelper::TimeStatsGlobal::toString(std::optional<uint32_t> maxLayers) const {
     std::string result = "SurfaceFlinger TimeStats:\n";
     StringAppendF(&result, "statsStart = %lld\n", static_cast<long long int>(statsStart));
     StringAppendF(&result, "statsEnd = %lld\n", static_cast<long long int>(statsEnd));
@@ -111,25 +94,25 @@
     StringAppendF(&result, "missedFrames= %d\n", missedFrames);
     StringAppendF(&result, "clientCompositionFrames= %d\n", clientCompositionFrames);
     StringAppendF(&result, "TimeStats for each layer is as below:\n");
-    for (auto ele : dumpStats) {
+    const auto dumpStats = generateDumpStats(maxLayers);
+    for (auto& ele : dumpStats) {
         StringAppendF(&result, "%s", ele->toString().c_str());
     }
 
     return result;
 }
 
-SFTimeStatsLayerProto TimeStatsHelper::TimeStatsLayer::toProto() {
+SFTimeStatsLayerProto TimeStatsHelper::TimeStatsLayer::toProto() const {
     SFTimeStatsLayerProto layerProto;
     layerProto.set_layer_name(layerName);
-    packageName = getPackageName(layerName);
     layerProto.set_package_name(packageName);
     layerProto.set_stats_start(statsStart);
     layerProto.set_stats_end(statsEnd);
     layerProto.set_total_frames(totalFrames);
-    for (auto ele : deltas) {
+    for (auto& ele : deltas) {
         SFTimeStatsDeltaProto* deltaProto = layerProto.add_deltas();
         deltaProto->set_delta_name(ele.first);
-        for (auto histEle : ele.second.hist) {
+        for (auto& histEle : ele.second.hist) {
             SFTimeStatsHistogramBucketProto* histProto = deltaProto->add_histograms();
             histProto->set_render_millis(histEle.first);
             histProto->set_frame_count(histEle.second);
@@ -138,19 +121,40 @@
     return layerProto;
 }
 
-SFTimeStatsGlobalProto TimeStatsHelper::TimeStatsGlobal::toProto() {
+SFTimeStatsGlobalProto TimeStatsHelper::TimeStatsGlobal::toProto(
+        std::optional<uint32_t> maxLayers) const {
     SFTimeStatsGlobalProto globalProto;
     globalProto.set_stats_start(statsStart);
     globalProto.set_stats_end(statsEnd);
     globalProto.set_total_frames(totalFrames);
     globalProto.set_missed_frames(missedFrames);
     globalProto.set_client_composition_frames(clientCompositionFrames);
-    for (auto ele : dumpStats) {
+    const auto dumpStats = generateDumpStats(maxLayers);
+    for (auto& ele : dumpStats) {
         SFTimeStatsLayerProto* layerProto = globalProto.add_stats();
         layerProto->CopyFrom(ele->toProto());
     }
     return globalProto;
 }
 
+std::vector<TimeStatsHelper::TimeStatsLayer const*>
+TimeStatsHelper::TimeStatsGlobal::generateDumpStats(std::optional<uint32_t> maxLayers) const {
+    std::vector<TimeStatsLayer const*> dumpStats;
+    for (auto& ele : stats) {
+        dumpStats.push_back(&ele.second);
+    }
+
+    std::sort(dumpStats.begin(), dumpStats.end(),
+              [](TimeStatsHelper::TimeStatsLayer const* l,
+                 TimeStatsHelper::TimeStatsLayer const* r) {
+                  return l->totalFrames > r->totalFrames;
+              });
+
+    if (maxLayers && (*maxLayers < dumpStats.size())) {
+        dumpStats.resize(*maxLayers);
+    }
+    return dumpStats;
+}
+
 } // namespace surfaceflinger
 } // namespace android
diff --git a/services/surfaceflinger/TimeStats/timestatsproto/include/timestatsproto/TimeStatsHelper.h b/services/surfaceflinger/TimeStats/timestatsproto/include/timestatsproto/TimeStatsHelper.h
index c876f21..1798555 100644
--- a/services/surfaceflinger/TimeStats/timestatsproto/include/timestatsproto/TimeStatsHelper.h
+++ b/services/surfaceflinger/TimeStats/timestatsproto/include/timestatsproto/TimeStatsHelper.h
@@ -17,9 +17,7 @@
 
 #include <timestatsproto/TimeStatsProtoHeader.h>
 
-#include <math/vec4.h>
-
-#include <memory>
+#include <optional>
 #include <string>
 #include <unordered_map>
 #include <vector>
@@ -36,8 +34,8 @@
         std::unordered_map<int32_t, int32_t> hist;
 
         void insert(int32_t delta);
-        float averageTime();
-        std::string toString();
+        float averageTime() const;
+        std::string toString() const;
     };
 
     class TimeStatsLayer {
@@ -49,8 +47,8 @@
         int32_t totalFrames = 0;
         std::unordered_map<std::string, Histogram> deltas;
 
-        std::string toString();
-        SFTimeStatsLayerProto toProto();
+        std::string toString() const;
+        SFTimeStatsLayerProto toProto() const;
     };
 
     class TimeStatsGlobal {
@@ -61,10 +59,13 @@
         int32_t missedFrames = 0;
         int32_t clientCompositionFrames = 0;
         std::unordered_map<std::string, TimeStatsLayer> stats;
-        std::vector<TimeStatsLayer*> dumpStats;
 
-        std::string toString();
-        SFTimeStatsGlobalProto toProto();
+        std::string toString(std::optional<uint32_t> maxLayers) const;
+        SFTimeStatsGlobalProto toProto(std::optional<uint32_t> maxLayers) const;
+
+    private:
+        std::vector<TimeStatsLayer const*> generateDumpStats(
+                std::optional<uint32_t> maxLayers) const;
     };
 };
 
diff --git a/services/surfaceflinger/TimeStats/timestatsproto/jarjar-rules.txt b/services/surfaceflinger/TimeStats/timestatsproto/jarjar-rules.txt
deleted file mode 100644
index 40043a8..0000000
--- a/services/surfaceflinger/TimeStats/timestatsproto/jarjar-rules.txt
+++ /dev/null
@@ -1 +0,0 @@
-rule com.google.protobuf.nano.** com.android.framework.protobuf.nano.@1
diff --git a/services/surfaceflinger/TimeStats/timestatsproto/timestats.proto b/services/surfaceflinger/TimeStats/timestatsproto/timestats.proto
index a8f6fa8..f29fbd1 100644
--- a/services/surfaceflinger/TimeStats/timestatsproto/timestats.proto
+++ b/services/surfaceflinger/TimeStats/timestatsproto/timestats.proto
@@ -20,10 +20,6 @@
 
 option optimize_for = LITE_RUNTIME;
 
-// frameworks/base/core/proto/android/service/sftimestats.proto is based on
-// this proto. Please only make valid protobuf changes to these messages, and
-// keep the other file in sync with this one.
-
 message SFTimeStatsGlobalProto {
   // The start & end timestamps in UTC as
   // milliseconds since January 1, 1970
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index 6fb3351..c42e811 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -185,6 +185,7 @@
 struct Surface {
     android::sp<ANativeWindow> window;
     VkSwapchainKHR swapchain_handle;
+    uint64_t consumer_usage;
 };
 
 VkSurfaceKHR HandleFromSurface(Surface* surface) {
@@ -496,9 +497,18 @@
 
     surface->window = pCreateInfo->window;
     surface->swapchain_handle = VK_NULL_HANDLE;
+    int err = native_window_get_consumer_usage(surface->window.get(),
+                                               &surface->consumer_usage);
+    if (err != android::NO_ERROR) {
+        ALOGE("native_window_get_consumer_usage() failed: %s (%d)",
+              strerror(-err), err);
+        surface->~Surface();
+        allocator->pfnFree(allocator->pUserData, surface);
+        return VK_ERROR_INITIALIZATION_FAILED;
+    }
 
     // TODO(jessehall): Create and use NATIVE_WINDOW_API_VULKAN.
-    int err =
+    err =
         native_window_api_connect(surface->window.get(), NATIVE_WINDOW_API_EGL);
     if (err != 0) {
         // TODO(jessehall): Improve error reporting. Can we enumerate possible
@@ -536,9 +546,45 @@
 VKAPI_ATTR
 VkResult GetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice /*pdev*/,
                                             uint32_t /*queue_family*/,
-                                            VkSurfaceKHR /*surface*/,
+                                            VkSurfaceKHR surface_handle,
                                             VkBool32* supported) {
-    *supported = VK_TRUE;
+    const Surface* surface = SurfaceFromHandle(surface_handle);
+    if (!surface) {
+        return VK_ERROR_SURFACE_LOST_KHR;
+    }
+    const ANativeWindow* window = surface->window.get();
+
+    int query_value;
+    int err = window->query(window, NATIVE_WINDOW_FORMAT, &query_value);
+    if (err != 0 || query_value < 0) {
+        ALOGE("NATIVE_WINDOW_FORMAT query failed: %s (%d) value=%d",
+              strerror(-err), err, query_value);
+        return VK_ERROR_SURFACE_LOST_KHR;
+    }
+
+    android_pixel_format native_format =
+        static_cast<android_pixel_format>(query_value);
+
+    bool format_supported = false;
+    switch (native_format) {
+        case HAL_PIXEL_FORMAT_RGBA_8888:
+        case HAL_PIXEL_FORMAT_RGB_565:
+            format_supported = true;
+            break;
+        default:
+            break;
+    }
+
+    // USAGE_CPU_READ_MASK 0xFUL
+    // USAGE_CPU_WRITE_MASK (0xFUL << 4)
+    // The currently used bits are as below:
+    // USAGE_CPU_READ_RARELY = 2UL
+    // USAGE_CPU_READ_OFTEN = 3UL
+    // USAGE_CPU_WRITE_RARELY = (2UL << 4)
+    // USAGE_CPU_WRITE_OFTEN = (3UL << 4)
+    *supported = static_cast<VkBool32>(format_supported ||
+                                       (surface->consumer_usage & 0xFFUL) == 0);
+
     return VK_SUCCESS;
 }