Merge "SurfaceFlinger: support negative phase offset" into qt-dev
diff --git a/include/audiomanager/AudioManager.h b/include/audiomanager/AudioManager.h
index 009dc52..639df7a 100644
--- a/include/audiomanager/AudioManager.h
+++ b/include/audiomanager/AudioManager.h
@@ -20,7 +20,6 @@
namespace android {
// must be kept in sync with definitions in AudioPlaybackConfiguration.java
-
#define PLAYER_PIID_INVALID -1
typedef enum {
@@ -40,6 +39,15 @@
PLAYER_STATE_STOPPED = 4,
} player_state_t;
+// must be kept in sync with definitions in AudioManager.java
+#define RECORD_RIID_INVALID -1
+
+typedef enum {
+ RECORDER_STATE_UNKNOWN = -1,
+ RECORDER_STATE_STARTED = 0,
+ RECORDER_STATE_STOPPED = 1,
+} recorder_state_t;
+
}; // namespace android
#endif // ANDROID_AUDIOMANAGER_H
diff --git a/include/audiomanager/IAudioManager.h b/include/audiomanager/IAudioManager.h
index d279bbd..d0642c6 100644
--- a/include/audiomanager/IAudioManager.h
+++ b/include/audiomanager/IAudioManager.h
@@ -36,6 +36,8 @@
PLAYER_ATTRIBUTES = IBinder::FIRST_CALL_TRANSACTION + 1,
PLAYER_EVENT = IBinder::FIRST_CALL_TRANSACTION + 2,
RELEASE_PLAYER = IBinder::FIRST_CALL_TRANSACTION + 3,
+ TRACK_RECORDER = IBinder::FIRST_CALL_TRANSACTION + 4,
+ RECORDER_EVENT = IBinder::FIRST_CALL_TRANSACTION + 5,
};
DECLARE_META_INTERFACE(AudioManager)
@@ -48,6 +50,8 @@
audio_content_type_t content)= 0;
/*oneway*/ virtual status_t playerEvent(audio_unique_id_t piid, player_state_t event) = 0;
/*oneway*/ virtual status_t releasePlayer(audio_unique_id_t piid) = 0;
+ virtual audio_unique_id_t trackRecorder(const sp<IBinder>& recorder) = 0;
+ /*oneway*/ virtual status_t recorderEvent(audio_unique_id_t riid, recorder_state_t event) = 0;
};
// ----------------------------------------------------------------------------
diff --git a/libs/binder/IAppOpsCallback.cpp b/libs/binder/IAppOpsCallback.cpp
index 2f4dbee..aba4967 100644
--- a/libs/binder/IAppOpsCallback.cpp
+++ b/libs/binder/IAppOpsCallback.cpp
@@ -57,7 +57,8 @@
case OP_CHANGED_TRANSACTION: {
CHECK_INTERFACE(IAppOpsCallback, data, reply);
int32_t op = data.readInt32();
- String16 packageName = data.readString16();
+ String16 packageName;
+ (void)data.readString16(&packageName);
opChanged(op, packageName);
reply->writeNoException();
return NO_ERROR;
diff --git a/libs/dumputils/dump_utils.cpp b/libs/dumputils/dump_utils.cpp
index 53ca7ea..26c2a0d 100644
--- a/libs/dumputils/dump_utils.cpp
+++ b/libs/dumputils/dump_utils.cpp
@@ -54,8 +54,10 @@
"android.hardware.media.c2@1.0::IComponentStore",
"android.hardware.media.omx@1.0::IOmx",
"android.hardware.media.omx@1.0::IOmxStore",
+ "android.hardware.power@1.3::IPower",
"android.hardware.power.stats@1.0::IPowerStats",
"android.hardware.sensors@1.0::ISensors",
+ "android.hardware.thermal@2.0::IThermal",
"android.hardware.vr@1.0::IVr",
NULL,
};
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 2083a2b..437cdd7 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -1149,8 +1149,12 @@
int x = dst.left;
int y = dst.top;
- float xScale = dst.getWidth() / static_cast<float>(source.getWidth());
- float yScale = dst.getHeight() / static_cast<float>(source.getHeight());
+
+ float sourceWidth = source.getWidth();
+ float sourceHeight = source.getHeight();
+
+ float xScale = sourceWidth < 0 ? 1.0f : dst.getWidth() / sourceWidth;
+ float yScale = sourceHeight < 0 ? 1.0f : dst.getHeight() / sourceHeight;
float matrix[4] = {1, 0, 0, 1};
switch (transform) {
diff --git a/libs/renderengine/gl/GLESRenderEngine.cpp b/libs/renderengine/gl/GLESRenderEngine.cpp
index faf6d2a..48cb620 100644
--- a/libs/renderengine/gl/GLESRenderEngine.cpp
+++ b/libs/renderengine/gl/GLESRenderEngine.cpp
@@ -540,16 +540,14 @@
return false;
}
- EGLint attribs[] = {EGL_SYNC_NATIVE_FENCE_FD_ANDROID, fenceFd, EGL_NONE};
+ // release the fd and transfer the ownership to EGLSync
+ EGLint attribs[] = {EGL_SYNC_NATIVE_FENCE_FD_ANDROID, fenceFd.release(), EGL_NONE};
EGLSyncKHR sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, attribs);
if (sync == EGL_NO_SYNC_KHR) {
ALOGE("failed to create EGL native fence sync: %#x", eglGetError());
return false;
}
- // fenceFd is now owned by EGLSync
- (void)fenceFd.release();
-
// XXX: The spec draft is inconsistent as to whether this should return an
// EGLint or void. Ignore the return value for now, as it's not strictly
// needed.
diff --git a/libs/renderengine/gl/ProgramCache.cpp b/libs/renderengine/gl/ProgramCache.cpp
index cd1182c..086a324 100644
--- a/libs/renderengine/gl/ProgramCache.cpp
+++ b/libs/renderengine/gl/ProgramCache.cpp
@@ -575,7 +575,9 @@
float applyCornerRadius(vec2 cropCoords)
{
vec2 position = cropCoords - cropCenter;
- vec2 dist = abs(position) + vec2(cornerRadius) - cropCenter;
+ // Increase precision here so that a large corner radius doesn't
+ // cause floating point error
+ highp vec2 dist = abs(position) + vec2(cornerRadius) - cropCenter;
float plane = length(max(dist, vec2(0.0)));
return 1.0 - clamp(plane - cornerRadius, 0.0, 1.0);
}
diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp
index 755418e..0407d88 100644
--- a/libs/ui/Android.bp
+++ b/libs/ui/Android.bp
@@ -82,6 +82,9 @@
"frameworks/native/include",
],
+ // Uncomment the following line to enable VALIDATE_REGIONS traces
+ //defaults: ["libui-validate-regions-defaults"],
+
shared_libs: [
"android.frameworks.bufferhub@1.0",
"android.hardware.graphics.allocator@2.0",
@@ -98,7 +101,6 @@
"libhwbinder",
"libsync",
"libutils",
- "libutilscallstack",
"liblog",
],
@@ -175,6 +177,13 @@
],
}
+// defaults to enable VALIDATE_REGIONS traces
+cc_defaults {
+ name: "libui-validate-regions-defaults",
+ shared_libs: ["libutilscallstack"],
+ cflags: ["-DVALIDATE_REGIONS"],
+}
+
subdirs = [
"tests",
"tools",
diff --git a/libs/ui/Region.cpp b/libs/ui/Region.cpp
index 224dc2c..55e3b99 100644
--- a/libs/ui/Region.cpp
+++ b/libs/ui/Region.cpp
@@ -22,7 +22,6 @@
#include <android-base/stringprintf.h>
#include <utils/Log.h>
-#include <utils/CallStack.h>
#include <ui/Rect.h>
#include <ui/Region.h>
@@ -31,10 +30,18 @@
#include <private/ui/RegionHelper.h>
// ----------------------------------------------------------------------------
-#define VALIDATE_REGIONS (false)
+
+// ### VALIDATE_REGIONS ###
+// To enable VALIDATE_REGIONS traces, use the "libui-validate-regions-defaults"
+// in Android.bp. Do not #define VALIDATE_REGIONS here as it requires extra libs.
+
#define VALIDATE_WITH_CORECG (false)
// ----------------------------------------------------------------------------
+#if defined(VALIDATE_REGIONS)
+#include <utils/CallStack.h>
+#endif
+
#if VALIDATE_WITH_CORECG
#include <core/SkRegion.h>
#endif
@@ -67,7 +74,7 @@
Region::Region(const Region& rhs)
: mStorage(rhs.mStorage)
{
-#if VALIDATE_REGIONS
+#if defined(VALIDATE_REGIONS)
validate(rhs, "rhs copy-ctor");
#endif
}
@@ -203,7 +210,7 @@
outputRegion.mStorage, direction_LTR);
outputRegion.mStorage.add(r.getBounds()); // to make region valid, mStorage must end with bounds
-#if VALIDATE_REGIONS
+#if defined(VALIDATE_REGIONS)
validate(outputRegion, "T-Junction free region");
#endif
@@ -212,7 +219,7 @@
Region& Region::operator = (const Region& rhs)
{
-#if VALIDATE_REGIONS
+#if defined(VALIDATE_REGIONS)
validate(*this, "this->operator=");
validate(rhs, "rhs.operator=");
#endif
@@ -599,10 +606,12 @@
result = false;
ALOGE_IF(!silent, "%s: mStorage size is 2, which is never valid", name);
}
+#if defined(VALIDATE_REGIONS)
if (result == false && !silent) {
reg.dump(name);
CallStack stack(LOG_TAG);
}
+#endif
return result;
}
@@ -610,7 +619,7 @@
const Region& lhs,
const Region& rhs, int dx, int dy)
{
-#if VALIDATE_REGIONS
+#if defined(VALIDATE_REGIONS)
validate(lhs, "boolean_operation (before): lhs");
validate(rhs, "boolean_operation (before): rhs");
validate(dst, "boolean_operation (before): dst");
@@ -630,7 +639,7 @@
operation(r);
}
-#if VALIDATE_REGIONS
+#if defined(VALIDATE_REGIONS)
validate(lhs, "boolean_operation: lhs");
validate(rhs, "boolean_operation: rhs");
validate(dst, "boolean_operation: dst");
@@ -728,7 +737,7 @@
return;
}
-#if VALIDATE_WITH_CORECG || VALIDATE_REGIONS
+#if VALIDATE_WITH_CORECG || defined(VALIDATE_REGIONS)
boolean_operation(op, dst, lhs, Region(rhs), dx, dy);
#else
size_t lhs_count;
@@ -760,7 +769,7 @@
void Region::translate(Region& reg, int dx, int dy)
{
if ((dx || dy) && !reg.isEmpty()) {
-#if VALIDATE_REGIONS
+#if defined(VALIDATE_REGIONS)
validate(reg, "translate (before)");
#endif
size_t count = reg.mStorage.size();
@@ -770,7 +779,7 @@
rects++;
count--;
}
-#if VALIDATE_REGIONS
+#if defined(VALIDATE_REGIONS)
validate(reg, "translate (after)");
#endif
}
@@ -789,7 +798,7 @@
}
status_t Region::flatten(void* buffer, size_t size) const {
-#if VALIDATE_REGIONS
+#if defined(VALIDATE_REGIONS)
validate(*this, "Region::flatten");
#endif
if (size < getFlattenedSize()) {
@@ -836,7 +845,7 @@
result.mStorage.push_back(rect);
}
-#if VALIDATE_REGIONS
+#if defined(VALIDATE_REGIONS)
validate(result, "Region::unflatten");
#endif
diff --git a/opengl/libs/EGL/Loader.cpp b/opengl/libs/EGL/Loader.cpp
index 10dd8cb..95c41bc 100644
--- a/opengl/libs/EGL/Loader.cpp
+++ b/opengl/libs/EGL/Loader.cpp
@@ -69,41 +69,6 @@
return loader;
}
-/* This function is called to check whether we run inside the emulator,
- * and if this is the case whether GLES GPU emulation is supported.
- *
- * Returned values are:
- * -1 -> not running inside the emulator
- * 0 -> running inside the emulator, but GPU emulation not supported
- * 1 -> running inside the emulator, GPU emulation is supported
- * through the "emulation" host-side OpenGL ES implementation.
- * 2 -> running inside the emulator, GPU emulation is supported
- * through a guest-side vendor driver's OpenGL ES implementation.
- */
-static int
-checkGlesEmulationStatus(void)
-{
- /* We're going to check for the following kernel parameters:
- *
- * qemu=1 -> tells us that we run inside the emulator
- * android.qemu.gles=<number> -> tells us the GLES GPU emulation status
- *
- * Note that we will return <number> if we find it. This let us support
- * more additionnal emulation modes in the future.
- */
- char prop[PROPERTY_VALUE_MAX];
- int result = -1;
-
- /* First, check for qemu=1 */
- property_get("ro.kernel.qemu",prop,"0");
- if (atoi(prop) != 1)
- return -1;
-
- /* We are in the emulator, get GPU status value */
- property_get("qemu.gles",prop,"0");
- return atoi(prop);
-}
-
static void* do_dlopen(const char* path, int mode) {
ATRACE_CALL();
return dlopen(path, mode);
@@ -208,6 +173,11 @@
}
}
+static const char* HAL_SUBNAME_KEY_PROPERTIES[2] = {
+ "ro.hardware.egl",
+ "ro.board.platform",
+};
+
void* Loader::open(egl_connection_t* cnx)
{
ATRACE_CALL();
@@ -229,12 +199,30 @@
hnd = attempt_to_load_updated_driver(cnx);
}
if (!hnd) {
- // Thirdly, try to load emulation driver.
- hnd = attempt_to_load_emulation_driver(cnx);
+ // Finally, try to load system driver, start by searching for the library name appended by
+ // the system properties of the GLES userspace driver in both locations.
+ // i.e.:
+ // libGLES_${prop}.so, or:
+ // libEGL_${prop}.so, libGLESv1_CM_${prop}.so, libGLESv2_${prop}.so
+ char prop[PROPERTY_VALUE_MAX + 1];
+ for (auto key : HAL_SUBNAME_KEY_PROPERTIES) {
+ if (property_get(key, prop, nullptr) <= 0) {
+ continue;
+ }
+ hnd = attempt_to_load_system_driver(cnx, prop);
+ if (hnd) {
+ break;
+ }
+ }
}
+
if (!hnd) {
- // Finally, load system driver.
- hnd = attempt_to_load_system_driver(cnx);
+ // Can't find graphics driver by appending system properties, now search for the exact name
+ // without any suffix of the GLES userspace driver in both locations.
+ // i.e.:
+ // libGLES.so, or:
+ // libEGL.so, libGLESv1_CM.so, libGLESv2.so
+ hnd = attempt_to_load_system_driver(cnx, nullptr);
}
if (!hnd) {
@@ -242,7 +230,9 @@
false, systemTime() - openTime);
}
- LOG_ALWAYS_FATAL_IF(!hnd, "couldn't find an OpenGL ES implementation");
+ LOG_ALWAYS_FATAL_IF(!hnd,
+ "couldn't find an OpenGL ES implementation, make sure you set %s or %s",
+ HAL_SUBNAME_KEY_PROPERTIES[0], HAL_SUBNAME_KEY_PROPERTIES[1]);
cnx->libEgl = load_wrapper(EGL_WRAPPER_DIR "/libEGL.so");
cnx->libGles2 = load_wrapper(EGL_WRAPPER_DIR "/libGLESv2.so");
@@ -350,71 +340,11 @@
}
}
-static void* load_emulation_driver(const char* kind) {
- const int emulationStatus = checkGlesEmulationStatus();
-
- // Invalid emulation status, abort.
- if (emulationStatus < 0 || emulationStatus > 2) {
- return nullptr;
- }
-
- std::string absolutePath;
- switch (emulationStatus) {
- case 0:
-#if defined(__LP64__)
- absolutePath = "/vendor/lib64/egl/libGLES_android.so";
-#else
- absolutePath = "/vendor/lib/egl/libGLES_android.so";
-#endif
- break;
- case 1:
- // Use host-side OpenGL through the "emulation" library
-#if defined(__LP64__)
- absolutePath = std::string("/vendor/lib64/egl/lib") + kind + "_emulation.so";
-#else
- absolutePath = std::string("/vendor/lib/egl/lib") + kind + "_emulation.so";
-#endif
- break;
- case 2:
- // Use guest side swiftshader library
-#if defined(__LP64__)
- absolutePath = std::string("/vendor/lib64/egl/lib") + kind + "_swiftshader.so";
-#else
- absolutePath = std::string("/vendor/lib/egl/lib") + kind + "_swiftshader.so";
-#endif
- break;
- default:
- // Not in emulator, or use other guest-side implementation
- break;
- }
- if (absolutePath.empty()) {
- // this happens often, we don't want to log an error
- return nullptr;
- }
- const char* const driver_absolute_path = absolutePath.c_str();
-
- // Try to load drivers from the 'sphal' namespace, if it exist. Fall back to
- // the original routine when the namespace does not exist.
- // See /system/core/rootdir/etc/ld.config.txt for the configuration of the
- // sphal namespace.
- void* dso = do_android_load_sphal_library(driver_absolute_path,
- RTLD_NOW | RTLD_LOCAL);
- if (dso == nullptr) {
- const char* err = dlerror();
- ALOGE("load_driver(%s): %s", driver_absolute_path, err ? err : "unknown");
- return nullptr;
- }
- ALOGD("loaded %s", driver_absolute_path);
- return dso;
-}
-
-static void* load_system_driver(const char* kind) {
+static void* load_system_driver(const char* kind, const char* suffix) {
ATRACE_CALL();
class MatchFile {
public:
- static std::string find(const char* kind) {
- std::string result;
- std::string pattern = std::string("lib") + kind;
+ static std::string find(const char* libraryName) {
const char* const searchPaths[] = {
#if defined(__LP64__)
"/vendor/lib64/egl",
@@ -425,74 +355,23 @@
#endif
};
- // first, we search for the exact name of the GLES userspace
- // driver in both locations.
- // i.e.:
- // libGLES.so, or:
- // libEGL.so, libGLESv1_CM.so, libGLESv2.so
-
- for (size_t i=0 ; i<NELEM(searchPaths) ; i++) {
- if (find(result, pattern, searchPaths[i], true)) {
- return result;
- }
- }
-
- // for compatibility with the old "egl.cfg" naming convention
- // we look for files that match:
- // libGLES_*.so, or:
- // libEGL_*.so, libGLESv1_CM_*.so, libGLESv2_*.so
-
- pattern.append("_");
- for (size_t i=0 ; i<NELEM(searchPaths) ; i++) {
- if (find(result, pattern, searchPaths[i], false)) {
- return result;
- }
- }
-
- // we didn't find the driver. gah.
- result.clear();
- return result;
- }
-
- private:
- static bool find(std::string& result,
- const std::string& pattern, const char* const search, bool exact) {
- if (exact) {
- std::string absolutePath = std::string(search) + "/" + pattern + ".so";
+ for (auto dir : searchPaths) {
+ std::string absolutePath = dir + std::string("/") + libraryName + ".so";
if (!access(absolutePath.c_str(), R_OK)) {
- result = absolutePath;
- return true;
+ return absolutePath;
}
- return false;
}
- DIR* d = opendir(search);
- if (d != nullptr) {
- struct dirent* e;
- while ((e = readdir(d)) != nullptr) {
- if (e->d_type == DT_DIR) {
- continue;
- }
- if (!strcmp(e->d_name, "libGLES_android.so")) {
- // always skip the software renderer
- continue;
- }
- if (strstr(e->d_name, pattern.c_str()) == e->d_name) {
- if (!strcmp(e->d_name + strlen(e->d_name) - 3, ".so")) {
- result = std::string(search) + "/" + e->d_name;
- closedir(d);
- return true;
- }
- }
- }
- closedir(d);
- }
- return false;
+ // Driver not found. gah.
+ return std::string();
}
};
-
- std::string absolutePath = MatchFile::find(kind);
+ std::string libraryName = std::string("lib") + kind;
+ if (suffix) {
+ libraryName += std::string("_") + suffix;
+ }
+ std::string absolutePath = MatchFile::find(libraryName.c_str());
if (absolutePath.empty()) {
// this happens often, we don't want to log an error
return nullptr;
@@ -574,7 +453,20 @@
cnx->angleBackend = angleBackendDefault;
if (!cnx->vendorEGL && (cnx->angleBackend == EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE)) {
// Find and load vendor libEGL for ANGLE's GL back-end to use.
- cnx->vendorEGL = load_system_driver("EGL");
+ char prop[PROPERTY_VALUE_MAX + 1];
+ for (auto key : HAL_SUBNAME_KEY_PROPERTIES) {
+ if (property_get(key, prop, nullptr) <= 0) {
+ continue;
+ }
+ void* dso = load_system_driver("EGL", prop);
+ if (dso) {
+ cnx->vendorEGL = dso;
+ break;
+ }
+ }
+ if (!cnx->vendorEGL) {
+ cnx->vendorEGL = load_system_driver("EGL", nullptr);
+ }
}
} else {
ALOGV("Loaded native %s library for '%s' (instead of ANGLE)", kind,
@@ -586,11 +478,6 @@
return so;
}
-static const char* HAL_SUBNAME_KEY_PROPERTIES[2] = {
- "ro.hardware.egl",
- "ro.board.platform",
-};
-
static void* load_updated_driver(const char* kind, android_namespace_t* ns) {
ATRACE_CALL();
const android_dlextinfo dlextinfo = {
@@ -600,12 +487,13 @@
void* so = nullptr;
char prop[PROPERTY_VALUE_MAX + 1];
for (auto key : HAL_SUBNAME_KEY_PROPERTIES) {
- if (property_get(key, prop, nullptr) > 0) {
- std::string name = std::string("lib") + kind + "_" + prop + ".so";
- so = do_android_dlopen_ext(name.c_str(), RTLD_LOCAL | RTLD_NOW, &dlextinfo);
- if (so) {
- return so;
- }
+ if (property_get(key, prop, nullptr) <= 0) {
+ continue;
+ }
+ std::string name = std::string("lib") + kind + "_" + prop + ".so";
+ so = do_android_dlopen_ext(name.c_str(), RTLD_LOCAL | RTLD_NOW, &dlextinfo);
+ if (so) {
+ return so;
}
}
return nullptr;
@@ -674,52 +562,26 @@
#endif
}
-Loader::driver_t* Loader::attempt_to_load_emulation_driver(egl_connection_t* cnx) {
+Loader::driver_t* Loader::attempt_to_load_system_driver(egl_connection_t* cnx, const char* suffix) {
ATRACE_CALL();
android::GraphicsEnv::getInstance().setDriverToLoad(android::GraphicsEnv::Driver::GL);
driver_t* hnd = nullptr;
- void* dso = load_emulation_driver("GLES");
+ void* dso = load_system_driver("GLES", suffix);
if (dso) {
initialize_api(dso, cnx, EGL | GLESv1_CM | GLESv2);
hnd = new driver_t(dso);
return hnd;
}
- dso = load_emulation_driver("EGL");
+ dso = load_system_driver("EGL", suffix);
if (dso) {
initialize_api(dso, cnx, EGL);
hnd = new driver_t(dso);
- dso = load_emulation_driver("GLESv1_CM");
+ dso = load_system_driver("GLESv1_CM", suffix);
initialize_api(dso, cnx, GLESv1_CM);
hnd->set(dso, GLESv1_CM);
- dso = load_emulation_driver("GLESv2");
- initialize_api(dso, cnx, GLESv2);
- hnd->set(dso, GLESv2);
- }
- return hnd;
-}
-
-Loader::driver_t* Loader::attempt_to_load_system_driver(egl_connection_t* cnx) {
- ATRACE_CALL();
- android::GraphicsEnv::getInstance().setDriverToLoad(android::GraphicsEnv::Driver::GL);
- driver_t* hnd = nullptr;
- void* dso = load_system_driver("GLES");
- if (dso) {
- initialize_api(dso, cnx, EGL | GLESv1_CM | GLESv2);
- hnd = new driver_t(dso);
- return hnd;
- }
- dso = load_system_driver("EGL");
- if (dso) {
- initialize_api(dso, cnx, EGL);
- hnd = new driver_t(dso);
-
- dso = load_system_driver("GLESv1_CM");
- initialize_api(dso, cnx, GLESv1_CM);
- hnd->set(dso, GLESv1_CM);
-
- dso = load_system_driver("GLESv2");
+ dso = load_system_driver("GLESv2", suffix);
initialize_api(dso, cnx, GLESv2);
hnd->set(dso, GLESv2);
}
diff --git a/opengl/libs/EGL/Loader.h b/opengl/libs/EGL/Loader.h
index c0f1b75..f6b67ab 100644
--- a/opengl/libs/EGL/Loader.h
+++ b/opengl/libs/EGL/Loader.h
@@ -57,8 +57,7 @@
Loader();
driver_t* attempt_to_load_angle(egl_connection_t* cnx);
driver_t* attempt_to_load_updated_driver(egl_connection_t* cnx);
- driver_t* attempt_to_load_emulation_driver(egl_connection_t* cnx);
- driver_t* attempt_to_load_system_driver(egl_connection_t* cnx);
+ driver_t* attempt_to_load_system_driver(egl_connection_t* cnx, const char* suffix);
void initialize_api(void* dso, egl_connection_t* cnx, uint32_t mask);
static __attribute__((noinline))
diff --git a/services/audiomanager/IAudioManager.cpp b/services/audiomanager/IAudioManager.cpp
index b9b0706..f5d4826 100644
--- a/services/audiomanager/IAudioManager.cpp
+++ b/services/audiomanager/IAudioManager.cpp
@@ -98,6 +98,30 @@
data.writeInt32((int32_t) piid);
return remote()->transact(RELEASE_PLAYER, data, &reply, IBinder::FLAG_ONEWAY);
}
+
+ virtual audio_unique_id_t trackRecorder(const sp<IBinder>& recorder) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioManager::getInterfaceDescriptor());
+ data.writeStrongBinder(recorder);
+ // get new RIId in reply
+ const status_t res = remote()->transact(TRACK_RECORDER, data, &reply, 0);
+ if (res != OK || reply.readExceptionCode() != 0) {
+ ALOGE("trackRecorder() failed, riid is %d", RECORD_RIID_INVALID);
+ return RECORD_RIID_INVALID;
+ } else {
+ const audio_unique_id_t riid = (audio_unique_id_t) reply.readInt32();
+ ALOGV("trackRecorder() returned riid %d", riid);
+ return riid;
+ }
+ }
+
+ virtual status_t recorderEvent(audio_unique_id_t riid, recorder_state_t event) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioManager::getInterfaceDescriptor());
+ data.writeInt32((int32_t) riid);
+ data.writeInt32((int32_t) event);
+ return remote()->transact(RECORDER_EVENT, data, &reply, IBinder::FLAG_ONEWAY);
+ }
};
IMPLEMENT_META_INTERFACE(AudioManager, "android.media.IAudioService");
diff --git a/services/inputflinger/InputClassifier.cpp b/services/inputflinger/InputClassifier.cpp
index b4db338..4a6efa6 100644
--- a/services/inputflinger/InputClassifier.cpp
+++ b/services/inputflinger/InputClassifier.cpp
@@ -507,19 +507,53 @@
// --- MotionClassifier ---
-MotionClassifier::MotionClassifier(
- sp<android::hardware::input::classifier::V1_0::IInputClassifier> service) :
- mEvents(MAX_EVENTS), mService(service) {
+MotionClassifier::MotionClassifier(sp<android::hardware::hidl_death_recipient> deathRecipient) :
+ mDeathRecipient(deathRecipient), mEvents(MAX_EVENTS) {
mHalThread = std::thread(&MotionClassifier::callInputClassifierHal, this);
#if defined(__linux__)
// Set the thread name for debugging
pthread_setname_np(mHalThread.native_handle(), "InputClassifier");
#endif
+}
+
+/**
+ * This function may block for some time to initialize the HAL, so it should only be called
+ * from the "InputClassifier HAL" thread.
+ */
+bool MotionClassifier::init() {
+ ensureHalThread(__func__);
+ sp<android::hardware::input::classifier::V1_0::IInputClassifier> service =
+ classifier::V1_0::IInputClassifier::getService();
+ if (!service) {
+ // Not really an error, maybe the device does not have this HAL,
+ // but somehow the feature flag is flipped
+ ALOGI("Could not obtain InputClassifier HAL");
+ return false;
+ }
+
+ sp<android::hardware::hidl_death_recipient> recipient = mDeathRecipient.promote();
+ if (recipient != nullptr) {
+ const bool linked = service->linkToDeath(recipient, 0 /* cookie */).withDefault(false);
+ if (!linked) {
+ ALOGE("Could not link MotionClassifier to the HAL death");
+ return false;
+ }
+ }
+
// Under normal operation, we do not need to reset the HAL here. But in the case where system
// crashed, but HAL didn't, we may be connecting to an existing HAL process that might already
// have received events in the past. That means, that HAL could be in an inconsistent state
// once it receives events from the newly created MotionClassifier.
mEvents.push(ClassifierEvent::createHalResetEvent());
+
+ {
+ std::scoped_lock lock(mLock);
+ if (mService) {
+ ALOGE("MotionClassifier::%s should only be called once", __func__);
+ }
+ mService = service;
+ }
+ return true;
}
MotionClassifier::~MotionClassifier() {
@@ -530,7 +564,7 @@
void MotionClassifier::ensureHalThread(const char* function) {
if (DEBUG) {
if (std::this_thread::get_id() != mHalThread.get_id()) {
- ALOGE("Function %s should only be called from InputClassifier thread", function);
+ LOG_FATAL("Function %s should only be called from InputClassifier thread", function);
}
}
}
@@ -547,6 +581,21 @@
*/
void MotionClassifier::callInputClassifierHal() {
ensureHalThread(__func__);
+ const bool initialized = init();
+ if (!initialized) {
+ // MotionClassifier no longer useful.
+ // Deliver death notification from a separate thread
+ // because ~MotionClassifier may be invoked, which calls mHalThread.join()
+ std::thread([deathRecipient = mDeathRecipient](){
+ sp<android::hardware::hidl_death_recipient> recipient = deathRecipient.promote();
+ if (recipient != nullptr) {
+ recipient->serviceDied(0 /*cookie*/, nullptr);
+ }
+ }).detach();
+ return;
+ }
+ // From this point on, mService is guaranteed to be non-null.
+
while (true) {
ClassifierEvent event = mEvents.pop();
bool halResponseOk = true;
@@ -666,10 +715,19 @@
enqueueEvent(std::make_unique<NotifyDeviceResetArgs>(args));
}
+const char* MotionClassifier::getServiceStatus() REQUIRES(mLock) {
+ if (!mService) {
+ return "null";
+ }
+ if (mService->ping().isOk()) {
+ return "running";
+ }
+ return "not responding";
+}
+
void MotionClassifier::dump(std::string& dump) {
std::scoped_lock lock(mLock);
- std::string serviceStatus = mService->ping().isOk() ? "running" : " not responding";
- dump += StringPrintf(INDENT2 "mService status: %s\n", serviceStatus.c_str());
+ dump += StringPrintf(INDENT2 "mService status: %s\n", getServiceStatus());
dump += StringPrintf(INDENT2 "mEvents: %zu element(s) (max=%zu)\n",
mEvents.size(), MAX_EVENTS);
dump += INDENT2 "mClassifications, mLastDownTimes:\n";
@@ -700,28 +758,14 @@
}
void InputClassifier::onFirstRef() {
- std::scoped_lock lock(mLock);
if (!deepPressEnabled()) {
- // If feature is not enabled, the InputClassifier will just be in passthrough
- // mode, and will forward all events to the next InputListener, unmodified
+ // If feature is not enabled, MotionClassifier should stay null to avoid unnecessary work.
+ // When MotionClassifier is null, InputClassifier will forward all events
+ // to the next InputListener, unmodified.
return;
}
-
- sp<android::hardware::input::classifier::V1_0::IInputClassifier> service =
- classifier::V1_0::IInputClassifier::getService();
- if (!service) {
- // Not really an error, maybe the device does not have this HAL,
- // but somehow the feature flag is flipped
- ALOGI("Could not obtain InputClassifier HAL");
- return;
- }
- const bool linked = service->linkToDeath(this, 0 /* cookie */).withDefault(false);
- if (!linked) {
- ALOGE("Could not link android::InputClassifier to the HAL death");
- return;
- }
-
- mMotionClassifier = std::make_unique<MotionClassifier>(service);
+ std::scoped_lock lock(mLock);
+ mMotionClassifier = std::make_unique<MotionClassifier>(this);
}
void InputClassifier::notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) {
@@ -786,4 +830,4 @@
dump += "\n";
}
-} // namespace android
\ No newline at end of file
+} // namespace android
diff --git a/services/inputflinger/InputClassifier.h b/services/inputflinger/InputClassifier.h
index 0b1483f..47e20db 100644
--- a/services/inputflinger/InputClassifier.h
+++ b/services/inputflinger/InputClassifier.h
@@ -114,15 +114,22 @@
class MotionClassifier final : public MotionClassifierInterface {
public:
/**
- * The provided pointer to the service cannot be null.
+ * The deathRecipient will be subscribed to the HAL death. If the death recipient
+ * owns MotionClassifier and receives HAL death, it should delete its copy of it.
+ * The callback serviceDied will also be sent if the MotionClassifier itself fails
+ * to initialize. If the MotionClassifier fails to initialize, it is not useful, and
+ * should be deleted.
+ * If no death recipient is supplied, then the registration step will be skipped, so there will
+ * be no listeners registered for the HAL death. This is useful for testing
+ * MotionClassifier in isolation.
*/
- MotionClassifier(sp<android::hardware::input::classifier::V1_0::IInputClassifier> service);
+ explicit MotionClassifier(sp<android::hardware::hidl_death_recipient> deathRecipient = nullptr);
~MotionClassifier();
+
/**
* Classifies events asynchronously; that is, it doesn't block events on a classification,
- * but instead sends them over to the classifier HAL
- * and after a classification is determined,
- * it then marks the next event it sees in the stream with it.
+ * but instead sends them over to the classifier HAL and after a classification is
+ * determined, it then marks the next event it sees in the stream with it.
*
* Therefore, it is acceptable to have the classifications be delayed by 1-2 events
* in a particular gesture.
@@ -134,6 +141,16 @@
virtual void dump(std::string& dump) override;
private:
+ /**
+ * Initialize MotionClassifier.
+ * Return true if initializaion is successful.
+ */
+ bool init();
+ /**
+ * Entity that will be notified of the HAL death (most likely InputClassifier).
+ */
+ wp<android::hardware::hidl_death_recipient> mDeathRecipient;
+
// The events that need to be sent to the HAL.
BlockingQueue<ClassifierEvent> mEvents;
/**
@@ -148,7 +165,7 @@
std::thread mHalThread;
/**
* Print an error message if the caller is not on the InputClassifier thread.
- * Caller must supply the name of the calling function as __function__
+ * Caller must supply the name of the calling function as __func__
*/
void ensureHalThread(const char* function);
/**
@@ -156,9 +173,14 @@
*/
void callInputClassifierHal();
/**
- * Access to the InputClassifier HAL. Can always be safely dereferenced.
+ * Access to the InputClassifier HAL. May be null if init() hasn't completed yet.
+ * When init() successfully completes, mService is guaranteed to remain non-null and to not
+ * change its value until MotionClassifier is destroyed.
+ * This variable is *not* guarded by mLock in the InputClassifier thread, because
+ * that thread knows exactly when this variable is initialized.
+ * When accessed in any other thread, mService is checked for nullness with a lock.
*/
- const sp<android::hardware::input::classifier::V1_0::IInputClassifier> mService;
+ sp<android::hardware::input::classifier::V1_0::IInputClassifier> mService;
std::mutex mLock;
/**
* Per-device input classifications. Should only be accessed using the
@@ -195,6 +217,10 @@
* Useful for tests to ensure proper cleanup.
*/
void requestExit();
+ /**
+ * Return string status of mService
+ */
+ const char* getServiceStatus() REQUIRES(mLock);
};
diff --git a/services/inputflinger/tests/InputClassifier_test.cpp b/services/inputflinger/tests/InputClassifier_test.cpp
index 1651057..7cc17a2 100644
--- a/services/inputflinger/tests/InputClassifier_test.cpp
+++ b/services/inputflinger/tests/InputClassifier_test.cpp
@@ -136,11 +136,7 @@
std::unique_ptr<MotionClassifierInterface> mMotionClassifier;
virtual void SetUp() override {
- sp<android::hardware::input::classifier::V1_0::IInputClassifier> service =
- classifier::V1_0::IInputClassifier::getService();
- if (service) {
- mMotionClassifier = std::make_unique<MotionClassifier>(service);
- }
+ mMotionClassifier = std::make_unique<MotionClassifier>();
}
};
@@ -165,9 +161,7 @@
// We are not checking the return value, because we can't be making assumptions
// about the HAL operation, since it will be highly hardware-dependent
- if (mMotionClassifier) {
- ASSERT_NO_FATAL_FAILURE(mMotionClassifier->classify(motionArgs));
- }
+ ASSERT_NO_FATAL_FAILURE(mMotionClassifier->classify(motionArgs));
}
/**
@@ -183,9 +177,7 @@
// We are not checking the return value, because we can't be making assumptions
// about the HAL operation, since it will be highly hardware-dependent
- if (mMotionClassifier) {
- ASSERT_NO_FATAL_FAILURE(mMotionClassifier->classify(motionArgs));
- }
+ ASSERT_NO_FATAL_FAILURE(mMotionClassifier->classify(motionArgs));
}
/**
@@ -206,18 +198,14 @@
// We are not checking the return value, because we can't be making assumptions
// about the HAL operation, since it will be highly hardware-dependent
- if (mMotionClassifier) {
- ASSERT_NO_FATAL_FAILURE(mMotionClassifier->classify(motionArgs));
- }
+ ASSERT_NO_FATAL_FAILURE(mMotionClassifier->classify(motionArgs));
}
/**
* Make sure MotionClassifier does not crash when it is reset.
*/
TEST_F(MotionClassifierTest, Reset_DoesNotCrash) {
- if (mMotionClassifier) {
- ASSERT_NO_FATAL_FAILURE(mMotionClassifier->reset());
- }
+ ASSERT_NO_FATAL_FAILURE(mMotionClassifier->reset());
}
/**
@@ -225,9 +213,7 @@
*/
TEST_F(MotionClassifierTest, DeviceReset_DoesNotCrash) {
NotifyDeviceResetArgs args(1/*sequenceNum*/, 2/*eventTime*/, 3/*deviceId*/);
- if (mMotionClassifier) {
- ASSERT_NO_FATAL_FAILURE(mMotionClassifier->reset(args));
- }
+ ASSERT_NO_FATAL_FAILURE(mMotionClassifier->reset(args));
}
} // namespace android
diff --git a/services/sensorservice/SensorDevice.cpp b/services/sensorservice/SensorDevice.cpp
index 6570704..659329e 100644
--- a/services/sensorservice/SensorDevice.cpp
+++ b/services/sensorservice/SensorDevice.cpp
@@ -767,6 +767,10 @@
checkReturn(mSensors->activate(sensor_handle, 1 /* enabled */)));
ALOGE_IF(err, "Error activating sensor %d (%s)", sensor_handle, strerror(-err));
}
+
+ if (err == NO_ERROR) {
+ info.isActive = true;
+ }
}
}
@@ -774,7 +778,7 @@
if (mSensors == nullptr) return;
Mutex::Autolock _l(mLock);
for (size_t i = 0; i< mActivationCount.size(); ++i) {
- const Info& info = mActivationCount.valueAt(i);
+ Info& info = mActivationCount.editValueAt(i);
// Check if this sensor has been activated previously and disable it.
if (info.batchParams.size() > 0) {
const int sensor_handle = mActivationCount.keyAt(i);
@@ -788,6 +792,8 @@
mDisabledClients.add(info.batchParams.keyAt(j));
ALOGI("added %p to mDisabledClients", info.batchParams.keyAt(j));
}
+
+ info.isActive = false;
}
}
}
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index cbdd473..0269990 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -1381,15 +1381,6 @@
ALOGD_IF(DEBUG_CONNECTIONS, "... and it was the last connection");
mActiveSensors.removeItemsAt(i, 1);
mActiveVirtualSensors.erase(handle);
-
- // If this is the last connection, then mark the RecentEventLogger as stale. This is
- // critical for on-change events since the previous event is sent to a client if the
- // sensor is already active. If two clients request the sensor at the same time, one
- // of the clients would receive a stale event.
- auto logger = mRecentEvent.find(handle);
- if (logger != mRecentEvent.end()) {
- logger->second->setLastEventStale();
- }
delete rec;
size--;
} else {
@@ -1444,6 +1435,20 @@
if (sensor->isVirtual()) {
mActiveVirtualSensors.emplace(handle);
}
+
+ // There was no SensorRecord for this sensor which means it was previously disabled. Mark
+ // the recent event as stale to ensure that the previous event is not sent to a client. This
+ // ensures on-change events that were generated during a previous sensor activation are not
+ // erroneously sent to newly connected clients, especially if a second client registers for
+ // an on-change sensor before the first client receives the updated event. Once an updated
+ // event is received, the recent events will be marked as current, and any new clients will
+ // immediately receive the most recent event.
+ if (sensor->getSensor().getReportingMode() == AREPORTING_MODE_ON_CHANGE) {
+ auto logger = mRecentEvent.find(handle);
+ if (logger != mRecentEvent.end()) {
+ logger->second->setLastEventStale();
+ }
+ }
} else {
if (rec->addConnection(connection)) {
// this sensor is already activated, but we are adding a connection that uses it.
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index dabc683..6ef4518 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -425,7 +425,7 @@
}
Region BufferStateLayer::getDrawingSurfaceDamage() const {
- return Region::INVALID_REGION;
+ return getDrawingState().surfaceDamageRegion;
}
const HdrMetadata& BufferStateLayer::getDrawingHdrMetadata() const {
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 5e0ba13..304ff4b 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -979,7 +979,7 @@
if (mCheckPendingFence) {
if (previousFrameMissed()) {
// fence has not signaled yet. wait for the next invalidate
- repaintEverythingForHWC();
+ mEventQueue->invalidateForHWC();
return true;
}
@@ -1030,7 +1030,7 @@
// we need to submit an empty frame to HWC to start the process
mCheckPendingFence = true;
-
+ mEventQueue->invalidateForHWC();
return false;
}
@@ -1446,10 +1446,6 @@
return;
}
- if (desiredConfigId == display->getActiveConfig()) {
- return;
- }
-
setDesiredActiveConfig({refreshRate, desiredConfigId, event});
}
@@ -3511,7 +3507,12 @@
flushedATransaction = true;
}
- it = (transactionQueue.empty()) ? mTransactionQueues.erase(it) : std::next(it, 1);
+ if (transactionQueue.empty()) {
+ it = mTransactionQueues.erase(it);
+ mTransactionCV.broadcast();
+ } else {
+ std::next(it, 1);
+ }
}
return flushedATransaction;
}
@@ -3584,7 +3585,22 @@
}
// If its TransactionQueue already has a pending TransactionState or if it is pending
- if (mTransactionQueues.find(applyToken) != mTransactionQueues.end() ||
+ auto itr = mTransactionQueues.find(applyToken);
+ // if this is an animation frame, wait until prior animation frame has
+ // been applied by SF
+ if (flags & eAnimation) {
+ while (itr != mTransactionQueues.end()) {
+ status_t err = mTransactionCV.waitRelative(mStateLock, s2ns(5));
+ if (CC_UNLIKELY(err != NO_ERROR)) {
+ ALOGW_IF(err == TIMED_OUT,
+ "setTransactionState timed out "
+ "waiting for animation frame to apply");
+ break;
+ }
+ itr = mTransactionQueues.find(applyToken);
+ }
+ }
+ if (itr != mTransactionQueues.end() ||
!transactionIsReadyToBeApplied(desiredPresentTime, states)) {
mTransactionQueues[applyToken].emplace(states, displays, flags, desiredPresentTime,
uncacheBuffer, listenerCallbacks, postTime,
@@ -4897,6 +4913,9 @@
result.append(mScheduler->doDump() + "\n");
StringAppendF(&result, "+ Smart video mode: %s\n\n", mUseSmart90ForVideo ? "on" : "off");
result.append(mRefreshRateStats.doDump() + "\n");
+
+ result.append(mTimeStats->miniDump());
+ result.append("\n");
}
const Vector<sp<Layer>>& SurfaceFlinger::getLayerSortedByZForHwcDisplay(DisplayId displayId) {
diff --git a/services/surfaceflinger/TimeStats/TimeStats.cpp b/services/surfaceflinger/TimeStats/TimeStats.cpp
index 740099e..c97a19b 100644
--- a/services/surfaceflinger/TimeStats/TimeStats.cpp
+++ b/services/surfaceflinger/TimeStats/TimeStats.cpp
@@ -67,6 +67,16 @@
}
}
+std::string TimeStats::miniDump() {
+ ATRACE_CALL();
+
+ std::string result = "TimeStats miniDump:\n";
+ std::lock_guard<std::mutex> lock(mMutex);
+ android::base::StringAppendF(&result, "Number of tracked layers is %zu\n",
+ mTimeStatsTracker.size());
+ return result;
+}
+
void TimeStats::incrementTotalFrames() {
if (!mEnabled.load()) return;
@@ -252,7 +262,8 @@
postTime);
std::lock_guard<std::mutex> lock(mMutex);
- if (!mTimeStatsTracker.count(layerID) && layerNameIsValid(layerName)) {
+ if (!mTimeStatsTracker.count(layerID) && mTimeStatsTracker.size() < MAX_NUM_LAYER_RECORDS &&
+ layerNameIsValid(layerName)) {
mTimeStatsTracker[layerID].layerName = layerName;
}
if (!mTimeStatsTracker.count(layerID)) return;
diff --git a/services/surfaceflinger/TimeStats/TimeStats.h b/services/surfaceflinger/TimeStats/TimeStats.h
index d8c0786..4e040a3 100644
--- a/services/surfaceflinger/TimeStats/TimeStats.h
+++ b/services/surfaceflinger/TimeStats/TimeStats.h
@@ -41,6 +41,7 @@
virtual void parseArgs(bool asProto, const Vector<String16>& args, std::string& result) = 0;
virtual bool isEnabled() = 0;
+ virtual std::string miniDump();
virtual void incrementTotalFrames() = 0;
virtual void incrementMissedFrames() = 0;
@@ -112,6 +113,7 @@
void parseArgs(bool asProto, const Vector<String16>& args, std::string& result) override;
bool isEnabled() override;
+ std::string miniDump() override;
void incrementTotalFrames() override;
void incrementMissedFrames() override;
@@ -137,8 +139,6 @@
void recordRefreshRate(uint32_t fps, nsecs_t duration) override;
void setPresentFenceGlobal(const std::shared_ptr<FenceTime>& presentFence) override;
- // TODO(zzyiwei): Bound the timeStatsTracker with weighted LRU
- // static const size_t MAX_NUM_LAYER_RECORDS = 200;
static const size_t MAX_NUM_TIME_RECORDS = 64;
private:
@@ -159,6 +159,8 @@
std::unordered_map<int32_t, LayerRecord> mTimeStatsTracker;
PowerTime mPowerTime;
GlobalRecord mGlobalRecord;
+
+ static const size_t MAX_NUM_LAYER_RECORDS = 200;
};
} // namespace impl
diff --git a/services/surfaceflinger/tests/unittests/mock/MockTimeStats.h b/services/surfaceflinger/tests/unittests/mock/MockTimeStats.h
index 08fdb9d..b1634a8 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockTimeStats.h
+++ b/services/surfaceflinger/tests/unittests/mock/MockTimeStats.h
@@ -30,6 +30,7 @@
MOCK_METHOD3(parseArgs, void(bool, const Vector<String16>&, std::string&));
MOCK_METHOD0(isEnabled, bool());
+ MOCK_METHOD0(miniDump, std::string());
MOCK_METHOD0(incrementTotalFrames, void());
MOCK_METHOD0(incrementMissedFrames, void());
MOCK_METHOD0(incrementClientCompositionFrames, void());