主页 > 开源代码  > 

Android14(13)添加墨水屏手写API

Android14(13)添加墨水屏手写API

软件平台:Android14

硬件平台:QCS6115

    需求:特殊品类的产品墨水屏实现手写的功能,本来Android自带的Input这一套可以实现实时展示笔迹,但是由于墨水屏特性,达不到正常的彩屏刷新的帧率,因此使用原生这一套onTouch事件监听去绘制笔迹用高分相机去测会发现有较大延迟,因此需要自研一套实时绘制手写的功能。

1、将手写功能涉及的笔so声明到build系统:

diff --git a/target/product/base_system.mk b/target/product/base_system.mk index c21cb5f647..42c7d93478 100644 --- a/target/product/base_system.mk +++ b/target/product/base_system.mk @@ -293,6 +293,8 @@ PRODUCT_PACKAGES += \ wificond \ wifi.rc \ wm \ + libyfdpen_jni \ + libyfdpen \ ifneq ($(TARGET_HAS_QTI_OPTIMIZATIONS), true) PRODUCT_PACKAGES += \ diff --git a/target/product/gsi/31.txt b/target/product/gsi/31.txt index 971ec922a5..d4e6b9ce83 100644 --- a/target/product/gsi/31.txt +++ b/target/product/gsi/31.txt @@ -147,6 +147,7 @@ VNDK-core: libui.so VNDK-core: libusbhost.so VNDK-core: libwifi-system-iface.so VNDK-core: libxml2.so +VNDK-core: libyfdpen.so VNDK-core: libyuv.so VNDK-core: libziparchive.so VNDK-private: libbacktrace.so diff --git a/target/product/gsi/33.txt b/target/product/gsi/33.txt index 03a143d02c..b742b9b5af 100644 --- a/target/product/gsi/33.txt +++ b/target/product/gsi/33.txt @@ -178,6 +178,7 @@ VNDK-core: libui.so VNDK-core: libusbhost.so VNDK-core: libwifi-system-iface.so VNDK-core: libxml2.so +VNDK-core: libyfdpen.so VNDK-core: libyuv.so VNDK-core: libziparchive.so VNDK-private: libbacktrace.so diff --git a/target/product/gsi/34.txt b/target/product/gsi/34.txt index ceb2060c19..3102665d12 100644 --- a/target/product/gsi/34.txt +++ b/target/product/gsi/34.txt @@ -136,6 +136,7 @@ VNDK-core: libui.so VNDK-core: libusbhost.so VNDK-core: libwifi-system-iface.so VNDK-core: libxml2.so +VNDK-core: libyfdpen.so VNDK-core: libyuv.so VNDK-core: libziparchive.so VNDK-private: libblas.so diff --git a/target/product/gsi/current.txt b/target/product/gsi/current.txt index ceb2060c19..3102665d12 100644 --- a/target/product/gsi/current.txt +++ b/target/product/gsi/current.txt @@ -136,6 +136,7 @@ VNDK-core: libui.so VNDK-core: libusbhost.so VNDK-core: libwifi-system-iface.so VNDK-core: libxml2.so +VNDK-core: libyfdpen.so VNDK-core: libyuv.so

2、使上述so支持apex:

diff --git a/apex/apex.go b/apex/apex.go index 0a48f2a4ed..992bbed891 100644 --- a/apex/apex.go +++ b/apex/apex.go @@ -3332,6 +3332,7 @@ func makeApexAvailableBaseline() map[string][]string { "libunwindstack", "libz", "libziparchive", + "libyfdpen", } // // Module separator diff --git a/cc/config/vndk.go b/cc/config/vndk.go index 8bc1e1e2ef..dd1b1f0c38 100644 --- a/cc/config/vndk.go +++ b/cc/config/vndk.go @@ -43,4 +43,5 @@ var VndkMustUseVendorVariantList = []string{ "libui", "libxml2", "libmedia_helper",//Remove it from the list once the workaround patch is cleared in S + "libyfdpen", }

3、framework层base目录添加HW SDK及HW API:

