Merge "Use a VBO when drawing blurs" into rvc-dev
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index 70bbc33..1af6edd 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -1273,11 +1273,6 @@
 Dex2oatFileWrapper maybe_open_app_image(const char* out_oat_path,
         bool generate_app_image, bool is_public, int uid, bool is_secondary_dex) {
 
-    // We don't create an image for secondary dex files.
-    if (is_secondary_dex) {
-        return Dex2oatFileWrapper();
-    }
-
     const std::string image_path = create_image_filename(out_oat_path);
     if (image_path.empty()) {
         // Happens when the out_oat_path has an unknown extension.
diff --git a/libs/renderengine/gl/GLFramebuffer.cpp b/libs/renderengine/gl/GLFramebuffer.cpp
index 153935b..cb0d5cf 100644
--- a/libs/renderengine/gl/GLFramebuffer.cpp
+++ b/libs/renderengine/gl/GLFramebuffer.cpp
@@ -32,23 +32,14 @@
 namespace gl {
 
 GLFramebuffer::GLFramebuffer(GLESRenderEngine& engine)
-      : GLFramebuffer(engine, false /* multiTarget */) {}
-
-GLFramebuffer::GLFramebuffer(GLESRenderEngine& engine, bool multiTarget)
       : mEngine(engine), mEGLDisplay(engine.getEGLDisplay()), mEGLImage(EGL_NO_IMAGE_KHR) {
     glGenTextures(1, &mTextureName);
-    if (multiTarget) {
-        glGenTextures(1, &mSecondaryTextureName);
-    }
     glGenFramebuffers(1, &mFramebufferName);
 }
 
 GLFramebuffer::~GLFramebuffer() {
     glDeleteFramebuffers(1, &mFramebufferName);
     glDeleteTextures(1, &mTextureName);
-    if (mSecondaryTextureName != -1) {
-        glDeleteTextures(1, &mSecondaryTextureName);
-    }
 }
 
 bool GLFramebuffer::setNativeWindowBuffer(ANativeWindowBuffer* nativeBuffer, bool isProtected,
@@ -87,28 +78,12 @@
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
 
-    const bool multiTarget = mSecondaryTextureName != -1;
-    if (multiTarget) {
-        glBindTexture(GL_TEXTURE_2D, mSecondaryTextureName);
-        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
-    }
-
     mBufferHeight = height;
     mBufferWidth = width;
     mEngine.checkErrors("Allocating Fbo texture");
 
     bind();
     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextureName, 0);
-    if (multiTarget) {
-        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_2D,
-                               mSecondaryTextureName, 0);
-        GLenum buffers[] = {GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT};
-        glDrawBuffers(2, buffers);
-    }
     mStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER);
     unbind();
     glBindTexture(GL_TEXTURE_2D, 0);
diff --git a/libs/renderengine/gl/GLFramebuffer.h b/libs/renderengine/gl/GLFramebuffer.h
index 69102d6..b88da3b 100644
--- a/libs/renderengine/gl/GLFramebuffer.h
+++ b/libs/renderengine/gl/GLFramebuffer.h
@@ -42,7 +42,6 @@
     void allocateBuffers(uint32_t width, uint32_t height);
     EGLImageKHR getEGLImage() const { return mEGLImage; }
     uint32_t getTextureName() const { return mTextureName; }
-    uint32_t getSecondaryTextureName() const { return mSecondaryTextureName; }
     uint32_t getFramebufferName() const { return mFramebufferName; }
     int32_t getBufferHeight() const { return mBufferHeight; }
     int32_t getBufferWidth() const { return mBufferWidth; }
@@ -59,7 +58,6 @@
     bool usingFramebufferCache = false;
     GLenum mStatus = GL_FRAMEBUFFER_UNSUPPORTED;
     uint32_t mTextureName, mFramebufferName;
-    uint32_t mSecondaryTextureName = -1;
 
     int32_t mBufferHeight = 0;
     int32_t mBufferWidth = 0;
diff --git a/libs/ui/include/ui/Size.h b/libs/ui/include/ui/Size.h
index d9b713d..c2cda17 100644
--- a/libs/ui/include/ui/Size.h
+++ b/libs/ui/include/ui/Size.h
@@ -19,6 +19,7 @@
 #include <algorithm>
 #include <cstdint>
 #include <limits>
+#include <ostream>
 #include <type_traits>
 #include <utility>
 
@@ -113,13 +114,12 @@
                     std::numeric_limits<Size::remove_cv_reference_t<ToType>>::is_bounded &&
                             std::numeric_limits<Size::remove_cv_reference_t<FromType>>::is_bounded,
                     FromType&&>::type v) {
-        static constexpr auto toHighest = std::numeric_limits<remove_cv_reference_t<ToType>>::max();
-        static constexpr auto toLowest =
-                std::numeric_limits<remove_cv_reference_t<ToType>>::lowest();
-        static constexpr auto fromHighest =
-                std::numeric_limits<remove_cv_reference_t<FromType>>::max();
-        static constexpr auto fromLowest =
-                std::numeric_limits<remove_cv_reference_t<FromType>>::lowest();
+        using BareToType = remove_cv_reference_t<ToType>;
+        using BareFromType = remove_cv_reference_t<FromType>;
+        static constexpr auto toHighest = std::numeric_limits<BareToType>::max();
+        static constexpr auto toLowest = std::numeric_limits<BareToType>::lowest();
+        static constexpr auto fromHighest = std::numeric_limits<BareFromType>::max();
+        static constexpr auto fromLowest = std::numeric_limits<BareFromType>::lowest();
 
         // A clamp is needed if the range of FromType is not a subset of the range of ToType
         static constexpr bool isClampNeeded = (toLowest > fromLowest) || (toHighest < fromHighest);
@@ -129,10 +129,13 @@
             return static_cast<ToType>(v);
         }
 
