Merge "SF Crash Bug fix"
diff --git a/cmds/installd/otapreopt_chroot.cpp b/cmds/installd/otapreopt_chroot.cpp
index 3ff9d11..7c989f6 100644
--- a/cmds/installd/otapreopt_chroot.cpp
+++ b/cmds/installd/otapreopt_chroot.cpp
@@ -73,7 +73,7 @@
     for (const apex::ApexFile& apex_file : active_packages) {
         const std::string& package_path = apex_file.GetPath();
         base::Result<void> status = apex::deactivatePackage(package_path);
-        if (!status) {
+        if (!status.ok()) {
             LOG(ERROR) << "Failed to deactivate " << package_path << ": "
                        << status.error();
         }
diff --git a/include/android/bitmap.h b/include/android/bitmap.h
index 412fc6b..727a4af 100644
--- a/include/android/bitmap.h
+++ b/include/android/bitmap.h
@@ -81,8 +81,8 @@
 
 enum {
     /** If this bit is set in AndroidBitmapInfo.flags, the Bitmap uses the
-      * HARDWARE Config, and its AHardwareBuffer can be retrieved via
-      * AndroidBitmap_getHardwareBuffer.
+      * HARDWARE Config, and its {@link AHardwareBuffer} can be retrieved via
+      * {@link AndroidBitmap_getHardwareBuffer}.
       */
     ANDROID_BITMAP_FLAGS_IS_HARDWARE = 1 << 31,
 };
@@ -120,10 +120,10 @@
 #if __ANDROID_API__ >= 30
 
 /**
- * Given a java bitmap object, return its ADataSpace.
+ * Given a java bitmap object, return its {@link ADataSpace}.
  *
- * Note that ADataSpace only exposes a few values. This may return
- * ADATASPACE_UNKNOWN, even for Named ColorSpaces, if they have no
+ * Note that {@link ADataSpace} only exposes a few values. This may return
+ * {@link ADATASPACE_UNKNOWN}, even for Named ColorSpaces, if they have no
  * corresponding ADataSpace.
  */
 int32_t AndroidBitmap_getDataSpace(JNIEnv* env, jobject jbitmap)  __INTRODUCED_IN(30);
@@ -206,17 +206,17 @@
  *  @param dataspace {@link ADataSpace} describing the color space of the
  *                   pixels.
  *  @param pixels Pointer to pixels to compress.
- *  @param format (@link AndroidBitmapCompressFormat} to compress to.
+ *  @param format {@link AndroidBitmapCompressFormat} to compress to.
  *  @param quality Hint to the compressor, 0-100. The value is interpreted
  *                 differently depending on the
  *                 {@link AndroidBitmapCompressFormat}.
  *  @param userContext User-defined data which will be passed to the supplied
  *                     {@link AndroidBitmap_CompressWriteFunc} each time it is
  *                     called. May be null.
- *  @parm fn Function that writes the compressed data. Will be called each time
- *           the compressor has compressed more data that is ready to be
- *           written. May be called more than once for each call to this method.
- *           May not be null.
+ *  @param fn Function that writes the compressed data. Will be called each time
+ *            the compressor has compressed more data that is ready to be
+ *            written. May be called more than once for each call to this method.
+ *            May not be null.
  *  @return AndroidBitmap functions result code.
  */
 int AndroidBitmap_compress(const AndroidBitmapInfo* info,
@@ -235,11 +235,11 @@
  *
  *  @param bitmap Handle to an android.graphics.Bitmap.
  *  @param outBuffer On success, is set to a pointer to the
- *         AHardwareBuffer associated with bitmap. This acquires
+ *         {@link AHardwareBuffer} associated with bitmap. This acquires
  *         a reference on the buffer, and the client must call
- *         AHardwareBuffer_release when finished with it.
+ *         {@link AHardwareBuffer_release} when finished with it.
  *  @return AndroidBitmap functions result code.
- *          ANDROID_BITMAP_RESULT_BAD_PARAMETER if bitmap is not a
+ *          {@link ANDROID_BITMAP_RESULT_BAD_PARAMETER} if bitmap is not a
  *          HARDWARE Bitmap.
  */
 int AndroidBitmap_getHardwareBuffer(JNIEnv* env, jobject bitmap,
diff --git a/include/android/imagedecoder.h b/include/android/imagedecoder.h
index 6e5da52..3a87da0 100644
--- a/include/android/imagedecoder.h
+++ b/include/android/imagedecoder.h
@@ -20,9 +20,18 @@
  * Functions for converting encoded images into RGBA pixels.
  *
  * Similar to the Java counterpart android.graphics.ImageDecoder, it can be used
- * to decode images like PNG, JPEG, GIF, WEBP and HEIF. It has similar options
- * for scaling, cropping, and choosing the output format. Unlike the Java API,
- * which can create an android.graphics.Bitmap or
+ * to decode images in the following formats:
+ * - JPEG
+ * - PNG
+ * - GIF
+ * - WebP
+ * - BMP
+ * - ICO
+ * - WBMP
+ * - HEIF
+ * - Digital negatives (via the DNG SDK)
+ * <p>It has similar options for scaling, cropping, and choosing the output format.
+ * Unlike the Java API, which can create an android.graphics.Bitmap or
  * android.graphics.drawable.Drawable object, AImageDecoder decodes directly
  * into memory provided by the client. For more information, see the
  * <a href="https://developer.android.com/ndk/guides/image-decoder">Image decoder</a>
@@ -62,7 +71,7 @@
      */
     ANDROID_IMAGE_DECODER_SUCCESS = 0,
     /**
-     * The input was incomplete.
+     * The input is incomplete.
      */
     ANDROID_IMAGE_DECODER_INCOMPLETE = -1,
     /**
@@ -80,7 +89,7 @@
      */
     ANDROID_IMAGE_DECODER_INVALID_SCALE = -4,
     /**
-     * Some other parameter was bad.
+     * Some other parameter is invalid.
      */
     ANDROID_IMAGE_DECODER_BAD_PARAMETER = -5,
     /**
@@ -133,6 +142,19 @@
  *                   responsible for calling {@link AImageDecoder_delete} on it.
  * @return {@link ANDROID_IMAGE_DECODER_SUCCESS} on success or a value
  *         indicating the reason for the failure.
+ *
+ * Errors:
+ * - {@link ANDROID_IMAGE_DECODER_INCOMPLETE}: The asset was truncated before
+ *   reading the image header.
+ * - {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER}: One of the parameters is
+ *   null.
+ * - {@link ANDROID_IMAGE_DECODER_INVALID_INPUT}: There is an error in the
+ *   header.
+ * - {@link ANDROID_IMAGE_DECODER_SEEK_ERROR}: The asset failed to seek.
+ * - {@link ANDROID_IMAGE_DECODER_INTERNAL_ERROR}: Some other error, like a
+ *   failure to allocate memory.
+ * - {@link ANDROID_IMAGE_DECODER_UNSUPPORTED_FORMAT}: The format is not
+ *   supported.
  */
 int AImageDecoder_createFromAAsset(struct AAsset* asset, AImageDecoder** outDecoder)
         __INTRODUCED_IN(30);
@@ -149,6 +171,19 @@
  *                   responsible for calling {@link AImageDecoder_delete} on it.
  * @return {@link ANDROID_IMAGE_DECODER_SUCCESS} on success or a value
  *         indicating the reason for the failure.
+ *
+ * Errors:
+ * - {@link ANDROID_IMAGE_DECODER_INCOMPLETE}: The file was truncated before
+ *   reading the image header.
+ * - {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER}: The {@link AImageDecoder} is
+ *   null, or |fd| does not represent a valid, seekable file descriptor.
+ * - {@link ANDROID_IMAGE_DECODER_INVALID_INPUT}: There is an error in the
+ *   header.
+ * - {@link ANDROID_IMAGE_DECODER_SEEK_ERROR}: The descriptor failed to seek.
+ * - {@link ANDROID_IMAGE_DECODER_INTERNAL_ERROR}: Some other error, like a
+ *   failure to allocate memory.
+ * - {@link ANDROID_IMAGE_DECODER_UNSUPPORTED_FORMAT}: The format is not
+ *   supported.
  */
 int AImageDecoder_createFromFd(int fd, AImageDecoder** outDecoder) __INTRODUCED_IN(30);
 
@@ -163,7 +198,19 @@
  *                   a newly created {@link AImageDecoder}. Caller is
  *                   responsible for calling {@link AImageDecoder_delete} on it.
  * @return {@link ANDROID_IMAGE_DECODER_SUCCESS} on success or a value
- *         indicating reason for the failure.
+ *         indicating the reason for the failure.
+ *
+ * Errors:
+ * - {@link ANDROID_IMAGE_DECODER_INCOMPLETE}: The encoded image was truncated before
+ *   reading the image header.
+ * - {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER}: One of the parameters is
+ *   invalid.
+ * - {@link ANDROID_IMAGE_DECODER_INVALID_INPUT}: There is an error in the
+ *   header.
+ * - {@link ANDROID_IMAGE_DECODER_INTERNAL_ERROR}: Some other error, like a
+ *   failure to allocate memory.
+ * - {@link ANDROID_IMAGE_DECODER_UNSUPPORTED_FORMAT}: The format is not
+ *   supported.
  */
 int AImageDecoder_createFromBuffer(const void* buffer, size_t length,
                                    AImageDecoder** outDecoder) __INTRODUCED_IN(30);
@@ -177,11 +224,18 @@
  * Choose the desired output format.
  *
  * @param format {@link AndroidBitmapFormat} to use for the output.
- * @return {@link ANDROID_IMAGE_DECODER_SUCCESS} if the format is compatible
- *         with the image and {@link ANDROID_IMAGE_DECODER_INVALID_CONVERSION}
- *         otherwise. In the latter case, the {@link AImageDecoder} uses the
- *         format it was already planning to use (either its default
- *         or a previously successful setting from this function).
+ * @return {@link ANDROID_IMAGE_DECODER_SUCCESS} on success or a value
+ *         indicating the reason for the failure. On failure, the
+ *         {@link AImageDecoder} uses the format it was already planning
+ *         to use (either its default or a previously successful setting
+ *         from this function).
+ *
+ * Errors:
+ * - {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER}: The
+ *   {@link AImageDecoder} is null or |format| does not correspond to an
+ *   {@link AndroidBitmapFormat}.
+ * - {@link ANDROID_IMAGE_DECODER_INVALID_CONVERSION}: The
+ *   {@link AndroidBitmapFormat} is incompatible with the image.
  */
 int AImageDecoder_setAndroidBitmapFormat(AImageDecoder*,
         int32_t format) __INTRODUCED_IN(30);
@@ -194,11 +248,15 @@
  * opaque image.
  *
  * @param unpremultipliedRequired Pass true to leave the pixels unpremultiplied.
- * @return an enum describing whether the call succeeded.
- *         - {@link ANDROID_IMAGE_DECODER_SUCCESS} on success
- *         - {@link ANDROID_IMAGE_DECODER_INVALID_CONVERSION} if the conversion
- *           is not possible
- *         - {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER} for bad parameters
+ * @return {@link ANDROID_IMAGE_DECODER_SUCCESS} on success or a value
+ *         indicating the reason for the failure.
+ *
+ * Errors:
+ * - {@link ANDROID_IMAGE_DECODER_INVALID_CONVERSION}: Unpremultiplied is not
+ *   possible due to an existing scale set by
+ *   {@link AImageDecoder_setTargetSize}.
+ * - {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER}: The
+ *   {@link AImageDecoder} is null.
  */
 int AImageDecoder_setUnpremultipliedRequired(AImageDecoder*,
                                              bool unpremultipliedRequired) __INTRODUCED_IN(30);
@@ -215,10 +273,13 @@
  *                  {@link AImageDecoderHeaderInfo_getDataSpace}. If this
  *                  parameter is set to a different ADataSpace, AImageDecoder
  *                  will transform the output into the specified ADataSpace.
- * @return {@link ANDROID_IMAGE_DECODER_SUCCESS} on success or
- *         {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER} for a null
- *         {@link AImageDecoder} or an integer that does not correspond to an
- *         {@link ADataSpace} value.
+ * @return {@link ANDROID_IMAGE_DECODER_SUCCESS} on success or a value
+ *         indicating the reason for the failure.
+ *
+ * Errors:
+ * - {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER}: The
+ *   {@link AImageDecoder} is null or |dataspace| does not correspond to an
+ *   {@link ADataSpace} value.
  */
 int AImageDecoder_setDataSpace(AImageDecoder*, int32_t dataspace) __INTRODUCED_IN(30);
 
@@ -236,11 +297,16 @@
  *              {@link AImageDecoder_getMinimumStride}, which will now return
  *              a value based on this width.
  * @param height Height of the output (prior to cropping).
- * @return an enum describing whether the call succeeded.
- * @return {@link ANDROID_IMAGE_DECODER_SUCCESS} on success or
- *         {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER} if the {@link AImageDecoder}
- *         pointer is null, width or height is <= 0, or any existing crop is
- *         not contained by the new image dimensions.
+ * @return {@link ANDROID_IMAGE_DECODER_SUCCESS} on success or a value
+ *         indicating the reason for the failure.
+ *
+ * Errors:
+ * - {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER}: The
+ *   {@link AImageDecoder} is null.
+ * - {@link ANDROID_IMAGE_DECODER_INVALID_SCALE}: |width| or |height| is <= 0,
+ *   the size is too big, any existing crop is not contained by the new image dimensions,
+ *   or the scale is incompatible with a previous call to
+ *   {@link AImageDecoder_setUnpremultipliedRequired}(true).
  */
 int AImageDecoder_setTargetSize(AImageDecoder*, int32_t width, int32_t height) __INTRODUCED_IN(30);
 
@@ -262,8 +328,12 @@
  *              in the direction that the decoder can do most efficiently.
  * @param height Out parameter for the height sampled by sampleSize, and rounded
  *               in the direction that the decoder can do most efficiently.
- * @return {@link ANDROID_IMAGE_DECODER_SUCCESS} on success or
- *         {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER} for bad input.
+ * @return {@link ANDROID_IMAGE_DECODER_SUCCESS} on success or a value
+ *         indicating the reason for the failure.
+ *
+ * Errors:
+ * - {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER}: The
+ *   {@link AImageDecoder}, |width| or |height| is null or |sampleSize| is < 1.
  */
 int AImageDecoder_computeSampledSize(const AImageDecoder*, int sampleSize,
                                      int32_t* width, int32_t* height) __INTRODUCED_IN(30);
@@ -282,18 +352,21 @@
  *             specifically { 0, 0, 0, 0 } - may be used to remove the cropping
  *             behavior. Any other empty or unsorted ARects will result in
  *             returning {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER}.
- * @return an enum describing whether the call succeeded.
- * @return {@link ANDROID_IMAGE_DECODER_SUCCESS} on success or
- *         {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER} if the {@link AImageDecoder}
- *         pointer is null or the crop is not contained by the image
- *         dimensions.
+ * @return {@link ANDROID_IMAGE_DECODER_SUCCESS} on success or a value
+ *         indicating the reason for the failure.
+ *
+ * Errors:
+ * - {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER}: The
+ *   {@link AImageDecoder} is null or the crop is not contained by the
+ *   (possibly scaled) image dimensions.
  */
 int AImageDecoder_setCrop(AImageDecoder*, ARect crop) __INTRODUCED_IN(30);
 
 struct AImageDecoderHeaderInfo;
 /**
- * Opaque handle for representing information about the encoded image. It can
- * be passed to methods like {@link AImageDecoderHeaderInfo_getWidth} and
+ * Opaque handle for representing information about the encoded image. Retrieved
+ * using {@link AImageDecoder_getHeaderInfo} and passed to methods like
+ * {@link AImageDecoderHeaderInfo_getWidth} and
  * {@link AImageDecoderHeaderInfo_getHeight}.
  */
 typedef struct AImageDecoderHeaderInfo AImageDecoderHeaderInfo;
@@ -310,14 +383,16 @@
 /**
  * Report the native width of the encoded image. This is also the logical
  * pixel width of the output, unless {@link AImageDecoder_setTargetSize} is
- * used to choose a different size.
+ * used to choose a different size or {@link AImageDecoder_setCrop} is used to
+ * set a crop rect.
  */
 int32_t AImageDecoderHeaderInfo_getWidth(const AImageDecoderHeaderInfo*) __INTRODUCED_IN(30);
 
 /**
  * Report the native height of the encoded image. This is also the logical
  * pixel height of the output, unless {@link AImageDecoder_setTargetSize} is
- * used to choose a different size.
+ * used to choose a different size or {@link AImageDecoder_setCrop} is used to
+ * set a crop rect.
  */
 int32_t AImageDecoderHeaderInfo_getHeight(const AImageDecoderHeaderInfo*) __INTRODUCED_IN(30);
 
@@ -349,20 +424,20 @@
         const AImageDecoderHeaderInfo*) __INTRODUCED_IN(30);
 
 /**
- * Report the dataspace the {@link AImageDecoder} will decode to by default.
- * AImageDecoder will try to choose one that is sensible for the
- * image and the system. Note that this may not exactly match the ICC
- * profile (or other color information) stored in the encoded image.
+ * Report the dataspace the AImageDecoder will decode to by default.
  *
- * @return The {@link ADataSpace} most closely representing the way the colors
- *         are encoded (or {@link ADATASPACE_UNKNOWN} if there is not an
- *         approximate ADataSpace). This specifies how to interpret the colors
+ * By default, {@link AImageDecoder_decodeImage} will not do any color
+ * conversion.
+ *
+ * @return The {@link ADataSpace} representing the way the colors
+ *         are encoded (or {@link ADATASPACE_UNKNOWN} if there is not a
+ *         corresponding ADataSpace). This specifies how to interpret the colors
  *         in the decoded image, unless {@link AImageDecoder_setDataSpace} is
  *         called to decode to a different ADataSpace.
  *
  *         Note that ADataSpace only exposes a few values. This may return
- *         ADATASPACE_UNKNOWN, even for Named ColorSpaces, if they have no
- *         corresponding ADataSpace.
+ *         {@link ADATASPACE_UNKNOWN}, even for Named ColorSpaces, if they have
+ *         no corresponding {@link ADataSpace}.
  */
 int32_t AImageDecoderHeaderInfo_getDataSpace(
         const AImageDecoderHeaderInfo*) __INTRODUCED_IN(30);
@@ -392,11 +467,23 @@
  * @param size Size of the pixel buffer in bytes. Must be at least
  *             stride * (height - 1) +
  *             {@link AImageDecoder_getMinimumStride}.
- * @return {@link ANDROID_IMAGE_DECODER_SUCCESS} on success, or an error code
- *         from the same enum describing the failure.
- *         {@link ANDROID_IMAGE_DECODER_INCOMPLETE} or
- *         {@link ANDROID_IMAGE_DECODER_ERROR} means that a partial image was
- *         decoded, and undecoded lines have been initialized to all zeroes.
+ * @return {@link ANDROID_IMAGE_DECODER_SUCCESS} on success or a value
+ *         indicating the reason for the failure.
+ *
+ * Errors:
+ * - {@link ANDROID_IMAGE_DECODER_INCOMPLETE}: The image was truncated. A
+ *   partial image was decoded, and undecoded lines have been initialized to all
+ *   zeroes.
+ * - {@link ANDROID_IMAGE_DECODER_ERROR}: The image contained an error. A
+ *   partial image was decoded, and undecoded lines have been initialized to all
+ *   zeroes.
+ * - {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER}: The {@link AImageDecoder} or
+ *   |pixels| is null, the stride is not large enough or not pixel aligned, or
+ *   |size| is not large enough.
+ * - {@link ANDROID_IMAGE_DECODER_SEEK_ERROR}: The asset or file descriptor
+ *   failed to seek.
+ * - {@link ANDROID_IMAGE_DECODER_INTERNAL_ERROR}: Some other error, like a
+ *   failure to allocate memory.
  */
 int AImageDecoder_decodeImage(AImageDecoder* decoder,
                               void* pixels, size_t stride,
diff --git a/include/android/sensor.h b/include/android/sensor.h
index 12c00ad..e63ac4b 100644
--- a/include/android/sensor.h
+++ b/include/android/sensor.h
@@ -15,6 +15,9 @@
  */
 
 /**
+ * Structures and functions to receive and process sensor events in
+ * native code.
+ *
  * @addtogroup Sensor
  * @{
  */
@@ -42,12 +45,6 @@
  *   - DO NOT CHANGE THE LAYOUT OR SIZE OF STRUCTURES
  */
 
-/**
- * Structures and functions to receive and process sensor events in
- * native code.
- *
- */
-
 #include <android/looper.h>
 
 #include <stdbool.h>
diff --git a/include/ui/FatVector.h b/include/ui/FatVector.h
new file mode 120000
index 0000000..c2047c0
--- /dev/null
+++ b/include/ui/FatVector.h
@@ -0,0 +1 @@
+../../libs/ui/include/ui/FatVector.h
\ No newline at end of file
diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp
index 328653a..9888b59 100644
--- a/libs/binder/IServiceManager.cpp
+++ b/libs/binder/IServiceManager.cpp
@@ -85,31 +85,36 @@
     sp<AidlServiceManager> mTheRealServiceManager;
 };
 
-static Mutex gDefaultServiceManagerLock;
+static std::once_flag gSmOnce;
 static sp<IServiceManager> gDefaultServiceManager;
 
 sp<IServiceManager> defaultServiceManager()
 {
-
-    if (gDefaultServiceManager != nullptr) return gDefaultServiceManager;
-
-    {
-        AutoMutex _l(gDefaultServiceManagerLock);
-        while (gDefaultServiceManager == nullptr) {
-            gDefaultServiceManager = new ServiceManagerShim(
-                interface_cast<AidlServiceManager>(
-                    ProcessState::self()->getContextObject(nullptr)));
-            if (gDefaultServiceManager == nullptr)
+    std::call_once(gSmOnce, []() {
+        sp<AidlServiceManager> sm = nullptr;
+        while (sm == nullptr) {
+            sm = interface_cast<AidlServiceManager>(ProcessState::self()->getContextObject(nullptr));
+            if (sm == nullptr) {
                 sleep(1);
+            }
         }
-    }
+
+        gDefaultServiceManager = new ServiceManagerShim(sm);
+    });
 
     return gDefaultServiceManager;
 }
 
 void setDefaultServiceManager(const sp<IServiceManager>& sm) {
-  AutoMutex _l(gDefaultServiceManagerLock);
-  gDefaultServiceManager = sm;
+    bool called = false;
+    std::call_once(gSmOnce, [&]() {
+        gDefaultServiceManager = sm;
+        called = true;
+    });
+
+    if (!called) {
+        LOG_ALWAYS_FATAL("setDefaultServiceManager() called after defaultServiceManager().");
+    }
 }
 
 #if !defined(__ANDROID_VNDK__) && defined(__ANDROID__)
diff --git a/libs/binder/include/binder/IServiceManager.h b/libs/binder/include/binder/IServiceManager.h
index 31f022d..1d520c1 100644
--- a/libs/binder/include/binder/IServiceManager.h
+++ b/libs/binder/include/binder/IServiceManager.h
@@ -102,6 +102,9 @@
 
 /**
  * Directly set the default service manager. Only used for testing.
+ * Note that the caller is responsible for caling this method
+ * *before* any call to defaultServiceManager(); if the latter is
+ * called first, setDefaultServiceManager() will abort.
  */
 void setDefaultServiceManager(const sp<IServiceManager>& sm);
 
diff --git a/libs/gui/tests/BLASTBufferQueue_test.cpp b/libs/gui/tests/BLASTBufferQueue_test.cpp
index b40eb14..e184c7f 100644
--- a/libs/gui/tests/BLASTBufferQueue_test.cpp
+++ b/libs/gui/tests/BLASTBufferQueue_test.cpp
@@ -239,7 +239,7 @@
     ASSERT_EQ(&next, adapter.getNextTransaction());
 }
 
-TEST_F(BLASTBufferQueueTest, onFrameAvailable_ApplyDesiredPresentTime) {
+TEST_F(BLASTBufferQueueTest, DISABLED_onFrameAvailable_ApplyDesiredPresentTime) {
     BLASTBufferQueueHelper adapter(mSurfaceControl, mDisplayWidth, mDisplayHeight);
     sp<IGraphicBufferProducer> igbProducer;
     setUpProducer(adapter, igbProducer);
diff --git a/libs/ui/Region.cpp b/libs/ui/Region.cpp
index bf487c4..cd2a448 100644
--- a/libs/ui/Region.cpp
+++ b/libs/ui/Region.cpp
@@ -67,19 +67,20 @@
 // ----------------------------------------------------------------------------
 
 Region::Region() {
-    mStorage.add(Rect(0,0));
+    mStorage.push_back(Rect(0, 0));
 }
 
 Region::Region(const Region& rhs)
-    : mStorage(rhs.mStorage)
 {
+    mStorage.clear();
+    mStorage.insert(mStorage.begin(), rhs.mStorage.begin(), rhs.mStorage.end());
 #if defined(VALIDATE_REGIONS)
     validate(rhs, "rhs copy-ctor");
 #endif
 }
 
 Region::Region(const Rect& rhs) {
-    mStorage.add(rhs);
+    mStorage.push_back(rhs);
 }
 
 Region::~Region()
@@ -100,8 +101,8 @@
  * final, correctly ordered region buffer. Each rectangle will be compared with the span directly
  * above it, and subdivided to resolve any remaining T-junctions.
  */
-static void reverseRectsResolvingJunctions(const Rect* begin, const Rect* end,
-        Vector<Rect>& dst, int spanDirection) {
+static void reverseRectsResolvingJunctions(const Rect* begin, const Rect* end, FatVector<Rect>& dst,
+                                           int spanDirection) {
     dst.clear();
 
     const Rect* current = end - 1;
@@ -109,7 +110,7 @@
 
     // add first span immediately
     do {
-        dst.add(*current);
+        dst.push_back(*current);
         current--;
     } while (current->top == lastTop && current >= begin);
 
@@ -147,12 +148,12 @@
                 if (prev.right <= left) break;
 
                 if (prev.right > left && prev.right < right) {
-                    dst.add(Rect(prev.right, top, right, bottom));
+                    dst.push_back(Rect(prev.right, top, right, bottom));
                     right = prev.right;
                 }
 
                 if (prev.left > left && prev.left < right) {
-                    dst.add(Rect(prev.left, top, right, bottom));
+                    dst.push_back(Rect(prev.left, top, right, bottom));
                     right = prev.left;
                 }
 
@@ -166,12 +167,12 @@
                 if (prev.left >= right) break;
 
                 if (prev.left > left && prev.left < right) {
-                    dst.add(Rect(left, top, prev.left, bottom));
+                    dst.push_back(Rect(left, top, prev.left, bottom));
                     left = prev.left;
                 }
 
                 if (prev.right > left && prev.right < right) {
-                    dst.add(Rect(left, top, prev.right, bottom));
+                    dst.push_back(Rect(left, top, prev.right, bottom));
                     left = prev.right;
                 }
                 // if an entry in the previous span is too far left, nothing further right in the
@@ -183,7 +184,7 @@
         }
 
         if (left < right) {
-            dst.add(Rect(left, top, right, bottom));
+            dst.push_back(Rect(left, top, right, bottom));
         }
 
         current--;
@@ -201,13 +202,14 @@
     if (r.isEmpty()) return r;
     if (r.isRect()) return r;
 
-    Vector<Rect> reversed;
+    FatVector<Rect> reversed;
     reverseRectsResolvingJunctions(r.begin(), r.end(), reversed, direction_RTL);
 
     Region outputRegion;
-    reverseRectsResolvingJunctions(reversed.begin(), reversed.end(),
-            outputRegion.mStorage, direction_LTR);
-    outputRegion.mStorage.add(r.getBounds()); // to make region valid, mStorage must end with bounds
+    reverseRectsResolvingJunctions(reversed.data(), reversed.data() + reversed.size(),
+                                   outputRegion.mStorage, direction_LTR);
+    outputRegion.mStorage.push_back(
+            r.getBounds()); // to make region valid, mStorage must end with bounds
 
 #if defined(VALIDATE_REGIONS)
     validate(outputRegion, "T-Junction free region");
@@ -222,7 +224,8 @@
     validate(*this, "this->operator=");
     validate(rhs, "rhs.operator=");
 #endif
-    mStorage = rhs.mStorage;
+    mStorage.clear();
+    mStorage.insert(mStorage.begin(), rhs.mStorage.begin(), rhs.mStorage.end());
     return *this;
 }
 
@@ -231,7 +234,7 @@
     if (mStorage.size() >= 2) {
         const Rect bounds(getBounds());
         mStorage.clear();
-        mStorage.add(bounds);
+        mStorage.push_back(bounds);
     }
     return *this;
 }
@@ -255,25 +258,25 @@
 void Region::clear()
 {
     mStorage.clear();
-    mStorage.add(Rect(0,0));
+    mStorage.push_back(Rect(0, 0));
 }
 
 void Region::set(const Rect& r)
 {
     mStorage.clear();
-    mStorage.add(r);
+    mStorage.push_back(r);
 }
 
 void Region::set(int32_t w, int32_t h)
 {
     mStorage.clear();
-    mStorage.add(Rect(w, h));
+    mStorage.push_back(Rect(w, h));
 }
 
 void Region::set(uint32_t w, uint32_t h)
 {
     mStorage.clear();
-    mStorage.add(Rect(w, h));
+    mStorage.push_back(Rect(w, h));
 }
 
 bool Region::isTriviallyEqual(const Region& region) const {
@@ -299,8 +302,7 @@
 void Region::addRectUnchecked(int l, int t, int r, int b)
 {
     Rect rect(l,t,r,b);
-    size_t where = mStorage.size() - 1;
-    mStorage.insertAt(rect, where, 1);
+    mStorage.insert(mStorage.end() - 1, rect);
 }
 
 // ----------------------------------------------------------------------------
@@ -350,7 +352,7 @@
 
 Region& Region::scaleSelf(float sx, float sy) {
     size_t count = mStorage.size();
-    Rect* rects = mStorage.editArray();
+    Rect* rects = mStorage.data();
     while (count) {
         rects->left = static_cast<int32_t>(static_cast<float>(rects->left) * sx + 0.5f);
         rects->right = static_cast<int32_t>(static_cast<float>(rects->right) * sx + 0.5f);
@@ -455,10 +457,10 @@
 class Region::rasterizer : public region_operator<Rect>::region_rasterizer
 {
     Rect bounds;
-    Vector<Rect>& storage;
+    FatVector<Rect>& storage;
     Rect* head;
     Rect* tail;
-    Vector<Rect> span;
+    FatVector<Rect> span;
     Rect* cur;
 public:
     explicit rasterizer(Region& reg)
@@ -485,8 +487,8 @@
         flushSpan();
     }
     if (storage.size()) {
-        bounds.top = storage.itemAt(0).top;
-        bounds.bottom = storage.top().bottom;
+        bounds.top = storage.front().top;
+        bounds.bottom = storage.back().bottom;
         if (storage.size() == 1) {
             storage.clear();
         }
@@ -494,7 +496,7 @@
         bounds.left  = 0;
         bounds.right = 0;
     }
-    storage.add(bounds);
+    storage.push_back(bounds);
 }
 
 void Region::rasterizer::operator()(const Rect& rect)
@@ -509,15 +511,15 @@
             return;
         }
     }
-    span.add(rect);
-    cur = span.editArray() + (span.size() - 1);
+    span.push_back(rect);
+    cur = span.data() + (span.size() - 1);
 }
 
 void Region::rasterizer::flushSpan()
 {
     bool merge = false;
     if (tail-head == ssize_t(span.size())) {
-        Rect const* p = span.editArray();
+        Rect const* p = span.data();
         Rect const* q = head;
         if (p->top == q->bottom) {
             merge = true;
@@ -532,17 +534,17 @@
         }
     }
     if (merge) {
-        const int bottom = span[0].bottom;
+        const int bottom = span.front().bottom;
         Rect* r = head;
         while (r != tail) {
             r->bottom = bottom;
             r++;
         }
     } else {
-        bounds.left = min(span.itemAt(0).left, bounds.left);
-        bounds.right = max(span.top().right, bounds.right);
-        storage.appendVector(span);
-        tail = storage.editArray() + storage.size();
+        bounds.left = min(span.front().left, bounds.left);
+        bounds.right = max(span.back().right, bounds.right);
+        storage.insert(storage.end(), span.begin(), span.end());
+        tail = storage.data() + storage.size();
         head = tail - span.size();
     }
     span.clear();
@@ -550,7 +552,7 @@
 
 bool Region::validate(const Region& reg, const char* name, bool silent)
 {
-    if (reg.mStorage.isEmpty()) {
+    if (reg.mStorage.empty()) {
         ALOGE_IF(!silent, "%s: mStorage is empty, which is never valid", name);
         // return immediately as the code below assumes mStorage is non-empty
         return false;
@@ -689,9 +691,8 @@
     }
     sk_dst.op(sk_lhs, sk_rhs, sk_op);
 
-    if (sk_dst.isEmpty() && dst.isEmpty())
-        return;
-    
+    if (sk_dst.empty() && dst.empty()) return;
+
     bool same = true;
     Region::const_iterator head = dst.begin();
     Region::const_iterator const tail = dst.end();
@@ -786,7 +787,7 @@
         validate(reg, "translate (before)");
 #endif
         size_t count = reg.mStorage.size();
-        Rect* rects = reg.mStorage.editArray();
+        Rect* rects = reg.mStorage.data();
         while (count) {
             rects->offsetBy(dx, dy);
             rects++;
@@ -866,24 +867,25 @@
         ALOGE("Region::unflatten() failed, invalid region");
         return BAD_VALUE;
     }
-    mStorage = result.mStorage;
+    mStorage.clear();
+    mStorage.insert(mStorage.begin(), result.mStorage.begin(), result.mStorage.end());
     return NO_ERROR;
 }
 
 // ----------------------------------------------------------------------------
 
 Region::const_iterator Region::begin() const {
-    return mStorage.array();
+    return mStorage.data();
 }
 
 Region::const_iterator Region::end() const {
     // Workaround for b/77643177
     // mStorage should never be empty, but somehow it is and it's causing
     // an abort in ubsan
-    if (mStorage.isEmpty()) return mStorage.array();
+    if (mStorage.empty()) return mStorage.data();
 
     size_t numRects = isRect() ? 1 : mStorage.size() - 1;
-    return mStorage.array() + numRects;
+    return mStorage.data() + numRects;
 }
 
 Rect const* Region::getArray(size_t* count) const {
diff --git a/libs/ui/include/ui/FatVector.h b/libs/ui/include/ui/FatVector.h
new file mode 100644
index 0000000..25fe3a0
--- /dev/null
+++ b/libs/ui/include/ui/FatVector.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2019, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_REGION_FAT_VECTOR_H
+#define ANDROID_REGION_FAT_VECTOR_H
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <utils/Log.h>
+#include <type_traits>
+
+#include <vector>
+
+namespace android {
+
+template <typename T, size_t SIZE = 4>
+class InlineStdAllocator {
+public:
+    struct Allocation {
+    private:
+        Allocation(const Allocation&) = delete;
+        void operator=(const Allocation&) = delete;
+
+    public:
+        Allocation() {}
+        // char array instead of T array, so memory is uninitialized, with no destructors run
+        char array[sizeof(T) * SIZE];
+        bool inUse = false;
+    };
+
+    typedef T value_type; // needed to implement std::allocator
+    typedef T* pointer;   // needed to implement std::allocator
+
+    explicit InlineStdAllocator(Allocation& allocation) : mAllocation(allocation) {}
+    InlineStdAllocator(const InlineStdAllocator& other) : mAllocation(other.mAllocation) {}
+    ~InlineStdAllocator() {}
+
+    T* allocate(size_t num, const void* = 0) {
+        if (!mAllocation.inUse && num <= SIZE) {
+            mAllocation.inUse = true;
+            return static_cast<T*>(static_cast<void*>(mAllocation.array));
+        } else {
+            return static_cast<T*>(static_cast<void*>(malloc(num * sizeof(T))));
+        }
+    }
+
+    void deallocate(pointer p, size_t) {
+        if (p == static_cast<T*>(static_cast<void*>(mAllocation.array))) {
+            mAllocation.inUse = false;
+        } else {
+            // 'free' instead of delete here - destruction handled separately
+            free(p);
+        }
+    }
+    Allocation& mAllocation;
+};
+
+/**
+ * std::vector with SIZE elements preallocated into an internal buffer.
+ *
+ * Useful for avoiding the cost of malloc in cases where only SIZE or
+ * fewer elements are needed in the common case.
+ */
+template <typename T, size_t SIZE = 4>
+class FatVector : public std::vector<T, InlineStdAllocator<T, SIZE>> {
+public:
+    FatVector()
+          : std::vector<T, InlineStdAllocator<T, SIZE>>(InlineStdAllocator<T, SIZE>(mAllocation)) {
+        this->reserve(SIZE);
+    }
+
+    explicit FatVector(size_t capacity) : FatVector() { this->resize(capacity); }
+
+private:
+    typename InlineStdAllocator<T, SIZE>::Allocation mAllocation;
+};
+
+} // namespace android
+
+#endif // ANDROID_REGION_FAT_VECTOR_H
diff --git a/libs/ui/include/ui/Region.h b/libs/ui/include/ui/Region.h
index 2db3b10..6bb7b8d 100644
--- a/libs/ui/include/ui/Region.h
+++ b/libs/ui/include/ui/Region.h
@@ -21,13 +21,13 @@
 #include <sys/types.h>
 #include <ostream>
 
-#include <utils/Vector.h>
-
 #include <ui/Rect.h>
 #include <utils/Flattenable.h>
 
 #include <android-base/macros.h>
 
+#include "FatVector.h"
+
 #include <string>
 
 namespace android {
@@ -180,7 +180,7 @@
     // with an extra Rect as the last element which is set to the
     // bounds of the region. However, if the region is
     // a simple Rect then mStorage contains only that rect.
-    Vector<Rect> mStorage;
+    FatVector<Rect> mStorage;
 };
 
 
@@ -235,4 +235,3 @@
 }; // namespace android
 
 #endif // ANDROID_UI_REGION_H
-
diff --git a/libs/ui/include_vndk/ui/FatVector.h b/libs/ui/include_vndk/ui/FatVector.h
new file mode 120000
index 0000000..bf30166
--- /dev/null
+++ b/libs/ui/include_vndk/ui/FatVector.h
@@ -0,0 +1 @@
+../../include/ui/FatVector.h
\ No newline at end of file
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index adecb8d..94791eb 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -108,7 +108,8 @@
         mUseContentDetectionV2(useContentDetectionV2) {
     using namespace sysprop;
 
-    if (property_get_bool("debug.sf.use_smart_90_for_video", 0) || use_smart_90_for_video(false)) {
+    if (property_get_bool("debug.sf.use_content_detection_for_refresh_rate", 0) ||
+        use_content_detection_for_refresh_rate(false)) {
         if (mUseContentDetectionV2) {
             mLayerHistory = std::make_unique<scheduler::impl::LayerHistoryV2>();
         } else {
diff --git a/services/surfaceflinger/SurfaceFlingerProperties.cpp b/services/surfaceflinger/SurfaceFlingerProperties.cpp
index e199b53..269cf94 100644
--- a/services/surfaceflinger/SurfaceFlingerProperties.cpp
+++ b/services/surfaceflinger/SurfaceFlingerProperties.cpp
@@ -18,6 +18,7 @@
 #include <android/hardware/configstore/1.1/ISurfaceFlingerConfigs.h>
 #include <android/hardware/configstore/1.1/types.h>
 #include <configstore/Utils.h>
+#include <utils/Log.h>
 
 #include <log/log.h>
 #include <cstdlib>
@@ -263,8 +264,17 @@
     return defaultValue;
 }
 
-bool use_smart_90_for_video(bool defaultValue) {
-    auto temp = SurfaceFlingerProperties::use_smart_90_for_video();
+bool use_content_detection_for_refresh_rate(bool defaultValue) {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+    auto smart_90_deprecated = SurfaceFlingerProperties::use_smart_90_for_video();
+#pragma clang diagnostic pop
+    if (smart_90_deprecated.has_value()) {
+        ALOGW("Using deprecated use_smart_90_for_video sysprop. Value: %d", *smart_90_deprecated);
+        return *smart_90_deprecated;
+    }
+
+    auto temp = SurfaceFlingerProperties::use_content_detection_for_refresh_rate();
     if (temp.has_value()) {
         return *temp;
     }
diff --git a/services/surfaceflinger/SurfaceFlingerProperties.h b/services/surfaceflinger/SurfaceFlingerProperties.h
index e394cca..440df49 100644
--- a/services/surfaceflinger/SurfaceFlingerProperties.h
+++ b/services/surfaceflinger/SurfaceFlingerProperties.h
@@ -81,7 +81,7 @@
 
 int32_t set_display_power_timer_ms(int32_t defaultValue);
 
-bool use_smart_90_for_video(bool defaultValue);
+bool use_content_detection_for_refresh_rate(bool defaultValue);
 
 bool enable_protected_contents(bool defaultValue);
 
diff --git a/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop b/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop
index 764181a..71f8d6a 100644
--- a/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop
+++ b/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop
@@ -345,14 +345,26 @@
     prop_name: "ro.surface_flinger.set_display_power_timer_ms"
 }
 
+# useContentDetectionForRefreshRate indicates whether Scheduler should detect content FPS, and try
+# to adjust the screen refresh rate based on that.
+prop {
+    api_name: "use_content_detection_for_refresh_rate"
+    type: Boolean
+    scope: Public
+    access: Readonly
+    prop_name: "ro.surface_flinger.use_content_detection_for_refresh_rate"
+}
+
 # useSmart90ForVideo indicates whether Scheduler should detect content FPS, and try to adjust the
 # screen refresh rate based on that.
+# Replaced by useContentDetectionForRefreshRate
 prop {
     api_name: "use_smart_90_for_video"
     type: Boolean
     scope: Public
     access: Readonly
     prop_name: "ro.surface_flinger.use_smart_90_for_video"
+    deprecated: true
 }
 
 prop {
diff --git a/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-current.txt b/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-current.txt
index bee99f4..cdfd0f5 100644
--- a/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-current.txt
+++ b/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-current.txt
@@ -113,12 +113,17 @@
     prop_name: "ro.surface_flinger.use_color_management"
   }
   prop {
+    api_name: "use_content_detection_for_refresh_rate"
+    prop_name: "ro.surface_flinger.use_content_detection_for_refresh_rate"
+  }
+  prop {
     api_name: "use_context_priority"
     prop_name: "ro.surface_flinger.use_context_priority"
   }
   prop {
     api_name: "use_smart_90_for_video"
     prop_name: "ro.surface_flinger.use_smart_90_for_video"
+    deprecated: true
   }
   prop {
     api_name: "use_vr_flinger"