diff --git a/Android.bp b/Android.bp index ba575d7eb771..7b0b7be12fa6 100755 --- a/Android.bp +++ b/Android.bp @@ -299,6 +299,7 @@ java_defaults { ":framework-bluetooth-sources", // TODO(b/214988855) : Remove once framework-bluetooth jar is ready "core/java/**/*.logtags", ":apex-info-list", + ":framework-handwrite-sources", ], aidl: { generate_get_transaction_name: true, @@ -590,6 +591,7 @@ metalava_framework_docs_args = "" + "--api-lint-ignore-prefix junit. " + "--api-lint-ignore-prefix android.yuanfudao. " + "--api-lint-ignore-prefix org. " + + "--api-lint-ignore-prefix android.yfd. " + "--error NoSettingsProvider " + "--error UnhiddenSystemApi " + "--force-convert-to-warning-nullability-annotations +*:-android.*:+android.icu.*:-dalvik.* " + @@ -738,3 +740,28 @@ build = [ "ProtoLibraries.bp", "TestProtoLibraries.bp", ] + +filegroup { + name: "framework-handwrite-sources", + srcs: [ + "handwrite/java/**/*.java", + "handwrite/java/**/*.aidl", + ], + path: "handwrite/java", +} + +java_library { + name: "framework-handwrite", + //defaults: ["framework-defaults"], + srcs: [":framework-handwrite-sources"], + installable: false, + required: [], + libs: [ + "framework-minus-apex", + "unsupportedappusage", + ], + dxflags: [ + "--core-library", + "--multi-dex", + ], +} diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java index 2574dd152c7f..6d6d096a2791 100644 --- a/core/java/android/content/pm/ApplicationInfo.java +++ b/core/java/android/content/pm/ApplicationInfo.java @@ -2379,7 +2379,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { } else if (isSystemApp() || isUpdatedSystemApp()) { return usesNonSdkApi() || isPackageWhitelistedForHiddenApis(); } else { - return false; + return isPackageWhitelistedForHiddenApis(); } } diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java old mode 100644 new mode 100755 index ef0a9fac10b1..5dc4cd31c467 --- a/core/java/android/view/SurfaceControl.java +++ b/core/java/android/view/SurfaceControl.java @@ -293,6 +293,18 @@ public final class SurfaceControl implements Parcelable { private static native void nativeClearTrustedPresentationCallback(long transactionObj, long nativeObject); + private static native boolean nativeYfdTest(); + private static native int nativeGetScreenRefreshMode(); + private static native void nativeSetScreenRefreshMode(int mode); + private static native int nativeGetHandwriteState(); + private static native void nativeSetHandwriteState(int state); + private static native boolean nativeSetHandwriteAreas(Rect validArea, Rect[] invalidAreas); + private static native void nativeSetHWLayerName(String lname); + private static native void nativeForceRefreshOnce(); + private static native void nativeUpdateHWLayerRef(boolean increase, int pid); + private static native void nativeSetHandwritePen(int type, int width, int color, int tag); + + /** * Transforms that can be applied to buffers as they are displayed to a window. * @@ -4366,4 +4378,100 @@ public final class SurfaceControl implements Parcelable { callback.accept(fence); } + + /** + * + * + * YFD handwrite api + * + */ + + /** + * Returns whether protected content is supported in GPU composition. + * @hide + */ + public static boolean yfdTest() { + Log.d(TAG, "yfdTest"); + return nativeYfdTest(); + } + + /** + * Return screen refresh mode. + * @hide + */ + public static int getScreenRefreshMode() { + Log.d(TAG, "getScreenRefreshMode"); } } diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java old mode 100644 new mode 100755 index ef0a9fac10b1..5dc4cd31c467 --- a/core/java/android/view/SurfaceControl.java +++ b/core/java/android/view/SurfaceControl.java @@ -293,6 +293,18 @@ public final class SurfaceControl implements Parcelable { private static native void nativeClearTrustedPresentationCallback(long transactionObj, long nativeObject); + private static native boolean nativeYfdTest(); + private static native int nativeGetScreenRefreshMode(); + private static native void nativeSetScreenRefreshMode(int mode); + private static native int nativeGetHandwriteState(); + private static native void nativeSetHandwriteState(int state); + private static native boolean nativeSetHandwriteAreas(Rect validArea, Rect[] invalidAreas); + private static native void nativeSetHWLayerName(String lname); + private static native void nativeForceRefreshOnce(); + private static native void nativeUpdateHWLayerRef(boolean increase, int pid); + private static native void nativeSetHandwritePen(int type, int width, int color, int tag); + + /** * Transforms that can be applied to buffers as they are displayed to a window. * @@ -4366,4 +4378,100 @@ public final class SurfaceControl implements Parcelable { callback.accept(fence); } + + /** + * + * + * YFD handwrite api + * + */ + + /** + * Returns whether protected content is supported in GPU composition. + * @hide + */ + public static boolean yfdTest() { + Log.d(TAG, "yfdTest"); + return nativeYfdTest(); + } + + /** + * Return screen refresh mode. + * @hide + */ + public static int getScreenRefreshMode() { + Log.d(TAG, "getScreenRefreshMode"); + return nativeGetScreenRefreshMode(); + } + + /** + * set screen refresh mode. + * @hide + */ + public static void setScreenRefreshMode(int mode) { + Log.d(TAG, "setScreenRefreshMode " + mode); + nativeSetScreenRefreshMode(mode); + } + + /** + * Return hand write state. + * @hide + */ + public static int getHandwriteState() { + Log.d(TAG, "getHandwriteState"); + return nativeGetHandwriteState(); + } + + /** + * set hand write state. + * @hide + */ + public static void setHandwriteState(int state) { + Log.d(TAG, "setHandwriteState " + state); + nativeSetHandwriteState(state); + } + + /** + * set hand write areas + * + * @hide + */ + public static boolean setHandwriteAreas(Rect validArea, Rect[] invalidAreas) { + return nativeSetHandwriteAreas(validArea, invalidAreas); + } + + /** + * set hand write layer name. + * @hide + */ + public static void setHWLayerName(String lname) { + nativeSetHWLayerName(lname); + } + + /** + * force refresh once. + * @hide + */ + public static void forceRefreshOnce() { + nativeForceRefreshOnce(); + } + + /** + * update hw layer reference + * + * @hide + */ + public static void updateHWLayerRef(boolean increase, int pid) { + nativeUpdateHWLayerRef(increase, pid); + } + + /** + * set hand write pen. + * + * @hide + */ + public static void setHandwritePen(int type, int width, int color, int tag) { + nativeSetHandwritePen(type, width, color, tag); + } + } diff --git a/core/jni/Android.bp b/core/jni/Android.bp old mode 100644 new mode 100755 index cc25334bd20e..b7e915a9349c --- a/core/jni/Android.bp +++ b/core/jni/Android.bp @@ -249,6 +249,8 @@ cc_library_shared { "android_window_WindowInfosListener.cpp", "android_window_ScreenCapture.cpp", "jni_common.cpp", + "android_yfd_view_TestSamplingListener.cpp", + "android_yfd_view_EmrListener.cpp", ], static_libs: [ diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp old mode 100644 new mode 100755 index ed1c26d20888..af417aebcef3 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -222,6 +222,8 @@ extern int register_android_window_WindowInfosListener(JNIEnv* env); extern int register_android_window_ScreenCapture(JNIEnv* env); extern int register_jni_common(JNIEnv* env); extern int register_com_android_internal_app_ActivityTrigger(JNIEnv *env); +extern int register_android_yfd_view_TestSamplingListener(JNIEnv* env); +extern int register_android_yfd_view_EmrListener(JNIEnv* env); // Namespace for Android Runtime flags applied during boot time. static const char* RUNTIME_NATIVE_BOOT_NAMESPACE = "runtime_native_boot"; @@ -1665,6 +1667,10 @@ static const RegJNIRec gRegJNI[] = { REG_JNI(register_jni_common), REG_JNI(register_com_android_internal_app_ActivityTrigger), REG_JNI(register_com_android_internal_os_KernelSingleProcessCpuThreadReader), + + // add by shawn + REG_JNI(register_android_yfd_view_TestSamplingListener), + REG_JNI(register_android_yfd_view_EmrListener), }; /* diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp old mode 100644 new mode 100755 index 424925328dfd..7fe349eb69fa --- a/core/jni/android_view_SurfaceControl.cpp +++ b/core/jni/android_view_SurfaceControl.cpp @@ -2032,6 +2032,79 @@ static jlong getNativeTrustedPresentationCallbackFinalizer(JNIEnv* env, jclass c return static_cast<jlong>(reinterpret_cast<uintptr_t>(&destroyNativeTpc)); } +static jboolean nativeYfdTest(JNIEnv* env, jclass) { + return static_cast<jboolean>(SurfaceComposerClient::yfdTest()); +} + +static jint nativeGetScreenRefreshMode(JNIEnv* env, jclass clazz) { + return static_cast<jint>(SurfaceComposerClient::getScreenRefreshMode()); +} + +static void nativeSetScreenRefreshMode(JNIEnv* env, jclass clazz, jint mode) { + SurfaceComposerClient::setScreenRefreshMode(mode); +} + +static jint nativeGetHandwriteState(JNIEnv* env, jclass clazz) { + return static_cast<jint>(SurfaceComposerClient::getHandwriteState()); +} + +static void nativeSetHandwriteState(JNIEnv* env, jclass clazz, jint state) { + SurfaceComposerClient::setHandwriteState(state); +} + +static jboolean nativeSetHandwriteAreas(JNIEnv* env, jclass clazz, jobject validAreaJ, + jobjectArray invalidAreasJ) { + if (validAreaJ == nullptr) { + ALOGE("validArea is null, ignore!"); + return JNI_FALSE; + } + + Rect validArea = JNICommon::rectFromObj(env, validAreaJ); + //ALOGI("validArea =[%d, %d - %d, %d]", validArea.left, validArea.top, + // validArea.right, validArea.bottom); + + jsize len; + std::vector<Rect> invalidAreas; + if (invalidAreasJ == nullptr) { + ALOGE("invalidAreas is null, ignore!"); + } else { + len = env->GetArrayLength(invalidAreasJ); + for (jsize i = 0; i < len; i++) { + jobject obj = env->GetObjectArrayElement(invalidAreasJ, i); + if (obj == nullptr) { + ALOGE("invalidAreas[%d] is null, stop!", i); + return JNI_FALSE; + } + Rect r = JNICommon::rectFromObj(env, obj); + invalidAreas.emplace_back(r); + //ALOGI("invalidAreas[%d] =[%d, %d - %d, %d",i, r.left, r.top, r.right, r.bottom); + } + } + + return static_cast<jboolean>(SurfaceComposerClient::setHandwriteAreas(validArea, invalidAreas)); +} + + +static void nativeSetHWLayerName(JNIEnv* env, jclass clazz, jstring lname) { + + ScopedUtfChars name(env, lname); + SurfaceComposerClient::setHWLayerName(String8(name.c_str())); +} + +static void nativeForceRefreshOnce(JNIEnv* env, jclass clazz) { + SurfaceComposerClient::forceRefreshOnce(); +} + +static void nativeUpdateHWLayerRef(JNIEnv* env, jclass clazz, jboolean increase, jint pid) { + SurfaceComposerClient::updateHWLayerRef(increase, pid); +} + +static void nativeSetHandwritePen(JNIEnv* env, jclass clazz, jint type, jint width,+ jint color, jint tag) { + SurfaceComposerClient::setHandwritePen(type, width, color, tag); +} + + // ---------------------------------------------------------------------------- SurfaceControl* android_view_SurfaceControl_getNativeSurfaceControl(JNIEnv* env, @@ -2282,6 +2355,29 @@ static const JNINativeMethod sSurfaceControlMethods[] = { (void*)nativeCreateTpc}, {"getNativeTrustedPresentationCallbackFinalizer", "()J", (void*)getNativeTrustedPresentationCallbackFinalizer }, // clang-format on + {"nativeYfdTest", "()Z", + (void*)nativeYfdTest }, + {"nativeGetScreenRefreshMode", "()I", + (void*)nativeGetScreenRefreshMode }, + {"nativeSetScreenRefreshMode", "(I)V", + (void*)nativeSetScreenRefreshMode }, + {"nativeGetHandwriteState", "()I", + (void*)nativeGetHandwriteState }, + {"nativeSetHandwriteState", "(I)V", + (void*)nativeSetHandwriteState }, + {"nativeSetHandwriteAreas", + "(Landroid/graphics/Rect;" + "[Landroid/graphics/Rect;)Z", + (void*)nativeSetHandwriteAreas }, + {"nativeSetHWLayerName", "(Ljava/lang/String;)V", + (void*)nativeSetHWLayerName }, + {"nativeForceRefreshOnce", "()V", + (void*)nativeForceRefreshOnce }, + {"nativeUpdateHWLayerRef", "(ZI)V", + (void*)nativeUpdateHWLayerRef }, + {"nativeSetHandwritePen", "(IIII)V", + (void*)nativeSetHandwritePen }, + }; int register_android_view_SurfaceControl(JNIEnv* env) diff --git a/core/jni/android_yfd_view_EmrListener.cpp b/core/jni/android_yfd_view_EmrListener.cpp new file mode 100755 index 000000000000..66e0e8dccc43 --- /dev/null +++ b/core/jni/android_yfd_view_EmrListener.cpp @@ -0,0 +1,194 @@ +/* + * Copyright (C) 2012 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:// .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 "EmrListener" + +#include "android_util_Binder.h" +#include "core_jni_helpers.h" + +#include <nativehelper/JNIHelp.h> + +#include <android_runtime/AndroidRuntime.h> +#include <android_runtime/Log.h> +#include <utils/Log.h> +#include <utils/RefBase.h> +#include <binder/IServiceManager.h> + +#include <gui/IYfdEmrListener.h> +#include <gui/ISurfaceComposer.h> +#include <gui/SurfaceComposerClient.h> +#include <ui/Rect.h> + +namespace android { + +namespace { + +struct { + jclass mClass; + jmethodID mDispatchOnAddPoint; + jmethodID mDispatchOnAddTrack; + jmethodID mDispatchOnSetPen; +} gListenerClassInfo; + +struct EmrListener : public BnYfdEmrListener { + EmrListener(JNIEnv* env, jobject listener) + : mListener(env->NewWeakGlobalRef(listener)) {} + + void onAddPoint(int action, float x, float y, int64_t eventtime, int pressure) override { + JNIEnv* env = AndroidRuntime::getJNIEnv(); + LOG_ALWAYS_FATAL_IF(env == nullptr, "Unable to retrieve JNIEnv in onAddPoint."); + + jobject listener = env->NewGlobalRef(mListener); + if (listener == NULL) { + // Weak reference went out of scope + return; + } + env->CallStaticVoidMethod(gListenerClassInfo.mClass, + gListenerClassInfo.mDispatchOnAddPoint, listener, + static_cast<jint>(action), static_cast<jfloat>(x), + static_cast<jfloat>(y), static_cast<jlong>(eventtime), + static_cast<jint>(pressure)); + + env->DeleteGlobalRef(listener); + + if (env->ExceptionCheck()) { + ALOGE("EmrListener.onAddPoint() failed."); + LOGE_EX(env); + env->ExceptionClear(); + } + } + + void onAddTrack(int left, int top, int right, int bottom) override { + JNIEnv* env = AndroidRuntime::getJNIEnv(); + LOG_ALWAYS_FATAL_IF(env == nullptr, "Unable to retrieve JNIEnv in onAddTrack."); + + jobject listener = env->NewGlobalRef(mListener); + if (listener == NULL) { + // Weak reference went out of scope + return; + } + env->CallStaticVoidMethod(gListenerClassInfo.mClass, + gListenerClassInfo.mDispatchOnAddTrack, listener, + static_cast<jint>(left), static_cast<jint>(top), + static_cast<jint>(right), static_cast<jint>(bottom)); + + env->DeleteGlobalRef(listener); + + if (env->ExceptionCheck()) { + ALOGE("EmrListener.onAddTrack() failed."); + LOGE_EX(env); + env->ExceptionClear(); + } + } + + void onSetPen(int type, int width, int color, int tag) override { + JNIEnv* env = AndroidRuntime::getJNIEnv(); + LOG_ALWAYS_FATAL_IF(env == nullptr, "Unable to retrieve JNIEnv in onSetPen."); + + jobject listener = env->NewGlobalRef(mListener); + if (listener == NULL) { + // Weak reference went out of scope + return; + } + env->CallStaticVoidMethod(gListenerClassInfo.mClass, + gListenerClassInfo.mDispatchOnSetPen, listener, + static_cast<jint>(type), static_cast<jint>(width), + static_cast<jint>(color), static_cast<jint>(tag)); + + env->DeleteGlobalRef(listener); + + if (env->ExceptionCheck()) { + ALOGE("EmrListener.onSetPen() failed."); + LOGE_EX(env); + env->ExceptionClear(); + } + } + +protected: + virtual ~EmrListener() { + JNIEnv* env = AndroidRuntime::getJNIEnv(); + env->DeleteWeakGlobalRef(mListener); + } + +private: + jweak mListener; +}; + +jlong nativeCreate(JNIEnv* env, jclass clazz, jobject obj) { + EmrListener* listener = new EmrListener(env, obj); + listener->incStrong((void*)nativeCreate); + return reinterpret_cast<jlong>(listener); +} + +void nativeDestroy(JNIEnv* env, jclass clazz, jlong ptr) { + EmrListener* listener = reinterpret_cast<EmrListener*>(ptr); + listener->decStrong((void*)nativeCreate); +} + +void nativeRegister(JNIEnv* env, jclass clazz, jlong ptr) { + sp<EmrListener> listener = reinterpret_cast<EmrListener*>(ptr); + + if (SurfaceComposerClient::addYfdEmrListener(listener) != OK) { + constexpr auto error_msg = "Couldn't addYfdEmrListener"; + ALOGE(error_msg); + jniThrowRuntimeException(env, error_msg); + } +} + +void nativeUnregister(JNIEnv* env, jclass clazz, jlong ptr) { + sp<EmrListener> listener = reinterpret_cast<EmrListener*>(ptr); + + if (SurfaceComposerClient::removeYfdEmrListener(listener) != OK) { + constexpr auto error_msg = "Couldn't removeYfdEmrListener"; + ALOGE(error_msg); + jniThrowRuntimeException(env, error_msg); + } +} + +const JNINativeMethod gMethods[] = { + /* name, signature, funcPtr */ + { "nativeCreate", "(Landroid/yfd/view/EmrListener;)J", + (void*)nativeCreate }, + { "nativeDestroy", "(J)V", + (void*)nativeDestroy }, + { "nativeRegister", "(J)V", + (void*)nativeRegister }, + { "nativeUnregister", "(J)V", + (void*)nativeUnregister } +}; + +} // namespace + +int register_android_yfd_view_EmrListener(JNIEnv* env) { + int res = jniRegisterNativeMethods(env, "android/yfd/view/EmrListener", + gMethods, NELEM(gMethods)); + LOG_ALWAYS_FATAL_IF(res < 0, "Unable to register native methods."); + + jclass clazz = env->FindClass("android/yfd/view/EmrListener"); + gListenerClassInfo.mClass = MakeGlobalRefOrDie(env, clazz); + gListenerClassInfo.mDispatchOnAddPoint = env->GetStaticMethodID( + clazz, "dispatchOnAddPoint", "(Landroid/yfd/view/EmrListener;IFFJI)V"); + + gListenerClassInfo.mDispatchOnAddTrack = env->GetStaticMethodID( + clazz, "dispatchOnAddTrack", "(Landroid/yfd/view/EmrListener;IIII)V"); + + gListenerClassInfo.mDispatchOnSetPen = env->GetStaticMethodID( + clazz, "dispatchOnSetPen", "(Landroid/yfd/view/EmrListener;IIII)V"); + + return 0; +} + +} // namespace android diff --git a/core/jni/android_yfd_view_TestSamplingListener.cpp b/core/jni/android_yfd_view_TestSamplingListener.cpp new file mode 100644 index 000000000000..8d97e6dea190 --- /dev/null +++ b/core/jni/android_yfd_view_TestSamplingListener.cpp @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2012 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:// .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 "TestSamplingListener" + +#include "android_util_Binder.h" +#include "core_jni_helpers.h" + +#include <nativehelper/JNIHelp.h> + +#include <android_runtime/AndroidRuntime.h> +#include <android_runtime/Log.h> +#include <utils/Log.h> +#include <utils/RefBase.h> +#include <binder/IServiceManager.h> + +#include <gui/IYfdTestSamplingListener.h> +#include <gui/ISurfaceComposer.h> +#include <gui/SurfaceComposerClient.h> +#include <ui/Rect.h> + +namespace android { + +namespace { + +struct { + jclass mClass; + jmethodID mDispatchOnSampleCollected; +} gListenerClassInfo; + +struct TestSamplingListener : public BnYfdTestSamplingListener { + TestSamplingListener(JNIEnv* env, jobject listener) + : mListener(env->NewWeakGlobalRef(listener)) {} + + void onSampleCollected(float medianLuma) override { + JNIEnv* env = AndroidRuntime::getJNIEnv(); + LOG_ALWAYS_FATAL_IF(env == nullptr, "Unable to retrieve JNIEnv in onSampleCollected."); + + jobject listener = env->NewGlobalRef(mListener); + if (listener == NULL) { + // Weak reference went out of scope + return; + } + env->CallStaticVoidMethod(gListenerClassInfo.mClass, + gListenerClassInfo.mDispatchOnSampleCollected, listener, + static_cast<jfloat>(medianLuma)); + env->DeleteGlobalRef(listener); + + if (env->ExceptionCheck()) { + ALOGE("TestSamplingListener.onSampleCollected() failed."); + LOGE_EX(env); + env->ExceptionClear(); + } + } + +protected: + virtual ~TestSamplingListener() { + JNIEnv* env = AndroidRuntime::getJNIEnv(); + env->DeleteWeakGlobalRef(mListener); + } + +private: + jweak mListener; +}; + +jlong nativeCreate(JNIEnv* env, jclass clazz, jobject obj) { + TestSamplingListener* listener = new TestSamplingListener(env, obj); + listener->incStrong((void*)nativeCreate); + return reinterpret_cast<jlong>(listener); +} + +void nativeDestroy(JNIEnv* env, jclass clazz, jlong ptr) { + TestSamplingListener* listener = reinterpret_cast<TestSamplingListener*>(ptr); + listener->decStrong((void*)nativeCreate); +} + +void nativeRegister(JNIEnv* env, jclass clazz, jlong ptr, jlong stopLayerObj, + +void nativeDestroy(JNIEnv* env, jclass clazz, jlong ptr) { + TestSamplingListener* listener = reinterpret_cast<TestSamplingListener*>(ptr); + listener->decStrong((void*)nativeCreate); +} + +void nativeRegister(JNIEnv* env, jclass clazz, jlong ptr, jlong stopLayerObj, + jint left, jint top, jint right, jint bottom) { + sp<TestSamplingListener> listener = reinterpret_cast<TestSamplingListener*>(ptr); + auto stopLayer = reinterpret_cast<SurfaceControl*>(stopLayerObj); + sp<IBinder> stopLayerHandle = stopLayer != nullptr ? stopLayer->getHandle() : nullptr; + + if (SurfaceComposerClient::addYfdTestListener( + Rect(left, top, right, bottom), stopLayerHandle, listener) != OK) { + constexpr auto error_msg = "Couldn't addYfdTestListener"; + ALOGE(error_msg); + jniThrowRuntimeException(env, error_msg); + } +} + +void nativeUnregister(JNIEnv* env, jclass clazz, jlong ptr) { + sp<TestSamplingListener> listener = reinterpret_cast<TestSamplingListener*>(ptr); + + if (SurfaceComposerClient::removeYfdTestListener(listener) != OK) { + constexpr auto error_msg = "Couldn't removeYfdTestListener"; + ALOGE(error_msg); + jniThrowRuntimeException(env, error_msg); + } +} + +const JNINativeMethod gMethods[] = { + /* name, signature, funcPtr */ + { "nativeCreate", "(Landroid/yfd/view/TestSamplingListener;)J", + (void*)nativeCreate }, + { "nativeDestroy", "(J)V", + (void*)nativeDestroy }, + { "nativeRegister", "(JJIIII)V", + (void*)nativeRegister }, + { "nativeUnregister", "(J)V", + (void*)nativeUnregister } +}; + +} // namespace + +int register_android_yfd_view_TestSamplingListener(JNIEnv* env) { + int res = jniRegisterNativeMethods(env, "android/yfd/view/TestSamplingListener", + gMethods, NELEM(gMethods)); + LOG_ALWAYS_FATAL_IF(res < 0, "Unable to register native methods."); + + jclass clazz = env->FindClass("android/yfd/view/TestSamplingListener"); + gListenerClassInfo.mClass = MakeGlobalRefOrDie(env, clazz); + gListenerClassInfo.mDispatchOnSampleCollected = env->GetStaticMethodID( + clazz, "dispatchOnSampleCollected", "(Landroid/yfd/view/TestSamplingListener;F)V"); + return 0; +} + +} // namespace android diff --git a/data/etc/hiddenapi-package-whitelist.xml b/data/etc/hiddenapi-package-whitelist.xml index 1c2cc613e9f6..c55c1d8e502c 100644 --- a/data/etc/hiddenapi-package-whitelist.xml +++ b/data/etc/hiddenapi-package-whitelist.xml + listener->decStrong((void*)nativeCreate); +} + +void nativeRegister(JNIEnv* env, jclass clazz, jlong ptr, jlong stopLayerObj, + jint left, jint top, jint right, jint bottom) { + sp<TestSamplingListener> listener = reinterpret_cast<TestSamplingListener*>(ptr); + auto stopLayer = reinterpret_cast<SurfaceControl*>(stopLayerObj); + sp<IBinder> stopLayerHandle = stopLayer != nullptr ? stopLayer->getHandle() : nullptr; + + if (SurfaceComposerClient::addYfdTestListener( + Rect(left, top, right, bottom), stopLayerHandle, listener) != OK) { + constexpr auto error_msg = "Couldn't addYfdTestListener"; + ALOGE(error_msg); + jniThrowRuntimeException(env, error_msg); + } +} + +void nativeUnregister(JNIEnv* env, jclass clazz, jlong ptr) { + sp<TestSamplingListener> listener = reinterpret_cast<TestSamplingListener*>(ptr); + + if (SurfaceComposerClient::removeYfdTestListener(listener) != OK) { + constexpr auto error_msg = "Couldn't removeYfdTestListener"; + ALOGE(error_msg); + jniThrowRuntimeException(env, error_msg); + } +} + +const JNINativeMethod gMethods[] = { + /* name, signature, funcPtr */ + { "nativeCreate", "(Landroid/yfd/view/TestSamplingListener;)J", + (void*)nativeCreate }, + { "nativeDestroy", "(J)V", + (void*)nativeDestroy }, + { "nativeRegister", "(JJIIII)V", + (void*)nativeRegister }, + { "nativeUnregister", "(J)V", + (void*)nativeUnregister } +}; + +} // namespace + +int register_android_yfd_view_TestSamplingListener(JNIEnv* env) { + int res = jniRegisterNativeMethods(env, "android/yfd/view/TestSamplingListener", + gMethods, NELEM(gMethods)); + LOG_ALWAYS_FATAL_IF(res < 0, "Unable to register native methods."); + + jclass clazz = env->FindClass("android/yfd/view/TestSamplingListener"); + gListenerClassInfo.mClass = MakeGlobalRefOrDie(env, clazz); + gListenerClassInfo.mDispatchOnSampleCollected = env->GetStaticMethodID( + clazz, "dispatchOnSampleCollected", "(Landroid/yfd/view/TestSamplingListener;F)V"); + return 0; +} + +} // namespace android diff --git a/data/etc/hiddenapi-package-whitelist.xml b/data/etc/hiddenapi-package-whitelist.xml index 1c2cc613e9f6..c55c1d8e502c 100644 --- a/data/etc/hiddenapi-package-whitelist.xml +++ b/data/etc/hiddenapi-package-whitelist.xml @@ -64,4 +64,5 @@ Do NOT include any apps that are updatable via Play Store! <hidden-api-whitelisted-app package="jp.co.omronsoft.openwnn" /> <!-- TODO: Remove NetworkStack whitelisting --> <hidden-api-whitelisted-app package="com.android.networkstack" /> + <hidden-api-whitelisted-app package="com.example.learn" /> </config>

此目录api接口文件会以代码压缩包方式绑定附件。

4、添加surfaceflinger hwc API:

diff --git a/libs/binder/include/binder/IInterface.h b/libs/binder/include/binder/IInterface.h old mode 100644 new mode 100755 index dc572ac953..54dbf1fb7e --- a/libs/binder/include/binder/IInterface.h +++ b/libs/binder/include/binder/IInterface.h @@ -233,6 +233,10 @@ constexpr const char* const kManualInterfaces[] = { "android.gui.ITransactionComposerListener", "android.gui.SensorEventConnection", "android.gui.SensorServer", + // add by yfd-shawn for handwrite +++ + "android.gui.IYfdTestSamplingListener", + "android.gui.IYfdEmrListener", + // add by yfd-shawn for handwrite --- "android.hardware.ICamera", "android.hardware.ICameraClient", "android.hardware.ICameraRecordingProxy", diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp old mode 100644 new mode 100755 index 0533aadbbe..bc7c30f161 --- a/libs/gui/Android.bp +++ b/libs/gui/Android.bp @@ -249,6 +249,8 @@ cc_library_shared { "bufferqueue/1.0/H2BGraphicBufferProducer.cpp", "bufferqueue/2.0/B2HProducerListener.cpp", "bufferqueue/2.0/H2BGraphicBufferProducer.cpp", + "IYfdTestSamplingListener.cpp", + "IYfdEmrListener.cpp", ], shared_libs: [ diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp old mode 100644 new mode 100755 index b526a6c92c..ce7d42153f --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -35,6 +35,9 @@ #include <ui/DynamicDisplayInfo.h> #include <ui/HdrCapabilities.h> #include <utils/Log.h> +#include <gui/IYfdTestSamplingListener.h> +#include <gui/IYfdEmrListener.h> + // --------------------------------------------------------------------------- @@ -114,6 +117,299 @@ public: data, &reply); } } + + virtual status_t yfdTest(bool* outSupported) const { + Parcel data, reply; + data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); + status_t error = + remote()->transact(BnSurfaceComposer::YFD_TEST, data, &reply); + if (error != NO_ERROR) { + return error; + } + error = reply.readBool(outSupported); + return error; + } + + virtual status_t getScreenRefreshMode() { + Parcel data, reply; + data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); + status_t error = remote()->transact(BnSurfaceComposer::YFD_GET_SCREEN_MODE, data, &reply); + if (error != NO_ERROR) { + return error; + } + return reply.readInt32(); + } + + virtual void setScreenRefreshMode(int mode) { + Parcel data, reply; + status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); + if (result != NO_ERROR) { + ALOGE("setScreenRefreshMode failed to writeInterfaceToken: %d", result); + return; + } + + result = data.writeInt32(mode); + if (result != NO_ERROR) { + ALOGE("setScreenRefreshMode failed to writeInt: %d", result); + return; + } + result = remote()->transact(BnSurfaceComposer::YFD_SET_SCREEN_MODE, data, &reply); + if (result != NO_ERROR) { + ALOGE("setScreenRefreshMode failed to transact: %d", result); + return; + } + } + + virtual status_t getHandwriteState() { + Parcel data, reply; + data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); + status_t error = remote()->transact(BnSurfaceComposer::YFD_GET_HW_STATE, data, &reply); + if (error != NO_ERROR) { + return error; + } + return reply.readInt32(); + } + + virtual void setHandwriteState(int state) { + Parcel data, reply; + status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); + if (result != NO_ERROR) { + ALOGE("setHandwriteState failed to writeInterfaceToken: %d", result); + return; + } + + result = data.writeInt32(state); + if (result != NO_ERROR) { + ALOGE("setHandwriteState failed to writeInt: %d", result); + return; + } + result = remote()->transact(BnSurfaceComposer::YFD_SET_HW_STATE, data, &reply); + if (result != NO_ERROR) { + ALOGE("setHandwriteState failed to transact: %d", result); + return; + } + } + + virtual status_t addYfdTestListener(const Rect& samplingArea, + const sp<IBinder>& stopLayerHandle, + const sp<IYfdTestSamplingListener>& listener) { + Parcel data, reply; + status_t error = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); + if (error != NO_ERROR) { + ALOGE("addYfdTestListener: Failed to write interface token"); + return error; + } + error = data.write(samplingArea); + if (error != NO_ERROR) { + ALOGE("addYfdTestListener: Failed to write sampling area"); + return error; + } + error = data.writeStrongBinder(stopLayerHandle); + if (error != NO_ERROR) { + ALOGE("addYfdTestListener: Failed to write stop layer handle"); + return error; + } + error = data.writeStrongBinder(IInterface::asBinder(listener)); + if (error != NO_ERROR) { + ALOGE("addYfdTestListener: Failed to write listener"); + return error; + } + error = remote()->transact(BnSurfaceComposer::YFD_ADD_TEST_LISTENER, data, &reply); + if (error != NO_ERROR) { + ALOGE("addYfdTestListener: Failed to transact"); + } + return error; + } + + virtual status_t removeYfdTestListener(const sp<IYfdTestSamplingListener>& listener) { + Parcel data, reply; + status_t error = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); + if (error != NO_ERROR) { + ALOGE("removeYfdTestListener: Failed to write interface token"); + return error; + } + error = data.writeStrongBinder(IInterface::asBinder(listener)); + if (error != NO_ERROR) { + ALOGE("removeYfdTestListener: Failed to write listener"); + return error; + } + error = remote()->transact(BnSurfaceComposer::YFD_REMOVE_TEST_LISTENER, data, + &reply); + if (error != NO_ERROR) { + ALOGE("removeYfdTestListener: Failed to transact"); + } + return error; + } + + virtual status_t addYfdEmrListener(const sp<IYfdEmrListener>& listener) { + Parcel data, reply; + status_t error = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); + if (error != NO_ERROR) { + ALOGE("addYfdEmrListener: Failed to write interface token"); + return error; + } + error = data.writeStrongBinder(IInterface::asBinder(listener)); + if (error != NO_ERROR) { + ALOGE("addYfdEmrListener: Failed to write listener"); + return error; + } + error = remote()->transact(BnSurfaceComposer::YFD_ADD_EMR_LISTENER, data, &reply); + if (error != NO_ERROR) { + ALOGE("addYfdEmrListener: Failed to transact"); + } + return error; + } + + virtual status_t removeYfdEmrListener(const sp<IYfdEmrListener>& listener) { + Parcel data, reply; + status_t error = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); + if (error != NO_ERROR) { + ALOGE("removeYfdEmrListener: Failed to write interface token"); + return error; + } + error = data.writeStrongBinder(IInterface::asBinder(listener)); + if (error != NO_ERROR) { + ALOGE("removeYfdEmrListener: Failed to write listener"); + return error; + } + error = remote()->transact(BnSurfaceComposer::YFD_REMOVE_EMR_LISTENER, data, + &reply); + if (error != NO_ERROR) { + ALOGE("removeYfdEmrListener: Failed to transact"); + } + return error; + } + + virtual status_t setHandwriteAreas(const Rect& validArea, + const std::vector<Rect>& invalidAreas, + bool* ret) { + Parcel data, reply; + status_t error = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); + if (error != NO_ERROR) { + ALOGE("setHandwriteAreas: Failed to write interface token"); + return error; + } + + error = data.write(validArea); + if (error != NO_ERROR) { + ALOGE("setHandwriteAreas: Failed to write validArea"); + return error; + } + + data.writeUint32(static_cast<uint32_t>(invalidAreas.size())); + //ALOGI("setHandwriteAreas_ bp :: invalidAreas.size = %d", + // static_cast<uint32_t>(invalidAreas.size())); + for (const auto& r : invalidAreas) { + data.write(r); + //ALOGE("setHandwriteAreas bp invalidAreas = [%d, %d - %d, %d]" + // , r.left, r.top, r.right, r.bottom); + if (error != NO_ERROR) { + ALOGE("setHandwriteAreas: Failed to write invalidAreas"); + return error; + } + } + + error = remote()->transact(BnSurfaceComposer::YFD_SET_HW_AREAS, data, &reply); + if (error != NO_ERROR) { + ALOGE("setHandwriteAreas: Failed to transact"); + return error; + } + + error = reply.readBool(ret); + return error; + } + + virtual void setHWLayerName(const String8& name) { + Parcel data, reply; + status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); + if (result != NO_ERROR) { + ALOGE("setHWLayerName failed to writeInterfaceToken: %d", result); + return; + } + result = data.writeString8(name); + if (result != NO_ERROR) { + ALOGE("setHWLayerName failed to writeInt: %d", result); + return; + } + result = remote()->transact(BnSurfaceComposer::YFD_SET_HW_LAYER_NAME, data, &reply); + if (result != NO_ERROR) { + ALOGE("setHWLayerName failed to transact: %d", result); + return; + } + } + + virtual void forceRefreshOnce() { + Parcel data, reply; + data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); + status_t error = remote()->transact(BnSurfaceComposer::YFD_FORCE_REFRESH_ONCE, data, &reply); + if (error != NO_ERROR) { + ALOGE("forceRefreshOnce failed to transact: %d", error); + // return error; + } + return; + } + + virtual void updateHWLayerRef(bool increase, int pid) { + Parcel data, reply; + status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); + if (result != NO_ERROR) { + ALOGE("updateHWLayerRef failed to writeInterfaceToken: %d", result); + return; + } + + data.writeBool(increase); + result = data.writeInt32(pid); + + if (result != NO_ERROR) { + ALOGE("updateHWLayerRef failed to writeInt: %d", result); + return; + } + + result = remote()->transact(BnSurfaceComposer::YFD_UPDATE_HW_LAYER_REF, data, &reply); + if (result != NO_ERROR) { + ALOGE("updateHWLayerRef failed to transact: %d", result); + return; + } + } + + virtual void setHandwritePen(int type, int width, int color, int tag) { + Parcel data, reply; + status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); + if (result != NO_ERROR) { + ALOGE("setHandwritePen failed to writeInterfaceToken: %d", result); + return; + } + + result = data.writeInt32(type); + if (result != NO_ERROR) { + ALOGE("setHandwritePen failed to writeInt: %d", result); + return; + } + + result = data.writeInt32(width); + if (result != NO_ERROR) { + ALOGE("setHandwritePen failed to writeInt: %d", result); + return; + } + + result = data.writeInt32(color); + if (result != NO_ERROR) { + ALOGE("setHandwritePen failed to writeInt: %d", result); + return; + } + + result = data.writeInt32(tag); + if (result != NO_ERROR) { + ALOGE("setHandwritePen failed to writeInt: %d", result); + return; + } + + result = remote()->transact(BnSurfaceComposer::YFD_SET_HW_PEN, data, &reply); + if (result != NO_ERROR) { + ALOGE("setHandwritePen failed to transact: %d", result); + return; + } + } }; // Out-of-line virtual method definition to trigger vtable emission in this @@ -201,6 +497,209 @@ status_t BnSurfaceComposer::onTransact( isAutoTimestamp, uncacheBuffers, hasListenerCallbacks, listenerCallbacks, transactionId, mergedTransactions); } + + case YFD_TEST: { + CHECK_INTERFACE(ISurfaceComposer, data, reply); + bool result; + status_t error = yfdTest(&result); + if (error == NO_ERROR) { + reply->writeBool(result); + } + return error; + } + + case YFD_GET_SCREEN_MODE: { + CHECK_INTERFACE(ISurfaceComposer, data, reply); + int32_t mode = getScreenRefreshMode(); + reply->writeInt32(mode); + return NO_ERROR; + } + + case YFD_SET_SCREEN_MODE: { + CHECK_INTERFACE(ISurfaceComposer, data, reply); + int32_t mode; + status_t result = data.readInt32(&mode); + if (result != NO_ERROR) { + ALOGE("setScreenRefreshMode failed to readInt: %d", result); + return result; + } + setScreenRefreshMode(mode); + return result; + } + + case YFD_GET_HW_STATE: { + CHECK_INTERFACE(ISurfaceComposer, data, reply); + //int32_t state; + //status_t result = getHandwriteState(&state); + //if (result == NO_ERROR) { + // reply->writeInt32(state); + //} + //return result; + + int32_t state = getHandwriteState(); + reply->writeInt32(state); + return NO_ERROR; + } + + case YFD_SET_HW_STATE: { + CHECK_INTERFACE(ISurfaceComposer, data, reply); + int32_t state; + status_t result = data.readInt32(&state); + if (result != NO_ERROR) { + ALOGE("setHandwriteState failed to readInt: %d", result); + return result; + } + setHandwriteState(state); + return result; + } + + case YFD_ADD_TEST_LISTENER: { + CHECK_INTERFACE(ISurfaceComposer, data, reply); + Rect samplingArea; + status_t result = data.read(samplingArea); + if (result != NO_ERROR) { + ALOGE("addYfdTestListener: Failed to read sampling area"); + return result; + } + sp<IBinder> stopLayerHandle; + result = data.readNullableStrongBinder(&stopLayerHandle); + if (result != NO_ERROR) { + ALOGE("addYfdTestListener: Failed to read stop layer handle"); + return result; + } + sp<IYfdTestSamplingListener> listener; + result = data.readNullableStrongBinder(&listener); + if (result != NO_ERROR) { + ALOGE("addYfdTestListener: Failed to read listener"); + return result; + } + return addYfdTestListener(samplingArea, stopLayerHandle, listener); + } + + case YFD_REMOVE_TEST_LISTENER: { + CHECK_INTERFACE(ISurfaceComposer, data, reply); + sp<IYfdTestSamplingListener> listener; + status_t result = data.readNullableStrongBinder(&listener); + if (result != NO_ERROR) { + ALOGE("removeYfdTestListener: Failed to read listener"); + return result; + } + return removeYfdTestListener(listener); + } + + case YFD_ADD_EMR_LISTENER: { + CHECK_INTERFACE(ISurfaceComposer, data, reply); + sp<IYfdEmrListener> listener; + status_t result = data.readNullableStrongBinder(&listener); + if (result != NO_ERROR) { + ALOGE("addYfdEmrListener: Failed to read listener"); + return result; + } + return addYfdEmrListener(listener); + } + + case YFD_REMOVE_EMR_LISTENER: { + CHECK_INTERFACE(ISurfaceComposer, data, reply); + sp<IYfdEmrListener> listener; + status_t result = data.readNullableStrongBinder(&listener); + if (result != NO_ERROR) { + ALOGE("removeYfdEmrListener: Failed to read listener"); + return result; + } + return removeYfdEmrListener(listener); + } + + case YFD_SET_HW_AREAS: { + CHECK_INTERFACE(ISurfaceComposer, data, reply); + bool ret; + + Rect validArea; + status_t result = data.read(validArea); + if (result != NO_ERROR) { + ALOGE("setHandwriteAreas: Failed to read validArea"); + return result; + } + + size_t len = data.readUint32(); + if (len > data.dataSize()) { + return BAD_VALUE; + } + + Rect r; + std::vector<Rect> invalidAreas; + for (size_t i = 0; i < len; i++) { + result = data.read(r); + if (result != NO_ERROR) { + ALOGE("setHandwriteAreas: Failed to read invalidAreas"); + return result; + } + invalidAreas.emplace_back(r); + ALOGI("setHandwriteAreas bn [%zu] =[%d, %d - %d, %d",i, r.left, r.top, r.right, r.bottom); + } + + result = setHandwriteAreas(validArea, invalidAreas, &ret); + if (result == NO_ERROR) { + reply->writeBool(ret); + } + return result; + } + + case YFD_SET_HW_LAYER_NAME: { + CHECK_INTERFACE(ISurfaceComposer, data, reply); + String8 name = data.readString8(); + setHWLayerName(name); + return NO_ERROR; + } + + case YFD_FORCE_REFRESH_ONCE: { + CHECK_INTERFACE(ISurfaceComposer, data, reply); + forceRefreshOnce(); + return NO_ERROR; + } + + case YFD_UPDATE_HW_LAYER_REF: { + CHECK_INTERFACE(ISurfaceComposer, data, reply); + bool increase = data.readBool(); + int32_t pid = data.readInt32(); + updateHWLayerRef(increase, pid); + return NO_ERROR; + } + + case YFD_SET_HW_PEN: { + CHECK_INTERFACE(ISurfaceComposer, data, reply); + int32_t type; + int32_t width; + int32_t color; + int32_t tag; + + status_t result = data.readInt32(&type); + if (result != NO_ERROR) { + ALOGE("setHandwritePen failed to readInt: %d", result); + return result; + } + + result = data.readInt32(&width); + if (result != NO_ERROR) { + ALOGE("setHandwritePen failed to readInt: %d", result); + return result; + } + + result = data.readInt32(&color); + if (result != NO_ERROR) { + ALOGE("setHandwritePen failed to readInt: %d", result); + return result; + } + + result = data.readInt32(&tag); + if (result != NO_ERROR) { + ALOGE("setHandwritePen failed to readInt: %d", result); + return result; + } + + setHandwritePen(type, width, color, tag); + return result; + } + default: { return BBinder::onTransact(code, data, reply, flags); } diff --git a/libs/gui/IYfdEmrListener.cpp b/libs/gui/IYfdEmrListener.cpp new file mode 100755 index 0000000000..f70b039b55 --- /dev/null +++ b/libs/gui/IYfdEmrListener.cpp @@ -0,0 +1,81 @@ +/* + * 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:// .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 "IYfdEmrListener" +//#define LOG_NDEBUG 0 + +#include <gui/IYfdEmrListener.h> + +namespace android { + +namespace { // Anonymous + + +enum class Tag : uint32_t { + ON_ADD_POINT = IBinder::FIRST_CALL_TRANSACTION, + ON_ADD_TRACK, + ON_SET_PEN, + LAST = ON_SET_PEN, +}; + +} // Anonymous namespace + +class BpYfdEmrListener : public SafeBpInterface<IYfdEmrListener> { +public: + explicit BpYfdEmrListener(const sp<IBinder>& impl) + : SafeBpInterface<IYfdEmrListener>(impl, "BpYfdEmrListener") {} + + ~BpYfdEmrListener() override; + + void onAddPoint(int action, float x, float y, int64_t eventtime, int pressure) override { + callRemoteAsync<decltype( + &IYfdEmrListener::onAddPoint)>(Tag::ON_ADD_POINT, action, x, y, eventtime, pressure); + } + + void onAddTrack(int left, int top, int right, int bottom) override { + callRemoteAsync<decltype( + &IYfdEmrListener::onAddTrack)>(Tag::ON_ADD_TRACK, left, top, right, bottom); + } + + void onSetPen(int type, int width, int color, int tag) override { + callRemoteAsync<decltype( + &IYfdEmrListener::onSetPen)>(Tag::ON_SET_PEN, type, width, color, tag); + } +}; + +// Out-of-line virtual method definitions to trigger vtable emission in this translation unit (see +// clang warning -Wweak-vtables) +BpYfdEmrListener::~BpYfdEmrListener() = default; + +IMPLEMENT_META_INTERFACE(YfdEmrListener, "android.gui.IYfdEmrListener"); + +status_t BnYfdEmrListener::onTransact(uint32_t code, const Parcel& data, Parcel* reply, + uint32_t flags) { + if (code < IBinder::FIRST_CALL_TRANSACTION || code > static_cast<uint32_t>(Tag::LAST)) { + return BBinder::onTransact(code, data, reply, flags); + } + auto tag = static_cast<Tag>(code); + switch (tag) { + case Tag::ON_ADD_POINT: + return callLocalAsync(data, reply, &IYfdEmrListener::onAddPoint); + case Tag::ON_ADD_TRACK: + return callLocalAsync(data, reply, &IYfdEmrListener::onAddTrack); + case Tag::ON_SET_PEN: + return callLocalAsync(data, reply, &IYfdEmrListener::onSetPen); + } +} + +} // namespace android diff --git a/libs/gui/IYfdTestSamplingListener.cpp b/libs/gui/IYfdTestSamplingListener.cpp new file mode 100644 index 0000000000..88d80dd917 --- /dev/null +++ b/libs/gui/IYfdTestSamplingListener.cpp @@ -0,0 +1,64 @@ +/* + * 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:// .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 "IYfdTestSamplingListener" +//#define LOG_NDEBUG 0 + +#include <gui/IYfdTestSamplingListener.h> + +namespace android { + +namespace { // Anonymous + +enum class Tag : uint32_t { + ON_SAMPLE_COLLECTED = IBinder::FIRST_CALL_TRANSACTION, + LAST = ON_SAMPLE_COLLECTED, +}; + +} // Anonymous namespace + +class BpYfdTestSamplingListener : public SafeBpInterface<IYfdTestSamplingListener> { +public: + explicit BpYfdTestSamplingListener(const sp<IBinder>& impl) + : SafeBpInterface<IYfdTestSamplingListener>(impl, "BpYfdTestSamplingListener") {} + + ~BpYfdTestSamplingListener() override; + + void onSampleCollected(float medianLuma) override { + callRemoteAsync<decltype( + &IYfdTestSamplingListener::onSampleCollected)>(Tag::ON_SAMPLE_COLLECTED, medianLuma); + } +}; + +// Out-of-line virtual method definitions to trigger vtable emission in this translation unit (see +// clang warning -Wweak-vtables) +BpYfdTestSamplingListener::~BpYfdTestSamplingListener() = default; + +IMPLEMENT_META_INTERFACE(YfdTestSamplingListener, "android.gui.IYfdTestSamplingListener"); + +status_t BnYfdTestSamplingListener::onTransact(uint32_t code, const Parcel& data, Parcel* reply, + uint32_t flags) { + if (code < IBinder::FIRST_CALL_TRANSACTION || code > static_cast<uint32_t>(Tag::LAST)) { + return BBinder::onTransact(code, data, reply, flags); + } + auto tag = static_cast<Tag>(code); + switch (tag) { + case Tag::ON_SAMPLE_COLLECTED: + return callLocalAsync(data, reply, &IYfdTestSamplingListener::onSampleCollected); + } +} + +} // namespace android diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp old mode 100644 new mode 100755 index abff1c9d30..622d3b9c69 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -3136,4 +3136,84 @@ void ReleaseCallbackThread::threadMain() { } } +bool SurfaceComposerClient::yfdTest() { + bool supported = false; + ALOGD("yfdTest"); + ComposerService::getComposerService() -> yfdTest(&supported); + return supported; +} + +int32_t SurfaceComposerClient::getScreenRefreshMode() { + //ALOGD("getScreenRefreshMode"); + return ComposerService::getComposerService() -> getScreenRefreshMode(); +} + +void SurfaceComposerClient::setScreenRefreshMode(int32_t mode) { + //ALOGD("setScreenRefreshMode = %d", mode); + ComposerService::getComposerService()->setScreenRefreshMode(mode); +} + +int32_t SurfaceComposerClient::getHandwriteState() { + //ALOGD("getHandwriteState"); + return ComposerService::getComposerService() -> getHandwriteState(); +} + +void SurfaceComposerClient::setHandwriteState(int32_t state) { + //ALOGD("setHandwriteState = %d", state); + ComposerService::getComposerService()->setHandwriteState(state); +} + +status_t SurfaceComposerClient::addYfdTestListener( + const Rect& samplingArea, const sp<IBinder>& stopLayerHandle, + const sp<IYfdTestSamplingListener>& listener) { + //ALOGD("addYfdTestListener"); + return ComposerService::getComposerService()->addYfdTestListener(samplingArea, + stopLayerHandle, listener); +} + +status_t SurfaceComposerClient::removeYfdTestListener( + const sp<IYfdTestSamplingListener>& listener) { + //ALOGD("removeYfdTestListener"); + return ComposerService::getComposerService()->removeYfdTestListener(listener); +} + +status_t SurfaceComposerClient::addYfdEmrListener( + const sp<IYfdEmrListener>& listener) { + //ALOGD("addYfdEmrListener"); + return ComposerService::getComposerService()->addYfdEmrListener(listener); +} + +status_t SurfaceComposerClient::removeYfdEmrListener( + const sp<IYfdEmrListener>& listener) { + //ALOGD("removeYfdEmrListener"); + return ComposerService::getComposerService()->removeYfdEmrListener(listener); +} + +bool SurfaceComposerClient::setHandwriteAreas(const Rect& validArea, + const std::vector<Rect>& invalidAreas) { + bool ret = false; + //ALOGD("setHandwriteAreas"); + ComposerService::getComposerService() -> setHandwriteAreas(validArea, invalidAreas, &ret); + return ret; +} + +void SurfaceComposerClient::setHWLayerName(const String8& name) { + //ALOGD("setHWLayerName = %s", name.string()); + ComposerService::getComposerService() -> setHWLayerName(name); +} + +void SurfaceComposerClient::forceRefreshOnce() { + //ALOGD("forceRefreshOnce"); + return ComposerService::getComposerService() -> forceRefreshOnce(); +} + +void SurfaceComposerClient::updateHWLayerRef(bool increase, int pid) { + //ALOGD("updateHWLayerRef %d, %d", (increase == true), pid); + ComposerService::getComposerService() -> updateHWLayerRef(increase, pid); +} + +void SurfaceComposerClient::setHandwritePen(int32_t type, int32_t width, int32_t color, int32_t tag) { + ComposerService::getComposerService()->setHandwritePen(type, width, color, tag); +} + } // namespace android diff --git a/libs/gui/aidl/android/gui/ISurfaceComposer.aidl b/libs/gui/aidl/android/gui/ISurfaceComposer.aidl old mode 100644 new mode 100755 diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h old mode 100644 new mode 100755 index 3ff6735926..3dcc3c227d --- a/libs/gui/include/gui/ISurfaceComposer.h +++ b/libs/gui/include/gui/ISurfaceComposer.h @@ -63,6 +63,9 @@ struct DisplayState; struct InputWindowCommands; class HdrCapabilities; class Rect; +class IYfdTestSamplingListener; +class IYfdEmrListener; + using gui::FrameTimelineInfo; using gui::IDisplayEventConnection; @@ -118,6 +121,39 @@ public: bool isAutoTimestamp, const std::vector<client_cache_t>& uncacheBuffer, bool hasListenerCallbacks, const std::vector<ListenerCallbacks>& listenerCallbacks, uint64_t transactionId, const std::vector<uint64_t>& mergedTransactionIds) = 0; + + // add by shawn + virtual status_t yfdTest(bool* outSupported) const = 0; + + virtual status_t getScreenRefreshMode() = 0; + + virtual void setScreenRefreshMode(int mode) = 0; + + virtual status_t getHandwriteState() = 0; + + virtual void setHandwriteState(int state) = 0; + + virtual status_t addYfdTestListener(const Rect& samplingArea, + const sp<IBinder>& stopLayerHandle, + const sp<IYfdTestSamplingListener>& listener) = 0; + virtual status_t removeYfdTestListener(const sp<IYfdTestSamplingListener>& listener) = 0; + + virtual status_t addYfdEmrListener(const sp<IYfdEmrListener>& listener) = 0; + + virtual status_t removeYfdEmrListener(const sp<IYfdEmrListener>& listener) = 0; + + virtual status_t setHandwriteAreas(const Rect& validArea, + const std::vector<Rect>& invalidAreas, + bool* ret) = 0; + + virtual void setHWLayerName(const String8& name) = 0; + + virtual void forceRefreshOnce() = 0; + + virtual void updateHWLayerRef(bool increase, int pid) = 0; + + virtual void setHandwritePen(int type, int width, int color, int tag) = 0; + }; // ---------------------------------------------------------------------------- @@ -200,6 +236,20 @@ public: CLEAR_BOOT_DISPLAY_MODE, // Deprecated. Autogenerated by .aidl now. SET_OVERRIDE_FRAME_RATE, // Deprecated. Autogenerated by .aidl now. // Always append new enum to the end. + YFD_TEST, + YFD_GET_SCREEN_MODE, + YFD_SET_SCREEN_MODE, + YFD_GET_HW_STATE, + YFD_SET_HW_STATE, + YFD_ADD_TEST_LISTENER, + YFD_REMOVE_TEST_LISTENER, + YFD_ADD_EMR_LISTENER, + YFD_REMOVE_EMR_LISTENER, + YFD_SET_HW_AREAS, + YFD_SET_HW_LAYER_NAME, + YFD_FORCE_REFRESH_ONCE, + YFD_UPDATE_HW_LAYER_REF, + YFD_SET_HW_PEN, }; virtual status_t onTransact(uint32_t code, const Parcel& data, diff --git a/libs/gui/include/gui/IYfdEmrListener.h b/libs/gui/include/gui/IYfdEmrListener.h new file mode 100755 index 0000000000..55fb6c93e3 --- /dev/null +++ b/libs/gui/include/gui/IYfdEmrListener.h @@ -0,0 +1,47 @@ +/* + * 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:// .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 <vector> + +#include <binder/IInterface.h> +#include <binder/SafeInterface.h> + +namespace android { + +class IYfdEmrListener : public IInterface { +public: + DECLARE_META_INTERFACE(YfdEmrListener) + + virtual void onAddPoint(int action, float x, float y, int64_t eventtime, int pressure) = 0; + + virtual void onAddTrack(int left, int top, int right, int bottom) = 0; + + virtual void onSetPen(int type, int width, int color, int tag) = 0; +}; + +class BnYfdEmrListener : public SafeBnInterface<IYfdEmrListener> { +public: + BnYfdEmrListener() + : SafeBnInterface<IYfdEmrListener>("BnYfdEmrListener") {} + + status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, + uint32_t flags = 0) override; +}; + +} // namespace android diff --git a/libs/gui/include/gui/IYfdTestSamplingListener.h b/libs/gui/include/gui/IYfdTestSamplingListener.h new file mode 100644 index 0000000000..cbef6343f9 --- /dev/null +++ b/libs/gui/include/gui/IYfdTestSamplingListener.h @@ -0,0 +1,43 @@ +/* + * 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:// .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 <vector> + +#include <binder/IInterface.h> +#include <binder/SafeInterface.h> + +namespace android { + +class IYfdTestSamplingListener : public IInterface { +public: + DECLARE_META_INTERFACE(YfdTestSamplingListener) + + virtual void onSampleCollected(float medianLuma) = 0; +}; + +class BnYfdTestSamplingListener : public SafeBnInterface<IYfdTestSamplingListener> { +public: + BnYfdTestSamplingListener() + : SafeBnInterface<IYfdTestSamplingListener>("BnYfdTestSamplingListener") {} + + status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, + uint32_t flags = 0) override; +}; + +} // namespace android diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h old mode 100644 new mode 100755 index fb57f63dad..14f5f994b6 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -815,6 +815,37 @@ private: mutable Mutex mLock; status_t mStatus; sp<ISurfaceComposerClient> mClient; + +public: + static bool yfdTest(); + + static int32_t getScreenRefreshMode(); + + static void setScreenRefreshMode(int32_t mode); + + static int32_t getHandwriteState(); + + static void setHandwriteState(int32_t state); + + static status_t addYfdTestListener(const Rect& samplingArea, + const sp<IBinder>& stopLayerHandle, + const sp<IYfdTestSamplingListener>& listener); + + static status_t removeYfdTestListener(const sp<IYfdTestSamplingListener>& listener); + + static status_t addYfdEmrListener(const sp<IYfdEmrListener>& listener); + + static status_t removeYfdEmrListener(const sp<IYfdEmrListener>& listener); + + static bool setHandwriteAreas(const Rect& validArea, const std::vector<Rect>& invalidAreas); + + static void setHWLayerName(const String8& name); + + static void forceRefreshOnce(); + + static void updateHWLayerRef(bool increase, int pid); + + static void setHandwritePen(int32_t type, int32_t width, int32_t color, int32_t tag); }; // --------------------------------------------------------------------------- @@ -942,6 +973,7 @@ public: private: ReleaseBufferCallback popReleaseBufferCallbackLocked(const ReleaseCallbackId&) REQUIRES(mMutex); static sp<TransactionCompletedListener> sInstance; + }; } // namespace android diff --git a/libs/nativewindow/include/android/hardware_buffer.h b/libs/nativewindow/include/android/hardware_buffer.h index 21798d0e29..f5399bcc89 100644 --- a/libs/nativewindow/include/android/hardware_buffer.h +++ b/libs/nativewindow/include/android/hardware_buffer.h @@ -45,7 +45,7 @@ #ifndef ANDROID_HARDWARE_BUFFER_H #define ANDROID_HARDWARE_BUFFER_H -#include <android/rect.h> +#include "rect_custom.h" #include <inttypes.h> #include <sys/cdefs.h> diff --git a/libs/nativewindow/include/android/rect_custom.h b/libs/nativewindow/include/android/rect_custom.h new file mode 100644 index 0000000000..b36728e934 --- /dev/null +++ b/libs/nativewindow/include/android/rect_custom.h @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2010 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:// .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. + */ + +/** + * @addtogroup NativeActivity Native Activity + * @{ + */ + +/** + * @file rect.h + */ + +#ifndef ANDROID_RECT_H +#define ANDROID_RECT_H + +#include <stdint.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Rectangular window area. + * + * This is the NDK equivalent of the android.graphics.Rect class in Java. It is + * used with {@link ANativeActivityCallbacks::onContentRectChanged} event + * callback and the ANativeWindow_lock() function. + * + * In a valid ARect, left <= right and top <= bottom. ARect with left=0, top=10, + * right=1, bottom=11 contains only one pixel at x=0, y=10. + */ +typedef struct ARect { +#ifdef __cplusplus + typedef int32_t value_type; +#endif + /// Minimum X coordinate of the rectangle. + int32_t left; + /// Minimum Y coordinate of the rectangle. + int32_t top; + /// Maximum X coordinate of the rectangle. + int32_t right; + /// Maximum Y coordinate of the rectangle. + int32_t bottom; +} ARect; + +#ifdef __cplusplus +}; +#endif + +#endif // ANDROID_RECT_H + +/** @} */ diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp old mode 100644 new mode 100755 index 0c179aca57..0bcc66dd84 --- a/services/surfaceflinger/Android.bp +++ b/services/surfaceflinger/Android.bp @@ -21,6 +21,7 @@ cc_defaults { "-Wconversion", "-DANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION", "-DDISABLE_DEVICE_INTEGRATION", + "-DTARGET_EPD_SUPPORT", ], } diff --git a/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp b/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp old mode 100644 new mode 100755 index f126710cbc..8b7a4d3fc2 --- a/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp +++ b/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp @@ -1660,5 +1660,34 @@ void AidlComposer::addDisplay(Display display) { void AidlComposer::onHotplugConnect(Display display) { addDisplay(display); } + +#ifdef TARGET_EPD_SUPPORT +V2_4::Error AidlComposer::setPanelRefreshMode(Display display, int32_t mode) { + return V2_4::Error::UNSUPPORTED; +} + +V2_4::Error AidlComposer::setHwState(Display display, int32_t state) { + return V2_4::Error::UNSUPPORTED; +} + +V2_4::Error AidlComposer::getHwState(Display display, int32_t* state) { + return V2_4::Error::UNSUPPORTED; +} + +V2_4::Error AidlComposer::getPanelRefreshMode(Display display, int32_t* mode) { + return V2_4::Error::UNSUPPORTED; +} + +V2_4::Error AidlComposer::commitHwArea(Display display, const IComposerClient::Rect& validRect, + const std::vector<IComposerClient::Rect>& invalidRects) { + return V2_4::Error::UNSUPPORTED; +} + +V2_4::Error AidlComposer::setHandwritePen(Display display, int32_t type, + int32_t width, int32_t color, int32_t tag) { + return V2_4::Error::UNSUPPORTED; +} +#endif + } // namespace Hwc2 } // namespace android diff --git a/services/surfaceflinger/DisplayHardware/AidlComposerHal.h b/services/surfaceflinger/DisplayHardware/AidlComposerHal.h old mode 100644 new mode 100755 index 02dc490cff..4b7aa97e5f --- a/services/surfaceflinger/DisplayHardware/AidlComposerHal.h +++ b/services/surfaceflinger/DisplayHardware/AidlComposerHal.h @@ -231,6 +231,17 @@ public: aidl::android::hardware::graphics::composer3::ClientTargetPropertyWithBrightness* outClientTargetProperty) override; +#ifdef TARGET_EPD_SUPPORT + V2_4::Error setPanelRefreshMode(Display displayId, int32_t mode) override; + V2_4::Error setHwState(Display displayId, int32_t state) override; + V2_4::Error getHwState(Display displayId, int32_t* state) override; + V2_4::Error getPanelRefreshMode(Display displayId, int32_t* mode) override; + V2_4::Error commitHwArea(Display displayId, const IComposerClient::Rect& validRect, + const std::vector<IComposerClient::Rect>& invalidRects) override; + V2_4::Error setHandwritePen(Display display, int32_t type, int32_t width, + int32_t color, int32_t tag) override; +#endif + // AIDL Composer HAL Error setLayerBrightness(Display display, Layer layer, float brightness) override; Error setLayerBlockingRegion(Display display, Layer layer, diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp old mode 100644 new mode 100755 diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.h b/services/surfaceflinger/DisplayHardware/ComposerHal.h old mode 100644 new mode 100755 index cf677955bf..118928392e --- a/services/surfaceflinger/DisplayHardware/ComposerHal.h +++ b/services/surfaceflinger/DisplayHardware/ComposerHal.h @@ -255,6 +255,16 @@ public: VsyncPeriodChangeTimeline* outTimeline) = 0; virtual V2_4::Error setAutoLowLatencyMode(Display displayId, bool on) = 0; +#ifdef TARGET_EPD_SUPPORT + virtual V2_4::Error setPanelRefreshMode(Display displayId, int32_t mode) = 0; + virtual V2_4::Error setHwState(Display displayId, int32_t state) = 0; + virtual V2_4::Error getHwState(Display displayId, int32_t* state) = 0; + virtual V2_4::Error getPanelRefreshMode(Display displayId, int32_t* mode) = 0; + virtual V2_4::Error commitHwArea(Display display, const IComposerClient::Rect& validRect, + const std::vector<IComposerClient::Rect>& invalidRects) = 0; + virtual V2_4::Error setHandwritePen(Display display, int32_t type, + int32_t width, int32_t color, int32_t tag) = 0; +#endif virtual V2_4::Error getSupportedContentTypes( Display displayId, std::vector<IComposerClient::ContentType>* outSupportedContentTypes) = 0; diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp old mode 100644 new mode 100755 index 859826874e..6bed0726fc --- a/services/surfaceflinger/DisplayHardware/HWC2.cpp +++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp @@ -1020,6 +1020,50 @@ Error Layer::setBlockingRegion(const Region& region) { return static_cast<Error>(intError); } +#ifdef TARGET_EPD_SUPPORT +Error Display::setPanelRefreshMode(int32_t mode) { + auto intError = mComposer.setPanelRefreshMode(mId, mode); + return static_cast<Error>(intError); +} + +Error Display::setHwState(int32_t state) { + auto intError = mComposer.setHwState(mId, state); + return static_cast<Error>(intError); +} + +Error Display::getHwState(int32_t* state) const { + auto intError = mComposer.getHwState(mId, state); + return static_cast<Error>(intError); +} + +Error Display::getPanelRefreshMode(int32_t* mode) const { + auto intError = mComposer.getPanelRefreshMode(mId, mode); + return static_cast<Error>(intError); +} + +Error Display::commitHwArea(const Rect& validRect, const std::vector<Rect>& invalidRects) { + Hwc2::IComposerClient::Rect hwRect{validRect.left, validRect.top, + validRect.right, validRect.bottom}; + std::vector<Hwc2::IComposerClient::Rect> hwRects; + if (!invalidRects.empty()) { + size_t size = invalidRects.size(); + for (size_t rect = 0; rect < size; ++rect) { + hwRects.push_back({invalidRects[rect].left, invalidRects[rect].top, + invalidRects[rect].right, invalidRects[rect].bottom}); + } + } + + auto intError = mComposer mitHwArea(mId, hwRect, hwRects); + return static_cast<Error>(intError); +} + +Error Display::setHandwritePen(int32_t type, int32_t width, int32_t color, int32_t tag) { + auto intError = mComposer.setHandwritePen(mId, type, width, color, tag); + return static_cast<Error>(intError); +} + +#endif + } // namespace impl } // namespace HWC2 } // namespace android diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h old mode 100644 new mode 100755 index 2c3f94681a..8bd41fd339 --- a/services/surfaceflinger/DisplayHardware/HWC2.h +++ b/services/surfaceflinger/DisplayHardware/HWC2.h @@ -81,6 +81,12 @@ struct ComposerCallback { virtual void onComposerHalSeamlessPossible(hal::HWDisplayId) = 0; virtual void onComposerHalVsyncIdle(hal::HWDisplayId) = 0; virtual void onRefreshRateChangedDebug(const RefreshRateChangedDebugData&) = 0; +#ifdef TARGET_EPD_SUPPORT + virtual void onEmrPointRecived(hal::HWDisplayId display, int32_t action, + float x, float y, int64_t eventtime, int32_t preesure) = 0; + virtual void onUpdateRequestRecived(hal::HWDisplayId display, + int64_t eventtime) = 0; +#endif protected: ~ComposerCallback() = default; @@ -178,6 +184,14 @@ public: [[nodiscard]] virtual hal::Error setIdleTimerEnabled(std::chrono::milliseconds timeout) = 0; [[nodiscard]] virtual hal::Error getPhysicalDisplayOrientation( Hwc2::AidlTransform* outTransform) const = 0; +#ifdef TARGET_EPD_SUPPORT + [[nodiscard]] virtual hal::Error setPanelRefreshMode(int32_t mode) = 0; + [[nodiscard]] virtual hal::Error setHwState(int32_t state) = 0; + [[nodiscard]] virtual hal::Error getHwState(int32_t* state) const = 0; + [[nodiscard]] virtual hal::Error getPanelRefreshMode(int32_t* mode) const = 0; + [[nodiscard]] virtual hal::Error commitHwArea(const android::Rect& validRect, const std::vector<android::Rect>& invalidRects) = 0; + [[nodiscard]] virtual hal::Error setHandwritePen(int32_t type, int32_t width, int32_t color, int32_t tag) = 0; +#endif }; namespace impl { @@ -271,6 +285,15 @@ public: void onLayerDestroyed(hal::HWLayerId layerId) override; hal::Error getPhysicalDisplayOrientation(Hwc2::AidlTransform* outTransform) const override; +#ifdef TARGET_EPD_SUPPORT + hal::Error setPanelRefreshMode(int32_t mode) override; + hal::Error setHwState(int32_t state) override; + hal::Error getHwState(int32_t* state) const override; + hal::Error getPanelRefreshMode(int32_t* mode) const override; + hal::Error commitHwArea(const Rect& validRect, const std::vector<Rect>& invalidRects) override; + hal::Error setHandwritePen(int32_t type, int32_t width, int32_t color, int32_t tag) override; +#endif + private: // This may fail (and return a null pointer) if no layer with this ID exists diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp old mode 100644 new mode 100755 index d1edd02c27..7bcb72e28f --- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp +++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp @@ -77,6 +77,7 @@ using aidl::android::hardware::graphics::composer3::Capability; using aidl::android::hardware::graphics::composer3::DisplayCapability; namespace hal = android::hardware::graphics::composer::hal; + namespace android { HWComposer::~HWComposer() = default; @@ -1095,6 +1096,90 @@ void HWComposer::loadLayerMetadataSupport() { } } +#ifdef TARGET_EPD_SUPPORT +status_t HWComposer::setPanelRefreshMode(PhysicalDisplayId displayId, int32_t mode) { + RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); + const auto error = mDisplayData.at(displayId).hwcDisplay->setPanelRefreshMode(mode); + if (error == hal::Error::UNSUPPORTED) { + RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION); + } + if (error == hal::Error::BAD_PARAMETER) { + RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE); + } + RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR); + return NO_ERROR; +} + +status_t HWComposer::setHwState(PhysicalDisplayId displayId, int32_t state) { + RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); + const auto error = mDisplayData.at(displayId).hwcDisplay->setHwState(state); + if (error == hal::Error::UNSUPPORTED) { + RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION); + } + if (error == hal::Error::BAD_PARAMETER) { + RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE); + } + RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR); + return NO_ERROR; +} + +int32_t HWComposer::getHwState(PhysicalDisplayId displayId) const { + RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); + int32_t state; + auto error = mDisplayData.at(displayId).hwcDisplay->getHwState(&state); + if (error == hal::Error::UNSUPPORTED) { + RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION); + } + if (error == hal::Error::BAD_PARAMETER) { + RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE); + } + RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR); + return state; +} + +int32_t HWComposer::getPanelRefreshMode(PhysicalDisplayId displayId) const { + RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); + int32_t mode; + auto error = mDisplayData.at(displayId).hwcDisplay->getPanelRefreshMode(&mode); + if (error == hal::Error::UNSUPPORTED) { + RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION); + } + if (error == hal::Error::BAD_PARAMETER) { + RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE); + } + RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR); + return mode; +} + +status_t HWComposer::commitHwArea(PhysicalDisplayId displayId, const Rect& validRect, + const std::vector<Rect>& invalidRects) { + RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); + const auto error = mDisplayData[displayId].hwcDisplay->commitHwArea(validRect, invalidRects); + if (error == hal::Error::UNSUPPORTED) { + RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION); + } + if (error == hal::Error::BAD_PARAMETER) { + RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE); + } + RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR); + return NO_ERROR; +} + +status_t HWComposer::setHandwritePen(PhysicalDisplayId displayId, int32_t type, + int32_t width, int32_t color, int32_t tag) { + RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); + const auto error = mDisplayData[displayId].hwcDisplay->setHandwritePen(type, width, color, tag); + if (error == hal::Error::UNSUPPORTED) { + RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION); + } + if (error == hal::Error::BAD_PARAMETER) { + RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE); + } + RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR); + return NO_ERROR; +} +#endif + } // namespace impl } // namespace android diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h old mode 100644 new mode 100755 index bc5a71ea77..e37489a62f --- a/services/surfaceflinger/DisplayHardware/HWComposer.h +++ b/services/surfaceflinger/DisplayHardware/HWComposer.h @@ -292,6 +292,17 @@ public: virtual std::optional<PhysicalDisplayId> toPhysicalDisplayId(hal::HWDisplayId) const = 0; virtual std::optional<hal::HWDisplayId> fromPhysicalDisplayId(PhysicalDisplayId) const = 0; +#ifdef TARGET_EPD_SUPPORT + virtual status_t setPanelRefreshMode(PhysicalDisplayId displayId, int32_t mode) = 0; + virtual status_t setHwState(PhysicalDisplayId displayId, int32_t state) = 0; + virtual int32_t getHwState(PhysicalDisplayId displayId) const = 0; + virtual int32_t getPanelRefreshMode(PhysicalDisplayId displayId) const = 0; + virtual status_t commitHwArea(PhysicalDisplayId displayId, const Rect& validRect, + const std::vector<Rect>& invalidRects) = 0; + virtual status_t setHandwritePen(PhysicalDisplayId displayId, int32_t type, int32_t width, + int32_t color, int32_t tag) = 0; +#endif + // Composer 3.0 virtual status_t setBootDisplayMode(PhysicalDisplayId, hal::HWConfigId) = 0; virtual status_t clearBootDisplayMode(PhysicalDisplayId) = 0; @@ -449,6 +460,16 @@ public: const std::unordered_map<std::string, bool>& getSupportedLayerGenericMetadata() const override; +#ifdef TARGET_EPD_SUPPORT + status_t setPanelRefreshMode(PhysicalDisplayId displayId, int32_t) override; + status_t setHwState(PhysicalDisplayId displayId, int32_t state) override; + int32_t getHwState(PhysicalDisplayId displayId) const override; + int32_t getPanelRefreshMode(PhysicalDisplayId displayId) const override; + status_t commitHwArea(PhysicalDisplayId displayId, const Rect& validRect, const std::vector<Rect>& invalidRects) override; + status_t setHandwritePen(PhysicalDisplayId displayId, int32_t type, + int32_t width, int32_t color, int32_t tag) override; +#endif + // Composer 3.0 status_t setBootDisplayMode(PhysicalDisplayId, hal::HWConfigId) override; status_t clearBootDisplayMode(PhysicalDisplayId) override; diff --git a/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp b/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp old mode 100644 new mode 100755 index 58454325fe..028c878dbd --- a/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp +++ b/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp @@ -44,6 +44,10 @@ #include <algorithm> #include <cinttypes> +#include <queue> +#include <thread> +#include <condition_variable> +#include <pthread.h> using aidl::android::hardware::graphics::common::HdrConversionCapability; using aidl::android::hardware::graphics::common::HdrConversionStrategy; @@ -65,11 +69,39 @@ namespace { using android::hardware::Return; using android::hardware::Void; using android::HWC2::ComposerCallback; +using Task = std::function<void()>; class ComposerCallbackBridge : public IComposerCallback { public: + std::queue<Task> tasks; + std::mutex mtx; + std::condition_variable cv; + std::thread worker; + ComposerCallbackBridge(ComposerCallback& callback, bool vsyncSwitchingSupported) - : mCallback(callback), mVsyncSwitchingSupported(vsyncSwitchingSupported) {} + : mCallback(callback), mVsyncSwitchingSupported(vsyncSwitchingSupported) { + worker = std::thread([this]() { + while (true) { + Task task; + + { + std::unique_lock<std::mutex> lock(mtx); + cv.wait(lock, [this](){ return !tasks.empty(); }); + + task = std::move(tasks.front()); + tasks.pop(); + } + + task(); + } + }); + } + + ~ComposerCallbackBridge() { + if (worker.joinable()) { + worker.join(); + } + } Return<void> onHotplug(Display display, Connection connection) override { mCallback.onComposerHalHotplug(display, connection); @@ -111,6 +143,26 @@ public: return Void(); } +#ifdef TARGET_EPD_SUPPORT + Return<void> onEmrPoint(Display display, int32_t action, + float x, float y, int64_t eventtime, int32_t pressure) override { + { + std::lock_guard<std::mutex> lock(mtx); + tasks.push([this, display, action, x, y, eventtime, pressure]() { + mCallback.onEmrPointRecived(display, action, x, y, eventtime, pressure); + }); + } + + cv.notify_one(); + return android::hardware::Void(); + } + + Return<void> onUpdateRequest(Display display, int64_t eventtime) override { + mCallback.onUpdateRequestRecived(display, eventtime); + return android::hardware::Void(); + } +#endif + private: ComposerCallback& mCallback; const bool mVsyncSwitchingSupported; @@ -1803,6 +1855,86 @@ void CommandReader::takeClientTargetProperty( *outClientTargetProperty = data.clientTargetProperty; } +#ifdef TARGET_EPD_SUPPORT +V2_4::Error HidlComposer::setPanelRefreshMode(Display display, int32_t mode) { + using Error = V2_4::Error; + if (!mClient_2_4) { + return Error::UNSUPPORTED; + } + + return mClient_2_4->setPanelRefreshMode(display, mode); +} + +V2_4::Error HidlComposer::setHwState(Display display, int32_t state) { + using Error = V2_4::Error; + if (!mClient_2_4) { + return Error::UNSUPPORTED; + } + + return mClient_2_4->setHwState(display, state); +} + +V2_4::Error HidlComposer::getHwState(Display display, int32_t* state) { + using Error = V2_4::Error; + if (!mClient_2_4) { + return Error::UNSUPPORTED; + } + + Error error = kDefaultError_2_4; + mClient_2_4->getHwState(display, [&](const auto& tmpError, const auto& tmpState) { + error = tmpError; + if (error != V2_4::Error::NONE) { + return; + } + + *state = tmpState; + }); + + return error; +} + +V2_4::Error HidlComposer::getPanelRefreshMode(Display display, int32_t* mode) { + using Error = V2_4::Error; + if (!mClient_2_4) { + return Error::UNSUPPORTED; + } + + Error error = kDefaultError_2_4; + mClient_2_4->getPanelRefreshMode(display, [&](const auto& tmpError, const auto& tmpMode) { + error = tmpError; + if (error != V2_4::Error::NONE) { + return; + } + + *mode = tmpMode; + }); + + return error; +} + +V2_4::Error HidlComposer::commitHwArea(Display display, const IComposerClient::Rect& validRect, + const std::vector<IComposerClient::Rect>& invalidRects) { + using Error = V2_4::Error; + if (!mClient_2_4) { + return Error::UNSUPPORTED; + } + + return mClient_2_4->commitHwArea(display, validRect, invalidRects); +} + +V2_4::Error HidlComposer::setHandwritePen(Display display, int32_t type, + int32_t width, int32_t color, int32_t tag) { + using Error = V2_4::Error; + if (!mClient_2_4) { + return Error::UNSUPPORTED; + } + + return mClient_2_4->setHandwritePen(display, type, width, color, tag); +} + +#endif + + } // namespace Hwc2 } // namespace android diff --git a/services/surfaceflinger/DisplayHardware/HidlComposerHal.h b/services/surfaceflinger/DisplayHardware/HidlComposerHal.h old mode 100644 new mode 100755 index aa1a7206c6..b7a5d965a6 --- a/services/surfaceflinger/DisplayHardware/HidlComposerHal.h +++ b/services/surfaceflinger/DisplayHardware/HidlComposerHal.h @@ -340,6 +340,16 @@ public: Display display, aidl::android::hardware::graphics::composer3::ClientTargetPropertyWithBrightness* outClientTargetProperty) override; +#ifdef TARGET_EPD_SUPPORT + V2_4::Error setPanelRefreshMode(Display displayId, int32_t mode) override; + V2_4::Error setHwState(Display displayId, int32_t state) override; + V2_4::Error getHwState(Display displayId, int32_t* state) override; + V2_4::Error getPanelRefreshMode(Display displayId, int32_t* mode) override; + V2_4::Error commitHwArea(Display displayId, const IComposerClient::Rect& validRect, + const std::vector<IComposerClient::Rect>& invalidRects) override; + V2_4::Error setHandwritePen(Display display, int32_t type, int32_t width, + int32_t color, int32_t tag) override; +#endif // AIDL Composer HAL Error setLayerBrightness(Display display, Layer layer, float brightness) override; diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h old mode 100644 new mode 100755 index 0f4b820ab7..c481c5b706 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -926,6 +926,8 @@ public: uint32_t qtiGetSmomoLayerStackId(); /* QTI_END */ + virtual void releaseHWBuffer() {} + protected: // For unit tests friend class TestableSurfaceFlinger; diff --git a/services/surfaceflinger/Scheduler/EventThread.cpp b/services/surfaceflinger/Scheduler/EventThread.cpp old mode 100644 new mode 100755 diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp old mode 100644 new mode 100755 index edbe050d7c..1d4f73d060 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -25,7 +25,7 @@ #pragma clang diagnostic ignored "-Wconversion" #pragma clang diagnostic ignored "-Wextra" -//#define LOG_NDEBUG 0 +#define LOG_NDEBUG 0 #define ATRACE_TAG ATRACE_TAG_GRAPHICS #include "SurfaceFlinger.h" @@ -170,6 +170,9 @@ #include <aidl/android/hardware/graphics/composer3/DisplayCapability.h> #include <aidl/android/hardware/graphics/composer3/RenderIntent.h> +#include <gui/IYfdTestSamplingListener.h> +#include <gui/IYfdEmrListener.h> + #undef NO_THREAD_SAFETY_ANALYSIS #define NO_THREAD_SAFETY_ANALYSIS \ _Pragma("GCC error \"Prefer <ftl/fake_guard.h> or MutexUtils.h helpers.\"") @@ -518,7 +521,18 @@ LatchUnsignaledConfig SurfaceFlinger::getLatchUnsignaledConfig() { SurfaceFlinger::~SurfaceFlinger() = default; -void SurfaceFlinger::binderDied(const wp<IBinder>&) { +void SurfaceFlinger::binderDied(const wp<IBinder>& who) { + { + std::lock_guard lock(mYfdEmrListenerMutex); + // the YfdEmrListener died. + if (!mDescriptors2.empty() && mDescriptors2.find(who) != mDescriptors2.end()) { + ALOGE("YfdEmrListener binder died before mDescriptors2 size = %" PRId32".", (int)mDescriptors2.size()); + mDescriptors2.erase(who); + ALOGE("YfdEmrListener binder died after mDescriptors2 size = %" PRId32".", (int)mDescriptors2.size()); + clearHWLayer(); + return; + } + } // the window manager died on us. prepare its eulogy. mBootFinished = false; @@ -2827,7 +2841,18 @@ void SurfaceFlinger::composite(TimePoint frameTime, VsyncId vsyncId) mVisibleRegionsDirty = false; if (mCompositionEngine->needsAnotherUpdate()) { + if (mRefreshState == rInvalidate) { + mRefreshState = rRefresh; + ALOGD("%s need rs=%d", __FUNCTION__, mRefreshState); + } scheduleCommit(FrameHint::kNone); + } else { + ALOGD("%s no need rs=%d", __FUNCTION__, mRefreshState); + if (mRefreshState == rInvalidate || mRefreshState == rReInvalidate) { + mRefreshState = rCompleted; + mForceRefreshOnce = false; + ALOGD("force refresh-"); + } } if (mPowerHintSessionEnabled) { @@ -4362,6 +4387,108 @@ bool SurfaceFlinger::latchBuffers() { } /* QTI_END */ + ALOGI("%s:: mLayersWithQueuedFrames size=%zu", __FUNCTION__, mLayersWithQueuedFrames.size()); + + if (mHwInitStage) { + // ALOGI("%s:: hw init stage", __FUNCTION__ ); + + // ensure layer refresh once, otherwise black + if ((mHwLayerName.size() > 0) && (mLayersWithQueuedFrames.size() > 0)) { + for (auto& layer : mLayersWithQueuedFrames) { + if (layer->getName().find(mHwLayerName, 0) != std::string::npos) { + mHwInitStage = false; + ALOGI("%s:: hw will init ready after this whole refresh cycle", __FUNCTION__ ); + forceRefreshOnce(); + break; + } + } + } + + } else { + if (mHwLayerName.size() > 0) { + + /*if (mIsWriting) { + if (mLayersWithQueuedFrames.size() > 0) { + bool hw = false; + bool other = false; + + for (auto& layer : mLayersWithQueuedFrames) { + if (layer->getName().find(mHwLayerName, 0) != std::string::npos) { + hw = true; + }else { + other = true; + } + } + + if (hw) { + mIsWriting = false; + //ALOGI("pen up"); + + if (other) { + // more layers update, don't intercept and reset + mLayerUpdate = false; + //ALOGI("reset"); + } + } + if (other) { + mLayerUpdate = true; + //ALOGI("state 1"); + } + } else { + // like refresh or rotation + mLayerUpdate = true; + //ALOGI("state 2"); + } + }*/ + + if (1 == mLayersWithQueuedFrames.size()) { + auto it = mLayersWithQueuedFrames.begin(); + sp<Layer> layer = *it; + if (layer->getName().find(mHwLayerName, 0) != std::string::npos) { + /* + if (!mIsWriting && mLayerUpdate) { + //ALOGE("%s:: force refresh 1", __FUNCTION__); + mForceRefreshOnce = true; + } + */ + + if(!mForceRefreshOnce) { + ALOGD("%s,ignore:%s", __FUNCTION__, layer->getName().c_str()); + layer -> releaseHWBuffer(); + mLayersWithQueuedFrames.clear(); + mTraceLayerUpdated = true; + return false; + } else { + ALOGD("%s,rs=%d, fr:%s", __FUNCTION__, mRefreshState, layer->getName().c_str()); + if (mRefreshState == rFrameAvailable) { + mRefreshState = rInvalidate; + } else if (mRefreshState == rRefresh) { + mRefreshState = rReInvalidate; + } + mTraceLayerUpdated = true; + } + } + } else if ((mLayersWithQueuedFrames.size() > 1) ) { + ALOGD("%s rs=%d", __FUNCTION__, mRefreshState); + if (mRefreshState == rFrameAvailable) { + mRefreshState = rInvalidate; + } else if (mRefreshState == rRefresh) { + mRefreshState = rReInvalidate; + } + + // pen up and has multi layers update + if (!mTraceLayerUpdated) { + for (auto& layer : mLayersWithQueuedFrames) { + if (layer->getName().find(mHwLayerName, 0) != std::string::npos) { + mTraceLayerUpdated = true; + break; + } + } + } + } + } + } + // The client can continue submitting buffers for offscreen layers, but they will not // be shown on screen. Therefore, we need to latch and release buffers of offscreen // layers to ensure dequeueBuffer doesn't block indefinitely. @@ -6682,6 +6809,22 @@ status_t SurfaceFlinger::CheckTransactCodeCredentials(uint32_t code) { case GET_MAX_ACQUIRED_BUFFER_COUNT: LOG_FATAL("Deprecated opcode: %d, migrated to AIDL", code); return PERMISSION_DENIED; + case YFD_TEST: + case YFD_GET_SCREEN_MODE: + case YFD_SET_SCREEN_MODE: + case YFD_GET_HW_STATE: + case YFD_SET_HW_STATE: + case YFD_ADD_TEST_LISTENER: + case YFD_REMOVE_TEST_LISTENER: + case YFD_ADD_EMR_LISTENER: + case YFD_REMOVE_EMR_LISTENER: + case YFD_SET_HW_AREAS: + case YFD_SET_HW_LAYER_NAME: + case YFD_FORCE_REFRESH_ONCE: + case YFD_UPDATE_HW_LAYER_REF: + case YFD_SET_HW_PEN: { + return OK; + } } // These codes are used for the IBinder protocol to either interrogate the recipient @@ -9650,6 +9793,490 @@ const DisplayDevice* SurfaceFlinger::getDisplayFromLayerStack(ui::LayerStack lay return nullptr; } + +#ifdef TARGET_EPD_SUPPORT +status_t SurfaceFlinger::yfdTest(bool* outSupported) const { + if (!outSupported) { + return BAD_VALUE; + } + // *outSupported = getRenderEngine().supportsProtectedContent(); + ALOGI("yfdTest"); + + std::vector<SurfaceFlinger::Descriptor1> descriptors1; + + for (const auto& [listener, descriptor] : mDescriptors1) { + descriptors1.emplace_back(descriptor); + } + + std::vector<Descriptor1> activeDescriptors; + for (const auto& descriptor : descriptors1) { + activeDescriptors.emplace_back(descriptor); + } + for (size_t d = 0; d < activeDescriptors.size(); ++d) { + activeDescriptors[d].listener -> onSampleCollected(4); + } + + /*std::vector<SurfaceFlinger::Descriptor2> descriptors2; + + for (const auto& [listener, descriptor] : mDescriptors2) { + descriptors2.emplace_back(descriptor); + } + + std::vector<Descriptor2> activeDescriptors2; + for (const auto& descriptor : descriptors2) { + activeDescriptors2.emplace_back(descriptor); + } + for (size_t d = 0; d < activeDescriptors2.size(); ++d) { + activeDescriptors2[d].listener -> onAddPoint(1, 100, 200, 1690, 398); + activeDescriptors2[d].listener -> onAddTrack(111, 222, 333, 444); + activeDescriptors2[d].listener -> onSetPen(5, 6, 7, 1690); + } + + SkCanvas* mCanvas = nullptr; + bool b = mCanvas->isClipRect(); + ALOGI("SurfaceFlinger ddddddddddd = %d", b); + */ + return NO_ERROR; +} + +int32_t SurfaceFlinger::getScreenRefreshMode() { + Mutex::Autolock lock(mStateLock); + sp<DisplayDevice> display = getDefaultDisplayDeviceLocked(); + const sp<IBinder> token = display->getDisplayToken().promote(); + if (const auto displayId = getPhysicalDisplayIdLocked(token)) { + mScreenRefreshMode = getHwComposer().getPanelRefreshMode(*displayId); + return mScreenRefreshMode; + } else { + ALOGE("%s: Invalid display token %p", __FUNCTION__, token.get()); + return -1; + } + ALOGI("getScreenRefreshMode %d", mScreenRefreshMode); + return mScreenRefreshMode; +} + +void SurfaceFlinger::setScreenRefreshMode(int32_t mode) { + Mutex::Autolock lock(mStateLock); + ALOGI("setScreenRefreshMode = %d", mode); + mScreenRefreshMode = mode; + sp<DisplayDevice> display = getDefaultDisplayDeviceLocked(); + const sp<IBinder> token = display->getDisplayToken().promote(); + if (const auto displayId = getPhysicalDisplayIdLocked(token)) { + getHwComposer().setPanelRefreshMode(*displayId, mode); + } else { + ALOGE("%s: Invalid display token %p", __FUNCTION__, token.get()); + } +} + +int32_t SurfaceFlinger::getHandwriteState() { + Mutex::Autolock lock(mStateLock); + sp<DisplayDevice> display = getDefaultDisplayDeviceLocked(); + const sp<IBinder> token = display->getDisplayToken().promote(); + if (const auto displayId = getPhysicalDisplayIdLocked(token)) { + mHandwriteState = getHwComposer().getHwState(*displayId); + return mHandwriteState; + } else { + ALOGE("%s: Invalid display token %p", __FUNCTION__, token.get()); + return -1; + } + ALOGI("getHandwriteState %d", mHandwriteState); + return mHandwriteState; +} + +void SurfaceFlinger::setHandwriteState(int32_t state) { + Mutex::Autolock lock(mStateLock); + ALOGI("setHandwriteState = %d", state); + mHandwriteState = state; + sp<DisplayDevice> display = getDefaultDisplayDeviceLocked(); + const sp<IBinder> token = display->getDisplayToken().promote(); + if (const auto displayId = getPhysicalDisplayIdLocked(token)) { + getHwComposer().setHwState(*displayId, state); + } else { + ALOGE("%s: Invalid display token %p", __FUNCTION__, token.get()); + } + + if(state == 2) { + clearHWLayer(); + } + +} + +void SurfaceFlinger::onEmrPointRecived(hal::HWDisplayId hwcDisplayId, + int32_t action, float x, float y, int64_t eventtime, int32_t pressure) { + int width = 0; + int height = 0; + float rotate_temp = 0; + // Mutex::Autolock lock(mStateLock); + std::vector<SurfaceFlinger::Descriptor2> descriptors2; + std::vector<Descriptor2> activeDescriptors2; + { + std::lock_guard lock(mYfdEmrListenerMutex); + if (mDescriptors2.empty()) { + ALOGE("YfdEmrListener is null"); + return; + } + + for (const auto& [listener, descriptor] : mDescriptors2) { + descriptors2.emplace_back(descriptor); + } + } + for (const auto& descriptor : descriptors2) { + activeDescriptors2.emplace_back(descriptor); + } + + if (mHwInitStage) { + mHwInitStage = false; + } + + Mutex::Autolock lock(mStateLock); + const auto display = getDefaultDisplayDeviceLocked(); + if (display && display->isPrimary()) { + //vertical display + height = display->getWidth(); + width = display->getHeight(); + switch (display->getOrientation()) { + case ui::ROTATION_270: + //default direction + break; + case ui::ROTATION_0: + if (x >= 0 && y >= 0) { + rotate_temp = x; + x = y; + y = width - rotate_temp; + if (y >= width) + y = width - 1; + if (y < 0) + y = 0; + } + break; + case ui::ROTATION_90: + if (x >= 0 && y >= 0) { + x = width - x; + if (x >= width) + x = width - 1; + if (x < 0) + x = 0; + y = height - y; + if (y >= height) + y = height - 1; + if (y < 0) + y = 0; + } + break; + case ui::ROTATION_180: + if (x >= 0 && y >= 0) { + rotate_temp = y; + y = x; + x = height - rotate_temp; + if (x >= height) + x = height - 1; + if (x < 0) + x = 0; + } + break; + default: + break; + } + } + + if (action == 1) { + ALOGI("pen down"); + //mIsWriting = true; + //mLayerUpdate = false; + mTraceLayerUpdated = true; + + track_rect = {static_cast<int32_t>(x), static_cast<int32_t>(y), static_cast<int32_t>(x), static_cast<int32_t>(y)}; + } else if (action == 3 || action == 2) { + // action is move or up, update rect + track_rect.left = std::min(track_rect.left, static_cast<int32_t>(x)); + track_rect.top = std::min(track_rect.top, static_cast<int32_t>(y)); + track_rect.right = std::max(track_rect.right, static_cast<int32_t>(x)); + track_rect.bottom = std::max(track_rect.bottom, static_cast<int32_t>(y)); + + if (action == 2) { + ALOGI("pen up"); + mTraceLayerUpdated = false; + } + } + // ALOGI("onEmrPointRecived action=%x,x=%f,y=%f,eventtime=%" PRId64",pressure=%" PRId32"", action, x, y, eventtime, pressure); + for (size_t d = 0; d < activeDescriptors2.size(); ++d) { + activeDescriptors2[d].listener -> onAddPoint(action, x, y, eventtime, pressure); + if (action == 2) { +// ALOGI("SurfaceFlinger onAddTrack rect = [%d, %d, %d, %d]", +// track_rect.left, track_rect.top, track_rect.right, track_rect.bottom); + activeDescriptors2[d].listener -> onAddTrack( + track_rect.left, track_rect.top, track_rect.right, track_rect.bottom); + + } +// activeDescriptors2[d].listener -> onSetPen(5, 6, 7, 1690); + } + +} + +void SurfaceFlinger::onUpdateRequestRecived(hal::HWDisplayId hwcDisplayId, + int64_t eventtime) { + Mutex::Autolock lock(mStateLock); + + ALOGI("updateRequest %" PRId64"", eventtime); + + if (mTraceLayerUpdated) { + scheduleComposite(FrameHint::kActive); + } else { + ALOGE("updateRequest: hw trace later, force refresh! "); + forceRefreshOnce(); + } +} + +status_t SurfaceFlinger::addYfdTestListener(const Rect& samplingArea, + const sp<IBinder>& stopLayerHandle, + const sp<IYfdTestSamplingListener>& listener) { + if (!listener || samplingArea == Rect::INVALID_RECT) { + return BAD_VALUE; + } + + sp<IBinder> asBinder = IInterface::asBinder(listener); + mDescriptors1.emplace(wp<IBinder>(asBinder), Descriptor1{listener}); + ALOGI("addYfdTestListener"); + + return NO_ERROR; +} + +status_t SurfaceFlinger::removeYfdTestListener(const sp<IYfdTestSamplingListener>& listener) { + if (!listener) { + return BAD_VALUE; + } + + mDescriptors1.erase(wp<IBinder>(IInterface::asBinder(listener))); + ALOGI("removeYfdTestListener"); + return NO_ERROR; +} + +status_t SurfaceFlinger::addYfdEmrListener(const sp<IYfdEmrListener>& listener) { + if (!listener) { + return BAD_VALUE; + } + + sp<IBinder> asBinder = IInterface::asBinder(listener); + if (asBinder != 0) { + asBinder->linkToDeath(sp<IBinder::DeathRecipient>::fromExisting(this)); + } + std::lock_guard lock(mYfdEmrListenerMutex); + mDescriptors2.emplace(wp<IBinder>(asBinder), Descriptor2{listener}); + ALOGI("addYfdEmrListener mDescriptors2 size = %" PRId32".", (int)mDescriptors2.size()); + + return NO_ERROR; +} + +status_t SurfaceFlinger::removeYfdEmrListener(const sp<IYfdEmrListener>& listener) { + if (!listener) { + ALOGE("removeYfdEmrListener listener is empty"); + return BAD_VALUE; + } + std::lock_guard lock(mYfdEmrListenerMutex); + // if (mDescriptors2.empty()) { + // ALOGE("removeYfdEmrListener mDescriptors2 is empty"); + // return BAD_VALUE; + // } + // wp<IBinder> rmBinder = wp<IBinder>(IInterface::asBinder(listener)); + // auto iter = mDescriptors2.find(rmBinder); + // if (iter == mDescriptors2.end()) { + // ALOGE("removeYfdEmrListener listener not found in mDescriptors2"); + // return BAD_VALUE; + // } + + // auto eraseCount = mDescriptors2.erase(rmBinder); + // if (eraseCount == 0) { + // ALOGE("removeYfdEmrListener failed to erase the listener"); + // return BAD_VALUE; + // } else { + // sp<IBinder> asBinder = IInterface::asBinder(listener); + // if (asBinder != 0) { + // asBinder->unlinkToDeath(sp<IBinder::DeathRecipient>::fromExisting(this)); + // } + // } + wp<IBinder> rmBinder = wp<IBinder>(IInterface::asBinder(listener)); + auto eraseCount = mDescriptors2.erase(rmBinder); + if (eraseCount == 0) { + ALOGE("removeYfdEmrListener failed to erase the listener"); + } else { + sp<IBinder> asBinder = IInterface::asBinder(listener); + if (asBinder != 0) { + asBinder->unlinkToDeath(sp<IBinder::DeathRecipient>::fromExisting(this)); + } + } + ALOGI("removeYfdEmrListener mDescriptors2 size = %" PRId32".", (int)mDescriptors2.size()); + return NO_ERROR; +} + +status_t SurfaceFlinger::setHandwriteAreas(const Rect& validArea, + const std::vector<Rect>& invalidAreas, + bool* ret ) { + int width = 0; + int height = 0; + int i = 0; + Rect validArea_rotation; + std::vector<Rect> invalidArea_rotation(invalidAreas); + + if (!ret) { + return BAD_VALUE; + } + + if (validArea == Rect::INVALID_RECT) { + return BAD_VALUE; + } + ALOGI("setHandwriteAreas [%d,%d - %d,%d]", validArea.left, validArea.top, + validArea.right, validArea.bottom); + size_t len = invalidAreas.size(); + ALOGI("setHandwriteAreas :invalidAreas size = %zu ", len); + + for (const auto& r : invalidAreas) { + ALOGI("setHandwriteAreas : invalidAreas = [%d, %d - %d, %d]", + r.left, r.top, r.right, r.bottom); + } + + validArea_rotation.left = validArea.left; + validArea_rotation.top = validArea.top; + validArea_rotation.right = validArea.right; + validArea_rotation.bottom = validArea.bottom; + + Mutex::Autolock lock(mStateLock); + sp<DisplayDevice> display = getDefaultDisplayDeviceLocked(); + if (display && display->isPrimary()) { + height = display->getWidth(); + width = display->getHeight(); + switch (display->getOrientation()) { + case ui::ROTATION_270: + //default direction + break; + case ui::ROTATION_0: + validArea_rotation.left = width - validArea.bottom; + validArea_rotation.top = validArea.left; + validArea_rotation.right = width - validArea.top; + validArea_rotation.bottom = validArea.right; + if (!invalidAreas.empty()) { + for (i = 0; i < invalidAreas.size(); i++) { + invalidArea_rotation[i].left = width - invalidAreas[i].bottom; + invalidArea_rotation[i].top = invalidAreas[i].left; + invalidArea_rotation[i].right = width - invalidAreas[i].top; + invalidArea_rotation[i].bottom = invalidAreas[i].right; + } + } + break; + case ui::ROTATION_90: + validArea_rotation.left = width - validArea.right; + validArea_rotation.top = height - validArea.bottom; + validArea_rotation.right = width - validArea.left; + validArea_rotation.bottom = height - validArea.top; + if (!invalidAreas.empty()) { + for (i = 0; i < invalidAreas.size(); i++) { + invalidArea_rotation[i].left = width - invalidAreas[i].right; + invalidArea_rotation[i].top = height - invalidAreas[i].bottom; + invalidArea_rotation[i].right = width - invalidAreas[i].left; + invalidArea_rotation[i].bottom = height - invalidAreas[i].top; + } + } + break; + case ui::ROTATION_180: + validArea_rotation.left = validArea.top; + validArea_rotation.top = height - validArea.right; + validArea_rotation.right = validArea.bottom; + validArea_rotation.bottom = height - validArea.left; + if (!invalidAreas.empty()) { + for (i = 0; i < invalidAreas.size(); i++) { + invalidArea_rotation[i].left = invalidAreas[i].top; + invalidArea_rotation[i].top = height - invalidAreas[i].right; + invalidArea_rotation[i].right = invalidAreas[i].bottom; + invalidArea_rotation[i].bottom = height - invalidAreas[i].left; + } + } + break; + default: + break; + } + ALOGI("setHandwriteAreas new: [%d,%d - %d,%d], %s, width=%d, height=%d", validArea_rotation.left, validArea_rotation.top, + validArea_rotation.right, validArea_rotation.bottom, toCString(display->getOrientation()), width, height); + + ALOGI("setHandwriteAreas new:invalidAreas size = %zu ", invalidArea_rotation.size()); + for (const auto& r : invalidArea_rotation) { + ALOGI("setHandwriteAreas new: invalidAreas = [%d, %d - %d, %d]", + r.left, r.top, r.right, r.bottom); + } + } + + const sp<IBinder> token = display->getDisplayToken().promote(); + if (const auto displayId = getPhysicalDisplayIdLocked(token)) { + getHwComposer() mitHwArea(*displayId, validArea_rotation, invalidArea_rotation); + } else { + ALOGE("%s: Invalid display token %p", __FUNCTION__, token.get()); + } + + return NO_ERROR; +} + +void SurfaceFlinger::setHandwritePen(int32_t type, int32_t width, + int32_t color, int32_t tag) { + Mutex::Autolock lock(mStateLock); + ALOGI("setHandwritePen t=%d, w=%d, c=%d, t=%d", type, width, color, tag); + sp<DisplayDevice> display = getDefaultDisplayDeviceLocked(); + const sp<IBinder> token = display->getDisplayToken().promote(); + if (const auto displayId = getPhysicalDisplayIdLocked(token)) { + getHwComposer().setHandwritePen(*displayId, type, width, color, tag); + } else { + ALOGE("%s: Invalid display token %p", __FUNCTION__, token.get()); + } +} + + +void SurfaceFlinger::setHWLayerName(const String8& name) { + Mutex::Autolock lock(mStateLock); + + mHwInitStage = true; + mHwLayerName = name.string(); + ALOGI("setHWLayerName: %s" , name.string()); + + if (name.size() == 0) { + mHwLayerNum = 0; + mForceRefreshOnce = false; + mRefreshState = rCompleted; + } +} + +void SurfaceFlinger::forceRefreshOnce() { + // Mutex::Autolock lock(mStateLock); + if(mHwInitStage) { + return; + } + + ALOGI("force refresh+"); + mForceRefreshOnce = true; + mRefreshState = rReceiveSignal; +} + +void SurfaceFlinger::clearHWLayer() { + if (mHwLayerNum <= 0) { + mHwLayerNum = 0; + mHwLayerName = ""; + ALOGI("clear hw Layer"); + } +} + +void SurfaceFlinger::updateHWLayerRef(bool increase, int pid) { + if (increase) { + if (mHwPid != pid) { + mHwPid = pid; + mHwLayerNum = 0; + } + mHwLayerNum ++; + } else { + mHwLayerNum --; + clearHWLayer(); + } + + ALOGI("updateHWLayerRef %d, %d", mHwLayerNum, pid); +} + +#endif + + } // namespace android #if defined(__gl_h_) diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h old mode 100644 new mode 100755 index c50f4b8c80..ea183d9963 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -135,6 +135,8 @@ class TimeStats; class FrameTracer; class ScreenCapturer; class WindowInfosListenerInvoker; +class IYfdTestSamplingListener; +class IYfdEmrListener; using ::aidl::android::hardware::graphics::composer3::RefreshRateChangedDebugData; using frontend::TransactionHandler; @@ -203,6 +205,15 @@ enum class LatchUnsignaledConfig { using DisplayColorSetting = compositionengine::OutputColorSetting; +enum { + rReceiveSignal = 0x01, + rFrameAvailable = 0x02, + rInvalidate = 0x03, + rRefresh = 0x04, + rReInvalidate = 0x05, + rCompleted = 0x0, +}; + class SurfaceFlinger : public BnSurfaceComposer, public PriorityDumper, private IBinder::DeathRecipient, @@ -1479,6 +1490,81 @@ private: // WindowInfo ids visible during the last commit. std::unordered_set<int32_t> mVisibleWindowIds; + +#ifdef TARGET_EPD_SUPPORT + // add by yfd-shawn for HandWrite ++++++++++++ +public: + Rect track_rect = {INT32_MIN, INT32_MIN, INT32_MAX, INT32_MAX}; + + status_t yfdTest(bool* outSupported) const override; + int32_t getScreenRefreshMode() override; + void setScreenRefreshMode(int32_t mode) override; + int32_t getHandwriteState() override; + void setHandwriteState(int32_t state) override; + void onEmrPointRecived(hal::HWDisplayId hwcDisplayId, + int32_t action, float x, float y, int64_t eventtime, int32_t pressure) override; + void onUpdateRequestRecived(hal::HWDisplayId hwcDisplayId, + int64_t eventtime) override; + + status_t addYfdTestListener(const Rect& samplingArea, const sp<IBinder>& stopLayerHandle, + const sp<IYfdTestSamplingListener>& listener) override; + status_t removeYfdTestListener(const sp<IYfdTestSamplingListener>& listener) override; + + status_t addYfdEmrListener(const sp<IYfdEmrListener>& listener) override; + status_t removeYfdEmrListener(const sp<IYfdEmrListener>& listener) override; + + status_t setHandwriteAreas(const Rect& validArea, + const std::vector<Rect>& invalidAreas, + bool* ret) override; + void setHandwritePen(int32_t type, int32_t width, int32_t color, + int32_t tag) override; + + void setHWLayerName(const String8& name) override; + + void forceRefreshOnce() override; + + void updateHWLayerRef(bool increase, int pid) override; + +private: + struct Descriptor1 { + sp<IYfdTestSamplingListener> listener; + }; + struct WpHash { + size_t operator()(const wp<IBinder>& p) const { + return std::hash<IBinder*>()(p.unsafe_get()); + } + }; + std::unordered_map<wp<IBinder>, Descriptor1, WpHash> mDescriptors1; + + struct Descriptor2 { + sp<IYfdEmrListener> listener; + }; + + std::mutex mYfdEmrListenerMutex; + std::unordered_map<wp<IBinder>, Descriptor2, WpHash> mDescriptors2 GUARDED_BY(mYfdEmrListenerMutex); + + bool mForceRefreshOnce = false; + + bool mHwInitStage = false; + + //bool mIsWriting = false; + + //bool mLayerUpdate = false; + + bool mTraceLayerUpdated = true; + + int32_t mScreenRefreshMode = 0; + int32_t mHandwriteState = 0; + std::string mHwLayerName; + int32_t mHwLayerNum = 0; + int32_t mHwPid = -1; + uint32_t mRefreshState = 0; + + void clearHWLayer(); + + + // add by yfd-shawn for HandWrite ------------ +#endif }; class SurfaceComposerAIDL : public gui::BnSurfaceComposer { diff --git a/services/surfaceflinger/main_surfaceflinger.cpp b/services/surfaceflinger/main_surfaceflinger.cpp old mode 100644 new mode 100755 index cf23169eae..20ee4c83a3 --- a/services/surfaceflinger/main_surfaceflinger.cpp +++ b/services/surfaceflinger/main_surfaceflinger.cpp @@ -139,6 +139,11 @@ int main(int, char**) { set_sched_policy(0, SP_FOREGROUND); + // Put most SurfaceFlinger threads in the system-background cpuset + // Keeps us from unnecessarily using big cores + // Do this after the binder thread pool init + if (cpusets_enabled()) set_cpuset_policy(0, SP_FOREGROUND); + // initialize before clients can connect flinger->init(); diff --git a/services/surfaceflinger/surfaceflinger.rc b/services/surfaceflinger/surfaceflinger.rc old mode 100644 new mode 100755 index 39d7bd948d..3af8cf5ac9 --- a/services/surfaceflinger/surfaceflinger.rc +++ b/services/surfaceflinger/surfaceflinger.rc @@ -4,7 +4,8 @@ service surfaceflinger /system/bin/surfaceflinger group graphics drmrpc readproc capabilities SYS_NICE onrestart restart --only-if-running zygote - task_profiles HighPerformance + writepid /dev/cpuset/display/tasks + task_profiles DisplayHighPerformance socket pdx/system/vr/display/client stream 0666 system graphics u:object_r:pdx_display_client_endpoint_socket:s0 socket pdx/system/vr/display/manager stream 0666 system graphics u:object_r:pdx_display_manager_endpoint_socket:s0 socket pdx/system/vr/display/vsync stream 0666 system graphics u:object_r:pdx_display_vsync_endpoint_socket:s0

5、将libyfdpen.so 添加至vndk,以下为prebuilts/vndk/v33目录的具体修改:

diff --git a/arm/Android.bp b/arm/Android.bp old mode 100644 new mode 100755 index f99cb29..1ba8144 --- a/arm/Android.bp +++ b/arm/Android.bp @@ -4551,3 +4551,22 @@ vndk_prebuilt_shared { }, }, } + +vndk_prebuilt_shared { + name: "libyfdpen", + version: "33", + target_arch: "arm", + vendor_available: true, + product_available: true, + vndk: { + enabled: true, + }, + arch: { + arm: { + export_include_dirs: [ + "include/external/yfd_pen", + ], + srcs: ["arch-arm-armv7-a-neon/shared/vndk-core/libyfdpen.so"], + }, + }, +} diff --git a/arm/arch-arm-armv7-a-neon/shared/vndk-core/libyfdpen.so b/arm/arch-arm-armv7-a-neon/shared/vndk-core/libyfdpen.so new file mode 100755 index 0000000..5c1c9d3 Binary files /dev/null and b/arm/arch-arm-armv7-a-neon/shared/vndk-core/libyfdpen.so differ diff --git a/arm/configs/module_names.txt b/arm/configs/module_names.txt old mode 100644 new mode 100755 index e2ef7a9..c91310e --- a/arm/configs/module_names.txt +++ b/arm/configs/module_names.txt @@ -179,6 +179,7 @@ libvndksupport.so libvndksupport libvulkan.so libvulkan libwifi-system-iface.so libwifi-system-iface libxml2.so libxml2 +libyfdpen.so libyfdpen libyuv.so libyuv libz.so libz libziparchive.so libziparchive diff --git a/arm/configs/module_paths.txt b/arm/configs/module_paths.txt old mode 100644 new mode 100755 index dad550b..f169368 --- a/arm/configs/module_paths.txt +++ b/arm/configs/module_paths.txt @@ -179,6 +179,7 @@ libvndksupport.so system/core/libvndksupport libvulkan.so frameworks/native/vulkan/libvulkan libwifi-system-iface.so frameworks/opt/net/wifi/libwifi_system_iface libxml2.so external/libxml2 +libyfdpen.so external/yfd_pen libyuv.so external/libyuv/files libz.so external/zlib libziparchive.so system/libziparchive diff --git a/arm/configs/vndkcore.libraries.33.txt b/arm/configs/vndkcore.libraries.33.txt old mode 100644 new mode 100755 index 34976b9..d08053c --- a/arm/configs/vndkcore.libraries.33.txt +++ b/arm/configs/vndkcore.libraries.33.txt @@ -119,5 +119,6 @@ libui.so libusbhost.so libwifi-system-iface.so libxml2.so +libyfdpen.so libyuv.so libziparchive.so diff --git a/arm/include/external/yfd_pen/EmrTrack.h b/arm/include/external/yfd_pen/EmrTrack.h new file mode 100755 index 0000000..946c311 --- /dev/null +++ b/arm/include/external/yfd_pen/EmrTrack.h @@ -0,0 +1,38 @@ +/* + * 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:// .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 <vector> + +namespace android { + + struct EmrPoint { + int action; + float x; + float y; + long timestamp; + int pressure; + }; + + struct EmrTrack { + int penType = 0; + int penWidth = 0; + int penColor = 0; + std::vector<EmrPoint> pointList; + }; + +} // namespace android diff --git a/arm/include/external/yfd_pen/yfd_pen.h b/arm/include/external/yfd_pen/yfd_pen.h new file mode 100755 index 0000000..2e9e325 --- /dev/null +++ b/arm/include/external/yfd_pen/yfd_pen.h @@ -0,0 +1,121 @@ +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "SkCanvas.h" +#include "SkPaint.h" +#include "SkColor.h" +#include "SkBitmap.h" +#include "SkImageInfo.h" +#include "SkPath.h" + +#include "EmrTrack.h" + +enum +{ + MODE_UNKNOWN = 0x01, + MODE_HWC = 0x02, + MODE_SDK = 0x03, +}; +static int penByWho = MODE_UNKNOWN; + +// pen width +static const int PEN_WIDTH_DEFAULT = 5; +static const int PEN_WIDTH_THIN = PEN_WIDTH_DEFAULT; +static const int PEN_WIDTH_MEDIUM = 10; +static const int PEN_WIDTH_THICK = 20; +static const int PEN_WIDTH_EXTRA_THICK = 50; + +// tag +static const int TAG_PENVENDOR_WACOM_CP = 0; +static const int TAG_PENVENDOR_MAXEYE_US317 = 1; //排他协议是固定的Vendor Data0 = 0x55AA + + +static uint8_t *gray_dis_buf = NULL; +//static int bufLen; +static SkBitmap bmp;// = nullptr; +static SkPaint paint;// = nullptr; +static SkCanvas* mCanvas; +static SkPath path; +static SkPaint dashPaint; +static SkPaint dashPaintBg; +static SkPaint hwcPaint; +static int mPenWidth = PEN_WIDTH_THIN; +static int mTag = 0;//TAG_PENVENDOR_WACOM_CP; + +enum +{ + PEN_DOWN = 0x01, + PEN_UP = 0x02, + PEN_MOVE = 0x03, +}; + +static float penWidth; +static float lastX = 0; +static float lastY = 0; +static long last_action_time = 0; +static long cur_time = 0; +static long time_diff = 0; +static float distance = 0; +static bool canDraw = false; +static bool penIsCreate = false; + +static bool mIsColorful = false; +static uint32_t mPenColor = SK_ColorBLACK; + +// public ++++ +void libTest(); + + +void ballpointAll(float x1, float y1, float x2, float y2, int pressure, SkPaint p, SkCanvas *canvas, + int pWidth); + +void ballpointThin(float x1, float y1, float x2, float y2, int pressure, SkPaint p, SkCanvas *canvas); + +void ballpointMedium(float x1, float y1, float x2, float y2, int pressure, SkPaint p, SkCanvas *canvas); + +void ballpointThick(float x1, float y1, float x2, float y2, int pressure, SkPaint p, SkCanvas *canvas); + +void ballpointExtraThick(float x1, float y1, float x2, float y2, int pressure, SkPaint p, SkCanvas *canvas); + +void ballpointPen(float x1, float y1, float x2, float y2, + int width, int color, int pressure, int action); + +void ballpointPenHwc(float x1, float y1, float x2, float y2, + int width, int color, int pressure, int action); + +//bool penCreate(int w, int h, unsigned char *buf); +bool penCreate(int w, int h, uint8_t *buf, bool isColorful); + +bool penDestroy(); + +bool penCreateJni(int w, int h); + +bool penDestroyJni(); + +void lockBufferJni(uint8_t *buf); + +void unlockBufferJni(); + +uint8_t* getPenBmpBuf(); + +void readPixels(SkBitmap b, int xlen, int ylen); + +void dashPen(float x1, float y1, float x2, float y2, int action, int point_count); + +bool drawPoints(android::EmrTrack *track, int w, int h, uint8_t *buf); + +bool setPen(int type, int width, int color, int tag); + +// public ---- + +// private ++++ +void initDrawJni(SkBitmap bmp); + +void initDashDraw(); + +void initHWCDraw(SkBitmap bmp); + +int checkPenWidth(int width); +// private ---- diff --git a/arm64/Android.bp b/arm64/Android.bp old mode 100644 new mode 100755 index 6ef8a08..6267b47 --- a/arm64/Android.bp +++ b/arm64/Android.bp @@ -6780,3 +6780,28 @@ vndk_prebuilt_shared { }, }, } + +vndk_prebuilt_shared { + name: "libyfdpen", + version: "33", + target_arch: "arm64", + vendor_available: true, + product_available: true, + vndk: { + enabled: true, + }, + arch: { + arm: { + export_include_dirs: [ + "include/external/yfd_pen", + ], + srcs: ["arch-arm-armv8-a/shared/vndk-core/libyfdpen.so"], + }, + arm64: { + export_include_dirs: [ + "include/external/yfd_pen", + ], + srcs: ["arch-arm64-armv8-a/shared/vndk-core/libyfdpen.so"], + }, + }, +} diff --git a/arm64/arch-arm-armv8-a/shared/vndk-core/libyfdpen.so b/arm64/arch-arm-armv8-a/shared/vndk-core/libyfdpen.so new file mode 100755 index 0000000..5c1c9d3 Binary files /dev/null and b/arm64/arch-arm-armv8-a/shared/vndk-core/libyfdpen.so differ diff --git a/arm64/arch-arm64-armv8-a/shared/vndk-core/libyfdpen.so b/arm64/arch-arm64-armv8-a/shared/vndk-core/libyfdpen.so new file mode 100755 index 0000000..9f126b8 Binary files /dev/null and b/arm64/arch-arm64-armv8-a/shared/vndk-core/libyfdpen.so differ diff --git a/arm64/configs/module_names.txt b/arm64/configs/module_names.txt old mode 100644 new mode 100755 index 85d9e55..91fb4ff --- a/arm64/configs/module_names.txt +++ b/arm64/configs/module_names.txt @@ -182,6 +182,7 @@ libvndksupport.so libvndksupport libvulkan.so libvulkan libwifi-system-iface.so libwifi-system-iface libxml2.so libxml2 +libyfdpen.so libyfdpen libyuv.so libyuv libz.so libz libziparchive.so libziparchive diff --git a/arm64/configs/module_paths.txt b/arm64/configs/module_paths.txt old mode 100644 new mode 100755 index 7dd4d67..9f65ef4 --- a/arm64/configs/module_paths.txt +++ b/arm64/configs/module_paths.txt @@ -183,5 +183,6 @@ libvulkan.so frameworks/native/vulkan/libvulkan libwifi-system-iface.so frameworks/opt/net/wifi/libwifi_system_iface libxml2.so external/libxml2 libyuv.so external/libyuv/files +libyfdpen.so external/yfd_pen libz.so external/zlib libziparchive.so system/libziparchive diff --git a/arm64/configs/vndkcore.libraries.33.txt b/arm64/configs/vndkcore.libraries.33.txt old mode 100644 new mode 100755 index 2c75e33..c0284dd --- a/arm64/configs/vndkcore.libraries.33.txt +++ b/arm64/configs/vndkcore.libraries.33.txt @@ -120,5 +120,6 @@ libui.so libusbhost.so libwifi-system-iface.so libxml2.so +libyfdpen.so libyuv.so libziparchive.so diff --git a/arm64/include/external/yfd_pen/EmrTrack.h b/arm64/include/external/yfd_pen/EmrTrack.h new file mode 100755 index 0000000..946c311 --- /dev/null +++ b/arm64/include/external/yfd_pen/EmrTrack.h @@ -0,0 +1,38 @@ +/* + * 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:// .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 <vector> + +namespace android { + + struct EmrPoint { + int action; + float x; + float y; + long timestamp; + int pressure; + }; + + struct EmrTrack { + int penType = 0; + int penWidth = 0; + int penColor = 0; + std::vector<EmrPoint> pointList; + }; + +} // namespace android diff --git a/arm64/include/external/yfd_pen/yfd_pen.h b/arm64/include/external/yfd_pen/yfd_pen.h new file mode 100755 index 0000000..2e9e325 --- /dev/null +++ b/arm64/include/external/yfd_pen/yfd_pen.h @@ -0,0 +1,121 @@ +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "SkCanvas.h" +#include "SkPaint.h" +#include "SkColor.h" +#include "SkBitmap.h" +#include "SkImageInfo.h" +#include "SkPath.h" + +#include "EmrTrack.h" + +enum +{ + MODE_UNKNOWN = 0x01, + MODE_HWC = 0x02, + MODE_SDK = 0x03, +}; +static int penByWho = MODE_UNKNOWN; + +// pen width +static const int PEN_WIDTH_DEFAULT = 5; +static const int PEN_WIDTH_THIN = PEN_WIDTH_DEFAULT; +static const int PEN_WIDTH_MEDIUM = 10; +static const int PEN_WIDTH_THICK = 20; +static const int PEN_WIDTH_EXTRA_THICK = 50; + +// tag +static const int TAG_PENVENDOR_WACOM_CP = 0; +static const int TAG_PENVENDOR_MAXEYE_US317 = 1; //排他协议是固定的Vendor Data0 = 0x55AA + + +static uint8_t *gray_dis_buf = NULL; +//static int bufLen; +static SkBitmap bmp;// = nullptr; +static SkPaint paint;// = nullptr; +static SkCanvas* mCanvas; +static SkPath path; +static SkPaint dashPaint; +static SkPaint dashPaintBg; +static SkPaint hwcPaint; +static int mPenWidth = PEN_WIDTH_THIN; +static int mTag = 0;//TAG_PENVENDOR_WACOM_CP; + +enum +{ + PEN_DOWN = 0x01, + PEN_UP = 0x02, + PEN_MOVE = 0x03, +}; + +static float penWidth; +static float lastX = 0; +static float lastY = 0; +static long last_action_time = 0; +static long cur_time = 0; +static long time_diff = 0; +static float distance = 0; +static bool canDraw = false; +static bool penIsCreate = false; + +static bool mIsColorful = false; +static uint32_t mPenColor = SK_ColorBLACK; + +// public ++++ +void libTest(); + + +void ballpointAll(float x1, float y1, float x2, float y2, int pressure, SkPaint p, SkCanvas *canvas, + int pWidth); + +void ballpointThin(float x1, float y1, float x2, float y2, int pressure, SkPaint p, SkCanvas *canvas); + +void ballpointMedium(float x1, float y1, float x2, float y2, int pressure, SkPaint p, SkCanvas *canvas); + +void ballpointThick(float x1, float y1, float x2, float y2, int pressure, SkPaint p, SkCanvas *canvas); + +void ballpointExtraThick(float x1, float y1, float x2, float y2, int pressure, SkPaint p, SkCanvas *canvas); + +void ballpointPen(float x1, float y1, float x2, float y2, + int width, int color, int pressure, int action); + +void ballpointPenHwc(float x1, float y1, float x2, float y2, + int width, int color, int pressure, int action); + +//bool penCreate(int w, int h, unsigned char *buf); +bool penCreate(int w, int h, uint8_t *buf, bool isColorful); + +bool penDestroy(); + +bool penCreateJni(int w, int h); + +bool penDestroyJni(); + +void lockBufferJni(uint8_t *buf); + +void unlockBufferJni(); + +uint8_t* getPenBmpBuf(); + +void readPixels(SkBitmap b, int xlen, int ylen); + +void dashPen(float x1, float y1, float x2, float y2, int action, int point_count); + +bool drawPoints(android::EmrTrack *track, int w, int h, uint8_t *buf); + +bool setPen(int type, int width, int color, int tag); + +// public ---- + +// private ++++ +void initDrawJni(SkBitmap bmp); + +void initDashDraw(); + +void initHWCDraw(SkBitmap bmp); + +int checkPenWidth(int width); +// private ----

该步添加了两个so文件,通过附件上传。

注:64位的放到prebuilts/vndk/v33/arm64/arch-arm64-armv8-a/shared/vndk-core目录

       32位的放到prebuilts/vndk/v33/arm64/arch-arm-armv8-a/shared/vndk-core目录,都命名为libyfdpen.so这个名字。

6、libwuffs_mirror_release_c支持vendor,改动目录在external/wuffs-mirror-release-c:

diff --git a/Android.bp b/Android.bp index c928405..b48dfcb 100644 --- a/Android.bp +++ b/Android.bp @@ -30,6 +30,10 @@ cc_library_static { ], sdk_version: "minimum", host_supported: true, + vendor_available: true, + vndk: { + enabled: true, + }, target: { windows: { enabled: true,

7、external下添加自定义字库,需要在externel目录新建yfd_skia仓:

该仓内容以附件形式上传;

8、external添加yfd_pen仓及相关源码:

diff --git a/Android.bp b/Android.bp new file mode 100755 index 0000000..3822ab7 --- /dev/null +++ b/Android.bp @@ -0,0 +1,46 @@ +cc_library_shared {^M + name: "libyfdpen",^M +^M + host_supported: false,^M + native_bridge_supported: false,^M + recovery_available: false,^M + vendor_available: true,^M + vndk: {^M + enabled: true,^M + },^M + clang: true,^M + double_loadable: false,^M +^M + srcs:["yfd_pen.cpp"],^M +^M + shared_libs: [^M + "liblog",^M + "libcutils",^M + "libjpeg",^M + "libEGL",^M + "libGLESv2",^M + "libvulkan",^M + "libnativewindow",^M + "libexpat",^M + "libpiex",^M + "libpng",^M + "libz",^M + ],^M +^M + static_libs: [^M + "libskia_yfd",^M + "libft2.nodep",^M + "libperfetto_client_experimental",^M + "libwuffs_mirror_release_c",^M + ],^M +^M + cflags: [^M + "-Wall",^M + "-Werror",^M + "-Wno-unused-parameter",^M + ],^M +^M + export_static_lib_headers: ["libskia_yfd"],^M +^M + export_include_dirs: ["."],^M +}^M diff --git a/EmrTrack.h b/EmrTrack.h new file mode 100755 index 0000000..946c311 --- /dev/null +++ b/EmrTrack.h @@ -0,0 +1,38 @@ +/* + * 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:// .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 <vector> + +namespace android { + + struct EmrPoint { + int action; + float x; + float y; + long timestamp; + int pressure; + }; + + struct EmrTrack { + int penType = 0; + int penWidth = 0; + int penColor = 0; + std::vector<EmrPoint> pointList; + }; + +} // namespace android diff --git a/yfd_pen.cpp b/yfd_pen.cpp new file mode 100755 index 0000000..d88c798 --- /dev/null +++ b/yfd_pen.cpp @@ -0,0 +1,624 @@ +#include "yfd_pen.h"^M +#include <math.h>^M +#include <log/log.h>^M +#include <cutils/log.h>^M +#include <cutils/klog.h>^M +#include "SkCanvas.h"^M +#include "SkPaint.h"^M +#include "SkColor.h"^M +#include "SkBitmap.h"^M +#include "SkImageInfo.h"^M +#include "SkPath.h"^M +#include "SkPathEffect.h"^M +#include "SkDashPathEffect.h"^M +#include <cutils/properties.h>^M +#include <sys/time.h>^M +^M +^M +^M +#pragma clang diagnostic ignored "-Wunused-variable"^M +#pragma clang diagnostic ignored "-Wunused-parameter"^M +^M +android::EmrTrack emrTrack;^M +^M +//+++++++++++++++++++++++++++++ Utils^M +void checkCanvas() {^M + if (mCanvas != nullptr) {^M + delete mCanvas;^M + mCanvas = nullptr;^M + }^M +}^M +^M +void libTest() {^M + ALOGI("yfdPen::libTest");^M +}^M +^M +/*#include "SkTime.h"^M +#include "SkTypes.h"^M +#include "SkString.h"^M +#include "SkImage.h"^M +#include "SkImageEncoder.h"^M +#include "SkStream.h"^M +#include "SkData.h"^M +void saveToFile() {^M + // allow all permission to debug^M + if (access("/data/hwdump", F_OK) == 0) {^M + SkMSec now = SkTime::GetMSecs();^M + ALOGE("### SkBitmap, start>>>%u", now);^M + SkString filename;^M + filename.printf("/data/hwdump/%u.jpg", now);^M +^M + SkBitmap *bitmap = &bmp;^M +^M + SkImageInfo info = bitmap->info();^M +^M + SkFILEWStream file_stream(filename.c_str());^M +^M + if (!file_stream.isValid()) {^M + ALOGE("Failed to create file stream at =%s", filename.c_str());^M + return;^M + }^M +^M + SkPixmap pixmap;^M + if (!bitmap->peekPixels(&pixmap)) {^M + ALOGE("Failed to get SkPixmap from bitmap");^M + return;^M + }^M +^M + sk_sp <SkData> jpg_data = SkEncodePixmap(pixmap, SkEncodedImageFormat::kJPEG, 100);^M + if (!jpg_data) {^M + ALOGE("Failed to encode bitmap to JPG data");^M + return;^M + }^M +^M + file_stream.write(jpg_data->data(), jpg_data->size());^M + file_stream.flush();^M + }^M +}*/^M +^M +//----------------------------- Utils^M +^M +^M +/*^M + * CP serial pressure curve^M + * 5%(1), 5%(1), 10%(2), 20%(4), 20%(4), 40%(8)^M +**/^M +static const int MAX_STEP = 6;^M +static int preMap[MAX_STEP][2] = {{0, 70},^M + {71, 110},^M + {111, 150},^M + {151, 185},^M + {186, 215},^M + {216, 255}};^M +static int preMapNum[MAX_STEP] = {70, 39, 39, 34, 29, 39};^M +^M +/*^M +// good^M +static int widthMap[6][2] = {{7, 22}, {22, 30}, {30, 37}, {37, 41}, {41, 45}, {45, 50}};^M +static int widthMapNum[6] = {16, 9, 8, 5, 5, 6};^M +^M +// better^M +static int widthMap[6][2] = {{0, 20}, {20, 30}, {30, 37}, {37, 41}, {41, 45}, {45, 50}};^M +static int widthMapNum[6] = {20, 10, 7, 4, 4, 5};^M +*/^M +^M +static int widthMapET[MAX_STEP][2] = {{0, 20},^M + {20, 30},^M + {30, 37},^M + {37, 41},^M + {41, 45},^M + {45, 50}};^M +static int widthMapNumET[MAX_STEP] = {20, 10, 7, 4, 4, 5};^M +^M +static int widthMapMedium[MAX_STEP][2] = {{0, 3},^M + {3, 6},^M + {6, 7},^M + {7, 8},^M + {8, 9},^M + {9, 10}};^M +static int widthMapNumMedium[MAX_STEP] = {3, 3, 1, 1, 1, 1};^M +^M +static int widthMapThick[MAX_STEP][2] = {{0, 5},^M + {5, 10},^M + {10, 12},^M + {12, 15},^M + {15, 18},^M + {18, 20}};^M +static int widthMapNumThick[MAX_STEP] = {5, 5, 2, 3, 3, 2};^M +^M +^M +int lastPre = 0;^M +void ballpointExtraThick(float x1, float y1, float x2, float y2, int pressure, SkPaint p,^M + SkCanvas *canvas) {^M + /**^M + * 256 level: pre / 4096 x 32 = pre / 16^M + * 128 level: pre / 4096 x 128 = pre / 32^M + * 32 level: pre / 4096 x 32 = pre / 128^M + */^M +^M + int pre = pressure / 16;^M +^M + // check large pre change and correct^M + if ((pre <preMap[1][1]) && (lastPre - pre > 33)) {^M + //ALOGE("#### %d", pre);^M + pre = (lastPre + pre) / 2;^M + }^M +^M + lastPre = pre;^M +^M + if (pre < 8) {^M + //ALOGE("ignore pre=%d", pre);^M + return;^M + }^M +^M + for (int i = 0; i < MAX_STEP; ++i) {^M + if ((pre > preMap[i][0]) && (pre <= preMap[i][1])) {^M + ALOGI("pre=%d, i=%d",pre, i);^M + penWidth = (pre - preMap[i][0]) / (float) (preMapNum[i]) * widthMapNumET[i] +^M + widthMapET[i][0];^M + break;^M + }^M + }^M +^M + //ALOGI("PM:last=[%f, %f] cur=[%f, %f], p=%d, w=%f", x1, y1, x2, y2, pressure, penWidth);^M +^M + p.setStrokeWidth(penWidth);^M + canvas->drawLine(x1, y1, x2, y2, p);^M +}^M +^M +^M +void ballpointThin(float x1, float y1, float x2, float y2, int pressure, SkPaint p,^M + SkCanvas *canvas) {^M + if (mTag == TAG_PENVENDOR_WACOM_CP) {^M + if (pressure <= 1000) {^M + penWidth = 2;^M + } else if (pressure > 1000 && pressure <= 2500) {^M + penWidth = 3;^M + } else if (pressure > 2500 && pressure <= 4000) {^M + penWidth = 4;^M + } else {^M + penWidth = 5;^M + }^M + } else if (mTag == TAG_PENVENDOR_MAXEYE_US317) {^M + //after tuning, set to 128 level^M + int pre = pressure / 32;^M + penWidth = (pre / (float) 127) * 3 + 2;^M +^M + if(penByWho == MODE_HWC) {^M + ALOGI("PM:last=[%f, %f] cur=[%f, %f], p=%d, w=%f", x1, y1, x2, y2, pressure, penWidth);^M + }^M + }^M +^M + //ALOGI("PM:last=[%f, %f] cur=[%f, %f], p=%d, w=%f", x1, y1, x2, y2, pressure, penWidth);^M +^M + p.setStrokeWidth(penWidth);^M + canvas->drawLine(x1, y1, x2, y2, p);^M +}^M +^M +void ballpointMedium(float x1, float y1, float x2, float y2, int pressure, SkPaint p,^M + SkCanvas *canvas) {^M + int pre = pressure / 16;^M +^M + if (pre < 8) {^M + //ALOGI("ignore pre=%d", pre);^M + return;^M + }^M +^M + for (int i = 0; i < MAX_STEP; ++i) {^M + if ((pre > preMap[i][0]) && (pre <= preMap[i][1])) {^M + ALOGI("pre=%d, i=%d",pre, i);^M + penWidth = (pre - preMap[i][0]) / (float) (preMapNum[i]) * widthMapNumMedium[i] +^M + widthMapMedium[i][0];^M + break;^M + }^M + }^M +^M + //ALOGI("PM:last=[%f, %f] cur=[%f, %f], p=%d, w=%f", x1, y1, x2, y2, pressure, penWidth);^M +^M + p.setStrokeWidth(penWidth);^M + canvas->drawLine(x1, y1, x2, y2, p);^M +}^M +^M +void ballpointThick(float x1, float y1, float x2, float y2, int pressure, SkPaint p,^M + SkCanvas *canvas) {^M +^M + int pre = pressure / 16;^M +^M + if (pre < 8) {^M + //ALOGI("ignore pre=%d", pre);^M + return;^M + }^M +^M + for (int i = 0; i < MAX_STEP; ++i) {^M + if ((pre > preMap[i][0]) && (pre <= preMap[i][1])) {^M + ALOGI("pre=%d, i=%d", pre, i);^M + penWidth = (pre - preMap[i][0]) / (float) (preMapNum[i]) * widthMapNumThick[i] +^M + widthMapThick[i][0];^M + break;^M + }^M + }^M +^M + //ALOGI("PM:last=[%f, %f] cur=[%f, %f], p=%d, w=%f", x1, y1, x2, y2, pressure, penWidth);^M +^M + p.setStrokeWidth(penWidth);^M + canvas->drawLine(x1, y1, x2, y2, p);^M +}^M +^M +void ballpointAll(float x1, float y1, float x2, float y2, int pressure, SkPaint p, SkCanvas *canvas,^M + int pWidth) {^M +^M + switch (pWidth) {^M + case PEN_WIDTH_THIN:^M + ballpointThin(x1, y1, x2, y2, pressure, p, canvas);^M + break;^M + case PEN_WIDTH_MEDIUM:^M + ballpointMedium(x1, y1, x2, y2, pressure, p, canvas);^M + break;^M + case PEN_WIDTH_THICK:^M + ballpointThick(x1, y1, x2, y2, pressure, p, canvas);^M + break;^M + case PEN_WIDTH_EXTRA_THICK:^M + ballpointExtraThick(x1, y1, x2, y2, pressure, p, canvas);^M + break;^M + default:^M + ballpointThin(x1, y1, x2, y2, pressure, p, canvas);^M + break;^M + }^M +}^M +^M +void ballpointPen(float x1, float y1, float x2, float y2,^M + int width, int color, int pressure, int action)^M +{^M +^M + if (mCanvas == nullptr) {^M + ALOGE("ballpoint canvas is nullptr");^M + return;^M + }^M + if (!canDraw) {^M + ALOGE("ballpointPen canDraw is false");^M + return;^M + }^M + if (!penIsCreate) {^M + ALOGE("ballpointPen penIsCreate is false");^M + return;^M + }^M + if (action == PEN_DOWN) {^M + ALOGI("ballpoint PD last=[%f, %f] cur=[%f, %f], p=%d", x1, y1, x2, y2, pressure);^M + return;^M + } else if (action ==PEN_UP) {^M + ALOGI("ballpoint PU last=[%f, %f] cur=[%f, %f], p=%d", x1, y1, x2, y2, pressure);^M + return;^M + }^M +^M + ballpointAll(x1, y1, x2, y2, pressure, paint, mCanvas, mPenWidth);^M +}^M +^M +void ballpointPenHwc(float x1, float y1, float x2, float y2,^M + int width, int color, int pressure, int action)^M +{^M + if (mCanvas == nullptr) {^M + ALOGE("ballpointH canvas is nullptr");^M + return;^M + }^M + if (action == PEN_DOWN) {^M + ALOGI("ballpointH PD last=[%f, %f] cur=[%f, %f], p=%d", x1, y1, x2, y2, pressure);^M + return;^M + } else if (action ==PEN_UP) {^M + ALOGI("ballpointH PU last=[%f, %f] cur=[%f, %f], p=%d", x1, y1, x2, y2, pressure);^M + return;^M + }^M +^M + ballpointAll(x1, y1, x2, y2, pressure, hwcPaint, mCanvas, mPenWidth);^M +}^M +^M +void dashPen(float x1, float y1, float x2, float y2, int action, int point_count)^M +{^M + if (mCanvas == nullptr) {^M + ALOGE("dashPen canvas is nullptr");^M + return;^M + }^M + struct timeval tp;^M + gettimeofday(&tp, NULL);^M + cur_time = tp.tv_sec * 1000 + tp.tv_usec / 1000; // get current time (ms)^M +^M + if (action == PEN_DOWN) {^M + ALOGI("DashPD last=[%f, %f] cur=[%f, %f]", x1, y1, x2, y2);^M + path.reset();^M + path.moveTo(x1, y1);^M + lastX = x1;^M + lastY = y1; ^M + last_action_time = cur_time;^M + distance = 0;^M + return;^M + } else if (action == PEN_UP) {^M + ALOGI("DashPU last=[%f, %f] cur=[%f, %f]", x1, y1, x2, y2);^M + path.reset();^M + return;^M + }^M +^M + if (lastX != x1 && lastY != y1) {^M + path.reset();^M + path.moveTo(x1, y1);^M + }^M + //ALOGI("DashPM: last=[%f, %f] cur=[%f, %f], action=%d, point_count=%d", x1, y1, x2, y2, action,^M + // point_count);^M + distance += sqrt(pow(x2 - lastX, 2) + pow(y2 - lastY, 2));^M + time_diff = cur_time - last_action_time;^M +^M + if (((time_diff > 500 || distance > 500) && point_count > 5)) {^M + path.reset();^M + path.moveTo(x1, y1);^M + ALOGI("DashPM: time_diff=%ld, distance=%f, point_count=%d", time_diff, distance, point_count);^M + last_action_time = cur_time;^M + distance = 0;^M + }^M +^M + path.lineTo(x2, y2);^M + lastX = x2;^M + lastY = y2;^M + mCanvas->drawPath(path, dashPaintBg);^M + mCanvas->drawPath(path, dashPaint);^M +}^M +^M +bool penCreate(int w, int h, uint8_t *buf, bool isColorful) {^M + ALOGI("yfdPen::penCreate width = %d, height=%d, isColorful=%d", w, h, (isColorful == true));^M +^M + if (buf == nullptr) {^M + ALOGE("yfdPen::penCreate failed, buf=null");^M + return false;^M + }^M +^M + mIsColorful = isColorful;^M + penByWho = MODE_HWC;^M + gray_dis_buf = buf;^M +^M + SkImageInfo info;^M + if (isColorful) {^M + info = SkImageInfo::Make(w, h, kRGBA_8888_SkColorType, kPremul_SkAlphaType);^M + } else {^M + info = SkImageInfo::Make(w, h, kGray_8_SkColorType, kOpaque_SkAlphaType);^M + }^M +^M +^M + //bmp = new SkBitmap();^M + bmp.setInfo(info);^M + bmp.allocPixels();^M + //readPixels(bmp,50,1);^M + bmp.setPixels(gray_dis_buf);^M +^M + initHWCDraw(bmp);^M + initDashDraw();^M + return true;^M +}^M +^M +void initDrawJni(SkBitmap bmp) {^M + checkCanvas();^M + mCanvas = new SkCanvas(bmp);^M + paint.setColor(mPenColor);^M + paint.setStyle(SkPaint::kStrokeAndFill_Style);^M + paint.setStrokeJoin(SkPaint::kRound_Join);^M + paint.setStrokeCap(SkPaint::kRound_Cap);^M + paint.setAntiAlias(true);^M + paint.setDither(true);^M +}^M +^M +void initDashDraw() {^M + dashPaint.setColor(SK_ColorBLACK);^M + dashPaint.setStyle(SkPaint::kStroke_Style);^M + dashPaint.setStrokeJoin(SkPaint::kRound_Join);^M + dashPaint.setStrokeCap(SkPaint::kRound_Cap);^M + dashPaint.setDither(true);^M + dashPaint.setStrokeWidth(2);^M + constexpr SkScalar intervals[2] = { 14, 14 };^M + sk_sp<SkPathEffect> dashEffect = SkDashPathEffect::Make(intervals, 2, 0);^M + dashPaint.setPathEffect(dashEffect);^M +^M + dashPaintBg.setColor(SK_ColorWHITE);^M + dashPaintBg.setStyle(SkPaint::kStroke_Style);^M + dashPaintBg.setStrokeJoin(SkPaint::kRound_Join);^M + dashPaintBg.setStrokeCap(SkPaint::kRound_Cap);^M + dashPaintBg.setDither(true);^M + dashPaintBg.setStrokeWidth(2);^M + sk_sp<SkPathEffect> dashEffectBg = SkDashPathEffect::Make(intervals, 2, 14);^M + dashPaintBg.setPathEffect(dashEffectBg);^M +}^M +^M +void initHWCDraw(SkBitmap bmp) {^M + checkCanvas();^M + mCanvas = new SkCanvas(bmp);^M + hwcPaint.setColor(mPenColor); // SK_ColorBLACK^M + hwcPaint.setStyle(SkPaint::kStrokeAndFill_Style);^M + hwcPaint.setStrokeJoin(SkPaint::kRound_Join);^M + hwcPaint.setStrokeCap(SkPaint::kRound_Cap);^M + hwcPaint.setDither(true);^M +}^M +^M +bool penDestroy() {^M + if (gray_dis_buf == nullptr) {^M + ALOGE("yfdPen::penDestroy failed, gray_dis_buf = null");^M + return false;^M + }^M +^M + penByWho = MODE_UNKNOWN;^M + gray_dis_buf = nullptr;^M + checkCanvas();^M + bmp.reset();^M + ALOGI("yfdPen::penDestroyed");^M + return true;^M +}^M +^M +void readPixels(SkBitmap bmp, int xlen, int ylen) {^M + ALOGI("yfdPen::readPixels width = %d, height= %d", xlen, ylen);^M +^M + for (int y = 0; y < ylen; y++ ) {^M + for (int x = 0; x < xlen; x++) {^M + const uint8_t* value = bmp.getAddr8(x, y);^M + ALOGI("yfdPen::readPixels bmp[%d, %d] = 0x%02x", x, y, *value);^M + }^M + }^M +}^M +^M +bool penCreateJni(int w, int h) {^M + ALOGI("yfdPen::penCreateJni w=%d, h=%d", w, h);^M +^M + penByWho = MODE_SDK;^M + ^M + // SkImageInfo info = SkImageInfo::Make(w, h, kARGB_4444_SkColorType, kPremul_SkAlphaType);^M + SkImageInfo info = SkImageInfo::Make(w, h, kRGBA_8888_SkColorType, kPremul_SkAlphaType);^M + //bufLen = w * h * 4; // ARGB8888^M + //bmp = SkBitmap();^M + bmp.setInfo(info);^M + // bmp.allocPixels();^M + //readPixels(bmp,50,1);^M + initDrawJni(bmp);^M + penIsCreate = true;^M + return true;^M +}^M +^M +bool penDestroyJni() {^M + // checkCanvas();^M + // bmp.reset();^M + penByWho = MODE_UNKNOWN;^M + canDraw = false;^M + penIsCreate = false;^M + ALOGI("yfdPen::penDestroyJni");^M + return true;^M +}^M +^M +void lockBufferJni(uint8_t *buf) {^M + if (buf == nullptr) {^M + ALOGI("yfdPen::lockBufferJni buf is null");^M + return;^M + }^M + gray_dis_buf = buf;^M + bmp.setPixels(gray_dis_buf);^M +^M + mCanvas = new SkCanvas(bmp);^M + canDraw = true;^M + ALOGI("yfdPen::lockBufferJni");^M +}^M +^M +void unlockBufferJni() {^M + gray_dis_buf = nullptr;^M + // bmp.allocPixels();^M + ALOGI("yfdPen::unlockBufferJni");^M +}^M +^M +uint8_t* getPenBmpBuf() {^M + ALOGI("yfdPen::getPenBmpBuf buf=%p", gray_dis_buf);^M + return gray_dis_buf;^M +}^M +^M +^M +/**^M + * drawPoints^M + *^M + * @param track^M + * @param w^M + * @param h^M + * @param buf^M + * @return^M + */^M +bool drawPoints(android::EmrTrack *track, int w, int h, uint8_t *buf) {^M +^M + if (buf == nullptr || track == nullptr) {^M + ALOGE("yfdPen:drawPoints buf is null");^M + return false;^M + }^M +^M + SkBitmap bmp;^M + SkImageInfo info = SkImageInfo::Make(w, h, kRGBA_8888_SkColorType, kPremul_SkAlphaType);^M + bmp.setInfo(info);^M + ALOGI("yfdPen:drawPoints bmp[%d, %d]", bmp.width(), bmp.height());^M +^M + SkPaint paint;^M +^M + paint.setColor(track->penColor);^M + paint.setStyle(SkPaint::kStrokeAndFill_Style);^M + paint.setStrokeJoin(SkPaint::kRound_Join);^M + paint.setStrokeCap(SkPaint::kRound_Cap);^M + paint.setAntiAlias(true);^M + paint.setDither(true);^M +^M + bmp.setPixels(buf);^M +^M + SkCanvas canvas(bmp);^M +^M + float lastX, lastY;^M + int penWidth = checkPenWidth(track->penWidth);^M +^M + ALOGI("drawPoints point list size = %zu", track->pointList.size());^M + for(android::EmrPoint p : track->pointList) {^M + //ALOGE("drawPoints action=%d, x=%f, y=%f, p=%d",^M + // p.action, p.x, p.y, p.pressure);^M +^M + if (p.action == PEN_DOWN) {^M + lastX = p.x;^M + lastY = p.y;^M +^M + ALOGI("drawPoints P_D last=[%f, %f] cur = [%f, %f], pressure= %d",^M + lastX, lastY, p.x, p.y, p.pressure);^M + continue;^M + } else if (p.action ==PEN_UP) {^M + ALOGI("drawPoints P_U last=[%f, %f] cur = [%f, %f], pressure= %d",^M + lastX, lastY, p.x, p.y, p.pressure);^M + continue;^M + }^M +^M +^M + /*if (p.pressure <= 1000) {^M + penWidth = 2;^M + } else if (p.pressure > 1000 && p.pressure <= 2500) {^M + penWidth = 3;^M + } else if (p.pressure > 2500 && p.pressure <= 4000) {^M + penWidth = 4;^M + } else {^M + penWidth = 5;^M + }^M + paint.setStrokeWidth(penWidth);^M + //ALOGI("drawPoints P_M last=[%f, %f] cur = [%f, %f],^M + // pressure= %d, width=%f", lastX, lastY, p.x, p.y, p.pressure, penWidth);^M + canvas.drawLine(lastX, lastY, p.x, p.y, paint);*/^M +^M + ballpointAll(lastX, lastY, p.x, p.y, p.pressure, paint, &canvas, penWidth);^M +^M + lastX = p.x;^M + lastY = p.y;^M + }^M +^M + return true;^M +}^M +^M +int checkPenWidth(int width) {^M + if ((width == PEN_WIDTH_THIN) || (width == PEN_WIDTH_MEDIUM) || (width == PEN_WIDTH_THICK) ||^M + (width == PEN_WIDTH_EXTRA_THICK)) {^M + return width;^M + } else {^M + return PEN_WIDTH_DEFAULT;^M + }^M +}^M +^M +int checkTag(int tag) {^M + if (tag == TAG_PENVENDOR_MAXEYE_US317) {^M + return tag;^M + } else {^M + return TAG_PENVENDOR_WACOM_CP;^M + }^M +}^M +^M +bool setPen(int type, int width, int color, int tag) {^M + ALOGI("setPen t=%d, w=%d, c=%d, t=%d", type, width, color, tag);^M +^M + mPenWidth = checkPenWidth(width);^M +^M + mTag = checkTag(tag);^M +^M + mPenColor = color;^M + if (penByWho == MODE_HWC) {^M + initHWCDraw(bmp);^M + } else if (penByWho == MODE_SDK) {^M + initDrawJni(bmp);^M + }^M +^M + return true;^M +}^M diff --git a/yfd_pen.h b/yfd_pen.h new file mode 100755 index 0000000..2e9e325 --- /dev/null +++ b/yfd_pen.h @@ -0,0 +1,121 @@ +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "SkCanvas.h" +#include "SkPaint.h" +#include "SkColor.h" +#include "SkBitmap.h" +#include "SkImageInfo.h" +#include "SkPath.h" + +#include "EmrTrack.h" + +enum +{ + MODE_UNKNOWN = 0x01, + MODE_HWC = 0x02, + MODE_SDK = 0x03, +}; +static int penByWho = MODE_UNKNOWN; + +// pen width +static const int PEN_WIDTH_DEFAULT = 5; +static const int PEN_WIDTH_THIN = PEN_WIDTH_DEFAULT; +static const int PEN_WIDTH_MEDIUM = 10; +static const int PEN_WIDTH_THICK = 20; +static const int PEN_WIDTH_EXTRA_THICK = 50; + +// tag +static const int TAG_PENVENDOR_WACOM_CP = 0; +static const int TAG_PENVENDOR_MAXEYE_US317 = 1; //排他协议是固定的Vendor Data0 = 0x55AA + + +static uint8_t *gray_dis_buf = NULL; +//static int bufLen; +static SkBitmap bmp;// = nullptr; +static SkPaint paint;// = nullptr; +static SkCanvas* mCanvas; +static SkPath path; +static SkPaint dashPaint; +static SkPaint dashPaintBg; +static SkPaint hwcPaint; +static int mPenWidth = PEN_WIDTH_THIN; +static int mTag = 0;//TAG_PENVENDOR_WACOM_CP; + +enum +{ + PEN_DOWN = 0x01, + PEN_UP = 0x02, + PEN_MOVE = 0x03, +}; + +static float penWidth; +static float lastX = 0; +static float lastY = 0; +static long last_action_time = 0; +static long cur_time = 0; +static long time_diff = 0; +static float distance = 0; +static bool canDraw = false; +static bool penIsCreate = false; + +static bool mIsColorful = false; +static uint32_t mPenColor = SK_ColorBLACK; + +// public ++++ +void libTest(); + + +void ballpointAll(float x1, float y1, float x2, float y2, int pressure, SkPaint p, SkCanvas *canvas, + int pWidth); + +void ballpointThin(float x1, float y1, float x2, float y2, int pressure, SkPaint p, SkCanvas *canvas); + +void ballpointMedium(float x1, float y1, float x2, float y2, int pressure, SkPaint p, SkCanvas *canvas); + +void ballpointThick(float x1, float y1, float x2, float y2, int pressure, SkPaint p, SkCanvas *canvas); + +void ballpointExtraThick(float x1, float y1, float x2, float y2, int pressure, SkPaint p, SkCanvas *canvas); + +void ballpointPen(float x1, float y1, float x2, float y2, + int width, int color, int pressure, int action); + +void ballpointPenHwc(float x1, float y1, float x2, float y2, + int width, int color, int pressure, int action); + +//bool penCreate(int w, int h, unsigned char *buf); +bool penCreate(int w, int h, uint8_t *buf, bool isColorful); + +bool penDestroy(); + +bool penCreateJni(int w, int h); + +bool penDestroyJni(); + +void lockBufferJni(uint8_t *buf); + +void unlockBufferJni(); + +uint8_t* getPenBmpBuf(); + +void readPixels(SkBitmap b, int xlen, int ylen); + +void dashPen(float x1, float y1, float x2, float y2, int action, int point_count); + +bool drawPoints(android::EmrTrack *track, int w, int h, uint8_t *buf); + +bool setPen(int type, int width, int color, int tag); + +// public ---- + +// private ++++ +void initDrawJni(SkBitmap bmp); + +void initDashDraw(); + +void initHWCDraw(SkBitmap bmp); + +int checkPenWidth(int width); +// private ----