-        // Otherwise we leverage implicit conversion to safely compare values of
-        // different types, to ensure we return a value clamped to the range of
-        // ToType.
-        return v < toLowest ? toLowest : (static_cast<ToType>(v) > toHighest ? toHighest : static_cast<ToType>(v));
+        // Otherwise we need to carefully compare the limits of ToType (casted
+        // for the comparisons to be warning free to FromType) while still
+        // ensuring we return a value clamped to the range of ToType.
+        return v < static_cast<const BareFromType>(toLowest)
+                ? toLowest
+                : (v > static_cast<const BareFromType>(toHighest) ? toHighest
+                                                                  : static_cast<ToType>(v));
     }
 };
 
@@ -154,5 +157,10 @@
     return lhs.height < rhs.height;
 }
 
+// Defining PrintTo helps with Google Tests.
+static inline void PrintTo(const Size& size, ::std::ostream* os) {
+    *os << "Size(" << size.width << ", " << size.height << ")";
+}
+
 } // namespace ui
 } // namespace android
diff --git a/libs/ui/tests/Android.bp b/libs/ui/tests/Android.bp
index ff55bc2..605c5a9 100644
--- a/libs/ui/tests/Android.bp
+++ b/libs/ui/tests/Android.bp
@@ -111,6 +111,7 @@
 
 cc_test {
     name: "Size_test",
+    test_suites: ["device-tests"],
     shared_libs: ["libui"],
     srcs: ["Size_test.cpp"],
     cflags: ["-Wall", "-Werror"],
diff --git a/libs/ui/tests/Size_test.cpp b/libs/ui/tests/Size_test.cpp
index 69e1ac8..40dc702 100644
--- a/libs/ui/tests/Size_test.cpp
+++ b/libs/ui/tests/Size_test.cpp
@@ -19,8 +19,18 @@
 #include <cmath>
 #include <cstdlib>
 
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic error "-Wimplicit-int-float-conversion"
+#pragma clang diagnostic error "-Wconversion"
+#endif // __clang__
+
 #include <ui/Size.h>
 
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif // __clang__
+
 #include <gtest/gtest.h>
 
 namespace android {
diff --git a/libs/ui/tests/TEST_MAPPING b/libs/ui/tests/TEST_MAPPING
new file mode 100644
index 0000000..7fcd7de
--- /dev/null
+++ b/libs/ui/tests/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+  "presubmit": [
+    {
+      "name": "Size_test"
+    }
+  ]
+}
diff --git a/services/gpuservice/gpustats/GpuStats.cpp b/services/gpuservice/gpustats/GpuStats.cpp
index d094532..263bf61 100644
--- a/services/gpuservice/gpustats/GpuStats.cpp
+++ b/services/gpuservice/gpustats/GpuStats.cpp
@@ -30,16 +30,11 @@
 
 namespace android {
 
-GpuStats::GpuStats() {
-    AStatsManager_registerPullAtomCallback(android::util::GPU_STATS_GLOBAL_INFO,
-                                           GpuStats::pullAtomCallback, nullptr, this);
-    AStatsManager_registerPullAtomCallback(android::util::GPU_STATS_APP_INFO,
-                                           GpuStats::pullAtomCallback, nullptr, this);
-}
-
 GpuStats::~GpuStats() {
-    AStatsManager_unregisterPullAtomCallback(android::util::GPU_STATS_GLOBAL_INFO);
-    AStatsManager_unregisterPullAtomCallback(android::util::GPU_STATS_APP_INFO);
+    if (mStatsdRegistered) {
+        AStatsManager_unregisterPullAtomCallback(android::util::GPU_STATS_GLOBAL_INFO);
+        AStatsManager_unregisterPullAtomCallback(android::util::GPU_STATS_APP_INFO);
+    }
 }
 
 static void addLoadingCount(GpuStatsInfo::Driver driver, bool isDriverLoaded,
@@ -97,6 +92,7 @@
     ATRACE_CALL();
 
     std::lock_guard<std::mutex> lock(mLock);
+    registerStatsdCallbacksIfNeeded();
     ALOGV("Received:\n"
           "\tdriverPackageName[%s]\n"
           "\tdriverVersionName[%s]\n"
@@ -150,6 +146,7 @@
     const std::string appStatsKey = appPackageName + std::to_string(driverVersionCode);
 
     std::lock_guard<std::mutex> lock(mLock);
+    registerStatsdCallbacksIfNeeded();
     if (!mAppStats.count(appStatsKey)) {
         return;
     }
@@ -179,6 +176,16 @@
     mGlobalStats[0].glesVersion = property_get_int32("ro.opengles.version", 0);
 }
 
+void GpuStats::registerStatsdCallbacksIfNeeded() {
+    if (!mStatsdRegistered) {
+        AStatsManager_registerPullAtomCallback(android::util::GPU_STATS_GLOBAL_INFO,
+                                               GpuStats::pullAtomCallback, nullptr, this);
+        AStatsManager_registerPullAtomCallback(android::util::GPU_STATS_APP_INFO,
+                                               GpuStats::pullAtomCallback, nullptr, this);
+        mStatsdRegistered = true;
+    }
+}
+
 void GpuStats::dump(const Vector<String16>& args, std::string* result) {
     ATRACE_CALL();
 
diff --git a/services/gpuservice/gpustats/include/gpustats/GpuStats.h b/services/gpuservice/gpustats/include/gpustats/GpuStats.h
index 8ca4e4e..55f0da1 100644
--- a/services/gpuservice/gpustats/include/gpustats/GpuStats.h
+++ b/services/gpuservice/gpustats/include/gpustats/GpuStats.h
@@ -30,7 +30,6 @@
 
 class GpuStats {
 public:
-    GpuStats();
     ~GpuStats();
 
     // Insert new gpu driver stats into global stats and app stats.
@@ -66,12 +65,16 @@
     void dumpAppLocked(std::string* result);
     // Append cpuVulkanVersion and glesVersion to system driver stats
     void interceptSystemDriverStatsLocked();
+    // Registers statsd callbacks if they have not already been registered
+    void registerStatsdCallbacksIfNeeded();
 
     // Below limits the memory usage of GpuStats to be less than 10KB. This is
     // the preferred number for statsd while maintaining nice data quality.
     static const size_t MAX_NUM_APP_RECORDS = 100;
     // GpuStats access should be guarded by mLock.
     std::mutex mLock;
+    // True if statsd callbacks have been registered.
+    bool mStatsdRegistered = false;
     // Key is driver version code.
     std::unordered_map<uint64_t, GpuStatsGlobalInfo> mGlobalStats;
     // Key is <app package name>+<driver version code>.
diff --git a/services/inputflinger/InputClassifier.cpp b/services/inputflinger/InputClassifier.cpp
index e5e83d7..8ba1f7f 100644
--- a/services/inputflinger/InputClassifier.cpp
+++ b/services/inputflinger/InputClassifier.cpp
@@ -46,8 +46,6 @@
 
 namespace android {
 
-static constexpr bool DEBUG = false;
-
 // Category (=namespace) name for the input settings that are applied at boot time
 static const char* INPUT_NATIVE_BOOT = "input_native_boot";
 // Feature flag name for the deep press feature
@@ -141,53 +139,46 @@
 
 // --- MotionClassifier ---
 
-MotionClassifier::MotionClassifier(sp<android::hardware::hidl_death_recipient> deathRecipient) :
-        mDeathRecipient(deathRecipient), mEvents(MAX_EVENTS) {
-    mHalThread = std::thread(&MotionClassifier::callInputClassifierHal, this);
-#if defined(__linux__)
-    // Set the thread name for debugging
-    pthread_setname_np(mHalThread.native_handle(), "InputClassifier");
-#endif
-}
-
-/**
- * This function may block for some time to initialize the HAL, so it should only be called
- * from the "InputClassifier HAL" thread.
- */
-bool MotionClassifier::init() {
-    ensureHalThread(__func__);
-    sp<android::hardware::input::classifier::V1_0::IInputClassifier> service =
-            classifier::V1_0::IInputClassifier::getService();
-    if (!service) {
-        // Not really an error, maybe the device does not have this HAL,
-        // but somehow the feature flag is flipped
-        ALOGI("Could not obtain InputClassifier HAL");
-        return false;
-    }
-
-    sp<android::hardware::hidl_death_recipient> recipient = mDeathRecipient.promote();
-    if (recipient != nullptr) {
-        const bool linked = service->linkToDeath(recipient, 0 /* cookie */).withDefault(false);
-        if (!linked) {
-            ALOGE("Could not link MotionClassifier to the HAL death");
-            return false;
-        }
-    }
-
+MotionClassifier::MotionClassifier(
+        sp<android::hardware::input::classifier::V1_0::IInputClassifier> service)
+      : mEvents(MAX_EVENTS), mService(service) {
     // Under normal operation, we do not need to reset the HAL here. But in the case where system
     // crashed, but HAL didn't, we may be connecting to an existing HAL process that might already
     // have received events in the past. That means, that HAL could be in an inconsistent state
     // once it receives events from the newly created MotionClassifier.
     mEvents.push(ClassifierEvent::createHalResetEvent());
 
-    {
-        std::scoped_lock lock(mLock);
-        if (mService) {
-            ALOGE("MotionClassifier::%s should only be called once", __func__);
-        }
-        mService = service;
+    mHalThread = std::thread(&MotionClassifier::processEvents, this);
+#if defined(__linux__)
+    // Set the thread name for debugging
+    pthread_setname_np(mHalThread.native_handle(), "InputClassifier");
+#endif
+}
+
+std::unique_ptr<MotionClassifierInterface> MotionClassifier::create(
+        sp<android::hardware::hidl_death_recipient> deathRecipient) {
+    if (!deepPressEnabled()) {
+        // If feature is not enabled, MotionClassifier should stay null to avoid unnecessary work.
+        // When MotionClassifier is null, InputClassifier will forward all events
+        // to the next InputListener, unmodified.
+        return nullptr;
     }
-    return true;
+    sp<android::hardware::input::classifier::V1_0::IInputClassifier> service =
+            classifier::V1_0::IInputClassifier::getService();
+    if (!service) {
+        // Not really an error, maybe the device does not have this HAL,
+        // but somehow the feature flag is flipped
+        ALOGI("Could not obtain InputClassifier HAL");
+        return nullptr;
+    }
+
+    const bool linked = service->linkToDeath(deathRecipient, 0 /* cookie */).withDefault(false);
+    if (!linked) {
+        ALOGE("Could not link death recipient to the HAL death");
+        return nullptr;
+    }
+    // Using 'new' to access a non-public constructor
+    return std::unique_ptr<MotionClassifier>(new MotionClassifier(service));
 }
 
 MotionClassifier::~MotionClassifier() {
@@ -195,14 +186,6 @@
     mHalThread.join();
 }
 
-void MotionClassifier::ensureHalThread(const char* function) {
-    if (DEBUG) {
-        if (std::this_thread::get_id() != mHalThread.get_id()) {
-            LOG_FATAL("Function %s should only be called from InputClassifier thread", function);
-        }
-    }
-}
-
 /**
  * Obtain the classification from the HAL for a given MotionEvent.
  * Should only be called from the InputClassifier thread (mHalThread).
@@ -213,23 +196,7 @@
  * To remove any possibility of negatively affecting the touch latency, the HAL
  * is called from a dedicated thread.
  */
-void MotionClassifier::callInputClassifierHal() {
-    ensureHalThread(__func__);
-    const bool initialized = init();
-    if (!initialized) {
-        // MotionClassifier no longer useful.
-        // Deliver death notification from a separate thread
-        // because ~MotionClassifier may be invoked, which calls mHalThread.join()
-        std::thread([deathRecipient = mDeathRecipient](){
-                sp<android::hardware::hidl_death_recipient> recipient = deathRecipient.promote();
-                if (recipient != nullptr) {
-                    recipient->serviceDied(0 /*cookie*/, nullptr);
-                }
-        }).detach();
-        return;
-    }
-    // From this point on, mService is guaranteed to be non-null.
-
+void MotionClassifier::processEvents() {
     while (true) {
         ClassifierEvent event = mEvents.pop();
         bool halResponseOk = true;
@@ -389,24 +356,30 @@
     }
 }
 
+// --- HalDeathRecipient
+
+InputClassifier::HalDeathRecipient::HalDeathRecipient(InputClassifier& parent) : mParent(parent) {}
+
+void InputClassifier::HalDeathRecipient::serviceDied(
+        uint64_t cookie, const wp<android::hidl::base::V1_0::IBase>& who) {
+    sp<android::hidl::base::V1_0::IBase> service = who.promote();
+    if (service) {
+        service->unlinkToDeath(this);
+    }
+    mParent.setMotionClassifier(nullptr);
+}
 
 // --- InputClassifier ---
 
-InputClassifier::InputClassifier(const sp<InputListenerInterface>& listener) :
-        mListener(listener) {
-    // The rest of the initialization is done in onFirstRef, because we need to obtain
-    // an sp to 'this' in order to register for HAL death notifications
-}
-
-void InputClassifier::onFirstRef() {
-    if (!deepPressEnabled()) {
-        // If feature is not enabled, MotionClassifier should stay null to avoid unnecessary work.
-        // When MotionClassifier is null, InputClassifier will forward all events
-        // to the next InputListener, unmodified.
-        return;
-    }
-    std::scoped_lock lock(mLock);
-    mMotionClassifier = std::make_unique<MotionClassifier>(this);
+InputClassifier::InputClassifier(const sp<InputListenerInterface>& listener)
+      : mListener(listener), mHalDeathRecipient(new HalDeathRecipient(*this)) {
+    mInitializeMotionClassifierThread = std::thread(
+            [this] { setMotionClassifier(MotionClassifier::create(mHalDeathRecipient)); });
+#if defined(__linux__)
+    // Set the thread name for debugging
+    pthread_setname_np(mInitializeMotionClassifierThread.native_handle(),
+                       "Create MotionClassifier");
+#endif
 }
 
 void InputClassifier::notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) {
@@ -447,15 +420,10 @@
     mListener->notifyDeviceReset(args);
 }
 
-void InputClassifier::serviceDied(uint64_t /*cookie*/,
-        const wp<android::hidl::base::V1_0::IBase>& who) {
+void InputClassifier::setMotionClassifier(
+        std::unique_ptr<MotionClassifierInterface> motionClassifier) {
     std::scoped_lock lock(mLock);
-    ALOGE("InputClassifier HAL has died. Setting mMotionClassifier to null");
-    mMotionClassifier = nullptr;
-    sp<android::hidl::base::V1_0::IBase> service = who.promote();
-    if (service) {
-        service->unlinkToDeath(this);
-    }
+    mMotionClassifier = std::move(motionClassifier);
 }
 
 void InputClassifier::dump(std::string& dump) {
@@ -472,4 +440,8 @@
     dump += "\n";
 }
 
+InputClassifier::~InputClassifier() {
+    mInitializeMotionClassifierThread.join();
+}
+
 } // namespace android
diff --git a/services/inputflinger/InputClassifier.h b/services/inputflinger/InputClassifier.h
index 9692352..8f58695 100644
--- a/services/inputflinger/InputClassifier.h
+++ b/services/inputflinger/InputClassifier.h
@@ -19,8 +19,8 @@
 
 #include <android-base/thread_annotations.h>
 #include <utils/RefBase.h>
-#include <unordered_map>
 #include <thread>
+#include <unordered_map>
 
 #include "BlockingQueue.h"
 #include "InputListener.h"
@@ -113,23 +113,23 @@
  */
 class MotionClassifier final : public MotionClassifierInterface {
 public:
-    /**
-     * The deathRecipient will be subscribed to the HAL death. If the death recipient
-     * owns MotionClassifier and receives HAL death, it should delete its copy of it.
-     * The callback serviceDied will also be sent if the MotionClassifier itself fails
-     * to initialize. If the MotionClassifier fails to initialize, it is not useful, and
-     * should be deleted.
-     * If no death recipient is supplied, then the registration step will be skipped, so there will
-     * be no listeners registered for the HAL death. This is useful for testing
-     * MotionClassifier in isolation.
+    /*
+     * Create an instance of MotionClassifier.
+     * The death recipient, if provided, will be subscribed to the HAL death.
+     * The death recipient could be used to destroy MotionClassifier.
+     *
+     * This function should be called asynchronously, because getService takes a long time.
      */
-    explicit MotionClassifier(sp<android::hardware::hidl_death_recipient> deathRecipient = nullptr);
+    static std::unique_ptr<MotionClassifierInterface> create(
+            sp<android::hardware::hidl_death_recipient> deathRecipient);
+
     ~MotionClassifier();
 
     /**
      * Classifies events asynchronously; that is, it doesn't block events on a classification,
-     * but instead sends them over to the classifier HAL and after a classification is
-     * determined, it then marks the next event it sees in the stream with it.
+     * but instead sends them over to the classifier HAL. After a classification of a specific
+     * event is determined, MotionClassifier then marks the next event in the stream with this
+     * classification.
      *
      * Therefore, it is acceptable to have the classifications be delayed by 1-2 events
      * in a particular gesture.
@@ -141,15 +141,9 @@
     virtual void dump(std::string& dump) override;
 
 private:
-    /**
-     * Initialize MotionClassifier.
-     * Return true if initializaion is successful.
-     */
-    bool init();
-    /**
-     * Entity that will be notified of the HAL death (most likely InputClassifier).
-     */
-    wp<android::hardware::hidl_death_recipient> mDeathRecipient;
+    friend class MotionClassifierTest; // to create MotionClassifier with a test HAL implementation
+    explicit MotionClassifier(
+            sp<android::hardware::input::classifier::V1_0::IInputClassifier> service);
 
     // The events that need to be sent to the HAL.
     BlockingQueue<ClassifierEvent> mEvents;
@@ -164,14 +158,9 @@
      */
     std::thread mHalThread;
     /**
-     * Print an error message if the caller is not on the InputClassifier thread.
-     * Caller must supply the name of the calling function as __func__
+     * Process events and call the InputClassifier HAL
      */
-    void ensureHalThread(const char* function);
-    /**
-     * Call the InputClassifier HAL
-     */
-    void callInputClassifierHal();
+    void processEvents();
     /**
      * Access to the InputClassifier HAL. May be null if init() hasn't completed yet.
      * When init() successfully completes, mService is guaranteed to remain non-null and to not
@@ -225,19 +214,15 @@
     const char* getServiceStatus() REQUIRES(mLock);
 };
 
-
 /**
  * Implementation of the InputClassifierInterface.
  * Represents a separate stage of input processing. All of the input events go through this stage.
  * Acts as a passthrough for all input events except for motion events.
  * The events of motion type are sent to MotionClassifier.
  */
-class InputClassifier : public InputClassifierInterface,
-        public android::hardware::hidl_death_recipient {
+class InputClassifier : public InputClassifierInterface {
 public:
     explicit InputClassifier(const sp<InputListenerInterface>& listener);
-    // Some of the constructor logic is finished in onFirstRef
-    virtual void onFirstRef() override;
 
     virtual void notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) override;
     virtual void notifyKey(const NotifyKeyArgs* args) override;
@@ -245,17 +230,44 @@
     virtual void notifySwitch(const NotifySwitchArgs* args) override;
     virtual void notifyDeviceReset(const NotifyDeviceResetArgs* args) override;
 
-    virtual void serviceDied(uint64_t cookie,
-            const wp<android::hidl::base::V1_0::IBase>& who) override;
-
     virtual void dump(std::string& dump) override;
 
+    ~InputClassifier();
+
 private:
     // Protect access to mMotionClassifier, since it may become null via a hidl callback
     std::mutex mLock;
-    std::unique_ptr<MotionClassifierInterface> mMotionClassifier GUARDED_BY(mLock);
     // The next stage to pass input events to
     sp<InputListenerInterface> mListener;
+
+    std::unique_ptr<MotionClassifierInterface> mMotionClassifier GUARDED_BY(mLock);
+    std::thread mInitializeMotionClassifierThread;
+    /**
+     * Set the value of mMotionClassifier.
+     * This is called from 2 different threads:
+     * 1) mInitializeMotionClassifierThread, when we have constructed a MotionClassifier
+     * 2) A binder thread of the HalDeathRecipient, which is created when HAL dies. This would cause
+     *    mMotionClassifier to become nullptr.
+     */
+    void setMotionClassifier(std::unique_ptr<MotionClassifierInterface> motionClassifier);
+
+    /**
+     * The deathRecipient will call setMotionClassifier(null) when the HAL dies.
+     */
+    class HalDeathRecipient : public android::hardware::hidl_death_recipient {
+    public:
+        explicit HalDeathRecipient(InputClassifier& parent);
+        virtual void serviceDied(uint64_t cookie,
+                                 const wp<android::hidl::base::V1_0::IBase>& who) override;
+
+    private:
+        InputClassifier& mParent;
+    };
+    // We retain a reference to death recipient, because the death recipient will be calling
+    // ~MotionClassifier if the HAL dies.
+    // If we don't retain a reference, and MotionClassifier is the only owner of the death
+    // recipient, the serviceDied call will cause death recipient to call its own destructor.
+    sp<HalDeathRecipient> mHalDeathRecipient;
 };
 
 } // namespace android
diff --git a/services/inputflinger/tests/InputClassifier_test.cpp b/services/inputflinger/tests/InputClassifier_test.cpp
index 40086ef..b4e755a 100644
--- a/services/inputflinger/tests/InputClassifier_test.cpp
+++ b/services/inputflinger/tests/InputClassifier_test.cpp
@@ -22,6 +22,9 @@
 #include <android/hardware/input/classifier/1.0/IInputClassifier.h>
 
 using namespace android::hardware::input;
+using android::hardware::Return;
+using android::hardware::Void;
+using android::hardware::input::common::V1_0::Classification;
 
 namespace android {
 
@@ -132,6 +135,27 @@
     ASSERT_EQ(args, outArgs);
 }
 
+/**
+ * A minimal implementation of IInputClassifier.
+ */
+struct TestHal : public android::hardware::input::classifier::V1_0::IInputClassifier {
+    Return<Classification> classify(
+            const android::hardware::input::common::V1_0::MotionEvent& event) override {
+        return Classification::NONE;
+    };
+    Return<void> reset() override { return Void(); };
+    Return<void> resetDevice(int32_t deviceId) override { return Void(); };
+};
+
+/**
+ * An entity that will be subscribed to the HAL death.
+ */
+class TestDeathRecipient : public android::hardware::hidl_death_recipient {
+public:
+    virtual void serviceDied(uint64_t cookie,
+                             const wp<android::hidl::base::V1_0::IBase>& who) override{};
+};
+
 // --- MotionClassifierTest ---
 
 class MotionClassifierTest : public testing::Test {
@@ -139,7 +163,14 @@
     std::unique_ptr<MotionClassifierInterface> mMotionClassifier;
 
     virtual void SetUp() override {
-        mMotionClassifier = std::make_unique<MotionClassifier>();
+        mMotionClassifier = MotionClassifier::create(new TestDeathRecipient());
+        if (mMotionClassifier == nullptr) {
+            // If the device running this test does not have IInputClassifier service,
+            // use the test HAL instead.
+            // Using 'new' to access non-public constructor
+            mMotionClassifier =
+                    std::unique_ptr<MotionClassifier>(new MotionClassifier(new TestHal()));
+        }
     }
 };
 
diff --git a/services/surfaceflinger/BufferLayerConsumer.cpp b/services/surfaceflinger/BufferLayerConsumer.cpp
index 5e04d95..e50a909 100644
--- a/services/surfaceflinger/BufferLayerConsumer.cpp
+++ b/services/surfaceflinger/BufferLayerConsumer.cpp
@@ -443,10 +443,7 @@
 }
 
 void BufferLayerConsumer::onDisconnect() {
-    sp<Layer> l = mLayer.promote();
-    if (l.get()) {
-        l->onDisconnect();
-    }
+    mLayer->onDisconnect();
 }
 
 void BufferLayerConsumer::onSidebandStreamChanged() {
@@ -480,10 +477,7 @@
 
 void BufferLayerConsumer::addAndGetFrameTimestamps(const NewFrameEventsEntry* newTimestamps,
                                                    FrameEventHistoryDelta* outDelta) {
-    sp<Layer> l = mLayer.promote();
-    if (l.get()) {
-        l->addAndGetFrameTimestamps(newTimestamps, outDelta);
-    }
+    mLayer->addAndGetFrameTimestamps(newTimestamps, outDelta);
 }
 
 void BufferLayerConsumer::abandonLocked() {
diff --git a/services/surfaceflinger/BufferLayerConsumer.h b/services/surfaceflinger/BufferLayerConsumer.h
index 39ed370..c71a1d9 100644
--- a/services/surfaceflinger/BufferLayerConsumer.h
+++ b/services/surfaceflinger/BufferLayerConsumer.h
@@ -332,7 +332,7 @@
     const uint32_t mTexName;
 
     // The layer for this BufferLayerConsumer
-    const wp<Layer> mLayer;
+    Layer* mLayer;
 
     wp<ContentsChangedListener> mContentsChangedListener;
 
diff --git a/services/surfaceflinger/Scheduler/VSyncPredictor.cpp b/services/surfaceflinger/Scheduler/VSyncPredictor.cpp
index 399da19..257b8b1 100644
--- a/services/surfaceflinger/Scheduler/VSyncPredictor.cpp
+++ b/services/surfaceflinger/Scheduler/VSyncPredictor.cpp
@@ -115,10 +115,10 @@
     auto it = mRateMap.find(mIdealPeriod);
     auto const currentPeriod = std::get<0>(it->second);
     // TODO (b/144707443): its important that there's some precision in the mean of the ordinals
-    //                     for the intercept calculation, so scale the ordinals by 10 to continue
+    //                     for the intercept calculation, so scale the ordinals by 1000 to continue
     //                     fixed point calculation. Explore expanding
     //                     scheduler::utils::calculate_mean to have a fixed point fractional part.
-    static constexpr int kScalingFactor = 10;
+    static constexpr int64_t kScalingFactor = 1000;
 
     for (auto i = 0u; i < mTimestamps.size(); i++) {
         traceInt64If("VSP-ts", mTimestamps[i]);
@@ -147,7 +147,7 @@
         return false;
     }
 
-    nsecs_t const anticipatedPeriod = top / bottom * kScalingFactor;
+    nsecs_t const anticipatedPeriod = top * kScalingFactor / bottom;
     nsecs_t const intercept = meanTS - (anticipatedPeriod * meanOrdinal / kScalingFactor);
 
     auto const percent = std::abs(anticipatedPeriod - mIdealPeriod) * kMaxPercent / mIdealPeriod;
diff --git a/services/surfaceflinger/SurfaceTracing.h b/services/surfaceflinger/SurfaceTracing.h
index 4b9f777..83872ed 100644
--- a/services/surfaceflinger/SurfaceTracing.h
+++ b/services/surfaceflinger/SurfaceTracing.h
@@ -101,7 +101,7 @@
     std::condition_variable mCanStartTrace;
 
     std::mutex& mSfLock;
-    uint32_t mTraceFlags GUARDED_BY(mSfLock) = TRACE_ALL;
+    uint32_t mTraceFlags GUARDED_BY(mSfLock) = TRACE_CRITICAL | TRACE_INPUT;
     const char* mWhere GUARDED_BY(mSfLock) = "";
 
     mutable std::mutex mTraceLock;
diff --git a/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp b/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp
index f834af8..bf2a889 100644
--- a/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp
+++ b/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp
@@ -204,7 +204,7 @@
     };
     auto idealPeriod = 2000000;
     auto expectedPeriod = 1999892;
-    auto expectedIntercept = 175409;
+    auto expectedIntercept = 86342;
 
     tracker.setPeriod(idealPeriod);
     for (auto const& timestamp : simulatedVsyncs) {
@@ -335,8 +335,8 @@
             158929706370359,
     };
     auto const idealPeriod = 11111111;
-    auto const expectedPeriod = 11113500;
-    auto const expectedIntercept = -395335;
+    auto const expectedPeriod = 11113919;
+    auto const expectedIntercept = -1195945;
 
     tracker.setPeriod(idealPeriod);
     for (auto const& timestamp : simulatedVsyncs) {
@@ -355,6 +355,32 @@
     EXPECT_THAT(prediction, Ge(timePoint));
 }
 
+// See b/151146131
+TEST_F(VSyncPredictorTest, hasEnoughPrecision) {
+    VSyncPredictor tracker{mPeriod, 20, kMinimumSamplesForPrediction, kOutlierTolerancePercent};
+    std::vector<nsecs_t> const simulatedVsyncs{840873348817, 840890049444, 840906762675,
+                                               840923581635, 840940161584, 840956868096,
+                                               840973702473, 840990256277, 841007116851,
+                                               841023722530, 841040452167, 841057073002,
+                                               841073800920, 841090474360, 841107278632,
+                                               841123898634, 841140750875, 841157287127,
+                                               841591357014, 840856664232
+
+    };
+    auto const idealPeriod = 16666666;
+    auto const expectedPeriod = 16698426;
+    auto const expectedIntercept = 58055;
+
+    tracker.setPeriod(idealPeriod);
+    for (auto const& timestamp : simulatedVsyncs) {
+        tracker.addVsyncTimestamp(timestamp);
+    }
+
+    auto [slope, intercept] = tracker.getVSyncPredictionModel();
+    EXPECT_THAT(slope, IsCloseTo(expectedPeriod, mMaxRoundingError));
+    EXPECT_THAT(intercept, IsCloseTo(expectedIntercept, mMaxRoundingError));
+}
+
 TEST_F(VSyncPredictorTest, resetsWhenInstructed) {
     auto const idealPeriod = 10000;
     auto const realPeriod = 10500;
@@ -390,6 +416,22 @@
     }
 }
 
+constexpr nsecs_t operator""_years(unsigned long long years) noexcept {
+    using namespace std::chrono_literals;
+    return years * 365 * 24 * 3600 *
+            std::chrono::duration_cast<std::chrono::nanoseconds>(1s).count();
+}
+TEST_F(VSyncPredictorTest, aPhoneThatHasBeenAroundAWhileCanStillComputePeriod) {
+    constexpr nsecs_t timeBase = 100_years;
+
+    for (auto i = 0; i < kHistorySize; i++) {
+        tracker.addVsyncTimestamp(timeBase + i * mPeriod);
+    }
+    auto [slope, intercept] = tracker.getVSyncPredictionModel();
+    EXPECT_THAT(slope, IsCloseTo(mPeriod, mMaxRoundingError));
+    EXPECT_THAT(intercept, Eq(0));
+}
+
 } // namespace android::scheduler
 
 // TODO(b/129481165): remove the #pragma below and fix conversion issues
diff --git a/vulkan/libvulkan/api.cpp b/vulkan/libvulkan/api.cpp
index aae72db..e607b05 100644
--- a/vulkan/libvulkan/api.cpp
+++ b/vulkan/libvulkan/api.cpp
@@ -29,6 +29,8 @@
 #include <algorithm>
 #include <mutex>
 #include <new>
+#include <string>
+#include <unordered_set>
 #include <utility>
 
 #include <android-base/strings.h>
@@ -1280,9 +1282,66 @@
         return *pPropertyCount < count ? VK_INCOMPLETE : VK_SUCCESS;
     }
 
-    // TODO(b/143293104): expose extensions from implicitly enabled layers
-    return vulkan::driver::EnumerateInstanceExtensionProperties(
-        nullptr, pPropertyCount, pProperties);
+    // If the pLayerName is nullptr, we must advertise all instance extensions
+    // from all implicitly enabled layers and the driver implementation. If
+    // there are duplicates among layers and the driver implementation, always
+    // only preserve the top layer closest to the application regardless of the
+    // spec version.
+    std::vector<VkExtensionProperties> properties;
+    std::unordered_set<std::string> extensionNames;
+
+    // Expose extensions from implicitly enabled layers.
+    const std::string layersSetting =
+        android::GraphicsEnv::getInstance().getDebugLayers();
+    if (!layersSetting.empty()) {
+        std::vector<std::string> layers =
+            android::base::Split(layersSetting, ":");
+        for (uint32_t i = 0; i < layers.size(); i++) {
+            const Layer* layer = FindLayer(layers[i].c_str());
+            if (!layer) {
+                continue;
+            }
+            uint32_t count = 0;
+            const VkExtensionProperties* props =
+                GetLayerInstanceExtensions(*layer, count);
+            if (count > 0) {
+                for (uint32_t i = 0; i < count; ++i) {
+                    if (extensionNames.emplace(props[i].extensionName).second) {
+                        properties.push_back(props[i]);
+                    }
+                }
+            }
+        }
+    }
+
+    // TODO(b/143293104): Parse debug.vulkan.layers properties
+
+    // Expose extensions from driver implementation.
+    {
+        uint32_t count = 0;
+        VkResult result = vulkan::driver::EnumerateInstanceExtensionProperties(
+            nullptr, &count, nullptr);
+        if (result == VK_SUCCESS && count > 0) {
+            std::vector<VkExtensionProperties> props(count);
+            result = vulkan::driver::EnumerateInstanceExtensionProperties(
+                nullptr, &count, props.data());
+            for (auto prop : props) {
+                if (extensionNames.emplace(prop.extensionName).second) {
+                    properties.push_back(prop);
+                }
+            }
+        }
+    }
+
+    uint32_t totalCount = properties.size();
+    if (!pProperties || *pPropertyCount > totalCount) {
+        *pPropertyCount = totalCount;
+    }
+    if (pProperties) {
+        std::copy(properties.data(), properties.data() + *pPropertyCount,
+                  pProperties);
+    }
+    return *pPropertyCount < totalCount ? VK_INCOMPLETE : VK_SUCCESS;
 }
 
 VkResult EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice,