Merge "Plumb FrameEventHistory to client"
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index f8b2fdb..312db67 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -156,6 +156,7 @@
#define WMTRACE_DATA_DIR "/data/misc/wmtrace"
#define OTA_METADATA_DIR "/metadata/ota"
#define SNAPSHOTCTL_LOG_DIR "/data/misc/snapshotctl_log"
+#define LINKERCONFIG_DIR "/linkerconfig"
// TODO(narayan): Since this information has to be kept in sync
// with tombstoned, we should just put it in a common header.
@@ -1533,6 +1534,9 @@
// This differs from the usual dumpsys stats, which is the stats report data.
RunDumpsys("STATSDSTATS", {"stats", "--metadata"});
+ // Add linker configuration directory
+ ds.AddDir(LINKERCONFIG_DIR, true);
+
RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(DumpIncidentReport);
return Dumpstate::RunStatus::OK;
diff --git a/cmds/installd/TEST_MAPPING b/cmds/installd/TEST_MAPPING
index 287f2d9..c6583a1 100644
--- a/cmds/installd/TEST_MAPPING
+++ b/cmds/installd/TEST_MAPPING
@@ -15,6 +15,10 @@
{
"name": "installd_utils_test"
},
+ // AdoptableHostTest moves packages, part of which is handled by installd
+ {
+ "name": "AdoptableHostTest"
+ },
{
"name": "CtsUsesLibraryHostTestCases"
},
diff --git a/include/android/imagedecoder.h b/include/android/imagedecoder.h
index 0d943b7..6e5da52 100644
--- a/include/android/imagedecoder.h
+++ b/include/android/imagedecoder.h
@@ -15,12 +15,24 @@
*/
/**
- * @addtogroup ImageDecoder
+ * @defgroup ImageDecoder
+ *
+ * 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
+ * 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>
+ * developer guide.
* @{
*/
/**
- * @file imageDecoder.h
+ * @file imagedecoder.h
+ * @brief API for decoding images.
*/
#ifndef ANDROID_IMAGE_DECODER_H
@@ -38,32 +50,54 @@
#if __ANDROID_API__ >= 30
-/** AImageDecoder functions result code. */
+/**
+ * {@link AImageDecoder} functions result code. Many functions will return one of these
+ * to indicate success ({@link ANDROID_IMAGE_DECODER_SUCCESS}) or the reason
+ * for the failure. On failure, any out-parameters should be considered
+ * uninitialized, except where specified.
+ */
enum {
- // Decoding was successful and complete.
+ /**
+ * Decoding was successful and complete.
+ */
ANDROID_IMAGE_DECODER_SUCCESS = 0,
- // The input was incomplete. In decodeImage, this means a partial
- // image was decoded. Undecoded lines are all zeroes.
- // In AImageDecoder_create*, no AImageDecoder was created.
+ /**
+ * The input was incomplete.
+ */
ANDROID_IMAGE_DECODER_INCOMPLETE = -1,
- // The input contained an error after decoding some lines. Similar to
- // INCOMPLETE, above.
+ /**
+ * The input contained an error after decoding some lines.
+ */
ANDROID_IMAGE_DECODER_ERROR = -2,
- // Could not convert, e.g. attempting to decode an image with
- // alpha to an opaque format.
+ /**
+ * Could not convert. For example, attempting to decode an image with
+ * alpha to an opaque format.
+ */
ANDROID_IMAGE_DECODER_INVALID_CONVERSION = -3,
- // The scale is invalid. It may have overflowed, or it may be incompatible
- // with the current alpha setting.
+ /**
+ * The scale is invalid. It may have overflowed, or it may be incompatible
+ * with the current alpha setting.
+ */
ANDROID_IMAGE_DECODER_INVALID_SCALE = -4,
- // Some other parameter was bad (e.g. pixels)
+ /**
+ * Some other parameter was bad.
+ */
ANDROID_IMAGE_DECODER_BAD_PARAMETER = -5,
- // Input was invalid i.e. broken before decoding any pixels.
+ /**
+ * Input was invalid before decoding any pixels.
+ */
ANDROID_IMAGE_DECODER_INVALID_INPUT = -6,
- // A seek was required, and failed.
+ /**
+ * A seek was required and it failed.
+ */
ANDROID_IMAGE_DECODER_SEEK_ERROR = -7,
- // Some other error (e.g. OOM)
+ /**
+ * Some other error. For example, an internal allocation failed.
+ */
ANDROID_IMAGE_DECODER_INTERNAL_ERROR = -8,
- // We did not recognize the format
+ /**
+ * AImageDecoder did not recognize the format.
+ */
ANDROID_IMAGE_DECODER_UNSUPPORTED_FORMAT = -9
};
@@ -76,36 +110,45 @@
* - {@link AImageDecoder_createFromAAsset}
* - {@link AImageDecoder_createFromFd}
* - {@link AImageDecoder_createFromBuffer}
+ *
+ * After creation, {@link AImageDecoder_getHeaderInfo} can be used to retrieve
+ * information about the encoded image. Other functions, like
+ * {@link AImageDecoder_setTargetSize}, can be used to specify how to decode, and
+ * {@link AImageDecoder_decode} will decode into client provided memory.
+ *
+ * {@link AImageDecoder} objects are NOT thread-safe, and should not be shared across
+ * threads.
*/
typedef struct AImageDecoder AImageDecoder;
/**
- * Create a new AImageDecoder from an AAsset.
+ * Create a new {@link AImageDecoder} from an {@link AAsset}.
*
* @param asset {@link AAsset} containing encoded image data. Client is still
- * responsible for calling {@link AAsset_close} on it.
+ * responsible for calling {@link AAsset_close} on it, which may be
+ * done after deleting the returned {@link AImageDecoder}.
* @param outDecoder On success (i.e. return value is
* {@link ANDROID_IMAGE_DECODER_SUCCESS}), this will be set to
* 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.
*/
int AImageDecoder_createFromAAsset(struct AAsset* asset, AImageDecoder** outDecoder)
__INTRODUCED_IN(30);
/**
- * Create a new AImageDecoder from a file descriptor.
+ * Create a new {@link AImageDecoder} from a file descriptor.
*
* @param fd Seekable, readable, open file descriptor for encoded data.
* Client is still responsible for closing it, which may be done
- * *after* deleting the returned AImageDecoder.
+ * after deleting the returned {@link AImageDecoder}.
* @param outDecoder On success (i.e. return value is
* {@link ANDROID_IMAGE_DECODER_SUCCESS}), this will be set to
* 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.
*/
int AImageDecoder_createFromFd(int fd, AImageDecoder** outDecoder) __INTRODUCED_IN(30);
@@ -113,7 +156,7 @@
* Create a new AImageDecoder from a buffer.
*
* @param buffer Pointer to encoded data. Must be valid for the entire time
- * the AImageDecoder is used.
+ * the {@link AImageDecoder} is used.
* @param length Byte length of buffer.
* @param outDecoder On success (i.e. return value is
* {@link ANDROID_IMAGE_DECODER_SUCCESS}), this will be set to
@@ -136,7 +179,7 @@
* @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 AImageDecoder uses the
+ * 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).
*/
@@ -146,23 +189,25 @@
/**
* Specify whether the output's pixels should be unpremultiplied.
*
- * By default, the decoder will premultiply the pixels, if they have alpha. Pass
- * false to this method to leave them unpremultiplied. This has no effect on an
+ * By default, {@link AImageDecoder_decodeImage} will premultiply the pixels, if they have alpha.
+ * Pass true to this method to leave them unpremultiplied. This has no effect on an
* opaque image.
*
- * @param required Pass true to leave the pixels unpremultiplied.
- * @return - {@link ANDROID_IMAGE_DECODER_SUCCESS} on success
+ * @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
*/
-int AImageDecoder_setUnpremultipliedRequired(AImageDecoder*, bool required) __INTRODUCED_IN(30);
+int AImageDecoder_setUnpremultipliedRequired(AImageDecoder*,
+ bool unpremultipliedRequired) __INTRODUCED_IN(30);
/**
* Choose the dataspace for the output.
*
- * Not supported for {@link ANDROID_BITMAP_FORMAT_A_8}, which does not support
- * an ADataSpace.
+ * Ignored by {@link ANDROID_BITMAP_FORMAT_A_8}, which does not support
+ * an {@link ADataSpace}.
*
* @param dataspace The {@link ADataSpace} to decode into. An ADataSpace
* specifies how to interpret the colors. By default,
@@ -170,10 +215,10 @@
* {@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
- * - {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER} for a null
- * AImageDecoder or an integer that does not correspond to an
- * ADataSpace value.
+ * @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.
*/
int AImageDecoder_setDataSpace(AImageDecoder*, int32_t dataspace) __INTRODUCED_IN(30);
@@ -191,10 +236,11 @@
* {@link AImageDecoder_getMinimumStride}, which will now return
* a value based on this width.
* @param height Height of the output (prior to cropping).
- * @return - {@link ANDROID_IMAGE_DECODER_SUCCESS} on success
- * - {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER} if the AImageDecoder
- * pointer is null, width or height is <= 0, or any existing crop is
- * not contained by the image dimensions.
+ * @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.
*/
int AImageDecoder_setTargetSize(AImageDecoder*, int32_t width, int32_t height) __INTRODUCED_IN(30);
@@ -213,10 +259,11 @@
* 1/2 of the original dimensions, with 1/4 the number of
* pixels.
* @param width Out parameter for the width sampled by sampleSize, and rounded
- * direction that the decoder can do most efficiently.
+ * in the direction that the decoder can do most efficiently.
* @param height Out parameter for the height sampled by sampleSize, and rounded
- * direction that the decoder can do most efficiently.
- * @return ANDROID_IMAGE_DECODER result code.
+ * 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.
*/
int AImageDecoder_computeSampledSize(const AImageDecoder*, int sampleSize,
int32_t* width, int32_t* height) __INTRODUCED_IN(30);
@@ -234,18 +281,21 @@
* value based on the width of the crop. An empty ARect -
* specifically { 0, 0, 0, 0 } - may be used to remove the cropping
* behavior. Any other empty or unsorted ARects will result in
- * returning ANDROID_IMAGE_DECODER_BAD_PARAMETER.
- * @return - {@link ANDROID_IMAGE_DECODER_SUCCESS} on success
- * - {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER} if the AImageDecoder
- * pointer is null or the crop is not contained by the image
- * dimensions.
+ * 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.
*/
int AImageDecoder_setCrop(AImageDecoder*, ARect crop) __INTRODUCED_IN(30);
-/**
- * Opaque handle for reading header info.
- */
struct AImageDecoderHeaderInfo;
+/**
+ * Opaque handle for representing information about the encoded image. It can
+ * be passed to methods like {@link AImageDecoderHeaderInfo_getWidth} and
+ * {@link AImageDecoderHeaderInfo_getHeight}.
+ */
typedef struct AImageDecoderHeaderInfo AImageDecoderHeaderInfo;
/**
@@ -258,12 +308,16 @@
const AImageDecoder*) __INTRODUCED_IN(30);
/**
- * Report the native width of the encoded image.
+ * 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.
*/
int32_t AImageDecoderHeaderInfo_getWidth(const AImageDecoderHeaderInfo*) __INTRODUCED_IN(30);
/**
- * Report the native height of the encoded image.
+ * 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.
*/
int32_t AImageDecoderHeaderInfo_getHeight(const AImageDecoderHeaderInfo*) __INTRODUCED_IN(30);
@@ -277,7 +331,7 @@
/**
* Report the {@link AndroidBitmapFormat} the AImageDecoder will decode to
- * by default. AImageDecoder will try to choose one that is sensible
+ * by default. {@link AImageDecoder} will try to choose one that is sensible
* for the image and the system. Note that this does not indicate the
* encoded format of the image.
*/
@@ -285,18 +339,17 @@
const AImageDecoderHeaderInfo*) __INTRODUCED_IN(30);
/**
- * Report how the AImageDecoder will handle alpha by default. If the image
+ * Report how the {@link AImageDecoder} will handle alpha by default. If the image
* contains no alpha (according to its header), this will return
* {@link ANDROID_BITMAP_FLAGS_ALPHA_OPAQUE}. If the image may contain alpha,
- * this returns {@link ANDROID_BITMAP_FLAGS_ALPHA_PREMUL}.
- *
- * For animated images only the opacity of the first frame is reported.
+ * this returns {@link ANDROID_BITMAP_FLAGS_ALPHA_PREMUL}, because
+ * {@link AImageDecoder_decodeImage} will premultiply pixels by default.
*/
int AImageDecoderHeaderInfo_getAlphaFlags(
const AImageDecoderHeaderInfo*) __INTRODUCED_IN(30);
/**
- * Report the dataspace the AImageDecoder will decode to by default.
+ * 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.
@@ -315,26 +368,35 @@
const AImageDecoderHeaderInfo*) __INTRODUCED_IN(30);
/**
- * Return the minimum stride that can be used, taking the specified
- * (or default) (possibly scaled) width, crop rect and
- * {@link AndroidBitmapFormat} into account.
+ * Return the minimum stride that can be used in
+ * {@link AImageDecoder_decodeImage).
+ *
+ * This stride provides no padding, meaning it will be exactly equal to the
+ * width times the number of bytes per pixel for the {@link AndroidBitmapFormat}
+ * being used.
+ *
+ * If the output is scaled (via {@link AImageDecoder_setTargetSize}) and/or
+ * cropped (via {@link AImageDecoder_setCrop}), this takes those into account.
*/
size_t AImageDecoder_getMinimumStride(AImageDecoder*) __INTRODUCED_IN(30);
/**
- * Decode the image into pixels, using the settings of the AImageDecoder.
+ * Decode the image into pixels, using the settings of the {@link AImageDecoder}.
*
* @param decoder Opaque object representing the decoder.
* @param pixels On success, will be filled with the result
- * of the decode. Must be large enough to fit |size| bytes.
+ * of the decode. Must be large enough to hold |size| bytes.
* @param stride Width in bytes of a single row. Must be at least
- * {@link AImageDecoder_getMinimumStride}.
+ * {@link AImageDecoder_getMinimumStride} and a multiple of the
+ * bytes per pixel of the {@link AndroidBitmapFormat}.
* @param size Size of the pixel buffer in bytes. Must be at least
* stride * (height - 1) +
- * {@link AImageDecoder_getMinimumStride}. Must also be a multiple
- * of the bytes per pixel of the {@link AndroidBitmapFormat}.
+ * {@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.
*/
int AImageDecoder_decodeImage(AImageDecoder* decoder,
void* pixels, size_t stride,
diff --git a/services/gpuservice/tests/unittests/GpuStatsTest.cpp b/services/gpuservice/tests/unittests/GpuStatsTest.cpp
index 276a334..f038c8a 100644
--- a/services/gpuservice/tests/unittests/GpuStatsTest.cpp
+++ b/services/gpuservice/tests/unittests/GpuStatsTest.cpp
@@ -39,8 +39,6 @@
#define UPDATED_DRIVER_VER_CODE 1
#define UPDATED_DRIVER_BUILD_TIME 234
#define VULKAN_VERSION 345
-#define CPU_VULKAN_VERSION 456
-#define OPENGLES_VERSION 567
#define APP_PKG_NAME_1 "testapp1"
#define APP_PKG_NAME_2 "testapp2"
#define DRIVER_LOADING_TIME_1 678
@@ -74,10 +72,8 @@
std::string inputCommand(InputCommand cmd);
void SetUp() override {
- property_set("ro.cpuvulkan.version", std::to_string(CPU_VULKAN_VERSION).c_str());
- property_set("ro.opengles.version", std::to_string(OPENGLES_VERSION).c_str());
- mCpuVulkanVersion = property_get_int32("ro.cpuvulkan.version", CPU_VULKAN_VERSION);
- mGlesVersion = property_get_int32("ro.opengles.version", OPENGLES_VERSION);
+ mCpuVulkanVersion = property_get_int32("ro.cpuvulkan.version", 0);
+ mGlesVersion = property_get_int32("ro.opengles.version", 0);
}
std::unique_ptr<GpuStats> mGpuStats = std::make_unique<GpuStats>();
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index b2b5145..f2b95e7 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -2686,6 +2686,19 @@
connection->getInputChannelName().c_str(), cancelationEvents.size(), options.reason,
options.mode);
#endif
+
+ InputTarget target;
+ sp<InputWindowHandle> windowHandle =
+ getWindowHandleLocked(connection->inputChannel->getConnectionToken());
+ if (windowHandle != nullptr) {
+ const InputWindowInfo* windowInfo = windowHandle->getInfo();
+ target.setDefaultPointerInfo(-windowInfo->frameLeft, -windowInfo->frameTop,
+ windowInfo->windowXScale, windowInfo->windowYScale);
+ target.globalScaleFactor = windowInfo->globalScaleFactor;
+ }
+ target.inputChannel = connection->inputChannel;
+ target.flags = InputTarget::FLAG_DISPATCH_AS_IS;
+
for (size_t i = 0; i < cancelationEvents.size(); i++) {
EventEntry* cancelationEventEntry = cancelationEvents[i];
switch (cancelationEventEntry->type) {
@@ -2711,18 +2724,6 @@
}
}
- InputTarget target;
- sp<InputWindowHandle> windowHandle =
- getWindowHandleLocked(connection->inputChannel->getConnectionToken());
- if (windowHandle != nullptr) {
- const InputWindowInfo* windowInfo = windowHandle->getInfo();
- target.setDefaultPointerInfo(-windowInfo->frameLeft, -windowInfo->frameTop,
- windowInfo->windowXScale, windowInfo->windowYScale);
- target.globalScaleFactor = windowInfo->globalScaleFactor;
- }
- target.inputChannel = connection->inputChannel;
- target.flags = InputTarget::FLAG_DISPATCH_AS_IS;
-
enqueueDispatchEntryLocked(connection, cancelationEventEntry, // increments ref
target, InputTarget::FLAG_DISPATCH_AS_IS);
@@ -2732,6 +2733,65 @@
startDispatchCycleLocked(currentTime, connection);
}
+void InputDispatcher::synthesizePointerDownEventsForConnectionLocked(
+ const sp<Connection>& connection) {
+ if (connection->status == Connection::STATUS_BROKEN) {
+ return;
+ }
+
+ nsecs_t currentTime = now();
+
+ std::vector<EventEntry*> downEvents =
+ connection->inputState.synthesizePointerDownEvents(currentTime);
+
+ if (downEvents.empty()) {
+ return;
+ }
+
+#if DEBUG_OUTBOUND_EVENT_DETAILS
+ ALOGD("channel '%s' ~ Synthesized %zu down events to ensure consistent event stream.",
+ connection->getInputChannelName().c_str(), downEvents.size());
+#endif
+
+ InputTarget target;
+ sp<InputWindowHandle> windowHandle =
+ getWindowHandleLocked(connection->inputChannel->getConnectionToken());
+ if (windowHandle != nullptr) {
+ const InputWindowInfo* windowInfo = windowHandle->getInfo();
+ target.setDefaultPointerInfo(-windowInfo->frameLeft, -windowInfo->frameTop,
+ windowInfo->windowXScale, windowInfo->windowYScale);
+ target.globalScaleFactor = windowInfo->globalScaleFactor;
+ }
+ target.inputChannel = connection->inputChannel;
+ target.flags = InputTarget::FLAG_DISPATCH_AS_IS;
+
+ for (EventEntry* downEventEntry : downEvents) {
+ switch (downEventEntry->type) {
+ case EventEntry::Type::MOTION: {
+ logOutboundMotionDetails("down - ",
+ static_cast<const MotionEntry&>(*downEventEntry));
+ break;
+ }
+
+ case EventEntry::Type::KEY:
+ case EventEntry::Type::FOCUS:
+ case EventEntry::Type::CONFIGURATION_CHANGED:
+ case EventEntry::Type::DEVICE_RESET: {
+ LOG_ALWAYS_FATAL("%s event should not be found inside Connections's queue",
+ EventEntry::typeToString(downEventEntry->type));
+ break;
+ }
+ }
+
+ enqueueDispatchEntryLocked(connection, downEventEntry, // increments ref
+ target, InputTarget::FLAG_DISPATCH_AS_IS);
+
+ downEventEntry->release();
+ }
+
+ startDispatchCycleLocked(currentTime, connection);
+}
+
MotionEntry* InputDispatcher::splitMotionEvent(const MotionEntry& originalMotionEntry,
BitSet32 pointerIds) {
ALOG_ASSERT(pointerIds.value != 0);
@@ -3770,11 +3830,12 @@
sp<Connection> fromConnection = getConnectionLocked(fromToken);
sp<Connection> toConnection = getConnectionLocked(toToken);
if (fromConnection != nullptr && toConnection != nullptr) {
- fromConnection->inputState.copyPointerStateTo(toConnection->inputState);
+ fromConnection->inputState.mergePointerStateTo(toConnection->inputState);
CancelationOptions
options(CancelationOptions::CANCEL_POINTER_EVENTS,
"transferring touch focus from this window to another window");
synthesizeCancelationEventsForConnectionLocked(fromConnection, options);
+ synthesizePointerDownEventsForConnectionLocked(toConnection);
}
if (DEBUG_FOCUS) {
diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h
index 93de18d..d2aea80 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.h
+++ b/services/inputflinger/dispatcher/InputDispatcher.h
@@ -417,6 +417,9 @@
const CancelationOptions& options)
REQUIRES(mLock);
+ void synthesizePointerDownEventsForConnectionLocked(const sp<Connection>& connection)
+ REQUIRES(mLock);
+
// Splitting motion events across windows.
MotionEntry* splitMotionEvent(const MotionEntry& originalMotionEntry, BitSet32 pointerIds);
diff --git a/services/inputflinger/dispatcher/InputState.cpp b/services/inputflinger/dispatcher/InputState.cpp
index c43e304..053598a 100644
--- a/services/inputflinger/dispatcher/InputState.cpp
+++ b/services/inputflinger/dispatcher/InputState.cpp
@@ -145,10 +145,13 @@
// Joysticks and trackballs can send MOVE events without corresponding DOWN or UP.
return true;
}
+
if (index >= 0) {
MotionMemento& memento = mMotionMementos[index];
- memento.setPointers(entry);
- return true;
+ if (memento.firstNewPointerIdx < 0) {
+ memento.setPointers(entry);
+ return true;
+ }
}
#if DEBUG_OUTBOUND_EVENT_DETAILS
ALOGD("Dropping inconsistent motion pointer up/down or move event: "
@@ -249,6 +252,17 @@
}
}
+void InputState::MotionMemento::mergePointerStateTo(MotionMemento& other) const {
+ for (uint32_t i = 0; i < pointerCount; i++) {
+ if (other.firstNewPointerIdx < 0) {
+ other.firstNewPointerIdx = other.pointerCount;
+ }
+ other.pointerProperties[other.pointerCount].copyFrom(pointerProperties[i]);
+ other.pointerCoords[other.pointerCount].copyFrom(pointerCoords[i]);
+ other.pointerCount++;
+ }
+}
+
std::vector<EventEntry*> InputState::synthesizeCancelationEvents(
nsecs_t currentTime, const CancelationOptions& options) {
std::vector<EventEntry*> events;
@@ -282,27 +296,87 @@
return events;
}
+std::vector<EventEntry*> InputState::synthesizePointerDownEvents(nsecs_t currentTime) {
+ std::vector<EventEntry*> events;
+ for (MotionMemento& memento : mMotionMementos) {
+ if (!(memento.source & AINPUT_SOURCE_CLASS_POINTER)) {
+ continue;
+ }
+
+ if (memento.firstNewPointerIdx < 0) {
+ continue;
+ }
+
+ uint32_t pointerCount = 0;
+ PointerProperties pointerProperties[MAX_POINTERS];
+ PointerCoords pointerCoords[MAX_POINTERS];
+
+ // We will deliver all pointers the target already knows about
+ for (uint32_t i = 0; i < static_cast<uint32_t>(memento.firstNewPointerIdx); i++) {
+ pointerProperties[i].copyFrom(memento.pointerProperties[i]);
+ pointerCoords[i].copyFrom(memento.pointerCoords[i]);
+ pointerCount++;
+ }
+
+ // We will send explicit events for all pointers the target doesn't know about
+ for (uint32_t i = static_cast<uint32_t>(memento.firstNewPointerIdx);
+ i < memento.pointerCount; i++) {
+
+ pointerProperties[i].copyFrom(memento.pointerProperties[i]);
+ pointerCoords[i].copyFrom(memento.pointerCoords[i]);
+ pointerCount++;
+
+ // Down only if the first pointer, pointer down otherwise
+ const int32_t action = (pointerCount <= 1)
+ ? AMOTION_EVENT_ACTION_DOWN
+ : AMOTION_EVENT_ACTION_POINTER_DOWN
+ | (i << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
+
+ events.push_back(new MotionEntry(SYNTHESIZED_EVENT_SEQUENCE_NUM, currentTime,
+ memento.deviceId, memento.source, memento.displayId,
+ memento.policyFlags, action, 0 /*actionButton*/,
+ memento.flags, AMETA_NONE, 0 /*buttonState*/,
+ MotionClassification::NONE,
+ AMOTION_EVENT_EDGE_FLAG_NONE, memento.xPrecision,
+ memento.yPrecision, memento.xCursorPosition,
+ memento.yCursorPosition, memento.downTime,
+ pointerCount, pointerProperties,
+ pointerCoords, 0 /*xOffset*/, 0 /*yOffset*/));
+ }
+
+ memento.firstNewPointerIdx = INVALID_POINTER_INDEX;
+ }
+
+ return events;
+}
+
void InputState::clear() {
mKeyMementos.clear();
mMotionMementos.clear();
mFallbackKeys.clear();
}
-void InputState::copyPointerStateTo(InputState& other) const {
+void InputState::mergePointerStateTo(InputState& other) {
for (size_t i = 0; i < mMotionMementos.size(); i++) {
- const MotionMemento& memento = mMotionMementos[i];
+ MotionMemento& memento = mMotionMementos[i];
+ // Since we support split pointers we need to merge touch events
+ // from the same source + device + screen.
if (memento.source & AINPUT_SOURCE_CLASS_POINTER) {
- for (size_t j = 0; j < other.mMotionMementos.size();) {
- const MotionMemento& otherMemento = other.mMotionMementos[j];
+ bool merged = false;
+ for (size_t j = 0; j < other.mMotionMementos.size(); j++) {
+ MotionMemento& otherMemento = other.mMotionMementos[j];
if (memento.deviceId == otherMemento.deviceId &&
memento.source == otherMemento.source &&
memento.displayId == otherMemento.displayId) {
- other.mMotionMementos.erase(other.mMotionMementos.begin() + j);
- } else {
- j += 1;
+ memento.mergePointerStateTo(otherMemento);
+ merged = true;
+ break;
}
}
- other.mMotionMementos.push_back(memento);
+ if (!merged) {
+ memento.firstNewPointerIdx = 0;
+ other.mMotionMementos.push_back(memento);
+ }
}
}
}
diff --git a/services/inputflinger/dispatcher/InputState.h b/services/inputflinger/dispatcher/InputState.h
index a93f486..08266ae 100644
--- a/services/inputflinger/dispatcher/InputState.h
+++ b/services/inputflinger/dispatcher/InputState.h
@@ -24,6 +24,8 @@
namespace android::inputdispatcher {
+static constexpr int32_t INVALID_POINTER_INDEX = -1;
+
/* Tracks dispatched key and motion event state so that cancellation events can be
* synthesized when events are dropped. */
class InputState {
@@ -52,11 +54,14 @@
std::vector<EventEntry*> synthesizeCancelationEvents(nsecs_t currentTime,
const CancelationOptions& options);
+ // Synthesizes down events for the current state.
+ std::vector<EventEntry*> synthesizePointerDownEvents(nsecs_t currentTime);
+
// Clears the current state.
void clear();
- // Copies pointer-related parts of the input state to another instance.
- void copyPointerStateTo(InputState& other) const;
+ // Merges pointer-related parts of the input state into another instance.
+ void mergePointerStateTo(InputState& other);
// Gets the fallback key associated with a keycode.
// Returns -1 if none.
@@ -97,10 +102,13 @@
uint32_t pointerCount;
PointerProperties pointerProperties[MAX_POINTERS];
PointerCoords pointerCoords[MAX_POINTERS];
+ // Track for which pointers the target doesn't know about.
+ int32_t firstNewPointerIdx = INVALID_POINTER_INDEX;
bool hovering;
uint32_t policyFlags;
void setPointers(const MotionEntry& entry);
+ void mergePointerStateTo(MotionMemento& other) const;
};
std::vector<KeyMemento> mKeyMementos;
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index 094452a..27db8f5 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -594,12 +594,40 @@
expectedFlags);
}
- void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
+ void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
+ int32_t expectedFlags = 0) {
+ consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL, expectedDisplayId,
+ expectedFlags);
+ }
+
+ void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
+ int32_t expectedFlags = 0) {
+ consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_MOVE, expectedDisplayId,
+ expectedFlags);
+ }
+
+ void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
+ int32_t expectedFlags = 0) {
consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN, expectedDisplayId,
expectedFlags);
}
- void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
+ void consumeMotionPointerDown(int32_t pointerIdx,
+ int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT, int32_t expectedFlags = 0) {
+ int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN
+ | (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
+ consumeEvent(AINPUT_EVENT_TYPE_MOTION, action, expectedDisplayId, expectedFlags);
+ }
+
+ void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
+ int32_t expectedFlags = 0) {
+ int32_t action = AMOTION_EVENT_ACTION_POINTER_UP
+ | (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
+ consumeEvent(AINPUT_EVENT_TYPE_MOTION, action, expectedDisplayId, expectedFlags);
+ }
+
+ void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
+ int32_t expectedFlags = 0) {
consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_UP, expectedDisplayId,
expectedFlags);
}
@@ -923,6 +951,161 @@
0 /*expectedFlags*/);
}
+TEST_F(InputDispatcherTest, TransferTouchFocus_OnePointer) {
+ sp<FakeApplicationHandle> application = new FakeApplicationHandle();
+
+ // Create a couple of windows
+ sp<FakeWindowHandle> firstWindow = new FakeWindowHandle(application, mDispatcher,
+ "First Window", ADISPLAY_ID_DEFAULT);
+ sp<FakeWindowHandle> secondWindow = new FakeWindowHandle(application, mDispatcher,
+ "Second Window", ADISPLAY_ID_DEFAULT);
+
+ // Add the windows to the dispatcher
+ mDispatcher->setInputWindows({firstWindow, secondWindow}, ADISPLAY_ID_DEFAULT);
+
+ // Send down to the first window
+ NotifyMotionArgs downMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
+ AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT);
+ mDispatcher->notifyMotion(&downMotionArgs);
+ // Only the first window should get the down event
+ firstWindow->consumeMotionDown();
+ secondWindow->assertNoEvents();
+
+ // Transfer touch focus to the second window
+ mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
+ // The first window gets cancel and the second gets down
+ firstWindow->consumeMotionCancel();
+ secondWindow->consumeMotionDown();
+
+ // Send up event to the second window
+ NotifyMotionArgs upMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP,
+ AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT);
+ mDispatcher->notifyMotion(&upMotionArgs);
+ // The first window gets no events and the second gets up
+ firstWindow->assertNoEvents();
+ secondWindow->consumeMotionUp();
+}
+
+TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointerNoSplitTouch) {
+ sp<FakeApplicationHandle> application = new FakeApplicationHandle();
+
+ PointF touchPoint = {10, 10};
+
+ // Create a couple of windows
+ sp<FakeWindowHandle> firstWindow = new FakeWindowHandle(application, mDispatcher,
+ "First Window", ADISPLAY_ID_DEFAULT);
+ sp<FakeWindowHandle> secondWindow = new FakeWindowHandle(application, mDispatcher,
+ "Second Window", ADISPLAY_ID_DEFAULT);
+
+ // Add the windows to the dispatcher
+ mDispatcher->setInputWindows({firstWindow, secondWindow}, ADISPLAY_ID_DEFAULT);
+
+ // Send down to the first window
+ NotifyMotionArgs downMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
+ AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {touchPoint});
+ mDispatcher->notifyMotion(&downMotionArgs);
+ // Only the first window should get the down event
+ firstWindow->consumeMotionDown();
+ secondWindow->assertNoEvents();
+
+ // Send pointer down to the first window
+ NotifyMotionArgs pointerDownMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_DOWN
+ | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
+ AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint});
+ mDispatcher->notifyMotion(&pointerDownMotionArgs);
+ // Only the first window should get the pointer down event
+ firstWindow->consumeMotionPointerDown(1);
+ secondWindow->assertNoEvents();
+
+ // Transfer touch focus to the second window
+ mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
+ // The first window gets cancel and the second gets down and pointer down
+ firstWindow->consumeMotionCancel();
+ secondWindow->consumeMotionDown();
+ secondWindow->consumeMotionPointerDown(1);
+
+ // Send pointer up to the second window
+ NotifyMotionArgs pointerUpMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_UP
+ | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
+ AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint});
+ mDispatcher->notifyMotion(&pointerUpMotionArgs);
+ // The first window gets nothing and the second gets pointer up
+ firstWindow->assertNoEvents();
+ secondWindow->consumeMotionPointerUp(1);
+
+ // Send up event to the second window
+ NotifyMotionArgs upMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP,
+ AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT);
+ mDispatcher->notifyMotion(&upMotionArgs);
+ // The first window gets nothing and the second gets up
+ firstWindow->assertNoEvents();
+ secondWindow->consumeMotionUp();
+}
+
+TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
+ sp<FakeApplicationHandle> application = new FakeApplicationHandle();
+
+ // Create a non touch modal window that supports split touch
+ sp<FakeWindowHandle> firstWindow = new FakeWindowHandle(application, mDispatcher,
+ "First Window", ADISPLAY_ID_DEFAULT);
+ firstWindow->setFrame(Rect(0, 0, 600, 400));
+ firstWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL
+ | InputWindowInfo::FLAG_SPLIT_TOUCH);
+
+ // Create a non touch modal window that supports split touch
+ sp<FakeWindowHandle> secondWindow = new FakeWindowHandle(application, mDispatcher,
+ "Second Window", ADISPLAY_ID_DEFAULT);
+ secondWindow->setFrame(Rect(0, 400, 600, 800));
+ secondWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL
+ | InputWindowInfo::FLAG_SPLIT_TOUCH);
+
+ // Add the windows to the dispatcher
+ mDispatcher->setInputWindows({firstWindow, secondWindow}, ADISPLAY_ID_DEFAULT);
+
+ PointF pointInFirst = {300, 200};
+ PointF pointInSecond = {300, 600};
+
+ // Send down to the first window
+ NotifyMotionArgs firstDownMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
+ AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {pointInFirst});
+ mDispatcher->notifyMotion(&firstDownMotionArgs);
+ // Only the first window should get the down event
+ firstWindow->consumeMotionDown();
+ secondWindow->assertNoEvents();
+
+ // Send down to the second window
+ NotifyMotionArgs secondDownMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_DOWN
+ | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
+ AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {pointInFirst, pointInSecond});
+ mDispatcher->notifyMotion(&secondDownMotionArgs);
+ // The first window gets a move and the second a down
+ firstWindow->consumeMotionMove();
+ secondWindow->consumeMotionDown();
+
+ // Transfer touch focus to the second window
+ mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
+ // The first window gets cancel and the new gets pointer down (it already saw down)
+ firstWindow->consumeMotionCancel();
+ secondWindow->consumeMotionPointerDown(1);
+
+ // Send pointer up to the second window
+ NotifyMotionArgs pointerUpMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_UP
+ | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
+ AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {pointInFirst, pointInSecond});
+ mDispatcher->notifyMotion(&pointerUpMotionArgs);
+ // The first window gets nothing and the second gets pointer up
+ firstWindow->assertNoEvents();
+ secondWindow->consumeMotionPointerUp(1);
+
+ // Send up event to the second window
+ NotifyMotionArgs upMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP,
+ AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT);
+ mDispatcher->notifyMotion(&upMotionArgs);
+ // The first window gets nothing and the second gets up
+ firstWindow->assertNoEvents();
+ secondWindow->consumeMotionUp();
+}
+
TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
sp<FakeApplicationHandle> application = new FakeApplicationHandle();
sp<FakeWindowHandle> window =
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index f8769c0..923a81c 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -158,6 +158,8 @@
!mLayerDetached;
}
+/* TODO: vhau uncomment once deferred transaction migration complete in
+ * WindowManager
void BufferStateLayer::pushPendingState() {
if (!mCurrentState.modified) {
return;
@@ -165,13 +167,12 @@
mPendingStates.push_back(mCurrentState);
ATRACE_INT(mTransactionName.c_str(), mPendingStates.size());
}
+*/
bool BufferStateLayer::applyPendingStates(Layer::State* stateToCommit) {
- const bool stateUpdateAvailable = !mPendingStates.empty();
- while (!mPendingStates.empty()) {
- popPendingState(stateToCommit);
- }
- mCurrentStateModified = stateUpdateAvailable && mCurrentState.modified;
+ mCurrentStateModified = mCurrentState.modified;
+ bool stateUpdateAvailable = Layer::applyPendingStates(stateToCommit);
+ mCurrentStateModified = stateUpdateAvailable && mCurrentStateModified;
mCurrentState.modified = false;
return stateUpdateAvailable;
}
diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h
index 8e22215..6ee5802 100644
--- a/services/surfaceflinger/BufferStateLayer.h
+++ b/services/surfaceflinger/BufferStateLayer.h
@@ -53,7 +53,9 @@
uint32_t doTransactionResize(uint32_t flags, Layer::State* /*stateToCommit*/) override {
return flags;
}
- void pushPendingState() override;
+ /*TODO:vhau return to using BufferStateLayer override once WM
+ * has removed deferred transactions!
+ void pushPendingState() override;*/
bool applyPendingStates(Layer::State* stateToCommit) override;
uint32_t getActiveWidth(const Layer::State& s) const override { return s.active.w; }
diff --git a/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp b/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp
index 45889a5..f9658a7 100644
--- a/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp
+++ b/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp
@@ -77,7 +77,7 @@
ISchedulerCallback& schedulerCallback) {
return std::make_unique<Scheduler>(std::move(setVSyncEnabled), configs, schedulerCallback,
property_get_bool("debug.sf.use_content_detection_v2",
- false));
+ true));
}
std::unique_ptr<SurfaceInterceptor> DefaultFactory::createSurfaceInterceptor(
diff --git a/services/surfaceflinger/TimeStats/TimeStats.cpp b/services/surfaceflinger/TimeStats/TimeStats.cpp
index fdf8a41..493a709 100644
--- a/services/surfaceflinger/TimeStats/TimeStats.cpp
+++ b/services/surfaceflinger/TimeStats/TimeStats.cpp
@@ -37,10 +37,11 @@
namespace impl {
-status_pull_atom_return_t TimeStats::pullAtomCallback(int32_t atom_tag,
- pulled_stats_event_list* data, void* cookie) {
+AStatsManager_PullAtomCallbackReturn TimeStats::pullAtomCallback(int32_t atom_tag,
+ AStatsEventList* data,
+ void* cookie) {
impl::TimeStats* timeStats = reinterpret_cast<impl::TimeStats*>(cookie);
- status_pull_atom_return_t result = STATS_PULL_SKIP;
+ AStatsManager_PullAtomCallbackReturn result = AStatsManager_PULL_SKIP;
if (atom_tag == android::util::SURFACEFLINGER_STATS_GLOBAL_INFO) {
result = timeStats->populateGlobalAtom(data);
} else if (atom_tag == android::util::SURFACEFLINGER_STATS_LAYER_INFO) {
@@ -54,15 +55,15 @@
return result;
}
-status_pull_atom_return_t TimeStats::populateGlobalAtom(pulled_stats_event_list* data) {
+AStatsManager_PullAtomCallbackReturn TimeStats::populateGlobalAtom(AStatsEventList* data) {
std::lock_guard<std::mutex> lock(mMutex);
if (mTimeStats.statsStart == 0) {
- return STATS_PULL_SKIP;
+ return AStatsManager_PULL_SKIP;
}
flushPowerTimeLocked();
- struct stats_event* event = mStatsDelegate->addStatsEventToPullData(data);
+ AStatsEvent* event = mStatsDelegate->addStatsEventToPullData(data);
mStatsDelegate->statsEventSetAtomId(event, android::util::SURFACEFLINGER_STATS_GLOBAL_INFO);
mStatsDelegate->statsEventWriteInt64(event, mTimeStats.totalFrames);
mStatsDelegate->statsEventWriteInt64(event, mTimeStats.missedFrames);
@@ -72,7 +73,7 @@
mStatsDelegate->statsEventBuild(event);
clearGlobalLocked();
- return STATS_PULL_SUCCESS;
+ return AStatsManager_PULL_SUCCESS;
}
namespace {
@@ -110,7 +111,7 @@
}
} // namespace
-status_pull_atom_return_t TimeStats::populateLayerAtom(pulled_stats_event_list* data) {
+AStatsManager_PullAtomCallbackReturn TimeStats::populateLayerAtom(AStatsEventList* data) {
std::lock_guard<std::mutex> lock(mMutex);
std::vector<TimeStatsHelper::TimeStatsLayer const*> dumpStats;
@@ -129,7 +130,7 @@
}
for (const auto& layer : dumpStats) {
- struct stats_event* event = mStatsDelegate->addStatsEventToPullData(data);
+ AStatsEvent* event = mStatsDelegate->addStatsEventToPullData(data);
mStatsDelegate->statsEventSetAtomId(event, android::util::SURFACEFLINGER_STATS_LAYER_INFO);
mStatsDelegate->statsEventWriteString8(event, layer->layerName.c_str());
mStatsDelegate->statsEventWriteInt64(event, layer->totalFrames);
@@ -151,7 +152,7 @@
}
clearLayersLocked();
- return STATS_PULL_SUCCESS;
+ return AStatsManager_PULL_SUCCESS;
}
TimeStats::TimeStats() : TimeStats(nullptr, std::nullopt, std::nullopt) {}
diff --git a/services/surfaceflinger/TimeStats/TimeStats.h b/services/surfaceflinger/TimeStats/TimeStats.h
index 7f58725..a428ef4 100644
--- a/services/surfaceflinger/TimeStats/TimeStats.h
+++ b/services/surfaceflinger/TimeStats/TimeStats.h
@@ -159,37 +159,38 @@
class StatsEventDelegate {
public:
virtual ~StatsEventDelegate() = default;
- virtual struct stats_event* addStatsEventToPullData(pulled_stats_event_list* data) {
- return add_stats_event_to_pull_data(data);
+ virtual AStatsEvent* addStatsEventToPullData(AStatsEventList* data) {
+ return AStatsEventList_addStatsEvent(data);
}
virtual void registerStatsPullAtomCallback(int32_t atom_tag,
- stats_pull_atom_callback_t callback,
- pull_atom_metadata* metadata, void* cookie) {
- return register_stats_pull_atom_callback(atom_tag, callback, metadata, cookie);
+ AStatsManager_PullAtomCallback callback,
+ AStatsManager_PullAtomMetadata* metadata,
+ void* cookie) {
+ return AStatsManager_registerPullAtomCallback(atom_tag, callback, metadata, cookie);
}
virtual void unregisterStatsPullAtomCallback(int32_t atom_tag) {
- return unregister_stats_pull_atom_callback(atom_tag);
+ return AStatsManager_unregisterPullAtomCallback(atom_tag);
}
- virtual void statsEventSetAtomId(struct stats_event* event, uint32_t atom_id) {
- return stats_event_set_atom_id(event, atom_id);
+ virtual void statsEventSetAtomId(AStatsEvent* event, uint32_t atom_id) {
+ return AStatsEvent_setAtomId(event, atom_id);
}
- virtual void statsEventWriteInt64(struct stats_event* event, int64_t field) {
- return stats_event_write_int64(event, field);
+ virtual void statsEventWriteInt64(AStatsEvent* event, int64_t field) {
+ return AStatsEvent_writeInt64(event, field);
}
- virtual void statsEventWriteString8(struct stats_event* event, const char* field) {
- return stats_event_write_string8(event, field);
+ virtual void statsEventWriteString8(AStatsEvent* event, const char* field) {
+ return AStatsEvent_writeString(event, field);
}
- virtual void statsEventWriteByteArray(struct stats_event* event, const uint8_t* buf,
+ virtual void statsEventWriteByteArray(AStatsEvent* event, const uint8_t* buf,
size_t numBytes) {
- return stats_event_write_byte_array(event, buf, numBytes);
+ return AStatsEvent_writeByteArray(event, buf, numBytes);
}
- virtual void statsEventBuild(struct stats_event* event) { return stats_event_build(event); }
+ virtual void statsEventBuild(AStatsEvent* event) { return AStatsEvent_build(event); }
};
// For testing only for injecting custom dependencies.
TimeStats(std::unique_ptr<StatsEventDelegate> statsDelegate,
@@ -238,10 +239,11 @@
static const size_t MAX_NUM_TIME_RECORDS = 64;
private:
- static status_pull_atom_return_t pullAtomCallback(int32_t atom_tag,
- pulled_stats_event_list* data, void* cookie);
- status_pull_atom_return_t populateGlobalAtom(pulled_stats_event_list* data);
- status_pull_atom_return_t populateLayerAtom(pulled_stats_event_list* data);
+ static AStatsManager_PullAtomCallbackReturn pullAtomCallback(int32_t atom_tag,
+ AStatsEventList* data,
+ void* cookie);
+ AStatsManager_PullAtomCallbackReturn populateGlobalAtom(AStatsEventList* data);
+ AStatsManager_PullAtomCallbackReturn populateLayerAtom(AStatsEventList* data);
bool recordReadyLocked(int32_t layerId, TimeRecord* timeRecord);
void flushAvailableRecordsToStatsLocked(int32_t layerId);
void flushPowerTimeLocked();
diff --git a/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp b/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp
index 30505b9..91a40d0 100644
--- a/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp
@@ -149,30 +149,31 @@
FakeStatsEventDelegate() = default;
~FakeStatsEventDelegate() override = default;
- struct stats_event* addStatsEventToPullData(pulled_stats_event_list*) override {
+ struct AStatsEvent* addStatsEventToPullData(AStatsEventList*) override {
return mEvent;
}
- void registerStatsPullAtomCallback(int32_t atom_tag, stats_pull_atom_callback_t callback,
- pull_atom_metadata*, void* cookie) override {
+ void registerStatsPullAtomCallback(int32_t atom_tag,
+ AStatsManager_PullAtomCallback callback,
+ AStatsManager_PullAtomMetadata*, void* cookie) override {
mAtomTags.push_back(atom_tag);
mCallback = callback;
mCookie = cookie;
}
- status_pull_atom_return_t makePullAtomCallback(int32_t atom_tag, void* cookie) {
+ AStatsManager_PullAtomCallbackReturn makePullAtomCallback(int32_t atom_tag, void* cookie) {
return (*mCallback)(atom_tag, nullptr, cookie);
}
MOCK_METHOD1(unregisterStatsPullAtomCallback, void(int32_t));
- MOCK_METHOD2(statsEventSetAtomId, void(struct stats_event*, uint32_t));
- MOCK_METHOD2(statsEventWriteInt64, void(struct stats_event*, int64_t));
- MOCK_METHOD2(statsEventWriteString8, void(struct stats_event*, const char*));
- MOCK_METHOD3(statsEventWriteByteArray, void(struct stats_event*, const uint8_t*, size_t));
- MOCK_METHOD1(statsEventBuild, void(struct stats_event*));
+ MOCK_METHOD2(statsEventSetAtomId, void(AStatsEvent*, uint32_t));
+ MOCK_METHOD2(statsEventWriteInt64, void(AStatsEvent*, int64_t));
+ MOCK_METHOD2(statsEventWriteString8, void(AStatsEvent*, const char*));
+ MOCK_METHOD3(statsEventWriteByteArray, void(AStatsEvent*, const uint8_t*, size_t));
+ MOCK_METHOD1(statsEventBuild, void(AStatsEvent*));
- struct stats_event* mEvent = stats_event_obtain();
+ AStatsEvent* mEvent = AStatsEvent_obtain();
std::vector<int32_t> mAtomTags;
- stats_pull_atom_callback_t mCallback = nullptr;
+ AStatsManager_PullAtomCallback mCallback = nullptr;
void* mCookie = nullptr;
};
FakeStatsEventDelegate* mDelegate = new FakeStatsEventDelegate;
@@ -835,7 +836,7 @@
EXPECT_CALL(*mDelegate, statsEventWriteInt64(mDelegate->mEvent, 2));
EXPECT_CALL(*mDelegate, statsEventBuild(mDelegate->mEvent));
}
- EXPECT_EQ(STATS_PULL_SUCCESS,
+ EXPECT_EQ(AStatsManager_PULL_SUCCESS,
mDelegate->makePullAtomCallback(android::util::SURFACEFLINGER_STATS_GLOBAL_INFO,
mDelegate->mCookie));
@@ -956,7 +957,7 @@
expectedPostToAcquire.size()));
EXPECT_CALL(*mDelegate, statsEventBuild(mDelegate->mEvent));
}
- EXPECT_EQ(STATS_PULL_SUCCESS,
+ EXPECT_EQ(AStatsManager_PULL_SUCCESS,
mDelegate->makePullAtomCallback(android::util::SURFACEFLINGER_STATS_LAYER_INFO,
mDelegate->mCookie));
@@ -990,7 +991,7 @@
statsEventWriteString8(mDelegate->mEvent, StrEq(genLayerName(LAYER_ID_0).c_str())));
EXPECT_CALL(*mDelegate,
statsEventWriteString8(mDelegate->mEvent, StrEq(genLayerName(LAYER_ID_1).c_str())));
- EXPECT_EQ(STATS_PULL_SUCCESS,
+ EXPECT_EQ(AStatsManager_PULL_SUCCESS,
mDelegate->makePullAtomCallback(android::util::SURFACEFLINGER_STATS_LAYER_INFO,
mDelegate->mCookie));
}
@@ -1031,7 +1032,7 @@
EXPECT_CALL(*mDelegate, statsEventWriteByteArray(mDelegate->mEvent, _, _))
.Times(AnyNumber());
}
- EXPECT_EQ(STATS_PULL_SUCCESS,
+ EXPECT_EQ(AStatsManager_PULL_SUCCESS,
mDelegate->makePullAtomCallback(android::util::SURFACEFLINGER_STATS_LAYER_INFO,
mDelegate->mCookie));
}
@@ -1071,7 +1072,7 @@
EXPECT_CALL(*mDelegate, statsEventWriteByteArray(mDelegate->mEvent, _, _))
.Times(AnyNumber());
}
- EXPECT_EQ(STATS_PULL_SUCCESS,
+ EXPECT_EQ(AStatsManager_PULL_SUCCESS,
mDelegate->makePullAtomCallback(android::util::SURFACEFLINGER_STATS_LAYER_INFO,
mDelegate->mCookie));
}
@@ -1103,7 +1104,7 @@
.Times(1);
EXPECT_CALL(*mDelegate,
statsEventWriteString8(mDelegate->mEvent, StrEq(genLayerName(LAYER_ID_1).c_str())));
- EXPECT_EQ(STATS_PULL_SUCCESS,
+ EXPECT_EQ(AStatsManager_PULL_SUCCESS,
mDelegate->makePullAtomCallback(android::util::SURFACEFLINGER_STATS_LAYER_INFO,
mDelegate->mCookie));
}