Merge "Kawase blur filter"
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index 4a84884..0473bb8 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -8,6 +8,7 @@
include/input/
libs/binder/fuzzer/
libs/binder/ndk/
+ libs/binderthreadstate/
libs/graphicsenv/
libs/gui/
libs/input/
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index a20db24..312db67 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -155,6 +155,8 @@
#define WLUTIL "/vendor/xbin/wlutil"
#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.
@@ -1532,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;
@@ -1563,6 +1568,7 @@
ds.AddDir(RECOVERY_DATA_DIR, true);
ds.AddDir(UPDATE_ENGINE_LOG_DIR, true);
ds.AddDir(LOGPERSIST_DATA_DIR, false);
+ ds.AddDir(SNAPSHOTCTL_LOG_DIR, false);
if (!PropertiesHelper::IsUserBuild()) {
ds.AddDir(PROFILE_DATA_DIR_CUR, true);
ds.AddDir(PROFILE_DATA_DIR_REF, true);
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index cfd6a3e..08d4657 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -1102,7 +1102,7 @@
binder::Status InstalldNativeService::moveCompleteApp(const std::unique_ptr<std::string>& fromUuid,
const std::unique_ptr<std::string>& toUuid, const std::string& packageName,
const std::string& dataAppName, int32_t appId, const std::string& seInfo,
- int32_t targetSdkVersion) {
+ int32_t targetSdkVersion, const std::string& fromCodePath) {
ENFORCE_UID(AID_SYSTEM);
CHECK_ARGUMENT_UUID(fromUuid);
CHECK_ARGUMENT_UUID(toUuid);
@@ -1119,13 +1119,12 @@
// Copy app
{
- auto from = create_data_app_package_path(from_uuid, data_app_name);
auto to = create_data_app_package_path(to_uuid, data_app_name);
auto to_parent = create_data_app_path(to_uuid);
- int rc = copy_directory_recursive(from.c_str(), to_parent.c_str());
+ int rc = copy_directory_recursive(fromCodePath.c_str(), to_parent.c_str());
if (rc != 0) {
- res = error(rc, "Failed copying " + from + " to " + to);
+ res = error(rc, "Failed copying " + fromCodePath + " to " + to);
goto fail;
}
diff --git a/cmds/installd/InstalldNativeService.h b/cmds/installd/InstalldNativeService.h
index dd56de6..eb35fd3 100644
--- a/cmds/installd/InstalldNativeService.h
+++ b/cmds/installd/InstalldNativeService.h
@@ -97,7 +97,7 @@
binder::Status moveCompleteApp(const std::unique_ptr<std::string>& fromUuid,
const std::unique_ptr<std::string>& toUuid, const std::string& packageName,
const std::string& dataAppName, int32_t appId, const std::string& seInfo,
- int32_t targetSdkVersion);
+ int32_t targetSdkVersion, const std::string& fromCodePath);
binder::Status dexopt(const std::string& apkPath, int32_t uid,
const std::unique_ptr<std::string>& packageName, const std::string& instructionSet,
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/cmds/installd/binder/android/os/IInstalld.aidl b/cmds/installd/binder/android/os/IInstalld.aidl
index 07ced0d..80d9703 100644
--- a/cmds/installd/binder/android/os/IInstalld.aidl
+++ b/cmds/installd/binder/android/os/IInstalld.aidl
@@ -52,7 +52,7 @@
void moveCompleteApp(@nullable @utf8InCpp String fromUuid, @nullable @utf8InCpp String toUuid,
@utf8InCpp String packageName, @utf8InCpp String dataAppName, int appId,
- @utf8InCpp String seInfo, int targetSdkVersion);
+ @utf8InCpp String seInfo, int targetSdkVersion, @utf8InCpp String fromCodePath);
void dexopt(@utf8InCpp String apkPath, int uid, @nullable @utf8InCpp String packageName,
@utf8InCpp String instructionSet, int dexoptNeeded,
diff --git a/include/android/bitmap.h b/include/android/bitmap.h
index 571a5ca..412fc6b 100644
--- a/include/android/bitmap.h
+++ b/include/android/bitmap.h
@@ -97,15 +97,21 @@
uint32_t stride;
/** The bitmap pixel format. See {@link AndroidBitmapFormat} */
int32_t format;
- /** Two bits are used to encode alpha. Use ANDROID_BITMAP_FLAGS_ALPHA_MASK
- * and ANDROID_BITMAP_FLAGS_ALPHA_SHIFT to retrieve them. One bit is used
- * to encode whether the Bitmap uses the HARDWARE Config. Use
- * ANDROID_BITMAP_FLAGS_IS_HARDWARE to know.*/
+ /** Bitfield containing information about the bitmap.
+ *
+ * <p>Two bits are used to encode alpha. Use {@link ANDROID_BITMAP_FLAGS_ALPHA_MASK}
+ * and {@link ANDROID_BITMAP_FLAGS_ALPHA_SHIFT} to retrieve them.</p>
+ *
+ * <p>One bit is used to encode whether the Bitmap uses the HARDWARE Config. Use
+ * {@link ANDROID_BITMAP_FLAGS_IS_HARDWARE} to know.</p>
+ *
+ * <p>These flags were introduced in API level 30.</p>
+ */
uint32_t flags;
} AndroidBitmapInfo;
/**
- * Given a java bitmap object, fill out the AndroidBitmapInfo struct for it.
+ * Given a java bitmap object, fill out the {@link AndroidBitmapInfo} struct for it.
* If the call fails, the info parameter will be ignored.
*/
int AndroidBitmap_getInfo(JNIEnv* env, jobject jbitmap,
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/libs/binder/Android.bp b/libs/binder/Android.bp
index 1ee3853..5f9d400 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -138,7 +138,6 @@
"liblog",
"libcutils",
"libutils",
- "libbinderthreadstate",
],
header_libs: [
diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp
index 4981d7a..4dcd07a 100644
--- a/libs/binder/IPCThreadState.cpp
+++ b/libs/binder/IPCThreadState.cpp
@@ -17,7 +17,6 @@
#define LOG_TAG "IPCThreadState"
#include <binder/IPCThreadState.h>
-#include <binderthreadstate/IPCThreadStateBase.h>
#include <binder/Binder.h>
#include <binder/BpBinder.h>
@@ -803,6 +802,7 @@
IPCThreadState::IPCThreadState()
: mProcess(ProcessState::self()),
+ mServingStackPointer(nullptr),
mWorkSource(kUnsetWorkSource),
mPropagateWorkSource(false),
mStrictModePolicy(0),
@@ -813,7 +813,6 @@
clearCaller();
mIn.setDataCapacity(256);
mOut.setDataCapacity(256);
- mIPCThreadStateBase = IPCThreadStateBase::self();
}
IPCThreadState::~IPCThreadState()
@@ -1163,9 +1162,6 @@
"Not enough command data for brTRANSACTION");
if (result != NO_ERROR) break;
- //Record the fact that we're in a binder call.
- mIPCThreadStateBase->pushCurrentState(
- IPCThreadStateBase::CallState::BINDER);
Parcel buffer;
buffer.ipcSetDataReference(
reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
@@ -1173,6 +1169,9 @@
reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets),
tr.offsets_size/sizeof(binder_size_t), freeBuffer, this);
+ const void* origServingStackPointer = mServingStackPointer;
+ mServingStackPointer = &origServingStackPointer; // anything on the stack
+
const pid_t origPid = mCallingPid;
const char* origSid = mCallingSid;
const uid_t origUid = mCallingUid;
@@ -1223,7 +1222,6 @@
error = the_context_object->transact(tr.code, buffer, &reply, tr.flags);
}
- mIPCThreadStateBase->popCurrentState();
//ALOGI("<<<< TRANSACT from pid %d restore pid %d sid %s uid %d\n",
// mCallingPid, origPid, (origSid ? origSid : "<N/A>"), origUid);
@@ -1235,6 +1233,7 @@
LOG_ONEWAY("NOT sending reply to %d!", mCallingPid);
}
+ mServingStackPointer = origServingStackPointer;
mCallingPid = origPid;
mCallingSid = origSid;
mCallingUid = origUid;
@@ -1290,8 +1289,8 @@
return result;
}
-bool IPCThreadState::isServingCall() const {
- return mIPCThreadStateBase->getCurrentBinderCallState() == IPCThreadStateBase::CallState::BINDER;
+const void* IPCThreadState::getServingStackPointer() const {
+ return mServingStackPointer;
}
void IPCThreadState::threadDestructor(void *st)
diff --git a/libs/binder/TEST_MAPPING b/libs/binder/TEST_MAPPING
index 7489afa..9aa7651 100644
--- a/libs/binder/TEST_MAPPING
+++ b/libs/binder/TEST_MAPPING
@@ -26,6 +26,9 @@
},
{
"name": "aidl_lazy_test"
+ },
+ {
+ "name": "libbinderthreadstateutils_test"
}
]
}
diff --git a/libs/binder/aidl/android/content/pm/IPackageManagerNative.aidl b/libs/binder/aidl/android/content/pm/IPackageManagerNative.aidl
index a7a7292..618f88c 100644
--- a/libs/binder/aidl/android/content/pm/IPackageManagerNative.aidl
+++ b/libs/binder/aidl/android/content/pm/IPackageManagerNative.aidl
@@ -87,4 +87,7 @@
* package.
*/
@utf8InCpp String getModuleMetadataPackageName();
+
+ /* Returns the names of all packages. */
+ @utf8InCpp String[] getAllPackages();
}
diff --git a/libs/binder/include/binder/IPCThreadState.h b/libs/binder/include/binder/IPCThreadState.h
index ff9244e..4818889 100644
--- a/libs/binder/include/binder/IPCThreadState.h
+++ b/libs/binder/include/binder/IPCThreadState.h
@@ -29,8 +29,6 @@
// ---------------------------------------------------------------------------
namespace android {
-class IPCThreadStateBase;
-
class IPCThreadState
{
public:
@@ -113,31 +111,12 @@
// Service manager registration
void setTheContextObject(sp<BBinder> obj);
- // Is this thread currently serving a binder call. This method
- // returns true if while traversing backwards from the function call
- // stack for this thread, we encounter a function serving a binder
- // call before encountering a hwbinder call / hitting the end of the
- // call stack.
- // Eg: If thread T1 went through the following call pattern
- // 1) T1 receives and executes hwbinder call H1.
- // 2) While handling H1, T1 makes binder call B1.
- // 3) The handler of B1, calls into T1 with a callback B2.
- // If isServingCall() is called during H1 before 3), this method
- // will return false, else true.
+ // WARNING: DO NOT USE THIS API
//
- // ----
- // | B2 | ---> While callback B2 is being handled, during 3).
- // ----
- // | H1 | ---> While H1 is being handled.
- // ----
- // Fig: Thread Call stack while handling B2
- //
- // This is since after 3), while traversing the thread call stack,
- // we hit a binder call before a hwbinder call / end of stack. This
- // method may be typically used to determine whether to use
- // hardware::IPCThreadState methods or IPCThreadState methods to
- // infer information about thread state.
- bool isServingCall() const;
+ // Returns a pointer to the stack from the last time a transaction
+ // was initiated by the kernel. Used to compare when making nested
+ // calls between multiple different transports.
+ const void* getServingStackPointer() const;
// The work source represents the UID of the process we should attribute the transaction
// to. We use -1 to specify that the work source was not set using #setWorkSource.
@@ -181,6 +160,7 @@
Parcel mIn;
Parcel mOut;
status_t mLastError;
+ const void* mServingStackPointer;
pid_t mCallingPid;
const char* mCallingSid;
uid_t mCallingUid;
@@ -191,7 +171,6 @@
bool mPropagateWorkSource;
int32_t mStrictModePolicy;
int32_t mLastTransactionBinderFlags;
- IPCThreadStateBase *mIPCThreadStateBase;
ProcessState::CallRestriction mCallRestriction;
};
diff --git a/libs/binderthreadstate/1.0/Android.bp b/libs/binderthreadstate/1.0/Android.bp
new file mode 100644
index 0000000..ebdc932
--- /dev/null
+++ b/libs/binderthreadstate/1.0/Android.bp
@@ -0,0 +1,14 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+ name: "binderthreadstateutilstest@1.0",
+ root: "binderthreadstateutilstest",
+ system_ext_specific: true,
+ srcs: [
+ "IHidlStuff.hal",
+ ],
+ interfaces: [
+ "android.hidl.base@1.0",
+ ],
+ gen_java: true,
+}
diff --git a/services/surfaceflinger/CompositionEngine/mock/Layer.cpp b/libs/binderthreadstate/1.0/IHidlStuff.hal
similarity index 60%
copy from services/surfaceflinger/CompositionEngine/mock/Layer.cpp
copy to libs/binderthreadstate/1.0/IHidlStuff.hal
index 08483cb..ffb6499 100644
--- a/services/surfaceflinger/CompositionEngine/mock/Layer.cpp
+++ b/libs/binderthreadstate/1.0/IHidlStuff.hal
@@ -1,5 +1,5 @@
/*
- * Copyright 2019 The Android Open Source Project
+ * Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,13 +14,9 @@
* limitations under the License.
*/
-#include <compositionengine/mock/Layer.h>
+package binderthreadstateutilstest@1.0;
-namespace android::compositionengine::mock {
-
-// The Google Mock documentation recommends explicit non-header instantiations
-// for better compile time performance.
-Layer::Layer() = default;
-Layer::~Layer() = default;
-
-} // namespace android::compositionengine::mock
+interface IHidlStuff {
+ callLocal();
+ call(int32_t idx);
+};
diff --git a/libs/binderthreadstate/Android.bp b/libs/binderthreadstate/Android.bp
index ee1a6a4..4655e1d 100644
--- a/libs/binderthreadstate/Android.bp
+++ b/libs/binderthreadstate/Android.bp
@@ -12,6 +12,59 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+// DO NOT ADD NEW USAGES OF THIS
+// See comments in header file.
+cc_library_static {
+ name: "libbinderthreadstateutils",
+ double_loadable: true,
+ vendor_available: true,
+ host_supported: true,
+
+ shared_libs: [
+ "libbinder",
+ "libhidlbase", // libhwbinder is in here
+ ],
+
+ export_include_dirs: ["include"],
+
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
+}
+
+hidl_package_root {
+ name: "binderthreadstateutilstest",
+}
+
+aidl_interface {
+ name: "binderthreadstateutilstest.aidl",
+ srcs: ["IAidlStuff.aidl"],
+}
+
+cc_test {
+ name: "libbinderthreadstateutils_test",
+ srcs: ["test.cpp"],
+ static_libs: [
+ "binderthreadstateutilstest@1.0",
+ "binderthreadstateutilstest.aidl-cpp",
+ "libbinderthreadstateutils",
+ ],
+ shared_libs: [
+ "libbase",
+ "libbinder",
+ "libcutils",
+ "libhidlbase",
+ "libutils",
+ "liblog",
+ ],
+ test_suites: [
+ "general-tests",
+ ],
+ require_root: true,
+}
+
+// TODO(b/148692216): remove empty lib
cc_library {
name: "libbinderthreadstate",
recovery_available: true,
@@ -21,28 +74,4 @@
support_system_process: true,
},
host_supported: true,
-
- srcs: [
- "IPCThreadStateBase.cpp",
- ],
-
- header_libs: [
- "libbase_headers",
- "libutils_headers",
- ],
-
- shared_libs: [
- "liblog",
- ],
-
- export_include_dirs: ["include"],
-
- sanitize: {
- misc_undefined: ["integer"],
- },
-
- cflags: [
- "-Wall",
- "-Werror",
- ],
}
diff --git a/services/surfaceflinger/CompositionEngine/mock/Layer.cpp b/libs/binderthreadstate/IAidlStuff.aidl
similarity index 60%
rename from services/surfaceflinger/CompositionEngine/mock/Layer.cpp
rename to libs/binderthreadstate/IAidlStuff.aidl
index 08483cb..0c81c42 100644
--- a/services/surfaceflinger/CompositionEngine/mock/Layer.cpp
+++ b/libs/binderthreadstate/IAidlStuff.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright 2019 The Android Open Source Project
+ * Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,13 +14,8 @@
* limitations under the License.
*/
-#include <compositionengine/mock/Layer.h>
-namespace android::compositionengine::mock {
-
-// The Google Mock documentation recommends explicit non-header instantiations
-// for better compile time performance.
-Layer::Layer() = default;
-Layer::~Layer() = default;
-
-} // namespace android::compositionengine::mock
+interface IAidlStuff {
+ void callLocal();
+ void call(int idx);
+}
diff --git a/libs/binderthreadstate/IPCThreadStateBase.cpp b/libs/binderthreadstate/IPCThreadStateBase.cpp
deleted file mode 100644
index fede151..0000000
--- a/libs/binderthreadstate/IPCThreadStateBase.cpp
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "IPCThreadStateBase"
-
-#include <binderthreadstate/IPCThreadStateBase.h>
-#include <android-base/macros.h>
-
-#include <utils/Log.h>
-
-#include <errno.h>
-#include <inttypes.h>
-#include <pthread.h>
-
-namespace android {
-
-static pthread_mutex_t gTLSMutex = PTHREAD_MUTEX_INITIALIZER;
-static bool gHaveTLS = false;
-static pthread_key_t gTLS = 0;
-
-IPCThreadStateBase::IPCThreadStateBase() {
- pthread_setspecific(gTLS, this);
-}
-
-IPCThreadStateBase* IPCThreadStateBase::self()
-{
- if (gHaveTLS) {
-restart:
- const pthread_key_t k = gTLS;
- IPCThreadStateBase* st = (IPCThreadStateBase*)pthread_getspecific(k);
- if (st) return st;
- return new IPCThreadStateBase;
- }
-
- pthread_mutex_lock(&gTLSMutex);
- if (!gHaveTLS) {
- int key_create_value = pthread_key_create(&gTLS, threadDestructor);
- if (key_create_value != 0) {
- pthread_mutex_unlock(&gTLSMutex);
- ALOGW("IPCThreadStateBase::self() unable to create TLS key, expect a crash: %s\n",
- strerror(key_create_value));
- return nullptr;
- }
- gHaveTLS = true;
- }
- pthread_mutex_unlock(&gTLSMutex);
- goto restart;
-}
-
-void IPCThreadStateBase::pushCurrentState(CallState callState) {
- mCallStateStack.emplace(callState);
-}
-
-IPCThreadStateBase::CallState IPCThreadStateBase::popCurrentState() {
- ALOG_ASSERT(mCallStateStack.size > 0);
- CallState val = mCallStateStack.top();
- mCallStateStack.pop();
- return val;
-}
-
-IPCThreadStateBase::CallState IPCThreadStateBase::getCurrentBinderCallState() {
- if (mCallStateStack.size() > 0) {
- return mCallStateStack.top();
- }
- return CallState::NONE;
-}
-
-void IPCThreadStateBase::threadDestructor(void *st)
-{
- IPCThreadStateBase* const self = static_cast<IPCThreadStateBase*>(st);
- if (self) {
- delete self;
- }
-}
-
-}; // namespace android
diff --git a/libs/binderthreadstate/TEST_MAPPING b/libs/binderthreadstate/TEST_MAPPING
new file mode 100644
index 0000000..2bd0463
--- /dev/null
+++ b/libs/binderthreadstate/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "presubmit": [
+ {
+ "name": "libbinderthreadstateutils_test"
+ }
+ ]
+}
diff --git a/libs/binderthreadstate/include/binderthreadstate/CallerUtils.h b/libs/binderthreadstate/include/binderthreadstate/CallerUtils.h
new file mode 100644
index 0000000..a3e5026
--- /dev/null
+++ b/libs/binderthreadstate/include/binderthreadstate/CallerUtils.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+// WARNING: DO NOT USE THIS
+// You should:
+// - have code know how it is handling things. Pass in caller information rather
+// than assuming that code is running in a specific global context
+// - use AIDL exclusively in your stack (HIDL is no longer required anywhere)
+
+#include <binder/IPCThreadState.h>
+#include <hwbinder/IPCThreadState.h>
+
+namespace android {
+
+enum class BinderCallType {
+ NONE,
+ BINDER,
+ HWBINDER,
+};
+
+// Based on where we are in recursion of nested binder/hwbinder calls, determine
+// which one we are closer to.
+inline static BinderCallType getCurrentServingCall() {
+ const void* hwbinderSp = android::hardware::IPCThreadState::self()->getServingStackPointer();
+ const void* binderSp = android::IPCThreadState::self()->getServingStackPointer();
+
+ if (hwbinderSp == nullptr && binderSp == nullptr) return BinderCallType::NONE;
+ if (hwbinderSp == nullptr) return BinderCallType::BINDER;
+ if (binderSp == nullptr) return BinderCallType::HWBINDER;
+
+ if (hwbinderSp < binderSp) return BinderCallType::HWBINDER;
+ return BinderCallType::BINDER;
+}
+
+} // namespace android
diff --git a/libs/binderthreadstate/include/binderthreadstate/IPCThreadStateBase.h b/libs/binderthreadstate/include/binderthreadstate/IPCThreadStateBase.h
deleted file mode 100644
index 6fdcc84..0000000
--- a/libs/binderthreadstate/include/binderthreadstate/IPCThreadStateBase.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef BINDER_THREADSTATE_IPC_THREADSTATE_BASE_H
-#define BINDER_THREADSTATE_IPC_THREADSTATE_BASE_H
-
-#include <stack>
-namespace android {
-
-class IPCThreadStateBase {
-public:
- enum CallState {
- HWBINDER,
- BINDER,
- NONE,
- };
- static IPCThreadStateBase* self();
- void pushCurrentState(CallState callState);
- CallState popCurrentState();
- CallState getCurrentBinderCallState();
-
-private:
- IPCThreadStateBase();
- static void threadDestructor(void *st);
-
- std::stack<CallState> mCallStateStack;
-};
-
-}; // namespace android
-
-#endif // BINDER_THREADSTATE_IPC_THREADSTATE_BASE_H
diff --git a/libs/binderthreadstate/test.cpp b/libs/binderthreadstate/test.cpp
new file mode 100644
index 0000000..68cc225
--- /dev/null
+++ b/libs/binderthreadstate/test.cpp
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <BnAidlStuff.h>
+#include <android-base/logging.h>
+#include <binder/IServiceManager.h>
+#include <binderthreadstate/CallerUtils.h>
+#include <binderthreadstateutilstest/1.0/IHidlStuff.h>
+#include <gtest/gtest.h>
+#include <hidl/HidlTransportSupport.h>
+#include <linux/prctl.h>
+#include <sys/prctl.h>
+
+using android::BinderCallType;
+using android::defaultServiceManager;
+using android::getCurrentServingCall;
+using android::getService;
+using android::OK;
+using android::sp;
+using android::String16;
+using android::binder::Status;
+using android::hardware::Return;
+using binderthreadstateutilstest::V1_0::IHidlStuff;
+
+constexpr size_t kP1Id = 1;
+constexpr size_t kP2Id = 2;
+
+// AIDL and HIDL are in separate namespaces so using same service names
+std::string id2name(size_t id) {
+ return "libbinderthreadstateutils-" + std::to_string(id);
+}
+
+// There are two servers calling each other recursively like this.
+//
+// P1 P2
+// | --HIDL--> |
+// | <--HIDL-- |
+// | --AIDL--> |
+// | <--AIDL-- |
+// | --HIDL--> |
+// | <--HIDL-- |
+// | --AIDL--> |
+// | <--AIDL-- |
+// ..........
+//
+// Calls always come in pairs (AIDL returns AIDL, HIDL returns HIDL) because
+// this means that P1 always has a 'waitForResponse' call which can service the
+// returning call and continue the recursion. Of course, with more threads, more
+// complicated calls are possible, but this should do here.
+
+static void callHidl(size_t id, int32_t idx) {
+ auto stuff = IHidlStuff::getService(id2name(id));
+ CHECK(stuff->call(idx).isOk());
+}
+
+static void callAidl(size_t id, int32_t idx) {
+ sp<IAidlStuff> stuff;
+ CHECK(OK == android::getService<IAidlStuff>(String16(id2name(id).c_str()), &stuff));
+ CHECK(stuff->call(idx).isOk());
+}
+
+class HidlServer : public IHidlStuff {
+public:
+ HidlServer(size_t thisId, size_t otherId) : thisId(thisId), otherId(otherId) {}
+ size_t thisId;
+ size_t otherId;
+
+ Return<void> callLocal() {
+ CHECK(BinderCallType::NONE == getCurrentServingCall());
+ return android::hardware::Status::ok();
+ }
+ Return<void> call(int32_t idx) {
+ LOG(INFO) << "HidlServer CALL " << thisId << " to " << otherId << " at idx: " << idx
+ << " with tid: " << gettid();
+ CHECK(BinderCallType::HWBINDER == getCurrentServingCall());
+ if (idx > 0) {
+ if (thisId == kP1Id && idx % 4 < 2) {
+ callHidl(otherId, idx - 1);
+ } else {
+ callAidl(otherId, idx - 1);
+ }
+ }
+ CHECK(BinderCallType::HWBINDER == getCurrentServingCall());
+ return android::hardware::Status::ok();
+ }
+};
+class AidlServer : public BnAidlStuff {
+public:
+ AidlServer(size_t thisId, size_t otherId) : thisId(thisId), otherId(otherId) {}
+ size_t thisId;
+ size_t otherId;
+
+ Status callLocal() {
+ CHECK(BinderCallType::NONE == getCurrentServingCall());
+ return Status::ok();
+ }
+ Status call(int32_t idx) {
+ LOG(INFO) << "AidlServer CALL " << thisId << " to " << otherId << " at idx: " << idx
+ << " with tid: " << gettid();
+ CHECK(BinderCallType::BINDER == getCurrentServingCall());
+ if (idx > 0) {
+ if (thisId == kP2Id && idx % 4 < 2) {
+ callHidl(otherId, idx - 1);
+ } else {
+ callAidl(otherId, idx - 1);
+ }
+ }
+ CHECK(BinderCallType::BINDER == getCurrentServingCall());
+ return Status::ok();
+ }
+};
+
+TEST(BinderThreadState, LocalHidlCall) {
+ sp<IHidlStuff> server = new HidlServer(0, 0);
+ EXPECT_TRUE(server->callLocal().isOk());
+}
+
+TEST(BinderThreadState, LocalAidlCall) {
+ sp<IAidlStuff> server = new AidlServer(0, 0);
+ EXPECT_TRUE(server->callLocal().isOk());
+}
+
+TEST(BindThreadState, RemoteHidlCall) {
+ auto stuff = IHidlStuff::getService(id2name(kP1Id));
+ ASSERT_NE(nullptr, stuff);
+ ASSERT_TRUE(stuff->call(0).isOk());
+}
+TEST(BindThreadState, RemoteAidlCall) {
+ sp<IAidlStuff> stuff;
+ ASSERT_EQ(OK, android::getService<IAidlStuff>(String16(id2name(kP1Id).c_str()), &stuff));
+ ASSERT_NE(nullptr, stuff);
+ ASSERT_TRUE(stuff->call(0).isOk());
+}
+
+TEST(BindThreadState, RemoteNestedStartHidlCall) {
+ auto stuff = IHidlStuff::getService(id2name(kP1Id));
+ ASSERT_NE(nullptr, stuff);
+ ASSERT_TRUE(stuff->call(100).isOk());
+}
+TEST(BindThreadState, RemoteNestedStartAidlCall) {
+ sp<IAidlStuff> stuff;
+ ASSERT_EQ(OK, android::getService<IAidlStuff>(String16(id2name(kP1Id).c_str()), &stuff));
+ ASSERT_NE(nullptr, stuff);
+ EXPECT_TRUE(stuff->call(100).isOk());
+}
+
+int server(size_t thisId, size_t otherId) {
+ // AIDL
+ android::ProcessState::self()->setThreadPoolMaxThreadCount(1);
+ sp<AidlServer> aidlServer = new AidlServer(thisId, otherId);
+ CHECK(OK == defaultServiceManager()->addService(String16(id2name(thisId).c_str()), aidlServer));
+ android::ProcessState::self()->startThreadPool();
+
+ // HIDL
+ setenv("TREBLE_TESTING_OVERRIDE", "true", true);
+ android::hardware::configureRpcThreadpool(1, true /*callerWillJoin*/);
+ sp<IHidlStuff> hidlServer = new HidlServer(thisId, otherId);
+ CHECK(OK == hidlServer->registerAsService(id2name(thisId).c_str()));
+ android::hardware::joinRpcThreadpool();
+
+ return EXIT_FAILURE;
+}
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ setenv("TREBLE_TESTING_OVERRIDE", "true", true);
+ if (fork() == 0) {
+ prctl(PR_SET_PDEATHSIG, SIGHUP);
+ return server(kP1Id, kP2Id);
+ }
+ if (fork() == 0) {
+ prctl(PR_SET_PDEATHSIG, SIGHUP);
+ return server(kP2Id, kP1Id);
+ }
+
+ android::waitForService<IAidlStuff>(String16(id2name(kP1Id).c_str()));
+ android::hardware::details::waitForHwService(IHidlStuff::descriptor, id2name(kP1Id).c_str());
+ android::waitForService<IAidlStuff>(String16(id2name(kP2Id).c_str()));
+ android::hardware::details::waitForHwService(IHidlStuff::descriptor, id2name(kP2Id).c_str());
+
+ return RUN_ALL_TESTS();
+}
diff --git a/libs/graphicsenv/IGpuService.cpp b/libs/graphicsenv/IGpuService.cpp
index 9f5b0ff..de3503b 100644
--- a/libs/graphicsenv/IGpuService.cpp
+++ b/libs/graphicsenv/IGpuService.cpp
@@ -48,50 +48,6 @@
remote()->transact(BnGpuService::SET_GPU_STATS, data, &reply, IBinder::FLAG_ONEWAY);
}
- virtual status_t getGpuStatsGlobalInfo(std::vector<GpuStatsGlobalInfo>* outStats) const {
- if (!outStats) return UNEXPECTED_NULL;
-
- Parcel data, reply;
- status_t status;
-
- if ((status = data.writeInterfaceToken(IGpuService::getInterfaceDescriptor())) != OK)
- return status;
-
- if ((status = remote()->transact(BnGpuService::GET_GPU_STATS_GLOBAL_INFO, data, &reply)) !=
- OK)
- return status;
-
- int32_t result = 0;
- if ((status = reply.readInt32(&result)) != OK) return status;
- if (result != OK) return result;
-
- outStats->clear();
- return reply.readParcelableVector(outStats);
- }
-
- virtual status_t getGpuStatsAppInfo(std::vector<GpuStatsAppInfo>* outStats) const {
- if (!outStats) return UNEXPECTED_NULL;
-
- Parcel data, reply;
- status_t status;
-
- if ((status = data.writeInterfaceToken(IGpuService::getInterfaceDescriptor())) != OK) {
- return status;
- }
-
- if ((status = remote()->transact(BnGpuService::GET_GPU_STATS_APP_INFO, data, &reply)) !=
- OK) {
- return status;
- }
-
- int32_t result = 0;
- if ((status = reply.readInt32(&result)) != OK) return status;
- if (result != OK) return result;
-
- outStats->clear();
- return reply.readParcelableVector(outStats);
- }
-
virtual void setTargetStats(const std::string& appPackageName, const uint64_t driverVersionCode,
const GpuStatsInfo::Stats stats, const uint64_t value) {
Parcel data, reply;
@@ -150,32 +106,6 @@
return OK;
}
- case GET_GPU_STATS_GLOBAL_INFO: {
- CHECK_INTERFACE(IGpuService, data, reply);
-
- std::vector<GpuStatsGlobalInfo> stats;
- const status_t result = getGpuStatsGlobalInfo(&stats);
-
- if ((status = reply->writeInt32(result)) != OK) return status;
- if (result != OK) return result;
-
- if ((status = reply->writeParcelableVector(stats)) != OK) return status;
-
- return OK;
- }
- case GET_GPU_STATS_APP_INFO: {
- CHECK_INTERFACE(IGpuService, data, reply);
-
- std::vector<GpuStatsAppInfo> stats;
- const status_t result = getGpuStatsAppInfo(&stats);
-
- if ((status = reply->writeInt32(result)) != OK) return status;
- if (result != OK) return result;
-
- if ((status = reply->writeParcelableVector(stats)) != OK) return status;
-
- return OK;
- }
case SET_TARGET_STATS: {
CHECK_INTERFACE(IGpuService, data, reply);
diff --git a/libs/graphicsenv/include/graphicsenv/IGpuService.h b/libs/graphicsenv/include/graphicsenv/IGpuService.h
index f523d58..c7c6d1e 100644
--- a/libs/graphicsenv/include/graphicsenv/IGpuService.h
+++ b/libs/graphicsenv/include/graphicsenv/IGpuService.h
@@ -16,12 +16,11 @@
#pragma once
-#include <vector>
-
#include <binder/IInterface.h>
#include <cutils/compiler.h>
#include <graphicsenv/GpuStatsInfo.h>
-#include <graphicsenv/GraphicsEnv.h>
+
+#include <vector>
namespace android {
@@ -43,20 +42,12 @@
// set target stats.
virtual void setTargetStats(const std::string& appPackageName, const uint64_t driverVersionCode,
const GpuStatsInfo::Stats stats, const uint64_t value = 0) = 0;
-
- // get GPU global stats from GpuStats module.
- virtual status_t getGpuStatsGlobalInfo(std::vector<GpuStatsGlobalInfo>* outStats) const = 0;
-
- // get GPU app stats from GpuStats module.
- virtual status_t getGpuStatsAppInfo(std::vector<GpuStatsAppInfo>* outStats) const = 0;
};
class BnGpuService : public BnInterface<IGpuService> {
public:
enum IGpuServiceTag {
SET_GPU_STATS = IBinder::FIRST_CALL_TRANSACTION,
- GET_GPU_STATS_GLOBAL_INFO,
- GET_GPU_STATS_APP_INFO,
SET_TARGET_STATS,
// Always append new enum to the end.
};
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp
index 55a892e..40c044d 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -202,6 +202,10 @@
"libvndksupport",
],
+ static_libs: [
+ "libbinderthreadstateutils",
+ ],
+
header_libs: [
"libgui_headers",
"libnativebase_headers",
diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp
index 4e62da7..e2f5d31 100644
--- a/libs/gui/BLASTBufferQueue.cpp
+++ b/libs/gui/BLASTBufferQueue.cpp
@@ -31,6 +31,68 @@
namespace android {
+void BLASTBufferItemConsumer::onDisconnect() {
+ Mutex::Autolock lock(mFrameEventHistoryMutex);
+ mPreviouslyConnected = mCurrentlyConnected;
+ mCurrentlyConnected = false;
+ if (mPreviouslyConnected) {
+ mDisconnectEvents.push(mCurrentFrameNumber);
+ }
+ mFrameEventHistory.onDisconnect();
+}
+
+void BLASTBufferItemConsumer::addAndGetFrameTimestamps(const NewFrameEventsEntry* newTimestamps,
+ FrameEventHistoryDelta* outDelta) {
+ Mutex::Autolock lock(mFrameEventHistoryMutex);
+ if (newTimestamps) {
+ // BufferQueueProducer only adds a new timestamp on
+ // queueBuffer
+ mCurrentFrameNumber = newTimestamps->frameNumber;
+ mFrameEventHistory.addQueue(*newTimestamps);
+ }
+ if (outDelta) {
+ // frame event histories will be processed
+ // only after the producer connects and requests
+ // deltas for the first time. Forward this intent
+ // to SF-side to turn event processing back on
+ mPreviouslyConnected = mCurrentlyConnected;
+ mCurrentlyConnected = true;
+ mFrameEventHistory.getAndResetDelta(outDelta);
+ }
+}
+
+void BLASTBufferItemConsumer::updateFrameTimestamps(uint64_t frameNumber, nsecs_t refreshStartTime,
+ const sp<Fence>& glDoneFence,
+ const sp<Fence>& presentFence,
+ const sp<Fence>& prevReleaseFence,
+ CompositorTiming compositorTiming,
+ nsecs_t latchTime, nsecs_t dequeueReadyTime) {
+ Mutex::Autolock lock(mFrameEventHistoryMutex);
+
+ // if the producer is not connected, don't bother updating,
+ // the next producer that connects won't access this frame event
+ if (!mCurrentlyConnected) return;
+ std::shared_ptr<FenceTime> glDoneFenceTime = std::make_shared<FenceTime>(glDoneFence);
+ std::shared_ptr<FenceTime> presentFenceTime = std::make_shared<FenceTime>(presentFence);
+ std::shared_ptr<FenceTime> releaseFenceTime = std::make_shared<FenceTime>(prevReleaseFence);
+
+ mFrameEventHistory.addLatch(frameNumber, latchTime);
+ mFrameEventHistory.addRelease(frameNumber, dequeueReadyTime, std::move(releaseFenceTime));
+ mFrameEventHistory.addPreComposition(frameNumber, refreshStartTime);
+ mFrameEventHistory.addPostComposition(frameNumber, glDoneFenceTime, presentFenceTime,
+ compositorTiming);
+}
+
+void BLASTBufferItemConsumer::getConnectionEvents(uint64_t frameNumber, bool* needsDisconnect) {
+ bool disconnect = false;
+ Mutex::Autolock lock(mFrameEventHistoryMutex);
+ while (!mDisconnectEvents.empty() && mDisconnectEvents.front() <= frameNumber) {
+ disconnect = true;
+ mDisconnectEvents.pop();
+ }
+ if (needsDisconnect != nullptr) *needsDisconnect = disconnect;
+}
+
BLASTBufferQueue::BLASTBufferQueue(const sp<SurfaceControl>& surface, int width, int height)
: mSurfaceControl(surface),
mWidth(width),
@@ -39,7 +101,7 @@
BufferQueue::createBufferQueue(&mProducer, &mConsumer);
mConsumer->setMaxAcquiredBufferCount(MAX_ACQUIRED_BUFFERS);
mBufferItemConsumer =
- new BufferItemConsumer(mConsumer, AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER, 1, true);
+ new BLASTBufferItemConsumer(mConsumer, AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER, 1, true);
static int32_t id = 0;
auto name = std::string("BLAST Consumer") + std::to_string(id);
id++;
@@ -79,11 +141,21 @@
std::unique_lock _lock{mMutex};
ATRACE_CALL();
+ if (!stats.empty()) {
+ mTransformHint = stats[0].transformHint;
+ mBufferItemConsumer->setTransformHint(mTransformHint);
+ mBufferItemConsumer->updateFrameTimestamps(stats[0].frameEventStats.frameNumber,
+ stats[0].frameEventStats.refreshStartTime,
+ stats[0].frameEventStats.gpuCompositionDoneFence,
+ stats[0].presentFence,
+ stats[0].previousReleaseFence,
+ stats[0].frameEventStats.compositorTiming,
+ stats[0].latchTime,
+ stats[0].frameEventStats.dequeueReadyTime);
+ }
if (mPendingReleaseItem.item.mGraphicBuffer != nullptr) {
- if (stats.size() > 0) {
+ if (!stats.empty()) {
mPendingReleaseItem.releaseFence = stats[0].previousReleaseFence;
- mTransformHint = stats[0].transformHint;
- mBufferItemConsumer->setTransformHint(mTransformHint);
} else {
ALOGE("Warning: no SurfaceControlStats returned in BLASTBufferQueue callback");
mPendingReleaseItem.releaseFence = nullptr;
@@ -144,6 +216,14 @@
mNumAcquired++;
mSubmitted.push(bufferItem);
+ bool needsDisconnect = false;
+ mBufferItemConsumer->getConnectionEvents(bufferItem.mFrameNumber, &needsDisconnect);
+
+ // if producer disconnected before, notify SurfaceFlinger
+ if (needsDisconnect) {
+ t->notifyProducerDisconnect(mSurfaceControl);
+ }
+
// Ensure BLASTBufferQueue stays alive until we receive the transaction complete callback.
incStrong((void*)transactionCallbackThunk);
diff --git a/libs/gui/BufferQueueThreadState.cpp b/libs/gui/BufferQueueThreadState.cpp
index 3b531ec..c13030b 100644
--- a/libs/gui/BufferQueueThreadState.cpp
+++ b/libs/gui/BufferQueueThreadState.cpp
@@ -15,6 +15,7 @@
*/
#include <binder/IPCThreadState.h>
+#include <binderthreadstate/CallerUtils.h>
#include <hwbinder/IPCThreadState.h>
#include <private/gui/BufferQueueThreadState.h>
#include <unistd.h>
@@ -22,14 +23,14 @@
namespace android {
uid_t BufferQueueThreadState::getCallingUid() {
- if (hardware::IPCThreadState::self()->isServingCall()) {
+ if (getCurrentServingCall() == BinderCallType::HWBINDER) {
return hardware::IPCThreadState::self()->getCallingUid();
}
return IPCThreadState::self()->getCallingUid();
}
pid_t BufferQueueThreadState::getCallingPid() {
- if (hardware::IPCThreadState::self()->isServingCall()) {
+ if (getCurrentServingCall() == BinderCallType::HWBINDER) {
return hardware::IPCThreadState::self()->getCallingPid();
}
return IPCThreadState::self()->getCallingPid();
diff --git a/libs/gui/DisplayEventDispatcher.cpp b/libs/gui/DisplayEventDispatcher.cpp
index 8af1a1c..15f966d 100644
--- a/libs/gui/DisplayEventDispatcher.cpp
+++ b/libs/gui/DisplayEventDispatcher.cpp
@@ -104,7 +104,7 @@
mConfigChangeFlag = configChangeFlag;
}
-int DisplayEventDispatcher::getFd() {
+int DisplayEventDispatcher::getFd() const {
return mReceiver.getFd();
}
diff --git a/libs/gui/FrameTimestamps.cpp b/libs/gui/FrameTimestamps.cpp
index c04d907..6749c3c 100644
--- a/libs/gui/FrameTimestamps.cpp
+++ b/libs/gui/FrameTimestamps.cpp
@@ -355,6 +355,10 @@
mProducerWantsEvents = false;
}
+void ConsumerFrameEventHistory::setProducerWantsEvents() {
+ mProducerWantsEvents = true;
+}
+
void ConsumerFrameEventHistory::initializeCompositorTiming(
const CompositorTiming& compositorTiming) {
mCompositorTiming = compositorTiming;
diff --git a/libs/gui/ITransactionCompletedListener.cpp b/libs/gui/ITransactionCompletedListener.cpp
index e5e25aa..69f7894 100644
--- a/libs/gui/ITransactionCompletedListener.cpp
+++ b/libs/gui/ITransactionCompletedListener.cpp
@@ -30,6 +30,66 @@
} // Anonymous namespace
+status_t FrameEventHistoryStats::writeToParcel(Parcel* output) const {
+ status_t err = output->writeUint64(frameNumber);
+ if (err != NO_ERROR) return err;
+
+ if (gpuCompositionDoneFence) {
+ err = output->writeBool(true);
+ if (err != NO_ERROR) return err;
+
+ err = output->write(*gpuCompositionDoneFence);
+ } else {
+ err = output->writeBool(false);
+ }
+ if (err != NO_ERROR) return err;
+
+ err = output->writeInt64(compositorTiming.deadline);
+ if (err != NO_ERROR) return err;
+
+ err = output->writeInt64(compositorTiming.interval);
+ if (err != NO_ERROR) return err;
+
+ err = output->writeInt64(compositorTiming.presentLatency);
+ if (err != NO_ERROR) return err;
+
+ err = output->writeInt64(refreshStartTime);
+ if (err != NO_ERROR) return err;
+
+ err = output->writeInt64(dequeueReadyTime);
+ return err;
+}
+
+status_t FrameEventHistoryStats::readFromParcel(const Parcel* input) {
+ status_t err = input->readUint64(&frameNumber);
+ if (err != NO_ERROR) return err;
+
+ bool hasFence = false;
+ err = input->readBool(&hasFence);
+ if (err != NO_ERROR) return err;
+
+ if (hasFence) {
+ gpuCompositionDoneFence = new Fence();
+ err = input->read(*gpuCompositionDoneFence);
+ if (err != NO_ERROR) return err;
+ }
+
+ err = input->readInt64(&(compositorTiming.deadline));
+ if (err != NO_ERROR) return err;
+
+ err = input->readInt64(&(compositorTiming.interval));
+ if (err != NO_ERROR) return err;
+
+ err = input->readInt64(&(compositorTiming.presentLatency));
+ if (err != NO_ERROR) return err;
+
+ err = input->readInt64(&refreshStartTime);
+ if (err != NO_ERROR) return err;
+
+ err = input->readInt64(&dequeueReadyTime);
+ return err;
+}
+
status_t SurfaceStats::writeToParcel(Parcel* output) const {
status_t err = output->writeStrongBinder(surfaceControl);
if (err != NO_ERROR) {
@@ -49,6 +109,11 @@
err = output->writeBool(false);
}
err = output->writeUint32(transformHint);
+ if (err != NO_ERROR) {
+ return err;
+ }
+
+ err = output->writeParcelable(eventStats);
return err;
}
@@ -74,6 +139,11 @@
}
}
err = input->readUint32(&transformHint);
+ if (err != NO_ERROR) {
+ return err;
+ }
+
+ err = input->readParcelable(&eventStats);
return err;
}
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 43bccf6..7017b7c 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -222,8 +222,10 @@
surfaceControlStats
.emplace_back(callbacksMap[callbackId]
.surfaceControls[surfaceStats.surfaceControl],
- surfaceStats.acquireTime, surfaceStats.previousReleaseFence,
- surfaceStats.transformHint);
+ transactionStats.latchTime, surfaceStats.acquireTime,
+ transactionStats.presentFence,
+ surfaceStats.previousReleaseFence, surfaceStats.transformHint,
+ surfaceStats.eventStats);
if (callbacksMap[callbackId].surfaceControls[surfaceStats.surfaceControl]) {
callbacksMap[callbackId]
.surfaceControls[surfaceStats.surfaceControl]
@@ -1235,6 +1237,18 @@
return *this;
}
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::notifyProducerDisconnect(
+ const sp<SurfaceControl>& sc) {
+ layer_state_t* s = getLayerState(sc);
+ if (!s) {
+ mStatus = BAD_INDEX;
+ return *this;
+ }
+
+ s->what |= layer_state_t::eProducerDisconnect;
+ return *this;
+}
+
SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::detachChildren(
const sp<SurfaceControl>& sc) {
layer_state_t* s = getLayerState(sc);
diff --git a/libs/gui/include/gui/BLASTBufferQueue.h b/libs/gui/include/gui/BLASTBufferQueue.h
index be429fe..d72eb5a 100644
--- a/libs/gui/include/gui/BLASTBufferQueue.h
+++ b/libs/gui/include/gui/BLASTBufferQueue.h
@@ -33,6 +33,35 @@
class BufferItemConsumer;
+class BLASTBufferItemConsumer : public BufferItemConsumer {
+public:
+ BLASTBufferItemConsumer(const sp<IGraphicBufferConsumer>& consumer, uint64_t consumerUsage,
+ int bufferCount, bool controlledByApp)
+ : BufferItemConsumer(consumer, consumerUsage, bufferCount, controlledByApp),
+ mCurrentlyConnected(false),
+ mPreviouslyConnected(false) {}
+
+ void onDisconnect() override;
+ void addAndGetFrameTimestamps(const NewFrameEventsEntry* newTimestamps,
+ FrameEventHistoryDelta* outDelta) override
+ REQUIRES(mFrameEventHistoryMutex);
+ void updateFrameTimestamps(uint64_t frameNumber, nsecs_t refreshStartTime,
+ const sp<Fence>& gpuCompositionDoneFence,
+ const sp<Fence>& presentFence, const sp<Fence>& prevReleaseFence,
+ CompositorTiming compositorTiming, nsecs_t latchTime,
+ nsecs_t dequeueReadyTime) REQUIRES(mFrameEventHistoryMutex);
+ void getConnectionEvents(uint64_t frameNumber, bool* needsDisconnect);
+
+private:
+ uint64_t mCurrentFrameNumber = 0;
+
+ Mutex mFrameEventHistoryMutex;
+ ConsumerFrameEventHistory mFrameEventHistory GUARDED_BY(mFrameEventHistoryMutex);
+ std::queue<uint64_t> mDisconnectEvents GUARDED_BY(mFrameEventHistoryMutex);
+ bool mCurrentlyConnected GUARDED_BY(mFrameEventHistoryMutex);
+ bool mPreviouslyConnected GUARDED_BY(mFrameEventHistoryMutex);
+};
+
class BLASTBufferQueue
: public ConsumerBase::FrameAvailableListener, public BufferItemConsumer::BufferFreedListener
{
@@ -89,7 +118,7 @@
sp<IGraphicBufferConsumer> mConsumer;
sp<IGraphicBufferProducer> mProducer;
- sp<BufferItemConsumer> mBufferItemConsumer;
+ sp<BLASTBufferItemConsumer> mBufferItemConsumer;
SurfaceComposerClient::Transaction* mNextTransaction GUARDED_BY(mMutex);
};
diff --git a/libs/gui/include/gui/DisplayEventDispatcher.h b/libs/gui/include/gui/DisplayEventDispatcher.h
index 679d572..fcdf6bf 100644
--- a/libs/gui/include/gui/DisplayEventDispatcher.h
+++ b/libs/gui/include/gui/DisplayEventDispatcher.h
@@ -32,7 +32,7 @@
void dispose();
status_t scheduleVsync();
void toggleConfigEvents(ISurfaceComposer::ConfigChanged configChangeFlag);
- int getFd();
+ int getFd() const;
virtual int handleEvent(int receiveFd, int events, void* data);
protected:
diff --git a/libs/gui/include/gui/FrameTimestamps.h b/libs/gui/include/gui/FrameTimestamps.h
index df02494..4af8659 100644
--- a/libs/gui/include/gui/FrameTimestamps.h
+++ b/libs/gui/include/gui/FrameTimestamps.h
@@ -174,7 +174,6 @@
std::shared_ptr<FenceTime> acquireFence{FenceTime::NO_FENCE};
};
-
// Used by the consumer to keep track of which fields it already sent to
// the producer.
class FrameEventDirtyFields {
@@ -207,6 +206,7 @@
~ConsumerFrameEventHistory() override;
void onDisconnect();
+ void setProducerWantsEvents();
void initializeCompositorTiming(const CompositorTiming& compositorTiming);
diff --git a/libs/gui/include/gui/ITransactionCompletedListener.h b/libs/gui/include/gui/ITransactionCompletedListener.h
index 9c15225..c58634b 100644
--- a/libs/gui/include/gui/ITransactionCompletedListener.h
+++ b/libs/gui/include/gui/ITransactionCompletedListener.h
@@ -21,6 +21,7 @@
#include <binder/Parcelable.h>
#include <binder/SafeInterface.h>
+#include <gui/FrameTimestamps.h>
#include <ui/Fence.h>
#include <utils/Timers.h>
@@ -35,6 +36,27 @@
using CallbackId = int64_t;
+class FrameEventHistoryStats : public Parcelable {
+public:
+ status_t writeToParcel(Parcel* output) const override;
+ status_t readFromParcel(const Parcel* input) override;
+
+ FrameEventHistoryStats() = default;
+ FrameEventHistoryStats(uint64_t fn, const sp<Fence>& gpuCompFence, CompositorTiming compTiming,
+ nsecs_t refreshTime, nsecs_t dequeueReadyTime)
+ : frameNumber(fn),
+ gpuCompositionDoneFence(gpuCompFence),
+ compositorTiming(compTiming),
+ refreshStartTime(refreshTime),
+ dequeueReadyTime(dequeueReadyTime) {}
+
+ uint64_t frameNumber;
+ sp<Fence> gpuCompositionDoneFence;
+ CompositorTiming compositorTiming;
+ nsecs_t refreshStartTime;
+ nsecs_t dequeueReadyTime;
+};
+
class SurfaceStats : public Parcelable {
public:
status_t writeToParcel(Parcel* output) const override;
@@ -42,16 +64,18 @@
SurfaceStats() = default;
SurfaceStats(const sp<IBinder>& sc, nsecs_t time, const sp<Fence>& prevReleaseFence,
- uint32_t hint)
+ uint32_t hint, FrameEventHistoryStats frameEventStats)
: surfaceControl(sc),
acquireTime(time),
previousReleaseFence(prevReleaseFence),
- transformHint(hint) {}
+ transformHint(hint),
+ eventStats(frameEventStats) {}
sp<IBinder> surfaceControl;
nsecs_t acquireTime = -1;
sp<Fence> previousReleaseFence;
uint32_t transformHint = 0;
+ FrameEventHistoryStats eventStats;
};
class TransactionStats : public Parcelable {
diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h
index c256a09..2d53b48 100644
--- a/libs/gui/include/gui/LayerState.h
+++ b/libs/gui/include/gui/LayerState.h
@@ -102,6 +102,7 @@
eFrameRateSelectionPriority = 0x20'00000000,
eFrameRateChanged = 0x40'00000000,
eBackgroundBlurRadiusChanged = 0x80'00000000,
+ eProducerDisconnect = 0x100'00000000,
};
layer_state_t()
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index 6eec2b7..d0bb6a3 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -52,17 +52,24 @@
class Region;
struct SurfaceControlStats {
- SurfaceControlStats(const sp<SurfaceControl>& sc, nsecs_t time,
- const sp<Fence>& prevReleaseFence, uint32_t hint)
+ SurfaceControlStats(const sp<SurfaceControl>& sc, nsecs_t latchTime, nsecs_t acquireTime,
+ const sp<Fence>& presentFence, const sp<Fence>& prevReleaseFence,
+ uint32_t hint, FrameEventHistoryStats eventStats)
: surfaceControl(sc),
- acquireTime(time),
+ latchTime(latchTime),
+ acquireTime(acquireTime),
+ presentFence(presentFence),
previousReleaseFence(prevReleaseFence),
- transformHint(hint) {}
+ transformHint(hint),
+ frameEventStats(eventStats) {}
sp<SurfaceControl> surfaceControl;
+ nsecs_t latchTime = -1;
nsecs_t acquireTime = -1;
+ sp<Fence> presentFence;
sp<Fence> previousReleaseFence;
uint32_t transformHint = 0;
+ FrameEventHistoryStats frameEventStats;
};
using TransactionCompletedCallbackTakesContext =
@@ -484,6 +491,9 @@
Transaction& addTransactionCompletedCallback(
TransactionCompletedCallbackTakesContext callback, void* callbackContext);
+ // ONLY FOR BLAST ADAPTER
+ Transaction& notifyProducerDisconnect(const sp<SurfaceControl>& sc);
+
// Detaches all child surfaces (and their children recursively)
// from their SurfaceControl.
// The child SurfaceControls will not throw exceptions or return errors,
diff --git a/libs/gui/tests/BLASTBufferQueue_test.cpp b/libs/gui/tests/BLASTBufferQueue_test.cpp
index a273914..b40eb14 100644
--- a/libs/gui/tests/BLASTBufferQueue_test.cpp
+++ b/libs/gui/tests/BLASTBufferQueue_test.cpp
@@ -21,6 +21,7 @@
#include <android/hardware/graphics/common/1.2/types.h>
#include <gui/BufferQueueCore.h>
#include <gui/BufferQueueProducer.h>
+#include <gui/FrameTimestamps.h>
#include <gui/IGraphicBufferProducer.h>
#include <gui/IProducerListener.h>
#include <gui/SurfaceComposerClient.h>
@@ -647,4 +648,79 @@
TEST_F(BLASTBufferQueueTransformTest, setTransform_ROT_270) {
test(ui::Transform::ROT_270);
}
+
+class BLASTFrameEventHistoryTest : public BLASTBufferQueueTest {
+public:
+ void setUpAndQueueBuffer(const sp<IGraphicBufferProducer>& igbProducer,
+ nsecs_t* requestedPresentTime, nsecs_t* postedTime,
+ IGraphicBufferProducer::QueueBufferOutput* qbOutput,
+ bool getFrameTimestamps) {
+ int slot;
+ sp<Fence> fence;
+ sp<GraphicBuffer> buf;
+ auto ret = igbProducer->dequeueBuffer(&slot, &fence, mDisplayWidth, mDisplayHeight,
+ PIXEL_FORMAT_RGBA_8888, GRALLOC_USAGE_SW_WRITE_OFTEN,
+ nullptr, nullptr);
+ ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, ret);
+ ASSERT_EQ(OK, igbProducer->requestBuffer(slot, &buf));
+
+ nsecs_t requestedTime = systemTime();
+ if (requestedPresentTime) *requestedPresentTime = requestedTime;
+ IGraphicBufferProducer::QueueBufferInput input(requestedTime, false, HAL_DATASPACE_UNKNOWN,
+ Rect(mDisplayWidth, mDisplayHeight),
+ NATIVE_WINDOW_SCALING_MODE_FREEZE, 0,
+ Fence::NO_FENCE, /*sticky*/ 0,
+ getFrameTimestamps);
+ if (postedTime) *postedTime = systemTime();
+ igbProducer->queueBuffer(slot, input, qbOutput);
+ }
+};
+
+TEST_F(BLASTFrameEventHistoryTest, FrameEventHistory_Basic) {
+ BLASTBufferQueueHelper adapter(mSurfaceControl, mDisplayWidth, mDisplayHeight);
+ sp<IGraphicBufferProducer> igbProducer;
+ ProducerFrameEventHistory history;
+ setUpProducer(adapter, igbProducer);
+
+ IGraphicBufferProducer::QueueBufferOutput qbOutput;
+ nsecs_t requestedPresentTimeA = 0;
+ nsecs_t postedTimeA = 0;
+ setUpAndQueueBuffer(igbProducer, &requestedPresentTimeA, &postedTimeA, &qbOutput, true);
+ history.applyDelta(qbOutput.frameTimestamps);
+
+ FrameEvents* events = nullptr;
+ events = history.getFrame(1);
+ ASSERT_NE(nullptr, events);
+ ASSERT_EQ(1, events->frameNumber);
+ ASSERT_EQ(requestedPresentTimeA, events->requestedPresentTime);
+ ASSERT_GE(events->postedTime, postedTimeA);
+
+ adapter.waitForCallbacks();
+
+ // queue another buffer so we query for frame event deltas
+ nsecs_t requestedPresentTimeB = 0;
+ nsecs_t postedTimeB = 0;
+ setUpAndQueueBuffer(igbProducer, &requestedPresentTimeB, &postedTimeB, &qbOutput, true);
+ history.applyDelta(qbOutput.frameTimestamps);
+ events = history.getFrame(1);
+ ASSERT_NE(nullptr, events);
+
+ // frame number, requestedPresentTime, and postTime should not have changed
+ ASSERT_EQ(1, events->frameNumber);
+ ASSERT_EQ(requestedPresentTimeA, events->requestedPresentTime);
+ ASSERT_GE(events->postedTime, postedTimeA);
+
+ ASSERT_GE(events->latchTime, postedTimeA);
+ ASSERT_GE(events->dequeueReadyTime, events->latchTime);
+ ASSERT_NE(nullptr, events->gpuCompositionDoneFence);
+ ASSERT_NE(nullptr, events->displayPresentFence);
+ ASSERT_NE(nullptr, events->releaseFence);
+
+ // we should also have gotten the initial values for the next frame
+ events = history.getFrame(2);
+ ASSERT_NE(nullptr, events);
+ ASSERT_EQ(2, events->frameNumber);
+ ASSERT_EQ(requestedPresentTimeB, events->requestedPresentTime);
+ ASSERT_GE(events->postedTime, postedTimeB);
+}
} // namespace android
diff --git a/libs/nativedisplay/AChoreographer.cpp b/libs/nativedisplay/AChoreographer.cpp
index 58fff8f..0f7e2fb 100644
--- a/libs/nativedisplay/AChoreographer.cpp
+++ b/libs/nativedisplay/AChoreographer.cpp
@@ -264,6 +264,11 @@
return reinterpret_cast<Choreographer*>(choreographer);
}
+static inline const Choreographer* AChoreographer_to_Choreographer(
+ const AChoreographer* choreographer) {
+ return reinterpret_cast<const Choreographer*>(choreographer);
+}
+
static inline AChoreographer* Choreographer_to_AChoreographer(Choreographer* choreographer) {
return reinterpret_cast<AChoreographer*>(choreographer);
}
@@ -321,7 +326,7 @@
delete AChoreographer_to_Choreographer(choreographer);
}
-int AChoreographer_getFd(AChoreographer* choreographer) {
+int AChoreographer_getFd(const AChoreographer* choreographer) {
return AChoreographer_to_Choreographer(choreographer)->getFd();
}
diff --git a/libs/nativedisplay/include/apex/choreographer.h b/libs/nativedisplay/include/apex/choreographer.h
index b17b497..683abc4 100644
--- a/libs/nativedisplay/include/apex/choreographer.h
+++ b/libs/nativedisplay/include/apex/choreographer.h
@@ -43,7 +43,7 @@
* events. One such way is registering the file descriptor to a Looper instance,
* although this is not a requirement.
*/
-int AChoreographer_getFd(AChoreographer* choreographer);
+int AChoreographer_getFd(const AChoreographer* choreographer);
/**
* Provides a callback to handle all pending events emitted by this
diff --git a/services/gpuservice/GpuService.cpp b/services/gpuservice/GpuService.cpp
index 91a76f1..7bb0e4a 100644
--- a/services/gpuservice/GpuService.cpp
+++ b/services/gpuservice/GpuService.cpp
@@ -57,16 +57,6 @@
isDriverLoaded, driverLoadingTime);
}
-status_t GpuService::getGpuStatsGlobalInfo(std::vector<GpuStatsGlobalInfo>* outStats) const {
- mGpuStats->pullGlobalStats(outStats);
- return OK;
-}
-
-status_t GpuService::getGpuStatsAppInfo(std::vector<GpuStatsAppInfo>* outStats) const {
- mGpuStats->pullAppStats(outStats);
- return OK;
-}
-
void GpuService::setTargetStats(const std::string& appPackageName, const uint64_t driverVersionCode,
const GpuStatsInfo::Stats stats, const uint64_t value) {
mGpuStats->insertTargetStats(appPackageName, driverVersionCode, stats, value);
diff --git a/services/gpuservice/GpuService.h b/services/gpuservice/GpuService.h
index b3dc2e2..b3e34d5 100644
--- a/services/gpuservice/GpuService.h
+++ b/services/gpuservice/GpuService.h
@@ -25,22 +25,11 @@
#include <mutex>
#include <vector>
-#include <unordered_map>
namespace android {
class GpuStats;
-struct MemoryStruct {
- int64_t gpuMemory;
- int64_t mappedMemory;
- int64_t ionMemory;
-};
-
-// A map that keeps track of how much memory of each type is allocated by every process.
-// Format: map[pid][memoryType] = MemoryStruct()'
-using GpuMemoryMap = std::unordered_map<int32_t, std::unordered_map<std::string, MemoryStruct>>;
-
class GpuService : public BnGpuService, public PriorityDumper {
public:
static const char* const SERVICE_NAME ANDROID_API;
@@ -59,8 +48,6 @@
const std::string& appPackageName, const int32_t vulkanVersion,
GpuStatsInfo::Driver driver, bool isDriverLoaded,
int64_t driverLoadingTime) override;
- status_t getGpuStatsGlobalInfo(std::vector<GpuStatsGlobalInfo>* outStats) const override;
- status_t getGpuStatsAppInfo(std::vector<GpuStatsAppInfo>* outStats) const override;
void setTargetStats(const std::string& appPackageName, const uint64_t driverVersionCode,
const GpuStatsInfo::Stats stats, const uint64_t value) override;
@@ -82,8 +69,6 @@
status_t doDump(int fd, const Vector<String16>& args, bool asProto);
- status_t getQCommGpuMemoryInfo(GpuMemoryMap* memories, std::string* result, int32_t dumpPid) const;
-
/*
* Attributes
*/
diff --git a/services/gpuservice/gpustats/Android.bp b/services/gpuservice/gpustats/Android.bp
index 49a98cc..f52602a 100644
--- a/services/gpuservice/gpustats/Android.bp
+++ b/services/gpuservice/gpustats/Android.bp
@@ -7,9 +7,17 @@
"libcutils",
"libgraphicsenv",
"liblog",
+ "libprotoutil",
+ "libstatslog",
+ "libstatspull",
+ "libstatssocket",
"libutils",
],
export_include_dirs: ["include"],
+ export_shared_lib_headers: [
+ "libstatspull",
+ "libstatssocket",
+ ],
cppflags: [
"-Wall",
"-Werror",
diff --git a/services/gpuservice/gpustats/GpuStats.cpp b/services/gpuservice/gpustats/GpuStats.cpp
index 71e6b97..d094532 100644
--- a/services/gpuservice/gpustats/GpuStats.cpp
+++ b/services/gpuservice/gpustats/GpuStats.cpp
@@ -17,16 +17,31 @@
#define LOG_TAG "GpuStats"
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
-#include <gpustats/GpuStats.h>
+#include "gpustats/GpuStats.h"
+#include <android/util/ProtoOutputStream.h>
#include <cutils/properties.h>
#include <log/log.h>
+#include <stats_event.h>
+#include <statslog.h>
#include <utils/Trace.h>
#include <unordered_set>
namespace android {
+GpuStats::GpuStats() {
+ AStatsManager_registerPullAtomCallback(android::util::GPU_STATS_GLOBAL_INFO,
+ GpuStats::pullAtomCallback, nullptr, this);
+ AStatsManager_registerPullAtomCallback(android::util::GPU_STATS_APP_INFO,
+ GpuStats::pullAtomCallback, nullptr, this);
+}
+
+GpuStats::~GpuStats() {
+ AStatsManager_unregisterPullAtomCallback(android::util::GPU_STATS_GLOBAL_INFO);
+ AStatsManager_unregisterPullAtomCallback(android::util::GPU_STATS_APP_INFO);
+}
+
static void addLoadingCount(GpuStatsInfo::Driver driver, bool isDriverLoaded,
GpuStatsGlobalInfo* const outGlobalInfo) {
switch (driver) {
@@ -233,34 +248,114 @@
}
}
-void GpuStats::pullGlobalStats(std::vector<GpuStatsGlobalInfo>* outStats) {
- ATRACE_CALL();
+static std::string protoOutputStreamToByteString(android::util::ProtoOutputStream& proto) {
+ if (!proto.size()) return "";
- std::lock_guard<std::mutex> lock(mLock);
- outStats->clear();
- outStats->reserve(mGlobalStats.size());
-
- interceptSystemDriverStatsLocked();
-
- for (const auto& ele : mGlobalStats) {
- outStats->emplace_back(ele.second);
+ std::string byteString;
+ sp<android::util::ProtoReader> reader = proto.data();
+ while (reader->readBuffer() != nullptr) {
+ const size_t toRead = reader->currentToRead();
+ byteString.append((char*)reader->readBuffer(), toRead);
+ reader->move(toRead);
}
- mGlobalStats.clear();
+ if (byteString.size() != proto.size()) return "";
+
+ return byteString;
}
-void GpuStats::pullAppStats(std::vector<GpuStatsAppInfo>* outStats) {
+static std::string int64VectorToProtoByteString(const std::vector<int64_t>& value) {
+ if (value.empty()) return "";
+
+ android::util::ProtoOutputStream proto;
+ for (const auto& ele : value) {
+ proto.write(android::util::FIELD_TYPE_INT64 | android::util::FIELD_COUNT_REPEATED |
+ 1 /* field id */,
+ (long long)ele);
+ }
+
+ return protoOutputStreamToByteString(proto);
+}
+
+AStatsManager_PullAtomCallbackReturn GpuStats::pullAppInfoAtom(AStatsEventList* data) {
ATRACE_CALL();
std::lock_guard<std::mutex> lock(mLock);
- outStats->clear();
- outStats->reserve(mAppStats.size());
- for (const auto& ele : mAppStats) {
- outStats->emplace_back(ele.second);
+ if (data) {
+ for (const auto& ele : mAppStats) {
+ AStatsEvent* event = AStatsEventList_addStatsEvent(data);
+ AStatsEvent_setAtomId(event, android::util::GPU_STATS_APP_INFO);
+ AStatsEvent_writeString(event, ele.second.appPackageName.c_str());
+ AStatsEvent_writeInt64(event, ele.second.driverVersionCode);
+
+ std::string bytes = int64VectorToProtoByteString(ele.second.glDriverLoadingTime);
+ AStatsEvent_writeByteArray(event, (const uint8_t*)bytes.c_str(), bytes.length());
+
+ bytes = int64VectorToProtoByteString(ele.second.vkDriverLoadingTime);
+ AStatsEvent_writeByteArray(event, (const uint8_t*)bytes.c_str(), bytes.length());
+
+ bytes = int64VectorToProtoByteString(ele.second.angleDriverLoadingTime);
+ AStatsEvent_writeByteArray(event, (const uint8_t*)bytes.c_str(), bytes.length());
+
+ AStatsEvent_writeBool(event, ele.second.cpuVulkanInUse);
+ AStatsEvent_writeBool(event, ele.second.falsePrerotation);
+ AStatsEvent_writeBool(event, ele.second.gles1InUse);
+ AStatsEvent_build(event);
+ }
}
mAppStats.clear();
+
+ return AStatsManager_PULL_SUCCESS;
+}
+
+AStatsManager_PullAtomCallbackReturn GpuStats::pullGlobalInfoAtom(AStatsEventList* data) {
+ ATRACE_CALL();
+
+ std::lock_guard<std::mutex> lock(mLock);
+ // flush cpuVulkanVersion and glesVersion to builtin driver stats
+ interceptSystemDriverStatsLocked();
+
+ if (data) {
+ for (const auto& ele : mGlobalStats) {
+ AStatsEvent* event = AStatsEventList_addStatsEvent(data);
+ AStatsEvent_setAtomId(event, android::util::GPU_STATS_GLOBAL_INFO);
+ AStatsEvent_writeString(event, ele.second.driverPackageName.c_str());
+ AStatsEvent_writeString(event, ele.second.driverVersionName.c_str());
+ AStatsEvent_writeInt64(event, ele.second.driverVersionCode);
+ AStatsEvent_writeInt64(event, ele.second.driverBuildTime);
+ AStatsEvent_writeInt64(event, ele.second.glLoadingCount);
+ AStatsEvent_writeInt64(event, ele.second.glLoadingFailureCount);
+ AStatsEvent_writeInt64(event, ele.second.vkLoadingCount);
+ AStatsEvent_writeInt64(event, ele.second.vkLoadingFailureCount);
+ AStatsEvent_writeInt32(event, ele.second.vulkanVersion);
+ AStatsEvent_writeInt32(event, ele.second.cpuVulkanVersion);
+ AStatsEvent_writeInt32(event, ele.second.glesVersion);
+ AStatsEvent_writeInt64(event, ele.second.angleLoadingCount);
+ AStatsEvent_writeInt64(event, ele.second.angleLoadingFailureCount);
+ AStatsEvent_build(event);
+ }
+ }
+
+ mGlobalStats.clear();
+
+ return AStatsManager_PULL_SUCCESS;
+}
+
+AStatsManager_PullAtomCallbackReturn GpuStats::pullAtomCallback(int32_t atomTag,
+ AStatsEventList* data,
+ void* cookie) {
+ ATRACE_CALL();
+
+ GpuStats* pGpuStats = reinterpret_cast<GpuStats*>(cookie);
+ if (atomTag == android::util::GPU_STATS_GLOBAL_INFO) {
+ return pGpuStats->pullGlobalInfoAtom(data);
+ } else if (atomTag == android::util::GPU_STATS_APP_INFO) {
+ return pGpuStats->pullAppInfoAtom(data);
+ }
+
+ return AStatsManager_PULL_SKIP;
}
} // namespace android
diff --git a/services/gpuservice/gpustats/include/gpustats/GpuStats.h b/services/gpuservice/gpustats/include/gpustats/GpuStats.h
index bcb9e0d..8ca4e4e 100644
--- a/services/gpuservice/gpustats/include/gpustats/GpuStats.h
+++ b/services/gpuservice/gpustats/include/gpustats/GpuStats.h
@@ -18,6 +18,7 @@
#include <graphicsenv/GpuStatsInfo.h>
#include <graphicsenv/GraphicsEnv.h>
+#include <stats_pull_atom_callback.h>
#include <utils/String16.h>
#include <utils/Vector.h>
@@ -29,8 +30,8 @@
class GpuStats {
public:
- GpuStats() = default;
- ~GpuStats() = default;
+ GpuStats();
+ ~GpuStats();
// Insert new gpu driver stats into global stats and app stats.
void insertDriverStats(const std::string& driverPackageName,
@@ -43,15 +44,22 @@
const GpuStatsInfo::Stats stats, const uint64_t value);
// dumpsys interface
void dump(const Vector<String16>& args, std::string* result);
- // Pull gpu global stats
- void pullGlobalStats(std::vector<GpuStatsGlobalInfo>* outStats);
- // Pull gpu app stats
- void pullAppStats(std::vector<GpuStatsAppInfo>* outStats);
// This limits the worst case number of loading times tracked.
static const size_t MAX_NUM_LOADING_TIMES = 50;
private:
+ // Friend class for testing.
+ friend class TestableGpuStats;
+
+ // Native atom puller callback registered in statsd.
+ static AStatsManager_PullAtomCallbackReturn pullAtomCallback(int32_t atomTag,
+ AStatsEventList* data,
+ void* cookie);
+ // Pull global into into global atom.
+ AStatsManager_PullAtomCallbackReturn pullGlobalInfoAtom(AStatsEventList* data);
+ // Pull app into into app atom.
+ AStatsManager_PullAtomCallbackReturn pullAppInfoAtom(AStatsEventList* data);
// Dump global stats
void dumpGlobalLocked(std::string* result);
// Dump app stats
diff --git a/services/gpuservice/tests/unittests/Android.bp b/services/gpuservice/tests/unittests/Android.bp
index fee5bd4..538506d 100644
--- a/services/gpuservice/tests/unittests/Android.bp
+++ b/services/gpuservice/tests/unittests/Android.bp
@@ -26,6 +26,8 @@
"libgfxstats",
"libgraphicsenv",
"liblog",
+ "libstatslog",
+ "libstatspull",
"libutils",
],
static_libs: [
diff --git a/services/gpuservice/tests/unittests/GpuStatsTest.cpp b/services/gpuservice/tests/unittests/GpuStatsTest.cpp
index 276a334..37ebeae 100644
--- a/services/gpuservice/tests/unittests/GpuStatsTest.cpp
+++ b/services/gpuservice/tests/unittests/GpuStatsTest.cpp
@@ -21,9 +21,13 @@
#include <gmock/gmock.h>
#include <gpustats/GpuStats.h>
#include <gtest/gtest.h>
+#include <stats_pull_atom_callback.h>
+#include <statslog.h>
#include <utils/String16.h>
#include <utils/Vector.h>
+#include "TestableGpuStats.h"
+
namespace android {
namespace {
@@ -39,8 +43,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 +76,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>();
@@ -253,5 +253,55 @@
EXPECT_FALSE(inputCommand(InputCommand::DUMP_GLOBAL).empty());
}
+TEST_F(GpuStatsTest, skipPullInvalidAtom) {
+ TestableGpuStats testableGpuStats(mGpuStats.get());
+ mGpuStats->insertDriverStats(BUILTIN_DRIVER_PKG_NAME, BUILTIN_DRIVER_VER_NAME,
+ BUILTIN_DRIVER_VER_CODE, BUILTIN_DRIVER_BUILD_TIME, APP_PKG_NAME_1,
+ VULKAN_VERSION, GpuStatsInfo::Driver::GL, true,
+ DRIVER_LOADING_TIME_1);
+
+ EXPECT_FALSE(inputCommand(InputCommand::DUMP_GLOBAL).empty());
+ EXPECT_FALSE(inputCommand(InputCommand::DUMP_APP).empty());
+
+ EXPECT_TRUE(testableGpuStats.makePullAtomCallback(-1) == AStatsManager_PULL_SKIP);
+
+ EXPECT_FALSE(inputCommand(InputCommand::DUMP_GLOBAL).empty());
+ EXPECT_FALSE(inputCommand(InputCommand::DUMP_APP).empty());
+}
+
+TEST_F(GpuStatsTest, canPullGlobalAtom) {
+ TestableGpuStats testableGpuStats(mGpuStats.get());
+ mGpuStats->insertDriverStats(BUILTIN_DRIVER_PKG_NAME, BUILTIN_DRIVER_VER_NAME,
+ BUILTIN_DRIVER_VER_CODE, BUILTIN_DRIVER_BUILD_TIME, APP_PKG_NAME_1,
+ VULKAN_VERSION, GpuStatsInfo::Driver::GL, true,
+ DRIVER_LOADING_TIME_1);
+
+ EXPECT_FALSE(inputCommand(InputCommand::DUMP_GLOBAL).empty());
+ EXPECT_FALSE(inputCommand(InputCommand::DUMP_APP).empty());
+
+ EXPECT_TRUE(testableGpuStats.makePullAtomCallback(android::util::GPU_STATS_GLOBAL_INFO) ==
+ AStatsManager_PULL_SUCCESS);
+
+ EXPECT_TRUE(inputCommand(InputCommand::DUMP_GLOBAL).empty());
+ EXPECT_FALSE(inputCommand(InputCommand::DUMP_APP).empty());
+}
+
+TEST_F(GpuStatsTest, canPullAppAtom) {
+ TestableGpuStats testableGpuStats(mGpuStats.get());
+ mGpuStats->insertDriverStats(BUILTIN_DRIVER_PKG_NAME, BUILTIN_DRIVER_VER_NAME,
+ BUILTIN_DRIVER_VER_CODE, BUILTIN_DRIVER_BUILD_TIME, APP_PKG_NAME_1,
+ VULKAN_VERSION, GpuStatsInfo::Driver::GL, true,
+ DRIVER_LOADING_TIME_1);
+
+ EXPECT_FALSE(inputCommand(InputCommand::DUMP_GLOBAL).empty());
+ EXPECT_FALSE(inputCommand(InputCommand::DUMP_APP).empty());
+
+ EXPECT_TRUE(testableGpuStats.makePullAtomCallback(android::util::GPU_STATS_APP_INFO) ==
+ AStatsManager_PULL_SUCCESS);
+
+ EXPECT_FALSE(inputCommand(InputCommand::DUMP_GLOBAL).empty());
+ EXPECT_TRUE(inputCommand(InputCommand::DUMP_APP).empty());
+}
+
} // namespace
} // namespace android
diff --git a/services/gpuservice/tests/unittests/TestableGpuStats.h b/services/gpuservice/tests/unittests/TestableGpuStats.h
new file mode 100644
index 0000000..4ea564c
--- /dev/null
+++ b/services/gpuservice/tests/unittests/TestableGpuStats.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <gpustats/GpuStats.h>
+#include <stdint.h>
+
+namespace android {
+
+class TestableGpuStats {
+public:
+ explicit TestableGpuStats(GpuStats *gpuStats) : mGpuStats(gpuStats) {}
+
+ AStatsManager_PullAtomCallbackReturn makePullAtomCallback(int32_t atomTag) {
+ return mGpuStats->pullAtomCallback(atomTag, nullptr, mGpuStats);
+ }
+
+private:
+ GpuStats *mGpuStats;
+};
+
+} // namespace android
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/sensorservice/Android.bp b/services/sensorservice/Android.bp
index 1c9a4af..5246c78 100644
--- a/services/sensorservice/Android.bp
+++ b/services/sensorservice/Android.bp
@@ -42,6 +42,7 @@
"libbinder",
"libsensor",
"libsensorprivacy",
+ "libprotoutil",
"libcrypto",
"libbase",
"libhidlbase",
@@ -52,6 +53,8 @@
static_libs: ["android.hardware.sensors@1.0-convert"],
+ generated_headers: ["framework-cppstream-protos"],
+
// our public headers depend on libsensor and libsensorprivacy
export_shared_lib_headers: ["libsensor", "libsensorprivacy"],
}
diff --git a/services/sensorservice/RecentEventLogger.cpp b/services/sensorservice/RecentEventLogger.cpp
index 207b097..d7ca6e1 100644
--- a/services/sensorservice/RecentEventLogger.cpp
+++ b/services/sensorservice/RecentEventLogger.cpp
@@ -17,6 +17,8 @@
#include "RecentEventLogger.h"
#include "SensorServiceUtils.h"
+#include <android/util/ProtoOutputStream.h>
+#include <frameworks/base/core/proto/android/service/sensor_service.proto.h>
#include <utils/Timers.h>
#include <inttypes.h>
@@ -84,6 +86,40 @@
return std::string(buffer.string());
}
+/**
+ * Dump debugging information as android.service.SensorEventsProto protobuf message using
+ * ProtoOutputStream.
+ *
+ * See proto definition and some notes about ProtoOutputStream in
+ * frameworks/base/core/proto/android/service/sensor_service.proto
+ */
+void RecentEventLogger::dump(util::ProtoOutputStream* proto) const {
+ using namespace service::SensorEventsProto;
+ std::lock_guard<std::mutex> lk(mLock);
+
+ proto->write(RecentEventsLog::RECENT_EVENTS_COUNT, int(mRecentEvents.size()));
+ for (int i = mRecentEvents.size() - 1; i >= 0; --i) {
+ const auto& ev = mRecentEvents[i];
+ const uint64_t token = proto->start(RecentEventsLog::EVENTS);
+ proto->write(Event::TIMESTAMP_SEC, float(ev.mEvent.timestamp) / 1e9f);
+ proto->write(Event::WALL_TIMESTAMP_MS, ev.mWallTime.tv_sec * 1000LL
+ + ns2ms(ev.mWallTime.tv_nsec));
+
+ if (mMaskData) {
+ proto->write(Event::MASKED, true);
+ } else {
+ if (mSensorType == SENSOR_TYPE_STEP_COUNTER) {
+ proto->write(Event::INT64_DATA, int64_t(ev.mEvent.u64.step_counter));
+ } else {
+ for (size_t k = 0; k < mEventSize; ++k) {
+ proto->write(Event::FLOAT_ARRAY, ev.mEvent.data[k]);
+ }
+ }
+ }
+ proto->end(token);
+ }
+}
+
void RecentEventLogger::setFormat(std::string format) {
if (format == "mask_data" ) {
mMaskData = true;
diff --git a/services/sensorservice/RecentEventLogger.h b/services/sensorservice/RecentEventLogger.h
index 67378b7..3a2ae77 100644
--- a/services/sensorservice/RecentEventLogger.h
+++ b/services/sensorservice/RecentEventLogger.h
@@ -48,6 +48,7 @@
// Dumpable interface
virtual std::string dump() const override;
+ virtual void dump(util::ProtoOutputStream* proto) const override;
virtual void setFormat(std::string format) override;
protected:
diff --git a/services/sensorservice/SensorDevice.cpp b/services/sensorservice/SensorDevice.cpp
index c7a8f5b..33f940f 100644
--- a/services/sensorservice/SensorDevice.cpp
+++ b/services/sensorservice/SensorDevice.cpp
@@ -21,6 +21,8 @@
#include "SensorService.h"
#include <android-base/logging.h>
+#include <android/util/ProtoOutputStream.h>
+#include <frameworks/base/core/proto/android/service/sensor_service.proto.h>
#include <sensors/convert.h>
#include <cutils/atomic.h>
#include <utils/Errors.h>
@@ -39,6 +41,7 @@
using android::hardware::hidl_vec;
using android::hardware::Return;
using android::SensorDeviceUtils::HidlServiceRegistrationWaiter;
+using android::util::ProtoOutputStream;
namespace android {
// ---------------------------------------------------------------------------
@@ -396,6 +399,43 @@
return result.string();
}
+/**
+ * Dump debugging information as android.service.SensorDeviceProto protobuf message using
+ * ProtoOutputStream.
+ *
+ * See proto definition and some notes about ProtoOutputStream in
+ * frameworks/base/core/proto/android/service/sensor_service.proto
+ */
+void SensorDevice::dump(ProtoOutputStream* proto) const {
+ using namespace service::SensorDeviceProto;
+ if (mSensors == nullptr) {
+ proto->write(INITIALIZED , false);
+ return;
+ }
+ proto->write(INITIALIZED , true);
+ proto->write(TOTAL_SENSORS , int(mSensorList.size()));
+ proto->write(ACTIVE_SENSORS , int(mActivationCount.size()));
+
+ Mutex::Autolock _l(mLock);
+ for (const auto & s : mSensorList) {
+ int32_t handle = s.handle;
+ const Info& info = mActivationCount.valueFor(handle);
+ if (info.numActiveClients() == 0) continue;
+
+ uint64_t token = proto->start(SENSORS);
+ proto->write(SensorProto::HANDLE , handle);
+ proto->write(SensorProto::ACTIVE_COUNT , int(info.batchParams.size()));
+ for (size_t j = 0; j < info.batchParams.size(); j++) {
+ const BatchParams& params = info.batchParams[j];
+ proto->write(SensorProto::SAMPLING_PERIOD_MS , params.mTSample / 1e6f);
+ proto->write(SensorProto::BATCHING_PERIOD_MS , params.mTBatch / 1e6f);
+ }
+ proto->write(SensorProto::SAMPLING_PERIOD_SELECTED , info.bestBatchParams.mTSample / 1e6f);
+ proto->write(SensorProto::BATCHING_PERIOD_SELECTED , info.bestBatchParams.mTBatch / 1e6f);
+ proto->end(token);
+ }
+}
+
ssize_t SensorDevice::getSensorList(sensor_t const** list) {
*list = &mSensorList[0];
diff --git a/services/sensorservice/SensorDevice.h b/services/sensorservice/SensorDevice.h
index d2c6994..33aa7d6 100644
--- a/services/sensorservice/SensorDevice.h
+++ b/services/sensorservice/SensorDevice.h
@@ -123,7 +123,8 @@
bool isSensorActive(int handle) const;
// Dumpable
- virtual std::string dump() const;
+ virtual std::string dump() const override;
+ virtual void dump(util::ProtoOutputStream* proto) const override;
private:
friend class Singleton<SensorDevice>;
diff --git a/services/sensorservice/SensorDirectConnection.cpp b/services/sensorservice/SensorDirectConnection.cpp
index cd0ea5d..106efd6 100644
--- a/services/sensorservice/SensorDirectConnection.cpp
+++ b/services/sensorservice/SensorDirectConnection.cpp
@@ -16,12 +16,16 @@
#include "SensorDevice.h"
#include "SensorDirectConnection.h"
+#include <android/util/ProtoOutputStream.h>
+#include <frameworks/base/core/proto/android/service/sensor_service.proto.h>
#include <hardware/sensors.h>
#define UNUSED(x) (void)(x)
namespace android {
+using util::ProtoOutputStream;
+
SensorService::SensorDirectConnection::SensorDirectConnection(const sp<SensorService>& service,
uid_t uid, const sensors_direct_mem_t *mem, int32_t halChannelHandle,
const String16& opPackageName)
@@ -64,6 +68,27 @@
}
}
+/**
+ * Dump debugging information as android.service.SensorDirectConnectionProto protobuf message using
+ * ProtoOutputStream.
+ *
+ * See proto definition and some notes about ProtoOutputStream in
+ * frameworks/base/core/proto/android/service/sensor_service.proto
+ */
+void SensorService::SensorDirectConnection::dump(ProtoOutputStream* proto) const {
+ using namespace service::SensorDirectConnectionProto;
+ Mutex::Autolock _l(mConnectionLock);
+ proto->write(PACKAGE_NAME, std::string(String8(mOpPackageName).string()));
+ proto->write(HAL_CHANNEL_HANDLE, getHalChannelHandle());
+ proto->write(NUM_SENSOR_ACTIVATED, int(mActivated.size()));
+ for (auto &i : mActivated) {
+ uint64_t token = proto->start(SENSORS);
+ proto->write(SensorProto::SENSOR, i.first);
+ proto->write(SensorProto::RATE, i.second);
+ proto->end(token);
+ }
+}
+
sp<BitTube> SensorService::SensorDirectConnection::getSensorChannel() const {
return nullptr;
}
diff --git a/services/sensorservice/SensorDirectConnection.h b/services/sensorservice/SensorDirectConnection.h
index 5c398a8..ead08d3 100644
--- a/services/sensorservice/SensorDirectConnection.h
+++ b/services/sensorservice/SensorDirectConnection.h
@@ -40,6 +40,7 @@
const sensors_direct_mem_t *mem, int32_t halChannelHandle,
const String16& opPackageName);
void dump(String8& result) const;
+ void dump(util::ProtoOutputStream* proto) const;
uid_t getUid() const { return mUid; }
int32_t getHalChannelHandle() const;
bool isEquivalent(const sensors_direct_mem_t *mem) const;
diff --git a/services/sensorservice/SensorEventConnection.cpp b/services/sensorservice/SensorEventConnection.cpp
index 0e40940..9a13c00 100644
--- a/services/sensorservice/SensorEventConnection.cpp
+++ b/services/sensorservice/SensorEventConnection.cpp
@@ -17,6 +17,8 @@
#include <sys/socket.h>
#include <utils/threads.h>
+#include <android/util/ProtoOutputStream.h>
+#include <frameworks/base/core/proto/android/service/sensor_service.proto.h>
#include <sensor/SensorEventQueue.h>
#include "vec.h"
@@ -110,6 +112,51 @@
#endif
}
+/**
+ * Dump debugging information as android.service.SensorEventConnectionProto protobuf message using
+ * ProtoOutputStream.
+ *
+ * See proto definition and some notes about ProtoOutputStream in
+ * frameworks/base/core/proto/android/service/sensor_service.proto
+ */
+void SensorService::SensorEventConnection::dump(util::ProtoOutputStream* proto) const {
+ using namespace service::SensorEventConnectionProto;
+ Mutex::Autolock _l(mConnectionLock);
+
+ if (!mService->isWhiteListedPackage(getPackageName())) {
+ proto->write(OPERATING_MODE, OP_MODE_RESTRICTED);
+ } else if (mDataInjectionMode) {
+ proto->write(OPERATING_MODE, OP_MODE_DATA_INJECTION);
+ } else {
+ proto->write(OPERATING_MODE, OP_MODE_NORMAL);
+ }
+ proto->write(PACKAGE_NAME, std::string(mPackageName.string()));
+ proto->write(WAKE_LOCK_REF_COUNT, int32_t(mWakeLockRefCount));
+ proto->write(UID, int32_t(mUid));
+ proto->write(CACHE_SIZE, int32_t(mCacheSize));
+ proto->write(MAX_CACHE_SIZE, int32_t(mMaxCacheSize));
+ for (size_t i = 0; i < mSensorInfo.size(); ++i) {
+ const FlushInfo& flushInfo = mSensorInfo.valueAt(i);
+ const uint64_t token = proto->start(FLUSH_INFOS);
+ proto->write(FlushInfoProto::SENSOR_NAME,
+ std::string(mService->getSensorName(mSensorInfo.keyAt(i))));
+ proto->write(FlushInfoProto::SENSOR_HANDLE, mSensorInfo.keyAt(i));
+ proto->write(FlushInfoProto::FIRST_FLUSH_PENDING, flushInfo.mFirstFlushPending);
+ proto->write(FlushInfoProto::PENDING_FLUSH_EVENTS_TO_SEND,
+ flushInfo.mPendingFlushEventsToSend);
+ proto->end(token);
+ }
+#if DEBUG_CONNECTIONS
+ proto->write(EVENTS_RECEIVED, mEventsReceived);
+ proto->write(EVENTS_SENT, mEventsSent);
+ proto->write(EVENTS_CACHE, mEventsSentFromCache);
+ proto->write(EVENTS_DROPPED, mEventsReceived - (mEventsSentFromCache + mEventsSent +
+ mCacheSize));
+ proto->write(TOTAL_ACKS_NEEDED, mTotalAcksNeeded);
+ proto->write(TOTAL_ACKS_RECEIVED, mTotalAcksReceived);
+#endif
+}
+
bool SensorService::SensorEventConnection::addSensor(int32_t handle) {
Mutex::Autolock _l(mConnectionLock);
sp<SensorInterface> si = mService->getSensorInterfaceFromHandle(handle);
diff --git a/services/sensorservice/SensorEventConnection.h b/services/sensorservice/SensorEventConnection.h
index fd881cb..caf5d7c 100644
--- a/services/sensorservice/SensorEventConnection.h
+++ b/services/sensorservice/SensorEventConnection.h
@@ -62,6 +62,7 @@
bool removeSensor(int32_t handle);
void setFirstFlushPending(int32_t handle, bool value);
void dump(String8& result);
+ void dump(util::ProtoOutputStream* proto) const;
bool needsWakeLock();
void resetWakeLockRefCount();
String8 getPackageName() const;
diff --git a/services/sensorservice/SensorFusion.cpp b/services/sensorservice/SensorFusion.cpp
index 414f673..e27b52b 100644
--- a/services/sensorservice/SensorFusion.cpp
+++ b/services/sensorservice/SensorFusion.cpp
@@ -18,6 +18,9 @@
#include "SensorFusion.h"
#include "SensorService.h"
+#include <android/util/ProtoOutputStream.h>
+#include <frameworks/base/core/proto/android/service/sensor_service.proto.h>
+
namespace android {
// ---------------------------------------------------------------------------
@@ -183,7 +186,7 @@
return mAcc.getMinDelay();
}
-void SensorFusion::dump(String8& result) {
+void SensorFusion::dump(String8& result) const {
const Fusion& fusion_9axis(mFusions[FUSION_9AXIS]);
result.appendFormat("9-axis fusion %s (%zd clients), gyro-rate=%7.2fHz, "
"q=< %g, %g, %g, %g > (%g), "
@@ -235,5 +238,42 @@
fusion_nogyro.getBias().z);
}
+void SensorFusion::dumpFusion(FUSION_MODE mode, util::ProtoOutputStream* proto) const {
+ using namespace service::SensorFusionProto::FusionProto;
+ const Fusion& fusion(mFusions[mode]);
+ proto->write(ENABLED, mEnabled[mode]);
+ proto->write(NUM_CLIENTS, (int)mClients[mode].size());
+ proto->write(ESTIMATED_GYRO_RATE, mEstimatedGyroRate);
+ proto->write(ATTITUDE_X, fusion.getAttitude().x);
+ proto->write(ATTITUDE_Y, fusion.getAttitude().y);
+ proto->write(ATTITUDE_Z, fusion.getAttitude().z);
+ proto->write(ATTITUDE_W, fusion.getAttitude().w);
+ proto->write(ATTITUDE_LENGTH, length(fusion.getAttitude()));
+ proto->write(BIAS_X, fusion.getBias().x);
+ proto->write(BIAS_Y, fusion.getBias().y);
+ proto->write(BIAS_Z, fusion.getBias().z);
+}
+
+/**
+ * Dump debugging information as android.service.SensorFusionProto protobuf message using
+ * ProtoOutputStream.
+ *
+ * See proto definition and some notes about ProtoOutputStream in
+ * frameworks/base/core/proto/android/service/sensor_service.proto
+ */
+void SensorFusion::dump(util::ProtoOutputStream* proto) const {
+ uint64_t token = proto->start(service::SensorFusionProto::FUSION_9AXIS);
+ dumpFusion(FUSION_9AXIS, proto);
+ proto->end(token);
+
+ token = proto->start(service::SensorFusionProto::FUSION_NOMAG);
+ dumpFusion(FUSION_NOMAG, proto);
+ proto->end(token);
+
+ token = proto->start(service::SensorFusionProto::FUSION_NOGYRO);
+ dumpFusion(FUSION_NOGYRO, proto);
+ proto->end(token);
+}
+
// ---------------------------------------------------------------------------
}; // namespace android
diff --git a/services/sensorservice/SensorFusion.h b/services/sensorservice/SensorFusion.h
index 8c0fbf9..66a7290 100644
--- a/services/sensorservice/SensorFusion.h
+++ b/services/sensorservice/SensorFusion.h
@@ -90,7 +90,9 @@
float getPowerUsage(int mode=FUSION_9AXIS) const;
int32_t getMinDelay() const;
- void dump(String8& result);
+ void dump(String8& result) const;
+ void dump(util::ProtoOutputStream* proto) const;
+ void dumpFusion(FUSION_MODE mode, util::ProtoOutputStream* proto) const;
};
diff --git a/services/sensorservice/SensorList.cpp b/services/sensorservice/SensorList.cpp
index aa306d8..0ce32cc 100644
--- a/services/sensorservice/SensorList.cpp
+++ b/services/sensorservice/SensorList.cpp
@@ -16,6 +16,8 @@
#include "SensorList.h"
+#include <android/util/ProtoOutputStream.h>
+#include <frameworks/base/core/proto/android/service/sensor_service.proto.h>
#include <hardware/sensors.h>
#include <utils/String8.h>
@@ -203,6 +205,64 @@
return std::string(result.string());
}
+/**
+ * Dump debugging information as android.service.SensorListProto protobuf message using
+ * ProtoOutputStream.
+ *
+ * See proto definition and some notes about ProtoOutputStream in
+ * frameworks/base/core/proto/android/service/sensor_service.proto
+ */
+void SensorList::dump(util::ProtoOutputStream* proto) const {
+ using namespace service::SensorListProto;
+ using namespace service::SensorListProto::SensorProto;
+
+ forEachSensor([&proto] (const Sensor& s) -> bool {
+ const uint64_t token = proto->start(SENSORS);
+ proto->write(HANDLE, s.getHandle());
+ proto->write(NAME, std::string(s.getName().string()));
+ proto->write(VENDOR, std::string(s.getVendor().string()));
+ proto->write(VERSION, s.getVersion());
+ proto->write(STRING_TYPE, std::string(s.getStringType().string()));
+ proto->write(TYPE, s.getType());
+ proto->write(REQUIRED_PERMISSION, std::string(s.getRequiredPermission().size() ?
+ s.getRequiredPermission().string() : ""));
+ proto->write(FLAGS, int(s.getFlags()));
+ switch (s.getReportingMode()) {
+ case AREPORTING_MODE_CONTINUOUS:
+ proto->write(REPORTING_MODE, RM_CONTINUOUS);
+ break;
+ case AREPORTING_MODE_ON_CHANGE:
+ proto->write(REPORTING_MODE, RM_ON_CHANGE);
+ break;
+ case AREPORTING_MODE_ONE_SHOT:
+ proto->write(REPORTING_MODE, RM_ONE_SHOT);
+ break;
+ case AREPORTING_MODE_SPECIAL_TRIGGER:
+ proto->write(REPORTING_MODE, RM_SPECIAL_TRIGGER);
+ break;
+ default:
+ proto->write(REPORTING_MODE, RM_UNKNOWN);
+ }
+ proto->write(MAX_DELAY_US, s.getMaxDelay());
+ proto->write(MIN_DELAY_US, s.getMinDelay());
+ proto->write(FIFO_MAX_EVENT_COUNT, int(s.getFifoMaxEventCount()));
+ proto->write(FIFO_RESERVED_EVENT_COUNT, int(s.getFifoReservedEventCount()));
+ proto->write(IS_WAKEUP, s.isWakeUpSensor());
+ proto->write(DATA_INJECTION_SUPPORTED, s.isDataInjectionSupported());
+ proto->write(IS_DYNAMIC, s.isDynamicSensor());
+ proto->write(HAS_ADDITIONAL_INFO, s.hasAdditionalInfo());
+ proto->write(HIGHEST_RATE_LEVEL, s.getHighestDirectReportRateLevel());
+ proto->write(ASHMEM, s.isDirectChannelTypeSupported(SENSOR_DIRECT_MEM_TYPE_ASHMEM));
+ proto->write(GRALLOC, s.isDirectChannelTypeSupported(SENSOR_DIRECT_MEM_TYPE_GRALLOC));
+ proto->write(MIN_VALUE, s.getMinValue());
+ proto->write(MAX_VALUE, s.getMaxValue());
+ proto->write(RESOLUTION, s.getResolution());
+ proto->write(POWER_USAGE, s.getPowerUsage());
+ proto->end(token);
+ return true;
+ });
+}
+
SensorList::~SensorList() {
}
diff --git a/services/sensorservice/SensorList.h b/services/sensorservice/SensorList.h
index 6b90ad9..8424b22 100644
--- a/services/sensorservice/SensorList.h
+++ b/services/sensorservice/SensorList.h
@@ -71,6 +71,7 @@
// Dumpable interface
virtual std::string dump() const override;
+ virtual void dump(util::ProtoOutputStream* proto) const override;
virtual ~SensorList();
private:
diff --git a/services/sensorservice/SensorRegistrationInfo.h b/services/sensorservice/SensorRegistrationInfo.h
index 5411515..a34a65b 100644
--- a/services/sensorservice/SensorRegistrationInfo.h
+++ b/services/sensorservice/SensorRegistrationInfo.h
@@ -17,10 +17,14 @@
#ifndef ANDROID_SENSOR_REGISTRATION_INFO_H
#define ANDROID_SENSOR_REGISTRATION_INFO_H
-#include "SensorServiceUtils.h"
-#include <utils/Thread.h>
+#include <ctime>
#include <iomanip>
#include <sstream>
+#include <utils/Thread.h>
+
+#include <android/util/ProtoOutputStream.h>
+#include <frameworks/base/core/proto/android/service/sensor_service.proto.h>
+#include "SensorServiceUtils.h"
namespace android {
@@ -30,7 +34,7 @@
public:
SensorRegistrationInfo() : mPackageName() {
mSensorHandle = mSamplingRateUs = mMaxReportLatencyUs = INT32_MIN;
- mHour = mMin = mSec = INT8_MIN;
+ mRealtimeSec = 0;
mActivated = false;
}
@@ -47,25 +51,26 @@
mPid = (thread != nullptr) ? thread->getCallingPid() : -1;
mUid = (thread != nullptr) ? thread->getCallingUid() : -1;
- time_t rawtime = time(nullptr);
- struct tm * timeinfo = localtime(&rawtime);
- mHour = static_cast<int8_t>(timeinfo->tm_hour);
- mMin = static_cast<int8_t>(timeinfo->tm_min);
- mSec = static_cast<int8_t>(timeinfo->tm_sec);
+ timespec curTime;
+ clock_gettime(CLOCK_REALTIME_COARSE, &curTime);
+ mRealtimeSec = curTime.tv_sec;
}
static bool isSentinel(const SensorRegistrationInfo& info) {
- return (info.mHour == INT8_MIN &&
- info.mMin == INT8_MIN &&
- info.mSec == INT8_MIN);
+ return (info.mSensorHandle == INT32_MIN && info.mRealtimeSec == 0);
}
// Dumpable interface
virtual std::string dump() const override {
+ struct tm* timeinfo = localtime(&mRealtimeSec);
+ const int8_t hour = static_cast<int8_t>(timeinfo->tm_hour);
+ const int8_t min = static_cast<int8_t>(timeinfo->tm_min);
+ const int8_t sec = static_cast<int8_t>(timeinfo->tm_sec);
+
std::ostringstream ss;
- ss << std::setfill('0') << std::setw(2) << static_cast<int>(mHour) << ":"
- << std::setw(2) << static_cast<int>(mMin) << ":"
- << std::setw(2) << static_cast<int>(mSec)
+ ss << std::setfill('0') << std::setw(2) << static_cast<int>(hour) << ":"
+ << std::setw(2) << static_cast<int>(min) << ":"
+ << std::setw(2) << static_cast<int>(sec)
<< (mActivated ? " +" : " -")
<< " 0x" << std::hex << std::setw(8) << mSensorHandle << std::dec
<< std::setfill(' ') << " pid=" << std::setw(5) << mPid
@@ -77,6 +82,25 @@
return ss.str();
}
+ /**
+ * Dump debugging information as android.service.SensorRegistrationInfoProto protobuf message
+ * using ProtoOutputStream.
+ *
+ * See proto definition and some notes about ProtoOutputStream in
+ * frameworks/base/core/proto/android/service/sensor_service.proto
+ */
+ virtual void dump(util::ProtoOutputStream* proto) const override {
+ using namespace service::SensorRegistrationInfoProto;
+ proto->write(TIMESTAMP_SEC, int64_t(mRealtimeSec));
+ proto->write(SENSOR_HANDLE, mSensorHandle);
+ proto->write(PACKAGE_NAME, std::string(mPackageName.string()));
+ proto->write(PID, int32_t(mPid));
+ proto->write(UID, int32_t(mUid));
+ proto->write(SAMPLING_RATE_US, mSamplingRateUs);
+ proto->write(MAX_REPORT_LATENCY_US, mMaxReportLatencyUs);
+ proto->write(ACTIVATED, mActivated);
+ }
+
private:
int32_t mSensorHandle;
String8 mPackageName;
@@ -85,8 +109,7 @@
int64_t mSamplingRateUs;
int64_t mMaxReportLatencyUs;
bool mActivated;
- int8_t mHour, mMin, mSec;
-
+ time_t mRealtimeSec;
};
} // namespace android;
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index c2e1204..e803c9a 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -14,6 +14,8 @@
* limitations under the License.
*/
#include <android/content/pm/IPackageManagerNative.h>
+#include <android/util/ProtoOutputStream.h>
+#include <frameworks/base/core/proto/android/service/sensor_service.proto.h>
#include <binder/ActivityManager.h>
#include <binder/BinderService.h>
#include <binder/IServiceManager.h>
@@ -404,6 +406,8 @@
// Transition to data injection mode supported only from NORMAL mode.
return INVALID_OPERATION;
}
+ } else if (args.size() == 1 && args[0] == String16("--proto")) {
+ return dumpProtoLocked(fd, &connLock);
} else if (!mSensors.hasAnySensor()) {
result.append("No Sensors on the device\n");
result.appendFormat("devInitCheck : %d\n", SensorDevice::getInstance().initCheck());
@@ -506,6 +510,124 @@
return NO_ERROR;
}
+/**
+ * Dump debugging information as android.service.SensorServiceProto protobuf message using
+ * ProtoOutputStream.
+ *
+ * See proto definition and some notes about ProtoOutputStream in
+ * frameworks/base/core/proto/android/service/sensor_service.proto
+ */
+status_t SensorService::dumpProtoLocked(int fd, ConnectionSafeAutolock* connLock) const {
+ using namespace service::SensorServiceProto;
+ util::ProtoOutputStream proto;
+ const bool privileged = IPCThreadState::self()->getCallingUid() == 0;
+
+ timespec curTime;
+ clock_gettime(CLOCK_REALTIME, &curTime);
+ proto.write(CURRENT_TIME_MS, curTime.tv_sec * 1000 + ns2ms(curTime.tv_nsec));
+
+ // Write SensorDeviceProto
+ uint64_t token = proto.start(SENSOR_DEVICE);
+ SensorDevice::getInstance().dump(&proto);
+ proto.end(token);
+
+ // Write SensorListProto
+ token = proto.start(SENSORS);
+ mSensors.dump(&proto);
+ proto.end(token);
+
+ // Write SensorFusionProto
+ token = proto.start(FUSION_STATE);
+ SensorFusion::getInstance().dump(&proto);
+ proto.end(token);
+
+ // Write SensorEventsProto
+ token = proto.start(SENSOR_EVENTS);
+ for (auto&& i : mRecentEvent) {
+ sp<SensorInterface> s = mSensors.getInterface(i.first);
+ if (!i.second->isEmpty()) {
+ i.second->setFormat(privileged || s->getSensor().getRequiredPermission().isEmpty() ?
+ "normal" : "mask_data");
+ const uint64_t mToken = proto.start(service::SensorEventsProto::RECENT_EVENTS_LOGS);
+ proto.write(service::SensorEventsProto::RecentEventsLog::NAME,
+ std::string(s->getSensor().getName().string()));
+ i.second->dump(&proto);
+ proto.end(mToken);
+ }
+ }
+ proto.end(token);
+
+ // Write ActiveSensorProto
+ SensorDevice& dev = SensorDevice::getInstance();
+ for (size_t i=0 ; i<mActiveSensors.size() ; i++) {
+ int handle = mActiveSensors.keyAt(i);
+ if (dev.isSensorActive(handle)) {
+ token = proto.start(ACTIVE_SENSORS);
+ proto.write(service::ActiveSensorProto::NAME,
+ std::string(getSensorName(handle).string()));
+ proto.write(service::ActiveSensorProto::HANDLE, handle);
+ proto.write(service::ActiveSensorProto::NUM_CONNECTIONS,
+ int(mActiveSensors.valueAt(i)->getNumConnections()));
+ proto.end(token);
+ }
+ }
+
+ proto.write(SOCKET_BUFFER_SIZE, int(mSocketBufferSize));
+ proto.write(SOCKET_BUFFER_SIZE_IN_EVENTS, int(mSocketBufferSize / sizeof(sensors_event_t)));
+ proto.write(WAKE_LOCK_ACQUIRED, mWakeLockAcquired);
+
+ switch(mCurrentOperatingMode) {
+ case NORMAL:
+ proto.write(OPERATING_MODE, OP_MODE_NORMAL);
+ break;
+ case RESTRICTED:
+ proto.write(OPERATING_MODE, OP_MODE_RESTRICTED);
+ proto.write(WHITELISTED_PACKAGE, std::string(mWhiteListedPackage.string()));
+ break;
+ case DATA_INJECTION:
+ proto.write(OPERATING_MODE, OP_MODE_DATA_INJECTION);
+ proto.write(WHITELISTED_PACKAGE, std::string(mWhiteListedPackage.string()));
+ break;
+ default:
+ proto.write(OPERATING_MODE, OP_MODE_UNKNOWN);
+ }
+ proto.write(SENSOR_PRIVACY, mSensorPrivacyPolicy->isSensorPrivacyEnabled());
+
+ // Write repeated SensorEventConnectionProto
+ const auto& activeConnections = connLock->getActiveConnections();
+ for (size_t i = 0; i < activeConnections.size(); i++) {
+ token = proto.start(ACTIVE_CONNECTIONS);
+ activeConnections[i]->dump(&proto);
+ proto.end(token);
+ }
+
+ // Write repeated SensorDirectConnectionProto
+ const auto& directConnections = connLock->getDirectConnections();
+ for (size_t i = 0 ; i < directConnections.size() ; i++) {
+ token = proto.start(DIRECT_CONNECTIONS);
+ directConnections[i]->dump(&proto);
+ proto.end(token);
+ }
+
+ // Write repeated SensorRegistrationInfoProto
+ const int startIndex = mNextSensorRegIndex;
+ int curr = startIndex;
+ do {
+ const SensorRegistrationInfo& reg_info = mLastNSensorRegistrations[curr];
+ if (SensorRegistrationInfo::isSentinel(reg_info)) {
+ // Ignore sentinel, proceed to next item.
+ curr = (curr + 1 + SENSOR_REGISTRATIONS_BUF_SIZE) % SENSOR_REGISTRATIONS_BUF_SIZE;
+ continue;
+ }
+ token = proto.start(PREVIOUS_REGISTRATIONS);
+ reg_info.dump(&proto);
+ proto.end(token);
+ curr = (curr + 1 + SENSOR_REGISTRATIONS_BUF_SIZE) % SENSOR_REGISTRATIONS_BUF_SIZE;
+ } while (startIndex != curr);
+
+ return proto.flush(fd) ? OK : UNKNOWN_ERROR;
+}
+
void SensorService::disableAllSensors() {
ConnectionSafeAutolock connLock = mConnectionHolder.lock(mLock);
disableAllSensorsLocked(&connLock);
diff --git a/services/sensorservice/SensorService.h b/services/sensorservice/SensorService.h
index fa23da0..7d17dda 100644
--- a/services/sensorservice/SensorService.h
+++ b/services/sensorservice/SensorService.h
@@ -286,6 +286,7 @@
virtual int setOperationParameter(
int32_t handle, int32_t type, const Vector<float> &floats, const Vector<int32_t> &ints);
virtual status_t dump(int fd, const Vector<String16>& args);
+ status_t dumpProtoLocked(int fd, ConnectionSafeAutolock* connLock) const;
String8 getSensorName(int handle) const;
bool isVirtualSensor(int handle) const;
sp<SensorInterface> getSensorInterfaceFromHandle(int handle) const;
diff --git a/services/sensorservice/SensorServiceUtils.h b/services/sensorservice/SensorServiceUtils.h
index 1558feb..49457cf 100644
--- a/services/sensorservice/SensorServiceUtils.h
+++ b/services/sensorservice/SensorServiceUtils.h
@@ -21,11 +21,17 @@
#include <string>
namespace android {
+
+namespace util {
+class ProtoOutputStream;
+}
+
namespace SensorServiceUtil {
class Dumpable {
public:
virtual std::string dump() const = 0;
+ virtual void dump(util::ProtoOutputStream*) const {}
virtual void setFormat(std::string ) {}
virtual ~Dumpable() {}
};
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index 35d0215..f4f45be 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -26,8 +26,6 @@
#include "BufferLayer.h"
#include <compositionengine/CompositionEngine.h>
-#include <compositionengine/Layer.h>
-#include <compositionengine/LayerCreationArgs.h>
#include <compositionengine/LayerFECompositionState.h>
#include <compositionengine/OutputLayer.h>
#include <compositionengine/impl/OutputLayerCompositionState.h>
@@ -66,8 +64,7 @@
BufferLayer::BufferLayer(const LayerCreationArgs& args)
: Layer(args),
mTextureName(args.textureName),
- mCompositionLayer{mFlinger->getCompositionEngine().createLayer(
- compositionengine::LayerCreationArgs{this})} {
+ mCompositionState{mFlinger->getCompositionEngine().createLayerFECompositionState()} {
ALOGV("Creating Layer %s", getDebugName());
mPremultipliedAlpha = !(args.flags & ISurfaceComposerClient::eNonPremultiplied);
@@ -184,7 +181,7 @@
bool blackOutLayer = (isProtected() && !targetSettings.supportsProtectedContent) ||
(isSecure() && !targetSettings.isSecure);
const State& s(getDrawingState());
- LayerFE::LayerSettings& layer = *result;
+ compositionengine::LayerFE::LayerSettings& layer = *result;
if (!blackOutLayer) {
layer.source.buffer.buffer = mBufferInfo.mBuffer;
layer.source.buffer.isOpaque = isOpaque(s);
@@ -282,17 +279,29 @@
mBufferInfo.mBuffer->getPixelFormat() == HAL_PIXEL_FORMAT_RGBA_1010102);
}
-void BufferLayer::latchPerFrameState(
- compositionengine::LayerFECompositionState& compositionState) const {
- Layer::latchPerFrameState(compositionState);
+sp<compositionengine::LayerFE> BufferLayer::getCompositionEngineLayerFE() const {
+ return asLayerFE();
+}
+
+compositionengine::LayerFECompositionState* BufferLayer::editCompositionState() {
+ return mCompositionState.get();
+}
+
+const compositionengine::LayerFECompositionState* BufferLayer::getCompositionState() const {
+ return mCompositionState.get();
+}
+
+void BufferLayer::preparePerFrameCompositionState() {
+ Layer::preparePerFrameCompositionState();
// Sideband layers
- if (compositionState.sidebandStream.get()) {
- compositionState.compositionType = Hwc2::IComposerClient::Composition::SIDEBAND;
+ auto* compositionState = editCompositionState();
+ if (compositionState->sidebandStream.get()) {
+ compositionState->compositionType = Hwc2::IComposerClient::Composition::SIDEBAND;
} else {
// Normal buffer layers
- compositionState.hdrMetadata = mBufferInfo.mHdrMetadata;
- compositionState.compositionType = mPotentialCursor
+ compositionState->hdrMetadata = mBufferInfo.mHdrMetadata;
+ compositionState->compositionType = mPotentialCursor
? Hwc2::IComposerClient::Composition::CURSOR
: Hwc2::IComposerClient::Composition::DEVICE;
}
@@ -641,10 +650,6 @@
return Rect(bufWidth, bufHeight);
}
-std::shared_ptr<compositionengine::Layer> BufferLayer::getCompositionLayer() const {
- return mCompositionLayer;
-}
-
FloatRect BufferLayer::computeSourceBounds(const FloatRect& parentBounds) const {
const State& s(getDrawingState());
diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h
index b2398a8..4085b52 100644
--- a/services/surfaceflinger/BufferLayer.h
+++ b/services/surfaceflinger/BufferLayer.h
@@ -54,7 +54,8 @@
// Overriden from Layer
// -----------------------------------------------------------------------
public:
- std::shared_ptr<compositionengine::Layer> getCompositionLayer() const override;
+ sp<compositionengine::LayerFE> getCompositionEngineLayerFE() const override;
+ compositionengine::LayerFECompositionState* editCompositionState() override;
// If we have received a new buffer this frame, we will pass its surface
// damage down to hardware composer. Otherwise, we must send a region with
@@ -175,8 +176,9 @@
/*
* compositionengine::LayerFE overrides
*/
+ const compositionengine::LayerFECompositionState* getCompositionState() const override;
bool onPreComposition(nsecs_t) override;
- void latchPerFrameState(compositionengine::LayerFECompositionState&) const override;
+ void preparePerFrameCompositionState() override;
std::optional<compositionengine::LayerFE::LayerSettings> prepareClientComposition(
compositionengine::LayerFE::ClientCompositionTargetSettings&) override;
@@ -210,7 +212,7 @@
// and its parent layer is not bounded
Rect getBufferSize(const State& s) const override;
- std::shared_ptr<compositionengine::Layer> mCompositionLayer;
+ std::unique_ptr<compositionengine::LayerFECompositionState> mCompositionState;
FloatRect computeSourceBounds(const FloatRect& parentBounds) const override;
};
diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp
index 61386f4..3cc803e 100644
--- a/services/surfaceflinger/BufferQueueLayer.cpp
+++ b/services/surfaceflinger/BufferQueueLayer.cpp
@@ -23,7 +23,6 @@
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
#include "BufferQueueLayer.h"
-#include <compositionengine/Layer.h>
#include <compositionengine/LayerFECompositionState.h>
#include <gui/BufferQueueConsumer.h>
#include <system/window.h>
@@ -223,9 +222,9 @@
if (mSidebandStreamChanged.compare_exchange_strong(sidebandStreamChanged, false)) {
// mSidebandStreamChanged was changed to false
mSidebandStream = mConsumer->getSidebandStream();
- auto& layerCompositionState = getCompositionLayer()->editFEState();
- layerCompositionState.sidebandStream = mSidebandStream;
- if (layerCompositionState.sidebandStream != nullptr) {
+ auto* layerCompositionState = editCompositionState();
+ layerCompositionState->sidebandStream = mSidebandStream;
+ if (layerCompositionState->sidebandStream != nullptr) {
setTransactionFlags(eTransactionNeeded);
mFlinger->setTransactionFlags(eTraversalNeeded);
}
@@ -359,8 +358,8 @@
mPreviousBufferId = getCurrentBufferId();
mBufferInfo.mBuffer =
mConsumer->getCurrentBuffer(&mBufferInfo.mBufferSlot, &mBufferInfo.mFence);
- auto& layerCompositionState = getCompositionLayer()->editFEState();
- layerCompositionState.buffer = mBufferInfo.mBuffer;
+ auto* layerCompositionState = editCompositionState();
+ layerCompositionState->buffer = mBufferInfo.mBuffer;
if (mBufferInfo.mBuffer == nullptr) {
// this can only happen if the very first buffer was rejected.
@@ -380,18 +379,19 @@
return NO_ERROR;
}
-void BufferQueueLayer::latchPerFrameState(
- compositionengine::LayerFECompositionState& compositionState) const {
- BufferLayer::latchPerFrameState(compositionState);
- if (compositionState.compositionType == Hwc2::IComposerClient::Composition::SIDEBAND) {
+void BufferQueueLayer::preparePerFrameCompositionState() {
+ BufferLayer::preparePerFrameCompositionState();
+
+ auto* compositionState = editCompositionState();
+ if (compositionState->compositionType == Hwc2::IComposerClient::Composition::SIDEBAND) {
return;
}
- compositionState.buffer = mBufferInfo.mBuffer;
- compositionState.bufferSlot = (mBufferInfo.mBufferSlot == BufferQueue::INVALID_BUFFER_SLOT)
+ compositionState->buffer = mBufferInfo.mBuffer;
+ compositionState->bufferSlot = (mBufferInfo.mBufferSlot == BufferQueue::INVALID_BUFFER_SLOT)
? 0
: mBufferInfo.mBufferSlot;
- compositionState.acquireFence = mBufferInfo.mFence;
+ compositionState->acquireFence = mBufferInfo.mFence;
}
// -----------------------------------------------------------------------
diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h
index 598bc6b..626af4b 100644
--- a/services/surfaceflinger/BufferQueueLayer.h
+++ b/services/surfaceflinger/BufferQueueLayer.h
@@ -85,7 +85,7 @@
status_t updateActiveBuffer() override;
status_t updateFrameNumber(nsecs_t latchTime) override;
- void latchPerFrameState(compositionengine::LayerFECompositionState&) const override;
+ void preparePerFrameCompositionState() override;
sp<Layer> createClone() override;
void onFrameAvailable(const BufferItem& item);
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index ed18901..923a81c 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -27,7 +27,6 @@
#include <limits>
-#include <compositionengine/Layer.h>
#include <compositionengine/LayerFECompositionState.h>
#include <gui/BufferQueue.h>
#include <private/gui/SyncFeatures.h>
@@ -116,6 +115,7 @@
void BufferStateLayer::releasePendingBuffer(nsecs_t dequeueReadyTime) {
for (const auto& handle : mDrawingState.callbackHandles) {
handle->transformHint = mTransformHint;
+ handle->dequeueReadyTime = dequeueReadyTime;
}
mFlinger->getTransactionCompletedThread().finalizePendingCallbackHandles(
@@ -134,6 +134,14 @@
}
}
+void BufferStateLayer::finalizeFrameEventHistory(const std::shared_ptr<FenceTime>& glDoneFence,
+ const CompositorTiming& compositorTiming) {
+ for (const auto& handle : mDrawingState.callbackHandles) {
+ handle->gpuCompositionDoneFence = glDoneFence;
+ handle->compositorTiming = compositorTiming;
+ }
+}
+
bool BufferStateLayer::shouldPresentNow(nsecs_t /*expectedPresentTime*/) const {
if (getSidebandStreamChanged() || getAutoRefresh()) {
return true;
@@ -150,6 +158,8 @@
!mLayerDetached;
}
+/* TODO: vhau uncomment once deferred transaction migration complete in
+ * WindowManager
void BufferStateLayer::pushPendingState() {
if (!mCurrentState.modified) {
return;
@@ -157,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;
}
@@ -245,14 +254,15 @@
return true;
}
-bool BufferStateLayer::updateFrameEventHistory(const sp<Fence>& acquireFence, nsecs_t postedTime,
- nsecs_t desiredPresentTime) {
+bool BufferStateLayer::addFrameEvent(const sp<Fence>& acquireFence, nsecs_t postedTime,
+ nsecs_t desiredPresentTime) {
Mutex::Autolock lock(mFrameEventHistoryMutex);
mAcquireTimeline.updateSignalTimes();
std::shared_ptr<FenceTime> acquireFenceTime =
std::make_shared<FenceTime>((acquireFence ? acquireFence : Fence::NO_FENCE));
NewFrameEventsEntry newTimestamps = {mCurrentState.frameNumber, postedTime, desiredPresentTime,
acquireFenceTime};
+ mFrameEventHistory.setProducerWantsEvents();
mFrameEventHistory.addQueue(newTimestamps);
return true;
}
@@ -277,12 +287,12 @@
mFlinger->mFrameTracer->traceNewLayer(layerId, getName().c_str());
mFlinger->mFrameTracer->traceTimestamp(layerId, buffer->getId(), mCurrentState.frameNumber,
postTime, FrameTracer::FrameEvent::POST);
+ desiredPresentTime = desiredPresentTime <= 0 ? 0 : desiredPresentTime;
mCurrentState.desiredPresentTime = desiredPresentTime;
- mFlinger->mScheduler->recordLayerHistory(this,
- desiredPresentTime <= 0 ? 0 : desiredPresentTime);
+ mFlinger->mScheduler->recordLayerHistory(this, desiredPresentTime);
- updateFrameEventHistory(acquireFence, postTime, desiredPresentTime);
+ addFrameEvent(acquireFence, postTime, desiredPresentTime);
return true;
}
@@ -447,6 +457,13 @@
return mCurrentState.desiredPresentTime <= expectedPresentTime;
}
+bool BufferStateLayer::onPreComposition(nsecs_t refreshStartTime) {
+ for (const auto& handle : mDrawingState.callbackHandles) {
+ handle->refreshStartTime = refreshStartTime;
+ }
+ return BufferLayer::onPreComposition(refreshStartTime);
+}
+
uint64_t BufferStateLayer::getFrameNumber(nsecs_t /*expectedPresentTime*/) const {
return mDrawingState.frameNumber;
}
@@ -464,9 +481,8 @@
if (mSidebandStreamChanged.exchange(false)) {
const State& s(getDrawingState());
// mSidebandStreamChanged was true
- LOG_ALWAYS_FATAL_IF(!getCompositionLayer());
mSidebandStream = s.sidebandStream;
- getCompositionLayer()->editFEState().sidebandStream = mSidebandStream;
+ editCompositionState()->sidebandStream = mSidebandStream;
if (mSidebandStream != nullptr) {
setTransactionFlags(eTransactionNeeded);
mFlinger->setTransactionFlags(eTraversalNeeded);
@@ -531,6 +547,7 @@
for (auto& handle : mDrawingState.callbackHandles) {
handle->latchTime = latchTime;
+ handle->frameNumber = mDrawingState.frameNumber;
}
if (!SyncFeatures::getInstance().useNativeFenceSync()) {
@@ -573,8 +590,7 @@
mPreviousBufferId = getCurrentBufferId();
mBufferInfo.mBuffer = s.buffer;
mBufferInfo.mFence = s.acquireFence;
- auto& layerCompositionState = getCompositionLayer()->editFEState();
- layerCompositionState.buffer = mBufferInfo.mBuffer;
+ editCompositionState()->buffer = mBufferInfo.mBuffer;
return NO_ERROR;
}
@@ -590,16 +606,17 @@
return NO_ERROR;
}
-void BufferStateLayer::latchPerFrameState(
- compositionengine::LayerFECompositionState& compositionState) const {
- BufferLayer::latchPerFrameState(compositionState);
- if (compositionState.compositionType == Hwc2::IComposerClient::Composition::SIDEBAND) {
+void BufferStateLayer::preparePerFrameCompositionState() {
+ BufferLayer::preparePerFrameCompositionState();
+
+ auto* compositionState = editCompositionState();
+ if (compositionState->compositionType == Hwc2::IComposerClient::Composition::SIDEBAND) {
return;
}
- compositionState.buffer = mBufferInfo.mBuffer;
- compositionState.bufferSlot = mBufferInfo.mBufferSlot;
- compositionState.acquireFence = mBufferInfo.mFence;
+ compositionState->buffer = mBufferInfo.mBuffer;
+ compositionState->bufferSlot = mBufferInfo.mBufferSlot;
+ compositionState->acquireFence = mBufferInfo.mFence;
}
void BufferStateLayer::HwcSlotGenerator::bufferErased(const client_cache_t& clientCacheId) {
diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h
index 03d9684..6ee5802 100644
--- a/services/surfaceflinger/BufferStateLayer.h
+++ b/services/surfaceflinger/BufferStateLayer.h
@@ -45,12 +45,17 @@
void setTransformHint(uint32_t orientation) const override;
void releasePendingBuffer(nsecs_t dequeueReadyTime) override;
+ void finalizeFrameEventHistory(const std::shared_ptr<FenceTime>& glDoneFence,
+ const CompositorTiming& compositorTiming) override;
+
bool shouldPresentNow(nsecs_t expectedPresentTime) const override;
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; }
@@ -78,6 +83,8 @@
bool setSidebandStream(const sp<NativeHandle>& sidebandStream) override;
bool setTransactionCompletedListeners(const std::vector<sp<CallbackHandle>>& handles) override;
void forceSendCallbacks() override;
+ bool addFrameEvent(const sp<Fence>& acquireFence, nsecs_t postedTime,
+ nsecs_t requestedPresentTime) override;
// Override to ignore legacy layer state properties that are not used by BufferStateLayer
bool setSize(uint32_t /*w*/, uint32_t /*h*/) override { return false; }
@@ -104,6 +111,7 @@
// -----------------------------------------------------------------------
bool fenceHasSignaled() const override;
bool framePresentTimeIsCurrent(nsecs_t expectedPresentTime) const override;
+ bool onPreComposition(nsecs_t refreshStartTime) override;
protected:
void gatherBufferInfo() override;
@@ -128,7 +136,7 @@
status_t updateActiveBuffer() override;
status_t updateFrameNumber(nsecs_t latchTime) override;
- void latchPerFrameState(compositionengine::LayerFECompositionState&) const override;
+ void preparePerFrameCompositionState() override;
sp<Layer> createClone() override;
// Crop that applies to the buffer
diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp
index dbdfd5b..83050c4 100644
--- a/services/surfaceflinger/ColorLayer.cpp
+++ b/services/surfaceflinger/ColorLayer.cpp
@@ -29,8 +29,6 @@
#include <sys/types.h>
#include <compositionengine/CompositionEngine.h>
-#include <compositionengine/Layer.h>
-#include <compositionengine/LayerCreationArgs.h>
#include <compositionengine/LayerFECompositionState.h>
#include <renderengine/RenderEngine.h>
#include <ui/GraphicBuffer.h>
@@ -45,8 +43,7 @@
ColorLayer::ColorLayer(const LayerCreationArgs& args)
: Layer(args),
- mCompositionLayer{mFlinger->getCompositionEngine().createLayer(
- compositionengine::LayerCreationArgs{this})} {}
+ mCompositionState{mFlinger->getCompositionEngine().createLayerFECompositionState()} {}
ColorLayer::~ColorLayer() = default;
@@ -91,16 +88,24 @@
return true;
}
-void ColorLayer::latchPerFrameState(
- compositionengine::LayerFECompositionState& compositionState) const {
- Layer::latchPerFrameState(compositionState);
+void ColorLayer::preparePerFrameCompositionState() {
+ Layer::preparePerFrameCompositionState();
- compositionState.color = getColor();
- compositionState.compositionType = Hwc2::IComposerClient::Composition::SOLID_COLOR;
+ auto* compositionState = editCompositionState();
+ compositionState->color = getColor();
+ compositionState->compositionType = Hwc2::IComposerClient::Composition::SOLID_COLOR;
}
-std::shared_ptr<compositionengine::Layer> ColorLayer::getCompositionLayer() const {
- return mCompositionLayer;
+sp<compositionengine::LayerFE> ColorLayer::getCompositionEngineLayerFE() const {
+ return asLayerFE();
+}
+
+compositionengine::LayerFECompositionState* ColorLayer::editCompositionState() {
+ return mCompositionState.get();
+}
+
+const compositionengine::LayerFECompositionState* ColorLayer::getCompositionState() const {
+ return mCompositionState.get();
}
bool ColorLayer::isOpaque(const Layer::State& s) const {
diff --git a/services/surfaceflinger/ColorLayer.h b/services/surfaceflinger/ColorLayer.h
index 9246eb2..4deb162 100644
--- a/services/surfaceflinger/ColorLayer.h
+++ b/services/surfaceflinger/ColorLayer.h
@@ -28,7 +28,8 @@
explicit ColorLayer(const LayerCreationArgs&);
~ColorLayer() override;
- std::shared_ptr<compositionengine::Layer> getCompositionLayer() const override;
+ sp<compositionengine::LayerFE> getCompositionEngineLayerFE() const override;
+ compositionengine::LayerFECompositionState* editCompositionState() override;
const char* getType() const override { return "ColorLayer"; }
bool isVisible() const override;
@@ -45,11 +46,12 @@
/*
* compositionengine::LayerFE overrides
*/
- void latchPerFrameState(compositionengine::LayerFECompositionState&) const override;
+ const compositionengine::LayerFECompositionState* getCompositionState() const override;
+ void preparePerFrameCompositionState() override;
std::optional<compositionengine::LayerFE::LayerSettings> prepareClientComposition(
compositionengine::LayerFE::ClientCompositionTargetSettings&) override;
- std::shared_ptr<compositionengine::Layer> mCompositionLayer;
+ std::unique_ptr<compositionengine::LayerFECompositionState> mCompositionState;
sp<Layer> createClone() override;
};
diff --git a/services/surfaceflinger/CompositionEngine/Android.bp b/services/surfaceflinger/CompositionEngine/Android.bp
index a634f2f..2792290 100644
--- a/services/surfaceflinger/CompositionEngine/Android.bp
+++ b/services/surfaceflinger/CompositionEngine/Android.bp
@@ -51,7 +51,6 @@
"src/DisplaySurface.cpp",
"src/DumpHelpers.cpp",
"src/HwcBufferCache.cpp",
- "src/Layer.cpp",
"src/LayerFECompositionState.cpp",
"src/Output.cpp",
"src/OutputCompositionState.cpp",
@@ -71,7 +70,6 @@
"mock/Display.cpp",
"mock/DisplayColorProfile.cpp",
"mock/DisplaySurface.cpp",
- "mock/Layer.cpp",
"mock/LayerFE.cpp",
"mock/NativeWindow.cpp",
"mock/Output.cpp",
@@ -96,7 +94,6 @@
"tests/DisplayColorProfileTest.cpp",
"tests/DisplayTest.cpp",
"tests/HwcBufferCacheTest.cpp",
- "tests/LayerTest.cpp",
"tests/MockHWC2.cpp",
"tests/MockHWComposer.cpp",
"tests/MockPowerAdvisor.cpp",
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionEngine.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionEngine.h
index e3650f3..3faa068 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionEngine.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionEngine.h
@@ -32,11 +32,11 @@
namespace compositionengine {
class Display;
-class Layer;
struct CompositionRefreshArgs;
struct DisplayCreationArgs;
struct LayerCreationArgs;
+struct LayerFECompositionState;
/**
* Encapsulates all the interfaces and implementation details for performing
@@ -48,7 +48,8 @@
// Create a composition Display
virtual std::shared_ptr<Display> createDisplay(const DisplayCreationArgs&) = 0;
- virtual std::shared_ptr<Layer> createLayer(const LayerCreationArgs&) = 0;
+ virtual std::unique_ptr<compositionengine::LayerFECompositionState>
+ createLayerFECompositionState() = 0;
virtual HWComposer& getHwComposer() const = 0;
virtual void setHwComposer(std::unique_ptr<HWComposer>) = 0;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionRefreshArgs.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionRefreshArgs.h
index 90158c7..4a0d6ee 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionRefreshArgs.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionRefreshArgs.h
@@ -21,15 +21,14 @@
#include <vector>
#include <compositionengine/Display.h>
-#include <compositionengine/Layer.h>
+#include <compositionengine/LayerFE.h>
#include <compositionengine/OutputColorSetting.h>
#include <math/mat4.h>
namespace android::compositionengine {
-using Layers = std::vector<std::shared_ptr<compositionengine::Layer>>;
+using Layers = std::vector<sp<compositionengine::LayerFE>>;
using Outputs = std::vector<std::shared_ptr<compositionengine::Output>>;
-using RawLayers = std::vector<compositionengine::Layer*>;
/**
* A parameter object for refreshing a set of outputs
@@ -44,7 +43,7 @@
Layers layers;
// All the layers that have queued updates.
- RawLayers layersWithQueuedFrames;
+ Layers layersWithQueuedFrames;
// If true, forces the entire display to be considered dirty and repainted
bool repaintEverything{false};
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/Layer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/Layer.h
deleted file mode 100644
index 1259c52..0000000
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/Layer.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <cstdint>
-#include <string>
-
-#include <utils/StrongPointer.h>
-
-namespace android::compositionengine {
-
-class Display;
-class LayerFE;
-
-struct LayerFECompositionState;
-
-/**
- * A layer contains the output-independent composition state for a front-end
- * Layer
- */
-class Layer {
-public:
- virtual ~Layer();
-
- // Gets the front-end interface for this layer. Can return nullptr if the
- // front-end layer no longer exists.
- virtual sp<LayerFE> getLayerFE() const = 0;
-
- // Gets the raw front-end composition state data for the layer
- // TODO(lpique): Make this protected once it is only internally called.
- virtual const LayerFECompositionState& getFEState() const = 0;
-
- // Allows mutable access to the raw front-end composition state
- // TODO(lpique): Make this protected once it is only internally called.
- virtual LayerFECompositionState& editFEState() = 0;
-
- // Debugging
- virtual void dump(std::string& result) const = 0;
-};
-
-} // namespace android::compositionengine
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerCreationArgs.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerCreationArgs.h
deleted file mode 100644
index db3312b..0000000
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerCreationArgs.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <utils/RefBase.h>
-
-namespace android::compositionengine {
-
-class CompositionEngine;
-class LayerFE;
-
-/**
- * A parameter object for creating Layer instances
- */
-struct LayerCreationArgs {
- // A weak pointer to the front-end layer instance that the new layer will
- // represent.
- wp<LayerFE> layerFE;
-};
-
-} // namespace android::compositionengine
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h
index 26442d9..912dffd 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h
@@ -44,6 +44,9 @@
// of the front-end layer
class LayerFE : public virtual RefBase {
public:
+ // Gets the raw front-end composition state data for the layer
+ virtual const LayerFECompositionState* getCompositionState() const = 0;
+
// Called before composition starts. Should return true if this layer has
// pending updates which would require an extra display refresh cycle to
// process.
@@ -60,19 +63,18 @@
// content (buffer or color) state for the layer.
GeometryAndContent,
- // Gets the per frame content (buffer or color) state the layer.
+ // Gets the per frame content (buffer or color) state for the layer.
Content,
+
+ // Gets the cursor state for the layer.
+ Cursor,
};
- // Latches the output-independent composition state for the layer. The
+ // Prepares the output-independent composition state for the layer. The
// StateSubset argument selects what portion of the state is actually needed
// by the CompositionEngine code, since computing everything may be
// expensive.
- virtual void latchCompositionState(LayerFECompositionState&, StateSubset) const = 0;
-
- // Latches the minimal bit of state for the cursor for a fast asynchronous
- // update.
- virtual void latchCursorCompositionState(LayerFECompositionState&) const = 0;
+ virtual void prepareCompositionState(StateSubset) = 0;
struct ClientCompositionTargetSettings {
// The clip region, or visible region that is being rendered to
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h
index 1af99c5..40cd3e0 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h
@@ -162,8 +162,10 @@
// The output-independent frame for the cursor
Rect cursorFrame;
+ virtual ~LayerFECompositionState();
+
// Debugging
- void dump(std::string& out) const;
+ virtual void dump(std::string& out) const;
};
} // namespace android::compositionengine
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h
index 4ab7082..9622e78 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h
@@ -41,7 +41,6 @@
namespace android::compositionengine {
class DisplayColorProfile;
-class Layer;
class LayerFE;
class RenderSurface;
class OutputLayer;
@@ -216,18 +215,17 @@
virtual bool belongsInOutput(std::optional<uint32_t> layerStackId, bool internalOnly) const = 0;
// Determines if a layer belongs to the output.
- virtual bool belongsInOutput(const Layer*) const = 0;
+ virtual bool belongsInOutput(const sp<LayerFE>&) const = 0;
// Returns a pointer to the output layer corresponding to the given layer on
// this output, or nullptr if the layer does not have one
- virtual OutputLayer* getOutputLayerForLayer(Layer*) const = 0;
+ virtual OutputLayer* getOutputLayerForLayer(const sp<LayerFE>&) const = 0;
// Immediately clears all layers from the output.
virtual void clearOutputLayers() = 0;
// For tests use only. Creates and appends an OutputLayer into the output.
- virtual OutputLayer* injectOutputLayerForTest(const std::shared_ptr<Layer>&,
- const sp<LayerFE>&) = 0;
+ virtual OutputLayer* injectOutputLayerForTest(const sp<LayerFE>&) = 0;
// Gets the count of output layers managed by this output
virtual size_t getOutputLayerCount() const = 0;
@@ -257,7 +255,7 @@
virtual void rebuildLayerStacks(const CompositionRefreshArgs&, LayerFESet&) = 0;
virtual void collectVisibleLayers(const CompositionRefreshArgs&, CoverageState&) = 0;
- virtual void ensureOutputLayerIfVisible(std::shared_ptr<Layer>, CoverageState&) = 0;
+ virtual void ensureOutputLayerIfVisible(sp<LayerFE>&, CoverageState&) = 0;
virtual void setReleasedLayers(const CompositionRefreshArgs&) = 0;
virtual void updateAndWriteCompositionState(const CompositionRefreshArgs&) = 0;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h
index a466561..007b0e8 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h
@@ -41,7 +41,6 @@
class CompositionEngine;
class Output;
-class Layer;
class LayerFE;
namespace impl {
@@ -61,9 +60,6 @@
// Gets the output which owns this output layer
virtual const Output& getOutput() const = 0;
- // Gets the display-independent layer which this output layer represents
- virtual Layer& getLayer() const = 0;
-
// Gets the front-end layer interface this output layer represents
virtual LayerFE& getLayerFE() const = 0;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/CompositionEngine.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/CompositionEngine.h
index 450b9ca..386808d 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/CompositionEngine.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/CompositionEngine.h
@@ -27,8 +27,8 @@
std::shared_ptr<compositionengine::Display> createDisplay(
const compositionengine::DisplayCreationArgs&) override;
- std::shared_ptr<compositionengine::Layer> createLayer(
- const compositionengine::LayerCreationArgs&) override;
+ std::unique_ptr<compositionengine::LayerFECompositionState> createLayerFECompositionState()
+ override;
HWComposer& getHwComposer() const override;
void setHwComposer(std::unique_ptr<HWComposer>) override;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h
index 39acb37..fb597ce 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h
@@ -73,8 +73,7 @@
virtual void applyLayerRequestsToLayers(const LayerRequests&);
// Internal
- std::unique_ptr<compositionengine::OutputLayer> createOutputLayer(
- const std::shared_ptr<compositionengine::Layer>&, const sp<LayerFE>&) const;
+ std::unique_ptr<compositionengine::OutputLayer> createOutputLayer(const sp<LayerFE>&) const;
private:
const bool mIsVirtual;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Layer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Layer.h
deleted file mode 100644
index 46489fb..0000000
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Layer.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <memory>
-
-#include <compositionengine/Layer.h>
-#include <compositionengine/LayerCreationArgs.h>
-#include <utils/StrongPointer.h>
-
-namespace android::compositionengine {
-
-struct LayerCreationArgs;
-
-namespace impl {
-
-// The implementation class contains the common implementation, but does not
-// actually contain the final layer state.
-class Layer : public virtual compositionengine::Layer {
-public:
- ~Layer() override;
-
- // compositionengine::Layer overrides
- void dump(std::string&) const override;
-
-protected:
- // Implemented by the final implementation for the final state it uses.
- virtual void dumpFEState(std::string&) const = 0;
-};
-
-// This template factory function standardizes the implementation details of the
-// final class using the types actually required by the implementation. This is
-// not possible to do in the base class as those types may not even be visible
-// to the base code.
-template <typename BaseLayer, typename LayerCreationArgs>
-std::shared_ptr<BaseLayer> createLayerTemplated(const LayerCreationArgs& args) {
- class Layer final : public BaseLayer {
- public:
-// Clang incorrectly complains that these are unused.
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wunused-local-typedef"
- using LayerFE = std::remove_pointer_t<decltype(
- std::declval<decltype(std::declval<LayerCreationArgs>().layerFE)>().unsafe_get())>;
- using LayerFECompositionState = std::remove_const_t<
- std::remove_reference_t<decltype(std::declval<BaseLayer>().getFEState())>>;
-#pragma clang diagnostic pop
-
- explicit Layer(const LayerCreationArgs& args) : mLayerFE(args.layerFE) {}
- ~Layer() override = default;
-
- private:
- // compositionengine::Layer overrides
- sp<compositionengine::LayerFE> getLayerFE() const override { return mLayerFE.promote(); }
- const LayerFECompositionState& getFEState() const override { return mFrontEndState; }
- LayerFECompositionState& editFEState() override { return mFrontEndState; }
-
- // compositionengine::impl::Layer overrides
- void dumpFEState(std::string& out) const override { mFrontEndState.dump(out); }
-
- const wp<LayerFE> mLayerFE;
- LayerFECompositionState mFrontEndState;
- };
-
- return std::make_shared<Layer>(args);
-}
-
-std::shared_ptr<Layer> createLayer(const LayerCreationArgs&);
-
-} // namespace impl
-} // namespace android::compositionengine
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
index 8dc440c..d41337c 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
@@ -60,10 +60,9 @@
Region getDirtyRegion(bool repaintEverything) const override;
bool belongsInOutput(std::optional<uint32_t>, bool) const override;
- bool belongsInOutput(const compositionengine::Layer*) const override;
+ bool belongsInOutput(const sp<LayerFE>&) const override;
- compositionengine::OutputLayer* getOutputLayerForLayer(
- compositionengine::Layer*) const override;
+ compositionengine::OutputLayer* getOutputLayerForLayer(const sp<LayerFE>&) const override;
void setReleasedLayers(ReleasedLayers&&) override;
@@ -73,7 +72,7 @@
void rebuildLayerStacks(const CompositionRefreshArgs&, LayerFESet&) override;
void collectVisibleLayers(const CompositionRefreshArgs&,
compositionengine::Output::CoverageState&) override;
- void ensureOutputLayerIfVisible(std::shared_ptr<compositionengine::Layer>,
+ void ensureOutputLayerIfVisible(sp<compositionengine::LayerFE>&,
compositionengine::Output::CoverageState&) override;
void setReleasedLayers(const compositionengine::CompositionRefreshArgs&) override;
@@ -94,9 +93,9 @@
void setRenderSurfaceForTest(std::unique_ptr<compositionengine::RenderSurface>);
protected:
- std::unique_ptr<compositionengine::OutputLayer> createOutputLayer(
- const std::shared_ptr<compositionengine::Layer>&, const sp<LayerFE>&) const;
- std::optional<size_t> findCurrentOutputLayerForLayer(compositionengine::Layer*) const;
+ std::unique_ptr<compositionengine::OutputLayer> createOutputLayer(const sp<LayerFE>&) const;
+ std::optional<size_t> findCurrentOutputLayerForLayer(
+ const sp<compositionengine::LayerFE>&) const;
void chooseCompositionStrategy() override;
bool getSkipColorTransform() const override;
compositionengine::Output::FrameFences presentAndGetFrameFences() override;
@@ -108,11 +107,9 @@
void dumpBase(std::string&) const;
// Implemented by the final implementation for the final state it uses.
- virtual compositionengine::OutputLayer* ensureOutputLayer(
- std::optional<size_t>, const std::shared_ptr<compositionengine::Layer>&,
- const sp<LayerFE>&) = 0;
- virtual compositionengine::OutputLayer* injectOutputLayerForTest(
- const std::shared_ptr<compositionengine::Layer>&, const sp<LayerFE>&) = 0;
+ virtual compositionengine::OutputLayer* ensureOutputLayer(std::optional<size_t>,
+ const sp<LayerFE>&) = 0;
+ virtual compositionengine::OutputLayer* injectOutputLayerForTest(const sp<LayerFE>&) = 0;
virtual void finalizePendingOutputLayers() = 0;
virtual const compositionengine::CompositionEngine& getCompositionEngine() const = 0;
virtual void dumpState(std::string& out) const = 0;
@@ -181,11 +178,10 @@
};
OutputLayer* ensureOutputLayer(std::optional<size_t> prevIndex,
- const std::shared_ptr<compositionengine::Layer>& layer,
const sp<LayerFE>& layerFE) {
auto outputLayer = (prevIndex && *prevIndex <= mCurrentOutputLayersOrderedByZ.size())
? std::move(mCurrentOutputLayersOrderedByZ[*prevIndex])
- : BaseOutput::createOutputLayer(layer, layerFE);
+ : BaseOutput::createOutputLayer(layerFE);
auto result = outputLayer.get();
mPendingOutputLayersOrderedByZ.emplace_back(std::move(outputLayer));
return result;
@@ -202,10 +198,8 @@
void dumpState(std::string& out) const override { mState.dump(out); }
- OutputLayer* injectOutputLayerForTest(
- const std::shared_ptr<compositionengine::Layer>& layer,
- const sp<LayerFE>& layerFE) override {
- auto outputLayer = BaseOutput::createOutputLayer(layer, layerFE);
+ OutputLayer* injectOutputLayerForTest(const sp<LayerFE>& layerFE) override {
+ auto outputLayer = BaseOutput::createOutputLayer(layerFE);
auto result = outputLayer.get();
mCurrentOutputLayersOrderedByZ.emplace_back(std::move(outputLayer));
return result;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h
index 95c8afb..79df9b2 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h
@@ -81,7 +81,6 @@
// to the base code.
template <typename BaseOutputLayer>
std::unique_ptr<BaseOutputLayer> createOutputLayerTemplated(const Output& output,
- std::shared_ptr<Layer> layer,
sp<LayerFE> layerFE) {
class OutputLayer final : public BaseOutputLayer {
public:
@@ -93,21 +92,18 @@
std::remove_reference_t<decltype(std::declval<BaseOutputLayer>().getState())>>;
using Output = std::remove_const_t<
std::remove_reference_t<decltype(std::declval<BaseOutputLayer>().getOutput())>>;
- using Layer = std::remove_reference_t<decltype(std::declval<BaseOutputLayer>().getLayer())>;
using LayerFE =
std::remove_reference_t<decltype(std::declval<BaseOutputLayer>().getLayerFE())>;
#pragma clang diagnostic pop
- OutputLayer(const Output& output, const std::shared_ptr<Layer>& layer,
- const sp<LayerFE>& layerFE)
- : mOutput(output), mLayer(layer), mLayerFE(layerFE) {}
+ OutputLayer(const Output& output, const sp<LayerFE>& layerFE)
+ : mOutput(output), mLayerFE(layerFE) {}
~OutputLayer() override = default;
private:
// compositionengine::OutputLayer overrides
const Output& getOutput() const override { return mOutput; }
- Layer& getLayer() const override { return *mLayer; }
LayerFE& getLayerFE() const override { return *mLayerFE; }
const OutputLayerCompositionState& getState() const override { return mState; }
OutputLayerCompositionState& editState() override { return mState; }
@@ -116,16 +112,14 @@
void dumpState(std::string& out) const override { mState.dump(out); }
const Output& mOutput;
- const std::shared_ptr<Layer> mLayer;
const sp<LayerFE> mLayerFE;
OutputLayerCompositionState mState;
};
- return std::make_unique<OutputLayer>(output, layer, layerFE);
+ return std::make_unique<OutputLayer>(output, layerFE);
}
std::unique_ptr<OutputLayer> createOutputLayer(const compositionengine::Output&,
- const std::shared_ptr<compositionengine::Layer>&,
const sp<LayerFE>&);
} // namespace impl
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/CompositionEngine.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/CompositionEngine.h
index 104e20d..f953d0b 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/CompositionEngine.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/CompositionEngine.h
@@ -19,7 +19,7 @@
#include <compositionengine/CompositionEngine.h>
#include <compositionengine/CompositionRefreshArgs.h>
#include <compositionengine/DisplayCreationArgs.h>
-#include <compositionengine/LayerCreationArgs.h>
+#include <compositionengine/LayerFECompositionState.h>
#include <gmock/gmock.h>
#include <renderengine/RenderEngine.h>
@@ -33,7 +33,8 @@
~CompositionEngine() override;
MOCK_METHOD1(createDisplay, std::shared_ptr<Display>(const DisplayCreationArgs&));
- MOCK_METHOD1(createLayer, std::shared_ptr<Layer>(const LayerCreationArgs&));
+ MOCK_METHOD0(createLayerFECompositionState,
+ std::unique_ptr<compositionengine::LayerFECompositionState>());
MOCK_CONST_METHOD0(getHwComposer, HWComposer&());
MOCK_METHOD1(setHwComposer, void(std::unique_ptr<HWComposer>));
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Layer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Layer.h
deleted file mode 100644
index 4f03cb4..0000000
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Layer.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <compositionengine/Layer.h>
-#include <compositionengine/LayerFE.h>
-#include <compositionengine/LayerFECompositionState.h>
-#include <gmock/gmock.h>
-
-namespace android::compositionengine::mock {
-
-class Layer : public compositionengine::Layer {
-public:
- Layer();
- virtual ~Layer();
-
- MOCK_CONST_METHOD0(getLayerFE, sp<LayerFE>());
-
- MOCK_CONST_METHOD0(getFEState, const LayerFECompositionState&());
- MOCK_METHOD0(editFEState, LayerFECompositionState&());
-
- MOCK_CONST_METHOD1(dump, void(std::string&));
-};
-
-} // namespace android::compositionengine::mock
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h
index 163e302..5c2ad15 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h
@@ -30,11 +30,11 @@
LayerFE();
virtual ~LayerFE();
+ MOCK_CONST_METHOD0(getCompositionState, const LayerFECompositionState*());
+
MOCK_METHOD1(onPreComposition, bool(nsecs_t));
- MOCK_CONST_METHOD2(latchCompositionState,
- void(LayerFECompositionState&, compositionengine::LayerFE::StateSubset));
- MOCK_CONST_METHOD1(latchCursorCompositionState, void(LayerFECompositionState&));
+ MOCK_METHOD1(prepareCompositionState, void(compositionengine::LayerFE::StateSubset));
MOCK_METHOD1(prepareClientComposition,
std::optional<LayerSettings>(
compositionengine::LayerFE::ClientCompositionTargetSettings&));
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h
index 59906b9..346c2d1 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h
@@ -18,7 +18,6 @@
#include <compositionengine/CompositionRefreshArgs.h>
#include <compositionengine/DisplayColorProfile.h>
-#include <compositionengine/Layer.h>
#include <compositionengine/LayerFE.h>
#include <compositionengine/Output.h>
#include <compositionengine/OutputLayer.h>
@@ -62,14 +61,13 @@
MOCK_CONST_METHOD1(getDirtyRegion, Region(bool));
MOCK_CONST_METHOD2(belongsInOutput, bool(std::optional<uint32_t>, bool));
- MOCK_CONST_METHOD1(belongsInOutput, bool(const compositionengine::Layer*));
+ MOCK_CONST_METHOD1(belongsInOutput, bool(const sp<compositionengine::LayerFE>&));
MOCK_CONST_METHOD1(getOutputLayerForLayer,
- compositionengine::OutputLayer*(compositionengine::Layer*));
+ compositionengine::OutputLayer*(const sp<compositionengine::LayerFE>&));
MOCK_METHOD0(clearOutputLayers, void());
- MOCK_METHOD2(injectOutputLayerForTest,
- compositionengine::OutputLayer*(const std::shared_ptr<compositionengine::Layer>&,
- const sp<compositionengine::LayerFE>&));
+ MOCK_METHOD1(injectOutputLayerForTest,
+ compositionengine::OutputLayer*(const sp<compositionengine::LayerFE>&));
MOCK_CONST_METHOD0(getOutputLayerCount, size_t());
MOCK_CONST_METHOD1(getOutputLayerOrderedByZByIndex, OutputLayer*(size_t));
@@ -84,8 +82,7 @@
void(const compositionengine::CompositionRefreshArgs&,
compositionengine::Output::CoverageState&));
MOCK_METHOD2(ensureOutputLayerIfVisible,
- void(std::shared_ptr<compositionengine::Layer>,
- compositionengine::Output::CoverageState&));
+ void(sp<compositionengine::LayerFE>&, compositionengine::Output::CoverageState&));
MOCK_METHOD1(setReleasedLayers, void(const compositionengine::CompositionRefreshArgs&));
MOCK_CONST_METHOD1(updateLayerStateFromFE, void(const CompositionRefreshArgs&));
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h
index 631760a..2ecbad8 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h
@@ -17,7 +17,6 @@
#pragma once
#include <compositionengine/CompositionEngine.h>
-#include <compositionengine/Layer.h>
#include <compositionengine/LayerFE.h>
#include <compositionengine/Output.h>
#include <compositionengine/OutputLayer.h>
@@ -34,7 +33,6 @@
MOCK_METHOD1(setHwcLayer, void(std::shared_ptr<HWC2::Layer>));
MOCK_CONST_METHOD0(getOutput, const compositionengine::Output&());
- MOCK_CONST_METHOD0(getLayer, compositionengine::Layer&());
MOCK_CONST_METHOD0(getLayerFE, compositionengine::LayerFE&());
MOCK_CONST_METHOD0(getState, const impl::OutputLayerCompositionState&());
diff --git a/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp b/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp
index aeaa18a..6203dc6 100644
--- a/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp
@@ -16,10 +16,10 @@
#include <compositionengine/CompositionRefreshArgs.h>
#include <compositionengine/LayerFE.h>
+#include <compositionengine/LayerFECompositionState.h>
#include <compositionengine/OutputLayer.h>
#include <compositionengine/impl/CompositionEngine.h>
#include <compositionengine/impl/Display.h>
-#include <compositionengine/impl/Layer.h>
#include <renderengine/RenderEngine.h>
#include <utils/Trace.h>
@@ -51,9 +51,9 @@
return compositionengine::impl::createDisplay(*this, args);
}
-std::shared_ptr<compositionengine::Layer> CompositionEngine::createLayer(
- const LayerCreationArgs& args) {
- return compositionengine::impl::createLayer(args);
+std::unique_ptr<compositionengine::LayerFECompositionState>
+CompositionEngine::createLayerFECompositionState() {
+ return std::make_unique<compositionengine::LayerFECompositionState>();
}
HWComposer& CompositionEngine::getHwComposer() const {
@@ -120,8 +120,7 @@
for (auto* layer : output->getOutputLayersOrderedByZ()) {
if (layer->isHardwareCursor()) {
// Latch the cursor composition state from each front-end layer.
- layer->getLayerFE().latchCursorCompositionState(layer->getLayer().editFEState());
-
+ layer->getLayerFE().prepareCompositionState(LayerFE::StateSubset::Cursor);
layer->writeCursorPositionToHWC();
}
}
@@ -137,8 +136,7 @@
mRefreshStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
for (auto& layer : args.layers) {
- sp<compositionengine::LayerFE> layerFE = layer->getLayerFE();
- if (layerFE && layerFE->onPreComposition(mRefreshStartTime)) {
+ if (layer->onPreComposition(mRefreshStartTime)) {
needsAnotherUpdate = true;
}
}
diff --git a/services/surfaceflinger/CompositionEngine/src/Display.cpp b/services/surfaceflinger/CompositionEngine/src/Display.cpp
index ccd6572..1d8a23f 100644
--- a/services/surfaceflinger/CompositionEngine/src/Display.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Display.cpp
@@ -147,9 +147,8 @@
}
std::unique_ptr<compositionengine::OutputLayer> Display::createOutputLayer(
- const std::shared_ptr<compositionengine::Layer>& layer,
const sp<compositionengine::LayerFE>& layerFE) const {
- auto result = impl::createOutputLayer(*this, layer, layerFE);
+ auto result = impl::createOutputLayer(*this, layerFE);
if (result && mId) {
auto& hwc = getCompositionEngine().getHwComposer();
@@ -184,16 +183,18 @@
// Any non-null entries in the current list of layers are layers that are no
// longer going to be visible
- for (auto* layer : getOutputLayersOrderedByZ()) {
- if (!layer) {
+ for (auto* outputLayer : getOutputLayersOrderedByZ()) {
+ if (!outputLayer) {
continue;
}
- sp<compositionengine::LayerFE> layerFE(&layer->getLayerFE());
+ compositionengine::LayerFE* layerFE = &outputLayer->getLayerFE();
const bool hasQueuedFrames =
- std::find(refreshArgs.layersWithQueuedFrames.cbegin(),
- refreshArgs.layersWithQueuedFrames.cend(),
- &layer->getLayer()) != refreshArgs.layersWithQueuedFrames.cend();
+ std::any_of(refreshArgs.layersWithQueuedFrames.cbegin(),
+ refreshArgs.layersWithQueuedFrames.cend(),
+ [layerFE](sp<compositionengine::LayerFE> layerWithQueuedFrames) {
+ return layerFE == layerWithQueuedFrames.get();
+ });
if (hasQueuedFrames) {
releasedLayers.emplace_back(layerFE);
diff --git a/services/surfaceflinger/CompositionEngine/src/Layer.cpp b/services/surfaceflinger/CompositionEngine/src/Layer.cpp
deleted file mode 100644
index ecacaee..0000000
--- a/services/surfaceflinger/CompositionEngine/src/Layer.cpp
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <android-base/stringprintf.h>
-#include <compositionengine/LayerFE.h>
-#include <compositionengine/LayerFECompositionState.h>
-#include <compositionengine/impl/Layer.h>
-
-namespace android::compositionengine {
-
-Layer::~Layer() = default;
-
-namespace impl {
-
-std::shared_ptr<Layer> createLayer(const LayerCreationArgs& args) {
- return compositionengine::impl::createLayerTemplated<Layer>(args);
-}
-
-Layer::~Layer() = default;
-
-void Layer::dump(std::string& out) const {
- auto layerFE = getLayerFE();
- android::base::StringAppendF(&out, "* compositionengine::Layer %p (%s)\n", this,
- layerFE ? layerFE->getDebugName() : "<unknown>");
- out.append(" frontend:\n");
- dumpFEState(out);
-}
-
-} // namespace impl
-} // namespace android::compositionengine
diff --git a/services/surfaceflinger/CompositionEngine/src/LayerFECompositionState.cpp b/services/surfaceflinger/CompositionEngine/src/LayerFECompositionState.cpp
index 016084f..3e0f803 100644
--- a/services/surfaceflinger/CompositionEngine/src/LayerFECompositionState.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/LayerFECompositionState.cpp
@@ -32,6 +32,8 @@
} // namespace
+LayerFECompositionState::~LayerFECompositionState() = default;
+
void LayerFECompositionState::dump(std::string& out) const {
out.append(" ");
dumpVal(out, "isSecure", isSecure);
diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp
index ce4b84a..a389bf3 100644
--- a/services/surfaceflinger/CompositionEngine/src/Output.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp
@@ -20,7 +20,6 @@
#include <compositionengine/CompositionEngine.h>
#include <compositionengine/CompositionRefreshArgs.h>
#include <compositionengine/DisplayColorProfile.h>
-#include <compositionengine/Layer.h>
#include <compositionengine/LayerFE.h>
#include <compositionengine/LayerFECompositionState.h>
#include <compositionengine/RenderSurface.h>
@@ -267,31 +266,26 @@
(!internalOnly || outputState.layerStackInternal);
}
-bool Output::belongsInOutput(const compositionengine::Layer* layer) const {
- if (!layer) {
- return false;
- }
-
- const auto& layerFEState = layer->getFEState();
- return belongsInOutput(layerFEState.layerStackId, layerFEState.internalOnly);
+bool Output::belongsInOutput(const sp<compositionengine::LayerFE>& layerFE) const {
+ const auto* layerFEState = layerFE->getCompositionState();
+ return layerFEState && belongsInOutput(layerFEState->layerStackId, layerFEState->internalOnly);
}
std::unique_ptr<compositionengine::OutputLayer> Output::createOutputLayer(
- const std::shared_ptr<compositionengine::Layer>& layer, const sp<LayerFE>& layerFE) const {
- return impl::createOutputLayer(*this, layer, layerFE);
+ const sp<LayerFE>& layerFE) const {
+ return impl::createOutputLayer(*this, layerFE);
}
-compositionengine::OutputLayer* Output::getOutputLayerForLayer(
- compositionengine::Layer* layer) const {
- auto index = findCurrentOutputLayerForLayer(layer);
+compositionengine::OutputLayer* Output::getOutputLayerForLayer(const sp<LayerFE>& layerFE) const {
+ auto index = findCurrentOutputLayerForLayer(layerFE);
return index ? getOutputLayerOrderedByZByIndex(*index) : nullptr;
}
std::optional<size_t> Output::findCurrentOutputLayerForLayer(
- compositionengine::Layer* layer) const {
+ const sp<compositionengine::LayerFE>& layer) const {
for (size_t i = 0; i < getOutputLayerCount(); i++) {
auto outputLayer = getOutputLayerOrderedByZByIndex(i);
- if (outputLayer && &outputLayer->getLayer() == layer) {
+ if (outputLayer && &outputLayer->getLayerFE() == layer.get()) {
return i;
}
}
@@ -354,7 +348,7 @@
// Evaluate the layers from front to back to determine what is visible. This
// also incrementally calculates the coverage information for each layer as
// well as the entire output.
- for (auto& layer : reversed(refreshArgs.layers)) {
+ for (auto layer : reversed(refreshArgs.layers)) {
// Incrementally process the coverage for each layer
ensureOutputLayerIfVisible(layer, coverage);
@@ -373,28 +367,29 @@
}
}
-void Output::ensureOutputLayerIfVisible(std::shared_ptr<compositionengine::Layer> layer,
+void Output::ensureOutputLayerIfVisible(sp<compositionengine::LayerFE>& layerFE,
compositionengine::Output::CoverageState& coverage) {
- // Note: Converts a wp<LayerFE> to a sp<LayerFE>
- auto layerFE = layer->getLayerFE();
- if (layerFE == nullptr) {
- return;
- }
-
// Ensure we have a snapshot of the basic geometry layer state. Limit the
// snapshots to once per frame for each candidate layer, as layers may
// appear on multiple outputs.
if (!coverage.latchedLayers.count(layerFE)) {
coverage.latchedLayers.insert(layerFE);
- layerFE->latchCompositionState(layer->editFEState(),
- compositionengine::LayerFE::StateSubset::BasicGeometry);
+ layerFE->prepareCompositionState(compositionengine::LayerFE::StateSubset::BasicGeometry);
}
- // Obtain a read-only reference to the front-end layer state
- const auto& layerFEState = layer->getFEState();
-
// Only consider the layers on the given layer stack
- if (!belongsInOutput(layer.get())) {
+ if (!belongsInOutput(layerFE)) {
+ return;
+ }
+
+ // Obtain a read-only pointer to the front-end layer state
+ const auto* layerFEState = layerFE->getCompositionState();
+ if (CC_UNLIKELY(!layerFEState)) {
+ return;
+ }
+
+ // handle hidden surfaces by setting the visible region to empty
+ if (CC_UNLIKELY(!layerFEState->isVisible)) {
return;
}
@@ -432,23 +427,18 @@
*/
Region shadowRegion;
- // handle hidden surfaces by setting the visible region to empty
- if (CC_UNLIKELY(!layerFEState.isVisible)) {
- return;
- }
-
- const ui::Transform& tr = layerFEState.geomLayerTransform;
+ const ui::Transform& tr = layerFEState->geomLayerTransform;
// Get the visible region
// TODO(b/121291683): Is it worth creating helper methods on LayerFEState
// for computations like this?
- const Rect visibleRect(tr.transform(layerFEState.geomLayerBounds));
+ const Rect visibleRect(tr.transform(layerFEState->geomLayerBounds));
visibleRegion.set(visibleRect);
- if (layerFEState.shadowRadius > 0.0f) {
+ if (layerFEState->shadowRadius > 0.0f) {
// if the layer casts a shadow, offset the layers visible region and
// calculate the shadow region.
- const auto inset = static_cast<int32_t>(ceilf(layerFEState.shadowRadius) * -1.0f);
+ const auto inset = static_cast<int32_t>(ceilf(layerFEState->shadowRadius) * -1.0f);
Rect visibleRectWithShadows(visibleRect);
visibleRectWithShadows.inset(inset, inset, inset, inset);
visibleRegion.set(visibleRectWithShadows);
@@ -460,10 +450,10 @@
}
// Remove the transparent area from the visible region
- if (!layerFEState.isOpaque) {
+ if (!layerFEState->isOpaque) {
if (tr.preserveRects()) {
// transform the transparent region
- transparentRegion = tr.transform(layerFEState.transparentRegionHint);
+ transparentRegion = tr.transform(layerFEState->transparentRegionHint);
} else {
// transformation too complex, can't do the
// transparent region optimization.
@@ -473,7 +463,7 @@
// compute the opaque region
const auto layerOrientation = tr.getOrientation();
- if (layerFEState.isOpaque && ((layerOrientation & ui::Transform::ROT_INVALID) == 0)) {
+ if (layerFEState->isOpaque && ((layerOrientation & ui::Transform::ROT_INVALID) == 0)) {
// If we one of the simple category of transforms (0/90/180/270 rotation
// + any flip), then the opaque region is the layer's footprint.
// Otherwise we don't try and compute the opaque region since there may
@@ -497,7 +487,7 @@
// Get coverage information for the layer as previously displayed,
// also taking over ownership from mOutputLayersorderedByZ.
- auto prevOutputLayerIndex = findCurrentOutputLayerForLayer(layer.get());
+ auto prevOutputLayerIndex = findCurrentOutputLayerForLayer(layerFE);
auto prevOutputLayer =
prevOutputLayerIndex ? getOutputLayerOrderedByZByIndex(*prevOutputLayerIndex) : nullptr;
@@ -511,7 +501,7 @@
// compute this layer's dirty region
Region dirty;
- if (layerFEState.contentDirty) {
+ if (layerFEState->contentDirty) {
// we need to invalidate the whole region
dirty = visibleRegion;
// as well, as the old visible region
@@ -558,7 +548,7 @@
// The layer is visible. Either reuse the existing outputLayer if we have
// one, or create a new one if we do not.
- auto result = ensureOutputLayer(prevOutputLayerIndex, layer, layerFE);
+ auto result = ensureOutputLayer(prevOutputLayerIndex, layerFE);
// Store the layer coverage information into the layer state as some of it
// is useful later.
@@ -577,10 +567,9 @@
void Output::updateLayerStateFromFE(const CompositionRefreshArgs& args) const {
for (auto* layer : getOutputLayersOrderedByZ()) {
- layer->getLayerFE().latchCompositionState(layer->getLayer().editFEState(),
- args.updatingGeometryThisFrame
- ? LayerFE::StateSubset::GeometryAndContent
- : LayerFE::StateSubset::Content);
+ layer->getLayerFE().prepareCompositionState(
+ args.updatingGeometryThisFrame ? LayerFE::StateSubset::GeometryAndContent
+ : LayerFE::StateSubset::Content);
}
}
@@ -613,7 +602,7 @@
compositionengine::OutputLayer* Output::findLayerRequestingBackgroundComposition() const {
compositionengine::OutputLayer* layerRequestingBgComposition = nullptr;
for (auto* layer : getOutputLayersOrderedByZ()) {
- if (layer->getLayer().getFEState().backgroundBlurRadius > 0) {
+ if (layer->getLayerFE().getCompositionState()->backgroundBlurRadius > 0) {
layerRequestingBgComposition = layer;
}
}
@@ -639,7 +628,7 @@
*outHdrDataSpace = ui::Dataspace::UNKNOWN;
for (const auto* layer : getOutputLayersOrderedByZ()) {
- switch (layer->getLayer().getFEState().dataspace) {
+ switch (layer->getLayerFE().getCompositionState()->dataspace) {
case ui::Dataspace::V0_SCRGB:
case ui::Dataspace::V0_SCRGB_LINEAR:
case ui::Dataspace::BT2020:
@@ -655,7 +644,8 @@
case ui::Dataspace::BT2020_ITU_PQ:
bestDataSpace = ui::Dataspace::DISPLAY_P3;
*outHdrDataSpace = ui::Dataspace::BT2020_PQ;
- *outIsHdrClientComposition = layer->getLayer().getFEState().forceClientComposition;
+ *outIsHdrClientComposition =
+ layer->getLayerFE().getCompositionState()->forceClientComposition;
break;
case ui::Dataspace::BT2020_HLG:
case ui::Dataspace::BT2020_ITU_HLG:
@@ -867,7 +857,7 @@
if (outputState.isSecure && supportsProtectedContent) {
auto layers = getOutputLayersOrderedByZ();
bool needsProtected = std::any_of(layers.begin(), layers.end(), [](auto* layer) {
- return layer->getLayer().getFEState().hasProtectedContent;
+ return layer->getLayerFE().getCompositionState()->hasProtectedContent;
});
if (needsProtected != renderEngine.isProtected()) {
renderEngine.useProtectedContext(needsProtected);
@@ -955,7 +945,7 @@
for (auto* layer : getOutputLayersOrderedByZ()) {
const auto& layerState = layer->getState();
- const auto& layerFEState = layer->getLayer().getFEState();
+ const auto* layerFEState = layer->getLayerFE().getCompositionState();
auto& layerFE = layer->getLayerFE();
const Region clip(viewportRegion.intersect(layerState.visibleRegion));
@@ -974,7 +964,7 @@
// underneath. We also skip the first layer as the buffer target is
// guaranteed to start out cleared.
bool clearClientComposition =
- layerState.clearClientTarget && layerFEState.isOpaque && !firstLayer;
+ layerState.clearClientTarget && layerFEState->isOpaque && !firstLayer;
ALOGV(" Composition type: client %d clear %d", clientComposition, clearClientComposition);
diff --git a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
index d92b7ef..b538d75 100644
--- a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
@@ -16,7 +16,6 @@
#include <android-base/stringprintf.h>
#include <compositionengine/DisplayColorProfile.h>
-#include <compositionengine/Layer.h>
#include <compositionengine/LayerFE.h>
#include <compositionengine/LayerFECompositionState.h>
#include <compositionengine/Output.h>
@@ -51,11 +50,9 @@
} // namespace
-std::unique_ptr<OutputLayer> createOutputLayer(
- const compositionengine::Output& output,
- const std::shared_ptr<compositionengine::Layer>& layer,
- const sp<compositionengine::LayerFE>& layerFE) {
- return createOutputLayerTemplated<OutputLayer>(output, layer, layerFE);
+std::unique_ptr<OutputLayer> createOutputLayer(const compositionengine::Output& output,
+ const sp<compositionengine::LayerFE>& layerFE) {
+ return createOutputLayerTemplated<OutputLayer>(output, layerFE);
}
OutputLayer::~OutputLayer() = default;
@@ -70,7 +67,7 @@
}
Rect OutputLayer::calculateInitialCrop() const {
- const auto& layerState = getLayer().getFEState();
+ const auto& layerState = *getLayerFE().getCompositionState();
// apply the projection's clipping to the window crop in
// layerstack space, and convert-back to layer space.
@@ -103,7 +100,7 @@
}
FloatRect OutputLayer::calculateOutputSourceCrop() const {
- const auto& layerState = getLayer().getFEState();
+ const auto& layerState = *getLayerFE().getCompositionState();
const auto& outputState = getOutput().getState();
if (!layerState.geomUsesSourceCrop) {
@@ -180,7 +177,7 @@
}
Rect OutputLayer::calculateOutputDisplayFrame() const {
- const auto& layerState = getLayer().getFEState();
+ const auto& layerState = *getLayerFE().getCompositionState();
const auto& outputState = getOutput().getState();
// apply the layer's transform, followed by the display's global transform
@@ -227,7 +224,7 @@
}
uint32_t OutputLayer::calculateOutputRelativeBufferTransform() const {
- const auto& layerState = getLayer().getFEState();
+ const auto& layerState = *getLayerFE().getCompositionState();
const auto& outputState = getOutput().getState();
/*
@@ -267,7 +264,11 @@
} // namespace impl
void OutputLayer::updateCompositionState(bool includeGeometry, bool forceClientComposition) {
- const auto& layerFEState = getLayer().getFEState();
+ const auto* layerFEState = getLayerFE().getCompositionState();
+ if (!layerFEState) {
+ return;
+ }
+
const auto& outputState = getOutput().getState();
const auto& profile = *getOutput().getDisplayColorProfile();
auto& state = editState();
@@ -285,7 +286,7 @@
state.bufferTransform =
static_cast<Hwc2::Transform>(calculateOutputRelativeBufferTransform());
- if ((layerFEState.isSecure && !outputState.isSecure) ||
+ if ((layerFEState->isSecure && !outputState.isSecure) ||
(state.bufferTransform & ui::Transform::ROT_INVALID)) {
state.forceClientComposition = true;
}
@@ -294,14 +295,14 @@
// Determine the output dependent dataspace for this layer. If it is
// colorspace agnostic, it just uses the dataspace chosen for the output to
// avoid the need for color conversion.
- state.dataspace = layerFEState.isColorspaceAgnostic &&
+ state.dataspace = layerFEState->isColorspaceAgnostic &&
outputState.targetDataspace != ui::Dataspace::UNKNOWN
? outputState.targetDataspace
- : layerFEState.dataspace;
+ : layerFEState->dataspace;
// These are evaluated every frame as they can potentially change at any
// time.
- if (layerFEState.forceClientComposition || !profile.isDataspaceSupported(state.dataspace) ||
+ if (layerFEState->forceClientComposition || !profile.isDataspaceSupported(state.dataspace) ||
forceClientComposition) {
state.forceClientComposition = true;
}
@@ -321,21 +322,25 @@
return;
}
- const auto& outputIndependentState = getLayer().getFEState();
- auto requestedCompositionType = outputIndependentState.compositionType;
+ const auto* outputIndependentState = getLayerFE().getCompositionState();
+ if (!outputIndependentState) {
+ return;
+ }
+
+ auto requestedCompositionType = outputIndependentState->compositionType;
if (includeGeometry) {
writeOutputDependentGeometryStateToHWC(hwcLayer.get(), requestedCompositionType);
- writeOutputIndependentGeometryStateToHWC(hwcLayer.get(), outputIndependentState);
+ writeOutputIndependentGeometryStateToHWC(hwcLayer.get(), *outputIndependentState);
}
writeOutputDependentPerFrameStateToHWC(hwcLayer.get());
- writeOutputIndependentPerFrameStateToHWC(hwcLayer.get(), outputIndependentState);
+ writeOutputIndependentPerFrameStateToHWC(hwcLayer.get(), *outputIndependentState);
writeCompositionTypeToHWC(hwcLayer.get(), requestedCompositionType);
// Always set the layer color after setting the composition type.
- writeSolidColorStateToHWC(hwcLayer.get(), outputIndependentState);
+ writeSolidColorStateToHWC(hwcLayer.get(), *outputIndependentState);
}
void OutputLayer::writeOutputDependentGeometryStateToHWC(
@@ -546,10 +551,14 @@
return;
}
- const auto& layerFEState = getLayer().getFEState();
+ const auto* layerFEState = getLayerFE().getCompositionState();
+ if (!layerFEState) {
+ return;
+ }
+
const auto& outputState = getOutput().getState();
- Rect frame = layerFEState.cursorFrame;
+ Rect frame = layerFEState->cursorFrame;
frame.intersect(outputState.viewport, &frame);
Rect position = outputState.transform.transform(frame);
@@ -646,8 +655,7 @@
void OutputLayer::dump(std::string& out) const {
using android::base::StringAppendF;
- StringAppendF(&out, " - Output Layer %p (Composition layer %p) (%s)\n", this, &getLayer(),
- getLayerFE().getDebugName());
+ StringAppendF(&out, " - Output Layer %p(%s)\n", this, getLayerFE().getDebugName());
dumpState(out);
}
diff --git a/services/surfaceflinger/CompositionEngine/tests/CompositionEngineTest.cpp b/services/surfaceflinger/CompositionEngine/tests/CompositionEngineTest.cpp
index c1faa90..d889d74 100644
--- a/services/surfaceflinger/CompositionEngine/tests/CompositionEngineTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/CompositionEngineTest.cpp
@@ -17,7 +17,6 @@
#include <compositionengine/CompositionRefreshArgs.h>
#include <compositionengine/LayerFECompositionState.h>
#include <compositionengine/impl/CompositionEngine.h>
-#include <compositionengine/mock/Layer.h>
#include <compositionengine/mock/LayerFE.h>
#include <compositionengine/mock/Output.h>
#include <compositionengine/mock/OutputLayer.h>
@@ -50,11 +49,6 @@
std::shared_ptr<mock::Output> mOutput1{std::make_shared<StrictMock<mock::Output>>()};
std::shared_ptr<mock::Output> mOutput2{std::make_shared<StrictMock<mock::Output>>()};
std::shared_ptr<mock::Output> mOutput3{std::make_shared<StrictMock<mock::Output>>()};
-
- std::shared_ptr<mock::Layer> mLayer1{std::make_shared<StrictMock<mock::Layer>>()};
- std::shared_ptr<mock::Layer> mLayer2{std::make_shared<StrictMock<mock::Layer>>()};
- std::shared_ptr<mock::Layer> mLayer3{std::make_shared<StrictMock<mock::Layer>>()};
- std::shared_ptr<mock::Layer> mLayer4{std::make_shared<StrictMock<mock::Layer>>()};
};
TEST_F(CompositionEngineTest, canInstantiateCompositionEngine) {
@@ -134,48 +128,32 @@
struct CompositionEngineUpdateCursorAsyncTest : public CompositionEngineTest {
public:
+ struct Layer {
+ Layer() { EXPECT_CALL(outputLayer, getLayerFE()).WillRepeatedly(ReturnRef(layerFE)); }
+
+ StrictMock<mock::OutputLayer> outputLayer;
+ StrictMock<mock::LayerFE> layerFE;
+ LayerFECompositionState layerFEState;
+ };
+
CompositionEngineUpdateCursorAsyncTest() {
EXPECT_CALL(*mOutput1, getOutputLayerCount()).WillRepeatedly(Return(0u));
EXPECT_CALL(*mOutput1, getOutputLayerOrderedByZByIndex(_)).Times(0);
EXPECT_CALL(*mOutput2, getOutputLayerCount()).WillRepeatedly(Return(1u));
EXPECT_CALL(*mOutput2, getOutputLayerOrderedByZByIndex(0))
- .WillRepeatedly(Return(&mOutput2OutputLayer1));
+ .WillRepeatedly(Return(&mOutput2Layer1.outputLayer));
EXPECT_CALL(*mOutput3, getOutputLayerCount()).WillRepeatedly(Return(2u));
EXPECT_CALL(*mOutput3, getOutputLayerOrderedByZByIndex(0))
- .WillRepeatedly(Return(&mOutput3OutputLayer1));
+ .WillRepeatedly(Return(&mOutput3Layer1.outputLayer));
EXPECT_CALL(*mOutput3, getOutputLayerOrderedByZByIndex(1))
- .WillRepeatedly(Return(&mOutput3OutputLayer2));
-
- EXPECT_CALL(mOutput2OutputLayer1, getLayerFE()).WillRepeatedly(ReturnRef(mOutput2Layer1FE));
- EXPECT_CALL(mOutput3OutputLayer1, getLayerFE()).WillRepeatedly(ReturnRef(mOutput3Layer1FE));
- EXPECT_CALL(mOutput3OutputLayer2, getLayerFE()).WillRepeatedly(ReturnRef(mOutput3Layer2FE));
-
- EXPECT_CALL(mOutput2OutputLayer1, getLayer()).WillRepeatedly(ReturnRef(mOutput2Layer1));
- EXPECT_CALL(mOutput3OutputLayer1, getLayer()).WillRepeatedly(ReturnRef(mOutput3Layer1));
- EXPECT_CALL(mOutput3OutputLayer2, getLayer()).WillRepeatedly(ReturnRef(mOutput3Layer2));
-
- EXPECT_CALL(mOutput2Layer1, editFEState()).WillRepeatedly(ReturnRef(mOutput2Layer1FEState));
- EXPECT_CALL(mOutput3Layer1, editFEState()).WillRepeatedly(ReturnRef(mOutput3Layer1FEState));
- EXPECT_CALL(mOutput3Layer2, editFEState()).WillRepeatedly(ReturnRef(mOutput3Layer2FEState));
+ .WillRepeatedly(Return(&mOutput3Layer2.outputLayer));
}
- StrictMock<mock::OutputLayer> mOutput2OutputLayer1;
- StrictMock<mock::OutputLayer> mOutput3OutputLayer1;
- StrictMock<mock::OutputLayer> mOutput3OutputLayer2;
-
- StrictMock<mock::LayerFE> mOutput2Layer1FE;
- StrictMock<mock::LayerFE> mOutput3Layer1FE;
- StrictMock<mock::LayerFE> mOutput3Layer2FE;
-
- StrictMock<mock::Layer> mOutput2Layer1;
- StrictMock<mock::Layer> mOutput3Layer1;
- StrictMock<mock::Layer> mOutput3Layer2;
-
- LayerFECompositionState mOutput2Layer1FEState;
- LayerFECompositionState mOutput3Layer1FEState;
- LayerFECompositionState mOutput3Layer2FEState;
+ Layer mOutput2Layer1;
+ Layer mOutput3Layer1;
+ Layer mOutput3Layer2;
};
TEST_F(CompositionEngineUpdateCursorAsyncTest, handlesNoOutputs) {
@@ -183,9 +161,9 @@
}
TEST_F(CompositionEngineUpdateCursorAsyncTest, handlesNoLayersBeingCursorLayers) {
- EXPECT_CALL(mOutput2OutputLayer1, isHardwareCursor()).WillRepeatedly(Return(false));
- EXPECT_CALL(mOutput3OutputLayer1, isHardwareCursor()).WillRepeatedly(Return(false));
- EXPECT_CALL(mOutput3OutputLayer2, isHardwareCursor()).WillRepeatedly(Return(false));
+ EXPECT_CALL(mOutput3Layer1.outputLayer, isHardwareCursor()).WillRepeatedly(Return(false));
+ EXPECT_CALL(mOutput3Layer2.outputLayer, isHardwareCursor()).WillRepeatedly(Return(false));
+ EXPECT_CALL(mOutput2Layer1.outputLayer, isHardwareCursor()).WillRepeatedly(Return(false));
mRefreshArgs.outputs = {mOutput1, mOutput2, mOutput3};
@@ -195,23 +173,23 @@
TEST_F(CompositionEngineUpdateCursorAsyncTest, handlesMultipleLayersBeingCursorLayers) {
{
InSequence seq;
- EXPECT_CALL(mOutput2OutputLayer1, isHardwareCursor()).WillRepeatedly(Return(true));
- EXPECT_CALL(mOutput2Layer1FE, latchCursorCompositionState(Ref(mOutput2Layer1FEState)));
- EXPECT_CALL(mOutput2OutputLayer1, writeCursorPositionToHWC());
+ EXPECT_CALL(mOutput2Layer1.outputLayer, isHardwareCursor()).WillRepeatedly(Return(true));
+ EXPECT_CALL(mOutput2Layer1.layerFE, prepareCompositionState(LayerFE::StateSubset::Cursor));
+ EXPECT_CALL(mOutput2Layer1.outputLayer, writeCursorPositionToHWC());
}
{
InSequence seq;
- EXPECT_CALL(mOutput3OutputLayer1, isHardwareCursor()).WillRepeatedly(Return(true));
- EXPECT_CALL(mOutput3Layer1FE, latchCursorCompositionState(Ref(mOutput3Layer1FEState)));
- EXPECT_CALL(mOutput3OutputLayer1, writeCursorPositionToHWC());
+ EXPECT_CALL(mOutput3Layer1.outputLayer, isHardwareCursor()).WillRepeatedly(Return(true));
+ EXPECT_CALL(mOutput3Layer1.layerFE, prepareCompositionState(LayerFE::StateSubset::Cursor));
+ EXPECT_CALL(mOutput3Layer1.outputLayer, writeCursorPositionToHWC());
}
{
InSequence seq;
- EXPECT_CALL(mOutput3OutputLayer2, isHardwareCursor()).WillRepeatedly(Return(true));
- EXPECT_CALL(mOutput3Layer2FE, latchCursorCompositionState(Ref(mOutput3Layer2FEState)));
- EXPECT_CALL(mOutput3OutputLayer2, writeCursorPositionToHWC());
+ EXPECT_CALL(mOutput3Layer2.outputLayer, isHardwareCursor()).WillRepeatedly(Return(true));
+ EXPECT_CALL(mOutput3Layer2.layerFE, prepareCompositionState(LayerFE::StateSubset::Cursor));
+ EXPECT_CALL(mOutput3Layer2.outputLayer, writeCursorPositionToHWC());
}
mRefreshArgs.outputs = {mOutput1, mOutput2, mOutput3};
@@ -224,14 +202,6 @@
*/
struct CompositionTestPreComposition : public CompositionEngineTest {
- CompositionTestPreComposition() {
- EXPECT_CALL(*mLayer1, getLayerFE()).WillRepeatedly(Return(mLayer1FE));
- EXPECT_CALL(*mLayer2, getLayerFE()).WillRepeatedly(Return(mLayer2FE));
- EXPECT_CALL(*mLayer3, getLayerFE()).WillRepeatedly(Return(mLayer3FE));
- // getLayerFE() can return nullptr. Ensure that this is handled.
- EXPECT_CALL(*mLayer4, getLayerFE()).WillRepeatedly(Return(nullptr));
- }
-
sp<StrictMock<mock::LayerFE>> mLayer1FE{new StrictMock<mock::LayerFE>()};
sp<StrictMock<mock::LayerFE>> mLayer2FE{new StrictMock<mock::LayerFE>()};
sp<StrictMock<mock::LayerFE>> mLayer3FE{new StrictMock<mock::LayerFE>()};
@@ -256,7 +226,7 @@
EXPECT_CALL(*mLayer3FE, onPreComposition(_)).WillOnce(DoAll(SaveArg<0>(&ts3), Return(false)));
mRefreshArgs.outputs = {mOutput1};
- mRefreshArgs.layers = {mLayer1, mLayer2, mLayer3, mLayer4};
+ mRefreshArgs.layers = {mLayer1FE, mLayer2FE, mLayer3FE};
mEngine.preComposition(mRefreshArgs);
@@ -274,7 +244,7 @@
mEngine.setNeedsAnotherUpdateForTest(true);
mRefreshArgs.outputs = {mOutput1};
- mRefreshArgs.layers = {mLayer1, mLayer2, mLayer3, mLayer4};
+ mRefreshArgs.layers = {mLayer1FE, mLayer2FE, mLayer3FE};
mEngine.preComposition(mRefreshArgs);
@@ -289,7 +259,7 @@
EXPECT_CALL(*mLayer3FE, onPreComposition(_)).WillOnce(Return(false));
mRefreshArgs.outputs = {mOutput1};
- mRefreshArgs.layers = {mLayer1, mLayer2, mLayer3, mLayer4};
+ mRefreshArgs.layers = {mLayer1FE, mLayer2FE, mLayer3FE};
mEngine.preComposition(mRefreshArgs);
diff --git a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
index ae93969..16f7a4e 100644
--- a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
@@ -25,7 +25,6 @@
#include <compositionengine/mock/CompositionEngine.h>
#include <compositionengine/mock/DisplayColorProfile.h>
#include <compositionengine/mock/DisplaySurface.h>
-#include <compositionengine/mock/Layer.h>
#include <compositionengine/mock/LayerFE.h>
#include <compositionengine/mock/NativeWindow.h>
#include <compositionengine/mock/OutputLayer.h>
@@ -53,6 +52,27 @@
constexpr int32_t DEFAULT_DISPLAY_WIDTH = 1920;
constexpr int32_t DEFAULT_DISPLAY_HEIGHT = 1080;
+struct Layer {
+ Layer() {
+ EXPECT_CALL(*outputLayer, getLayerFE()).WillRepeatedly(ReturnRef(*layerFE));
+ EXPECT_CALL(*outputLayer, getHwcLayer()).WillRepeatedly(Return(&hwc2Layer));
+ }
+
+ sp<mock::LayerFE> layerFE = new StrictMock<mock::LayerFE>();
+ StrictMock<mock::OutputLayer>* outputLayer = new StrictMock<mock::OutputLayer>();
+ StrictMock<HWC2::mock::Layer> hwc2Layer;
+};
+
+struct LayerNoHWC2Layer {
+ LayerNoHWC2Layer() {
+ EXPECT_CALL(*outputLayer, getLayerFE()).WillRepeatedly(ReturnRef(*layerFE));
+ EXPECT_CALL(*outputLayer, getHwcLayer()).WillRepeatedly(Return(nullptr));
+ }
+
+ sp<mock::LayerFE> layerFE = new StrictMock<mock::LayerFE>();
+ StrictMock<mock::OutputLayer>* outputLayer = new StrictMock<mock::OutputLayer>();
+};
+
struct DisplayTest : public testing::Test {
class Display : public impl::Display {
public:
@@ -71,28 +91,24 @@
DisplayTest() {
EXPECT_CALL(mCompositionEngine, getHwComposer()).WillRepeatedly(ReturnRef(mHwComposer));
- EXPECT_CALL(*mLayer1, getHwcLayer()).WillRepeatedly(Return(&mHWC2Layer1));
- EXPECT_CALL(*mLayer2, getHwcLayer()).WillRepeatedly(Return(&mHWC2Layer2));
- EXPECT_CALL(*mLayer3, getHwcLayer()).WillRepeatedly(Return(nullptr));
mDisplay->injectOutputLayerForTest(
- std::unique_ptr<compositionengine::OutputLayer>(mLayer1));
+ std::unique_ptr<compositionengine::OutputLayer>(mLayer1.outputLayer));
mDisplay->injectOutputLayerForTest(
- std::unique_ptr<compositionengine::OutputLayer>(mLayer2));
+ std::unique_ptr<compositionengine::OutputLayer>(mLayer2.outputLayer));
mDisplay->injectOutputLayerForTest(
- std::unique_ptr<compositionengine::OutputLayer>(mLayer3));
+ std::unique_ptr<compositionengine::OutputLayer>(mLayer3.outputLayer));
}
StrictMock<android::mock::HWComposer> mHwComposer;
StrictMock<Hwc2::mock::PowerAdvisor> mPowerAdvisor;
StrictMock<mock::CompositionEngine> mCompositionEngine;
sp<mock::NativeWindow> mNativeWindow = new StrictMock<mock::NativeWindow>();
- StrictMock<HWC2::mock::Layer> mHWC2Layer1;
- StrictMock<HWC2::mock::Layer> mHWC2Layer2;
- StrictMock<HWC2::mock::Layer> mHWC2LayerUnknown;
- mock::OutputLayer* mLayer1 = new StrictMock<mock::OutputLayer>();
- mock::OutputLayer* mLayer2 = new StrictMock<mock::OutputLayer>();
- mock::OutputLayer* mLayer3 = new StrictMock<mock::OutputLayer>();
+ Layer mLayer1;
+ Layer mLayer2;
+ LayerNoHWC2Layer mLayer3;
+ StrictMock<HWC2::mock::Layer> hwc2LayerUnknown;
+
std::shared_ptr<Display> mDisplay = createDisplay(mCompositionEngine,
DisplayCreationArgsBuilder()
.setDisplayId(DEFAULT_DISPLAY_ID)
@@ -283,12 +299,11 @@
TEST_F(DisplayTest, createOutputLayerSetsHwcLayer) {
sp<mock::LayerFE> layerFE = new StrictMock<mock::LayerFE>();
- auto layer = std::make_shared<StrictMock<mock::Layer>>();
StrictMock<HWC2::mock::Layer> hwcLayer;
EXPECT_CALL(mHwComposer, createLayer(DEFAULT_DISPLAY_ID)).WillOnce(Return(&hwcLayer));
- auto outputLayer = mDisplay->createOutputLayer(layer, layerFE);
+ auto outputLayer = mDisplay->createOutputLayer(layerFE);
EXPECT_EQ(&hwcLayer, outputLayer->getHwcLayer());
@@ -305,7 +320,6 @@
impl::createDisplay(mCompositionEngine, DisplayCreationArgsBuilder().build())};
sp<mock::LayerFE> layerXLayerFE = new StrictMock<mock::LayerFE>();
- mock::Layer layerXLayer;
{
Output::ReleasedLayers releasedLayers;
@@ -314,7 +328,7 @@
}
CompositionRefreshArgs refreshArgs;
- refreshArgs.layersWithQueuedFrames.push_back(&layerXLayer);
+ refreshArgs.layersWithQueuedFrames.push_back(layerXLayerFE);
nonHwcDisplay->setReleasedLayers(refreshArgs);
@@ -339,34 +353,19 @@
}
TEST_F(DisplayTest, setReleasedLayers) {
- sp<mock::LayerFE> layer1LayerFE = new StrictMock<mock::LayerFE>();
- sp<mock::LayerFE> layer2LayerFE = new StrictMock<mock::LayerFE>();
- sp<mock::LayerFE> layer3LayerFE = new StrictMock<mock::LayerFE>();
- sp<mock::LayerFE> layerXLayerFE = new StrictMock<mock::LayerFE>();
- mock::Layer layer1Layer;
- mock::Layer layer2Layer;
- mock::Layer layer3Layer;
- mock::Layer layerXLayer;
-
- EXPECT_CALL(*mLayer1, getLayer()).WillRepeatedly(ReturnRef(layer1Layer));
- EXPECT_CALL(*mLayer1, getLayerFE()).WillRepeatedly(ReturnRef(*layer1LayerFE.get()));
- EXPECT_CALL(*mLayer2, getLayer()).WillRepeatedly(ReturnRef(layer2Layer));
- EXPECT_CALL(*mLayer2, getLayerFE()).WillRepeatedly(ReturnRef(*layer2LayerFE.get()));
- EXPECT_CALL(*mLayer3, getLayer()).WillRepeatedly(ReturnRef(layer3Layer));
- EXPECT_CALL(*mLayer3, getLayerFE()).WillRepeatedly(ReturnRef(*layer3LayerFE.get()));
+ sp<mock::LayerFE> unknownLayer = new StrictMock<mock::LayerFE>();
CompositionRefreshArgs refreshArgs;
- refreshArgs.layersWithQueuedFrames.push_back(&layer1Layer);
- refreshArgs.layersWithQueuedFrames.push_back(&layer2Layer);
- refreshArgs.layersWithQueuedFrames.push_back(&layerXLayer);
- refreshArgs.layersWithQueuedFrames.push_back(nullptr);
+ refreshArgs.layersWithQueuedFrames.push_back(mLayer1.layerFE);
+ refreshArgs.layersWithQueuedFrames.push_back(mLayer2.layerFE);
+ refreshArgs.layersWithQueuedFrames.push_back(unknownLayer);
mDisplay->setReleasedLayers(refreshArgs);
const auto& releasedLayers = mDisplay->getReleasedLayersForTest();
ASSERT_EQ(2, releasedLayers.size());
- ASSERT_EQ(layer1LayerFE.get(), releasedLayers[0].promote().get());
- ASSERT_EQ(layer2LayerFE.get(), releasedLayers[1].promote().get());
+ ASSERT_EQ(mLayer1.layerFE.get(), releasedLayers[0].promote().get());
+ ASSERT_EQ(mLayer2.layerFE.get(), releasedLayers[1].promote().get());
}
/*
@@ -400,16 +399,12 @@
MOCK_CONST_METHOD0(getOutputLayerCount, size_t());
MOCK_CONST_METHOD1(getOutputLayerOrderedByZByIndex,
compositionengine::OutputLayer*(size_t));
- MOCK_METHOD3(ensureOutputLayer,
- compositionengine::OutputLayer*(
- std::optional<size_t>,
- const std::shared_ptr<compositionengine::Layer>&, const sp<LayerFE>&));
+ MOCK_METHOD2(ensureOutputLayer,
+ compositionengine::OutputLayer*(std::optional<size_t>, const sp<LayerFE>&));
MOCK_METHOD0(finalizePendingOutputLayers, void());
MOCK_METHOD0(clearOutputLayers, void());
MOCK_CONST_METHOD1(dumpState, void(std::string&));
- MOCK_METHOD2(injectOutputLayerForTest,
- compositionengine::OutputLayer*(
- const std::shared_ptr<compositionengine::Layer>&, const sp<LayerFE>&));
+ MOCK_METHOD1(injectOutputLayerForTest, compositionengine::OutputLayer*(const sp<LayerFE>&));
MOCK_METHOD1(injectOutputLayerForTest, void(std::unique_ptr<OutputLayer>));
const compositionengine::CompositionEngine& mCompositionEngine;
@@ -523,16 +518,16 @@
*/
TEST_F(DisplayTest, anyLayersRequireClientCompositionReturnsFalse) {
- EXPECT_CALL(*mLayer1, requiresClientComposition()).WillOnce(Return(false));
- EXPECT_CALL(*mLayer2, requiresClientComposition()).WillOnce(Return(false));
- EXPECT_CALL(*mLayer3, requiresClientComposition()).WillOnce(Return(false));
+ EXPECT_CALL(*mLayer1.outputLayer, requiresClientComposition()).WillOnce(Return(false));
+ EXPECT_CALL(*mLayer2.outputLayer, requiresClientComposition()).WillOnce(Return(false));
+ EXPECT_CALL(*mLayer3.outputLayer, requiresClientComposition()).WillOnce(Return(false));
EXPECT_FALSE(mDisplay->anyLayersRequireClientComposition());
}
TEST_F(DisplayTest, anyLayersRequireClientCompositionReturnsTrue) {
- EXPECT_CALL(*mLayer1, requiresClientComposition()).WillOnce(Return(false));
- EXPECT_CALL(*mLayer2, requiresClientComposition()).WillOnce(Return(true));
+ EXPECT_CALL(*mLayer1.outputLayer, requiresClientComposition()).WillOnce(Return(false));
+ EXPECT_CALL(*mLayer2.outputLayer, requiresClientComposition()).WillOnce(Return(true));
EXPECT_TRUE(mDisplay->anyLayersRequireClientComposition());
}
@@ -542,16 +537,16 @@
*/
TEST_F(DisplayTest, allLayersRequireClientCompositionReturnsTrue) {
- EXPECT_CALL(*mLayer1, requiresClientComposition()).WillOnce(Return(true));
- EXPECT_CALL(*mLayer2, requiresClientComposition()).WillOnce(Return(true));
- EXPECT_CALL(*mLayer3, requiresClientComposition()).WillOnce(Return(true));
+ EXPECT_CALL(*mLayer1.outputLayer, requiresClientComposition()).WillOnce(Return(true));
+ EXPECT_CALL(*mLayer2.outputLayer, requiresClientComposition()).WillOnce(Return(true));
+ EXPECT_CALL(*mLayer3.outputLayer, requiresClientComposition()).WillOnce(Return(true));
EXPECT_TRUE(mDisplay->allLayersRequireClientComposition());
}
TEST_F(DisplayTest, allLayersRequireClientCompositionReturnsFalse) {
- EXPECT_CALL(*mLayer1, requiresClientComposition()).WillOnce(Return(true));
- EXPECT_CALL(*mLayer2, requiresClientComposition()).WillOnce(Return(false));
+ EXPECT_CALL(*mLayer1.outputLayer, requiresClientComposition()).WillOnce(Return(true));
+ EXPECT_CALL(*mLayer2.outputLayer, requiresClientComposition()).WillOnce(Return(false));
EXPECT_FALSE(mDisplay->allLayersRequireClientComposition());
}
@@ -565,17 +560,17 @@
}
TEST_F(DisplayTest, applyChangedTypesToLayersAppliesChanges) {
- EXPECT_CALL(*mLayer1,
+ EXPECT_CALL(*mLayer1.outputLayer,
applyDeviceCompositionTypeChange(Hwc2::IComposerClient::Composition::CLIENT))
.Times(1);
- EXPECT_CALL(*mLayer2,
+ EXPECT_CALL(*mLayer2.outputLayer,
applyDeviceCompositionTypeChange(Hwc2::IComposerClient::Composition::DEVICE))
.Times(1);
mDisplay->applyChangedTypesToLayers(impl::Display::ChangedTypes{
- {&mHWC2Layer1, HWC2::Composition::Client},
- {&mHWC2Layer2, HWC2::Composition::Device},
- {&mHWC2LayerUnknown, HWC2::Composition::SolidColor},
+ {&mLayer1.hwc2Layer, HWC2::Composition::Client},
+ {&mLayer2.hwc2Layer, HWC2::Composition::Device},
+ {&hwc2LayerUnknown, HWC2::Composition::SolidColor},
});
}
@@ -616,25 +611,25 @@
*/
TEST_F(DisplayTest, applyLayerRequestsToLayersPreparesAllLayers) {
- EXPECT_CALL(*mLayer1, prepareForDeviceLayerRequests()).Times(1);
- EXPECT_CALL(*mLayer2, prepareForDeviceLayerRequests()).Times(1);
- EXPECT_CALL(*mLayer3, prepareForDeviceLayerRequests()).Times(1);
+ EXPECT_CALL(*mLayer1.outputLayer, prepareForDeviceLayerRequests()).Times(1);
+ EXPECT_CALL(*mLayer2.outputLayer, prepareForDeviceLayerRequests()).Times(1);
+ EXPECT_CALL(*mLayer3.outputLayer, prepareForDeviceLayerRequests()).Times(1);
mDisplay->applyLayerRequestsToLayers(impl::Display::LayerRequests());
}
TEST_F(DisplayTest, applyLayerRequestsToLayers2) {
- EXPECT_CALL(*mLayer1, prepareForDeviceLayerRequests()).Times(1);
- EXPECT_CALL(*mLayer2, prepareForDeviceLayerRequests()).Times(1);
- EXPECT_CALL(*mLayer3, prepareForDeviceLayerRequests()).Times(1);
+ EXPECT_CALL(*mLayer1.outputLayer, prepareForDeviceLayerRequests()).Times(1);
+ EXPECT_CALL(*mLayer2.outputLayer, prepareForDeviceLayerRequests()).Times(1);
+ EXPECT_CALL(*mLayer3.outputLayer, prepareForDeviceLayerRequests()).Times(1);
- EXPECT_CALL(*mLayer1,
+ EXPECT_CALL(*mLayer1.outputLayer,
applyDeviceLayerRequest(Hwc2::IComposerClient::LayerRequest::CLEAR_CLIENT_TARGET))
.Times(1);
mDisplay->applyLayerRequestsToLayers(impl::Display::LayerRequests{
- {&mHWC2Layer1, HWC2::LayerRequest::ClearClientTarget},
- {&mHWC2LayerUnknown, HWC2::LayerRequest::ClearClientTarget},
+ {&mLayer1.hwc2Layer, HWC2::LayerRequest::ClearClientTarget},
+ {&hwc2LayerUnknown, HWC2::LayerRequest::ClearClientTarget},
});
}
@@ -660,9 +655,9 @@
EXPECT_CALL(mHwComposer, presentAndGetReleaseFences(DEFAULT_DISPLAY_ID)).Times(1);
EXPECT_CALL(mHwComposer, getPresentFence(DEFAULT_DISPLAY_ID)).WillOnce(Return(presentFence));
- EXPECT_CALL(mHwComposer, getLayerReleaseFence(DEFAULT_DISPLAY_ID, &mHWC2Layer1))
+ EXPECT_CALL(mHwComposer, getLayerReleaseFence(DEFAULT_DISPLAY_ID, &mLayer1.hwc2Layer))
.WillOnce(Return(layer1Fence));
- EXPECT_CALL(mHwComposer, getLayerReleaseFence(DEFAULT_DISPLAY_ID, &mHWC2Layer2))
+ EXPECT_CALL(mHwComposer, getLayerReleaseFence(DEFAULT_DISPLAY_ID, &mLayer2.hwc2Layer))
.WillOnce(Return(layer2Fence));
EXPECT_CALL(mHwComposer, clearReleaseFences(DEFAULT_DISPLAY_ID)).Times(1);
@@ -671,10 +666,10 @@
EXPECT_EQ(presentFence, result.presentFence);
EXPECT_EQ(2u, result.layerFences.size());
- ASSERT_EQ(1, result.layerFences.count(&mHWC2Layer1));
- EXPECT_EQ(layer1Fence, result.layerFences[&mHWC2Layer1]);
- ASSERT_EQ(1, result.layerFences.count(&mHWC2Layer2));
- EXPECT_EQ(layer2Fence, result.layerFences[&mHWC2Layer2]);
+ ASSERT_EQ(1, result.layerFences.count(&mLayer1.hwc2Layer));
+ EXPECT_EQ(layer1Fence, result.layerFences[&mLayer1.hwc2Layer]);
+ ASSERT_EQ(1, result.layerFences.count(&mLayer2.hwc2Layer));
+ EXPECT_EQ(layer2Fence, result.layerFences[&mLayer2.hwc2Layer]);
}
/*
diff --git a/services/surfaceflinger/CompositionEngine/tests/LayerTest.cpp b/services/surfaceflinger/CompositionEngine/tests/LayerTest.cpp
deleted file mode 100644
index 787f973..0000000
--- a/services/surfaceflinger/CompositionEngine/tests/LayerTest.cpp
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <gtest/gtest.h>
-
-#include <compositionengine/LayerCreationArgs.h>
-#include <compositionengine/LayerFECompositionState.h>
-#include <compositionengine/impl/Layer.h>
-#include <compositionengine/mock/CompositionEngine.h>
-#include <compositionengine/mock/LayerFE.h>
-
-namespace android::compositionengine {
-namespace {
-
-using testing::StrictMock;
-
-struct LayerTest : public testing::Test {
- struct Layer final : public impl::Layer {
- explicit Layer(const LayerCreationArgs& args) : mLayerFE(args.layerFE) {}
- ~Layer() override = default;
-
- // compositionengine::Layer overrides
- sp<LayerFE> getLayerFE() const { return mLayerFE.promote(); }
- const LayerFECompositionState& getFEState() const override { return mFrontEndState; }
- LayerFECompositionState& editFEState() override { return mFrontEndState; }
-
- // compositionengine::impl::Layer overrides
- void dumpFEState(std::string& out) const override { mFrontEndState.dump(out); }
-
- const wp<LayerFE> mLayerFE;
- LayerFECompositionState mFrontEndState;
- };
-
- ~LayerTest() override = default;
-
- StrictMock<mock::CompositionEngine> mCompositionEngine;
- sp<LayerFE> mLayerFE = new StrictMock<mock::LayerFE>();
- Layer mLayer{LayerCreationArgs{mLayerFE}};
-};
-
-/* ------------------------------------------------------------------------
- * Basic construction
- */
-
-TEST_F(LayerTest, canInstantiateLayer) {}
-
-} // namespace
-} // namespace android::compositionengine
diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
index 0e579fa..963062f 100644
--- a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
@@ -18,7 +18,6 @@
#include <compositionengine/impl/OutputLayerCompositionState.h>
#include <compositionengine/mock/CompositionEngine.h>
#include <compositionengine/mock/DisplayColorProfile.h>
-#include <compositionengine/mock/Layer.h>
#include <compositionengine/mock/LayerFE.h>
#include <compositionengine/mock/Output.h>
#include <gtest/gtest.h>
@@ -56,15 +55,12 @@
struct OutputLayerTest : public testing::Test {
struct OutputLayer final : public impl::OutputLayer {
- OutputLayer(const compositionengine::Output& output,
- std::shared_ptr<compositionengine::Layer> layer,
- sp<compositionengine::LayerFE> layerFE)
- : mOutput(output), mLayer(layer), mLayerFE(layerFE) {}
+ OutputLayer(const compositionengine::Output& output, sp<compositionengine::LayerFE> layerFE)
+ : mOutput(output), mLayerFE(layerFE) {}
~OutputLayer() override = default;
// compositionengine::OutputLayer overrides
const compositionengine::Output& getOutput() const override { return mOutput; }
- compositionengine::Layer& getLayer() const override { return *mLayer; }
compositionengine::LayerFE& getLayerFE() const override { return *mLayerFE; }
const impl::OutputLayerCompositionState& getState() const override { return mState; }
impl::OutputLayerCompositionState& editState() override { return mState; }
@@ -73,7 +69,6 @@
void dumpState(std::string& out) const override { mState.dump(out); }
const compositionengine::Output& mOutput;
- std::shared_ptr<compositionengine::Layer> mLayer;
sp<compositionengine::LayerFE> mLayerFE;
impl::OutputLayerCompositionState mState;
};
@@ -82,16 +77,14 @@
EXPECT_CALL(*mLayerFE, getDebugName()).WillRepeatedly(Return("Test LayerFE"));
EXPECT_CALL(mOutput, getName()).WillRepeatedly(ReturnRef(kOutputName));
- EXPECT_CALL(*mLayer, getFEState()).WillRepeatedly(ReturnRef(mLayerFEState));
+ EXPECT_CALL(*mLayerFE, getCompositionState()).WillRepeatedly(Return(&mLayerFEState));
EXPECT_CALL(mOutput, getState()).WillRepeatedly(ReturnRef(mOutputState));
}
compositionengine::mock::Output mOutput;
- std::shared_ptr<compositionengine::mock::Layer> mLayer{
- new StrictMock<compositionengine::mock::Layer>()};
sp<compositionengine::mock::LayerFE> mLayerFE{
new StrictMock<compositionengine::mock::LayerFE>()};
- OutputLayer mOutputLayer{mOutput, mLayer, mLayerFE};
+ OutputLayer mOutputLayer{mOutput, mLayerFE};
LayerFECompositionState mLayerFEState;
impl::OutputCompositionState mOutputState;
@@ -436,9 +429,8 @@
struct OutputLayerPartialMockForUpdateCompositionState : public impl::OutputLayer {
OutputLayerPartialMockForUpdateCompositionState(const compositionengine::Output& output,
- std::shared_ptr<compositionengine::Layer> layer,
sp<compositionengine::LayerFE> layerFE)
- : mOutput(output), mLayer(layer), mLayerFE(layerFE) {}
+ : mOutput(output), mLayerFE(layerFE) {}
// Mock everything called by updateCompositionState to simplify testing it.
MOCK_CONST_METHOD0(calculateOutputSourceCrop, FloatRect());
MOCK_CONST_METHOD0(calculateOutputDisplayFrame, Rect());
@@ -446,7 +438,6 @@
// compositionengine::OutputLayer overrides
const compositionengine::Output& getOutput() const override { return mOutput; }
- compositionengine::Layer& getLayer() const override { return *mLayer; }
compositionengine::LayerFE& getLayerFE() const override { return *mLayerFE; }
const impl::OutputLayerCompositionState& getState() const override { return mState; }
impl::OutputLayerCompositionState& editState() override { return mState; }
@@ -455,7 +446,6 @@
MOCK_CONST_METHOD1(dumpState, void(std::string&));
const compositionengine::Output& mOutput;
- std::shared_ptr<compositionengine::Layer> mLayer;
sp<compositionengine::LayerFE> mLayerFE;
impl::OutputLayerCompositionState mState;
};
@@ -463,7 +453,6 @@
struct OutputLayerUpdateCompositionStateTest : public OutputLayerTest {
public:
OutputLayerUpdateCompositionStateTest() {
- EXPECT_CALL(*mLayer, getFEState()).WillRepeatedly(ReturnRef(mLayerFEState));
EXPECT_CALL(mOutput, getState()).WillRepeatedly(ReturnRef(mOutputState));
EXPECT_CALL(mOutput, getDisplayColorProfile())
.WillRepeatedly(Return(&mDisplayColorProfile));
@@ -491,10 +480,16 @@
uint32_t mBufferTransform{21};
using OutputLayer = OutputLayerPartialMockForUpdateCompositionState;
- StrictMock<OutputLayer> mOutputLayer{mOutput, mLayer, mLayerFE};
+ StrictMock<OutputLayer> mOutputLayer{mOutput, mLayerFE};
StrictMock<mock::DisplayColorProfile> mDisplayColorProfile;
};
+TEST_F(OutputLayerUpdateCompositionStateTest, doesNothingIfNoFECompositionState) {
+ EXPECT_CALL(*mLayerFE, getCompositionState()).WillOnce(Return(nullptr));
+
+ mOutputLayer.updateCompositionState(true, false);
+}
+
TEST_F(OutputLayerUpdateCompositionStateTest, setsStateNormally) {
mLayerFEState.isSecure = true;
mOutputState.isSecure = true;
@@ -745,6 +740,12 @@
const sp<GraphicBuffer> OutputLayerWriteStateToHWCTest::kBuffer;
const sp<Fence> OutputLayerWriteStateToHWCTest::kFence;
+TEST_F(OutputLayerWriteStateToHWCTest, doesNothingIfNoFECompositionState) {
+ EXPECT_CALL(*mLayerFE, getCompositionState()).WillOnce(Return(nullptr));
+
+ mOutputLayer.writeStateToHWC(true);
+}
+
TEST_F(OutputLayerWriteStateToHWCTest, doesNothingIfNoHWCState) {
mOutputLayer.editState().hwc.reset();
@@ -888,6 +889,12 @@
const Rect OutputLayerWriteCursorPositionToHWCTest::kDefaultDisplayViewport{0, 0, 1920, 1080};
const Rect OutputLayerWriteCursorPositionToHWCTest::kDefaultCursorFrame{1, 2, 3, 4};
+TEST_F(OutputLayerWriteCursorPositionToHWCTest, doesNothingIfNoFECompositionState) {
+ EXPECT_CALL(*mLayerFE, getCompositionState()).WillOnce(Return(nullptr));
+
+ mOutputLayer.writeCursorPositionToHWC();
+}
+
TEST_F(OutputLayerWriteCursorPositionToHWCTest, writeCursorPositionToHWCHandlesNoHwcState) {
mOutputLayer.editState().hwc.reset();
diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
index 463d095..2b45046 100644
--- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
@@ -23,7 +23,6 @@
#include <compositionengine/impl/OutputLayerCompositionState.h>
#include <compositionengine/mock/CompositionEngine.h>
#include <compositionengine/mock/DisplayColorProfile.h>
-#include <compositionengine/mock/Layer.h>
#include <compositionengine/mock/LayerFE.h>
#include <compositionengine/mock/OutputLayer.h>
#include <compositionengine/mock/RenderSurface.h>
@@ -78,22 +77,48 @@
// not implemented by the base implementation class.
MOCK_CONST_METHOD0(getOutputLayerCount, size_t());
MOCK_CONST_METHOD1(getOutputLayerOrderedByZByIndex, compositionengine::OutputLayer*(size_t));
- MOCK_METHOD3(ensureOutputLayer,
- compositionengine::OutputLayer*(std::optional<size_t>,
- const std::shared_ptr<compositionengine::Layer>&,
- const sp<LayerFE>&));
+ MOCK_METHOD2(ensureOutputLayer,
+ compositionengine::OutputLayer*(std::optional<size_t>, const sp<LayerFE>&));
MOCK_METHOD0(finalizePendingOutputLayers, void());
MOCK_METHOD0(clearOutputLayers, void());
MOCK_CONST_METHOD1(dumpState, void(std::string&));
MOCK_CONST_METHOD0(getCompositionEngine, const CompositionEngine&());
- MOCK_METHOD2(injectOutputLayerForTest,
- compositionengine::OutputLayer*(const std::shared_ptr<compositionengine::Layer>&,
- const sp<LayerFE>&));
+ MOCK_METHOD1(injectOutputLayerForTest, compositionengine::OutputLayer*(const sp<LayerFE>&));
MOCK_METHOD1(injectOutputLayerForTest, void(std::unique_ptr<OutputLayer>));
impl::OutputCompositionState mState;
};
+struct InjectedLayer {
+ InjectedLayer() {
+ EXPECT_CALL(*outputLayer, getLayerFE()).WillRepeatedly(ReturnRef(*layerFE.get()));
+ EXPECT_CALL(*outputLayer, getState()).WillRepeatedly(ReturnRef(outputLayerState));
+ EXPECT_CALL(*outputLayer, editState()).WillRepeatedly(ReturnRef(outputLayerState));
+
+ EXPECT_CALL(*layerFE, getCompositionState()).WillRepeatedly(Return(&layerFEState));
+ }
+
+ mock::OutputLayer* outputLayer = {new StrictMock<mock::OutputLayer>};
+ sp<StrictMock<mock::LayerFE>> layerFE = new StrictMock<mock::LayerFE>();
+ LayerFECompositionState layerFEState;
+ impl::OutputLayerCompositionState outputLayerState;
+};
+
+struct NonInjectedLayer {
+ NonInjectedLayer() {
+ EXPECT_CALL(outputLayer, getLayerFE()).WillRepeatedly(ReturnRef(*layerFE.get()));
+ EXPECT_CALL(outputLayer, getState()).WillRepeatedly(ReturnRef(outputLayerState));
+ EXPECT_CALL(outputLayer, editState()).WillRepeatedly(ReturnRef(outputLayerState));
+
+ EXPECT_CALL(*layerFE, getCompositionState()).WillRepeatedly(Return(&layerFEState));
+ }
+
+ mock::OutputLayer outputLayer;
+ sp<StrictMock<mock::LayerFE>> layerFE = new StrictMock<mock::LayerFE>();
+ LayerFECompositionState layerFEState;
+ impl::OutputLayerCompositionState outputLayerState;
+};
+
struct OutputTest : public testing::Test {
class Output : public impl::Output {
public:
@@ -114,6 +139,14 @@
mOutput->editState().bounds = kDefaultDisplaySize;
}
+ void injectOutputLayer(InjectedLayer& layer) {
+ mOutput->injectOutputLayerForTest(std::unique_ptr<OutputLayer>(layer.outputLayer));
+ }
+
+ void injectNullOutputLayer() {
+ mOutput->injectOutputLayerForTest(std::unique_ptr<OutputLayer>(nullptr));
+ }
+
static const Rect kDefaultDisplaySize;
StrictMock<mock::CompositionEngine> mCompositionEngine;
@@ -122,48 +155,6 @@
std::shared_ptr<Output> mOutput = createOutput(mCompositionEngine);
};
-// Extension of the base test useful for checking interactions with the LayerFE
-// functions to latch composition state.
-struct OutputLatchFEStateTest : public OutputTest {
- OutputLatchFEStateTest() {
- EXPECT_CALL(*mOutputLayer1, getLayer()).WillRepeatedly(ReturnRef(mLayer1));
- EXPECT_CALL(*mOutputLayer2, getLayer()).WillRepeatedly(ReturnRef(mLayer2));
- EXPECT_CALL(*mOutputLayer3, getLayer()).WillRepeatedly(ReturnRef(mLayer3));
-
- EXPECT_CALL(*mOutputLayer1, getLayerFE()).WillRepeatedly(ReturnRef(mLayer1FE));
- EXPECT_CALL(*mOutputLayer2, getLayerFE()).WillRepeatedly(ReturnRef(mLayer2FE));
- EXPECT_CALL(*mOutputLayer3, getLayerFE()).WillRepeatedly(ReturnRef(mLayer3FE));
-
- EXPECT_CALL(mLayer1, editFEState()).WillRepeatedly(ReturnRef(mLayer1FEState));
- EXPECT_CALL(mLayer2, editFEState()).WillRepeatedly(ReturnRef(mLayer2FEState));
- EXPECT_CALL(mLayer3, editFEState()).WillRepeatedly(ReturnRef(mLayer3FEState));
-
- EXPECT_CALL(mLayer1, getFEState()).WillRepeatedly(ReturnRef(mLayer1FEState));
- EXPECT_CALL(mLayer2, getFEState()).WillRepeatedly(ReturnRef(mLayer2FEState));
- EXPECT_CALL(mLayer3, getFEState()).WillRepeatedly(ReturnRef(mLayer3FEState));
- }
-
- void injectLayer(std::unique_ptr<mock::OutputLayer> layer) {
- mOutput->injectOutputLayerForTest(std::unique_ptr<OutputLayer>(layer.release()));
- }
-
- std::unique_ptr<mock::OutputLayer> mOutputLayer1{new StrictMock<mock::OutputLayer>};
- std::unique_ptr<mock::OutputLayer> mOutputLayer2{new StrictMock<mock::OutputLayer>};
- std::unique_ptr<mock::OutputLayer> mOutputLayer3{new StrictMock<mock::OutputLayer>};
-
- StrictMock<mock::Layer> mLayer1;
- StrictMock<mock::Layer> mLayer2;
- StrictMock<mock::Layer> mLayer3;
-
- StrictMock<mock::LayerFE> mLayer1FE;
- StrictMock<mock::LayerFE> mLayer2FE;
- StrictMock<mock::LayerFE> mLayer3FE;
-
- LayerFECompositionState mLayer1FEState;
- LayerFECompositionState mLayer2FEState;
- LayerFECompositionState mLayer3FEState;
-};
-
const Rect OutputTest::kDefaultDisplaySize{100, 200};
using ColorProfile = compositionengine::Output::ColorProfile;
@@ -503,11 +494,18 @@
EXPECT_FALSE(mOutput->belongsInOutput(layerStack2, false));
}
-TEST_F(OutputTest, belongsInOutputFiltersLayersAsExpected) {
- StrictMock<mock::Layer> layer;
- LayerFECompositionState layerFEState;
+TEST_F(OutputTest, belongsInOutputHandlesLayerWithNoCompositionState) {
+ NonInjectedLayer layer;
+ sp<LayerFE> layerFE(layer.layerFE);
- EXPECT_CALL(layer, getFEState()).WillRepeatedly(ReturnRef(layerFEState));
+ // If the layer has no composition state, it does not belong to any output.
+ EXPECT_CALL(*layer.layerFE, getCompositionState).WillOnce(Return(nullptr));
+ EXPECT_FALSE(mOutput->belongsInOutput(layerFE));
+}
+
+TEST_F(OutputTest, belongsInOutputFiltersLayersAsExpected) {
+ NonInjectedLayer layer;
+ sp<LayerFE> layerFE(layer.layerFE);
const uint32_t layerStack1 = 123u;
const uint32_t layerStack2 = 456u;
@@ -515,57 +513,51 @@
// If the output accepts layerStack1 and internal-only layers....
mOutput->setLayerStackFilter(layerStack1, true);
- // A null layer pointer does not belong to the output
- EXPECT_FALSE(mOutput->belongsInOutput(nullptr));
-
// A layer with no layerStack does not belong to it, internal-only or not.
- layerFEState.layerStackId = std::nullopt;
- layerFEState.internalOnly = false;
- EXPECT_FALSE(mOutput->belongsInOutput(&layer));
+ layer.layerFEState.layerStackId = std::nullopt;
+ layer.layerFEState.internalOnly = false;
+ EXPECT_FALSE(mOutput->belongsInOutput(layerFE));
- layerFEState.layerStackId = std::nullopt;
- layerFEState.internalOnly = true;
- EXPECT_FALSE(mOutput->belongsInOutput(&layer));
+ layer.layerFEState.layerStackId = std::nullopt;
+ layer.layerFEState.internalOnly = true;
+ EXPECT_FALSE(mOutput->belongsInOutput(layerFE));
// Any layer with layerStack1 belongs to it, internal-only or not.
- layerFEState.layerStackId = layerStack1;
- layerFEState.internalOnly = false;
- EXPECT_TRUE(mOutput->belongsInOutput(&layer));
+ layer.layerFEState.layerStackId = layerStack1;
+ layer.layerFEState.internalOnly = false;
+ EXPECT_TRUE(mOutput->belongsInOutput(layerFE));
- layerFEState.layerStackId = layerStack1;
- layerFEState.internalOnly = true;
- EXPECT_TRUE(mOutput->belongsInOutput(&layer));
+ layer.layerFEState.layerStackId = layerStack1;
+ layer.layerFEState.internalOnly = true;
+ EXPECT_TRUE(mOutput->belongsInOutput(layerFE));
- layerFEState.layerStackId = layerStack2;
- layerFEState.internalOnly = true;
- EXPECT_FALSE(mOutput->belongsInOutput(&layer));
+ layer.layerFEState.layerStackId = layerStack2;
+ layer.layerFEState.internalOnly = true;
+ EXPECT_FALSE(mOutput->belongsInOutput(layerFE));
- layerFEState.layerStackId = layerStack2;
- layerFEState.internalOnly = false;
- EXPECT_FALSE(mOutput->belongsInOutput(&layer));
+ layer.layerFEState.layerStackId = layerStack2;
+ layer.layerFEState.internalOnly = false;
+ EXPECT_FALSE(mOutput->belongsInOutput(layerFE));
// If the output accepts layerStack1 but not internal-only layers...
mOutput->setLayerStackFilter(layerStack1, false);
- // A null layer pointer does not belong to the output
- EXPECT_FALSE(mOutput->belongsInOutput(nullptr));
-
// Only non-internal layers with layerStack1 belong to it.
- layerFEState.layerStackId = layerStack1;
- layerFEState.internalOnly = false;
- EXPECT_TRUE(mOutput->belongsInOutput(&layer));
+ layer.layerFEState.layerStackId = layerStack1;
+ layer.layerFEState.internalOnly = false;
+ EXPECT_TRUE(mOutput->belongsInOutput(layerFE));
- layerFEState.layerStackId = layerStack1;
- layerFEState.internalOnly = true;
- EXPECT_FALSE(mOutput->belongsInOutput(&layer));
+ layer.layerFEState.layerStackId = layerStack1;
+ layer.layerFEState.internalOnly = true;
+ EXPECT_FALSE(mOutput->belongsInOutput(layerFE));
- layerFEState.layerStackId = layerStack2;
- layerFEState.internalOnly = true;
- EXPECT_FALSE(mOutput->belongsInOutput(&layer));
+ layer.layerFEState.layerStackId = layerStack2;
+ layer.layerFEState.internalOnly = true;
+ EXPECT_FALSE(mOutput->belongsInOutput(layerFE));
- layerFEState.layerStackId = layerStack2;
- layerFEState.internalOnly = false;
- EXPECT_FALSE(mOutput->belongsInOutput(&layer));
+ layer.layerFEState.layerStackId = layerStack2;
+ layer.layerFEState.internalOnly = false;
+ EXPECT_FALSE(mOutput->belongsInOutput(layerFE));
}
/*
@@ -573,29 +565,27 @@
*/
TEST_F(OutputTest, getOutputLayerForLayerWorks) {
- mock::OutputLayer* outputLayer1 = new StrictMock<mock::OutputLayer>();
- mock::OutputLayer* outputLayer2 = new StrictMock<mock::OutputLayer>();
+ InjectedLayer layer1;
+ InjectedLayer layer2;
+ NonInjectedLayer layer3;
- mOutput->injectOutputLayerForTest(std::unique_ptr<OutputLayer>(outputLayer1));
- mOutput->injectOutputLayerForTest(nullptr);
- mOutput->injectOutputLayerForTest(std::unique_ptr<OutputLayer>(outputLayer2));
-
- StrictMock<mock::Layer> layer;
- StrictMock<mock::Layer> otherLayer;
+ injectOutputLayer(layer1);
+ injectNullOutputLayer();
+ injectOutputLayer(layer2);
// If the input layer matches the first OutputLayer, it will be returned.
- EXPECT_CALL(*outputLayer1, getLayer()).WillOnce(ReturnRef(layer));
- EXPECT_EQ(outputLayer1, mOutput->getOutputLayerForLayer(&layer));
+ EXPECT_CALL(*layer1.outputLayer, getLayerFE()).WillOnce(ReturnRef(*layer1.layerFE.get()));
+ EXPECT_EQ(layer1.outputLayer, mOutput->getOutputLayerForLayer(layer1.layerFE));
// If the input layer matches the second OutputLayer, it will be returned.
- EXPECT_CALL(*outputLayer1, getLayer()).WillOnce(ReturnRef(otherLayer));
- EXPECT_CALL(*outputLayer2, getLayer()).WillOnce(ReturnRef(layer));
- EXPECT_EQ(outputLayer2, mOutput->getOutputLayerForLayer(&layer));
+ EXPECT_CALL(*layer1.outputLayer, getLayerFE()).WillOnce(ReturnRef(*layer1.layerFE.get()));
+ EXPECT_CALL(*layer2.outputLayer, getLayerFE()).WillOnce(ReturnRef(*layer2.layerFE.get()));
+ EXPECT_EQ(layer2.outputLayer, mOutput->getOutputLayerForLayer(layer2.layerFE));
// If the input layer does not match an output layer, null will be returned.
- EXPECT_CALL(*outputLayer1, getLayer()).WillOnce(ReturnRef(otherLayer));
- EXPECT_CALL(*outputLayer2, getLayer()).WillOnce(ReturnRef(otherLayer));
- EXPECT_EQ(nullptr, mOutput->getOutputLayerForLayer(&layer));
+ EXPECT_CALL(*layer1.outputLayer, getLayerFE()).WillOnce(ReturnRef(*layer1.layerFE.get()));
+ EXPECT_CALL(*layer2.outputLayer, getLayerFE()).WillOnce(ReturnRef(*layer2.layerFE.get()));
+ EXPECT_EQ(nullptr, mOutput->getOutputLayerForLayer(layer3.layerFE));
}
/*
@@ -627,7 +617,7 @@
* Output::updateLayerStateFromFE()
*/
-using OutputUpdateLayerStateFromFETest = OutputLatchFEStateTest;
+using OutputUpdateLayerStateFromFETest = OutputTest;
TEST_F(OutputUpdateLayerStateFromFETest, handlesNoOutputLayerCase) {
CompositionRefreshArgs refreshArgs;
@@ -635,18 +625,18 @@
mOutput->updateLayerStateFromFE(refreshArgs);
}
-TEST_F(OutputUpdateLayerStateFromFETest, latchesContentStateForAllContainedLayers) {
- EXPECT_CALL(mLayer1FE,
- latchCompositionState(Ref(mLayer1FEState), LayerFE::StateSubset::Content));
- EXPECT_CALL(mLayer2FE,
- latchCompositionState(Ref(mLayer2FEState), LayerFE::StateSubset::Content));
- EXPECT_CALL(mLayer3FE,
- latchCompositionState(Ref(mLayer3FEState), LayerFE::StateSubset::Content));
+TEST_F(OutputUpdateLayerStateFromFETest, preparesContentStateForAllContainedLayers) {
+ InjectedLayer layer1;
+ InjectedLayer layer2;
+ InjectedLayer layer3;
- // Note: Must be performed after any expectations on these mocks
- injectLayer(std::move(mOutputLayer1));
- injectLayer(std::move(mOutputLayer2));
- injectLayer(std::move(mOutputLayer3));
+ EXPECT_CALL(*layer1.layerFE.get(), prepareCompositionState(LayerFE::StateSubset::Content));
+ EXPECT_CALL(*layer2.layerFE.get(), prepareCompositionState(LayerFE::StateSubset::Content));
+ EXPECT_CALL(*layer3.layerFE.get(), prepareCompositionState(LayerFE::StateSubset::Content));
+
+ injectOutputLayer(layer1);
+ injectOutputLayer(layer2);
+ injectOutputLayer(layer3);
CompositionRefreshArgs refreshArgs;
refreshArgs.updatingGeometryThisFrame = false;
@@ -654,21 +644,18 @@
mOutput->updateLayerStateFromFE(refreshArgs);
}
-TEST_F(OutputUpdateLayerStateFromFETest, latchesGeometryAndContentStateForAllContainedLayers) {
- EXPECT_CALL(mLayer1FE,
- latchCompositionState(Ref(mLayer1FEState),
- LayerFE::StateSubset::GeometryAndContent));
- EXPECT_CALL(mLayer2FE,
- latchCompositionState(Ref(mLayer2FEState),
- LayerFE::StateSubset::GeometryAndContent));
- EXPECT_CALL(mLayer3FE,
- latchCompositionState(Ref(mLayer3FEState),
- LayerFE::StateSubset::GeometryAndContent));
+TEST_F(OutputUpdateLayerStateFromFETest, preparesGeometryAndContentStateForAllContainedLayers) {
+ InjectedLayer layer1;
+ InjectedLayer layer2;
+ InjectedLayer layer3;
- // Note: Must be performed after any expectations on these mocks
- injectLayer(std::move(mOutputLayer1));
- injectLayer(std::move(mOutputLayer2));
- injectLayer(std::move(mOutputLayer3));
+ EXPECT_CALL(*layer1.layerFE, prepareCompositionState(LayerFE::StateSubset::GeometryAndContent));
+ EXPECT_CALL(*layer2.layerFE, prepareCompositionState(LayerFE::StateSubset::GeometryAndContent));
+ EXPECT_CALL(*layer3.layerFE, prepareCompositionState(LayerFE::StateSubset::GeometryAndContent));
+
+ injectOutputLayer(layer1);
+ injectOutputLayer(layer2);
+ injectOutputLayer(layer3);
CompositionRefreshArgs refreshArgs;
refreshArgs.updatingGeometryThisFrame = true;
@@ -680,7 +667,7 @@
* Output::updateAndWriteCompositionState()
*/
-using OutputUpdateAndWriteCompositionStateTest = OutputLatchFEStateTest;
+using OutputUpdateAndWriteCompositionStateTest = OutputTest;
TEST_F(OutputUpdateAndWriteCompositionStateTest, doesNothingIfLayers) {
mOutput->editState().isEnabled = true;
@@ -690,27 +677,35 @@
}
TEST_F(OutputUpdateAndWriteCompositionStateTest, doesNothingIfOutputNotEnabled) {
+ InjectedLayer layer1;
+ InjectedLayer layer2;
+ InjectedLayer layer3;
+
mOutput->editState().isEnabled = false;
- injectLayer(std::move(mOutputLayer1));
- injectLayer(std::move(mOutputLayer2));
- injectLayer(std::move(mOutputLayer3));
+ injectOutputLayer(layer1);
+ injectOutputLayer(layer2);
+ injectOutputLayer(layer3);
CompositionRefreshArgs args;
mOutput->updateAndWriteCompositionState(args);
}
TEST_F(OutputUpdateAndWriteCompositionStateTest, updatesLayerContentForAllLayers) {
- EXPECT_CALL(*mOutputLayer1, updateCompositionState(false, false));
- EXPECT_CALL(*mOutputLayer1, writeStateToHWC(false));
- EXPECT_CALL(*mOutputLayer2, updateCompositionState(false, false));
- EXPECT_CALL(*mOutputLayer2, writeStateToHWC(false));
- EXPECT_CALL(*mOutputLayer3, updateCompositionState(false, false));
- EXPECT_CALL(*mOutputLayer3, writeStateToHWC(false));
+ InjectedLayer layer1;
+ InjectedLayer layer2;
+ InjectedLayer layer3;
- injectLayer(std::move(mOutputLayer1));
- injectLayer(std::move(mOutputLayer2));
- injectLayer(std::move(mOutputLayer3));
+ EXPECT_CALL(*layer1.outputLayer, updateCompositionState(false, false));
+ EXPECT_CALL(*layer1.outputLayer, writeStateToHWC(false));
+ EXPECT_CALL(*layer2.outputLayer, updateCompositionState(false, false));
+ EXPECT_CALL(*layer2.outputLayer, writeStateToHWC(false));
+ EXPECT_CALL(*layer3.outputLayer, updateCompositionState(false, false));
+ EXPECT_CALL(*layer3.outputLayer, writeStateToHWC(false));
+
+ injectOutputLayer(layer1);
+ injectOutputLayer(layer2);
+ injectOutputLayer(layer3);
mOutput->editState().isEnabled = true;
@@ -721,16 +716,20 @@
}
TEST_F(OutputUpdateAndWriteCompositionStateTest, updatesLayerGeometryAndContentForAllLayers) {
- EXPECT_CALL(*mOutputLayer1, updateCompositionState(true, false));
- EXPECT_CALL(*mOutputLayer1, writeStateToHWC(true));
- EXPECT_CALL(*mOutputLayer2, updateCompositionState(true, false));
- EXPECT_CALL(*mOutputLayer2, writeStateToHWC(true));
- EXPECT_CALL(*mOutputLayer3, updateCompositionState(true, false));
- EXPECT_CALL(*mOutputLayer3, writeStateToHWC(true));
+ InjectedLayer layer1;
+ InjectedLayer layer2;
+ InjectedLayer layer3;
- injectLayer(std::move(mOutputLayer1));
- injectLayer(std::move(mOutputLayer2));
- injectLayer(std::move(mOutputLayer3));
+ EXPECT_CALL(*layer1.outputLayer, updateCompositionState(true, false));
+ EXPECT_CALL(*layer1.outputLayer, writeStateToHWC(true));
+ EXPECT_CALL(*layer2.outputLayer, updateCompositionState(true, false));
+ EXPECT_CALL(*layer2.outputLayer, writeStateToHWC(true));
+ EXPECT_CALL(*layer3.outputLayer, updateCompositionState(true, false));
+ EXPECT_CALL(*layer3.outputLayer, writeStateToHWC(true));
+
+ injectOutputLayer(layer1);
+ injectOutputLayer(layer2);
+ injectOutputLayer(layer3);
mOutput->editState().isEnabled = true;
@@ -741,16 +740,20 @@
}
TEST_F(OutputUpdateAndWriteCompositionStateTest, forcesClientCompositionForAllLayers) {
- EXPECT_CALL(*mOutputLayer1, updateCompositionState(false, true));
- EXPECT_CALL(*mOutputLayer1, writeStateToHWC(false));
- EXPECT_CALL(*mOutputLayer2, updateCompositionState(false, true));
- EXPECT_CALL(*mOutputLayer2, writeStateToHWC(false));
- EXPECT_CALL(*mOutputLayer3, updateCompositionState(false, true));
- EXPECT_CALL(*mOutputLayer3, writeStateToHWC(false));
+ InjectedLayer layer1;
+ InjectedLayer layer2;
+ InjectedLayer layer3;
- injectLayer(std::move(mOutputLayer1));
- injectLayer(std::move(mOutputLayer2));
- injectLayer(std::move(mOutputLayer3));
+ EXPECT_CALL(*layer1.outputLayer, updateCompositionState(false, true));
+ EXPECT_CALL(*layer1.outputLayer, writeStateToHWC(false));
+ EXPECT_CALL(*layer2.outputLayer, updateCompositionState(false, true));
+ EXPECT_CALL(*layer2.outputLayer, writeStateToHWC(false));
+ EXPECT_CALL(*layer3.outputLayer, updateCompositionState(false, true));
+ EXPECT_CALL(*layer3.outputLayer, writeStateToHWC(false));
+
+ injectOutputLayer(layer1);
+ injectOutputLayer(layer2);
+ injectOutputLayer(layer3);
mOutput->editState().isEnabled = true;
@@ -972,7 +975,7 @@
// Sets up the helper functions called by the function under test to use
// mock implementations.
MOCK_METHOD2(ensureOutputLayerIfVisible,
- void(std::shared_ptr<compositionengine::Layer>,
+ void(sp<compositionengine::LayerFE>&,
compositionengine::Output::CoverageState&));
MOCK_METHOD1(setReleasedLayers, void(const compositionengine::CompositionRefreshArgs&));
MOCK_METHOD0(finalizePendingOutputLayers, void());
@@ -985,8 +988,8 @@
}
StrictMock<mock::OutputLayer> outputLayer;
- std::shared_ptr<StrictMock<mock::Layer>> layer{new StrictMock<mock::Layer>()};
impl::OutputLayerCompositionState outputLayerState;
+ sp<StrictMock<mock::LayerFE>> layerFE{new StrictMock<mock::LayerFE>()};
};
OutputCollectVisibleLayersTest() {
@@ -998,9 +1001,9 @@
EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(2))
.WillRepeatedly(Return(&mLayer3.outputLayer));
- mRefreshArgs.layers.push_back(mLayer1.layer);
- mRefreshArgs.layers.push_back(mLayer2.layer);
- mRefreshArgs.layers.push_back(mLayer3.layer);
+ mRefreshArgs.layers.push_back(mLayer1.layerFE);
+ mRefreshArgs.layers.push_back(mLayer2.layerFE);
+ mRefreshArgs.layers.push_back(mLayer3.layerFE);
}
StrictMock<OutputPartialMock> mOutput;
@@ -1027,9 +1030,9 @@
InSequence seq;
// Layer coverage is evaluated from front to back!
- EXPECT_CALL(mOutput, ensureOutputLayerIfVisible(Eq(mLayer3.layer), Ref(mCoverageState)));
- EXPECT_CALL(mOutput, ensureOutputLayerIfVisible(Eq(mLayer2.layer), Ref(mCoverageState)));
- EXPECT_CALL(mOutput, ensureOutputLayerIfVisible(Eq(mLayer1.layer), Ref(mCoverageState)));
+ EXPECT_CALL(mOutput, ensureOutputLayerIfVisible(Eq(mLayer3.layerFE), Ref(mCoverageState)));
+ EXPECT_CALL(mOutput, ensureOutputLayerIfVisible(Eq(mLayer2.layerFE), Ref(mCoverageState)));
+ EXPECT_CALL(mOutput, ensureOutputLayerIfVisible(Eq(mLayer1.layerFE), Ref(mCoverageState)));
EXPECT_CALL(mOutput, setReleasedLayers(Ref(mRefreshArgs)));
EXPECT_CALL(mOutput, finalizePendingOutputLayers());
@@ -1050,43 +1053,39 @@
struct OutputPartialMock : public OutputPartialMockBase {
// Sets up the helper functions called by the function under test to use
// mock implementations.
- MOCK_CONST_METHOD1(belongsInOutput, bool(const compositionengine::Layer*));
+ MOCK_CONST_METHOD1(belongsInOutput, bool(const sp<compositionengine::LayerFE>&));
MOCK_CONST_METHOD1(getOutputLayerOrderedByZByIndex, OutputLayer*(size_t));
- MOCK_METHOD3(ensureOutputLayer,
- compositionengine::OutputLayer*(
- std::optional<size_t>,
- const std::shared_ptr<compositionengine::Layer>&, const sp<LayerFE>&));
+ MOCK_METHOD2(ensureOutputLayer,
+ compositionengine::OutputLayer*(std::optional<size_t>, const sp<LayerFE>&));
};
OutputEnsureOutputLayerIfVisibleTest() {
- EXPECT_CALL(*mLayer, getLayerFE()).WillRepeatedly(Return(mLayerFE));
- EXPECT_CALL(*mLayer, getFEState()).WillRepeatedly(ReturnRef(mLayerFEState));
- EXPECT_CALL(*mLayer, editFEState()).WillRepeatedly(ReturnRef(mLayerFEState));
-
- EXPECT_CALL(mOutput, belongsInOutput(mLayer.get())).WillRepeatedly(Return(true));
+ EXPECT_CALL(mOutput, belongsInOutput(sp<LayerFE>(mLayer.layerFE)))
+ .WillRepeatedly(Return(true));
EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(1u));
EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0u))
- .WillRepeatedly(Return(&mOutputLayer));
-
- EXPECT_CALL(mOutputLayer, getState()).WillRepeatedly(ReturnRef(mOutputLayerState));
- EXPECT_CALL(mOutputLayer, editState()).WillRepeatedly(ReturnRef(mOutputLayerState));
- EXPECT_CALL(mOutputLayer, getLayer()).WillRepeatedly(ReturnRef(*mLayer.get()));
+ .WillRepeatedly(Return(&mLayer.outputLayer));
mOutput.mState.bounds = Rect(0, 0, 200, 300);
mOutput.mState.viewport = Rect(0, 0, 200, 300);
mOutput.mState.transform = ui::Transform(TR_IDENT, 200, 300);
- mLayerFEState.isVisible = true;
- mLayerFEState.isOpaque = true;
- mLayerFEState.contentDirty = true;
- mLayerFEState.geomLayerBounds = FloatRect{0, 0, 100, 200};
- mLayerFEState.geomLayerTransform = ui::Transform(TR_IDENT, 100, 200);
- mLayerFEState.transparentRegionHint = Region(Rect(0, 0, 100, 100));
+ mLayer.layerFEState.isVisible = true;
+ mLayer.layerFEState.isOpaque = true;
+ mLayer.layerFEState.contentDirty = true;
+ mLayer.layerFEState.geomLayerBounds = FloatRect{0, 0, 100, 200};
+ mLayer.layerFEState.geomLayerTransform = ui::Transform(TR_IDENT, 100, 200);
+ mLayer.layerFEState.transparentRegionHint = Region(Rect(0, 0, 100, 100));
- mOutputLayerState.visibleRegion = Region(Rect(0, 0, 50, 200));
- mOutputLayerState.coveredRegion = Region(Rect(50, 0, 100, 200));
+ mLayer.outputLayerState.visibleRegion = Region(Rect(0, 0, 50, 200));
+ mLayer.outputLayerState.coveredRegion = Region(Rect(50, 0, 100, 200));
- mGeomSnapshots.insert(mLayerFE);
+ mGeomSnapshots.insert(mLayer.layerFE);
+ }
+
+ void ensureOutputLayerIfVisible() {
+ sp<LayerFE> layerFE(mLayer.layerFE);
+ mOutput.ensureOutputLayerIfVisible(layerFE, mCoverageState);
}
static const Region kEmptyRegion;
@@ -1099,11 +1098,7 @@
LayerFESet mGeomSnapshots;
Output::CoverageState mCoverageState{mGeomSnapshots};
- std::shared_ptr<mock::Layer> mLayer{new StrictMock<mock::Layer>()};
- sp<StrictMock<mock::LayerFE>> mLayerFE{new StrictMock<mock::LayerFE>()};
- LayerFECompositionState mLayerFEState;
- mock::OutputLayer mOutputLayer;
- impl::OutputLayerCompositionState mOutputLayerState;
+ NonInjectedLayer mLayer;
};
const Region OutputEnsureOutputLayerIfVisibleTest::kEmptyRegion = Region(Rect(0, 0, 0, 0));
@@ -1116,275 +1111,282 @@
const Region OutputEnsureOutputLayerIfVisibleTest::kFullBounds90Rotation =
Region(Rect(0, 0, 200, 100));
-TEST_F(OutputEnsureOutputLayerIfVisibleTest, doesNothingIfNoLayerFE) {
- EXPECT_CALL(*mLayer, getLayerFE).WillOnce(Return(sp<LayerFE>()));
-
- mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
-}
-
TEST_F(OutputEnsureOutputLayerIfVisibleTest, performsGeomLatchBeforeCheckingIfLayerBelongs) {
- EXPECT_CALL(mOutput, belongsInOutput(mLayer.get())).WillOnce(Return(false));
- EXPECT_CALL(*mLayerFE.get(),
- latchCompositionState(Ref(mLayerFEState),
- compositionengine::LayerFE::StateSubset::BasicGeometry));
+ EXPECT_CALL(mOutput, belongsInOutput(sp<LayerFE>(mLayer.layerFE))).WillOnce(Return(false));
+ EXPECT_CALL(*mLayer.layerFE,
+ prepareCompositionState(compositionengine::LayerFE::StateSubset::BasicGeometry));
mGeomSnapshots.clear();
- mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
+ ensureOutputLayerIfVisible();
}
TEST_F(OutputEnsureOutputLayerIfVisibleTest,
skipsLatchIfAlreadyLatchedBeforeCheckingIfLayerBelongs) {
- EXPECT_CALL(mOutput, belongsInOutput(mLayer.get())).WillOnce(Return(false));
+ EXPECT_CALL(mOutput, belongsInOutput(sp<LayerFE>(mLayer.layerFE))).WillOnce(Return(false));
- mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
+ ensureOutputLayerIfVisible();
+}
+
+TEST_F(OutputEnsureOutputLayerIfVisibleTest, takesEarlyOutIfLayerHasNoCompositionState) {
+ EXPECT_CALL(*mLayer.layerFE, getCompositionState()).WillOnce(Return(nullptr));
+
+ ensureOutputLayerIfVisible();
}
TEST_F(OutputEnsureOutputLayerIfVisibleTest, takesEarlyOutIfLayerNotVisible) {
- mLayerFEState.isVisible = false;
+ mLayer.layerFEState.isVisible = false;
- mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
+ ensureOutputLayerIfVisible();
}
TEST_F(OutputEnsureOutputLayerIfVisibleTest, takesEarlyOutIfLayerHasEmptyVisibleRegion) {
- mLayerFEState.geomLayerBounds = FloatRect{0, 0, 0, 0};
+ mLayer.layerFEState.geomLayerBounds = FloatRect{0, 0, 0, 0};
- mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
+ ensureOutputLayerIfVisible();
}
TEST_F(OutputEnsureOutputLayerIfVisibleTest, takesNotSoEarlyOutifDrawRegionEmpty) {
mOutput.mState.bounds = Rect(0, 0, 0, 0);
- mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
+ ensureOutputLayerIfVisible();
}
TEST_F(OutputEnsureOutputLayerIfVisibleTest,
handlesCreatingOutputLayerForOpaqueDirtyNotRotatedLayer) {
- mLayerFEState.isOpaque = true;
- mLayerFEState.contentDirty = true;
- mLayerFEState.geomLayerTransform = ui::Transform(TR_IDENT, 100, 200);
+ mLayer.layerFEState.isOpaque = true;
+ mLayer.layerFEState.contentDirty = true;
+ mLayer.layerFEState.geomLayerTransform = ui::Transform(TR_IDENT, 100, 200);
EXPECT_CALL(mOutput, getOutputLayerCount()).WillOnce(Return(0u));
- EXPECT_CALL(mOutput, ensureOutputLayer(Eq(std::nullopt), Eq(mLayer), Eq(mLayerFE)))
- .WillOnce(Return(&mOutputLayer));
+ EXPECT_CALL(mOutput, ensureOutputLayer(Eq(std::nullopt), Eq(mLayer.layerFE)))
+ .WillOnce(Return(&mLayer.outputLayer));
- mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
+ ensureOutputLayerIfVisible();
EXPECT_THAT(mCoverageState.dirtyRegion, RegionEq(kFullBoundsNoRotation));
EXPECT_THAT(mCoverageState.aboveCoveredLayers, RegionEq(kFullBoundsNoRotation));
EXPECT_THAT(mCoverageState.aboveOpaqueLayers, RegionEq(kFullBoundsNoRotation));
- EXPECT_THAT(mOutputLayerState.visibleRegion, RegionEq(kFullBoundsNoRotation));
- EXPECT_THAT(mOutputLayerState.visibleNonTransparentRegion, RegionEq(kFullBoundsNoRotation));
- EXPECT_THAT(mOutputLayerState.coveredRegion, RegionEq(kEmptyRegion));
- EXPECT_THAT(mOutputLayerState.outputSpaceVisibleRegion, RegionEq(kFullBoundsNoRotation));
+ EXPECT_THAT(mLayer.outputLayerState.visibleRegion, RegionEq(kFullBoundsNoRotation));
+ EXPECT_THAT(mLayer.outputLayerState.visibleNonTransparentRegion,
+ RegionEq(kFullBoundsNoRotation));
+ EXPECT_THAT(mLayer.outputLayerState.coveredRegion, RegionEq(kEmptyRegion));
+ EXPECT_THAT(mLayer.outputLayerState.outputSpaceVisibleRegion, RegionEq(kFullBoundsNoRotation));
}
TEST_F(OutputEnsureOutputLayerIfVisibleTest,
handlesUpdatingOutputLayerForOpaqueDirtyNotRotatedLayer) {
- mLayerFEState.isOpaque = true;
- mLayerFEState.contentDirty = true;
- mLayerFEState.geomLayerTransform = ui::Transform(TR_IDENT, 100, 200);
+ mLayer.layerFEState.isOpaque = true;
+ mLayer.layerFEState.contentDirty = true;
+ mLayer.layerFEState.geomLayerTransform = ui::Transform(TR_IDENT, 100, 200);
- EXPECT_CALL(mOutput, ensureOutputLayer(Eq(0u), Eq(mLayer), Eq(mLayerFE)))
- .WillOnce(Return(&mOutputLayer));
+ EXPECT_CALL(mOutput, ensureOutputLayer(Eq(0u), Eq(mLayer.layerFE)))
+ .WillOnce(Return(&mLayer.outputLayer));
- mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
+ ensureOutputLayerIfVisible();
EXPECT_THAT(mCoverageState.dirtyRegion, RegionEq(kFullBoundsNoRotation));
EXPECT_THAT(mCoverageState.aboveCoveredLayers, RegionEq(kFullBoundsNoRotation));
EXPECT_THAT(mCoverageState.aboveOpaqueLayers, RegionEq(kFullBoundsNoRotation));
- EXPECT_THAT(mOutputLayerState.visibleRegion, RegionEq(kFullBoundsNoRotation));
- EXPECT_THAT(mOutputLayerState.visibleNonTransparentRegion, RegionEq(kFullBoundsNoRotation));
- EXPECT_THAT(mOutputLayerState.coveredRegion, RegionEq(kEmptyRegion));
- EXPECT_THAT(mOutputLayerState.outputSpaceVisibleRegion, RegionEq(kFullBoundsNoRotation));
+ EXPECT_THAT(mLayer.outputLayerState.visibleRegion, RegionEq(kFullBoundsNoRotation));
+ EXPECT_THAT(mLayer.outputLayerState.visibleNonTransparentRegion,
+ RegionEq(kFullBoundsNoRotation));
+ EXPECT_THAT(mLayer.outputLayerState.coveredRegion, RegionEq(kEmptyRegion));
+ EXPECT_THAT(mLayer.outputLayerState.outputSpaceVisibleRegion, RegionEq(kFullBoundsNoRotation));
}
TEST_F(OutputEnsureOutputLayerIfVisibleTest,
handlesCreatingOutputLayerForTransparentDirtyNotRotatedLayer) {
- mLayerFEState.isOpaque = false;
- mLayerFEState.contentDirty = true;
- mLayerFEState.geomLayerTransform = ui::Transform(TR_IDENT, 100, 200);
+ mLayer.layerFEState.isOpaque = false;
+ mLayer.layerFEState.contentDirty = true;
+ mLayer.layerFEState.geomLayerTransform = ui::Transform(TR_IDENT, 100, 200);
EXPECT_CALL(mOutput, getOutputLayerCount()).WillOnce(Return(0u));
- EXPECT_CALL(mOutput, ensureOutputLayer(Eq(std::nullopt), Eq(mLayer), Eq(mLayerFE)))
- .WillOnce(Return(&mOutputLayer));
+ EXPECT_CALL(mOutput, ensureOutputLayer(Eq(std::nullopt), Eq(mLayer.layerFE)))
+ .WillOnce(Return(&mLayer.outputLayer));
- mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
+ ensureOutputLayerIfVisible();
EXPECT_THAT(mCoverageState.dirtyRegion, RegionEq(kFullBoundsNoRotation));
EXPECT_THAT(mCoverageState.aboveCoveredLayers, RegionEq(kFullBoundsNoRotation));
EXPECT_THAT(mCoverageState.aboveOpaqueLayers, RegionEq(kEmptyRegion));
- EXPECT_THAT(mOutputLayerState.visibleRegion, RegionEq(kFullBoundsNoRotation));
- EXPECT_THAT(mOutputLayerState.visibleNonTransparentRegion,
+ EXPECT_THAT(mLayer.outputLayerState.visibleRegion, RegionEq(kFullBoundsNoRotation));
+ EXPECT_THAT(mLayer.outputLayerState.visibleNonTransparentRegion,
RegionEq(kRightHalfBoundsNoRotation));
- EXPECT_THAT(mOutputLayerState.coveredRegion, RegionEq(kEmptyRegion));
- EXPECT_THAT(mOutputLayerState.outputSpaceVisibleRegion, RegionEq(kFullBoundsNoRotation));
+ EXPECT_THAT(mLayer.outputLayerState.coveredRegion, RegionEq(kEmptyRegion));
+ EXPECT_THAT(mLayer.outputLayerState.outputSpaceVisibleRegion, RegionEq(kFullBoundsNoRotation));
}
TEST_F(OutputEnsureOutputLayerIfVisibleTest,
handlesUpdatingOutputLayerForTransparentDirtyNotRotatedLayer) {
- mLayerFEState.isOpaque = false;
- mLayerFEState.contentDirty = true;
- mLayerFEState.geomLayerTransform = ui::Transform(TR_IDENT, 100, 200);
+ mLayer.layerFEState.isOpaque = false;
+ mLayer.layerFEState.contentDirty = true;
+ mLayer.layerFEState.geomLayerTransform = ui::Transform(TR_IDENT, 100, 200);
- EXPECT_CALL(mOutput, ensureOutputLayer(Eq(0u), Eq(mLayer), Eq(mLayerFE)))
- .WillOnce(Return(&mOutputLayer));
+ EXPECT_CALL(mOutput, ensureOutputLayer(Eq(0u), Eq(mLayer.layerFE)))
+ .WillOnce(Return(&mLayer.outputLayer));
- mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
+ ensureOutputLayerIfVisible();
EXPECT_THAT(mCoverageState.dirtyRegion, RegionEq(kFullBoundsNoRotation));
EXPECT_THAT(mCoverageState.aboveCoveredLayers, RegionEq(kFullBoundsNoRotation));
EXPECT_THAT(mCoverageState.aboveOpaqueLayers, RegionEq(kEmptyRegion));
- EXPECT_THAT(mOutputLayerState.visibleRegion, RegionEq(kFullBoundsNoRotation));
- EXPECT_THAT(mOutputLayerState.visibleNonTransparentRegion,
+ EXPECT_THAT(mLayer.outputLayerState.visibleRegion, RegionEq(kFullBoundsNoRotation));
+ EXPECT_THAT(mLayer.outputLayerState.visibleNonTransparentRegion,
RegionEq(kRightHalfBoundsNoRotation));
- EXPECT_THAT(mOutputLayerState.coveredRegion, RegionEq(kEmptyRegion));
- EXPECT_THAT(mOutputLayerState.outputSpaceVisibleRegion, RegionEq(kFullBoundsNoRotation));
+ EXPECT_THAT(mLayer.outputLayerState.coveredRegion, RegionEq(kEmptyRegion));
+ EXPECT_THAT(mLayer.outputLayerState.outputSpaceVisibleRegion, RegionEq(kFullBoundsNoRotation));
}
TEST_F(OutputEnsureOutputLayerIfVisibleTest,
handlesCreatingOutputLayerForOpaqueNonDirtyNotRotatedLayer) {
- mLayerFEState.isOpaque = true;
- mLayerFEState.contentDirty = false;
- mLayerFEState.geomLayerTransform = ui::Transform(TR_IDENT, 100, 200);
+ mLayer.layerFEState.isOpaque = true;
+ mLayer.layerFEState.contentDirty = false;
+ mLayer.layerFEState.geomLayerTransform = ui::Transform(TR_IDENT, 100, 200);
EXPECT_CALL(mOutput, getOutputLayerCount()).WillOnce(Return(0u));
- EXPECT_CALL(mOutput, ensureOutputLayer(Eq(std::nullopt), Eq(mLayer), Eq(mLayerFE)))
- .WillOnce(Return(&mOutputLayer));
+ EXPECT_CALL(mOutput, ensureOutputLayer(Eq(std::nullopt), Eq(mLayer.layerFE)))
+ .WillOnce(Return(&mLayer.outputLayer));
- mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
+ ensureOutputLayerIfVisible();
EXPECT_THAT(mCoverageState.dirtyRegion, RegionEq(kFullBoundsNoRotation));
EXPECT_THAT(mCoverageState.aboveCoveredLayers, RegionEq(kFullBoundsNoRotation));
EXPECT_THAT(mCoverageState.aboveOpaqueLayers, RegionEq(kFullBoundsNoRotation));
- EXPECT_THAT(mOutputLayerState.visibleRegion, RegionEq(kFullBoundsNoRotation));
- EXPECT_THAT(mOutputLayerState.visibleNonTransparentRegion, RegionEq(kFullBoundsNoRotation));
- EXPECT_THAT(mOutputLayerState.coveredRegion, RegionEq(kEmptyRegion));
- EXPECT_THAT(mOutputLayerState.outputSpaceVisibleRegion, RegionEq(kFullBoundsNoRotation));
+ EXPECT_THAT(mLayer.outputLayerState.visibleRegion, RegionEq(kFullBoundsNoRotation));
+ EXPECT_THAT(mLayer.outputLayerState.visibleNonTransparentRegion,
+ RegionEq(kFullBoundsNoRotation));
+ EXPECT_THAT(mLayer.outputLayerState.coveredRegion, RegionEq(kEmptyRegion));
+ EXPECT_THAT(mLayer.outputLayerState.outputSpaceVisibleRegion, RegionEq(kFullBoundsNoRotation));
}
TEST_F(OutputEnsureOutputLayerIfVisibleTest,
handlesUpdatingOutputLayerForOpaqueNonDirtyNotRotatedLayer) {
- mLayerFEState.isOpaque = true;
- mLayerFEState.contentDirty = false;
- mLayerFEState.geomLayerTransform = ui::Transform(TR_IDENT, 100, 200);
+ mLayer.layerFEState.isOpaque = true;
+ mLayer.layerFEState.contentDirty = false;
+ mLayer.layerFEState.geomLayerTransform = ui::Transform(TR_IDENT, 100, 200);
- EXPECT_CALL(mOutput, ensureOutputLayer(Eq(0u), Eq(mLayer), Eq(mLayerFE)))
- .WillOnce(Return(&mOutputLayer));
+ EXPECT_CALL(mOutput, ensureOutputLayer(Eq(0u), Eq(mLayer.layerFE)))
+ .WillOnce(Return(&mLayer.outputLayer));
- mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
+ ensureOutputLayerIfVisible();
EXPECT_THAT(mCoverageState.dirtyRegion, RegionEq(kLowerHalfBoundsNoRotation));
EXPECT_THAT(mCoverageState.aboveCoveredLayers, RegionEq(kFullBoundsNoRotation));
EXPECT_THAT(mCoverageState.aboveOpaqueLayers, RegionEq(kFullBoundsNoRotation));
- EXPECT_THAT(mOutputLayerState.visibleRegion, RegionEq(kFullBoundsNoRotation));
- EXPECT_THAT(mOutputLayerState.visibleNonTransparentRegion, RegionEq(kFullBoundsNoRotation));
- EXPECT_THAT(mOutputLayerState.coveredRegion, RegionEq(kEmptyRegion));
- EXPECT_THAT(mOutputLayerState.outputSpaceVisibleRegion, RegionEq(kFullBoundsNoRotation));
+ EXPECT_THAT(mLayer.outputLayerState.visibleRegion, RegionEq(kFullBoundsNoRotation));
+ EXPECT_THAT(mLayer.outputLayerState.visibleNonTransparentRegion,
+ RegionEq(kFullBoundsNoRotation));
+ EXPECT_THAT(mLayer.outputLayerState.coveredRegion, RegionEq(kEmptyRegion));
+ EXPECT_THAT(mLayer.outputLayerState.outputSpaceVisibleRegion, RegionEq(kFullBoundsNoRotation));
}
TEST_F(OutputEnsureOutputLayerIfVisibleTest,
handlesCreatingOutputLayerForOpaqueDirtyRotated90Layer) {
- mLayerFEState.isOpaque = true;
- mLayerFEState.contentDirty = true;
- mLayerFEState.geomLayerBounds = FloatRect{0, 0, 200, 100};
- mLayerFEState.geomLayerTransform = ui::Transform(TR_ROT_90, 100, 200);
- mOutputLayerState.visibleRegion = Region(Rect(0, 0, 100, 100));
- mOutputLayerState.coveredRegion = Region(Rect(100, 0, 200, 100));
+ mLayer.layerFEState.isOpaque = true;
+ mLayer.layerFEState.contentDirty = true;
+ mLayer.layerFEState.geomLayerBounds = FloatRect{0, 0, 200, 100};
+ mLayer.layerFEState.geomLayerTransform = ui::Transform(TR_ROT_90, 100, 200);
+ mLayer.outputLayerState.visibleRegion = Region(Rect(0, 0, 100, 100));
+ mLayer.outputLayerState.coveredRegion = Region(Rect(100, 0, 200, 100));
EXPECT_CALL(mOutput, getOutputLayerCount()).WillOnce(Return(0u));
- EXPECT_CALL(mOutput, ensureOutputLayer(Eq(std::nullopt), Eq(mLayer), Eq(mLayerFE)))
- .WillOnce(Return(&mOutputLayer));
+ EXPECT_CALL(mOutput, ensureOutputLayer(Eq(std::nullopt), Eq(mLayer.layerFE)))
+ .WillOnce(Return(&mLayer.outputLayer));
- mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
+ ensureOutputLayerIfVisible();
EXPECT_THAT(mCoverageState.dirtyRegion, RegionEq(kFullBoundsNoRotation));
EXPECT_THAT(mCoverageState.aboveCoveredLayers, RegionEq(kFullBoundsNoRotation));
EXPECT_THAT(mCoverageState.aboveOpaqueLayers, RegionEq(kFullBoundsNoRotation));
- EXPECT_THAT(mOutputLayerState.visibleRegion, RegionEq(kFullBoundsNoRotation));
- EXPECT_THAT(mOutputLayerState.visibleNonTransparentRegion, RegionEq(kFullBoundsNoRotation));
- EXPECT_THAT(mOutputLayerState.coveredRegion, RegionEq(kEmptyRegion));
- EXPECT_THAT(mOutputLayerState.outputSpaceVisibleRegion, RegionEq(kFullBoundsNoRotation));
+ EXPECT_THAT(mLayer.outputLayerState.visibleRegion, RegionEq(kFullBoundsNoRotation));
+ EXPECT_THAT(mLayer.outputLayerState.visibleNonTransparentRegion,
+ RegionEq(kFullBoundsNoRotation));
+ EXPECT_THAT(mLayer.outputLayerState.coveredRegion, RegionEq(kEmptyRegion));
+ EXPECT_THAT(mLayer.outputLayerState.outputSpaceVisibleRegion, RegionEq(kFullBoundsNoRotation));
}
TEST_F(OutputEnsureOutputLayerIfVisibleTest,
handlesUpdatingOutputLayerForOpaqueDirtyRotated90Layer) {
- mLayerFEState.isOpaque = true;
- mLayerFEState.contentDirty = true;
- mLayerFEState.geomLayerBounds = FloatRect{0, 0, 200, 100};
- mLayerFEState.geomLayerTransform = ui::Transform(TR_ROT_90, 100, 200);
- mOutputLayerState.visibleRegion = Region(Rect(0, 0, 100, 100));
- mOutputLayerState.coveredRegion = Region(Rect(100, 0, 200, 100));
+ mLayer.layerFEState.isOpaque = true;
+ mLayer.layerFEState.contentDirty = true;
+ mLayer.layerFEState.geomLayerBounds = FloatRect{0, 0, 200, 100};
+ mLayer.layerFEState.geomLayerTransform = ui::Transform(TR_ROT_90, 100, 200);
+ mLayer.outputLayerState.visibleRegion = Region(Rect(0, 0, 100, 100));
+ mLayer.outputLayerState.coveredRegion = Region(Rect(100, 0, 200, 100));
- EXPECT_CALL(mOutput, ensureOutputLayer(Eq(0u), Eq(mLayer), Eq(mLayerFE)))
- .WillOnce(Return(&mOutputLayer));
+ EXPECT_CALL(mOutput, ensureOutputLayer(Eq(0u), Eq(mLayer.layerFE)))
+ .WillOnce(Return(&mLayer.outputLayer));
- mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
+ ensureOutputLayerIfVisible();
EXPECT_THAT(mCoverageState.dirtyRegion, RegionEq(kFullBoundsNoRotation));
EXPECT_THAT(mCoverageState.aboveCoveredLayers, RegionEq(kFullBoundsNoRotation));
EXPECT_THAT(mCoverageState.aboveOpaqueLayers, RegionEq(kFullBoundsNoRotation));
- EXPECT_THAT(mOutputLayerState.visibleRegion, RegionEq(kFullBoundsNoRotation));
- EXPECT_THAT(mOutputLayerState.visibleNonTransparentRegion, RegionEq(kFullBoundsNoRotation));
- EXPECT_THAT(mOutputLayerState.coveredRegion, RegionEq(kEmptyRegion));
- EXPECT_THAT(mOutputLayerState.outputSpaceVisibleRegion, RegionEq(kFullBoundsNoRotation));
+ EXPECT_THAT(mLayer.outputLayerState.visibleRegion, RegionEq(kFullBoundsNoRotation));
+ EXPECT_THAT(mLayer.outputLayerState.visibleNonTransparentRegion,
+ RegionEq(kFullBoundsNoRotation));
+ EXPECT_THAT(mLayer.outputLayerState.coveredRegion, RegionEq(kEmptyRegion));
+ EXPECT_THAT(mLayer.outputLayerState.outputSpaceVisibleRegion, RegionEq(kFullBoundsNoRotation));
}
TEST_F(OutputEnsureOutputLayerIfVisibleTest,
handlesCreatingOutputLayerForOpaqueDirtyNotRotatedLayerRotatedOutput) {
- mLayerFEState.isOpaque = true;
- mLayerFEState.contentDirty = true;
- mLayerFEState.geomLayerTransform = ui::Transform(TR_IDENT, 100, 200);
+ mLayer.layerFEState.isOpaque = true;
+ mLayer.layerFEState.contentDirty = true;
+ mLayer.layerFEState.geomLayerTransform = ui::Transform(TR_IDENT, 100, 200);
mOutput.mState.viewport = Rect(0, 0, 300, 200);
mOutput.mState.transform = ui::Transform(TR_ROT_90, 200, 300);
EXPECT_CALL(mOutput, getOutputLayerCount()).WillOnce(Return(0u));
- EXPECT_CALL(mOutput, ensureOutputLayer(Eq(std::nullopt), Eq(mLayer), Eq(mLayerFE)))
- .WillOnce(Return(&mOutputLayer));
+ EXPECT_CALL(mOutput, ensureOutputLayer(Eq(std::nullopt), Eq(mLayer.layerFE)))
+ .WillOnce(Return(&mLayer.outputLayer));
- mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
+ ensureOutputLayerIfVisible();
EXPECT_THAT(mCoverageState.dirtyRegion, RegionEq(kFullBoundsNoRotation));
EXPECT_THAT(mCoverageState.aboveCoveredLayers, RegionEq(kFullBoundsNoRotation));
EXPECT_THAT(mCoverageState.aboveOpaqueLayers, RegionEq(kFullBoundsNoRotation));
- EXPECT_THAT(mOutputLayerState.visibleRegion, RegionEq(kFullBoundsNoRotation));
- EXPECT_THAT(mOutputLayerState.visibleNonTransparentRegion, RegionEq(kFullBoundsNoRotation));
- EXPECT_THAT(mOutputLayerState.coveredRegion, RegionEq(kEmptyRegion));
- EXPECT_THAT(mOutputLayerState.outputSpaceVisibleRegion, RegionEq(kFullBounds90Rotation));
+ EXPECT_THAT(mLayer.outputLayerState.visibleRegion, RegionEq(kFullBoundsNoRotation));
+ EXPECT_THAT(mLayer.outputLayerState.visibleNonTransparentRegion,
+ RegionEq(kFullBoundsNoRotation));
+ EXPECT_THAT(mLayer.outputLayerState.coveredRegion, RegionEq(kEmptyRegion));
+ EXPECT_THAT(mLayer.outputLayerState.outputSpaceVisibleRegion, RegionEq(kFullBounds90Rotation));
}
TEST_F(OutputEnsureOutputLayerIfVisibleTest,
handlesUpdatingOutputLayerForOpaqueDirtyNotRotatedLayerRotatedOutput) {
- mLayerFEState.isOpaque = true;
- mLayerFEState.contentDirty = true;
- mLayerFEState.geomLayerTransform = ui::Transform(TR_IDENT, 100, 200);
+ mLayer.layerFEState.isOpaque = true;
+ mLayer.layerFEState.contentDirty = true;
+ mLayer.layerFEState.geomLayerTransform = ui::Transform(TR_IDENT, 100, 200);
mOutput.mState.viewport = Rect(0, 0, 300, 200);
mOutput.mState.transform = ui::Transform(TR_ROT_90, 200, 300);
- EXPECT_CALL(mOutput, ensureOutputLayer(Eq(0u), Eq(mLayer), Eq(mLayerFE)))
- .WillOnce(Return(&mOutputLayer));
+ EXPECT_CALL(mOutput, ensureOutputLayer(Eq(0u), Eq(mLayer.layerFE)))
+ .WillOnce(Return(&mLayer.outputLayer));
- mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
+ ensureOutputLayerIfVisible();
EXPECT_THAT(mCoverageState.dirtyRegion, RegionEq(kFullBoundsNoRotation));
EXPECT_THAT(mCoverageState.aboveCoveredLayers, RegionEq(kFullBoundsNoRotation));
EXPECT_THAT(mCoverageState.aboveOpaqueLayers, RegionEq(kFullBoundsNoRotation));
- EXPECT_THAT(mOutputLayerState.visibleRegion, RegionEq(kFullBoundsNoRotation));
- EXPECT_THAT(mOutputLayerState.visibleNonTransparentRegion, RegionEq(kFullBoundsNoRotation));
- EXPECT_THAT(mOutputLayerState.coveredRegion, RegionEq(kEmptyRegion));
- EXPECT_THAT(mOutputLayerState.outputSpaceVisibleRegion, RegionEq(kFullBounds90Rotation));
+ EXPECT_THAT(mLayer.outputLayerState.visibleRegion, RegionEq(kFullBoundsNoRotation));
+ EXPECT_THAT(mLayer.outputLayerState.visibleNonTransparentRegion,
+ RegionEq(kFullBoundsNoRotation));
+ EXPECT_THAT(mLayer.outputLayerState.coveredRegion, RegionEq(kEmptyRegion));
+ EXPECT_THAT(mLayer.outputLayerState.outputSpaceVisibleRegion, RegionEq(kFullBounds90Rotation));
}
TEST_F(OutputEnsureOutputLayerIfVisibleTest,
@@ -1393,16 +1395,16 @@
arbitraryTransform.set(1, 1, -1, 1);
arbitraryTransform.set(0, 100);
- mLayerFEState.isOpaque = true;
- mLayerFEState.contentDirty = true;
- mLayerFEState.geomLayerBounds = FloatRect{0, 0, 100, 200};
- mLayerFEState.geomLayerTransform = arbitraryTransform;
+ mLayer.layerFEState.isOpaque = true;
+ mLayer.layerFEState.contentDirty = true;
+ mLayer.layerFEState.geomLayerBounds = FloatRect{0, 0, 100, 200};
+ mLayer.layerFEState.geomLayerTransform = arbitraryTransform;
EXPECT_CALL(mOutput, getOutputLayerCount()).WillOnce(Return(0u));
- EXPECT_CALL(mOutput, ensureOutputLayer(Eq(std::nullopt), Eq(mLayer), Eq(mLayerFE)))
- .WillOnce(Return(&mOutputLayer));
+ EXPECT_CALL(mOutput, ensureOutputLayer(Eq(std::nullopt), Eq(mLayer.layerFE)))
+ .WillOnce(Return(&mLayer.outputLayer));
- mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
+ ensureOutputLayerIfVisible();
const Region kRegion = Region(Rect(0, 0, 300, 300));
const Region kRegionClipped = Region(Rect(0, 0, 200, 300));
@@ -1411,25 +1413,25 @@
EXPECT_THAT(mCoverageState.aboveCoveredLayers, RegionEq(kRegion));
EXPECT_THAT(mCoverageState.aboveOpaqueLayers, RegionEq(kEmptyRegion));
- EXPECT_THAT(mOutputLayerState.visibleRegion, RegionEq(kRegion));
- EXPECT_THAT(mOutputLayerState.visibleNonTransparentRegion, RegionEq(kRegion));
- EXPECT_THAT(mOutputLayerState.coveredRegion, RegionEq(kEmptyRegion));
- EXPECT_THAT(mOutputLayerState.outputSpaceVisibleRegion, RegionEq(kRegionClipped));
+ EXPECT_THAT(mLayer.outputLayerState.visibleRegion, RegionEq(kRegion));
+ EXPECT_THAT(mLayer.outputLayerState.visibleNonTransparentRegion, RegionEq(kRegion));
+ EXPECT_THAT(mLayer.outputLayerState.coveredRegion, RegionEq(kEmptyRegion));
+ EXPECT_THAT(mLayer.outputLayerState.outputSpaceVisibleRegion, RegionEq(kRegionClipped));
}
TEST_F(OutputEnsureOutputLayerIfVisibleTest, coverageAccumulatesTest) {
- mLayerFEState.isOpaque = false;
- mLayerFEState.contentDirty = true;
- mLayerFEState.geomLayerTransform = ui::Transform(TR_IDENT, 100, 200);
+ mLayer.layerFEState.isOpaque = false;
+ mLayer.layerFEState.contentDirty = true;
+ mLayer.layerFEState.geomLayerTransform = ui::Transform(TR_IDENT, 100, 200);
mCoverageState.dirtyRegion = Region(Rect(0, 0, 500, 500));
mCoverageState.aboveCoveredLayers = Region(Rect(50, 0, 150, 200));
mCoverageState.aboveOpaqueLayers = Region(Rect(50, 0, 150, 200));
- EXPECT_CALL(mOutput, ensureOutputLayer(Eq(0u), Eq(mLayer), Eq(mLayerFE)))
- .WillOnce(Return(&mOutputLayer));
+ EXPECT_CALL(mOutput, ensureOutputLayer(Eq(0u), Eq(mLayer.layerFE)))
+ .WillOnce(Return(&mLayer.outputLayer));
- mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
+ ensureOutputLayerIfVisible();
const Region kExpectedDirtyRegion = Region(Rect(0, 0, 500, 500));
const Region kExpectedAboveCoveredRegion = Region(Rect(0, 0, 150, 200));
@@ -1442,28 +1444,29 @@
EXPECT_THAT(mCoverageState.aboveCoveredLayers, RegionEq(kExpectedAboveCoveredRegion));
EXPECT_THAT(mCoverageState.aboveOpaqueLayers, RegionEq(kExpectedAboveOpaqueRegion));
- EXPECT_THAT(mOutputLayerState.visibleRegion, RegionEq(kExpectedLayerVisibleRegion));
- EXPECT_THAT(mOutputLayerState.visibleNonTransparentRegion,
+ EXPECT_THAT(mLayer.outputLayerState.visibleRegion, RegionEq(kExpectedLayerVisibleRegion));
+ EXPECT_THAT(mLayer.outputLayerState.visibleNonTransparentRegion,
RegionEq(kExpectedLayerVisibleNonTransparentRegion));
- EXPECT_THAT(mOutputLayerState.coveredRegion, RegionEq(kExpectedLayerCoveredRegion));
- EXPECT_THAT(mOutputLayerState.outputSpaceVisibleRegion, RegionEq(kExpectedLayerVisibleRegion));
+ EXPECT_THAT(mLayer.outputLayerState.coveredRegion, RegionEq(kExpectedLayerCoveredRegion));
+ EXPECT_THAT(mLayer.outputLayerState.outputSpaceVisibleRegion,
+ RegionEq(kExpectedLayerVisibleRegion));
}
TEST_F(OutputEnsureOutputLayerIfVisibleTest, coverageAccumulatesWithShadowsTest) {
ui::Transform translate;
translate.set(50, 50);
- mLayerFEState.geomLayerTransform = translate;
- mLayerFEState.shadowRadius = 10.0f;
+ mLayer.layerFEState.geomLayerTransform = translate;
+ mLayer.layerFEState.shadowRadius = 10.0f;
mCoverageState.dirtyRegion = Region(Rect(0, 0, 500, 500));
// half of the layer including the casting shadow is covered and opaque
mCoverageState.aboveCoveredLayers = Region(Rect(40, 40, 100, 260));
mCoverageState.aboveOpaqueLayers = Region(Rect(40, 40, 100, 260));
- EXPECT_CALL(mOutput, ensureOutputLayer(Eq(0u), Eq(mLayer), Eq(mLayerFE)))
- .WillOnce(Return(&mOutputLayer));
+ EXPECT_CALL(mOutput, ensureOutputLayer(Eq(0u), Eq(mLayer.layerFE)))
+ .WillOnce(Return(&mLayer.outputLayer));
- mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
+ ensureOutputLayerIfVisible();
const Region kExpectedDirtyRegion = Region(Rect(0, 0, 500, 500));
const Region kExpectedAboveCoveredRegion = Region(Rect(40, 40, 160, 260));
@@ -1481,53 +1484,53 @@
EXPECT_THAT(mCoverageState.aboveCoveredLayers, RegionEq(kExpectedAboveCoveredRegion));
EXPECT_THAT(mCoverageState.aboveOpaqueLayers, RegionEq(kExpectedAboveOpaqueRegion));
- EXPECT_THAT(mOutputLayerState.visibleRegion, RegionEq(kExpectedLayerVisibleRegion));
- EXPECT_THAT(mOutputLayerState.visibleNonTransparentRegion,
+ EXPECT_THAT(mLayer.outputLayerState.visibleRegion, RegionEq(kExpectedLayerVisibleRegion));
+ EXPECT_THAT(mLayer.outputLayerState.visibleNonTransparentRegion,
RegionEq(kExpectedLayerVisibleNonTransparentRegion));
- EXPECT_THAT(mOutputLayerState.coveredRegion, RegionEq(kExpectedLayerCoveredRegion));
- EXPECT_THAT(mOutputLayerState.outputSpaceVisibleRegion,
+ EXPECT_THAT(mLayer.outputLayerState.coveredRegion, RegionEq(kExpectedLayerCoveredRegion));
+ EXPECT_THAT(mLayer.outputLayerState.outputSpaceVisibleRegion,
RegionEq(kExpectedoutputSpaceLayerVisibleRegion));
- EXPECT_THAT(mOutputLayerState.shadowRegion, RegionEq(kExpectedLayerShadowRegion));
+ EXPECT_THAT(mLayer.outputLayerState.shadowRegion, RegionEq(kExpectedLayerShadowRegion));
EXPECT_FALSE(kExpectedLayerVisibleRegion.subtract(kExpectedLayerShadowRegion).isEmpty());
}
TEST_F(OutputEnsureOutputLayerIfVisibleTest, shadowRegionOnlyTest) {
ui::Transform translate;
translate.set(50, 50);
- mLayerFEState.geomLayerTransform = translate;
- mLayerFEState.shadowRadius = 10.0f;
+ mLayer.layerFEState.geomLayerTransform = translate;
+ mLayer.layerFEState.shadowRadius = 10.0f;
mCoverageState.dirtyRegion = Region(Rect(0, 0, 500, 500));
// Casting layer is covered by an opaque region leaving only part of its shadow to be drawn
mCoverageState.aboveCoveredLayers = Region(Rect(40, 40, 150, 260));
mCoverageState.aboveOpaqueLayers = Region(Rect(40, 40, 150, 260));
- EXPECT_CALL(mOutput, ensureOutputLayer(Eq(0u), Eq(mLayer), Eq(mLayerFE)))
- .WillOnce(Return(&mOutputLayer));
+ EXPECT_CALL(mOutput, ensureOutputLayer(Eq(0u), Eq(mLayer.layerFE)))
+ .WillOnce(Return(&mLayer.outputLayer));
- mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
+ ensureOutputLayerIfVisible();
const Region kExpectedLayerVisibleRegion = Region(Rect(150, 40, 160, 260));
const Region kExpectedLayerShadowRegion =
Region(Rect(40, 40, 160, 260)).subtractSelf(Rect(50, 50, 150, 250));
- EXPECT_THAT(mOutputLayerState.visibleRegion, RegionEq(kExpectedLayerVisibleRegion));
- EXPECT_THAT(mOutputLayerState.shadowRegion, RegionEq(kExpectedLayerShadowRegion));
+ EXPECT_THAT(mLayer.outputLayerState.visibleRegion, RegionEq(kExpectedLayerVisibleRegion));
+ EXPECT_THAT(mLayer.outputLayerState.shadowRegion, RegionEq(kExpectedLayerShadowRegion));
EXPECT_TRUE(kExpectedLayerVisibleRegion.subtract(kExpectedLayerShadowRegion).isEmpty());
}
TEST_F(OutputEnsureOutputLayerIfVisibleTest, takesNotSoEarlyOutifLayerWithShadowIsCovered) {
ui::Transform translate;
translate.set(50, 50);
- mLayerFEState.geomLayerTransform = translate;
- mLayerFEState.shadowRadius = 10.0f;
+ mLayer.layerFEState.geomLayerTransform = translate;
+ mLayer.layerFEState.shadowRadius = 10.0f;
mCoverageState.dirtyRegion = Region(Rect(0, 0, 500, 500));
// Casting layer and its shadows are covered by an opaque region
mCoverageState.aboveCoveredLayers = Region(Rect(40, 40, 160, 260));
mCoverageState.aboveOpaqueLayers = Region(Rect(40, 40, 160, 260));
- mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
+ ensureOutputLayerIfVisible();
}
/*
@@ -1583,13 +1586,11 @@
struct Layer {
Layer() {
- EXPECT_CALL(mOutputLayer, getLayer()).WillRepeatedly(ReturnRef(mLayer));
EXPECT_CALL(mOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(mLayerFE));
- EXPECT_CALL(mLayer, getFEState()).WillRepeatedly(ReturnRef(mLayerFEState));
+ EXPECT_CALL(mLayerFE, getCompositionState()).WillRepeatedly(Return(&mLayerFEState));
}
StrictMock<mock::OutputLayer> mOutputLayer;
- StrictMock<mock::Layer> mLayer;
StrictMock<mock::LayerFE> mLayerFE;
LayerFECompositionState mLayerFEState;
};
@@ -3151,12 +3152,12 @@
struct OutputComposeSurfacesTest_HandlesProtectedContent : public OutputComposeSurfacesTest {
struct Layer {
Layer() {
- EXPECT_CALL(mOutputLayer, getLayer()).WillRepeatedly(ReturnRef(mLayer));
- EXPECT_CALL(mLayer, getFEState()).WillRepeatedly(ReturnRef(mLayerFEState));
+ EXPECT_CALL(mLayerFE, getCompositionState()).WillRepeatedly(Return(&mLayerFEState));
+ EXPECT_CALL(mOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(mLayerFE));
}
StrictMock<mock::OutputLayer> mOutputLayer;
- StrictMock<mock::Layer> mLayer;
+ StrictMock<mock::LayerFE> mLayerFE;
LayerFECompositionState mLayerFEState;
};
@@ -3323,13 +3324,11 @@
Layer() {
EXPECT_CALL(mOutputLayer, getState()).WillRepeatedly(ReturnRef(mOutputLayerState));
EXPECT_CALL(mOutputLayer, editState()).WillRepeatedly(ReturnRef(mOutputLayerState));
- EXPECT_CALL(mOutputLayer, getLayer()).WillRepeatedly(ReturnRef(mLayer));
EXPECT_CALL(mOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(mLayerFE));
- EXPECT_CALL(mLayer, getFEState()).WillRepeatedly(ReturnRef(mLayerFEState));
+ EXPECT_CALL(mLayerFE, getCompositionState()).WillRepeatedly(Return(&mLayerFEState));
}
StrictMock<mock::OutputLayer> mOutputLayer;
- StrictMock<mock::Layer> mLayer;
StrictMock<mock::LayerFE> mLayerFE;
LayerFECompositionState mLayerFEState;
impl::OutputLayerCompositionState mOutputLayerState;
@@ -3773,19 +3772,23 @@
}
TEST_F(OutputUpdateAndWriteCompositionStateTest, handlesBackgroundBlurRequests) {
+ InjectedLayer layer1;
+ InjectedLayer layer2;
+ InjectedLayer layer3;
+
// Layer requesting blur, or below, should request client composition.
- EXPECT_CALL(*mOutputLayer1, updateCompositionState(false, true));
- EXPECT_CALL(*mOutputLayer1, writeStateToHWC(false));
- EXPECT_CALL(*mOutputLayer2, updateCompositionState(false, true));
- EXPECT_CALL(*mOutputLayer2, writeStateToHWC(false));
- EXPECT_CALL(*mOutputLayer3, updateCompositionState(false, false));
- EXPECT_CALL(*mOutputLayer3, writeStateToHWC(false));
+ EXPECT_CALL(*layer1.outputLayer, updateCompositionState(false, true));
+ EXPECT_CALL(*layer1.outputLayer, writeStateToHWC(false));
+ EXPECT_CALL(*layer2.outputLayer, updateCompositionState(false, true));
+ EXPECT_CALL(*layer2.outputLayer, writeStateToHWC(false));
+ EXPECT_CALL(*layer3.outputLayer, updateCompositionState(false, false));
+ EXPECT_CALL(*layer3.outputLayer, writeStateToHWC(false));
- mLayer2FEState.backgroundBlurRadius = 10;
+ layer2.layerFEState.backgroundBlurRadius = 10;
- injectLayer(std::move(mOutputLayer1));
- injectLayer(std::move(mOutputLayer2));
- injectLayer(std::move(mOutputLayer3));
+ injectOutputLayer(layer1);
+ injectOutputLayer(layer2);
+ injectOutputLayer(layer3);
mOutput->editState().isEnabled = true;
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index cf1e8b0..effbed6 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -28,7 +28,6 @@
#include <android-base/stringprintf.h>
#include <binder/IPCThreadState.h>
#include <compositionengine/Display.h>
-#include <compositionengine/Layer.h>
#include <compositionengine/LayerFECompositionState.h>
#include <compositionengine/OutputLayer.h>
#include <compositionengine/impl/OutputLayerCompositionState.h>
@@ -415,7 +414,7 @@
win.bottom -= roundedCornersCrop.top;
}
-void Layer::latchBasicGeometry(compositionengine::LayerFECompositionState& compositionState) const {
+void Layer::prepareBasicGeometryCompositionState() {
const auto& drawingState{getDrawingState()};
const uint32_t layerStack = getLayerStack();
const auto alpha = static_cast<float>(getAlpha());
@@ -428,31 +427,28 @@
: Hwc2::IComposerClient::BlendMode::COVERAGE;
}
- // TODO(b/121291683): Instead of filling in a passed-in compositionState
- // structure, switch to Layer owning the structure and have
- // CompositionEngine be able to get a reference to it.
-
- compositionState.layerStackId =
+ auto* compositionState = editCompositionState();
+ compositionState->layerStackId =
(layerStack != ~0u) ? std::make_optional(layerStack) : std::nullopt;
- compositionState.internalOnly = getPrimaryDisplayOnly();
- compositionState.isVisible = isVisible();
- compositionState.isOpaque = opaque && !usesRoundedCorners && alpha == 1.f;
- compositionState.shadowRadius = mEffectiveShadowRadius;
+ compositionState->internalOnly = getPrimaryDisplayOnly();
+ compositionState->isVisible = isVisible();
+ compositionState->isOpaque = opaque && !usesRoundedCorners && alpha == 1.f;
+ compositionState->shadowRadius = mEffectiveShadowRadius;
- compositionState.contentDirty = contentDirty;
+ compositionState->contentDirty = contentDirty;
contentDirty = false;
- compositionState.geomLayerBounds = mBounds;
- compositionState.geomLayerTransform = getTransform();
- compositionState.geomInverseLayerTransform = compositionState.geomLayerTransform.inverse();
- compositionState.transparentRegionHint = getActiveTransparentRegion(drawingState);
+ compositionState->geomLayerBounds = mBounds;
+ compositionState->geomLayerTransform = getTransform();
+ compositionState->geomInverseLayerTransform = compositionState->geomLayerTransform.inverse();
+ compositionState->transparentRegionHint = getActiveTransparentRegion(drawingState);
- compositionState.blendMode = static_cast<Hwc2::IComposerClient::BlendMode>(blendMode);
- compositionState.alpha = alpha;
- compositionState.backgroundBlurRadius = drawingState.backgroundBlurRadius;
+ compositionState->blendMode = static_cast<Hwc2::IComposerClient::BlendMode>(blendMode);
+ compositionState->alpha = alpha;
+ compositionState->backgroundBlurRadius = drawingState.backgroundBlurRadius;
}
-void Layer::latchGeometry(compositionengine::LayerFECompositionState& compositionState) const {
+void Layer::prepareGeometryCompositionState() {
const auto& drawingState{getDrawingState()};
int type = drawingState.metadata.getInt32(METADATA_WINDOW_TYPE, 0);
@@ -468,45 +464,48 @@
}
}
- compositionState.geomBufferSize = getBufferSize(drawingState);
- compositionState.geomContentCrop = getBufferCrop();
- compositionState.geomCrop = getCrop(drawingState);
- compositionState.geomBufferTransform = getBufferTransform();
- compositionState.geomBufferUsesDisplayInverseTransform = getTransformToDisplayInverse();
- compositionState.geomUsesSourceCrop = usesSourceCrop();
- compositionState.isSecure = isSecure();
+ auto* compositionState = editCompositionState();
- compositionState.type = type;
- compositionState.appId = appId;
+ compositionState->geomBufferSize = getBufferSize(drawingState);
+ compositionState->geomContentCrop = getBufferCrop();
+ compositionState->geomCrop = getCrop(drawingState);
+ compositionState->geomBufferTransform = getBufferTransform();
+ compositionState->geomBufferUsesDisplayInverseTransform = getTransformToDisplayInverse();
+ compositionState->geomUsesSourceCrop = usesSourceCrop();
+ compositionState->isSecure = isSecure();
+
+ compositionState->type = type;
+ compositionState->appId = appId;
}
-void Layer::latchPerFrameState(compositionengine::LayerFECompositionState& compositionState) const {
+void Layer::preparePerFrameCompositionState() {
const auto& drawingState{getDrawingState()};
- compositionState.forceClientComposition = false;
+ auto* compositionState = editCompositionState();
- compositionState.isColorspaceAgnostic = isColorSpaceAgnostic();
- compositionState.dataspace = getDataSpace();
- compositionState.colorTransform = getColorTransform();
- compositionState.colorTransformIsIdentity = !hasColorTransform();
- compositionState.surfaceDamage = surfaceDamageRegion;
- compositionState.hasProtectedContent = isProtected();
+ compositionState->forceClientComposition = false;
+
+ compositionState->isColorspaceAgnostic = isColorSpaceAgnostic();
+ compositionState->dataspace = getDataSpace();
+ compositionState->colorTransform = getColorTransform();
+ compositionState->colorTransformIsIdentity = !hasColorTransform();
+ compositionState->surfaceDamage = surfaceDamageRegion;
+ compositionState->hasProtectedContent = isProtected();
const bool usesRoundedCorners = getRoundedCornerState().radius != 0.f;
const bool drawsShadows = mEffectiveShadowRadius != 0.f;
- compositionState.isOpaque =
+ compositionState->isOpaque =
isOpaque(drawingState) && !usesRoundedCorners && getAlpha() == 1.0_hf;
// Force client composition for special cases known only to the front-end.
if (isHdrY410() || usesRoundedCorners || drawsShadows) {
- compositionState.forceClientComposition = true;
+ compositionState->forceClientComposition = true;
}
}
-void Layer::latchCursorCompositionState(
- compositionengine::LayerFECompositionState& compositionState) const {
- // This gives us only the "orientation" component of the transform
+void Layer::prepareCursorCompositionState() {
const State& drawingState{getDrawingState()};
+ auto* compositionState = editCompositionState();
// Apply the layer's transform, followed by the display's global transform
// Here we're guaranteed that the layer's transform preserves rects
@@ -515,30 +514,50 @@
Rect bounds = reduce(win, getActiveTransparentRegion(drawingState));
Rect frame(getTransform().transform(bounds));
- compositionState.cursorFrame = frame;
+ compositionState->cursorFrame = frame;
+}
+
+sp<compositionengine::LayerFE> Layer::asLayerFE() const {
+ return const_cast<compositionengine::LayerFE*>(
+ static_cast<const compositionengine::LayerFE*>(this));
+}
+
+sp<compositionengine::LayerFE> Layer::getCompositionEngineLayerFE() const {
+ return nullptr;
+}
+
+compositionengine::LayerFECompositionState* Layer::editCompositionState() {
+ return nullptr;
+}
+
+const compositionengine::LayerFECompositionState* Layer::getCompositionState() const {
+ return nullptr;
}
bool Layer::onPreComposition(nsecs_t) {
return false;
}
-void Layer::latchCompositionState(compositionengine::LayerFECompositionState& compositionState,
- compositionengine::LayerFE::StateSubset subset) const {
+void Layer::prepareCompositionState(compositionengine::LayerFE::StateSubset subset) {
using StateSubset = compositionengine::LayerFE::StateSubset;
switch (subset) {
case StateSubset::BasicGeometry:
- latchBasicGeometry(compositionState);
+ prepareBasicGeometryCompositionState();
break;
case StateSubset::GeometryAndContent:
- latchBasicGeometry(compositionState);
- latchGeometry(compositionState);
- latchPerFrameState(compositionState);
+ prepareBasicGeometryCompositionState();
+ prepareGeometryCompositionState();
+ preparePerFrameCompositionState();
break;
case StateSubset::Content:
- latchPerFrameState(compositionState);
+ preparePerFrameCompositionState();
+ break;
+
+ case StateSubset::Cursor:
+ prepareCursorCompositionState();
break;
}
}
@@ -553,7 +572,7 @@
std::optional<compositionengine::LayerFE::LayerSettings> Layer::prepareClientComposition(
compositionengine::LayerFE::ClientCompositionTargetSettings& targetSettings) {
- if (!getCompositionLayer()) {
+ if (!getCompositionState()) {
return {};
}
@@ -1418,7 +1437,7 @@
StringAppendF(&result, " %s\n", name.c_str());
const State& layerState(getDrawingState());
- const auto& compositionState = outputLayer->getState();
+ const auto& outputLayerState = outputLayer->getState();
if (layerState.zOrderRelativeOf != nullptr || mDrawingParent != nullptr) {
StringAppendF(&result, " rel %6d | ", layerState.z);
@@ -1427,13 +1446,10 @@
}
StringAppendF(&result, " %10d | ", mWindowType);
StringAppendF(&result, "%10s | ", toString(getCompositionType(displayDevice)).c_str());
- StringAppendF(&result, "%10s | ",
- toString(getCompositionLayer() ? compositionState.bufferTransform
- : static_cast<Hwc2::Transform>(0))
- .c_str());
- const Rect& frame = compositionState.displayFrame;
+ StringAppendF(&result, "%10s | ", toString(outputLayerState.bufferTransform).c_str());
+ const Rect& frame = outputLayerState.displayFrame;
StringAppendF(&result, "%4d %4d %4d %4d | ", frame.left, frame.top, frame.right, frame.bottom);
- const FloatRect& crop = compositionState.sourceCrop;
+ const FloatRect& crop = outputLayerState.sourceCrop;
StringAppendF(&result, "%6.1f %6.1f %6.1f %6.1f\n", crop.left, crop.top, crop.right,
crop.bottom);
@@ -2210,17 +2226,13 @@
return mDrawingState.inputInfo.token != nullptr;
}
-std::shared_ptr<compositionengine::Layer> Layer::getCompositionLayer() const {
- return nullptr;
-}
-
bool Layer::canReceiveInput() const {
return !isHiddenByPolicy();
}
compositionengine::OutputLayer* Layer::findOutputLayerForDisplay(
const sp<const DisplayDevice>& display) const {
- return display->getCompositionDisplay()->getOutputLayerForLayer(getCompositionLayer().get());
+ return display->getCompositionDisplay()->getOutputLayerForLayer(getCompositionEngineLayerFE());
}
Region Layer::debugGetVisibleRegionOnDefaultDisplay() const {
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index f7907c3..de4a080 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -66,7 +66,6 @@
class LayerDebugInfo;
namespace compositionengine {
-class Layer;
class OutputLayer;
struct LayerFECompositionState;
}
@@ -94,7 +93,7 @@
uint32_t textureName;
};
-class Layer : public compositionengine::LayerFE {
+class Layer : public virtual RefBase, compositionengine::LayerFE {
static std::atomic<int32_t> sSequence;
static constexpr int32_t PRIORITY_UNSET = -1;
@@ -373,6 +372,10 @@
return false;
};
virtual void forceSendCallbacks() {}
+ virtual bool addFrameEvent(const sp<Fence>& /*acquireFence*/, nsecs_t /*postedTime*/,
+ nsecs_t /*requestedPresentTime*/) {
+ return false;
+ }
virtual bool setBackgroundColor(const half3& color, float alpha, ui::Dataspace dataspace);
virtual bool setColorSpaceAgnostic(const bool agnostic);
bool setShadowRadius(float shadowRadius);
@@ -390,7 +393,8 @@
// visually.
bool isLegacyDataSpace() const;
- virtual std::shared_ptr<compositionengine::Layer> getCompositionLayer() const;
+ virtual sp<compositionengine::LayerFE> getCompositionEngineLayerFE() const;
+ virtual compositionengine::LayerFECompositionState* editCompositionState();
// If we have received a new buffer this frame, we will pass its surface
// damage down to hardware composer. Otherwise, we must send a region with
@@ -535,6 +539,7 @@
virtual void updateCloneBufferInfo(){};
protected:
+ sp<compositionengine::LayerFE> asLayerFE() const;
sp<Layer> getClonedFrom() { return mClonedFrom != nullptr ? mClonedFrom.promote() : nullptr; }
bool isClone() { return mClonedFrom != nullptr; }
bool isClonedFromAlive() { return getClonedFrom() != nullptr; }
@@ -552,10 +557,9 @@
/*
* compositionengine::LayerFE overrides
*/
+ const compositionengine::LayerFECompositionState* getCompositionState() const override;
bool onPreComposition(nsecs_t) override;
- void latchCompositionState(compositionengine::LayerFECompositionState&,
- compositionengine::LayerFE::StateSubset subset) const override;
- void latchCursorCompositionState(compositionengine::LayerFECompositionState&) const override;
+ void prepareCompositionState(compositionengine::LayerFE::StateSubset subset) override;
std::optional<LayerSettings> prepareClientComposition(
compositionengine::LayerFE::ClientCompositionTargetSettings&) override;
std::optional<LayerSettings> prepareShadowClientComposition(
@@ -565,9 +569,10 @@
const char* getDebugName() const override;
protected:
- void latchBasicGeometry(compositionengine::LayerFECompositionState& outState) const;
- void latchGeometry(compositionengine::LayerFECompositionState& outState) const;
- virtual void latchPerFrameState(compositionengine::LayerFECompositionState& outState) const;
+ void prepareBasicGeometryCompositionState();
+ void prepareGeometryCompositionState();
+ virtual void preparePerFrameCompositionState();
+ void prepareCursorCompositionState();
public:
virtual void setDefaultBufferSize(uint32_t /*w*/, uint32_t /*h*/) {}
@@ -595,6 +600,8 @@
// If a buffer was replaced this frame, release the former buffer
virtual void releasePendingBuffer(nsecs_t /*dequeueReadyTime*/) { }
+ virtual void finalizeFrameEventHistory(const std::shared_ptr<FenceTime>& /*glDoneFence*/,
+ const CompositorTiming& /*compositorTiming*/) {}
/*
* doTransaction - process the transaction. This is a good place to figure
* out which attributes of the surface have changed.
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
index c73e825..0f55615 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
@@ -216,12 +216,20 @@
const RefreshRate& RefreshRateConfigs::getMinRefreshRateByPolicy() const {
std::lock_guard lock(mLock);
- return *mAvailableRefreshRates.front();
+ if (!mRefreshRateSwitching) {
+ return *mCurrentRefreshRate;
+ } else {
+ return *mAvailableRefreshRates.front();
+ }
}
const RefreshRate& RefreshRateConfigs::getMaxRefreshRateByPolicy() const {
std::lock_guard lock(mLock);
+ if (!mRefreshRateSwitching) {
+ return *mCurrentRefreshRate;
+ } else {
return *mAvailableRefreshRates.back();
+ }
}
const RefreshRate& RefreshRateConfigs::getCurrentRefreshRate() const {
@@ -234,14 +242,18 @@
mCurrentRefreshRate = &mRefreshRates.at(configId);
}
-RefreshRateConfigs::RefreshRateConfigs(const std::vector<InputConfig>& configs,
- HwcConfigIndexType currentHwcConfig) {
+RefreshRateConfigs::RefreshRateConfigs(bool refreshRateSwitching,
+ const std::vector<InputConfig>& configs,
+ HwcConfigIndexType currentHwcConfig)
+ : mRefreshRateSwitching(refreshRateSwitching) {
init(configs, currentHwcConfig);
}
RefreshRateConfigs::RefreshRateConfigs(
+ bool refreshRateSwitching,
const std::vector<std::shared_ptr<const HWC2::Display::Config>>& configs,
- HwcConfigIndexType currentConfigId) {
+ HwcConfigIndexType currentConfigId)
+ : mRefreshRateSwitching(refreshRateSwitching) {
std::vector<InputConfig> inputConfigs;
for (size_t configId = 0; configId < configs.size(); ++configId) {
auto configGroup = HwcConfigGroupType(configs[configId]->getConfigGroup());
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
index fc95959..c4dea0d 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
@@ -94,6 +94,9 @@
// Returns true if config is allowed by the current policy.
bool isConfigAllowed(HwcConfigIndexType config) const EXCLUDES(mLock);
+ // Returns true if this device is doing refresh rate switching. This won't change at runtime.
+ bool refreshRateSwitchingSupported() const { return mRefreshRateSwitching; }
+
// Describes the different options the layer voted for refresh rate
enum class LayerVoteType {
NoVote, // Doesn't care about the refresh rate
@@ -164,9 +167,10 @@
nsecs_t vsyncPeriod = 0;
};
- RefreshRateConfigs(const std::vector<InputConfig>& configs,
+ RefreshRateConfigs(bool refreshRateSwitching, const std::vector<InputConfig>& configs,
HwcConfigIndexType currentHwcConfig);
- RefreshRateConfigs(const std::vector<std::shared_ptr<const HWC2::Display::Config>>& configs,
+ RefreshRateConfigs(bool refreshRateSwitching,
+ const std::vector<std::shared_ptr<const HWC2::Display::Config>>& configs,
HwcConfigIndexType currentConfigId);
private:
@@ -204,6 +208,8 @@
const RefreshRate* mMinSupportedRefreshRate;
const RefreshRate* mMaxSupportedRefreshRate;
+ const bool mRefreshRateSwitching;
+
mutable std::mutex mLock;
};
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index 56d1581..bc4f805 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -530,6 +530,8 @@
using base::StringAppendF;
const char* const states[] = {"off", "on"};
+ const bool supported = mRefreshRateConfigs.refreshRateSwitchingSupported();
+ StringAppendF(&result, "+ Refresh rate switching: %s\n", states[supported]);
StringAppendF(&result, "+ Content detection: %s\n", states[mLayerHistory != nullptr]);
StringAppendF(&result, "+ Idle timer: %s\n",
@@ -573,44 +575,35 @@
}
HwcConfigIndexType Scheduler::calculateRefreshRateType() {
- // This block of the code checks whether any layers used the SetFrameRate API. If they have,
- // their request should be honored regardless of whether the device has refresh rate switching
- // turned off.
- if (layerHistoryHasClientSpecifiedFrameRate()) {
- if (!mUseContentDetectionV2) {
- return mRefreshRateConfigs.getRefreshRateForContent(mFeatures.contentRequirements)
- .configId;
- } else {
- return mRefreshRateConfigs.getRefreshRateForContentV2(mFeatures.contentRequirements)
- .configId;
- }
+ if (!mRefreshRateConfigs.refreshRateSwitchingSupported()) {
+ return mRefreshRateConfigs.getCurrentRefreshRate().configId;
}
// If the layer history doesn't have the frame rate specified, use the old path. NOTE:
// if we remove the kernel idle timer, and use our internal idle timer, this code will have to
// be refactored.
- // If Display Power is not in normal operation we want to be in performance mode.
- // When coming back to normal mode, a grace period is given with DisplayPowerTimer
- if (mDisplayPowerTimer &&
- (!mFeatures.isDisplayPowerStateNormal ||
- mFeatures.displayPowerTimer == TimerState::Reset)) {
- return mRefreshRateConfigs.getMaxRefreshRateByPolicy().configId;
- }
+ if (!layerHistoryHasClientSpecifiedFrameRate()) {
+ // If Display Power is not in normal operation we want to be in performance mode.
+ // When coming back to normal mode, a grace period is given with DisplayPowerTimer
+ if (!mFeatures.isDisplayPowerStateNormal ||
+ mFeatures.displayPowerTimer == TimerState::Reset) {
+ return mRefreshRateConfigs.getMaxRefreshRateByPolicy().configId;
+ }
- // As long as touch is active we want to be in performance mode
- if (mTouchTimer && mFeatures.touch == TouchState::Active) {
- return mRefreshRateConfigs.getMaxRefreshRateByPolicy().configId;
- }
+ // As long as touch is active we want to be in performance mode
+ if (mFeatures.touch == TouchState::Active) {
+ return mRefreshRateConfigs.getMaxRefreshRateByPolicy().configId;
+ }
- // If timer has expired as it means there is no new content on the screen
- if (mIdleTimer && mFeatures.idleTimer == TimerState::Expired) {
- return mRefreshRateConfigs.getMinRefreshRateByPolicy().configId;
+ // If timer has expired as it means there is no new content on the screen
+ if (mFeatures.idleTimer == TimerState::Expired) {
+ return mRefreshRateConfigs.getMinRefreshRateByPolicy().configId;
+ }
}
if (!mUseContentDetectionV2) {
- // If content detection is off we choose performance as we don't know the content fps.
+ // If content detection is off we choose performance as we don't know the content fps
if (mFeatures.contentDetection == ContentDetectionState::Off) {
- // TODO(b/148428554): Be careful to not always call this.
return mRefreshRateConfigs.getMaxRefreshRateByPolicy().configId;
}
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index e4578f8..c125b2c 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -45,6 +45,7 @@
#include <compositionengine/CompositionRefreshArgs.h>
#include <compositionengine/Display.h>
#include <compositionengine/DisplayColorProfile.h>
+#include <compositionengine/LayerFECompositionState.h>
#include <compositionengine/OutputLayer.h>
#include <compositionengine/RenderSurface.h>
#include <compositionengine/impl/OutputCompositionState.h>
@@ -555,6 +556,12 @@
readPersistentProperties();
mBootStage = BootStage::FINISHED;
+ if (mRefreshRateConfigs->refreshRateSwitchingSupported()) {
+ // set the refresh rate according to the policy
+ const auto& performanceRefreshRate = mRefreshRateConfigs->getMaxRefreshRateByPolicy();
+ changeRefreshRateLocked(performanceRefreshRate, Scheduler::ConfigEvent::None);
+ }
+
if (property_get_bool("sf.debug.show_refresh_rate_overlay", false)) {
mRefreshRateOverlay = std::make_unique<RefreshRateOverlay>(*this);
mRefreshRateOverlay->changeRefreshRate(mRefreshRateConfigs->getCurrentRefreshRate());
@@ -1871,13 +1878,13 @@
refreshArgs.outputs.push_back(display->getCompositionDisplay());
}
mDrawingState.traverseInZOrder([&refreshArgs](Layer* layer) {
- auto compositionLayer = layer->getCompositionLayer();
- if (compositionLayer) refreshArgs.layers.push_back(compositionLayer);
+ if (auto layerFE = layer->getCompositionEngineLayerFE())
+ refreshArgs.layers.push_back(layerFE);
});
refreshArgs.layersWithQueuedFrames.reserve(mLayersWithQueuedFrames.size());
for (sp<Layer> layer : mLayersWithQueuedFrames) {
- auto compositionLayer = layer->getCompositionLayer();
- if (compositionLayer) refreshArgs.layersWithQueuedFrames.push_back(compositionLayer.get());
+ if (auto layerFE = layer->getCompositionEngineLayerFE())
+ refreshArgs.layersWithQueuedFrames.push_back(layerFE);
}
refreshArgs.repaintEverything = mRepaintEverything.exchange(false);
@@ -2030,12 +2037,10 @@
ATRACE_CALL();
ALOGV("postComposition");
- // Release any buffers which were replaced this frame
nsecs_t dequeueReadyTime = systemTime();
for (auto& layer : mLayersWithQueuedFrames) {
layer->releasePendingBuffer(dequeueReadyTime);
}
-
// |mStateLock| not needed as we are on the main thread
const auto displayDevice = getDefaultDisplayDeviceLocked();
@@ -2713,7 +2718,8 @@
auto currentConfig = HwcConfigIndexType(getHwComposer().getActiveConfigIndex(primaryDisplayId));
mRefreshRateConfigs =
- std::make_unique<scheduler::RefreshRateConfigs>(getHwComposer().getConfigs(
+ std::make_unique<scheduler::RefreshRateConfigs>(refresh_rate_switching(false),
+ getHwComposer().getConfigs(
primaryDisplayId),
currentConfig);
mRefreshRateStats =
@@ -3341,6 +3347,11 @@
layer->pushPendingState();
}
+ // Only set by BLAST adapter layers
+ if (what & layer_state_t::eProducerDisconnect) {
+ layer->onDisconnect();
+ }
+
if (what & layer_state_t::ePositionChanged) {
if (layer->setPosition(s.x, s.y)) {
flags |= eTraversalNeeded;
@@ -4438,8 +4449,13 @@
{
StringAppendF(&result, "Composition layers\n");
mDrawingState.traverseInZOrder([&](Layer* layer) {
- auto compositionLayer = layer->getCompositionLayer();
- if (compositionLayer) compositionLayer->dump(result);
+ auto* compositionState = layer->getCompositionState();
+ if (!compositionState) return;
+
+ android::base::StringAppendF(&result, "* Layer %p (%s)\n", layer,
+ layer->getDebugName() ? layer->getDebugName()
+ : "<unknown>");
+ compositionState->dump(result);
});
}
@@ -5693,19 +5709,26 @@
mScheduler->onConfigChanged(mAppConnectionHandle, display->getId()->value,
display->getActiveConfig(), vsyncPeriod);
- auto configId = mScheduler->getPreferredConfigId();
- auto preferredRefreshRate = configId
- ? mRefreshRateConfigs->getRefreshRateFromConfigId(*configId)
- // NOTE: Choose the default config ID, if Scheduler doesn't have one in mind.
- : mRefreshRateConfigs->getRefreshRateFromConfigId(defaultConfig);
- ALOGV("trying to switch to Scheduler preferred config %d (%s)",
- preferredRefreshRate.configId.value(), preferredRefreshRate.name.c_str());
-
- if (isDisplayConfigAllowed(preferredRefreshRate.configId)) {
- ALOGV("switching to Scheduler preferred config %d", preferredRefreshRate.configId.value());
- setDesiredActiveConfig({preferredRefreshRate.configId, Scheduler::ConfigEvent::Changed});
+ if (mRefreshRateConfigs->refreshRateSwitchingSupported()) {
+ auto configId = mScheduler->getPreferredConfigId();
+ auto preferredRefreshRate = configId
+ ? mRefreshRateConfigs->getRefreshRateFromConfigId(*configId)
+ : mRefreshRateConfigs->getMinRefreshRateByPolicy();
+ ALOGV("trying to switch to Scheduler preferred config %d (%s)",
+ preferredRefreshRate.configId.value(), preferredRefreshRate.name.c_str());
+ if (isDisplayConfigAllowed(preferredRefreshRate.configId)) {
+ ALOGV("switching to Scheduler preferred config %d",
+ preferredRefreshRate.configId.value());
+ setDesiredActiveConfig(
+ {preferredRefreshRate.configId, Scheduler::ConfigEvent::Changed});
+ } else {
+ // Set the highest allowed config
+ setDesiredActiveConfig({mRefreshRateConfigs->getMaxRefreshRateByPolicy().configId,
+ Scheduler::ConfigEvent::Changed});
+ }
} else {
- LOG_ALWAYS_FATAL("Desired config not allowed: %d", preferredRefreshRate.configId.value());
+ ALOGV("switching to config %d", defaultConfig.value());
+ setDesiredActiveConfig({defaultConfig, Scheduler::ConfigEvent::Changed});
}
return NO_ERROR;
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/SurfaceFlingerProperties.cpp b/services/surfaceflinger/SurfaceFlingerProperties.cpp
index 768074a..b4716eb 100644
--- a/services/surfaceflinger/SurfaceFlingerProperties.cpp
+++ b/services/surfaceflinger/SurfaceFlingerProperties.cpp
@@ -226,6 +226,14 @@
return static_cast<int64_t>(defaultValue);
}
+bool refresh_rate_switching(bool defaultValue) {
+ auto temp = SurfaceFlingerProperties::refresh_rate_switching();
+ if (temp.has_value()) {
+ return *temp;
+ }
+ return defaultValue;
+}
+
int32_t set_idle_timer_ms(int32_t defaultValue) {
auto temp = SurfaceFlingerProperties::set_idle_timer_ms();
if (temp.has_value()) {
diff --git a/services/surfaceflinger/SurfaceFlingerProperties.h b/services/surfaceflinger/SurfaceFlingerProperties.h
index 5f88322..e394cca 100644
--- a/services/surfaceflinger/SurfaceFlingerProperties.h
+++ b/services/surfaceflinger/SurfaceFlingerProperties.h
@@ -73,6 +73,8 @@
int64_t color_space_agnostic_dataspace(
android::hardware::graphics::common::V1_2::Dataspace defaultValue);
+bool refresh_rate_switching(bool defaultValue);
+
int32_t set_idle_timer_ms(int32_t defaultValue);
int32_t set_touch_timer_ms(int32_t defaultValue);
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/TransactionCompletedThread.cpp b/services/surfaceflinger/TransactionCompletedThread.cpp
index daa67ae..0cdff8f 100644
--- a/services/surfaceflinger/TransactionCompletedThread.cpp
+++ b/services/surfaceflinger/TransactionCompletedThread.cpp
@@ -237,9 +237,13 @@
// destroyed the client side is dead and there won't be anyone to send the callback to.
sp<IBinder> surfaceControl = handle->surfaceControl.promote();
if (surfaceControl) {
+ FrameEventHistoryStats eventStats(handle->frameNumber,
+ handle->gpuCompositionDoneFence->getSnapshot().fence,
+ handle->compositorTiming, handle->refreshStartTime,
+ handle->dequeueReadyTime);
transactionStats->surfaceStats.emplace_back(surfaceControl, handle->acquireTime,
handle->previousReleaseFence,
- handle->transformHint);
+ handle->transformHint, eventStats);
}
return NO_ERROR;
}
diff --git a/services/surfaceflinger/TransactionCompletedThread.h b/services/surfaceflinger/TransactionCompletedThread.h
index 12ea8fe..f50147a 100644
--- a/services/surfaceflinger/TransactionCompletedThread.h
+++ b/services/surfaceflinger/TransactionCompletedThread.h
@@ -45,6 +45,11 @@
nsecs_t acquireTime = -1;
nsecs_t latchTime = -1;
uint32_t transformHint = 0;
+ std::shared_ptr<FenceTime> gpuCompositionDoneFence{FenceTime::NO_FENCE};
+ CompositorTiming compositorTiming;
+ nsecs_t refreshStartTime = 0;
+ nsecs_t dequeueReadyTime = 0;
+ uint64_t frameNumber = 0;
};
class TransactionCompletedThread {
diff --git a/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop b/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop
index 0653959..ed2b220 100644
--- a/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop
+++ b/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop
@@ -301,6 +301,18 @@
prop_name: "ro.surface_flinger.display_primary_white"
}
+# refreshRateSwitching indicates whether SurfaceFlinger should use refresh rate
+# switching on the device, e.g. to switch between 60 and 90 Hz. The settings
+# below that are related to refresh rate switching will only have an effect if
+# refresh_rate_switching is enabled.
+prop {
+ api_name: "refresh_rate_switching"
+ type: Boolean
+ scope: System
+ access: Readonly
+ prop_name: "ro.surface_flinger.refresh_rate_switching"
+}
+
prop {
api_name: "set_idle_timer_ms"
type: Integer
diff --git a/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-current.txt b/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-current.txt
index 1adab84..d24ad18 100644
--- a/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-current.txt
+++ b/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-current.txt
@@ -73,6 +73,10 @@
enum_values: "ORIENTATION_0|ORIENTATION_90|ORIENTATION_180|ORIENTATION_270"
}
prop {
+ api_name: "refresh_rate_switching"
+ prop_name: "ro.surface_flinger.refresh_rate_switching"
+ }
+ prop {
api_name: "running_without_sync_framework"
prop_name: "ro.surface_flinger.running_without_sync_framework"
}
diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
index c6d8a2e..888e009 100644
--- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
@@ -842,8 +842,8 @@
EXPECT_CALL(*test->mComposer, createLayer(HWC_DISPLAY, _))
.WillOnce(DoAll(SetArgPointee<1>(HWC_LAYER), Return(Error::NONE)));
- auto outputLayer = test->mDisplay->getCompositionDisplay()
- ->injectOutputLayerForTest(layer->getCompositionLayer(), layer);
+ auto outputLayer = test->mDisplay->getCompositionDisplay()->injectOutputLayerForTest(
+ layer->getCompositionEngineLayerFE());
outputLayer->editState().visibleRegion = Region(Rect(0, 0, 100, 100));
outputLayer->editState().outputSpaceVisibleRegion = Region(Rect(0, 0, 100, 100));
diff --git a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp
index 18e9941..d9481be 100644
--- a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp
+++ b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp
@@ -63,7 +63,8 @@
auto createLayer() { return sp<mock::MockLayer>(new mock::MockLayer(mFlinger.flinger())); }
- RefreshRateConfigs mConfigs{{
+ RefreshRateConfigs mConfigs{true,
+ {
RefreshRateConfigs::InputConfig{HwcConfigIndexType(0),
HwcConfigGroupType(0),
LO_FPS_PERIOD},
diff --git a/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp b/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp
index 959c256..bb3bbad 100644
--- a/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp
+++ b/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp
@@ -71,7 +71,8 @@
auto createLayer() { return sp<mock::MockLayer>(new mock::MockLayer(mFlinger.flinger())); }
- RefreshRateConfigs mConfigs{{
+ RefreshRateConfigs mConfigs{true,
+ {
RefreshRateConfigs::InputConfig{HwcConfigIndexType(0),
HwcConfigGroupType(0),
LO_FPS_PERIOD},
diff --git a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
index 841c624..7c1ecea 100644
--- a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
+++ b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
@@ -74,14 +74,26 @@
std::vector<RefreshRateConfigs::InputConfig> configs{
{{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60}}};
auto refreshRateConfigs =
- std::make_unique<RefreshRateConfigs>(configs, /*currentConfigId=*/HWC_CONFIG_ID_60);
+ std::make_unique<RefreshRateConfigs>(/*refreshRateSwitching=*/true, configs,
+ /*currentConfigId=*/HWC_CONFIG_ID_60);
+ ASSERT_TRUE(refreshRateConfigs->refreshRateSwitchingSupported());
+}
+
+TEST_F(RefreshRateConfigsTest, oneDeviceConfig_SwitchingNotSupported) {
+ std::vector<RefreshRateConfigs::InputConfig> configs{
+ {{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60}}};
+ auto refreshRateConfigs =
+ std::make_unique<RefreshRateConfigs>(/*refreshRateSwitching=*/false, configs,
+ /*currentConfigId=*/HWC_CONFIG_ID_60);
+ ASSERT_FALSE(refreshRateConfigs->refreshRateSwitchingSupported());
}
TEST_F(RefreshRateConfigsTest, invalidPolicy) {
std::vector<RefreshRateConfigs::InputConfig> configs{
{{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60}}};
auto refreshRateConfigs =
- std::make_unique<RefreshRateConfigs>(configs, /*currentConfigId=*/HWC_CONFIG_ID_60);
+ std::make_unique<RefreshRateConfigs>(/*refreshRateSwitching=*/true, configs,
+ /*currentConfigId=*/HWC_CONFIG_ID_60);
ASSERT_LT(refreshRateConfigs->setPolicy(HwcConfigIndexType(10), 60, 60, nullptr), 0);
ASSERT_LT(refreshRateConfigs->setPolicy(HWC_CONFIG_ID_60, 20, 40, nullptr), 0);
}
@@ -91,7 +103,10 @@
{{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60},
{HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}};
auto refreshRateConfigs =
- std::make_unique<RefreshRateConfigs>(configs, /*currentConfigId=*/HWC_CONFIG_ID_60);
+ std::make_unique<RefreshRateConfigs>(/*refreshRateSwitching=*/true, configs,
+ /*currentConfigId=*/HWC_CONFIG_ID_60);
+
+ ASSERT_TRUE(refreshRateConfigs->refreshRateSwitchingSupported());
const auto minRate = refreshRateConfigs->getMinRefreshRate();
const auto performanceRate = refreshRateConfigs->getMaxRefreshRate();
@@ -113,8 +128,10 @@
{{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60},
{HWC_CONFIG_ID_90, HWC_GROUP_ID_1, VSYNC_90}}};
auto refreshRateConfigs =
- std::make_unique<RefreshRateConfigs>(configs, /*currentConfigId=*/HWC_CONFIG_ID_60);
+ std::make_unique<RefreshRateConfigs>(/*refreshRateSwitching=*/true, configs,
+ /*currentConfigId=*/HWC_CONFIG_ID_60);
+ ASSERT_TRUE(refreshRateConfigs->refreshRateSwitchingSupported());
const auto minRate = refreshRateConfigs->getMinRefreshRateByPolicy();
const auto performanceRate = refreshRateConfigs->getMaxRefreshRate();
const auto minRate60 = refreshRateConfigs->getMinRefreshRateByPolicy();
@@ -128,6 +145,7 @@
ASSERT_GE(refreshRateConfigs->setPolicy(HWC_CONFIG_ID_90, 60, 90, nullptr), 0);
refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_90);
+ ASSERT_TRUE(refreshRateConfigs->refreshRateSwitchingSupported());
const auto minRate90 = refreshRateConfigs->getMinRefreshRateByPolicy();
const auto performanceRate90 = refreshRateConfigs->getMaxRefreshRateByPolicy();
@@ -143,8 +161,9 @@
{{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60},
{HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}};
auto refreshRateConfigs =
- std::make_unique<RefreshRateConfigs>(configs, /*currentConfigId=*/HWC_CONFIG_ID_60);
-
+ std::make_unique<RefreshRateConfigs>(/*refreshRateSwitching=*/true, configs,
+ /*currentConfigId=*/HWC_CONFIG_ID_60);
+ ASSERT_TRUE(refreshRateConfigs->refreshRateSwitchingSupported());
auto minRate = refreshRateConfigs->getMinRefreshRateByPolicy();
auto performanceRate = refreshRateConfigs->getMaxRefreshRateByPolicy();
@@ -155,6 +174,7 @@
ASSERT_EQ(expectedPerformanceConfig, performanceRate);
ASSERT_GE(refreshRateConfigs->setPolicy(HWC_CONFIG_ID_60, 60, 60, nullptr), 0);
+ ASSERT_TRUE(refreshRateConfigs->refreshRateSwitchingSupported());
auto minRate60 = refreshRateConfigs->getMinRefreshRateByPolicy();
auto performanceRate60 = refreshRateConfigs->getMaxRefreshRateByPolicy();
@@ -167,7 +187,8 @@
{{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60},
{HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}};
auto refreshRateConfigs =
- std::make_unique<RefreshRateConfigs>(configs, /*currentConfigId=*/HWC_CONFIG_ID_60);
+ std::make_unique<RefreshRateConfigs>(/*refreshRateSwitching=*/true, configs,
+ /*currentConfigId=*/HWC_CONFIG_ID_60);
{
auto current = refreshRateConfigs->getCurrentRefreshRate();
EXPECT_EQ(current.configId, HWC_CONFIG_ID_60);
@@ -191,7 +212,10 @@
{{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60},
{HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}};
auto refreshRateConfigs =
- std::make_unique<RefreshRateConfigs>(configs, /*currentConfigId=*/HWC_CONFIG_ID_60);
+ std::make_unique<RefreshRateConfigs>(/*refreshRateSwitching=*/true, configs,
+ /*currentConfigId=*/HWC_CONFIG_ID_60);
+
+ ASSERT_TRUE(refreshRateConfigs->refreshRateSwitchingSupported());
RefreshRate expected60Config = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60};
RefreshRate expected90Config = {HWC_CONFIG_ID_90, VSYNC_90, HWC_GROUP_ID_0, "90fps", 90};
@@ -252,7 +276,10 @@
{{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60},
{HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}};
auto refreshRateConfigs =
- std::make_unique<RefreshRateConfigs>(configs, /*currentConfigId=*/HWC_CONFIG_ID_60);
+ std::make_unique<RefreshRateConfigs>(/*refreshRateSwitching=*/true, configs,
+ /*currentConfigId=*/HWC_CONFIG_ID_60);
+
+ ASSERT_TRUE(refreshRateConfigs->refreshRateSwitchingSupported());
RefreshRate expected60Config = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60};
RefreshRate expected90Config = {HWC_CONFIG_ID_90, VSYNC_90, HWC_GROUP_ID_0, "90fps", 90};
@@ -360,7 +387,10 @@
{HWC_CONFIG_ID_72, HWC_GROUP_ID_0, VSYNC_72},
{HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}};
auto refreshRateConfigs =
- std::make_unique<RefreshRateConfigs>(configs, /*currentConfigId=*/HWC_CONFIG_ID_60);
+ std::make_unique<RefreshRateConfigs>(/*refreshRateSwitching=*/true, configs,
+ /*currentConfigId=*/HWC_CONFIG_ID_60);
+
+ ASSERT_TRUE(refreshRateConfigs->refreshRateSwitchingSupported());
RefreshRate expected60Config = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60};
RefreshRate expected72Config = {HWC_CONFIG_ID_72, VSYNC_72, HWC_GROUP_ID_0, "72fps", 70};
@@ -400,7 +430,10 @@
{HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90},
{HWC_CONFIG_ID_120, HWC_GROUP_ID_0, VSYNC_120}}};
auto refreshRateConfigs =
- std::make_unique<RefreshRateConfigs>(configs, /*currentConfigId=*/HWC_CONFIG_ID_60);
+ std::make_unique<RefreshRateConfigs>(/*refreshRateSwitching=*/true, configs,
+ /*currentConfigId=*/HWC_CONFIG_ID_60);
+
+ ASSERT_TRUE(refreshRateConfigs->refreshRateSwitchingSupported());
RefreshRate expected30Config = {HWC_CONFIG_ID_30, VSYNC_30, HWC_GROUP_ID_0, "30fps", 30};
RefreshRate expected60Config = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60};
@@ -441,7 +474,8 @@
{HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90},
{HWC_CONFIG_ID_120, HWC_GROUP_ID_0, VSYNC_120}}};
auto refreshRateConfigs =
- std::make_unique<RefreshRateConfigs>(configs, /*currentConfigId=*/HWC_CONFIG_ID_60);
+ std::make_unique<RefreshRateConfigs>(/*refreshRateSwitching=*/true, configs,
+ /*currentConfigId=*/HWC_CONFIG_ID_60);
RefreshRate expected30Config = {HWC_CONFIG_ID_30, VSYNC_30, HWC_GROUP_ID_0, "30fps", 30};
RefreshRate expected60Config = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60};
@@ -508,7 +542,10 @@
{{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60},
{HWC_CONFIG_ID_30, HWC_GROUP_ID_0, VSYNC_30}}};
auto refreshRateConfigs =
- std::make_unique<RefreshRateConfigs>(configs, /*currentConfigId=*/HWC_CONFIG_ID_60);
+ std::make_unique<RefreshRateConfigs>(/*refreshRateSwitching=*/true, configs,
+ /*currentConfigId=*/HWC_CONFIG_ID_60);
+
+ ASSERT_TRUE(refreshRateConfigs->refreshRateSwitchingSupported());
RefreshRate expected60Config = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60};
RefreshRate expected30Config = {HWC_CONFIG_ID_30, VSYNC_30, HWC_GROUP_ID_0, "30fps", 30};
@@ -546,7 +583,10 @@
{HWC_CONFIG_ID_72, HWC_GROUP_ID_0, VSYNC_72},
{HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}};
auto refreshRateConfigs =
- std::make_unique<RefreshRateConfigs>(configs, /*currentConfigId=*/HWC_CONFIG_ID_60);
+ std::make_unique<RefreshRateConfigs>(/*refreshRateSwitching=*/true, configs,
+ /*currentConfigId=*/HWC_CONFIG_ID_60);
+
+ ASSERT_TRUE(refreshRateConfigs->refreshRateSwitchingSupported());
RefreshRate expected30Config = {HWC_CONFIG_ID_30, VSYNC_30, HWC_GROUP_ID_0, "30fps", 30};
RefreshRate expected60Config = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60};
@@ -585,7 +625,10 @@
{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60},
{HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}};
auto refreshRateConfigs =
- std::make_unique<RefreshRateConfigs>(configs, /*currentConfigId=*/HWC_CONFIG_ID_60);
+ std::make_unique<RefreshRateConfigs>(/*refreshRateSwitching=*/true, configs,
+ /*currentConfigId=*/HWC_CONFIG_ID_60);
+
+ ASSERT_TRUE(refreshRateConfigs->refreshRateSwitchingSupported());
RefreshRate expected30Config = {HWC_CONFIG_ID_30, VSYNC_30, HWC_GROUP_ID_0, "30fps", 30};
RefreshRate expected60Config = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60};
@@ -638,7 +681,10 @@
{{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60},
{HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}};
auto refreshRateConfigs =
- std::make_unique<RefreshRateConfigs>(configs, /*currentConfigId=*/HWC_CONFIG_ID_60);
+ std::make_unique<RefreshRateConfigs>(/*refreshRateSwitching=*/true, configs,
+ /*currentConfigId=*/HWC_CONFIG_ID_60);
+
+ ASSERT_TRUE(refreshRateConfigs->refreshRateSwitchingSupported());
RefreshRate expected30Config = {HWC_CONFIG_ID_30, VSYNC_30, HWC_GROUP_ID_0, "30fps", 30};
RefreshRate expected60Config = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60};
@@ -661,7 +707,10 @@
{{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60},
{HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}};
auto refreshRateConfigs =
- std::make_unique<RefreshRateConfigs>(configs, /*currentConfigId=*/HWC_CONFIG_ID_60);
+ std::make_unique<RefreshRateConfigs>(/*refreshRateSwitching=*/true, configs,
+ /*currentConfigId=*/HWC_CONFIG_ID_60);
+
+ ASSERT_TRUE(refreshRateConfigs->refreshRateSwitchingSupported());
RefreshRate expected60Config = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60};
RefreshRate expected90Config = {HWC_CONFIG_ID_90, VSYNC_90, HWC_GROUP_ID_0, "90fps", 90};
@@ -689,7 +738,10 @@
{{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60},
{HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}};
auto refreshRateConfigs =
- std::make_unique<RefreshRateConfigs>(configs, /*currentConfigId=*/HWC_CONFIG_ID_60);
+ std::make_unique<RefreshRateConfigs>(/*refreshRateSwitching=*/true, configs,
+ /*currentConfigId=*/HWC_CONFIG_ID_60);
+
+ ASSERT_TRUE(refreshRateConfigs->refreshRateSwitchingSupported());
RefreshRate expected60Config = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60};
RefreshRate expected90Config = {HWC_CONFIG_ID_90, VSYNC_90, HWC_GROUP_ID_0, "90fps", 90};
@@ -727,7 +779,10 @@
{{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60},
{HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}};
auto refreshRateConfigs =
- std::make_unique<RefreshRateConfigs>(configs, /*currentConfigId=*/HWC_CONFIG_ID_60);
+ std::make_unique<RefreshRateConfigs>(/*refreshRateSwitching=*/true, configs,
+ /*currentConfigId=*/HWC_CONFIG_ID_60);
+
+ ASSERT_TRUE(refreshRateConfigs->refreshRateSwitchingSupported());
RefreshRate expected30Config = {HWC_CONFIG_ID_30, VSYNC_30, HWC_GROUP_ID_0, "30fps", 30};
RefreshRate expected60Config = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60};
diff --git a/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp
index 18d6bd2..8e07c79 100644
--- a/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp
+++ b/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp
@@ -47,8 +47,8 @@
~RefreshRateStatsTest();
void init(const std::vector<RefreshRateConfigs::InputConfig>& configs) {
- mRefreshRateConfigs =
- std::make_unique<RefreshRateConfigs>(configs, /*currentConfig=*/CONFIG_ID_0);
+ mRefreshRateConfigs = std::make_unique<RefreshRateConfigs>(
+ /*refreshRateSwitching=*/true, configs, /*currentConfig=*/CONFIG_ID_0);
mRefreshRateStats =
std::make_unique<RefreshRateStats>(*mRefreshRateConfigs, mTimeStats,
/*currentConfigId=*/CONFIG_ID_0,
diff --git a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
index 89002a8..82a00ee 100644
--- a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
@@ -73,7 +73,8 @@
std::vector<scheduler::RefreshRateConfigs::InputConfig> configs{
{{HwcConfigIndexType(0), HwcConfigGroupType(0), 16666667}}};
mRefreshRateConfigs = std::make_unique<
- scheduler::RefreshRateConfigs>(configs, /*currentConfig=*/HwcConfigIndexType(0));
+ scheduler::RefreshRateConfigs>(/*refreshRateSwitching=*/false, configs,
+ /*currentConfig=*/HwcConfigIndexType(0));
mScheduler = std::make_unique<TestableScheduler>(*mRefreshRateConfigs, false);
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index be233bb..64838ca 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -17,7 +17,6 @@
#pragma once
#include <compositionengine/Display.h>
-#include <compositionengine/Layer.h>
#include <compositionengine/LayerFECompositionState.h>
#include <compositionengine/OutputLayer.h>
#include <compositionengine/impl/CompositionEngine.h>
@@ -203,7 +202,8 @@
std::vector<scheduler::RefreshRateConfigs::InputConfig> configs{
{{HwcConfigIndexType(0), HwcConfigGroupType(0), 16666667}}};
mFlinger->mRefreshRateConfigs = std::make_unique<
- scheduler::RefreshRateConfigs>(configs, /*currentConfig=*/HwcConfigIndexType(0));
+ scheduler::RefreshRateConfigs>(/*refreshRateSwitching=*/false, configs,
+ /*currentConfig=*/HwcConfigIndexType(0));
mFlinger->mRefreshRateStats = std::make_unique<
scheduler::RefreshRateStats>(*mFlinger->mRefreshRateConfigs, *mFlinger->mTimeStats,
/*currentConfig=*/HwcConfigIndexType(0),
@@ -251,7 +251,7 @@
void setLayerSidebandStream(sp<Layer> layer, sp<NativeHandle> sidebandStream) {
layer->mDrawingState.sidebandStream = sidebandStream;
layer->mSidebandStream = sidebandStream;
- layer->getCompositionLayer()->editFEState().sidebandStream = sidebandStream;
+ layer->editCompositionState()->sidebandStream = sidebandStream;
}
void setLayerCompositionType(sp<Layer> layer, HWC2::Composition type) {
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));
}
diff --git a/services/surfaceflinger/tests/utils/CallbackUtils.h b/services/surfaceflinger/tests/utils/CallbackUtils.h
index 4e2b7c3..1318deb 100644
--- a/services/surfaceflinger/tests/utils/CallbackUtils.h
+++ b/services/surfaceflinger/tests/utils/CallbackUtils.h
@@ -121,8 +121,10 @@
void verifySurfaceControlStats(const SurfaceControlStats& surfaceControlStats,
nsecs_t latchTime) const {
- const auto& [surfaceControl, acquireTime, previousReleaseFence, transformHint] =
- surfaceControlStats;
+ const auto&
+ [surfaceControl, latch, acquireTime, presentFence, previousReleaseFence,
+ transformHint,
+ frameEvents] = surfaceControlStats;
ASSERT_EQ(acquireTime > 0, mBufferResult == ExpectedResult::Buffer::ACQUIRED)
<< "bad acquire time";