9、surfaceflinger hwc api添加hardware/interfaces:

diff --git a/current.txt b/current.txt old mode 100644 new mode 100755 index afde7b17fa..f1b0d00661 --- a/current.txt +++ b/current.txt @@ -704,8 +704,8 @@ df52e2c39ed701a355b5e0fdbf83fe5fa7d04bfecd715116b39373d46dc3c682 android.hardwar 956c1576ca0d6f11b42980ef59052062836b6763fe973af6cb709da50787f710 android.hardware.gnss.measurement_corrections@1.1::types a2dcf188b02102d3cf80ca0a280dce05d45a8df809751b3c52347426ed58ebbe android.hardware.graphics.allocator@4.0::IAllocator 0a90c665605df3d7d7b0fcafcc4178c3345a6e4ba7e3148fefe4973629827463 android.hardware.graphics poser@2.4::IComposer -809b815bac3d9a5ead591b5fed20f08dbd2bcf7b5c6858201fdd0d8347db9177 android.hardware.graphics poser@2.4::IComposerCallback -8006ee6e02453443f7e79cfcd9f85d9863bed53c4cfc55519de98b64ca72edc2 android.hardware.graphics poser@2.4::IComposerClient +795b81f2fc43db1f50b73038318967aa438235fa5dba825ff86d3122e2e8cc3e android.hardware.graphics poser@2.4::IComposerCallback +9dd3ce84488290dbd3700b5a330a6ed7212179dbddacad627d18e393a60e0824 android.hardware.graphics poser@2.4::IComposerClient fda61f0a5a56cf4e0e8697fb4899a26a4dc450ff837f3425b53932fe34583d11 android.hardware.graphics poser@2.4::types 4d674afdc4447f614c8cc466ed45c5955a0192fa3d3c70884b11dd3c88f0b468 android.hardware.graphics.mapper@4.0::IMapper b58a5e83a8ab04ff6e500f6afc17a1129a1f3de044b296b4b6bd34a085220f87 android.hardware.graphics.mapper@4.0::types diff --git a/graphics/composer/2.4/IComposerCallback.hal b/graphics/composer/2.4/IComposerCallback.hal old mode 100644 new mode 100755 index f343ceef6e..c7272fb436 --- a/graphics/composer/2.4/IComposerCallback.hal +++ b/graphics/composer/2.4/IComposerCallback.hal @@ -52,4 +52,24 @@ interface IComposerCallback extends @2.1::IComposerCallback { * SEAMLESS_NOT_POSSIBLE. */ oneway onSeamlessPossible(Display display); + + /** + * Notifies the client that pick up the pen and return to the reporting point set + * + * @param display is a display which is the primary display. + * @param action is emr event. + * @param x is emr point location x. + * @param y is emr point location y. + * @param eventtime is emr point event time. + * @param pressure is emr point pressure. + */ + oneway onEmrPoint(Display display, int32_t action, float x, float y, int64_t eventtime, int32_t pressure); + + /** + * Notifies the client that a refresh occurred when handwrite. + * + * @param display is a display which is the primary display. + * @param eventtime is emr point event time. + */ + oneway onUpdateRequest(Display display, int64_t eventtime); }; diff --git a/graphics/composer/2.4/IComposerClient.hal b/graphics/composer/2.4/IComposerClient.hal old mode 100644 new mode 100755 index 476302f1bf..1bf0545877 --- a/graphics/composer/2.4/IComposerClient.hal +++ b/graphics/composer/2.4/IComposerClient.hal @@ -19,6 +19,7 @@ package android.hardware.graphics poser@2.4; import android.hardware.graphics mon@1.2::PixelFormat; import android.hardware.graphics mon@1.2::Dataspace; import android.hardware.graphics poser@2.1::IComposerClient.Command; +import android.hardware.graphics poser@2.1::IComposerClient.Rect; import IComposerCallback; import @2.1::Config; import @2.1::Display; @@ -279,6 +280,62 @@ interface IComposerClient extends @2.3::IComposerClient { setAutoLowLatencyMode(Display display, bool on) generates (Error error); + /** + * Set the display refresh mode. + * + * @return error is NONE upon success. Otherwise, + */ + setPanelRefreshMode(Display display, int32_t mode) + generates (Error error); + + /** + * Set the display handwrite state. + * + * @return error is NONE upon success. Otherwise, + */ + setHwState(Display display, int32_t state) + generates (Error error); + + /** + * Get the display handwrite state. + * + * @return error is NONE upon success. Otherwise, + * @return hwState is handwrite state. + */ + getHwState(Display display) + generates (Error error, int32_t hwState); + + /** + * Get the display refresh mode. + * + * @return error is NONE upon success. Otherwise, + * @return refreshMode is t1000 refresh mode. + */ + getPanelRefreshMode(Display display) + generates (Error error, int32_t refreshMode); + + /** + * Set the hand write area. + * @param validRect is valid handwrite rect. + * @param invalidRects is invalid handwrite rects. + * + * @return error is NONE upon success. Otherwise, + */ + commitHwArea(Display display, Rect validRect, vec<Rect> invalidRects) + generates (Error error); + + /** + * Set the hand write pen. + * @param type is pen style. + * @param width is pen width. + * @param color is pen color. + * @param tag is pen tag. + * + * @return error is NONE upon success. Otherwise, + */ + setHandwritePen(Display display, int32_t type, int32_t width, int32_t color, int32_t tag) + generates (Error error); + /** * Provides a list of all the content types supported by this display (any of * ContentType::{GRAPHICS, PHOTO, CINEMA, GAME}). This list must not change after diff --git a/graphics/composer/2.4/default/android.hardware.graphics poser@2.4-service.rc b/graphics/composer/2.4/default/android.hardware.graphics poser@2.4-service.rc old mode 100644 new mode 100755 index 06003b02b3..2be9a729ba --- a/graphics/composer/2.4/default/android.hardware.graphics poser@2.4-service.rc +++ b/graphics/composer/2.4/default/android.hardware.graphics poser@2.4-service.rc @@ -1,8 +1,9 @@ service vendor.hwcomposer-2-4 /vendor/bin/hw/android.hardware.graphics poser@2.4-service class hal animation user system - group graphics drmrpc - capabilities SYS_NICE + group graphics drmrpc wakelock input + capabilities SYS_NICE BLOCK_SUSPEND onrestart restart surfaceflinger - task_profiles ServiceCapacityLow + writepid /dev/cpuset/display/tasks + task_profiles DisplayHighPerformance socket pps stream 0660 system system diff --git a/graphics/composer/2.4/utils/hal/include/composer-hal/2.4/ComposerClient.h b/graphics/composer/2.4/utils/hal/include/composer-hal/2.4/ComposerClient.h old mode 100644 new mode 100755 index 3464342719..5611558ed0 --- a/graphics/composer/2.4/utils/hal/include/composer-hal/2.4/ComposerClient.h +++ b/graphics/composer/2.4/utils/hal/include/composer-hal/2.4/ComposerClient.h @@ -99,6 +99,17 @@ class ComposerClientImpl : public V2_3::hal::detail::ComposerClientImpl<Interfac ret.description().c_str()); } + void onEmrPoint(Display display, int32_t action, float x, float y, int64_t eventtime, int32_t pressure) override { + auto ret = mCallback->onEmrPoint(display, action, x, y, eventtime, pressure); + ALOGE_IF(!ret.isOk(), "failed to send onEmrPoint: %s", + ret.description().c_str()); + } + + void onUpdateRequest(Display display, int64_t eventtime) override { + auto ret = mCallback->onUpdateRequest(display, eventtime); + ALOGE_IF(!ret.isOk(), "failed to send onUpdateRequest: %s", + ret.description().c_str()); + } protected: Hal* const mHal; const sp<IComposerCallback> mCallback; @@ -161,6 +172,36 @@ class ComposerClientImpl : public V2_3::hal::detail::ComposerClientImpl<Interfac return mHal->setAutoLowLatencyMode(display, on); } + Return<Error> setPanelRefreshMode(Display display, int32_t mode) override { + return mHal->setPanelRefreshMode(display, mode); + } + + Return<Error> setHwState(Display display, int32_t state) override { + return mHal->setHwState(display, state); + } + + Return<void> getHwState(Display display, IComposerClient::getHwState_cb hidl_cb) override { + int32_t hwState = 0; + Error error = mHal->getHwState(display, &hwState); + hidl_cb(error, hwState); + return Void(); + } + + Return<void> getPanelRefreshMode(Display display, IComposerClient::getPanelRefreshMode_cb hidl_cb) override { + int32_t refreshMode = 0; + Error error = mHal->getPanelRefreshMode(display, &refreshMode); + hidl_cb(error, refreshMode); + return Void(); + } + + Return<Error> commitHwArea(Display display, const IComposerClient::Rect& validRect, const hidl_vec<IComposerClient::Rect>& invalidRects) override { + return mHal->commitHwArea(display, toHwRect(validRect), toHwRectList(invalidRects)); + } + + Return<Error> setHandwritePen(Display display, int32_t type, int32_t width, int32_t color, int32_t tag) override { + return mHal->setHandwritePen(display, type, width, color, tag); + } + Return<void> getSupportedContentTypes( Display display, IComposerClient::getSupportedContentTypes_cb hidl_cb) override { std::vector<IComposerClient::ContentType> supportedContentTypes; @@ -188,6 +229,23 @@ class ComposerClientImpl : public V2_3::hal::detail::ComposerClientImpl<Interfac return client->init() ? std::move(client) : nullptr; } + static inline hw_rect_t toHwRect(const IComposerClient::Rect& rect) { + hw_rect_t hwRect; + hwRect.left = rect.left; + hwRect.top = rect.top; + hwRect.right = rect.right; + hwRect.bottom = rect.bottom; + return hwRect; + } + + static inline hidl_vec<hw_rect_t> toHwRectList(const hidl_vec<IComposerClient::Rect>& rectList) { + hidl_vec<hw_rect_t> hwRectList(rectList.size()); + for (size_t i = 0; i < rectList.size(); ++i) { + hwRectList[i] = toHwRect(rectList[i]); + } + return hwRectList; + } + protected: std::unique_ptr<V2_1::hal::ComposerCommandEngine> createCommandEngine() override { return std::make_unique<ComposerCommandEngine>( diff --git a/graphics/composer/2.4/utils/hal/include/composer-hal/2.4/ComposerHal.h b/graphics/composer/2.4/utils/hal/include/composer-hal/2.4/ComposerHal.h old mode 100644 new mode 100755 index 58991c1d8d..738669f286 --- a/graphics/composer/2.4/utils/hal/include/composer-hal/2.4/ComposerHal.h +++ b/graphics/composer/2.4/utils/hal/include/composer-hal/2.4/ComposerHal.h @@ -50,6 +50,8 @@ class ComposerHal : public V2_3::hal::ComposerHal { virtual void onVsyncPeriodTimingChanged(Display display, const VsyncPeriodChangeTimeline& timeline) = 0; virtual void onSeamlessPossible(Display display) = 0; + virtual void onEmrPoint(Display display, int32_t action, float x, float y, int64_t eventtime, int32_t pressure) = 0; + virtual void onUpdateRequest(Display display, int64_t eventtime) = 0; }; virtual void registerEventCallback_2_4(EventCallback_2_4* callback) = 0; @@ -69,6 +71,14 @@ class ComposerHal : public V2_3::hal::ComposerHal { const IComposerClient::VsyncPeriodChangeConstraints& vsyncPeriodChangeConstraints, VsyncPeriodChangeTimeline* timeline) = 0; virtual Error setAutoLowLatencyMode(Display display, bool on) = 0; + virtual Error setPanelRefreshMode(Display display, int32_t mode) = 0; + virtual Error setHwState(Display display, int32_t state) = 0; + virtual Error getHwState(Display display, int32_t* outHwState) = 0; + virtual Error getPanelRefreshMode(Display display, int32_t* outRefreshMode) = 0; + virtual Error commitHwArea(Display display, const hw_rect_t& validRect, + const hidl_vec<hw_rect_t> &invalidRects) = 0; + virtual Error setHandwritePen(Display display, int32_t type, int32_t width, + int32_t color, int32_t tag) = 0; virtual Error getSupportedContentTypes( Display display, std::vector<IComposerClient::ContentType>* outSupportedContentTypes) = 0; diff --git a/graphics/composer/2.4/utils/passthrough/include/composer-passthrough/2.4/HwcHal.h b/graphics/composer/2.4/utils/passthrough/include/composer-passthrough/2.4/HwcHal.h old mode 100644 new mode 100755 index d28e00625f..6c6f013e05 --- a/graphics/composer/2.4/utils/passthrough/include/composer-passthrough/2.4/HwcHal.h +++ b/graphics/composer/2.4/utils/passthrough/include/composer-passthrough/2.4/HwcHal.h @@ -68,6 +68,12 @@ class HwcHalImpl : public V2_3::passthrough::detail::HwcHalImpl<Hal> { BaseType2_1::mDispatch.registerCallback( mDevice, HWC2_CALLBACK_SEAMLESS_POSSIBLE, this, reinterpret_cast<hwc2_function_pointer_t>(seamlessPossibleHook)); + BaseType2_1::mDispatch.registerCallback( + mDevice, HWC2_CALLBACK_EMR_POINT, this, + reinterpret_cast<hwc2_function_pointer_t>(emrPointHook)); + BaseType2_1::mDispatch.registerCallback( + mDevice, HWC2_CALLBACK_UPDATE_REQUEST, this, + reinterpret_cast<hwc2_function_pointer_t>(updateRequestHook)); } void unregisterEventCallback_2_4() override { @@ -85,7 +91,8 @@ class HwcHalImpl : public V2_3::passthrough::detail::HwcHalImpl<Hal> { this, nullptr); BaseType2_1::mDispatch.registerCallback(mDevice, HWC2_CALLBACK_SEAMLESS_POSSIBLE, this, nullptr); - + BaseType2_1::mDispatch.registerCallback(mDevice, HWC2_CALLBACK_EMR_POINT, this, nullptr); + BaseType2_1::mDispatch.registerCallback(mDevice, HWC2_CALLBACK_UPDATE_REQUEST, this, nullptr); mEventCallback_2_4 = nullptr; } @@ -180,6 +187,80 @@ class HwcHalImpl : public V2_3::passthrough::detail::HwcHalImpl<Hal> { return Error::NONE; } + Error setPanelRefreshMode(Display display, int32_t mode) override { + if (!mDispatch.setPanelRefreshMode) { + return Error::UNSUPPORTED; + } + + int32_t error = mDispatch.setPanelRefreshMode(mDevice, display, mode); + if (error != HWC2_ERROR_NONE) { + return static_cast<Error>(error); + } + return Error::NONE; + } + + Error setHwState(Display display, int32_t state) override { + if (!mDispatch.setHwState) { + return Error::UNSUPPORTED; + } + + int32_t error = mDispatch.setHwState(mDevice, display, state); + if (error != HWC2_ERROR_NONE) { + return static_cast<Error>(error); + } + return Error::NONE; + } + + Error getHwState(Display display, int32_t* outHwState) override { + if (!mDispatch.getHwState) { + return Error::UNSUPPORTED; + } + + int32_t error = mDispatch.getHwState(mDevice, display, outHwState); + if (error != HWC2_ERROR_NONE) { + return static_cast<Error>(error); + } + return Error::NONE; + } + + Error getPanelRefreshMode(Display display, int32_t* outRefreshMode) override { + if (!mDispatch.getPanelRefreshMode) { + return Error::UNSUPPORTED; + } + + int32_t error = mDispatch.getPanelRefreshMode(mDevice, display, outRefreshMode); + if (error != HWC2_ERROR_NONE) { + return static_cast<Error>(error); + } + return Error::NONE; + } + + Error commitHwArea(Display display, const hw_rect_t& validRect, + const hidl_vec<hw_rect_t>& invalidRects) override { + if (!mDispatch mitHwArea) { + return Error::UNSUPPORTED; + } + + int32_t error = mDispatch mitHwArea(mDevice, display, validRect, invalidRects); + if (error != HWC2_ERROR_NONE) { + return static_cast<Error>(error); + } + return Error::NONE; + } + + Error setHandwritePen(Display display, int32_t type, int32_t width, + int32_t color, int32_t tag) override { + if (!mDispatch.setHandwritePen) { + return Error::UNSUPPORTED; + } + + int32_t error = mDispatch.setHandwritePen(mDevice, display, type, width, color, tag); + if (error != HWC2_ERROR_NONE) { + return static_cast<Error>(error); + } + return Error::NONE; + } + Error getSupportedContentTypes( Display display, std::vector<IComposerClient::ContentType>* outSupportedContentTypes) override { @@ -317,6 +398,18 @@ class HwcHalImpl : public V2_3::passthrough::detail::HwcHalImpl<Hal> { &mDispatch.getDisplayConnectionType); this->initOptionalDispatch(HWC2_FUNCTION_SET_AUTO_LOW_LATENCY_MODE, &mDispatch.setAutoLowLatencyMode); + this->initOptionalDispatch(HWC2_FUNCTION_SET_PANEL_REFRESH_MODE, + &mDispatch.setPanelRefreshMode); + this->initOptionalDispatch(HWC2_FUNCTION_SET_HW_STATE, + &mDispatch.setHwState); + this->initOptionalDispatch(HWC2_FUNCTION_GET_HW_STATE, + &mDispatch.getHwState); + this->initOptionalDispatch(HWC2_FUNCTION_GET_PANEL_REFRESH_MODE, + &mDispatch.getPanelRefreshMode); + this->initOptionalDispatch(HWC2_FUNCTION_COMMIT_HW_AREA, + &mDispatch mitHwArea); + this->initOptionalDispatch(HWC2_FUNCTION_SET_HW_PEN, + &mDispatch.setHandwritePen); this->initOptionalDispatch(HWC2_FUNCTION_GET_SUPPORTED_CONTENT_TYPES, &mDispatch.getSupportedContentTypes); this->initOptionalDispatch(HWC2_FUNCTION_SET_CONTENT_TYPE, &mDispatch.setContentType); @@ -370,12 +463,28 @@ class HwcHalImpl : public V2_3::passthrough::detail::HwcHalImpl<Hal> { hal->mEventCallback_2_4->onSeamlessPossible(display); } + static void emrPointHook(hwc2_callback_data_t callbackData, hwc2_display_t display, int32_t action, float x, float y, int64_t eventtime, int32_t pressure) { + auto hal = static_cast<HwcHalImpl*>(callbackData); + hal->mEventCallback_2_4->onEmrPoint(display, action, x, y, eventtime, pressure); + } + + static void updateRequestHook(hwc2_callback_data_t callbackData, hwc2_display_t display, int64_t eventtime) { + auto hal = static_cast<HwcHalImpl*>(callbackData); + hal->mEventCallback_2_4->onUpdateRequest(display, eventtime); + } + private: struct { HWC2_PFN_GET_DISPLAY_CONNECTION_TYPE getDisplayConnectionType; HWC2_PFN_GET_DISPLAY_VSYNC_PERIOD getDisplayVsyncPeriod; HWC2_PFN_SET_ACTIVE_CONFIG_WITH_CONSTRAINTS setActiveConfigWithConstraints; HWC2_PFN_SET_AUTO_LOW_LATENCY_MODE setAutoLowLatencyMode; + HWC2_PFN_SET_PANEL_REFRESH_MODE setPanelRefreshMode; + HWC2_PFN_SET_HW_STATE setHwState; + HWC2_PFN_GET_HW_STATE getHwState; + HWC2_PFN_GET_PANEL_REFRESH_MODE getPanelRefreshMode; + HWC2_PFN_COMMIT_HW_AREA commitHwArea; + HWC2_PFN_SET_HW_PEN setHandwritePen; HWC2_PFN_GET_SUPPORTED_CONTENT_TYPES getSupportedContentTypes; HWC2_PFN_SET_CONTENT_TYPE setContentType; HWC2_PFN_GET_CLIENT_TARGET_PROPERTY getClientTargetProperty; diff --git a/graphics/composer/2.4/utils/vts/include/composer-vts/2.4/GraphicsComposerCallback.h b/graphics/composer/2.4/utils/vts/include/composer-vts/2.4/GraphicsComposerCallback.h old mode 100644 new mode 100755 index c03070b10c..80036e93c4 --- a/graphics/composer/2.4/utils/vts/include/composer-vts/2.4/GraphicsComposerCallback.h +++ b/graphics/composer/2.4/utils/vts/include/composer-vts/2.4/GraphicsComposerCallback.h @@ -43,6 +43,10 @@ class GraphicsComposerCallback : public IComposerCallback { int32_t getInvalidSeamlessPossibleCount() const; + int32_t getInvalidEmrPointCount() const; + + int32_t getInvalidUpdateRequestCount() const; + std::optional<VsyncPeriodChangeTimeline> takeLastVsyncPeriodChangeTimeline(); private: @@ -53,6 +57,8 @@ class GraphicsComposerCallback : public IComposerCallback { Return<void> onVsyncPeriodTimingChanged( Display display, const VsyncPeriodChangeTimeline& updatedTimeline) override; Return<void> onSeamlessPossible(Display display) override; + Return<void> onEmrPoint(Display display, int32_t action, float x, float y, int64_t eventtime, int32_t pressure) override; + Return<void> onUpdateRequest(Display display, int64_t eventtime) override; mutable std::mutex mMutex; // the set of all currently connected displays @@ -69,6 +75,8 @@ class GraphicsComposerCallback : public IComposerCallback { int32_t mInvalidVsync_2_4Count = 0; int32_t mInvalidVsyncPeriodChangeCount = 0; int32_t mInvalidSeamlessPossibleCount = 0; + int32_t mInvalidEmrPointCount = 0; + int32_t mInvalidUpdateRequestCount = 0; }; } // namespace android::hardware::graphics::composer::V2_4::vts diff --git a/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp b/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp old mode 100644 new mode 100755 index fa294ff259..989bb818cd --- a/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp +++ b/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp @@ -120,6 +120,8 @@ class GraphicsComposerHidlTest : public ::testing::TestWithParam<std::string> { EXPECT_EQ(0, mComposerCallback->getInvalidVsync_2_4Count()); EXPECT_EQ(0, mComposerCallback->getInvalidVsyncPeriodChangeCount()); EXPECT_EQ(0, mComposerCallback->getInvalidSeamlessPossibleCount()); + EXPECT_EQ(0, mComposerCallback->getInvalidEmrPointCount()); + EXPECT_EQ(0, mComposerCallback->getInvalidUpdateRequestCount()); } }

10、上一步对应的头文件更改hardware/libhardware:

diff --git a/include/hardware/hwcomposer2.h b/include/hardware/hwcomposer2.h old mode 100644 new mode 100755 index 76122a57..d6ebdd1d --- a/include/hardware/hwcomposer2.h +++ b/include/hardware/hwcomposer2.h @@ -81,6 +81,8 @@ typedef enum { HWC2_CALLBACK_VSYNC_2_4 = 4, HWC2_CALLBACK_VSYNC_PERIOD_TIMING_CHANGED = 5, HWC2_CALLBACK_SEAMLESS_POSSIBLE = 6, + HWC2_CALLBACK_EMR_POINT = 7, + HWC2_CALLBACK_UPDATE_REQUEST = 8, } hwc2_callback_descriptor_t; /* Optional capabilities which may be supported by some devices. The particular @@ -304,6 +306,12 @@ typedef enum { HWC2_FUNCTION_GET_DISPLAY_VSYNC_PERIOD, HWC2_FUNCTION_SET_ACTIVE_CONFIG_WITH_CONSTRAINTS, HWC2_FUNCTION_SET_AUTO_LOW_LATENCY_MODE, + HWC2_FUNCTION_SET_PANEL_REFRESH_MODE, + HWC2_FUNCTION_SET_HW_STATE, + HWC2_FUNCTION_GET_HW_STATE, + HWC2_FUNCTION_GET_PANEL_REFRESH_MODE, + HWC2_FUNCTION_COMMIT_HW_AREA, + HWC2_FUNCTION_SET_HW_PEN, HWC2_FUNCTION_GET_SUPPORTED_CONTENT_TYPES, HWC2_FUNCTION_SET_CONTENT_TYPE, HWC2_FUNCTION_GET_CLIENT_TARGET_PROPERTY, @@ -497,6 +505,8 @@ static inline const char* getCallbackDescriptorName( case HWC2_CALLBACK_VSYNC_2_4: return "Vsync2.4"; case HWC2_CALLBACK_VSYNC_PERIOD_TIMING_CHANGED: return "VsyncPeriodTimingChanged"; case HWC2_CALLBACK_SEAMLESS_POSSIBLE: return "SeamlessPossible"; + case HWC2_CALLBACK_EMR_POINT: return "EmrPoint"; + case HWC2_CALLBACK_UPDATE_REQUEST: return "UpdateRequest"; default: return "Unknown"; } } @@ -666,6 +676,12 @@ static inline const char* getFunctionDescriptorName( case HWC2_FUNCTION_GET_DISPLAY_VSYNC_PERIOD: return "GetDisplayVsyncPeriod"; case HWC2_FUNCTION_SET_ACTIVE_CONFIG_WITH_CONSTRAINTS: return "SetActiveConfigWithConstraints"; case HWC2_FUNCTION_SET_AUTO_LOW_LATENCY_MODE: return "SetAutoLowLatencyMode"; + case HWC2_FUNCTION_SET_PANEL_REFRESH_MODE: return "SetPanelRefreshMode"; + case HWC2_FUNCTION_COMMIT_HW_AREA: return "CommitHwArea"; + case HWC2_FUNCTION_SET_HW_PEN: return "SetHandwritePen"; + case HWC2_FUNCTION_SET_HW_STATE: return "SetHwState"; + case HWC2_FUNCTION_GET_HW_STATE: return "GetHwState"; + case HWC2_FUNCTION_GET_PANEL_REFRESH_MODE: return "GetPanelRefreshMode"; case HWC2_FUNCTION_GET_SUPPORTED_CONTENT_TYPES: return "GetSupportedContentTypes"; case HWC2_FUNCTION_SET_CONTENT_TYPE: return "SetContentType"; case HWC2_FUNCTION_GET_CLIENT_TARGET_PROPERTY: return "GetClientTargetProperty"; @@ -811,6 +827,8 @@ enum class Callback : int32_t { Vsync_2_4 = HWC2_CALLBACK_VSYNC_2_4, VsyncPeriodTimingChanged = HWC2_CALLBACK_VSYNC_PERIOD_TIMING_CHANGED, SeamlessPossible = HWC2_CALLBACK_SEAMLESS_POSSIBLE, + EmrPoint = HWC2_CALLBACK_EMR_POINT, + UpdateRequest = HWC2_CALLBACK_UPDATE_REQUEST, }; TO_STRING(hwc2_callback_descriptor_t, Callback, getCallbackDescriptorName)

11、hardware层使能手写api功能hardware/qcom/display:

diff --git a/composer/Android.bp b/composer/Android.bp index 4adcaf3f..889e96e5 100755 --- a/composer/Android.bp +++ b/composer/Android.bp @@ -33,7 +33,6 @@ cc_binary { "libc++", "liblog", "libhidlbase", - "liblog", "libfmq", "libhardware_legacy", "libsdmcore", @@ -60,6 +59,7 @@ cc_binary { "libgralloctypes", "libdisplayconfig.qti", "libdrm", + "libyfdpen", ], srcs: composer_srcs, diff --git a/composer/QtiComposerClient.cpp b/composer/QtiComposerClient.cpp old mode 100644 new mode 100755 index aee1326b..44917818 --- a/composer/QtiComposerClient.cpp +++ b/composer/QtiComposerClient.cpp @@ -189,6 +189,22 @@ void QtiComposerClient::onSeamlessPossible(hwc2_callback_data_t callbackData, ret.description().c_str()); } +void QtiComposerClient::onEmrPoint(hwc2_callback_data_t callbackData, hwc2_display_t display, + int32_t action, float x, float y, int64_t eventtime, int32_t pressure) { + auto client = reinterpret_cast<QtiComposerClient*>(callbackData); + auto ret = client->callback24_->onEmrPoint(display, action, x, y, eventtime, pressure); + ALOGW_IF(!ret.isOk(), "failed to send onEmrPoint: %s. SF likely unavailable.", + ret.description().c_str()); +} + +void QtiComposerClient::onUpdateRequest(hwc2_callback_data_t callbackData, + hwc2_display_t display, int64_t eventtime) { + auto client = reinterpret_cast<QtiComposerClient*>(callbackData); + auto ret = client->callback24_->onUpdateRequest(display, eventtime); + ALOGW_IF(!ret.isOk(), "failed to send onUpdateRequest: %s. SF likely unavailable.", + ret.description().c_str()); +} + // convert fenceFd to or from hidl_handle // Handle would still own original fence. Hence create a Fence object on duped fd. Error QtiComposerClient::getFence(const hidl_handle& fenceHandle, shared_ptr<Fence>* outFence, @@ -269,6 +285,12 @@ void QtiComposerClient::enableCallback(bool enable) { reinterpret_cast<hwc2_function_pointer_t>(onVsyncPeriodTimingChanged)); hwc_session_->RegisterCallback(HWC2_CALLBACK_SEAMLESS_POSSIBLE, this, reinterpret_cast<hwc2_function_pointer_t>(onSeamlessPossible)); +#ifdef TARGET_EPD_SUPPORT + hwc_session_->RegisterCallback(HWC2_CALLBACK_EMR_POINT, this, + reinterpret_cast<hwc2_function_pointer_t>(onEmrPoint)); + hwc_session_->RegisterCallback(HWC2_CALLBACK_UPDATE_REQUEST, this, + reinterpret_cast<hwc2_function_pointer_t>(onUpdateRequest)); +#endif

大功告成!

标签:

Android14(13)添加墨水屏手写API由讯客互联开源代码栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“Android14(13)添加墨水屏手写API