Merge "Move HwVsyncState into VsyncSchedule"
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index ecafcfc..a48313a 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -186,6 +186,7 @@
 #define SYSTEM_TRACE_SNAPSHOT "/data/misc/perfetto-traces/bugreport/systrace.pftrace"
 #define CGROUPFS_DIR "/sys/fs/cgroup"
 #define SDK_EXT_INFO "/apex/com.android.sdkext/bin/derive_sdk"
+#define DROPBOX_DIR "/data/system/dropbox"
 
 // TODO(narayan): Since this information has to be kept in sync
 // with tombstoned, we should just put it in a common header.
@@ -526,6 +527,15 @@
     return strcmp(path + len - sizeof(stat) + 1, stat); /* .../stat? */
 }
 
+static bool skip_wtf_strictmode(const char *path) {
+    if (strstr(path, "_wtf")) {
+        return true;
+    } else if (strstr(path, "_strictmode")) {
+        return true;
+    }
+    return false;
+}
+
 static bool skip_none(const char* path __attribute__((unused))) {
     return false;
 }
@@ -1895,6 +1905,11 @@
     DumpIpTablesAsRoot();
     DumpDynamicPartitionInfo();
     ds.AddDir(OTA_METADATA_DIR, true);
+    if (!PropertiesHelper::IsUserBuild()) {
+        // Include dropbox entry files inside ZIP, but exclude
+        // noisy WTF and StrictMode entries
+        dump_files("", DROPBOX_DIR, skip_wtf_strictmode, _add_file_from_fd);
+    }
 
     // Capture any IPSec policies in play. No keys are exposed here.
     RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"}, CommandOptions::WithTimeout(10).Build());
diff --git a/cmds/dumpstate/tests/dumpstate_test.cpp b/cmds/dumpstate/tests/dumpstate_test.cpp
index 87f9254..aa5219b 100644
--- a/cmds/dumpstate/tests/dumpstate_test.cpp
+++ b/cmds/dumpstate/tests/dumpstate_test.cpp
@@ -1051,7 +1051,8 @@
 };
 
 // Generate a quick LimitedOnly report redirected to a file, open it and verify entry exist.
-TEST_F(ZippedBugReportStreamTest, StreamLimitedOnlyReport) {
+// TODO: broken test tracked in b/249983726
+TEST_F(ZippedBugReportStreamTest, DISABLED_StreamLimitedOnlyReport) {
     std::string out_path = kTestDataPath + "StreamLimitedOnlyReportOut.zip";
     android::base::unique_fd out_fd;
     CreateFd(out_path, &out_fd);
diff --git a/libs/binder/rust/rpcbinder/Android.bp b/libs/binder/rust/rpcbinder/Android.bp
index afb73e9..38dd4fe 100644
--- a/libs/binder/rust/rpcbinder/Android.bp
+++ b/libs/binder/rust/rpcbinder/Android.bp
@@ -23,7 +23,13 @@
         "liblibc",
         "liblog_rust",
     ],
+    visibility: [
+        "//device/google/cuttlefish/shared/minidroid/sample",
+        "//packages/modules/Uwb",
+        "//packages/modules/Virtualization:__subpackages__",
+    ],
     apex_available: [
+        "//apex_available:platform",
         "com.android.compos",
         "com.android.uwb",
         "com.android.virt",
@@ -51,6 +57,7 @@
         "libutils",
     ],
     apex_available: [
+        "//apex_available:platform",
         "com.android.compos",
         "com.android.uwb",
         "com.android.virt",
@@ -84,6 +91,7 @@
         "libutils",
     ],
     apex_available: [
+        "//apex_available:platform",
         "com.android.compos",
         "com.android.uwb",
         "com.android.virt",
diff --git a/libs/jpegrecoverymap/Android.bp b/libs/jpegrecoverymap/Android.bp
index 2c4b3bf..ee112e8 100644
--- a/libs/jpegrecoverymap/Android.bp
+++ b/libs/jpegrecoverymap/Android.bp
@@ -57,7 +57,7 @@
     export_include_dirs: ["include"],
 
     srcs: [
-        "jpegencoder.cpp",
+        "jpegencoderhelper.cpp",
     ],
 }
 
@@ -73,6 +73,6 @@
     export_include_dirs: ["include"],
 
     srcs: [
-        "jpegdecoder.cpp",
+        "jpegdecoderhelper.cpp",
     ],
 }
diff --git a/libs/jpegrecoverymap/include/jpegrecoverymap/jpegdecoder.h b/libs/jpegrecoverymap/include/jpegrecoverymap/jpegdecoderhelper.h
similarity index 94%
rename from libs/jpegrecoverymap/include/jpegrecoverymap/jpegdecoder.h
rename to libs/jpegrecoverymap/include/jpegrecoverymap/jpegdecoderhelper.h
index 419b63d..485869d 100644
--- a/libs/jpegrecoverymap/include/jpegrecoverymap/jpegdecoder.h
+++ b/libs/jpegrecoverymap/include/jpegrecoverymap/jpegdecoderhelper.h
@@ -1,4 +1,3 @@
-
 /*
  * Copyright 2022 The Android Open Source Project
  *
@@ -15,8 +14,8 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_JPEGRECOVERYMAP_JPEGDECODER_H
-#define ANDROID_JPEGRECOVERYMAP_JPEGDECODER_H
+#ifndef ANDROID_JPEGRECOVERYMAP_JPEGDECODERHELPER_H
+#define ANDROID_JPEGRECOVERYMAP_JPEGDECODERHELPER_H
 
 // We must include cstdio before jpeglib.h. It is a requirement of libjpeg.
 #include <cstdio>
@@ -31,10 +30,10 @@
  * Encapsulates a converter from JPEG to raw image (YUV420planer or grey-scale) format.
  * This class is not thread-safe.
  */
