软件平台:Android11
硬件平台:QCS6125
直接上需求:首先添加自定义系统服务并且开机自启动;其次该服务要调用HW层service的方法。
前半部分之前添加过N次,不是难点,后半部分的实现最开始也是想借助binder通信,直接去调用接口,遇到了一大堆selinux权限问题,这是google针对android8.0之后新添加的策略,使用了三个binder,分别是标准/dev/binder该节点主要用于System分区的系统服务去注册使用,/dev/hwbinder该节点主要用于运行于HW的服务注册使用,/dev/vndbinder该节点主要用于运行在vendor分区的服务注册使用,而需求中所说的HW层的服务注册的是vndbinder,自定义的服务是binder,因此系统层面是隔离的,无法通过binder直接通信,只能通过hwbinder去迂回,因为binder可以跟hwbinder通信,而hwbinder可以和vndbinder交互,从而达到binder服务和vndbinder服务通信的目的。
前半部分(系统服务)的实现:
1、创建frameworks/base/core/java/android/app/yfd/目录,建立如下文件:
HandWriteManager.java
/*************************************************************************
* File Name: HandWriteManager.java
* Author: kongbo
* Mail: [email protected]
* Created Time: 2022年11月21日 星期一 17时17分35秒
************************************************************************/
package android.app.yfd;
import android.content.Context;
import android.os.RemoteException;
import android.util.Slog;
public class HandWriteManager {
Context mContext;
IHandWriteManager mService;
static final String TAG = "HandWriteManager";
public HandWriteManager(Context context, IHandWriteManager service) {
mContext = context;
mService = service;
if (mService != null)
Slog.d(TAG, " mService not null");
}
public void setRefreshMode(int mode) {
if (mService != null) {
Slog.d(TAG, " Will setRefreshMode");
try {
mService.setRefreshMode(mode);
} catch (RemoteException e) {
Slog.d(TAG, "RemoteException " + e);
}
}
//return null;
}
public void commitRefreshArea(int x, int y, int h, int w) {
if (mService != null) {
Slog.d(TAG, " Will commitRefreshArea");
try {
mService.commitRefreshArea(x, y, h, w);
} catch (RemoteException e) {
Slog.d(TAG, "RemoteException " + e);
}
}
}
}
IHandWriteManager.aidl
/**
* Hand Writes Service
*/
package android.app.yfd;
interface IHandWriteManager {
void setRefreshMode(int mode);
void commitRefreshArea(int x, int y, int h, int w);
}
frameworks/base/services/core/java/com/android/server目录添加HandWriteManagerService.java
/*************************************************************************
* File Name: HandWriteManagerService.java
* Author: kongbo
* Mail:[email protected]
* Created Time: 2022年11月21日 星期一 17时36分04秒
************************************************************************/
package com.android.server;
import android.app.yfd.IHandWriteManager;
import android.content.Context;
import android.os.Build;
import android.util.Slog;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.FileReader;
import java.io.IOException;
public class HandWriteManagerService extends IHandWriteManager.Stub {
private Context mContext;
static final String TAG = "HandWriteManagerService";
private boolean Debug = true;
private final int LEISURE_MODE = 1;
private final int WRITE_MODE = 2;
private final int NETWORK_MODE = 3;
private native void HandWriteServiceNative_setRefreshMode(int mode);
private native void HandWriteServiceNative_Init();
private native void HandWriteServiceNative_commitRefreshArea(int x, int y, int h, int w);
public HandWriteManagerService(Context context) {
//Slog.e(TAG," ====== call native method HandWriteServiceNative_Init");
HandWriteServiceNative_Init();
mContext = context;
/*try {
Slog.e(TAG," ====== Runtime will exec ======");
Runtime.getRuntime().exec("su");
Runtime.getRuntime().exec("vndservice call display.qservice 47 i32 2");
Slog.e(TAG," ====== Runtime exec end ======");
} catch (IOException e) {
Slog.e(TAG," ====== Runtime exec has exception ======");
e.printStackTrace();
}*/
}
@Override
public void setRefreshMode(int mode) {
BufferedWriter bufWriter = null;
try {
//bufWriter = new BufferedWriter(new FileWriter(LMAP_BRIGHTNESS_PATH));
if (Debug)
Slog.e(TAG," ====== write brightness:");
HandWriteServiceNative_setRefreshMode(mode);
//bufWriter.write(String.valueOf(brightness));
//bufWriter.close();
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void commitRefreshArea(int x, int y, int h, int w) {
HandWriteServiceNative_commitRefreshArea(x, y, h, w);
}
}
向SystemServer完成注册:
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 3d8328bd193..1279df76dd5 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -89,6 +89,7 @@ import com.android.internal.util.ConcurrentUtils;
import com.android.internal.util.EmergencyAffordanceManager;
import com.android.internal.util.FrameworkStatsLog;
import com.android.internal.widget.ILockSettings;
+import com.android.server.HandWriteManagerService;
import com.android.server.am.ActivityManagerService;
import com.android.server.appbinding.AppBindingService;
import com.android.server.attention.AttentionManagerService;
@@ -1614,6 +1615,16 @@ public final class SystemServer {
}
t.traceEnd();
+ t.traceBegin("StartHandWriteManagerService");
+ try {
+ Slog.i(TAG, "HandWriteManagerService is create");
+ ServiceManager.addService(Context.HAND_WRITE_SERVICE,
+ new HandWriteManagerService(context));
+ } catch (Throwable e) {
+ reportWtf("starting HandWriteManagerService", e);
+ }
+ t.traceEnd();
+
t.traceBegin("StartNotificationManager");
mSystemServiceManager.startService(NotificationManagerService.class);
SystemNotificationChannels.removeDeprecated(context);
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index e599a5ce81e..38473ee5e6e 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -43,6 +43,8 @@ import android.app.usage.IUsageStatsManager;
import android.app.usage.NetworkStatsManager;
import android.app.usage.StorageStatsManager;
import android.app.usage.UsageStatsManager;
+import android.app.yfd.HandWriteManager;
+import android.app.yfd.IHandWriteManager;
import android.appwidget.AppWidgetManager;
import android.bluetooth.BluetoothManager;
import android.companion.CompanionDeviceManager;
@@ -1189,6 +1191,17 @@ public final class SystemServiceRegistry {
}
});
+ registerService(Context.HAND_WRITE_SERVICE, HandWriteManager.class,
+ new CachedServiceFetcher() {
+ @Override
+ public HandWriteManager createService(ContextImpl ctx)
+ throws ServiceNotFoundException {
+ IBinder b = ServiceManager.getServiceOrThrow(
+ Context.HAND_WRITE_SERVICE);
+ return new HandWriteManager(ctx, IHandWriteManager.Stub.asInterface(b));
+ }
+ });
+
registerService(Context.SLICE_SERVICE, SliceManager.class,
new CachedServiceFetcher() {
@Override
在Context.java添加服务ID定义:
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 8472144a92c..d9ee340cd55 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -5024,6 +5024,15 @@ public abstract class Context {
*/
public static final String CROSS_PROFILE_APPS_SERVICE = "crossprofileapps";
+ /**
+ * Use with {@link #getSystemService(String)} to retrieve a
+ * {@link android.app.yfd.HandWriteManager} for handwriting
+ *
+ * @see #getSystemService(String)
+ * @see android.app.yfd.HandWriteManager
+ */
+ public static final String HAND_WRITE_SERVICE = "hand_write";
+
/**
* Use with {@link #getSystemService} to retrieve a
* {@link android.se.omapi.ISecureElementService}
此时增量编译代码,会提示api需要更新还有一个lint检测的报错,API更新执行make update-api指令,去掉lint检查需要修改framework/base/Android.bp如下:
diff --git a/Android.bp b/Android.bp
index bf6c99d0cf2..bb4a6a9a4e7 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1219,7 +1219,8 @@ metalava_framework_docs_args = "--manifest $(location core/res/AndroidManifest.x
"--api-lint-ignore-prefix android.icu. " +
"--api-lint-ignore-prefix java. " +
"--api-lint-ignore-prefix junit. " +
- "--api-lint-ignore-prefix org. "
+ "--api-lint-ignore-prefix org. " +
+ "--api-lint-ignore-prefix android.app.yfd. "
build = [
"StubLibraries.bp",
在执行完make update-api之后,系统会自动更新api文件:
diff --git a/api/current.txt b/api/current.txt
index 952ccdad992..f91544dde68 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -8106,6 +8106,37 @@ package android.app.usage {
}
+package android.app.yfd {
+
+ public class HandWriteManager {
+ ctor public HandWriteManager(android.content.Context, android.app.yfd.IHandWriteManager);
+ method public void commitRefreshArea(int, int, int, int);
+ method public void setRefreshMode(int);
+ }
+
+ public interface IHandWriteManager extends android.os.IInterface {
+ method public void commitRefreshArea(int, int, int, int) throws android.os.RemoteException;
+ method public void setRefreshMode(int) throws android.os.RemoteException;
+ }
+
+ public static class IHandWriteManager.Default implements android.app.yfd.IHandWriteManager {
+ ctor public IHandWriteManager.Default();
+ method public android.os.IBinder asBinder();
+ method public void commitRefreshArea(int, int, int, int) throws android.os.RemoteException;
+ method public void setRefreshMode(int) throws android.os.RemoteException;
+ }
+
+ public abstract static class IHandWriteManager.Stub extends android.os.Binder implements android.app.yfd.IHandWriteManager {
+ ctor public IHandWriteManager.Stub();
+ method public android.os.IBinder asBinder();
+ method public static android.app.yfd.IHandWriteManager asInterface(android.os.IBinder);
+ method public static android.app.yfd.IHandWriteManager getDefaultImpl();
+ method public boolean onTransact(int, android.os.Parcel, android.os.Parcel, int) throws android.os.RemoteException;
+ method public static boolean setDefaultImpl(android.app.yfd.IHandWriteManager);
+ }
+
+}
+
package android.appwidget {
public class AppWidgetHost {
@@ -10190,6 +10221,7 @@ package android.content {
field public static final String EUICC_SERVICE = "euicc";
field public static final String FILE_INTEGRITY_SERVICE = "file_integrity";
field public static final String FINGERPRINT_SERVICE = "fingerprint";
+ field public static final String HAND_WRITE_SERVICE = "hand_write";
field public static final String HARDWARE_PROPERTIES_SERVICE = "hardware_properties";
field public static final String INPUT_METHOD_SERVICE = "input_method";
field public static final String INPUT_SERVICE = "input";
diff --git a/non-updatable-api/current.txt b/non-updatable-api/current.txt
index 5f15216e840..c6047ab6ff4 100644
--- a/non-updatable-api/current.txt
+++ b/non-updatable-api/current.txt
@@ -8106,6 +8106,37 @@ package android.app.usage {
}
+package android.app.yfd {
+
+ public class HandWriteManager {
+ ctor public HandWriteManager(android.content.Context, android.app.yfd.IHandWriteManager);
+ method public void commitRefreshArea(int, int, int, int);
+ method public void setRefreshMode(int);
+ }
+
+ public interface IHandWriteManager extends android.os.IInterface {
+ method public void commitRefreshArea(int, int, int, int) throws android.os.RemoteException;
+ method public void setRefreshMode(int) throws android.os.RemoteException;
+ }
+
+ public static class IHandWriteManager.Default implements android.app.yfd.IHandWriteManager {
+ ctor public IHandWriteManager.Default();
+ method public android.os.IBinder asBinder();
+ method public void commitRefreshArea(int, int, int, int) throws android.os.RemoteException;
+ method public void setRefreshMode(int) throws android.os.RemoteException;
+ }
+
+ public abstract static class IHandWriteManager.Stub extends android.os.Binder implements android.app.yfd.IHandWriteManager {
+ ctor public IHandWriteManager.Stub();
+ method public android.os.IBinder asBinder();
+ method public static android.app.yfd.IHandWriteManager asInterface(android.os.IBinder);
+ method public static android.app.yfd.IHandWriteManager getDefaultImpl();
+ method public boolean onTransact(int, android.os.Parcel, android.os.Parcel, int) throws android.os.RemoteException;
+ method public static boolean setDefaultImpl(android.app.yfd.IHandWriteManager);
+ }
+
+}
+
package android.appwidget {
public class AppWidgetHost {
@@ -10190,6 +10221,7 @@ package android.content {
field public static final String EUICC_SERVICE = "euicc";
field public static final String FILE_INTEGRITY_SERVICE = "file_integrity";
field public static final String FINGERPRINT_SERVICE = "fingerprint";
+ field public static final String HAND_WRITE_SERVICE = "hand_write";
field public static final String HARDWARE_PROPERTIES_SERVICE = "hardware_properties";
field public static final String INPUT_METHOD_SERVICE = "input_method";
field public static final String INPUT_SERVICE = "input";
接着添加服务的jni层:
frameworks/base/services/core/jni添加com_android_server_HandWriteManagerService.cpp
/*************************************************************************
> File Name: com_android_server_HandWriteManagerService.cpp
> Author: kongbo
> Mail: [email protected]
> Created Time: 2022年11月23日 星期三 14时56分34秒
************************************************************************/
#define LOG_TAG "HandWrite_JNI"
#include "jni.h"
#include "core_jni_helpers.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
namespace android {
/*
struct hello_device* hello_device = NULL;
static inline int hello_device_open(const hw_module_t* module, struct hello_device** device) {
return module->methods->open(module, HELLO_HARDWARE_MODULE_ID, (struct hw_device_t**)device);
}*/
static sp service;
static String16 ifName;
static String16 get_interface_name(sp service) {
if (service != nullptr) {
Parcel data, reply;
status_t err = service->transact(IBinder::INTERFACE_TRANSACTION, data, &reply);
if (err == NO_ERROR) {
return reply.readString16();
}
}
return String16();
}
static void HandWriteServiceNative_Init(JNIEnv* env, jobject) {
/* ALOGE("com_android_server_HelloService HelloServiceInit");
const hw_module_t *hw_module = NULL;
ALOGE("Hello JNI: initializing......");
if(hw_get_module(HELLO_HARDWARE_MODULE_ID, &hw_module) == 0) {
ALOGE("Hello JNI: hello Stub found.");
if(hello_device_open(hw_module, &hello_device) == 0) {
ALOGE("Hello JNI: hello device is open.");
return 0;
}
ALOGE("Hello JNI: failed to open hello device.");
return -1;
}
ALOGE("Hello JNI: failed to get hello stub hw_module.");
*/
ALOGE("====== HandWriteServiceNative_Init JNI: initializing......");
ALOGE("====== HandWriteServiceNative_Init JNI: 000000......");
sp sm = defaultServiceManager();
ALOGE("====== HandWriteServiceNative_Init JNI: 111111......");
service = sm->checkService(String16("SurfaceFlinger"));
ALOGE("====== HandWriteServiceNative_Init JNI: 222222......");
ifName = get_interface_name(service);
ALOGE("====== HandWriteServiceNative_Init JNI: 333333......");
if (service != nullptr && ifName.size() > 0) {
Parcel data1, data2, reply;
ALOGE("====== HandWriteServiceNative_Init JNI: data init");
// the interface name is first
data1.writeInterfaceToken(ifName);
int32_t code = atoi("20006");
data1.writeInt32(atoi("2"));
ALOGE("====== HandWriteServiceNative_Init JNI: 6666666......");
service->transact(code, data1, &reply);
data2.writeInterfaceToken(ifName);
int32_t code1 = atoi("20007");
data2.writeInt32(atoi("100"));
data2.writeInt32(atoi("100"));
data2.writeInt32(atoi("100"));
data2.writeInt32(atoi("100"));
ALOGE("====== HandWriteServiceNative_Init JNI: 77777777......");
service->transact(code1, data2, &reply);
}
//Runtime.getRuntime().exec("vndservice call display.qservice 47 i32 2");
/*bool supported = SurfaceComposerClient::getProtectedContentSupport();
if (supported) {
ALOGE("====== HandWriteServiceNative_Init getProtectedContentSupport: true");
} else {
ALOGE("====== HandWriteServiceNative_Init getProtectedContentSupport: false");
}*/
ALOGE("====== HandWriteServiceNative_Init already write cmd to hwc service");
}
static void HandWriteServiceNative_setRefreshMode(JNIEnv* env, jobject clazz, jint nativeValue) {
/* ALOGE("com_android_server_HelloService HelloServiceNativeSetVal");
if(!hello_device) {
ALOGI("Hello JNI: hello_device is not open.");
return;
}
const char* local_value = (nativeValue) ? env->GetStringUTFChars(nativeValue, NULL) : NULL;
ALOGE("com_android_server_HelloService HelloServiceNativeSetVal local_value = %s",local_value);
hello_device->write_string(hello_device, local_value);
ALOGI("Hello JNI: write string %s to Hello hello_device.", local_value);
env->ReleaseStringUTFChars(nativeValue, local_value);
*/
if (service != nullptr && ifName.size() > 0) {
Parcel data, reply;
// the interface name is first
data.writeInterfaceToken(ifName);
int32_t code = atoi("20006");
data.writeInt32(atoi("2"));
ALOGE("====== HandWriteServiceNative_Init JNI: 6666666......");
service->transact(code, data, &reply);
}
}
static void HandWriteServiceNative_commitRefreshArea(JNIEnv* env, jobject clazz, jint x, jint y, jint h, jint w) {
if (service != nullptr && ifName.size() > 0) {
Parcel data, reply;
// the interface name is first
data.writeInterfaceToken(ifName);
ALOGE("====== HandWriteServiceNative_Init JNI: 6666666......");
int32_t code = atoi("20007");
data.writeInt32(atoi("100"));
data.writeInt32(atoi("100"));
data.writeInt32(atoi("100"));
data.writeInt32(atoi("100"));
service->transact(code, data, &reply);
}
}
static const JNINativeMethod methods[] = {
// {"HelloServiceInit", "()I", (void*) HelloServiceInit},
{"HandWriteServiceNative_Init", "()V",(void*) HandWriteServiceNative_Init},
{"HandWriteServiceNative_setRefreshMode", "(I)V",(void*) HandWriteServiceNative_setRefreshMode},
{"HandWriteServiceNative_commitRefreshArea", "(IIII)V",(void*) HandWriteServiceNative_commitRefreshArea},
};
int register_android_server_HandWriteService(JNIEnv *env) {
return jniRegisterNativeMethods(env, "com/android/server/HandWriteManagerService", methods, NELEM(methods));
}
}
将该文件添加到jni的makefile:
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index 88fa8f7d597..72d5eaf8e18 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -60,6 +60,7 @@ cc_library_static {
"com_android_server_am_LowMemDetector.cpp",
"com_android_server_pm_PackageManagerShellCommandDataLoader.cpp",
"com_android_server_activityTriggerService.cpp",
+ "com_android_server_HandWriteManagerService.cpp",
"onload.cpp",
":lib_networkStatsFactory_native",
],
在onload类添加jni method注册:
diff --git a/services/core/jni/onload.cpp b/services/core/jni/onload.cpp
index ec104ec8666..5b5855bffe9 100644
--- a/services/core/jni/onload.cpp
+++ b/services/core/jni/onload.cpp
@@ -53,6 +53,7 @@ int register_android_server_SyntheticPasswordManager(JNIEnv* env);
int register_android_hardware_display_DisplayViewport(JNIEnv* env);
int register_android_server_net_NetworkStatsFactory(JNIEnv* env);
int register_android_server_net_NetworkStatsService(JNIEnv* env);
+int register_android_server_HandWriteService(JNIEnv *env);
int register_android_server_security_VerityUtils(JNIEnv* env);
int register_android_server_am_CachedAppOptimizer(JNIEnv* env);
int register_android_server_am_LowMemDetector(JNIEnv* env);
@@ -111,6 +112,7 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
register_android_hardware_display_DisplayViewport(env);
register_android_server_net_NetworkStatsFactory(env);
register_android_server_net_NetworkStatsService(env);
+ register_android_server_HandWriteService(env);
register_android_server_security_VerityUtils(env);
register_android_server_am_CachedAppOptimizer(env);
register_android_server_am_LowMemDetector(env);
至此,前半部分需求开发完成~~~
下面展开第二部分需求:
因为需求部分是想调用display相关的服务,很容易联想到Framework层的SF是跟显示系统的HW打交道的,而自定义的服务是可以直接跟SF交互的,因此就打算给SF扩展接口来实现,具体改动如下,集中在framework/native目录:
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index e62a61fc5..a1edb0f78 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -540,6 +540,71 @@ public:
return reply.readBool(outSupport);
}
+ virtual void setPanelRefreshMode(const sp& display, int32_t mode) {
+ Parcel data, reply;
+ status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
+ if (result != NO_ERROR) {
+ ALOGE("setPanelRefreshMode failed to writeInterfaceToken: %d", result);
+ return;
+ }
+
+ result = data.writeStrongBinder(display);
+ if (result != NO_ERROR) {
+ ALOGE("setPanelRefreshMode failed to writeStrongBinder: %d", result);
+ return;
+ }
+ result = data.writeInt32(mode);
+ if (result != NO_ERROR) {
+ ALOGE("setPanelRefreshMode failed to writeInt32: %d", result);
+ return;
+ }
+ result = remote()->transact(BnSurfaceComposer::SET_PANEL_REFRESH_MODE, data, &reply);
+ if (result != NO_ERROR) {
+ ALOGE("setPanelRefreshMode failed to transact: %d", result);
+ return;
+ }
+ }
+
+ virtual void commitRefreshArea(const sp& display, int32_t x, int32_t y, int32_t h, int32_t w) {
+ Parcel data, reply;
+ status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
+ if (result != NO_ERROR) {
+ ALOGE("commitRefreshArea failed to writeInterfaceToken: %d", result);
+ return;
+ }
+
+ result = data.writeStrongBinder(display);
+ if (result != NO_ERROR) {
+ ALOGE("commitRefreshArea failed to writeStrongBinder: %d", result);
+ return;
+ }
+ result = data.writeInt32(x);
+ if (result != NO_ERROR) {
+ ALOGE("commitRefreshArea failed to writeInt32: %d", result);
+ return;
+ }
+ result = data.writeInt32(y);
+ if (result != NO_ERROR) {
+ ALOGE("commitRefreshArea failed to writeInt32: %d", result);
+ return;
+ }
+ result = data.writeInt32(h);
+ if (result != NO_ERROR) {
+ ALOGE("commitRefreshArea failed to writeInt32: %d", result);
+ return;
+ }
+ result = data.writeInt32(w);
+ if (result != NO_ERROR) {
+ ALOGE("commitRefreshArea failed to writeInt32: %d", result);
+ return;
+ }
+ result = remote()->transact(BnSurfaceComposer::COMMIT_REFRESH_AREA, data, &reply);
+ if (result != NO_ERROR) {
+ ALOGE("commitRefreshArea failed to transact: %d", result);
+ return;
+ }
+ }
+
virtual void setAutoLowLatencyMode(const sp& display, bool on) {
Parcel data, reply;
status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
@@ -1568,6 +1633,57 @@ status_t BnSurfaceComposer::onTransact(
return result;
}
+ case SET_PANEL_REFRESH_MODE: {
+ CHECK_INTERFACE(ISurfaceComposer, data, reply);
+ sp display = nullptr;
+ status_t result = data.readStrongBinder(&display);
+ if (result != NO_ERROR) {
+ ALOGE("setPanelRefreshMode failed to readStrongBinder: %d", result);
+ return result;
+ }
+ int32_t setAllm = false;
+ result = data.readInt32(&setAllm);
+ if (result != NO_ERROR) {
+ ALOGE("setPanelRefreshMode failed to readBool: %d", result);
+ return result;
+ }
+ setPanelRefreshMode(display, setAllm);
+ return result;
+ }
+
+ case COMMIT_REFRESH_AREA: {
+ CHECK_INTERFACE(ISurfaceComposer, data, reply);
+ sp display = nullptr;
+ status_t result = data.readStrongBinder(&display);
+ if (result != NO_ERROR) {
+ ALOGE("setPanelRefreshMode failed to readStrongBinder: %d", result);
+ return result;
+ }
+ int32_t x, y ,h, w = 0;
+ result = data.readInt32(&x);
+ if (result != NO_ERROR) {
+ ALOGE("setPanelRefreshMode failed to readBool: %d", result);
+ return result;
+ }
+ result = data.readInt32(&y);
+ if (result != NO_ERROR) {
+ ALOGE("setPanelRefreshMode failed to readBool: %d", result);
+ return result;
+ }
+ result = data.readInt32(&h);
+ if (result != NO_ERROR) {
+ ALOGE("setPanelRefreshMode failed to readBool: %d", result);
+ return result;
+ }
+ result = data.readInt32(&w);
+ if (result != NO_ERROR) {
+ ALOGE("setPanelRefreshMode failed to readBool: %d", result);
+ return result;
+ }
+ commitRefreshArea(display, x, y, h, w);
+ return result;
+ }
+
case SET_AUTO_LOW_LATENCY_MODE: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
sp display = nullptr;
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 83bc06997..3dd441e7c 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -1792,6 +1792,14 @@ bool SurfaceComposerClient::getAutoLowLatencyModeSupport(const sp& disp
return supported;
}
+void SurfaceComposerClient::setPanelRefreshMode(const sp& display, int32_t mode) {
+ ComposerService::getComposerService()->setPanelRefreshMode(display, mode);
+}
+
+void SurfaceComposerClient::commitRefreshArea(const sp& display, int32_t x, int32_t y, int32_t h, int32_t w) {
+ ComposerService::getComposerService()->commitRefreshArea(display, x, y, h, w);
+}
+
void SurfaceComposerClient::setAutoLowLatencyMode(const sp& display, bool on) {
ComposerService::getComposerService()->setAutoLowLatencyMode(display, on);
}
diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h
index 8d3160a81..913e334bc 100644
--- a/libs/gui/include/gui/ISurfaceComposer.h
+++ b/libs/gui/include/gui/ISurfaceComposer.h
@@ -228,6 +228,10 @@ public:
*/
virtual void setAutoLowLatencyMode(const sp& display, bool on) = 0;
+ virtual void setPanelRefreshMode(const sp& displayToken, int32_t mode) = 0;
+
+ virtual void commitRefreshArea(const sp& displayToken, int32_t x, int32_t y, int32_t h, int32_t w) = 0;
+
/**
* Returns true if the connected display reports support for Game Content Type.
* For more information, see the HDMI 1.4 specification.
@@ -599,6 +603,8 @@ public:
SET_GAME_CONTENT_TYPE,
SET_FRAME_RATE,
ACQUIRE_FRAME_RATE_FLEXIBILITY_TOKEN,
+ SET_PANEL_REFRESH_MODE,
+ COMMIT_REFRESH_AREA,
// Always append new enum to the end.
};
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index adcb8982a..89f1c3540 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -155,6 +155,10 @@ public:
// #getAutoLowLatencyModeSupport
static void setAutoLowLatencyMode(const sp& display, bool on);
+ static void setPanelRefreshMode(const sp& displayToken, int32_t mode);
+
+ static void commitRefreshArea(const sp& displayToken, int32_t x, int32_t y, int32_t h, int32_t w);
+
// Reports whether the connected display supports Game content type
static bool getGameContentTypeSupport(const sp& display);
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
index 805050de2..9990ee385 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
@@ -1366,6 +1366,24 @@ V2_4::Error Composer::setAutoLowLatencyMode(Display display, bool on) {
return mClient_2_4->setAutoLowLatencyMode(display, on);
}
+V2_4::Error Composer::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 Composer::commitRefreshArea(Display display, int32_t x, int32_t y, int32_t h, int32_t w) {
+ using Error = V2_4::Error;
+ if (!mClient_2_4) {
+ return Error::UNSUPPORTED;
+ }
+
+ return mClient_2_4->commitRefreshArea(display, x, y, h, w);
+}
+
V2_4::Error Composer::getSupportedContentTypes(
Display displayId, std::vector* outSupportedContentTypes) {
using Error = V2_4::Error;
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.h b/services/surfaceflinger/DisplayHardware/ComposerHal.h
index 5408d5515..06cc105fa 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.h
@@ -231,6 +231,8 @@ public:
VsyncPeriodChangeTimeline* outTimeline) = 0;
virtual V2_4::Error setAutoLowLatencyMode(Display displayId, bool on) = 0;
+ virtual V2_4::Error setPanelRefreshMode(Display displayId, int32_t mode) = 0;
+ virtual V2_4::Error commitRefreshArea(Display displayId, int32_t x, int32_t y, int32_t h, int32_t w) = 0;
virtual V2_4::Error getSupportedContentTypes(
Display displayId,
std::vector* outSupportedContentTypes) = 0;
@@ -480,6 +482,8 @@ public:
const IComposerClient::VsyncPeriodChangeConstraints& vsyncPeriodChangeConstraints,
VsyncPeriodChangeTimeline* outTimeline) override;
V2_4::Error setAutoLowLatencyMode(Display displayId, bool on) override;
+ V2_4::Error setPanelRefreshMode(Display displayId, int32_t mode) override;
+ V2_4::Error commitRefreshArea(Display displayId, int32_t x, int32_t y, int32_t h, int32_t w) override;
V2_4::Error getSupportedContentTypes(
Display displayId,
std::vector* outSupportedContentTypes) override;
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp
index 940437f18..745d2c464 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -659,6 +659,16 @@ std::future Display::setDisplayBrightness(float brightness) {
});
}
+Error Display::setPanelRefreshMode(int32_t mode) {
+ const auto intError = mComposer.setPanelRefreshMode(mId, mode);
+ return static_cast(intError);
+}
+
+Error Display::commitRefreshArea(int32_t x, int32_t y, int32_t h, int32_t w) {
+ const auto intError = mComposer.commitRefreshArea(mId, x, y, h, w);
+ return static_cast(intError);
+}
+
Error Display::setAutoLowLatencyMode(bool on) {
auto intError = mComposer.setAutoLowLatencyMode(mId, on);
return static_cast(intError);
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h
index 469baf736..d76886f67 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2.h
@@ -231,6 +231,8 @@ public:
const hal::VsyncPeriodChangeConstraints& constraints,
hal::VsyncPeriodChangeTimeline* outTimeline) = 0;
[[clang::warn_unused_result]] virtual hal::Error setAutoLowLatencyMode(bool on) = 0;
+ [[clang::warn_unused_result]] virtual hal::Error setPanelRefreshMode(int32_t mode) = 0;
+ [[clang::warn_unused_result]] virtual hal::Error commitRefreshArea(int32_t x, int32_t y, int32_t h, int32_t w) = 0;
[[clang::warn_unused_result]] virtual hal::Error getSupportedContentTypes(
std::vector*) const = 0;
[[clang::warn_unused_result]] virtual hal::Error setContentType(hal::ContentType) = 0;
@@ -305,6 +307,8 @@ public:
const hal::VsyncPeriodChangeConstraints& constraints,
hal::VsyncPeriodChangeTimeline* outTimeline) override;
hal::Error setAutoLowLatencyMode(bool on) override;
+ hal::Error setPanelRefreshMode(int32_t mode) override;
+ hal::Error commitRefreshArea(int32_t x, int32_t y, int32_t h, int32_t w) override;
hal::Error getSupportedContentTypes(
std::vector* outSupportedContentTypes) const override;
hal::Error setContentType(hal::ContentType) override;
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 910f99dc5..6832ad8ab 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -833,6 +833,32 @@ status_t HWComposer::setAutoLowLatencyMode(DisplayId displayId, bool on) {
return NO_ERROR;
}
+status_t HWComposer::setPanelRefreshMode(DisplayId displayId, int32_t mode) {
+ RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
+ const auto error = mDisplayData[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::commitRefreshArea(DisplayId displayId, int32_t x, int32_t y, int32_t h, int32_t w) {
+ RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
+ const auto error = mDisplayData[displayId].hwcDisplay->commitRefreshArea(x, y, h, w);
+ 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::getSupportedContentTypes(
DisplayId displayId, std::vector* outSupportedContentTypes) {
RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index eb90ab2e2..77a564d71 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -206,6 +206,9 @@ public:
const hal::VsyncPeriodChangeConstraints& constraints,
hal::VsyncPeriodChangeTimeline* outTimeline) = 0;
virtual status_t setAutoLowLatencyMode(DisplayId displayId, bool on) = 0;
+ // Sets T1000 refresh mode..
+ virtual status_t setPanelRefreshMode(DisplayId displayId, int32_t mode) = 0;
+ virtual status_t commitRefreshArea(DisplayId displayId, int32_t x, int32_t y, int32_t h, int32_t w) = 0;
virtual status_t getSupportedContentTypes(
DisplayId displayId, std::vector* outSupportedContentTypes) = 0;
virtual status_t setContentType(DisplayId displayId, hal::ContentType contentType) = 0;
@@ -311,7 +314,7 @@ public:
DisplayedFrameStats* outStats) override;
std::future setDisplayBrightness(DisplayId displayId, float brightness) override;
- // Events handling ---------------------------------------------------------
+ // Events handling ---------------------------------------------------------
// Returns stable display ID (and display name on connection of new or previously disconnected
// display), or std::nullopt if hotplug event was ignored.
@@ -348,6 +351,8 @@ public:
const hal::VsyncPeriodChangeConstraints& constraints,
hal::VsyncPeriodChangeTimeline* outTimeline) override;
status_t setAutoLowLatencyMode(DisplayId displayId, bool) override;
+ status_t setPanelRefreshMode(DisplayId displayId, int32_t mode) override;
+ status_t commitRefreshArea(DisplayId displayId, int32_t x, int32_t y, int32_t h, int32_t w) override;
status_t getSupportedContentTypes(DisplayId displayId, std::vector*) override;
status_t setContentType(DisplayId displayId, hal::ContentType) override;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 0d07abb1d..017caae08 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1562,6 +1562,26 @@ void SurfaceFlinger::setAutoLowLatencyMode(const sp& displayToken, bool
}));
}
+void SurfaceFlinger::setPanelRefreshMode(const sp& displayToken, int32_t mode) {
+ static_cast(schedule([=]() MAIN_THREAD {
+ if (const auto displayId = getPhysicalDisplayIdLocked(displayToken)) {
+ getHwComposer().setPanelRefreshMode(*displayId, mode);
+ } else {
+ ALOGE("%s: Invalid display token %p", __FUNCTION__, displayToken.get());
+ }
+ }));
+}
+
+void SurfaceFlinger::commitRefreshArea(const sp& displayToken, int32_t x, int32_t y, int32_t h, int32_t w) {
+ static_cast(schedule([=]() MAIN_THREAD {
+ if (const auto displayId = getPhysicalDisplayIdLocked(displayToken)) {
+ getHwComposer().commitRefreshArea(*displayId, x, y, h, w);
+ } else {
+ ALOGE("%s: Invalid display token %p", __FUNCTION__, displayToken.get());
+ }
+ }));
+}
+
status_t SurfaceFlinger::getGameContentTypeSupport(const sp& displayToken,
bool* outSupport) const {
if (!displayToken) {
@@ -5949,6 +5969,8 @@ status_t SurfaceFlinger::CheckTransactCodeCredentials(uint32_t code) {
case SET_ACTIVE_COLOR_MODE:
case GET_AUTO_LOW_LATENCY_MODE_SUPPORT:
case SET_AUTO_LOW_LATENCY_MODE:
+ case SET_PANEL_REFRESH_MODE:
+ case COMMIT_REFRESH_AREA:
case GET_GAME_CONTENT_TYPE_SUPPORT:
case SET_GAME_CONTENT_TYPE:
case INJECT_VSYNC:
@@ -6045,9 +6067,9 @@ status_t SurfaceFlinger::CheckTransactCodeCredentials(uint32_t code) {
code == IBinder::SYSPROPS_TRANSACTION) {
return OK;
}
- // Numbers from 1000 to 1036 and 20000 to 20002 are currently used for backdoors. The code
+ // Numbers from 1000 to 1036 and 20000 to 20007 are currently used for backdoors. The code
// in onTransact verifies that the user is root, and has access to use SF.
- if ((code >= 1000 && code <= 1036) || (code >= 20000 && code <= 20002)) {
+ if ((code >= 1000 && code <= 1036) || (code >= 20000 && code <= 20007)) {
ALOGV("Accessing SurfaceFlinger through backdoor code: %u", code);
return OK;
}
@@ -6549,6 +6571,35 @@ status_t SurfaceFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* r
#endif
return NO_ERROR;
}
+ case 20006: {
+ int32_t mode = 0;
+ Mutex::Autolock lock(mStateLock);
+ const auto displayId = getInternalDisplayIdLocked();
+ if (data.readInt32(&mode) != NO_ERROR) {
+ err = BAD_TYPE;
+ ALOGE("Invalid 32-bit signed-int wider-mode t1000 fresh mode.");
+ break;
+ }
+
+ ALOGE("====== SF get T1000 fresh mode value: %d, will set to hw layer.", mode);
+ getHwComposer().setPanelRefreshMode(*displayId, mode);
+
+ return NO_ERROR;
+ }
+ case 20007: {
+ int32_t x, y, h, w = 0;
+ Mutex::Autolock lock(mStateLock);
+ const auto displayId = getInternalDisplayIdLocked();
+ x = data.readInt32();
+ y = data.readInt32();
+ h = data.readInt32();
+ w = data.readInt32();
+
+ ALOGE("====== SF get T1000 fresh area value: %d,%d,%d,%d will set to hw layer.",x, y, h, w);
+ getHwComposer().commitRefreshArea(*displayId, x, y, h, w);
+
+ return NO_ERROR;
+ }
}
}
return err;
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 6c7fb3419..4499a7e2e 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -532,6 +532,8 @@ private:
status_t getAutoLowLatencyModeSupport(const sp& displayToken,
bool* outSupported) const override;
void setAutoLowLatencyMode(const sp& displayToken, bool on) override;
+ void setPanelRefreshMode(const sp& displayToken, int32_t mode) override;
+ void commitRefreshArea(const sp& displayToken, int32_t x, int32_t y, int32_t h, int32_t w) override;
status_t getGameContentTypeSupport(const sp& displayToken,
bool* outSupported) const override;
void setGameContentType(const sp& displayToken, bool on) override;
以上只是sf native层面的扩展,还需要通过HIDL接口扩展到HW,从而实现通信,首先实现interface定义扩展:
diff --git a/graphics/composer/2.4/IComposerClient.hal b/graphics/composer/2.4/IComposerClient.hal
index 9e3cf0e08..72d6d7d60 100644
--- a/graphics/composer/2.4/IComposerClient.hal
+++ b/graphics/composer/2.4/IComposerClient.hal
@@ -279,6 +279,34 @@ interface IComposerClient extends @2.3::IComposerClient {
setAutoLowLatencyMode(Display display, bool on)
generates (Error error);
+ /**
+ * Set the display refresh mode.
+ *
+ * If the display is connected via HDMI 2.1, then Auto Low Latency Mode should be triggered. If
+ * the display is internally connected and a custom low latency mode is available, that should
+ * be triggered.
+ *
+ * This function should only be called if the display reports support for
+ *
+ * @return error is NONE upon success. Otherwise,
+ */
+ setPanelRefreshMode(Display display, int32_t mode)
+ generates (Error error);
+
+ /**
+ * Set the refresh area.
+ *
+ * If the display is connected via HDMI 2.1, then Auto Low Latency Mode should be triggered. If
+ * the display is internally connected and a custom low latency mode is available, that should
+ * be triggered.
+ *
+ * This function should only be called if the display reports support for
+ *
+ * @return error is NONE upon success. Otherwise,
+ */
+ commitRefreshArea(Display display, int32_t x, int32_t y, int32_t h, int32_t w)
+ 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/utils/hal/include/composer-hal/2.4/ComposerClient.h b/graphics/composer/2.4/utils/hal/include/composer-hal/2.4/ComposerClient.h
index c88906914..b9ac48a03 100644
--- 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
@@ -150,6 +150,14 @@ class ComposerClientImpl : public V2_3::hal::detail::ComposerClientImplsetAutoLowLatencyMode(display, on);
}
+ Return setPanelRefreshMode(Display display, int32_t mode) override {
+ return mHal->setPanelRefreshMode(display, mode);
+ }
+
+ Return commitRefreshArea(Display display, int32_t x, int32_t y, int32_t h, int32_t w) override {
+ return mHal->commitRefreshArea(display, x, y, h, w);
+ }
+
Return getSupportedContentTypes(
Display display, IComposerClient::getSupportedContentTypes_cb hidl_cb) override {
std::vector supportedContentTypes;
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
index 58991c1d8..390d7f05d 100644
--- 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
@@ -69,6 +69,8 @@ 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 commitRefreshArea(Display display, int32_t x, int32_t y, int32_t h, int32_t w) = 0;
virtual Error getSupportedContentTypes(
Display display,
std::vector* 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
index d28e00625..5eac92438 100644
--- 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
@@ -180,6 +180,30 @@ class HwcHalImpl : public V2_3::passthrough::detail::HwcHalImpl {
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);
+ }
+ return Error::NONE;
+ }
+
+ Error commitRefreshArea(Display display, int32_t x, int32_t y, int32_t h, int32_t w) override {
+ if (!mDispatch.commitRefreshArea) {
+ return Error::UNSUPPORTED;
+ }
+
+ int32_t error = mDispatch.commitRefreshArea(mDevice, display, x, y, h, w);
+ if (error != HWC2_ERROR_NONE) {
+ return static_cast(error);
+ }
+ return Error::NONE;
+ }
+
Error getSupportedContentTypes(
Display display,
std::vector* outSupportedContentTypes) override {
@@ -317,6 +341,10 @@ class HwcHalImpl : public V2_3::passthrough::detail::HwcHalImpl {
&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_COMMIT_REFRESH_AREA,
+ &mDispatch.commitRefreshArea);
this->initOptionalDispatch(HWC2_FUNCTION_GET_SUPPORTED_CONTENT_TYPES,
&mDispatch.getSupportedContentTypes);
this->initOptionalDispatch(HWC2_FUNCTION_SET_CONTENT_TYPE, &mDispatch.setContentType);
@@ -376,6 +404,8 @@ class HwcHalImpl : public V2_3::passthrough::detail::HwcHalImpl {
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_COMMIT_REFRESH_AREA commitRefreshArea;
HWC2_PFN_GET_SUPPORTED_CONTENT_TYPES getSupportedContentTypes;
HWC2_PFN_SET_CONTENT_TYPE setContentType;
HWC2_PFN_GET_CLIENT_TARGET_PROPERTY getClientTargetProperty;
这个时候做一次增量编译,会提示如下两个编译错误,按如下方式修改解决:
修改如上几个地方后,编译报错
错误一、which does not match hash on record. This interface has been frozen. Do not change it!
ERROR: output handler failed.
HIDL c++-sources: hardware/interfaces/light/2.0/types.hal hardware/interfaces/light/2.0/ILight.hal hardware/interfaces/current.txt => 'out/soong/.intermediates/hardware/interfaces/light/2.0/[email protected]_genc++/gen/android/hardware/light/2.0/LightAll.cpp'
FAILED: out/soong/.intermediates/hardware/interfaces/light/2.0/[email protected]_genc++/gen/android/hardware/light/2.0/LightAll.cpp out/soong/.intermediates/hardware/interfaces/light/2.0/[email protected]_genc++/gen/android/hardware/light/2.0/types.cpp
rm -rf out/soong/.intermediates/hardware/interfaces/light/2.0/[email protected]_genc++/gen && out/soong/host/linux-x86/bin/hidl-gen -R -p . -d out/soong/.intermediates/hardware/interfaces/light/2.0/[email protected]_genc++/gen/android/hardware/light/2.0/LightAll.cpp.d -o out/soong/.intermediates/hardware/interfaces/light/2.0/[email protected]_genc++/gen -L c++-sources -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport [email protected]
ERROR: [email protected]::types has hash cd082c47c3940f2c4d4ef489c9f34e0c737dfcbd7dd09e0e270563e699a9d91e which does not match hash on record. This interface has been frozen. Do not change it!
ERROR: Could not parse [email protected]::types. Aborting.
原因:Android P 开始,Google 对 Hidl 有了严格的限制。Google release 出来的 hidl 接口不允许修改。
需要重新生成修改 hardware 对应的 hashcode,错误中已经包含新的 hashcode 值 cd082c47c3940f2c4d4ef489c9f34e0c737dfcbd7dd09e0e270563e699a9d91e
如果没有此 hashcode 值,可以通过指令 hidl-gen -L hash -r 来生成,得到和错误提示中的hash值一模一样
$ hidl-gen -L hash -r android.hardware:hardware/interfaces -r android.hidl:system/libhidl/transport [email protected]::types
cd082c47c3940f2c4d4ef489c9f34e0c737dfcbd7dd09e0e270563e699a9d91e [email protected]::types
将刚刚得到的新 hashcode 值更新到 hardware/interfaces/current.txt
可直接在文档末尾增加
cd082c47c3940f2c4d4ef489c9f34e0c737dfcbd7dd09e0e270563e699a9d91e [email protected]::types
错误二、error: VNDK library: [email protected]’s ABI has INCOMPATIBLE CHANGES
Please check compatibility report at: out/soong/.intermediates/hardware/interfaces/light/2.0/[email protected]/android_arm64_armv8-a_cortex-a53_vendor_shared/[email protected]
Install: out/target/product/full_171_bsp/system/lib64/vndk-29/[email protected]
//hardware/interfaces/light/2.0:[email protected] header-abi-diff [email protected]
FAILED: out/soong/.intermediates/hardware/interfaces/light/2.0/[email protected]/android_arm64_armv8-a_cortex-a53_vendor_shared/[email protected]
(prebuilts/clang-tools/linux-x86/bin/header-abi-diff -allow-unreferenced-changes -allow-unreferenced-elf-symbol-changes -lib [email protected] -arch arm64 -o 'out/soong/.intermediates/hardware/interfaces/light/2.0/[email protected]/android_arm64_armv8-a_cortex-a53_vendor_shared/[email protected]' -new 'out/soong/.intermediates/hardware/interfaces/light/2.0/[email protected]/android_arm64_armv8-a_cortex-a53_vendor_shared/[email protected]' -old prebuilts/abi-dumps/vndk/29/64/arm64_armv8-a/source-based/[email protected])|| (echo 'error: Please update ABI references with: $ANDROID_BUILD_TOP/development/vndk/tools/header-checker/utils/create_reference_dumps.py -l [email protected]' && (mkdir -p $DIST_DIR/abidiffs && cp 'out/soong/.intermediates/hardware/interfaces/light/2.0/[email protected]/android_arm64_armv8-a_cortex-a53_vendor_shared/[email protected]' $DIST_DIR/abidiffs/) && exit 1)
******************************************************
error: VNDK library: [email protected]'s ABI has INCOMPATIBLE CHANGES Please check compatibility report at: out/soong/.intermediates/hardware/interfaces/light/2.0/[email protected]/android_arm64_armv8-a_cortex-a53_vendor_shared/[email protected]
******************************************************
error: Please update ABI references with: $ANDROID_BUILD_TOP/development/vndk/tools/header-checker/utils/create_reference_dumps.py -l [email protected]
根据提示执行指令 development/vndk/tools/header-checker/utils/create_reference_dumps.py -l [email protected] ,发现报错
$ development/vndk/tools/header-checker/utils/create_reference_dumps.py -l [email protected]
Removing reference dumps...
removing /platform/prebuilts/abi-dumps/vndk/28/32/arm_armv7-a-neon/source-based/[email protected]
removing /platform/prebuilts/abi-dumps/ndk/28/32/arm_armv7-a-neon/source-based/[email protected]
making libs for product: aosp_arm_ab
Traceback (most recent call last):
File "development/vndk/tools/header-checker/utils/create_reference_dumps.py", line 224, in
main()
File "development/vndk/tools/header-checker/utils/create_reference_dumps.py", line 215, in main
make_libs_for_product(args.libs, args.llndk, product)
File "development/vndk/tools/header-checker/utils/create_reference_dumps.py", line 97, in make_libs_for_product
make_libraries(libs, product, llndk_mode)
File "/platform/development/vndk/tools/header-checker/utils/utils.py", line 146, in make_libraries
make_targets(lib_targets, product)
File "/platform/development/vndk/tools/header-checker/utils/utils.py", line 137, in make_targets
stderr=subprocess.STDOUT)
File "/usr/lib/python3.5/subprocess.py", line 581, in check_call
raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command '['build/soong/soong_ui.bash', '--make-mode', '-j', '[email protected]', 'TARGET_PRODUCT=aosp_arm_ab']' returned non-zero exit status 1
看到 making libs for product: aosp_arm_ab 这行,这个是因为我的项目 product名字不一样导致的,加上参数-product product_name 即可,product_name 是你的项目的 product 名称。
development/vndk/tools/header-checker/utils/create_reference_dumps.py -l [email protected] -product full_171_bsp
AllowBuildBrokenUsesNetwork: true
BuildBrokenUsesNetwork: true
//hardware/interfaces/light/2.0:[email protected] header-abi-linker [email protected] [arm]
Creating dumps for target_arch: arm and variant armv8-a
Created abi dump at /prebuilts/abi-dumps/vndk/29/64/arm_armv8-a/source-based/[email protected]
Creating dumps for target_arch: arm64 and variant armv8-a
Created abi dump at /prebuilts/abi-dumps/vndk/29/64/arm64_armv8-a/source-based/[email protected]
msg: Processed 2 libraries in 14.642458236217498 minutes
添加头文件定义:
diff --git a/include/hardware/hwcomposer2.h b/include/hardware/hwcomposer2.h
index 76122a57..698ae498 100644
--- a/include/hardware/hwcomposer2.h
+++ b/include/hardware/hwcomposer2.h
@@ -304,6 +304,8 @@ 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_COMMIT_REFRESH_AREA,
HWC2_FUNCTION_GET_SUPPORTED_CONTENT_TYPES,
HWC2_FUNCTION_SET_CONTENT_TYPE,
HWC2_FUNCTION_GET_CLIENT_TARGET_PROPERTY,
@@ -666,6 +668,8 @@ 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_REFRESH_AREA: return "CommitRefreshArea";
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";
@@ -946,6 +950,8 @@ enum class FunctionDescriptor : int32_t {
GetDisplayVsyncPeriod = HWC2_FUNCTION_GET_DISPLAY_VSYNC_PERIOD,
SetActiveConfigWithConstraints = HWC2_FUNCTION_SET_ACTIVE_CONFIG_WITH_CONSTRAINTS,
SetAutoLowLatencyMode = HWC2_FUNCTION_SET_AUTO_LOW_LATENCY_MODE,
+ SetPanelRefreshMode = HWC2_FUNCTION_SET_PANEL_REFRESH_MODE,
+ CommitRefreshArea = HWC2_FUNCTION_COMMIT_REFRESH_AREA,
GetSupportedContentTypes = HWC2_FUNCTION_GET_SUPPORTED_CONTENT_TYPES,
SetContentType = HWC2_FUNCTION_SET_CONTENT_TYPE,
GetClientTargetProperty = HWC2_FUNCTION_GET_CLIENT_TARGET_PROPERTY,
@@ -3004,6 +3010,36 @@ typedef int32_t /*hwc2_error_t*/ (*HWC2_PFN_SET_ACTIVE_CONFIG_WITH_CONSTRAINTS)(
typedef int32_t /*hwc_error_t*/ (*HWC2_PFN_SET_AUTO_LOW_LATENCY_MODE)(hwc2_device_t* device,
hwc2_display_t display, bool on);
+/* setPanelRefreshMode(displayToken, mode)
+ * Descriptor: HWC2_FUNCTION_SET_PANEL_REFRESH_MODE
+ * Optional for HWC2 devices
+ *
+ * setAutoLowLatencyMode requests that the display goes into low latency mode. If the display
+ * is connected via HDMI 2.1, then Auto Low Latency Mode should be triggered. If the display is
+ * internally connected, then a custom low latency mode should be triggered (if available).
+ *
+ * Returns HWC2_ERROR_NONE or one of the following errors:
+ * HWC2_ERROR_BAD_DISPLAY - when the display is invalid, or
+ * HWC2_ERROR_UNSUPPORTED - when the display does not support any low latency mode
+ */
+typedef int32_t /*hwc_error_t*/ (*HWC2_PFN_SET_PANEL_REFRESH_MODE)(hwc2_device_t* device,
+ hwc2_display_t display, int32_t mode);
+
+/* commitRefreshArea(displayToken, x, y, h, w)
+ * Descriptor:HWC2_FUNCTION_COMMIT_REFRESH_AREA
+ * Optional for HWC2 devices
+ *
+ * setAutoLowLatencyMode requests that the display goes into low latency mode. If the display
+ * is connected via HDMI 2.1, then Auto Low Latency Mode should be triggered. If the display is
+ * internally connected, then a custom low latency mode should be triggered (if available).
+ *
+ * Returns HWC2_ERROR_NONE or one of the following errors:
+ * HWC2_ERROR_BAD_DISPLAY - when the display is invalid, or
+ * HWC2_ERROR_UNSUPPORTED - when the display does not support any low latency mode
+ */
+typedef int32_t /*hwc_error_t*/ (*HWC2_PFN_COMMIT_REFRESH_AREA)(hwc2_device_t* device,
+ hwc2_display_t display, int32_t x, int32_t y, int32_t h, int32_t w);
+
/* getSupportedContentTypes(..., outSupportedContentTypes)
* Descriptor: HWC2_FUNCTION_GET_SUPPORTED_CONTENT_TYPES
* Optional for HWC2 devices
最后扩展hw服务的接口在android/hardware/qcom/display/sdm/libs/hwc2目录:
diff --git a/sdm/libs/hwc2/hwc_session.cpp b/sdm/libs/hwc2/hwc_session.cpp
index 21be352f..e4f2fef8 100644
--- a/sdm/libs/hwc2/hwc_session.cpp
+++ b/sdm/libs/hwc2/hwc_session.cpp
@@ -1191,6 +1191,22 @@ int32_t HWCSession::SetAutoLowLatencyMode(hwc2_device_t *device, hwc2_display_t
return HWC2_ERROR_UNSUPPORTED;
}
+int32_t HWCSession::SetPanelRefreshMode(hwc2_device_t *device, hwc2_display_t display, int32_t mode) {
+ DLOGE("====== HWCSession::SetPanelRefreshMode get from fw: %d .", mode);
+ if (!device || display >= HWCCallbacks::kNumDisplays) {
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
+ return HWC2_ERROR_NONE;
+}
+
+int32_t HWCSession::CommitRefreshArea(hwc2_device_t *device, hwc2_display_t display, int32_t x, int32_t y, int32_t h, int32_t w) {
+ DLOGE("====== HWCSession::CommitRefreshArea get from fw: x= %d y= %d h= %d w= %d\n .", x, y, h, w);
+ if (!device || display >= HWCCallbacks::kNumDisplays) {
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
+ return HWC2_ERROR_NONE;
+}
+
int32_t HWCSession::GetSupportedContentTypes(hwc2_device_t *device, hwc2_display_t display,
uint32_t *count, uint32_t *contentTypes) {
contentTypes = {};
@@ -1382,6 +1398,10 @@ hwc2_function_pointer_t HWCSession::GetFunction(struct hwc2_device *device,
(HWCSession::SetActiveConfigWithConstraints);
case HWC2::FunctionDescriptor::SetAutoLowLatencyMode:
return AsFP(HWCSession::SetAutoLowLatencyMode);
+ case HWC2::FunctionDescriptor::SetPanelRefreshMode:
+ return AsFP(HWCSession::SetPanelRefreshMode);
+ case HWC2::FunctionDescriptor::CommitRefreshArea:
+ return AsFP(HWCSession::CommitRefreshArea);
case HWC2::FunctionDescriptor::GetSupportedContentTypes:
return AsFP(HWCSession::GetSupportedContentTypes);
case HWC2::FunctionDescriptor::SetContentType:
@@ -1808,6 +1828,15 @@ android::status_t HWCSession::notifyCallback(uint32_t command, const android::Pa
status = SetPanelLuminanceAttributes(input_parcel);
break;
+ case qService::IQService::SET_DISPLAY_REFRESH_MODE:
+ if (!input_parcel) {
+ DLOGE("QService command SET_DISPLAY_REFRESH_MODE = %d: input_parcel needed.", command);
+ break;
+ }
+ DLOGE("====== HW session rec SET_DISPLAY_REFRESH_MODE cmd");
+ //status = SetPanelLuminanceAttributes(input_parcel);
+ break;
+
case qService::IQService::SET_COLOR_MODE_FROM_CLIENT:
if (!input_parcel) {
DLOGE("QService command = %d: input_parcel needed.", command);
diff --git a/sdm/libs/hwc2/hwc_session.h b/sdm/libs/hwc2/hwc_session.h
index 5931a5d9..c0c3bd45 100644
--- a/sdm/libs/hwc2/hwc_session.h
+++ b/sdm/libs/hwc2/hwc_session.h
@@ -233,6 +233,8 @@ class HWCSession : hwc2_device_t, HWCUEventListener, public qClient::BnQClient,
static int32_t GetDozeSupport(hwc2_device_t *device, hwc2_display_t display,
int32_t *out_support);
static int32_t SetAutoLowLatencyMode(hwc2_device_t *device, hwc2_display_t display, bool on);
+ static int32_t SetPanelRefreshMode(hwc2_device_t *device, hwc2_display_t display, int32_t mode);
+ static int32_t CommitRefreshArea(hwc2_device_t *device, hwc2_display_t display, int32_t x, int32_t y, int32_t h, int32_t w);
static int32_t GetSupportedContentTypes(hwc2_device_t *device, hwc2_display_t display,
uint32_t *count, uint32_t *contentTypes);
static int32_t SetContentType(hwc2_device_t *device, hwc2_display_t display,int32_t type);
刷机验证即可~~~
顺利的话会得到如下日志:
11-21 11:20:54.105 1050 1050 I SystemServerTiming: StartSystemUpdateManagerService
11-21 11:20:54.106 1050 1050 I SystemUpdateManagerService: No existing info file /data/system/system-update-info.xml
11-21 11:20:54.107 1050 1050 D SystemServerTiming: StartSystemUpdateManagerService took to complete: 2ms
11-21 11:20:54.108 1050 1050 I SystemServerTiming: StartUpdateLockService
11-21 11:20:54.109 1050 1050 D SystemServerTiming: StartUpdateLockService took to complete: 1ms
11-21 11:20:54.109 1050 1050 I SystemServerTiming: ====== StartHandWriteManagerService
11-21 11:20:54.109 1050 1050 E HandWrite_JNI: ====== HandWriteServiceNative_Init JNI: initializing......
11-21 11:20:54.110 1050 1050 E HandWrite_JNI: ====== HandWriteServiceNative_Init JNI: 000000......
11-21 11:20:54.110 1050 1050 E HandWrite_JNI: ====== HandWriteServiceNative_Init JNI: 111111......
11-21 11:20:54.110 1050 1050 E HandWrite_JNI: ====== HandWriteServiceNative_Init JNI: 222222......
11-21 11:20:54.111 1050 1050 E HandWrite_JNI: ====== HandWriteServiceNative_Init JNI: 333333......
11-21 11:20:54.111 1050 1050 E HandWrite_JNI: ====== HandWriteServiceNative_Init JNI: data init
11-21 11:20:54.111 1050 1050 E HandWrite_JNI: ====== HandWriteServiceNative_Init JNI: 6666666......
11-21 11:20:54.111 818 1400 E SurfaceFlinger: ====== SF get T1000 fresh mode value: 2, will set to hw layer.
11-21 11:20:54.112 715 715 E SDM : HWCSession::SetPanelRefreshMode: ====== HWCSession::SetPanelRefreshMode get from fw: 2 .
11-21 11:20:54.112 1050 1050 E HandWrite_JNI: ====== HandWriteServiceNative_Init JNI: 77777777......
11-21 11:20:54.113 818 1400 E SurfaceFlinger: ====== SF get T1000 fresh area value: 100,100,100,100 will set to hw layer.
11-21 11:20:54.113 715 715 E SDM : HWCSession::CommitRefreshArea: ====== HWCSession::CommitRefreshArea get from fw: x= 100 y= 100 h= 100 w= 100
11-21 11:20:54.113 715 715 E SDM : .
11-21 11:20:54.113 1050 1050 E HandWrite_JNI: ====== HandWriteServiceNative_Init already write cmd to hwc service
11-21 11:20:54.115 1050 1050 D SystemServerTiming: ====== StartHandWriteManagerService took to complete: 6ms
11-21 11:20:54.116 1050 1050 I SystemServerTiming: StartNotificationManager
11-21 11:20:54.116 1050 1050 I SystemServiceManager: Starting com.android.server.notification.NotificationManagerService
01-01 00:24:43.550 0 0 I chatty : uid=0(root) logd identical 107 lines
01-01 00:24:43.559 0 0 I bad ioctl: -1072934383
可以看到“======”标示的内容,从自定义服务开始到SF日志,到最终HW层扩展接口拿到传递的数据值证明接口通了~~~~完事大吉!!!!!!
Mark一下,本文只做数据通路走通,可参考实现自己的控制和数据传输接口!