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"