-class JpegDecoder {
+class JpegDecoderHelper {
 public:
-    JpegDecoder();
-    ~JpegDecoder();
+    JpegDecoderHelper();
+    ~JpegDecoderHelper();
     /*
      * Decompresses JPEG image to raw image (YUV420planer, grey-scale or RGBA) format. After
      * calling this method, call getDecompressedImage() to get the image.
@@ -118,4 +117,4 @@
 };
 } /* namespace android  */
 
-#endif // ANDROID_JPEGRECOVERYMAP_JPEGDECODER_H
+#endif // ANDROID_JPEGRECOVERYMAP_JPEGDECODERHELPER_H
diff --git a/libs/jpegrecoverymap/include/jpegrecoverymap/jpegencoder.h b/libs/jpegrecoverymap/include/jpegrecoverymap/jpegencoderhelper.h
similarity index 93%
rename from libs/jpegrecoverymap/include/jpegrecoverymap/jpegencoder.h
rename to libs/jpegrecoverymap/include/jpegrecoverymap/jpegencoderhelper.h
index 61aeb8a..f087b55 100644
--- a/libs/jpegrecoverymap/include/jpegrecoverymap/jpegencoder.h
+++ b/libs/jpegrecoverymap/include/jpegrecoverymap/jpegencoderhelper.h
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_JPEGRECOVERYMAP_JPEGENCODER_H
-#define ANDROID_JPEGRECOVERYMAP_JPEGENCODER_H
+#ifndef ANDROID_JPEGRECOVERYMAP_JPEGENCODERHELPER_H
+#define ANDROID_JPEGRECOVERYMAP_JPEGENCODERHELPER_H
 
 // We must include cstdio before jpeglib.h. It is a requirement of libjpeg.
 #include <cstdio>
@@ -34,10 +34,10 @@
  * Encapsulates a converter from raw image (YUV420planer or grey-scale) to JPEG format.
  * This class is not thread-safe.
  */
-class JpegEncoder {
+class JpegEncoderHelper {
 public:
-    JpegEncoder();
-    ~JpegEncoder();
+    JpegEncoderHelper();
+    ~JpegEncoderHelper();
 
     /*
      * Compresses YUV420Planer image to JPEG format. After calling this method, call
@@ -92,4 +92,4 @@
 
 } /* namespace android  */
 
-#endif // ANDROID_JPEGRECOVERYMAP_JPEGENCODER_H
+#endif // ANDROID_JPEGRECOVERYMAP_JPEGENCODERHELPER_H
diff --git a/libs/jpegrecoverymap/jpegdecoder.cpp b/libs/jpegrecoverymap/jpegdecoderhelper.cpp
similarity index 91%
rename from libs/jpegrecoverymap/jpegdecoder.cpp
rename to libs/jpegrecoverymap/jpegdecoderhelper.cpp
index 1bf609a..0754ec9 100644
--- a/libs/jpegrecoverymap/jpegdecoder.cpp
+++ b/libs/jpegrecoverymap/jpegdecoderhelper.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include <jpegrecoverymap/jpegdecoder.h>
+#include <jpegrecoverymap/jpegdecoderhelper.h>
 
 #include <utils/Log.h>
 
@@ -90,14 +90,14 @@
     longjmp(err->setjmp_buffer, 1);
 }
 
-JpegDecoder::JpegDecoder() {
+JpegDecoderHelper::JpegDecoderHelper() {
   mExifPos = 0;
 }
 
-JpegDecoder::~JpegDecoder() {
+JpegDecoderHelper::~JpegDecoderHelper() {
 }
 
-bool JpegDecoder::decompressImage(const void* image, int length, bool decodeToRGBA) {
+bool JpegDecoderHelper::decompressImage(const void* image, int length, bool decodeToRGBA) {
     if (image == nullptr || length <= 0) {
         ALOGE("Image size can not be handled: %d", length);
         return false;
@@ -112,39 +112,39 @@
     return true;
 }
 
-void* JpegDecoder::getDecompressedImagePtr() {
+void* JpegDecoderHelper::getDecompressedImagePtr() {
     return mResultBuffer.data();
 }
 
-size_t JpegDecoder::getDecompressedImageSize() {
+size_t JpegDecoderHelper::getDecompressedImageSize() {
     return mResultBuffer.size();
 }
 
-void* JpegDecoder::getXMPPtr() {
+void* JpegDecoderHelper::getXMPPtr() {
     return mXMPBuffer.data();
 }
 
-size_t JpegDecoder::getXMPSize() {
+size_t JpegDecoderHelper::getXMPSize() {
     return mXMPBuffer.size();
 }
 
-void* JpegDecoder::getEXIFPtr() {
+void* JpegDecoderHelper::getEXIFPtr() {
     return mEXIFBuffer.data();
 }
 
-size_t JpegDecoder::getEXIFSize() {
+size_t JpegDecoderHelper::getEXIFSize() {
     return mEXIFBuffer.size();
 }
 
-size_t JpegDecoder::getDecompressedImageWidth() {
+size_t JpegDecoderHelper::getDecompressedImageWidth() {
     return mWidth;
 }
 
-size_t JpegDecoder::getDecompressedImageHeight() {
+size_t JpegDecoderHelper::getDecompressedImageHeight() {
     return mHeight;
 }
 
-bool JpegDecoder::decode(const void* image, int length, bool decodeToRGBA) {
+bool JpegDecoderHelper::decode(const void* image, int length, bool decodeToRGBA) {
     jpeg_decompress_struct cinfo;
     jpegr_source_mgr mgr(static_cast<const uint8_t*>(image), length);
     jpegrerror_mgr myerr;
@@ -248,7 +248,7 @@
     return true;
 }
 
-bool JpegDecoder::decompress(jpeg_decompress_struct* cinfo, const uint8_t* dest,
+bool JpegDecoderHelper::decompress(jpeg_decompress_struct* cinfo, const uint8_t* dest,
         bool isSingleChannel) {
     if (isSingleChannel) {
         return decompressSingleChannel(cinfo, dest);
@@ -259,7 +259,7 @@
         return decompressYUV(cinfo, dest);
 }
 
-bool JpegDecoder::getCompressedImageParameters(const void* image, int length,
+bool JpegDecoderHelper::getCompressedImageParameters(const void* image, int length,
                               size_t *pWidth, size_t *pHeight,
                               std::vector<uint8_t> *iccData , std::vector<uint8_t> *exifData) {
     jpeg_decompress_struct cinfo;
@@ -326,7 +326,7 @@
     return true;
 }
 
-bool JpegDecoder::decompressRGBA(jpeg_decompress_struct* cinfo, const uint8_t* dest) {
+bool JpegDecoderHelper::decompressRGBA(jpeg_decompress_struct* cinfo, const uint8_t* dest) {
     JSAMPLE* decodeDst = (JSAMPLE*) dest;
     uint32_t lines = 0;
     // TODO: use batches for more effectiveness
@@ -341,7 +341,7 @@
     return lines == cinfo->image_height;
 }
 
-bool JpegDecoder::decompressYUV(jpeg_decompress_struct* cinfo, const uint8_t* dest) {
+bool JpegDecoderHelper::decompressYUV(jpeg_decompress_struct* cinfo, const uint8_t* dest) {
 
     JSAMPROW y[kCompressBatchSize];
     JSAMPROW cb[kCompressBatchSize / 2];
@@ -386,7 +386,7 @@
     return true;
 }
 
-bool JpegDecoder::decompressSingleChannel(jpeg_decompress_struct* cinfo, const uint8_t* dest) {
+bool JpegDecoderHelper::decompressSingleChannel(jpeg_decompress_struct* cinfo, const uint8_t* dest) {
     JSAMPROW y[kCompressBatchSize];
     JSAMPARRAY planes[1] {y};
 
diff --git a/libs/jpegrecoverymap/jpegencoder.cpp b/libs/jpegrecoverymap/jpegencoderhelper.cpp
similarity index 86%
rename from libs/jpegrecoverymap/jpegencoder.cpp
rename to libs/jpegrecoverymap/jpegencoderhelper.cpp
index 627dcdf..54b184d 100644
--- a/libs/jpegrecoverymap/jpegencoder.cpp
+++ b/libs/jpegrecoverymap/jpegencoderhelper.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include <jpegrecoverymap/jpegencoder.h>
+#include <jpegrecoverymap/jpegencoderhelper.h>
 
 #include <utils/Log.h>
 
@@ -22,20 +22,20 @@
 
 namespace android::recoverymap {
 
-// The destination manager that can access |mResultBuffer| in JpegEncoder.
+// The destination manager that can access |mResultBuffer| in JpegEncoderHelper.
 struct destination_mgr {
 public:
     struct jpeg_destination_mgr mgr;
-    JpegEncoder* encoder;
+    JpegEncoderHelper* encoder;
 };
 
-JpegEncoder::JpegEncoder() {
+JpegEncoderHelper::JpegEncoderHelper() {
 }
 
-JpegEncoder::~JpegEncoder() {
+JpegEncoderHelper::~JpegEncoderHelper() {
 }
 
-bool JpegEncoder::compressImage(const void* image, int width, int height, int quality,
+bool JpegEncoderHelper::compressImage(const void* image, int width, int height, int quality,
                                    const void* iccBuffer, unsigned int iccSize,
                                    bool isSingleChannel) {
     if (width % 8 != 0 || height % 2 != 0) {
@@ -52,15 +52,15 @@
     return true;
 }
 
-void* JpegEncoder::getCompressedImagePtr() {
+void* JpegEncoderHelper::getCompressedImagePtr() {
     return mResultBuffer.data();
 }
 
-size_t JpegEncoder::getCompressedImageSize() {
+size_t JpegEncoderHelper::getCompressedImageSize() {
     return mResultBuffer.size();
 }
 
-void JpegEncoder::initDestination(j_compress_ptr cinfo) {
+void JpegEncoderHelper::initDestination(j_compress_ptr cinfo) {
     destination_mgr* dest = reinterpret_cast<destination_mgr*>(cinfo->dest);
     std::vector<JOCTET>& buffer = dest->encoder->mResultBuffer;
     buffer.resize(kBlockSize);
@@ -68,7 +68,7 @@
     dest->mgr.free_in_buffer = buffer.size();
 }
 
-boolean JpegEncoder::emptyOutputBuffer(j_compress_ptr cinfo) {
+boolean JpegEncoderHelper::emptyOutputBuffer(j_compress_ptr cinfo) {
     destination_mgr* dest = reinterpret_cast<destination_mgr*>(cinfo->dest);
     std::vector<JOCTET>& buffer = dest->encoder->mResultBuffer;
     size_t oldsize = buffer.size();
@@ -78,13 +78,13 @@
     return true;
 }
 
-void JpegEncoder::terminateDestination(j_compress_ptr cinfo) {
+void JpegEncoderHelper::terminateDestination(j_compress_ptr cinfo) {
     destination_mgr* dest = reinterpret_cast<destination_mgr*>(cinfo->dest);
     std::vector<JOCTET>& buffer = dest->encoder->mResultBuffer;
     buffer.resize(buffer.size() - dest->mgr.free_in_buffer);
 }
 
-void JpegEncoder::outputErrorMessage(j_common_ptr cinfo) {
+void JpegEncoderHelper::outputErrorMessage(j_common_ptr cinfo) {
     char buffer[JMSG_LENGTH_MAX];
 
     /* Create the message */
@@ -92,7 +92,7 @@
     ALOGE("%s\n", buffer);
 }
 
-bool JpegEncoder::encode(const void* image, int width, int height, int jpegQuality,
+bool JpegEncoderHelper::encode(const void* image, int width, int height, int jpegQuality,
                          const void* iccBuffer, unsigned int iccSize, bool isSingleChannel) {
     jpeg_compress_struct cinfo;
     jpeg_error_mgr jerr;
@@ -118,7 +118,7 @@
     return true;
 }
 
-void JpegEncoder::setJpegDestination(jpeg_compress_struct* cinfo) {
+void JpegEncoderHelper::setJpegDestination(jpeg_compress_struct* cinfo) {
     destination_mgr* dest = static_cast<struct destination_mgr *>((*cinfo->mem->alloc_small) (
             (j_common_ptr) cinfo, JPOOL_PERMANENT, sizeof(destination_mgr)));
     dest->encoder = this;
@@ -128,7 +128,7 @@
     cinfo->dest = reinterpret_cast<struct jpeg_destination_mgr*>(dest);
 }
 
-void JpegEncoder::setJpegCompressStruct(int width, int height, int quality,
+void JpegEncoderHelper::setJpegCompressStruct(int width, int height, int quality,
                                         jpeg_compress_struct* cinfo, bool isSingleChannel) {
     cinfo->image_width = width;
     cinfo->image_height = height;
@@ -158,7 +158,7 @@
     }
 }
 
-bool JpegEncoder::compress(
+bool JpegEncoderHelper::compress(
         jpeg_compress_struct* cinfo, const uint8_t* image, bool isSingleChannel) {
     if (isSingleChannel) {
         return compressSingleChannel(cinfo, image);
@@ -166,7 +166,7 @@
     return compressYuv(cinfo, image);
 }
 
-bool JpegEncoder::compressYuv(jpeg_compress_struct* cinfo, const uint8_t* yuv) {
+bool JpegEncoderHelper::compressYuv(jpeg_compress_struct* cinfo, const uint8_t* yuv) {
     JSAMPROW y[kCompressBatchSize];
     JSAMPROW cb[kCompressBatchSize / 2];
     JSAMPROW cr[kCompressBatchSize / 2];
@@ -210,7 +210,7 @@
     return true;
 }
 
-bool JpegEncoder::compressSingleChannel(jpeg_compress_struct* cinfo, const uint8_t* image) {
+bool JpegEncoderHelper::compressSingleChannel(jpeg_compress_struct* cinfo, const uint8_t* image) {
     JSAMPROW y[kCompressBatchSize];
     JSAMPARRAY planes[1] {y};
 
diff --git a/libs/jpegrecoverymap/recoverymap.cpp b/libs/jpegrecoverymap/recoverymap.cpp
index 8b8c2e7..218c430 100644
--- a/libs/jpegrecoverymap/recoverymap.cpp
+++ b/libs/jpegrecoverymap/recoverymap.cpp
@@ -15,8 +15,8 @@
  */
 
 #include <jpegrecoverymap/recoverymap.h>
-#include <jpegrecoverymap/jpegencoder.h>
-#include <jpegrecoverymap/jpegdecoder.h>
+#include <jpegrecoverymap/jpegencoderhelper.h>
+#include <jpegrecoverymap/jpegdecoderhelper.h>
 #include <jpegrecoverymap/recoverymapmath.h>
 #include <jpegrecoverymap/recoverymaputils.h>
 
@@ -146,7 +146,7 @@
           jrTransFunc_to_skTransFunc.at(JPEGR_TF_SRGB),
           jrGamut_to_skGamut.at(uncompressed_yuv_420_image.colorGamut));
 
-  JpegEncoder jpeg_encoder;
+  JpegEncoderHelper jpeg_encoder;
   if (!jpeg_encoder.compressImage(uncompressed_yuv_420_image.data,
                                   uncompressed_yuv_420_image.width,
                                   uncompressed_yuv_420_image.height, quality,
@@ -210,7 +210,7 @@
           jrTransFunc_to_skTransFunc.at(JPEGR_TF_SRGB),
           jrGamut_to_skGamut.at(uncompressed_yuv_420_image->colorGamut));
 
-  JpegEncoder jpeg_encoder;
+  JpegEncoderHelper jpeg_encoder;
   if (!jpeg_encoder.compressImage(uncompressed_yuv_420_image->data,
                                   uncompressed_yuv_420_image->width,
                                   uncompressed_yuv_420_image->height, quality,
@@ -289,7 +289,7 @@
     return ERROR_JPEGR_INVALID_INPUT_TYPE;
   }
 
-  JpegDecoder jpeg_decoder;
+  JpegDecoderHelper jpeg_decoder;
   if (!jpeg_decoder.decompressImage(compressed_jpeg_image->data, compressed_jpeg_image->length)) {
     return ERROR_JPEGR_DECODE_ERROR;
   }
@@ -334,7 +334,7 @@
   JPEGR_CHECK(extractPrimaryImageAndRecoveryMap(compressed_jpegr_image,
                                                 &primary_image, &recovery_map));
 
-  JpegDecoder jpeg_decoder;
+  JpegDecoderHelper jpeg_decoder;
   if (!jpeg_decoder.getCompressedImageParameters(primary_image.data, primary_image.length,
                                                  &jpegr_info->width, &jpegr_info->height,
                                                  jpegr_info->iccData, jpegr_info->exifData)) {
@@ -356,7 +356,7 @@
   (void) exif;
 
   if (request_sdr) {
-    JpegDecoder jpeg_decoder;
+    JpegDecoderHelper jpeg_decoder;
     if (!jpeg_decoder.decompressImage(compressed_jpegr_image->data, compressed_jpegr_image->length,
                                       true)) {
         return ERROR_JPEGR_DECODE_ERROR;
@@ -376,12 +376,12 @@
   jpegr_metadata metadata;
   JPEGR_CHECK(extractRecoveryMap(compressed_jpegr_image, &compressed_map));
 
-  JpegDecoder jpeg_decoder;
+  JpegDecoderHelper jpeg_decoder;
   if (!jpeg_decoder.decompressImage(compressed_jpegr_image->data, compressed_jpegr_image->length)) {
     return ERROR_JPEGR_DECODE_ERROR;
   }
 
-  JpegDecoder recovery_map_decoder;
+  JpegDecoderHelper recovery_map_decoder;
   if (!recovery_map_decoder.decompressImage(compressed_map.data, compressed_map.length)) {
     return ERROR_JPEGR_DECODE_ERROR;
   }
@@ -411,7 +411,7 @@
     return ERROR_JPEGR_INVALID_NULL_PTR;
   }
 
-  JpegEncoder jpeg_encoder;
+  JpegEncoderHelper jpeg_encoder;
   if (!jpeg_encoder.compressImage(uncompressed_recovery_map->data,
                                   uncompressed_recovery_map->width,
                                   uncompressed_recovery_map->height,
diff --git a/libs/jpegrecoverymap/tests/Android.bp b/libs/jpegrecoverymap/tests/Android.bp
index e381caf..e416db9 100644
--- a/libs/jpegrecoverymap/tests/Android.bp
+++ b/libs/jpegrecoverymap/tests/Android.bp
@@ -44,10 +44,10 @@
 }
 
 cc_test {
-    name: "libjpegencoder_test",
+    name: "libjpegencoderhelper_test",
     test_suites: ["device-tests"],
     srcs: [
-        "jpegencoder_test.cpp",
+        "jpegencoderhelper_test.cpp",
     ],
     shared_libs: [
         "libjpeg",
@@ -60,10 +60,10 @@
 }
 
 cc_test {
-    name: "libjpegdecoder_test",
+    name: "libjpegdecoderhelper_test",
     test_suites: ["device-tests"],
     srcs: [
-        "jpegdecoder_test.cpp",
+        "jpegdecoderhelper_test.cpp",
     ],
     shared_libs: [
         "libjpeg",
diff --git a/libs/jpegrecoverymap/tests/jpegdecoder_test.cpp b/libs/jpegrecoverymap/tests/jpegdecoderhelper_test.cpp
similarity index 79%
rename from libs/jpegrecoverymap/tests/jpegdecoder_test.cpp
rename to libs/jpegrecoverymap/tests/jpegdecoderhelper_test.cpp
index 8e01351..278bf3b 100644
--- a/libs/jpegrecoverymap/tests/jpegdecoder_test.cpp
+++ b/libs/jpegrecoverymap/tests/jpegdecoderhelper_test.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include <jpegrecoverymap/jpegdecoder.h>
+#include <jpegrecoverymap/jpegdecoderhelper.h>
 #include <gtest/gtest.h>
 #include <utils/Log.h>
 
@@ -27,14 +27,14 @@
 #define GREY_IMAGE "/sdcard/Documents/minnie-320x240-y.jpg"
 #define GREY_IMAGE_SIZE 20193
 
-class JpegDecoderTest : public testing::Test {
+class JpegDecoderHelperTest : public testing::Test {
 public:
     struct Image {
         std::unique_ptr<uint8_t[]> buffer;
         size_t size;
     };
-    JpegDecoderTest();
-    ~JpegDecoderTest();
+    JpegDecoderHelperTest();
+    ~JpegDecoderHelperTest();
 protected:
     virtual void SetUp();
     virtual void TearDown();
@@ -42,9 +42,9 @@
     Image mYuvImage, mGreyImage;
 };
 
-JpegDecoderTest::JpegDecoderTest() {}
+JpegDecoderHelperTest::JpegDecoderHelperTest() {}
 
-JpegDecoderTest::~JpegDecoderTest() {}
+JpegDecoderHelperTest::~JpegDecoderHelperTest() {}
 
 static size_t getFileSize(int fd) {
     struct stat st;
@@ -55,7 +55,7 @@
     return st.st_size; // bytes
 }
 
-static bool loadFile(const char filename[], JpegDecoderTest::Image* result) {
+static bool loadFile(const char filename[], JpegDecoderHelperTest::Image* result) {
     int fd = open(filename, O_CLOEXEC);
     if (fd < 0) {
         return false;
@@ -74,7 +74,7 @@
     return true;
 }
 
-void JpegDecoderTest::SetUp() {
+void JpegDecoderHelperTest::SetUp() {
     if (!loadFile(YUV_IMAGE, &mYuvImage)) {
         FAIL() << "Load file " << YUV_IMAGE << " failed";
     }
@@ -85,16 +85,16 @@
     mGreyImage.size = GREY_IMAGE_SIZE;
 }
 
-void JpegDecoderTest::TearDown() {}
+void JpegDecoderHelperTest::TearDown() {}
 
-TEST_F(JpegDecoderTest, decodeYuvImage) {
-    JpegDecoder decoder;
+TEST_F(JpegDecoderHelperTest, decodeYuvImage) {
+    JpegDecoderHelper decoder;
     EXPECT_TRUE(decoder.decompressImage(mYuvImage.buffer.get(), mYuvImage.size));
     ASSERT_GT(decoder.getDecompressedImageSize(), static_cast<uint32_t>(0));
 }
 
-TEST_F(JpegDecoderTest, decodeGreyImage) {
-    JpegDecoder decoder;
+TEST_F(JpegDecoderHelperTest, decodeGreyImage) {
+    JpegDecoderHelper decoder;
     EXPECT_TRUE(decoder.decompressImage(mGreyImage.buffer.get(), mGreyImage.size));
     ASSERT_GT(decoder.getDecompressedImageSize(), static_cast<uint32_t>(0));
 }
diff --git a/libs/jpegrecoverymap/tests/jpegencoder_test.cpp b/libs/jpegrecoverymap/tests/jpegencoderhelper_test.cpp
similarity index 83%
rename from libs/jpegrecoverymap/tests/jpegencoder_test.cpp
rename to libs/jpegrecoverymap/tests/jpegencoderhelper_test.cpp
index 4cd2a5e..532688d 100644
--- a/libs/jpegrecoverymap/tests/jpegencoder_test.cpp
+++ b/libs/jpegrecoverymap/tests/jpegencoderhelper_test.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include <jpegrecoverymap/jpegencoder.h>
+#include <jpegrecoverymap/jpegencoderhelper.h>
 #include <gtest/gtest.h>
 #include <utils/Log.h>
 
@@ -33,15 +33,15 @@
 #define INVALID_SIZE_IMAGE_HEIGHT 240
 #define JPEG_QUALITY 90
 
-class JpegEncoderTest : public testing::Test {
+class JpegEncoderHelperTest : public testing::Test {
 public:
     struct Image {
         std::unique_ptr<uint8_t[]> buffer;
         size_t width;
         size_t height;
     };
-    JpegEncoderTest();
-    ~JpegEncoderTest();
+    JpegEncoderHelperTest();
+    ~JpegEncoderHelperTest();
 protected:
     virtual void SetUp();
     virtual void TearDown();
@@ -49,9 +49,9 @@
     Image mValidImage, mInvalidSizeImage, mSingleChannelImage;
 };
 
-JpegEncoderTest::JpegEncoderTest() {}
+JpegEncoderHelperTest::JpegEncoderHelperTest() {}
 
-JpegEncoderTest::~JpegEncoderTest() {}
+JpegEncoderHelperTest::~JpegEncoderHelperTest() {}
 
 static size_t getFileSize(int fd) {
     struct stat st;
@@ -62,7 +62,7 @@
     return st.st_size; // bytes
 }
 
-static bool loadFile(const char filename[], JpegEncoderTest::Image* result) {
+static bool loadFile(const char filename[], JpegEncoderHelperTest::Image* result) {
     int fd = open(filename, O_CLOEXEC);
     if (fd < 0) {
         return false;
@@ -81,7 +81,7 @@
     return true;
 }
 
-void JpegEncoderTest::SetUp() {
+void JpegEncoderHelperTest::SetUp() {
     if (!loadFile(VALID_IMAGE, &mValidImage)) {
         FAIL() << "Load file " << VALID_IMAGE << " failed";
     }
@@ -99,23 +99,23 @@
     mSingleChannelImage.height = SINGLE_CHANNEL_IMAGE_HEIGHT;
 }
 
-void JpegEncoderTest::TearDown() {}
+void JpegEncoderHelperTest::TearDown() {}
 
-TEST_F(JpegEncoderTest, validImage) {
-    JpegEncoder encoder;
+TEST_F(JpegEncoderHelperTest, validImage) {
+    JpegEncoderHelper encoder;
     EXPECT_TRUE(encoder.compressImage(mValidImage.buffer.get(), mValidImage.width,
                                          mValidImage.height, JPEG_QUALITY, NULL, 0));
     ASSERT_GT(encoder.getCompressedImageSize(), static_cast<uint32_t>(0));
 }
 
-TEST_F(JpegEncoderTest, invalidSizeImage) {
-    JpegEncoder encoder;
+TEST_F(JpegEncoderHelperTest, invalidSizeImage) {
+    JpegEncoderHelper encoder;
     EXPECT_FALSE(encoder.compressImage(mInvalidSizeImage.buffer.get(), mInvalidSizeImage.width,
                                           mInvalidSizeImage.height, JPEG_QUALITY, NULL, 0));
 }
 
-TEST_F(JpegEncoderTest, singleChannelImage) {
-    JpegEncoder encoder;
+TEST_F(JpegEncoderHelperTest, singleChannelImage) {
+    JpegEncoderHelper encoder;
     EXPECT_TRUE(encoder.compressImage(mSingleChannelImage.buffer.get(), mSingleChannelImage.width,
                                          mSingleChannelImage.height, JPEG_QUALITY, NULL, 0, true));
     ASSERT_GT(encoder.getCompressedImageSize(), static_cast<uint32_t>(0));
diff --git a/services/inputflinger/dispatcher/CancelationOptions.h b/services/inputflinger/dispatcher/CancelationOptions.h
index 48f9f2b..83e6a60 100644
--- a/services/inputflinger/dispatcher/CancelationOptions.h
+++ b/services/inputflinger/dispatcher/CancelationOptions.h
@@ -30,6 +30,7 @@
         CANCEL_POINTER_EVENTS = 1,
         CANCEL_NON_POINTER_EVENTS = 2,
         CANCEL_FALLBACK_EVENTS = 3,
+        ftl_last = CANCEL_FALLBACK_EVENTS,
     };
 
     // The criterion to use to determine which events should be canceled.
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index d14a781..9d5bbbd 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -2185,8 +2185,9 @@
     const bool isFromMouse = isFromSource(entry.source, AINPUT_SOURCE_MOUSE);
 
     if (newGesture) {
-        bool down = maskedAction == AMOTION_EVENT_ACTION_DOWN;
-        if (switchedDevice && tempTouchState.isDown() && !down && !isHoverAction) {
+        // If pointers are already down, let's finish the current gesture and ignore the new events
+        // from another device.
+        if (switchedDevice && wasDown) {
             ALOGI("Dropping event because a pointer for a different device is already down "
                   "in display %" PRId32,
                   displayId);
@@ -3761,9 +3762,9 @@
     }
     if (DEBUG_OUTBOUND_EVENT_DETAILS) {
         ALOGD("channel '%s' ~ Synthesized %zu cancelation events to bring channel back in sync "
-              "with reality: %s, mode=%d.",
+              "with reality: %s, mode=%s.",
               connection->getInputChannelName().c_str(), cancelationEvents.size(), options.reason,
-              options.mode);
+              ftl::enum_string(options.mode).c_str());
     }
 
     std::string reason = std::string("reason=").append(options.reason);
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index 3605be2..e71cdce 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -2461,6 +2461,86 @@
 }
 
 /**
+ * Start hovering with a stylus device, and then tap with a touch device. Ensure no crash occurs.
+ * While the touch is down, new hover events from the stylus device should be ignored. After the
+ * touch is gone, stylus hovering should start working again.
+ */
+TEST_F(InputDispatcherTest, StylusHoverAndTouchTap) {
+    std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
+    sp<FakeWindowHandle> window =
+            sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
+    window->setFrame(Rect(0, 0, 200, 200));
+
+    mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
+
+    const int32_t stylusDeviceId = 5;
+    const int32_t touchDeviceId = 4;
+    // Start hovering with stylus
+    ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
+              injectMotionEvent(mDispatcher,
+                                MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
+                                                   AINPUT_SOURCE_STYLUS)
+                                        .deviceId(stylusDeviceId)
+                                        .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_STYLUS)
+                                                         .x(50)
+                                                         .y(50))
+                                        .build()));
+    window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
+
+    // Finger down on the window
+    ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
+              injectMotionEvent(mDispatcher,
+                                MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
+                                                   AINPUT_SOURCE_TOUCHSCREEN)
+                                        .deviceId(touchDeviceId)
+                                        .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER)
+                                                         .x(100)
+                                                         .y(100))
+                                        .build()));
+    window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
+    window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
+
+    // Try to continue hovering with stylus. Since we are already down, injection should fail
+    ASSERT_EQ(InputEventInjectionResult::FAILED,
+              injectMotionEvent(mDispatcher,
+                                MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
+                                                   AINPUT_SOURCE_STYLUS)
+                                        .deviceId(stylusDeviceId)
+                                        .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_STYLUS)
+                                                         .x(50)
+                                                         .y(50))
+                                        .build()));
+    // No event should be sent. This event should be ignored because a pointer from another device
+    // is already down.
+
+    // Lift up the finger
+    ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
+              injectMotionEvent(mDispatcher,
+                                MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
+                                                   AINPUT_SOURCE_TOUCHSCREEN)
+                                        .deviceId(touchDeviceId)
+                                        .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER)
+                                                         .x(100)
+                                                         .y(100))
+                                        .build()));
+    window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
+
+    // Now that the touch is gone, stylus hovering should start working again
+    ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
+              injectMotionEvent(mDispatcher,
+                                MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
+                                                   AINPUT_SOURCE_STYLUS)
+                                        .deviceId(stylusDeviceId)
+                                        .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_STYLUS)
+                                                         .x(50)
+                                                         .y(50))
+                                        .build()));
+    window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
+    // No more events
+    window->assertNoEvents();
+}
+
+/**
  * On the display, have a single window, and also an area where there's no window.
  * First pointer touches the "no window" area of the screen. Second pointer touches the window.
  * Make sure that the window receives the second pointer, and first pointer is simply ignored.
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index d1f6e87..17cdff9 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -28,10 +28,10 @@
 #include <ftl/enum.h>
 #include <ftl/fake_guard.h>
 #include <ftl/small_map.h>
+#include <gui/TraceUtils.h>
 #include <gui/WindowInfo.h>
 #include <system/window.h>
 #include <utils/Timers.h>
-#include <utils/Trace.h>
 
 #include <FrameTimeline/FrameTimeline.h>
 #include <scheduler/interface/ICompositor.h>
@@ -171,6 +171,7 @@
         return true;
     }
 
+    ATRACE_FORMAT("%s uid: %d frameRate: %s", __func__, uid, to_string(*frameRate).c_str());
     return mVsyncSchedule->getTracker().isVSyncInPhase(expectedVsyncTimestamp.ns(), *frameRate);
 }
 
diff --git a/services/surfaceflinger/Scheduler/VSyncPredictor.cpp b/services/surfaceflinger/Scheduler/VSyncPredictor.cpp
index 02e12fd..f8cb323 100644
--- a/services/surfaceflinger/Scheduler/VSyncPredictor.cpp
+++ b/services/surfaceflinger/Scheduler/VSyncPredictor.cpp
@@ -31,8 +31,8 @@
 #include <android-base/stringprintf.h>
 #include <cutils/compiler.h>
 #include <cutils/properties.h>
+#include <gui/TraceUtils.h>
 #include <utils/Log.h>
-#include <utils/Trace.h>
 
 #include "RefreshRateSelector.h"
 #include "VSyncPredictor.h"
@@ -282,6 +282,13 @@
 }
 
 bool VSyncPredictor::isVSyncInPhaseLocked(nsecs_t timePoint, unsigned divisor) const {
+    const TimePoint now = TimePoint::now();
+    const auto getTimePointIn = [](TimePoint now, nsecs_t timePoint) -> float {
+        return ticks<std::milli, float>(TimePoint::fromNs(timePoint) - now);
+    };
+    ATRACE_FORMAT("%s timePoint in: %.2f divisor: %zu", __func__, getTimePointIn(now, timePoint),
+                  divisor);
+
     struct VsyncError {
         nsecs_t vsyncTimestamp;
         float error;
@@ -304,6 +311,7 @@
     if (knownTimestampIter == mRateDivisorKnownTimestampMap.end()) {
         const auto vsync = nextAnticipatedVSyncTimeFromLocked(justBeforeTimePoint);
         mRateDivisorKnownTimestampMap[dividedPeriod] = vsync;
+        ATRACE_FORMAT_INSTANT("(first) knownVsync in: %.2f", getTimePointIn(now, vsync));
         return true;
     }
 
@@ -323,6 +331,8 @@
 
     const auto minVsyncError = std::min_element(vsyncs.begin(), vsyncs.end());
     mRateDivisorKnownTimestampMap[dividedPeriod] = minVsyncError->vsyncTimestamp;
+    ATRACE_FORMAT_INSTANT("knownVsync in: %.2f",
+                          getTimePointIn(now, minVsyncError->vsyncTimestamp));
     return std::abs(minVsyncError->vsyncTimestamp - timePoint) < period / 2;
 }
 
diff --git a/services/surfaceflinger/main_surfaceflinger.cpp b/services/surfaceflinger/main_surfaceflinger.cpp
index fedd71e..0495678 100644
--- a/services/surfaceflinger/main_surfaceflinger.cpp
+++ b/services/surfaceflinger/main_surfaceflinger.cpp
@@ -139,11 +139,6 @@
 
     set_sched_policy(0, SP_FOREGROUND);
 
-    // Put most SurfaceFlinger threads in the system-background cpuset
-    // Keeps us from unnecessarily using big cores
-    // Do this after the binder thread pool init
-    if (cpusets_enabled()) set_cpuset_policy(0, SP_SYSTEM);
-
     // initialize before clients can connect
     flinger->init();