简介
Android 7.1引入了一项新功能,允许开发者实时监测设备的帧率(FPS),LCD帧数和相机帧数。这对于开发高性能应用和游戏非常重要。在本文中,我将详细解释如何利用SurfaceFlinger实现这些功能,并提供相关的代码示例。
SurfaceFlinger
SurfaceFlinger是Android系统中的一个关键组件,负责管理和显示所有2D和3D图形层,以及将它们合成到设备的显示器上。它负责处理应用程序的绘制请求,并确保它们以适当的顺序和速度呈现。SurfaceFlinger是一个位于系统级别的服务,运行在系统进程中,并具有独立于应用程序进程的特权。因此,它能够获取更多底层信息,如帧率、LCD帧数和相机帧数。
实时显示帧率FPS
要实时显示帧率,我们需要在应用程序中通过SurfaceFlinger获取每秒钟的帧数,并将其显示在屏幕上。这样一来,开发者可以随时监测应用程序的性能,并及时进行调整。
下面是一段示例代码,展示了如何使用Choreographer
类获取帧率数据:
public class FrameRateMonitor {
private Choreographer.FrameCallback frameCallback;
private long frameCount;
public void startMonitoring() {
frameCallback = new Choreographer.FrameCallback() {
@Override
public void doFrame(long frameTimeNanos) {
frameCount++;
Choreographer.getInstance().postFrameCallback(this);
}
};
Choreographer.getInstance().postFrameCallback(frameCallback);
}
public void stopMonitoring() {
if (frameCallback != null) {
Choreographer.getInstance().removeFrameCallback(frameCallback);
frameCallback = null;
}
}
public float getFramesPerSecond() {
float frameRate = frameCount / ((float) getElapsedTimeMillis() / 1000);
frameCount = 0;
return frameRate;
}
}
在启动监测时,我们使用postFrameCallback()
方法注册一个FrameCallback
回调函数。每次帧渲染完成后,该回调函数会被调用,我们可以在其中更新帧数,并使用postFrameCallback()
方法注册下一帧。停止监测时,我们调用removeFrameCallback()
方法移除回调函数。
实时显示LCD帧数
要实时显示LCD帧数,我们需要通过SurfaceFlinger获取显示器每秒钟的帧数,并将其显示在屏幕上。这样一来,开发者可以了解设备显示的性能。
下面是一段示例代码,展示了如何使用SurfaceFlinger
类获取LCD帧数:
public class LcdFrameRateMonitor {
private final static String SERVICE_NAME = "SurfaceFlinger";
private IBinder service;
private long frameCount;
private long lastFrameTime;
public void startMonitoring() {
service = ServiceManager.getService(SERVICE_NAME);
final ISurfaceComposer serviceInterface = ISurfaceComposer.Stub.asInterface(service);
final SurfaceComposerClient.TransactionCallback transactionCallback =
new SurfaceComposerClient.TransactionCallback() {
@Override
public void onTransactionReady(int transaction) {
try {
frameCount++;
serviceInterface.setTransactionNestCount(transaction, 0);
serviceInterface.setDisplayProjection(transaction,
Display.DEFAULT_DISPLAY,
SurfaceComposerClient.getDisplayRect(Display.DEFAULT_DISPLAY),
SurfaceComposerClient.getDisplayRect(Display.DEFAULT_DISPLAY));
serviceInterface.setTransactionName(transaction, null);
serviceInterface.applyTransaction(transaction);
lastFrameTime = System.nanoTime();
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onTransactionCancelled(int transaction) {
// Ignored
}
};
SurfaceComposerClient.openTransaction();
SurfaceComposerClient.closeTransaction(transactionCallback);
}
public void stopMonitoring() {
if (service != null) {
service = null;
frameCount = 0;
lastFrameTime = 0;
}
}
public float getFramesPerSecond() {
long elapsedTime = System.nanoTime() - lastFrameTime;
float frameRate = frameCount / ((float) elapsedTime / 1000000000);
frameCount = 0;
lastFrameTime = System.nanoTime();
return frameRate;
}
}
在启动监测时,我们先获取SurfaceFlinger
服务对象,并根据其接口进行操作。我们的目标是在每次事务执行完成后计算帧数,并使用setTransactionNestCount()
方法将事务设置为0。如果不这样做,事务嵌套将会导致错误的帧数统计。
实时显示Camera帧数
要实时显示Camera帧数,我们需要通过Camera API获取相机每秒钟的帧数,并将其显示在屏幕上。这样一来,开发者可以查看相机的性能。
下面是一段示例代码,展示了如何使用Camera
类获取相机帧数:
public class CameraFrameRateMonitor {
private final static int CAMERA_ID = 0;
private Camera camera;
private long frameCount;
private long lastFrameTime;
public void startMonitoring() {
camera = Camera.open(CAMERA_ID);
camera.setPreviewCallback(new Camera.PreviewCallback() {
@Override
public void onPreviewFrame(byte[] data, Camera camera) {
frameCount++;
lastFrameTime = System.nanoTime();
}
});
}
public void stopMonitoring() {
if (camera != null) {
camera.setPreviewCallback(null);
camera.release();
camera = null;
frameCount = 0;
lastFrameTime = 0;
}
}
public float getFramesPerSecond() {
long elapsedTime = System.nanoTime() - lastFrameTime;
float frameRate = frameCount / ((float) elapsedTime / 1000000000);
frameCount = 0;
lastFrameTime = System.nanoTime();
return frameRate;
}
}
在启动监测时,我们使用open()
方法打开相机,并利用setPreviewCallback()
方法注册一个预览回调函数。每当相机预览帧可用时,该回调函数将被调用,我们可以在其中更新帧数。
结论
通过使用SurfaceFlinger,我们可以实时监测设备的帧率FPS、LCD帧数和Camera帧数。这对于开发高性能应用和游戏非常重要。在本文中,我们介绍了如何使用SurfaceFlinger获取帧率和帧数,并提供了相关的代码示例。希望这篇文章对你有所帮助!
参考链接:
- https://developer.android.com/reference/android/view/Choreographer
- https://android.googlesource.com/platform/frameworks/native/+/master/libs/surfaceflinger/README.md
本文来自极简博客,作者:浅笑安然,转载请注明原文链接:Android 7.1之SurfaceFlinger实时显示帧率FPS/LCD帧数/Camera帧数