Merge "Add test that makes sure color transform from the layer is used"
diff --git a/aidl/gui/android/view/LayerMetadataKey.aidl b/aidl/gui/android/view/LayerMetadataKey.aidl
index 491c629..a1d8ce5 100644
--- a/aidl/gui/android/view/LayerMetadataKey.aidl
+++ b/aidl/gui/android/view/LayerMetadataKey.aidl
@@ -25,4 +25,5 @@
METADATA_MOUSE_CURSOR = 4,
METADATA_ACCESSIBILITY_ID = 5,
METADATA_OWNER_PID = 6,
+ METADATA_DEQUEUE_TIME = 7,
}
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index afa0b4d..c215c95 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -227,7 +227,6 @@
static const std::string DUMP_HALS_TASK = "DUMP HALS";
static const std::string DUMP_BOARD_TASK = "dumpstate_board()";
static const std::string DUMP_CHECKINS_TASK = "DUMP CHECKINS";
-static const std::string DUMP_APP_INFOS_TASK = "DUMP APP INFOS";
namespace android {
namespace os {
@@ -1577,7 +1576,6 @@
ds.dump_pool_->enqueueTask(DUMP_INCIDENT_REPORT_TASK, &DumpIncidentReport);
ds.dump_pool_->enqueueTaskWithFd(DUMP_BOARD_TASK, &Dumpstate::DumpstateBoard, &ds, _1);
ds.dump_pool_->enqueueTaskWithFd(DUMP_CHECKINS_TASK, &DumpCheckins, _1);
- ds.dump_pool_->enqueueTaskWithFd(DUMP_APP_INFOS_TASK, &DumpAppInfos, _1);
}
// Dump various things. Note that anything that takes "long" (i.e. several seconds) should
@@ -1730,11 +1728,7 @@
RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_CHECKINS_TASK, DumpCheckins);
}
- if (ds.dump_pool_) {
- WAIT_TASK_WITH_CONSENT_CHECK(DUMP_APP_INFOS_TASK, ds.dump_pool_);
- } else {
- RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_APP_INFOS_TASK, DumpAppInfos);
- }
+ RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(DumpAppInfos);
printf("========================================================\n");
printf("== Dropbox crashes\n");
diff --git a/cmds/dumpsys/dumpsys.cpp b/cmds/dumpsys/dumpsys.cpp
index 1327cfd..a017246 100644
--- a/cmds/dumpsys/dumpsys.cpp
+++ b/cmds/dumpsys/dumpsys.cpp
@@ -427,7 +427,7 @@
<< strerror(errno) << std::endl;
status = -errno;
break;
- } else if (rc == 0) {
+ } else if (rc == 0 || time_left_ms() == 0) {
status = TIMED_OUT;
break;
}
diff --git a/include/android/imagedecoder.h b/include/android/imagedecoder.h
index 49a616f..b5f3b10 100644
--- a/include/android/imagedecoder.h
+++ b/include/android/imagedecoder.h
@@ -65,7 +65,8 @@
* Many functions will return this 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.
+ * specified. Use {@link AImageDecoder_resultToString} for a readable
+ * version of the result code.
*/
enum {
/**
@@ -109,9 +110,39 @@
/**
* AImageDecoder did not recognize the format.
*/
- ANDROID_IMAGE_DECODER_UNSUPPORTED_FORMAT = -9
+ ANDROID_IMAGE_DECODER_UNSUPPORTED_FORMAT = -9,
+ /**
+ * The animation has reached the end.
+ */
+ ANDROID_IMAGE_DECODER_FINISHED = -10,
+ /**
+ * This method cannot be called while the AImageDecoder is in its current
+ * state. For example, various setters (like {@link AImageDecoder_setTargetSize})
+ * can only be called while the AImageDecoder is set to decode the first
+ * frame of an animation. This ensures that any blending and/or restoring
+ * prior frames works correctly.
+ */
+ ANDROID_IMAGE_DECODER_INVALID_STATE = -11,
};
+#if __ANDROID_API__ >= 31
+
+/**
+ * Return a constant string value representing the error code.
+ *
+ * Introduced in API 31.
+ *
+ * Pass the return value from an {@link AImageDecoder} method (e.g.
+ * {@link AImageDecoder_decodeImage}) for a text string representing the error
+ * code.
+ *
+ * Errors:
+ * - Returns null for a value out of range.
+ */
+const char* _Nullable AImageDecoder_resultToString(int)__INTRODUCED_IN(31);
+
+#endif // __ANDROID_API__ >= 31
+
struct AImageDecoder;
/**
@@ -127,7 +158,7 @@
* 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_decodeImage} will decode into client provided memory.
*
* {@link AImageDecoder} objects are NOT thread-safe, and should not be shared across
* threads.
@@ -165,7 +196,7 @@
* supported.
*/
int AImageDecoder_createFromAAsset(struct AAsset* _Nonnull asset,
- AImageDecoder* _Nonnull * _Nonnull outDecoder)
+ AImageDecoder* _Nullable * _Nonnull outDecoder)
__INTRODUCED_IN(30);
/**
@@ -196,7 +227,7 @@
* - {@link ANDROID_IMAGE_DECODER_UNSUPPORTED_FORMAT}: The format is not
* supported.
*/
-int AImageDecoder_createFromFd(int fd, AImageDecoder* _Nonnull * _Nonnull outDecoder)
+int AImageDecoder_createFromFd(int fd, AImageDecoder* _Nullable * _Nonnull outDecoder)
__INTRODUCED_IN(30);
/**
@@ -227,7 +258,7 @@
* supported.
*/
int AImageDecoder_createFromBuffer(const void* _Nonnull buffer, size_t length,
- AImageDecoder* _Nonnull * _Nonnull outDecoder)
+ AImageDecoder* _Nullable * _Nonnull outDecoder)
__INTRODUCED_IN(30);
/**
@@ -235,11 +266,15 @@
*
* Available since API level 30.
*/
-void AImageDecoder_delete(AImageDecoder* _Nonnull decoder) __INTRODUCED_IN(30);
+void AImageDecoder_delete(AImageDecoder* _Nullable decoder) __INTRODUCED_IN(30);
/**
* Choose the desired output format.
*
+ * If the encoded image represents an animation, this must be called while on
+ * the first frame (e.g. before calling {@link AImageDecoder_advanceFrame} or
+ * after calling {@link AImageDecoder_rewind}).
+ *
* Available since API level 30.
*
* @param format {@link AndroidBitmapFormat} to use for the output.
@@ -255,6 +290,8 @@
* {@link AndroidBitmapFormat}.
* - {@link ANDROID_IMAGE_DECODER_INVALID_CONVERSION}: The
* {@link AndroidBitmapFormat} is incompatible with the image.
+ * - {@link ANDROID_IMAGE_DECODER_INVALID_STATE}: The animation is not on
+ * the first frame.
*/
int AImageDecoder_setAndroidBitmapFormat(AImageDecoder* _Nonnull decoder,
int32_t format) __INTRODUCED_IN(30);
@@ -266,6 +303,10 @@
* Pass true to this method to leave them unpremultiplied. This has no effect on an
* opaque image.
*
+ * If the encoded image represents an animation, this must be called while on
+ * the first frame (e.g. before calling {@link AImageDecoder_advanceFrame} or
+ * after calling {@link AImageDecoder_rewind}).
+ *
* Available since API level 30.
*
* @param unpremultipliedRequired Pass true to leave the pixels unpremultiplied.
@@ -278,6 +319,8 @@
* {@link AImageDecoder_setTargetSize}.
* - {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER}: The
* {@link AImageDecoder} is null.
+ * - {@link ANDROID_IMAGE_DECODER_INVALID_STATE}: The animation is not on
+ * the first frame.
*/
int AImageDecoder_setUnpremultipliedRequired(AImageDecoder* _Nonnull decoder,
bool unpremultipliedRequired) __INTRODUCED_IN(30);
@@ -288,6 +331,10 @@
* Ignored by {@link ANDROID_BITMAP_FORMAT_A_8}, which does not support
* an {@link ADataSpace}.
*
+ * If the encoded image represents an animation, this must be called while on
+ * the first frame (e.g. before calling {@link AImageDecoder_advanceFrame} or
+ * after calling {@link AImageDecoder_rewind}).
+ *
* Available since API level 30.
*
* @param dataspace The {@link ADataSpace} to decode into. An ADataSpace
@@ -303,6 +350,8 @@
* - {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER}: The
* {@link AImageDecoder} is null or |dataspace| does not correspond to an
* {@link ADataSpace} value.
+ * - {@link ANDROID_IMAGE_DECODER_INVALID_STATE}: The animation is not on
+ * the first frame.
*/
int AImageDecoder_setDataSpace(AImageDecoder* _Nonnull decoder, int32_t dataspace)
__INTRODUCED_IN(30);
@@ -316,6 +365,10 @@
* specified by width and height, and the output image will be the size of the
* crop rect.
*
+ * If the encoded image represents an animation, this must be called while on
+ * the first frame (e.g. before calling {@link AImageDecoder_advanceFrame} or
+ * after calling {@link AImageDecoder_rewind}).
+ *
* Available since API level 30.
*
* @param width Width of the output (prior to cropping).
@@ -330,9 +383,11 @@
* - {@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
+ * 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).
+ * - {@link ANDROID_IMAGE_DECODER_INVALID_STATE}: The animation is not on
+ * the first frame.
*/
int AImageDecoder_setTargetSize(AImageDecoder* _Nonnull decoder, int32_t width,
int32_t height) __INTRODUCED_IN(30);
@@ -374,6 +429,10 @@
* the specified {@link ARect}. Clients will only need to allocate enough memory
* for the cropped ARect.
*
+ * If the encoded image represents an animation, this must be called while on
+ * the first frame (e.g. before calling {@link AImageDecoder_advanceFrame} or
+ * after calling {@link AImageDecoder_rewind}).
+ *
* Available since API level 30.
*
* @param crop Rectangle describing a crop of the decode. It must be contained inside of
@@ -389,8 +448,10 @@
*
* Errors:
* - {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER}: The
- * {@link AImageDecoder} is null or the crop is not contained by the
+ * {@link AImageDecoder} is null, or the crop is not contained by the
* (possibly scaled) image dimensions.
+ * - {@link ANDROID_IMAGE_DECODER_INVALID_STATE}: The animation is not on
+ * the first frame.
*/
int AImageDecoder_setCrop(AImageDecoder* _Nonnull decoder, ARect crop) __INTRODUCED_IN(30);
@@ -472,6 +533,10 @@
* {@link AImageDecoder_decodeImage} will premultiply pixels by default.
*
* Available since API level 30.
+ *
+ * Starting in API level 31, an AImageDecoder may contain multiple frames of an
+ * animation, but this method still only reports whether the first frame has
+ * alpha.
*/
int AImageDecoderHeaderInfo_getAlphaFlags(
const AImageDecoderHeaderInfo* _Nonnull) __INTRODUCED_IN(30);
@@ -518,8 +583,44 @@
* Available since API level 30.
*
* Starting in API level 31, it can be used to decode all of the frames of an
- * animated image (i.e. GIF, WebP, HEIF) using new APIs (TODO (scroggo): list
- * and describe here).
+ * animated image (i.e. GIF, WebP, HEIF) using new APIs. Internally,
+ * AImageDecoder keeps track of its "current frame" - that is, the frame that
+ * will be decoded by a call to AImageDecoder_decodeImage. At creation time, the
+ * current frame is always the first frame, and multiple calls to this method
+ * will each decode the first frame. {@link AImageDecoder_advanceFrame} advances
+ * the current frame to the following frame, so that future calls to this method
+ * will decode that frame. Some frames may update only part of the image. They
+ * may only update a sub-rectangle (see {@link
+ * AImageDecoderFrameInfo_getFrameRect}), or they may have alpha (see
+ * {@link AImageDecoderFrameInfo_hasAlphaWithinBounds}). In these cases, this
+ * method assumes that the prior frame is still residing in the |pixels| buffer,
+ * decodes only the new portion, and blends it with the buffer. Frames that change
+ * the entire |pixels| buffer are "independent", and do not require the prior
+ * frame to remain in the buffer. The first frame is always independent. A
+ * sophisticated client can use information from the {@link AImageDecoderFrameInfo}
+ * to determine whether other frames are independent, or what frames they rely on.
+ *
+ * If the current frame is marked {@link ANDROID_IMAGE_DECODER_DISPOSE_OP_PREVIOUS},
+ * AImageDecoder_decodeImage will cache the |pixels| buffer prior to decoding
+ * (note: this only happens for the first in a string of consecutive
+ * ANDROID_IMAGE_DECODER_DISPOSE_OP_PREVIOUS frames). After advancing to the
+ * following frame, AImageDecoder_decodeImage will restore the cached buffer
+ * prior to decoding that frame.
+ *
+ * Ignoring timing information, display, etc, a client wishing to decode all
+ * frames of an animated image may conceptually use code like the following:
+ *
+ * while (true) {
+ * int result = AImageDecoder_decodeImage(decoder, pixels, stride, size);
+ * if (result != ANDROID_IMAGE_DECODER_SUCCESS) break;
+ *
+ * // Display or save the image in |pixels|, keeping the buffer intact for
+ * // AImageDecoder to decode the next frame correctly.
+ * Application_viewImage(pixels);
+ *
+ * result = AImageDecoder_advanceFrame(decoder);
+ * if (result != ANDROID_IMAGE_DECODER_SUCCESS) break;
+ * }
*
* @param decoder Opaque object representing the decoder.
* @param pixels On success, will be filled with the result
@@ -547,6 +648,10 @@
* failed to seek.
* - {@link ANDROID_IMAGE_DECODER_INTERNAL_ERROR}: Some other error, like a
* failure to allocate memory.
+ * - {@link ANDROID_IMAGE_DECODER_FINISHED}: The input contains no
+ * more frames. No decoding occurred. The client must call
+ * {@link AImageDecoder_rewind} before calling
+ * {@link AImageDecoder_decodeImage} again.
*/
int AImageDecoder_decodeImage(AImageDecoder* _Nonnull decoder,
void* _Nonnull pixels, size_t stride,
@@ -561,8 +666,8 @@
*
* Introduced in API 31.
*
- * This may require seeking past the first frame to verify whether
- * there is a following frame (e.g. for GIF).
+ * A single frame GIF is considered to *not* be animated. This may require
+ * seeking past the first frame to verify whether there is a following frame.
*
* Errors:
* - returns false if |decoder| is null.
@@ -610,6 +715,286 @@
int32_t AImageDecoder_getRepeatCount(AImageDecoder* _Nonnull decoder);
__INTRODUCED_IN(31);
+/**
+ * Advance to the next frame in the animation.
+ *
+ * Introduced in API 31.
+ *
+ * The AImageDecoder keeps track internally which frame it is ready to decode
+ * (the "current frame"). Initially it is set to decode the first frame, and
+ * each call to {@link AImageDecoder_decodeImage} will continue to decode
+ * the same frame until this method (or {@link AImageDecoder_rewind})
+ * is called.
+ *
+ * Note that this can be used to skip a frame without decoding it. But
+ * some frames depend on (i.e. blend with) prior frames, and
+ * AImageDecoder_decodeImage assumes that the prior frame is in the
+ * |pixels| buffer. In addition, AImageDecoder_decodeImage handles caching and
+ * restoring frames (see {@link ANDROID_IMAGE_DECODER_DISPOSE_OP_PREVIOUS}), so
+ * skipping frames in an image with such frames may not produce the correct
+ * results.
+ *
+ * @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 AImageDecoder
+ * represents an image that is not animated (see
+ * {@link AImageDecoder_isAnimated}) or the AImageDecoder is null.
+ * - {@link ANDROID_IMAGE_DECODER_INCOMPLETE}: The input appears
+ * to be truncated. The client must call {@link AImageDecoder_rewind}
+ * before calling {@link AImageDecoder_decodeImage} again.
+ * - {@link ANDROID_IMAGE_DECODER_ERROR}: The input contains an error.
+ * The client must call {@link AImageDecoder_rewind} before
+ * calling {@link AImageDecoder_decodeImage} again.
+ * - {@link ANDROID_IMAGE_DECODER_FINISHED}: The input contains no
+ * more frames. The client must call {@link AImageDecoder_rewind}
+ * before calling {@link AImageDecoder_decodeImage} again.
+ */
+int AImageDecoder_advanceFrame(AImageDecoder* _Nonnull decoder)
+ __INTRODUCED_IN(31);
+
+/**
+ * Return to the beginning of the animation.
+ *
+ * Introduced in API 31.
+ *
+ * After this call, the AImageDecoder will be ready to decode the
+ * first frame of the animation. This can be called after reaching
+ * the end of the animation or an error or in the middle of the
+ * animation.
+ *
+ * @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 AImageDecoder
+ * represents an image that is not animated (see
+ * {@link AImageDecoder_isAnimated}) or the AImageDecoder is
+ * null.
+ * - {@link ANDROID_IMAGE_DECODER_SEEK_ERROR}: The asset or file
+ * descriptor failed to seek.
+ */
+int AImageDecoder_rewind(AImageDecoder* _Nonnull decoder)
+ __INTRODUCED_IN(31);
+
+#endif // __ANDROID_API__ >= 31
+
+struct AImageDecoderFrameInfo;
+
+/**
+ * Opaque handle to animation information about a single frame.
+ *
+ * Introduced in API 31
+ *
+ * The duration (retrieved with {@link AImageDecoderFrameInfo_getDuration}) is
+ * necessary for clients to display the animation at the proper speed. The other
+ * information is helpful for a client that wants to determine what frames are
+ * independent (or what frames they depend on), but is unnecessary for
+ * a simple client that wants to sequentially display all frames.
+ */
+typedef struct AImageDecoderFrameInfo AImageDecoderFrameInfo;
+
+#if __ANDROID_API__ >= 31
+
+/**
+ * Create an uninitialized AImageDecoderFrameInfo.
+ *
+ * Introduced in API 31.
+ *
+ * This can be passed to {@link AImageDecoder_getFrameInfo} to fill
+ * in information about the current frame. It may be reused.
+ *
+ * Must be deleted with {@link AImageDecoderFrameInfo_delete}.
+ */
+AImageDecoderFrameInfo* _Nullable AImageDecoderFrameInfo_create()
+ __INTRODUCED_IN(31);
+
+/**
+ * Delete an AImageDecoderFrameInfo.
+ *
+ * Introduced in API 31.
+ */
+void AImageDecoderFrameInfo_delete(
+ AImageDecoderFrameInfo* _Nullable info) __INTRODUCED_IN(31);
+
+/**
+ * Fill |info| with information about the current frame.
+ *
+ * Introduced in API 31.
+ *
+ * Initially, this will return information about the first frame.
+ * {@link AImageDecoder_advanceFrame} and
+ * {@link AImageDecoder_rewind} can be used to change which frame
+ * is the current frame.
+ *
+ * If the image only has one frame, this will fill the {@link
+ * AImageDecoderFrameInfo} with the encoded info, if any, or reasonable
+ * defaults.
+ *
+ * @param decoder Opaque object representing the decoder.
+ * @param info Opaque object to hold frame information. On success, will be
+ * filled with information regarding the current frame.
+ * @return {@link ANDROID_IMAGE_DECODER_SUCCESS} on success or a value
+ * indicating the reason for the failure.
+ *
+ * Errors:
+ * - {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER}: One of the parameters is null.
+ * - {@link ANDROID_IMAGE_DECODER_FINISHED}: The input contains no
+ * more frames. The client must call {@link AImageDecoder_rewind} to reset the
+ * current frame to a valid frame (0).
+ */
+int AImageDecoder_getFrameInfo(AImageDecoder* _Nonnull decoder,
+ AImageDecoderFrameInfo* _Nonnull info) __INTRODUCED_IN(31);
+
+/**
+ * Report the number of nanoseconds to show the current frame.
+ *
+ * Introduced in API 31.
+ *
+ * Errors:
+ * - returns 0 if |info| is null.
+ */
+int64_t AImageDecoderFrameInfo_getDuration(
+ const AImageDecoderFrameInfo* _Nonnull info) __INTRODUCED_IN(31);
+
+/**
+ * The rectangle of the image (within 0, 0,
+ * {@link AImageDecoder_getWidth}, {@link AImageDecoder_getHeight})
+ * updated by this frame.
+ *
+ * Introduced in API 31.
+ *
+ * Note that this is unaffected by calls to
+ * {@link AImageDecoder_setTargetSize} or
+ * {@link AImageDecoder_setCrop}.
+ *
+ * A frame may update only part of the image. This will always be
+ * contained by the image’s dimensions.
+ *
+ * This, along with other information in AImageDecoderFrameInfo,
+ * can be useful for determining whether a frame is independent, but
+ * the decoder handles blending frames, so a simple
+ * sequential client does not need this.
+ *
+ * Errors:
+ * - returns an empty ARect if |info| is null.
+ */
+ARect AImageDecoderFrameInfo_getFrameRect(
+ const AImageDecoderFrameInfo* _Nonnull info) __INTRODUCED_IN(31);
+
+/**
+ * Whether the new portion of this frame may contain alpha.
+ *
+ * Introduced in API 31.
+ *
+ * Note that this may differ from whether the composed frame has
+ * alpha. If this frame does not fill the entire image dimensions
+ * (see {@link AImageDecoderFrameInfo_getFrameRect}) or it blends
+ * with an opaque frame, for example, the composed frame’s alpha
+ * may not match. It is also conservative; for example, if a color
+ * index-based frame has a color with alpha but does not use it,
+ * this will still return true.
+ *
+ * This, along with other information in AImageDecoderFrameInfo,
+ * can be useful for determining whether a frame is independent, but
+ * the decoder handles blending frames, so a simple
+ * sequential client does not need this.
+ *
+ * Errors:
+ * - returns false if |info| is null.
+ */
+bool AImageDecoderFrameInfo_hasAlphaWithinBounds(
+ const AImageDecoderFrameInfo* _Nonnull info) __INTRODUCED_IN(31);
+
+#endif // __ANDROID_API__ >= 31
+
+/**
+ * How a frame is “disposed” before showing the next one.
+ *
+ * Introduced in API 31.
+ *
+ * This, along with other information in AImageDecoderFrameInfo,
+ * can be useful for determining whether a frame is independent, but
+ * the decoder handles disposing of frames, so a simple
+ * sequential client does not need this.
+ */
+enum {
+ // No disposal. The following frame will be drawn directly
+ // on top of this one.
+ ANDROID_IMAGE_DECODER_DISPOSE_OP_NONE = 1,
+ // The frame’s rectangle is cleared (by AImageDecoder) before
+ // decoding the next frame.
+ ANDROID_IMAGE_DECODER_DISPOSE_OP_BACKGROUND = 2,
+ // The frame’s rectangle is reverted (by AImageDecoder) to the
+ // prior frame before decoding the next frame.
+ ANDROID_IMAGE_DECODER_DISPOSE_OP_PREVIOUS = 3,
+};
+
+#if __ANDROID_API__ >= 31
+
+/**
+ * Return how this frame is “disposed” before showing the next one.
+ *
+ * Introduced in API 31.
+ *
+ * This, along with other information in AImageDecoderFrameInfo,
+ * can be useful for determining whether a frame is independent, but
+ * the decoder handles disposing of frames, so a simple
+ * sequential client does not need this.
+ *
+ * @return one of:
+ * - {@link ANDROID_IMAGE_DECODER_DISPOSE_OP_NONE}
+ * - {@link ANDROID_IMAGE_DECODER_DISPOSE_OP_BACKGROUND}
+ * - {@link ANDROID_IMAGE_DECODER_DISPOSE_OP_PREVIOUS}
+ * Errors:
+ * - {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER} if |info| is null.
+ */
+int32_t AImageDecoderFrameInfo_getDisposeOp(
+ const AImageDecoderFrameInfo* _Nonnull info) __INTRODUCED_IN(31);
+
+#endif // __ANDROID_API__ >= 31
+
+/**
+ * How a frame is blended with the previous frame.
+ *
+ * Introduced in API 31.
+ *
+ * This, along with other information in AImageDecoderFrameInfo,
+ * can be useful for determining whether a frame is independent, but
+ * the decoder handles blending frames, so a simple
+ * sequential client does not need this.
+ */
+enum {
+ // This frame replaces existing content. This corresponds
+ // to webp’s “do not blend”.
+ ANDROID_IMAGE_DECODER_BLEND_OP_SRC = 1,
+ // This frame blends with the previous frame.
+ ANDROID_IMAGE_DECODER_BLEND_OP_SRC_OVER = 2,
+};
+
+#if __ANDROID_API__ >= 31
+
+/**
+ * Return how this frame is blended with the previous frame.
+ *
+ * Introduced in API 31.
+ *
+ * This, along with other information in AImageDecoderFrameInfo,
+ * can be useful for determining whether a frame is independent, but
+ * the decoder handles blending frames, so a simple
+ * sequential client does not need this.
+ *
+ * @return one of:
+ * - {@link ANDROID_IMAGE_DECODER_BLEND_OP_SRC}
+ * - {@link ANDROID_IMAGE_DECODER_BLEND_OP_SRC_OVER}
+ * Errors:
+ * - {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER} if |info| is null.
+ */
+int32_t AImageDecoderFrameInfo_getBlendOp(
+ const AImageDecoderFrameInfo* _Nonnull info)
+ __INTRODUCED_IN(31);
+
#endif // __ANDROID_API__ >= 31
#ifdef __cplusplus
diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp
index eaa47f9..f4b5a26 100644
--- a/libs/gui/BLASTBufferQueue.cpp
+++ b/libs/gui/BLASTBufferQueue.cpp
@@ -354,6 +354,16 @@
t->setAutoRefresh(mSurfaceControl, bufferItem.mAutoRefresh);
mAutoRefresh = bufferItem.mAutoRefresh;
}
+ {
+ std::unique_lock _lock{mTimestampMutex};
+ auto dequeueTime = mDequeueTimestamps.find(buffer->getId());
+ if (dequeueTime != mDequeueTimestamps.end()) {
+ Parcel p;
+ p.writeInt64(dequeueTime->second);
+ t->setMetadata(mSurfaceControl, METADATA_DEQUEUE_TIME, p);
+ mDequeueTimestamps.erase(dequeueTime);
+ }
+ }
auto mergeTransaction =
[&t, currentFrameNumber = bufferItem.mFrameNumber](
@@ -412,6 +422,16 @@
// Do nothing since we are not storing unacquired buffer items locally.
}
+void BLASTBufferQueue::onFrameDequeued(const uint64_t bufferId) {
+ std::unique_lock _lock{mTimestampMutex};
+ mDequeueTimestamps[bufferId] = systemTime();
+};
+
+void BLASTBufferQueue::onFrameCancelled(const uint64_t bufferId) {
+ std::unique_lock _lock{mTimestampMutex};
+ mDequeueTimestamps.erase(bufferId);
+};
+
void BLASTBufferQueue::setNextTransaction(SurfaceComposerClient::Transaction* t) {
std::lock_guard _lock{mMutex};
mNextTransaction = t;
diff --git a/libs/gui/LayerMetadata.cpp b/libs/gui/LayerMetadata.cpp
index 30c9b37..634d8b7 100644
--- a/libs/gui/LayerMetadata.cpp
+++ b/libs/gui/LayerMetadata.cpp
@@ -17,6 +17,7 @@
#include <android-base/stringprintf.h>
#include <binder/Parcel.h>
#include <gui/LayerMetadata.h>
+#include <inttypes.h>
#include "android/view/LayerMetadataKey.h"
@@ -113,6 +114,15 @@
memcpy(data.data(), p.data(), p.dataSize());
}
+std::optional<int64_t> LayerMetadata::getInt64(uint32_t key) const {
+ if (!has(key)) return std::nullopt;
+ const std::vector<uint8_t>& data = mMap.at(key);
+ if (data.size() < sizeof(int64_t)) return std::nullopt;
+ Parcel p;
+ p.setData(data.data(), data.size());
+ return p.readInt64();
+}
+
std::string LayerMetadata::itemToString(uint32_t key, const char* separator) const {
if (!has(key)) return std::string();
switch (static_cast<view::LayerMetadataKey>(key)) {
@@ -124,6 +134,8 @@
return StringPrintf("taskId%s%d", separator, getInt32(key, 0));
case view::LayerMetadataKey::METADATA_OWNER_PID:
return StringPrintf("ownerPID%s%d", separator, getInt32(key, 0));
+ case view::LayerMetadataKey::METADATA_DEQUEUE_TIME:
+ return StringPrintf("dequeueTime%s%" PRId64, separator, *getInt64(key));
default:
return StringPrintf("%d%s%dbytes", key, separator,
static_cast<int>(mMap.at(key).size()));
diff --git a/libs/gui/include/gui/BLASTBufferQueue.h b/libs/gui/include/gui/BLASTBufferQueue.h
index 1198135..0fbcbdc 100644
--- a/libs/gui/include/gui/BLASTBufferQueue.h
+++ b/libs/gui/include/gui/BLASTBufferQueue.h
@@ -78,6 +78,8 @@
void onBufferFreed(const wp<GraphicBuffer>&/* graphicBuffer*/) override { /* TODO */ }
void onFrameReplaced(const BufferItem& item) override;
void onFrameAvailable(const BufferItem& item) override;
+ void onFrameDequeued(const uint64_t) override;
+ void onFrameCancelled(const uint64_t) override;
void transactionCallback(nsecs_t latchTime, const sp<Fence>& presentFence,
const std::vector<SurfaceControlStats>& stats);
@@ -168,7 +170,15 @@
// Queues up transactions using this token in SurfaceFlinger. This prevents queued up
// transactions from other parts of the client from blocking this transaction.
- const sp<IBinder> mApplyToken = new BBinder();
+ const sp<IBinder> mApplyToken GUARDED_BY(mMutex) = new BBinder();
+
+ // Guards access to mDequeueTimestamps since we cannot hold to mMutex in onFrameDequeued or
+ // we will deadlock.
+ std::mutex mTimestampMutex;
+ // Tracks buffer dequeue times by the client. This info is sent to SurfaceFlinger which uses
+ // it for debugging purposes.
+ std::unordered_map<uint64_t /* bufferId */, nsecs_t> mDequeueTimestamps
+ GUARDED_BY(mTimestampMutex);
};
} // namespace android
diff --git a/libs/gui/include/gui/LayerMetadata.h b/libs/gui/include/gui/LayerMetadata.h
index ac48aef..41982c2 100644
--- a/libs/gui/include/gui/LayerMetadata.h
+++ b/libs/gui/include/gui/LayerMetadata.h
@@ -29,6 +29,7 @@
METADATA_MOUSE_CURSOR = 4,
METADATA_ACCESSIBILITY_ID = 5,
METADATA_OWNER_PID = 6,
+ METADATA_DEQUEUE_TIME = 7
};
struct LayerMetadata : public Parcelable {
@@ -51,6 +52,8 @@
bool has(uint32_t key) const;
int32_t getInt32(uint32_t key, int32_t fallback) const;
void setInt32(uint32_t key, int32_t value);
+ std::optional<int64_t> getInt64(uint32_t key) const;
+ void setInt64(uint32_t key, int64_t value);
std::string itemToString(uint32_t key, const char* separator) const;
};
diff --git a/libs/renderengine/RenderEngine.cpp b/libs/renderengine/RenderEngine.cpp
index 3e65d9a..45db31c 100644
--- a/libs/renderengine/RenderEngine.cpp
+++ b/libs/renderengine/RenderEngine.cpp
@@ -41,6 +41,9 @@
if (strcmp(prop, "skiagl") == 0) {
renderEngineType = RenderEngineType::SKIA_GL;
}
+ if (strcmp(prop, "skiaglthreaded") == 0) {
+ renderEngineType = RenderEngineType::SKIA_GL_THREADED;
+ }
switch (renderEngineType) {
case RenderEngineType::THREADED:
@@ -49,6 +52,10 @@
[args]() { return android::renderengine::gl::GLESRenderEngine::create(args); });
case RenderEngineType::SKIA_GL:
return renderengine::skia::SkiaGLRenderEngine::create(args);
+ case RenderEngineType::SKIA_GL_THREADED:
+ return renderengine::threaded::RenderEngineThreaded::create([args]() {
+ return android::renderengine::skia::SkiaGLRenderEngine::create(args);
+ });
case RenderEngineType::GLES:
default:
ALOGD("RenderEngine with GLES Backend");
diff --git a/libs/renderengine/include/renderengine/RenderEngine.h b/libs/renderengine/include/renderengine/RenderEngine.h
index 9157066..506f81e 100644
--- a/libs/renderengine/include/renderengine/RenderEngine.h
+++ b/libs/renderengine/include/renderengine/RenderEngine.h
@@ -82,6 +82,7 @@
GLES = 1,
THREADED = 2,
SKIA_GL = 3,
+ SKIA_GL_THREADED = 4,
};
static std::unique_ptr<RenderEngine> create(const RenderEngineCreationArgs& args);
diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.cpp b/libs/renderengine/skia/SkiaGLRenderEngine.cpp
index 7567f05..d9495a9 100644
--- a/libs/renderengine/skia/SkiaGLRenderEngine.cpp
+++ b/libs/renderengine/skia/SkiaGLRenderEngine.cpp
@@ -19,25 +19,10 @@
#define LOG_TAG "RenderEngine"
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
-#include <cstdint>
-#include <memory>
-
-#include "SkImageInfo.h"
-#include "log/log_main.h"
-#include "system/graphics-base-v1.0.h"
+#include "SkiaGLRenderEngine.h"
#include <EGL/egl.h>
#include <EGL/eglext.h>
-#include <sync/sync.h>
-#include <ui/BlurRegion.h>
-#include <ui/GraphicBuffer.h>
-#include <utils/Trace.h>
-#include "../gl/GLExtensions.h"
-#include "SkiaGLRenderEngine.h"
-#include "filters/BlurFilter.h"
-#include "filters/LinearEffect.h"
-#include "skia/debug/SkiaCapture.h"
-
#include <GrContextOptions.h>
#include <SkCanvas.h>
#include <SkColorFilter.h>
@@ -48,8 +33,23 @@
#include <SkShadowUtils.h>
#include <SkSurface.h>
#include <gl/GrGLInterface.h>
+#include <sync/sync.h>
+#include <ui/BlurRegion.h>
+#include <ui/GraphicBuffer.h>
+#include <utils/Trace.h>
#include <cmath>
+#include <cstdint>
+#include <memory>
+
+#include "../gl/GLExtensions.h"
+#include "SkBlendMode.h"
+#include "SkImageInfo.h"
+#include "filters/BlurFilter.h"
+#include "filters/LinearEffect.h"
+#include "log/log_main.h"
+#include "skia/debug/SkiaCapture.h"
+#include "system/graphics-base-v1.0.h"
bool checkGlError(const char* op, int lineNumber);
@@ -668,7 +668,35 @@
/* undoPremultipliedAlpha */ false));
}
- paint.setColorFilter(SkColorFilters::Matrix(toSkColorMatrix(display.colorTransform)));
+ sk_sp<SkColorFilter> filter =
+ SkColorFilters::Matrix(toSkColorMatrix(display.colorTransform));
+
+ // Handle opaque images - it's a little nonstandard how we do this.
+ // Fundamentally we need to support SurfaceControl.Builder#setOpaque:
+ // https://developer.android.com/reference/android/view/SurfaceControl.Builder#setOpaque(boolean)
+ // The important language is that when isOpaque is set, opacity is not sampled from the
+ // alpha channel, but blending may still be supported on a transaction via setAlpha. So,
+ // here's the conundrum:
+ // 1. We can't force the SkImage alpha type to kOpaque_SkAlphaType, because it's treated as
+ // an internal hint - composition is undefined when there are alpha bits present.
+ // 2. We can try to lie about the pixel layout, but that only works for RGBA8888 buffers,
+ // i.e., treating them as RGBx8888 instead. But we can't do the same for RGBA1010102 because
+ // RGBx1010102 is not supported as a pixel layout for SkImages. It's also not clear what to
+ // use for F16 either, and lying about the pixel layout is a bit of a hack anyways.
+ // 3. We can't change the blendmode to src, because while this satisfies the requirement for
+ // ignoring the alpha channel, it doesn't quite satisfy the blending requirement because
+ // src always clobbers the destination content.
+ //
+ // So, what we do here instead is an additive blend mode where we compose the input image
+ // with a solid black. This might need to be reassess if this does not support FP16
+ // incredibly well, but FP16 end-to-end isn't well supported anyway at the moment.
+ if (layer->source.buffer.buffer && layer->source.buffer.isOpaque) {
+ filter = SkColorFilters::Compose(filter,
+ SkColorFilters::Blend(SK_ColorBLACK,
+ SkBlendMode::kPlus));
+ }
+
+ paint.setColorFilter(filter);
for (const auto effectRegion : layer->blurRegions) {
drawBlurRegion(canvas, effectRegion, layerRect, cachedBlurs[effectRegion.blurRadius]);
diff --git a/libs/renderengine/skia/debug/SkiaCapture.cpp b/libs/renderengine/skia/debug/SkiaCapture.cpp
index 8006a11..e9cfead 100644
--- a/libs/renderengine/skia/debug/SkiaCapture.cpp
+++ b/libs/renderengine/skia/debug/SkiaCapture.cpp
@@ -129,8 +129,14 @@
// SkDocuments don't take ownership of the streams they write.
// we need to keep it until after mMultiPic.close()
// procs is passed as a pointer, but just as a method of having an optional default.
- // procs doesn't need to outlive this Make call.
- mMultiPic = SkMakeMultiPictureDocument(mOpenMultiPicStream.get(), &procs);
+ // procs doesn't need to outlive this Make call
+ // The last argument is a callback for the endPage behavior.
+ // See SkSharingProc.h for more explanation of this callback.
+ mMultiPic = SkMakeMultiPictureDocument(
+ mOpenMultiPicStream.get(), &procs,
+ [sharingCtx = mSerialContext.get()](const SkPicture* pic) {
+ SkSharingSerialContext::collectNonTextureImagesFromPicture(pic, sharingCtx);
+ });
mCaptureRunning = true;
return true;
} else {
diff --git a/services/inputflinger/reader/InputDevice.cpp b/services/inputflinger/reader/InputDevice.cpp
index c7c8e7c..3e6910d 100644
--- a/services/inputflinger/reader/InputDevice.cpp
+++ b/services/inputflinger/reader/InputDevice.cpp
@@ -505,8 +505,7 @@
}
void InputDevice::notifyReset(nsecs_t when) {
- NotifyDeviceResetArgs args(mContext->getNextId(), when, mId);
- mContext->getListener()->notifyDeviceReset(&args);
+ mContext->notifyDeviceReset(when, mId);
}
std::optional<int32_t> InputDevice::getAssociatedDisplayId() {
diff --git a/services/inputflinger/reader/InputReader.cpp b/services/inputflinger/reader/InputReader.cpp
index 6c493ff..7c448e4 100644
--- a/services/inputflinger/reader/InputReader.cpp
+++ b/services/inputflinger/reader/InputReader.cpp
@@ -339,8 +339,7 @@
updateGlobalMetaStateLocked();
// Enqueue configuration changed.
- NotifyConfigurationChangedArgs args(mContext.getNextId(), when);
- mQueuedListener->notifyConfigurationChanged(&args);
+ mContext.notifyConfigurationChanged(when);
}
void InputReader::refreshConfigurationLocked(uint32_t changes) {
@@ -367,9 +366,7 @@
}
if (changes & InputReaderConfiguration::CHANGE_POINTER_CAPTURE) {
- const NotifyPointerCaptureChangedArgs args(mContext.getNextId(), now,
- mConfig.pointerCapture);
- mQueuedListener->notifyPointerCaptureChanged(&args);
+ mContext.notifyPointerCaptureChanged(now, mConfig.pointerCapture);
}
}
@@ -868,16 +865,64 @@
return mReader->mPolicy.get();
}
-InputListenerInterface* InputReader::ContextImpl::getListener() {
- return mReader->mQueuedListener.get();
-}
-
EventHubInterface* InputReader::ContextImpl::getEventHub() {
return mReader->mEventHub.get();
}
-int32_t InputReader::ContextImpl::getNextId() {
- return mIdGenerator.nextId();
+void InputReader::ContextImpl::notifyConfigurationChanged(nsecs_t when) {
+ NotifyConfigurationChangedArgs args(mIdGenerator.nextId(), when);
+ mReader->mQueuedListener->notifyConfigurationChanged(&args);
+}
+
+void InputReader::ContextImpl::notifyKey(nsecs_t eventTime, int32_t deviceId, uint32_t source,
+ int32_t displayId, uint32_t policyFlags, int32_t action,
+ int32_t flags, int32_t keyCode, int32_t scanCode,
+ int32_t metaState, nsecs_t downTime) {
+ NotifyKeyArgs args(mIdGenerator.nextId(), eventTime, deviceId, source, displayId, policyFlags,
+ action, flags, keyCode, scanCode, metaState, downTime);
+ mReader->mQueuedListener->notifyKey(&args);
+}
+void InputReader::ContextImpl::notifyMotion(
+ nsecs_t eventTime, int32_t deviceId, uint32_t source, int32_t displayId,
+ uint32_t policyFlags, int32_t action, int32_t actionButton, int32_t flags,
+ int32_t metaState, int32_t buttonState, MotionClassification classification,
+ int32_t edgeFlags, uint32_t pointerCount, const PointerProperties* pointerProperties,
+ const PointerCoords* pointerCoords, float xPrecision, float yPrecision,
+ float xCursorPosition, float yCursorPosition, nsecs_t downTime,
+ const std::vector<TouchVideoFrame>& videoFrames) {
+ NotifyMotionArgs args(mIdGenerator.nextId(), eventTime, deviceId, source, displayId,
+ policyFlags, action, actionButton, flags, metaState, buttonState,
+ classification, edgeFlags, pointerCount, pointerProperties, pointerCoords,
+ xPrecision, yPrecision, xCursorPosition, yCursorPosition, downTime,
+ videoFrames);
+ mReader->mQueuedListener->notifyMotion(&args);
+}
+
+void InputReader::ContextImpl::notifySensor(nsecs_t when, int32_t deviceId,
+ InputDeviceSensorType sensorType,
+ InputDeviceSensorAccuracy accuracy,
+ bool accuracyChanged, nsecs_t timestamp,
+ std::vector<float> values) {
+ NotifySensorArgs args(mIdGenerator.nextId(), when, deviceId, AINPUT_SOURCE_SENSOR, sensorType,
+ accuracy, accuracyChanged, timestamp, std::move(values));
+ mReader->mQueuedListener->notifySensor(&args);
+}
+
+void InputReader::ContextImpl::notifySwitch(nsecs_t eventTime, uint32_t switchValues,
+ uint32_t switchMask) {
+ NotifySwitchArgs args(mIdGenerator.nextId(), eventTime, 0 /*policyFlags*/, switchValues,
+ switchMask);
+ mReader->mQueuedListener->notifySwitch(&args);
+}
+
+void InputReader::ContextImpl::notifyDeviceReset(nsecs_t when, int32_t deviceId) {
+ NotifyDeviceResetArgs args(mIdGenerator.nextId(), when, deviceId);
+ mReader->mQueuedListener->notifyDeviceReset(&args);
+}
+
+void InputReader::ContextImpl::notifyPointerCaptureChanged(nsecs_t when, bool hasCapture) {
+ const NotifyPointerCaptureChangedArgs args(mIdGenerator.nextId(), when, hasCapture);
+ mReader->mQueuedListener->notifyPointerCaptureChanged(&args);
}
} // namespace android
diff --git a/services/inputflinger/reader/include/InputReader.h b/services/inputflinger/reader/include/InputReader.h
index 48d4596..7be932a 100644
--- a/services/inputflinger/reader/include/InputReader.h
+++ b/services/inputflinger/reader/include/InputReader.h
@@ -127,11 +127,30 @@
void dispatchExternalStylusState(const StylusState& outState)
NO_THREAD_SAFETY_ANALYSIS override;
InputReaderPolicyInterface* getPolicy() NO_THREAD_SAFETY_ANALYSIS override;
- InputListenerInterface* getListener() NO_THREAD_SAFETY_ANALYSIS override;
EventHubInterface* getEventHub() NO_THREAD_SAFETY_ANALYSIS override;
- int32_t getNextId() NO_THREAD_SAFETY_ANALYSIS override;
void updateLedMetaState(int32_t metaState) NO_THREAD_SAFETY_ANALYSIS override;
int32_t getLedMetaState() NO_THREAD_SAFETY_ANALYSIS override;
+
+ // Send events to InputListener interface
+ void notifyConfigurationChanged(nsecs_t when) override;
+ void notifyKey(nsecs_t eventTime, int32_t deviceId, uint32_t source, int32_t displayId,
+ uint32_t policyFlags, int32_t action, int32_t flags, int32_t keyCode,
+ int32_t scanCode, int32_t metaState, nsecs_t downTime) override;
+ void notifyMotion(nsecs_t eventTime, int32_t deviceId, uint32_t source, int32_t displayId,
+ uint32_t policyFlags, int32_t action, int32_t actionButton, int32_t flags,
+ int32_t metaState, int32_t buttonState,
+ MotionClassification classification, int32_t edgeFlags,
+ uint32_t pointerCount, const PointerProperties* pointerProperties,
+ const PointerCoords* pointerCoords, float xPrecision, float yPrecision,
+ float xCursorPosition, float yCursorPosition, nsecs_t downTime,
+ const std::vector<TouchVideoFrame>& videoFrames) override;
+ void notifySwitch(nsecs_t eventTime, uint32_t switchValues, uint32_t switchMask) override;
+ void notifySensor(nsecs_t when, int32_t deviceId, InputDeviceSensorType sensorType,
+ InputDeviceSensorAccuracy accuracy, bool accuracyChanged,
+ nsecs_t timestamp, std::vector<float> values) override;
+ void notifyDeviceReset(nsecs_t when, int32_t deviceId) override;
+ void notifyPointerCaptureChanged(nsecs_t when, bool hasCapture) override;
+
} mContext;
friend class ContextImpl;
diff --git a/services/inputflinger/reader/include/InputReaderContext.h b/services/inputflinger/reader/include/InputReaderContext.h
index dc807f7..edab312 100644
--- a/services/inputflinger/reader/include/InputReaderContext.h
+++ b/services/inputflinger/reader/include/InputReaderContext.h
@@ -55,13 +55,33 @@
virtual void dispatchExternalStylusState(const StylusState& outState) = 0;
virtual InputReaderPolicyInterface* getPolicy() = 0;
- virtual InputListenerInterface* getListener() = 0;
virtual EventHubInterface* getEventHub() = 0;
- virtual int32_t getNextId() = 0;
-
virtual void updateLedMetaState(int32_t metaState) = 0;
virtual int32_t getLedMetaState() = 0;
+
+ // Send events to InputListener interface
+
+ virtual void notifyConfigurationChanged(nsecs_t when) = 0;
+ virtual void notifyKey(nsecs_t eventTime, int32_t deviceId, uint32_t source, int32_t displayId,
+ uint32_t policyFlags, int32_t action, int32_t flags, int32_t keyCode,
+ int32_t scanCode, int32_t metaState, nsecs_t downTime) = 0;
+ virtual void notifyMotion(nsecs_t eventTime, int32_t deviceId, uint32_t source,
+ int32_t displayId, uint32_t policyFlags, int32_t action,
+ int32_t actionButton, int32_t flags, int32_t metaState,
+ int32_t buttonState, MotionClassification classification,
+ int32_t edgeFlags, uint32_t pointerCount,
+ const PointerProperties* pointerProperties,
+ const PointerCoords* pointerCoords, float xPrecision,
+ float yPrecision, float xCursorPosition, float yCursorPosition,
+ nsecs_t downTime,
+ const std::vector<TouchVideoFrame>& videoFrames) = 0;
+ virtual void notifySwitch(nsecs_t eventTime, uint32_t switchValues, uint32_t switchMask) = 0;
+ virtual void notifySensor(nsecs_t when, int32_t deviceId, InputDeviceSensorType sensorType,
+ InputDeviceSensorAccuracy accuracy, bool accuracyChanged,
+ nsecs_t timestamp, std::vector<float> values) = 0;
+ virtual void notifyDeviceReset(nsecs_t when, int32_t deviceId) = 0;
+ virtual void notifyPointerCaptureChanged(nsecs_t when, bool hasCapture) = 0;
};
} // namespace android
diff --git a/services/inputflinger/reader/mapper/CursorInputMapper.cpp b/services/inputflinger/reader/mapper/CursorInputMapper.cpp
index 254b64b..7f7b33c 100644
--- a/services/inputflinger/reader/mapper/CursorInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/CursorInputMapper.cpp
@@ -175,8 +175,7 @@
}
bumpGeneration();
if (changes) {
- NotifyDeviceResetArgs args(getContext()->getNextId(), when, getDeviceId());
- getListener()->notifyDeviceReset(&args);
+ getContext()->notifyDeviceReset(when, getDeviceId());
}
}
@@ -383,40 +382,35 @@
while (!released.isEmpty()) {
int32_t actionButton = BitSet32::valueForBit(released.clearFirstMarkedBit());
buttonState &= ~actionButton;
- NotifyMotionArgs releaseArgs(getContext()->getNextId(), when, getDeviceId(),
- mSource, displayId, policyFlags,
- AMOTION_EVENT_ACTION_BUTTON_RELEASE, actionButton, 0,
- metaState, buttonState, MotionClassification::NONE,
- AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerProperties,
- &pointerCoords, mXPrecision, mYPrecision,
- xCursorPosition, yCursorPosition, downTime,
- /* videoFrames */ {});
- getListener()->notifyMotion(&releaseArgs);
+ getContext()->notifyMotion(when, getDeviceId(), mSource, displayId, policyFlags,
+ AMOTION_EVENT_ACTION_BUTTON_RELEASE, actionButton, 0,
+ metaState, buttonState, MotionClassification::NONE,
+ AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerProperties,
+ &pointerCoords, mXPrecision, mYPrecision,
+ xCursorPosition, yCursorPosition, downTime,
+ /* videoFrames */ {});
}
}
- NotifyMotionArgs args(getContext()->getNextId(), when, getDeviceId(), mSource, displayId,
- policyFlags, motionEventAction, 0, 0, metaState, currentButtonState,
- MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, 1,
- &pointerProperties, &pointerCoords, mXPrecision, mYPrecision,
- xCursorPosition, yCursorPosition, downTime,
- /* videoFrames */ {});
- getListener()->notifyMotion(&args);
+ getContext()->notifyMotion(when, getDeviceId(), mSource, displayId, policyFlags,
+ motionEventAction, 0, 0, metaState, currentButtonState,
+ MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, 1,
+ &pointerProperties, &pointerCoords, mXPrecision, mYPrecision,
+ xCursorPosition, yCursorPosition, downTime,
+ /* videoFrames */ {});
if (buttonsPressed) {
BitSet32 pressed(buttonsPressed);
while (!pressed.isEmpty()) {
int32_t actionButton = BitSet32::valueForBit(pressed.clearFirstMarkedBit());
buttonState |= actionButton;
- NotifyMotionArgs pressArgs(getContext()->getNextId(), when, getDeviceId(), mSource,
- displayId, policyFlags,
+ getContext()->notifyMotion(when, getDeviceId(), mSource, displayId, policyFlags,
AMOTION_EVENT_ACTION_BUTTON_PRESS, actionButton, 0,
metaState, buttonState, MotionClassification::NONE,
AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerProperties,
&pointerCoords, mXPrecision, mYPrecision,
xCursorPosition, yCursorPosition, downTime,
/* videoFrames */ {});
- getListener()->notifyMotion(&pressArgs);
}
}
@@ -424,13 +418,12 @@
// Send hover move after UP to tell the application that the mouse is hovering now.
if (motionEventAction == AMOTION_EVENT_ACTION_UP && (mSource == AINPUT_SOURCE_MOUSE)) {
- NotifyMotionArgs hoverArgs(getContext()->getNextId(), when, getDeviceId(), mSource,
- displayId, policyFlags, AMOTION_EVENT_ACTION_HOVER_MOVE, 0,
- 0, metaState, currentButtonState, MotionClassification::NONE,
+ getContext()->notifyMotion(when, getDeviceId(), mSource, displayId, policyFlags,
+ AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0, metaState,
+ currentButtonState, MotionClassification::NONE,
AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerProperties,
&pointerCoords, mXPrecision, mYPrecision, xCursorPosition,
yCursorPosition, downTime, /* videoFrames */ {});
- getListener()->notifyMotion(&hoverArgs);
}
// Send scroll events.
@@ -438,13 +431,12 @@
pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_VSCROLL, vscroll);
pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, hscroll);
- NotifyMotionArgs scrollArgs(getContext()->getNextId(), when, getDeviceId(), mSource,
- displayId, policyFlags, AMOTION_EVENT_ACTION_SCROLL, 0, 0,
- metaState, currentButtonState, MotionClassification::NONE,
- AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerProperties,
- &pointerCoords, mXPrecision, mYPrecision, xCursorPosition,
- yCursorPosition, downTime, /* videoFrames */ {});
- getListener()->notifyMotion(&scrollArgs);
+ getContext()->notifyMotion(when, getDeviceId(), mSource, displayId, policyFlags,
+ AMOTION_EVENT_ACTION_SCROLL, 0, 0, metaState,
+ currentButtonState, MotionClassification::NONE,
+ AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerProperties,
+ &pointerCoords, mXPrecision, mYPrecision, xCursorPosition,
+ yCursorPosition, downTime, /* videoFrames */ {});
}
}
diff --git a/services/inputflinger/reader/mapper/InputMapper.h b/services/inputflinger/reader/mapper/InputMapper.h
index bd64d8d..6ca6ec9 100644
--- a/services/inputflinger/reader/mapper/InputMapper.h
+++ b/services/inputflinger/reader/mapper/InputMapper.h
@@ -19,7 +19,6 @@
#include "EventHub.h"
#include "InputDevice.h"
-#include "InputListener.h"
#include "InputReaderContext.h"
#include "StylusState.h"
#include "VibrationElement.h"
@@ -48,7 +47,6 @@
inline const std::string getDeviceName() { return mDeviceContext.getName(); }
inline InputReaderContext* getContext() { return mDeviceContext.getContext(); }
inline InputReaderPolicyInterface* getPolicy() { return getContext()->getPolicy(); }
- inline InputListenerInterface* getListener() { return getContext()->getListener(); }
virtual uint32_t getSources() = 0;
virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo);
diff --git a/services/inputflinger/reader/mapper/JoystickInputMapper.cpp b/services/inputflinger/reader/mapper/JoystickInputMapper.cpp
index abd8aa9..ac4669c 100644
--- a/services/inputflinger/reader/mapper/JoystickInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/JoystickInputMapper.cpp
@@ -337,13 +337,12 @@
// TODO: Use the input device configuration to control this behavior more finely.
uint32_t policyFlags = 0;
- NotifyMotionArgs args(getContext()->getNextId(), when, getDeviceId(), AINPUT_SOURCE_JOYSTICK,
- ADISPLAY_ID_NONE, policyFlags, AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState,
- buttonState, MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, 1,
- &pointerProperties, &pointerCoords, 0, 0,
- AMOTION_EVENT_INVALID_CURSOR_POSITION,
- AMOTION_EVENT_INVALID_CURSOR_POSITION, 0, /* videoFrames */ {});
- getListener()->notifyMotion(&args);
+ getContext()->notifyMotion(when, getDeviceId(), AINPUT_SOURCE_JOYSTICK, ADISPLAY_ID_NONE,
+ policyFlags, AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState, buttonState,
+ MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, 1,
+ &pointerProperties, &pointerCoords, 0, 0,
+ AMOTION_EVENT_INVALID_CURSOR_POSITION,
+ AMOTION_EVENT_INVALID_CURSOR_POSITION, 0, /* videoFrames */ {});
}
void JoystickInputMapper::setPointerCoordsAxisValue(PointerCoords* pointerCoords, int32_t axis,
diff --git a/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp b/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp
index 8b9f235..03d7405 100644
--- a/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp
@@ -350,10 +350,9 @@
policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
}
- NotifyKeyArgs args(getContext()->getNextId(), when, getDeviceId(), mSource, getDisplayId(),
- policyFlags, down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,
- AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, keyMetaState, downTime);
- getListener()->notifyKey(&args);
+ getContext()->notifyKey(when, getDeviceId(), mSource, getDisplayId(), policyFlags,
+ down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,
+ AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, keyMetaState, downTime);
}
ssize_t KeyboardInputMapper::findKeyDown(int32_t scanCode) {
diff --git a/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.cpp b/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.cpp
index 594ff42..3f8a364 100644
--- a/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.cpp
@@ -121,13 +121,12 @@
int32_t metaState = getContext()->getGlobalMetaState();
pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_SCROLL, scroll * mScalingFactor);
- NotifyMotionArgs scrollArgs(getContext()->getNextId(), when, getDeviceId(), mSource,
- displayId, policyFlags, AMOTION_EVENT_ACTION_SCROLL, 0, 0,
- metaState, /* buttonState */ 0, MotionClassification::NONE,
- AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerProperties,
- &pointerCoords, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
- AMOTION_EVENT_INVALID_CURSOR_POSITION, 0, /* videoFrames */ {});
- getListener()->notifyMotion(&scrollArgs);
+ getContext()->notifyMotion(when, getDeviceId(), mSource, displayId, policyFlags,
+ AMOTION_EVENT_ACTION_SCROLL, 0, 0, metaState,
+ /* buttonState */ 0, MotionClassification::NONE,
+ AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerProperties,
+ &pointerCoords, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
+ AMOTION_EVENT_INVALID_CURSOR_POSITION, 0, /* videoFrames */ {});
}
mRotaryEncoderScrollAccumulator.finishSync();
diff --git a/services/inputflinger/reader/mapper/SensorInputMapper.cpp b/services/inputflinger/reader/mapper/SensorInputMapper.cpp
index 7ac2dec..68c1e40 100644
--- a/services/inputflinger/reader/mapper/SensorInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/SensorInputMapper.cpp
@@ -405,13 +405,10 @@
// Convert to Android unit
convertFromLinuxToAndroid(values, sensorType);
// Notify dispatcher for sensor event
- NotifySensorArgs args(getContext()->getNextId(), when, getDeviceId(),
- AINPUT_SOURCE_SENSOR, sensorType, sensor.sensorInfo.accuracy,
- sensor.accuracy !=
- sensor.sensorInfo.accuracy /* accuracyChanged */,
- timestamp /* hwTimestamp */, values);
-
- getListener()->notifySensor(&args);
+ getContext()->notifySensor(when, getDeviceId(), sensorType, sensor.sensorInfo.accuracy,
+ sensor.accuracy !=
+ sensor.sensorInfo.accuracy /* accuracyChanged */,
+ timestamp /* hwTimestamp */, std::move(values));
sensor.lastSampleTimeNs = timestamp;
sensor.accuracy = sensor.sensorInfo.accuracy;
}
diff --git a/services/inputflinger/reader/mapper/SwitchInputMapper.cpp b/services/inputflinger/reader/mapper/SwitchInputMapper.cpp
index 4f73681..07de244 100644
--- a/services/inputflinger/reader/mapper/SwitchInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/SwitchInputMapper.cpp
@@ -56,10 +56,7 @@
void SwitchInputMapper::sync(nsecs_t when) {
if (mUpdatedSwitchMask) {
uint32_t updatedSwitchValues = mSwitchValues & mUpdatedSwitchMask;
- NotifySwitchArgs args(getContext()->getNextId(), when, 0 /*policyFlags*/,
- updatedSwitchValues, mUpdatedSwitchMask);
- getListener()->notifySwitch(&args);
-
+ getContext()->notifySwitch(when, updatedSwitchValues, mUpdatedSwitchMask);
mUpdatedSwitchMask = 0;
}
}
diff --git a/services/inputflinger/reader/mapper/TouchCursorInputMapperCommon.h b/services/inputflinger/reader/mapper/TouchCursorInputMapperCommon.h
index a86443d..ff6341f 100644
--- a/services/inputflinger/reader/mapper/TouchCursorInputMapperCommon.h
+++ b/services/inputflinger/reader/mapper/TouchCursorInputMapperCommon.h
@@ -66,9 +66,8 @@
(currentButtonState & buttonState)) ||
(action == AKEY_EVENT_ACTION_UP && (lastButtonState & buttonState) &&
!(currentButtonState & buttonState))) {
- NotifyKeyArgs args(context->getNextId(), when, deviceId, source, displayId, policyFlags,
- action, 0, keyCode, 0, context->getGlobalMetaState(), when);
- context->getListener()->notifyKey(&args);
+ context->notifyKey(when, deviceId, source, displayId, policyFlags, action, 0 /*flags*/,
+ keyCode, 0 /*scanCode*/, context->getGlobalMetaState(), when);
}
}
diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.cpp b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
index 18168d8..fb30b88 100644
--- a/services/inputflinger/reader/mapper/TouchInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
@@ -397,8 +397,7 @@
if (changes && resetNeeded) {
// Send reset, unless this is the first time the device has been configured,
// in which case the reader will call reset itself after all mappers are ready.
- NotifyDeviceResetArgs args(getContext()->getNextId(), when, getDeviceId());
- getListener()->notifyDeviceReset(&args);
+ getContext()->notifyDeviceReset(when, getDeviceId());
}
}
@@ -1829,10 +1828,9 @@
int32_t metaState = getContext()->getGlobalMetaState();
policyFlags |= POLICY_FLAG_VIRTUAL;
- NotifyKeyArgs args(getContext()->getNextId(), when, getDeviceId(), AINPUT_SOURCE_KEYBOARD,
- mViewport.displayId, policyFlags, keyEventAction, keyEventFlags, keyCode,
- scanCode, metaState, downTime);
- getListener()->notifyKey(&args);
+ getContext()->notifyKey(when, getDeviceId(), AINPUT_SOURCE_KEYBOARD, mViewport.displayId,
+ policyFlags, keyEventAction, keyEventFlags, keyCode, scanCode,
+ metaState, downTime);
}
void TouchInputMapper::abortTouches(nsecs_t when, uint32_t policyFlags) {
@@ -2508,12 +2506,11 @@
pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
const int32_t displayId = mPointerController->getDisplayId();
- NotifyMotionArgs args(getContext()->getNextId(), when, getDeviceId(), mSource, displayId,
- policyFlags, AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0, metaState,
- buttonState, MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE,
- 1, &pointerProperties, &pointerCoords, 0, 0, x, y,
- mPointerGesture.downTime, /* videoFrames */ {});
- getListener()->notifyMotion(&args);
+ getContext()->notifyMotion(when, getDeviceId(), mSource, displayId, policyFlags,
+ AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0, metaState, buttonState,
+ MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, 1,
+ &pointerProperties, &pointerCoords, 0, 0, x, y,
+ mPointerGesture.downTime, /* videoFrames */ {});
}
// Update state.
@@ -3428,28 +3425,28 @@
mPointerSimple.down = false;
// Send up.
- NotifyMotionArgs args(getContext()->getNextId(), when, getDeviceId(), mSource, displayId,
- policyFlags, AMOTION_EVENT_ACTION_UP, 0, 0, metaState,
- mLastRawState.buttonState, MotionClassification::NONE,
- AMOTION_EVENT_EDGE_FLAG_NONE, 1, &mPointerSimple.lastProperties,
- &mPointerSimple.lastCoords, mOrientedXPrecision, mOrientedYPrecision,
- xCursorPosition, yCursorPosition, mPointerSimple.downTime,
- /* videoFrames */ {});
- getListener()->notifyMotion(&args);
+ getContext()->notifyMotion(when, getDeviceId(), mSource, displayId, policyFlags,
+ AMOTION_EVENT_ACTION_UP, 0, 0, metaState,
+ mLastRawState.buttonState, MotionClassification::NONE,
+ AMOTION_EVENT_EDGE_FLAG_NONE, 1, &mPointerSimple.lastProperties,
+ &mPointerSimple.lastCoords, mOrientedXPrecision,
+ mOrientedYPrecision, xCursorPosition, yCursorPosition,
+ mPointerSimple.downTime,
+ /* videoFrames */ {});
}
if (mPointerSimple.hovering && !hovering) {
mPointerSimple.hovering = false;
// Send hover exit.
- NotifyMotionArgs args(getContext()->getNextId(), when, getDeviceId(), mSource, displayId,
- policyFlags, AMOTION_EVENT_ACTION_HOVER_EXIT, 0, 0, metaState,
- mLastRawState.buttonState, MotionClassification::NONE,
- AMOTION_EVENT_EDGE_FLAG_NONE, 1, &mPointerSimple.lastProperties,
- &mPointerSimple.lastCoords, mOrientedXPrecision, mOrientedYPrecision,
- xCursorPosition, yCursorPosition, mPointerSimple.downTime,
- /* videoFrames */ {});
- getListener()->notifyMotion(&args);
+ getContext()->notifyMotion(when, getDeviceId(), mSource, displayId, policyFlags,
+ AMOTION_EVENT_ACTION_HOVER_EXIT, 0, 0, metaState,
+ mLastRawState.buttonState, MotionClassification::NONE,
+ AMOTION_EVENT_EDGE_FLAG_NONE, 1, &mPointerSimple.lastProperties,
+ &mPointerSimple.lastCoords, mOrientedXPrecision,
+ mOrientedYPrecision, xCursorPosition, yCursorPosition,
+ mPointerSimple.downTime,
+ /* videoFrames */ {});
}
if (down) {
@@ -3458,25 +3455,24 @@
mPointerSimple.downTime = when;
// Send down.
- NotifyMotionArgs args(getContext()->getNextId(), when, getDeviceId(), mSource,
- displayId, policyFlags, AMOTION_EVENT_ACTION_DOWN, 0, 0,
- metaState, mCurrentRawState.buttonState,
- MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, 1,
- &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
- mOrientedXPrecision, mOrientedYPrecision, xCursorPosition,
- yCursorPosition, mPointerSimple.downTime, /* videoFrames */ {});
- getListener()->notifyMotion(&args);
+ getContext()->notifyMotion(when, getDeviceId(), mSource, displayId, policyFlags,
+ AMOTION_EVENT_ACTION_DOWN, 0, 0, metaState,
+ mCurrentRawState.buttonState, MotionClassification::NONE,
+ AMOTION_EVENT_EDGE_FLAG_NONE, 1,
+ &mPointerSimple.currentProperties,
+ &mPointerSimple.currentCoords, mOrientedXPrecision,
+ mOrientedYPrecision, xCursorPosition, yCursorPosition,
+ mPointerSimple.downTime, /* videoFrames */ {});
}
// Send move.
- NotifyMotionArgs args(getContext()->getNextId(), when, getDeviceId(), mSource, displayId,
- policyFlags, AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState,
- mCurrentRawState.buttonState, MotionClassification::NONE,
- AMOTION_EVENT_EDGE_FLAG_NONE, 1, &mPointerSimple.currentProperties,
- &mPointerSimple.currentCoords, mOrientedXPrecision,
- mOrientedYPrecision, xCursorPosition, yCursorPosition,
- mPointerSimple.downTime, /* videoFrames */ {});
- getListener()->notifyMotion(&args);
+ getContext()->notifyMotion(when, getDeviceId(), mSource, displayId, policyFlags,
+ AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState,
+ mCurrentRawState.buttonState, MotionClassification::NONE,
+ AMOTION_EVENT_EDGE_FLAG_NONE, 1,
+ &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
+ mOrientedXPrecision, mOrientedYPrecision, xCursorPosition,
+ yCursorPosition, mPointerSimple.downTime, /* videoFrames */ {});
}
if (hovering) {
@@ -3484,25 +3480,24 @@
mPointerSimple.hovering = true;
// Send hover enter.
- NotifyMotionArgs args(getContext()->getNextId(), when, getDeviceId(), mSource,
- displayId, policyFlags, AMOTION_EVENT_ACTION_HOVER_ENTER, 0, 0,
- metaState, mCurrentRawState.buttonState,
- MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, 1,
- &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
- mOrientedXPrecision, mOrientedYPrecision, xCursorPosition,
- yCursorPosition, mPointerSimple.downTime, /* videoFrames */ {});
- getListener()->notifyMotion(&args);
+ getContext()->notifyMotion(when, getDeviceId(), mSource, displayId, policyFlags,
+ AMOTION_EVENT_ACTION_HOVER_ENTER, 0, 0, metaState,
+ mCurrentRawState.buttonState, MotionClassification::NONE,
+ AMOTION_EVENT_EDGE_FLAG_NONE, 1,
+ &mPointerSimple.currentProperties,
+ &mPointerSimple.currentCoords, mOrientedXPrecision,
+ mOrientedYPrecision, xCursorPosition, yCursorPosition,
+ mPointerSimple.downTime, /* videoFrames */ {});
}
// Send hover move.
- NotifyMotionArgs args(getContext()->getNextId(), when, getDeviceId(), mSource, displayId,
- policyFlags, AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0, metaState,
- mCurrentRawState.buttonState, MotionClassification::NONE,
- AMOTION_EVENT_EDGE_FLAG_NONE, 1, &mPointerSimple.currentProperties,
- &mPointerSimple.currentCoords, mOrientedXPrecision,
- mOrientedYPrecision, xCursorPosition, yCursorPosition,
- mPointerSimple.downTime, /* videoFrames */ {});
- getListener()->notifyMotion(&args);
+ getContext()->notifyMotion(when, getDeviceId(), mSource, displayId, policyFlags,
+ AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0, metaState,
+ mCurrentRawState.buttonState, MotionClassification::NONE,
+ AMOTION_EVENT_EDGE_FLAG_NONE, 1,
+ &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
+ mOrientedXPrecision, mOrientedYPrecision, xCursorPosition,
+ yCursorPosition, mPointerSimple.downTime, /* videoFrames */ {});
}
if (mCurrentRawState.rawVScroll || mCurrentRawState.rawHScroll) {
@@ -3517,14 +3512,14 @@
pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_VSCROLL, vscroll);
pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, hscroll);
- NotifyMotionArgs args(getContext()->getNextId(), when, getDeviceId(), mSource, displayId,
- policyFlags, AMOTION_EVENT_ACTION_SCROLL, 0, 0, metaState,
- mCurrentRawState.buttonState, MotionClassification::NONE,
- AMOTION_EVENT_EDGE_FLAG_NONE, 1, &mPointerSimple.currentProperties,
- &pointerCoords, mOrientedXPrecision, mOrientedYPrecision,
- xCursorPosition, yCursorPosition, mPointerSimple.downTime,
- /* videoFrames */ {});
- getListener()->notifyMotion(&args);
+ getContext()->notifyMotion(when, getDeviceId(), mSource, displayId, policyFlags,
+ AMOTION_EVENT_ACTION_SCROLL, 0, 0, metaState,
+ mCurrentRawState.buttonState, MotionClassification::NONE,
+ AMOTION_EVENT_EDGE_FLAG_NONE, 1,
+ &mPointerSimple.currentProperties, &pointerCoords,
+ mOrientedXPrecision, mOrientedYPrecision, xCursorPosition,
+ yCursorPosition, mPointerSimple.downTime,
+ /* videoFrames */ {});
}
// Save state.
@@ -3595,12 +3590,11 @@
std::vector<TouchVideoFrame> frames = getDeviceContext().getVideoFrames();
std::for_each(frames.begin(), frames.end(),
[this](TouchVideoFrame& frame) { frame.rotate(this->mSurfaceOrientation); });
- NotifyMotionArgs args(getContext()->getNextId(), when, deviceId, source, displayId, policyFlags,
- action, actionButton, flags, metaState, buttonState,
- MotionClassification::NONE, edgeFlags, pointerCount, pointerProperties,
- pointerCoords, xPrecision, yPrecision, xCursorPosition, yCursorPosition,
- downTime, std::move(frames));
- getListener()->notifyMotion(&args);
+ getContext()->notifyMotion(when, deviceId, source, displayId, policyFlags, action, actionButton,
+ flags, metaState, buttonState, MotionClassification::NONE, edgeFlags,
+ pointerCount, pointerProperties, pointerCoords, xPrecision,
+ yPrecision, xCursorPosition, yCursorPosition, downTime,
+ std::move(frames));
}
bool TouchInputMapper::updateMovedPointers(const PointerProperties* inProperties,
diff --git a/services/powermanager/PowerHalWrapper.cpp b/services/powermanager/PowerHalWrapper.cpp
index 4a711ca..2f32827 100644
--- a/services/powermanager/PowerHalWrapper.cpp
+++ b/services/powermanager/PowerHalWrapper.cpp
@@ -114,14 +114,15 @@
HalResult AidlHalWrapper::setBoost(Boost boost, int32_t durationMs) {
std::unique_lock<std::mutex> lock(mBoostMutex);
+ size_t idx = static_cast<size_t>(boost);
+
// Quick return if boost is not supported by HAL
- if (boost > Boost::DISPLAY_UPDATE_IMMINENT ||
- mBoostSupportedArray[static_cast<int32_t>(boost)] == HalSupport::OFF) {
+ if (idx >= mBoostSupportedArray.size() || mBoostSupportedArray[idx] == HalSupport::OFF) {
ALOGV("Skipped setBoost %s because Power HAL doesn't support it", toString(boost).c_str());
return HalResult::UNSUPPORTED;
}
- if (mBoostSupportedArray[static_cast<int32_t>(boost)] == HalSupport::UNKNOWN) {
+ if (mBoostSupportedArray[idx] == HalSupport::UNKNOWN) {
bool isSupported = false;
auto isSupportedRet = mHandle->isBoostSupported(boost, &isSupported);
if (!isSupportedRet.isOk()) {
@@ -130,8 +131,7 @@
return HalResult::FAILED;
}
- mBoostSupportedArray[static_cast<int32_t>(boost)] =
- isSupported ? HalSupport::ON : HalSupport::OFF;
+ mBoostSupportedArray[idx] = isSupported ? HalSupport::ON : HalSupport::OFF;
if (!isSupported) {
ALOGV("Skipped setBoost %s because Power HAL doesn't support it",
toString(boost).c_str());
@@ -145,14 +145,15 @@
HalResult AidlHalWrapper::setMode(Mode mode, bool enabled) {
std::unique_lock<std::mutex> lock(mModeMutex);
+ size_t idx = static_cast<size_t>(mode);
+
// Quick return if mode is not supported by HAL
- if (mode > Mode::DISPLAY_INACTIVE ||
- mModeSupportedArray[static_cast<int32_t>(mode)] == HalSupport::OFF) {
+ if (idx >= mModeSupportedArray.size() || mModeSupportedArray[idx] == HalSupport::OFF) {
ALOGV("Skipped setMode %s because Power HAL doesn't support it", toString(mode).c_str());
return HalResult::UNSUPPORTED;
}
- if (mModeSupportedArray[static_cast<int32_t>(mode)] == HalSupport::UNKNOWN) {
+ if (mModeSupportedArray[idx] == HalSupport::UNKNOWN) {
bool isSupported = false;
auto isSupportedRet = mHandle->isModeSupported(mode, &isSupported);
if (!isSupportedRet.isOk()) {
@@ -161,8 +162,7 @@
return HalResult::FAILED;
}
- mModeSupportedArray[static_cast<int32_t>(mode)] =
- isSupported ? HalSupport::ON : HalSupport::OFF;
+ mModeSupportedArray[idx] = isSupported ? HalSupport::ON : HalSupport::OFF;
if (!isSupported) {
ALOGV("Skipped setMode %s because Power HAL doesn't support it",
toString(mode).c_str());
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index ad08f82..0cc15c2 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -335,7 +335,8 @@
bool BufferStateLayer::setBuffer(const sp<GraphicBuffer>& buffer, const sp<Fence>& acquireFence,
nsecs_t postTime, nsecs_t desiredPresentTime, bool isAutoTimestamp,
- const client_cache_t& clientCacheId, uint64_t frameNumber) {
+ const client_cache_t& clientCacheId, uint64_t frameNumber,
+ std::optional<nsecs_t> /* dequeueTime */) {
ATRACE_CALL();
if (mCurrentState.buffer) {
@@ -636,7 +637,10 @@
if (s.buffer == nullptr) {
return BAD_VALUE;
}
- decrementPendingBufferCount();
+
+ if (s.buffer != mBufferInfo.mBuffer) {
+ decrementPendingBufferCount();
+ }
mPreviousBufferId = getCurrentBufferId();
mBufferInfo.mBuffer = s.buffer;
diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h
index bc508e3..f638caa 100644
--- a/services/surfaceflinger/BufferStateLayer.h
+++ b/services/surfaceflinger/BufferStateLayer.h
@@ -71,7 +71,8 @@
bool setFrame(const Rect& frame) override;
bool setBuffer(const sp<GraphicBuffer>& buffer, const sp<Fence>& acquireFence, nsecs_t postTime,
nsecs_t desiredPresentTime, bool isAutoTimestamp,
- const client_cache_t& clientCacheId, uint64_t frameNumber) override;
+ const client_cache_t& clientCacheId, uint64_t frameNumber,
+ std::optional<nsecs_t> dequeueTime) override;
bool setAcquireFence(const sp<Fence>& fence) override;
bool setDataspace(ui::Dataspace dataspace) override;
bool setHdrMetadata(const HdrMetadata& hdrMetadata) override;
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index d6023b6..f78b5f3 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -446,7 +446,7 @@
virtual bool setBuffer(const sp<GraphicBuffer>& /*buffer*/, const sp<Fence>& /*acquireFence*/,
nsecs_t /*postTime*/, nsecs_t /*desiredPresentTime*/,
bool /*isAutoTimestamp*/, const client_cache_t& /*clientCacheId*/,
- uint64_t /* frameNumber */) {
+ uint64_t /* frameNumber */, std::optional<nsecs_t> /* dequeueTime */) {
return false;
};
virtual bool setAcquireFence(const sp<Fence>& /*fence*/) { return false; };
diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp
index 6a511a8..32110e9 100644
--- a/services/surfaceflinger/RefreshRateOverlay.cpp
+++ b/services/surfaceflinger/RefreshRateOverlay.cpp
@@ -237,7 +237,8 @@
mCurrentFps = refreshRate.getFps().getIntValue();
auto buffer = getOrCreateBuffers(*mCurrentFps)[mFrame];
mLayer->setBuffer(buffer, Fence::NO_FENCE, 0, 0, true, {},
- mLayer->getHeadFrameNumber(-1 /* expectedPresentTime */));
+ mLayer->getHeadFrameNumber(-1 /* expectedPresentTime */),
+ std::nullopt /* dequeueTime */);
mFlinger.mTransactionFlags.fetch_or(eTransactionMask);
}
@@ -249,7 +250,8 @@
mFrame = (mFrame + 1) % buffers.size();
auto buffer = buffers[mFrame];
mLayer->setBuffer(buffer, Fence::NO_FENCE, 0, 0, true, {},
- mLayer->getHeadFrameNumber(-1 /* expectedPresentTime */));
+ mLayer->getHeadFrameNumber(-1 /* expectedPresentTime */),
+ std::nullopt /* dequeueTime */);
mFlinger.mTransactionFlags.fetch_or(eTransactionMask);
}
diff --git a/services/surfaceflinger/StartPropertySetThread.cpp b/services/surfaceflinger/StartPropertySetThread.cpp
index db82772..f42cd53 100644
--- a/services/surfaceflinger/StartPropertySetThread.cpp
+++ b/services/surfaceflinger/StartPropertySetThread.cpp
@@ -31,6 +31,7 @@
property_set(kTimestampProperty, mTimestampPropertyValue ? "1" : "0");
// Clear BootAnimation exit flag
property_set("service.bootanim.exit", "0");
+ property_set("service.bootanim.progress", "0");
// Start BootAnimation if not started
property_set("ctl.start", "bootanim");
// Exit immediately
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 6967f69..44c7f96 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1994,11 +1994,6 @@
mScheduler->onDisplayRefreshed(presentTime);
- // Set presentation information before calling postComposition, such that jank information from
- // this' frame classification is already available when sending jank info to clients.
- mFrameTimeline->setSfPresent(systemTime(),
- std::make_shared<FenceTime>(mPreviousPresentFences[0]));
-
postFrame();
postComposition();
@@ -2120,11 +2115,6 @@
ATRACE_CALL();
ALOGV("postComposition");
- nsecs_t dequeueReadyTime = systemTime();
- for (const auto& layer : mLayersWithQueuedFrames) {
- layer->releasePendingBuffer(dequeueReadyTime);
- }
-
const auto* display = ON_MAIN_THREAD(getDefaultDisplayDeviceLocked()).get();
getBE().mGlCompositionDoneTimeline.updateSignalTimes();
@@ -2146,6 +2136,17 @@
auto presentFenceTime = std::make_shared<FenceTime>(mPreviousPresentFences[0]);
getBE().mDisplayTimeline.push(presentFenceTime);
+ // Set presentation information before calling Layer::releasePendingBuffer, such that jank
+ // information from previous' frame classification is already available when sending jank info
+ // to clients, so they get jank classification as early as possible.
+ mFrameTimeline->setSfPresent(systemTime(),
+ std::make_shared<FenceTime>(mPreviousPresentFences[0]));
+
+ nsecs_t dequeueReadyTime = systemTime();
+ for (const auto& layer : mLayersWithQueuedFrames) {
+ layer->releasePendingBuffer(dequeueReadyTime);
+ }
+
const DisplayStatInfo stats = mScheduler->getDisplayStatInfo(systemTime());
// We use the CompositionEngine::getLastFrameRefreshTimestamp() which might
@@ -3376,8 +3377,10 @@
const int originPid = ipc->getCallingPid();
const int originUid = ipc->getCallingUid();
- if (pendingTransactions ||
- !transactionIsReadyToBeApplied(isAutoTimestamp ? 0 : desiredPresentTime, states, true)) {
+ // Call transactionIsReadyToBeApplied first in case we need to incrementPendingBufferCount
+ // if the transaction contains a buffer.
+ if (!transactionIsReadyToBeApplied(isAutoTimestamp ? 0 : desiredPresentTime, states, true) ||
+ pendingTransactions) {
mTransactionQueues[applyToken].emplace(frameTimelineVsyncId, states, displays, flags,
desiredPresentTime, isAutoTimestamp, uncacheBuffer,
postTime, privileged, hasListenerCallbacks,
@@ -3840,7 +3843,9 @@
ALOGE("Attempt to update InputWindowInfo without permission ACCESS_SURFACE_FLINGER");
}
}
+ std::optional<nsecs_t> dequeueBufferTimestamp;
if (what & layer_state_t::eMetadataChanged) {
+ dequeueBufferTimestamp = s.metadata.getInt64(METADATA_DEQUEUE_TIME);
if (layer->setMetadata(s.metadata)) flags |= eTraversalNeeded;
}
if (what & layer_state_t::eColorSpaceAgnosticChanged) {
@@ -3928,7 +3933,7 @@
: layer->getHeadFrameNumber(-1 /* expectedPresentTime */) + 1;
if (layer->setBuffer(buffer, s.acquireFence, postTime, desiredPresentTime, isAutoTimestamp,
- s.cachedBuffer, frameNumber)) {
+ s.cachedBuffer, frameNumber, dequeueBufferTimestamp)) {
flags |= eTraversalNeeded;
}
}
@@ -4507,12 +4512,9 @@
void SurfaceFlinger::dumpFrameEventsLocked(std::string& result) {
result.append("Layer frame timestamps:\n");
-
- const LayerVector& currentLayers = mCurrentState.layersSortedByZ;
- const size_t count = currentLayers.size();
- for (size_t i=0 ; i<count ; i++) {
- currentLayers[i]->dumpFrameEvents(result);
- }
+ // Traverse all layers to dump frame-events for each layer
+ mCurrentState.traverseInZOrder(
+ [&] (Layer* layer) { layer->dumpFrameEvents(result); });
}
void SurfaceFlinger::dumpBufferingStats(std::string& result) const {